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,114 +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 'stringio'
18
-
19
- module Net
20
- module SSH
21
- module Service
22
- module Shell
23
-
24
- # A version of Shell::Shell that acts synchronously, allowing clients
25
- # to execute a command via a shell, wait for it to finish, and then
26
- # inspect both the stdout and stderr from the command, as well as the
27
- # exit status.
28
- class SyncShell
29
-
30
- # A struct representing the result of executing a command.
31
- CommandOutput = Struct.new( :stdout, :stderr, :status )
32
-
33
- # The unique confirmation string that is used to recognize the
34
- # end of a command's execution.
35
- CONFIRMATION = "2357foobarbazzabraboof7532"
36
-
37
- # Create a new SyncShell that uses the given +shell+ factory to obtain
38
- # a shell to wrap. The other parameters are used
39
- def initialize( shell, log, pty_opts )
40
- @log = log
41
- @shell = shell.call( pty_opts )
42
- end
43
-
44
- # Delegates to Shell::Shell.open?
45
- def open?
46
- @shell.open?
47
- end
48
-
49
- # Attempts to invoke the given command, which must not be
50
- # terminated with a newline. If +stdin+ is not nil, it will be sent
51
- # to the shell immediately after sending the request to execute the
52
- # command. It is expected that this will be used by the program that
53
- # was just executed somehow, but this is not (cannot) be enforced.
54
- def send_command( cmd, stdin=nil )
55
- @log.debug "executing #{cmd.inspect}" if @log.debug?
56
- send_data "#{cmd}; printf '%s %d' #{CONFIRMATION} $?\n"
57
- send_data stdin if stdin
58
-
59
- out = ""
60
- err = ""
61
-
62
- @log.debug "waiting for #{cmd.inspect}" if @log.debug?
63
- loop do
64
- sleep 0.01
65
- out << @shell.stdout while @shell.open? && @shell.stdout?
66
- err << @shell.stderr while @shell.open? && @shell.stderr?
67
-
68
- break if !@shell.open? || out.index( CONFIRMATION + " " )
69
- end
70
-
71
- if @log.debug?
72
- @log.debug "#{cmd.inspect} finished"
73
- @log.debug " stdout --> #{out.inspect}"
74
- @log.debug " stderr --> #{err.inspect}"
75
- end
76
-
77
- if @shell.open?
78
- match = out.match( /#{CONFIRMATION} /o )
79
- out = match.pre_match
80
- status = match.post_match.strip.to_i
81
- else
82
- status = 0
83
- end
84
-
85
- CommandOutput.new( out, ( err.empty? ? nil : err ), status )
86
- end
87
-
88
- # Sends the given string directly to the shell, without waiting for
89
- # any response.
90
- def send_data( data )
91
- @shell.send_data data
92
- end
93
-
94
- # Dends the given string directly to the shell as the given type of
95
- # data, without waiting for any response.
96
- def send_extended_data( type, data )
97
- @shell.send_extended_data type, data
98
- end
99
-
100
- # Reinterprets missing methods as requests to execute commands. The
101
- # parameters to the method are concatenated together with spaces
102
- # and sent to the shell via #send_command.
103
- def method_missing( sym, *args )
104
- cmd = sym.to_s
105
- cmd << " " << args.join( " " ) unless args.empty?
106
- send_command cmd
107
- end
108
-
109
- end
110
-
111
- end # SyncShell
112
- end # Service
113
- end # SSH
114
- end # Net
@@ -1,305 +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 'needle'
18
- require 'net/ssh/errors'
19
-
20
- module Net
21
- module SSH
22
-
23
- # Encapsulates a single session (connection) to a server via SSH.
24
- class Session
25
-
26
- # The dependency-injection registry used by this session.
27
- attr_reader :registry
28
-
29
- # The name of the host that this session is connected to.
30
- attr_reader :host
31
-
32
- # The hash of options that were used to establish this session.
33
- attr_reader :options
34
-
35
- # The underlying connection
36
- attr_reader :connection
37
-
38
- # Create a new SSH session. This method polymorphically accepts a
39
- # variable number of parameters, as follows:
40
- #
41
- # * 1 parameter: must be the hostname to connect to.
42
- # * 2 parameters: must be the hostname, and either the port (as an
43
- # integer) or the username to connect as.
44
- # * 3 parameters: must be the hostname, and either the port (as an
45
- # integer) and username, or the username and the password.
46
- # * 4 parameters: must be the hostname, port, username, and password.
47
- #
48
- # Any scenario above that omits the username assumes that the USER
49
- # environment variable is set to the user's name. Any scenario above that
50
- # omits the password assumes that the user will log in without a password
51
- # (ie, using a public key). Any scenario above that omits the port number
52
- # assumes a port number of 22 (the default for SSH).
53
- #
54
- # Any of the above scenarios may also accept a Hash as the last
55
- # parameter, specifying a list of additional options to be used to
56
- # initialize the session. (See Net::SSH::Session.add_options).
57
- #
58
- # Alternatively, named parameters may be used, in which case the first
59
- # parameter is positional and is always the host to connect to, following
60
- # which you may specify any of the following named parameters (as
61
- # symbols):
62
- #
63
- # * :port
64
- # * :username
65
- # * :password
66
- #
67
- # Any additional parameters are treated as options that configure how the
68
- # connection behaves.
69
- #
70
- # Allowed options are:
71
- #
72
- # * :keys (the list of filenames identifying the user's keys)
73
- # * :host_keys (the list of filenames identifying the host's keys)
74
- # * :auth_methods (a list of authentication methods to use)
75
- # * :crypto_backend (defaults to :ossl, and specifies the cryptography
76
- # backend to use)
77
- # * :registry_options (a hash of options to use when creating the
78
- # registry)
79
- # * :container (the registry to use. If not specified, a new registry
80
- # will be created)
81
- # * :verbose (how verbose the logging output should be. Defaults to
82
- # :warn).
83
- # * :log (the name of the file, or the IO object, to which messages will
84
- # be logged. Defaults to STDERR.)
85
- # * :forward_agent (true or false, whether or not to forward requests
86
- # for the authentication agent. Defaults to false.)
87
- # * :paranoid (either false, in which case server fingerprints are not
88
- # verified, true, in which case they are verified and mismatches result
89
- # in a warning and a prompt, or an object responding to :allow?, which
90
- # will be invoked and should return true or false for whether or not
91
- # to allow the connection. Defaults to true.)
92
- #
93
- # Also, any options recognized by Net::SSH::Transport::Session may be
94
- # given, and will be passed through to initialize the transport session.
95
- #
96
- # If a block is given to this method, then it is called with the new
97
- # session object. The session object is then closed when the block
98
- # terminates. If a block is not given, then the session object is
99
- # returned (and must be closed explicitly).
100
- def initialize( *args )
101
- @open = false
102
- @agent_forwarded = false
103
-
104
- process_arguments( *args )
105
-
106
- @registry.define do |b|
107
- b.crypto_backend { @crypto_backend }
108
- b.transport_host { @host }
109
- b.transport_options { @options }
110
-
111
- b.userauth_keys { @keys }
112
- b.userauth_host_keys { @host_keys }
113
- b.userauth_method_order { @auth_methods }
114
-
115
- b.host_key_verifier { @host_key_verifier }
116
-
117
- # Register myself with the registry, so that other services may
118
- # access me.
119
- b.session( :pipeline => [] ) { self }
120
-
121
- b.prompter do
122
- require 'net/ssh/util/prompter'
123
- Net::SSH::Util::Prompter.new
124
- end
125
-
126
- b.require 'net/ssh/transport/services', "Net::SSH::Transport"
127
- b.require 'net/ssh/connection/services', "Net::SSH::Connection"
128
- b.require 'net/ssh/userauth/services', "Net::SSH::UserAuth"
129
-
130
- b.require 'net/ssh/service/services', "Net::SSH::Service"
131
- end
132
-
133
- userauth = @registry[:userauth][:driver]
134
- if userauth.authenticate( "ssh-connection", @username, @password )
135
- @open = true
136
- @connection = @registry[:connection][:driver]
137
- if block_given?
138
- yield self
139
- close
140
- end
141
- else
142
- @registry[:transport][:session].close
143
- raise AuthenticationFailed, @username
144
- end
145
- end
146
-
147
- # Closes the session, if it is open. If it is not open, this does
148
- # nothing.
149
- def close
150
- @registry[:transport][:session].close if @open
151
- @open = false
152
- end
153
-
154
- # Returns +true+ if the session is currently open.
155
- def open?
156
- @open
157
- end
158
-
159
- # Opens a new communication channel over the current connection. This
160
- # returns immediately. The block will be invoked when then the channel
161
- # has been opened. (See Net::SSH::Connection::Driver#open_channel).
162
- def open_channel( type="session", data=nil, &block )
163
- sanity_check
164
- channel = @connection.open_channel( type, data )
165
- channel.on_confirm_open(&block)
166
-
167
- # If we have an agent, and agent-forwarding is enabled, set up
168
- # the forwarding. Do this once only, after the first channel
169
- # is opened.
170
- if @forward_agent && @registry[:userauth].agent
171
- unless @agent_forwarded
172
- agentforward.request
173
- @agent_forwarded = true
174
- end
175
- end
176
-
177
- channel
178
- end
179
-
180
- # Enters the main communication loop. This processes events occuring over
181
- # the channel. If a block is given, the loop will continue for as long
182
- # as the block returns +true+. Otherwise, the loop continues until there
183
- # are no more open channels. (See Net::SSH::Connection::Driver#loop).
184
- def loop( &block )
185
- sanity_check
186
- @connection.loop(&block)
187
- end
188
-
189
- # Provides convenient access to services that have been registered with
190
- # the session, such as "process" and "forward".
191
- #
192
- # Usage:
193
- #
194
- # session.forward.local(...)
195
- def method_missing( sym, *args, &block )
196
- if args.empty? && block.nil? && @registry[:services].has_key?( sym )
197
- return @registry[:services][ sym ]
198
- else
199
- super
200
- end
201
- end
202
-
203
- # Processes the argument list, determining the meaning of each argument
204
- # and allowing polymorphic argument lists. (See #initialize).
205
- def process_arguments( *args )
206
- @options = {}
207
- @username = ENV['USER'] || ENV['USERNAME']
208
-
209
- raise ArgumentError,
210
- "you must specify the host to connect to" if args.length < 1
211
-
212
- @host = args.shift
213
-
214
- # support for both named arguments, and positional arguments...
215
- if args.length == 1 && args[0].is_a?( Hash ) &&
216
- ( args[0][:username] || args[0][:password] ||
217
- args[0][:port] || args[0][:options] )
218
- # then
219
- @username = args[0][:username] || @username
220
- @password = args[0][:password]
221
-
222
- @options.update args.shift
223
- else
224
- @options[ :port ] = args.shift if args.first.is_a? Numeric
225
- if args.first.nil? || args.first.is_a?( String )
226
- @username = args.shift || @username
227
- end
228
- if args.first.nil? || args.first.is_a?( String )
229
- @password = args.shift
230
- end
231
- @options.update args.shift if args.first.is_a?( Hash )
232
- end
233
-
234
- if !args.empty?
235
- raise ArgumentError, "extra parameters detected: #{args.inspect}"
236
- elsif @username.nil?
237
- raise ArgumentError, "no username was given and none could be inferred from the environment"
238
- end
239
-
240
- @keys = @options[ :keys ]
241
- @host_keys = @options[ :host_keys ]
242
- @auth_methods = @options[ :auth_methods ]
243
- @forward_agent = @options[ :forward_agent ] || false
244
- @crypto_backend = @options.fetch( :crypto_backend, :ossl )
245
- @host_key_verifier = host_key_verifier_from(@options.fetch(:paranoid, true))
246
-
247
- verbose = @options.fetch( :verbose, :warn )
248
- log = @options.fetch( :log, STDERR )
249
-
250
- @registry_options = @options.fetch( :registry_options, {} )
251
-
252
- @registry_options[ :logs ] ||= {}
253
- @registry_options[ :logs ][ :default_level ] = verbose
254
-
255
- if log.is_a? IO
256
- @registry_options[ :logs ][ :device ] ||= log
257
- else
258
- @registry_options[ :logs ][ :filename ] ||= log
259
- end
260
-
261
- @registry = @options[ :container ] ||
262
- Needle::Registry.new( @registry_options )
263
-
264
- [ :keys, :host_keys, :auth_methods, :username, :password,
265
- :crypto_backend, :registry_options, :container, :log, :verbose,
266
- :forward_agent, :paranoid
267
- ].each do |i|
268
- @options.delete i
269
- end
270
-
271
- @options.freeze
272
- end
273
- private :process_arguments
274
-
275
- def host_key_verifier_from(paranoia)
276
- case paranoia
277
- when true then
278
- require 'net/ssh/lenient-host-key-verifier'
279
- Net::SSH::LenientHostKeyVerifier.new
280
- when false then
281
- require 'net/ssh/null-host-key-verifier'
282
- Net::SSH::NullHostKeyVerifier.new
283
- when :very then
284
- require 'net/ssh/host-key-verifier'
285
- Net::SSH::HostKeyVerifier.new
286
- else
287
- if paranoia.respond_to?(:verify)
288
- paranoia
289
- else
290
- raise ArgumentError, "argument to :paranoid is not valid: #{paranoia.inspect}"
291
- end
292
- end
293
- end
294
- private :host_key_verifier_from
295
-
296
- # Make sure we're in an acceptible state.
297
- def sanity_check
298
- raise Net::SSH::Exception, "session not open" unless @open
299
- end
300
- private :sanity_check
301
-
302
- end
303
-
304
- end
305
- end
@@ -1,275 +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 'net/ssh/errors'
18
- require 'net/ssh/transport/constants'
19
- require 'net/ssh/known-hosts'
20
-
21
- module Net
22
- module SSH
23
- module Transport
24
-
25
- # The AlgorithmNegotiator is used for negotiating the algorithms to be
26
- # employed for a specific SSH session.
27
- class AlgorithmNegotiator
28
- include Constants
29
-
30
- Algorithms = Struct.new( :server_packet,
31
- :client_packet,
32
- :kex,
33
- :host_key,
34
- :encryption_c2s,
35
- :encryption_s2c,
36
- :mac_c2s,
37
- :mac_s2c,
38
- :compression_c2s,
39
- :compression_s2c,
40
- :language_c2s,
41
- :language_s2c,
42
- :compression_level )
43
-
44
- # Create a new AlgorithmNegotiator instance, using the given logger,
45
- # set of default algorithms, and buffer factory.
46
- def initialize( logger, algorithms, buffers )
47
- @default_algorithms = algorithms
48
- @buffers = buffers
49
- @logger = logger
50
- end
51
-
52
- # Adds the algorithms of the specified type from +options+ to the
53
- # @algorithms hash. Also verifies that the specified algorithms are
54
- # supported.
55
- def prepare_preferred_algorithm( options, algorithm )
56
- @algorithms[ algorithm ] = @default_algorithms[ algorithm ].dup
57
- if options[algorithm]
58
- algos = [ *options[algorithm] ]
59
- algos.each do |algo|
60
- unless @algorithms[algorithm].include?(algo)
61
- raise NotImplementedError,
62
- "unsupported algorithm for #{algorithm.inspect}: #{algo}"
63
- end
64
- end
65
- @algorithms[ algorithm ].unshift( *algos ).uniq!
66
- end
67
- end
68
- private :prepare_preferred_algorithm
69
-
70
- # Builds the @algorithms hash from the values specified in the
71
- # +options+ hash.
72
- def prepare_preferred_algorithms( session, options )
73
- @algorithms = Hash.new
74
-
75
- if !options.key?(:host_key)
76
- keys = Net::SSH::KnownHosts.search_for(Net::SSH::KnownHosts.canonize(session.host, session.port))
77
- preferred_order = []
78
- preferred_order << keys.first.ssh_type if keys.any?
79
- options = options.merge(:host_key => preferred_order)
80
- end
81
-
82
- prepare_preferred_algorithm options, :host_key
83
- prepare_preferred_algorithm options, :kex
84
- prepare_preferred_algorithm options, :encryption
85
- prepare_preferred_algorithm options, :hmac
86
- prepare_preferred_algorithm options, :compression
87
- prepare_preferred_algorithm options, :languages
88
-
89
- @compression_level = options[ :compression_level ]
90
- end
91
- private :prepare_preferred_algorithms
92
-
93
- # looks for the first element in list1 that is also in list2
94
- def first_matching_element( list1, list2 )
95
- list1 = list1.split( /,/ ) if String === list1
96
- list2 = list2.split( /,/ ) if String === list2
97
-
98
- list1.each do |item|
99
- return item if list2.include? item
100
- end
101
-
102
- return nil
103
- end
104
- private :first_matching_element
105
-
106
- # Negotiate the supported algorithms with the server. If a compromise
107
- # cannot be reached between what the client wants and what the server
108
- # can provide, this will fail.
109
- def negotiate( session, options )
110
- prepare_preferred_algorithms session, options
111
-
112
- # first, discover what the server can do
113
- type, buffer = session.wait_for_message
114
- raise Net::SSH::Exception, "expected KEXINIT" unless type == KEXINIT
115
-
116
- server_algorithm_packet = buffer.content
117
-
118
- cookie = buffer.read( 16 )
119
- kex_algorithms = buffer.read_string
120
- server_host_key_algorithms = buffer.read_string
121
- encryption_algorithms_client_to_server = buffer.read_string
122
- encryption_algorithms_server_to_client = buffer.read_string
123
- mac_algorithms_client_to_server = buffer.read_string
124
- mac_algorithms_server_to_client = buffer.read_string
125
- compression_algorithms_client_to_server = buffer.read_string
126
- compression_algorithms_server_to_client = buffer.read_string
127
- languages_client_to_server = buffer.read_string
128
- languages_server_to_client = buffer.read_string
129
- first_kex_packet_follows = buffer.read_bool
130
- zero = buffer.read_long
131
-
132
- # TODO: if first_kex_packet_follows, we need to try to skip the
133
- # actual kexinit stuff and try to guess what the server is doing...
134
- # need to read more about this scenario.
135
-
136
- # next, tell the server what we can do
137
-
138
- my_kex = @algorithms[ :kex ].join( "," )
139
- my_server_host_key_algorithms = @algorithms[ :host_key ].join( "," )
140
- my_encryption_algorithms = @algorithms[ :encryption ].join( "," )
141
- my_mac_algorithms = @algorithms[ :hmac ].join( "," )
142
- my_compression_algorithms = @algorithms[ :compression ].join( "," )
143
- my_languages = @algorithms[ :languages ].join( "," )
144
-
145
- msg = @buffers.writer
146
- msg.write_byte KEXINIT
147
- msg.write_long rand(0xFFFFFFFF), rand(0xFFFFFFFF), rand(0xFFFFFFFF),
148
- rand(0xFFFFFFFF)
149
- msg.write_string my_kex, my_server_host_key_algorithms
150
- msg.write_string my_encryption_algorithms, my_encryption_algorithms
151
- msg.write_string my_mac_algorithms, my_mac_algorithms
152
- msg.write_string my_compression_algorithms, my_compression_algorithms
153
- msg.write_string my_languages, my_languages
154
- msg.write_bool false
155
- msg.write_long 0
156
-
157
- client_algorithm_packet = msg.to_s
158
- session.send_message msg
159
-
160
- # negotiate algorithms
161
-
162
- kex_algorithm = first_matching_element( @algorithms[ :kex ],
163
- kex_algorithms )
164
- raise Net::SSH::Exception,
165
- "could not settle on kex algorithm" unless kex_algorithm
166
- @logger.debug "kex algorithm: #{kex_algorithm}" if @logger.debug?
167
-
168
- host_key_algorithm = first_matching_element(
169
- @algorithms[ :host_key ], server_host_key_algorithms )
170
- raise Net::SSH::Exception,
171
- "could not settle on host key algorithm" unless host_key_algorithm
172
- if @logger.debug?
173
- @logger.debug "host key algorithm: #{host_key_algorithm}"
174
- end
175
-
176
- encryption_algorithm_c2s = first_matching_element(
177
- @algorithms[ :encryption ], encryption_algorithms_client_to_server )
178
- unless encryption_algorithm_c2s
179
- raise Net::SSH::Exception,
180
- "could not settle on client-to-server encryption algorithm"
181
- end
182
- if @logger.debug?
183
- @logger.debug "encryption algorithm (client-to-server): " +
184
- encryption_algorithm_c2s
185
- end
186
-
187
- encryption_algorithm_s2c = first_matching_element(
188
- @algorithms[ :encryption ], encryption_algorithms_server_to_client )
189
- unless encryption_algorithm_s2c
190
- raise Net::SSH::Exception,
191
- "could not settle on server-to-client encryption algorithm"
192
- end
193
- if @logger.debug?
194
- @logger.debug "encryption algorithm (server-to-client): " +
195
- encryption_algorithm_s2c
196
- end
197
-
198
- mac_algorithm_c2s = first_matching_element(
199
- @algorithms[ :hmac ], mac_algorithms_client_to_server )
200
- unless mac_algorithm_c2s
201
- raise Net::SSH::Exception,
202
- "could not settle on client-to-server HMAC algorithm"
203
- end
204
- if @logger.debug?
205
- @logger.debug "hmac algorithm (client-to-server): " +
206
- mac_algorithm_c2s
207
- end
208
-
209
- mac_algorithm_s2c = first_matching_element( @algorithms[ :hmac ],
210
- mac_algorithms_server_to_client )
211
- unless mac_algorithm_s2c
212
- raise Net::SSH::Exception,
213
- "could not settle on server-to-client HMAC algorithm"
214
- end
215
- if @logger.debug?
216
- @logger.debug "hmac algorithm (server-to-client): " +
217
- mac_algorithm_s2c
218
- end
219
-
220
- compression_algorithm_c2s = first_matching_element(
221
- @algorithms[ :compression ],
222
- compression_algorithms_client_to_server )
223
- unless compression_algorithm_c2s
224
- raise Net::SSH::Exception,
225
- "could not settle on client-to-server compression algorithm"
226
- end
227
- if @logger.debug?
228
- @logger.debug "compression algorithm (client-to-server): " +
229
- compression_algorithm_c2s
230
- end
231
-
232
- compression_algorithm_s2c = first_matching_element(
233
- @algorithms[ :compression ],
234
- compression_algorithms_server_to_client )
235
- unless compression_algorithm_s2c
236
- raise Net::SSH::Exception,
237
- "could not settle on server-to-client compression algorithm"
238
- end
239
- if @logger.debug?
240
- @logger.debug "compression algorithm (server-to-client): " +
241
- compression_algorithm_s2c
242
- end
243
-
244
- language_c2s = first_matching_element( @algorithms[ :languages ],
245
- languages_client_to_server ) || ""
246
- if @logger.debug?
247
- @logger.debug "language (client-to-server): #{language_c2s}"
248
- end
249
-
250
- language_s2c = first_matching_element( @algorithms[ :languages ],
251
- languages_server_to_client ) || ""
252
- if @logger.debug?
253
- @logger.debug "language (server-to-client): #{language_s2c}"
254
- end
255
-
256
- return Algorithms.new( server_algorithm_packet,
257
- client_algorithm_packet,
258
- kex_algorithm,
259
- host_key_algorithm,
260
- encryption_algorithm_c2s,
261
- encryption_algorithm_s2c,
262
- mac_algorithm_c2s,
263
- mac_algorithm_s2c,
264
- compression_algorithm_c2s,
265
- compression_algorithm_s2c,
266
- language_c2s,
267
- language_s2c,
268
- @compression_level )
269
- end
270
-
271
- end
272
-
273
- end
274
- end
275
- end