net-ssh 1.1.4 → 2.0.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (297) hide show
  1. data/CHANGELOG.rdoc +37 -0
  2. data/Manifest +101 -0
  3. data/README.rdoc +110 -0
  4. data/Rakefile +26 -0
  5. data/{THANKS → THANKS.rdoc} +2 -5
  6. data/lib/net/ssh.rb +189 -57
  7. data/lib/net/ssh/authentication/agent.rb +175 -0
  8. data/lib/net/ssh/authentication/constants.rb +18 -0
  9. data/lib/net/ssh/authentication/key_manager.rb +166 -0
  10. data/lib/net/ssh/authentication/methods/abstract.rb +60 -0
  11. data/lib/net/ssh/authentication/methods/hostbased.rb +71 -0
  12. data/lib/net/ssh/authentication/methods/keyboard_interactive.rb +66 -0
  13. data/lib/net/ssh/authentication/methods/password.rb +39 -0
  14. data/lib/net/ssh/authentication/methods/publickey.rb +92 -0
  15. data/lib/net/ssh/authentication/pageant.rb +176 -0
  16. data/lib/net/ssh/authentication/session.rb +116 -0
  17. data/lib/net/ssh/buffer.rb +339 -0
  18. data/lib/net/ssh/buffered_io.rb +149 -0
  19. data/lib/net/ssh/config.rb +173 -0
  20. data/lib/net/ssh/connection/channel.rb +575 -454
  21. data/lib/net/ssh/connection/constants.rb +31 -45
  22. data/lib/net/ssh/connection/session.rb +569 -0
  23. data/lib/net/ssh/connection/term.rb +176 -88
  24. data/lib/net/ssh/errors.rb +83 -61
  25. data/lib/net/ssh/key_factory.rb +85 -0
  26. data/lib/net/ssh/known_hosts.rb +129 -0
  27. data/lib/net/ssh/loggable.rb +61 -0
  28. data/lib/net/ssh/packet.rb +102 -0
  29. data/lib/net/ssh/prompt.rb +93 -0
  30. data/lib/net/ssh/proxy/errors.rb +8 -28
  31. data/lib/net/ssh/proxy/http.rb +75 -107
  32. data/lib/net/ssh/proxy/socks4.rb +35 -48
  33. data/lib/net/ssh/proxy/socks5.rb +76 -108
  34. data/lib/net/ssh/service/forward.rb +267 -0
  35. data/lib/net/ssh/test.rb +89 -0
  36. data/lib/net/ssh/test/channel.rb +129 -0
  37. data/lib/net/ssh/test/extensions.rb +152 -0
  38. data/lib/net/ssh/test/kex.rb +44 -0
  39. data/lib/net/ssh/test/local_packet.rb +51 -0
  40. data/lib/net/ssh/test/packet.rb +81 -0
  41. data/lib/net/ssh/test/remote_packet.rb +38 -0
  42. data/lib/net/ssh/test/script.rb +157 -0
  43. data/lib/net/ssh/test/socket.rb +59 -0
  44. data/lib/net/ssh/transport/algorithms.rb +384 -0
  45. data/lib/net/ssh/transport/cipher_factory.rb +72 -0
  46. data/lib/net/ssh/transport/constants.rb +22 -58
  47. data/lib/net/ssh/transport/hmac.rb +31 -0
  48. data/lib/net/ssh/transport/hmac/abstract.rb +48 -0
  49. data/lib/net/ssh/transport/hmac/md5.rb +12 -0
  50. data/lib/net/ssh/transport/hmac/md5_96.rb +11 -0
  51. data/lib/net/ssh/transport/hmac/none.rb +15 -0
  52. data/lib/net/ssh/transport/hmac/sha1.rb +13 -0
  53. data/lib/net/ssh/transport/hmac/sha1_96.rb +11 -0
  54. data/lib/net/ssh/transport/identity_cipher.rb +40 -0
  55. data/lib/net/ssh/transport/kex.rb +13 -0
  56. data/lib/net/ssh/transport/kex/diffie_hellman_group1_sha1.rb +208 -0
  57. data/lib/net/ssh/transport/kex/diffie_hellman_group_exchange_sha1.rb +77 -0
  58. data/lib/net/ssh/{util → transport}/openssl.rb +22 -40
  59. data/lib/net/ssh/transport/packet_stream.rb +230 -0
  60. data/lib/net/ssh/transport/server_version.rb +61 -0
  61. data/lib/net/ssh/transport/session.rb +225 -303
  62. data/lib/net/ssh/transport/state.rb +170 -0
  63. data/lib/net/ssh/verifiers/lenient.rb +30 -0
  64. data/lib/net/ssh/verifiers/null.rb +12 -0
  65. data/lib/net/ssh/verifiers/strict.rb +53 -0
  66. data/lib/net/ssh/version.rb +57 -26
  67. data/net-ssh.gemspec +54 -0
  68. data/setup.rb +1585 -0
  69. data/test/authentication/methods/common.rb +28 -0
  70. data/test/authentication/methods/test_abstract.rb +51 -0
  71. data/test/authentication/methods/test_hostbased.rb +108 -0
  72. data/test/authentication/methods/test_keyboard_interactive.rb +98 -0
  73. data/test/authentication/methods/test_password.rb +50 -0
  74. data/test/authentication/methods/test_publickey.rb +123 -0
  75. data/test/authentication/test_agent.rb +205 -0
  76. data/test/authentication/test_key_manager.rb +100 -0
  77. data/test/authentication/test_session.rb +93 -0
  78. data/test/common.rb +106 -0
  79. data/test/configs/exact_match +8 -0
  80. data/test/configs/wild_cards +14 -0
  81. data/test/connection/test_channel.rb +452 -0
  82. data/test/connection/test_session.rb +483 -0
  83. data/test/test_all.rb +6 -0
  84. data/test/test_buffer.rb +336 -0
  85. data/test/test_buffered_io.rb +63 -0
  86. data/test/test_config.rb +78 -0
  87. data/test/test_key_factory.rb +67 -0
  88. data/test/transport/hmac/test_md5.rb +34 -0
  89. data/test/transport/hmac/test_md5_96.rb +25 -0
  90. data/test/transport/hmac/test_none.rb +34 -0
  91. data/test/transport/hmac/test_sha1.rb +34 -0
  92. data/test/transport/hmac/test_sha1_96.rb +25 -0
  93. data/test/transport/kex/test_diffie_hellman_group1_sha1.rb +146 -0
  94. data/test/transport/kex/test_diffie_hellman_group_exchange_sha1.rb +92 -0
  95. data/test/transport/test_algorithms.rb +302 -0
  96. data/test/transport/test_cipher_factory.rb +163 -0
  97. data/test/transport/test_hmac.rb +34 -0
  98. data/test/transport/test_identity_cipher.rb +40 -0
  99. data/test/transport/test_packet_stream.rb +433 -0
  100. data/test/transport/test_server_version.rb +55 -0
  101. data/test/transport/test_session.rb +312 -0
  102. data/test/transport/test_state.rb +173 -0
  103. metadata +102 -253
  104. data/ChangeLog +0 -560
  105. data/LICENSE +0 -7
  106. data/NEWS +0 -152
  107. data/README +0 -14
  108. data/bin/rb-keygen +0 -210
  109. data/doc/LICENSE-BSD +0 -27
  110. data/doc/LICENSE-GPL +0 -280
  111. data/doc/LICENSE-RUBY +0 -56
  112. data/doc/manual-html/chapter-1.html +0 -388
  113. data/doc/manual-html/chapter-2.html +0 -552
  114. data/doc/manual-html/chapter-3.html +0 -470
  115. data/doc/manual-html/chapter-4.html +0 -413
  116. data/doc/manual-html/chapter-5.html +0 -525
  117. data/doc/manual-html/chapter-6.html +0 -456
  118. data/doc/manual-html/chapter-7.html +0 -343
  119. data/doc/manual-html/index.html +0 -235
  120. data/doc/manual-html/stylesheets/manual.css +0 -270
  121. data/doc/manual-html/stylesheets/ruby.css +0 -17
  122. data/doc/manual/chapter.erb +0 -38
  123. data/doc/manual/example.erb +0 -18
  124. data/doc/manual/index.erb +0 -29
  125. data/doc/manual/manual.rb +0 -311
  126. data/doc/manual/manual.yml +0 -73
  127. data/doc/manual/page.erb +0 -87
  128. data/doc/manual/parts/0000.txt +0 -5
  129. data/doc/manual/parts/0001.txt +0 -3
  130. data/doc/manual/parts/0002.txt +0 -40
  131. data/doc/manual/parts/0003.txt +0 -6
  132. data/doc/manual/parts/0004.txt +0 -7
  133. data/doc/manual/parts/0005.txt +0 -1
  134. data/doc/manual/parts/0006.txt +0 -49
  135. data/doc/manual/parts/0007.txt +0 -67
  136. data/doc/manual/parts/0008.txt +0 -43
  137. data/doc/manual/parts/0009.txt +0 -14
  138. data/doc/manual/parts/0010.txt +0 -7
  139. data/doc/manual/parts/0011.txt +0 -14
  140. data/doc/manual/parts/0012.txt +0 -3
  141. data/doc/manual/parts/0013.txt +0 -20
  142. data/doc/manual/parts/0014.txt +0 -32
  143. data/doc/manual/parts/0015.txt +0 -14
  144. data/doc/manual/parts/0016.txt +0 -28
  145. data/doc/manual/parts/0017.txt +0 -50
  146. data/doc/manual/parts/0018.txt +0 -35
  147. data/doc/manual/parts/0019.txt +0 -7
  148. data/doc/manual/parts/0020.txt +0 -72
  149. data/doc/manual/parts/0021.txt +0 -50
  150. data/doc/manual/parts/0022.txt +0 -42
  151. data/doc/manual/parts/0023.txt +0 -51
  152. data/doc/manual/parts/0024.txt +0 -18
  153. data/doc/manual/parts/0025.txt +0 -18
  154. data/doc/manual/parts/0026.txt +0 -15
  155. data/doc/manual/parts/0027.txt +0 -37
  156. data/doc/manual/parts/0028.txt +0 -16
  157. data/doc/manual/parts/0029.txt +0 -1
  158. data/doc/manual/parts/0030.txt +0 -52
  159. data/doc/manual/parts/0031.txt +0 -25
  160. data/doc/manual/stylesheets/manual.css +0 -270
  161. data/doc/manual/stylesheets/ruby.css +0 -17
  162. data/doc/manual/tutorial.erb +0 -30
  163. data/examples/auth-forward.rb +0 -41
  164. data/examples/channel-demo.rb +0 -81
  165. data/examples/port-forward.rb +0 -51
  166. data/examples/process-demo.rb +0 -91
  167. data/examples/remote-net-port-forward.rb +0 -45
  168. data/examples/remote-port-forward.rb +0 -80
  169. data/examples/shell-demo.rb +0 -46
  170. data/examples/ssh-client.rb +0 -67
  171. data/examples/sync-shell-demo.rb +0 -69
  172. data/examples/tail-demo.rb +0 -49
  173. data/lib/net/ssh/connection/driver.rb +0 -446
  174. data/lib/net/ssh/connection/services.rb +0 -72
  175. data/lib/net/ssh/host-key-verifier.rb +0 -52
  176. data/lib/net/ssh/known-hosts.rb +0 -96
  177. data/lib/net/ssh/lenient-host-key-verifier.rb +0 -25
  178. data/lib/net/ssh/null-host-key-verifier.rb +0 -14
  179. data/lib/net/ssh/service/agentforward/driver.rb +0 -78
  180. data/lib/net/ssh/service/agentforward/services.rb +0 -41
  181. data/lib/net/ssh/service/forward/driver.rb +0 -319
  182. data/lib/net/ssh/service/forward/local-network-handler.rb +0 -71
  183. data/lib/net/ssh/service/forward/remote-network-handler.rb +0 -83
  184. data/lib/net/ssh/service/forward/services.rb +0 -76
  185. data/lib/net/ssh/service/process/driver.rb +0 -153
  186. data/lib/net/ssh/service/process/open.rb +0 -193
  187. data/lib/net/ssh/service/process/popen3.rb +0 -178
  188. data/lib/net/ssh/service/process/services.rb +0 -66
  189. data/lib/net/ssh/service/services.rb +0 -60
  190. data/lib/net/ssh/service/shell/driver.rb +0 -86
  191. data/lib/net/ssh/service/shell/services.rb +0 -54
  192. data/lib/net/ssh/service/shell/shell.rb +0 -222
  193. data/lib/net/ssh/service/shell/sync.rb +0 -114
  194. data/lib/net/ssh/session.rb +0 -305
  195. data/lib/net/ssh/transport/algorithm-negotiator.rb +0 -275
  196. data/lib/net/ssh/transport/compress/compressor.rb +0 -53
  197. data/lib/net/ssh/transport/compress/decompressor.rb +0 -53
  198. data/lib/net/ssh/transport/compress/none-compressor.rb +0 -39
  199. data/lib/net/ssh/transport/compress/none-decompressor.rb +0 -39
  200. data/lib/net/ssh/transport/compress/services.rb +0 -68
  201. data/lib/net/ssh/transport/compress/zlib-compressor.rb +0 -60
  202. data/lib/net/ssh/transport/compress/zlib-decompressor.rb +0 -52
  203. data/lib/net/ssh/transport/errors.rb +0 -47
  204. data/lib/net/ssh/transport/identity-cipher.rb +0 -61
  205. data/lib/net/ssh/transport/kex/dh-gex.rb +0 -106
  206. data/lib/net/ssh/transport/kex/dh.rb +0 -249
  207. data/lib/net/ssh/transport/kex/services.rb +0 -62
  208. data/lib/net/ssh/transport/ossl/buffer-factory.rb +0 -52
  209. data/lib/net/ssh/transport/ossl/buffer.rb +0 -87
  210. data/lib/net/ssh/transport/ossl/cipher-factory.rb +0 -98
  211. data/lib/net/ssh/transport/ossl/digest-factory.rb +0 -51
  212. data/lib/net/ssh/transport/ossl/hmac-factory.rb +0 -71
  213. data/lib/net/ssh/transport/ossl/hmac/hmac.rb +0 -62
  214. data/lib/net/ssh/transport/ossl/hmac/md5-96.rb +0 -44
  215. data/lib/net/ssh/transport/ossl/hmac/md5.rb +0 -46
  216. data/lib/net/ssh/transport/ossl/hmac/none.rb +0 -46
  217. data/lib/net/ssh/transport/ossl/hmac/services.rb +0 -68
  218. data/lib/net/ssh/transport/ossl/hmac/sha1-96.rb +0 -44
  219. data/lib/net/ssh/transport/ossl/hmac/sha1.rb +0 -45
  220. data/lib/net/ssh/transport/ossl/key-factory.rb +0 -116
  221. data/lib/net/ssh/transport/ossl/services.rb +0 -149
  222. data/lib/net/ssh/transport/packet-stream.rb +0 -236
  223. data/lib/net/ssh/transport/services.rb +0 -146
  224. data/lib/net/ssh/transport/version-negotiator.rb +0 -73
  225. data/lib/net/ssh/userauth/agent.rb +0 -222
  226. data/lib/net/ssh/userauth/constants.rb +0 -35
  227. data/lib/net/ssh/userauth/driver.rb +0 -183
  228. data/lib/net/ssh/userauth/methods/hostbased.rb +0 -119
  229. data/lib/net/ssh/userauth/methods/keyboard-interactive.rb +0 -104
  230. data/lib/net/ssh/userauth/methods/password.rb +0 -70
  231. data/lib/net/ssh/userauth/methods/publickey.rb +0 -137
  232. data/lib/net/ssh/userauth/methods/services.rb +0 -90
  233. data/lib/net/ssh/userauth/pageant.rb +0 -197
  234. data/lib/net/ssh/userauth/services.rb +0 -141
  235. data/lib/net/ssh/userauth/userkeys.rb +0 -258
  236. data/lib/net/ssh/util/buffer.rb +0 -274
  237. data/lib/net/ssh/util/prompter.rb +0 -73
  238. data/test/ALL-TESTS.rb +0 -18
  239. data/test/connection/tc_channel.rb +0 -136
  240. data/test/connection/tc_driver.rb +0 -287
  241. data/test/connection/tc_integration.rb +0 -87
  242. data/test/proxy/tc_http.rb +0 -209
  243. data/test/proxy/tc_socks4.rb +0 -148
  244. data/test/proxy/tc_socks5.rb +0 -214
  245. data/test/service/agentforward/tc_driver.rb +0 -138
  246. data/test/service/forward/tc_driver.rb +0 -289
  247. data/test/service/forward/tc_local_network_handler.rb +0 -123
  248. data/test/service/forward/tc_remote_network_handler.rb +0 -111
  249. data/test/service/process/tc_driver.rb +0 -79
  250. data/test/service/process/tc_integration.rb +0 -119
  251. data/test/service/process/tc_open.rb +0 -179
  252. data/test/service/process/tc_popen3.rb +0 -164
  253. data/test/tc_integration.rb +0 -80
  254. data/test/transport/compress/tc_none_compress.rb +0 -41
  255. data/test/transport/compress/tc_none_decompress.rb +0 -45
  256. data/test/transport/compress/tc_zlib_compress.rb +0 -61
  257. data/test/transport/compress/tc_zlib_decompress.rb +0 -48
  258. data/test/transport/kex/tc_dh.rb +0 -312
  259. data/test/transport/kex/tc_dh_gex.rb +0 -71
  260. data/test/transport/ossl/fixtures/dsa-encrypted +0 -15
  261. data/test/transport/ossl/fixtures/dsa-encrypted-bad +0 -15
  262. data/test/transport/ossl/fixtures/dsa-unencrypted +0 -12
  263. data/test/transport/ossl/fixtures/dsa-unencrypted-bad +0 -12
  264. data/test/transport/ossl/fixtures/dsa-unencrypted.pub +0 -1
  265. data/test/transport/ossl/fixtures/not-a-private-key +0 -4
  266. data/test/transport/ossl/fixtures/not-supported +0 -2
  267. data/test/transport/ossl/fixtures/rsa-encrypted +0 -18
  268. data/test/transport/ossl/fixtures/rsa-encrypted-bad +0 -18
  269. data/test/transport/ossl/fixtures/rsa-unencrypted +0 -15
  270. data/test/transport/ossl/fixtures/rsa-unencrypted-bad +0 -15
  271. data/test/transport/ossl/fixtures/rsa-unencrypted.pub +0 -1
  272. data/test/transport/ossl/hmac/tc_hmac.rb +0 -58
  273. data/test/transport/ossl/hmac/tc_md5.rb +0 -50
  274. data/test/transport/ossl/hmac/tc_md5_96.rb +0 -50
  275. data/test/transport/ossl/hmac/tc_none.rb +0 -50
  276. data/test/transport/ossl/hmac/tc_sha1.rb +0 -50
  277. data/test/transport/ossl/hmac/tc_sha1_96.rb +0 -50
  278. data/test/transport/ossl/tc_buffer.rb +0 -97
  279. data/test/transport/ossl/tc_buffer_factory.rb +0 -67
  280. data/test/transport/ossl/tc_cipher_factory.rb +0 -84
  281. data/test/transport/ossl/tc_digest_factory.rb +0 -39
  282. data/test/transport/ossl/tc_hmac_factory.rb +0 -72
  283. data/test/transport/ossl/tc_key_factory.rb +0 -199
  284. data/test/transport/tc_algorithm_negotiator.rb +0 -170
  285. data/test/transport/tc_identity_cipher.rb +0 -52
  286. data/test/transport/tc_integration.rb +0 -115
  287. data/test/transport/tc_packet_stream.rb +0 -184
  288. data/test/transport/tc_session.rb +0 -296
  289. data/test/transport/tc_version_negotiator.rb +0 -86
  290. data/test/userauth/methods/tc_hostbased.rb +0 -136
  291. data/test/userauth/methods/tc_password.rb +0 -89
  292. data/test/userauth/methods/tc_publickey.rb +0 -167
  293. data/test/userauth/tc_agent.rb +0 -223
  294. data/test/userauth/tc_driver.rb +0 -190
  295. data/test/userauth/tc_integration.rb +0 -97
  296. data/test/userauth/tc_userkeys.rb +0 -265
  297. data/test/util/tc_buffer.rb +0 -217
