Переглянути джерело

go.crypto/ssh: fix authentication after all public keys are rejected by a server.

Validating a public key doesn't return any remaining methods so, if all public keys were rejected, a nil slice would be returned for the remaining methods and authentication would stop.

We could have validateKey return methods, but that wouldn't solve the problem of what to do if the callback returns no keys. In that case we don't have any keys to test.

So this change makes it possible for an AuthMethod to return a nil slice for the remaining methods (meaning "reuse the last list"). It also fixes a scoping bug.

Fixes golang/go#7787.

LGTM=hanwen
R=hanwen
CC=golang-codereviews
https://golang.org/cl/94350043
Adam Langley 11 роки тому
батько
коміт
c34e38ab9e
1 змінених файлів з 9 додано та 2 видалено
  1. 9 2
      ssh/client_auth.go

+ 9 - 2
ssh/client_auth.go

@@ -29,6 +29,7 @@ func (c *connection) clientAuthenticate(config *ClientConfig) error {
 	// during the authentication phase the client first attempts the "none" method
 	// then any untried methods suggested by the server.
 	tried := make(map[string]bool)
+	var lastMethods []string
 	for auth := AuthMethod(new(noneAuth)); auth != nil; {
 		ok, methods, err := auth.auth(c.transport.getSessionID(), config.User, c.transport, config.Rand)
 		if err != nil {
@@ -39,6 +40,10 @@ func (c *connection) clientAuthenticate(config *ClientConfig) error {
 			return nil
 		}
 		tried[auth.method()] = true
+		if methods == nil {
+			methods = lastMethods
+		}
+		lastMethods = methods
 
 		auth = nil
 
@@ -73,7 +78,8 @@ type AuthMethod interface {
 	// auth authenticates user over transport t.
 	// Returns true if authentication is successful.
 	// If authentication is not successful, a []string of alternative
-	// method names is returned.
+	// method names is returned. If the slice is nil, it will be ignored
+	// and the previous set of possible methods will be reused.
 	auth(session []byte, user string, p packetConn, rand io.Reader) (bool, []string, error)
 
 	// method returns the RFC 4252 method name.
@@ -223,7 +229,8 @@ func (cb publicKeyCallback) auth(session []byte, user string, c packetConn, rand
 		if err := c.writePacket(p); err != nil {
 			return false, nil, err
 		}
-		success, methods, err := handleAuthResponse(c)
+		var success bool
+		success, methods, err = handleAuthResponse(c)
 		if err != nil {
 			return false, nil, err
 		}