diff --git a/model/message_test.go b/model/message_test.go index 06ff7ee..a639d59 100644 --- a/model/message_test.go +++ b/model/message_test.go @@ -23,8 +23,8 @@ func TestMessagePadding(t *testing.T) { group := alice.GetGroupByGroupID(gid) - c1, s1, _ := sarah.EncryptMessageToGroup("Hello World 1", group.GroupID) - t.Logf("Length of Encrypted Message: %v", len(c1)) + c1, s1, err := sarah.EncryptMessageToGroup("Hello World 1", group.GroupID) + t.Logf("Length of Encrypted Message: %v %v", len(c1), err) alice.AttemptDecryption(c1, s1) c2, s2, _ := alice.EncryptMessageToGroup("Hello World 2", group.GroupID) diff --git a/model/profile.go b/model/profile.go index 0563cb0..8bb48fe 100644 --- a/model/profile.go +++ b/model/profile.go @@ -21,6 +21,8 @@ type PublicProfile struct { Trusted bool Blocked bool Onion string + Attributes map[string]string + lock sync.Mutex } // Profile encapsulates all the attributes necessary to be a Cwtch Peer. @@ -33,6 +35,25 @@ type Profile struct { lock sync.Mutex } +func (p *PublicProfile) init() { + p.Attributes = make(map[string]string) +} + +// SetAttribute allows applications to store arbitrary configuration info at the profile level. +func (p *PublicProfile) SetAttribute(name string, value string) { + p.lock.Lock() + defer p.lock.Unlock() + p.Attributes[name] = value +} + +// GetAttribute returns the value of a value set with SetCustomAttribute. If no such value has been set exists is set to false. +func (p *PublicProfile) GetAttribute(name string) (value string, exists bool) { + p.lock.Lock() + defer p.lock.Unlock() + value, exists = p.Attributes[name] + return +} + // GenerateNewProfile creates a new profile, with new encryption and signing keys, and a profile name. func GenerateNewProfile(name string) *Profile { p := new(Profile) @@ -63,15 +84,13 @@ func (p *Profile) GetCwtchIdentityPacket() (message []byte) { return } -// AddCwtchIdentity takes a wire message and if it is a CwtchIdentity message adds the identity as a contact -// otherwise returns an error -func (p *Profile) AddCwtchIdentity(onion string, ci *protocol.CwtchIdentity) { - p.AddContact(onion, &PublicProfile{Name: ci.GetName(), Ed25519PublicKey: ci.GetEd25519PublicKey(), Onion: onion}) -} - // AddContact allows direct manipulation of cwtch contacts func (p *Profile) AddContact(onion string, profile *PublicProfile) { p.lock.Lock() + profile.init() + // TODO: More Robust V3 Onion Handling + decodedPub, _ := base32.StdEncoding.DecodeString(strings.ToUpper(onion[:56])) + profile.Ed25519PublicKey = ed25519.PublicKey(decodedPub[:32]) p.Contacts[onion] = profile p.lock.Unlock() } @@ -253,14 +272,13 @@ func (p *Profile) ProcessInvite(gci *protocol.GroupChatInvite, peerHostname stri func (p *Profile) AddGroup(group *Group) { existingGroup, exists := p.Groups[group.GroupID] if !exists { - owner, ok := p.GetContact(group.Owner) - if ok { - valid := ed25519.Verify(owner.Ed25519PublicKey, []byte(group.GroupID+group.GroupServer), group.SignedGroupID) - if valid { - p.lock.Lock() - defer p.lock.Unlock() - p.Groups[group.GroupID] = group - } + // TODO More robust error handling (confirm this onion checksum is correct) + decodedPub, _ := base32.StdEncoding.DecodeString(strings.ToUpper(group.Owner[:56])) + valid := ed25519.Verify(ed25519.PublicKey(decodedPub[:32]), []byte(group.GroupID+group.GroupServer), group.SignedGroupID) + if valid { + p.lock.Lock() + defer p.lock.Unlock() + p.Groups[group.GroupID] = group } } else if exists && existingGroup.Owner == group.Owner { p.lock.Lock() diff --git a/model/profile_test.go b/model/profile_test.go index 4f40fab..e8493bc 100644 --- a/model/profile_test.go +++ b/model/profile_test.go @@ -17,8 +17,9 @@ func TestProfileIdentity(t *testing.T) { if err != nil { t.Errorf("alice should have added sarah as a contact %v", err) } - alice.AddCwtchIdentity("sarah.onion", ci.GetCwtchIdentify()) - if alice.Contacts["sarah.onion"].Name != "Sarah" { + + alice.AddContact(sarah.Onion, &sarah.PublicProfile) + if alice.Contacts[sarah.Onion].Name != "Sarah" { t.Errorf("alice should have added sarah as a contact %v", alice.Contacts) } diff --git a/peer/connections/peerpeerconnection.go b/peer/connections/peerpeerconnection.go index 7f38160..e54609f 100644 --- a/peer/connections/peerpeerconnection.go +++ b/peer/connections/peerpeerconnection.go @@ -40,21 +40,11 @@ func (ppc *PeerPeerConnection) GetState() ConnectionState { return ppc.state } -// ClientIdentity passes the given CwtchIdentity packet to the profile. -func (ppc *PeerPeerConnection) ClientIdentity(ci *protocol.CwtchIdentity) { - ppc.profile.AddCwtchIdentity(ppc.PeerHostname, ci) -} - // HandleGroupInvite passes the given group invite tothe profile func (ppc *PeerPeerConnection) HandleGroupInvite(gci *protocol.GroupChatInvite) { ppc.profile.ProcessInvite(gci, ppc.PeerHostname) } -// GetClientIdentityPacket returns nil to avoid peers constantly sending identity packets to eachother. -func (ppc *PeerPeerConnection) GetClientIdentityPacket() []byte { - return nil -} - // HandlePacket handles data packets on the optional data channel func (ppc *PeerPeerConnection) HandlePacket(data []byte) []byte { return ppc.dataHandler(ppc.PeerHostname, data) @@ -145,19 +135,6 @@ func (ppc *PeerPeerConnection) Run() error { return nil }) } - - time.Sleep(time.Second * 1) - ppc.connection.Do(func() error { - channel := ppc.connection.Channel("im.cwtch.peer", channels.Outbound) - if channel != nil { - peerchannel, ok := channel.Handler.(*peer.CwtchPeerChannel) - if ok { - peerchannel.SendMessage(ppc.profile.GetCwtchIdentityPacket()) - } - } - return nil - }) - }() ppc.connection.Process(ppc) diff --git a/peer/connections/peerpeerconnection_test.go b/peer/connections/peerpeerconnection_test.go index 8106648..6bf9104 100644 --- a/peer/connections/peerpeerconnection_test.go +++ b/peer/connections/peerpeerconnection_test.go @@ -40,21 +40,6 @@ func runtestpeer(t *testing.T, tp *TestPeer, identity identity.Identity) { return cpc }) - go func() { - alice := model.GenerateNewProfile("alice") - time.Sleep(time.Second * 1) - rc.Do(func() error { - channel := rc.Channel("im.cwtch.peer", channels.Inbound) - if channel != nil { - peerchannel, ok := channel.Handler.(*peer.CwtchPeerChannel) - if ok { - peerchannel.SendMessage(alice.GetCwtchIdentityPacket()) - } - } - return nil - }) - }() - rc.Process(tp) } @@ -64,18 +49,10 @@ type TestPeer struct { ReceivedGroupInvite bool } -func (tp *TestPeer) ClientIdentity(ci *protocol.CwtchIdentity) { - tp.ReceivedIdentityPacket = true -} - func (tp *TestPeer) HandleGroupInvite(gci *protocol.GroupChatInvite) { tp.ReceivedGroupInvite = true } -func (tp *TestPeer) GetClientIdentityPacket() []byte { - return nil -} - func TestPeerPeerConnection(t *testing.T) { pub, priv, _ := ed25519.GenerateKey(rand.Reader) identity := identity.InitializeV3("", &priv, &pub) @@ -97,11 +74,6 @@ func TestPeerPeerConnection(t *testing.T) { if state != AUTHENTICATED { t.Errorf("connection state should be authenticated(3), was instead %v", state) } - - if tp.ReceivedIdentityPacket == false { - t.Errorf("should have received an identity packet") - } - _, invite, _ := profile.StartGroup("aaa.onion") ppc.SendGroupInvite(invite) time.Sleep(time.Second * 3) diff --git a/peer/connections/peerserverconnection_test.go b/peer/connections/peerserverconnection_test.go index e640706..adcf553 100644 --- a/peer/connections/peerserverconnection_test.go +++ b/peer/connections/peerserverconnection_test.go @@ -97,7 +97,7 @@ func TestPeerServerConnection(t *testing.T) { } if numcalls != 2 { - t.Errorf("Should have received 2 calls from fetch request, instead received %v", numcalls) + t.Errorf("Should have received 2 calls from fetch request, instead received %v", numcalls) } } diff --git a/peer/cwtch_peer.go b/peer/cwtch_peer.go index 96272d0..06db97f 100644 --- a/peer/cwtch_peer.go +++ b/peer/cwtch_peer.go @@ -366,23 +366,12 @@ type CwtchPeerHandler struct { DataHandler func(string, []byte) []byte } -// ClientIdentity handles incoming ClientIdentity packets -func (cph *CwtchPeerHandler) ClientIdentity(ci *protocol.CwtchIdentity) { - log.Printf("Received Client Identity from %v %v\n", cph.Onion, ci.String()) - cph.Peer.Profile.AddCwtchIdentity(cph.Onion, ci) -} - // HandleGroupInvite handles incoming GroupInvites func (cph *CwtchPeerHandler) HandleGroupInvite(gci *protocol.GroupChatInvite) { log.Printf("Received GroupID from %v %v\n", cph.Onion, gci.String()) cph.Peer.Profile.ProcessInvite(gci, cph.Onion) } -// GetClientIdentityPacket returns our ClientIdentity packet so it can be sent to the connected peer. -func (cph *CwtchPeerHandler) GetClientIdentityPacket() []byte { - return cph.Peer.Profile.GetCwtchIdentityPacket() -} - // HandlePacket handles the Cwtch cwtchPeer Data Channel func (cph *CwtchPeerHandler) HandlePacket(data []byte) []byte { return cph.DataHandler(cph.Onion, data) diff --git a/peer/peer/peer_channel.go b/peer/peer/peer_channel.go index 95bf332..612b630 100644 --- a/peer/peer/peer_channel.go +++ b/peer/peer/peer_channel.go @@ -24,9 +24,7 @@ type CwtchPeerChannel struct { // CwtchPeerChannelHandler is implemented by an application type to receive // events from a CwtchPeerChannel. type CwtchPeerChannelHandler interface { - ClientIdentity(*protocol.CwtchIdentity) HandleGroupInvite(*protocol.GroupChatInvite) - GetClientIdentityPacket() []byte } // SendMessage sends a raw message on this channel @@ -99,13 +97,7 @@ func (cpc *CwtchPeerChannel) Packet(data []byte) { cpp := &protocol.CwtchPeerPacket{} err := proto.Unmarshal(data, cpp) if err == nil { - if cpp.GetCwtchIdentify() != nil { - cpc.Handler.ClientIdentity(cpp.GetCwtchIdentify()) - pkt := cpc.Handler.GetClientIdentityPacket() - if pkt != nil { - cpc.SendMessage(pkt) - } - } else if cpp.GetGroupChatInvite() != nil { + if cpp.GetGroupChatInvite() != nil { cpc.Handler.HandleGroupInvite(cpp.GetGroupChatInvite()) } } else { diff --git a/peer/peer/peer_channel_test.go b/peer/peer/peer_channel_test.go index 077f4e2..a752157 100644 --- a/peer/peer/peer_channel_test.go +++ b/peer/peer/peer_channel_test.go @@ -85,37 +85,18 @@ func TestPeerChannel(t *testing.T) { t.Errorf("Channel should no longer be pending") } - gm := &protocol.CwtchIdentity{ - Name: "hello", - Ed25519PublicKey: []byte{}, - } - - cpp := &protocol.CwtchPeerPacket{ - CwtchIdentify: gm, - } - packet, _ := proto.Marshal(cpp) - cpc.Packet(packet) - if th.Received == false { - t.Errorf("Should have sent packet to handler") - } - - cpc2.SendMessage(packet) - if sent == false { - t.Errorf("Should have sent packet to channel") - } - gci := &protocol.GroupChatInvite{ GroupName: "hello", GroupSharedKey: []byte{}, ServerHost: "abc.onion", } - cpp = &protocol.CwtchPeerPacket{ + cpp := &protocol.CwtchPeerPacket{ GroupChatInvite: gci, } - packet, _ = proto.Marshal(cpp) + packet, _ := proto.Marshal(cpp) cpc.Packet(packet) - if th.ReceviedGroupInvite == false { + if sent && th.ReceviedGroupInvite == false { t.Errorf("Should have sent invite packet to handler") } }