|
|
|
|
@ -95,6 +95,7 @@ type Conn struct { |
|
|
|
|
discoOfNode map[tailcfg.NodeKey]tailcfg.DiscoKey |
|
|
|
|
|
|
|
|
|
endpointOfDisco map[tailcfg.DiscoKey]*discoEndpoint |
|
|
|
|
sharedDiscoKey map[tailcfg.DiscoKey]*[32]byte // nacl/box precomputed key
|
|
|
|
|
|
|
|
|
|
// addrsByUDP is a map of every remote ip:port to a priority
|
|
|
|
|
// list of endpoint addresses for a peer.
|
|
|
|
|
@ -250,6 +251,7 @@ func newConn() *Conn { |
|
|
|
|
derpStarted: make(chan struct{}), |
|
|
|
|
peerLastDerp: make(map[key.Public]int), |
|
|
|
|
endpointOfDisco: make(map[tailcfg.DiscoKey]*discoEndpoint), |
|
|
|
|
sharedDiscoKey: make(map[tailcfg.DiscoKey]*[32]byte), |
|
|
|
|
} |
|
|
|
|
c.endpointsUpdateWaiter = sync.NewCond(&c.mu) |
|
|
|
|
return c |
|
|
|
|
@ -499,6 +501,11 @@ func (c *Conn) SetNetInfoCallback(fn func(*tailcfg.NetInfo)) { |
|
|
|
|
func (c *Conn) SetDiscoPrivateKey(k key.Private) { |
|
|
|
|
c.mu.Lock() |
|
|
|
|
defer c.mu.Unlock() |
|
|
|
|
if !c.discoPrivate.IsZero() && c.discoPrivate != k { |
|
|
|
|
// TODO: support changing a key at runtime; need to
|
|
|
|
|
// clear a bunch of maps at least
|
|
|
|
|
panic("unsupported") |
|
|
|
|
} |
|
|
|
|
c.discoPrivate = k |
|
|
|
|
c.logf("magicsock: disco key set; public: %x", k.Public()) |
|
|
|
|
} |
|
|
|
|
@ -1348,7 +1355,7 @@ func (c *Conn) handleDiscoMessage(msg []byte, addr *net.UDPAddr) bool { |
|
|
|
|
var nonce [nonceLen]byte |
|
|
|
|
copy(nonce[:], msg[len(magic)+len(key.Public{}):]) |
|
|
|
|
sealedBox := msg[headerLen:] |
|
|
|
|
payload, ok := box.Open(nil, sealedBox, &nonce, key.Public(sender).B32(), c.discoPrivate.B32()) |
|
|
|
|
payload, ok := box.OpenAfterPrecomputation(nil, sealedBox, &nonce, c.sharedDiscoKeyLocked(sender)) |
|
|
|
|
if !ok { |
|
|
|
|
c.logf("magicsock: failed to open disco message box purportedly from %s (disco key %x)", senderNode.Key.ShortString(), sender[:]) |
|
|
|
|
return false |
|
|
|
|
@ -1358,6 +1365,16 @@ func (c *Conn) handleDiscoMessage(msg []byte, addr *net.UDPAddr) bool { |
|
|
|
|
return true |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
func (c *Conn) sharedDiscoKeyLocked(k tailcfg.DiscoKey) *[32]byte { |
|
|
|
|
if v, ok := c.sharedDiscoKey[k]; ok { |
|
|
|
|
return v |
|
|
|
|
} |
|
|
|
|
shared := new([32]byte) |
|
|
|
|
box.Precompute(shared, key.Public(k).B32(), c.discoPrivate.B32()) |
|
|
|
|
c.sharedDiscoKey[k] = shared |
|
|
|
|
return shared |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
// SetPrivateKey sets the connection's private key.
|
|
|
|
|
//
|
|
|
|
|
// This is only used to be able prove our identity when connecting to
|
|
|
|
|
@ -1491,6 +1508,7 @@ func (c *Conn) SetNetworkMap(nm *controlclient.NetworkMap) { |
|
|
|
|
if _, ok := c.nodeOfDisco[dk]; !ok { |
|
|
|
|
de.cleanup() |
|
|
|
|
delete(c.endpointOfDisco, dk) |
|
|
|
|
delete(c.sharedDiscoKey, dk) |
|
|
|
|
} |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
|