net-ssh 7.3.6 → 8.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.
Files changed (68) hide show
  1. checksums.yaml +4 -4
  2. checksums.yaml.gz.sig +0 -0
  3. data/.github/pull_request_template.md +1 -0
  4. data/.github/workflows/changelog.yml +43 -0
  5. data/.github/workflows/ci-with-docker.yml +0 -3
  6. data/.github/workflows/ci.yml +2 -17
  7. data/.github/workflows/rubocop.yml +3 -1
  8. data/.rubocop.yml +1 -1
  9. data/.rubocop_todo.yml +1 -0
  10. data/CHANGES.txt +73 -7
  11. data/CONTRIBUTING.md +35 -0
  12. data/Dockerfile +3 -3
  13. data/Dockerfile.openssl3 +1 -1
  14. data/Dockerfile.zlib_ng +1 -1
  15. data/README.md +71 -57
  16. data/Rakefile +66 -12
  17. data/appveyor.yml +4 -16
  18. data/changelog.d/README.md +1 -0
  19. data/docker-compose.yml +1 -7
  20. data/lib/net/ssh/authentication/agent.rb +35 -11
  21. data/lib/net/ssh/authentication/ed25519.rb +137 -44
  22. data/lib/net/ssh/authentication/ed25519_loader.rb +14 -9
  23. data/lib/net/ssh/authentication/key_manager.rb +22 -11
  24. data/lib/net/ssh/authentication/methods/abstract.rb +2 -8
  25. data/lib/net/ssh/authentication/methods/publickey.rb +3 -1
  26. data/lib/net/ssh/authentication/security_key.rb +71 -0
  27. data/lib/net/ssh/authentication/session.rb +29 -17
  28. data/lib/net/ssh/buffer.rb +6 -1
  29. data/lib/net/ssh/buffered_io.rb +40 -3
  30. data/lib/net/ssh/config.rb +28 -12
  31. data/lib/net/ssh/connection/channel.rb +49 -2
  32. data/lib/net/ssh/connection/session.rb +58 -8
  33. data/lib/net/ssh/errors.rb +24 -6
  34. data/lib/net/ssh/key_factory.rb +7 -1
  35. data/lib/net/ssh/known_hosts.rb +18 -8
  36. data/lib/net/ssh/multiplex/client.rb +162 -0
  37. data/lib/net/ssh/multiplex/control_path.rb +120 -0
  38. data/lib/net/ssh/multiplex/proxy_transport.rb +218 -0
  39. data/lib/net/ssh/multiplex.rb +130 -0
  40. data/lib/net/ssh/prompt.rb +3 -3
  41. data/lib/net/ssh/proxy/jump.rb +40 -2
  42. data/lib/net/ssh/service/forward.rb +29 -24
  43. data/lib/net/ssh/test.rb +2 -1
  44. data/lib/net/ssh/transport/algorithms.rb +88 -33
  45. data/lib/net/ssh/transport/chacha20_poly1305_cipher.rb +89 -16
  46. data/lib/net/ssh/transport/chacha20_poly1305_cipher_loader.rb +20 -1
  47. data/lib/net/ssh/transport/cipher_factory.rb +23 -1
  48. data/lib/net/ssh/transport/constants.rb +1 -0
  49. data/lib/net/ssh/transport/gcm_cipher.rb +27 -6
  50. data/lib/net/ssh/transport/hmac/sha1_etm.rb +12 -0
  51. data/lib/net/ssh/transport/hmac.rb +2 -0
  52. data/lib/net/ssh/transport/kex/curve25519_sha256.rb +41 -9
  53. data/lib/net/ssh/transport/kex/curve25519_sha256_loader.rb +14 -6
  54. data/lib/net/ssh/transport/kex/diffie_hellman_group1_sha1.rb +8 -0
  55. data/lib/net/ssh/transport/kex/diffie_hellman_group_exchange_sha1.rb +45 -15
  56. data/lib/net/ssh/transport/openssl.rb +2 -1
  57. data/lib/net/ssh/transport/packet_stream.rb +12 -0
  58. data/lib/net/ssh/transport/session.rb +41 -44
  59. data/lib/net/ssh/verifiers/always.rb +0 -3
  60. data/lib/net/ssh/version.rb +3 -3
  61. data/lib/net/ssh.rb +139 -57
  62. data/net-ssh.gemspec +5 -8
  63. data/rakelib/changelog.rb +229 -0
  64. data.tar.gz.sig +0 -0
  65. metadata +37 -36
  66. metadata.gz.sig +0 -0
  67. data/Gemfile.noed25519 +0 -12
  68. data/Gemfile.norbnacl +0 -12
