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 ErrLinkPriorityInvalid = linkError("priority value 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 ErrLinkMaxBackoffInvalid = linkError("max backoff duration invalid")
@ -363,9 +363,11 @@ func (l *links) add(u *url.URL, sintf string, linkType linkType) error {
_ = lc.Close()
phony.Block(l, func() {
state._conn = nil
if state._err = err; state._err != nil {
state._errtime = time.Now()
if err == nil {
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
@ -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",
dir, remoteStr, localStr, err)
}
return nil
return err
}
func urlForLinkInfo(u url.URL) url.URL {

View File

@ -8,7 +8,6 @@ import (
"bytes"
"crypto/ed25519"
"encoding/binary"
"fmt"
"io"
"golang.org/x/crypto/blake2b"
@ -38,6 +37,16 @@ const (
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.
func version_getBaseMetadata() version_metadata {
return version_metadata{
@ -77,7 +86,7 @@ func (m *version_metadata) encode(privateKey ed25519.PrivateKey, password []byte
return nil, err
}
if n != ed25519.PublicKeySize {
return nil, fmt.Errorf("hash writer only wrote %d bytes", n)
return nil, ErrHandshakeHashFailure
}
hash := hasher.Sum(nil)
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'}
if !bytes.Equal(bh[:4], meta[:]) {
return fmt.Errorf("invalid handshake preamble")
return ErrHandshakeInvalidPreamble
}
hl := binary.BigEndian.Uint16(bh[4:6])
if hl < ed25519.SignatureSize {
return fmt.Errorf("invalid handshake length")
return ErrHandshakeInvalidLength
}
bs := make([]byte, hl)
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)
if err != nil {
return fmt.Errorf("invalid password supplied")
return ErrHandshakeInvalidPassword
}
n, err := hasher.Write(m.publicKey)
if err != nil || n != ed25519.PublicKeySize {
return fmt.Errorf("failed to generate hash")
return ErrHandshakeHashFailure
}
hash := hasher.Sum(nil)
if !ed25519.Verify(m.publicKey, hash, sig) {
return fmt.Errorf("password is incorrect")
return ErrHandshakeIncorrectPassword
}
return nil
}