5
0
mirror of https://github.com/cwinfo/yggdrasil-go.git synced 2024-09-19 16:09:36 +00:00

when using tls, if no pinned key is set, pin the key from the cert. require that cert keys match a pinned key

This commit is contained in:
Arceliar 2021-06-19 09:53:11 -05:00
parent 1bf751a474
commit 5564de94ba
2 changed files with 38 additions and 6 deletions

View File

@ -54,7 +54,7 @@ type TcpListener struct {
}
type TcpUpgrade struct {
upgrade func(c net.Conn) (net.Conn, error)
upgrade func(c net.Conn, o *tcpOptions) (net.Conn, error)
name string
}
@ -361,7 +361,7 @@ func (t *tcp) handler(sock net.Conn, incoming bool, options tcpOptions) chan str
var upgraded bool
if options.upgrade != nil {
var err error
if sock, err = options.upgrade.upgrade(sock); err != nil {
if sock, err = options.upgrade.upgrade(sock, &options); err != nil {
t.links.core.log.Errorln("TCP handler upgrade failed:", err)
return nil
}

View File

@ -9,6 +9,7 @@ import (
"crypto/x509/pkix"
"encoding/hex"
"encoding/pem"
"errors"
"log"
"math/big"
"net"
@ -76,16 +77,47 @@ func (t *tcptls) init(tcp *tcp) {
}
}
func (t *tcptls) upgradeListener(c net.Conn) (net.Conn, error) {
conn := tls.Server(c, t.config)
func (t *tcptls) configForOptions(options *tcpOptions) *tls.Config {
config := *t.config
config.VerifyPeerCertificate = func(rawCerts [][]byte, _ [][]*x509.Certificate) error {
if len(rawCerts) != 1 {
return errors.New("tls not exactly 1 cert")
}
cert, err := x509.ParseCertificate(rawCerts[0])
if err != nil {
return errors.New("tls failed to parse cert")
}
if cert.PublicKeyAlgorithm != x509.Ed25519 {
return errors.New("tls wrong cert algorithm")
}
pk := cert.PublicKey.(ed25519.PublicKey)
var key keyArray
copy(key[:], pk)
// If options does not have a pinned key, then pin one now
if options.pinnedEd25519Keys == nil {
options.pinnedEd25519Keys = make(map[keyArray]struct{})
options.pinnedEd25519Keys[key] = struct{}{}
}
if _, isIn := options.pinnedEd25519Keys[key]; !isIn {
return errors.New("tls key does not match pinned key")
}
return nil
}
return &config
}
func (t *tcptls) upgradeListener(c net.Conn, options *tcpOptions) (net.Conn, error) {
config := t.configForOptions(options)
conn := tls.Server(c, config)
if err := conn.Handshake(); err != nil {
return c, err
}
return conn, nil
}
func (t *tcptls) upgradeDialer(c net.Conn) (net.Conn, error) {
conn := tls.Client(c, t.config)
func (t *tcptls) upgradeDialer(c net.Conn, options *tcpOptions) (net.Conn, error) {
config := t.configForOptions(options)
conn := tls.Client(c, config)
if err := conn.Handshake(); err != nil {
return c, err
}