session_test.go 19 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776
  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. // Session tests.
  6. import (
  7. "bytes"
  8. crypto_rand "crypto/rand"
  9. "errors"
  10. "io"
  11. "io/ioutil"
  12. "math/rand"
  13. "net"
  14. "testing"
  15. "golang.org/x/crypto/ssh/terminal"
  16. )
  17. type serverType func(Channel, <-chan *Request, *testing.T)
  18. // dial constructs a new test server and returns a *ClientConn.
  19. func dial(handler serverType, t *testing.T) *Client {
  20. c1, c2, err := netPipe()
  21. if err != nil {
  22. t.Fatalf("netPipe: %v", err)
  23. }
  24. go func() {
  25. defer c1.Close()
  26. conf := ServerConfig{
  27. NoClientAuth: true,
  28. }
  29. conf.AddHostKey(testSigners["rsa"])
  30. conn, chans, reqs, err := NewServerConn(c1, &conf)
  31. if err != nil {
  32. t.Fatalf("Unable to handshake: %v", err)
  33. }
  34. go DiscardRequests(reqs)
  35. for newCh := range chans {
  36. if newCh.ChannelType() != "session" {
  37. newCh.Reject(UnknownChannelType, "unknown channel type")
  38. continue
  39. }
  40. ch, inReqs, err := newCh.Accept()
  41. if err != nil {
  42. t.Errorf("Accept: %v", err)
  43. continue
  44. }
  45. go func() {
  46. handler(ch, inReqs, t)
  47. }()
  48. }
  49. if err := conn.Wait(); err != io.EOF {
  50. t.Logf("server exit reason: %v", err)
  51. }
  52. }()
  53. config := &ClientConfig{
  54. User: "testuser",
  55. HostKeyCallback: InsecureIgnoreHostKey(),
  56. }
  57. conn, chans, reqs, err := NewClientConn(c2, "", config)
  58. if err != nil {
  59. t.Fatalf("unable to dial remote side: %v", err)
  60. }
  61. return NewClient(conn, chans, reqs)
  62. }
  63. // Test a simple string is returned to session.Stdout.
  64. func TestSessionShell(t *testing.T) {
  65. conn := dial(shellHandler, t)
  66. defer conn.Close()
  67. session, err := conn.NewSession()
  68. if err != nil {
  69. t.Fatalf("Unable to request new session: %v", err)
  70. }
  71. defer session.Close()
  72. stdout := new(bytes.Buffer)
  73. session.Stdout = stdout
  74. if err := session.Shell(); err != nil {
  75. t.Fatalf("Unable to execute command: %s", err)
  76. }
  77. if err := session.Wait(); err != nil {
  78. t.Fatalf("Remote command did not exit cleanly: %v", err)
  79. }
  80. actual := stdout.String()
  81. if actual != "golang" {
  82. t.Fatalf("Remote shell did not return expected string: expected=golang, actual=%s", actual)
  83. }
  84. }
  85. // TODO(dfc) add support for Std{in,err}Pipe when the Server supports it.
  86. // Test a simple string is returned via StdoutPipe.
  87. func TestSessionStdoutPipe(t *testing.T) {
  88. conn := dial(shellHandler, t)
  89. defer conn.Close()
  90. session, err := conn.NewSession()
  91. if err != nil {
  92. t.Fatalf("Unable to request new session: %v", err)
  93. }
  94. defer session.Close()
  95. stdout, err := session.StdoutPipe()
  96. if err != nil {
  97. t.Fatalf("Unable to request StdoutPipe(): %v", err)
  98. }
  99. var buf bytes.Buffer
  100. if err := session.Shell(); err != nil {
  101. t.Fatalf("Unable to execute command: %v", err)
  102. }
  103. done := make(chan bool, 1)
  104. go func() {
  105. if _, err := io.Copy(&buf, stdout); err != nil {
  106. t.Errorf("Copy of stdout failed: %v", err)
  107. }
  108. done <- true
  109. }()
  110. if err := session.Wait(); err != nil {
  111. t.Fatalf("Remote command did not exit cleanly: %v", err)
  112. }
  113. <-done
  114. actual := buf.String()
  115. if actual != "golang" {
  116. t.Fatalf("Remote shell did not return expected string: expected=golang, actual=%s", actual)
  117. }
  118. }
  119. // Test that a simple string is returned via the Output helper,
  120. // and that stderr is discarded.
  121. func TestSessionOutput(t *testing.T) {
  122. conn := dial(fixedOutputHandler, t)
  123. defer conn.Close()
  124. session, err := conn.NewSession()
  125. if err != nil {
  126. t.Fatalf("Unable to request new session: %v", err)
  127. }
  128. defer session.Close()
  129. buf, err := session.Output("") // cmd is ignored by fixedOutputHandler
  130. if err != nil {
  131. t.Error("Remote command did not exit cleanly:", err)
  132. }
  133. w := "this-is-stdout."
  134. g := string(buf)
  135. if g != w {
  136. t.Error("Remote command did not return expected string:")
  137. t.Logf("want %q", w)
  138. t.Logf("got %q", g)
  139. }
  140. }
  141. // Test that both stdout and stderr are returned
  142. // via the CombinedOutput helper.
  143. func TestSessionCombinedOutput(t *testing.T) {
  144. conn := dial(fixedOutputHandler, t)
  145. defer conn.Close()
  146. session, err := conn.NewSession()
  147. if err != nil {
  148. t.Fatalf("Unable to request new session: %v", err)
  149. }
  150. defer session.Close()
  151. buf, err := session.CombinedOutput("") // cmd is ignored by fixedOutputHandler
  152. if err != nil {
  153. t.Error("Remote command did not exit cleanly:", err)
  154. }
  155. const stdout = "this-is-stdout."
  156. const stderr = "this-is-stderr."
  157. g := string(buf)
  158. if g != stdout+stderr && g != stderr+stdout {
  159. t.Error("Remote command did not return expected string:")
  160. t.Logf("want %q, or %q", stdout+stderr, stderr+stdout)
  161. t.Logf("got %q", g)
  162. }
  163. }
  164. // Test non-0 exit status is returned correctly.
  165. func TestExitStatusNonZero(t *testing.T) {
  166. conn := dial(exitStatusNonZeroHandler, t)
  167. defer conn.Close()
  168. session, err := conn.NewSession()
  169. if err != nil {
  170. t.Fatalf("Unable to request new session: %v", err)
  171. }
  172. defer session.Close()
  173. if err := session.Shell(); err != nil {
  174. t.Fatalf("Unable to execute command: %v", err)
  175. }
  176. err = session.Wait()
  177. if err == nil {
  178. t.Fatalf("expected command to fail but it didn't")
  179. }
  180. e, ok := err.(*ExitError)
  181. if !ok {
  182. t.Fatalf("expected *ExitError but got %T", err)
  183. }
  184. if e.ExitStatus() != 15 {
  185. t.Fatalf("expected command to exit with 15 but got %v", e.ExitStatus())
  186. }
  187. }
  188. // Test 0 exit status is returned correctly.
  189. func TestExitStatusZero(t *testing.T) {
  190. conn := dial(exitStatusZeroHandler, t)
  191. defer conn.Close()
  192. session, err := conn.NewSession()
  193. if err != nil {
  194. t.Fatalf("Unable to request new session: %v", err)
  195. }
  196. defer session.Close()
  197. if err := session.Shell(); err != nil {
  198. t.Fatalf("Unable to execute command: %v", err)
  199. }
  200. err = session.Wait()
  201. if err != nil {
  202. t.Fatalf("expected nil but got %v", err)
  203. }
  204. }
  205. // Test exit signal and status are both returned correctly.
  206. func TestExitSignalAndStatus(t *testing.T) {
  207. conn := dial(exitSignalAndStatusHandler, t)
  208. defer conn.Close()
  209. session, err := conn.NewSession()
  210. if err != nil {
  211. t.Fatalf("Unable to request new session: %v", err)
  212. }
  213. defer session.Close()
  214. if err := session.Shell(); err != nil {
  215. t.Fatalf("Unable to execute command: %v", err)
  216. }
  217. err = session.Wait()
  218. if err == nil {
  219. t.Fatalf("expected command to fail but it didn't")
  220. }
  221. e, ok := err.(*ExitError)
  222. if !ok {
  223. t.Fatalf("expected *ExitError but got %T", err)
  224. }
  225. if e.Signal() != "TERM" || e.ExitStatus() != 15 {
  226. t.Fatalf("expected command to exit with signal TERM and status 15 but got signal %s and status %v", e.Signal(), e.ExitStatus())
  227. }
  228. }
  229. // Test exit signal and status are both returned correctly.
  230. func TestKnownExitSignalOnly(t *testing.T) {
  231. conn := dial(exitSignalHandler, t)
  232. defer conn.Close()
  233. session, err := conn.NewSession()
  234. if err != nil {
  235. t.Fatalf("Unable to request new session: %v", err)
  236. }
  237. defer session.Close()
  238. if err := session.Shell(); err != nil {
  239. t.Fatalf("Unable to execute command: %v", err)
  240. }
  241. err = session.Wait()
  242. if err == nil {
  243. t.Fatalf("expected command to fail but it didn't")
  244. }
  245. e, ok := err.(*ExitError)
  246. if !ok {
  247. t.Fatalf("expected *ExitError but got %T", err)
  248. }
  249. if e.Signal() != "TERM" || e.ExitStatus() != 143 {
  250. t.Fatalf("expected command to exit with signal TERM and status 143 but got signal %s and status %v", e.Signal(), e.ExitStatus())
  251. }
  252. }
  253. // Test exit signal and status are both returned correctly.
  254. func TestUnknownExitSignal(t *testing.T) {
  255. conn := dial(exitSignalUnknownHandler, t)
  256. defer conn.Close()
  257. session, err := conn.NewSession()
  258. if err != nil {
  259. t.Fatalf("Unable to request new session: %v", err)
  260. }
  261. defer session.Close()
  262. if err := session.Shell(); err != nil {
  263. t.Fatalf("Unable to execute command: %v", err)
  264. }
  265. err = session.Wait()
  266. if err == nil {
  267. t.Fatalf("expected command to fail but it didn't")
  268. }
  269. e, ok := err.(*ExitError)
  270. if !ok {
  271. t.Fatalf("expected *ExitError but got %T", err)
  272. }
  273. if e.Signal() != "SYS" || e.ExitStatus() != 128 {
  274. t.Fatalf("expected command to exit with signal SYS and status 128 but got signal %s and status %v", e.Signal(), e.ExitStatus())
  275. }
  276. }
  277. func TestExitWithoutStatusOrSignal(t *testing.T) {
  278. conn := dial(exitWithoutSignalOrStatus, t)
  279. defer conn.Close()
  280. session, err := conn.NewSession()
  281. if err != nil {
  282. t.Fatalf("Unable to request new session: %v", err)
  283. }
  284. defer session.Close()
  285. if err := session.Shell(); err != nil {
  286. t.Fatalf("Unable to execute command: %v", err)
  287. }
  288. err = session.Wait()
  289. if err == nil {
  290. t.Fatalf("expected command to fail but it didn't")
  291. }
  292. if _, ok := err.(*ExitMissingError); !ok {
  293. t.Fatalf("got %T want *ExitMissingError", err)
  294. }
  295. }
  296. // windowTestBytes is the number of bytes that we'll send to the SSH server.
  297. const windowTestBytes = 16000 * 200
  298. // TestServerWindow writes random data to the server. The server is expected to echo
  299. // the same data back, which is compared against the original.
  300. func TestServerWindow(t *testing.T) {
  301. origBuf := bytes.NewBuffer(make([]byte, 0, windowTestBytes))
  302. io.CopyN(origBuf, crypto_rand.Reader, windowTestBytes)
  303. origBytes := origBuf.Bytes()
  304. conn := dial(echoHandler, t)
  305. defer conn.Close()
  306. session, err := conn.NewSession()
  307. if err != nil {
  308. t.Fatal(err)
  309. }
  310. defer session.Close()
  311. result := make(chan []byte)
  312. go func() {
  313. defer close(result)
  314. echoedBuf := bytes.NewBuffer(make([]byte, 0, windowTestBytes))
  315. serverStdout, err := session.StdoutPipe()
  316. if err != nil {
  317. t.Errorf("StdoutPipe failed: %v", err)
  318. return
  319. }
  320. n, err := copyNRandomly("stdout", echoedBuf, serverStdout, windowTestBytes)
  321. if err != nil && err != io.EOF {
  322. t.Errorf("Read only %d bytes from server, expected %d: %v", n, windowTestBytes, err)
  323. }
  324. result <- echoedBuf.Bytes()
  325. }()
  326. serverStdin, err := session.StdinPipe()
  327. if err != nil {
  328. t.Fatalf("StdinPipe failed: %v", err)
  329. }
  330. written, err := copyNRandomly("stdin", serverStdin, origBuf, windowTestBytes)
  331. if err != nil {
  332. t.Errorf("failed to copy origBuf to serverStdin: %v", err)
  333. } else if written != windowTestBytes {
  334. t.Errorf("Wrote only %d of %d bytes to server", written, windowTestBytes)
  335. }
  336. echoedBytes := <-result
  337. if !bytes.Equal(origBytes, echoedBytes) {
  338. t.Fatalf("Echoed buffer differed from original, orig %d, echoed %d", len(origBytes), len(echoedBytes))
  339. }
  340. }
  341. // Verify the client can handle a keepalive packet from the server.
  342. func TestClientHandlesKeepalives(t *testing.T) {
  343. conn := dial(channelKeepaliveSender, t)
  344. defer conn.Close()
  345. session, err := conn.NewSession()
  346. if err != nil {
  347. t.Fatal(err)
  348. }
  349. defer session.Close()
  350. if err := session.Shell(); err != nil {
  351. t.Fatalf("Unable to execute command: %v", err)
  352. }
  353. err = session.Wait()
  354. if err != nil {
  355. t.Fatalf("expected nil but got: %v", err)
  356. }
  357. }
  358. type exitStatusMsg struct {
  359. Status uint32
  360. }
  361. type exitSignalMsg struct {
  362. Signal string
  363. CoreDumped bool
  364. Errmsg string
  365. Lang string
  366. }
  367. func handleTerminalRequests(in <-chan *Request) {
  368. for req := range in {
  369. ok := false
  370. switch req.Type {
  371. case "shell":
  372. ok = true
  373. if len(req.Payload) > 0 {
  374. // We don't accept any commands, only the default shell.
  375. ok = false
  376. }
  377. case "env":
  378. ok = true
  379. }
  380. req.Reply(ok, nil)
  381. }
  382. }
  383. func newServerShell(ch Channel, in <-chan *Request, prompt string) *terminal.Terminal {
  384. term := terminal.NewTerminal(ch, prompt)
  385. go handleTerminalRequests(in)
  386. return term
  387. }
  388. func exitStatusZeroHandler(ch Channel, in <-chan *Request, t *testing.T) {
  389. defer ch.Close()
  390. // this string is returned to stdout
  391. shell := newServerShell(ch, in, "> ")
  392. readLine(shell, t)
  393. sendStatus(0, ch, t)
  394. }
  395. func exitStatusNonZeroHandler(ch Channel, in <-chan *Request, t *testing.T) {
  396. defer ch.Close()
  397. shell := newServerShell(ch, in, "> ")
  398. readLine(shell, t)
  399. sendStatus(15, ch, t)
  400. }
  401. func exitSignalAndStatusHandler(ch Channel, in <-chan *Request, t *testing.T) {
  402. defer ch.Close()
  403. shell := newServerShell(ch, in, "> ")
  404. readLine(shell, t)
  405. sendStatus(15, ch, t)
  406. sendSignal("TERM", ch, t)
  407. }
  408. func exitSignalHandler(ch Channel, in <-chan *Request, t *testing.T) {
  409. defer ch.Close()
  410. shell := newServerShell(ch, in, "> ")
  411. readLine(shell, t)
  412. sendSignal("TERM", ch, t)
  413. }
  414. func exitSignalUnknownHandler(ch Channel, in <-chan *Request, t *testing.T) {
  415. defer ch.Close()
  416. shell := newServerShell(ch, in, "> ")
  417. readLine(shell, t)
  418. sendSignal("SYS", ch, t)
  419. }
  420. func exitWithoutSignalOrStatus(ch Channel, in <-chan *Request, t *testing.T) {
  421. defer ch.Close()
  422. shell := newServerShell(ch, in, "> ")
  423. readLine(shell, t)
  424. }
  425. func shellHandler(ch Channel, in <-chan *Request, t *testing.T) {
  426. defer ch.Close()
  427. // this string is returned to stdout
  428. shell := newServerShell(ch, in, "golang")
  429. readLine(shell, t)
  430. sendStatus(0, ch, t)
  431. }
  432. // Ignores the command, writes fixed strings to stderr and stdout.
  433. // Strings are "this-is-stdout." and "this-is-stderr.".
  434. func fixedOutputHandler(ch Channel, in <-chan *Request, t *testing.T) {
  435. defer ch.Close()
  436. _, err := ch.Read(nil)
  437. req, ok := <-in
  438. if !ok {
  439. t.Fatalf("error: expected channel request, got: %#v", err)
  440. return
  441. }
  442. // ignore request, always send some text
  443. req.Reply(true, nil)
  444. _, err = io.WriteString(ch, "this-is-stdout.")
  445. if err != nil {
  446. t.Fatalf("error writing on server: %v", err)
  447. }
  448. _, err = io.WriteString(ch.Stderr(), "this-is-stderr.")
  449. if err != nil {
  450. t.Fatalf("error writing on server: %v", err)
  451. }
  452. sendStatus(0, ch, t)
  453. }
  454. func readLine(shell *terminal.Terminal, t *testing.T) {
  455. if _, err := shell.ReadLine(); err != nil && err != io.EOF {
  456. t.Errorf("unable to read line: %v", err)
  457. }
  458. }
  459. func sendStatus(status uint32, ch Channel, t *testing.T) {
  460. msg := exitStatusMsg{
  461. Status: status,
  462. }
  463. if _, err := ch.SendRequest("exit-status", false, Marshal(&msg)); err != nil {
  464. t.Errorf("unable to send status: %v", err)
  465. }
  466. }
  467. func sendSignal(signal string, ch Channel, t *testing.T) {
  468. sig := exitSignalMsg{
  469. Signal: signal,
  470. CoreDumped: false,
  471. Errmsg: "Process terminated",
  472. Lang: "en-GB-oed",
  473. }
  474. if _, err := ch.SendRequest("exit-signal", false, Marshal(&sig)); err != nil {
  475. t.Errorf("unable to send signal: %v", err)
  476. }
  477. }
  478. func discardHandler(ch Channel, t *testing.T) {
  479. defer ch.Close()
  480. io.Copy(ioutil.Discard, ch)
  481. }
  482. func echoHandler(ch Channel, in <-chan *Request, t *testing.T) {
  483. defer ch.Close()
  484. if n, err := copyNRandomly("echohandler", ch, ch, windowTestBytes); err != nil {
  485. t.Errorf("short write, wrote %d, expected %d: %v ", n, windowTestBytes, err)
  486. }
  487. }
  488. // copyNRandomly copies n bytes from src to dst. It uses a variable, and random,
  489. // buffer size to exercise more code paths.
  490. func copyNRandomly(title string, dst io.Writer, src io.Reader, n int) (int, error) {
  491. var (
  492. buf = make([]byte, 32*1024)
  493. written int
  494. remaining = n
  495. )
  496. for remaining > 0 {
  497. l := rand.Intn(1 << 15)
  498. if remaining < l {
  499. l = remaining
  500. }
  501. nr, er := src.Read(buf[:l])
  502. nw, ew := dst.Write(buf[:nr])
  503. remaining -= nw
  504. written += nw
  505. if ew != nil {
  506. return written, ew
  507. }
  508. if nr != nw {
  509. return written, io.ErrShortWrite
  510. }
  511. if er != nil && er != io.EOF {
  512. return written, er
  513. }
  514. }
  515. return written, nil
  516. }
  517. func channelKeepaliveSender(ch Channel, in <-chan *Request, t *testing.T) {
  518. defer ch.Close()
  519. shell := newServerShell(ch, in, "> ")
  520. readLine(shell, t)
  521. if _, err := ch.SendRequest("keepalive@openssh.com", true, nil); err != nil {
  522. t.Errorf("unable to send channel keepalive request: %v", err)
  523. }
  524. sendStatus(0, ch, t)
  525. }
  526. func TestClientWriteEOF(t *testing.T) {
  527. conn := dial(simpleEchoHandler, t)
  528. defer conn.Close()
  529. session, err := conn.NewSession()
  530. if err != nil {
  531. t.Fatal(err)
  532. }
  533. defer session.Close()
  534. stdin, err := session.StdinPipe()
  535. if err != nil {
  536. t.Fatalf("StdinPipe failed: %v", err)
  537. }
  538. stdout, err := session.StdoutPipe()
  539. if err != nil {
  540. t.Fatalf("StdoutPipe failed: %v", err)
  541. }
  542. data := []byte(`0000`)
  543. _, err = stdin.Write(data)
  544. if err != nil {
  545. t.Fatalf("Write failed: %v", err)
  546. }
  547. stdin.Close()
  548. res, err := ioutil.ReadAll(stdout)
  549. if err != nil {
  550. t.Fatalf("Read failed: %v", err)
  551. }
  552. if !bytes.Equal(data, res) {
  553. t.Fatalf("Read differed from write, wrote: %v, read: %v", data, res)
  554. }
  555. }
  556. func simpleEchoHandler(ch Channel, in <-chan *Request, t *testing.T) {
  557. defer ch.Close()
  558. data, err := ioutil.ReadAll(ch)
  559. if err != nil {
  560. t.Errorf("handler read error: %v", err)
  561. }
  562. _, err = ch.Write(data)
  563. if err != nil {
  564. t.Errorf("handler write error: %v", err)
  565. }
  566. }
  567. func TestSessionID(t *testing.T) {
  568. c1, c2, err := netPipe()
  569. if err != nil {
  570. t.Fatalf("netPipe: %v", err)
  571. }
  572. defer c1.Close()
  573. defer c2.Close()
  574. serverID := make(chan []byte, 1)
  575. clientID := make(chan []byte, 1)
  576. serverConf := &ServerConfig{
  577. NoClientAuth: true,
  578. }
  579. serverConf.AddHostKey(testSigners["ecdsa"])
  580. clientConf := &ClientConfig{
  581. HostKeyCallback: InsecureIgnoreHostKey(),
  582. User: "user",
  583. }
  584. go func() {
  585. conn, chans, reqs, err := NewServerConn(c1, serverConf)
  586. if err != nil {
  587. t.Fatalf("server handshake: %v", err)
  588. }
  589. serverID <- conn.SessionID()
  590. go DiscardRequests(reqs)
  591. for ch := range chans {
  592. ch.Reject(Prohibited, "")
  593. }
  594. }()
  595. go func() {
  596. conn, chans, reqs, err := NewClientConn(c2, "", clientConf)
  597. if err != nil {
  598. t.Fatalf("client handshake: %v", err)
  599. }
  600. clientID <- conn.SessionID()
  601. go DiscardRequests(reqs)
  602. for ch := range chans {
  603. ch.Reject(Prohibited, "")
  604. }
  605. }()
  606. s := <-serverID
  607. c := <-clientID
  608. if bytes.Compare(s, c) != 0 {
  609. t.Errorf("server session ID (%x) != client session ID (%x)", s, c)
  610. } else if len(s) == 0 {
  611. t.Errorf("client and server SessionID were empty.")
  612. }
  613. }
  614. type noReadConn struct {
  615. readSeen bool
  616. net.Conn
  617. }
  618. func (c *noReadConn) Close() error {
  619. return nil
  620. }
  621. func (c *noReadConn) Read(b []byte) (int, error) {
  622. c.readSeen = true
  623. return 0, errors.New("noReadConn error")
  624. }
  625. func TestInvalidServerConfiguration(t *testing.T) {
  626. c1, c2, err := netPipe()
  627. if err != nil {
  628. t.Fatalf("netPipe: %v", err)
  629. }
  630. defer c1.Close()
  631. defer c2.Close()
  632. serveConn := noReadConn{Conn: c1}
  633. serverConf := &ServerConfig{}
  634. NewServerConn(&serveConn, serverConf)
  635. if serveConn.readSeen {
  636. t.Fatalf("NewServerConn attempted to Read() from Conn while configuration is missing host key")
  637. }
  638. serverConf.AddHostKey(testSigners["ecdsa"])
  639. NewServerConn(&serveConn, serverConf)
  640. if serveConn.readSeen {
  641. t.Fatalf("NewServerConn attempted to Read() from Conn while configuration is missing authentication method")
  642. }
  643. }
  644. func TestHostKeyAlgorithms(t *testing.T) {
  645. serverConf := &ServerConfig{
  646. NoClientAuth: true,
  647. }
  648. serverConf.AddHostKey(testSigners["rsa"])
  649. serverConf.AddHostKey(testSigners["ecdsa"])
  650. connect := func(clientConf *ClientConfig, want string) {
  651. var alg string
  652. clientConf.HostKeyCallback = func(h string, a net.Addr, key PublicKey) error {
  653. alg = key.Type()
  654. return nil
  655. }
  656. c1, c2, err := netPipe()
  657. if err != nil {
  658. t.Fatalf("netPipe: %v", err)
  659. }
  660. defer c1.Close()
  661. defer c2.Close()
  662. go NewServerConn(c1, serverConf)
  663. _, _, _, err = NewClientConn(c2, "", clientConf)
  664. if err != nil {
  665. t.Fatalf("NewClientConn: %v", err)
  666. }
  667. if alg != want {
  668. t.Errorf("selected key algorithm %s, want %s", alg, want)
  669. }
  670. }
  671. // By default, we get the preferred algorithm, which is ECDSA 256.
  672. clientConf := &ClientConfig{
  673. HostKeyCallback: InsecureIgnoreHostKey(),
  674. }
  675. connect(clientConf, KeyAlgoECDSA256)
  676. // Client asks for RSA explicitly.
  677. clientConf.HostKeyAlgorithms = []string{KeyAlgoRSA}
  678. connect(clientConf, KeyAlgoRSA)
  679. c1, c2, err := netPipe()
  680. if err != nil {
  681. t.Fatalf("netPipe: %v", err)
  682. }
  683. defer c1.Close()
  684. defer c2.Close()
  685. go NewServerConn(c1, serverConf)
  686. clientConf.HostKeyAlgorithms = []string{"nonexistent-hostkey-algo"}
  687. _, _, _, err = NewClientConn(c2, "", clientConf)
  688. if err == nil {
  689. t.Fatal("succeeded connecting with unknown hostkey algorithm")
  690. }
  691. }