ssh: add ServerConfig.NoClientAuthCallback
It was possible to accept auth type "none" before, but not dynamically at runtime as a function of the ConnMetadata like the other auth types' callback hooks. Fixes golang/go#51994 Change-Id: I83ea80901d4977d8f78523e3d1e16e0a7df5b172 Reviewed-on: https://go-review.googlesource.com/c/crypto/+/395314 Reviewed-by: Roland Shoemaker <roland@golang.org> Run-TryBot: Brad Fitzpatrick <bradfitz@golang.org> TryBot-Result: Gopher Robot <gobot@golang.org> Reviewed-by: Julie Qiu <julieqiu@google.com>
This commit is contained in:
committed by
Roland Shoemaker
parent
4161e89ecf
commit
d6f0a8c073
+13
-1
@@ -68,8 +68,16 @@ type ServerConfig struct {
|
||||
|
||||
// NoClientAuth is true if clients are allowed to connect without
|
||||
// authenticating.
|
||||
// To determine NoClientAuth at runtime, set NoClientAuth to true
|
||||
// and the optional NoClientAuthCallback to a non-nil value.
|
||||
NoClientAuth bool
|
||||
|
||||
// NoClientAuthCallback, if non-nil, is called when a user
|
||||
// attempts to authenticate with auth method "none".
|
||||
// NoClientAuth must also be set to true for this be used, or
|
||||
// this func is unused.
|
||||
NoClientAuthCallback func(ConnMetadata) (*Permissions, error)
|
||||
|
||||
// MaxAuthTries specifies the maximum number of authentication attempts
|
||||
// permitted per connection. If set to a negative number, the number of
|
||||
// attempts are unlimited. If set to zero, the number of attempts are limited
|
||||
@@ -455,7 +463,11 @@ userAuthLoop:
|
||||
switch userAuthReq.Method {
|
||||
case "none":
|
||||
if config.NoClientAuth {
|
||||
authErr = nil
|
||||
if config.NoClientAuthCallback != nil {
|
||||
perms, authErr = config.NoClientAuthCallback(s)
|
||||
} else {
|
||||
authErr = nil
|
||||
}
|
||||
}
|
||||
|
||||
// allow initial attempt of 'none' without penalty
|
||||
|
||||
@@ -779,3 +779,54 @@ func TestHostKeyAlgorithms(t *testing.T) {
|
||||
t.Fatal("succeeded connecting with unknown hostkey algorithm")
|
||||
}
|
||||
}
|
||||
|
||||
func TestServerClientAuthCallback(t *testing.T) {
|
||||
c1, c2, err := netPipe()
|
||||
if err != nil {
|
||||
t.Fatalf("netPipe: %v", err)
|
||||
}
|
||||
defer c1.Close()
|
||||
defer c2.Close()
|
||||
|
||||
userCh := make(chan string, 1)
|
||||
|
||||
serverConf := &ServerConfig{
|
||||
NoClientAuth: true,
|
||||
NoClientAuthCallback: func(conn ConnMetadata) (*Permissions, error) {
|
||||
userCh <- conn.User()
|
||||
return nil, nil
|
||||
},
|
||||
}
|
||||
const someUsername = "some-username"
|
||||
|
||||
serverConf.AddHostKey(testSigners["ecdsa"])
|
||||
clientConf := &ClientConfig{
|
||||
HostKeyCallback: InsecureIgnoreHostKey(),
|
||||
User: someUsername,
|
||||
}
|
||||
|
||||
go func() {
|
||||
_, chans, reqs, err := NewServerConn(c1, serverConf)
|
||||
if err != nil {
|
||||
t.Errorf("server handshake: %v", err)
|
||||
userCh <- "error"
|
||||
return
|
||||
}
|
||||
go DiscardRequests(reqs)
|
||||
for ch := range chans {
|
||||
ch.Reject(Prohibited, "")
|
||||
}
|
||||
}()
|
||||
|
||||
conn, _, _, err := NewClientConn(c2, "", clientConf)
|
||||
if err != nil {
|
||||
t.Fatalf("client handshake: %v", err)
|
||||
return
|
||||
}
|
||||
conn.Close()
|
||||
|
||||
got := <-userCh
|
||||
if got != someUsername {
|
||||
t.Errorf("username = %q; want %q", got, someUsername)
|
||||
}
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user