client_auth_test.go 23 KB

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