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,72 @@
1
+ require 'openssl'
2
+ require 'net/ssh/transport/identity_cipher'
3
+
4
+ module Net; module SSH; module Transport
5
+
6
+ # Implements a factory of OpenSSL cipher algorithms.
7
+ class CipherFactory
8
+ # Maps the SSH name of a cipher to it's corresponding OpenSSL name
9
+ SSH_TO_OSSL = {
10
+ "3des-cbc" => "des-ede3-cbc",
11
+ "blowfish-cbc" => "bf-cbc",
12
+ "aes256-cbc" => "aes-256-cbc",
13
+ "aes192-cbc" => "aes-192-cbc",
14
+ "aes128-cbc" => "aes-128-cbc",
15
+ "idea-cbc" => "idea-cbc",
16
+ "cast128-cbc" => "cast-cbc",
17
+ "rijndael-cbc@lysator.liu.se" => "aes-256-cbc",
18
+ "none" => "none"
19
+ }
20
+
21
+ # Retrieves a new instance of the named algorithm. The new instance
22
+ # will be initialized using an iv and key generated from the given
23
+ # iv, key, shared, hash and digester values. Additionally, the
24
+ # cipher will be put into encryption or decryption mode, based on the
25
+ # value of the +encrypt+ parameter.
26
+ def self.get(name, options={})
27
+ ossl_name = SSH_TO_OSSL[name] or raise NotImplementedError, "unimplemented cipher `#{name}'"
28
+ return IdentityCipher if ossl_name == "none"
29
+
30
+ cipher = OpenSSL::Cipher::Cipher.new(ossl_name)
31
+ cipher.send(options[:encrypt] ? :encrypt : :decrypt)
32
+
33
+ cipher.padding = 0
34
+ cipher.iv = make_key(cipher.iv_len, options[:iv], options)
35
+ cipher.key = make_key(cipher.key_len, options[:key], options)
36
+
37
+ return cipher
38
+ end
39
+
40
+ # Returns a two-element array containing the [ key-length,
41
+ # block-size ] for the named cipher algorithm. If the cipher
42
+ # algorithm is unknown, or is "none", 0 is returned for both elements
43
+ # of the tuple.
44
+ def self.get_lengths(name)
45
+ ossl_name = SSH_TO_OSSL[name]
46
+ return [0, 0] if ossl_name.nil? || ossl_name == "none"
47
+
48
+ cipher = OpenSSL::Cipher::Cipher.new(ossl_name)
49
+ return [cipher.key_len, cipher.block_size]
50
+ end
51
+
52
+ private
53
+
54
+ # Generate a key value in accordance with the SSH2 specification.
55
+ def self.make_key(bytes, start, options={})
56
+ k = start[0, bytes]
57
+
58
+ digester = options[:digester]
59
+ shared = options[:shared]
60
+ hash = options[:hash]
61
+
62
+ while k.length < bytes
63
+ step = digester.digest(shared + hash + k)
64
+ bytes_needed = bytes - k.length
65
+ k << step[0, bytes_needed]
66
+ end
67
+
68
+ return k
69
+ end
70
+ end
71
+
72
+ end; end; end
@@ -1,66 +1,30 @@
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
- #++
1
+ module Net; module SSH; module Transport
2
+ module Constants
16
3
 
17
- module Net
18
- module SSH
19
- module Transport
4
+ #--
5
+ # Transport layer generic messages
6
+ #++
20
7
 
21
- module Constants
8
+ DISCONNECT = 1
9
+ IGNORE = 2
10
+ UNIMPLEMENTED = 3
11
+ DEBUG = 4
12
+ SERVICE_REQUEST = 5
13
+ SERVICE_ACCEPT = 6
22
14
 
23
- # Transport layer generic messages
15
+ #--
16
+ # Algorithm negotiation messages
17
+ #++
24
18
 
25
- DISCONNECT = 1
26
- IGNORE = 2
27
- UNIMPLEMENTED = 3
28
- DEBUG = 4
29
- SERVICE_REQUEST = 5
30
- SERVICE_ACCEPT = 6
19
+ KEXINIT = 20
20
+ NEWKEYS = 21
31
21
 
32
- # Algorithm negotiation messages
22
+ #--
23
+ # Key exchange method specific messages
24
+ #++
33
25
 
