Skip to content

Commit 8bef38d

Browse files
bradfitziQQBot
authored andcommitted
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. See golang/go#51994 and https://go-review.googlesource.com/c/crypto/+/395314 Change-Id: I83ea80901d4977d8f78523e3d1e16e0a7df5b172 (cherry picked from commit 4a431fab27b09acb1458fbb8709e12b2760e58a2)
1 parent 0b15d35 commit 8bef38d

File tree

2 files changed

+64
-1
lines changed

2 files changed

+64
-1
lines changed

ssh/server.go

Lines changed: 13 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -68,8 +68,16 @@ type ServerConfig struct {
6868

6969
// NoClientAuth is true if clients are allowed to connect without
7070
// authenticating.
71+
// To determine NoClientAuth at runtime, set NoClientAuth to true
72+
// and the optional NoClientAuthCallback to a non-nil value.
7173
NoClientAuth bool
7274

75+
// NoClientAuthCallback, if non-nil, is called when a user
76+
// attempts to authenticate with auth method "none".
77+
// NoClientAuth must also be set to true for this be used, or
78+
// this func is unused.
79+
NoClientAuthCallback func(ConnMetadata) (*Permissions, error)
80+
7381
// MaxAuthTries specifies the maximum number of authentication attempts
7482
// permitted per connection. If set to a negative number, the number of
7583
// attempts are unlimited. If set to zero, the number of attempts are limited
@@ -455,7 +463,11 @@ userAuthLoop:
455463
switch userAuthReq.Method {
456464
case "none":
457465
if config.NoClientAuth {
458-
authErr = nil
466+
if config.NoClientAuthCallback != nil {
467+
perms, authErr = config.NoClientAuthCallback(s)
468+
} else {
469+
authErr = nil
470+
}
459471
}
460472

461473
// allow initial attempt of 'none' without penalty

ssh/session_test.go

Lines changed: 51 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -780,3 +780,54 @@ func TestHostKeyAlgorithms(t *testing.T) {
780780
t.Fatal("succeeded connecting with unknown hostkey algorithm")
781781
}
782782
}
783+
784+
func TestServerClientAuthCallback(t *testing.T) {
785+
c1, c2, err := netPipe()
786+
if err != nil {
787+
t.Fatalf("netPipe: %v", err)
788+
}
789+
defer c1.Close()
790+
defer c2.Close()
791+
792+
userCh := make(chan string, 1)
793+
794+
serverConf := &ServerConfig{
795+
NoClientAuth: true,
796+
NoClientAuthCallback: func(conn ConnMetadata) (*Permissions, error) {
797+
userCh <- conn.User()
798+
return nil, nil
799+
},
800+
}
801+
const someUsername = "some-username"
802+
803+
serverConf.AddHostKey(testSigners["ecdsa"])
804+
clientConf := &ClientConfig{
805+
HostKeyCallback: InsecureIgnoreHostKey(),
806+
User: someUsername,
807+
}
808+
809+
go func() {
810+
_, chans, reqs, err := NewServerConn(c1, serverConf)
811+
if err != nil {
812+
t.Errorf("server handshake: %v", err)
813+
userCh <- "error"
814+
return
815+
}
816+
go DiscardRequests(reqs)
817+
for ch := range chans {
818+
ch.Reject(Prohibited, "")
819+
}
820+
}()
821+
822+
conn, _, _, err := NewClientConn(c2, "", clientConf)
823+
if err != nil {
824+
t.Fatalf("client handshake: %v", err)
825+
return
826+
}
827+
conn.Close()
828+
829+
got := <-userCh
830+
if got != someUsername {
831+
t.Errorf("username = %q; want %q", got, someUsername)
832+
}
833+
}

0 commit comments

Comments
 (0)