net-ssh 3.2.0 → 7.2.0.rc1

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 (210) hide show
  1. checksums.yaml +5 -5
  2. checksums.yaml.gz.sig +0 -0
  3. data/.dockerignore +6 -0
  4. data/.github/FUNDING.yml +1 -0
  5. data/.github/config/rubocop_linter_action.yml +4 -0
  6. data/.github/workflows/ci-with-docker.yml +44 -0
  7. data/.github/workflows/ci.yml +93 -0
  8. data/.github/workflows/rubocop.yml +16 -0
  9. data/.gitignore +13 -0
  10. data/.rubocop.yml +22 -0
  11. data/.rubocop_todo.yml +1081 -0
  12. data/CHANGES.txt +237 -7
  13. data/DEVELOPMENT.md +23 -0
  14. data/Dockerfile +27 -0
  15. data/Dockerfile.openssl3 +17 -0
  16. data/Gemfile +13 -0
  17. data/Gemfile.noed25519 +12 -0
  18. data/Gemfile.norbnacl +12 -0
  19. data/ISSUE_TEMPLATE.md +30 -0
  20. data/Manifest +4 -5
  21. data/README.md +298 -0
  22. data/Rakefile +125 -74
  23. data/SECURITY.md +4 -0
  24. data/appveyor.yml +58 -0
  25. data/docker-compose.yml +23 -0
  26. data/lib/net/ssh/authentication/agent.rb +279 -18
  27. data/lib/net/ssh/authentication/certificate.rb +183 -0
  28. data/lib/net/ssh/authentication/constants.rb +17 -15
  29. data/lib/net/ssh/authentication/ed25519.rb +186 -0
  30. data/lib/net/ssh/authentication/ed25519_loader.rb +31 -0
  31. data/lib/net/ssh/authentication/key_manager.rb +86 -39
  32. data/lib/net/ssh/authentication/methods/abstract.rb +67 -48
  33. data/lib/net/ssh/authentication/methods/hostbased.rb +34 -37
  34. data/lib/net/ssh/authentication/methods/keyboard_interactive.rb +13 -13
  35. data/lib/net/ssh/authentication/methods/none.rb +16 -19
  36. data/lib/net/ssh/authentication/methods/password.rb +27 -17
  37. data/lib/net/ssh/authentication/methods/publickey.rb +96 -55
  38. data/lib/net/ssh/authentication/pageant.rb +471 -367
  39. data/lib/net/ssh/authentication/pub_key_fingerprint.rb +43 -0
  40. data/lib/net/ssh/authentication/session.rb +131 -121
  41. data/lib/net/ssh/buffer.rb +399 -300
  42. data/lib/net/ssh/buffered_io.rb +154 -150
  43. data/lib/net/ssh/config.rb +308 -185
  44. data/lib/net/ssh/connection/channel.rb +635 -613
  45. data/lib/net/ssh/connection/constants.rb +29 -29
  46. data/lib/net/ssh/connection/event_loop.rb +123 -0
  47. data/lib/net/ssh/connection/keepalive.rb +55 -51
  48. data/lib/net/ssh/connection/session.rb +620 -551
  49. data/lib/net/ssh/connection/term.rb +125 -123
  50. data/lib/net/ssh/errors.rb +101 -99
  51. data/lib/net/ssh/key_factory.rb +197 -105
  52. data/lib/net/ssh/known_hosts.rb +214 -127
  53. data/lib/net/ssh/loggable.rb +50 -49
  54. data/lib/net/ssh/packet.rb +83 -79
  55. data/lib/net/ssh/prompt.rb +50 -81
  56. data/lib/net/ssh/proxy/command.rb +105 -90
  57. data/lib/net/ssh/proxy/errors.rb +12 -10
  58. data/lib/net/ssh/proxy/http.rb +82 -79
  59. data/lib/net/ssh/proxy/https.rb +50 -0
  60. data/lib/net/ssh/proxy/jump.rb +54 -0
  61. data/lib/net/ssh/proxy/socks4.rb +2 -6
  62. data/lib/net/ssh/proxy/socks5.rb +14 -17
  63. data/lib/net/ssh/service/forward.rb +370 -317
  64. data/lib/net/ssh/test/channel.rb +145 -136
  65. data/lib/net/ssh/test/extensions.rb +131 -110
  66. data/lib/net/ssh/test/kex.rb +34 -32
  67. data/lib/net/ssh/test/local_packet.rb +46 -44
  68. data/lib/net/ssh/test/packet.rb +89 -70
  69. data/lib/net/ssh/test/remote_packet.rb +32 -30
  70. data/lib/net/ssh/test/script.rb +156 -142
  71. data/lib/net/ssh/test/socket.rb +49 -48
  72. data/lib/net/ssh/test.rb +82 -77
  73. data/lib/net/ssh/transport/algorithms.rb +462 -359
  74. data/lib/net/ssh/transport/chacha20_poly1305_cipher.rb +117 -0
  75. data/lib/net/ssh/transport/chacha20_poly1305_cipher_loader.rb +17 -0
  76. data/lib/net/ssh/transport/cipher_factory.rb +122 -99
  77. data/lib/net/ssh/transport/constants.rb +32 -24
  78. data/lib/net/ssh/transport/ctr.rb +42 -22
  79. data/lib/net/ssh/transport/hmac/abstract.rb +81 -63
  80. data/lib/net/ssh/transport/hmac/md5.rb +0 -2
  81. data/lib/net/ssh/transport/hmac/md5_96.rb +0 -2
  82. data/lib/net/ssh/transport/hmac/none.rb +0 -2
  83. data/lib/net/ssh/transport/hmac/ripemd160.rb +0 -2
  84. data/lib/net/ssh/transport/hmac/sha1.rb +0 -2
  85. data/lib/net/ssh/transport/hmac/sha1_96.rb +0 -2
  86. data/lib/net/ssh/transport/hmac/sha2_256.rb +7 -11
  87. data/lib/net/ssh/transport/hmac/sha2_256_96.rb +4 -8
  88. data/lib/net/ssh/transport/hmac/sha2_256_etm.rb +12 -0
  89. data/lib/net/ssh/transport/hmac/sha2_512.rb +6 -9
  90. data/lib/net/ssh/transport/hmac/sha2_512_96.rb +4 -8
  91. data/lib/net/ssh/transport/hmac/sha2_512_etm.rb +12 -0
  92. data/lib/net/ssh/transport/hmac.rb +14 -12
  93. data/lib/net/ssh/transport/identity_cipher.rb +54 -44
  94. data/lib/net/ssh/transport/kex/abstract.rb +130 -0
  95. data/lib/net/ssh/transport/kex/abstract5656.rb +72 -0
  96. data/lib/net/ssh/transport/kex/curve25519_sha256.rb +39 -0
  97. data/lib/net/ssh/transport/kex/curve25519_sha256_loader.rb +30 -0
  98. data/lib/net/ssh/transport/kex/diffie_hellman_group14_sha1.rb +33 -40
  99. data/lib/net/ssh/transport/kex/diffie_hellman_group14_sha256.rb +11 -0
  100. data/lib/net/ssh/transport/kex/diffie_hellman_group1_sha1.rb +119 -213
  101. data/lib/net/ssh/transport/kex/diffie_hellman_group_exchange_sha1.rb +53 -61
  102. data/lib/net/ssh/transport/kex/diffie_hellman_group_exchange_sha256.rb +5 -9
  103. data/lib/net/ssh/transport/kex/ecdh_sha2_nistp256.rb +36 -90
  104. data/lib/net/ssh/transport/kex/ecdh_sha2_nistp384.rb +18 -10
  105. data/lib/net/ssh/transport/kex/ecdh_sha2_nistp521.rb +18 -10
  106. data/lib/net/ssh/transport/kex.rb +15 -12
  107. data/lib/net/ssh/transport/key_expander.rb +24 -20
  108. data/lib/net/ssh/transport/openssl.rb +161 -124
  109. data/lib/net/ssh/transport/openssl_cipher_extensions.rb +8 -0
  110. data/lib/net/ssh/transport/packet_stream.rb +246 -185
  111. data/lib/net/ssh/transport/server_version.rb +55 -56
  112. data/lib/net/ssh/transport/session.rb +306 -255
  113. data/lib/net/ssh/transport/state.rb +178 -176
  114. data/lib/net/ssh/verifiers/accept_new.rb +33 -0
  115. data/lib/net/ssh/verifiers/accept_new_or_local_tunnel.rb +33 -0
  116. data/lib/net/ssh/verifiers/always.rb +58 -0
  117. data/lib/net/ssh/verifiers/never.rb +19 -0
  118. data/lib/net/ssh/version.rb +55 -53
  119. data/lib/net/ssh.rb +111 -47
  120. data/net-ssh-public_cert.pem +18 -18
  121. data/net-ssh.gemspec +38 -205
  122. data/support/ssh_tunnel_bug.rb +5 -5
  123. data.tar.gz.sig +0 -0
  124. metadata +173 -118
  125. metadata.gz.sig +0 -0
  126. data/.travis.yml +0 -18
  127. data/README.rdoc +0 -182
  128. data/lib/net/ssh/authentication/agent/java_pageant.rb +0 -85
  129. data/lib/net/ssh/authentication/agent/socket.rb +0 -178
  130. data/lib/net/ssh/ruby_compat.rb +0 -46
  131. data/lib/net/ssh/verifiers/lenient.rb +0 -30
  132. data/lib/net/ssh/verifiers/null.rb +0 -12
  133. data/lib/net/ssh/verifiers/secure.rb +0 -52
  134. data/lib/net/ssh/verifiers/strict.rb +0 -24
  135. data/setup.rb +0 -1585
  136. data/support/arcfour_check.rb +0 -20
  137. data/test/README.txt +0 -18
  138. data/test/authentication/methods/common.rb +0 -28
  139. data/test/authentication/methods/test_abstract.rb +0 -51
  140. data/test/authentication/methods/test_hostbased.rb +0 -114
  141. data/test/authentication/methods/test_keyboard_interactive.rb +0 -121
  142. data/test/authentication/methods/test_none.rb +0 -41
  143. data/test/authentication/methods/test_password.rb +0 -95
  144. data/test/authentication/methods/test_publickey.rb +0 -148
  145. data/test/authentication/test_agent.rb +0 -232
  146. data/test/authentication/test_key_manager.rb +0 -240
  147. data/test/authentication/test_session.rb +0 -107
  148. data/test/common.rb +0 -125
  149. data/test/configs/auth_off +0 -5
  150. data/test/configs/auth_on +0 -4
  151. data/test/configs/empty +0 -0
  152. data/test/configs/eqsign +0 -3
  153. data/test/configs/exact_match +0 -8
  154. data/test/configs/host_plus +0 -10
  155. data/test/configs/multihost +0 -4
  156. data/test/configs/negative_match +0 -6
  157. data/test/configs/nohost +0 -19
  158. data/test/configs/numeric_host +0 -4
  159. data/test/configs/proxy_remote_user +0 -2
  160. data/test/configs/send_env +0 -2
  161. data/test/configs/substitutes +0 -8
  162. data/test/configs/wild_cards +0 -14
  163. data/test/connection/test_channel.rb +0 -487
  164. data/test/connection/test_session.rb +0 -564
  165. data/test/integration/README.txt +0 -17
  166. data/test/integration/Vagrantfile +0 -12
  167. data/test/integration/common.rb +0 -63
  168. data/test/integration/playbook.yml +0 -56
  169. data/test/integration/test_forward.rb +0 -637
  170. data/test/integration/test_id_rsa_keys.rb +0 -96
  171. data/test/integration/test_proxy.rb +0 -93
  172. data/test/known_hosts/github +0 -1
  173. data/test/known_hosts/github_hash +0 -1
  174. data/test/manual/test_pageant.rb +0 -37
  175. data/test/start/test_connection.rb +0 -53
  176. data/test/start/test_options.rb +0 -57
  177. data/test/start/test_transport.rb +0 -28
  178. data/test/start/test_user_nil.rb +0 -27
  179. data/test/test_all.rb +0 -12
  180. data/test/test_buffer.rb +0 -433
  181. data/test/test_buffered_io.rb +0 -63
  182. data/test/test_config.rb +0 -268
  183. data/test/test_key_factory.rb +0 -191
  184. data/test/test_known_hosts.rb +0 -66
  185. data/test/transport/hmac/test_md5.rb +0 -41
  186. data/test/transport/hmac/test_md5_96.rb +0 -27
  187. data/test/transport/hmac/test_none.rb +0 -34
  188. data/test/transport/hmac/test_ripemd160.rb +0 -36
  189. data/test/transport/hmac/test_sha1.rb +0 -36
  190. data/test/transport/hmac/test_sha1_96.rb +0 -27
  191. data/test/transport/hmac/test_sha2_256.rb +0 -37
  192. data/test/transport/hmac/test_sha2_256_96.rb +0 -27
  193. data/test/transport/hmac/test_sha2_512.rb +0 -37
  194. data/test/transport/hmac/test_sha2_512_96.rb +0 -27
  195. data/test/transport/kex/test_diffie_hellman_group14_sha1.rb +0 -13
  196. data/test/transport/kex/test_diffie_hellman_group1_sha1.rb +0 -150
  197. data/test/transport/kex/test_diffie_hellman_group_exchange_sha1.rb +0 -96
  198. data/test/transport/kex/test_diffie_hellman_group_exchange_sha256.rb +0 -19
  199. data/test/transport/kex/test_ecdh_sha2_nistp256.rb +0 -161
  200. data/test/transport/kex/test_ecdh_sha2_nistp384.rb +0 -38
  201. data/test/transport/kex/test_ecdh_sha2_nistp521.rb +0 -38
  202. data/test/transport/test_algorithms.rb +0 -328
  203. data/test/transport/test_cipher_factory.rb +0 -443
  204. data/test/transport/test_hmac.rb +0 -34
  205. data/test/transport/test_identity_cipher.rb +0 -40
  206. data/test/transport/test_packet_stream.rb +0 -1762
  207. data/test/transport/test_server_version.rb +0 -74
  208. data/test/transport/test_session.rb +0 -331
  209. data/test/transport/test_state.rb +0 -181
  210. data/test/verifiers/test_secure.rb +0 -40
