minmb-net-ssh 2.5.1

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 (137) hide show
  1. data/CHANGELOG.rdoc +291 -0
  2. data/Manifest +132 -0
  3. data/README.rdoc +184 -0
  4. data/Rakefile +86 -0
  5. data/Rudyfile +96 -0
  6. data/THANKS.rdoc +19 -0
  7. data/lib/net/ssh.rb +223 -0
  8. data/lib/net/ssh/authentication/agent.rb +23 -0
  9. data/lib/net/ssh/authentication/agent/java_pageant.rb +85 -0
  10. data/lib/net/ssh/authentication/agent/socket.rb +170 -0
  11. data/lib/net/ssh/authentication/constants.rb +18 -0
  12. data/lib/net/ssh/authentication/key_manager.rb +253 -0
  13. data/lib/net/ssh/authentication/methods/abstract.rb +60 -0
  14. data/lib/net/ssh/authentication/methods/hostbased.rb +75 -0
  15. data/lib/net/ssh/authentication/methods/keyboard_interactive.rb +70 -0
  16. data/lib/net/ssh/authentication/methods/password.rb +43 -0
  17. data/lib/net/ssh/authentication/methods/publickey.rb +96 -0
  18. data/lib/net/ssh/authentication/pageant.rb +301 -0
  19. data/lib/net/ssh/authentication/session.rb +154 -0
  20. data/lib/net/ssh/buffer.rb +350 -0
  21. data/lib/net/ssh/buffered_io.rb +207 -0
  22. data/lib/net/ssh/config.rb +207 -0
  23. data/lib/net/ssh/connection/channel.rb +630 -0
  24. data/lib/net/ssh/connection/constants.rb +33 -0
  25. data/lib/net/ssh/connection/session.rb +603 -0
  26. data/lib/net/ssh/connection/term.rb +178 -0
  27. data/lib/net/ssh/errors.rb +88 -0
  28. data/lib/net/ssh/key_factory.rb +107 -0
  29. data/lib/net/ssh/known_hosts.rb +141 -0
  30. data/lib/net/ssh/loggable.rb +61 -0
  31. data/lib/net/ssh/packet.rb +102 -0
  32. data/lib/net/ssh/prompt.rb +93 -0
  33. data/lib/net/ssh/proxy/command.rb +75 -0
  34. data/lib/net/ssh/proxy/errors.rb +14 -0
  35. data/lib/net/ssh/proxy/http.rb +94 -0
  36. data/lib/net/ssh/proxy/socks4.rb +70 -0
  37. data/lib/net/ssh/proxy/socks5.rb +142 -0
  38. data/lib/net/ssh/ruby_compat.rb +77 -0
  39. data/lib/net/ssh/service/forward.rb +327 -0
  40. data/lib/net/ssh/test.rb +89 -0
  41. data/lib/net/ssh/test/channel.rb +129 -0
  42. data/lib/net/ssh/test/extensions.rb +152 -0
  43. data/lib/net/ssh/test/kex.rb +44 -0
  44. data/lib/net/ssh/test/local_packet.rb +51 -0
  45. data/lib/net/ssh/test/packet.rb +81 -0
  46. data/lib/net/ssh/test/remote_packet.rb +38 -0
  47. data/lib/net/ssh/test/script.rb +157 -0
  48. data/lib/net/ssh/test/socket.rb +64 -0
  49. data/lib/net/ssh/transport/algorithms.rb +407 -0
  50. data/lib/net/ssh/transport/cipher_factory.rb +106 -0
  51. data/lib/net/ssh/transport/constants.rb +32 -0
  52. data/lib/net/ssh/transport/ctr.rb +95 -0
  53. data/lib/net/ssh/transport/hmac.rb +45 -0
  54. data/lib/net/ssh/transport/hmac/abstract.rb +79 -0
  55. data/lib/net/ssh/transport/hmac/md5.rb +12 -0
  56. data/lib/net/ssh/transport/hmac/md5_96.rb +11 -0
  57. data/lib/net/ssh/transport/hmac/none.rb +15 -0
  58. data/lib/net/ssh/transport/hmac/ripemd160.rb +13 -0
  59. data/lib/net/ssh/transport/hmac/sha1.rb +13 -0
  60. data/lib/net/ssh/transport/hmac/sha1_96.rb +11 -0
  61. data/lib/net/ssh/transport/hmac/sha2_256.rb +15 -0
  62. data/lib/net/ssh/transport/hmac/sha2_256_96.rb +13 -0
  63. data/lib/net/ssh/transport/hmac/sha2_512.rb +14 -0
  64. data/lib/net/ssh/transport/hmac/sha2_512_96.rb +13 -0
  65. data/lib/net/ssh/transport/identity_cipher.rb +55 -0
  66. data/lib/net/ssh/transport/kex.rb +28 -0
  67. data/lib/net/ssh/transport/kex/diffie_hellman_group14_sha1.rb +44 -0
  68. data/lib/net/ssh/transport/kex/diffie_hellman_group1_sha1.rb +216 -0
  69. data/lib/net/ssh/transport/kex/diffie_hellman_group_exchange_sha1.rb +80 -0
  70. data/lib/net/ssh/transport/kex/diffie_hellman_group_exchange_sha256.rb +15 -0
  71. data/lib/net/ssh/transport/kex/ecdh_sha2_nistp256.rb +93 -0
  72. data/lib/net/ssh/transport/kex/ecdh_sha2_nistp384.rb +13 -0
  73. data/lib/net/ssh/transport/kex/ecdh_sha2_nistp521.rb +13 -0
  74. data/lib/net/ssh/transport/key_expander.rb +26 -0
  75. data/lib/net/ssh/transport/openssl.rb +237 -0
  76. data/lib/net/ssh/transport/packet_stream.rb +235 -0
  77. data/lib/net/ssh/transport/server_version.rb +71 -0
  78. data/lib/net/ssh/transport/session.rb +278 -0
  79. data/lib/net/ssh/transport/state.rb +206 -0
  80. data/lib/net/ssh/verifiers/lenient.rb +30 -0
  81. data/lib/net/ssh/verifiers/null.rb +12 -0
  82. data/lib/net/ssh/verifiers/strict.rb +53 -0
  83. data/lib/net/ssh/version.rb +62 -0
  84. data/net-ssh.gemspec +164 -0
  85. data/setup.rb +1585 -0
  86. data/support/arcfour_check.rb +20 -0
  87. data/support/ssh_tunnel_bug.rb +65 -0
  88. data/test/authentication/methods/common.rb +28 -0
  89. data/test/authentication/methods/test_abstract.rb +51 -0
  90. data/test/authentication/methods/test_hostbased.rb +114 -0
  91. data/test/authentication/methods/test_keyboard_interactive.rb +100 -0
  92. data/test/authentication/methods/test_password.rb +52 -0
  93. data/test/authentication/methods/test_publickey.rb +148 -0
  94. data/test/authentication/test_agent.rb +205 -0
  95. data/test/authentication/test_key_manager.rb +218 -0
  96. data/test/authentication/test_session.rb +106 -0
  97. data/test/common.rb +107 -0
  98. data/test/configs/eqsign +3 -0
  99. data/test/configs/exact_match +8 -0
  100. data/test/configs/host_plus +10 -0
  101. data/test/configs/multihost +4 -0
  102. data/test/configs/wild_cards +14 -0
  103. data/test/connection/test_channel.rb +467 -0
  104. data/test/connection/test_session.rb +488 -0
  105. data/test/known_hosts/github +1 -0
  106. data/test/test_all.rb +9 -0
  107. data/test/test_buffer.rb +426 -0
  108. data/test/test_buffered_io.rb +63 -0
  109. data/test/test_config.rb +120 -0
  110. data/test/test_key_factory.rb +121 -0
  111. data/test/test_known_hosts.rb +13 -0
  112. data/test/transport/hmac/test_md5.rb +39 -0
  113. data/test/transport/hmac/test_md5_96.rb +25 -0
  114. data/test/transport/hmac/test_none.rb +34 -0
  115. data/test/transport/hmac/test_ripemd160.rb +34 -0
  116. data/test/transport/hmac/test_sha1.rb +34 -0
  117. data/test/transport/hmac/test_sha1_96.rb +25 -0
  118. data/test/transport/hmac/test_sha2_256.rb +35 -0
  119. data/test/transport/hmac/test_sha2_256_96.rb +25 -0
  120. data/test/transport/hmac/test_sha2_512.rb +35 -0
  121. data/test/transport/hmac/test_sha2_512_96.rb +25 -0
  122. data/test/transport/kex/test_diffie_hellman_group14_sha1.rb +13 -0
  123. data/test/transport/kex/test_diffie_hellman_group1_sha1.rb +146 -0
  124. data/test/transport/kex/test_diffie_hellman_group_exchange_sha1.rb +92 -0
  125. data/test/transport/kex/test_diffie_hellman_group_exchange_sha256.rb +33 -0
  126. data/test/transport/kex/test_ecdh_sha2_nistp256.rb +161 -0
  127. data/test/transport/kex/test_ecdh_sha2_nistp384.rb +37 -0
  128. data/test/transport/kex/test_ecdh_sha2_nistp521.rb +37 -0
  129. data/test/transport/test_algorithms.rb +330 -0
  130. data/test/transport/test_cipher_factory.rb +441 -0
  131. data/test/transport/test_hmac.rb +34 -0
  132. data/test/transport/test_identity_cipher.rb +40 -0
  133. data/test/transport/test_packet_stream.rb +1745 -0
  134. data/test/transport/test_server_version.rb +78 -0
  135. data/test/transport/test_session.rb +315 -0
  136. data/test/transport/test_state.rb +179 -0
  137. metadata +208 -0