@@ -5,7 +5,11 @@ module Net
5
5
  module Transport
6
6
  ## Extension module for aes(128|256)gcm ciphers
7
7
  module GCMCipher
8
- # rubocop:disable Metrics/AbcSize
8
+ BLOCK_SIZE = 16
9
+ IV_BYTES = 12
10
+ AUTH_TAG_BYTES = 16
11
+
12
+ # rubocop:disable Metrics/AbcSize, Metrics/MethodLength
9
13
  def self.extended(orig)
10
14
  # rubocop:disable Metrics/BlockLength
11
15
  orig.class_eval do
@@ -100,15 +104,32 @@ module Net
100
104
  end
101
105
 
102
106
  def mac_length
103
- 16
107
+ GCMCipher::AUTH_TAG_BYTES
104
108
  end
105
109
 
106
110
  def block_size
107
- 16
111
+ GCMCipher::BLOCK_SIZE
108
112
  end
109
113
 
110
114
  def self.block_size
111
- 16
115
+ GCMCipher::BLOCK_SIZE
116
+ end
117
+
118
+ def self.iv_len
119
+ GCMCipher::IV_BYTES
120
+ end
121
+
122
+ def self.auth_length
123
+ GCMCipher::AUTH_TAG_BYTES
124
+ end
125
+
126
+ def self.decrypt_private_key(ciphertext, auth_tag, key, initialization_vector)
127
+ cipher = new(encrypt: false, key: key)
128
+
129
+ cipher.nonce = initialization_vector
130
+ cipher.cipher.auth_tag = auth_tag.to_s
131
+ cipher.cipher.auth_data = ''
132
+ cipher.cipher.update(ciphertext.to_s) << cipher.cipher.final
112
133
  end
113
134
 
114
135
  #
@@ -117,7 +138,7 @@ module Net
117
138
  # N_MAX maximum nonce (IV) length 12 octets
118
139
  #
119
140
  def iv_len
120
- 12
141
+ GCMCipher::IV_BYTES
121
142
  end
122
143
 
123
144
  #
@@ -201,7 +222,7 @@ module Net
201
222
  end
202
223
  # rubocop:enable Metrics/BlockLength
203
224
  end
204
- # rubocop:enable Metrics/AbcSize
225
+ # rubocop:enable Metrics/AbcSize, Metrics/MethodLength
205
226
  end
206
227
  end
207
228
  end
@@ -0,0 +1,12 @@
1
+ require 'net/ssh/transport/hmac/abstract'
2
+
3
+ module Net::SSH::Transport::HMAC
4
+ # The SHA1 Encrypt-Then-Mac HMAC algorithm. This has a mac and
5
+ # key length of 20, and uses the SHA1 digest algorithm.
6
+ class SHA1_Etm < Abstract
7
+ etm true
8
+ mac_length 20
9
+ key_length 20
10
+ digest_class OpenSSL::Digest::SHA1
11
+ end
12
+ end
@@ -9,6 +9,7 @@ require 'net/ssh/transport/hmac/sha2_512'
9
9
  require 'net/ssh/transport/hmac/sha2_512_96'
10
10
  require 'net/ssh/transport/hmac/sha2_256_etm'
11
11
  require 'net/ssh/transport/hmac/sha2_512_etm'
12
+ require 'net/ssh/transport/hmac/sha1_etm'
12
13
  require 'net/ssh/transport/hmac/ripemd160'
13
14
  require 'net/ssh/transport/hmac/none'
14
15
 
@@ -27,6 +28,7 @@ module Net::SSH::Transport::HMAC
27
28
  'hmac-sha2-512-96' => SHA2_512_96,
28
29
  'hmac-sha2-256-etm@openssh.com' => SHA2_256_Etm,
29
30
  'hmac-sha2-512-etm@openssh.com' => SHA2_512_Etm,
