source sync 20190409
[platform/core/system/edge-orchestration.git] / vendor / golang.org / x / crypto / ssh / client_auth_test.go
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         "io"
13         "os"
14         "strings"
15         "testing"
16 )
17
18 type keyboardInteractive map[string]string
19
20 func (cr keyboardInteractive) Challenge(user string, instruction string, questions []string, echos []bool) ([]string, error) {
21         var answers []string
22         for _, q := range questions {
23                 answers = append(answers, cr[q])
24         }
25         return answers, nil
26 }
27
28 // reused internally by tests
29 var clientPassword = "tiger"
30
31 // tryAuth runs a handshake with a given config against an SSH server
32 // with config serverConfig. Returns both client and server side errors.
33 func tryAuth(t *testing.T, config *ClientConfig) error {
34         err, _ := tryAuthBothSides(t, config)
35         return err
36 }
37
38 // tryAuthBothSides runs the handshake and returns the resulting errors from both sides of the connection.
39 func tryAuthBothSides(t *testing.T, config *ClientConfig) (clientError error, serverAuthErrors []error) {
40         c1, c2, err := netPipe()
41         if err != nil {
42                 t.Fatalf("netPipe: %v", err)
43         }
44         defer c1.Close()
45         defer c2.Close()
46
47         certChecker := CertChecker{
48                 IsUserAuthority: func(k PublicKey) bool {
49                         return bytes.Equal(k.Marshal(), testPublicKeys["ecdsa"].Marshal())
50                 },
51                 UserKeyFallback: func(conn ConnMetadata, key PublicKey) (*Permissions, error) {
52                         if conn.User() == "testuser" && bytes.Equal(key.Marshal(), testPublicKeys["rsa"].Marshal()) {
53                                 return nil, nil
54                         }
55
56                         return nil, fmt.Errorf("pubkey for %q not acceptable", conn.User())
57                 },
58                 IsRevoked: func(c *Certificate) bool {
59                         return c.Serial == 666
60                 },
61         }
62
63         serverConfig := &ServerConfig{
64                 PasswordCallback: func(conn ConnMetadata, pass []byte) (*Permissions, error) {
65                         if conn.User() == "testuser" && string(pass) == clientPassword {
66                                 return nil, nil
67                         }
68                         return nil, errors.New("password auth failed")
69                 },
70                 PublicKeyCallback: certChecker.Authenticate,
71                 KeyboardInteractiveCallback: func(conn ConnMetadata, challenge KeyboardInteractiveChallenge) (*Permissions, error) {
72                         ans, err := challenge("user",
73                                 "instruction",
74                                 []string{"question1", "question2"},
75                                 []bool{true, true})
76                         if err != nil {
77                                 return nil, err
78                         }
79                         ok := conn.User() == "testuser" && ans[0] == "answer1" && ans[1] == "answer2"
80                         if ok {
81                                 challenge("user", "motd", nil, nil)
82                                 return nil, nil
83                         }
84                         return nil, errors.New("keyboard-interactive failed")
85                 },
86         }
87         serverConfig.AddHostKey(testSigners["rsa"])
88
89         serverConfig.AuthLogCallback = func(conn ConnMetadata, method string, err error) {
90                 serverAuthErrors = append(serverAuthErrors, err)
91         }
92
93         go newServer(c1, serverConfig)
94         _, _, _, err = NewClientConn(c2, "", config)
95         return err, serverAuthErrors
96 }
97
98 func TestClientAuthPublicKey(t *testing.T) {
99         config := &ClientConfig{
100                 User: "testuser",
101                 Auth: []AuthMethod{
102                         PublicKeys(testSigners["rsa"]),
103                 },
104                 HostKeyCallback: InsecureIgnoreHostKey(),
105         }
106         if err := tryAuth(t, config); err != nil {
107                 t.Fatalf("unable to dial remote side: %s", err)
108         }
109 }
110
111 func TestAuthMethodPassword(t *testing.T) {
112         config := &ClientConfig{
113                 User: "testuser",
114                 Auth: []AuthMethod{
115                         Password(clientPassword),
116                 },
117                 HostKeyCallback: InsecureIgnoreHostKey(),
118         }
119
120         if err := tryAuth(t, config); err != nil {
121                 t.Fatalf("unable to dial remote side: %s", err)
122         }
123 }
124
125 func TestAuthMethodFallback(t *testing.T) {
126         var passwordCalled bool
127         config := &ClientConfig{
128                 User: "testuser",
129                 Auth: []AuthMethod{
130                         PublicKeys(testSigners["rsa"]),
131                         PasswordCallback(
132                                 func() (string, error) {
133                                         passwordCalled = true
134                                         return "WRONG", nil
135                                 }),
136                 },
137                 HostKeyCallback: InsecureIgnoreHostKey(),
138         }
139
140         if err := tryAuth(t, config); err != nil {
141                 t.Fatalf("unable to dial remote side: %s", err)
142         }
143
144         if passwordCalled {
145                 t.Errorf("password auth tried before public-key auth.")
146         }
147 }
148
149 func TestAuthMethodWrongPassword(t *testing.T) {
150         config := &ClientConfig{
151                 User: "testuser",
152                 Auth: []AuthMethod{
153                         Password("wrong"),
154                         PublicKeys(testSigners["rsa"]),
155                 },
156                 HostKeyCallback: InsecureIgnoreHostKey(),
157         }
158
159         if err := tryAuth(t, config); err != nil {
160                 t.Fatalf("unable to dial remote side: %s", err)
161         }
162 }
163
164 func TestAuthMethodKeyboardInteractive(t *testing.T) {
165         answers := keyboardInteractive(map[string]string{
166                 "question1": "answer1",
167                 "question2": "answer2",
168         })
169         config := &ClientConfig{
170                 User: "testuser",
171                 Auth: []AuthMethod{
172                         KeyboardInteractive(answers.Challenge),
173                 },
174                 HostKeyCallback: InsecureIgnoreHostKey(),
175         }
176
177         if err := tryAuth(t, config); err != nil {
178                 t.Fatalf("unable to dial remote side: %s", err)
179         }
180 }
181
182 func TestAuthMethodWrongKeyboardInteractive(t *testing.T) {
183         answers := keyboardInteractive(map[string]string{
184                 "question1": "answer1",
185                 "question2": "WRONG",
186         })
187         config := &ClientConfig{
188                 User: "testuser",
189                 Auth: []AuthMethod{
190                         KeyboardInteractive(answers.Challenge),
191                 },
192         }
193
194         if err := tryAuth(t, config); err == nil {
195                 t.Fatalf("wrong answers should not have authenticated with KeyboardInteractive")
196         }
197 }
198
199 // the mock server will only authenticate ssh-rsa keys
200 func TestAuthMethodInvalidPublicKey(t *testing.T) {
201         config := &ClientConfig{
202                 User: "testuser",
203                 Auth: []AuthMethod{
204                         PublicKeys(testSigners["dsa"]),
205                 },
206         }
207
208         if err := tryAuth(t, config); err == nil {
209                 t.Fatalf("dsa private key should not have authenticated with rsa public key")
210         }
211 }
212
213 // the client should authenticate with the second key
214 func TestAuthMethodRSAandDSA(t *testing.T) {
215         config := &ClientConfig{
216                 User: "testuser",
217                 Auth: []AuthMethod{
218                         PublicKeys(testSigners["dsa"], testSigners["rsa"]),
219                 },
220                 HostKeyCallback: InsecureIgnoreHostKey(),
221         }
222         if err := tryAuth(t, config); err != nil {
223                 t.Fatalf("client could not authenticate with rsa key: %v", err)
224         }
225 }
226
227 type invalidAlgSigner struct {
228         Signer
229 }
230
231 func (s *invalidAlgSigner) Sign(rand io.Reader, data []byte) (*Signature, error) {
232         sig, err := s.Signer.Sign(rand, data)
233         if sig != nil {
234                 sig.Format = "invalid"
235         }
236         return sig, err
237 }
238
239 func TestMethodInvalidAlgorithm(t *testing.T) {
240         config := &ClientConfig{
241                 User: "testuser",
242                 Auth: []AuthMethod{
243                         PublicKeys(&invalidAlgSigner{testSigners["rsa"]}),
244                 },
245                 HostKeyCallback: InsecureIgnoreHostKey(),
246         }
247
248         err, serverErrors := tryAuthBothSides(t, config)
249         if err == nil {
250                 t.Fatalf("login succeeded")
251         }
252
253         found := false
254         want := "algorithm \"invalid\""
255
256         var errStrings []string
257         for _, err := range serverErrors {
258                 found = found || (err != nil && strings.Contains(err.Error(), want))
259                 errStrings = append(errStrings, err.Error())
260         }
261         if !found {
262                 t.Errorf("server got error %q, want substring %q", errStrings, want)
263         }
264 }
265
266 func TestClientHMAC(t *testing.T) {
267         for _, mac := range supportedMACs {
268                 config := &ClientConfig{
269                         User: "testuser",
270                         Auth: []AuthMethod{
271                                 PublicKeys(testSigners["rsa"]),
272                         },
273                         Config: Config{
274                                 MACs: []string{mac},
275                         },
276                         HostKeyCallback: InsecureIgnoreHostKey(),
277                 }
278                 if err := tryAuth(t, config); err != nil {
279                         t.Fatalf("client could not authenticate with mac algo %s: %v", mac, err)
280                 }
281         }
282 }
283
284 // issue 4285.
285 func TestClientUnsupportedCipher(t *testing.T) {
286         config := &ClientConfig{
287                 User: "testuser",
288                 Auth: []AuthMethod{
289                         PublicKeys(),
290                 },
291                 Config: Config{
292                         Ciphers: []string{"aes128-cbc"}, // not currently supported
293                 },
294         }
295         if err := tryAuth(t, config); err == nil {
296                 t.Errorf("expected no ciphers in common")
297         }
298 }
299
300 func TestClientUnsupportedKex(t *testing.T) {
301         if os.Getenv("GO_BUILDER_NAME") != "" {
302                 t.Skip("skipping known-flaky test on the Go build dashboard; see golang.org/issue/15198")
303         }
304         config := &ClientConfig{
305                 User: "testuser",
306                 Auth: []AuthMethod{
307                         PublicKeys(),
308                 },
309                 Config: Config{
310                         KeyExchanges: []string{"diffie-hellman-group-exchange-sha256"}, // not currently supported
311                 },
312                 HostKeyCallback: InsecureIgnoreHostKey(),
313         }
314         if err := tryAuth(t, config); err == nil || !strings.Contains(err.Error(), "common algorithm") {
315                 t.Errorf("got %v, expected 'common algorithm'", err)
316         }
317 }
318
319 func TestClientLoginCert(t *testing.T) {
320         cert := &Certificate{
321                 Key:         testPublicKeys["rsa"],
322                 ValidBefore: CertTimeInfinity,
323                 CertType:    UserCert,
324         }
325         cert.SignCert(rand.Reader, testSigners["ecdsa"])
326         certSigner, err := NewCertSigner(cert, testSigners["rsa"])
327         if err != nil {
328                 t.Fatalf("NewCertSigner: %v", err)
329         }
330
331         clientConfig := &ClientConfig{
332                 User:            "user",
333                 HostKeyCallback: InsecureIgnoreHostKey(),
334         }
335         clientConfig.Auth = append(clientConfig.Auth, PublicKeys(certSigner))
336
337         // should succeed
338         if err := tryAuth(t, clientConfig); err != nil {
339                 t.Errorf("cert login failed: %v", err)
340         }
341
342         // corrupted signature
343         cert.Signature.Blob[0]++
344         if err := tryAuth(t, clientConfig); err == nil {
345                 t.Errorf("cert login passed with corrupted sig")
346         }
347
348         // revoked
349         cert.Serial = 666
350         cert.SignCert(rand.Reader, testSigners["ecdsa"])
351         if err := tryAuth(t, clientConfig); err == nil {
352                 t.Errorf("revoked cert login succeeded")
353         }
354         cert.Serial = 1
355
356         // sign with wrong key
357         cert.SignCert(rand.Reader, testSigners["dsa"])
358         if err := tryAuth(t, clientConfig); err == nil {
359                 t.Errorf("cert login passed with non-authoritative key")
360         }
361
362         // host cert
363         cert.CertType = HostCert
364         cert.SignCert(rand.Reader, testSigners["ecdsa"])
365         if err := tryAuth(t, clientConfig); err == nil {
366                 t.Errorf("cert login passed with wrong type")
367         }
368         cert.CertType = UserCert
369
370         // principal specified
371         cert.ValidPrincipals = []string{"user"}
372         cert.SignCert(rand.Reader, testSigners["ecdsa"])
373         if err := tryAuth(t, clientConfig); err != nil {
374                 t.Errorf("cert login failed: %v", err)
375         }
376
377         // wrong principal specified
378         cert.ValidPrincipals = []string{"fred"}
379         cert.SignCert(rand.Reader, testSigners["ecdsa"])
380         if err := tryAuth(t, clientConfig); err == nil {
381                 t.Errorf("cert login passed with wrong principal")
382         }
383         cert.ValidPrincipals = nil
384
385         // added critical option
386         cert.CriticalOptions = map[string]string{"root-access": "yes"}
387         cert.SignCert(rand.Reader, testSigners["ecdsa"])
388         if err := tryAuth(t, clientConfig); err == nil {
389                 t.Errorf("cert login passed with unrecognized critical option")
390         }
391
392         // allowed source address
393         cert.CriticalOptions = map[string]string{"source-address": "127.0.0.42/24,::42/120"}
394         cert.SignCert(rand.Reader, testSigners["ecdsa"])
395         if err := tryAuth(t, clientConfig); err != nil {
396                 t.Errorf("cert login with source-address failed: %v", err)
397         }
398
399         // disallowed source address
400         cert.CriticalOptions = map[string]string{"source-address": "127.0.0.42,::42"}
401         cert.SignCert(rand.Reader, testSigners["ecdsa"])
402         if err := tryAuth(t, clientConfig); err == nil {
403                 t.Errorf("cert login with source-address succeeded")
404         }
405 }
406
407 func testPermissionsPassing(withPermissions bool, t *testing.T) {
408         serverConfig := &ServerConfig{
409                 PublicKeyCallback: func(conn ConnMetadata, key PublicKey) (*Permissions, error) {
410                         if conn.User() == "nopermissions" {
411                                 return nil, nil
412                         }
413                         return &Permissions{}, nil
414                 },
415         }
416         serverConfig.AddHostKey(testSigners["rsa"])
417
418         clientConfig := &ClientConfig{
419                 Auth: []AuthMethod{
420                         PublicKeys(testSigners["rsa"]),
421                 },
422                 HostKeyCallback: InsecureIgnoreHostKey(),
423         }
424         if withPermissions {
425                 clientConfig.User = "permissions"
426         } else {
427                 clientConfig.User = "nopermissions"
428         }
429
430         c1, c2, err := netPipe()
431         if err != nil {
432                 t.Fatalf("netPipe: %v", err)
433         }
434         defer c1.Close()
435         defer c2.Close()
436
437         go NewClientConn(c2, "", clientConfig)
438         serverConn, err := newServer(c1, serverConfig)
439         if err != nil {
440                 t.Fatal(err)
441         }
442         if p := serverConn.Permissions; (p != nil) != withPermissions {
443                 t.Fatalf("withPermissions is %t, but Permissions object is %#v", withPermissions, p)
444         }
445 }
446
447 func TestPermissionsPassing(t *testing.T) {
448         testPermissionsPassing(true, t)
449 }
450
451 func TestNoPermissionsPassing(t *testing.T) {
452         testPermissionsPassing(false, t)
453 }
454
455 func TestRetryableAuth(t *testing.T) {
456         n := 0
457         passwords := []string{"WRONG1", "WRONG2"}
458
459         config := &ClientConfig{
460                 User: "testuser",
461                 Auth: []AuthMethod{
462                         RetryableAuthMethod(PasswordCallback(func() (string, error) {
463                                 p := passwords[n]
464                                 n++
465                                 return p, nil
466                         }), 2),
467                         PublicKeys(testSigners["rsa"]),
468                 },
469                 HostKeyCallback: InsecureIgnoreHostKey(),
470         }
471
472         if err := tryAuth(t, config); err != nil {
473                 t.Fatalf("unable to dial remote side: %s", err)
474         }
475         if n != 2 {
476                 t.Fatalf("Did not try all passwords")
477         }
478 }
479
480 func ExampleRetryableAuthMethod(t *testing.T) {
481         user := "testuser"
482         NumberOfPrompts := 3
483
484         // Normally this would be a callback that prompts the user to answer the
485         // provided questions
486         Cb := func(user, instruction string, questions []string, echos []bool) (answers []string, err error) {
487                 return []string{"answer1", "answer2"}, nil
488         }
489
490         config := &ClientConfig{
491                 HostKeyCallback: InsecureIgnoreHostKey(),
492                 User:            user,
493                 Auth: []AuthMethod{
494                         RetryableAuthMethod(KeyboardInteractiveChallenge(Cb), NumberOfPrompts),
495                 },
496         }
497
498         if err := tryAuth(t, config); err != nil {
499                 t.Fatalf("unable to dial remote side: %s", err)
500         }
501 }
502
503 // Test if username is received on server side when NoClientAuth is used
504 func TestClientAuthNone(t *testing.T) {
505         user := "testuser"
506         serverConfig := &ServerConfig{
507                 NoClientAuth: true,
508         }
509         serverConfig.AddHostKey(testSigners["rsa"])
510
511         clientConfig := &ClientConfig{
512                 User:            user,
513                 HostKeyCallback: InsecureIgnoreHostKey(),
514         }
515
516         c1, c2, err := netPipe()
517         if err != nil {
518                 t.Fatalf("netPipe: %v", err)
519         }
520         defer c1.Close()
521         defer c2.Close()
522
523         go NewClientConn(c2, "", clientConfig)
524         serverConn, err := newServer(c1, serverConfig)
525         if err != nil {
526                 t.Fatalf("newServer: %v", err)
527         }
528         if serverConn.User() != user {
529                 t.Fatalf("server: got %q, want %q", serverConn.User(), user)
530         }
531 }
532
533 // Test if authentication attempts are limited on server when MaxAuthTries is set
534 func TestClientAuthMaxAuthTries(t *testing.T) {
535         user := "testuser"
536
537         serverConfig := &ServerConfig{
538                 MaxAuthTries: 2,
539                 PasswordCallback: func(conn ConnMetadata, pass []byte) (*Permissions, error) {
540                         if conn.User() == "testuser" && string(pass) == "right" {
541                                 return nil, nil
542                         }
543                         return nil, errors.New("password auth failed")
544                 },
545         }
546         serverConfig.AddHostKey(testSigners["rsa"])
547
548         expectedErr := fmt.Errorf("ssh: handshake failed: %v", &disconnectMsg{
549                 Reason:  2,
550                 Message: "too many authentication failures",
551         })
552
553         for tries := 2; tries < 4; tries++ {
554                 n := tries
555                 clientConfig := &ClientConfig{
556                         User: user,
557                         Auth: []AuthMethod{
558                                 RetryableAuthMethod(PasswordCallback(func() (string, error) {
559                                         n--
560                                         if n == 0 {
561                                                 return "right", nil
562                                         }
563                                         return "wrong", nil
564                                 }), tries),
565                         },
566                         HostKeyCallback: InsecureIgnoreHostKey(),
567                 }
568
569                 c1, c2, err := netPipe()
570                 if err != nil {
571                         t.Fatalf("netPipe: %v", err)
572                 }
573                 defer c1.Close()
574                 defer c2.Close()
575
576                 go newServer(c1, serverConfig)
577                 _, _, _, err = NewClientConn(c2, "", clientConfig)
578                 if tries > 2 {
579                         if err == nil {
580                                 t.Fatalf("client: got no error, want %s", expectedErr)
581                         } else if err.Error() != expectedErr.Error() {
582                                 t.Fatalf("client: got %s, want %s", err, expectedErr)
583                         }
584                 } else {
585                         if err != nil {
586                                 t.Fatalf("client: got %s, want no error", err)
587                         }
588                 }
589         }
590 }
591
592 // Test if authentication attempts are correctly limited on server
593 // when more public keys are provided then MaxAuthTries
594 func TestClientAuthMaxAuthTriesPublicKey(t *testing.T) {
595         signers := []Signer{}
596         for i := 0; i < 6; i++ {
597                 signers = append(signers, testSigners["dsa"])
598         }
599
600         validConfig := &ClientConfig{
601                 User: "testuser",
602                 Auth: []AuthMethod{
603                         PublicKeys(append([]Signer{testSigners["rsa"]}, signers...)...),
604                 },
605                 HostKeyCallback: InsecureIgnoreHostKey(),
606         }
607         if err := tryAuth(t, validConfig); err != nil {
608                 t.Fatalf("unable to dial remote side: %s", err)
609         }
610
611         expectedErr := fmt.Errorf("ssh: handshake failed: %v", &disconnectMsg{
612                 Reason:  2,
613                 Message: "too many authentication failures",
614         })
615         invalidConfig := &ClientConfig{
616                 User: "testuser",
617                 Auth: []AuthMethod{
618                         PublicKeys(append(signers, testSigners["rsa"])...),
619                 },
620                 HostKeyCallback: InsecureIgnoreHostKey(),
621         }
622         if err := tryAuth(t, invalidConfig); err == nil {
623                 t.Fatalf("client: got no error, want %s", expectedErr)
624         } else if err.Error() != expectedErr.Error() {
625                 t.Fatalf("client: got %s, want %s", err, expectedErr)
626         }
627 }
628
629 // Test whether authentication errors are being properly logged if all
630 // authentication methods have been exhausted
631 func TestClientAuthErrorList(t *testing.T) {
632         publicKeyErr := errors.New("This is an error from PublicKeyCallback")
633
634         clientConfig := &ClientConfig{
635                 Auth: []AuthMethod{
636                         PublicKeys(testSigners["rsa"]),
637                 },
638                 HostKeyCallback: InsecureIgnoreHostKey(),
639         }
640         serverConfig := &ServerConfig{
641                 PublicKeyCallback: func(_ ConnMetadata, _ PublicKey) (*Permissions, error) {
642                         return nil, publicKeyErr
643                 },
644         }
645         serverConfig.AddHostKey(testSigners["rsa"])
646
647         c1, c2, err := netPipe()
648         if err != nil {
649                 t.Fatalf("netPipe: %v", err)
650         }
651         defer c1.Close()
652         defer c2.Close()
653
654         go NewClientConn(c2, "", clientConfig)
655         _, err = newServer(c1, serverConfig)
656         if err == nil {
657                 t.Fatal("newServer: got nil, expected errors")
658         }
659
660         authErrs, ok := err.(*ServerAuthError)
661         if !ok {
662                 t.Fatalf("errors: got %T, want *ssh.ServerAuthError", err)
663         }
664         for i, e := range authErrs.Errors {
665                 switch i {
666                 case 0:
667                         if e != ErrNoAuth {
668                                 t.Fatalf("errors: got error %v, want ErrNoAuth", e)
669                         }
670                 case 1:
671                         if e != publicKeyErr {
672                                 t.Fatalf("errors: got %v, want %v", e, publicKeyErr)
673                         }
674                 default:
675                         t.Fatalf("errors: got %v, expected 2 errors", authErrs.Errors)
676                 }
677         }
678 }