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