~nskaggs/+junk/xenial-test

« back to all changes in this revision

Viewing changes to src/golang.org/x/crypto/ssh/client_auth_test.go

  • Committer: Nicholas Skaggs
  • Date: 2016-10-24 20:56:05 UTC
  • Revision ID: nicholas.skaggs@canonical.com-20161024205605-z8lta0uvuhtxwzwl
Initi with beta15

Show diffs side-by-side

added added

removed removed

Lines of Context:
 
1
// Copyright 2011 The Go Authors. All rights reserved.
 
2
// Use of this source code is governed by a BSD-style
 
3
// license that can be found in the LICENSE file.
 
4
 
 
5
package ssh
 
6
 
 
7
import (
 
8
        "bytes"
 
9
        "crypto/rand"
 
10
        "errors"
 
11
        "fmt"
 
12
        "strings"
 
13
        "testing"
 
14
)
 
15
 
 
16
type keyboardInteractive map[string]string
 
17
 
 
18
func (cr keyboardInteractive) Challenge(user string, instruction string, questions []string, echos []bool) ([]string, error) {
 
19
        var answers []string
 
20
        for _, q := range questions {
 
21
                answers = append(answers, cr[q])
 
22
        }
 
23
        return answers, nil
 
24
}
 
25
 
 
26
// reused internally by tests
 
27
var clientPassword = "tiger"
 
28
 
 
29
// tryAuth runs a handshake with a given config against an SSH server
 
30
// with config serverConfig
 
31
func tryAuth(t *testing.T, config *ClientConfig) error {
 
32
        c1, c2, err := netPipe()
 
33
        if err != nil {
 
34
                t.Fatalf("netPipe: %v", err)
 
35
        }
 
36
        defer c1.Close()
 
37
        defer c2.Close()
 
38
 
 
39
        certChecker := CertChecker{
 
40
                IsAuthority: func(k PublicKey) bool {
 
41
                        return bytes.Equal(k.Marshal(), testPublicKeys["ecdsa"].Marshal())
 
42
                },
 
43
                UserKeyFallback: func(conn ConnMetadata, key PublicKey) (*Permissions, error) {
 
44
                        if conn.User() == "testuser" && bytes.Equal(key.Marshal(), testPublicKeys["rsa"].Marshal()) {
 
45
                                return nil, nil
 
46
                        }
 
47
 
 
48
                        return nil, fmt.Errorf("pubkey for %q not acceptable", conn.User())
 
49
                },
 
50
                IsRevoked: func(c *Certificate) bool {
 
51
                        return c.Serial == 666
 
52
                },
 
53
        }
 
54
 
 
55
        serverConfig := &ServerConfig{
 
56
                PasswordCallback: func(conn ConnMetadata, pass []byte) (*Permissions, error) {
 
57
                        if conn.User() == "testuser" && string(pass) == clientPassword {
 
58
                                return nil, nil
 
59
                        }
 
60
                        return nil, errors.New("password auth failed")
 
61
                },
 
62
                PublicKeyCallback: certChecker.Authenticate,
 
63
                KeyboardInteractiveCallback: func(conn ConnMetadata, challenge KeyboardInteractiveChallenge) (*Permissions, error) {
 
64
                        ans, err := challenge("user",
 
65
                                "instruction",
 
66
                                []string{"question1", "question2"},
 
67
                                []bool{true, true})
 
68
                        if err != nil {
 
69
                                return nil, err
 
70
                        }
 
71
                        ok := conn.User() == "testuser" && ans[0] == "answer1" && ans[1] == "answer2"
 
72
                        if ok {
 
73
                                challenge("user", "motd", nil, nil)
 
74
                                return nil, nil
 
75
                        }
 
76
                        return nil, errors.New("keyboard-interactive failed")
 
77
                },
 
78
                AuthLogCallback: func(conn ConnMetadata, method string, err error) {
 
79
                        t.Logf("user %q, method %q: %v", conn.User(), method, err)
 
80
                },
 
81
        }
 
82
        serverConfig.AddHostKey(testSigners["rsa"])
 
83
 
 
84
        go newServer(c1, serverConfig)
 
85
        _, _, _, err = NewClientConn(c2, "", config)
 
86
        return err
 
87
}
 
