Store Server Key Bundle + a few stricter checks #352
|
@ -13,6 +13,10 @@ import (
|
||||||
type KeyType string
|
type KeyType string
|
||||||
|
|
||||||
const (
|
const (
|
||||||
|
|
||||||
|
// BundleType - the attribute under which the signed server bundle is stored...
|
||||||
|
BundleType = KeyType("server_key_bundle")
|
||||||
|
|
||||||
// KeyTypeServerOnion - a cwtch address
|
// KeyTypeServerOnion - a cwtch address
|
||||||
KeyTypeServerOnion = KeyType("bulletin_board_onion") // bulletin board
|
KeyTypeServerOnion = KeyType("bulletin_board_onion") // bulletin board
|
||||||
|
|
||||||
|
|
|
@ -295,40 +295,43 @@ func (cp *cwtchPeer) AddServer(serverSpecification string) error {
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return err
|
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) {
|
if keyBundle.HasKeyType(model.KeyTypeServerOnion) {
|
||||||
onionKey, _ := keyBundle.GetKey(model.KeyTypeServerOnion)
|
onionKey, _ := keyBundle.GetKey(model.KeyTypeServerOnion)
|
||||||
onion := string(onionKey)
|
onion := string(onionKey)
|
||||||
|
|
||||||
|
// Add the contact if we don't already have it
|
||||||
if cp.GetContact(onion) == nil {
|
if cp.GetContact(onion) == nil {
|
||||||
decodedPub, _ := base32.StdEncoding.DecodeString(strings.ToUpper(onion))
|
decodedPub, _ := base32.StdEncoding.DecodeString(strings.ToUpper(onion))
|
||||||
ab := keyBundle.AttributeBundle()
|
ab := keyBundle.AttributeBundle()
|
||||||
pp := &model.PublicProfile{Name: onion, Ed25519PublicKey: decodedPub, Authorization: model.AuthUnknown, Onion: onion, Attributes: ab}
|
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.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,
|
||||||
}))
|
}))
|
||||||
|
|
||||||
// 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
|
// At this point we know the server exists
|
||||||
// peer).
|
|
||||||
server := cp.GetContact(onion)
|
server := cp.GetContact(onion)
|
||||||
ab := keyBundle.AttributeBundle()
|
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 {
|
for k, v := range ab {
|
||||||
val, exists := server.GetAttribute(k)
|
val, exists := server.GetAttribute(k)
|
||||||
if exists {
|
if exists {
|
||||||
|
@ -340,11 +343,14 @@ func (cp *cwtchPeer) AddServer(serverSpecification string) error {
|
||||||
// we haven't seen this key associated with the server before
|
// 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
|
// 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
|
// server with no conflicting keys. So we are going to publish all the keys
|
||||||
for k, v := range ab {
|
for k, v := range ab {
|
||||||
log.Debugf("Server (%v) has %v key %v", onion, k, v)
|
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
|
return nil
|
||||||
|
|
Loading…
Reference in New Issue