add version metadata to key exchange at the start of connections

This commit is contained in:
Arceliar 2018-06-09 17:46:19 -05:00
parent f5c850f098
commit 8733099516

View File

@ -10,6 +10,10 @@ package yggdrasil
// Could be used to DoS (connect, give someone else's keys, spew garbage) // Could be used to DoS (connect, give someone else's keys, spew garbage)
// I guess the "peer" part should watch for link packets, disconnect? // I guess the "peer" part should watch for link packets, disconnect?
// TCP connections start with a metadata exchange.
// It involves exchanging version numbers and crypto keys
// See version.go for version metadata format
import "net" import "net"
import "time" import "time"
import "errors" import "errors"
@ -142,29 +146,43 @@ func (iface *tcpInterface) handler(sock net.Conn, incoming bool) {
defer sock.Close() defer sock.Close()
// Get our keys // Get our keys
myLinkPub, myLinkPriv := newBoxKeys() // ephemeral link keys myLinkPub, myLinkPriv := newBoxKeys() // ephemeral link keys
keys := []byte{} meta := version_getBaseMetadata()
keys = append(keys, tcp_key[:]...) meta.box = iface.core.boxPub
keys = append(keys, iface.core.boxPub[:]...) meta.sig = iface.core.sigPub
keys = append(keys, iface.core.sigPub[:]...) meta.link = *myLinkPub
keys = append(keys, myLinkPub[:]...) metaBytes := meta.encode()
_, err := sock.Write(keys) _, err := sock.Write(metaBytes)
if err != nil { if err != nil {
return return
} }
timeout := time.Now().Add(6 * time.Second) timeout := time.Now().Add(6 * time.Second)
sock.SetReadDeadline(timeout) sock.SetReadDeadline(timeout)
n, err := sock.Read(keys) n, err := sock.Read(metaBytes)
if err != nil { if err != nil {
return return
} }
if n < len(keys) { /*panic("Partial key packet?") ;*/ if n != version_getMetaLength() {
return return
} }
info := tcpInfo{} // used as a map key, so don't include ephemeral link eys meta = version_metadata{} // Reset to zero value
var theirLinkPub boxPubKey if !meta.decode(metaBytes) {
if !tcp_chop_keys(&info.box, &info.sig, &theirLinkPub, &keys) { /*panic("Invalid key packet?") ;*/
return return
} }
if !meta.check() {
base := version_getBaseMetadata()
if meta.meta == base.meta {
if meta.ver > base.ver {
iface.core.log.Println("Failed to connect to node:", sock.RemoteAddr().String(), "version:", meta.ver)
} else if meta.ver == base.ver && meta.minorVer > base.minorVer {
iface.core.log.Println("Failed to connect to node:", sock.RemoteAddr().String(), "version:", fmt.Sprintf("%d.%d", meta.ver, meta.minorVer))
}
}
return
}
info := tcpInfo{ // used as a map key, so don't include ephemeral link key
box: meta.box,
sig: meta.sig,
}
// Quit the parent call if this is a connection to ourself // Quit the parent call if this is a connection to ourself
equiv := func(k1, k2 []byte) bool { equiv := func(k1, k2 []byte) bool {
for idx := range k1 { for idx := range k1 {
@ -210,7 +228,7 @@ func (iface *tcpInterface) handler(sock net.Conn, incoming bool) {
}() }()
// Note that multiple connections to the same node are allowed // Note that multiple connections to the same node are allowed
// E.g. over different interfaces // E.g. over different interfaces
p := iface.core.peers.newPeer(&info.box, &info.sig, getSharedKey(myLinkPriv, &theirLinkPub)) p := iface.core.peers.newPeer(&info.box, &info.sig, getSharedKey(myLinkPriv, &meta.link))
p.linkOut = make(chan []byte, 1) p.linkOut = make(chan []byte, 1)
in := func(bs []byte) { in := func(bs []byte) {
p.handlePacket(bs) p.handlePacket(bs)