net-ssh 6.0.2 → 7.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 +2 -1
- data/.dockerignore +6 -0
- data/.github/config/rubocop_linter_action.yml +4 -0
- data/.github/workflows/ci-with-docker.yml +44 -0
- data/.github/workflows/ci.yml +87 -0
- data/.github/workflows/rubocop.yml +16 -0
- data/.gitignore +2 -0
- data/.rubocop.yml +12 -1
- data/.rubocop_todo.yml +474 -375
- data/CHANGES.txt +51 -3
- data/Dockerfile +27 -0
- data/Dockerfile.openssl3 +17 -0
- data/Gemfile +2 -0
- data/Gemfile.noed25519 +2 -0
- data/README.md +19 -8
- data/Rakefile +59 -0
- data/SECURITY.md +4 -0
- data/docker-compose.yml +23 -0
- data/lib/net/ssh/authentication/agent.rb +29 -13
- data/lib/net/ssh/authentication/certificate.rb +14 -11
- data/lib/net/ssh/authentication/constants.rb +0 -1
- data/lib/net/ssh/authentication/ed25519.rb +12 -7
- data/lib/net/ssh/authentication/ed25519_loader.rb +4 -7
- data/lib/net/ssh/authentication/key_manager.rb +46 -34
- data/lib/net/ssh/authentication/methods/abstract.rb +12 -3
- data/lib/net/ssh/authentication/methods/hostbased.rb +3 -5
- data/lib/net/ssh/authentication/methods/keyboard_interactive.rb +2 -2
- data/lib/net/ssh/authentication/methods/none.rb +6 -9
- data/lib/net/ssh/authentication/methods/password.rb +2 -3
- data/lib/net/ssh/authentication/methods/publickey.rb +56 -16
- data/lib/net/ssh/authentication/pageant.rb +97 -97
- data/lib/net/ssh/authentication/pub_key_fingerprint.rb +2 -2
- data/lib/net/ssh/authentication/session.rb +18 -17
- data/lib/net/ssh/buffer.rb +71 -51
- data/lib/net/ssh/buffered_io.rb +24 -25
- data/lib/net/ssh/config.rb +33 -20
- data/lib/net/ssh/connection/channel.rb +84 -82
- data/lib/net/ssh/connection/constants.rb +0 -4
- data/lib/net/ssh/connection/event_loop.rb +30 -24
- data/lib/net/ssh/connection/keepalive.rb +12 -12
- data/lib/net/ssh/connection/session.rb +109 -108
- data/lib/net/ssh/connection/term.rb +56 -58
- data/lib/net/ssh/errors.rb +12 -12
- data/lib/net/ssh/key_factory.rb +7 -8
- data/lib/net/ssh/known_hosts.rb +84 -15
- data/lib/net/ssh/loggable.rb +8 -9
- data/lib/net/ssh/packet.rb +1 -1
- data/lib/net/ssh/prompt.rb +9 -11
- data/lib/net/ssh/proxy/command.rb +1 -1
- data/lib/net/ssh/proxy/errors.rb +2 -4
- data/lib/net/ssh/proxy/http.rb +18 -20
- data/lib/net/ssh/proxy/https.rb +8 -10
- data/lib/net/ssh/proxy/jump.rb +8 -10
- data/lib/net/ssh/proxy/socks4.rb +2 -4
- data/lib/net/ssh/proxy/socks5.rb +3 -5
- data/lib/net/ssh/service/forward.rb +7 -7
- data/lib/net/ssh/test/channel.rb +24 -26
- data/lib/net/ssh/test/extensions.rb +35 -35
- data/lib/net/ssh/test/kex.rb +6 -8
- data/lib/net/ssh/test/local_packet.rb +0 -2
- data/lib/net/ssh/test/packet.rb +3 -3
- data/lib/net/ssh/test/remote_packet.rb +6 -8
- data/lib/net/ssh/test/script.rb +25 -27
- data/lib/net/ssh/test/socket.rb +12 -15
- data/lib/net/ssh/test.rb +4 -5
- data/lib/net/ssh/transport/algorithms.rb +37 -21
- data/lib/net/ssh/transport/cipher_factory.rb +28 -28
- data/lib/net/ssh/transport/constants.rb +3 -3
- data/lib/net/ssh/transport/ctr.rb +7 -7
- data/lib/net/ssh/transport/hmac/abstract.rb +4 -5
- data/lib/net/ssh/transport/hmac/md5.rb +0 -2
- data/lib/net/ssh/transport/hmac/md5_96.rb +0 -2
- data/lib/net/ssh/transport/hmac/none.rb +0 -2
- data/lib/net/ssh/transport/hmac/ripemd160.rb +0 -2
- data/lib/net/ssh/transport/hmac/sha1.rb +0 -2
- data/lib/net/ssh/transport/hmac/sha1_96.rb +0 -2
- data/lib/net/ssh/transport/hmac.rb +12 -12
- data/lib/net/ssh/transport/identity_cipher.rb +11 -13
- data/lib/net/ssh/transport/kex/abstract.rb +12 -5
- data/lib/net/ssh/transport/kex/abstract5656.rb +1 -1
- data/lib/net/ssh/transport/kex/curve25519_sha256.rb +2 -1
- data/lib/net/ssh/transport/kex/diffie_hellman_group14_sha1.rb +4 -4
- data/lib/net/ssh/transport/kex/diffie_hellman_group14_sha256.rb +11 -0
- data/lib/net/ssh/transport/kex/diffie_hellman_group1_sha1.rb +21 -21
- data/lib/net/ssh/transport/kex/diffie_hellman_group_exchange_sha1.rb +1 -2
- data/lib/net/ssh/transport/kex/ecdh_sha2_nistp256.rb +2 -2
- data/lib/net/ssh/transport/kex.rb +8 -6
- data/lib/net/ssh/transport/key_expander.rb +7 -8
- data/lib/net/ssh/transport/openssl.rb +51 -26
- data/lib/net/ssh/transport/packet_stream.rb +2 -3
- data/lib/net/ssh/transport/server_version.rb +17 -16
- data/lib/net/ssh/transport/session.rb +9 -7
- data/lib/net/ssh/transport/state.rb +43 -43
- data/lib/net/ssh/verifiers/accept_new.rb +0 -2
- data/lib/net/ssh/verifiers/accept_new_or_local_tunnel.rb +1 -2
- data/lib/net/ssh/verifiers/always.rb +6 -4
- data/lib/net/ssh/verifiers/never.rb +0 -2
- data/lib/net/ssh/version.rb +3 -3
- data/lib/net/ssh.rb +11 -7
- data/net-ssh-public_cert.pem +8 -8
- data/net-ssh.gemspec +2 -2
- data/support/ssh_tunnel_bug.rb +3 -3
- data.tar.gz.sig +0 -0
- metadata +24 -15
- metadata.gz.sig +0 -0
- data/.travis.yml +0 -52
|
@@ -6,7 +6,6 @@ require 'net/ssh/authentication/agent'
|
|
|
6
6
|
module Net
|
|
7
7
|
module SSH
|
|
8
8
|
module Authentication
|
|
9
|
-
|
|
10
9
|
# A trivial exception class used to report errors in the key manager.
|
|
11
10
|
class KeyManagerError < Net::SSH::Exception; end
|
|
12
11
|
|
|
@@ -42,7 +41,7 @@ module Net
|
|
|
42
41
|
# Create a new KeyManager. By default, the manager will
|
|
43
42
|
# use the ssh-agent if it is running and the `:use_agent` option
|
|
44
43
|
# is not false.
|
|
45
|
-
def initialize(logger, options={})
|
|
44
|
+
def initialize(logger, options = {})
|
|
46
45
|
self.logger = logger
|
|
47
46
|
@key_files = []
|
|
48
47
|
@key_data = []
|
|
@@ -159,7 +158,7 @@ module Net
|
|
|
159
158
|
# Regardless of the identity's origin or who does the signing, this
|
|
160
159
|
# will always return the signature in an SSH2-specified "signature
|
|
161
160
|
# blob" format.
|
|
162
|
-
def sign(identity, data)
|
|
161
|
+
def sign(identity, data, sig_alg = nil)
|
|
163
162
|
info = known_identities[identity] or raise KeyManagerError, "the given identity is unknown to the key manager"
|
|
164
163
|
|
|
165
164
|
if info[:key].nil? && info[:from] == :file
|
|
@@ -171,13 +170,27 @@ module Net
|
|
|
171
170
|
end
|
|
172
171
|
|
|
173
172
|
if info[:key]
|
|
174
|
-
|
|
175
|
-
|
|
173
|
+
if sig_alg.nil?
|
|
174
|
+
signed = info[:key].ssh_do_sign(data.to_s)
|
|
175
|
+
sig_alg = identity.ssh_signature_type
|
|
176
|
+
else
|
|
177
|
+
signed = info[:key].ssh_do_sign(data.to_s, sig_alg)
|
|
178
|
+
end
|
|
179
|
+
return Net::SSH::Buffer.from(:string, sig_alg,
|
|
180
|
+
:mstring, signed).to_s
|
|
176
181
|
end
|
|
177
182
|
|
|
178
183
|
if info[:from] == :agent
|
|
179
184
|
raise KeyManagerError, "the agent is no longer available" unless agent
|
|
180
|
-
|
|
185
|
+
|
|
186
|
+
case sig_alg
|
|
187
|
+
when "rsa-sha2-512"
|
|
188
|
+
return agent.sign(info[:identity], data.to_s, Net::SSH::Authentication::Agent::SSH_AGENT_RSA_SHA2_512)
|
|
189
|
+
when "rsa-sha2-256"
|
|
190
|
+
return agent.sign(info[:identity], data.to_s, Net::SSH::Authentication::Agent::SSH_AGENT_RSA_SHA2_256)
|
|
191
|
+
else
|
|
192
|
+
return agent.sign(info[:identity], data.to_s)
|
|
193
|
+
end
|
|
181
194
|
end
|
|
182
195
|
|
|
183
196
|
raise KeyManagerError, "[BUG] can't determine identity origin (#{info.inspect})"
|
|
@@ -201,6 +214,7 @@ module Net
|
|
|
201
214
|
# or if the agent is otherwise not available.
|
|
202
215
|
def agent
|
|
203
216
|
return unless use_agent?
|
|
217
|
+
|
|
204
218
|
@agent ||= Agent.connect(logger, options[:agent_socket_factory], options[:identity_agent])
|
|
205
219
|
rescue AgentNotAvailable
|
|
206
220
|
@use_agent = false
|
|
@@ -248,37 +262,35 @@ module Net
|
|
|
248
262
|
# Load prepared identities. Private key decryption errors ignored if ignore_decryption_errors
|
|
249
263
|
def load_identities(identities, ask_passphrase, ignore_decryption_errors)
|
|
250
264
|
identities.map do |identity|
|
|
251
|
-
|
|
252
|
-
|
|
253
|
-
|
|
254
|
-
|
|
255
|
-
|
|
256
|
-
|
|
257
|
-
|
|
258
|
-
|
|
259
|
-
|
|
260
|
-
|
|
261
|
-
|
|
262
|
-
|
|
263
|
-
|
|
264
|
-
|
|
265
|
-
|
|
266
|
-
|
|
267
|
-
|
|
268
|
-
|
|
269
|
-
|
|
270
|
-
|
|
271
|
-
|
|
272
|
-
|
|
273
|
-
|
|
274
|
-
else
|
|
275
|
-
process_identity_loading_error(identity, e)
|
|
276
|
-
nil
|
|
277
|
-
end
|
|
278
|
-
rescue Exception => e
|
|
265
|
+
case identity[:load_from]
|
|
266
|
+
when :pubkey_file
|
|
267
|
+
key = KeyFactory.load_public_key(identity[:pubkey_file])
|
|
268
|
+
{ public_key: key, from: :file, file: identity[:privkey_file] }
|
|
269
|
+
when :privkey_file
|
|
270
|
+
private_key = KeyFactory.load_private_key(
|
|
271
|
+
identity[:privkey_file], options[:passphrase], ask_passphrase, options[:password_prompt]
|
|
272
|
+
)
|
|
273
|
+
key = private_key.send(:public_key)
|
|
274
|
+
{ public_key: key, from: :file, file: identity[:privkey_file], key: private_key }
|
|
275
|
+
when :data
|
|
276
|
+
private_key = KeyFactory.load_data_private_key(
|
|
277
|
+
identity[:data], options[:passphrase], ask_passphrase, "<key in memory>", options[:password_prompt]
|
|
278
|
+
)
|
|
279
|
+
key = private_key.send(:public_key)
|
|
280
|
+
{ public_key: key, from: :key_data, data: identity[:data], key: private_key }
|
|
281
|
+
else
|
|
282
|
+
identity
|
|
283
|
+
end
|
|
284
|
+
rescue OpenSSL::PKey::RSAError, OpenSSL::PKey::DSAError, OpenSSL::PKey::ECError, OpenSSL::PKey::PKeyError, ArgumentError => e
|
|
285
|
+
if ignore_decryption_errors
|
|
286
|
+
identity
|
|
287
|
+
else
|
|
279
288
|
process_identity_loading_error(identity, e)
|
|
280
289
|
nil
|
|
281
290
|
end
|
|
291
|
+
rescue Exception => e
|
|
292
|
+
process_identity_loading_error(identity, e)
|
|
293
|
+
nil
|
|
282
294
|
end.compact
|
|
283
295
|
end
|
|
284
296
|
|
|
@@ -7,7 +7,6 @@ module Net
|
|
|
7
7
|
module SSH
|
|
8
8
|
module Authentication
|
|
9
9
|
module Methods
|
|
10
|
-
|
|
11
10
|
# The base class of all user authentication methods. It provides a few
|
|
12
11
|
# bits of common functionality.
|
|
13
12
|
class Abstract
|
|
@@ -21,12 +20,22 @@ module Net
|
|
|
21
20
|
# this.
|
|
22
21
|
attr_reader :key_manager
|
|
23
22
|
|
|
23
|
+
# So far only affects algorithms used for rsa keys, but can be
|
|
24
|
+
# extended to other keys, e.g after reading of
|
|
25
|
+
# PubkeyAcceptedAlgorithms option from ssh_config file is implemented.
|
|
26
|
+
attr_reader :pubkey_algorithms
|
|
27
|
+
|
|
24
28
|
# Instantiates a new authentication method.
|
|
25
|
-
def initialize(session, options={})
|
|
29
|
+
def initialize(session, options = {})
|
|
26
30
|
@session = session
|
|
27
31
|
@key_manager = options[:key_manager]
|
|
28
32
|
@options = options
|
|
29
33
|
@prompt = options[:password_prompt]
|
|
34
|
+
@pubkey_algorithms = options[:pubkey_algorithms] \
|
|
35
|
+
|| %w[rsa-sha2-256-cert-v01@openssh.com
|
|
36
|
+
ssh-rsa-cert-v01@openssh.com
|
|
37
|
+
rsa-sha2-256
|
|
38
|
+
ssh-rsa]
|
|
30
39
|
self.logger = session.logger
|
|
31
40
|
end
|
|
32
41
|
|
|
@@ -47,7 +56,7 @@ module Net
|
|
|
47
56
|
# of the packet. The new packet is returned, ready for sending.
|
|
48
57
|
def userauth_request(username, next_service, auth_method, *others)
|
|
49
58
|
buffer = Net::SSH::Buffer.from(:byte, USERAUTH_REQUEST,
|
|
50
|
-
|
|
59
|
+
:string, username, :string, next_service, :string, auth_method)
|
|
51
60
|
|
|
52
61
|
others.each do |value|
|
|
53
62
|
case value
|
|
@@ -4,19 +4,18 @@ module Net
|
|
|
4
4
|
module SSH
|
|
5
5
|
module Authentication
|
|
6
6
|
module Methods
|
|
7
|
-
|
|
8
7
|
# Implements the host-based SSH authentication method.
|
|
9
8
|
class Hostbased < Abstract
|
|
10
9
|
include Constants
|
|
11
10
|
|
|
12
11
|
# Attempts to perform host-based authorization of the user by trying
|
|
13
12
|
# all known keys.
|
|
14
|
-
def authenticate(next_service, username, password=nil)
|
|
13
|
+
def authenticate(next_service, username, password = nil)
|
|
15
14
|
return false unless key_manager
|
|
16
15
|
|
|
17
16
|
key_manager.each_identity do |identity|
|
|
18
17
|
return true if authenticate_with(identity, next_service,
|
|
19
|
-
|
|
18
|
+
username, key_manager)
|
|
20
19
|
end
|
|
21
20
|
|
|
22
21
|
return false
|
|
@@ -64,10 +63,9 @@ module Net
|
|
|
64
63
|
# Build the "core" hostbased request string.
|
|
65
64
|
def build_request(identity, next_service, username, hostname, client_username)
|
|
66
65
|
userauth_request(username, next_service, "hostbased", identity.ssh_type,
|
|
67
|
-
|
|
66
|
+
Buffer.from(:key, identity).to_s, hostname, client_username).to_s
|
|
68
67
|
end
|
|
69
68
|
end
|
|
70
|
-
|
|
71
69
|
end
|
|
72
70
|
end
|
|
73
71
|
end
|
|
@@ -5,14 +5,13 @@ module Net
|
|
|
5
5
|
module SSH
|
|
6
6
|
module Authentication
|
|
7
7
|
module Methods
|
|
8
|
-
|
|
9
8
|
# Implements the "keyboard-interactive" SSH authentication method.
|
|
10
9
|
class KeyboardInteractive < Abstract
|
|
11
10
|
USERAUTH_INFO_REQUEST = 60
|
|
12
11
|
USERAUTH_INFO_RESPONSE = 61
|
|
13
12
|
|
|
14
13
|
# Attempt to authenticate the given user for the given service.
|
|
15
|
-
def authenticate(next_service, username, password=nil)
|
|
14
|
+
def authenticate(next_service, username, password = nil)
|
|
16
15
|
debug { "trying keyboard-interactive" }
|
|
17
16
|
send_message(userauth_request(username, next_service, "keyboard-interactive", "", ""))
|
|
18
17
|
|
|
@@ -32,6 +31,7 @@ module Net
|
|
|
32
31
|
message[:authentications].split(/,/).include? 'keyboard-interactive'
|
|
33
32
|
|
|
34
33
|
return false unless interactive?
|
|
34
|
+
|
|
35
35
|
password = nil
|
|
36
36
|
debug { "retrying keyboard-interactive" }
|
|
37
37
|
send_message(userauth_request(username, next_service, "keyboard-interactive", "", ""))
|
|
@@ -5,32 +5,29 @@ module Net
|
|
|
5
5
|
module SSH
|
|
6
6
|
module Authentication
|
|
7
7
|
module Methods
|
|
8
|
-
|
|
9
8
|
# Implements the "none" SSH authentication method.
|
|
10
9
|
class None < Abstract
|
|
11
10
|
# Attempt to authenticate as "none"
|
|
12
|
-
def authenticate(next_service, user="", password="")
|
|
13
|
-
send_message(userauth_request(user, next_service, "none"))
|
|
11
|
+
def authenticate(next_service, user = "", password = "")
|
|
12
|
+
send_message(userauth_request(user, next_service, "none"))
|
|
14
13
|
message = session.next_message
|
|
15
|
-
|
|
14
|
+
|
|
16
15
|
case message.type
|
|
17
16
|
when USERAUTH_SUCCESS
|
|
18
17
|
debug { "none succeeded" }
|
|
19
18
|
return true
|
|
20
19
|
when USERAUTH_FAILURE
|
|
21
20
|
debug { "none failed" }
|
|
22
|
-
|
|
21
|
+
|
|
23
22
|
raise Net::SSH::Authentication::DisallowedMethod unless
|
|
24
23
|
message[:authentications].split(/,/).include? 'none'
|
|
25
|
-
|
|
24
|
+
|
|
26
25
|
return false
|
|
27
26
|
else
|
|
28
27
|
raise Net::SSH::Exception, "unexpected reply to USERAUTH_REQUEST: #{message.type} (#{message.inspect})"
|
|
29
|
-
end
|
|
30
|
-
|
|
28
|
+
end
|
|
31
29
|
end
|
|
32
30
|
end
|
|
33
|
-
|
|
34
31
|
end
|
|
35
32
|
end
|
|
36
33
|
end
|
|
@@ -6,12 +6,11 @@ module Net
|
|
|
6
6
|
module SSH
|
|
7
7
|
module Authentication
|
|
8
8
|
module Methods
|
|
9
|
-
|
|
10
9
|
# Implements the "password" SSH authentication method.
|
|
11
10
|
class Password < Abstract
|
|
12
11
|
# Attempt to authenticate the given user for the given service. If
|
|
13
12
|
# the password parameter is nil, this will ask for password
|
|
14
|
-
def authenticate(next_service, username, password=nil)
|
|
13
|
+
def authenticate(next_service, username, password = nil)
|
|
15
14
|
clear_prompter!
|
|
16
15
|
retries = 0
|
|
17
16
|
max_retries = get_max_retries
|
|
@@ -29,6 +28,7 @@ module Net
|
|
|
29
28
|
|
|
30
29
|
raise Net::SSH::Authentication::DisallowedMethod unless
|
|
31
30
|
message[:authentications].split(/,/).include? 'password'
|
|
31
|
+
|
|
32
32
|
password = nil
|
|
33
33
|
end
|
|
34
34
|
end until (message.type != USERAUTH_FAILURE || retries >= max_retries)
|
|
@@ -74,7 +74,6 @@ module Net
|
|
|
74
74
|
options[:non_interactive] ? 0 : result
|
|
75
75
|
end
|
|
76
76
|
end
|
|
77
|
-
|
|
78
77
|
end
|
|
79
78
|
end
|
|
80
79
|
end
|
|
@@ -6,14 +6,13 @@ module Net
|
|
|
6
6
|
module SSH
|
|
7
7
|
module Authentication
|
|
8
8
|
module Methods
|
|
9
|
-
|
|
10
9
|
# Implements the "publickey" SSH authentication method.
|
|
11
10
|
class Publickey < Abstract
|
|
12
11
|
# Attempts to perform public-key authentication for the given
|
|
13
12
|
# username, trying each identity known to the key manager. If any of
|
|
14
13
|
# them succeed, returns +true+, otherwise returns +false+. This
|
|
15
14
|
# requires the presence of a key manager.
|
|
16
|
-
def authenticate(next_service, username, password=nil)
|
|
15
|
+
def authenticate(next_service, username, password = nil)
|
|
17
16
|
return false unless key_manager
|
|
18
17
|
|
|
19
18
|
key_manager.each_identity do |identity|
|
|
@@ -27,41 +26,40 @@ module Net
|
|
|
27
26
|
|
|
28
27
|
# Builds a packet that contains the request formatted for sending
|
|
29
28
|
# a public-key request to the server.
|
|
30
|
-
def build_request(pub_key, username, next_service, has_sig)
|
|
29
|
+
def build_request(pub_key, username, next_service, alg, has_sig)
|
|
31
30
|
blob = Net::SSH::Buffer.new
|
|
32
31
|
blob.write_key pub_key
|
|
33
32
|
|
|
34
33
|
userauth_request(username, next_service, "publickey", has_sig,
|
|
35
|
-
|
|
34
|
+
alg, blob.to_s)
|
|
36
35
|
end
|
|
37
36
|
|
|
38
37
|
# Builds and sends a request formatted for a public-key
|
|
39
38
|
# authentication request.
|
|
40
|
-
def send_request(pub_key, username, next_service, signature=nil)
|
|
41
|
-
msg = build_request(pub_key, username, next_service,
|
|
39
|
+
def send_request(pub_key, username, next_service, alg, signature = nil)
|
|
40
|
+
msg = build_request(pub_key, username, next_service, alg,
|
|
41
|
+
!signature.nil?)
|
|
42
42
|
msg.write_string(signature) if signature
|
|
43
43
|
send_message(msg)
|
|
44
44
|
end
|
|
45
45
|
|
|
46
|
-
|
|
47
|
-
# username, with the given identity (public key). Returns +true+ if
|
|
48
|
-
# successful, or +false+ otherwise.
|
|
49
|
-
def authenticate_with(identity, next_service, username)
|
|
46
|
+
def authenticate_with_alg(identity, next_service, username, alg, sig_alg = nil)
|
|
50
47
|
debug { "trying publickey (#{identity.fingerprint})" }
|
|
51
|
-
send_request(identity, username, next_service)
|
|
48
|
+
send_request(identity, username, next_service, alg)
|
|
52
49
|
|
|
53
50
|
message = session.next_message
|
|
54
51
|
|
|
55
52
|
case message.type
|
|
56
53
|
when USERAUTH_PK_OK
|
|
57
|
-
buffer = build_request(identity, username, next_service,
|
|
54
|
+
buffer = build_request(identity, username, next_service, alg,
|
|
55
|
+
true)
|
|
58
56
|
sig_data = Net::SSH::Buffer.new
|
|
59
57
|
sig_data.write_string(session_id)
|
|
60
58
|
sig_data.append(buffer.to_s)
|
|
61
59
|
|
|
62
|
-
sig_blob = key_manager.sign(identity, sig_data)
|
|
60
|
+
sig_blob = key_manager.sign(identity, sig_data, sig_alg)
|
|
63
61
|
|
|
64
|
-
send_request(identity, username, next_service, sig_blob.to_s)
|
|
62
|
+
send_request(identity, username, next_service, alg, sig_blob.to_s)
|
|
65
63
|
message = session.next_message
|
|
66
64
|
|
|
67
65
|
case message.type
|
|
@@ -77,7 +75,7 @@ module Net
|
|
|
77
75
|
return false
|
|
78
76
|
else
|
|
79
77
|
raise Net::SSH::Exception,
|
|
80
|
-
|
|
78
|
+
"unexpected server response to USERAUTH_REQUEST: #{message.type} (#{message.inspect})"
|
|
81
79
|
end
|
|
82
80
|
|
|
83
81
|
when USERAUTH_FAILURE
|
|
@@ -89,8 +87,50 @@ module Net
|
|
|
89
87
|
raise Net::SSH::Exception, "unexpected reply to USERAUTH_REQUEST: #{message.type} (#{message.inspect})"
|
|
90
88
|
end
|
|
91
89
|
end
|
|
92
|
-
end
|
|
93
90
|
|
|
91
|
+
# Attempts to perform public-key authentication for the given
|
|
92
|
+
# username, with the given identity (public key). Returns +true+ if
|
|
93
|
+
# successful, or +false+ otherwise.
|
|
94
|
+
def authenticate_with(identity, next_service, username)
|
|
95
|
+
type = identity.ssh_type
|
|
96
|
+
if type == "ssh-rsa"
|
|
97
|
+
pubkey_algorithms.each do |pk_alg|
|
|
98
|
+
case pk_alg
|
|
99
|
+
when "rsa-sha2-512", "rsa-sha2-256", "ssh-rsa"
|
|
100
|
+
if authenticate_with_alg(identity, next_service, username, pk_alg, pk_alg)
|
|
101
|
+
# success
|
|
102
|
+
return true
|
|
103
|
+
end
|
|
104
|
+
end
|
|
105
|
+
end
|
|
106
|
+
elsif type == "ssh-rsa-cert-v01@openssh.com"
|
|
107
|
+
pubkey_algorithms.each do |pk_alg|
|
|
108
|
+
case pk_alg
|
|
109
|
+
when "rsa-sha2-512-cert-v01@openssh.com"
|
|
110
|
+
if authenticate_with_alg(identity, next_service, username, pk_alg, "rsa-sha2-512")
|
|
111
|
+
# success
|
|
112
|
+
return true
|
|
113
|
+
end
|
|
114
|
+
when "rsa-sha2-256-cert-v01@openssh.com"
|
|
115
|
+
if authenticate_with_alg(identity, next_service, username, pk_alg, "rsa-sha2-256")
|
|
116
|
+
# success
|
|
117
|
+
return true
|
|
118
|
+
end
|
|
119
|
+
when "ssh-rsa-cert-v01@openssh.com"
|
|
120
|
+
if authenticate_with_alg(identity, next_service, username, pk_alg)
|
|
121
|
+
# success
|
|
122
|
+
return true
|
|
123
|
+
end
|
|
124
|
+
end
|
|
125
|
+
end
|
|
126
|
+
elsif authenticate_with_alg(identity, next_service, username, type)
|
|
127
|
+
# success
|
|
128
|
+
return true
|
|
129
|
+
end
|
|
130
|
+
# failure
|
|
131
|
+
return false
|
|
132
|
+
end
|
|
133
|
+
end
|
|
94
134
|
end
|
|
95
135
|
end
|
|
96
136
|
end
|