net-ssh 5.2.0 → 6.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.
- checksums.yaml +5 -5
- checksums.yaml.gz.sig +0 -0
- data.tar.gz.sig +0 -0
- data/.gitignore +1 -0
- data/.rubocop.yml +7 -4
- data/.rubocop_todo.yml +392 -379
- data/.travis.yml +16 -17
- data/CHANGES.txt +11 -0
- data/Manifest +0 -1
- data/README.md +286 -0
- data/Rakefile +1 -2
- data/appveyor.yml +4 -2
- data/lib/net/ssh.rb +7 -2
- data/lib/net/ssh/authentication/certificate.rb +10 -1
- data/lib/net/ssh/authentication/ed25519.rb +2 -1
- data/lib/net/ssh/authentication/ed25519_loader.rb +1 -1
- data/lib/net/ssh/authentication/key_manager.rb +34 -5
- data/lib/net/ssh/authentication/methods/keyboard_interactive.rb +3 -1
- data/lib/net/ssh/authentication/pub_key_fingerprint.rb +0 -1
- data/lib/net/ssh/authentication/session.rb +9 -6
- data/lib/net/ssh/buffer.rb +1 -10
- data/lib/net/ssh/buffered_io.rb +0 -1
- data/lib/net/ssh/config.rb +51 -32
- data/lib/net/ssh/connection/channel.rb +17 -5
- data/lib/net/ssh/connection/event_loop.rb +0 -1
- data/lib/net/ssh/connection/session.rb +7 -4
- data/lib/net/ssh/key_factory.rb +6 -8
- data/lib/net/ssh/known_hosts.rb +27 -29
- data/lib/net/ssh/loggable.rb +2 -2
- data/lib/net/ssh/proxy/command.rb +0 -1
- data/lib/net/ssh/proxy/socks5.rb +0 -1
- data/lib/net/ssh/service/forward.rb +2 -1
- data/lib/net/ssh/test.rb +3 -2
- data/lib/net/ssh/transport/algorithms.rb +67 -42
- data/lib/net/ssh/transport/cipher_factory.rb +11 -27
- data/lib/net/ssh/transport/constants.rb +10 -6
- data/lib/net/ssh/transport/ctr.rb +1 -7
- data/lib/net/ssh/transport/hmac.rb +15 -13
- data/lib/net/ssh/transport/hmac/abstract.rb +16 -0
- 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/kex.rb +14 -11
- 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 +1 -15
- data/lib/net/ssh/transport/kex/diffie_hellman_group1_sha1.rb +9 -118
- data/lib/net/ssh/transport/kex/diffie_hellman_group_exchange_sha1.rb +0 -6
- data/lib/net/ssh/transport/kex/diffie_hellman_group_exchange_sha256.rb +5 -9
- data/lib/net/ssh/transport/kex/ecdh_sha2_nistp256.rb +18 -79
- data/lib/net/ssh/transport/kex/ecdh_sha2_nistp384.rb +5 -4
- data/lib/net/ssh/transport/kex/ecdh_sha2_nistp521.rb +5 -4
- data/lib/net/ssh/transport/openssl.rb +104 -107
- data/lib/net/ssh/transport/packet_stream.rb +44 -11
- data/lib/net/ssh/transport/state.rb +1 -1
- data/lib/net/ssh/version.rb +2 -2
- data/net-ssh-public_cert.pem +8 -8
- data/net-ssh.gemspec +9 -7
- metadata +46 -29
- metadata.gz.sig +2 -3
- data/Gemfile.noed25519.lock +0 -41
- data/README.rdoc +0 -194
- data/lib/net/ssh/ruby_compat.rb +0 -13
- data/support/arcfour_check.rb +0 -20
data/lib/net/ssh/known_hosts.rb
CHANGED
@@ -41,14 +41,11 @@ module Net
|
|
41
41
|
# This is used internally by Net::SSH, and will never need to be used directly
|
42
42
|
# by consumers of the library.
|
43
43
|
class KnownHosts
|
44
|
-
|
45
|
-
|
46
|
-
|
47
|
-
|
48
|
-
|
49
|
-
else
|
50
|
-
SUPPORTED_TYPE = %w[ssh-rsa ssh-dss]
|
51
|
-
end
|
44
|
+
SUPPORTED_TYPE = %w[ssh-rsa ssh-dss
|
45
|
+
ecdsa-sha2-nistp256
|
46
|
+
ecdsa-sha2-nistp384
|
47
|
+
ecdsa-sha2-nistp521]
|
48
|
+
|
52
49
|
SUPPORTED_TYPE.push('ssh-ed25519') if Net::SSH::Authentication::ED25519Loader::LOADED
|
53
50
|
|
54
51
|
class <<self
|
@@ -78,7 +75,9 @@ module Net
|
|
78
75
|
|
79
76
|
files += Array(options[:user_known_hosts_file] || %w[~/.ssh/known_hosts ~/.ssh/known_hosts2]) if which == :all || which == :user
|
80
77
|
|
81
|
-
|
78
|
+
if which == :all || which == :global
|
79
|
+
files += Array(options[:global_known_hosts_file] || %w[/etc/ssh/ssh_known_hosts /etc/ssh/ssh_known_hosts2])
|
80
|
+
end
|
82
81
|
|
83
82
|
return files
|
84
83
|
end
|
@@ -130,27 +129,22 @@ module Net
|
|
130
129
|
host_ip = entries[1]
|
131
130
|
|
132
131
|
File.open(source) do |file|
|
133
|
-
scanner = StringScanner.new("")
|
134
132
|
file.each_line do |line|
|
135
|
-
|
133
|
+
hosts, type, key_content = line.split(' ')
|
134
|
+
# Skip empty line or one that is commented
|
135
|
+
next if hosts.nil? || hosts.start_with?('#')
|
136
136
|
|
137
|
-
|
138
|
-
|
137
|
+
hostlist = hosts.split(',')
|
138
|
+
|
139
|
+
next unless SUPPORTED_TYPE.include?(type)
|
139
140
|
|
140
|
-
hostlist = scanner.scan(/\S+/).split(/,/)
|
141
141
|
found = hostlist.any? { |pattern| match(host_name, pattern) } || known_host_hash?(hostlist, entries)
|
142
142
|
next unless found
|
143
143
|
|
144
144
|
found = hostlist.include?(host_ip) if options[:check_host_ip] && entries.size > 1 && hostlist.size > 1
|
145
145
|
next unless found
|
146
146
|
|
147
|
-
|
148
|
-
type = scanner.scan(/\S+/)
|
149
|
-
|
150
|
-
next unless SUPPORTED_TYPE.include?(type)
|
151
|
-
|
152
|
-
scanner.skip(/\s*/)
|
153
|
-
blob = scanner.rest.unpack("m*").first
|
147
|
+
blob = key_content.unpack("m*").first
|
154
148
|
keys << Net::SSH::Buffer.new(blob).read_key
|
155
149
|
end
|
156
150
|
end
|
@@ -159,14 +153,18 @@ module Net
|
|
159
153
|
end
|
160
154
|
|
161
155
|
def match(host, pattern)
|
162
|
-
|
163
|
-
|
164
|
-
|
165
|
-
|
166
|
-
|
167
|
-
|
168
|
-
|
169
|
-
|
156
|
+
if pattern.include?('*') || pattern.include?('?')
|
157
|
+
# see man 8 sshd for pattern details
|
158
|
+
pattern_regexp = pattern.split('*').map do |x|
|
159
|
+
x.split('?').map do |y|
|
160
|
+
Regexp.escape(y)
|
161
|
+
end.join('.')
|
162
|
+
end.join('[^.]*')
|
163
|
+
|
164
|
+
host =~ Regexp.new("\\A#{pattern_regexp}\\z")
|
165
|
+
else
|
166
|
+
host == pattern
|
167
|
+
end
|
170
168
|
end
|
171
169
|
|
172
170
|
# Indicates whether one of the entries matches an hostname that has been
|
data/lib/net/ssh/loggable.rb
CHANGED
@@ -56,8 +56,8 @@ module Net
|
|
56
56
|
# originates. It defaults to the name of class with the object_id
|
57
57
|
# appended.
|
58
58
|
def facility
|
59
|
-
@facility ||= self.class.
|
59
|
+
@facility ||= self.class.to_s.gsub(/::/, ".").gsub(/([a-z])([A-Z])/, "\\1_\\2").downcase + "[%x]" % object_id
|
60
60
|
end
|
61
61
|
end
|
62
62
|
end
|
63
|
-
end
|
63
|
+
end
|
data/lib/net/ssh/proxy/socks5.rb
CHANGED
@@ -85,7 +85,8 @@ module Net
|
|
85
85
|
client = server.accept
|
86
86
|
debug { "received connection on #{socket}" }
|
87
87
|
|
88
|
-
channel = session.open_channel("direct-tcpip", :string, remote_host, :long,
|
88
|
+
channel = session.open_channel("direct-tcpip", :string, remote_host, :long,
|
89
|
+
remote_port, :string, bind_address, local_port_type, local_port) do |achannel|
|
89
90
|
achannel.info { "direct channel established" }
|
90
91
|
end
|
91
92
|
|
data/lib/net/ssh/test.rb
CHANGED
@@ -74,7 +74,7 @@ module Net
|
|
74
74
|
def transport(options={})
|
75
75
|
@transport ||= Net::SSH::Transport::Session.new(
|
76
76
|
options[:host] || "localhost",
|
77
|
-
options.merge(kex: "test", host_key: "ssh-rsa", verify_host_key: :never, proxy: socket(options))
|
77
|
+
options.merge(kex: "test", host_key: "ssh-rsa", append_all_supported_algorithms: true, verify_host_key: :never, proxy: socket(options))
|
78
78
|
)
|
79
79
|
end
|
80
80
|
|
@@ -86,7 +86,8 @@ module Net
|
|
86
86
|
def assert_scripted
|
87
87
|
raise "there is no script to be processed" if socket.script.events.empty?
|
88
88
|
Net::SSH::Test::Extensions::IO.with_test_extension { yield }
|
89
|
-
assert socket.script.events.empty?, "there should not be any remaining scripted events, but there are still
|
89
|
+
assert socket.script.events.empty?, "there should not be any remaining scripted events, but there are still" \
|
90
|
+
"#{socket.script.events.length} pending"
|
90
91
|
end
|
91
92
|
end
|
92
93
|
|
@@ -5,13 +5,13 @@ require 'net/ssh/transport/cipher_factory'
|
|
5
5
|
require 'net/ssh/transport/constants'
|
6
6
|
require 'net/ssh/transport/hmac'
|
7
7
|
require 'net/ssh/transport/kex'
|
8
|
+
require 'net/ssh/transport/kex/curve25519_sha256_loader'
|
8
9
|
require 'net/ssh/transport/server_version'
|
9
10
|
require 'net/ssh/authentication/ed25519_loader'
|
10
11
|
|
11
12
|
module Net
|
12
13
|
module SSH
|
13
14
|
module Transport
|
14
|
-
|
15
15
|
# Implements the higher-level logic behind an SSH key-exchange. It handles
|
16
16
|
# both the initial exchange, as well as subsequent re-exchanges (as needed).
|
17
17
|
# It also encapsulates the negotiation of the algorithms, and provides a
|
@@ -23,56 +23,72 @@ module Net
|
|
23
23
|
include Loggable
|
24
24
|
include Constants
|
25
25
|
|
26
|
-
# Define the default algorithms, in order of preference, supported by
|
27
|
-
|
28
|
-
|
29
|
-
|
26
|
+
# Define the default algorithms, in order of preference, supported by Net::SSH.
|
27
|
+
DEFAULT_ALGORITHMS = {
|
28
|
+
host_key: %w[ecdsa-sha2-nistp521-cert-v01@openssh.com
|
29
|
+
ecdsa-sha2-nistp384-cert-v01@openssh.com
|
30
|
+
ecdsa-sha2-nistp256-cert-v01@openssh.com
|
31
|
+
ecdsa-sha2-nistp521
|
32
|
+
ecdsa-sha2-nistp384
|
33
|
+
ecdsa-sha2-nistp256
|
34
|
+
ssh-rsa-cert-v01@openssh.com
|
30
35
|
ssh-rsa-cert-v00@openssh.com
|
31
|
-
ssh-rsa
|
32
|
-
|
33
|
-
|
34
|
-
|
36
|
+
ssh-rsa],
|
37
|
+
|
38
|
+
kex: %w[ecdh-sha2-nistp521
|
39
|
+
ecdh-sha2-nistp384
|
40
|
+
ecdh-sha2-nistp256
|
41
|
+
diffie-hellman-group-exchange-sha256
|
42
|
+
diffie-hellman-group14-sha1],
|
43
|
+
|
44
|
+
encryption: %w[aes256-ctr aes192-ctr aes128-ctr],
|
45
|
+
|
46
|
+
hmac: %w[hmac-sha2-512-etm@openssh.com hmac-sha2-256-etm@openssh.com
|
47
|
+
hmac-sha2-512 hmac-sha2-256
|
48
|
+
hmac-sha1]
|
49
|
+
}.freeze
|
50
|
+
|
51
|
+
if Net::SSH::Authentication::ED25519Loader::LOADED
|
52
|
+
DEFAULT_ALGORITHMS[:host_key].unshift(
|
53
|
+
'ssh-ed25519-cert-v01@openssh.com',
|
54
|
+
'ssh-ed25519'
|
55
|
+
)
|
56
|
+
end
|
57
|
+
|
58
|
+
if Net::SSH::Transport::Kex::Curve25519Sha256Loader::LOADED
|
59
|
+
DEFAULT_ALGORITHMS[:kex].unshift(
|
60
|
+
'curve25519-sha256',
|
61
|
+
'curve25519-sha256@libssh.org'
|
62
|
+
)
|
63
|
+
end
|
64
|
+
|
65
|
+
# Define all algorithms, with the deprecated, supported by Net::SSH.
|
66
|
+
ALGORITHMS = {
|
67
|
+
host_key: DEFAULT_ALGORITHMS[:host_key] + %w[ssh-dss],
|
68
|
+
|
69
|
+
kex: DEFAULT_ALGORITHMS[:kex] +
|
70
|
+
%w[diffie-hellman-group-exchange-sha1
|
35
71
|
diffie-hellman-group1-sha1],
|
36
|
-
|
37
|
-
|
72
|
+
|
73
|
+
encryption: DEFAULT_ALGORITHMS[:encryption] +
|
74
|
+
%w[aes256-cbc aes192-cbc aes128-cbc
|
38
75
|
rijndael-cbc@lysator.liu.se
|
39
76
|
blowfish-ctr blowfish-cbc
|
40
77
|
cast128-ctr cast128-cbc
|
41
78
|
3des-ctr 3des-cbc
|
42
|
-
idea-cbc
|
79
|
+
idea-cbc
|
43
80
|
none],
|
44
81
|
|
45
|
-
hmac:
|
46
|
-
|
47
|
-
hmac-sha1
|
82
|
+
hmac: DEFAULT_ALGORITHMS[:hmac] +
|
83
|
+
%w[hmac-sha2-512-96 hmac-sha2-256-96
|
84
|
+
hmac-sha1-96
|
48
85
|
hmac-ripemd160 hmac-ripemd160@openssh.com
|
49
86
|
hmac-md5 hmac-md5-96
|
50
87
|
none],
|
51
88
|
|
52
89
|
compression: %w[none zlib@openssh.com zlib],
|
53
90
|
language: %w[]
|
54
|
-
}
|
55
|
-
if defined?(OpenSSL::PKey::EC)
|
56
|
-
ALGORITHMS[:host_key].unshift(
|
57
|
-
"ecdsa-sha2-nistp521-cert-v01@openssh.com",
|
58
|
-
"ecdsa-sha2-nistp384-cert-v01@openssh.com",
|
59
|
-
"ecdsa-sha2-nistp256-cert-v01@openssh.com",
|
60
|
-
"ecdsa-sha2-nistp521",
|
61
|
-
"ecdsa-sha2-nistp384",
|
62
|
-
"ecdsa-sha2-nistp256"
|
63
|
-
)
|
64
|
-
if Net::SSH::Authentication::ED25519Loader::LOADED
|
65
|
-
ALGORITHMS[:host_key].unshift(
|
66
|
-
"ssh-ed25519-cert-v01@openssh.com",
|
67
|
-
"ssh-ed25519"
|
68
|
-
)
|
69
|
-
end
|
70
|
-
ALGORITHMS[:kex].unshift(
|
71
|
-
"ecdh-sha2-nistp521",
|
72
|
-
"ecdh-sha2-nistp384",
|
73
|
-
"ecdh-sha2-nistp256"
|
74
|
-
)
|
75
|
-
end
|
91
|
+
}.freeze
|
76
92
|
|
77
93
|
# The underlying transport layer session that supports this object
|
78
94
|
attr_reader :session
|
@@ -140,6 +156,7 @@ module Net
|
|
140
156
|
# Start the algorithm negotation
|
141
157
|
def start
|
142
158
|
raise ArgumentError, "Cannot call start if it's negotiation started or done" if @pending || @initialized
|
159
|
+
|
143
160
|
send_kexinit
|
144
161
|
end
|
145
162
|
|
@@ -197,8 +214,8 @@ module Net
|
|
197
214
|
|
198
215
|
def host_key_format
|
199
216
|
case host_key
|
200
|
-
when
|
201
|
-
|
217
|
+
when /^([a-z0-9-]+)-cert-v\d{2}@openssh.com$/
|
218
|
+
Regexp.last_match[1]
|
202
219
|
else
|
203
220
|
host_key
|
204
221
|
end
|
@@ -239,7 +256,10 @@ module Net
|
|
239
256
|
options[:compression] = %w[zlib@openssh.com zlib] if options[:compression] == true
|
240
257
|
|
241
258
|
ALGORITHMS.each do |algorithm, supported|
|
242
|
-
algorithms[algorithm] = compose_algorithm_list(
|
259
|
+
algorithms[algorithm] = compose_algorithm_list(
|
260
|
+
supported, options[algorithm] || DEFAULT_ALGORITHMS[algorithm],
|
261
|
+
options[:append_all_supported_algorithms]
|
262
|
+
)
|
243
263
|
end
|
244
264
|
|
245
265
|
# for convention, make sure our list has the same keys as the server
|
@@ -356,7 +376,8 @@ module Net
|
|
356
376
|
|
357
377
|
debug do
|
358
378
|
"negotiated:\n" +
|
359
|
-
%i[kex host_key encryption_server encryption_client hmac_client hmac_server
|
379
|
+
%i[kex host_key encryption_server encryption_client hmac_client hmac_server
|
380
|
+
compression_client compression_server language_client language_server].map do |key|
|
360
381
|
"* #{key}: #{instance_variable_get("@#{key}")}"
|
361
382
|
end.join("\n")
|
362
383
|
end
|
@@ -368,7 +389,11 @@ module Net
|
|
368
389
|
def negotiate(algorithm)
|
369
390
|
match = self[algorithm].find { |item| @server_data[algorithm].include?(item) }
|
370
391
|
|
371
|
-
|
392
|
+
if match.nil?
|
393
|
+
raise Net::SSH::Exception, "could not settle on #{algorithm} algorithm\n"\
|
394
|
+
"Server #{algorithm} preferences: #{@server_data[algorithm].join(',')}\n"\
|
395
|
+
"Client #{algorithm} preferences: #{self[algorithm].join(',')}"
|
396
|
+
end
|
372
397
|
|
373
398
|
return match
|
374
399
|
end
|
@@ -19,30 +19,17 @@ module Net
|
|
19
19
|
"idea-cbc" => "idea-cbc",
|
20
20
|
"cast128-cbc" => "cast-cbc",
|
21
21
|
"rijndael-cbc@lysator.liu.se" => "aes-256-cbc",
|
22
|
-
"arcfour128" => "rc4",
|
23
|
-
"arcfour256" => "rc4",
|
24
|
-
"arcfour512" => "rc4",
|
25
|
-
"arcfour" => "rc4",
|
26
|
-
|
27
22
|
"3des-ctr" => "des-ede3",
|
28
23
|
"blowfish-ctr" => "bf-ecb",
|
29
|
-
|
30
|
-
|
31
|
-
|
32
|
-
|
33
|
-
|
34
|
-
|
35
|
-
|
36
|
-
}
|
37
|
-
|
38
|
-
# Ruby's OpenSSL bindings always return a key length of 16 for RC4 ciphers
|
39
|
-
# resulting in the error: OpenSSL::CipherError: key length too short.
|
40
|
-
# The following ciphers will override this key length.
|
41
|
-
KEY_LEN_OVERRIDE = {
|
42
|
-
"arcfour256" => 32,
|
43
|
-
"arcfour512" => 64
|
24
|
+
|
25
|
+
'aes256-ctr' => 'aes-256-ctr',
|
26
|
+
'aes192-ctr' => 'aes-192-ctr',
|
27
|
+
'aes128-ctr' => 'aes-128-ctr',
|
28
|
+
'cast128-ctr' => 'cast5-ecb',
|
29
|
+
|
30
|
+
'none' => 'none'
|
44
31
|
}
|
45
|
-
|
32
|
+
|
46
33
|
# Returns true if the underlying OpenSSL library supports the given cipher,
|
47
34
|
# and false otherwise.
|
48
35
|
def self.supported?(name)
|
@@ -72,12 +59,11 @@ module Net
|
|
72
59
|
cipher = Net::SSH::Transport::OpenSSLAESCTR.new(cipher)
|
73
60
|
end
|
74
61
|
end
|
75
|
-
cipher.iv = Net::SSH::Transport::KeyExpander.expand_key(cipher.iv_len, options[:iv], options)
|
62
|
+
cipher.iv = Net::SSH::Transport::KeyExpander.expand_key(cipher.iv_len, options[:iv], options)
|
76
63
|
|
77
|
-
key_len =
|
64
|
+
key_len = cipher.key_len
|
78
65
|
cipher.key_len = key_len
|
79
66
|
cipher.key = Net::SSH::Transport::KeyExpander.expand_key(key_len, options[:key], options)
|
80
|
-
cipher.update(" " * 1536) if (ossl_name == "rc4" && name != "arcfour")
|
81
67
|
|
82
68
|
return cipher
|
83
69
|
end
|
@@ -94,13 +80,11 @@ module Net
|
|
94
80
|
result << 0 if options[:iv_len]
|
95
81
|
else
|
96
82
|
cipher = OpenSSL::Cipher.new(ossl_name)
|
97
|
-
key_len =
|
83
|
+
key_len = cipher.key_len
|
98
84
|
cipher.key_len = key_len
|
99
85
|
|
100
86
|
block_size =
|
101
87
|
case ossl_name
|
102
|
-
when "rc4"
|
103
|
-
8
|
104
88
|
when /\-ctr/
|
105
89
|
Net::SSH::Transport::OpenSSLAESCTR.block_size
|
106
90
|
else
|
@@ -2,11 +2,10 @@ module Net
|
|
2
2
|
module SSH
|
3
3
|
module Transport
|
4
4
|
module Constants
|
5
|
-
|
6
5
|
#--
|
7
6
|
# Transport layer generic messages
|
8
7
|
#++
|
9
|
-
|
8
|
+
|
10
9
|
DISCONNECT = 1
|
11
10
|
IGNORE = 2
|
12
11
|
UNIMPLEMENTED = 3
|
@@ -17,19 +16,24 @@ module Net
|
|
17
16
|
#--
|
18
17
|
# Algorithm negotiation messages
|
19
18
|
#++
|
20
|
-
|
19
|
+
|
21
20
|
KEXINIT = 20
|
22
21
|
NEWKEYS = 21
|
23
|
-
|
22
|
+
|
24
23
|
#--
|
25
24
|
# Key exchange method specific messages
|
26
25
|
#++
|
27
|
-
|
26
|
+
|
28
27
|
KEXDH_INIT = 30
|
29
28
|
KEXDH_REPLY = 31
|
30
|
-
|
29
|
+
|
31
30
|
KEXECDH_INIT = 30
|
32
31
|
KEXECDH_REPLY = 31
|
32
|
+
|
33
|
+
KEXDH_GEX_GROUP = 31
|
34
|
+
KEXDH_GEX_INIT = 32
|
35
|
+
KEXDH_GEX_REPLY = 33
|
36
|
+
KEXDH_GEX_REQUEST = 34
|
33
37
|
end
|
34
38
|
end
|
35
39
|
end
|
@@ -88,14 +88,8 @@ module Net::SSH::Transport
|
|
88
88
|
end
|
89
89
|
|
90
90
|
def final
|
91
|
-
|
92
|
-
s = xor!(@remaining, _update(@counter))
|
93
|
-
else
|
94
|
-
s = ""
|
95
|
-
end
|
96
|
-
|
91
|
+
s = @remaining.empty? ? '' : xor!(@remaining, _update(@counter))
|
97
92
|
@remaining = ""
|
98
|
-
|
99
93
|
s
|
100
94
|
end
|
101
95
|
|