net-ssh 5.0.2 → 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 +4 -4
- checksums.yaml.gz.sig +0 -0
- data.tar.gz.sig +0 -0
- data/.gitignore +1 -0
- data/.rubocop.yml +8 -2
- data/.rubocop_todo.yml +392 -379
- data/.travis.yml +22 -22
- data/CHANGES.txt +63 -0
- data/Manifest +0 -1
- data/README.md +287 -0
- data/Rakefile +1 -2
- data/appveyor.yml +4 -2
- data/lib/net/ssh.rb +13 -4
- data/lib/net/ssh/authentication/agent.rb +9 -3
- data/lib/net/ssh/authentication/certificate.rb +10 -1
- data/lib/net/ssh/authentication/ed25519.rb +75 -46
- data/lib/net/ssh/authentication/ed25519_loader.rb +1 -1
- data/lib/net/ssh/authentication/key_manager.rb +35 -6
- data/lib/net/ssh/authentication/methods/keyboard_interactive.rb +3 -1
- data/lib/net/ssh/authentication/methods/publickey.rb +2 -0
- 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 +41 -10
- data/lib/net/ssh/buffered_io.rb +0 -1
- data/lib/net/ssh/config.rb +68 -35
- 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 +104 -17
- data/lib/net/ssh/known_hosts.rb +41 -26
- 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 +8 -7
- data/lib/net/ssh/test/extensions.rb +2 -0
- data/lib/net/ssh/transport/algorithms.rb +161 -105
- 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 +106 -93
- data/lib/net/ssh/transport/packet_stream.rb +52 -20
- data/lib/net/ssh/transport/session.rb +26 -4
- data/lib/net/ssh/transport/state.rb +1 -1
- data/lib/net/ssh/verifiers/accept_new.rb +7 -0
- data/lib/net/ssh/verifiers/always.rb +4 -0
- data/lib/net/ssh/verifiers/never.rb +4 -0
- data/lib/net/ssh/version.rb +3 -3
- data/net-ssh-public_cert.pem +18 -19
- data/net-ssh.gemspec +9 -7
- metadata +56 -40
- metadata.gz.sig +0 -0
- data/Gemfile.noed25519.lock +0 -41
- data/README.rdoc +0 -169
- data/lib/net/ssh/ruby_compat.rb +0 -13
- data/support/arcfour_check.rb +0 -20
@@ -1,8 +1,9 @@
|
|
1
|
-
|
2
|
-
module SSH
|
3
|
-
module Transport
|
4
|
-
module Kex
|
1
|
+
require 'net/ssh/transport/kex/ecdh_sha2_nistp256'
|
5
2
|
|
3
|
+
module Net
|
4
|
+
module SSH
|
5
|
+
module Transport
|
6
|
+
module Kex
|
6
7
|
# A key-exchange service implementing the "ecdh-sha2-nistp256"
|
7
8
|
# key-exchange algorithm. (defined in RFC 5656)
|
8
9
|
class EcdhSHA2NistP384 < EcdhSHA2NistP256
|
@@ -1,8 +1,9 @@
|
|
1
|
-
|
2
|
-
module SSH
|
3
|
-
module Transport
|
4
|
-
module Kex
|
1
|
+
require 'net/ssh/transport/kex/ecdh_sha2_nistp256'
|
5
2
|
|
3
|
+
module Net
|
4
|
+
module SSH
|
5
|
+
module Transport
|
6
|
+
module Kex
|
6
7
|
# A key-exchange service implementing the "ecdh-sha2-nistp521"
|
7
8
|
# key-exchange algorithm. (defined in RFC 5656)
|
8
9
|
class EcdhSHA2NistP521 < EcdhSHA2NistP256
|
@@ -98,9 +98,9 @@ module OpenSSL
|
|
98
98
|
sig_r = sig[0,20].unpack("H*")[0].to_i(16)
|
99
99
|
sig_s = sig[20,20].unpack("H*")[0].to_i(16)
|
100
100
|
a1sig = OpenSSL::ASN1::Sequence([
|
101
|
-
|
102
|
-
|
103
|
-
|
101
|
+
OpenSSL::ASN1::Integer(sig_r),
|
102
|
+
OpenSSL::ASN1::Integer(sig_s)
|
103
|
+
])
|
104
104
|
return verify(OpenSSL::Digest::SHA1.new, a1sig.to_der, data)
|
105
105
|
end
|
106
106
|
|
@@ -121,115 +121,128 @@ module OpenSSL
|
|
121
121
|
end
|
122
122
|
end
|
123
123
|
|
124
|
-
|
125
|
-
|
126
|
-
|
127
|
-
|
128
|
-
|
129
|
-
|
130
|
-
|
131
|
-
|
132
|
-
|
133
|
-
|
134
|
-
|
135
|
-
|
136
|
-
|
137
|
-
|
138
|
-
|
139
|
-
|
140
|
-
|
141
|
-
|
142
|
-
|
143
|
-
|
144
|
-
|
145
|
-
begin
|
146
|
-
key = OpenSSL::PKey::EC.new(OpenSSL::PKey::EC::CurveNameAlias[curve_name_in_key])
|
147
|
-
group = key.group
|
148
|
-
point = OpenSSL::PKey::EC::Point.new(group, OpenSSL::BN.new(public_key_oct, 2))
|
149
|
-
key.public_key = point
|
150
|
-
|
151
|
-
return key
|
152
|
-
rescue OpenSSL::PKey::ECError
|
153
|
-
raise NotImplementedError, "unsupported key type `#{type}'"
|
154
|
-
end
|
124
|
+
# This class is originally defined in the OpenSSL module. As needed, methods
|
125
|
+
# have been added to it by the Net::SSH module for convenience in dealing
|
126
|
+
# with SSH functionality.
|
127
|
+
class EC
|
128
|
+
CurveNameAlias = {
|
129
|
+
'nistp256' => 'prime256v1',
|
130
|
+
'nistp384' => 'secp384r1',
|
131
|
+
'nistp521' => 'secp521r1'
|
132
|
+
}.freeze
|
133
|
+
|
134
|
+
CurveNameAliasInv = {
|
135
|
+
'prime256v1' => 'nistp256',
|
136
|
+
'secp384r1' => 'nistp384',
|
137
|
+
'secp521r1' => 'nistp521'
|
138
|
+
}.freeze
|
139
|
+
|
140
|
+
def self.read_keyblob(curve_name_in_type, buffer)
|
141
|
+
curve_name_in_key = buffer.read_string
|
142
|
+
|
143
|
+
unless curve_name_in_type == curve_name_in_key
|
144
|
+
raise Net::SSH::Exception, "curve name mismatched (`#{curve_name_in_key}' with `#{curve_name_in_type}')"
|
155
145
|
end
|
156
146
|
|
157
|
-
|
158
|
-
|
159
|
-
|
160
|
-
|
161
|
-
|
147
|
+
public_key_oct = buffer.read_string
|
148
|
+
begin
|
149
|
+
key = OpenSSL::PKey::EC.new(OpenSSL::PKey::EC::CurveNameAlias[curve_name_in_key])
|
150
|
+
group = key.group
|
151
|
+
point = OpenSSL::PKey::EC::Point.new(group, OpenSSL::BN.new(public_key_oct, 2))
|
152
|
+
key.public_key = point
|
162
153
|
|
163
|
-
|
164
|
-
|
154
|
+
return key
|
155
|
+
rescue OpenSSL::PKey::ECError
|
156
|
+
raise NotImplementedError, "unsupported key type `#{type}'"
|
165
157
|
end
|
158
|
+
end
|
166
159
|
|
167
|
-
|
168
|
-
|
169
|
-
|
170
|
-
|
171
|
-
|
172
|
-
|
173
|
-
|
174
|
-
|
175
|
-
|
176
|
-
|
177
|
-
|
160
|
+
# Returns the description of this key type used by the
|
161
|
+
# SSH2 protocol, like "ecdsa-sha2-nistp256"
|
162
|
+
def ssh_type
|
163
|
+
"ecdsa-sha2-#{CurveNameAliasInv[group.curve_name]}"
|
164
|
+
end
|
165
|
+
|
166
|
+
def ssh_signature_type
|
167
|
+
ssh_type
|
168
|
+
end
|
169
|
+
|
170
|
+
def digester
|
171
|
+
if group.curve_name =~ /^[a-z]+(\d+)\w*\z/
|
172
|
+
curve_size = Regexp.last_match(1).to_i
|
173
|
+
if curve_size <= 256
|
178
174
|
OpenSSL::Digest::SHA256.new
|
175
|
+
elsif curve_size <= 384
|
176
|
+
OpenSSL::Digest::SHA384.new
|
177
|
+
else
|
178
|
+
OpenSSL::Digest::SHA512.new
|
179
179
|
end
|
180
|
+
else
|
181
|
+
OpenSSL::Digest::SHA256.new
|
180
182
|
end
|
181
|
-
|
183
|
+
end
|
184
|
+
private :digester
|
182
185
|
|
183
|
-
|
184
|
-
|
185
|
-
|
186
|
-
|
187
|
-
|
188
|
-
|
189
|
-
|
186
|
+
# Converts the key to a blob, according to the SSH2 protocol.
|
187
|
+
def to_blob
|
188
|
+
@blob ||= Net::SSH::Buffer.from(:string, ssh_type,
|
189
|
+
:string, CurveNameAliasInv[group.curve_name],
|
190
|
+
:mstring, public_key.to_bn.to_s(2)).to_s
|
191
|
+
@blob
|
192
|
+
end
|
190
193
|
|
191
|
-
|
192
|
-
|
193
|
-
|
194
|
-
|
194
|
+
# Verifies the given signature matches the given data.
|
195
|
+
def ssh_do_verify(sig, data)
|
196
|
+
digest = digester.digest(data)
|
197
|
+
a1sig = nil
|
195
198
|
|
196
|
-
|
197
|
-
|
198
|
-
|
199
|
+
begin
|
200
|
+
sig_r_len = sig[0, 4].unpack('H*')[0].to_i(16)
|
201
|
+
sig_l_len = sig[4 + sig_r_len, 4].unpack('H*')[0].to_i(16)
|
199
202
|
|
200
|
-
|
201
|
-
|
203
|
+
sig_r = sig[4, sig_r_len].unpack('H*')[0]
|
204
|
+
sig_s = sig[4 + sig_r_len + 4, sig_l_len].unpack('H*')[0]
|
202
205
|
|
203
|
-
|
204
|
-
|
205
|
-
|
206
|
-
|
207
|
-
|
208
|
-
|
206
|
+
a1sig = OpenSSL::ASN1::Sequence([
|
207
|
+
OpenSSL::ASN1::Integer(sig_r.to_i(16)),
|
208
|
+
OpenSSL::ASN1::Integer(sig_s.to_i(16))
|
209
|
+
])
|
210
|
+
rescue StandardError
|
211
|
+
end
|
209
212
|
|
210
|
-
|
211
|
-
|
212
|
-
|
213
|
-
|
214
|
-
end
|
213
|
+
if a1sig.nil?
|
214
|
+
return false
|
215
|
+
else
|
216
|
+
dsa_verify_asn1(digest, a1sig.to_der)
|
215
217
|
end
|
218
|
+
end
|
219
|
+
|
220
|
+
# Returns the signature for the given data.
|
221
|
+
def ssh_do_sign(data)
|
222
|
+
digest = digester.digest(data)
|
223
|
+
sig = dsa_sign_asn1(digest)
|
224
|
+
a1sig = OpenSSL::ASN1.decode(sig)
|
216
225
|
|
217
|
-
|
218
|
-
|
219
|
-
digest = digester.digest(data)
|
220
|
-
sig = dsa_sign_asn1(digest)
|
221
|
-
a1sig = OpenSSL::ASN1.decode(sig)
|
226
|
+
sig_r = a1sig.value[0].value
|
227
|
+
sig_s = a1sig.value[1].value
|
222
228
|
|
223
|
-
|
224
|
-
|
229
|
+
Net::SSH::Buffer.from(:bignum, sig_r, :bignum, sig_s).to_s
|
230
|
+
end
|
225
231
|
|
226
|
-
|
232
|
+
class Point
|
233
|
+
# Returns the description of this key type used by the
|
234
|
+
# SSH2 protocol, like "ecdsa-sha2-nistp256"
|
235
|
+
def ssh_type
|
236
|
+
"ecdsa-sha2-#{CurveNameAliasInv[group.curve_name]}"
|
237
|
+
end
|
238
|
+
|
239
|
+
# Converts the key to a blob, according to the SSH2 protocol.
|
240
|
+
def to_blob
|
241
|
+
@blob ||= Net::SSH::Buffer.from(:string, ssh_type,
|
242
|
+
:string, CurveNameAliasInv[group.curve_name],
|
243
|
+
:mstring, to_bn.to_s(2)).to_s
|
244
|
+
@blob
|
227
245
|
end
|
228
|
-
end
|
229
|
-
else
|
230
|
-
class OpenSSL::PKey::ECError < RuntimeError
|
231
|
-
# for compatibility with interpreters
|
232
|
-
# without EC support (i.e. JRuby)
|
233
246
|
end
|
234
247
|
end
|
235
248
|
end
|
@@ -1,7 +1,6 @@
|
|
1
1
|
require 'net/ssh/buffered_io'
|
2
2
|
require 'net/ssh/errors'
|
3
3
|
require 'net/ssh/packet'
|
4
|
-
require 'net/ssh/ruby_compat'
|
5
4
|
require 'net/ssh/transport/cipher_factory'
|
6
5
|
require 'net/ssh/transport/hmac'
|
7
6
|
require 'net/ssh/transport/state'
|
@@ -81,8 +80,8 @@ module Net
|
|
81
80
|
# default), then this will return immediately, whether a packet is
|
82
81
|
# available or not, and will return nil if there is no packet ready to be
|
83
82
|
# returned. If the mode parameter is :block, then this method will block
|
84
|
-
# until a packet is available.
|
85
|
-
def next_packet(mode=:nonblock)
|
83
|
+
# until a packet is available or timeout seconds have passed.
|
84
|
+
def next_packet(mode=:nonblock, timeout=nil)
|
86
85
|
case mode
|
87
86
|
when :nonblock then
|
88
87
|
packet = poll_next_packet
|
@@ -105,11 +104,8 @@ module Net
|
|
105
104
|
packet = poll_next_packet
|
106
105
|
return packet if packet
|
107
106
|
|
108
|
-
|
109
|
-
|
110
|
-
break if result.first.any?
|
111
|
-
end
|
112
|
-
|
107
|
+
result = IO.select([self], nil, nil, timeout)
|
108
|
+
raise Net::SSH::ConnectionTimeout, "timeout waiting for next packet" unless result
|
113
109
|
raise Net::SSH::Disconnect, "connection closed by remote host" if fill <= 0
|
114
110
|
end
|
115
111
|
|
@@ -133,7 +129,7 @@ module Net
|
|
133
129
|
payload = client.compress(payload)
|
134
130
|
|
135
131
|
# the length of the packet, minus the padding
|
136
|
-
actual_length = 4 + payload.bytesize + 1
|
132
|
+
actual_length = (client.hmac.etm ? 0 : 4) + payload.bytesize + 1
|
137
133
|
|
138
134
|
# compute the padding length
|
139
135
|
padding_length = client.block_size - (actual_length % client.block_size)
|
@@ -149,11 +145,32 @@ module Net
|
|
149
145
|
|
150
146
|
padding = Array.new(padding_length) { rand(256) }.pack("C*")
|
151
147
|
|
152
|
-
|
153
|
-
|
148
|
+
if client.hmac.etm
|
149
|
+
debug { "using encrypt-then-mac" }
|
150
|
+
|
151
|
+
# Encrypt padding_length, payload, and padding. Take MAC
|
152
|
+
# from the unencrypted packet_lenght and the encrypted
|
153
|
+
# data.
|
154
|
+
length_data = [packet_length].pack("N")
|
155
|
+
|
156
|
+
unencrypted_data = [padding_length, payload, padding].pack("CA*A*")
|
154
157
|
|
155
|
-
|
156
|
-
|
158
|
+
encrypted_data = client.update_cipher(unencrypted_data) << client.final_cipher
|
159
|
+
|
160
|
+
mac_data = length_data + encrypted_data
|
161
|
+
|
162
|
+
mac = client.hmac.digest([client.sequence_number, mac_data].pack("NA*"))
|
163
|
+
|
164
|
+
message = mac_data + mac
|
165
|
+
else
|
166
|
+
unencrypted_data = [packet_length, padding_length, payload, padding].pack("NCA*A*")
|
167
|
+
|
168
|
+
mac = client.hmac.digest([client.sequence_number, unencrypted_data].pack("NA*"))
|
169
|
+
|
170
|
+
encrypted_data = client.update_cipher(unencrypted_data) << client.final_cipher
|
171
|
+
|
172
|
+
message = encrypted_data + mac
|
173
|
+
end
|
157
174
|
|
158
175
|
debug { "queueing packet nr #{client.sequence_number} type #{payload.getbyte(0)} len #{packet_length}" }
|
159
176
|
enqueue(message)
|
@@ -198,18 +215,27 @@ module Net
|
|
198
215
|
# read, post-processed according to the cipher, hmac, and compression
|
199
216
|
# algorithms specified in the server state object, and returned as a
|
200
217
|
# new Packet object.
|
218
|
+
# rubocop:disable Metrics/AbcSize
|
201
219
|
def poll_next_packet
|
220
|
+
aad_length = server.hmac.etm ? 4 : 0
|
221
|
+
|
202
222
|
if @packet.nil?
|
203
223
|
minimum = server.block_size < 4 ? 4 : server.block_size
|
204
|
-
return nil if available < minimum
|
205
|
-
data = read_available(minimum)
|
224
|
+
return nil if available < minimum + aad_length
|
225
|
+
data = read_available(minimum + aad_length)
|
206
226
|
|
207
227
|
# decipher it
|
208
|
-
|
209
|
-
|
228
|
+
if server.hmac.etm
|
229
|
+
@packet_length = data.unpack("N").first
|
230
|
+
@mac_data = data
|
231
|
+
@packet = Net::SSH::Buffer.new(server.update_cipher(data[aad_length..-1]))
|
232
|
+
else
|
233
|
+
@packet = Net::SSH::Buffer.new(server.update_cipher(data))
|
234
|
+
@packet_length = @packet.read_long
|
235
|
+
end
|
210
236
|
end
|
211
237
|
|
212
|
-
need = @packet_length + 4 - server.block_size
|
238
|
+
need = @packet_length + 4 - aad_length - server.block_size
|
213
239
|
raise Net::SSH::Exception, "padding error, need #{need} block #{server.block_size}" if need % server.block_size != 0
|
214
240
|
|
215
241
|
return nil if available < need + server.hmac.mac_length
|
@@ -217,6 +243,7 @@ module Net
|
|
217
243
|
if need > 0
|
218
244
|
# read the remainder of the packet and decrypt it.
|
219
245
|
data = read_available(need)
|
246
|
+
@mac_data += data if server.hmac.etm
|
220
247
|
@packet.append(server.update_cipher(data))
|
221
248
|
end
|
222
249
|
|
@@ -229,8 +256,12 @@ module Net
|
|
229
256
|
|
230
257
|
payload = @packet.read(@packet_length - padding_length - 1)
|
231
258
|
|
232
|
-
my_computed_hmac = server.hmac.
|
233
|
-
|
259
|
+
my_computed_hmac = if server.hmac.etm
|
260
|
+
server.hmac.digest([server.sequence_number, @mac_data].pack("NA*"))
|
261
|
+
else
|
262
|
+
server.hmac.digest([server.sequence_number, @packet.content].pack("NA*"))
|
263
|
+
end
|
264
|
+
raise Net::SSH::Exception, "corrupted hmac detected #{server.hmac.class}" if real_hmac != my_computed_hmac
|
234
265
|
|
235
266
|
# try to decompress the payload, in case compression is active
|
236
267
|
payload = server.decompress(payload)
|
@@ -243,6 +274,7 @@ module Net
|
|
243
274
|
return Packet.new(payload)
|
244
275
|
end
|
245
276
|
end
|
277
|
+
# rubocop:enable Metrics/AbcSize
|
246
278
|
|
247
279
|
end
|
248
280
|
end
|
@@ -190,7 +190,7 @@ module Net
|
|
190
190
|
loop do
|
191
191
|
return @queue.shift if consume_queue && @queue.any? && algorithms.allow?(@queue.first)
|
192
192
|
|
193
|
-
packet = socket.next_packet(mode)
|
193
|
+
packet = socket.next_packet(mode, options[:timeout])
|
194
194
|
return nil if packet.nil?
|
195
195
|
|
196
196
|
case packet.type
|
@@ -274,6 +274,23 @@ module Net
|
|
274
274
|
|
275
275
|
private
|
276
276
|
|
277
|
+
# Compatibility verifier which allows users to keep using
|
278
|
+
# custom verifier code without adding new :verify_signature
|
279
|
+
# method.
|
280
|
+
class CompatibleVerifier
|
281
|
+
def initialize(verifier)
|
282
|
+
@verifier = verifier
|
283
|
+
end
|
284
|
+
|
285
|
+
def verify(arguments)
|
286
|
+
@verifier.verify(arguments)
|
287
|
+
end
|
288
|
+
|
289
|
+
def verify_signature(&block)
|
290
|
+
yield
|
291
|
+
end
|
292
|
+
end
|
293
|
+
|
277
294
|
# Instantiates a new host-key verification class, based on the value of
|
278
295
|
# the parameter.
|
279
296
|
#
|
@@ -285,8 +302,8 @@ module Net
|
|
285
302
|
# - :accept_new (insecure)
|
286
303
|
# - :always (secure)
|
287
304
|
#
|
288
|
-
# If the argument happens to respond to :verify
|
289
|
-
# directly. Otherwise, an exception is raised.
|
305
|
+
# If the argument happens to respond to :verify and :verify_signature,
|
306
|
+
# it is returned directly. Otherwise, an exception is raised.
|
290
307
|
#
|
291
308
|
# Values false, true, and :very were deprecated in
|
292
309
|
# [#595](https://github.com/net-ssh/net-ssh/pull/595)
|
@@ -314,7 +331,12 @@ module Net
|
|
314
331
|
Net::SSH::Verifiers::Always.new
|
315
332
|
else
|
316
333
|
if verifier.respond_to?(:verify)
|
317
|
-
verifier
|
334
|
+
if verifier.respond_to?(:verify_signature)
|
335
|
+
verifier
|
336
|
+
else
|
337
|
+
Kernel.warn("Warning: verifier without :verify_signature is deprecated")
|
338
|
+
CompatibleVerifier.new(verifier)
|
339
|
+
end
|
318
340
|
else
|
319
341
|
raise(
|
320
342
|
ArgumentError,
|