Skip to content

Commit

Permalink
ssh: wrap errors from client handshake
Browse files Browse the repository at this point in the history
When an error is returned by a user defined host key callback,
it is now possible to handle it using standard Go mechanisms
such as errors.Is or errors.As.

Fixes golang/go#61309

Change-Id: I4269c5f8eacd8e7e8d85070ad249f0e27777b15f
GitHub-Last-Rev: d2a34d5
GitHub-Pull-Request: #266
Reviewed-on: https://go-review.googlesource.com/c/crypto/+/508876
Run-TryBot: Nicola Murino <nicola.murino@gmail.com>
Auto-Submit: Dmitri Shuralyov <dmitshur@golang.org>
Reviewed-by: Muhammad Shulhan <m.shulhan@gmail.com>
Reviewed-by: Michael Knyszek <mknyszek@google.com>
Reviewed-by: Dmitri Shuralyov <dmitshur@google.com>
Reviewed-by: Nicola Murino <nicola.murino@gmail.com>
TryBot-Result: Gopher Robot <gobot@golang.org>
  • Loading branch information
paxan authored and gopherbot committed Nov 27, 2023
1 parent bda2f3f commit 7e6fbd8
Show file tree
Hide file tree
Showing 2 changed files with 24 additions and 3 deletions.
2 changes: 1 addition & 1 deletion ssh/client.go
Original file line number Diff line number Diff line change
Expand Up @@ -82,7 +82,7 @@ func NewClientConn(c net.Conn, addr string, config *ClientConfig) (Conn, <-chan

if err := conn.clientHandshake(addr, &fullConf); err != nil {
c.Close()
return nil, nil, nil, fmt.Errorf("ssh: handshake failed: %v", err)
return nil, nil, nil, fmt.Errorf("ssh: handshake failed: %w", err)
}
conn.mux = newMux(conn.transport)
return conn, conn.mux.incomingChannels, conn.mux.incomingRequests, nil
Expand Down
25 changes: 23 additions & 2 deletions ssh/client_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,9 @@ package ssh
import (
"bytes"
"crypto/rand"
"errors"
"fmt"
"net"
"strings"
"testing"
)
Expand Down Expand Up @@ -207,9 +210,12 @@ func TestBannerCallback(t *testing.T) {
}

func TestNewClientConn(t *testing.T) {
errHostKeyMismatch := errors.New("host key mismatch")

for _, tt := range []struct {
name string
user string
name string
user string
simulateHostKeyMismatch HostKeyCallback
}{
{
name: "good user field for ConnMetadata",
Expand All @@ -219,6 +225,13 @@ func TestNewClientConn(t *testing.T) {
name: "empty user field for ConnMetadata",
user: "",
},
{
name: "host key mismatch",
user: "testuser",
simulateHostKeyMismatch: func(hostname string, remote net.Addr, key PublicKey) error {
return fmt.Errorf("%w: %s", errHostKeyMismatch, bytes.TrimSpace(MarshalAuthorizedKey(key)))
},
},
} {
t.Run(tt.name, func(t *testing.T) {
c1, c2, err := netPipe()
Expand All @@ -243,8 +256,16 @@ func TestNewClientConn(t *testing.T) {
},
HostKeyCallback: InsecureIgnoreHostKey(),
}

if tt.simulateHostKeyMismatch != nil {
clientConf.HostKeyCallback = tt.simulateHostKeyMismatch
}

clientConn, _, _, err := NewClientConn(c2, "", clientConf)
if err != nil {
if tt.simulateHostKeyMismatch != nil && errors.Is(err, errHostKeyMismatch) {
return
}
t.Fatal(err)
}

Expand Down

0 comments on commit 7e6fbd8

Please sign in to comment.