From 0075d1cd05ce36a5c1b8142572b90ebf2ef8d018 Mon Sep 17 00:00:00 2001 From: Sarah Jamie Lewis Date: Thu, 6 May 2021 17:15:01 -0700 Subject: [PATCH] Store Server Key Bundle + a few stricter checks --- model/keyBundle.go | 4 ++++ peer/cwtch_peer.go | 36 +++++++++++++++++++++--------------- 2 files changed, 25 insertions(+), 15 deletions(-) diff --git a/model/keyBundle.go b/model/keyBundle.go index 9842efd..edb814e 100644 --- a/model/keyBundle.go +++ b/model/keyBundle.go @@ -13,6 +13,10 @@ import ( type KeyType string const ( + + // BundleType - the attribute under which the signed server bundle is stored... + BundleType = KeyType("server_key_bundle") + // KeyTypeServerOnion - a cwtch address KeyTypeServerOnion = KeyType("bulletin_board_onion") // bulletin board diff --git a/peer/cwtch_peer.go b/peer/cwtch_peer.go index c4002a3..02787a0 100644 --- a/peer/cwtch_peer.go +++ b/peer/cwtch_peer.go @@ -295,40 +295,43 @@ func (cp *cwtchPeer) AddServer(serverSpecification string) error { if err != nil { return err } - log.Debugf("Got new key bundle %v", keyBundle) + log.Debugf("Got new key bundle %v", keyBundle.Serialize()) + + // TODO if the key bundle is incomplete then error out. In the future we may allow servers to attest to new + // keys or subsets of keys, but for now they must commit only to a complete set of keys required for Cwtch Groups + // (that way we can be assured that the keybundle we store is a valid one) + if keyBundle.HasKeyType(model.KeyTypeTokenOnion) == false || keyBundle.HasKeyType(model.KeyTypeServerOnion) == false || keyBundle.HasKeyType(model.KeyTypePrivacyPass) == false { + return errors.New("keybundle is incomplete") + } + if keyBundle.HasKeyType(model.KeyTypeServerOnion) { onionKey, _ := keyBundle.GetKey(model.KeyTypeServerOnion) onion := string(onionKey) + // Add the contact if we don't already have it if cp.GetContact(onion) == nil { decodedPub, _ := base32.StdEncoding.DecodeString(strings.ToUpper(onion)) ab := keyBundle.AttributeBundle() pp := &model.PublicProfile{Name: onion, Ed25519PublicKey: decodedPub, Authorization: model.AuthUnknown, Onion: onion, Attributes: ab} + // The only part of this function that actually modifies the profile... + cp.mutex.Lock() cp.Profile.AddContact(onion, pp) + cp.mutex.Unlock() + pd, _ := json.Marshal(pp) cp.eventBus.Publish(event.NewEvent(event.PeerCreated, map[event.Field]string{ event.Data: string(pd), event.RemotePeer: onion, })) - - // Publish every key as an attribute - for k, v := range ab { - log.Debugf("Server (%v) has %v key %v", onion, k, v) - cp.eventBus.Publish(event.NewEventList(event.SetPeerAttribute, event.RemotePeer, onion, k, v)) - } - - // Default to Deleting Peer History - cp.eventBus.Publish(event.NewEventList(event.SetPeerAttribute, event.RemotePeer, onion, event.SaveHistoryKey, event.DeleteHistoryDefault)) - return nil } - // We have already seen this server and so some additional checks are needed (and we don't need to create the - // peer). + // At this point we know the server exists server := cp.GetContact(onion) ab := keyBundle.AttributeBundle() - // Check server bundle for consistency + // Check server bundle for consistency if we have different keys stored than in the tofu bundle then we + // abort... for k, v := range ab { val, exists := server.GetAttribute(k) if exists { @@ -340,11 +343,14 @@ func (cp *cwtchPeer) AddServer(serverSpecification string) error { // we haven't seen this key associated with the server before } + // Store the key bundle for the server so we can reconstruct a tofubundle invite + cp.SetAttribute(string(model.BundleType), serverSpecification) + // If we have gotten to this point we can assume this is a safe key bundle signed by the // server with no conflicting keys. So we are going to publish all the keys for k, v := range ab { log.Debugf("Server (%v) has %v key %v", onion, k, v) - cp.eventBus.Publish(event.NewEventList(event.SetPeerAttribute, event.RemotePeer, onion, k, v)) + cp.SetAttribute(k, v) } return nil