@@ -0,0 +1,72 @@
1
+ require 'net/ssh/transport/kex/abstract'
2
+
3
+ module Net
4
+ module SSH
5
+ module Transport
6
+ module Kex
7
+ # Implement key-exchange algorithm from Elliptic Curve Algorithm Integration
8
+ # in the Secure Shell Transport Layer (RFC 5656)
9
+ class Abstract5656 < Abstract
10
+ alias ecdh dh
11
+
12
+ def curve_name
13
+ raise NotImplementedError, 'abstract class: curve_name not implemented'
14
+ end
15
+
16
+ private
17
+
18
+ def get_message_types
19
+ [KEXECDH_INIT, KEXECDH_REPLY]
20
+ end
21
+
22
+ def build_signature_buffer(result)
23
+ response = Net::SSH::Buffer.new
24
+ response.write_string data[:client_version_string],
25
+ data[:server_version_string],
26
+ data[:client_algorithm_packet],
27
+ data[:server_algorithm_packet],
28
+ result[:key_blob],
29
+ ecdh_public_key_bytes,
30
+ result[:server_ecdh_pubkey]
31
+ response.write_bignum result[:shared_secret]
32
+ response
33
+ end
34
+
35
+ def send_kexinit # :nodoc:
36
+ init, reply = get_message_types
37
+
38
+ # send the KEXECDH_INIT message
39
+ ## byte SSH_MSG_KEX_ECDH_INIT
40
+ ## string Q_C, client's ephemeral public key octet string
41
+ buffer = Net::SSH::Buffer.from(:byte, init, :mstring, ecdh_public_key_bytes)
42
+ connection.send_message(buffer)
43
+
44
+ # expect the following KEXECDH_REPLY message
45
+ ## byte SSH_MSG_KEX_ECDH_REPLY
46
+ ## string K_S, server's public host key
47
+ ## string Q_S, server's ephemeral public key octet string
48
+ ## string the signature on the exchange hash
49
+ buffer = connection.next_message
50
+ raise Net::SSH::Exception, 'expected REPLY' unless buffer.type == reply
51
+
52
+ result = {}
53
+ result[:key_blob] = buffer.read_string
54
+ result[:server_key] = Net::SSH::Buffer.new(result[:key_blob]).read_key
55
+ result[:server_ecdh_pubkey] = buffer.read_string
56
+ result[:shared_secret] = compute_shared_secret(result[:server_ecdh_pubkey])
57
+
58
+ sig_buffer = Net::SSH::Buffer.new(buffer.read_string)
59
+ sig_type = sig_buffer.read_string
60
+ if sig_type != algorithms.host_key_format
61
+ raise Net::SSH::Exception, "host key algorithm mismatch for signature '#{sig_type}' != '#{algorithms.host_key_format}'"
62
+ end
63
+
64
+ result[:server_sig] = sig_buffer.read_string
65
+
66
+ result
67
+ end
68
+ end
69
+ end
70
+ end
71
+ end
72
+ end
@@ -0,0 +1,39 @@
1
+ gem 'x25519' # raise if the gem x25519 is not installed
2
+
3
+ require 'x25519'
4
+
5
+ require 'net/ssh/transport/constants'
6
+ require 'net/ssh/transport/kex/abstract5656'
7
+
8
+ module Net
9
+ module SSH
10
+ module Transport
11
+ module Kex
12
+ # A key-exchange service implementing the "curve25519-sha256@libssh.org"
13
+ # key-exchange algorithm. (defined in https://tools.ietf.org/html/draft-ietf-curdle-ssh-curves-06)
14
+ class Curve25519Sha256 < Abstract5656
15
+ def digester
16
+ OpenSSL::Digest::SHA256
17
+ end
18
+
19
+ private
20
+
21
+ def generate_key # :nodoc:
22
+ ::X25519::Scalar.generate
23
+ end
24
+
25
+ ## string Q_C, client's ephemeral public key octet string
26
+ def ecdh_public_key_bytes
27
+ ecdh.public_key.to_bytes
28
+ end
29
+
30
+ # compute shared secret from server's public key and client's private key
31
+ def compute_shared_secret(server_ecdh_pubkey)
32
+ pk = ::X25519::MontgomeryU.new(server_ecdh_pubkey)
33
+ OpenSSL::BN.new(ecdh.diffie_hellman(pk).to_bytes, 2)
34
+ end
35
+ end
36
+ end
37
+ end
38
+ end
39
+ end
@@ -0,0 +1,30 @@
1
+ module Net
2
+ module SSH
3
+ module Transport
4
+ module Kex
5
+ # Loads Curve25519Sha256 support which requires optinal dependencies
6
+ module Curve25519Sha256Loader
7
+ begin
8
+ require 'net/ssh/transport/kex/curve25519_sha256'
9
+ LOADED = true
10
+ ERROR = nil
11
+ rescue LoadError => e
12
+ ERROR = e
13
+ LOADED = false
14
+ end
15
+
16
+ def self.raiseUnlessLoaded(message)
17
+ description = ERROR.is_a?(LoadError) ? dependenciesRequiredForX25519 : ''
18
+ description << "#{ERROR.class} : \"#{ERROR.message}\"\n" if ERROR
19
+ raise NotImplementedError, "#{message}\n#{description}" unless LOADED
20
+ end
21
+
22
+ def self.dependenciesRequiredForX25519
23
+ result = "net-ssh requires the following gems for x25519 support:\n"
24
+ result << " * x25519\n"
25
+ end
26
+ end
27
+ end
28
+ end
29
+ end
30
+ end
@@ -1,44 +1,37 @@
1
1
  require 'net/ssh/transport/kex/diffie_hellman_group1_sha1'
