session_test.go 15 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587
  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. "io"
  9. "io/ioutil"
  10. "net"
  11. "testing"
  12. "code.google.com/p/go.crypto/ssh/terminal"
  13. )
  14. type serverType func(*serverChan, *testing.T)
  15. // dial constructs a new test server and returns a *ClientConn.
  16. func dial(handler serverType, t *testing.T) *ClientConn {
  17. pw := password("tiger")
  18. serverConfig.PasswordCallback = func(conn *ServerConn, user, pass string) bool {
  19. return user == "testuser" && pass == string(pw)
  20. }
  21. serverConfig.PublicKeyCallback = nil
  22. l, err := Listen("tcp", "127.0.0.1:0", serverConfig)
  23. if err != nil {
  24. t.Fatalf("unable to listen: %v", err)
  25. }
  26. go func() {
  27. defer l.Close()
  28. conn, err := l.Accept()
  29. if err != nil {
  30. t.Errorf("Unable to accept: %v", err)
  31. return
  32. }
  33. defer conn.Close()
  34. if err := conn.Handshake(); err != nil {
  35. t.Errorf("Unable to handshake: %v", err)
  36. return
  37. }
  38. for {
  39. ch, err := conn.Accept()
  40. if err == io.EOF {
  41. return
  42. }
  43. // We sometimes get ECONNRESET rather than EOF.
  44. if _, ok := err.(*net.OpError); ok {
  45. return
  46. }
  47. if err != nil {
  48. t.Errorf("Unable to accept incoming channel request: %v", err)
  49. return
  50. }
  51. if ch.ChannelType() != "session" {
  52. ch.Reject(UnknownChannelType, "unknown channel type")
  53. continue
  54. }
  55. ch.Accept()
  56. go handler(ch.(*serverChan), t)
  57. }
  58. t.Log("done")
  59. }()
  60. config := &ClientConfig{
  61. User: "testuser",
  62. Auth: []ClientAuth{
  63. ClientAuthPassword(pw),
  64. },
  65. }
  66. c, err := Dial("tcp", l.Addr().String(), config)
  67. if err != nil {
  68. t.Fatalf("unable to dial remote side: %v", err)
  69. }
  70. return c
  71. }
  72. // Test a simple string is returned to session.Stdout.
  73. func TestSessionShell(t *testing.T) {
  74. conn := dial(shellHandler, t)
  75. defer conn.Close()
  76. session, err := conn.NewSession()
  77. if err != nil {
  78. t.Fatalf("Unable to request new session: %v", err)
  79. }
  80. defer session.Close()
  81. stdout := new(bytes.Buffer)
  82. session.Stdout = stdout
  83. if err := session.Shell(); err != nil {
  84. t.Fatalf("Unable to execute command: %s", err)
  85. }
  86. if err := session.Wait(); err != nil {
  87. t.Fatalf("Remote command did not exit cleanly: %v", err)
  88. }
  89. actual := stdout.String()
  90. if actual != "golang" {
  91. t.Fatalf("Remote shell did not return expected string: expected=golang, actual=%s", actual)
  92. }
  93. }
  94. // TODO(dfc) add support for Std{in,err}Pipe when the Server supports it.
  95. // Test a simple string is returned via StdoutPipe.
  96. func TestSessionStdoutPipe(t *testing.T) {
  97. conn := dial(shellHandler, t)
  98. defer conn.Close()
  99. session, err := conn.NewSession()
  100. if err != nil {
  101. t.Fatalf("Unable to request new session: %v", err)
  102. }
  103. defer session.Close()
  104. stdout, err := session.StdoutPipe()
  105. if err != nil {
  106. t.Fatalf("Unable to request StdoutPipe(): %v", err)
  107. }
  108. var buf bytes.Buffer
  109. if err := session.Shell(); err != nil {
  110. t.Fatalf("Unable to execute command: %v", err)
  111. }
  112. done := make(chan bool, 1)
  113. go func() {
  114. if _, err := io.Copy(&buf, stdout); err != nil {
  115. t.Errorf("Copy of stdout failed: %v", err)
  116. }
  117. done <- true
  118. }()
  119. if err := session.Wait(); err != nil {
  120. t.Fatalf("Remote command did not exit cleanly: %v", err)
  121. }
  122. <-done
  123. actual := buf.String()
  124. if actual != "golang" {
  125. t.Fatalf("Remote shell did not return expected string: expected=golang, actual=%s", actual)
  126. }
  127. }
  128. // Test non-0 exit status is returned correctly.
  129. func TestExitStatusNonZero(t *testing.T) {
  130. conn := dial(exitStatusNonZeroHandler, t)
  131. defer conn.Close()
  132. session, err := conn.NewSession()
  133. if err != nil {
  134. t.Fatalf("Unable to request new session: %v", err)
  135. }
  136. defer session.Close()
  137. if err := session.Shell(); err != nil {
  138. t.Fatalf("Unable to execute command: %v", err)
  139. }
  140. err = session.Wait()
  141. if err == nil {
  142. t.Fatalf("expected command to fail but it didn't")
  143. }
  144. e, ok := err.(*ExitError)
  145. if !ok {
  146. t.Fatalf("expected *ExitError but got %T", err)
  147. }
  148. if e.ExitStatus() != 15 {
  149. t.Fatalf("expected command to exit with 15 but got %v", e.ExitStatus())
  150. }
  151. }
  152. // Test 0 exit status is returned correctly.
  153. func TestExitStatusZero(t *testing.T) {
  154. conn := dial(exitStatusZeroHandler, t)
  155. defer conn.Close()
  156. session, err := conn.NewSession()
  157. if err != nil {
  158. t.Fatalf("Unable to request new session: %v", err)
  159. }
  160. defer session.Close()
  161. if err := session.Shell(); err != nil {
  162. t.Fatalf("Unable to execute command: %v", err)
  163. }
  164. err = session.Wait()
  165. if err != nil {
  166. t.Fatalf("expected nil but got %v", err)
  167. }
  168. }
  169. // Test exit signal and status are both returned correctly.
  170. func TestExitSignalAndStatus(t *testing.T) {
  171. conn := dial(exitSignalAndStatusHandler, t)
  172. defer conn.Close()
  173. session, err := conn.NewSession()
  174. if err != nil {
  175. t.Fatalf("Unable to request new session: %v", err)
  176. }
  177. defer session.Close()
  178. if err := session.Shell(); err != nil {
  179. t.Fatalf("Unable to execute command: %v", err)
  180. }
  181. err = session.Wait()
  182. if err == nil {
  183. t.Fatalf("expected command to fail but it didn't")
  184. }
  185. e, ok := err.(*ExitError)
  186. if !ok {
  187. t.Fatalf("expected *ExitError but got %T", err)
  188. }
  189. if e.Signal() != "TERM" || e.ExitStatus() != 15 {
  190. t.Fatalf("expected command to exit with signal TERM and status 15 but got signal %s and status %v", e.Signal(), e.ExitStatus())
  191. }
  192. }
  193. // Test exit signal and status are both returned correctly.
  194. func TestKnownExitSignalOnly(t *testing.T) {
  195. conn := dial(exitSignalHandler, t)
  196. defer conn.Close()
  197. session, err := conn.NewSession()
  198. if err != nil {
  199. t.Fatalf("Unable to request new session: %v", err)
  200. }
  201. defer session.Close()
  202. if err := session.Shell(); err != nil {
  203. t.Fatalf("Unable to execute command: %v", err)
  204. }
  205. err = session.Wait()
  206. if err == nil {
  207. t.Fatalf("expected command to fail but it didn't")
  208. }
  209. e, ok := err.(*ExitError)
  210. if !ok {
  211. t.Fatalf("expected *ExitError but got %T", err)
  212. }
  213. if e.Signal() != "TERM" || e.ExitStatus() != 143 {
  214. t.Fatalf("expected command to exit with signal TERM and status 143 but got signal %s and status %v", e.Signal(), e.ExitStatus())
  215. }
  216. }
  217. // Test exit signal and status are both returned correctly.
  218. func TestUnknownExitSignal(t *testing.T) {
  219. conn := dial(exitSignalUnknownHandler, t)
  220. defer conn.Close()
  221. session, err := conn.NewSession()
  222. if err != nil {
  223. t.Fatalf("Unable to request new session: %v", err)
  224. }
  225. defer session.Close()
  226. if err := session.Shell(); err != nil {
  227. t.Fatalf("Unable to execute command: %v", err)
  228. }
  229. err = session.Wait()
  230. if err == nil {
  231. t.Fatalf("expected command to fail but it didn't")
  232. }
  233. e, ok := err.(*ExitError)
  234. if !ok {
  235. t.Fatalf("expected *ExitError but got %T", err)
  236. }
  237. if e.Signal() != "SYS" || e.ExitStatus() != 128 {
  238. t.Fatalf("expected command to exit with signal SYS and status 128 but got signal %s and status %v", e.Signal(), e.ExitStatus())
  239. }
  240. }
  241. // Test WaitMsg is not returned if the channel closes abruptly.
  242. func TestExitWithoutStatusOrSignal(t *testing.T) {
  243. conn := dial(exitWithoutSignalOrStatus, t)
  244. defer conn.Close()
  245. session, err := conn.NewSession()
  246. if err != nil {
  247. t.Fatalf("Unable to request new session: %v", err)
  248. }
  249. defer session.Close()
  250. if err := session.Shell(); err != nil {
  251. t.Fatalf("Unable to execute command: %v", err)
  252. }
  253. err = session.Wait()
  254. if err == nil {
  255. t.Fatalf("expected command to fail but it didn't")
  256. }
  257. _, ok := err.(*ExitError)
  258. if ok {
  259. // you can't actually test for errors.errorString
  260. // because it's not exported.
  261. t.Fatalf("expected *errorString but got %T", err)
  262. }
  263. }
  264. func TestInvalidServerMessage(t *testing.T) {
  265. conn := dial(sendInvalidRecord, t)
  266. defer conn.Close()
  267. session, err := conn.NewSession()
  268. if err != nil {
  269. t.Fatalf("Unable to request new session: %v", err)
  270. }
  271. // Make sure that we closed all the clientChans when the connection
  272. // failed.
  273. session.wait()
  274. defer session.Close()
  275. }
  276. // In the wild some clients (and servers) send zero sized window updates.
  277. // Test that the client can continue after receiving a zero sized update.
  278. func TestClientZeroWindowAdjust(t *testing.T) {
  279. conn := dial(sendZeroWindowAdjust, t)
  280. defer conn.Close()
  281. session, err := conn.NewSession()
  282. if err != nil {
  283. t.Fatalf("Unable to request new session: %v", err)
  284. }
  285. defer session.Close()
  286. if err := session.Shell(); err != nil {
  287. t.Fatalf("Unable to execute command: %v", err)
  288. }
  289. err = session.Wait()
  290. if err != nil {
  291. t.Fatalf("expected nil but got %v", err)
  292. }
  293. }
  294. // In the wild some clients (and servers) send zero sized window updates.
  295. // Test that the server can continue after receiving a zero size update.
  296. func TestServerZeroWindowAdjust(t *testing.T) {
  297. conn := dial(exitStatusZeroHandler, t)
  298. defer conn.Close()
  299. session, err := conn.NewSession()
  300. if err != nil {
  301. t.Fatalf("Unable to request new session: %v", err)
  302. }
  303. defer session.Close()
  304. if err := session.Shell(); err != nil {
  305. t.Fatalf("Unable to execute command: %v", err)
  306. }
  307. // send a bogus zero sized window update
  308. session.clientChan.sendWindowAdj(0)
  309. err = session.Wait()
  310. if err != nil {
  311. t.Fatalf("expected nil but got %v", err)
  312. }
  313. }
  314. // Verify that the client never sends a packet larger than maxpacket.
  315. func TestClientStdinRespectsMaxPacketSize(t *testing.T) {
  316. conn := dial(discardHandler, t)
  317. defer conn.Close()
  318. session, err := conn.NewSession()
  319. if err != nil {
  320. t.Fatalf("Unable to request new session: %v", err)
  321. }
  322. defer session.Close()
  323. if err := session.Shell(); err != nil {
  324. t.Fatalf("Unable to execute command: %v", err)
  325. }
  326. // try to stuff 128k of data into a 32k hole.
  327. const size = 128 * 1024
  328. n, err := session.clientChan.stdin.Write(make([]byte, size))
  329. if n != size || err != nil {
  330. t.Fatalf("failed to write: %d, %v", n, err)
  331. }
  332. }
  333. // Verify that the client never accepts a packet larger than maxpacket.
  334. func TestServerStdoutRespectsMaxPacketSize(t *testing.T) {
  335. conn := dial(largeSendHandler, t)
  336. defer conn.Close()
  337. session, err := conn.NewSession()
  338. if err != nil {
  339. t.Fatalf("Unable to request new session: %v", err)
  340. }
  341. defer session.Close()
  342. out, err := session.StdoutPipe()
  343. if err != nil {
  344. t.Fatalf("Unable to connect to Stdout: %v", err)
  345. }
  346. if err := session.Shell(); err != nil {
  347. t.Fatalf("Unable to execute command: %v", err)
  348. }
  349. if _, err := ioutil.ReadAll(out); err != nil {
  350. t.Fatalf("failed to read: %v", err)
  351. }
  352. }
  353. func TestClientCannotSendAfterEOF(t *testing.T) {
  354. // TODO(dfc) currently writes succeed after Close()
  355. t.Logf("test skipped")
  356. return
  357. conn := dial(shellHandler, t)
  358. defer conn.Close()
  359. session, err := conn.NewSession()
  360. if err != nil {
  361. t.Fatalf("Unable to request new session: %v", err)
  362. }
  363. defer session.Close()
  364. in, err := session.StdinPipe()
  365. if err != nil {
  366. t.Fatalf("Unable to connect channel stdin: %v", err)
  367. }
  368. if err := session.Shell(); err != nil {
  369. t.Fatalf("Unable to execute command: %v", err)
  370. }
  371. if err := in.Close(); err != nil {
  372. t.Fatalf("Unable to close stdin: %v", err)
  373. }
  374. if _, err := in.Write([]byte("foo")); err == nil {
  375. t.Fatalf("Session write should fail")
  376. }
  377. }
  378. func TestClientCannotSendAfterClose(t *testing.T) {
  379. conn := dial(exitWithoutSignalOrStatus, t)
  380. defer conn.Close()
  381. session, err := conn.NewSession()
  382. if err != nil {
  383. t.Fatalf("Unable to request new session: %v", err)
  384. }
  385. defer session.Close()
  386. in, err := session.StdinPipe()
  387. if err != nil {
  388. t.Fatalf("Unable to connect channel stdin: %v", err)
  389. }
  390. if err := session.Shell(); err != nil {
  391. t.Fatalf("Unable to execute command: %v", err)
  392. }
  393. // close underlying channel
  394. if err := session.channel.Close(); err != nil {
  395. t.Fatalf("Unable to close session: %v", err)
  396. }
  397. if _, err := in.Write([]byte("foo")); err == nil {
  398. t.Fatalf("Session write should fail")
  399. }
  400. }
  401. type exitStatusMsg struct {
  402. PeersId uint32
  403. Request string
  404. WantReply bool
  405. Status uint32
  406. }
  407. type exitSignalMsg struct {
  408. PeersId uint32
  409. Request string
  410. WantReply bool
  411. Signal string
  412. CoreDumped bool
  413. Errmsg string
  414. Lang string
  415. }
  416. func newServerShell(ch *serverChan, prompt string) *ServerTerminal {
  417. term := terminal.NewTerminal(ch, prompt)
  418. return &ServerTerminal{
  419. Term: term,
  420. Channel: ch,
  421. }
  422. }
  423. func exitStatusZeroHandler(ch *serverChan, t *testing.T) {
  424. defer ch.Close()
  425. // this string is returned to stdout
  426. shell := newServerShell(ch, "> ")
  427. readLine(shell, t)
  428. sendStatus(0, ch, t)
  429. }
  430. func exitStatusNonZeroHandler(ch *serverChan, t *testing.T) {
  431. defer ch.Close()
  432. shell := newServerShell(ch, "> ")
  433. readLine(shell, t)
  434. sendStatus(15, ch, t)
  435. }
  436. func exitSignalAndStatusHandler(ch *serverChan, t *testing.T) {
  437. defer ch.Close()
  438. shell := newServerShell(ch, "> ")
  439. readLine(shell, t)
  440. sendStatus(15, ch, t)
  441. sendSignal("TERM", ch, t)
  442. }
  443. func exitSignalHandler(ch *serverChan, t *testing.T) {
  444. defer ch.Close()
  445. shell := newServerShell(ch, "> ")
  446. readLine(shell, t)
  447. sendSignal("TERM", ch, t)
  448. }
  449. func exitSignalUnknownHandler(ch *serverChan, t *testing.T) {
  450. defer ch.Close()
  451. shell := newServerShell(ch, "> ")
  452. readLine(shell, t)
  453. sendSignal("SYS", ch, t)
  454. }
  455. func exitWithoutSignalOrStatus(ch *serverChan, t *testing.T) {
  456. defer ch.Close()
  457. shell := newServerShell(ch, "> ")
  458. readLine(shell, t)
  459. }
  460. func shellHandler(ch *serverChan, t *testing.T) {
  461. defer ch.Close()
  462. // this string is returned to stdout
  463. shell := newServerShell(ch, "golang")
  464. readLine(shell, t)
  465. sendStatus(0, ch, t)
  466. }
  467. func readLine(shell *ServerTerminal, t *testing.T) {
  468. if _, err := shell.ReadLine(); err != nil && err != io.EOF {
  469. t.Fatalf("unable to read line: %v", err)
  470. }
  471. }
  472. func sendStatus(status uint32, ch *serverChan, t *testing.T) {
  473. msg := exitStatusMsg{
  474. PeersId: ch.remoteId,
  475. Request: "exit-status",
  476. WantReply: false,
  477. Status: status,
  478. }
  479. if err := ch.writePacket(marshal(msgChannelRequest, msg)); err != nil {
  480. t.Errorf("unable to send status: %v", err)
  481. }
  482. }
  483. func sendSignal(signal string, ch *serverChan, t *testing.T) {
  484. sig := exitSignalMsg{
  485. PeersId: ch.remoteId,
  486. Request: "exit-signal",
  487. WantReply: false,
  488. Signal: signal,
  489. CoreDumped: false,
  490. Errmsg: "Process terminated",
  491. Lang: "en-GB-oed",
  492. }
  493. if err := ch.writePacket(marshal(msgChannelRequest, sig)); err != nil {
  494. t.Errorf("unable to send signal: %v", err)
  495. }
  496. }
  497. func sendInvalidRecord(ch *serverChan, t *testing.T) {
  498. defer ch.Close()
  499. packet := make([]byte, 1+4+4+1)
  500. packet[0] = msgChannelData
  501. marshalUint32(packet[1:], 29348723 /* invalid channel id */)
  502. marshalUint32(packet[5:], 1)
  503. packet[9] = 42
  504. if err := ch.writePacket(packet); err != nil {
  505. t.Errorf("unable send invalid record: %v", err)
  506. }
  507. }
  508. func sendZeroWindowAdjust(ch *serverChan, t *testing.T) {
  509. defer ch.Close()
  510. // send a bogus zero sized window update
  511. ch.sendWindowAdj(0)
  512. shell := newServerShell(ch, "> ")
  513. readLine(shell, t)
  514. sendStatus(0, ch, t)
  515. }
  516. func discardHandler(ch *serverChan, t *testing.T) {
  517. defer ch.Close()
  518. // grow the window to avoid being fooled by
  519. // the initial 1 << 14 window.
  520. ch.sendWindowAdj(1024 * 1024)
  521. shell := newServerShell(ch, "> ")
  522. readLine(shell, t)
  523. io.Copy(ioutil.Discard, ch.serverConn)
  524. }
  525. func largeSendHandler(ch *serverChan, t *testing.T) {
  526. defer ch.Close()
  527. // grow the window to avoid being fooled by
  528. // the initial 1 << 14 window.
  529. ch.sendWindowAdj(1024 * 1024)
  530. shell := newServerShell(ch, "> ")
  531. readLine(shell, t)
  532. // try to send more than the 32k window
  533. // will allow
  534. if err := ch.writePacket(make([]byte, 128*1024)); err == nil {
  535. t.Errorf("wrote packet larger than 32k")
  536. }
  537. }