1
2
3
4
5 package ssh
6
7 import (
8 "bytes"
9 "crypto/rand"
10 "errors"
11 "fmt"
12 "io"
13 "log"
14 "net"
15 "os"
16 "runtime"
17 "strings"
18 "testing"
19 )
20
21 type keyboardInteractive map[string]string
22
23 func (cr keyboardInteractive) Challenge(user string, instruction string, questions []string, echos []bool) ([]string, error) {
24 var answers []string
25 for _, q := range questions {
26 answers = append(answers, cr[q])
27 }
28 return answers, nil
29 }
30
31
32 var clientPassword = "tiger"
33
34
35
36 func tryAuth(t *testing.T, config *ClientConfig) error {
37 err, _ := tryAuthBothSides(t, config, nil)
38 return err
39 }
40
41
42
43 func tryAuthWithGSSAPIWithMICConfig(t *testing.T, clientConfig *ClientConfig, gssAPIWithMICConfig *GSSAPIWithMICConfig) error {
44 err, _ := tryAuthBothSides(t, clientConfig, gssAPIWithMICConfig)
45 return err
46 }
47
48
49 func tryAuthBothSides(t *testing.T, config *ClientConfig, gssAPIWithMICConfig *GSSAPIWithMICConfig) (clientError error, serverAuthErrors []error) {
50 c1, c2, err := netPipe()
51 if err != nil {
52 t.Fatalf("netPipe: %v", err)
53 }
54 defer c1.Close()
55 defer c2.Close()
56
57 certChecker := CertChecker{
58 IsUserAuthority: func(k PublicKey) bool {
59 return bytes.Equal(k.Marshal(), testPublicKeys["ecdsa"].Marshal())
60 },
61 UserKeyFallback: func(conn ConnMetadata, key PublicKey) (*Permissions, error) {
62 if conn.User() == "testuser" && bytes.Equal(key.Marshal(), testPublicKeys["rsa"].Marshal()) {
63 return nil, nil
64 }
65
66 return nil, fmt.Errorf("pubkey for %q not acceptable", conn.User())
67 },
68 IsRevoked: func(c *Certificate) bool {
69 return c.Serial == 666
70 },
71 }
72 serverConfig := &ServerConfig{
73 PasswordCallback: func(conn ConnMetadata, pass []byte) (*Permissions, error) {
74 if conn.User() == "testuser" && string(pass) == clientPassword {
75 return nil, nil
76 }
77 return nil, errors.New("password auth failed")
78 },
79 PublicKeyCallback: certChecker.Authenticate,
80 KeyboardInteractiveCallback: func(conn ConnMetadata, challenge KeyboardInteractiveChallenge) (*Permissions, error) {
81 ans, err := challenge("user",
82 "instruction",
83 []string{"question1", "question2"},
84 []bool{true, true})
85 if err != nil {
86 return nil, err
87 }
88 ok := conn.User() == "testuser" && ans[0] == "answer1" && ans[1] == "answer2"
89 if ok {
90 challenge("user", "motd", nil, nil)
91 return nil, nil
92 }
93 return nil, errors.New("keyboard-interactive failed")
94 },
95 GSSAPIWithMICConfig: gssAPIWithMICConfig,
96 }
97 serverConfig.AddHostKey(testSigners["rsa"])
98
99 serverConfig.AuthLogCallback = func(conn ConnMetadata, method string, err error) {
100 serverAuthErrors = append(serverAuthErrors, err)
101 }
102
103 go newServer(c1, serverConfig)
104 _, _, _, err = NewClientConn(c2, "", config)
105 return err, serverAuthErrors
106 }
107
108 type loggingAlgorithmSigner struct {
109 used []string
110 AlgorithmSigner
111 }
112
113 func (l *loggingAlgorithmSigner) Sign(rand io.Reader, data []byte) (*Signature, error) {
114 l.used = append(l.used, "[Sign]")
115 return l.AlgorithmSigner.Sign(rand, data)
116 }
117
118 func (l *loggingAlgorithmSigner) SignWithAlgorithm(rand io.Reader, data []byte, algorithm string) (*Signature, error) {
119 l.used = append(l.used, algorithm)
120 return l.AlgorithmSigner.SignWithAlgorithm(rand, data, algorithm)
121 }
122
123 func TestClientAuthPublicKey(t *testing.T) {
124 signer := &loggingAlgorithmSigner{AlgorithmSigner: testSigners["rsa"].(AlgorithmSigner)}
125 config := &ClientConfig{
126 User: "testuser",
127 Auth: []AuthMethod{
128 PublicKeys(signer),
129 },
130 HostKeyCallback: InsecureIgnoreHostKey(),
131 }
132 if err := tryAuth(t, config); err != nil {
133 t.Fatalf("unable to dial remote side: %s", err)
134 }
135 if len(signer.used) != 1 || signer.used[0] != KeyAlgoRSASHA256 {
136 t.Errorf("unexpected Sign/SignWithAlgorithm calls: %q", signer.used)
137 }
138 }
139
140
141 func TestClientAuthNoSHA2(t *testing.T) {
142 config := &ClientConfig{
143 User: "testuser",
144 Auth: []AuthMethod{
145 PublicKeys(&legacyRSASigner{testSigners["rsa"]}),
146 },
147 HostKeyCallback: InsecureIgnoreHostKey(),
148 }
149 if err := tryAuth(t, config); err != nil {
150 t.Fatalf("unable to dial remote side: %s", err)
151 }
152 }
153
154
155
156
157 func TestClientAuthThirdKey(t *testing.T) {
158 config := &ClientConfig{
159 User: "testuser",
160 Auth: []AuthMethod{
161 PublicKeys(testSigners["rsa-openssh-format"],
162 testSigners["rsa-openssh-format"], testSigners["rsa"]),
163 },
164 HostKeyCallback: InsecureIgnoreHostKey(),
165 }
166 if err := tryAuth(t, config); err != nil {
167 t.Fatalf("unable to dial remote side: %s", err)
168 }
169 }
170
171 func TestAuthMethodPassword(t *testing.T) {
172 config := &ClientConfig{
173 User: "testuser",
174 Auth: []AuthMethod{
175 Password(clientPassword),
176 },
177 HostKeyCallback: InsecureIgnoreHostKey(),
178 }
179
180 if err := tryAuth(t, config); err != nil {
181 t.Fatalf("unable to dial remote side: %s", err)
182 }
183 }
184
185 func TestAuthMethodFallback(t *testing.T) {
186 var passwordCalled bool
187 config := &ClientConfig{
188 User: "testuser",
189 Auth: []AuthMethod{
190 PublicKeys(testSigners["rsa"]),
191 PasswordCallback(
192 func() (string, error) {
193 passwordCalled = true
194 return "WRONG", nil
195 }),
196 },
197 HostKeyCallback: InsecureIgnoreHostKey(),
198 }
199
200 if err := tryAuth(t, config); err != nil {
201 t.Fatalf("unable to dial remote side: %s", err)
202 }
203
204 if passwordCalled {
205 t.Errorf("password auth tried before public-key auth.")
206 }
207 }
208
209 func TestAuthMethodWrongPassword(t *testing.T) {
210 config := &ClientConfig{
211 User: "testuser",
212 Auth: []AuthMethod{
213 Password("wrong"),
214 PublicKeys(testSigners["rsa"]),
215 },
216 HostKeyCallback: InsecureIgnoreHostKey(),
217 }
218
219 if err := tryAuth(t, config); err != nil {
220 t.Fatalf("unable to dial remote side: %s", err)
221 }
222 }
223
224 func TestAuthMethodKeyboardInteractive(t *testing.T) {
225 answers := keyboardInteractive(map[string]string{
226 "question1": "answer1",
227 "question2": "answer2",
228 })
229 config := &ClientConfig{
230 User: "testuser",
231 Auth: []AuthMethod{
232 KeyboardInteractive(answers.Challenge),
233 },
234 HostKeyCallback: InsecureIgnoreHostKey(),
235 }
236
237 if err := tryAuth(t, config); err != nil {
238 t.Fatalf("unable to dial remote side: %s", err)
239 }
240 }
241
242 func TestAuthMethodWrongKeyboardInteractive(t *testing.T) {
243 answers := keyboardInteractive(map[string]string{
244 "question1": "answer1",
245 "question2": "WRONG",
246 })
247 config := &ClientConfig{
248 User: "testuser",
249 Auth: []AuthMethod{
250 KeyboardInteractive(answers.Challenge),
251 },
252 }
253
254 if err := tryAuth(t, config); err == nil {
255 t.Fatalf("wrong answers should not have authenticated with KeyboardInteractive")
256 }
257 }
258
259
260 func TestAuthMethodInvalidPublicKey(t *testing.T) {
261 config := &ClientConfig{
262 User: "testuser",
263 Auth: []AuthMethod{
264 PublicKeys(testSigners["dsa"]),
265 },
266 }
267
268 if err := tryAuth(t, config); err == nil {
269 t.Fatalf("dsa private key should not have authenticated with rsa public key")
270 }
271 }
272
273
274 func TestAuthMethodRSAandDSA(t *testing.T) {
275 config := &ClientConfig{
276 User: "testuser",
277 Auth: []AuthMethod{
278 PublicKeys(testSigners["dsa"], testSigners["rsa"]),
279 },
280 HostKeyCallback: InsecureIgnoreHostKey(),
281 }
282 if err := tryAuth(t, config); err != nil {
283 t.Fatalf("client could not authenticate with rsa key: %v", err)
284 }
285 }
286
287 type invalidAlgSigner struct {
288 Signer
289 }
290
291 func (s *invalidAlgSigner) Sign(rand io.Reader, data []byte) (*Signature, error) {
292 sig, err := s.Signer.Sign(rand, data)
293 if sig != nil {
294 sig.Format = "invalid"
295 }
296 return sig, err
297 }
298
299 func TestMethodInvalidAlgorithm(t *testing.T) {
300 config := &ClientConfig{
301 User: "testuser",
302 Auth: []AuthMethod{
303 PublicKeys(&invalidAlgSigner{testSigners["rsa"]}),
304 },
305 HostKeyCallback: InsecureIgnoreHostKey(),
306 }
307
308 err, serverErrors := tryAuthBothSides(t, config, nil)
309 if err == nil {
310 t.Fatalf("login succeeded")
311 }
312
313 found := false
314 want := "algorithm \"invalid\""
315
316 var errStrings []string
317 for _, err := range serverErrors {
318 found = found || (err != nil && strings.Contains(err.Error(), want))
319 errStrings = append(errStrings, err.Error())
320 }
321 if !found {
322 t.Errorf("server got error %q, want substring %q", errStrings, want)
323 }
324 }
325
326 func TestClientHMAC(t *testing.T) {
327 for _, mac := range supportedMACs {
328 config := &ClientConfig{
329 User: "testuser",
330 Auth: []AuthMethod{
331 PublicKeys(testSigners["rsa"]),
332 },
333 Config: Config{
334 MACs: []string{mac},
335 },
336 HostKeyCallback: InsecureIgnoreHostKey(),
337 }
338 if err := tryAuth(t, config); err != nil {
339 t.Fatalf("client could not authenticate with mac algo %s: %v", mac, err)
340 }
341 }
342 }
343
344
345 func TestClientUnsupportedCipher(t *testing.T) {
346 config := &ClientConfig{
347 User: "testuser",
348 Auth: []AuthMethod{
349 PublicKeys(),
350 },
351 Config: Config{
352 Ciphers: []string{"aes128-cbc"},
353 },
354 }
355 if err := tryAuth(t, config); err == nil {
356 t.Errorf("expected no ciphers in common")
357 }
358 }
359
360 func TestClientUnsupportedKex(t *testing.T) {
361 if os.Getenv("GO_BUILDER_NAME") != "" {
362 t.Skip("skipping known-flaky test on the Go build dashboard; see golang.org/issue/15198")
363 }
364 config := &ClientConfig{
365 User: "testuser",
366 Auth: []AuthMethod{
367 PublicKeys(),
368 },
369 Config: Config{
370 KeyExchanges: []string{"non-existent-kex"},
371 },
372 HostKeyCallback: InsecureIgnoreHostKey(),
373 }
374 if err := tryAuth(t, config); err == nil || !strings.Contains(err.Error(), "common algorithm") {
375 t.Errorf("got %v, expected 'common algorithm'", err)
376 }
377 }
378
379 func TestClientLoginCert(t *testing.T) {
380 cert := &Certificate{
381 Key: testPublicKeys["rsa"],
382 ValidBefore: CertTimeInfinity,
383 CertType: UserCert,
384 }
385 cert.SignCert(rand.Reader, testSigners["ecdsa"])
386 certSigner, err := NewCertSigner(cert, testSigners["rsa"])
387 if err != nil {
388 t.Fatalf("NewCertSigner: %v", err)
389 }
390
391 clientConfig := &ClientConfig{
392 User: "user",
393 HostKeyCallback: InsecureIgnoreHostKey(),
394 }
395 clientConfig.Auth = append(clientConfig.Auth, PublicKeys(certSigner))
396
397
398 if err := tryAuth(t, clientConfig); err != nil {
399 t.Errorf("cert login failed: %v", err)
400 }
401
402
403 cert.Signature.Blob[0]++
404 if err := tryAuth(t, clientConfig); err == nil {
405 t.Errorf("cert login passed with corrupted sig")
406 }
407
408
409 cert.Serial = 666
410 cert.SignCert(rand.Reader, testSigners["ecdsa"])
411 if err := tryAuth(t, clientConfig); err == nil {
412 t.Errorf("revoked cert login succeeded")
413 }
414 cert.Serial = 1
415
416
417 cert.SignCert(rand.Reader, testSigners["dsa"])
418 if err := tryAuth(t, clientConfig); err == nil {
419 t.Errorf("cert login passed with non-authoritative key")
420 }
421
422
423 cert.CertType = HostCert
424 cert.SignCert(rand.Reader, testSigners["ecdsa"])
425 if err := tryAuth(t, clientConfig); err == nil {
426 t.Errorf("cert login passed with wrong type")
427 }
428 cert.CertType = UserCert
429
430
431 cert.ValidPrincipals = []string{"user"}
432 cert.SignCert(rand.Reader, testSigners["ecdsa"])
433 if err := tryAuth(t, clientConfig); err != nil {
434 t.Errorf("cert login failed: %v", err)
435 }
436
437
438 cert.ValidPrincipals = []string{"fred"}
439 cert.SignCert(rand.Reader, testSigners["ecdsa"])
440 if err := tryAuth(t, clientConfig); err == nil {
441 t.Errorf("cert login passed with wrong principal")
442 }
443 cert.ValidPrincipals = nil
444
445
446 cert.CriticalOptions = map[string]string{"root-access": "yes"}
447 cert.SignCert(rand.Reader, testSigners["ecdsa"])
448 if err := tryAuth(t, clientConfig); err == nil {
449 t.Errorf("cert login passed with unrecognized critical option")
450 }
451
452
453 cert.CriticalOptions = map[string]string{"source-address": "127.0.0.42/24,::42/120"}
454 cert.SignCert(rand.Reader, testSigners["ecdsa"])
455 if err := tryAuth(t, clientConfig); err != nil {
456 t.Errorf("cert login with source-address failed: %v", err)
457 }
458
459
460 cert.CriticalOptions = map[string]string{"source-address": "127.0.0.42,::42"}
461 cert.SignCert(rand.Reader, testSigners["ecdsa"])
462 if err := tryAuth(t, clientConfig); err == nil {
463 t.Errorf("cert login with source-address succeeded")
464 }
465 }
466
467 func testPermissionsPassing(withPermissions bool, t *testing.T) {
468 serverConfig := &ServerConfig{
469 PublicKeyCallback: func(conn ConnMetadata, key PublicKey) (*Permissions, error) {
470 if conn.User() == "nopermissions" {
471 return nil, nil
472 }
473 return &Permissions{}, nil
474 },
475 }
476 serverConfig.AddHostKey(testSigners["rsa"])
477
478 clientConfig := &ClientConfig{
479 Auth: []AuthMethod{
480 PublicKeys(testSigners["rsa"]),
481 },
482 HostKeyCallback: InsecureIgnoreHostKey(),
483 }
484 if withPermissions {
485 clientConfig.User = "permissions"
486 } else {
487 clientConfig.User = "nopermissions"
488 }
489
490 c1, c2, err := netPipe()
491 if err != nil {
492 t.Fatalf("netPipe: %v", err)
493 }
494 defer c1.Close()
495 defer c2.Close()
496
497 go NewClientConn(c2, "", clientConfig)
498 serverConn, err := newServer(c1, serverConfig)
499 if err != nil {
500 t.Fatal(err)
501 }
502 if p := serverConn.Permissions; (p != nil) != withPermissions {
503 t.Fatalf("withPermissions is %t, but Permissions object is %#v", withPermissions, p)
504 }
505 }
506
507 func TestPermissionsPassing(t *testing.T) {
508 testPermissionsPassing(true, t)
509 }
510
511 func TestNoPermissionsPassing(t *testing.T) {
512 testPermissionsPassing(false, t)
513 }
514
515 func TestRetryableAuth(t *testing.T) {
516 n := 0
517 passwords := []string{"WRONG1", "WRONG2"}
518
519 config := &ClientConfig{
520 User: "testuser",
521 Auth: []AuthMethod{
522 RetryableAuthMethod(PasswordCallback(func() (string, error) {
523 p := passwords[n]
524 n++
525 return p, nil
526 }), 2),
527 PublicKeys(testSigners["rsa"]),
528 },
529 HostKeyCallback: InsecureIgnoreHostKey(),
530 }
531
532 if err := tryAuth(t, config); err != nil {
533 t.Fatalf("unable to dial remote side: %s", err)
534 }
535 if n != 2 {
536 t.Fatalf("Did not try all passwords")
537 }
538 }
539
540 func ExampleRetryableAuthMethod() {
541 user := "testuser"
542 NumberOfPrompts := 3
543
544
545
546 Cb := func(user, instruction string, questions []string, echos []bool) (answers []string, err error) {
547 return []string{"answer1", "answer2"}, nil
548 }
549
550 config := &ClientConfig{
551 HostKeyCallback: InsecureIgnoreHostKey(),
552 User: user,
553 Auth: []AuthMethod{
554 RetryableAuthMethod(KeyboardInteractiveChallenge(Cb), NumberOfPrompts),
555 },
556 }
557
558 host := "mysshserver"
559 netConn, err := net.Dial("tcp", host)
560 if err != nil {
561 log.Fatal(err)
562 }
563
564 sshConn, _, _, err := NewClientConn(netConn, host, config)
565 if err != nil {
566 log.Fatal(err)
567 }
568 _ = sshConn
569 }
570
571
572 func TestClientAuthNone(t *testing.T) {
573 user := "testuser"
574 serverConfig := &ServerConfig{
575 NoClientAuth: true,
576 }
577 serverConfig.AddHostKey(testSigners["rsa"])
578
579 clientConfig := &ClientConfig{
580 User: user,
581 HostKeyCallback: InsecureIgnoreHostKey(),
582 }
583
584 c1, c2, err := netPipe()
585 if err != nil {
586 t.Fatalf("netPipe: %v", err)
587 }
588 defer c1.Close()
589 defer c2.Close()
590
591 go NewClientConn(c2, "", clientConfig)
592 serverConn, err := newServer(c1, serverConfig)
593 if err != nil {
594 t.Fatalf("newServer: %v", err)
595 }
596 if serverConn.User() != user {
597 t.Fatalf("server: got %q, want %q", serverConn.User(), user)
598 }
599 }
600
601
602 func TestClientAuthMaxAuthTries(t *testing.T) {
603 user := "testuser"
604
605 serverConfig := &ServerConfig{
606 MaxAuthTries: 2,
607 PasswordCallback: func(conn ConnMetadata, pass []byte) (*Permissions, error) {
608 if conn.User() == "testuser" && string(pass) == "right" {
609 return nil, nil
610 }
611 return nil, errors.New("password auth failed")
612 },
613 }
614 serverConfig.AddHostKey(testSigners["rsa"])
615
616 expectedErr := fmt.Errorf("ssh: handshake failed: %v", &disconnectMsg{
617 Reason: 2,
618 Message: "too many authentication failures",
619 })
620
621 for tries := 2; tries < 4; tries++ {
622 n := tries
623 clientConfig := &ClientConfig{
624 User: user,
625 Auth: []AuthMethod{
626 RetryableAuthMethod(PasswordCallback(func() (string, error) {
627 n--
628 if n == 0 {
629 return "right", nil
630 }
631 return "wrong", nil
632 }), tries),
633 },
634 HostKeyCallback: InsecureIgnoreHostKey(),
635 }
636
637 c1, c2, err := netPipe()
638 if err != nil {
639 t.Fatalf("netPipe: %v", err)
640 }
641 defer c1.Close()
642 defer c2.Close()
643
644 errCh := make(chan error, 1)
645
646 go func() {
647 _, err := newServer(c1, serverConfig)
648 errCh <- err
649 }()
650 _, _, _, cliErr := NewClientConn(c2, "", clientConfig)
651 srvErr := <-errCh
652
653 if tries > serverConfig.MaxAuthTries {
654 if cliErr == nil {
655 t.Fatalf("client: got no error, want %s", expectedErr)
656 } else if cliErr.Error() != expectedErr.Error() {
657 t.Fatalf("client: got %s, want %s", err, expectedErr)
658 }
659 var authErr *ServerAuthError
660 if !errors.As(srvErr, &authErr) {
661 t.Errorf("expected ServerAuthError, got: %v", srvErr)
662 }
663 } else {
664 if cliErr != nil {
665 t.Fatalf("client: got %s, want no error", cliErr)
666 }
667 }
668 }
669 }
670
671
672
673 func TestClientAuthMaxAuthTriesPublicKey(t *testing.T) {
674 signers := []Signer{}
675 for i := 0; i < 6; i++ {
676 signers = append(signers, testSigners["dsa"])
677 }
678
679 validConfig := &ClientConfig{
680 User: "testuser",
681 Auth: []AuthMethod{
682 PublicKeys(append([]Signer{testSigners["rsa"]}, signers...)...),
683 },
684 HostKeyCallback: InsecureIgnoreHostKey(),
685 }
686 if err := tryAuth(t, validConfig); err != nil {
687 t.Fatalf("unable to dial remote side: %s", err)
688 }
689
690 expectedErr := fmt.Errorf("ssh: handshake failed: %v", &disconnectMsg{
691 Reason: 2,
692 Message: "too many authentication failures",
693 })
694 invalidConfig := &ClientConfig{
695 User: "testuser",
696 Auth: []AuthMethod{
697 PublicKeys(append(signers, testSigners["rsa"])...),
698 },
699 HostKeyCallback: InsecureIgnoreHostKey(),
700 }
701 if err := tryAuth(t, invalidConfig); err == nil {
702 t.Fatalf("client: got no error, want %s", expectedErr)
703 } else if err.Error() != expectedErr.Error() {
704
705
706
707
708 if runtime.GOOS == "windows" && strings.Contains(err.Error(), "wsarecv: An established connection was aborted") {
709
710 } else {
711 t.Fatalf("client: got %s, want %s", err, expectedErr)
712 }
713 }
714 }
715
716
717
718 func TestClientAuthErrorList(t *testing.T) {
719 publicKeyErr := errors.New("This is an error from PublicKeyCallback")
720
721 clientConfig := &ClientConfig{
722 Auth: []AuthMethod{
723 PublicKeys(testSigners["rsa"]),
724 },
725 HostKeyCallback: InsecureIgnoreHostKey(),
726 }
727 serverConfig := &ServerConfig{
728 PublicKeyCallback: func(_ ConnMetadata, _ PublicKey) (*Permissions, error) {
729 return nil, publicKeyErr
730 },
731 }
732 serverConfig.AddHostKey(testSigners["rsa"])
733
734 c1, c2, err := netPipe()
735 if err != nil {
736 t.Fatalf("netPipe: %v", err)
737 }
738 defer c1.Close()
739 defer c2.Close()
740
741 go NewClientConn(c2, "", clientConfig)
742 _, err = newServer(c1, serverConfig)
743 if err == nil {
744 t.Fatal("newServer: got nil, expected errors")
745 }
746
747 authErrs, ok := err.(*ServerAuthError)
748 if !ok {
749 t.Fatalf("errors: got %T, want *ssh.ServerAuthError", err)
750 }
751 for i, e := range authErrs.Errors {
752 switch i {
753 case 0:
754 if e != ErrNoAuth {
755 t.Fatalf("errors: got error %v, want ErrNoAuth", e)
756 }
757 case 1:
758 if e != publicKeyErr {
759 t.Fatalf("errors: got %v, want %v", e, publicKeyErr)
760 }
761 default:
762 t.Fatalf("errors: got %v, expected 2 errors", authErrs.Errors)
763 }
764 }
765 }
766
767 func TestAuthMethodGSSAPIWithMIC(t *testing.T) {
768 type testcase struct {
769 config *ClientConfig
770 gssConfig *GSSAPIWithMICConfig
771 clientWantErr string
772 serverWantErr string
773 }
774 testcases := []*testcase{
775 {
776 config: &ClientConfig{
777 User: "testuser",
778 Auth: []AuthMethod{
779 GSSAPIWithMICAuthMethod(
780 &FakeClient{
781 exchanges: []*exchange{
782 {
783 outToken: "client-valid-token-1",
784 },
785 {
786 expectedToken: "server-valid-token-1",
787 },
788 },
789 mic: []byte("valid-mic"),
790 maxRound: 2,
791 }, "testtarget",
792 ),
793 },
794 HostKeyCallback: InsecureIgnoreHostKey(),
795 },
796 gssConfig: &GSSAPIWithMICConfig{
797 AllowLogin: func(conn ConnMetadata, srcName string) (*Permissions, error) {
798 if srcName != conn.User()+"@DOMAIN" {
799 return nil, fmt.Errorf("srcName is %s, conn user is %s", srcName, conn.User())
800 }
801 return nil, nil
802 },
803 Server: &FakeServer{
804 exchanges: []*exchange{
805 {
806 outToken: "server-valid-token-1",
807 expectedToken: "client-valid-token-1",
808 },
809 },
810 maxRound: 1,
811 expectedMIC: []byte("valid-mic"),
812 srcName: "testuser@DOMAIN",
813 },
814 },
815 },
816 {
817 config: &ClientConfig{
818 User: "testuser",
819 Auth: []AuthMethod{
820 GSSAPIWithMICAuthMethod(
821 &FakeClient{
822 exchanges: []*exchange{
823 {
824 outToken: "client-valid-token-1",
825 },
826 {
827 expectedToken: "server-valid-token-1",
828 },
829 },
830 mic: []byte("valid-mic"),
831 maxRound: 2,
832 }, "testtarget",
833 ),
834 },
835 HostKeyCallback: InsecureIgnoreHostKey(),
836 },
837 gssConfig: &GSSAPIWithMICConfig{
838 AllowLogin: func(conn ConnMetadata, srcName string) (*Permissions, error) {
839 return nil, fmt.Errorf("user is not allowed to login")
840 },
841 Server: &FakeServer{
842 exchanges: []*exchange{
843 {
844 outToken: "server-valid-token-1",
845 expectedToken: "client-valid-token-1",
846 },
847 },
848 maxRound: 1,
849 expectedMIC: []byte("valid-mic"),
850 srcName: "testuser@DOMAIN",
851 },
852 },
853 serverWantErr: "user is not allowed to login",
854 clientWantErr: "ssh: handshake failed: ssh: unable to authenticate",
855 },
856 {
857 config: &ClientConfig{
858 User: "testuser",
859 Auth: []AuthMethod{
860 GSSAPIWithMICAuthMethod(
861 &FakeClient{
862 exchanges: []*exchange{
863 {
864 outToken: "client-valid-token-1",
865 },
866 {
867 expectedToken: "server-valid-token-1",
868 },
869 },
870 mic: []byte("valid-mic"),
871 maxRound: 2,
872 }, "testtarget",
873 ),
874 },
875 HostKeyCallback: InsecureIgnoreHostKey(),
876 },
877 gssConfig: &GSSAPIWithMICConfig{
878 AllowLogin: func(conn ConnMetadata, srcName string) (*Permissions, error) {
879 if srcName != conn.User() {
880 return nil, fmt.Errorf("srcName is %s, conn user is %s", srcName, conn.User())
881 }
882 return nil, nil
883 },
884 Server: &FakeServer{
885 exchanges: []*exchange{
886 {
887 outToken: "server-invalid-token-1",
888 expectedToken: "client-valid-token-1",
889 },
890 },
891 maxRound: 1,
892 expectedMIC: []byte("valid-mic"),
893 srcName: "testuser@DOMAIN",
894 },
895 },
896 clientWantErr: "ssh: handshake failed: got \"server-invalid-token-1\", want token \"server-valid-token-1\"",
897 },
898 {
899 config: &ClientConfig{
900 User: "testuser",
901 Auth: []AuthMethod{
902 GSSAPIWithMICAuthMethod(
903 &FakeClient{
904 exchanges: []*exchange{
905 {
906 outToken: "client-valid-token-1",
907 },
908 {
909 expectedToken: "server-valid-token-1",
910 },
911 },
912 mic: []byte("invalid-mic"),
913 maxRound: 2,
914 }, "testtarget",
915 ),
916 },
917 HostKeyCallback: InsecureIgnoreHostKey(),
918 },
919 gssConfig: &GSSAPIWithMICConfig{
920 AllowLogin: func(conn ConnMetadata, srcName string) (*Permissions, error) {
921 if srcName != conn.User() {
922 return nil, fmt.Errorf("srcName is %s, conn user is %s", srcName, conn.User())
923 }
924 return nil, nil
925 },
926 Server: &FakeServer{
927 exchanges: []*exchange{
928 {
929 outToken: "server-valid-token-1",
930 expectedToken: "client-valid-token-1",
931 },
932 },
933 maxRound: 1,
934 expectedMIC: []byte("valid-mic"),
935 srcName: "testuser@DOMAIN",
936 },
937 },
938 serverWantErr: "got MICToken \"invalid-mic\", want \"valid-mic\"",
939 clientWantErr: "ssh: handshake failed: ssh: unable to authenticate",
940 },
941 }
942
943 for i, c := range testcases {
944 clientErr, serverErrs := tryAuthBothSides(t, c.config, c.gssConfig)
945 if (c.clientWantErr == "") != (clientErr == nil) {
946 t.Fatalf("client got %v, want %s, case %d", clientErr, c.clientWantErr, i)
947 }
948 if (c.serverWantErr == "") != (len(serverErrs) == 2 && serverErrs[1] == nil || len(serverErrs) == 1) {
949 t.Fatalf("server got err %v, want %s", serverErrs, c.serverWantErr)
950 }
951 if c.clientWantErr != "" {
952 if clientErr != nil && !strings.Contains(clientErr.Error(), c.clientWantErr) {
953 t.Fatalf("client got %v, want %s, case %d", clientErr, c.clientWantErr, i)
954 }
955 }
956 found := false
957 var errStrings []string
958 if c.serverWantErr != "" {
959 for _, err := range serverErrs {
960 found = found || (err != nil && strings.Contains(err.Error(), c.serverWantErr))
961 errStrings = append(errStrings, err.Error())
962 }
963 if !found {
964 t.Errorf("server got error %q, want substring %q, case %d", errStrings, c.serverWantErr, i)
965 }
966 }
967 }
968 }
969
970 func TestCompatibleAlgoAndSignatures(t *testing.T) {
971 type testcase struct {
972 algo string
973 sigFormat string
974 compatible bool
975 }
976 testcases := []*testcase{
977 {
978 KeyAlgoRSA,
979 KeyAlgoRSA,
980 true,
981 },
982 {
983 KeyAlgoRSA,
984 KeyAlgoRSASHA256,
985 true,
986 },
987 {
988 KeyAlgoRSA,
989 KeyAlgoRSASHA512,
990 true,
991 },
992 {
993 KeyAlgoRSASHA256,
994 KeyAlgoRSA,
995 true,
996 },
997 {
998 KeyAlgoRSASHA512,
999 KeyAlgoRSA,
1000 true,
1001 },
1002 {
1003 KeyAlgoRSASHA512,
1004 KeyAlgoRSASHA256,
1005 true,
1006 },
1007 {
1008 KeyAlgoRSASHA256,
1009 KeyAlgoRSASHA512,
1010 true,
1011 },
1012 {
1013 KeyAlgoRSASHA512,
1014 KeyAlgoRSASHA512,
1015 true,
1016 },
1017 {
1018 CertAlgoRSAv01,
1019 KeyAlgoRSA,
1020 true,
1021 },
1022 {
1023 CertAlgoRSAv01,
1024 KeyAlgoRSASHA256,
1025 true,
1026 },
1027 {
1028 CertAlgoRSAv01,
1029 KeyAlgoRSASHA512,
1030 true,
1031 },
1032 {
1033 CertAlgoRSASHA256v01,
1034 KeyAlgoRSASHA512,
1035 true,
1036 },
1037 {
1038 CertAlgoRSASHA512v01,
1039 KeyAlgoRSASHA512,
1040 true,
1041 },
1042 {
1043 CertAlgoRSASHA512v01,
1044 KeyAlgoRSASHA256,
1045 true,
1046 },
1047 {
1048 CertAlgoRSASHA256v01,
1049 CertAlgoRSAv01,
1050 true,
1051 },
1052 {
1053 CertAlgoRSAv01,
1054 CertAlgoRSASHA512v01,
1055 true,
1056 },
1057 {
1058 KeyAlgoECDSA256,
1059 KeyAlgoRSA,
1060 false,
1061 },
1062 {
1063 KeyAlgoECDSA256,
1064 KeyAlgoECDSA521,
1065 false,
1066 },
1067 {
1068 KeyAlgoECDSA256,
1069 KeyAlgoECDSA256,
1070 true,
1071 },
1072 {
1073 KeyAlgoECDSA256,
1074 KeyAlgoED25519,
1075 false,
1076 },
1077 {
1078 KeyAlgoED25519,
1079 KeyAlgoED25519,
1080 true,
1081 },
1082 }
1083
1084 for _, c := range testcases {
1085 if isAlgoCompatible(c.algo, c.sigFormat) != c.compatible {
1086 t.Errorf("algorithm %q, signature format %q, expected compatible to be %t", c.algo, c.sigFormat, c.compatible)
1087 }
1088 }
1089 }
1090
1091 func TestPickSignatureAlgorithm(t *testing.T) {
1092 type testcase struct {
1093 name string
1094 extensions map[string][]byte
1095 }
1096 cases := []testcase{
1097 {
1098 name: "server with empty server-sig-algs",
1099 extensions: map[string][]byte{
1100 "server-sig-algs": []byte(``),
1101 },
1102 },
1103 {
1104 name: "server with no server-sig-algs",
1105 extensions: nil,
1106 },
1107 }
1108 for _, c := range cases {
1109 t.Run(c.name, func(t *testing.T) {
1110 signer, ok := testSigners["rsa"].(MultiAlgorithmSigner)
1111 if !ok {
1112 t.Fatalf("rsa test signer does not implement the MultiAlgorithmSigner interface")
1113 }
1114
1115 _, algo, err := pickSignatureAlgorithm(signer, c.extensions)
1116 if err != nil {
1117 t.Fatalf("got %v, want no error", err)
1118 }
1119 if algo != signer.PublicKey().Type() {
1120 t.Fatalf("got algo %q, want %q", algo, signer.PublicKey().Type())
1121 }
1122
1123
1124 cert := &Certificate{
1125 CertType: UserCert,
1126 Key: signer.PublicKey(),
1127 }
1128 cert.SignCert(rand.Reader, signer)
1129
1130 certSigner, err := NewCertSigner(cert, signer)
1131 if err != nil {
1132 t.Fatalf("error generating cert signer: %v", err)
1133 }
1134
1135
1136
1137 _, algo, err = pickSignatureAlgorithm(certSigner, c.extensions)
1138 if err != nil {
1139 t.Fatalf("got %v, want no error", err)
1140 }
1141 if algo != certSigner.PublicKey().Type() {
1142 t.Fatalf("got algo %q, want %q", algo, certSigner.PublicKey().Type())
1143 }
1144 signer, err = NewSignerWithAlgorithms(signer.(AlgorithmSigner), []string{KeyAlgoRSASHA512, KeyAlgoRSASHA256})
1145 if err != nil {
1146 t.Fatalf("unable to create signer with algorithms: %v", err)
1147 }
1148
1149
1150 _, _, err = pickSignatureAlgorithm(signer, c.extensions)
1151 if err == nil {
1152 t.Fatal("got no error, no common public key signature algorithm error expected")
1153 }
1154 })
1155 }
1156 }
1157
1158
1159
1160
1161 type configurablePublicKeyCallback struct {
1162 signer AlgorithmSigner
1163 signatureAlgo string
1164 signatureFormat string
1165 }
1166
1167 func (cb configurablePublicKeyCallback) method() string {
1168 return "publickey"
1169 }
1170
1171 func (cb configurablePublicKeyCallback) auth(session []byte, user string, c packetConn, rand io.Reader, extensions map[string][]byte) (authResult, []string, error) {
1172 pub := cb.signer.PublicKey()
1173
1174 ok, err := validateKey(pub, cb.signatureAlgo, user, c)
1175 if err != nil {
1176 return authFailure, nil, err
1177 }
1178 if !ok {
1179 return authFailure, nil, fmt.Errorf("invalid public key")
1180 }
1181
1182 pubKey := pub.Marshal()
1183 data := buildDataSignedForAuth(session, userAuthRequestMsg{
1184 User: user,
1185 Service: serviceSSH,
1186 Method: cb.method(),
1187 }, cb.signatureAlgo, pubKey)
1188 sign, err := cb.signer.SignWithAlgorithm(rand, data, underlyingAlgo(cb.signatureFormat))
1189 if err != nil {
1190 return authFailure, nil, err
1191 }
1192
1193 s := Marshal(sign)
1194 sig := make([]byte, stringLength(len(s)))
1195 marshalString(sig, s)
1196 msg := publickeyAuthMsg{
1197 User: user,
1198 Service: serviceSSH,
1199 Method: cb.method(),
1200 HasSig: true,
1201 Algoname: cb.signatureAlgo,
1202 PubKey: pubKey,
1203 Sig: sig,
1204 }
1205 p := Marshal(&msg)
1206 if err := c.writePacket(p); err != nil {
1207 return authFailure, nil, err
1208 }
1209 var success authResult
1210 success, methods, err := handleAuthResponse(c)
1211 if err != nil {
1212 return authFailure, nil, err
1213 }
1214 if success == authSuccess || !contains(methods, cb.method()) {
1215 return success, methods, err
1216 }
1217
1218 return authFailure, methods, nil
1219 }
1220
1221 func TestPublicKeyAndAlgoCompatibility(t *testing.T) {
1222 cert := &Certificate{
1223 Key: testPublicKeys["rsa"],
1224 ValidBefore: CertTimeInfinity,
1225 CertType: UserCert,
1226 }
1227 cert.SignCert(rand.Reader, testSigners["ecdsa"])
1228 certSigner, err := NewCertSigner(cert, testSigners["rsa"])
1229 if err != nil {
1230 t.Fatalf("NewCertSigner: %v", err)
1231 }
1232
1233 clientConfig := &ClientConfig{
1234 User: "user",
1235 HostKeyCallback: InsecureIgnoreHostKey(),
1236 Auth: []AuthMethod{
1237 configurablePublicKeyCallback{
1238 signer: certSigner.(AlgorithmSigner),
1239 signatureAlgo: KeyAlgoRSASHA256,
1240 signatureFormat: KeyAlgoRSASHA256,
1241 },
1242 },
1243 }
1244 if err := tryAuth(t, clientConfig); err == nil {
1245 t.Error("cert login passed with incompatible public key type and algorithm")
1246 }
1247 }
1248
1249 func TestClientAuthGPGAgentCompat(t *testing.T) {
1250 clientConfig := &ClientConfig{
1251 User: "testuser",
1252 HostKeyCallback: InsecureIgnoreHostKey(),
1253 Auth: []AuthMethod{
1254
1255 configurablePublicKeyCallback{
1256 signer: testSigners["rsa"].(AlgorithmSigner),
1257 signatureAlgo: KeyAlgoRSASHA512,
1258 signatureFormat: KeyAlgoRSA,
1259 },
1260 },
1261 }
1262 if err := tryAuth(t, clientConfig); err != nil {
1263 t.Fatalf("unable to dial remote side: %s", err)
1264 }
1265 }
1266
1267 func TestCertAuthOpenSSHCompat(t *testing.T) {
1268 cert := &Certificate{
1269 Key: testPublicKeys["rsa"],
1270 ValidBefore: CertTimeInfinity,
1271 CertType: UserCert,
1272 }
1273 cert.SignCert(rand.Reader, testSigners["ecdsa"])
1274 certSigner, err := NewCertSigner(cert, testSigners["rsa"])
1275 if err != nil {
1276 t.Fatalf("NewCertSigner: %v", err)
1277 }
1278
1279 clientConfig := &ClientConfig{
1280 User: "user",
1281 HostKeyCallback: InsecureIgnoreHostKey(),
1282 Auth: []AuthMethod{
1283
1284
1285 configurablePublicKeyCallback{
1286 signer: certSigner.(AlgorithmSigner),
1287 signatureAlgo: CertAlgoRSAv01,
1288 signatureFormat: KeyAlgoRSASHA256,
1289 },
1290 },
1291 }
1292 if err := tryAuth(t, clientConfig); err != nil {
1293 t.Fatalf("unable to dial remote side: %s", err)
1294 }
1295 }
1296
1297 func TestKeyboardInteractiveAuthEarlyFail(t *testing.T) {
1298 const maxAuthTries = 2
1299
1300 c1, c2, err := netPipe()
1301 if err != nil {
1302 t.Fatalf("netPipe: %v", err)
1303 }
1304 defer c1.Close()
1305 defer c2.Close()
1306
1307
1308 serverConfig := &ServerConfig{
1309 MaxAuthTries: maxAuthTries,
1310 KeyboardInteractiveCallback: func(c ConnMetadata,
1311 client KeyboardInteractiveChallenge) (*Permissions, error) {
1312
1313
1314 return nil, errors.New("keyboard-interactive auth failed")
1315 },
1316 PasswordCallback: func(c ConnMetadata,
1317 pass []byte) (*Permissions, error) {
1318 if string(pass) == clientPassword {
1319 return nil, nil
1320 }
1321 return nil, errors.New("password auth failed")
1322 },
1323 }
1324 serverConfig.AddHostKey(testSigners["rsa"])
1325
1326 serverDone := make(chan struct{})
1327 go func() {
1328 defer func() { serverDone <- struct{}{} }()
1329 conn, chans, reqs, err := NewServerConn(c2, serverConfig)
1330 if err != nil {
1331 return
1332 }
1333 _ = conn.Close()
1334
1335 discarderDone := make(chan struct{})
1336 go func() {
1337 defer func() { discarderDone <- struct{}{} }()
1338 DiscardRequests(reqs)
1339 }()
1340 for newChannel := range chans {
1341 newChannel.Reject(Prohibited,
1342 "testserver not accepting requests")
1343 }
1344
1345 <-discarderDone
1346 }()
1347
1348
1349
1350 passwordCallbackCalled := false
1351 clientConfig := &ClientConfig{
1352 User: "testuser",
1353 Auth: []AuthMethod{
1354 RetryableAuthMethod(KeyboardInteractive(func(name,
1355 instruction string, questions []string,
1356 echos []bool) ([]string, error) {
1357 t.Errorf("unexpected call to KeyboardInteractive()")
1358 return []string{clientPassword}, nil
1359 }), maxAuthTries),
1360 RetryableAuthMethod(PasswordCallback(func() (secret string,
1361 err error) {
1362 t.Logf("PasswordCallback()")
1363 passwordCallbackCalled = true
1364 return clientPassword, nil
1365 }), maxAuthTries),
1366 },
1367 HostKeyCallback: InsecureIgnoreHostKey(),
1368 }
1369
1370 conn, _, _, err := NewClientConn(c1, "", clientConfig)
1371 if err != nil {
1372 t.Errorf("unexpected NewClientConn() error: %v", err)
1373 }
1374 if conn != nil {
1375 conn.Close()
1376 }
1377
1378
1379 <-serverDone
1380
1381 if !passwordCallbackCalled {
1382 t.Errorf("expected PasswordCallback() to be called")
1383 }
1384 }
1385
View as plain text