88
 
 
89
func TestClientAuthPublicKey(t *testing.T) {
 
90
        config := &ClientConfig{
 
91
                User: "testuser",
 
92
                Auth: []AuthMethod{
 
93
                        PublicKeys(testSigners["rsa"]),
 
94
                },
 
95
        }
 
96
        if err := tryAuth(t, config); err != nil {
 
97
                t.Fatalf("unable to dial remote side: %s", err)
 
98
        }
 
99
}
 
100
 
 
101
func TestAuthMethodPassword(t *testing.T) {
 
102
        config := &ClientConfig{
 
103
                User: "testuser",
 
104
                Auth: []AuthMethod{
 
105
                        Password(clientPassword),
 
106
                },
 
107
        }
 
108
 
 
109
        if err := tryAuth(t, config); err != nil {
 
110
                t.Fatalf("unable to dial remote side: %s", err)
 
111
        }
 
112
}
 
113
 
 
114
func TestAuthMethodFallback(t *testing.T) {
 
115
        var passwordCalled bool
 
116
        config := &ClientConfig{
 
117
                User: "testuser",
 
118
                Auth: []AuthMethod{
 
119
                        PublicKeys(testSigners["rsa"]),
 
120
                        PasswordCallback(
 
121
                                func() (string, error) {
 
122
                                        passwordCalled = true
 
123
                                        return "WRONG", nil
 
124
                                }),
 
125
                },
 
126
        }
 
127
 
 
128
        if err := tryAuth(t, config); err != nil {
 
129
                t.Fatalf("unable to dial remote side: %s", err)
 
130
        }
 
131
 
 
132
        if passwordCalled {
 
133
                t.Errorf("password auth tried before public-key auth.")
 
134
        }
 
135
}
 
136
 
 
137
func TestAuthMethodWrongPassword(t *testing.T) {
 
138
        config := &ClientConfig{
 
139
                User: "testuser",
 
140
                Auth: []AuthMethod{
 
141
                        Password("wrong"),
 
142
                        PublicKeys(testSigners["rsa"]),
 
143
                },
 
144
        }
 
145
 
 
146
        if err := tryAuth(t, config); err != nil {
 
147
                t.Fatalf("unable to dial remote side: %s", err)
 
148
        }
 
149
}
 
150
 
 
151
func TestAuthMethodKeyboardInteractive(t *testing.T) {
 
152
        answers := keyboardInteractive(map[string]string{
 
153
                "question1": "answer1",
 
154
                "question2": "answer2",
 
155
        })
 
156
        config := &ClientConfig{
 
157
                User: "testuser",
 
158
                Auth: []AuthMethod{
 
159
                        KeyboardInteractive(answers.Challenge),
 
160
                },
 
161
        }
 
162
 
 
163
        if err := tryAuth(t, config); err != nil {
 
164
                t.Fatalf("unable to dial remote side: %s", err)
 
165
        }
 
166
}
 
167
 
 
168
func TestAuthMethodWrongKeyboardInteractive(t *testing.T) {
 
169
        answers := keyboardInteractive(map[string]string{
 
170
                "question1": "answer1",
 
171
                "question2": "WRONG",
 
172
        })
 
173
        config := &ClientConfig{
 
174
                User: "testuser",
 
175
                Auth: []AuthMethod{
 
176
                        KeyboardInteractive(answers.Challenge),
 
177
                },
 
178
        }
 
179
 
 
180
        if err := tryAuth(t, config); err == nil {
 
181
                t.Fatalf("wrong answers should not have authenticated with KeyboardInteractive")
 
182
        }
 
183
}
 
184
 
 
185
// the mock server will only authenticate ssh-rsa keys
 
186
func TestAuthMethodInvalidPublicKey(t *testing.T) {
 
187
        config := &ClientConfig{
 
188
                User: "testuser",
 
189
                Auth: []AuthMethod{
 
190
                        PublicKeys(testSigners["dsa"]),
 
191
                },
 
192
        }
 
193
 
 
194
        if err := tryAuth(t, config); err == nil {
 
195
                t.Fatalf("dsa private key should not have authenticated with rsa public key")
 
196
        }
 
197
}
 
198
 
 
199
// the client should authenticate with the second key
 
