session_test.go 19 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774
  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. "github.com/gogits/gogs/modules/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. _, 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. }()
  50. config := &ClientConfig{
  51. User: "testuser",
  52. }
  53. conn, chans, reqs, err := NewClientConn(c2, "", config)
  54. if err != nil {
  55. t.Fatalf("unable to dial remote side: %v", err)
  56. }
  57. return NewClient(conn, chans, reqs)
  58. }
  59. // Test a simple string is returned to session.Stdout.
  60. func TestSessionShell(t *testing.T) {
  61. conn := dial(shellHandler, t)
  62. defer conn.Close()
  63. session, err := conn.NewSession()
  64. if err != nil {
  65. t.Fatalf("Unable to request new session: %v", err)
  66. }
  67. defer session.Close()
  68. stdout := new(bytes.Buffer)
  69. session.Stdout = stdout
  70. if err := session.Shell(); err != nil {
  71. t.Fatalf("Unable to execute command: %s", err)
  72. }
  73. if err := session.Wait(); err != nil {
  74. t.Fatalf("Remote command did not exit cleanly: %v", err)
  75. }
  76. actual := stdout.String()
  77. if actual != "golang" {
  78. t.Fatalf("Remote shell did not return expected string: expected=golang, actual=%s", actual)
  79. }
  80. }
  81. // TODO(dfc) add support for Std{in,err}Pipe when the Server supports it.
  82. // Test a simple string is returned via StdoutPipe.
  83. func TestSessionStdoutPipe(t *testing.T) {
  84. conn := dial(shellHandler, t)
  85. defer conn.Close()
  86. session, err := conn.NewSession()
  87. if err != nil {
  88. t.Fatalf("Unable to request new session: %v", err)
  89. }
  90. defer session.Close()
  91. stdout, err := session.StdoutPipe()
  92. if err != nil {
  93. t.Fatalf("Unable to request StdoutPipe(): %v", err)
  94. }
  95. var buf bytes.Buffer
  96. if err := session.Shell(); err != nil {
  97. t.Fatalf("Unable to execute command: %v", err)
  98. }
  99. done := make(chan bool, 1)
  100. go func() {
  101. if _, err := io.Copy(&buf, stdout); err != nil {
  102. t.Errorf("Copy of stdout failed: %v", err)
  103. }
  104. done <- true
  105. }()
  106. if err := session.Wait(); err != nil {
  107. t.Fatalf("Remote command did not exit cleanly: %v", err)
  108. }
  109. <-done
  110. actual := buf.String()
  111. if actual != "golang" {
  112. t.Fatalf("Remote shell did not return expected string: expected=golang, actual=%s", actual)
  113. }
  114. }
  115. // Test that a simple string is returned via the Output helper,
  116. // and that stderr is discarded.
  117. func TestSessionOutput(t *testing.T) {
  118. conn := dial(fixedOutputHandler, t)
  119. defer conn.Close()
  120. session, err := conn.NewSession()
  121. if err != nil {
  122. t.Fatalf("Unable to request new session: %v", err)
  123. }
  124. defer session.Close()
  125. buf, err := session.Output("") // cmd is ignored by fixedOutputHandler
  126. if err != nil {
  127. t.Error("Remote command did not exit cleanly:", err)
  128. }
  129. w := "this-is-stdout."
  130. g := string(buf)
  131. if g != w {
  132. t.Error("Remote command did not return expected string:")
  133. t.Logf("want %q", w)
  134. t.Logf("got %q", g)
  135. }
  136. }
  137. // Test that both stdout and stderr are returned
  138. // via the CombinedOutput helper.
  139. func TestSessionCombinedOutput(t *testing.T) {
  140. conn := dial(fixedOutputHandler, t)
  141. defer conn.Close()
  142. session, err := conn.NewSession()
  143. if err != nil {
  144. t.Fatalf("Unable to request new session: %v", err)
  145. }
  146. defer session.Close()
  147. buf, err := session.CombinedOutput("") // cmd is ignored by fixedOutputHandler
  148. if err != nil {
  149. t.Error("Remote command did not exit cleanly:", err)
  150. }
  151. const stdout = "this-is-stdout."
  152. const stderr = "this-is-stderr."
  153. g := string(buf)
  154. if g != stdout+stderr && g != stderr+stdout {
  155. t.Error("Remote command did not return expected string:")
  156. t.Logf("want %q, or %q", stdout+stderr, stderr+stdout)
  157. t.Logf("got %q", g)
  158. }
  159. }
  160. // Test non-0 exit status is returned correctly.
  161. func TestExitStatusNonZero(t *testing.T) {
  162. conn := dial(exitStatusNonZeroHandler, t)
  163. defer conn.Close()
  164. session, err := conn.NewSession()
  165. if err != nil {
  166. t.Fatalf("Unable to request new session: %v", err)
  167. }
  168. defer session.Close()
  169. if err := session.Shell(); err != nil {
  170. t.Fatalf("Unable to execute command: %v", err)
  171. }
  172. err = session.Wait()
  173. if err == nil {
  174. t.Fatalf("expected command to fail but it didn't")
  175. }
  176. e, ok := err.(*ExitError)
  177. if !ok {
  178. t.Fatalf("expected *ExitError but got %T", err)
  179. }
  180. if e.ExitStatus() != 15 {
  181. t.Fatalf("expected command to exit with 15 but got %v", e.ExitStatus())
  182. }
  183. }
  184. // Test 0 exit status is returned correctly.
  185. func TestExitStatusZero(t *testing.T) {
  186. conn := dial(exitStatusZeroHandler, t)
  187. defer conn.Close()
  188. session, err := conn.NewSession()
  189. if err != nil {
  190. t.Fatalf("Unable to request new session: %v", err)
  191. }
  192. defer session.Close()
  193. if err := session.Shell(); err != nil {
  194. t.Fatalf("Unable to execute command: %v", err)
  195. }
  196. err = session.Wait()
  197. if err != nil {
  198. t.Fatalf("expected nil but got %v", err)
  199. }
  200. }
  201. // Test exit signal and status are both returned correctly.
  202. func TestExitSignalAndStatus(t *testing.T) {
  203. conn := dial(exitSignalAndStatusHandler, t)
  204. defer conn.Close()
  205. session, err := conn.NewSession()
  206. if err != nil {
  207. t.Fatalf("Unable to request new session: %v", err)
  208. }
  209. defer session.Close()
  210. if err := session.Shell(); err != nil {
  211. t.Fatalf("Unable to execute command: %v", err)
  212. }
  213. err = session.Wait()
  214. if err == nil {
  215. t.Fatalf("expected command to fail but it didn't")
  216. }
  217. e, ok := err.(*ExitError)
  218. if !ok {
  219. t.Fatalf("expected *ExitError but got %T", err)
  220. }
  221. if e.Signal() != "TERM" || e.ExitStatus() != 15 {
  222. t.Fatalf("expected command to exit with signal TERM and status 15 but got signal %s and status %v", e.Signal(), e.ExitStatus())
  223. }
  224. }
  225. // Test exit signal and status are both returned correctly.
  226. func TestKnownExitSignalOnly(t *testing.T) {
  227. conn := dial(exitSignalHandler, t)
  228. defer conn.Close()
  229. session, err := conn.NewSession()
  230. if err != nil {
  231. t.Fatalf("Unable to request new session: %v", err)
  232. }
  233. defer session.Close()
  234. if err := session.Shell(); err != nil {
  235. t.Fatalf("Unable to execute command: %v", err)
  236. }
  237. err = session.Wait()
  238. if err == nil {
  239. t.Fatalf("expected command to fail but it didn't")
  240. }
  241. e, ok := err.(*ExitError)
  242. if !ok {
  243. t.Fatalf("expected *ExitError but got %T", err)
  244. }
  245. if e.Signal() != "TERM" || e.ExitStatus() != 143 {
  246. t.Fatalf("expected command to exit with signal TERM and status 143 but got signal %s and status %v", e.Signal(), e.ExitStatus())
  247. }
  248. }
  249. // Test exit signal and status are both returned correctly.
  250. func TestUnknownExitSignal(t *testing.T) {
  251. conn := dial(exitSignalUnknownHandler, t)
  252. defer conn.Close()
  253. session, err := conn.NewSession()
  254. if err != nil {
  255. t.Fatalf("Unable to request new session: %v", err)
  256. }
  257. defer session.Close()
  258. if err := session.Shell(); err != nil {
  259. t.Fatalf("Unable to execute command: %v", err)
  260. }
  261. err = session.Wait()
  262. if err == nil {
  263. t.Fatalf("expected command to fail but it didn't")
  264. }
  265. e, ok := err.(*ExitError)
  266. if !ok {
  267. t.Fatalf("expected *ExitError but got %T", err)
  268. }
  269. if e.Signal() != "SYS" || e.ExitStatus() != 128 {
  270. t.Fatalf("expected command to exit with signal SYS and status 128 but got signal %s and status %v", e.Signal(), e.ExitStatus())
  271. }
  272. }
  273. // Test WaitMsg is not returned if the channel closes abruptly.
  274. func TestExitWithoutStatusOrSignal(t *testing.T) {
  275. conn := dial(exitWithoutSignalOrStatus, t)
  276. defer conn.Close()
  277. session, err := conn.NewSession()
  278. if err != nil {
  279. t.Fatalf("Unable to request new session: %v", err)
  280. }
  281. defer session.Close()
  282. if err := session.Shell(); err != nil {
  283. t.Fatalf("Unable to execute command: %v", err)
  284. }
  285. err = session.Wait()
  286. if err == nil {
  287. t.Fatalf("expected command to fail but it didn't")
  288. }
  289. _, ok := err.(*ExitError)
  290. if ok {
  291. // you can't actually test for errors.errorString
  292. // because it's not exported.
  293. t.Fatalf("expected *errorString but got %T", 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.Fatalf("failed to copy origBuf to serverStdin: %v", err)
  333. }
  334. if written != windowTestBytes {
  335. t.Fatalf("Wrote only %d of %d bytes to server", written, windowTestBytes)
  336. }
  337. echoedBytes := <-result
  338. if !bytes.Equal(origBytes, echoedBytes) {
  339. t.Fatalf("Echoed buffer differed from original, orig %d, echoed %d", len(origBytes), len(echoedBytes))
  340. }
  341. }
  342. // Verify the client can handle a keepalive packet from the server.
  343. func TestClientHandlesKeepalives(t *testing.T) {
  344. conn := dial(channelKeepaliveSender, t)
  345. defer conn.Close()
  346. session, err := conn.NewSession()
  347. if err != nil {
  348. t.Fatal(err)
  349. }
  350. defer session.Close()
  351. if err := session.Shell(); err != nil {
  352. t.Fatalf("Unable to execute command: %v", err)
  353. }
  354. err = session.Wait()
  355. if err != nil {
  356. t.Fatalf("expected nil but got: %v", err)
  357. }
  358. }
  359. type exitStatusMsg struct {
  360. Status uint32
  361. }
  362. type exitSignalMsg struct {
  363. Signal string
  364. CoreDumped bool
  365. Errmsg string
  366. Lang string
  367. }
  368. func handleTerminalRequests(in <-chan *Request) {
  369. for req := range in {
  370. ok := false
  371. switch req.Type {
  372. case "shell":
  373. ok = true
  374. if len(req.Payload) > 0 {
  375. // We don't accept any commands, only the default shell.
  376. ok = false
  377. }
  378. case "env":
  379. ok = true
  380. }
  381. req.Reply(ok, nil)
  382. }
  383. }
  384. func newServerShell(ch Channel, in <-chan *Request, prompt string) *terminal.Terminal {
  385. term := terminal.NewTerminal(ch, prompt)
  386. go handleTerminalRequests(in)
  387. return term
  388. }
  389. func exitStatusZeroHandler(ch Channel, in <-chan *Request, t *testing.T) {
  390. defer ch.Close()
  391. // this string is returned to stdout
  392. shell := newServerShell(ch, in, "> ")
  393. readLine(shell, t)
  394. sendStatus(0, ch, t)
  395. }
  396. func exitStatusNonZeroHandler(ch Channel, in <-chan *Request, t *testing.T) {
  397. defer ch.Close()
  398. shell := newServerShell(ch, in, "> ")
  399. readLine(shell, t)
  400. sendStatus(15, ch, t)
  401. }
  402. func exitSignalAndStatusHandler(ch Channel, in <-chan *Request, t *testing.T) {
  403. defer ch.Close()
  404. shell := newServerShell(ch, in, "> ")
  405. readLine(shell, t)
  406. sendStatus(15, ch, t)
  407. sendSignal("TERM", ch, t)
  408. }
  409. func exitSignalHandler(ch Channel, in <-chan *Request, t *testing.T) {
  410. defer ch.Close()
  411. shell := newServerShell(ch, in, "> ")
  412. readLine(shell, t)
  413. sendSignal("TERM", ch, t)
  414. }
  415. func exitSignalUnknownHandler(ch Channel, in <-chan *Request, t *testing.T) {
  416. defer ch.Close()
  417. shell := newServerShell(ch, in, "> ")
  418. readLine(shell, t)
  419. sendSignal("SYS", ch, t)
  420. }
  421. func exitWithoutSignalOrStatus(ch Channel, in <-chan *Request, t *testing.T) {
  422. defer ch.Close()
  423. shell := newServerShell(ch, in, "> ")
  424. readLine(shell, t)
  425. }
  426. func shellHandler(ch Channel, in <-chan *Request, t *testing.T) {
  427. defer ch.Close()
  428. // this string is returned to stdout
  429. shell := newServerShell(ch, in, "golang")
  430. readLine(shell, t)
  431. sendStatus(0, ch, t)
  432. }
  433. // Ignores the command, writes fixed strings to stderr and stdout.
  434. // Strings are "this-is-stdout." and "this-is-stderr.".
  435. func fixedOutputHandler(ch Channel, in <-chan *Request, t *testing.T) {
  436. defer ch.Close()
  437. _, err := ch.Read(nil)
  438. req, ok := <-in
  439. if !ok {
  440. t.Fatalf("error: expected channel request, got: %#v", err)
  441. return
  442. }
  443. // ignore request, always send some text
  444. req.Reply(true, nil)
  445. _, err = io.WriteString(ch, "this-is-stdout.")
  446. if err != nil {
  447. t.Fatalf("error writing on server: %v", err)
  448. }
  449. _, err = io.WriteString(ch.Stderr(), "this-is-stderr.")
  450. if err != nil {
  451. t.Fatalf("error writing on server: %v", err)
  452. }
  453. sendStatus(0, ch, t)
  454. }
  455. func readLine(shell *terminal.Terminal, t *testing.T) {
  456. if _, err := shell.ReadLine(); err != nil && err != io.EOF {
  457. t.Errorf("unable to read line: %v", err)
  458. }
  459. }
  460. func sendStatus(status uint32, ch Channel, t *testing.T) {
  461. msg := exitStatusMsg{
  462. Status: status,
  463. }
  464. if _, err := ch.SendRequest("exit-status", false, Marshal(&msg)); err != nil {
  465. t.Errorf("unable to send status: %v", err)
  466. }
  467. }
  468. func sendSignal(signal string, ch Channel, t *testing.T) {
  469. sig := exitSignalMsg{
  470. Signal: signal,
  471. CoreDumped: false,
  472. Errmsg: "Process terminated",
  473. Lang: "en-GB-oed",
  474. }
  475. if _, err := ch.SendRequest("exit-signal", false, Marshal(&sig)); err != nil {
  476. t.Errorf("unable to send signal: %v", err)
  477. }
  478. }
  479. func discardHandler(ch Channel, t *testing.T) {
  480. defer ch.Close()
  481. io.Copy(ioutil.Discard, ch)
  482. }
  483. func echoHandler(ch Channel, in <-chan *Request, t *testing.T) {
  484. defer ch.Close()
  485. if n, err := copyNRandomly("echohandler", ch, ch, windowTestBytes); err != nil {
  486. t.Errorf("short write, wrote %d, expected %d: %v ", n, windowTestBytes, err)
  487. }
  488. }
  489. // copyNRandomly copies n bytes from src to dst. It uses a variable, and random,
  490. // buffer size to exercise more code paths.
  491. func copyNRandomly(title string, dst io.Writer, src io.Reader, n int) (int, error) {
  492. var (
  493. buf = make([]byte, 32*1024)
  494. written int
  495. remaining = n
  496. )
  497. for remaining > 0 {
  498. l := rand.Intn(1 << 15)
  499. if remaining < l {
  500. l = remaining
  501. }
  502. nr, er := src.Read(buf[:l])
  503. nw, ew := dst.Write(buf[:nr])
  504. remaining -= nw
  505. written += nw
  506. if ew != nil {
  507. return written, ew
  508. }
  509. if nr != nw {
  510. return written, io.ErrShortWrite
  511. }
  512. if er != nil && er != io.EOF {
  513. return written, er
  514. }
  515. }
  516. return written, nil
  517. }
  518. func channelKeepaliveSender(ch Channel, in <-chan *Request, t *testing.T) {
  519. defer ch.Close()
  520. shell := newServerShell(ch, in, "> ")
  521. readLine(shell, t)
  522. if _, err := ch.SendRequest("keepalive@openssh.com", true, nil); err != nil {
  523. t.Errorf("unable to send channel keepalive request: %v", err)
  524. }
  525. sendStatus(0, ch, t)
  526. }
  527. func TestClientWriteEOF(t *testing.T) {
  528. conn := dial(simpleEchoHandler, t)
  529. defer conn.Close()
  530. session, err := conn.NewSession()
  531. if err != nil {
  532. t.Fatal(err)
  533. }
  534. defer session.Close()
  535. stdin, err := session.StdinPipe()
  536. if err != nil {
  537. t.Fatalf("StdinPipe failed: %v", err)
  538. }
  539. stdout, err := session.StdoutPipe()
  540. if err != nil {
  541. t.Fatalf("StdoutPipe failed: %v", err)
  542. }
  543. data := []byte(`0000`)
  544. _, err = stdin.Write(data)
  545. if err != nil {
  546. t.Fatalf("Write failed: %v", err)
  547. }
  548. stdin.Close()
  549. res, err := ioutil.ReadAll(stdout)
  550. if err != nil {
  551. t.Fatalf("Read failed: %v", err)
  552. }
  553. if !bytes.Equal(data, res) {
  554. t.Fatalf("Read differed from write, wrote: %v, read: %v", data, res)
  555. }
  556. }
  557. func simpleEchoHandler(ch Channel, in <-chan *Request, t *testing.T) {
  558. defer ch.Close()
  559. data, err := ioutil.ReadAll(ch)
  560. if err != nil {
  561. t.Errorf("handler read error: %v", err)
  562. }
  563. _, err = ch.Write(data)
  564. if err != nil {
  565. t.Errorf("handler write error: %v", err)
  566. }
  567. }
  568. func TestSessionID(t *testing.T) {
  569. c1, c2, err := netPipe()
  570. if err != nil {
  571. t.Fatalf("netPipe: %v", err)
  572. }
  573. defer c1.Close()
  574. defer c2.Close()
  575. serverID := make(chan []byte, 1)
  576. clientID := make(chan []byte, 1)
  577. serverConf := &ServerConfig{
  578. NoClientAuth: true,
  579. }
  580. serverConf.AddHostKey(testSigners["ecdsa"])
  581. clientConf := &ClientConfig{
  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. connect(clientConf, KeyAlgoECDSA256)
  674. // Client asks for RSA explicitly.
  675. clientConf.HostKeyAlgorithms = []string{KeyAlgoRSA}
  676. connect(clientConf, KeyAlgoRSA)
  677. c1, c2, err := netPipe()
  678. if err != nil {
  679. t.Fatalf("netPipe: %v", err)
  680. }
  681. defer c1.Close()
  682. defer c2.Close()
  683. go NewServerConn(c1, serverConf)
  684. clientConf.HostKeyAlgorithms = []string{"nonexistent-hostkey-algo"}
  685. _, _, _, err = NewClientConn(c2, "", clientConf)
  686. if err == nil {
  687. t.Fatal("succeeded connecting with unknown hostkey algorithm")
  688. }
  689. }