test_unix_test.go 9.1 KB

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