31
+ 'hmac-sha1-etm@openssh.com' => SHA1_Etm,
30
32
  'hmac-ripemd160' => RIPEMD160,
31
33
  'hmac-ripemd160@openssh.com' => RIPEMD160,
32
34
  'none' => None
@@ -1,7 +1,4 @@
1
- gem 'x25519' # raise if the gem x25519 is not installed
2
-
3
- require 'x25519'
4
-
1
+ require 'openssl'
5
2
  require 'net/ssh/transport/constants'
6
3
  require 'net/ssh/transport/kex/abstract5656'
7
4
 
@@ -12,25 +9,60 @@ module Net
12
9
  # A key-exchange service implementing the "curve25519-sha256@libssh.org"
13
10
  # key-exchange algorithm. (defined in https://tools.ietf.org/html/draft-ietf-curdle-ssh-curves-06)
14
11
  class Curve25519Sha256 < Abstract5656
12
+ ALGORITHM = "X25519"
13
+ KEY_BYTES = 32
14
+
15
+ class UnsupportedError < StandardError; end
16
+
17
+ def self.ensure_supported!
18
+ unless OpenSSL::PKey.respond_to?(:generate_key) && OpenSSL::PKey.respond_to?(:new_raw_public_key)
19
+ raise UnsupportedError, "OpenSSL::PKey raw public key APIs are unavailable"
20
+ end
21
+
22
+ key = generate_x25519_key
23
+ public_key = new_raw_public_key(key.raw_public_key)
24
+ validate_key_bytes!(key.derive(public_key), "shared secret", KEY_BYTES)
25
+ rescue OpenSSL::PKey::PKeyError => e
26
+ raise UnsupportedError, e.message
27
+ end
28
+
29
+ def self.generate_x25519_key
30
+ OpenSSL::PKey.generate_key(ALGORITHM)
31
+ end
32
+
33
+ def self.new_raw_public_key(key)
34
+ validate_key_bytes!(key, "public key", KEY_BYTES)
35
+ OpenSSL::PKey.new_raw_public_key(ALGORITHM, binary_string(key))
36
+ end
37
+
38
+ def self.validate_key_bytes!(key, label, expected_bytes)
39
+ raise ArgumentError, "invalid X25519 #{label}" unless key.respond_to?(:bytesize) && key.bytesize == expected_bytes
40
+ end
41
+
42
+ def self.binary_string(string)
43
+ string.dup.force_encoding('BINARY')
44
+ end
45
+ private_class_method :binary_string
46
+
15
47
  def digester
16
48
  OpenSSL::Digest::SHA256
17
49
  end
18
50
 
19
51
  private
20
52
 
21
- def generate_key # :nodoc:
22
- ::X25519::Scalar.generate
53
+ def generate_key
54
+ self.class.generate_x25519_key
23
55
  end
24
56
 
25
57
  ## string Q_C, client's ephemeral public key octet string
26
58
  def ecdh_public_key_bytes
27
- ecdh.public_key.to_bytes
59
+ ecdh.raw_public_key
28
60
  end
29
61
 
30
62
  # compute shared secret from server's public key and client's private key
31
63
  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)
64
+ pk = self.class.new_raw_public_key(server_ecdh_pubkey)
65
+ OpenSSL::BN.new(ecdh.derive(pk), 2)
34
66
  end
35
67
  end
36
68
  end
@@ -2,26 +2,34 @@ module Net
2
2
  module SSH
3
3
  module Transport
4
4
  module Kex
5
- # Loads Curve25519Sha256 support which requires optinal dependencies
5
+ # Loads Curve25519Sha256 support backed by Ruby OpenSSL X25519 APIs.
6
6
  module Curve25519Sha256Loader
7
7
  begin
8
8
  require 'net/ssh/transport/kex/curve25519_sha256'
9
+ Net::SSH::Transport::Kex::Curve25519Sha256.ensure_supported!
9
10
  LOADED = true
10
11
  ERROR = nil
11
12
  rescue LoadError => e
12
13
  ERROR = e
13
14
  LOADED = false