@@ -1,69 +0,0 @@
1
- #--
2
- # =============================================================================
3
- # Copyright (c) 2004,2005 Jamis Buck (jamis@37signals.com)
4
- # All rights reserved.
5
- #
6
- # This source file is distributed as part of the Net::SSH Secure Shell Client
7
- # library for Ruby. This file (and the library as a whole) may be used only as
8
- # allowed by either the BSD license, or the Ruby license (or, by association
9
- # with the Ruby license, the GPL). See the "doc" subdirectory of the Net::SSH
10
- # distribution for the texts of these licenses.
11
- # -----------------------------------------------------------------------------
12
- # net-ssh website : http://net-ssh.rubyforge.org
13
- # project website: http://rubyforge.org/projects/net-ssh
14
- # =============================================================================
15
- #++
16
-
17
- $:.unshift "../lib"
18
- require 'net/ssh'
19
-
20
- Net::SSH.start( 'localhost' ) do |session|
21
-
22
- shell = session.shell.sync
23
-
24
- out = shell.pwd
25
- p out.stdout
26
-
27
- out = shell.cd "/"
28
-
29
- out = shell.pwd
30
- p out.stdout
31
-
32
- out = shell.test "-e foo"
33
- p out.status
34
-
35
- out = shell.ls "-laZ"
36
- p out.stderr
37
- p out.status
38
-
39
- out = shell.cd "/really/bogus/directory"
40
- p out.stderr
41
- p out.status
42
-
43
- out = shell.send_command "/sbin/ifconfig"
44
- p out.stdout
45
- p out.status
46
-
47
- out = shell.pwd
48
- p out.stdout
49
-
50
- out = shell.ruby "-v"
51
- p out.stdout
52
-
53
- out = shell.cd "/usr/lib"
54
-
55
- out = shell.pwd
56
- p out.stdout
57
-
58
- out = shell.send_command( "bc", <<CMD )
59
- 5+5
60
- 10*2
61
- scale=5
62
- 3/4
63
- quit
64
- CMD
65
- p out.stdout
66
-
67
- p shell.exit
68
-
69
- end
@@ -1,49 +0,0 @@
1
- #--
2
- # =============================================================================
3
- # Copyright (c) 2004,2005 Jamis Buck (jamis@37signals.com)
4
- # All rights reserved.
5
- #
6
- # This source file is distributed as part of the Net::SSH Secure Shell Client
7
- # library for Ruby. This file (and the library as a whole) may be used only as
8
- # allowed by either the BSD license, or the Ruby license (or, by association
9
- # with the Ruby license, the GPL). See the "doc" subdirectory of the Net::SSH
10
- # distribution for the texts of these licenses.
11
- # -----------------------------------------------------------------------------
12
- # net-ssh website : http://net-ssh.rubyforge.org
13
- # project website: http://rubyforge.org/projects/net-ssh
14
- # =============================================================================
15
- #++
16
-
17
- $:.unshift "../lib"
18
- require 'net/ssh'
19
-
20
- # This assumes three things:
21
- #
22
- # 1) That you have an SSH server running on your local machine,
23
- # 2) That the USER environment variable is set to your user name, and
24
- # 3) That you have public and private keys conigured so that you can log into
25
- # your machine via SSH without being prompted for a password.
26
- #
27
- # If #2 or #3 are not true, you can add your user-name and password as the
28
- # second and third parameters (respectively) to Net::SSH.start.
29
-
30
- Net::SSH.start( 'localhost' ) do |session|
31
-
32
- # Note: two things here,
33
- #
34
- # 1) open_channel does not immediately invoke the associated block. It only
35
- # calls the block after the server has confirmed that the channel is valid.
36
- # 2) channel.exec does not block--it just sends the request to the server and
37
- # returns.
38
- #
39
- # For these two reasons, you MUST call session.loop, so that packets get
40
- # processed and dispatched to the appropriate channel for handling.
41
-
42
- session.open_channel do |channel|
43
- channel.on_data { |chan,data| puts "--> #{data.inspect}" }
44
- channel.on_extended_data { |chan,type,data| print data }
45
- channel.exec "tail -f /tmp/mylog"
46
- end
47
-
48
- session.loop
49
- end
@@ -1,446 +0,0 @@
1
- #--
2
- # =============================================================================
3
- # Copyright (c) 2004,2005 Jamis Buck (jamis@37signals.com)
4
- # All rights reserved.
5
- #
6
- # This source file is distributed as part of the Net::SSH Secure Shell Client
7
- # library for Ruby. This file (and the library as a whole) may be used only as
8
- # allowed by either the BSD license, or the Ruby license (or, by association
9
- # with the Ruby license, the GPL). See the "doc" subdirectory of the Net::SSH
10
- # distribution for the texts of these licenses.
11
- # -----------------------------------------------------------------------------
12
- # net-ssh website : http://net-ssh.rubyforge.org
13
- # project website: http://rubyforge.org/projects/net-ssh
14
- # =============================================================================
15
- #++
16
-
17
- require 'thread'
18
- require 'net/ssh/connection/constants'
19
- require 'net/ssh/errors'
20
-
21
- module Net
22
- module SSH
23
- module Connection
24
-
25
- class Driver
26
- include Constants
27
-
28
- # A structure for representing global requests, as registered by the
29
- # #global_request method.
30
- Request = Struct.new( :type, :data, :callback )
31
-
32
- # A structure for representing a data buffer that must be sent
33
- # across a channel.
34
- DataRequest = Struct.new( :channel, :data, :type )
35
-
36
- #--
37
- # ====================================================================
38
- # CONSTRUCTOR
39
- # ====================================================================
40
- #++
41
-
42
- # Create a new connection driver that communicates over the given
43
- # transport session. +log+ is the logger instance to write log messages
44
- # to, buffers is a buffer factory, and channels is a factory that can
45
- # return new channel instances.
46
- def initialize( session, log, buffers, factories )
47
- @session = session
48
- @log = log
49
- @buffers = buffers
50
- @factories = factories
51
-
52
- @channel_id_mutex = Mutex.new
53
- @next_channel_id = 0
54
-
55
- @channel_map = Hash.new
56
- @request_queue = Array.new
57
- @channel_open_handlers = Hash.new
58
-
59
- @data_requests = Array.new
60
- @data_requests_mutex = Mutex.new
61
- end
62
-
63
- #--
64
- # ====================================================================
65
- # CHANNEL MANAGEMENT
66
- # ====================================================================
67
- #++
68
-
69
- # Open and return a new channel. This returns immediately, before the
70
- # server confirms that the channel was opened. When the server sends
71
- # the confirmation, the +on_confirm+ callback will be invoked.
72
- def open_channel( type, extra_data=nil, &on_confirm )
73
- channel = @factories[:open].call( type, extra_data )
74
- channel.on_confirm_open(&on_confirm)
75
- @channel_map[ channel.local_id ] = channel
76
- end
77
-
78
- # Remove the given channel from the connection.
79
- def remove_channel( channel )
80
- @channel_map.delete channel.local_id
81
- end
82
-
83
- # Returns an array of active channels.
84
- def channels
85
- @channel_map.values
86
- end
87
-
88
- # Add a callback to be invoked when a channel-open request is recieved
89
- # for a channel of the given type. The handler-id is returned.
90
- def add_channel_open_handler( type, &block )
91
- ( @channel_open_handlers[ type ] ||= Array.new ).push block
92
- @channel_open_handlers.length
93
- end
94
-
95
- # Remove a callback with the given id for channel-open requests of the
96
- # given type.
97
- def remove_channel_open_handler( type, id )
98
- @channel_open_handlers[ type ][ id-1 ] = nil
99
- end
100
-
101
- # Return the next available channel id for this connection. This
102
- # method is thread-safe.
103
- def allocate_channel_id
104
- @channel_id_mutex.synchronize do
105
- @next_channel_id += 1
106
- return @next_channel_id
107
- end
108
- end
109
-
110
- # Register a data buffer (of an optional type) to be sent across the
111
- # given channel at the next available opportunity.
112
- #
113
- # This is used internally by channels to hide the window size and
114
- # maximum packet size from the client. Clients should not call this
115
- # method directly.
116
- def register_data_request( channel, data, type=nil )
117
- @data_requests_mutex.synchronize do
118
- @data_requests << DataRequest.new( channel, data, type )
119
- end
120
-
121
- # make sure the new data request has a chance to be sent to the
122
- # server... Otherwise, it cannot be sent until the next time #process
123
- # is invoked, which can be unexpected in synchronous situations.
124
- process_data_requests
125
- end
126
-
127
- #--
128
- # ====================================================================
129
- # CONNECTION PROCESSING
130
- # ====================================================================
131
- #++
132
-
133
- # Repeated call #process for as long as the given block returns
134
- # +true+. If no block is given, then the loop continues until there
135
- # are no more open channels on this connection.
136
- def loop( &block )
137
- block ||= proc do
138
- channels = @channel_map.reject {|k,v| v.type == 'auth-agent@openssh.com' }
139
- not channels.empty?
140
- end
141
- process while block.call
142
- end
143
-
144
- # Wait for and dispatch a single event. If +nonblock+ is false (the
145
- # default) this will block until a message has been received. Otherwise,
146
- # it will return immediately.
147
- def process( nonblock=false )
148
- process_data_requests
149
-
150
- if !nonblock || reader_ready?
151
- type, response = @session.wait_for_message
152
-
153
- unless ( dispatcher = MESSAGES[ type ] )
154
- raise Net::SSH::Exception,
155
- "Unexpected response type '#{type}', (#{response.inspect})"
156
- end
157
-
158
- dispatcher[:method].bind( self ).call( response )
159
- end
160
-
161
- self
162
- end
163
-
164
- #--
165
- # ====================================================================
166
- # COMMUNICATION
167
- # ====================================================================
168
- #++
169
-
170
- # Send a global request packet to the server. This returns immediately.
171
- # The given block will be invoked when the server responds.
172
- def global_request( type, data=nil, &block )
173
- writer = @buffers.writer
174
- writer.write_byte GLOBAL_REQUEST
175
- writer.write_string type.to_s
176
- writer.write_bool true
177
- writer.write data.to_s if data
178
- @session.send_message writer
179
-
180
- @request_queue.push Request.new( type, data, block )
181
- self
182
- end
183
-
184
- # Send a channel request packet to the server.
185
- def channel_request( type )
186
- writer = @buffers.writer
187
- writer.write_byte CHANNEL_REQUEST
188
- writer.write_long 0 # channel id
189
- writer.write_string type
190
- writer.write_byte 0 # want_confirm
191
-
192
- @session.send_message writer
193
- end
194
-
195
- # A convenience method for sending messages.
196
- def send_message( msg )
197
- @session.send_message msg
198
- self
199
- end
200
-
201
- # Delegates to the #reader_ready method of the transport session.
202
- def reader_ready?
203
- @session.reader_ready?
204
- end
205
-
206
- # Sends an innocuous packet to the server to test the connection. Can
207
- # be used to defeat timeouts on long-running commands.
208
- def ping!
209
- @session.ping!
210
- end
211
-
212
- #--
213
- # ====================================================================
214
- # MESSAGE HANDLERS
215
- # ====================================================================
216
- #++
217
-
218
- def do_global_request( response )
219
- name = response.read_string
220
- want_reply = response.read_bool
221
- request_data = response.remainder_as_buffer
222
-
223
- @log.debug "GLOBAL_REQUEST received (#{name})" if @log.debug?
224
-
225
- if want_reply
226
- writer = @buffers.writer
227
- writer.write_byte REQUEST_SUCCESS
228
- @session.send_message writer
229
- end
230
- end
231
-
232
- def do_request_success( response )
233
- @log.debug "REQUEST_SUCCESS received" if @log.debug?
234
- process_request response, true
235
- end
236
-
237
- def do_request_failure( response )
238
- @log.debug "REQUEST_FAILURE received" if @log.debug?
239
- process_request response, false
240
- end
241
-
242
- def do_channel_open( response )
243
- ch_type = response.read_string
244
- @log.debug "CHANNEL_OPEN recieved (#{ch_type})" if @log.debug?
245
- handled = false
246
-
247
- sender_channel = response.read_long
248
- window_size = response.read_long
249
- packet_size = response.read_long
250
-
251
- channel = @factories[:create].call( ch_type, sender_channel,
252
- window_size, packet_size )
253
-
254
- ( @channel_open_handlers[ ch_type ] || [] ).each do |handler|
255
- next unless handler
256
- handled = true
257
- handler.call( self, channel, response )
258
- end
259
-
260
- unless handled
261
- raise Net::SSH::Exception,
262
- "cannot handle request to open a channel of type '#{ch_type}'"
263
- end
264
-
265
- @channel_map[channel.local_id] = channel
266
-
267
- writer = @buffers.writer
268
- writer.write_byte CHANNEL_OPEN_CONFIRMATION
269
- writer.write_long channel.remote_id
270
- writer.write_long channel.local_id
271
- writer.write_long 0x7FFFFFFF
272
- writer.write_long 0x7FFFFFFF
273
- @session.send_message writer
274
- end
275
-
276
- def do_channel_open_failure( response )
277
- local_id = response.read_long
278
- reason_code = response.read_long
279
- reason = response.read_string
280
- language = response.read_string
281
-
282
- @log.debug "CHANNEL_OPEN_FAILURE recieved (#{reason})" if @log.debug?
283
-
284
- channel = @channel_map[ local_id ]
285
- @channel_map.delete local_id
286
- channel.do_confirm_failed reason_code, reason, language
287
- end
288
-
289
- def do_channel_open_confirmation( response )
290
- local_id = response.read_long
291
- remote_id = response.read_long
292
- window_size = response.read_long
293
- packet_size = response.read_long
294
-
295
- if @log.debug?
296
- @log.debug "CHANNEL_OPEN_CONFIRMATION recieved (#{local_id})"
297
- end
298
-
299
- channel = @channel_map[ local_id ]
300
- channel.do_confirm_open remote_id, window_size, packet_size
301
- end
302
-
303
- def do_channel_window_adjust( response )
304
- local_id = response.read_long
305
- bytes_to_add = response.read_long
306
-
307
- if @log.debug?
308
- @log.debug "CHANNEL_WINDOW_ADJUST recieved " +
309
- "(#{local_id}:#{bytes_to_add})"
310
- end
311
-
312
- @channel_map[ local_id ].do_window_adjust( bytes_to_add )
313
- end
314
-
315
- def do_channel_data( response )
316
- local_id = response.read_long
317
- data = response.read_string
318
-
319
- if @log.debug?
320
- @log.debug "CHANNEL_DATA recieved (#{local_id}:#{data.inspect})"
321
- end
322
-
323
- @channel_map[ local_id ].do_data data
324
- end
325
-
326
- def do_channel_extended_data( response )
327
- local_id = response.read_long
328
- data_type = response.read_long
329
- data = response.read_string
330
-
331
- if @log.debug?
332
- @log.debug "CHANNEL_EXTENDED_DATA recieved " +
333
- "(#{local_id}:#{data_type}:#{data.inspect})"
334
- end
335
-
336
- @channel_map[ local_id ].do_extended_data data_type, data
337
- end
338
-
339
- def do_channel_eof( response )
340
- local_id = response.read_long
341
- @log.debug "CHANNEL_EOF recieved (#{local_id})" if @log.debug?
342
- @channel_map[ local_id ].do_eof
343
- end
344
-
345
- def do_channel_close( response )
346
- local_id = response.read_long
347
- @log.debug "CHANNEL_CLOSE recieved (#{local_id})" if @log.debug?
348
- @channel_map[ local_id ].close false
349
- end
350
-
351
- def do_channel_request( response )
352
- local_id = response.read_long
353
- request = response.read_string
354
- want_reply = response.read_bool
355
- request_data = response.remainder_as_buffer
356
-
357
- if @log.debug?
358
- @log.debug "CHANNEL_REQUEST recieved (#{local_id}:#{request})"
359
- end
360
-
361
- @channel_map[ local_id ].do_request request, want_reply, request_data
362
- end
363
-
364
- def do_channel_success( response )
365
- local_id = response.read_long
366
- @log.debug "CHANNEL_SUCCESS recieved (#{local_id})" if @log.debug?
367
- @channel_map[ local_id ].do_success
368
- end
369
-
370
- def do_channel_failure( response )
371
- local_id = response.read_long
372
- @log.debug "CHANNEL_FAILURE recieved (#{local_id})" if @log.debug?
373
- @channel_map[ local_id ].do_failure
374
- end
375
-
376
- #--
377
- # ====================================================================
378
- # INTERNAL STATE MANAGEMENT
379
- # ====================================================================
380
- private
381
- #++
382
-
383
- # Process a response recived from a "global_request".
384
- def process_request( response, success )
385
- request = @request_queue.shift
386
- request.callback.call( success, response ) if request.callback
387
- end
388
-
389
- # Process all pending data requests.
390
- def process_data_requests
391
- # guard against recursive calls
392
- return if @processing_data_requests
393
-
394
- # guard against simultaneous calls
395
- @data_requests_mutex.synchronize do
396
- begin
397
- @processing_data_requests = true
398
- @data_requests.map! do |req|
399
- while req && req.channel.window_size > 0
400
- remaining = if req.type
401
- req.channel.send_extended_data_packet( req.type, req.data )
402
- else
403
- req.channel.send_data_packet( req.data )
404
- end
405
- if remaining
406
- req.data = remaining
407
- else
408
- req = nil
409
- end
410
- end
411
-
412
- req
413
- end
414
- @data_requests.compact!
415
- ensure
416
- @processing_data_requests = false
417
- end
418
- end
419
- end
420
-
421
- #--
422
- # ====================================================================
423
- # MESSAGE DISPATCHER SETUP
424
- # ====================================================================
425
- #++
426
-
427
- MESSAGES = %w(
428
- global_request
429
- request_success request_failure channel_open channel_open_failure
430
- channel_open_confirmation channel_window_adjust channel_data
431
- channel_extended_data channel_eof channel_close channel_request
432
- channel_success channel_failure
433
- ).inject({}) do |map, event|
434
- constant = Constants.const_get event.upcase.to_sym
435
- map[constant] = {
436
- :name => event.to_sym,
437
- :method => instance_method( "do_#{event}".to_sym )
438
- }
439
- map
440
- end
441
-
442
- end
443
-
444
- end
445
- end
446
- end