+60
-4
lines changedFilter options
+60
-4
lines changed Original file line number Diff line number Diff line change
@@ -149,15 +149,21 @@ func (s *ServerConfig) AddHostKey(key Signer) {
149
149
}
150
150
151
151
// cachedPubKey contains the results of querying whether a public key is
152
-
// acceptable for a user.
152
+
// acceptable for a user. This is a FIFO cache.
153
153
type cachedPubKey struct {
154
154
user string
155
155
pubKeyData []byte
156
156
result error
157
157
perms *Permissions
158
158
}
159
159
160
-
const maxCachedPubKeys = 16
160
+
// maxCachedPubKeys is the number of cache entries we store.
161
+
//
162
+
// Due to consistent misuse of the PublicKeyCallback API, we have reduced this
163
+
// to 1, such that the only key in the cache is the most recently seen one. This
164
+
// forces the behavior that the last call to PublicKeyCallback will always be
165
+
// with the key that is used for authentication.
166
+
const maxCachedPubKeys = 1
161
167
162
168
// pubKeyCache caches tests for public keys. Since SSH clients
163
169
// will query whether a public key is acceptable before attempting to
@@ -179,9 +185,10 @@ func (c *pubKeyCache) get(user string, pubKeyData []byte) (cachedPubKey, bool) {
179
185
180
186
// add adds the given tuple to the cache.
181
187
func (c *pubKeyCache) add(candidate cachedPubKey) {
182
-
if len(c.keys) < maxCachedPubKeys {
183
-
c.keys = append(c.keys, candidate)
188
+
if len(c.keys) >= maxCachedPubKeys {
189
+
c.keys = c.keys[1:]
184
190
}
191
+
c.keys = append(c.keys, candidate)
185
192
}
186
193
187
194
// ServerConn is an authenticated SSH connection, as seen from the
Original file line number Diff line number Diff line change
@@ -5,6 +5,7 @@
5
5
package ssh
6
6
7
7
import (
8
+
"bytes"
8
9
"errors"
9
10
"fmt"
10
11
"io"
@@ -299,6 +300,54 @@ func TestBannerError(t *testing.T) {
299
300
}
300
301
}
301
302
303
+
func TestPublicKeyCallbackLastSeen(t *testing.T) {
304
+
var lastSeenKey PublicKey
305
+
306
+
c1, c2, err := netPipe()
307
+
if err != nil {
308
+
t.Fatalf("netPipe: %v", err)
309
+
}
310
+
defer c1.Close()
311
+
defer c2.Close()
312
+
serverConf := &ServerConfig{
313
+
PublicKeyCallback: func(conn ConnMetadata, key PublicKey) (*Permissions, error) {
314
+
lastSeenKey = key
315
+
fmt.Printf("seen %#v\n", key)
316
+
if _, ok := key.(*dsaPublicKey); !ok {
317
+
return nil, errors.New("nope")
318
+
}
319
+
return nil, nil
320
+
},
321
+
}
322
+
serverConf.AddHostKey(testSigners["ecdsap256"])
323
+
324
+
done := make(chan struct{})
325
+
go func() {
326
+
defer close(done)
327
+
NewServerConn(c1, serverConf)
328
+
}()
329
+
330
+
clientConf := ClientConfig{
331
+
User: "user",
332
+
Auth: []AuthMethod{
333
+
PublicKeys(testSigners["rsa"], testSigners["dsa"], testSigners["ed25519"]),
334
+
},
335
+
HostKeyCallback: InsecureIgnoreHostKey(),
336
+
}
337
+
338
+
_, _, _, err = NewClientConn(c2, "", &clientConf)
339
+
if err != nil {
340
+
t.Fatal(err)
341
+
}
342
+
<-done
343
+
344
+
expectedPublicKey := testSigners["dsa"].PublicKey().Marshal()
345
+
lastSeenMarshalled := lastSeenKey.Marshal()
346
+
if !bytes.Equal(lastSeenMarshalled, expectedPublicKey) {
347
+
t.Errorf("unexpected key: got %#v, want %#v", lastSeenKey, testSigners["dsa"].PublicKey())
348
+
}
349
+
}
350
+
302
351
type markerConn struct {
303
352
closed uint32
304
353
used uint32
You can’t perform that action at this time.
RetroSearch is an open source project built by @garambo | Open a GitHub Issue
Search and Browse the WWW like it's 1997 | Search results from DuckDuckGo
HTML:
3.2
| Encoding:
UTF-8
| Version:
0.7.4