34
- KEXINIT = 20
35
- NEWKEYS = 21
26
+ KEXDH_INIT = 30
27
+ KEXDH_REPLY = 31
36
28
 
37
- # Key exchange method specific messages
38
-
39
- KEXDH_INIT = 30
40
- KEXDH_REPLY = 31
41
-
42
- end
43
-
44
- module DisconnectReasons
45
-
46
- HOST_NOT_ALLOWED_TO_CONNECT = 1
47
- PROTOCOL_ERROR = 2
48
- KEY_EXCHANGE_FAILED = 3
49
- RESERVED = 4
50
- MAC_ERROR = 5
51
- COMPRESSION_ERROR = 6
52
- SERVICE_NOT_AVAILABLE = 7
53
- PROTOCOL_VERSION_NOT_SUPPORTED = 8
54
- HOST_KEY_NOT_VERIFIABLE = 9
55
- CONNECTION_LOST = 10
56
- BY_APPLICATION = 11
57
- TOO_MANY_CONNECTIONS = 12
58
- AUTH_CANCELLED_BY_USER = 13
59
- NO_MORE_AUTH_METHODS_AVAILABLE = 14
60
- ILLEGAL_USER_NAME = 15
61
-
62
- end
63
-
64
- end
65
29
  end
66
- end
30
+ end; end; end
@@ -0,0 +1,31 @@
1
+ require 'net/ssh/transport/hmac/md5'
2
+ require 'net/ssh/transport/hmac/md5_96'
3
+ require 'net/ssh/transport/hmac/sha1'
4
+ require 'net/ssh/transport/hmac/sha1_96'
5
+ require 'net/ssh/transport/hmac/none'
6
+
7
+ # Implements a simple factory interface for fetching hmac implementations, or
8
+ # for finding the key lengths for hmac implementations.s
9
+ module Net::SSH::Transport::HMAC
10
+ # The mapping of SSH hmac algorithms to their implementations
11
+ MAP = {
12
+ 'hmac-md5' => MD5,
13
+ 'hmac-md5-96' => MD5_96,
14
+ 'hmac-sha1' => SHA1,
15
+ 'hmac-sha1-96' => SHA1_96,
16
+ 'none' => None
17
+ }
18
+
19
+ # Retrieves a new hmac instance of the given SSH type (+name+). If +key+ is
20
+ # given, the new instance will be initialized with that key.
21
+ def self.get(name, key="")
22
+ impl = MAP[name] or raise ArgumentError, "hmac not found: #{name.inspect}"
23
+ impl.new(key)
24
+ end
25
+
26
+ # Retrieves the key length for the hmac of the given SSH type (+name+).
27
+ def self.key_length(name)
28
+ impl = MAP[name] or raise ArgumentError, "hmac not found: #{name.inspect}"
29
+ impl.key_length
30
+ end
31
+ end
@@ -0,0 +1,48 @@
1
+ require 'openssl'
2
+
3
+ module Net; module SSH; module Transport; module HMAC
4
+
5
+ # The base class of all OpenSSL-based HMAC algorithm wrappers.
6
+ class Abstract
7
+
8
+ class <<self
9
+ %w(key_length mac_length digest_class).each do |attribute|
10
+ define_method(attribute) do |*v|
11
+ # satisfy ruby -w
12
+ if !instance_variables.include?("@#{attribute}")
13
+ instance_variable_set("@#{attribute}", nil)
14
+ end
15
+
16
+ if v.empty?
17
+ v = instance_variable_get("@#{attribute}")
18
+ if v.nil? && superclass.respond_to?(attribute)
19
+ v = superclass.send(attribute)
20
+ instance_variable_set("@#{attribute}", v)
21
+ end
22
+ v
23
+ else
24
+ instance_variable_set("@#{attribute}", v.first)
25
+ end
26
+ end
27
+ end
28
+ end
29
+
30
+ %w(key_length mac_length digest_class).each do |attribute|
31
+ define_method(attribute) { self.class.send(attribute) }
32
+ end
33
+
34
+ # The key to use for this instance.
35
+ attr_accessor :key
36
+
37
+ def initialize(key=nil)
38
+ self.key = key
39
+ end
40
+
41
+ # Compute the HMAC digest for the given data string.
42
+ def digest(data)
43
+ OpenSSL::HMAC.digest(digest_class.new, key, data)[0,mac_length]
44
+ end
45
+
46
+ end
47
+
48
+ end; end; end; end
@@ -0,0 +1,12 @@
1
+ require 'net/ssh/transport/hmac/abstract'
2
+
3
+ module Net::SSH::Transport::HMAC
4
+
5
+ # The MD5 HMAC algorithm.
6
+ class MD5 < Abstract
7
+ mac_length 16
8
+ key_length 16
9
+ digest_class OpenSSL::Digest::MD5
10
+ end
11
+
12
+ end
@@ -0,0 +1,11 @@
1
+ require 'net/ssh/transport/hmac/md5'
2
+
3
+ module Net::SSH::Transport::HMAC
4
+
5
+ # The MD5-96 HMAC algorithm. This returns only the first 12 bytes of
6
+ # the digest.
7
+ class MD5_96 < MD5
8
+ mac_length 12
9
+ end
10
+
11
+ end
@@ -0,0 +1,15 @@
1
+ require 'net/ssh/transport/hmac/abstract'
2
+
3
+ module Net::SSH::Transport::HMAC
4
+
5
+ # The "none" algorithm. This has a key and mac length of 0.
6
+ class None < Abstract
7
+ key_length 0
8
+ mac_length 0
9
+
10
+ def digest(data)
11
+ ""
12
+ end
13
+ end
14
+
15
+ end
@@ -0,0 +1,13 @@
1
+ require 'net/ssh/transport/hmac/abstract'
2
+
3
+ module Net::SSH::Transport::HMAC
4
+
5
+ # The SHA1 HMAC algorithm. This has a mac and key length of 20, and
6
+ # uses the SHA1 digest algorithm.
7
+ class SHA1 < Abstract
8
+ mac_length 20
9
+ key_length 20
10
+ digest_class OpenSSL::Digest::SHA1
11
+ end
12
+
13
+ end
@@ -0,0 +1,11 @@
1
+ require 'net/ssh/transport/hmac/sha1'
2
+
3
+ module Net::SSH::Transport::HMAC
4
+
5
+ # The SHA1-96 HMAC algorithm. This returns only the first 12 bytes of
6
+ # the digest.
7
+ class SHA1_96 < SHA1
8
+ mac_length 12
9
+ end
10
+
11
+ end
@@ -0,0 +1,40 @@
1
+ module Net; module SSH; module Transport
2
+
3
+ # A cipher that does nothing but pass the data through, unchanged. This
4
+ # keeps things in the code nice and clean when a cipher has not yet been
5
+ # determined (i.e., during key exchange).
6
+ class IdentityCipher
7
+ class <<self
8
+ # A default block size of 8 is required by the SSH2 protocol.
9
+ def block_size
10
+ 8
11
+ end
12
+
13
+ # Does nothing. Returns self.
14
+ def encrypt
15
+ self
16
+ end
17
+
18
+ # Does nothing. Returns self.
19
+ def decrypt
20
+ self
21
+ end
22
+
23
+ # Passes its single argument through unchanged.
24
+ def update(text)
25
+ text
26
+ end
27
+
28
+ # Returns the empty string.
29
+ def final
30
+ ""
31
+ end
32
+
33
+ # The name of this cipher, which is "identity".
34
+ def name
35
+ "identity"
36
+ end
37
+ end
38
+ end
39
+
40
+ end; end; end
@@ -0,0 +1,13 @@
1
+ require 'net/ssh/transport/kex/diffie_hellman_group1_sha1'
2
+ require 'net/ssh/transport/kex/diffie_hellman_group_exchange_sha1'
3
+
4
+ module Net::SSH::Transport
5
+ module Kex
6
+ # Maps the supported key-exchange algorithms as named by the SSH protocol
7
+ # to their corresponding implementors.
8
+ MAP = {
9
+ 'diffie-hellman-group-exchange-sha1' => DiffieHellmanGroupExchangeSHA1,
10
+ 'diffie-hellman-group1-sha1' => DiffieHellmanGroup1SHA1
11
+ }
12
+ end
13
+ end
@@ -0,0 +1,208 @@
1
+ require 'net/ssh/buffer'
2
+ require 'net/ssh/errors'
3
+ require 'net/ssh/loggable'
4
+ require 'net/ssh/transport/openssl'
5
+ require 'net/ssh/transport/constants'
6
+
7
+ module Net; module SSH; module Transport; module Kex
8
+
9
+ # A key-exchange service implementing the "diffie-hellman-group1-sha1"
10
+ # key-exchange algorithm.
11
+ class DiffieHellmanGroup1SHA1
12
+ include Constants, Loggable
13
+
14
+ # The value of 'P', as a string, in hexadecimal
15
+ P_s = "FFFFFFFF" "FFFFFFFF" "C90FDAA2" "2168C234" +
16
+ "C4C6628B" "80DC1CD1" "29024E08" "8A67CC74" +
17
+ "020BBEA6" "3B139B22" "514A0879" "8E3404DD" +
18
+ "EF9519B3" "CD3A431B" "302B0A6D" "F25F1437" +
19
+ "4FE1356D" "6D51C245" "E485B576" "625E7EC6" +
20
+ "F44C42E9" "A637ED6B" "0BFF5CB6" "F406B7ED" +
21
+ "EE386BFB" "5A899FA5" "AE9F2411" "7C4B1FE6" +
22
+ "49286651" "ECE65381" "FFFFFFFF" "FFFFFFFF"
23
+
24
+ # The radix in which P_s represents the value of P
25
+ P_r = 16
26
+
27
+ # The group constant
28
+ G = 2
29
+
30
+ attr_reader :p
31
+ attr_reader :g
32
+ attr_reader :digester
33
+ attr_reader :algorithms
34
+ attr_reader :connection
35
+ attr_reader :data
36
+ attr_reader :dh
37
+
38
+ # Create a new instance of the DiffieHellmanGroup1SHA1 algorithm.
39
+ # The data is a Hash of symbols representing information
40
+ # required by this algorithm, which was acquired during earlier
41
+ # processing.
42
+ def initialize(algorithms, connection, data)
43
+ @p = OpenSSL::BN.new(P_s, P_r)
44
+ @g = G
45
+
46
+ @digester = OpenSSL::Digest::SHA1
47
+ @algorithms = algorithms
48
+ @connection = connection
49
+
50
+ @data = data.dup
51
+ @dh = generate_key
52
+ @logger = @data.delete(:logger)
53
+ end
54
+
55
+ # Perform the key-exchange for the given session, with the given
56
+ # data. This method will return a hash consisting of the
57
+ # following keys:
58
+ #
59
+ # * :session_id
60
+ # * :server_key
61
+ # * :shared_secret
62
+ # * :hashing_algorithm
63
+ #
64
+ # The caller is expected to be able to understand how to use these
65
+ # deliverables.
66
+ def exchange_keys
67
+ result = send_kexinit
68
+ verify_server_key(result[:server_key])
69
+ session_id = verify_signature(result)
70
+ confirm_newkeys
71
+
72
+ return { :session_id => session_id,
73
+ :server_key => result[:server_key],
74
+ :shared_secret => result[:shared_secret],
75
+ :hashing_algorithm => digester }
76
+ end
77
+
78
+ private
79
+
80
+ # Returns the DH key parameters for the current connection.
81
+ def get_parameters
82
+ [p, g]
83
+ end
84
+
85
+ # Returns the INIT/REPLY constants used by this algorithm.
86
+ def get_message_types
87
+ [KEXDH_INIT, KEXDH_REPLY]
88
+ end
89
+
90
+ # Build the signature buffer to use when verifying a signature from
91
+ # the server.
92
+ def build_signature_buffer(result)
93
+ response = Net::SSH::Buffer.new
94
+ response.write_string data[:client_version_string],
95
+ data[:server_version_string],
96
+ data[:client_algorithm_packet],
97
+ data[:server_algorithm_packet],
98
+ result[:key_blob]
99
+ response.write_bignum dh.pub_key,
100
+ result[:server_dh_pubkey],
101
+ result[:shared_secret]
102
+ response
103
+ end
104
+
105
+ # Generate a DH key with a private key consisting of the given
106
+ # number of bytes.
107
+ def generate_key #:nodoc:
108
+ dh = OpenSSL::PKey::DH.new
109
+
110
+ dh.p, dh.g = get_parameters
111
+ dh.priv_key = OpenSSL::BN.rand(data[:need_bytes] * 8)
112
+
113
+ dh.generate_key! until dh.valid?
114
+
115
+ dh
116
+ end
117
+
118
+ # Send the KEXDH_INIT message, and expect the KEXDH_REPLY. Return the
119
+ # resulting buffer.
120
+ #
121
+ # Parse the buffer from a KEXDH_REPLY message, returning a hash of
122
+ # the extracted values.
123
+ def send_kexinit #:nodoc:
124
+ init, reply = get_message_types
125
+
126
+ # send the KEXDH_INIT message
127
+ buffer = Net::SSH::Buffer.from(:byte, init, :bignum, dh.pub_key)
128
+ connection.send_message(buffer)
129
+
130
+ # expect the KEXDH_REPLY message
131
+ buffer = connection.next_message
132
+ raise Net::SSH::Exception, "expected REPLY" unless buffer.type == reply
133
+
134
+ result = Hash.new
135
+
136
+ result[:key_blob] = buffer.read_string
137
+ result[:server_key] = Net::SSH::Buffer.new(result[:key_blob]).read_key
138
+ result[:server_dh_pubkey] = buffer.read_bignum
139
+ result[:shared_secret] = OpenSSL::BN.new(dh.compute_key(result[:server_dh_pubkey]), 2)
140
+
141
+ sig_buffer = Net::SSH::Buffer.new(buffer.read_string)
142
+ sig_type = sig_buffer.read_string
143
+ if sig_type != algorithms.host_key
144
+ raise Net::SSH::Exception,
145
+ "host key algorithm mismatch for signature " +
146
+ "'#{sig_type}' != '#{algorithms.host_key}'"
147
+ end
148
+ result[:server_sig] = sig_buffer.read_string
149
+
150
+ return result
151
+ end
152
+
153
+ # Verify that the given key is of the expected type, and that it
154
+ # really is the key for the session's host. Raise Net::SSH::Exception
155
+ # if it is not.
156
+ def verify_server_key(key) #:nodoc:
157
+ if key.ssh_type != algorithms.host_key
158
+ raise Net::SSH::Exception,
159
+ "host key algorithm mismatch " +
160
+ "'#{key.ssh_type}' != '#{algorithms.host_key}'"
161
+ end
162
+
163
+ blob, fingerprint = generate_key_fingerprint(key)
164
+
165
+ unless connection.host_key_verifier.verify(:key => key, :key_blob => blob, :fingerprint => fingerprint, :session => connection)
166
+ raise Net::SSH::Exception, "host key verification failed"
167
+ end
168
+ end
169
+
170
+ def generate_key_fingerprint(key)
171
+ blob = Net::SSH::Buffer.from(:key, key).to_s
172
+ fingerprint = OpenSSL::Digest::MD5.hexdigest(blob).scan(/../).join(":")
173
+
174
+ [blob, fingerprint]
175
+ rescue ::Exception => e
176
+ [nil, "(could not generate fingerprint: #{e.message})"]
177
+ end
178
+
179
+ # Verify the signature that was received. Raise Net::SSH::Exception
180
+ # if the signature could not be verified. Otherwise, return the new
181
+ # session-id.
182
+ def verify_signature(result) #:nodoc:
183
+ response = build_signature_buffer(result)
184
+
185
+ hash = @digester.digest(response.to_s)
186
+
187
+ unless result[:server_key].ssh_do_verify(result[:server_sig], hash)
188
+ raise Net::SSH::Exception, "could not verify server signature"
189
+ end
190
+
191
+ return hash
192
+ end
193
+
194
+ # Send the NEWKEYS message, and expect the NEWKEYS message in
195
+ # reply.
196
+ def confirm_newkeys #:nodoc:
197
+ # send own NEWKEYS message first (the wodSSHServer won't send first)
198
+ response = Net::SSH::Buffer.new
199
+ response.write_byte(NEWKEYS)
200
+ connection.send_message(response)
201
+
202
+ # wait for the server's NEWKEYS message
203
+ buffer = connection.next_message
204
+ raise Net::SSH::Exception, "expected NEWKEYS" unless buffer.type == NEWKEYS
205
+ end
206
+ end
207
+
208
+ end; end; end; end