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
@@ -0,0 +1,77 @@
1
+ require 'net/ssh/errors'
2
+ require 'net/ssh/transport/constants'
3
+ require 'net/ssh/transport/kex/diffie_hellman_group1_sha1'
4
+
5
+ module Net::SSH::Transport::Kex
6
+
7
+ # A key-exchange service implementing the
8
+ # "diffie-hellman-group-exchange-sha1" key-exchange algorithm.
9
+ class DiffieHellmanGroupExchangeSHA1 < DiffieHellmanGroup1SHA1
10
+ MINIMUM_BITS = 1024
11
+ MAXIMUM_BITS = 8192
12
+
13
+ KEXDH_GEX_GROUP = 31
14
+ KEXDH_GEX_INIT = 32
15
+ KEXDH_GEX_REPLY = 33
16
+ KEXDH_GEX_REQUEST = 34
17
+
18
+ private
19
+
20
+ # Compute the number of bits needed for the given number of bytes.
21
+ def compute_need_bits
22
+ need_bits = data[:need_bytes] * 8
23
+ if need_bits < MINIMUM_BITS
24
+ need_bits = MINIMUM_BITS
25
+ elsif need_bits > MAXIMUM_BITS
26
+ need_bits = MAXIMUM_BITS
27
+ end
28
+
29
+ data[:need_bits ] = need_bits
30
+ data[:need_bytes] = need_bits / 8
31
+ end
32
+
33
+ # Returns the DH key parameters for the given session.
34
+ def get_parameters
35
+ compute_need_bits
36
+
37
+ # request the DH key parameters for the given number of bits.
38
+ buffer = Net::SSH::Buffer.from(:byte, KEXDH_GEX_REQUEST, :long, MINIMUM_BITS,
39
+ :long, data[:need_bits], :long, MAXIMUM_BITS)
40
+ connection.send_message(buffer)
41
+
42
+ buffer = connection.next_message
43
+ unless buffer.type == KEXDH_GEX_GROUP
44
+ raise Net::SSH::Exception, "expected KEXDH_GEX_GROUP, got #{buffer.type}"
45
+ end
46
+
47
+ p = buffer.read_bignum
48
+ g = buffer.read_bignum
49
+
50
+ [p, g]
51
+ end
52
+
53
+ # Returns the INIT/REPLY constants used by this algorithm.
54
+ def get_message_types
55
+ [KEXDH_GEX_INIT, KEXDH_GEX_REPLY]
56
+ end
57
+
58
+ # Build the signature buffer to use when verifying a signature from
59
+ # the server.
60
+ def build_signature_buffer(result)
61
+ response = Net::SSH::Buffer.new
62
+ response.write_string data[:client_version_string],
63
+ data[:server_version_string],
64
+ data[:client_algorithm_packet],
65
+ data[:server_algorithm_packet],
66
+ result[:key_blob]
67
+ response.write_long MINIMUM_BITS,
68
+ data[:need_bits],
69
+ MAXIMUM_BITS
70
+ response.write_bignum dh.p, dh.g, dh.pub_key,
71
+ result[:server_dh_pubkey],
72
+ result[:shared_secret]
73
+ response
74
+ end
75
+ end
76
+
77
+ end
@@ -1,22 +1,5 @@
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 'base64'
18
1
  require 'openssl'
19
- require 'net/ssh/util/buffer'
2
+ require 'net/ssh/buffer'
20
3
 
21
4
  module OpenSSL
22
5
 
@@ -29,13 +12,13 @@ module OpenSSL
29
12
  # required by the SSH2 protocol.
30
13
  def to_ssh
31
14
  if zero?
32
- return [ 0 ].pack( "N" )
15
+ return [0].pack("N")
33
16
  else
34
- buf = to_s( 2 )
17
+ buf = to_s(2)
35
18
  if buf[0][7] == 1
36
- return [ buf.length+1, 0, buf ].pack( "NCA*" )
19
+ return [buf.length+1, 0, buf].pack("NCA*")
37
20
  else
38
- return [ buf.length, buf ].pack( "NA*" )
21
+ return [buf.length, buf].pack("NA*")
39
22
  end
40
23
  end
41
24
  end
@@ -44,6 +27,12 @@ module OpenSSL
44
27
 
45
28
  module PKey
46
29
 
30
+ class PKey
31
+ def fingerprint
32
+ @fingerprint ||= OpenSSL::Digest::MD5.hexdigest(to_blob).scan(/../).join(":")
33
+ end
34
+ end
35
+
47
36
  # This class is originally defined in the OpenSSL module. As needed, methods
48
37
  # have been added to it by the Net::SSH module for convenience in dealing
49
38
  # with SSH functionality.
@@ -52,9 +41,9 @@ module OpenSSL
52
41
  # Determines whether the pub_key for this key is valid. (This algorithm
