test_unix_test.go 9.3 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304
  1. // Copyright 2012 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. // +build darwin freebsd linux netbsd openbsd
  5. package test
  6. // functional test harness for unix.
  7. import (
  8. "bytes"
  9. "crypto"
  10. "crypto/dsa"
  11. "crypto/rsa"
  12. "crypto/x509"
  13. "encoding/pem"
  14. "errors"
  15. "io"
  16. "io/ioutil"
  17. "net"
  18. "os"
  19. "os/exec"
  20. "os/user"
  21. "path/filepath"
  22. "testing"
  23. "text/template"
  24. "time"
  25. "code.google.com/p/go.crypto/ssh"
  26. )
  27. const (
  28. sshd_config = `
  29. Protocol 2
  30. HostKey {{.Dir}}/ssh_host_rsa_key
  31. HostKey {{.Dir}}/ssh_host_dsa_key
  32. HostKey {{.Dir}}/ssh_host_ecdsa_key
  33. Pidfile {{.Dir}}/sshd.pid
  34. #UsePrivilegeSeparation no
  35. KeyRegenerationInterval 3600
  36. ServerKeyBits 768
  37. SyslogFacility AUTH
  38. LogLevel DEBUG2
  39. LoginGraceTime 120
  40. PermitRootLogin no
  41. StrictModes no
  42. RSAAuthentication yes
  43. PubkeyAuthentication yes
  44. AuthorizedKeysFile {{.Dir}}/authorized_keys
  45. IgnoreRhosts yes
  46. RhostsRSAAuthentication no
  47. HostbasedAuthentication no
  48. `
  49. testClientPrivateKey = `-----BEGIN RSA PRIVATE KEY-----
  50. MIIEowIBAAKCAQEAxF/3T7uD5rb4Cty2vc4qAhA6yclK+sRCCuz6/qy4MnXKlk1P
  51. 5Le8O4CozsOL784B34ypdPQlsr4G/suXQok5PTMSPnqxjYbN6cGqEvhGrwG2sAe4
  52. hKmMk3qd2GiSvuESeDl+2ZVzACDK0y/lFayvPbeeoQpBWGgIKN1WPs+q2/292wwW
  53. LRNWNrUuwt2ru92g4Hm/abCK0lfOrnCgU5eV+thZ2IshnfvsQpyweri8YpjOTil3
  54. y8yUDUv0MmcpNdoNw/MuvV8NRswkil9btfjEG6Mn9ByXBtq8lAix3XA1aaQKch8d
  55. ji6ud4ZZEP8sXX5Q6gqgBOI/naGoErCHwtU9kwIDAQABAoIBAFJRKAp0QEZmTHPB
  56. MZk+4r0asIoFpziXLFgIHu7C2DPOzK1Umzj1DCKlPB3wOqi7Ym2jOSWdcnAK2EPW
  57. dAGgJC5TSkKGjAcXixmB5RkumfKidUI0+lQh/puTurcMnvcEwglDkLkEvMBA/sSo
  58. Pw9m486rOgOnmNzGPyViItURmD2+0yDdLl/vOsO/L1p76GCd0q0J3LqnmsQmawi7
  59. Zwj2Stm6BIrggG5GsF204Iet5219TYLo4g1Qb2AlJ9C8P1FtAWhMwJalDxH9Os2/
  60. KCDjnaq5n3bXbIU+3QjskjeVXL/Fnbhjnh4zs1EA7eHzl9dCGbcZ2LOimo2PRo8q
  61. wVQmz4ECgYEA9dhiu74TxRVoaO5N2X+FsMzRO8gZdP3Z9IrV4jVN8WT4Vdp0snoF
  62. gkVkqqbQUNKUb5K6B3Js/qNKfcjLbCNq9fewTcT6WsHQdtPbX/QA6Pa2Z29wrlA2
  63. wrIYaAkmVaHny7wsOmgX01aOnuf2MlUnksK43sjZHdIo/m+sDKwwY1cCgYEAzHx4
  64. mwUDMdRF4qpDKJhthraBNejRextNQQYsHVnNaMwZ4aeQcH5l85Cgjm7VpGlbVyBQ
  65. h4zwFvllImp3D2U3mjVkV8Tm9ID98eWvw2YDzBnS3P3SysajD23Z+BXSG9GNv/8k
  66. oAm+bVlvnJy4haK2AcIMk1YFuDuAOmy73abk7iUCgYEAj4qVM1sq/eKfAM1LJRfg
  67. /jbIX+hYfMePD8pUUWygIra6jJ4tjtvSBZrwyPb3IImjY3W/KoP0AcVjxAeORohz
  68. dkP1a6L8LiuFxSuzpdW5BkyuebxGhXCOWKVVvMDC4jLTPVCUXlHSv3GFemCjjgXM
  69. QlNxT5rjsha4Gr8nLIsJAacCgYA4VA1Q/pd7sXKy1p37X8nD8yAyvnh+Be5I/C9I
  70. woUP2jFC9MqYAmmJJ4ziz2swiAkuPeuQ+2Tjnz2ZtmQnrIUdiJmkh8vrDGFnshKx
  71. q7deELsCPzVCwGcIiAUkDra7DQWUHu9y2lxHePyC0rUNst2aLF8UcvzOXC2danhx
  72. vViQtQKBgCmZ7YavE/GNWww8N3xHBJ6UPmUuhQlnAbgNCcdyz30MevBg/JbyUTs2
  73. slftTH15QusJ1UoITnnZuFJ40LqDvh8UhiK09ffM/IbUx839/m2vUOdFZB/WNn9g
  74. Cy0LzddU4KE8JZ/tlk68+hM5fjLLA0aqSunaql5CKfplwLu8x1hL
  75. -----END RSA PRIVATE KEY-----
  76. `
  77. )
  78. var keys = map[string]string{
  79. "ssh_host_dsa_key": `-----BEGIN DSA PRIVATE KEY-----
  80. MIIBugIBAAKBgQDe2SIKvZdBp+InawtSXH0NotiMPhm3udyu4hh/E+icMz264kDX
  81. v+sV7ddnSQGQWZ/eVU7Jtx29dCMD1VlFpEd7yGKzmdwJIeA+YquNWoqBRQEJsWWS
  82. 7Fsfvv83dA/DTNIQfOY3+TIs6Mb9vagbgQMU3JUWEhbLE9LCEU6UwwRlpQIVAL4p
  83. JF83SwpE8Jx6KnDpR89npkl/AoGAAy00TdDnAXvStwrZiAFbjZi8xDmPa9WwpfhJ
  84. Rkno45TthDLrS+WmqY8/LTwlqZdOBtoBAynMJfKkUiZM21lWWpL1hRKYdwBlIBy5
  85. XdR2/6wcPSuZ0tCQhDBTstX0Q3P1j198KGKvzy7q9vILKQwtSRqLS1y4JJERafdO
  86. E+9CnGwCgYBz0WwBe2EZtGhGhBdnelTIBeo7PIsr0PzqxQj+dc8PBl8K9FfhRyOp
  87. U39stUvoUxE9vaIFrY1P5xENjLFnPf+hlcuf40GUWEssW9YWPOaBp8afa9hY5Sxs
  88. pvNR6eZFEFOJnx/ZgcA4g+vbrgGi5cM0W470mbGw2CkfJQUafdoIgAIUF+2I9kZe
  89. 2FTBuC9uacqczDlc+0k=
  90. -----END DSA PRIVATE KEY-----`,
  91. "ssh_host_rsa_key": `-----BEGIN RSA PRIVATE KEY-----
  92. MIIEowIBAAKCAQEAuf76Ue2Wtae9oDtaS6rIJgO7iCFTsZUTW9LBsvx/2nli6jKU
  93. d9tUbBRzgdbnRLJ32UljXhERuB/axlrX8/lBzUZ+oYiM0KkEEOXY1z/bcMxdRxGF
  94. XHuf4uXvyC2XyA4+ZvBeS4j1QFyIHZ62o7gAlKMTjiek3B4AQEJAlCLmhH3jB8wc
  95. K/IYXAOlNGM5G44/ZLQpTi8diOV6DLs7tJ7rtEQedOEJfZng5rwp0USFkqcbfDbe
  96. 9/hk0J32jZvOtZNBokYtBb4YEdIiWBzzNtHzU3Dzw61+TKVXaH5HaIvzL9iMrw9f
  97. kJbJyogfZk9BJfemEN+xqP72jlhE8LXNhpTxFQIDAQABAoIBAHbdf+Y5+5XuNF6h
  98. b8xpwW2h9whBnDYiOnP1VfroKWFbMB7R4lZS4joMO+FfkP8zOyqvHwTvza4pFWys
  99. g9SUmDvy8FyVYsC7MzEFYzX0xm3o/Te898ip7P1Zy4rXsGeWysSImwqU5X+TYx3i
  100. 33/zyNM1APtZVJ+jwK9QZ+sD/uPuZK2yS03HGSMZq6ebdoOSaYhluKrxXllSLO1J
  101. KJxDiDdy2lEFw0W8HcI3ly1lg6OI+TRqqaCcLVNF4fNJmYIFM+2VEI9BdgynIh0Q
  102. pMZlJKgaEBcSqCymnTK81ohYD1cV4st2B0km3Sw35Rl04Ij5ITeiya3hp8VfE6UY
  103. PljkA6UCgYEA4811FTFj+kzNZ86C4OW1T5sM4NZt8gcz6CSvVnl+bDzbEOMMyzP7
  104. 2I9zKsR5ApdodH2m8d+RUw1Oe0bNGW5xig/DH/hn9lLQaO52JAi0we8A94dUUMSq
  105. fUk9jKZEXpP/MlfTdJaPos9mxT7z8jREQxIiqH9AV0rLVDOCfDbSWj8CgYEA0QTE
  106. IAUuki3UUqYKzLQrh/QmhY5KTx5amNW9XZ2VGtJvDPJrtBSBZlPEuXZAc4eBWEc7
  107. U3Y9QwsalzupU6Yi6+gmofaXs8xJnj+jKth1DnJvrbLLGlSmf2Ijnwt22TyFUOtt
  108. UAknpjHutDjQPf7pUGWaCPgwwKFsdB8EBjpJF6sCgYAfXesBQAvEK08dPBJJZVfR
  109. 3kenrd71tIgxLtv1zETcIoUHjjv0vvOunhH9kZAYC0EWyTZzl5UrGmn0D4uuNMbt
  110. e74iaNHn2P9Zc3xQ+eHp0j8P1lKFzI6tMaiH9Vz0qOw6wl0bcJ/WizhbcI+migvc
  111. MGMVUHBLlMDqly0gbWwJgQKBgQCgtb9ut01FjANSwORQ3L8Tu3/a9Lrh9n7GQKFn
  112. V4CLrP1BwStavOF5ojMCPo/zxF6JV8ufsqwL3n/FhFP/QyBarpb1tTqTPiHkkR2O
  113. Ffx67TY9IdnUFv4lt3mYEiKBiW0f+MSF42Qe/wmAfKZw5IzUCirTdrFVi0huSGK5
  114. vxrwHQKBgHZ7RoC3I2f6F5fflA2ZAe9oJYC7XT624rY7VeOBwK0W0F47iV3euPi/
  115. pKvLIBLcWL1Lboo+girnmSZtIYg2iLS3b4T9VFcKWg0y4AVwmhMWe9jWIltfWAAX
  116. 9l0lNikMRGAx3eXudKXEtbGt3/cUzPVaQUHy5LiBxkxnFxgaJPXs
  117. -----END RSA PRIVATE KEY-----`,
  118. "ssh_host_ecdsa_key": `-----BEGIN EC PRIVATE KEY-----
  119. MHcCAQEEINGWx0zo6fhJ/0EAfrPzVFyFC9s18lBt3cRoEDhS3ARooAoGCCqGSM49
  120. AwEHoUQDQgAEi9Hdw6KvZcWxfg2IDhA7UkpDtzzt6ZqJXSsFdLd+Kx4S3Sx4cVO+
  121. 6/ZOXRnPmNAlLUqjShUsUBBngG0u2fqEqA==
  122. -----END EC PRIVATE KEY-----`,
  123. "authorized_keys": `ssh-rsa AAAAB3NzaC1yc2EAAAADAQABAAABAQDEX/dPu4PmtvgK3La9zioCEDrJyUr6xEIK7Pr+rLgydcqWTU/kt7w7gKjOw4vvzgHfjKl09CWyvgb+y5dCiTk9MxI+erGNhs3pwaoS+EavAbawB7iEqYyTep3YaJK+4RJ4OX7ZlXMAIMrTL+UVrK89t56hCkFYaAgo3VY+z6rb/b3bDBYtE1Y2tS7C3au73aDgeb9psIrSV86ucKBTl5X62FnYiyGd++xCnLB6uLximM5OKXfLzJQNS/QyZyk12g3D8y69Xw1GzCSKX1u1+MQboyf0HJcG2ryUCLHdcDVppApyHx2OLq53hlkQ/yxdflDqCqAE4j+doagSsIfC1T2T user@host`,
  124. }
  125. var (
  126. configTmpl template.Template
  127. sshd string // path to sshd
  128. rsakey *rsa.PrivateKey
  129. )
  130. func init() {
  131. template.Must(configTmpl.Parse(sshd_config))
  132. block, _ := pem.Decode([]byte(testClientPrivateKey))
  133. rsakey, _ = x509.ParsePKCS1PrivateKey(block.Bytes)
  134. }
  135. type server struct {
  136. t *testing.T
  137. cleanup func() // executed during Shutdown
  138. configfile string
  139. cmd *exec.Cmd
  140. output bytes.Buffer // holds stderr from sshd process
  141. }
  142. func clientConfig() *ssh.ClientConfig {
  143. user, err := user.Current()
  144. if err != nil {
  145. panic(err)
  146. }
  147. kc := new(keychain)
  148. kc.keys = append(kc.keys, rsakey)
  149. config := &ssh.ClientConfig{
  150. User: user.Username,
  151. Auth: []ssh.ClientAuth{
  152. ssh.ClientAuthKeyring(kc),
  153. },
  154. }
  155. return config
  156. }
  157. func (s *server) Dial(config *ssh.ClientConfig) *ssh.ClientConn {
  158. s.cmd = exec.Command("sshd", "-f", s.configfile, "-i")
  159. stdin, err := s.cmd.StdinPipe()
  160. if err != nil {
  161. s.t.Fatal(err)
  162. }
  163. stdout, err := s.cmd.StdoutPipe()
  164. if err != nil {
  165. s.t.Fatal(err)
  166. }
  167. s.cmd.Stderr = os.Stderr // &s.output
  168. err = s.cmd.Start()
  169. if err != nil {
  170. s.t.FailNow()
  171. s.Shutdown()
  172. s.t.Fatal(err)
  173. }
  174. conn, err := ssh.Client(&client{stdin, stdout}, config)
  175. if err != nil {
  176. s.t.FailNow()
  177. s.Shutdown()
  178. s.t.Fatal(err)
  179. }
  180. return conn
  181. }
  182. func (s *server) Shutdown() {
  183. if err := s.cmd.Process.Kill(); err != nil {
  184. s.t.Error(err)
  185. }
  186. if s.t.Failed() {
  187. // log any output from sshd process
  188. s.t.Log(s.output.String())
  189. }
  190. s.cleanup()
  191. }
  192. // client wraps a pair of Reader/WriteClosers to implement the
  193. // net.Conn interface.
  194. type client struct {
  195. io.WriteCloser
  196. io.Reader
  197. }
  198. func (c *client) LocalAddr() net.Addr { return nil }
  199. func (c *client) RemoteAddr() net.Addr { return nil }
  200. func (c *client) SetDeadline(time.Time) error { return nil }
  201. func (c *client) SetReadDeadline(time.Time) error { return nil }
  202. func (c *client) SetWriteDeadline(time.Time) error { return nil }
  203. // newServer returns a new mock ssh server.
  204. func newServer(t *testing.T) *server {
  205. dir, err := ioutil.TempDir("", "sshtest")
  206. if err != nil {
  207. t.Fatal(err)
  208. }
  209. f, err := os.Create(filepath.Join(dir, "sshd_config"))
  210. if err != nil {
  211. t.Fatal(err)
  212. }
  213. err = configTmpl.Execute(f, map[string]string{
  214. "Dir": dir,
  215. })
  216. if err != nil {
  217. t.Fatal(err)
  218. }
  219. f.Close()
  220. for k, v := range keys {
  221. f, err := os.OpenFile(filepath.Join(dir, k), os.O_WRONLY|os.O_TRUNC|os.O_CREATE, 0600)
  222. if err != nil {
  223. t.Fatal(err)
  224. }
  225. if _, err := f.Write([]byte(v)); err != nil {
  226. t.Fatal(err)
  227. }
  228. f.Close()
  229. }
  230. return &server{
  231. t: t,
  232. configfile: f.Name(),
  233. cleanup: func() {
  234. if err := os.RemoveAll(dir); err != nil {
  235. t.Error(err)
  236. }
  237. },
  238. }
  239. }
  240. // keychain implements the ClientKeyring interface
  241. type keychain struct {
  242. keys []interface{}
  243. }
  244. func (k *keychain) Key(i int) (interface{}, error) {
  245. if i < 0 || i >= len(k.keys) {
  246. return nil, nil
  247. }
  248. switch key := k.keys[i].(type) {
  249. case *rsa.PrivateKey:
  250. return &key.PublicKey, nil
  251. case *dsa.PrivateKey:
  252. return &key.PublicKey, nil
  253. }
  254. panic("unknown key type")
  255. }
  256. func (k *keychain) Sign(i int, rand io.Reader, data []byte) (sig []byte, err error) {
  257. hashFunc := crypto.SHA1
  258. h := hashFunc.New()
  259. h.Write(data)
  260. digest := h.Sum(nil)
  261. switch key := k.keys[i].(type) {
  262. case *rsa.PrivateKey:
  263. return rsa.SignPKCS1v15(rand, key, hashFunc, digest)
  264. }
  265. return nil, errors.New("ssh: unknown key type")
  266. }
  267. func (k *keychain) loadPEM(file string) error {
  268. buf, err := ioutil.ReadFile(file)
  269. if err != nil {
  270. return err
  271. }
  272. block, _ := pem.Decode(buf)
  273. if block == nil {
  274. return errors.New("ssh: no key found")
  275. }
  276. r, err := x509.ParsePKCS1PrivateKey(block.Bytes)
  277. if err != nil {
  278. return err
  279. }
  280. k.keys = append(k.keys, r)
  281. return nil
  282. }