2
2
 
3
- module Net; module SSH; module Transport; module Kex
4
-
5
- # A key-exchange service implementing the "diffie-hellman-group14-sha1"
6
- # key-exchange algorithm. (defined in RFC 4253)
7
- class DiffieHellmanGroup14SHA1 < DiffieHellmanGroup1SHA1
8
- include Constants, Loggable
9
-
10
- # The value of 'P', as a string, in hexadecimal
11
- P_s = "FFFFFFFF" "FFFFFFFF" "C90FDAA2" "2168C234" +
12
- "C4C6628B" "80DC1CD1" "29024E08" "8A67CC74" +
13
- "020BBEA6" "3B139B22" "514A0879" "8E3404DD" +
14
- "EF9519B3" "CD3A431B" "302B0A6D" "F25F1437" +
15
- "4FE1356D" "6D51C245" "E485B576" "625E7EC6" +
16
- "F44C42E9" "A637ED6B" "0BFF5CB6" "F406B7ED" +
17
- "EE386BFB" "5A899FA5" "AE9F2411" "7C4B1FE6" +
18
- "49286651" "ECE45B3D" "C2007CB8" "A163BF05" +
19
- "98DA4836" "1C55D39A" "69163FA8" "FD24CF5F" +
20
- "83655D23" "DCA3AD96" "1C62F356" "208552BB" +
21
- "9ED52907" "7096966D" "670C354E" "4ABC9804" +
22
- "F1746C08" "CA18217C" "32905E46" "2E36CE3B" +
23
- "E39E772C" "180E8603" "9B2783A2" "EC07A28F" +
24
- "B5C55DF0" "6F4C52C9" "DE2BCBF6" "95581718" +
25
- "3995497C" "EA956AE5" "15D22618" "98FA0510" +
26
- "15728E5A" "8AACAA68" "FFFFFFFF" "FFFFFFFF"
27
-
28
- # The radix in which P_s represents the value of P
29
- P_r = 16
30
-
31
- # The group constant
32
- G = 2
33
-
34
- private
35
-
36
- def get_p
37
- OpenSSL::BN.new(P_s, P_r)
38
- end
39
-
40
- def get_g
41
- G
3
+ module Net
4
+ module SSH
5
+ module Transport
6
+ module Kex
7
+ # A key-exchange service implementing the "diffie-hellman-group14-sha1"
8
+ # key-exchange algorithm. (defined in RFC 4253)
9
+ class DiffieHellmanGroup14SHA1 < DiffieHellmanGroup1SHA1
10
+ # The value of 'P', as a string, in hexadecimal
11
+ P_s = "FFFFFFFF" "FFFFFFFF" "C90FDAA2" "2168C234" +
12
+ "C4C6628B" "80DC1CD1" "29024E08" "8A67CC74" +
13
+ "020BBEA6" "3B139B22" "514A0879" "8E3404DD" +
14
+ "EF9519B3" "CD3A431B" "302B0A6D" "F25F1437" +
15
+ "4FE1356D" "6D51C245" "E485B576" "625E7EC6" +
16
+ "F44C42E9" "A637ED6B" "0BFF5CB6" "F406B7ED" +
17
+ "EE386BFB" "5A899FA5" "AE9F2411" "7C4B1FE6" +
18
+ "49286651" "ECE45B3D" "C2007CB8" "A163BF05" +
19
+ "98DA4836" "1C55D39A" "69163FA8" "FD24CF5F" +
20
+ "83655D23" "DCA3AD96" "1C62F356" "208552BB" +
21
+ "9ED52907" "7096966D" "670C354E" "4ABC9804" +
22
+ "F1746C08" "CA18217C" "32905E46" "2E36CE3B" +
23
+ "E39E772C" "180E8603" "9B2783A2" "EC07A28F" +
24
+ "B5C55DF0" "6F4C52C9" "DE2BCBF6" "95581718" +
25
+ "3995497C" "EA956AE5" "15D22618" "98FA0510" +
26
+ "15728E5A" "8AACAA68" "FFFFFFFF" "FFFFFFFF"
27
+
28
+ # The radix in which P_s represents the value of P
29
+ P_r = 16
30
+
31
+ # The group constant
32
+ G = 2
33
+ end
34
+ end
42
35
  end