@@ -0,0 +1,15 @@
1
+ require 'net/ssh/transport/hmac/abstract'
2
+
3
+ if defined?(OpenSSL::Digest::SHA256) # need openssl support
4
+ module Net::SSH::Transport::HMAC
5
+
6
+ # The SHA-256 HMAC algorithm. This has a mac and key length of 32, and
7
+ # uses the SHA-256 digest algorithm.
8
+ class SHA2_256 < Abstract
9
+ mac_length 32
10
+ key_length 32
11
+ digest_class OpenSSL::Digest::SHA256
12
+ end
13
+
14
+ end
15
+ end
@@ -0,0 +1,13 @@
1
+ require 'net/ssh/transport/hmac/abstract'
2
+
3
+ module Net::SSH::Transport::HMAC
4
+
5
+ if defined?(SHA2_256) # need openssl support
6
+ # The SHA256-96 HMAC algorithm. This returns only the first 12 bytes of
7
+ # the digest.
8
+ class SHA2_256_96 < SHA2_256
9
+ mac_length 12
10
+ end
11
+ end
12
+
13
+ end
@@ -0,0 +1,14 @@
1
+ require 'net/ssh/transport/hmac/abstract'
2
+
3
+ module Net::SSH::Transport::HMAC
4
+
5
+ if defined?(OpenSSL::Digest::SHA512) # need openssl support
6
+ # The SHA-512 HMAC algorithm. This has a mac and key length of 64, and
7
+ # uses the SHA-512 digest algorithm.
8
+ class SHA2_512 < Abstract
9
+ mac_length 64
10
+ key_length 64
11
+ digest_class OpenSSL::Digest::SHA512
12
+ end
13
+ end
14
+ end
@@ -0,0 +1,13 @@
1
+ require 'net/ssh/transport/hmac/abstract'
2
+
3
+ module Net::SSH::Transport::HMAC
4
+
5
+ if defined?(SHA2_512) # need openssl support
6
+ # The SHA2-512-96 HMAC algorithm. This returns only the first 12 bytes of
7
+ # the digest.
8
+ class SHA2_512_96 < SHA2_512
9
+ mac_length 12
10
+ end
11
+ end
12
+
13
+ end
@@ -0,0 +1,55 @@
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
+ # Returns an arbitrary integer.
14
+ def iv_len
15
+ 4
16
+ end
17
+
18
+ # Does nothing. Returns self.
19
+ def encrypt
20
+ self
21
+ end
22
+
23
+ # Does nothing. Returns self.
24
+ def decrypt
25
+ self
26
+ end
27
+
28
+ # Passes its single argument through unchanged.
29
+ def update(text)
30
+ text
31
+ end
32
+
33
+ # Returns the empty string.
34
+ def final
35
+ ""
36
+ end
37
+
38
+ # The name of this cipher, which is "identity".
39
+ def name
40
+ "identity"
41
+ end
42
+
43
+ # Does nothing. Returns nil.
44
+ def iv=(v)
45
+ nil
46
+ end
47
+
48
+ # Does nothing. Returns self.
49
+ def reset
50
+ self
51
+ end
52
+ end
53
+ end
54
+
55
+ end; end; end
@@ -0,0 +1,28 @@
1
+ require 'net/ssh/transport/kex/diffie_hellman_group1_sha1'
2
+ require 'net/ssh/transport/kex/diffie_hellman_group14_sha1'
3
+ require 'net/ssh/transport/kex/diffie_hellman_group_exchange_sha1'
4
+ require 'net/ssh/transport/kex/diffie_hellman_group_exchange_sha256'
5
+
6
+ module Net::SSH::Transport
7
+ module Kex
8
+ # Maps the supported key-exchange algorithms as named by the SSH protocol
9
+ # to their corresponding implementors.
10
+ MAP = {
11
+ 'diffie-hellman-group-exchange-sha1' => DiffieHellmanGroupExchangeSHA1,
12
+ 'diffie-hellman-group1-sha1' => DiffieHellmanGroup1SHA1,
13
+ 'diffie-hellman-group14-sha1' => DiffieHellmanGroup14SHA1,
14
+ }
15
+ if defined?(DiffieHellmanGroupExchangeSHA256)
16
+ MAP['diffie-hellman-group-exchange-sha256'] = DiffieHellmanGroupExchangeSHA256
17
+ end
18
+ if defined?(OpenSSL::PKey::EC)
19
+ require 'net/ssh/transport/kex/ecdh_sha2_nistp256'
20
+ require 'net/ssh/transport/kex/ecdh_sha2_nistp384'
21
+ require 'net/ssh/transport/kex/ecdh_sha2_nistp521'
22
+
23
+ MAP['ecdh-sha2-nistp256'] = EcdhSHA2NistP256
24
+ MAP['ecdh-sha2-nistp384'] = EcdhSHA2NistP384
25
+ MAP['ecdh-sha2-nistp521'] = EcdhSHA2NistP521
26
+ end
27
+ end
28
+ end
@@ -0,0 +1,44 @@
1
+ require 'net/ssh/transport/kex/diffie_hellman_group1_sha1'
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
42
+ end
43
+ end
44
+ end; end; end; end
@@ -0,0 +1,216 @@
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}'"
155
+ 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
+ end
214
+ end
215
+
216
+ end; end; end; end
@@ -0,0 +1,80 @@
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
+
23
+ # for Compatibility: OpenSSH requires (need_bits * 2 + 1) length of parameter
24
+ need_bits = data[:need_bytes] * 8 * 2 + 1
25
+
26
+ if need_bits < MINIMUM_BITS
27
+ need_bits = MINIMUM_BITS
28
+ elsif need_bits > MAXIMUM_BITS
29
+ need_bits = MAXIMUM_BITS
30
+ end
31
+
32
+ data[:need_bits ] = need_bits
33
+ data[:need_bytes] = need_bits / 8
34
+ end
35
+
36
+ # Returns the DH key parameters for the given session.
37
+ def get_parameters
38
+ compute_need_bits
39
+
40
+ # request the DH key parameters for the given number of bits.
41
+ buffer = Net::SSH::Buffer.from(:byte, KEXDH_GEX_REQUEST, :long, MINIMUM_BITS,
42
+ :long, data[:need_bits], :long, MAXIMUM_BITS)
43
+ connection.send_message(buffer)
44
+
45
+ buffer = connection.next_message
46
+ unless buffer.type == KEXDH_GEX_GROUP
47
+ raise Net::SSH::Exception, "expected KEXDH_GEX_GROUP, got #{buffer.type}"
48
+ end
49
+
50
+ p = buffer.read_bignum
51
+ g = buffer.read_bignum
52
+
53
+ [p, g]
54
+ end
55
+
56
+ # Returns the INIT/REPLY constants used by this algorithm.
57
+ def get_message_types
58
+ [KEXDH_GEX_INIT, KEXDH_GEX_REPLY]
59
+ end
60
+
61
+ # Build the signature buffer to use when verifying a signature from
62
+ # the server.
63
+ def build_signature_buffer(result)
64
+ response = Net::SSH::Buffer.new
65
+ response.write_string data[:client_version_string],
66
+ data[:server_version_string],
67
+ data[:client_algorithm_packet],
68
+ data[:server_algorithm_packet],
69
+ result[:key_blob]
70
+ response.write_long MINIMUM_BITS,
71
+ data[:need_bits],
72
+ MAXIMUM_BITS
73
+ response.write_bignum dh.p, dh.g, dh.pub_key,
74
+ result[:server_dh_pubkey],
75
+ result[:shared_secret]
76
+ response
77
+ end
78
+ end
79
+
80
+ end