200
func TestAuthMethodRSAandDSA(t *testing.T) {
 
201
        config := &ClientConfig{
 
202
                User: "testuser",
 
203
                Auth: []AuthMethod{
 
204
                        PublicKeys(testSigners["dsa"], testSigners["rsa"]),
 
205
                },
 
206
        }
 
207
        if err := tryAuth(t, config); err != nil {
 
208
                t.Fatalf("client could not authenticate with rsa key: %v", err)
 
209
        }
 
210
}
 
211
 
 
212
func TestClientHMAC(t *testing.T) {
 
213
        for _, mac := range supportedMACs {
 
214
                config := &ClientConfig{
 
215
                        User: "testuser",
 
216
                        Auth: []AuthMethod{
 
217
                                PublicKeys(testSigners["rsa"]),
 
218
                        },
 
219
                        Config: Config{
 
220
                                MACs: []string{mac},
 
221
                        },
 
222
                }
 
223
                if err := tryAuth(t, config); err != nil {
 
224
                        t.Fatalf("client could not authenticate with mac algo %s: %v", mac, err)
 
225
                }
 
226
        }
 
227
}
 
228
 
 
229
// issue 4285.
 
230
func TestClientUnsupportedCipher(t *testing.T) {
 
231
        config := &ClientConfig{
 
232
                User: "testuser",
 
233
                Auth: []AuthMethod{
 
234
                        PublicKeys(),
 
235
                },
 
236
                Config: Config{
 
237
                        Ciphers: []string{"aes128-cbc"}, // not currently supported
 
238
                },
 
239
        }
 
240
        if err := tryAuth(t, config); err == nil {
 
241
                t.Errorf("expected no ciphers in common")
 
242
        }
 
243
}
 
244
 
 
245
func TestClientUnsupportedKex(t *testing.T) {
 
246
        config := &ClientConfig{
 
247
                User: "testuser",
 
248
                Auth: []AuthMethod{
 
249
                        PublicKeys(),
 
250
                },
 
251
                Config: Config{
 
252
                        KeyExchanges: []string{"diffie-hellman-group-exchange-sha256"}, // not currently supported
 
253
                },
 
254
        }
 
255
        if err := tryAuth(t, config); err == nil || !strings.Contains(err.Error(), "common algorithm") {
 
256
                t.Errorf("got %v, expected 'common algorithm'", err)
 
257
        }
 
258
}
 
