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  }