aboutsummaryrefslogtreecommitdiff
path: root/ssh
diff options
context:
space:
mode:
authorAdam Langley <agl@golang.org>2014-05-12 11:19:56 -0700
committerAdam Langley <agl@golang.org>2014-05-12 11:19:56 -0700
commit2dfe547928fdf792f2d4b626eeab4490419ca5f4 (patch)
treee24ebd7be9a7c5a98f7ae8f8720f97001c2d5c82 /ssh
parent6f0540ef5e740839c84c8a89ac9cd1c72a3bdacd (diff)
downloadgo-x-crypto-2dfe547928fdf792f2d4b626eeab4490419ca5f4.tar.xz
go.crypto/ssh: use permissions from public key cache when accepting a key.
Fixes golang/go#7913. LGTM=hanwen R=hanwen CC=golang-codereviews https://golang.org/cl/96220043
Diffstat (limited to 'ssh')
-rw-r--r--ssh/client_auth_test.go48
-rw-r--r--ssh/server.go21
2 files changed, 56 insertions, 13 deletions
diff --git a/ssh/client_auth_test.go b/ssh/client_auth_test.go
index e6b979f..c92b587 100644
--- a/ssh/client_auth_test.go
+++ b/ssh/client_auth_test.go
@@ -343,3 +343,51 @@ func TestClientLoginCert(t *testing.T) {
t.Errorf("cert login with source-address succeeded")
}
}
+
+func testPermissionsPassing(withPermissions bool, t *testing.T) {
+ serverConfig := &ServerConfig{
+ PublicKeyCallback: func(conn ConnMetadata, key PublicKey) (*Permissions, error) {
+ if conn.User() == "nopermissions" {
+ return nil, nil
+ } else {
+ return &Permissions{}, nil
+ }
+ },
+ }
+ serverConfig.AddHostKey(testSigners["rsa"])
+
+ clientConfig := &ClientConfig{
+ Auth: []AuthMethod{
+ PublicKeys(testSigners["rsa"]),
+ },
+ }
+ if withPermissions {
+ clientConfig.User = "permissions"
+ } else {
+ clientConfig.User = "nopermissions"
+ }
+
+ c1, c2, err := netPipe()
+ if err != nil {
+ t.Fatalf("netPipe: %v", err)
+ }
+ defer c1.Close()
+ defer c2.Close()
+
+ go NewClientConn(c2, "", clientConfig)
+ serverConn, err := newServer(c1, serverConfig)
+ if err != nil {
+ t.Fatal(err)
+ }
+ if p := serverConn.Permissions; (p != nil) != withPermissions {
+ t.Fatalf("withPermissions is %t, but Permissions object is %#v", withPermissions, p)
+ }
+}
+
+func TestPermissionsPassing(t *testing.T) {
+ testPermissionsPassing(true, t)
+}
+
+func TestNoPermissionsPassing(t *testing.T) {
+ testPermissionsPassing(false, t)
+}
diff --git a/ssh/server.go b/ssh/server.go
index 7a53d57..8c4f142 100644
--- a/ssh/server.go
+++ b/ssh/server.go
@@ -90,10 +90,6 @@ type cachedPubKey struct {
perms *Permissions
}
-func (k1 *cachedPubKey) Equal(k2 *cachedPubKey) bool {
- return k1.user == k2.user && bytes.Equal(k1.pubKeyData, k2.pubKeyData)
-}
-
const maxCachedPubKeys = 16
// pubKeyCache caches tests for public keys. Since SSH clients
@@ -105,13 +101,13 @@ type pubKeyCache struct {
}
// get returns the result for a given user/algo/key tuple.
-func (c *pubKeyCache) get(candidate cachedPubKey) (result error, ok bool) {
+func (c *pubKeyCache) get(user string, pubKeyData []byte) (cachedPubKey, bool) {
for _, k := range c.keys {
- if k.Equal(&candidate) {
- return k.result, true
+ if k.user == user && bytes.Equal(k.pubKeyData, pubKeyData) {
+ return k, true
}
}
- return errors.New("ssh: not in cache"), false
+ return cachedPubKey{}, false
}
// add adds the given tuple to the cache.
@@ -333,12 +329,11 @@ userAuthLoop:
if err != nil {
return nil, err
}
- candidate := cachedPubKey{
- user: s.user,
- pubKeyData: pubKeyData,
- }
- candidate.result, ok = cache.get(candidate)
+
+ candidate, ok := cache.get(s.user, pubKeyData)
if !ok {
+ candidate.user = s.user
+ candidate.pubKeyData = pubKeyData
candidate.perms, candidate.result = config.PublicKeyCallback(s, pubKey)
if candidate.result == nil && candidate.perms != nil && candidate.perms.CriticalOptions != nil && candidate.perms.CriticalOptions[sourceAddressCriticalOption] != "" {
candidate.result = checkSourceAddress(