From 5f3ee80627b79d4fe9f0586724edefed2f430f88 Mon Sep 17 00:00:00 2001 From: Sarah Jamie Lewis Date: Wed, 16 May 2018 14:31:06 -0700 Subject: [PATCH] More golinting, fixing timing sidechannel --- peer/connections/connectionsmanager.go | 9 ++++++ peer/connections/peerpeerconnection.go | 6 ++++ peer/connections/peerserverconnection.go | 4 +++ peer/cwtch_peer.go | 36 +++++++++++++++--------- peer/fetch/peer_fetch_channel.go | 1 + peer/listen/peer_listen_channel.go | 5 +++- peer/test_profile | 2 +- 7 files changed, 47 insertions(+), 16 deletions(-) diff --git a/peer/connections/connectionsmanager.go b/peer/connections/connectionsmanager.go index ce508ac..75fa9b7 100644 --- a/peer/connections/connectionsmanager.go +++ b/peer/connections/connectionsmanager.go @@ -7,12 +7,14 @@ import ( "time" ) +// Manager encapsulates all the logic necessary to manage outgoing peer and server connections. type Manager struct { peerConnections map[string]*PeerPeerConnection serverConnections map[string]*PeerServerConnection lock sync.Mutex } +// NewConnectionsManager creates a new instance of Manager. func NewConnectionsManager() *Manager { m := new(Manager) m.peerConnections = make(map[string]*PeerPeerConnection) @@ -20,6 +22,7 @@ func NewConnectionsManager() *Manager { return m } +// ManagePeerConnection creates a new PeerConnection for the given Host and Profile. func (m *Manager) ManagePeerConnection(host string, profile *model.Profile) { m.lock.Lock() @@ -33,6 +36,7 @@ func (m *Manager) ManagePeerConnection(host string, profile *model.Profile) { } +// ManageServerConnection creates a new ServerConnection for Host with the given callback handler. func (m *Manager) ManageServerConnection(host string, handler func(string, *protocol.GroupMessage)) { m.lock.Lock() @@ -46,6 +50,7 @@ func (m *Manager) ManageServerConnection(host string, handler func(string, *prot m.lock.Unlock() } +// GetPeers returns a map of all peer connections with their state func (m *Manager) GetPeers() map[string]ConnectionState { rm := make(map[string]ConnectionState) m.lock.Lock() @@ -56,6 +61,7 @@ func (m *Manager) GetPeers() map[string]ConnectionState { return rm } +// GetServers returns a map of all server connections with their state. func (m *Manager) GetServers() map[string]ConnectionState { rm := make(map[string]ConnectionState) m.lock.Lock() @@ -66,6 +72,7 @@ func (m *Manager) GetServers() map[string]ConnectionState { return rm } +// GetPeerPeerConnectionForOnion safely returns a given peer connection func (m *Manager) GetPeerPeerConnectionForOnion(host string) (ppc *PeerPeerConnection) { m.lock.Lock() ppc = m.peerConnections[host] @@ -73,6 +80,7 @@ func (m *Manager) GetPeerPeerConnectionForOnion(host string) (ppc *PeerPeerConne return } +// GetPeerServerConnectionForOnion safely returns a given host connection func (m *Manager) GetPeerServerConnectionForOnion(host string) (psc *PeerServerConnection) { m.lock.Lock() psc = m.serverConnections[host] @@ -80,6 +88,7 @@ func (m *Manager) GetPeerServerConnectionForOnion(host string) (psc *PeerServerC return } +// AttemptReconnections repeatedly attempts to reconnect with failed peers and servers. func (m *Manager) AttemptReconnections() { m.lock.Lock() for _, ppc := range m.peerConnections { diff --git a/peer/connections/peerpeerconnection.go b/peer/connections/peerpeerconnection.go index 0b50648..0e421e0 100644 --- a/peer/connections/peerpeerconnection.go +++ b/peer/connections/peerpeerconnection.go @@ -13,6 +13,7 @@ import ( "time" ) +// PeerPeerConnection encapsulates a single outgoing Peer->Peer connection type PeerPeerConnection struct { connection.AutoConnectionHandler PeerHostname string @@ -21,6 +22,7 @@ type PeerPeerConnection struct { profile *model.Profile } +// NewPeerPeerConnection creates a new peer connection for the given hostname and profile. func NewPeerPeerConnection(peerhostname string, profile *model.Profile) *PeerPeerConnection { ppc := new(PeerPeerConnection) ppc.PeerHostname = peerhostname @@ -34,18 +36,22 @@ 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 } +// SendGroupInvite sends the given serialized invite packet to the Peer func (ppc *PeerPeerConnection) SendGroupInvite(invite []byte) { ppc.connection.Do(func() error { channel := ppc.connection.Channel("im.cwtch.peer", channels.Outbound) diff --git a/peer/connections/peerserverconnection.go b/peer/connections/peerserverconnection.go index 1df5f58..1084293 100644 --- a/peer/connections/peerserverconnection.go +++ b/peer/connections/peerserverconnection.go @@ -15,6 +15,7 @@ import ( "time" ) +// PeerServerConnection encapsulates a single Peer->Server connection type PeerServerConnection struct { connection.AutoConnectionHandler Server string @@ -24,6 +25,7 @@ type PeerServerConnection struct { GroupMessageHandler func(string, *protocol.GroupMessage) } +// NewPeerServerConnection creates a new Peer->Server outbound connection func NewPeerServerConnection(serverhostname string) *PeerServerConnection { psc := new(PeerServerConnection) psc.Server = serverhostname @@ -74,6 +76,7 @@ func (psc *PeerServerConnection) Break() error { return psc.connection.Break() } +// SendGroupMessage sends the given protocol message to the Server. func (psc *PeerServerConnection) SendGroupMessage(gm *protocol.GroupMessage) error { if psc.state != AUTHENTICATED { return errors.New("peer is not yet connected & authenticated to server cannot send message") @@ -109,6 +112,7 @@ func (psc *PeerServerConnection) SendGroupMessage(gm *protocol.GroupMessage) err return err } +// HandleGroupMessage passes the given group message back to the profile. func (psc *PeerServerConnection) HandleGroupMessage(gm *protocol.GroupMessage) { log.Printf("Received Group Message: %v", gm) psc.GroupMessageHandler(psc.Server, gm) diff --git a/peer/cwtch_peer.go b/peer/cwtch_peer.go index 4afea94..5d8e9e2 100644 --- a/peer/cwtch_peer.go +++ b/peer/cwtch_peer.go @@ -16,16 +16,7 @@ import ( "sync" ) -/** - -PeerConnectionPool - Background thread running Process() - Pointer to connections - -Move CwtchPeerChannel under peer/ - Write tests for Peer Channel -*/ - +// CwtchPeer manages incoming and outgoing connections and all processing for a Cwtch Peer type CwtchPeer struct { connection.AutoConnectionHandler Profile *model.Profile @@ -55,6 +46,7 @@ func (cp *CwtchPeer) setup() { } } +// NewCwtchPeer creates and returns a new CwtchPeer with the given name. func NewCwtchPeer(name string) *CwtchPeer { cp := new(CwtchPeer) cp.Profile = model.GenerateNewProfile(name) @@ -62,6 +54,7 @@ func NewCwtchPeer(name string) *CwtchPeer { return cp } +// Save saves the CwtchPeer profile state to a file. func (cp *CwtchPeer) Save(profilefile string) error { cp.mutex.Lock() bytes, _ := json.Marshal(cp) @@ -71,6 +64,7 @@ func (cp *CwtchPeer) Save(profilefile string) error { return err } +// LoadCwtchPeer loads an existing CwtchPeer from a file. func LoadCwtchPeer(profilefile string) (*CwtchPeer, error) { bytes, _ := ioutil.ReadFile(profilefile) cp := new(CwtchPeer) @@ -80,7 +74,7 @@ func LoadCwtchPeer(profilefile string) (*CwtchPeer, error) { return cp, err } -// AddContactRequest is the entry point for CwtchPeer relationships +// PeerWithOnion is the entry point for CwtchPeer relationships func (cp *CwtchPeer) PeerWithOnion(onion string) { cp.connectionsManager.ManagePeerConnection(onion, cp.Profile) } @@ -110,14 +104,17 @@ func (cp *CwtchPeer) InviteOnionToGroup(onion string, groupid string) error { return errors.New("group id could not be found") } +// ReceiveGroupMessage is a callback function that processes GroupMessages from a given server func (cp *CwtchPeer) ReceiveGroupMessage(server string, gm *protocol.GroupMessage) { cp.Profile.AttemptDecryption(gm.Ciphertext) } +// JoinServer manages a new server connection with the given onion address func (cp *CwtchPeer) JoinServer(onion string) { cp.connectionsManager.ManageServerConnection(onion, cp.ReceiveGroupMessage) } +// SendMessageToGroup attemps to sent the given message to the given group id. func (cp *CwtchPeer) SendMessageToGroup(groupid string, message string) error { group := cp.Profile.GetGroupByGroupID(groupid) if group == nil { @@ -138,14 +135,17 @@ func (cp *CwtchPeer) SendMessageToGroup(groupid string, message string) error { return err } +// GetPeers returns a list of peer connections. func (cp *CwtchPeer) GetPeers() map[string]connections.ConnectionState { return cp.connectionsManager.GetPeers() } +// GetServers returns a list of server connections func (cp *CwtchPeer) GetServers() map[string]connections.ConnectionState { return cp.connectionsManager.GetServers() } +// TrustPeer sets an existing peer relationship to trusted func (cp *CwtchPeer) TrustPeer(peer string) error { _, ok := cp.Profile.Contacts[peer] if !ok { @@ -156,6 +156,7 @@ func (cp *CwtchPeer) TrustPeer(peer string) error { return nil } +// BlockPeer blocks an existing peer relationship. func (cp *CwtchPeer) BlockPeer(peer string) error { _, ok := cp.Profile.Contacts[peer] if !ok { @@ -165,6 +166,7 @@ func (cp *CwtchPeer) BlockPeer(peer string) error { return nil } +// AcceptInvite accepts a given existing group invite func (cp *CwtchPeer) AcceptInvite(groupID string) error { g := cp.Profile.GetGroupByGroupID(groupID) if g == nil { @@ -174,15 +176,18 @@ func (cp *CwtchPeer) AcceptInvite(groupID string) error { return nil } +// RejectInvite rejects a given group invite. func (cp *CwtchPeer) RejectInvite(groupID string) error { g := cp.Profile.GetGroupByGroupID(groupID) if g == nil { return errors.New("group invite does not exit") } g.Accepted = false + // TODO delete group from Profile return nil } +// Listen sets up an onion listener to process incoming cwtch messages func (cp *CwtchPeer) Listen() error { cwtchpeer := new(application.RicochetApplication) l, err := application.SetupOnion("127.0.0.1:9051", "tcp4", "", cp.Profile.OnionPrivateKey, 9878) @@ -209,35 +214,38 @@ func (cp *CwtchPeer) Listen() error { return nil } +// CwtchPeerInstance encapsulates incoming peer connections type CwtchPeerInstance struct { rai *application.ApplicationInstance ra *application.RicochetApplication } +// Init sets up a CwtchPeerInstance func (cpi *CwtchPeerInstance) Init(rai *application.ApplicationInstance, ra *application.RicochetApplication) { cpi.rai = rai cpi.ra = ra } +// CwtchPeerHandler encapsulates handling of incoming CwtchPackets type CwtchPeerHandler struct { Onion string Peer *CwtchPeer } +// 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) cph.Peer.Save(cph.Peer.profilefile) } +// 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) } -func (cph *CwtchPeerHandler) HandleGroupMessage(gm *protocol.GroupMessage) { -} - +// GetClientIdentityPacket returns our ClientIdentity packet so it can be sent to the connected peer. func (cph *CwtchPeerHandler) GetClientIdentityPacket() []byte { return cph.Peer.Profile.GetCwtchIdentityPacket() } diff --git a/peer/fetch/peer_fetch_channel.go b/peer/fetch/peer_fetch_channel.go index a7a1f5b..279852a 100644 --- a/peer/fetch/peer_fetch_channel.go +++ b/peer/fetch/peer_fetch_channel.go @@ -73,6 +73,7 @@ func (cpfc *CwtchPeerFetchChannel) OpenOutboundResult(err error, crm *Protocol_D } } +// FetchRequest sends a FetchMessage to the Server. func (cpfc *CwtchPeerFetchChannel) FetchRequest() { fm := &protocol.FetchMessage{} csp := &protocol.CwtchServerPacket{ diff --git a/peer/listen/peer_listen_channel.go b/peer/listen/peer_listen_channel.go index c1f19d4..56c7d61 100644 --- a/peer/listen/peer_listen_channel.go +++ b/peer/listen/peer_listen_channel.go @@ -78,7 +78,10 @@ func (cplc *CwtchPeerListenChannel) Packet(data []byte) { if err == nil { if csp.GetGroupMessage() != nil { gm := csp.GetGroupMessage() - cplc.Handler.HandleGroupMessage(gm) + // We create a new profile here to avoid leaking any information about processing + // times. + // TODO Is this necessary / sufficient? + go cplc.Handler.HandleGroupMessage(gm) } } } diff --git a/peer/test_profile b/peer/test_profile index 514ed0c..2f5cd78 100644 --- a/peer/test_profile +++ b/peer/test_profile @@ -1 +1 @@ -{"Profile":{"Name":"alice","Ed25519PublicKey":"EPP2ByelMR8QbCRZ56TvNZIn3zQa2lgF2stgkpPJ+aM=","Trusted":false,"Blocked":false,"Onion":"7isshkc2i3djqbvm","Contacts":{"7isshkc2i3djqbvm":{"Name":"alice","Ed25519PublicKey":"EPP2ByelMR8QbCRZ56TvNZIn3zQa2lgF2stgkpPJ+aM=","Trusted":false,"Blocked":false,"Onion":"7isshkc2i3djqbvm"}},"Ed25519PrivateKey":"sJ5CAaTezNmdt8oAHbXF42fw5tD9yY67fqjaell9UWUQ8/YHJ6UxHxBsJFnnpO81kiffNBraWAXay2CSk8n5ow==","OnionPrivateKey":{"N":109264965121269102864268122399717914981859407652105503986871936893865494823555161493388959985138872973433399135905775525157924873337104893694978392209273343269778013691805532688273390165440742501637993188808873815612746664566611221222356706841643278718951875953660024258163364129880350927070816248541790972927,"E":65537,"D":80405289727992508412576998321119304909137336967485422597538381381211395377505756646499982806709071621981057114718828085688866485594832807547304925783551650481916788738771615371037649919470056628797374101427393208956491043600211579247644280949777877409955527302067923539607079105105839036975582591395024605569,"Primes":[10488093793005778253652455285384166778311422933955447489461025546115184116803524144032108593418314278741083466541849319796911230734922592676584779174557633,10418000380024719809017535929593675542117900930084020826809324556106965859207771141464817326453354343332212022219319386849128962897507240725843863893136319],"Precomputed":{"Dp":9125571392626584881181988155369659004831656468299456523666570940325711336992650827244807182545623618973294513215677766189774770132863741126339226129832001,"Dq":3288798844352524957333472707743161165309325302386564946302975658655370503092139968960520098066640951053605360753398825007577843254749642238384175352626719,"Qinv":9470686814605331096328774018187602768490278876204799167115558347990281971237179616039742279558354704162800553043867292124027611347849132182052052306560962,"CRTValues":[]}},"Groups":{}}} \ No newline at end of file +{"Profile":{"Name":"alice","Ed25519PublicKey":"0S45Wi1Isv/cFd0kDBMGO7RtQ052ykhaCd6L1zZiGJk=","Trusted":false,"Blocked":false,"Onion":"k5eov6vrcwfwxtll","Contacts":{"k5eov6vrcwfwxtll":{"Name":"alice","Ed25519PublicKey":"0S45Wi1Isv/cFd0kDBMGO7RtQ052ykhaCd6L1zZiGJk=","Trusted":false,"Blocked":false,"Onion":"k5eov6vrcwfwxtll"}},"Ed25519PrivateKey":"2bcZKNNADNvjPbvqi92lX4/m+S9JhtdKT6jvGXCbzFPRLjlaLUiy/9wV3SQMEwY7tG1DTnbKSFoJ3ovXNmIYmQ==","OnionPrivateKey":{"N":129372676647459794327830253373463393606614906660537850553935500200530603388955991892570404489884752658911733140595540603298204271320256261391136774929958682162097800498560829735266250139995081586925851310901551963943491407445610456311068913491697886096166012618097156047960858604885507865489761463667080301053,"E":65537,"D":13830126075226258740265479883645643462592795460026064375556893272577588344645401516690545094467744588985391494621547484119004823609101963277328901920431059810319615003421932162013637268371590049232355377940028961198027904729545745481971750183753640418115007446942300337049266027513914090369018266501543413697,"Primes":[10134035533655370825395777494371157149217307934744138685965355987639016807004540627179525764862351274689439670035451419591678388697397084668693600989506869,12766155814020000856737163927670455275067799350422878241672290736027598052735005956636650394580684371305614873375636621519903205433400104443307931969940137],"Precomputed":{"Dp":3537951584754182896456282543772404528344172079084271375480832888249091422315087500951638761311176849182818555173583296157248600537046939854123771161937793,"Dq":4462515274476771894151268572241672031013446073497989191425767253179978390681695095298671344270395322676355816319978933463531478909223232566210559126895625,"Qinv":2690107827925082851885736485760405702598764576265172898377988691597466473116754634766336624610955703441824524110562956288452424664297519088478250787531223,"CRTValues":[]}},"Groups":{}}} \ No newline at end of file