Improve link and handshake errors

This commit is contained in:
Neil Alexander 2024-08-01 21:53:48 +01:00
parent 4fbdeb4e3f
commit 9950d1225d
No known key found for this signature in database
GPG Key ID: A02A2019A2BB0944
2 changed files with 22 additions and 11 deletions

View File

@ -140,7 +140,7 @@ const ErrLinkAlreadyConfigured = linkError("peer is already configured")
const ErrLinkNotConfigured = linkError("peer is not configured") const ErrLinkNotConfigured = linkError("peer is not configured")
const ErrLinkPriorityInvalid = linkError("priority value is invalid") const ErrLinkPriorityInvalid = linkError("priority value is invalid")
const ErrLinkPinnedKeyInvalid = linkError("pinned public key is invalid") const ErrLinkPinnedKeyInvalid = linkError("pinned public key is invalid")
const ErrLinkPasswordInvalid = linkError("password is invalid") const ErrLinkPasswordInvalid = linkError("invalid password supplied")
const ErrLinkUnrecognisedSchema = linkError("link schema unknown") const ErrLinkUnrecognisedSchema = linkError("link schema unknown")
const ErrLinkMaxBackoffInvalid = linkError("max backoff duration invalid") const ErrLinkMaxBackoffInvalid = linkError("max backoff duration invalid")
@ -363,9 +363,11 @@ func (l *links) add(u *url.URL, sintf string, linkType linkType) error {
_ = lc.Close() _ = lc.Close()
phony.Block(l, func() { phony.Block(l, func() {
state._conn = nil state._conn = nil
if state._err = err; state._err != nil { if err == nil {
state._errtime = time.Now() err = fmt.Errorf("remote side closed the connection")
} }
state._err = err
state._errtime = time.Now()
}) })
// If the link is persistently configured, back off if needed // If the link is persistently configured, back off if needed
@ -647,7 +649,7 @@ func (l *links) handler(linkType linkType, options linkOptions, conn net.Conn, s
l.core.log.Infof("Disconnected %s: %s, source %s; error: %s", l.core.log.Infof("Disconnected %s: %s, source %s; error: %s",
dir, remoteStr, localStr, err) dir, remoteStr, localStr, err)
} }
return nil return err
} }
func urlForLinkInfo(u url.URL) url.URL { func urlForLinkInfo(u url.URL) url.URL {

View File

@ -8,7 +8,6 @@ import (
"bytes" "bytes"
"crypto/ed25519" "crypto/ed25519"
"encoding/binary" "encoding/binary"
"fmt"
"io" "io"
"golang.org/x/crypto/blake2b" "golang.org/x/crypto/blake2b"
@ -38,6 +37,16 @@ const (
metaPriority // uint8 metaPriority // uint8
) )
type handshakeError string
func (e handshakeError) Error() string { return string(e) }
const ErrHandshakeInvalidPreamble = handshakeError("invalid handshake, remote side is not Yggdrasil")
const ErrHandshakeInvalidLength = handshakeError("invalid handshake length, possible version mismatch")
const ErrHandshakeInvalidPassword = handshakeError("invalid password supplied, check your config")
const ErrHandshakeHashFailure = handshakeError("invalid hash length")
const ErrHandshakeIncorrectPassword = handshakeError("password does not match remote side")
// Gets a base metadata with no keys set, but with the correct version numbers. // Gets a base metadata with no keys set, but with the correct version numbers.
func version_getBaseMetadata() version_metadata { func version_getBaseMetadata() version_metadata {
return version_metadata{ return version_metadata{
@ -77,7 +86,7 @@ func (m *version_metadata) encode(privateKey ed25519.PrivateKey, password []byte
return nil, err return nil, err
} }
if n != ed25519.PublicKeySize { if n != ed25519.PublicKeySize {
return nil, fmt.Errorf("hash writer only wrote %d bytes", n) return nil, ErrHandshakeHashFailure
} }
hash := hasher.Sum(nil) hash := hasher.Sum(nil)
bs = append(bs, ed25519.Sign(privateKey, hash)...) bs = append(bs, ed25519.Sign(privateKey, hash)...)
@ -94,11 +103,11 @@ func (m *version_metadata) decode(r io.Reader, password []byte) error {
} }
meta := [4]byte{'m', 'e', 't', 'a'} meta := [4]byte{'m', 'e', 't', 'a'}
if !bytes.Equal(bh[:4], meta[:]) { if !bytes.Equal(bh[:4], meta[:]) {
return fmt.Errorf("invalid handshake preamble") return ErrHandshakeInvalidPreamble
} }
hl := binary.BigEndian.Uint16(bh[4:6]) hl := binary.BigEndian.Uint16(bh[4:6])
if hl < ed25519.SignatureSize { if hl < ed25519.SignatureSize {
return fmt.Errorf("invalid handshake length") return ErrHandshakeInvalidLength
} }
bs := make([]byte, hl) bs := make([]byte, hl)
if _, err := io.ReadFull(r, bs); err != nil { if _, err := io.ReadFull(r, bs); err != nil {
@ -132,15 +141,15 @@ func (m *version_metadata) decode(r io.Reader, password []byte) error {
hasher, err := blake2b.New512(password) hasher, err := blake2b.New512(password)
if err != nil { if err != nil {
return fmt.Errorf("invalid password supplied") return ErrHandshakeInvalidPassword
} }
n, err := hasher.Write(m.publicKey) n, err := hasher.Write(m.publicKey)
if err != nil || n != ed25519.PublicKeySize { if err != nil || n != ed25519.PublicKeySize {
return fmt.Errorf("failed to generate hash") return ErrHandshakeHashFailure
} }
hash := hasher.Sum(nil) hash := hasher.Sum(nil)
if !ed25519.Verify(m.publicKey, hash, sig) { if !ed25519.Verify(m.publicKey, hash, sig) {
return fmt.Errorf("password is incorrect") return ErrHandshakeIncorrectPassword
} }
return nil return nil
} }