43
36
  end
44
- end; end; end; end
37
+ end
@@ -0,0 +1,11 @@
1
+ require 'net/ssh/transport/kex/diffie_hellman_group14_sha1'
2
+
3
+ module Net::SSH::Transport::Kex
4
+ # A key-exchange service implementing the "diffie-hellman-group14-sha256"
5
+ # key-exchange algorithm.
6
+ class DiffieHellmanGroup14SHA256 < DiffieHellmanGroup14SHA1
7
+ def digester
8
+ OpenSSL::Digest::SHA256
9
+ end
10
+ end
11
+ end
@@ -1,216 +1,122 @@
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 = get_p
44
- @g = get_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
- def get_p
81
- OpenSSL::BN.new(P_s, P_r)
82
- end
83
-
84
- def get_g
85
- G
86
- end
87
-
88
- # Returns the DH key parameters for the current connection.
89
- def get_parameters
90
- [p, g]
91
- end
92
-
93
- # Returns the INIT/REPLY constants used by this algorithm.
94
- def get_message_types
95
- [KEXDH_INIT, KEXDH_REPLY]
96
- end
97
-
98
- # Build the signature buffer to use when verifying a signature from
99
- # the server.
100
- def build_signature_buffer(result)
101
- response = Net::SSH::Buffer.new
102
- response.write_string data[:client_version_string],
103
- data[:server_version_string],
104
- data[:client_algorithm_packet],
105
- data[:server_algorithm_packet],
106
- result[:key_blob]
107
- response.write_bignum dh.pub_key,
108
- result[:server_dh_pubkey],
109
- result[:shared_secret]
110
- response
111
- end
112
-
113
- # Generate a DH key with a private key consisting of the given
114
- # number of bytes.
115
- def generate_key #:nodoc:
116
- dh = OpenSSL::PKey::DH.new
117
-
118
- dh.p, dh.g = get_parameters
119
- dh.priv_key = OpenSSL::BN.rand(data[:need_bytes] * 8)
120
-
121
- dh.generate_key! until dh.valid?
122
-
123
- dh
124
- end
125
-
126
- # Send the KEXDH_INIT message, and expect the KEXDH_REPLY. Return the
127
- # resulting buffer.
128
- #
129
- # Parse the buffer from a KEXDH_REPLY message, returning a hash of
130
- # the extracted values.
131
- def send_kexinit #:nodoc:
132
- init, reply = get_message_types
133
-
134
- # send the KEXDH_INIT message
135
- buffer = Net::SSH::Buffer.from(:byte, init, :bignum, dh.pub_key)
136
- connection.send_message(buffer)
137
-
138
- # expect the KEXDH_REPLY message
139
- buffer = connection.next_message
140
- raise Net::SSH::Exception, "expected REPLY" unless buffer.type == reply
141
-
142
- result = Hash.new
143
-
144
- result[:key_blob] = buffer.read_string
145
- result[:server_key] = Net::SSH::Buffer.new(result[:key_blob]).read_key
146
- result[:server_dh_pubkey] = buffer.read_bignum
147
- result[:shared_secret] = OpenSSL::BN.new(dh.compute_key(result[:server_dh_pubkey]), 2)
148
-
149
- sig_buffer = Net::SSH::Buffer.new(buffer.read_string)
150
- sig_type = sig_buffer.read_string
151
- if sig_type != algorithms.host_key
152
- raise Net::SSH::Exception,
153
- "host key algorithm mismatch for signature " +
154
- "'#{sig_type}' != '#{algorithms.host_key}'"
1
+ require 'net/ssh/transport/kex/abstract'
2
+
3
+ module Net
4
+ module SSH
5
+ module Transport
6
+ module Kex
7
+ # A key-exchange service implementing the "diffie-hellman-group1-sha1"
8
+ # key-exchange algorithm.
9
+ class DiffieHellmanGroup1SHA1 < Abstract
10
+ # The value of 'P', as a string, in hexadecimal
11
+ P_s = "FFFFFFFF" "FFFFFFFF" "C90FDAA2" "2168C234" +
12
+ "C4C6628B" "80DC1CD1" "29024E08" "8A67CC74" +
13
+ "020BBEA6" "3B139B22" "514A0879" "8E3404DD" +
14
+ "EF9519B3" "CD3A431B" "302B0A6D" "F25F1437" +
15
+ "4FE1356D" "6D51C245" "E485B576" "625E7EC6" +
16
+ "F44C42E9" "A637ED6B" "0BFF5CB6" "F406B7ED" +
17
+ "EE386BFB" "5A899FA5" "AE9F2411" "7C4B1FE6" +
18
+ "49286651" "ECE65381" "FFFFFFFF" "FFFFFFFF"
19
+
20
+ # The radix in which P_s represents the value of P
21
+ P_r = 16
22
+
23
+ # The group constant
24
+ G = 2
25
+
26
+ def digester
27
+ OpenSSL::Digest::SHA1
28
+ end
29
+
30
+ private
31
+
32
+ # Returns the DH key parameters for the current connection. [p, q]
33
+ def get_parameters
34
+ [
35
+ OpenSSL::BN.new(self.class::P_s, self.class::P_r),
36
+ self.class::G
37
+ ]
38
+ end
39
+
40
+ # Returns the INIT/REPLY constants used by this algorithm.
41
+ def get_message_types
42
+ [KEXDH_INIT, KEXDH_REPLY]
43
+ end
44
+
45
+ # Build the signature buffer to use when verifying a signature from
46
+ # the server.
47
+ def build_signature_buffer(result)
48
+ response = Net::SSH::Buffer.new
49
+ response.write_string data[:client_version_string],
50
+ data[:server_version_string],
51
+ data[:client_algorithm_packet],
52
+ data[:server_algorithm_packet],
53
+ result[:key_blob]
54
+ response.write_bignum dh.pub_key,
55
+ result[:server_dh_pubkey],
56
+ result[:shared_secret]
57
+ response
58
+ end
59
+
60
+ # Generate a DH key with a private key consisting of the given
61
+ # number of bytes.
62
+ def generate_key # :nodoc:
63
+ p, g = get_parameters
64
+
65
+ asn1 = OpenSSL::ASN1::Sequence(
66
+ [
67
+ OpenSSL::ASN1::Integer(p),
68
+ OpenSSL::ASN1::Integer(g)
69
+ ]
70
+ )
71
+
72
+ dh_params = OpenSSL::PKey::DH.new(asn1.to_der)
73
+ # XXX No private key size check! In theory the latter call should work but fails on OpenSSL 3.0 as
74
+ # dh_paramgen_subprime_len is now reserved for DHX algorithm
75
+ # key = OpenSSL::PKey.generate_key(dh_params, "dh_paramgen_subprime_len" => data[:need_bytes]/8)
76
+ if OpenSSL::PKey.respond_to?(:generate_key)
77
+ OpenSSL::PKey.generate_key(dh_params)
78
+ else
79
+ dh_params.generate_key!
80
+ dh_params
81
+ end
82
+ end
83
+
84
+ # Send the KEXDH_INIT message, and expect the KEXDH_REPLY. Return the
85
+ # resulting buffer.
86
+ #
87
+ # Parse the buffer from a KEXDH_REPLY message, returning a hash of
88
+ # the extracted values.
89
+ def send_kexinit # :nodoc:
90
+ init, reply = get_message_types
91
+
92
+ # send the KEXDH_INIT message
93
+ buffer = Net::SSH::Buffer.from(:byte, init, :bignum, dh.pub_key)
94
+ connection.send_message(buffer)
95
+
96
+ # expect the KEXDH_REPLY message
97
+ buffer = connection.next_message
98
+ raise Net::SSH::Exception, "expected REPLY" unless buffer.type == reply
99
+
100
+ result = Hash.new
101
+
102
+ result[:key_blob] = buffer.read_string
103
+ result[:server_key] = Net::SSH::Buffer.new(result[:key_blob]).read_key
104
+ result[:server_dh_pubkey] = buffer.read_bignum
105
+ result[:shared_secret] = OpenSSL::BN.new(dh.compute_key(result[:server_dh_pubkey]), 2)
106
+
107
+ sig_buffer = Net::SSH::Buffer.new(buffer.read_string)
108
+ sig_type = sig_buffer.read_string
109
+ if sig_type != algorithms.host_key_format
110
+ raise Net::SSH::Exception,
111
+ "host key algorithm mismatch for signature " +
112
+ "'#{sig_type}' != '#{algorithms.host_key_format}'"
113
+ end
114
+ result[:server_sig] = sig_buffer.read_string
115
+
116
+ return result
117
+ end
155
118
  end
