net-ssh 7.3.9 → 8.0.0.beta3
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/.github/workflows/ci-with-docker.yml +0 -3
- data/.github/workflows/ci.yml +2 -17
- data/.rubocop.yml +1 -1
- data/.rubocop_todo.yml +1 -0
- data/CHANGES.txt +2 -27
- data/Dockerfile +1 -4
- data/Dockerfile.openssl3 +1 -1
- data/Dockerfile.zlib_ng +1 -1
- data/README.md +10 -13
- data/Rakefile +12 -20
- data/appveyor.yml +4 -16
- data/docker-compose.yml +1 -7
- data/lib/net/ssh/authentication/agent.rb +4 -4
- data/lib/net/ssh/authentication/ed25519.rb +134 -46
- data/lib/net/ssh/authentication/ed25519_loader.rb +14 -9
- data/lib/net/ssh/errors.rb +0 -10
- data/lib/net/ssh/key_factory.rb +3 -4
- data/lib/net/ssh/known_hosts.rb +30 -85
- data/lib/net/ssh/proxy/command.rb +3 -28
- data/lib/net/ssh/proxy/jump.rb +7 -38
- data/lib/net/ssh/service/forward.rb +0 -6
- data/lib/net/ssh/transport/chacha20_poly1305_cipher.rb +89 -16
- data/lib/net/ssh/transport/chacha20_poly1305_cipher_loader.rb +20 -1
- data/lib/net/ssh/transport/cipher_factory.rb +23 -1
- data/lib/net/ssh/transport/gcm_cipher.rb +27 -6
- data/lib/net/ssh/transport/kex/curve25519_sha256.rb +41 -9
- data/lib/net/ssh/transport/kex/curve25519_sha256_loader.rb +14 -6
- data/lib/net/ssh/transport/packet_stream.rb +0 -4
- data/lib/net/ssh/transport/server_version.rb +13 -33
- data/lib/net/ssh/transport/session.rb +1 -19
- data/lib/net/ssh/verifiers/accept_new_or_local_tunnel.rb +1 -3
- data/lib/net/ssh/verifiers/always.rb +1 -19
- data/lib/net/ssh/verifiers/never.rb +1 -2
- data/lib/net/ssh/version.rb +4 -4
- data/net-ssh.gemspec +3 -9
- data.tar.gz.sig +0 -0
- metadata +8 -52
- metadata.gz.sig +0 -0
- data/Gemfile.noed25519 +0 -12
- 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
|
-
|
|
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
|
-
|
|
107
|
+
GCMCipher::AUTH_TAG_BYTES
|
|
104
108
|
end
|
|
105
109
|
|
|
106
110
|
def block_size
|
|
107
|
-
|
|
111
|
+
GCMCipher::BLOCK_SIZE
|
|
108
112
|
end
|
|
109
113
|
|
|
110
114
|
def self.block_size
|
|
111
|
-
|
|
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
|
-
|
|
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
|
|
@@ -1,7 +1,4 @@
|
|
|
1
|
-
|
|
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
|
|
22
|
-
|
|
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.
|
|
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 =
|
|
33
|
-
OpenSSL::BN.new(ecdh.
|
|
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
|
|
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 =
|
|
18
|
-
description
|
|
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.
|
|
23
|
-
|
|
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
|
|
@@ -15,9 +15,6 @@ module Net
|
|
|
15
15
|
module PacketStream # rubocop:disable Metrics/ModuleLength
|
|
16
16
|
PROXY_COMMAND_HOST_IP = '<no hostip for proxy command>'.freeze
|
|
17
17
|
|
|
18
|
-
# Same limit as OpenSSH; a larger length would make us buffer whatever the server streams (GHSA-pfqh-p9vh-wx4p).
|
|
19
|
-
PACKET_MAX_SIZE = 256 * 1024
|
|
20
|
-
|
|
21
18
|
include BufferedIo
|
|
22
19
|
|
|
23
20
|
def self.extended(object)
|
|
@@ -243,7 +240,6 @@ module Net
|
|
|
243
240
|
@packet = Net::SSH::Buffer.new(server.update_cipher(data))
|
|
244
241
|
@packet_length = @packet.read_long
|
|
245
242
|
end
|
|
246
|
-
raise Net::SSH::Exception, "bad packet length #{@packet_length}" if @packet_length < 5 || @packet_length > PACKET_MAX_SIZE
|
|
247
243
|
end
|
|
248
244
|
|
|
249
245
|
need = @packet_length + 4 - aad_length - server.block_size
|
|
@@ -18,10 +18,6 @@ module Net
|
|
|
18
18
|
# The SSH version string as reported by Net::SSH
|
|
19
19
|
PROTO_VERSION = "SSH-2.0-Ruby/Net::SSH_#{Net::SSH::Version::CURRENT} #{RUBY_PLATFORM}"
|
|
20
20
|
|
|
21
|
-
# Same limits as OpenSSH, so a server can't make us buffer its banner without bound (GHSA-r75w-7fhp-84w8).
|
|
22
|
-
MAX_LINE_LENGTH = 8192
|
|
23
|
-
MAX_HEADER_LINES = 1024
|
|
24
|
-
|
|
25
21
|
# Any header text sent by the server prior to sending the version.
|
|
26
22
|
attr_reader :header
|
|
27
23
|
|
|
@@ -49,15 +45,24 @@ module Net
|
|
|
49
45
|
socket.write "#{PROTO_VERSION}\r\n"
|
|
50
46
|
socket.flush
|
|
51
47
|
|
|
52
|
-
|
|
48
|
+
raise Net::SSH::ConnectionTimeout, "timeout during server version negotiating" if timeout && !IO.select([socket], nil, nil, timeout)
|
|
53
49
|
|
|
54
|
-
|
|
55
|
-
@version =
|
|
50
|
+
loop do
|
|
51
|
+
@version = String.new
|
|
52
|
+
loop do
|
|
53
|
+
begin
|
|
54
|
+
b = socket.readpartial(1)
|
|
55
|
+
raise Net::SSH::Disconnect, "connection closed by remote host" if b.nil?
|
|
56
|
+
rescue EOFError
|
|
57
|
+
raise Net::SSH::Disconnect, "connection closed by remote host"
|
|
58
|
+
end
|
|
59
|
+
@version << b
|
|
60
|
+
break if b == "\n"
|
|
61
|
+
end
|
|
56
62
|
break if @version.match(/^SSH-/)
|
|
57
63
|
|
|
58
64
|
@header << @version
|
|
59
65
|
end
|
|
60
|
-
raise Net::SSH::Exception, "no SSH version received in the first #{MAX_HEADER_LINES} lines" unless @version.match(/^SSH-/)
|
|
61
66
|
|
|
62
67
|
@version.chomp!
|
|
63
68
|
debug { "remote is `#{@version}'" }
|
|
@@ -66,31 +71,6 @@ module Net
|
|
|
66
71
|
|
|
67
72
|
raise Net::SSH::ConnectionTimeout, "timeout during client version negotiating" if timeout && !IO.select(nil, [socket], nil, timeout)
|
|
68
73
|
end
|
|
69
|
-
|
|
70
|
-
def read_line(socket, deadline)
|
|
71
|
-
line = String.new
|
|
72
|
-
loop do
|
|
73
|
-
wait_readable(socket, deadline)
|
|
74
|
-
begin
|
|
75
|
-
b = socket.readpartial(1)
|
|
76
|
-
raise Net::SSH::Disconnect, "connection closed by remote host" if b.nil?
|
|
77
|
-
rescue EOFError
|
|
78
|
-
raise Net::SSH::Disconnect, "connection closed by remote host"
|
|
79
|
-
end
|
|
80
|
-
line << b
|
|
81
|
-
return line if b == "\n"
|
|
82
|
-
raise Net::SSH::Exception, "server version line exceeds #{MAX_LINE_LENGTH} bytes" if line.bytesize > MAX_LINE_LENGTH
|
|
83
|
-
end
|
|
84
|
-
end
|
|
85
|
-
|
|
86
|
-
def wait_readable(socket, deadline)
|
|
87
|
-
return unless deadline
|
|
88
|
-
|
|
89
|
-
remaining = deadline - Process.clock_gettime(Process::CLOCK_MONOTONIC)
|
|
90
|
-
return if remaining > 0 && IO.select([socket], nil, nil, remaining)
|
|
91
|
-
|
|
92
|
-
raise Net::SSH::ConnectionTimeout, "timeout during server version negotiating"
|
|
93
|
-
end
|
|
94
74
|
end
|
|
95
75
|
end
|
|
96
76
|
end
|
|
@@ -27,10 +27,6 @@ module Net
|
|
|
27
27
|
# The standard port for the SSH protocol.
|
|
28
28
|
DEFAULT_PORT = 22
|
|
29
29
|
|
|
30
|
-
# Packets held back during a re-key are bounded so a server can't exhaust memory (GHSA-ggxh-cfwq-5xqc).
|
|
31
|
-
MAX_QUEUED_PACKETS = 16_384
|
|
32
|
-
MAX_QUEUED_BYTES = 32 * 1024 * 1024
|
|
33
|
-
|
|
34
30
|
# The host to connect to, as given to the constructor.
|
|
35
31
|
attr_reader :host
|
|
36
32
|
|
|
@@ -83,7 +79,6 @@ module Net
|
|
|
83
79
|
debug { "connection established" }
|
|
84
80
|
|
|
85
81
|
@queue = []
|
|
86
|
-
@queued_bytes = 0
|
|
87
82
|
|
|
88
83
|
@host_key_verifier = select_host_key_verifier(options[:verify_host_key])
|
|
89
84
|
|
|
@@ -193,7 +188,7 @@ module Net
|
|
|
193
188
|
# read from the queue before the socket is queried.
|
|
194
189
|
def poll_message(mode = :nonblock, consume_queue = true)
|
|
195
190
|
loop do
|
|
196
|
-
return
|
|
191
|
+
return @queue.shift if consume_queue && @queue.any? && algorithms.allow?(@queue.first)
|
|
197
192
|
|
|
198
193
|
packet = socket.next_packet(mode, options[:timeout])
|
|
199
194
|
return nil if packet.nil?
|
|
@@ -216,8 +211,6 @@ module Net
|
|
|
216
211
|
|
|
217
212
|
else
|
|
218
213
|
return packet if algorithms.allow?(packet)
|
|
219
|
-
# Algorithms#rekey! clears initialized?, so the session id is what marks the first key exchange as done.
|
|
220
|
-
raise Net::SSH::Exception, "unexpected packet type #{packet.type} during initial key exchange" unless algorithms.session_id
|
|
221
214
|
|
|
222
215
|
push(packet)
|
|
223
216
|
end
|
|
@@ -241,11 +234,6 @@ module Net
|
|
|
241
234
|
# #poll_message will return packets from the queue in the order they
|
|
242
235
|
# were received.
|
|
243
236
|
def push(packet)
|
|
244
|
-
@queued_bytes += packet.length
|
|
245
|
-
if @queue.size >= MAX_QUEUED_PACKETS || @queued_bytes > MAX_QUEUED_BYTES
|
|
246
|
-
raise Net::SSH::Exception, "too many packets queued during key exchange"
|
|
247
|
-
end
|
|
248
|
-
|
|
249
237
|
@queue.push(packet)
|
|
250
238
|
end
|
|
251
239
|
|
|
@@ -288,12 +276,6 @@ module Net
|
|
|
288
276
|
|
|
289
277
|
private
|
|
290
278
|
|
|
291
|
-
def shift_queue
|
|
292
|
-
packet = @queue.shift
|
|
293
|
-
@queued_bytes -= packet.length
|
|
294
|
-
packet
|
|
295
|
-
end
|
|
296
|
-
|
|
297
279
|
# Compatibility verifier which allows users to keep using
|
|
298
280
|
# custom verifier code without adding new :verify_signature
|
|
299
281
|
# method.
|
|
@@ -7,13 +7,11 @@ module Net
|
|
|
7
7
|
# verify a connection if the server is the localhost and the port is a
|
|
8
8
|
# nonstandard port number. Those two conditions will typically mean the
|
|
9
9
|
# connection is being tunnelled through a forwarded port, so the known-hosts
|
|
10
|
-
# file will not be helpful (in general).
|
|
11
|
-
# either way.
|
|
10
|
+
# file will not be helpful (in general).
|
|
12
11
|
class AcceptNewOrLocalTunnel < AcceptNew
|
|
13
12
|
# Tries to determine if the connection is being tunnelled, and if so,
|
|
14
13
|
# returns true. Otherwise, performs the standard strict verification.
|
|
15
14
|
def verify(arguments)
|
|
16
|
-
refuse_revoked!(arguments)
|
|
17
15
|
return true if tunnelled?(arguments)
|
|
18
16
|
|
|
19
17
|
super
|
|
@@ -10,13 +10,10 @@ module Net
|
|
|
10
10
|
# (HostKeyUnknown). This is in contrast to the "Strict" class, which will
|
|
11
11
|
# silently add the key to your known_hosts file. If the server does appear at
|
|
12
12
|
# least once, but the key given does not match any known for the server, an
|
|
13
|
-
# exception will be raised (HostKeyMismatch).
|
|
14
|
-
# host file is always refused (HostKeyRevoked).
|
|
13
|
+
# exception will be raised (HostKeyMismatch).
|
|
15
14
|
# Otherwise, this returns true.
|
|
16
15
|
class Always
|
|
17
16
|
def verify(arguments)
|
|
18
|
-
refuse_revoked!(arguments)
|
|
19
|
-
|
|
20
17
|
host_keys = arguments[:session].host_keys
|
|
21
18
|
|
|
22
19
|
# We've never seen this host before, so raise an exception.
|
|
@@ -50,25 +47,10 @@ module Net
|
|
|
50
47
|
|
|
51
48
|
private
|
|
52
49
|
|
|
53
|
-
# Custom :known_hosts objects may return a host_keys collection with no
|
|
54
|
-
# revocation support.
|
|
55
|
-
def refuse_revoked!(arguments)
|
|
56
|
-
host_keys = arguments[:session].host_keys
|
|
57
|
-
return unless host_keys.respond_to?(:revoked?) && host_keys.revoked?(arguments[:key])
|
|
58
|
-
|
|
59
|
-
exception = HostKeyRevoked.new("fingerprint #{arguments[:fingerprint]} " +
|
|
60
|
-
"is revoked for #{host_keys.host.inspect}")
|
|
61
|
-
exception.data = arguments
|
|
62
|
-
raise exception
|
|
63
|
-
end
|
|
64
|
-
|
|
65
50
|
# Enforces the @cert-authority certificate constraints for entries that
|
|
66
51
|
# implement them (Net::SSH::HostKeyEntries::CertAuthority). Non-certificate
|
|
67
52
|
# entries do not respond to these predicates and are left untouched.
|
|
68
53
|
def verify_certificate!(entry, host_keys, arguments)
|
|
69
|
-
# Plain keys carry no certificate constraints, and respond_to? on this delegator prints a deprecation warning (#1026).
|
|
70
|
-
return if entry.is_a?(Net::SSH::HostKeyEntries::PubKey)
|
|
71
|
-
|
|
72
54
|
cert = arguments[:key]
|
|
73
55
|
|
|
74
56
|
if entry.respond_to?(:matches_validity?) && !entry.matches_validity?(cert)
|
|
@@ -3,8 +3,7 @@ module Net
|
|
|
3
3
|
module Verifiers
|
|
4
4
|
# This host key verifier simply allows every key it sees, without
|
|
5
5
|
# any verification. This is simple, but very insecure because it
|
|
6
|
-
# exposes you to MiTM attacks.
|
|
7
|
-
# so it accepts keys marked @revoked as well.
|
|
6
|
+
# exposes you to MiTM attacks.
|
|
8
7
|
class Never
|
|
9
8
|
# Returns true.
|
|
10
9
|
def verify(arguments)
|
data/lib/net/ssh/version.rb
CHANGED
|
@@ -46,17 +46,17 @@ module Net
|
|
|
46
46
|
end
|
|
47
47
|
|
|
48
48
|
# The major component of this version of the Net::SSH library
|
|
49
|
-
MAJOR =
|
|
49
|
+
MAJOR = 8
|
|
50
50
|
|
|
51
51
|
# The minor component of this version of the Net::SSH library
|
|
52
|
-
MINOR =
|
|
52
|
+
MINOR = 0
|
|
53
53
|
|
|
54
54
|
# The tiny component of this version of the Net::SSH library
|
|
55
|
-
TINY =
|
|
55
|
+
TINY = 0
|
|
56
56
|
|
|
57
57
|
# The prerelease component of this version of the Net::SSH library
|
|
58
58
|
# nil allowed
|
|
59
|
-
PRE =
|
|
59
|
+
PRE = "beta3"
|
|
60
60
|
|
|
61
61
|
# The current version of the Net::SSH library as a Version instance
|
|
62
62
|
CURRENT = new(*[MAJOR, MINOR, TINY, PRE].compact)
|
data/net-ssh.gemspec
CHANGED
|
@@ -15,7 +15,7 @@ Gem::Specification.new do |spec|
|
|
|
15
15
|
spec.description = %q{Net::SSH: a pure-Ruby implementation of the SSH2 client protocol. It allows you to write programs that invoke and interact with processes on remote servers, via SSH2.}
|
|
16
16
|
spec.homepage = "https://github.com/net-ssh/net-ssh"
|
|
17
17
|
spec.license = "MIT"
|
|
18
|
-
spec.required_ruby_version = Gem::Requirement.new(">= 2.
|
|
18
|
+
spec.required_ruby_version = Gem::Requirement.new(">= 2.7")
|
|
19
19
|
spec.metadata = {
|
|
20
20
|
"changelog_uri" => "https://github.com/net-ssh/net-ssh/blob/master/CHANGES.txt"
|
|
21
21
|
}
|
|
@@ -30,15 +30,9 @@ Gem::Specification.new do |spec|
|
|
|
30
30
|
spec.executables = spec.files.grep(%r{^exe/}) { |f| File.basename(f) }
|
|
31
31
|
spec.require_paths = ["lib"]
|
|
32
32
|
|
|
33
|
-
spec.add_dependency("
|
|
33
|
+
spec.add_dependency("openssl", ">= 3.2.0")
|
|
34
34
|
|
|
35
|
-
unless
|
|
36
|
-
spec.add_development_dependency("bcrypt_pbkdf", "~> 1.0") unless RUBY_PLATFORM == "java"
|
|
37
|
-
spec.add_development_dependency("ed25519", "~> 1.2")
|
|
38
|
-
spec.add_development_dependency('x25519') unless RUBY_PLATFORM == 'java'
|
|
39
|
-
end
|
|
40
|
-
|
|
41
|
-
spec.add_development_dependency('rbnacl', '~> 7.1') unless ENV['NET_SSH_NO_RBNACL']
|
|
35
|
+
spec.add_development_dependency("bcrypt_pbkdf", "~> 1.0") unless RUBY_PLATFORM == "java"
|
|
42
36
|
|
|
43
37
|
spec.add_development_dependency "base64"
|
|
44
38
|
spec.add_development_dependency "bundler", ">= 1.17"
|
data.tar.gz.sig
CHANGED
|
Binary file
|
metadata
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
|
2
2
|
name: net-ssh
|
|
3
3
|
version: !ruby/object:Gem::Version
|
|
4
|
-
version:
|
|
4
|
+
version: 8.0.0.beta3
|
|
5
5
|
platform: ruby
|
|
6
6
|
authors:
|
|
7
7
|
- Jamis Buck
|
|
@@ -32,22 +32,22 @@ cert_chain:
|
|
|
32
32
|
ufHf4AX2UIkJbh7zCPkiNCqIr7MSWLNFG/9lOlHYsEJM8XujT1ofPobYx6YSFx/C
|
|
33
33
|
7HBrI7UX7awt6UvBZebhcHzyMHxg/B5PVQllPA==
|
|
34
34
|
-----END CERTIFICATE-----
|
|
35
|
-
date: 2026-
|
|
35
|
+
date: 2026-08-09 00:00:00.000000000 Z
|
|
36
36
|
dependencies:
|
|
37
37
|
- !ruby/object:Gem::Dependency
|
|
38
|
-
name:
|
|
38
|
+
name: openssl
|
|
39
39
|
requirement: !ruby/object:Gem::Requirement
|
|
40
40
|
requirements:
|
|
41
41
|
- - ">="
|
|
42
42
|
- !ruby/object:Gem::Version
|
|
43
|
-
version:
|
|
43
|
+
version: 3.2.0
|
|
44
44
|
type: :runtime
|
|
45
45
|
prerelease: false
|
|
46
46
|
version_requirements: !ruby/object:Gem::Requirement
|
|
47
47
|
requirements:
|
|
48
48
|
- - ">="
|
|
49
49
|
- !ruby/object:Gem::Version
|
|
50
|
-
version:
|
|
50
|
+
version: 3.2.0
|
|
51
51
|
- !ruby/object:Gem::Dependency
|
|
52
52
|
name: bcrypt_pbkdf
|
|
53
53
|
requirement: !ruby/object:Gem::Requirement
|
|
@@ -62,48 +62,6 @@ dependencies:
|
|
|
62
62
|
- - "~>"
|
|
63
63
|
- !ruby/object:Gem::Version
|
|
64
64
|
version: '1.0'
|
|
65
|
-
- !ruby/object:Gem::Dependency
|
|
66
|
-
name: ed25519
|
|
67
|
-
requirement: !ruby/object:Gem::Requirement
|
|
68
|
-
requirements:
|
|
69
|
-
- - "~>"
|
|
70
|
-
- !ruby/object:Gem::Version
|
|
71
|
-
version: '1.2'
|
|
72
|
-
type: :development
|
|
73
|
-
prerelease: false
|
|
74
|
-
version_requirements: !ruby/object:Gem::Requirement
|
|
75
|
-
requirements:
|
|
76
|
-
- - "~>"
|
|
77
|
-
- !ruby/object:Gem::Version
|
|
78
|
-
version: '1.2'
|
|
79
|
-
- !ruby/object:Gem::Dependency
|
|
80
|
-
name: x25519
|
|
81
|
-
requirement: !ruby/object:Gem::Requirement
|
|
82
|
-
requirements:
|
|
83
|
-
- - ">="
|
|
84
|
-
- !ruby/object:Gem::Version
|
|
85
|
-
version: '0'
|
|
86
|
-
type: :development
|
|
87
|
-
prerelease: false
|
|
88
|
-
version_requirements: !ruby/object:Gem::Requirement
|
|
89
|
-
requirements:
|
|
90
|
-
- - ">="
|
|
91
|
-
- !ruby/object:Gem::Version
|
|
92
|
-
version: '0'
|
|
93
|
-
- !ruby/object:Gem::Dependency
|
|
94
|
-
name: rbnacl
|
|
95
|
-
requirement: !ruby/object:Gem::Requirement
|
|
96
|
-
requirements:
|
|
97
|
-
- - "~>"
|
|
98
|
-
- !ruby/object:Gem::Version
|
|
99
|
-
version: '7.1'
|
|
100
|
-
type: :development
|
|
101
|
-
prerelease: false
|
|
102
|
-
version_requirements: !ruby/object:Gem::Requirement
|
|
103
|
-
requirements:
|
|
104
|
-
- - "~>"
|
|
105
|
-
- !ruby/object:Gem::Version
|
|
106
|
-
version: '7.1'
|
|
107
65
|
- !ruby/object:Gem::Dependency
|
|
108
66
|
name: base64
|
|
109
67
|
requirement: !ruby/object:Gem::Requirement
|
|
@@ -228,8 +186,6 @@ files:
|
|
|
228
186
|
- Dockerfile.openssl3
|
|
229
187
|
- Dockerfile.zlib_ng
|
|
230
188
|
- Gemfile
|
|
231
|
-
- Gemfile.noed25519
|
|
232
|
-
- Gemfile.norbnacl
|
|
233
189
|
- ISSUE_TEMPLATE.md
|
|
234
190
|
- LICENSE.txt
|
|
235
191
|
- Manifest
|
|
@@ -352,12 +308,12 @@ required_ruby_version: !ruby/object:Gem::Requirement
|
|
|
352
308
|
requirements:
|
|
353
309
|
- - ">="
|
|
354
310
|
- !ruby/object:Gem::Version
|
|
355
|
-
version: '2.
|
|
311
|
+
version: '2.7'
|
|
356
312
|
required_rubygems_version: !ruby/object:Gem::Requirement
|
|
357
313
|
requirements:
|
|
358
|
-
- - "
|
|
314
|
+
- - ">"
|
|
359
315
|
- !ruby/object:Gem::Version
|
|
360
|
-
version:
|
|
316
|
+
version: 1.3.1
|
|
361
317
|
requirements: []
|
|
362
318
|
rubygems_version: 3.3.3
|
|
363
319
|
signing_key:
|
metadata.gz.sig
CHANGED
|
Binary file
|
data/Gemfile.noed25519
DELETED
|
@@ -1,12 +0,0 @@
|
|
|
1
|
-
source 'https://rubygems.org'
|
|
2
|
-
|
|
3
|
-
ENV['NET_SSH_NO_ED25519'] = 'true'
|
|
4
|
-
# Specify your gem's dependencies in mygem.gemspec
|
|
5
|
-
gemspec
|
|
6
|
-
|
|
7
|
-
if ENV["CI"] && !Gem.win_platform?
|
|
8
|
-
gem 'simplecov', require: false, group: :test
|
|
9
|
-
gem 'codecov', require: false, group: :test
|
|
10
|
-
end
|
|
11
|
-
|
|
12
|
-
gem 'webrick', group: %i[development test] if RUBY_VERSION.split(".")[0].to_i >= 3
|
data/Gemfile.norbnacl
DELETED
|
@@ -1,12 +0,0 @@
|
|
|
1
|
-
source 'https://rubygems.org'
|
|
2
|
-
|
|
3
|
-
ENV['NET_SSH_NO_RBNACL'] = 'true'
|
|
4
|
-
# Specify your gem's dependencies in mygem.gemspec
|
|
5
|
-
gemspec
|
|
6
|
-
|
|
7
|
-
if ENV["CI"] && !Gem.win_platform?
|
|
8
|
-
gem 'simplecov', require: false, group: :test
|
|
9
|
-
gem 'codecov', require: false, group: :test
|
|
10
|
-
end
|
|
11
|
-
|
|
12
|
-
gem 'webrick', group: %i[development test] if RUBY_VERSION.split(".")[0].to_i >= 3
|