259
 
 
260
func TestClientLoginCert(t *testing.T) {
 
261
        cert := &Certificate{
 
262
                Key:         testPublicKeys["rsa"],
 
263
                ValidBefore: CertTimeInfinity,
 
264
                CertType:    UserCert,
 
265
        }
 
266
        cert.SignCert(rand.Reader, testSigners["ecdsa"])
 
267
        certSigner, err := NewCertSigner(cert, testSigners["rsa"])
 
268
        if err != nil {
 
269
                t.Fatalf("NewCertSigner: %v", err)
 
270
        }
 
271
 
 
272
        clientConfig := &ClientConfig{
 
273
                User: "user",
 
274
        }
 
275
        clientConfig.Auth = append(clientConfig.Auth, PublicKeys(certSigner))
 
276
 
 
277
        t.Log("should succeed")
 
278
        if err := tryAuth(t, clientConfig); err != nil {
 
279
                t.Errorf("cert login failed: %v", err)
 
280
        }
 
281
 
 
282
        t.Log("corrupted signature")
 
283
        cert.Signature.Blob[0]++
 
284
        if err := tryAuth(t, clientConfig); err == nil {
 
285
                t.Errorf("cert login passed with corrupted sig")
 
286
        }
 
287
 
 
288
        t.Log("revoked")
 
289
        cert.Serial = 666
 
290
        cert.SignCert(rand.Reader, testSigners["ecdsa"])
 
291
        if err := tryAuth(t, clientConfig); err == nil {
 
292
                t.Errorf("revoked cert login succeeded")
 
293
        }
 
294
        cert.Serial = 1
 
295
 
 
296
        t.Log("sign with wrong key")
 
297
        cert.SignCert(rand.Reader, testSigners["dsa"])
 
298
        if err := tryAuth(t, clientConfig); err == nil {
 
299
                t.Errorf("cert login passed with non-authoritive key")
 
300
        }
 
301
 
 
302
        t.Log("host cert")
 
303
        cert.CertType = HostCert
 
304
        cert.SignCert(rand.Reader, testSigners["ecdsa"])
 
305
        if err := tryAuth(t, clientConfig); err == nil {
 
306
                t.Errorf("cert login passed with wrong type")
 
307
        }
 
308
        cert.CertType = UserCert
 
309
 
 
310
        t.Log("principal specified")
 
311
        cert.ValidPrincipals = []string{"user"}
 
312
        cert.SignCert(rand.Reader, testSigners["ecdsa"])
 
313
        if err := tryAuth(t, clientConfig); err != nil {
 
314
                t.Errorf("cert login failed: %v", err)
 
315
        }
 
316
 
 
317
        t.Log("wrong principal specified")
 
318
        cert.ValidPrincipals = []string{"fred"}
 
319
        cert.SignCert(rand.Reader, testSigners["ecdsa"])
 
320
        if err := tryAuth(t, clientConfig); err == nil {
 
321
                t.Errorf("cert login passed with wrong principal")
 
322
        }
 
323
        cert.ValidPrincipals = nil
 
324
 
 
325
        t.Log("added critical option")
 
326
        cert.CriticalOptions = map[string]string{"root-access": "yes"}
 
327
        cert.SignCert(rand.Reader, testSigners["ecdsa"])
 
328
        if err := tryAuth(t, clientConfig); err == nil {
 
329
                t.Errorf("cert login passed with unrecognized critical option")
 
330
        }
 
331
 
 
332
        t.Log("allowed source address")
 
333
        cert.CriticalOptions = map[string]string{"source-address": "127.0.0.42/24"}
 
334
        cert.SignCert(rand.Reader, testSigners["ecdsa"])
 
335
        if err := tryAuth(t, clientConfig); err != nil {
 
336
                t.Errorf("cert login with source-address failed: %v", err)
 
337
        }
 
338
 
 
339
        t.Log("disallowed source address")
 
340
        cert.CriticalOptions = map[string]string{"source-address": "127.0.0.42"}
 
341
        cert.SignCert(rand.Reader, testSigners["ecdsa"])
 
342
        if err := tryAuth(t, clientConfig); err == nil {
 
343
                t.Errorf("cert login with source-address succeeded")
 
344
        }
 
345
}
 
346
 
 
347
func testPermissionsPassing(withPermissions bool, t *testing.T) {
 
348
        serverConfig := &ServerConfig{
 
349
                PublicKeyCallback: func(conn ConnMetadata, key PublicKey) (*Permissions, error) {
 
350
                        if conn.User() == "nopermissions" {
 
351
                                return nil, nil
 
352
                        } else {
 
353
                                return &Permissions{}, nil
 
354
                        }
 
355
                },
 
356
        }
 
357
        serverConfig.AddHostKey(testSigners["rsa"])
 
358
 
 
359
        clientConfig := &ClientConfig{
 
360
                Auth: []AuthMethod{
 
361
                        PublicKeys(testSigners["rsa"]),
 
362
                },
 
363
        }
 
364
        if withPermissions {
 
365
                clientConfig.User = "permissions"
 
366
        } else {
 
367
                clientConfig.User = "nopermissions"
 
368
        }
 
369
 
 
370
        c1, c2, err := netPipe()
 
371
        if err != nil {
 
372
                t.Fatalf("netPipe: %v", err)
 
373
        }
 
374
        defer c1.Close()
 
375
        defer c2.Close()
 
376
 
 
377
        go NewClientConn(c2, "", clientConfig)
 
378
        serverConn, err := newServer(c1, serverConfig)
 
379
        if err != nil {
 
380
                t.Fatal(err)
 
381
        }
 
382
        if p := serverConn.Permissions; (p != nil) != withPermissions {
 
383
                t.Fatalf("withPermissions is %t, but Permissions object is %#v", withPermissions, p)
 
384
        }
 
385
}
 
386
 
 
387
func TestPermissionsPassing(t *testing.T) {
 
388
        testPermissionsPassing(true, t)
 
389
}
 
390
 
 
391
func TestNoPermissionsPassing(t *testing.T) {
 
392
        testPermissionsPassing(false, t)
 
393
}