浏览代码

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
 		}