15
+ rescue StandardError => e
16
+ if defined?(Net::SSH::Transport::Kex::Curve25519Sha256::UnsupportedError) &&
17
+ e.is_a?(Net::SSH::Transport::Kex::Curve25519Sha256::UnsupportedError)
18
+ ERROR = e
19
+ LOADED = false
20
+ else
21
+ raise
22
+ end
14
23
  end
15
24
 
16
25
  def self.raiseUnlessLoaded(message)
17
- description = ERROR.is_a?(LoadError) ? dependenciesRequiredForX25519 : ''
18
- description << "#{ERROR.class} : \"#{ERROR.message}\"\n" if ERROR
26
+ description = LOADED ? '' : x25519SupportRequired
27
+ description += "#{ERROR.class} : \"#{ERROR.message}\"\n" if ERROR
19
28
  raise NotImplementedError, "#{message}\n#{description}" unless LOADED
20
29
  end
21
30
 
22
- def self.dependenciesRequiredForX25519
23
- result = "net-ssh requires the following gems for x25519 support:\n"
24
- result << " * x25519\n"
31
+ def self.x25519SupportRequired
32
+ "net-ssh requires openssl >= 3.2.0 and a crypto backend with X25519 enabled for curve25519-sha256 support.\n"
25
33
  end
26
34
  end
27
35
  end
@@ -102,6 +102,7 @@ module Net
102
102
  result[:key_blob] = buffer.read_string
103
103
  result[:server_key] = Net::SSH::Buffer.new(result[:key_blob]).read_key
104
104
  result[:server_dh_pubkey] = buffer.read_bignum
105
+ validate_server_dh_pubkey(result[:server_dh_pubkey])
105
106
  result[:shared_secret] = OpenSSL::BN.new(dh.compute_key(result[:server_dh_pubkey]), 2)
106
107
 
107
108
  sig_buffer = Net::SSH::Buffer.new(buffer.read_string)
@@ -115,6 +116,13 @@ module Net
115
116
 
116
117
  return result
117
118
  end
119
+
120
+ # Rejects degenerate values that would let the server force a
121
+ # predictable shared secret, as OpenSSH's dh_pub_is_valid.
122
+ def validate_server_dh_pubkey(pub)
123
+ valid = pub > 1 && pub < dh.p - 1 && pub.to_i.to_s(2).count("1") >= 4
124
+ raise Net::SSH::Exception, "server's DH public value is invalid" unless valid
125
+ end
118
126
  end
119
127
  end
120
128
  end
@@ -6,26 +6,43 @@ module Net::SSH::Transport::Kex
6
6
  # A key-exchange service implementing the
7
7
  # "diffie-hellman-group-exchange-sha1" key-exchange algorithm.
8
8
  class DiffieHellmanGroupExchangeSHA1 < DiffieHellmanGroup1SHA1
9
- MINIMUM_BITS = 1024
9
+ MINIMUM_BITS = 2048
10
10
  MAXIMUM_BITS = 8192
11
+ CISCO_MAXIMUM_NEED_BITS = 4096
11
12
 
12
13
  private
13
14
 
14
- # Compute the number of bits needed for the given number of bytes.
15
+ # Computes the minimum, preferred and maximum group sizes to request,
16
+ # like OpenSSH's kexgex_client.
15
17
  def compute_need_bits
16
- # for Compatibility: OpenSSH requires (need_bits * 2 + 1) length of parameter
17
- need_bits = data[:need_bytes] * 8 * 2 + 1
18
-
19
18
  data[:minimum_dh_bits] ||= MINIMUM_BITS
19
+ data[:maximum_dh_bits] = [MAXIMUM_BITS, data[:minimum_dh_bits]].max
20
+ data[:need_bits] = estimate_group_bits(data[:need_bytes] * 8).clamp(data[:minimum_dh_bits], maximum_need_bits)
21
+ end
20
22
 
21
- if need_bits < data[:minimum_dh_bits]
22
- need_bits = data[:minimum_dh_bits]
23
- elsif need_bits > MAXIMUM_BITS
24
- need_bits = MAXIMUM_BITS
25
- end
23
+ # Some Cisco servers fail instead of returning their 4096-bit group when asked for more (OpenSSH bz#2209).
24
+ def maximum_need_bits
25
+ return data[:maximum_dh_bits] unless cisco_server?
26
+
27
+ [CISCO_MAXIMUM_NEED_BITS, data[:minimum_dh_bits]].max
28
+ end
29
+
30
+ def cisco_server?
31
+ data[:server_version_string].to_s.match?(/\ASSH-[\d.]+-Cisco-1\./)
32
+ end
26
33
 
