x/crypto/ssh: error from ssh.HostKeyCallback is not wrapped during handshake #61309
Closed
Description
What version of Go are you using (go version
)?
$ go version go version go1.20.5 darwin/arm64
Does this issue reproduce with the latest release?
Yes.
Root cause
https://github.com/golang/crypto/blob/2e82bdd17/ssh/client.go#L85
return nil, nil, nil, fmt.Errorf("ssh: handshake failed: %v", err)
It does not wrap the causing err
using %w
.
What did you do?
In my program, there is a mechanism that, for a given host, maintains []ssh.PublicKey
with known host keys.
With this slice in hands, we proceed to call ssh.NewClientConn
with:
ssh.ClientConfig{
HostKeyCallback: validateHostKeys(known),
...
}
During ssh handshake if the host key doesn't match any keys from that slice, we get an error:
ssh: handshake failed: unknown host key: ecdsa-sha2-nistp256 AAAAElided...
The "unknown host key: ..."
part comes from function validateHostKeys
:
var ErrUnknownHostKey = errors.New("unknown host key")
func validateHostKeys(knownHostKeys []ssh.PublicKey) ssh.HostKeyCallback {
return func(hostname string, remote net.Addr, hostKey ssh.PublicKey) error {
if hostKey == nil {
return fmt.Errorf("got a nil host key")
}
for _, knownHostKey := range knownHostKeys {
if bytes.Equal(hostKey.Marshal(), knownHostKey.Marshal()) {
return nil
}
}
return fmt.Errorf("%w: %s",
ErrUnknownHostKey, bytes.TrimSpace(ssh.MarshalAuthorizedKey(hostKey)))
}
}
What did you expect to see?
In my host validation error handler, I am using:
errors.Is(err, ErrUnknownHostKey)
... and expect it to return true
when such error indeed arises.
What did you see instead?
It returns false
.