156
- result[:server_sig] = sig_buffer.read_string
157
-
158
- return result
159
- end
160
-
161
- # Verify that the given key is of the expected type, and that it
162
- # really is the key for the session's host. Raise Net::SSH::Exception
163
- # if it is not.
164
- def verify_server_key(key) #:nodoc:
165
- if key.ssh_type != algorithms.host_key
166
- raise Net::SSH::Exception,
167
- "host key algorithm mismatch " +
168
- "'#{key.ssh_type}' != '#{algorithms.host_key}'"
169
- end
170
-
171
- blob, fingerprint = generate_key_fingerprint(key)
172
-
173
- unless connection.host_key_verifier.verify(:key => key, :key_blob => blob, :fingerprint => fingerprint, :session => connection)
174
- raise Net::SSH::Exception, "host key verification failed"
175
- end
176
- end
177
-
178
- def generate_key_fingerprint(key)
179
- blob = Net::SSH::Buffer.from(:key, key).to_s
180
- fingerprint = OpenSSL::Digest::MD5.hexdigest(blob).scan(/../).join(":")
181
-
182
- [blob, fingerprint]
183
- rescue ::Exception => e
184
- [nil, "(could not generate fingerprint: #{e.message})"]
185
- end
186
-
187
- # Verify the signature that was received. Raise Net::SSH::Exception
188
- # if the signature could not be verified. Otherwise, return the new
189
- # session-id.
190
- def verify_signature(result) #:nodoc:
191
- response = build_signature_buffer(result)
192
-
193
- hash = @digester.digest(response.to_s)
194
-
195
- unless result[:server_key].ssh_do_verify(result[:server_sig], hash)
196
- raise Net::SSH::Exception, "could not verify server signature"
197
- end
198
-
199
- return hash
200
- end
201
-
202
- # Send the NEWKEYS message, and expect the NEWKEYS message in
203
- # reply.
204
- def confirm_newkeys #:nodoc:
205
- # send own NEWKEYS message first (the wodSSHServer won't send first)
206
- response = Net::SSH::Buffer.new
207
- response.write_byte(NEWKEYS)
208
- connection.send_message(response)
209
-
210
- # wait for the server's NEWKEYS message
211
- buffer = connection.next_message
212
- raise Net::SSH::Exception, "expected NEWKEYS" unless buffer.type == NEWKEYS
213
119
  end
120
+ end
214
121
  end
215
-
216
- end; end; end; end
122
+ end