More golinting, fixing timing sidechannel

This commit is contained in:
Sarah Jamie Lewis 2018-05-16 14:31:06 -07:00
parent 96fd3bbdda
commit 5f3ee80627
7 changed files with 47 additions and 16 deletions

View File

@ -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 {

View File

@ -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)

View File

@ -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)

View File

@ -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()
}

View File

@ -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{

View File

@ -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)
}
}
}

View File

@ -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":{}}}
{"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":{}}}