Skip to content

Commit

Permalink
ssh: return specific error for invalid signature algorithm
Browse files Browse the repository at this point in the history
Previously, this would return the default error "no auth passed yet".

Not only is the new error more specific, it makes it easier to verify
the control flow of server authentication code.

Change-Id: I6c8de4e3f91da74274acbe9d87ec4f6158b4a94f
Reviewed-on: https://go-review.googlesource.com/c/142897
Run-TryBot: Han-Wen Nienhuys <hanwen@google.com>
TryBot-Result: Gobot Gobot <gobot@golang.org>
Reviewed-by: Brad Fitzpatrick <bradfitz@golang.org>
  • Loading branch information
hanwen committed Nov 6, 2018
1 parent bfa7d42 commit e4dc69e
Show file tree
Hide file tree
Showing 2 changed files with 53 additions and 2 deletions.
54 changes: 52 additions & 2 deletions ssh/client_auth_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,7 @@ import (
"crypto/rand"
"errors"
"fmt"
"io"
"os"
"strings"
"testing"
Expand All @@ -28,8 +29,14 @@ func (cr keyboardInteractive) Challenge(user string, instruction string, questio
var clientPassword = "tiger"

// tryAuth runs a handshake with a given config against an SSH server
// with config serverConfig
// with config serverConfig. Returns both client and server side errors.
func tryAuth(t *testing.T, config *ClientConfig) error {
err, _ := tryAuthBothSides(t, config)
return err
}

// tryAuthBothSides runs the handshake and returns the resulting errors from both sides of the connection.
func tryAuthBothSides(t *testing.T, config *ClientConfig) (clientError error, serverAuthErrors []error) {
c1, c2, err := netPipe()
if err != nil {
t.Fatalf("netPipe: %v", err)
Expand Down Expand Up @@ -79,9 +86,13 @@ func tryAuth(t *testing.T, config *ClientConfig) error {
}
serverConfig.AddHostKey(testSigners["rsa"])

serverConfig.AuthLogCallback = func(conn ConnMetadata, method string, err error) {
serverAuthErrors = append(serverAuthErrors, err)
}

go newServer(c1, serverConfig)
_, _, _, err = NewClientConn(c2, "", config)
return err
return err, serverAuthErrors
}

func TestClientAuthPublicKey(t *testing.T) {
Expand Down Expand Up @@ -213,6 +224,45 @@ func TestAuthMethodRSAandDSA(t *testing.T) {
}
}

type invalidAlgSigner struct {
Signer
}

func (s *invalidAlgSigner) Sign(rand io.Reader, data []byte) (*Signature, error) {
sig, err := s.Signer.Sign(rand, data)
if sig != nil {
sig.Format = "invalid"
}
return sig, err
}

func TestMethodInvalidAlgorithm(t *testing.T) {
config := &ClientConfig{
User: "testuser",
Auth: []AuthMethod{
PublicKeys(&invalidAlgSigner{testSigners["rsa"]}),
},
HostKeyCallback: InsecureIgnoreHostKey(),
}

err, serverErrors := tryAuthBothSides(t, config)
if err == nil {
t.Fatalf("login succeeded")
}

found := false
want := "algorithm \"invalid\""

var errStrings []string
for _, err := range serverErrors {
found = found || (err != nil && strings.Contains(err.Error(), want))
errStrings = append(errStrings, err.Error())
}
if !found {
t.Errorf("server got error %q, want substring %q", errStrings, want)
}
}

func TestClientHMAC(t *testing.T) {
for _, mac := range supportedMACs {
config := &ClientConfig{
Expand Down
1 change: 1 addition & 0 deletions ssh/server.go
Original file line number Diff line number Diff line change
Expand Up @@ -484,6 +484,7 @@ userAuthLoop:
// sig.Format. This is usually the same, but
// for certs, the names differ.
if !isAcceptableAlgo(sig.Format) {
authErr = fmt.Errorf("ssh: algorithm %q not accepted", sig.Format)
break
}
signedData := buildDataSignedForAuth(sessionID, userAuthReq, algoBytes, pubKeyData)
Expand Down

0 comments on commit e4dc69e

Please sign in to comment.