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