Files
funknetz/station/tls.go
T
konradandCursor 3d1a2a1669 Speak protocol 3.0 and fall back to 2.0 only when that is the reflector's maximum.
A reflector that has moved to 3.0 will not accept a station that always announces 2.0, and a 2.x reflector still needs one explicit plaintext session.

Co-authored-by: Cursor <cursoragent@cursor.com>
2026-10-07 14:24:00 +02:00

61 lines
1.4 KiB
Go

package station
import (
"crypto/tls"
"crypto/x509"
"errors"
"net"
"strings"
)
var errHostMismatch = errors.New("host mismatch")
func tlsConfig(host string, caPEM []byte, client tls.Certificate, present bool) (*tls.Config, error) {
pool := x509.NewCertPool()
if !pool.AppendCertsFromPEM(caPEM) {
return nil, errors.New("ca bundle")
}
cfg := &tls.Config{
MinVersion: tls.VersionTLS12,
RootCAs: pool,
InsecureSkipVerify: true,
VerifyConnection: func(cs tls.ConnectionState) error {
return verifyPeer(host, pool, cs)
},
}
if present {
cfg.Certificates = []tls.Certificate{client}
}
return cfg, nil
}
func verifyPeer(host string, pool *x509.CertPool, cs tls.ConnectionState) error {
if len(cs.PeerCertificates) == 0 {
return errors.New("no peer certificate")
}
leaf := cs.PeerCertificates[0]
opts := x509.VerifyOptions{Roots: pool, KeyUsages: []x509.ExtKeyUsage{x509.ExtKeyUsageServerAuth}}
if len(cs.PeerCertificates) > 1 {
opts.Intermediates = x509.NewCertPool()
for _, cert := range cs.PeerCertificates[1:] {
opts.Intermediates.AddCert(cert)
}
}
if _, err := leaf.Verify(opts); err != nil {
return err
}
host = strings.TrimSuffix(host, ".")
if ip := net.ParseIP(host); ip != nil {
for _, cand := range leaf.IPAddresses {
if cand.Equal(ip) {
return nil
}
}
return errHostMismatch
}
if err := leaf.VerifyHostname(host); err != nil {
return errHostMismatch
}
return nil
}