53
42
  # lifted more-or-less directly from OpenSSH, dh.c, dh_pub_is_valid.)
54
43
  def valid?
55
- return false if pub_key < 0
44
+ return false if pub_key.nil? || pub_key < 0
56
45
  bits_set = 0
57
- pub_key.num_bits.times { |i| bits_set += 1 if pub_key.bit_set? i }
46
+ pub_key.num_bits.times { |i| bits_set += 1 if pub_key.bit_set?(i) }
58
47
  return ( bits_set > 1 && pub_key < p )
59
48
  end
60
49
 
@@ -73,20 +62,17 @@ module OpenSSL
73
62
 
74
63
  # Converts the key to a blob, according to the SSH2 protocol.
75
64
  def to_blob
76
- buffer = Net::SSH::Util::WriterBuffer.new
77
- buffer.write_bignum( e )
78
- buffer.write_bignum( n )
79
- return buffer.to_s
65
+ @blob ||= Net::SSH::Buffer.from(:string, ssh_type, :bignum, e, :bignum, n).to_s
80
66
  end
81
67
 
82
68
  # Verifies the given signature matches the given data.
83
- def ssh_do_verify( sig, data )
84
- verify( OpenSSL::Digest::SHA1.new, sig, data )
69
+ def ssh_do_verify(sig, data)
70
+ verify(OpenSSL::Digest::SHA1.new, sig, data)
85
71
  end
86
72
 
87
73
  # Returns the signature for the given data.
88
- def ssh_do_sign( data )
89
- sign( OpenSSL::Digest::SHA1.new, data )
74
+ def ssh_do_sign(data)
75
+ sign(OpenSSL::Digest::SHA1.new, data)
90
76
  end
91
77
  end
92
78
 
@@ -103,16 +89,12 @@ module OpenSSL
103
89
 
104
90
  # Converts the key to a blob, according to the SSH2 protocol.
105
91
  def to_blob
106
- buffer = Net::SSH::Util::WriterBuffer.new
107
- buffer.write_bignum( p )
108
- buffer.write_bignum( q )
109
- buffer.write_bignum( g )
110
- buffer.write_bignum( pub_key )
111
- return buffer.to_s
92
+ @blob ||= Net::SSH::Buffer.from(:string, ssh_type,
93
+ :bignum, p, :bignum, q, :bignum, g, :bignum, pub_key).to_s
112
94
  end
113
95
 
114
96
  # Verifies the given signature matches the given data.
115
- def ssh_do_verify( sig, data )
97
+ def ssh_do_verify(sig, data)
116
98
  sig_r = sig[0,20].unpack("H*")[0].to_i(16)
117
99
  sig_s = sig[20,20].unpack("H*")[0].to_i(16)