27
- data[:need_bits] = need_bits
28
- data[:need_bytes] = need_bits / 8
34
+ # Group size giving at least the given bits of security (NIST SP 800-57),
35
+ # as OpenSSH's dh_estimate.
36
+ def estimate_group_bits(security_bits)
37
+ if security_bits <= 112
38
+ 2048
39
+ elsif security_bits <= 128
40
+ 3072
41
+ elsif security_bits <= 192
42
+ 7680
43
+ else
44
+ 8192
45
+ end
29
46
  end
30
47
 
31
48
  # Returns the DH key parameters for the given session.
@@ -34,7 +51,7 @@ module Net::SSH::Transport::Kex
34
51
 
35
52
  # request the DH key parameters for the given number of bits.
36
53
  buffer = Net::SSH::Buffer.from(:byte, KEXDH_GEX_REQUEST, :long, data[:minimum_dh_bits],
37
- :long, data[:need_bits], :long, MAXIMUM_BITS)
54
+ :long, data[:need_bits], :long, data[:maximum_dh_bits])
38
55
  connection.send_message(buffer)
39
56
 
40
57
  buffer = connection.next_message
@@ -43,9 +60,22 @@ module Net::SSH::Transport::Kex
43
60
  p = buffer.read_bignum
44
61
  g = buffer.read_bignum
45
62
 
63
+ validate_group(p, g)
64
+
46
65
  [p, g]
47
66
  end
48
67
 
68
+ def validate_group(prime, generator)
69
+ bits = prime.num_bits
70
+ if bits < data[:minimum_dh_bits]
71
+ raise Net::SSH::Exception,
72
+ "server's DH group is #{bits} bits, below the minimum of #{data[:minimum_dh_bits]}; " \
73
+ "pass minimum_dh_bits: #{bits} to allow it"
74
+ end
75
+ raise Net::SSH::Exception, "server's DH group is #{bits} bits, above the maximum of #{data[:maximum_dh_bits]}" if bits > data[:maximum_dh_bits]
76
+ raise Net::SSH::Exception, "server's DH group generator is invalid" unless generator > 1 && generator < prime - 1
77
+ end
78
+
49
79
  # Returns the INIT/REPLY constants used by this algorithm.
50
80
  def get_message_types
51
81
  [KEXDH_GEX_INIT, KEXDH_GEX_REPLY]
@@ -60,9 +90,9 @@ module Net::SSH::Transport::Kex
60
90
  data[:client_algorithm_packet],
61
91
  data[:server_algorithm_packet],
62
92
  result[:key_blob]
63
- response.write_long MINIMUM_BITS,
93
+ response.write_long data[:minimum_dh_bits],
64
94
  data[:need_bits],
65
- MAXIMUM_BITS
95
+ data[:maximum_dh_bits]
66
96
  response.write_bignum dh.p, dh.g, dh.pub_key,
67
97
  result[:server_dh_pubkey],
68
98
  result[:shared_secret]
@@ -1,4 +1,5 @@
1
1
  require 'openssl'
2
+ require 'net/ssh/errors'
2
3
  require 'net/ssh/authentication/pub_key_fingerprint'
3
4
 
4
5
  module OpenSSL
@@ -178,7 +179,7 @@ module OpenSSL
178
179
 
179
180
  return key
180
181
  rescue OpenSSL::PKey::ECError
181
- raise NotImplementedError, "unsupported key type `#{type}'"
182
+ raise Net::SSH::UnsupportedKeyType, "unsupported key type `ecdsa-sha2-#{curve_name_in_type}'"
182
183
  end
183
184
  end
184
185
 
@@ -190,6 +190,7 @@ module Net
190
190
  def cleanup
191
191
  client.cleanup
192
192
  server.cleanup
193
+ hang_up_proxy_command
193
194
  end
194
195
 
195
196
  # If the IO object requires a rekey operation (as indicated by either its
