aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorBrad Fitzpatrick <bradfitz@golang.org>2022-03-23 14:41:31 -0700
committerRoland Shoemaker <roland@golang.org>2022-10-10 15:29:10 +0000
commitd6f0a8c073c28df7d0a9b3c8f4206a8f72b341e4 (patch)
tree8c0566611630f5317b4ac2628e9a66f6ca2aa11f
parent4161e89ecf1b4f3413a75e017ee689d0c5a3192a (diff)
downloadgo-x-crypto-d6f0a8c073c28df7d0a9b3c8f4206a8f72b341e4.tar.xz
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>
-rw-r--r--ssh/server.go14
-rw-r--r--ssh/session_test.go51
2 files changed, 64 insertions, 1 deletions
diff --git a/ssh/server.go b/ssh/server.go
index 70045bd..2260b20 100644
--- a/ssh/server.go
+++ b/ssh/server.go
@@ -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
diff --git a/ssh/session_test.go b/ssh/session_test.go
index 2568a88..c4b9f0e 100644
--- a/ssh/session_test.go
+++ b/ssh/session_test.go
@@ -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)
+ }
+}