net-ssh 4.1.0 → 6.1.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.
- checksums.yaml +5 -5
- checksums.yaml.gz.sig +0 -0
- data.tar.gz.sig +0 -0
- data/.gitignore +5 -0
- data/.rubocop.yml +8 -2
- data/.rubocop_todo.yml +405 -552
- data/.travis.yml +23 -22
- data/CHANGES.txt +112 -1
- data/Gemfile +1 -7
- data/{Gemfile.norbnacl → Gemfile.noed25519} +1 -1
- data/Manifest +4 -5
- data/README.md +287 -0
- data/Rakefile +40 -29
- data/appveyor.yml +12 -6
- data/lib/net/ssh.rb +68 -32
- data/lib/net/ssh/authentication/agent.rb +234 -222
- data/lib/net/ssh/authentication/certificate.rb +175 -164
- data/lib/net/ssh/authentication/constants.rb +17 -14
- data/lib/net/ssh/authentication/ed25519.rb +162 -141
- data/lib/net/ssh/authentication/ed25519_loader.rb +32 -29
- data/lib/net/ssh/authentication/key_manager.rb +40 -9
- data/lib/net/ssh/authentication/methods/abstract.rb +53 -47
- data/lib/net/ssh/authentication/methods/hostbased.rb +32 -33
- data/lib/net/ssh/authentication/methods/keyboard_interactive.rb +1 -1
- data/lib/net/ssh/authentication/methods/none.rb +10 -10
- data/lib/net/ssh/authentication/methods/password.rb +13 -13
- data/lib/net/ssh/authentication/methods/publickey.rb +56 -55
- data/lib/net/ssh/authentication/pageant.rb +468 -465
- data/lib/net/ssh/authentication/pub_key_fingerprint.rb +43 -0
- data/lib/net/ssh/authentication/session.rb +130 -122
- data/lib/net/ssh/buffer.rb +345 -312
- data/lib/net/ssh/buffered_io.rb +163 -163
- data/lib/net/ssh/config.rb +316 -238
- data/lib/net/ssh/connection/channel.rb +670 -650
- data/lib/net/ssh/connection/constants.rb +30 -26
- data/lib/net/ssh/connection/event_loop.rb +108 -105
- data/lib/net/ssh/connection/keepalive.rb +54 -50
- data/lib/net/ssh/connection/session.rb +682 -671
- data/lib/net/ssh/connection/term.rb +180 -176
- data/lib/net/ssh/errors.rb +101 -99
- data/lib/net/ssh/key_factory.rb +195 -108
- data/lib/net/ssh/known_hosts.rb +161 -152
- data/lib/net/ssh/loggable.rb +57 -55
- data/lib/net/ssh/packet.rb +82 -78
- data/lib/net/ssh/prompt.rb +55 -53
- data/lib/net/ssh/proxy/command.rb +104 -89
- data/lib/net/ssh/proxy/errors.rb +12 -8
- data/lib/net/ssh/proxy/http.rb +93 -91
- data/lib/net/ssh/proxy/https.rb +42 -39
- data/lib/net/ssh/proxy/jump.rb +50 -47
- data/lib/net/ssh/proxy/socks4.rb +0 -2
- data/lib/net/ssh/proxy/socks5.rb +11 -12
- data/lib/net/ssh/service/forward.rb +370 -317
- data/lib/net/ssh/test.rb +83 -77
- data/lib/net/ssh/test/channel.rb +146 -142
- data/lib/net/ssh/test/extensions.rb +150 -146
- data/lib/net/ssh/test/kex.rb +35 -31
- data/lib/net/ssh/test/local_packet.rb +48 -44
- data/lib/net/ssh/test/packet.rb +87 -84
- data/lib/net/ssh/test/remote_packet.rb +35 -31
- data/lib/net/ssh/test/script.rb +173 -171
- data/lib/net/ssh/test/socket.rb +59 -55
- data/lib/net/ssh/transport/algorithms.rb +430 -364
- data/lib/net/ssh/transport/cipher_factory.rb +95 -91
- data/lib/net/ssh/transport/constants.rb +33 -25
- data/lib/net/ssh/transport/ctr.rb +33 -11
- data/lib/net/ssh/transport/hmac.rb +15 -13
- data/lib/net/ssh/transport/hmac/abstract.rb +82 -63
- data/lib/net/ssh/transport/hmac/sha2_256.rb +7 -11
- data/lib/net/ssh/transport/hmac/sha2_256_96.rb +4 -8
- data/lib/net/ssh/transport/hmac/sha2_256_etm.rb +12 -0
- data/lib/net/ssh/transport/hmac/sha2_512.rb +6 -9
- data/lib/net/ssh/transport/hmac/sha2_512_96.rb +4 -8
- data/lib/net/ssh/transport/hmac/sha2_512_etm.rb +12 -0
- data/lib/net/ssh/transport/identity_cipher.rb +55 -51
- data/lib/net/ssh/transport/kex.rb +14 -13
- data/lib/net/ssh/transport/kex/abstract.rb +123 -0
- data/lib/net/ssh/transport/kex/abstract5656.rb +72 -0
- data/lib/net/ssh/transport/kex/curve25519_sha256.rb +38 -0
- data/lib/net/ssh/transport/kex/curve25519_sha256_loader.rb +30 -0
- data/lib/net/ssh/transport/kex/diffie_hellman_group14_sha1.rb +33 -40
- data/lib/net/ssh/transport/kex/diffie_hellman_group1_sha1.rb +112 -217
- data/lib/net/ssh/transport/kex/diffie_hellman_group_exchange_sha1.rb +53 -62
- data/lib/net/ssh/transport/kex/diffie_hellman_group_exchange_sha256.rb +5 -9
- data/lib/net/ssh/transport/kex/ecdh_sha2_nistp256.rb +36 -90
- data/lib/net/ssh/transport/kex/ecdh_sha2_nistp384.rb +18 -10
- data/lib/net/ssh/transport/kex/ecdh_sha2_nistp521.rb +18 -10
- data/lib/net/ssh/transport/key_expander.rb +29 -25
- data/lib/net/ssh/transport/openssl.rb +116 -116
- data/lib/net/ssh/transport/packet_stream.rb +223 -190
- data/lib/net/ssh/transport/server_version.rb +64 -66
- data/lib/net/ssh/transport/session.rb +306 -257
- data/lib/net/ssh/transport/state.rb +198 -196
- data/lib/net/ssh/verifiers/accept_new.rb +35 -0
- data/lib/net/ssh/verifiers/accept_new_or_local_tunnel.rb +34 -0
- data/lib/net/ssh/verifiers/always.rb +56 -0
- data/lib/net/ssh/verifiers/never.rb +21 -0
- data/lib/net/ssh/version.rb +55 -53
- data/net-ssh-public_cert.pem +18 -19
- data/net-ssh.gemspec +12 -11
- data/support/ssh_tunnel_bug.rb +2 -2
- metadata +86 -75
- metadata.gz.sig +0 -0
- data/Gemfile.norbnacl.lock +0 -41
- data/README.rdoc +0 -169
- data/lib/net/ssh/ruby_compat.rb +0 -24
- data/lib/net/ssh/verifiers/lenient.rb +0 -30
- data/lib/net/ssh/verifiers/null.rb +0 -12
- data/lib/net/ssh/verifiers/secure.rb +0 -52
- data/lib/net/ssh/verifiers/strict.rb +0 -24
- data/support/arcfour_check.rb +0 -20
@@ -0,0 +1,38 @@
|
|
1
|
+
gem 'x25519' # raise if the gem x25519 is not installed
|
2
|
+
|
3
|
+
require 'x25519'
|
4
|
+
require 'net/ssh/transport/constants'
|
5
|
+
require 'net/ssh/transport/kex/abstract5656'
|
6
|
+
|
7
|
+
module Net
|
8
|
+
module SSH
|
9
|
+
module Transport
|
10
|
+
module Kex
|
11
|
+
# A key-exchange service implementing the "curve25519-sha256@libssh.org"
|
12
|
+
# key-exchange algorithm. (defined in https://tools.ietf.org/html/draft-ietf-curdle-ssh-curves-06)
|
13
|
+
class Curve25519Sha256 < Abstract5656
|
14
|
+
def digester
|
15
|
+
OpenSSL::Digest::SHA256
|
16
|
+
end
|
17
|
+
|
18
|
+
private
|
19
|
+
|
20
|
+
def generate_key #:nodoc:
|
21
|
+
::X25519::Scalar.generate
|
22
|
+
end
|
23
|
+
|
24
|
+
## string Q_C, client's ephemeral public key octet string
|
25
|
+
def ecdh_public_key_bytes
|
26
|
+
ecdh.public_key.to_bytes
|
27
|
+
end
|
28
|
+
|
29
|
+
# compute shared secret from server's public key and client's private key
|
30
|
+
def compute_shared_secret(server_ecdh_pubkey)
|
31
|
+
pk = ::X25519::MontgomeryU.new(server_ecdh_pubkey)
|
32
|
+
OpenSSL::BN.new(ecdh.diffie_hellman(pk).to_bytes, 2)
|
33
|
+
end
|
34
|
+
end
|
35
|
+
end
|
36
|
+
end
|
37
|
+
end
|
38
|
+
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
|
4
|
-
|
5
|
-
|
6
|
-
|
7
|
-
|
8
|
-
|
9
|
-
|
10
|
-
|
11
|
-
|
12
|
-
|
13
|
-
|
14
|
-
|
15
|
-
|
16
|
-
|
17
|
-
|
18
|
-
|
19
|
-
|
20
|
-
|
21
|
-
|
22
|
-
|
23
|
-
|
24
|
-
|
25
|
-
|
26
|
-
|
27
|
-
|
28
|
-
|
29
|
-
|
30
|
-
|
31
|
-
|
32
|
-
|
33
|
-
|
34
|
-
|
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
|
37
|
+
end
|
@@ -1,227 +1,122 @@
|
|
1
|
-
require 'net/ssh/
|
2
|
-
|
3
|
-
|
4
|
-
|
5
|
-
|
6
|
-
|
7
|
-
|
8
|
-
|
9
|
-
|
10
|
-
|
11
|
-
|
12
|
-
|
13
|
-
|
14
|
-
|
15
|
-
|
16
|
-
|
17
|
-
|
18
|
-
|
19
|
-
|
20
|
-
|
21
|
-
|
22
|
-
|
23
|
-
|
24
|
-
|
25
|
-
|
26
|
-
|
27
|
-
|
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
|
-
if dh.respond_to?(:set_pqg)
|
119
|
-
p, g = get_parameters
|
120
|
-
dh.set_pqg(p, nil, g)
|
121
|
-
else
|
122
|
-
dh.p, dh.g = get_parameters
|
123
|
-
end
|
124
|
-
|
125
|
-
dh.generate_key!
|
126
|
-
until dh.valid? && dh.priv_key.num_bytes == data[:need_bytes]
|
127
|
-
if dh.respond_to?(:set_key)
|
128
|
-
dh.set_key(nil, OpenSSL::BN.rand(data[:need_bytes] * 8))
|
129
|
-
else
|
130
|
-
dh.priv_key = OpenSSL::BN.rand(data[:need_bytes] * 8)
|
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
|
131
28
|
end
|
132
|
-
dh.generate_key!
|
133
|
-
end
|
134
|
-
dh
|
135
|
-
end
|
136
29
|
|
137
|
-
|
138
|
-
# resulting buffer.
|
139
|
-
#
|
140
|
-
# Parse the buffer from a KEXDH_REPLY message, returning a hash of
|
141
|
-
# the extracted values.
|
142
|
-
def send_kexinit #:nodoc:
|
143
|
-
init, reply = get_message_types
|
144
|
-
|
145
|
-
# send the KEXDH_INIT message
|
146
|
-
buffer = Net::SSH::Buffer.from(:byte, init, :bignum, dh.pub_key)
|
147
|
-
connection.send_message(buffer)
|
148
|
-
|
149
|
-
# expect the KEXDH_REPLY message
|
150
|
-
buffer = connection.next_message
|
151
|
-
raise Net::SSH::Exception, "expected REPLY" unless buffer.type == reply
|
152
|
-
|
153
|
-
result = Hash.new
|
154
|
-
|
155
|
-
result[:key_blob] = buffer.read_string
|
156
|
-
result[:server_key] = Net::SSH::Buffer.new(result[:key_blob]).read_key
|
157
|
-
result[:server_dh_pubkey] = buffer.read_bignum
|
158
|
-
result[:shared_secret] = OpenSSL::BN.new(dh.compute_key(result[:server_dh_pubkey]), 2)
|
159
|
-
|
160
|
-
sig_buffer = Net::SSH::Buffer.new(buffer.read_string)
|
161
|
-
sig_type = sig_buffer.read_string
|
162
|
-
if sig_type != algorithms.host_key
|
163
|
-
raise Net::SSH::Exception,
|
164
|
-
"host key algorithm mismatch for signature " +
|
165
|
-
"'#{sig_type}' != '#{algorithms.host_key}'"
|
166
|
-
end
|
167
|
-
result[:server_sig] = sig_buffer.read_string
|
168
|
-
|
169
|
-
return result
|
170
|
-
end
|
171
|
-
|
172
|
-
# Verify that the given key is of the expected type, and that it
|
173
|
-
# really is the key for the session's host. Raise Net::SSH::Exception
|
174
|
-
# if it is not.
|
175
|
-
def verify_server_key(key) #:nodoc:
|
176
|
-
if key.ssh_type != algorithms.host_key
|
177
|
-
raise Net::SSH::Exception,
|
178
|
-
"host key algorithm mismatch " +
|
179
|
-
"'#{key.ssh_type}' != '#{algorithms.host_key}'"
|
180
|
-
end
|
30
|
+
private
|
181
31
|
|
182
|
-
|
183
|
-
|
184
|
-
|
185
|
-
|
186
|
-
|
187
|
-
|
188
|
-
|
189
|
-
def generate_key_fingerprint(key)
|
190
|
-
blob = Net::SSH::Buffer.from(:key, key).to_s
|
191
|
-
fingerprint = OpenSSL::Digest::MD5.hexdigest(blob).scan(/../).join(":")
|
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
|
192
39
|
|
193
|
-
|
194
|
-
|
195
|
-
|
196
|
-
|
40
|
+
# Returns the INIT/REPLY constants used by this algorithm.
|
41
|
+
def get_message_types
|
42
|
+
[KEXDH_INIT, KEXDH_REPLY]
|
43
|
+
end
|
197
44
|
|
198
|
-
|
199
|
-
|
200
|
-
|
201
|
-
|
202
|
-
|
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
|
203
59
|
|
204
|
-
|
60
|
+
# Generate a DH key with a private key consisting of the given
|
61
|
+
# number of bytes.
|
62
|
+
def generate_key #:nodoc:
|
63
|
+
dh = OpenSSL::PKey::DH.new
|
64
|
+
|
65
|
+
if dh.respond_to?(:set_pqg)
|
66
|
+
p, g = get_parameters
|
67
|
+
dh.set_pqg(p, nil, g)
|
68
|
+
else
|
69
|
+
dh.p, dh.g = get_parameters
|
70
|
+
end
|
71
|
+
|
72
|
+
dh.generate_key!
|
73
|
+
until dh.valid? && dh.priv_key.num_bytes == data[:need_bytes]
|
74
|
+
if dh.respond_to?(:set_key)
|
75
|
+
dh.set_key(nil, OpenSSL::BN.rand(data[:need_bytes] * 8))
|
76
|
+
else
|
77
|
+
dh.priv_key = OpenSSL::BN.rand(data[:need_bytes] * 8)
|
78
|
+
end
|
79
|
+
dh.generate_key!
|
80
|
+
end
|
81
|
+
dh
|
82
|
+
end
|
205
83
|
|
206
|
-
|
207
|
-
|
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
|
208
118
|
end
|
209
|
-
|
210
|
-
return hash
|
211
|
-
end
|
212
|
-
|
213
|
-
# Send the NEWKEYS message, and expect the NEWKEYS message in
|
214
|
-
# reply.
|
215
|
-
def confirm_newkeys #:nodoc:
|
216
|
-
# send own NEWKEYS message first (the wodSSHServer won't send first)
|
217
|
-
response = Net::SSH::Buffer.new
|
218
|
-
response.write_byte(NEWKEYS)
|
219
|
-
connection.send_message(response)
|
220
|
-
|
221
|
-
# wait for the server's NEWKEYS message
|
222
|
-
buffer = connection.next_message
|
223
|
-
raise Net::SSH::Exception, "expected NEWKEYS" unless buffer.type == NEWKEYS
|
224
119
|
end
|
120
|
+
end
|
225
121
|
end
|
226
|
-
|
227
|
-
end; end; end; end
|
122
|
+
end
|