Adding new authorization level to peers; porting Blocked status to authorization; removing trusted; securing engine/peerapp message processing around authoriztion
the build failed
Details
the build failed
Details
This commit is contained in:
parent
e05d1addf6
commit
e91e892eef
10
app/app.go
10
app/app.go
|
@ -121,10 +121,10 @@ func (app *application) CreateTaggedPeer(name string, password string, tag strin
|
||||||
p := peer.FromProfile(pc)
|
p := peer.FromProfile(pc)
|
||||||
p.Init(app.eventBuses[profile.Onion])
|
p.Init(app.eventBuses[profile.Onion])
|
||||||
|
|
||||||
blockedPeers := profile.BlockedPeers()
|
peerAuthorizations := profile.ContactsAuthorizations()
|
||||||
// TODO: Would be nice if ProtocolEngine did not need to explicitly be given the Private Key.
|
// TODO: Would be nice if ProtocolEngine did not need to explicitly be given the Private Key.
|
||||||
identity := primitives.InitializeIdentity(profile.Name, &profile.Ed25519PrivateKey, &profile.Ed25519PublicKey)
|
identity := primitives.InitializeIdentity(profile.Name, &profile.Ed25519PrivateKey, &profile.Ed25519PublicKey)
|
||||||
engine := connections.NewProtocolEngine(identity, profile.Ed25519PrivateKey, app.acn, app.eventBuses[profile.Onion], profile.GetContacts(), blockedPeers)
|
engine := connections.NewProtocolEngine(identity, profile.Ed25519PrivateKey, app.acn, app.eventBuses[profile.Onion], peerAuthorizations)
|
||||||
|
|
||||||
app.peers[profile.Onion] = p
|
app.peers[profile.Onion] = p
|
||||||
app.engines[profile.Onion] = engine
|
app.engines[profile.Onion] = engine
|
||||||
|
@ -213,9 +213,9 @@ func (app *application) LoadProfiles(password string) {
|
||||||
peer := peer.FromProfile(profile)
|
peer := peer.FromProfile(profile)
|
||||||
peer.Init(app.eventBuses[profile.Onion])
|
peer.Init(app.eventBuses[profile.Onion])
|
||||||
|
|
||||||
blockedPeers := profile.BlockedPeers()
|
peerAuthorizations := profile.ContactsAuthorizations()
|
||||||
identity := primitives.InitializeIdentity(profile.Name, &profile.Ed25519PrivateKey, &profile.Ed25519PublicKey)
|
identity := primitives.InitializeIdentity(profile.Name, &profile.Ed25519PrivateKey, &profile.Ed25519PublicKey)
|
||||||
engine := connections.NewProtocolEngine(identity, profile.Ed25519PrivateKey, app.acn, app.eventBuses[profile.Onion], profile.GetContacts(), blockedPeers)
|
engine := connections.NewProtocolEngine(identity, profile.Ed25519PrivateKey, app.acn, app.eventBuses[profile.Onion], peerAuthorizations)
|
||||||
app.appmutex.Lock()
|
app.appmutex.Lock()
|
||||||
app.peers[profile.Onion] = peer
|
app.peers[profile.Onion] = peer
|
||||||
app.storage[profile.Onion] = profileStore
|
app.storage[profile.Onion] = profileStore
|
||||||
|
@ -246,10 +246,12 @@ func (ac *applicationCore) GetEventBus(onion string) event.Manager {
|
||||||
func (app *application) getACNStatusHandler() func(int, string) {
|
func (app *application) getACNStatusHandler() func(int, string) {
|
||||||
return func(progress int, status string) {
|
return func(progress int, status string) {
|
||||||
progStr := strconv.Itoa(progress)
|
progStr := strconv.Itoa(progress)
|
||||||
|
app.peerLock.Lock()
|
||||||
app.appBus.Publish(event.NewEventList(event.ACNStatus, event.Progreess, progStr, event.Status, status))
|
app.appBus.Publish(event.NewEventList(event.ACNStatus, event.Progreess, progStr, event.Status, status))
|
||||||
for _, bus := range app.eventBuses {
|
for _, bus := range app.eventBuses {
|
||||||
bus.Publish(event.NewEventList(event.ACNStatus, event.Progreess, progStr, event.Status, status))
|
bus.Publish(event.NewEventList(event.ACNStatus, event.Progreess, progStr, event.Status, status))
|
||||||
}
|
}
|
||||||
|
app.peerLock.Unlock()
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -107,10 +107,10 @@ func (as *applicationService) createPeer(name, password, tag string) {
|
||||||
|
|
||||||
profileStore := storage.CreateProfileWriterStore(as.eventBuses[profile.Onion], path.Join(as.directory, "profiles", profile.LocalID), password, profile)
|
profileStore := storage.CreateProfileWriterStore(as.eventBuses[profile.Onion], path.Join(as.directory, "profiles", profile.LocalID), password, profile)
|
||||||
|
|
||||||
blockedPeers := profile.BlockedPeers()
|
peerAuthorizations := profile.ContactsAuthorizations()
|
||||||
// TODO: Would be nice if ProtocolEngine did not need to explicitly be given the Private Key.
|
// TODO: Would be nice if ProtocolEngine did not need to explicitly be given the Private Key.
|
||||||
identity := primitives.InitializeIdentity(profile.Name, &profile.Ed25519PrivateKey, &profile.Ed25519PublicKey)
|
identity := primitives.InitializeIdentity(profile.Name, &profile.Ed25519PrivateKey, &profile.Ed25519PublicKey)
|
||||||
engine := connections.NewProtocolEngine(identity, profile.Ed25519PrivateKey, as.acn, as.eventBuses[profile.Onion], profile.GetContacts(), blockedPeers)
|
engine := connections.NewProtocolEngine(identity, profile.Ed25519PrivateKey, as.acn, as.eventBuses[profile.Onion], peerAuthorizations)
|
||||||
|
|
||||||
as.storage[profile.Onion] = profileStore
|
as.storage[profile.Onion] = profileStore
|
||||||
as.engines[profile.Onion] = engine
|
as.engines[profile.Onion] = engine
|
||||||
|
@ -126,9 +126,9 @@ func (as *applicationService) loadProfiles(password string) {
|
||||||
as.applicationCore.LoadProfiles(password, false, func(profile *model.Profile, profileStore storage.ProfileStore) {
|
as.applicationCore.LoadProfiles(password, false, func(profile *model.Profile, profileStore storage.ProfileStore) {
|
||||||
as.eventBuses[profile.Onion] = event.IPCEventManagerFrom(as.bridge, profile.Onion, as.eventBuses[profile.Onion])
|
as.eventBuses[profile.Onion] = event.IPCEventManagerFrom(as.bridge, profile.Onion, as.eventBuses[profile.Onion])
|
||||||
|
|
||||||
blockedPeers := profile.BlockedPeers()
|
peerAuthorizations := profile.ContactsAuthorizations()
|
||||||
identity := primitives.InitializeIdentity(profile.Name, &profile.Ed25519PrivateKey, &profile.Ed25519PublicKey)
|
identity := primitives.InitializeIdentity(profile.Name, &profile.Ed25519PrivateKey, &profile.Ed25519PublicKey)
|
||||||
engine := connections.NewProtocolEngine(identity, profile.Ed25519PrivateKey, as.acn, as.eventBuses[profile.Onion], profile.GetContacts(), blockedPeers)
|
engine := connections.NewProtocolEngine(identity, profile.Ed25519PrivateKey, as.acn, as.eventBuses[profile.Onion], peerAuthorizations)
|
||||||
as.asmutex.Lock()
|
as.asmutex.Lock()
|
||||||
as.storage[profile.Onion] = profileStore
|
as.storage[profile.Onion] = profileStore
|
||||||
as.engines[profile.Onion] = engine
|
as.engines[profile.Onion] = engine
|
||||||
|
|
|
@ -48,7 +48,6 @@ var suggestionsSelectedProfile = []prompt.Suggest{
|
||||||
/*{Text: "/list-servers", Description: "retrieve a list of servers and their connection status"},
|
/*{Text: "/list-servers", Description: "retrieve a list of servers and their connection status"},
|
||||||
{Text: "/list-peers", Description: "retrieve a list of peers and their connection status"},*/
|
{Text: "/list-peers", Description: "retrieve a list of peers and their connection status"},*/
|
||||||
{Text: "/export-group", Description: "export a group invite: prints as a string"},
|
{Text: "/export-group", Description: "export a group invite: prints as a string"},
|
||||||
{Text: "/trust", Description: "trust a peer"},
|
|
||||||
{Text: "/block", Description: "block a peer - you will no longer see messages or connect to this peer"},
|
{Text: "/block", Description: "block a peer - you will no longer see messages or connect to this peer"},
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -411,7 +410,7 @@ func main() {
|
||||||
// think over.
|
// think over.
|
||||||
for _, name := range p.GetContacts() {
|
for _, name := range p.GetContacts() {
|
||||||
profile := p.GetContact(name)
|
profile := p.GetContact(name)
|
||||||
if profile.Trusted && !profile.Blocked {
|
if profile.Authorization == model.AuthApproved {
|
||||||
p.PeerWithOnion(profile.Onion)
|
p.PeerWithOnion(profile.Onion)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -453,22 +452,16 @@ func main() {
|
||||||
contacts := peer.GetContacts()
|
contacts := peer.GetContacts()
|
||||||
for _, onion := range contacts {
|
for _, onion := range contacts {
|
||||||
c := peer.GetContact(onion)
|
c := peer.GetContact(onion)
|
||||||
fmt.Printf("Name: %v Onion: %v Trusted: %v\n", c.Name, c.Onion, c.Trusted)
|
fmt.Printf("Name: %v Onion: %v Authorization: %v\n", c.Name, c.Onion, c.Authorization)
|
||||||
}
|
}
|
||||||
case "/list-groups":
|
case "/list-groups":
|
||||||
for _, gid := range peer.GetGroups() {
|
for _, gid := range peer.GetGroups() {
|
||||||
g := peer.GetGroup(gid)
|
g := peer.GetGroup(gid)
|
||||||
fmt.Printf("Group Id: %v Owner: %v Accepted:%v\n", gid, g.Owner, g.Accepted)
|
fmt.Printf("Group Id: %v Owner: %v Accepted:%v\n", gid, g.Owner, g.Accepted)
|
||||||
}
|
}
|
||||||
case "/trust":
|
|
||||||
if len(commands) == 2 {
|
|
||||||
peer.TrustPeer(commands[1])
|
|
||||||
} else {
|
|
||||||
fmt.Printf("Error trusting peer, usage: %s\n", usages[commands[0]])
|
|
||||||
}
|
|
||||||
case "/block":
|
case "/block":
|
||||||
if len(commands) == 2 {
|
if len(commands) == 2 {
|
||||||
peer.BlockPeer(commands[1])
|
peer.SetContactAuthorization(commands[1], model.AuthBlocked)
|
||||||
} else {
|
} else {
|
||||||
fmt.Printf("Error blocking peer, usage: %s\n", usages[commands[0]])
|
fmt.Printf("Error blocking peer, usage: %s\n", usages[commands[0]])
|
||||||
}
|
}
|
||||||
|
|
|
@ -19,11 +19,9 @@ const (
|
||||||
// RemotePeer: [eg "chpr7qm6op5vfcg2pi4vllco3h6aa7exexc4rqwnlupqhoogx2zgd6qd"
|
// RemotePeer: [eg "chpr7qm6op5vfcg2pi4vllco3h6aa7exexc4rqwnlupqhoogx2zgd6qd"
|
||||||
RetryPeerRequest = Type("RetryPeerRequest")
|
RetryPeerRequest = Type("RetryPeerRequest")
|
||||||
|
|
||||||
// Blocking Events both Block and Unblock have the same structure
|
// RemotePeer
|
||||||
// attributes:
|
// Authorization(model.peer.Auth_...)
|
||||||
// RemotePeer: [eg "chpr7qm6op5vfcg2pi4vllco3h6aa7exexc4rqwnlupqhoogx2zgd6qd"
|
SetPeerAuthorization = Type("UpdatePeerAuthorization")
|
||||||
BlockPeer = Type("BlockPeer")
|
|
||||||
UnblockPeer = Type("UnblockPeer")
|
|
||||||
|
|
||||||
// Turn on/off blocking of unknown peers (if peers aren't in the contact list then they will be autoblocked
|
// Turn on/off blocking of unknown peers (if peers aren't in the contact list then they will be autoblocked
|
||||||
BlockUnknownPeers = Type("BlockUnknownPeers")
|
BlockUnknownPeers = Type("BlockUnknownPeers")
|
||||||
|
@ -92,6 +90,7 @@ const (
|
||||||
// a peer contact has been added
|
// a peer contact has been added
|
||||||
// attributes:
|
// attributes:
|
||||||
// RemotePeer [eg ""]
|
// RemotePeer [eg ""]
|
||||||
|
// Authorization
|
||||||
PeerCreated = Type("PeerCreated")
|
PeerCreated = Type("PeerCreated")
|
||||||
|
|
||||||
// Password, NewPassword
|
// Password, NewPassword
|
||||||
|
@ -244,6 +243,8 @@ const (
|
||||||
Status = Field("Status")
|
Status = Field("Status")
|
||||||
EventID = Field("EventID")
|
EventID = Field("EventID")
|
||||||
EventContext = Field("EventContext")
|
EventContext = Field("EventContext")
|
||||||
|
|
||||||
|
Authorization = Field("Authorization")
|
||||||
)
|
)
|
||||||
|
|
||||||
// Defining Common errors
|
// Defining Common errors
|
||||||
|
|
3
go.mod
3
go.mod
|
@ -4,7 +4,7 @@ go 1.14
|
||||||
|
|
||||||
require (
|
require (
|
||||||
cwtch.im/tapir v0.1.18
|
cwtch.im/tapir v0.1.18
|
||||||
git.openprivacy.ca/openprivacy/connectivity v1.1.1
|
git.openprivacy.ca/openprivacy/connectivity v1.1.2
|
||||||
git.openprivacy.ca/openprivacy/libricochet-go v1.0.13
|
git.openprivacy.ca/openprivacy/libricochet-go v1.0.13
|
||||||
git.openprivacy.ca/openprivacy/log v1.0.0
|
git.openprivacy.ca/openprivacy/log v1.0.0
|
||||||
github.com/c-bata/go-prompt v0.2.3
|
github.com/c-bata/go-prompt v0.2.3
|
||||||
|
@ -19,7 +19,6 @@ require (
|
||||||
golang.org/x/crypto v0.0.0-20200420104511-884d27f42877
|
golang.org/x/crypto v0.0.0-20200420104511-884d27f42877
|
||||||
golang.org/x/net v0.0.0-20200324143707-d3edc9973b7e
|
golang.org/x/net v0.0.0-20200324143707-d3edc9973b7e
|
||||||
golang.org/x/sys v0.0.0-20200331124033-c3d80250170d // indirect
|
golang.org/x/sys v0.0.0-20200331124033-c3d80250170d // indirect
|
||||||
golang.org/x/tools v0.0.0-20200420001825-978e26b7c37c // indirect
|
|
||||||
gopkg.in/check.v1 v1.0.0-20200227125254-8fa46927fb4f // indirect
|
gopkg.in/check.v1 v1.0.0-20200227125254-8fa46927fb4f // indirect
|
||||||
google.golang.org/genproto v0.0.0-20180831171423-11092d34479b // indirect
|
google.golang.org/genproto v0.0.0-20180831171423-11092d34479b // indirect
|
||||||
)
|
)
|
||||||
|
|
2
go.sum
2
go.sum
|
@ -3,6 +3,8 @@ cwtch.im/tapir v0.1.18/go.mod h1:/IrAI6CBHfgzsfgRT8WHVb1P9fCCz7+45hfsdkKn8Zg=
|
||||||
git.openprivacy.ca/openprivacy/connectivity v1.1.0/go.mod h1:4P8mirZZslKbo2zBrXXVjgEdqGwHo/6qoFBwFQW6d6E=
|
git.openprivacy.ca/openprivacy/connectivity v1.1.0/go.mod h1:4P8mirZZslKbo2zBrXXVjgEdqGwHo/6qoFBwFQW6d6E=
|
||||||
git.openprivacy.ca/openprivacy/connectivity v1.1.1 h1:hKxBOmxP7Jdu3K1BJ93mRtKNiWUoP6YHt/o2snE2Z0w=
|
git.openprivacy.ca/openprivacy/connectivity v1.1.1 h1:hKxBOmxP7Jdu3K1BJ93mRtKNiWUoP6YHt/o2snE2Z0w=
|
||||||
git.openprivacy.ca/openprivacy/connectivity v1.1.1/go.mod h1:4P8mirZZslKbo2zBrXXVjgEdqGwHo/6qoFBwFQW6d6E=
|
git.openprivacy.ca/openprivacy/connectivity v1.1.1/go.mod h1:4P8mirZZslKbo2zBrXXVjgEdqGwHo/6qoFBwFQW6d6E=
|
||||||
|
git.openprivacy.ca/openprivacy/connectivity v1.1.2 h1:Bk8ul3+4/awpQGvskfLpp7/K3Lj8OAxBwlmQqeZy3Ok=
|
||||||
|
git.openprivacy.ca/openprivacy/connectivity v1.1.2/go.mod h1:4P8mirZZslKbo2zBrXXVjgEdqGwHo/6qoFBwFQW6d6E=
|
||||||
git.openprivacy.ca/openprivacy/libricochet-go v1.0.13 h1:Z86uL9K47onznY1wP1P/wWfWMbbyvk6xnCp94R180os=
|
git.openprivacy.ca/openprivacy/libricochet-go v1.0.13 h1:Z86uL9K47onznY1wP1P/wWfWMbbyvk6xnCp94R180os=
|
||||||
git.openprivacy.ca/openprivacy/libricochet-go v1.0.13/go.mod h1:ZUuX1SOrgV4K18IEcp0hQJNPKszRr2oGb3UeK2iYe5U=
|
git.openprivacy.ca/openprivacy/libricochet-go v1.0.13/go.mod h1:ZUuX1SOrgV4K18IEcp0hQJNPKszRr2oGb3UeK2iYe5U=
|
||||||
git.openprivacy.ca/openprivacy/log v1.0.0 h1:Rvqm1weUdR4AOnJ79b1upHCc9vC/QF1rhSD2Um7sr1Y=
|
git.openprivacy.ca/openprivacy/log v1.0.0 h1:Rvqm1weUdR4AOnJ79b1upHCc9vC/QF1rhSD2Um7sr1Y=
|
||||||
|
|
|
@ -18,12 +18,24 @@ import (
|
||||||
"time"
|
"time"
|
||||||
)
|
)
|
||||||
|
|
||||||
|
// Authorization is a type determining client assigned authorization to a peer
|
||||||
|
type Authorization string
|
||||||
|
|
||||||
|
const (
|
||||||
|
// AuthUnknown is an inital state for a new unseen peer
|
||||||
|
AuthUnknown Authorization = "unknown"
|
||||||
|
// AuthApproved means the client has approved the peer, it can send messages to us, perform GetVals, etc
|
||||||
|
AuthApproved Authorization = "approved"
|
||||||
|
// AuthBlocked means the client has blocked the peer, it's messages and connections should be rejected
|
||||||
|
AuthBlocked Authorization = "blocked"
|
||||||
|
)
|
||||||
|
|
||||||
// PublicProfile is a local copy of a CwtchIdentity
|
// PublicProfile is a local copy of a CwtchIdentity
|
||||||
type PublicProfile struct {
|
type PublicProfile struct {
|
||||||
Name string
|
Name string
|
||||||
Ed25519PublicKey ed25519.PublicKey
|
Ed25519PublicKey ed25519.PublicKey
|
||||||
Trusted bool
|
Authorization Authorization
|
||||||
Blocked bool
|
DeprecatedBlocked bool `json:"Blocked"`
|
||||||
Onion string
|
Onion string
|
||||||
Attributes map[string]string
|
Attributes map[string]string
|
||||||
Timeline Timeline `json:"-"`
|
Timeline Timeline `json:"-"`
|
||||||
|
@ -239,64 +251,38 @@ func (p *Profile) GetContacts() []string {
|
||||||
return keys
|
return keys
|
||||||
}
|
}
|
||||||
|
|
||||||
// BlockPeer blocks a contact
|
// SetContactAuthorization sets the authoirization level of a peer
|
||||||
func (p *Profile) BlockPeer(onion string) (err error) {
|
func (p *Profile) SetContactAuthorization(onion string, auth Authorization) (err error) {
|
||||||
p.lock.Lock()
|
p.lock.Lock()
|
||||||
defer p.lock.Unlock()
|
defer p.lock.Unlock()
|
||||||
contact, ok := p.Contacts[onion]
|
contact, ok := p.Contacts[onion]
|
||||||
if ok {
|
if ok {
|
||||||
contact.Blocked = true
|
contact.Authorization = auth
|
||||||
} else {
|
} else {
|
||||||
err = errors.New("peer does not exist")
|
err = errors.New("peer does not exist")
|
||||||
}
|
}
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
// UnblockPeer unblocks a contact
|
// GetContactAuthorization returns the contact's authorization level
|
||||||
func (p *Profile) UnblockPeer(onion string) (err error) {
|
func (p *Profile) GetContactAuthorization(onion string) Authorization {
|
||||||
p.lock.Lock()
|
p.lock.Lock()
|
||||||
defer p.lock.Unlock()
|
defer p.lock.Unlock()
|
||||||
contact, ok := p.Contacts[onion]
|
contact, ok := p.Contacts[onion]
|
||||||
if ok {
|
if ok {
|
||||||
contact.Blocked = false
|
return contact.Authorization
|
||||||
} else {
|
|
||||||
err = errors.New("peer does not exist")
|
|
||||||
}
|
}
|
||||||
return
|
return AuthUnknown
|
||||||
}
|
}
|
||||||
|
|
||||||
// BlockedPeers calculates a list of Peers who have been Blocked.
|
// ContactsAuthorizations calculates a list of Peers who are at the supplied auth levels
|
||||||
func (p *Profile) BlockedPeers() []string {
|
func (p *Profile) ContactsAuthorizations(authorizationFilter ...Authorization) map[string]Authorization {
|
||||||
blockedPeers := []string{}
|
authorizations := map[string]Authorization{}
|
||||||
for _, contact := range p.GetContacts() {
|
for _, contact := range p.GetContacts() {
|
||||||
c, _ := p.GetContact(contact)
|
c, _ := p.GetContact(contact)
|
||||||
if c.Blocked {
|
authorizations[c.Onion] = c.Authorization
|
||||||
blockedPeers = append(blockedPeers, c.Onion)
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
return blockedPeers
|
return authorizations
|
||||||
}
|
|
||||||
|
|
||||||
// TrustPeer sets a contact to trusted
|
|
||||||
func (p *Profile) TrustPeer(onion string) (err error) {
|
|
||||||
p.lock.Lock()
|
|
||||||
defer p.lock.Unlock()
|
|
||||||
contact, ok := p.Contacts[onion]
|
|
||||||
if ok {
|
|
||||||
contact.Trusted = true
|
|
||||||
} else {
|
|
||||||
err = errors.New("peer does not exist")
|
|
||||||
}
|
|
||||||
return
|
|
||||||
}
|
|
||||||
|
|
||||||
// IsBlocked returns true if the contact has been blocked, false otherwise
|
|
||||||
func (p *Profile) IsBlocked(onion string) bool {
|
|
||||||
contact, ok := p.GetContact(onion)
|
|
||||||
if ok {
|
|
||||||
return contact.Blocked
|
|
||||||
}
|
|
||||||
return false
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// GetContact returns a contact if the profile has it
|
// GetContact returns a contact if the profile has it
|
||||||
|
|
|
@ -31,13 +31,9 @@ func TestTrustPeer(t *testing.T) {
|
||||||
alice := GenerateNewProfile("Alice")
|
alice := GenerateNewProfile("Alice")
|
||||||
sarah.AddContact(alice.Onion, &alice.PublicProfile)
|
sarah.AddContact(alice.Onion, &alice.PublicProfile)
|
||||||
alice.AddContact(sarah.Onion, &sarah.PublicProfile)
|
alice.AddContact(sarah.Onion, &sarah.PublicProfile)
|
||||||
alice.TrustPeer(sarah.Onion)
|
alice.SetContactAuthorization(sarah.Onion, AuthApproved)
|
||||||
if alice.IsBlocked(sarah.Onion) {
|
if alice.GetContactAuthorization(sarah.Onion) != AuthApproved {
|
||||||
t.Errorf("peer should not be blocked")
|
t.Errorf("peer should be approved")
|
||||||
}
|
|
||||||
|
|
||||||
if alice.TrustPeer("") == nil {
|
|
||||||
t.Errorf("trusting a non existent peer should error")
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -46,13 +42,13 @@ func TestBlockPeer(t *testing.T) {
|
||||||
alice := GenerateNewProfile("Alice")
|
alice := GenerateNewProfile("Alice")
|
||||||
sarah.AddContact(alice.Onion, &alice.PublicProfile)
|
sarah.AddContact(alice.Onion, &alice.PublicProfile)
|
||||||
alice.AddContact(sarah.Onion, &sarah.PublicProfile)
|
alice.AddContact(sarah.Onion, &sarah.PublicProfile)
|
||||||
alice.BlockPeer(sarah.Onion)
|
alice.SetContactAuthorization(sarah.Onion, AuthBlocked)
|
||||||
if !alice.IsBlocked(sarah.Onion) {
|
if alice.GetContactAuthorization(sarah.Onion) != AuthBlocked {
|
||||||
t.Errorf("peer should not be blocked")
|
t.Errorf("peer should be blocked")
|
||||||
}
|
}
|
||||||
|
|
||||||
if alice.BlockPeer("") == nil {
|
if alice.SetContactAuthorization("", AuthUnknown) == nil {
|
||||||
t.Errorf("blocking a non existent peer should error")
|
t.Errorf("Seting Auth level of a non existent peer should error")
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -41,9 +41,7 @@ type CwtchPeer interface {
|
||||||
SendMessageToPeer(string, string) string
|
SendMessageToPeer(string, string) string
|
||||||
SendGetValToPeer(string, string, string)
|
SendGetValToPeer(string, string, string)
|
||||||
|
|
||||||
TrustPeer(string) error
|
SetContactAuthorization(string, model.Authorization) error
|
||||||
BlockPeer(string) error
|
|
||||||
UnblockPeer(string) error
|
|
||||||
ProcessInvite(string, string) (string, error)
|
ProcessInvite(string, string) (string, error)
|
||||||
AcceptInvite(string) error
|
AcceptInvite(string) error
|
||||||
RejectInvite(string)
|
RejectInvite(string)
|
||||||
|
@ -68,7 +66,7 @@ type CwtchPeer interface {
|
||||||
GetGroup(string) *model.Group
|
GetGroup(string) *model.Group
|
||||||
GetGroupState(string) (connections.ConnectionState, bool)
|
GetGroupState(string) (connections.ConnectionState, bool)
|
||||||
GetGroups() []string
|
GetGroups() []string
|
||||||
AddContact(nick, onion string, trusted bool)
|
AddContact(nick, onion string, authorization model.Authorization)
|
||||||
GetContacts() []string
|
GetContacts() []string
|
||||||
GetContact(string) *model.PublicProfile
|
GetContact(string) *model.PublicProfile
|
||||||
|
|
||||||
|
@ -191,17 +189,16 @@ func (cp *cwtchPeer) GetGroup(groupID string) *model.Group {
|
||||||
return cp.Profile.GetGroup(groupID)
|
return cp.Profile.GetGroup(groupID)
|
||||||
}
|
}
|
||||||
|
|
||||||
func (cp *cwtchPeer) AddContact(nick, onion string, trusted bool) {
|
func (cp *cwtchPeer) AddContact(nick, onion string, authorization model.Authorization) {
|
||||||
decodedPub, _ := base32.StdEncoding.DecodeString(strings.ToUpper(onion))
|
decodedPub, _ := base32.StdEncoding.DecodeString(strings.ToUpper(onion))
|
||||||
pp := &model.PublicProfile{Name: nick, Ed25519PublicKey: decodedPub, Trusted: trusted, Blocked: false, Onion: onion, Attributes: map[string]string{"nick": nick}}
|
pp := &model.PublicProfile{Name: nick, Ed25519PublicKey: decodedPub, Authorization: authorization, Onion: onion, Attributes: map[string]string{"nick": nick}}
|
||||||
cp.mutex.Lock()
|
|
||||||
cp.Profile.AddContact(onion, pp)
|
cp.Profile.AddContact(onion, pp)
|
||||||
cp.mutex.Unlock()
|
|
||||||
pd, _ := json.Marshal(pp)
|
pd, _ := json.Marshal(pp)
|
||||||
cp.eventBus.Publish(event.NewEvent(event.PeerCreated, map[event.Field]string{
|
cp.eventBus.Publish(event.NewEvent(event.PeerCreated, map[event.Field]string{
|
||||||
event.Data: string(pd),
|
event.Data: string(pd),
|
||||||
event.RemotePeer: onion,
|
event.RemotePeer: onion,
|
||||||
}))
|
}))
|
||||||
|
cp.eventBus.Publish(event.NewEventList(event.SetPeerAuthorization, event.RemotePeer, onion, event.Authorization, string(authorization)))
|
||||||
}
|
}
|
||||||
|
|
||||||
// GetContacts returns an unordered list of onions
|
// GetContacts returns an unordered list of onions
|
||||||
|
@ -257,10 +254,10 @@ func (cp *cwtchPeer) GetGroupState(groupid string) (connections.ConnectionState,
|
||||||
// PeerWithOnion is the entry point for cwtchPeer relationships
|
// PeerWithOnion is the entry point for cwtchPeer relationships
|
||||||
func (cp *cwtchPeer) PeerWithOnion(onion string) {
|
func (cp *cwtchPeer) PeerWithOnion(onion string) {
|
||||||
cp.mutex.Lock()
|
cp.mutex.Lock()
|
||||||
if _, exists := cp.Profile.GetContact(onion); !exists {
|
|
||||||
cp.AddContact(onion, onion, false)
|
|
||||||
}
|
|
||||||
defer cp.mutex.Unlock()
|
defer cp.mutex.Unlock()
|
||||||
|
if _, exists := cp.Profile.GetContact(onion); !exists {
|
||||||
|
cp.AddContact(onion, onion, model.AuthApproved)
|
||||||
|
}
|
||||||
cp.eventBus.Publish(event.NewEvent(event.PeerRequest, map[event.Field]string{event.RemotePeer: onion}))
|
cp.eventBus.Publish(event.NewEvent(event.PeerRequest, map[event.Field]string{event.RemotePeer: onion}))
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -343,32 +340,12 @@ func (cp *cwtchPeer) SendGetValToPeer(onion string, scope string, path string) {
|
||||||
cp.eventBus.Publish(event)
|
cp.eventBus.Publish(event)
|
||||||
}
|
}
|
||||||
|
|
||||||
// TrustPeer sets an existing peer relationship to trusted
|
|
||||||
func (cp *cwtchPeer) TrustPeer(peer string) error {
|
|
||||||
cp.mutex.Lock()
|
|
||||||
defer cp.mutex.Unlock()
|
|
||||||
err := cp.Profile.TrustPeer(peer)
|
|
||||||
if err == nil {
|
|
||||||
cp.PeerWithOnion(peer)
|
|
||||||
}
|
|
||||||
return err
|
|
||||||
}
|
|
||||||
|
|
||||||
// BlockPeer blocks an existing peer relationship.
|
// BlockPeer blocks an existing peer relationship.
|
||||||
func (cp *cwtchPeer) BlockPeer(peer string) error {
|
func (cp *cwtchPeer) SetContactAuthorization(peer string, authorization model.Authorization) error {
|
||||||
cp.mutex.Lock()
|
cp.mutex.Lock()
|
||||||
err := cp.Profile.BlockPeer(peer)
|
err := cp.Profile.SetContactAuthorization(peer, authorization)
|
||||||
cp.mutex.Unlock()
|
cp.mutex.Unlock()
|
||||||
cp.eventBus.Publish(event.NewEvent(event.BlockPeer, map[event.Field]string{event.RemotePeer: peer}))
|
cp.eventBus.Publish(event.NewEvent(event.SetPeerAuthorization, map[event.Field]string{event.RemotePeer: peer, event.Authorization: string(authorization)}))
|
||||||
return err
|
|
||||||
}
|
|
||||||
|
|
||||||
// UnblockPeer blocks an existing peer relationship.
|
|
||||||
func (cp *cwtchPeer) UnblockPeer(peer string) error {
|
|
||||||
cp.mutex.Lock()
|
|
||||||
err := cp.Profile.UnblockPeer(peer)
|
|
||||||
cp.mutex.Unlock()
|
|
||||||
cp.eventBus.Publish(event.NewEvent(event.UnblockPeer, map[event.Field]string{event.RemotePeer: peer}))
|
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -82,7 +82,9 @@ func (x *ChannelResult_CommonError) UnmarshalJSON(data []byte) error {
|
||||||
*x = ChannelResult_CommonError(value)
|
*x = ChannelResult_CommonError(value)
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
func (ChannelResult_CommonError) EnumDescriptor() ([]byte, []int) { return fileDescriptor0, []int{2, 0} }
|
func (ChannelResult_CommonError) EnumDescriptor() ([]byte, []int) {
|
||||||
|
return fileDescriptor0, []int{2, 0}
|
||||||
|
}
|
||||||
|
|
||||||
type Packet struct {
|
type Packet struct {
|
||||||
// Must contain exactly one field
|
// Must contain exactly one field
|
||||||
|
|
|
@ -2,6 +2,7 @@ package connections
|
||||||
|
|
||||||
import (
|
import (
|
||||||
"cwtch.im/cwtch/event"
|
"cwtch.im/cwtch/event"
|
||||||
|
"cwtch.im/cwtch/model"
|
||||||
"cwtch.im/cwtch/protocol"
|
"cwtch.im/cwtch/protocol"
|
||||||
"cwtch.im/tapir"
|
"cwtch.im/tapir"
|
||||||
"cwtch.im/tapir/networks/tor"
|
"cwtch.im/tapir/networks/tor"
|
||||||
|
@ -28,8 +29,8 @@ type engine struct {
|
||||||
// Engine State
|
// Engine State
|
||||||
started bool
|
started bool
|
||||||
|
|
||||||
// Blocklist
|
// Authorization list of contacts to authorization status
|
||||||
blocked sync.Map
|
authorizations sync.Map // string(onion) => model.Authorization
|
||||||
|
|
||||||
// Block Unknown Contacts
|
// Block Unknown Contacts
|
||||||
blockUnknownContacts bool
|
blockUnknownContacts bool
|
||||||
|
@ -55,7 +56,7 @@ type Engine interface {
|
||||||
}
|
}
|
||||||
|
|
||||||
// NewProtocolEngine initializes a new engine that runs Cwtch using the given parameters
|
// NewProtocolEngine initializes a new engine that runs Cwtch using the given parameters
|
||||||
func NewProtocolEngine(identity primitives.Identity, privateKey ed25519.PrivateKey, acn connectivity.ACN, eventManager event.Manager, knownPeers []string, blockedPeers []string) Engine {
|
func NewProtocolEngine(identity primitives.Identity, privateKey ed25519.PrivateKey, acn connectivity.ACN, eventManager event.Manager, peerAuthorizations map[string]model.Authorization) Engine {
|
||||||
engine := new(engine)
|
engine := new(engine)
|
||||||
engine.identity = identity
|
engine.identity = identity
|
||||||
engine.privateKey = privateKey
|
engine.privateKey = privateKey
|
||||||
|
@ -83,17 +84,12 @@ func NewProtocolEngine(identity primitives.Identity, privateKey ed25519.PrivateK
|
||||||
engine.eventManager.Subscribe(event.DeleteContact, engine.queue)
|
engine.eventManager.Subscribe(event.DeleteContact, engine.queue)
|
||||||
engine.eventManager.Subscribe(event.DeleteGroup, engine.queue)
|
engine.eventManager.Subscribe(event.DeleteGroup, engine.queue)
|
||||||
|
|
||||||
engine.eventManager.Subscribe(event.BlockPeer, engine.queue)
|
engine.eventManager.Subscribe(event.SetPeerAuthorization, engine.queue)
|
||||||
engine.eventManager.Subscribe(event.UnblockPeer, engine.queue)
|
|
||||||
engine.eventManager.Subscribe(event.BlockUnknownPeers, engine.queue)
|
engine.eventManager.Subscribe(event.BlockUnknownPeers, engine.queue)
|
||||||
engine.eventManager.Subscribe(event.AllowUnknownPeers, engine.queue)
|
engine.eventManager.Subscribe(event.AllowUnknownPeers, engine.queue)
|
||||||
|
|
||||||
for _, peer := range knownPeers {
|
for peer, authorization := range peerAuthorizations {
|
||||||
engine.blocked.Store(peer, false)
|
engine.authorizations.Store(peer, authorization)
|
||||||
}
|
|
||||||
|
|
||||||
for _, peer := range blockedPeers {
|
|
||||||
engine.blocked.Store(peer, true)
|
|
||||||
}
|
}
|
||||||
return engine
|
return engine
|
||||||
}
|
}
|
||||||
|
@ -115,7 +111,6 @@ func (e *engine) eventHandler() {
|
||||||
e.eventManager.Publish(event.Event{EventType: event.ProtocolEngineStatus, EventID: ev.EventID})
|
e.eventManager.Publish(event.Event{EventType: event.ProtocolEngineStatus, EventID: ev.EventID})
|
||||||
case event.PeerRequest:
|
case event.PeerRequest:
|
||||||
if torProdider.IsValidHostname(ev.Data[event.RemotePeer]) {
|
if torProdider.IsValidHostname(ev.Data[event.RemotePeer]) {
|
||||||
e.blocked.Store(ev.Data[event.RemotePeer], false)
|
|
||||||
go e.peerWithOnion(ev.Data[event.RemotePeer])
|
go e.peerWithOnion(ev.Data[event.RemotePeer])
|
||||||
}
|
}
|
||||||
case event.RetryPeerRequest:
|
case event.RetryPeerRequest:
|
||||||
|
@ -131,7 +126,7 @@ func (e *engine) eventHandler() {
|
||||||
case event.DeleteContact:
|
case event.DeleteContact:
|
||||||
onion := ev.Data[event.RemotePeer]
|
onion := ev.Data[event.RemotePeer]
|
||||||
// We remove this peer from out blocklist which will prevent them from contacting us if we have "block unknown peers" turned on.
|
// We remove this peer from out blocklist which will prevent them from contacting us if we have "block unknown peers" turned on.
|
||||||
e.blocked.Delete(ev.Data[event.RemotePeer])
|
e.authorizations.Delete(ev.Data[event.RemotePeer])
|
||||||
e.deleteConnection(onion)
|
e.deleteConnection(onion)
|
||||||
case event.DeleteGroup:
|
case event.DeleteGroup:
|
||||||
// TODO: There isn't a way here to determine if other Groups are using a server connection...
|
// TODO: There isn't a way here to determine if other Groups are using a server connection...
|
||||||
|
@ -151,21 +146,19 @@ func (e *engine) eventHandler() {
|
||||||
e.sendGetValToPeer(ev.EventID, ev.Data[event.RemotePeer], ev.Data[event.Scope], ev.Data[event.Path])
|
e.sendGetValToPeer(ev.EventID, ev.Data[event.RemotePeer], ev.Data[event.Scope], ev.Data[event.Path])
|
||||||
case event.SendRetValMessageToPeer:
|
case event.SendRetValMessageToPeer:
|
||||||
e.sendRetValToPeer(ev.EventID, ev.Data[event.RemotePeer], ev.Data[event.Data], ev.Data[event.Exists])
|
e.sendRetValToPeer(ev.EventID, ev.Data[event.RemotePeer], ev.Data[event.Data], ev.Data[event.Exists])
|
||||||
case event.UnblockPeer:
|
case event.SetPeerAuthorization:
|
||||||
// We simply remove the peer from our blocklist
|
auth := model.Authorization(ev.Data[event.Authorization])
|
||||||
// The UI has the responsibility to reinitiate contact with the peer.
|
e.authorizations.Store(ev.Data[event.RemotePeer], auth)
|
||||||
// (this should happen periodically in any case)
|
if auth == model.AuthBlocked {
|
||||||
e.blocked.Store(ev.Data[event.RemotePeer], false)
|
connection, err := e.service.GetConnection(ev.Data[event.RemotePeer])
|
||||||
case event.BlockPeer:
|
if connection != nil && err == nil {
|
||||||
e.blocked.Store(ev.Data[event.RemotePeer], true)
|
connection.Close()
|
||||||
connection, err := e.service.GetConnection(ev.Data[event.RemotePeer])
|
}
|
||||||
if connection != nil && err == nil {
|
// Explicitly send a disconnected event (if we don't do this here then the UI can wait for a while before
|
||||||
connection.Close()
|
// an ongoing Open() connection fails and so the user will see a blocked peer as still connecting (because
|
||||||
|
// there isn't an active connection and we are stuck waiting for tor to time out)
|
||||||
|
e.peerDisconnected(ev.Data[event.RemotePeer])
|
||||||
}
|
}
|
||||||
// Explicitly send a disconnected event (if we don't do this here then the UI can wait for a while before
|
|
||||||
// an ongoing Open() connection fails and so the user will see a blocked peer as still connecting (because
|
|
||||||
// there isn't an active connection and we are stuck waiting for tor to time out)
|
|
||||||
e.peerDisconnected(ev.Data[event.RemotePeer])
|
|
||||||
case event.AllowUnknownPeers:
|
case event.AllowUnknownPeers:
|
||||||
e.blockUnknownContacts = false
|
e.blockUnknownContacts = false
|
||||||
case event.BlockUnknownPeers:
|
case event.BlockUnknownPeers:
|
||||||
|
@ -178,16 +171,27 @@ func (e *engine) eventHandler() {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func (e *engine) isBlocked(onion string) bool {
|
||||||
|
authorization, known := e.authorizations.Load(onion)
|
||||||
|
if !known {
|
||||||
|
// if we block unknown peers we will block this contact
|
||||||
|
return e.blockUnknownContacts
|
||||||
|
}
|
||||||
|
return authorization.(model.Authorization) == model.AuthBlocked
|
||||||
|
}
|
||||||
|
|
||||||
|
func (e *engine) isApproved(onion string) bool {
|
||||||
|
authorization, known := e.authorizations.Load(onion)
|
||||||
|
if !known {
|
||||||
|
return false
|
||||||
|
}
|
||||||
|
return authorization.(model.Authorization) == model.AuthApproved
|
||||||
|
}
|
||||||
|
|
||||||
func (e *engine) createPeerTemplate() *PeerApp {
|
func (e *engine) createPeerTemplate() *PeerApp {
|
||||||
peerAppTemplate := new(PeerApp)
|
peerAppTemplate := new(PeerApp)
|
||||||
peerAppTemplate.IsBlocked = func(onion string) bool {
|
peerAppTemplate.IsBlocked = e.isBlocked
|
||||||
blocked, known := e.blocked.Load(onion)
|
peerAppTemplate.IsApproved = e.isApproved
|
||||||
if !known {
|
|
||||||
// if we block unknown peers we will block this contact
|
|
||||||
return e.blockUnknownContacts
|
|
||||||
}
|
|
||||||
return blocked.(bool)
|
|
||||||
}
|
|
||||||
peerAppTemplate.MessageHandler = e.handlePeerMessage
|
peerAppTemplate.MessageHandler = e.handlePeerMessage
|
||||||
peerAppTemplate.OnAcknowledgement = e.ignoreOnShutdown2(e.peerAck)
|
peerAppTemplate.OnAcknowledgement = e.ignoreOnShutdown2(e.peerAck)
|
||||||
peerAppTemplate.OnAuth = e.ignoreOnShutdown(e.peerAuthed)
|
peerAppTemplate.OnAuth = e.ignoreOnShutdown(e.peerAuthed)
|
||||||
|
@ -217,8 +221,7 @@ func (e *engine) Shutdown() {
|
||||||
// peerWithOnion is the entry point for cwtchPeer relationships
|
// peerWithOnion is the entry point for cwtchPeer relationships
|
||||||
// needs to be run in a goroutine as will block on Open.
|
// needs to be run in a goroutine as will block on Open.
|
||||||
func (e *engine) peerWithOnion(onion string) {
|
func (e *engine) peerWithOnion(onion string) {
|
||||||
blocked, known := e.blocked.Load(onion)
|
if !e.isBlocked(onion) {
|
||||||
if known && !(blocked.(bool)) {
|
|
||||||
e.ignoreOnShutdown(e.peerConnecting)(onion)
|
e.ignoreOnShutdown(e.peerConnecting)(onion)
|
||||||
connected, err := e.service.Connect(onion, e.createPeerTemplate())
|
connected, err := e.service.Connect(onion, e.createPeerTemplate())
|
||||||
|
|
||||||
|
@ -258,6 +261,10 @@ func (e *engine) ignoreOnShutdown2(f func(string, string)) func(string, string)
|
||||||
}
|
}
|
||||||
|
|
||||||
func (e *engine) peerAuthed(onion string) {
|
func (e *engine) peerAuthed(onion string) {
|
||||||
|
_, known := e.authorizations.Load(onion)
|
||||||
|
if !known {
|
||||||
|
e.authorizations.Store(onion, model.AuthUnknown)
|
||||||
|
}
|
||||||
e.eventManager.Publish(event.NewEvent(event.PeerStateChange, map[event.Field]string{
|
e.eventManager.Publish(event.NewEvent(event.PeerStateChange, map[event.Field]string{
|
||||||
event.RemotePeer: string(onion),
|
event.RemotePeer: string(onion),
|
||||||
event.ConnectionState: ConnectionStateName[AUTHENTICATED],
|
event.ConnectionState: ConnectionStateName[AUTHENTICATED],
|
||||||
|
|
|
@ -18,6 +18,7 @@ type PeerApp struct {
|
||||||
MessageHandler func(string, string, string, []byte)
|
MessageHandler func(string, string, string, []byte)
|
||||||
RetValHandler func(string, []byte, []byte)
|
RetValHandler func(string, []byte, []byte)
|
||||||
IsBlocked func(string) bool
|
IsBlocked func(string) bool
|
||||||
|
IsApproved func(string) bool
|
||||||
OnAcknowledgement func(string, string)
|
OnAcknowledgement func(string, string)
|
||||||
OnAuth func(string)
|
OnAuth func(string)
|
||||||
OnClose func(string)
|
OnClose func(string)
|
||||||
|
@ -47,6 +48,7 @@ func (pa *PeerApp) NewInstance() tapir.Application {
|
||||||
newApp := new(PeerApp)
|
newApp := new(PeerApp)
|
||||||
newApp.MessageHandler = pa.MessageHandler
|
newApp.MessageHandler = pa.MessageHandler
|
||||||
newApp.IsBlocked = pa.IsBlocked
|
newApp.IsBlocked = pa.IsBlocked
|
||||||
|
newApp.IsApproved = pa.IsApproved
|
||||||
newApp.OnAcknowledgement = pa.OnAcknowledgement
|
newApp.OnAcknowledgement = pa.OnAcknowledgement
|
||||||
newApp.OnAuth = pa.OnAuth
|
newApp.OnAuth = pa.OnAuth
|
||||||
newApp.OnClose = pa.OnClose
|
newApp.OnClose = pa.OnClose
|
||||||
|
@ -99,10 +101,12 @@ func (pa *PeerApp) listen() {
|
||||||
pa.getValRequests.Delete(peerMessage.ID)
|
pa.getValRequests.Delete(peerMessage.ID)
|
||||||
}
|
}
|
||||||
default:
|
default:
|
||||||
pa.MessageHandler(pa.connection.Hostname(), peerMessage.ID, peerMessage.Context, peerMessage.Data)
|
if pa.IsApproved(pa.connection.Hostname()) {
|
||||||
|
pa.MessageHandler(pa.connection.Hostname(), peerMessage.ID, peerMessage.Context, peerMessage.Data)
|
||||||
|
|
||||||
// Acknowledge the message
|
// Acknowledge the message
|
||||||
pa.SendMessage(PeerMessage{peerMessage.ID, event.ContextAck, []byte{}})
|
pa.SendMessage(PeerMessage{peerMessage.ID, event.ContextAck, []byte{}})
|
||||||
|
}
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
log.Errorf("Error unmarshalling PeerMessage package: %x %v", message, err)
|
log.Errorf("Error unmarshalling PeerMessage package: %x %v", message, err)
|
||||||
|
|
|
@ -78,7 +78,7 @@ func TestPeerServerConnection(t *testing.T) {
|
||||||
onionAddr := identity.Hostname()
|
onionAddr := identity.Hostname()
|
||||||
|
|
||||||
manager := event.NewEventManager()
|
manager := event.NewEventManager()
|
||||||
engine := NewProtocolEngine(identity, priv, connectivity.NewLocalACN(), manager, nil, nil)
|
engine := NewProtocolEngine(identity, priv, connectivity.NewLocalACN(), manager, nil)
|
||||||
|
|
||||||
psc := NewPeerServerConnection(engine, "127.0.0.1:5451|"+onionAddr)
|
psc := NewPeerServerConnection(engine, "127.0.0.1:5451|"+onionAddr)
|
||||||
numcalls := 0
|
numcalls := 0
|
||||||
|
|
|
@ -66,8 +66,7 @@ func (ps *ProfileStoreV1) initProfileWriterStore() {
|
||||||
ps.queue = event.NewQueue()
|
ps.queue = event.NewQueue()
|
||||||
go ps.eventHandler()
|
go ps.eventHandler()
|
||||||
|
|
||||||
ps.eventManager.Subscribe(event.BlockPeer, ps.queue)
|
ps.eventManager.Subscribe(event.SetPeerAuthorization, ps.queue)
|
||||||
ps.eventManager.Subscribe(event.UnblockPeer, ps.queue)
|
|
||||||
ps.eventManager.Subscribe(event.PeerCreated, ps.queue)
|
ps.eventManager.Subscribe(event.PeerCreated, ps.queue)
|
||||||
ps.eventManager.Subscribe(event.GroupCreated, ps.queue)
|
ps.eventManager.Subscribe(event.GroupCreated, ps.queue)
|
||||||
ps.eventManager.Subscribe(event.SetProfileName, ps.queue)
|
ps.eventManager.Subscribe(event.SetProfileName, ps.queue)
|
||||||
|
@ -249,6 +248,18 @@ func (ps *ProfileStoreV1) load() error {
|
||||||
if err == nil {
|
if err == nil {
|
||||||
ps.profile = cp
|
ps.profile = cp
|
||||||
|
|
||||||
|
// TODO 2020.06.09: v1 update, Remove on v2
|
||||||
|
// if we already have the contact it can be assumed "approved" unless blocked
|
||||||
|
for _, contact := range cp.Contacts {
|
||||||
|
if contact.Authorization == "" {
|
||||||
|
if contact.DeprecatedBlocked {
|
||||||
|
contact.Authorization = model.AuthBlocked
|
||||||
|
} else {
|
||||||
|
contact.Authorization = model.AuthApproved
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
for gid, group := range cp.Groups {
|
for gid, group := range cp.Groups {
|
||||||
ss := NewStreamStore(ps.directory, group.LocalID, ps.key)
|
ss := NewStreamStore(ps.directory, group.LocalID, ps.key)
|
||||||
|
|
||||||
|
@ -272,16 +283,9 @@ func (ps *ProfileStoreV1) eventHandler() {
|
||||||
log.Debugf("eventHandler event %v %v\n", ev.EventType, ev.EventID)
|
log.Debugf("eventHandler event %v %v\n", ev.EventType, ev.EventID)
|
||||||
|
|
||||||
switch ev.EventType {
|
switch ev.EventType {
|
||||||
case event.BlockPeer:
|
case event.SetPeerAuthorization:
|
||||||
contact, exists := ps.profile.GetContact(ev.Data[event.RemotePeer])
|
err := ps.profile.SetContactAuthorization(ev.Data[event.RemotePeer], model.Authorization(ev.Data[event.Authorization]))
|
||||||
if exists {
|
if err == nil {
|
||||||
contact.Blocked = true
|
|
||||||
ps.save()
|
|
||||||
}
|
|
||||||
case event.UnblockPeer:
|
|
||||||
contact, exists := ps.profile.GetContact(ev.Data[event.RemotePeer])
|
|
||||||
if exists {
|
|
||||||
contact.Blocked = false
|
|
||||||
ps.save()
|
ps.save()
|
||||||
}
|
}
|
||||||
case event.PeerCreated:
|
case event.PeerCreated:
|
||||||
|
|
|
@ -188,9 +188,11 @@ func TestCwtchPeerIntegration(t *testing.T) {
|
||||||
app.LaunchPeers()
|
app.LaunchPeers()
|
||||||
appClient.LaunchPeers()
|
appClient.LaunchPeers()
|
||||||
|
|
||||||
fmt.Println("Waiting for Alice, Bob, and Carol to connect with onion network...")
|
waitTime := time.Duration(60) * time.Second
|
||||||
time.Sleep(time.Second * 60)
|
t.Logf("** Waiting for Alice, Bob, and Carol to connect with onion network... (%v)\n", waitTime)
|
||||||
|
time.Sleep(waitTime)
|
||||||
numGoRoutinesPostPeerStart := runtime.NumGoroutine()
|
numGoRoutinesPostPeerStart := runtime.NumGoroutine()
|
||||||
|
fmt.Println("** Wait Done!")
|
||||||
|
|
||||||
// ***** Peering, server joining, group creation / invite *****
|
// ***** Peering, server joining, group creation / invite *****
|
||||||
|
|
||||||
|
@ -198,11 +200,9 @@ func TestCwtchPeerIntegration(t *testing.T) {
|
||||||
alice.JoinServer(serverAddr)
|
alice.JoinServer(serverAddr)
|
||||||
|
|
||||||
fmt.Println("Alice peering with Bob...")
|
fmt.Println("Alice peering with Bob...")
|
||||||
alice.AddContact("Bob", bob.GetOnion(), false) // Add contact so we can track connection state
|
|
||||||
alice.PeerWithOnion(bob.GetOnion())
|
alice.PeerWithOnion(bob.GetOnion())
|
||||||
|
|
||||||
fmt.Println("Alice peering with Carol...")
|
fmt.Println("Alice peering with Carol...")
|
||||||
alice.AddContact("Carol", carol.GetOnion(), false)
|
|
||||||
alice.PeerWithOnion(carol.GetOnion())
|
alice.PeerWithOnion(carol.GetOnion())
|
||||||
|
|
||||||
fmt.Println("Creating group on ", serverAddr, "...")
|
fmt.Println("Creating group on ", serverAddr, "...")
|
||||||
|
@ -218,9 +218,15 @@ func TestCwtchPeerIntegration(t *testing.T) {
|
||||||
|
|
||||||
fmt.Println("Waiting for alice and Bob to peer...")
|
fmt.Println("Waiting for alice and Bob to peer...")
|
||||||
waitForPeerPeerConnection(t, alice, bob)
|
waitForPeerPeerConnection(t, alice, bob)
|
||||||
bob.AddContact("alice?", alice.GetOnion(), true)
|
// Need to add contact else SetContactAuth fails on peer peer doesnt exist
|
||||||
|
// Normal flow would be Bob app monitors for the new connection (a new connection state change to Auth
|
||||||
|
// and the adds the user to peer, and then approves or blocks it
|
||||||
|
bob.AddContact("alice?", alice.GetOnion(), model.AuthApproved)
|
||||||
|
bob.SetContactAuthorization(alice.GetOnion(), model.AuthApproved)
|
||||||
|
|
||||||
waitForPeerPeerConnection(t, alice, carol)
|
waitForPeerPeerConnection(t, alice, carol)
|
||||||
carol.AddContact("alice?", alice.GetOnion(), true)
|
carol.AddContact("alice?", alice.GetOnion(), model.AuthApproved)
|
||||||
|
carol.SetContactAuthorization(alice.GetOnion(), model.AuthApproved)
|
||||||
|
|
||||||
fmt.Println("Alice and Bob getVal public.name...")
|
fmt.Println("Alice and Bob getVal public.name...")
|
||||||
|
|
||||||
|
@ -234,13 +240,13 @@ func TestCwtchPeerIntegration(t *testing.T) {
|
||||||
|
|
||||||
aliceName, exists := bob.GetContactAttribute(alice.GetOnion(), attr.GetPeerScope("name"))
|
aliceName, exists := bob.GetContactAttribute(alice.GetOnion(), attr.GetPeerScope("name"))
|
||||||
if !exists || aliceName != "Alice" {
|
if !exists || aliceName != "Alice" {
|
||||||
t.Fatalf("alice GetKeyVal error on alice peer.name %v\n", exists)
|
t.Fatalf("Bob: alice GetKeyVal error on alice peer.name %v\n", exists)
|
||||||
}
|
}
|
||||||
fmt.Printf("Bob has alice's name as '%v'\n", aliceName)
|
fmt.Printf("Bob has alice's name as '%v'\n", aliceName)
|
||||||
|
|
||||||
bobName, exists := alice.GetContactAttribute(bob.GetOnion(), attr.GetPeerScope("name"))
|
bobName, exists := alice.GetContactAttribute(bob.GetOnion(), attr.GetPeerScope("name"))
|
||||||
if !exists || bobName != "Bob" {
|
if !exists || bobName != "Bob" {
|
||||||
t.Fatalf("bob GetKeyVal error, alice peer.name\n")
|
t.Fatalf("Alice: bob GetKeyVal error on bob peer.name\n")
|
||||||
}
|
}
|
||||||
fmt.Printf("Alice has bob's name as '%v'\n", bobName)
|
fmt.Printf("Alice has bob's name as '%v'\n", bobName)
|
||||||
|
|
||||||
|
|
Loading…
Reference in New Issue