@@ -205,6 +206,17 @@ module Net
205
206
 
206
207
  protected
207
208
 
209
+ # Like OpenSSH, hang up a ProxyCommand child: tunnels such as EC2 Instance
210
+ # Connect don't exit on their own, and IO#close waits for them.
211
+ def hang_up_proxy_command
212
+ return unless respond_to?(:pid)
213
+
214
+ child = pid
215
+ Process.kill('HUP', child) if child
216
+ rescue IOError, Errno::ESRCH
217
+ # already closed, or the child has already been reaped
218
+ end
219
+
208
220
  # Called when this module is used to extend an object. It initializes
209
221
  # the states and generally prepares the object for use as a packet stream.
210
222
  def initialize_ssh
@@ -66,6 +66,7 @@ module Net
66
66
  @port = options[:port] || DEFAULT_PORT
67
67
  @bind_address = options[:bind_address] || nil
68
68
  @options = options
69
+ @host_key_verifier = select_host_key_verifier(options[:verify_host_key])
69
70
 
70
71
  @socket =
71
72
  if (factory = options[:proxy])
@@ -79,21 +80,24 @@ module Net
79
80
 
80
81
  @socket.extend(PacketStream)
81
82
  @socket.logger = @logger
83
+ set_no_delay unless options[:no_delay] == false
82
84
 
83
85
  debug { "connection established" }
84
86
 
85
87
  @queue = []
86
88
  @queued_bytes = 0
87
89
 
88
- @host_key_verifier = select_host_key_verifier(options[:verify_host_key])
89
-
90
90
  @server_version = ServerVersion.new(socket, logger, options[:timeout])
91
91
 
92
92
  @algorithms = Algorithms.new(self, options)
93
93
  @algorithms.start
94
94
  wait { algorithms.initialized? }
95
95
  rescue Errno::ETIMEDOUT
96
+ @socket&.close
96
97
  raise Net::SSH::ConnectionTimeout
98
+ rescue StandardError
99
+ @socket&.close
100
+ raise
97
101
  end
98
102
 
99
103
  def host_keys
@@ -103,6 +107,10 @@ module Net
103
107
  end
104
108
  end
105
109
 
110
+ def pubkey_algorithms
111
+ algorithms[:pubkey_algorithms]
112
+ end
113
+
106
114
  # Returns the host (and possibly IP address) in a format compatible with
107
115
  # SSH known-host files.
108
116
  def host_as_string
@@ -211,6 +219,10 @@ module Net
211
219
  when DEBUG
212
220
  send(packet[:always_display] ? :fatal : :debug) { packet[:message] }
213
221
 
222
+ # We don't advertise ext-info-c, but some servers send EXT_INFO anyway (#955).
223
+ when EXT_INFO
224
+ debug { "ignoring EXT_INFO packet" }
225
+
214
226
  when KEXINIT
215
227
  algorithms.accept_kexinit(packet)
216
228
 
@@ -293,23 +305,25 @@ module Net
293
305
  packet
294
306
  end
295
307
 
296
- # Compatibility verifier which allows users to keep using
297
- # custom verifier code without adding new :verify_signature
298
- # method.
299
- class CompatibleVerifier
300
- def initialize(verifier)
301
- @verifier = verifier
302
- end
308
+ # Turns Nagle's algorithm off on the socket, so that a packet written
309
+ # while the previous one is still unacknowledged goes out right away
310
+ # instead of waiting for the server's ACK. A ProxyCommand hands the
311
+ # transport a pipe rather than a socket, and the command on its other
312
+ # end owns the TCP connection, so there is nothing to set in that case.
313
+ def set_no_delay
314
+ return unless socket.respond_to?(:setsockopt)
303
315
 
304
- def verify(arguments)
305
- @verifier.verify(arguments)
306
- end
307
-
308
- def verify_signature(&block)
309
- yield
310
- end
316
+ debug { "setting TCP_NODELAY" }
317
+ socket.setsockopt(Socket::IPPROTO_TCP, Socket::TCP_NODELAY, 1)
311
318
  end
312
319
 
320
+ REMOVED_VERIFY_HOST_KEY_VALUES = {
321
+ false => :never,
322
+ true => :accept_new_or_local_tunnel,
323
+ very: :accept_new,
324
+ secure: :always
325
+ }.freeze
326
+
313
327
  # Instantiates a new host-key verification class, based on the value of
