5
0
mirror of https://github.com/cwinfo/yggdrasil-go.git synced 2024-11-10 02:50:27 +00:00

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)
// 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 "time"
import "errors"
@ -142,29 +146,43 @@ func (iface *tcpInterface) handler(sock net.Conn, incoming bool) {
defer sock.Close()
// Get our keys
myLinkPub, myLinkPriv := newBoxKeys() // ephemeral link keys
keys := []byte{}
keys = append(keys, tcp_key[:]...)
keys = append(keys, iface.core.boxPub[:]...)
keys = append(keys, iface.core.sigPub[:]...)
keys = append(keys, myLinkPub[:]...)
_, err := sock.Write(keys)
meta := version_getBaseMetadata()
meta.box = iface.core.boxPub
meta.sig = iface.core.sigPub
meta.link = *myLinkPub
metaBytes := meta.encode()
_, err := sock.Write(metaBytes)
if err != nil {
return
}
timeout := time.Now().Add(6 * time.Second)
sock.SetReadDeadline(timeout)
n, err := sock.Read(keys)
n, err := sock.Read(metaBytes)
if err != nil {
return
}
if n < len(keys) { /*panic("Partial key packet?") ;*/
if n != version_getMetaLength() {
return
}
info := tcpInfo{} // used as a map key, so don't include ephemeral link eys
var theirLinkPub boxPubKey
if !tcp_chop_keys(&info.box, &info.sig, &theirLinkPub, &keys) { /*panic("Invalid key packet?") ;*/
meta = version_metadata{} // Reset to zero value
if !meta.decode(metaBytes) {
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
equiv := func(k1, k2 []byte) bool {
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
// 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)
in := func(bs []byte) {
p.handlePacket(bs)