Skip to content

Commit 8347f93

Browse files
committed
ssh: clarify intended use of Permissions.
The Permissions struct should be used to pass information from authentication callback to server application. Fixes golang/go#20094. Change-Id: I5542b657d053452327260707a24925286546bfdd Reviewed-on: https://go-review.googlesource.com/45311 Run-TryBot: Han-Wen Nienhuys <[email protected]> TryBot-Result: Gobot Gobot <[email protected]> Reviewed-by: Brad Fitzpatrick <[email protected]>
1 parent 561dd56 commit 8347f93

File tree

2 files changed

+41
-18
lines changed

2 files changed

+41
-18
lines changed

example_test.go

Lines changed: 9 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -56,7 +56,12 @@ func ExampleNewServerConn() {
5656
// Remove to disable public key auth.
5757
PublicKeyCallback: func(c ssh.ConnMetadata, pubKey ssh.PublicKey) (*ssh.Permissions, error) {
5858
if authorizedKeysMap[string(pubKey.Marshal())] {
59-
return nil, nil
59+
return &ssh.Permissions{
60+
// Record the public key used for authentication.
61+
Extensions: map[string]string{
62+
"pubkey-fp": ssh.FingerprintSHA256(pubKey),
63+
},
64+
}, nil
6065
}
6166
return nil, fmt.Errorf("unknown public key for %q", c.User())
6267
},
@@ -87,10 +92,12 @@ func ExampleNewServerConn() {
8792

8893
// Before use, a handshake must be performed on the incoming
8994
// net.Conn.
90-
_, chans, reqs, err := ssh.NewServerConn(nConn, config)
95+
conn, chans, reqs, err := ssh.NewServerConn(nConn, config)
9196
if err != nil {
9297
log.Fatal("failed to handshake: ", err)
9398
}
99+
log.Printf("logged in with key %s", conn.Permissions.Extensions["pubkey-fp"])
100+
94101
// The incoming Request channel must be serviced.
95102
go ssh.DiscardRequests(reqs)
96103

server.go

Lines changed: 32 additions & 16 deletions
Original file line numberDiff line numberDiff line change
@@ -14,23 +14,34 @@ import (
1414
)
1515

1616
// The Permissions type holds fine-grained permissions that are
17-
// specific to a user or a specific authentication method for a
18-
// user. Permissions, except for "source-address", must be enforced in
19-
// the server application layer, after successful authentication. The
20-
// Permissions are passed on in ServerConn so a server implementation
21-
// can honor them.
17+
// specific to a user or a specific authentication method for a user.
18+
// The Permissions value for a successful authentication attempt is
19+
// available in ServerConn, so it can be used to pass information from
20+
// the user-authentication phase to the application layer.
2221
type Permissions struct {
23-
// Critical options restrict default permissions. Common
24-
// restrictions are "source-address" and "force-command". If
25-
// the server cannot enforce the restriction, or does not
26-
// recognize it, the user should not authenticate.
22+
// CriticalOptions indicate restrictions to the default
23+
// permissions, and are typically used in conjunction with
24+
// user certificates. The standard for SSH certificates
25+
// defines "force-command" (only allow the given command to
26+
// execute) and "source-address" (only allow connections from
27+
// the given address). The SSH package currently only enforces
28+
// the "source-address" critical option. It is up to server
29+
// implementations to enforce other critical options, such as
30+
// "force-command", by checking them after the SSH handshake
31+
// is successful. In general, SSH servers should reject
32+
// connections that specify critical options that are unknown
33+
// or not supported.
2734
CriticalOptions map[string]string
2835

2936
// Extensions are extra functionality that the server may
30-
// offer on authenticated connections. Common extensions are
31-
// "permit-agent-forwarding", "permit-X11-forwarding". Lack of
32-
// support for an extension does not preclude authenticating a
33-
// user.
37+
// offer on authenticated connections. Lack of support for an
38+
// extension does not preclude authenticating a user. Common
39+
// extensions are "permit-agent-forwarding",
40+
// "permit-X11-forwarding". The Go SSH library currently does
41+
// not act on any extension, and it is up to server
42+
// implementations to honor them. Extensions can be used to
43+
// pass data from the authentication callbacks to the server
44+
// application layer.
3445
Extensions map[string]string
3546
}
3647

@@ -55,9 +66,14 @@ type ServerConfig struct {
5566
// attempts to authenticate using a password.
5667
PasswordCallback func(conn ConnMetadata, password []byte) (*Permissions, error)
5768

58-
// PublicKeyCallback, if non-nil, is called when a client attempts public
59-
// key authentication. It must return true if the given public key is
60-
// valid for the given user. For example, see CertChecker.Authenticate.
69+
// PublicKeyCallback, if non-nil, is called when a client
70+
// offers a public key for authentication. It must return true
71+
// if the given public key can be used to authenticate the
72+
// given user. For example, see CertChecker.Authenticate. A
73+
// call to this function does not guarantee that the key
74+
// offered is in fact used to authenticate. To record any data
75+
// depending on the public key, store it inside a
76+
// Permissions.Extensions entry.
6177
PublicKeyCallback func(conn ConnMetadata, key PublicKey) (*Permissions, error)
6278

6379
// KeyboardInteractiveCallback, if non-nil, is called when

0 commit comments

Comments
 (0)