314
328
  # the parameter.
315
329
  #
@@ -323,46 +337,29 @@ module Net
323
337
  #
324
338
  # If the argument happens to respond to :verify and :verify_signature,
325
339
  # it is returned directly. Otherwise, an exception is raised.
326
- #
327
- # Values false, true, and :very were deprecated in
328
- # [#595](https://github.com/net-ssh/net-ssh/pull/595)
329
340
  def select_host_key_verifier(verifier)
330
341
  case verifier
331
- when false
332
- Kernel.warn('verify_host_key: false is deprecated, use :never')
333
- Net::SSH::Verifiers::Never.new
334
342
  when :never then
335
343
  Net::SSH::Verifiers::Never.new
336
- when true
337
- Kernel.warn('verify_host_key: true is deprecated, use :accept_new_or_local_tunnel')
338
- Net::SSH::Verifiers::AcceptNewOrLocalTunnel.new
339
344
  when :accept_new_or_local_tunnel, nil then
340
345
  Net::SSH::Verifiers::AcceptNewOrLocalTunnel.new
341
- when :very
342
- Kernel.warn('verify_host_key: :very is deprecated, use :accept_new')
343
- Net::SSH::Verifiers::AcceptNew.new
344
346
  when :accept_new then
345
347
  Net::SSH::Verifiers::AcceptNew.new
346
- when :secure then
347
- Kernel.warn('verify_host_key: :secure is deprecated, use :always')
348
- Net::SSH::Verifiers::Always.new
349
348
  when :always then
350
349
  Net::SSH::Verifiers::Always.new
350
+ when *REMOVED_VERIFY_HOST_KEY_VALUES.keys
351
+ raise ArgumentError,
352
+ "verify_host_key: #{verifier.inspect} has been removed, use #{REMOVED_VERIFY_HOST_KEY_VALUES[verifier].inspect}"
351
353
  else
352
- if verifier.respond_to?(:verify)
353
- if verifier.respond_to?(:verify_signature)
354
- verifier
355
- else
356
- Kernel.warn("Warning: verifier without :verify_signature is deprecated")
357
- CompatibleVerifier.new(verifier)
358
- end
359
- else
360
- raise(
361
- ArgumentError,
362
- "Invalid argument to :verify_host_key (or deprecated " \
363
- ":paranoid): #{verifier.inspect}"
364
- )
354
+ raise ArgumentError, "Invalid argument to :verify_host_key: #{verifier.inspect}" unless verifier.respond_to?(:verify)
355
+
356
+ unless verifier.respond_to?(:verify_signature)
357
+ raise ArgumentError,
358
+ "verify_host_key verifier #{verifier.inspect} must implement verify_signature(&block): " \
359
+ "yield to the block, which checks the server's host key signature, and return its result"
365
360
  end
361
+
362
+ verifier
366
363
  end
367
364
  end
368
365
  end
@@ -51,9 +51,6 @@ module Net
51
51
  # implement them (Net::SSH::HostKeyEntries::CertAuthority). Non-certificate
52
52
  # entries do not respond to these predicates and are left untouched.
53
53
  def verify_certificate!(entry, host_keys, arguments)
54
- # Plain keys carry no certificate constraints, and respond_to? on this delegator prints a deprecation warning (#1026).
55
- return if entry.is_a?(Net::SSH::HostKeyEntries::PubKey)
56
-
57
54
  cert = arguments[:key]
58
55
 
59
56
  if entry.respond_to?(:matches_validity?) && !entry.matches_validity?(cert)
@@ -46,13 +46,13 @@ module Net
46
46
  end
47
47
 
48
48
  # The major component of this version of the Net::SSH library
49
- MAJOR = 7
49
+ MAJOR = 8
50
50
 
51
51
  # The minor component of this version of the Net::SSH library
52
- MINOR = 3
52
+ MINOR = 0
53
53
 
54
54
  # The tiny component of this version of the Net::SSH library
55
- TINY = 6
55
+ TINY = 0
56
56
 
57
57
  # The prerelease component of this version of the Net::SSH library
58
58
  # nil allowed