118
100
  a1sig = OpenSSL::ASN1::Sequence([
@@ -123,7 +105,7 @@ module OpenSSL
123
105
  end
124
106
 
125
107
  # Signs the given data.
126
- def ssh_do_sign( data )
108
+ def ssh_do_sign(data)
127
109
  sig = sign( OpenSSL::Digest::DSS1.new, data)
128
110
  a1sig = OpenSSL::ASN1.decode( sig )
129
111
 
@@ -0,0 +1,230 @@
1
+ require 'net/ssh/buffered_io'
2
+ require 'net/ssh/errors'
3
+ require 'net/ssh/packet'
4
+ require 'net/ssh/transport/cipher_factory'
5
+ require 'net/ssh/transport/hmac'
6
+ require 'net/ssh/transport/state'
7
+
8
+ module Net; module SSH; module Transport
9
+
10
+ # A module that builds additional functionality onto the Net::SSH::BufferedIo
11
+ # module. It adds SSH encryption, compression, and packet validation, as
12
+ # per the SSH2 protocol. It also adds an abstraction for polling packets,
13
+ # to allow for both blocking and non-blocking reads.
14
+ module PacketStream
15
+ include BufferedIo
16
+
17
+ def self.extended(object)
18
+ object.__send__(:initialize_ssh)
19
+ end
20
+
21
+ # The map of "hints" that can be used to modify the behavior of the packet
22
+ # stream. For instance, when authentication succeeds, an "authenticated"
23
+ # hint is set, which is used to determine whether or not to compress the
24
+ # data when using the "delayed" compression algorithm.
25
+ attr_reader :hints
26
+
27
+ # The server state object, which encapsulates the algorithms used to interpret
28
+ # packets coming from the server.
29
+ attr_reader :server
30
+
31
+ # The client state object, which encapsulates the algorithms used to build
32
+ # packets to send to the server.
33
+ attr_reader :client
34
+
35
+ # The name of the client (local) end of the socket, as reported by the
36
+ # socket.
37
+ def client_name
38
+ @client_name ||= begin
39
+ sockaddr = getsockname
40
+ begin
41
+ Socket.getnameinfo(sockaddr, Socket::NI_NAMEREQD).first
42
+ rescue
43
+ begin
44
+ Socket.getnameinfo(sockaddr).first
45
+ rescue
46
+ begin
47
+ Socket.gethostbyname(Socket.gethostname).first
48
+ rescue
49
+ lwarn { "the client ipaddr/name could not be determined" }
50
+ "unknown"
51
+ end
52
+ end
53
+ end
54
+ end
55
+ end
56
+
57
+ # The IP address of the peer (remote) end of the socket, as reported by
58
+ # the socket.
59
+ def peer_ip
60
+ @peer_ip ||= begin
61
+ addr = getpeername
62
+ Socket.getnameinfo(addr, Socket::NI_NUMERICHOST | Socket::NI_NUMERICSERV).first
63
+ end
64
+ end
65
+
66
+ # Returns true if the IO is available for reading, and false otherwise.
67
+ def available_for_read?
68
+ result = IO.select([self], nil, nil, 0)
69
+ result && result.first.any?
70
+ end
71
+
72
+ # Returns the next full packet. If the mode parameter is :nonblock (the
73
+ # default), then this will return immediately, whether a packet is
74
+ # available or not, and will return nil if there is no packet ready to be
75
+ # returned. If the mode parameter is :block, then this method will block
76
+ # until a packet is available.
77
+ def next_packet(mode=:nonblock)
78
+ case mode
79
+ when :nonblock then
80
+ fill if available_for_read?
81
+ poll_next_packet
82
+
83
+ when :block then
84
+ loop do
85
+ packet = poll_next_packet
86
+ return packet if packet
87
+
88
+ loop do
89
+ result = IO.select([self]) or next
90
+ break if result.first.any?
91
+ end
92
+
93
+ if fill <= 0
94
+ raise Net::SSH::Disconnect, "connection closed by remote host"
95
+ end
96
+ end
97
+
98
+ else
99
+ raise ArgumentError, "expected :block or :nonblock, got #{mode.inspect}"
100
+ end
101
+ end
102
+
103
+ # Enqueues a packet to be sent, and blocks until the entire packet is
104
+ # sent.
105
+ def send_packet(payload)
106
+ enqueue_packet(payload)
107
+ wait_for_pending_sends
108
+ end
109
+
110
+ # Enqueues a packet to be sent, but does not immediately send the packet.
111
+ # The given payload is pre-processed according to the algorithms specified
112
+ # in the client state (compression, cipher, and hmac).
113
+ def enqueue_packet(payload)
114
+ # try to compress the packet
115
+ payload = client.compress(payload)
116
+
117
+ # the length of the packet, minus the padding
118
+ actual_length = 4 + payload.length + 1
119
+
120
+ # compute the padding length
121
+ padding_length = client.cipher.block_size - (actual_length % client.cipher.block_size)
122
+ padding_length += client.cipher.block_size if padding_length < 4
123
+
124
+ # compute the packet length (sans the length field itself)
125
+ packet_length = payload.length + padding_length + 1
126
+
127
+ if packet_length < 16
128
+ padding_length += client.cipher.block_size
129
+ packet_length = payload.length + padding_length + 1
130
+ end
131
+
132
+ padding = Array.new(padding_length) { rand(256) }.pack("C*")
133
+
134
+ unencrypted_data = [packet_length, padding_length, payload, padding].pack("NCA*A*")
135
+ mac = client.hmac.digest([client.sequence_number, unencrypted_data].pack("NA*"))
136
+
137
+ encrypted_data = client.cipher.update(unencrypted_data) << client.cipher.final
138
+ message = encrypted_data + mac
139
+
140
+ debug { "queueing packet nr #{client.sequence_number} type #{payload[0]} len #{packet_length}" }
141
+ enqueue(message)
142
+
143
+ client.increment(packet_length)
144
+
145
+ self
146
+ end
147
+
148
+ # Performs any pending cleanup necessary on the IO and its associated
149
+ # state objects. (See State#cleanup).
150
+ def cleanup
151
+ client.cleanup
152
+ server.cleanup
153
+ end
154
+
155
+ # If the IO object requires a rekey operation (as indicated by either its
156
+ # client or server state objects, see State#needs_rekey?), this will
157
+ # yield. Otherwise, this does nothing.
158
+ def if_needs_rekey?
159
+ if client.needs_rekey? || server.needs_rekey?
160
+ yield
161
+ client.reset! if client.needs_rekey?
162
+ server.reset! if server.needs_rekey?
163
+ end
164
+ end
165
+
166
+ protected
167
+
168
+ # Called when this module is used to extend an object. It initializes
169
+ # the states and generally prepares the object for use as a packet stream.
170
+ def initialize_ssh
171
+ @hints = {}
172
+ @server = State.new(self)
173
+ @client = State.new(self)
174
+ @packet = nil
175
+ initialize_buffered_io
176
+ end
177
+
178
+ # Tries to read the next packet. If there is insufficient data to read
179
+ # an entire packet, this returns immediately, otherwise the packet is
180
+ # read, post-processed according to the cipher, hmac, and compression
181
+ # algorithms specified in the server state object, and returned as a
182
+ # new Packet object.
183
+ def poll_next_packet
184
+ if @packet.nil?
185
+ minimum = server.cipher.block_size < 4 ? 4 : server.cipher.block_size
186
+ return nil if available < minimum
187
+ data = read_available(minimum)
188
+
189
+ # decipher it
190
+ @packet = Net::SSH::Buffer.new(server.cipher.update(data))
191
+ @packet_length = @packet.read_long
192
+ end
193
+
194
+ need = @packet_length + 4 - server.cipher.block_size
195
+ raise Net::SSH::Exception, "padding error, need #{need} block #{server.cipher.block_size}" if need % server.cipher.block_size != 0
196
+
197
+ return nil if available < need + server.hmac.mac_length
198
+
199
+ if need > 0
200
+ # read the remainder of the packet and decrypt it.
201
+ data = read_available(need)
202
+ @packet.append(server.cipher.update(data))
203
+ end
204
+
205
+ # get the hmac from the tail of the packet (if one exists), and
206
+ # then validate it.
207
+ real_hmac = read_available(server.hmac.mac_length) || ""
208
+
209
+ @packet.append(server.cipher.final)
210
+ padding_length = @packet.read_byte
211
+
212
+ payload = @packet.read(@packet_length - padding_length - 1)
213
+ padding = @packet.read(padding_length) if padding_length > 0
214
+
215
+ my_computed_hmac = server.hmac.digest([server.sequence_number, @packet.content].pack("NA*"))
216
+ raise Net::SSH::Exception, "corrupted mac detected" if real_hmac != my_computed_hmac
217
+
218
+ # try to decompress the payload, in case compression is active
219
+ payload = server.decompress(payload)
220
+
221
+ debug { "received packet nr #{server.sequence_number} type #{payload[0]} len #{@packet_length}" }
222
+
223
+ server.increment(@packet_length)
224
+ @packet = nil
225
+
226
+ return Packet.new(payload)
227
+ end
228
+ end
229
+
230
+ end; end; end
@@ -0,0 +1,61 @@
1
+ require 'net/ssh/errors'
2
+ require 'net/ssh/loggable'
3
+ require 'net/ssh/version'
4
+
5
+ module Net; module SSH; module Transport
6
+
7
+ # Negotiates the SSH protocol version and trades information about server
8
+ # and client. This is never used directly--it is always called by the
9
+ # transport layer as part of the initialization process of the transport
10
+ # layer.
11
+ #
12
+ # Note that this class also encapsulates the negotiated version, and acts as
13
+ # the authoritative reference for any queries regarding the version in effect.
14
+ class ServerVersion
15
+ include Loggable
16
+
17
+ # The SSH version string as reported by Net::SSH
18
+ PROTO_VERSION = "SSH-2.0-Ruby/Net::SSH_#{Net::SSH::Version::CURRENT} #{RUBY_PLATFORM}"
19
+
20
+ # Any header text sent by the server prior to sending the version.
21
+ attr_reader :header
22
+
23
+ # The version string reported by the server.
24
+ attr_reader :version
25
+
26
+ # Instantiates a new ServerVersion and immediately (and synchronously)
27
+ # negotiates the SSH protocol in effect, using the given socket.
28
+ def initialize(socket, logger)
29
+ @header = ""
30
+ @version = nil
31
+ @logger = logger
32
+ negotiate!(socket)
33
+ end
34
+
35
+ private
36
+
37
+ # Negotiates the SSH protocol to use, via the given socket. If the server
38
+ # reports an incompatible SSH version (e.g., SSH1), this will raise an
39
+ # exception.
40
+ def negotiate!(socket)
41
+ info { "negotiating protocol version" }
42
+
43
+ loop do
44
+ @version = socket.readline
45
+ break if @version.nil? || @version.match(/^SSH-/)
46
+ @header << @version
47
+ end
48
+
49
+ debug { "remote is #{@version.strip}" }
50
+
51
+ unless @version.match(/^SSH-(1\.99|2\.0)-/)
52
+ raise Net::SSH::Exception, "incompatible SSH version `#{@version}'"
53
+ end
54
+
55
+ @version.strip!
56
+
57
+ debug { "local is #{PROTO_VERSION}" }
58
+ socket.write "#{PROTO_VERSION}\r\n"
59
+ end
60
+ end
61
+ end; end; end