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
data/lib/net/ssh.rb
CHANGED
@@ -4,6 +4,7 @@ ENV['HOME'] ||= ENV['HOMEPATH'] ? "#{ENV['HOMEDRIVE']}#{ENV['HOMEPATH']}" : Dir.
|
|
4
4
|
|
5
5
|
require 'logger'
|
6
6
|
require 'etc'
|
7
|
+
require 'shellwords'
|
7
8
|
|
8
9
|
require 'net/ssh/config'
|
9
10
|
require 'net/ssh/errors'
|
@@ -66,14 +67,14 @@ module Net
|
|
66
67
|
auth_methods bind_address compression compression_level config
|
67
68
|
encryption forward_agent hmac host_key remote_user
|
68
69
|
keepalive keepalive_interval keepalive_maxcount kex keys key_data
|
69
|
-
languages logger paranoid password port proxy
|
70
|
+
keycerts languages logger paranoid password port proxy
|
70
71
|
rekey_blocks_limit rekey_limit rekey_packet_limit timeout verbose
|
71
72
|
known_hosts global_known_hosts_file user_known_hosts_file host_key_alias
|
72
73
|
host_name user properties passphrase keys_only max_pkt_size
|
73
|
-
max_win_size send_env use_agent number_of_password_prompts
|
74
|
+
max_win_size send_env set_env use_agent number_of_password_prompts
|
74
75
|
append_all_supported_algorithms non_interactive password_prompt
|
75
76
|
agent_socket_factory minimum_dh_bits verify_host_key
|
76
|
-
fingerprint_hash
|
77
|
+
fingerprint_hash check_host_ip
|
77
78
|
]
|
78
79
|
|
79
80
|
# The standard means of starting a new SSH connection. When used with a
|
@@ -108,6 +109,8 @@ module Net
|
|
108
109
|
# * :bind_address => the IP address on the connecting machine to use in
|
109
110
|
# establishing connection. (:bind_address is discarded if :proxy
|
110
111
|
# is set.)
|
112
|
+
# * :check_host_ip => Also ckeck IP address when connecting to remote host.
|
113
|
+
# Defaults to +true+.
|
111
114
|
# * :compression => the compression algorithm to use, or +true+ to use
|
112
115
|
# whatever is supported.
|
113
116
|
# * :compression_level => the compression level to use when sending data
|
@@ -142,6 +145,8 @@ module Net
|
|
142
145
|
# * :kex => the key exchange algorithm (or algorithms) to use
|
143
146
|
# * :keys => an array of file names of private keys to use for publickey
|
144
147
|
# and hostbased authentication
|
148
|
+
# * :keycerts => an array of file names of key certificates to use
|
149
|
+
# with publickey authentication
|
145
150
|
# * :key_data => an array of strings, with each element of the array being
|
146
151
|
# a raw private key in PEM format.
|
147
152
|
# * :keys_only => set to +true+ to use only private keys from +keys+ and
|
@@ -171,6 +176,8 @@ module Net
|
|
171
176
|
# * :rekey_packet_limit => the max number of packets to process before rekeying
|
172
177
|
# * :send_env => an array of local environment variable names to export to the
|
173
178
|
# remote environment. Names may be given as String or Regexp.
|
179
|
+
# * :set_env => a hash of environment variable names and values to set to the
|
180
|
+
# remote environment. Override the ones if specified in +send_env+.
|
174
181
|
# * :timeout => how long to wait for the initial connection to be made
|
175
182
|
# * :user => the user name to log in as; this overrides the +user+
|
176
183
|
# parameter, and is primarily only useful when provided via an SSH
|
@@ -221,6 +228,8 @@ module Net
|
|
221
228
|
options = configuration_for(host, options.fetch(:config, true)).merge(options)
|
222
229
|
host = options.fetch(:host_name, host)
|
223
230
|
|
231
|
+
options[:check_host_ip] = true unless options.key?(:check_host_ip)
|
232
|
+
|
224
233
|
if options[:non_interactive]
|
225
234
|
options[:number_of_password_prompts] = 0
|
226
235
|
end
|
@@ -242,7 +251,7 @@ module Net
|
|
242
251
|
transport = Transport::Session.new(host, options)
|
243
252
|
auth = Authentication::Session.new(transport, options)
|
244
253
|
|
245
|
-
user = options.fetch(:user, user) || Etc.
|
254
|
+
user = options.fetch(:user, user) || Etc.getpwuid.name
|
246
255
|
if auth.authenticate("ssh-connection", user, options[:password])
|
247
256
|
connection = Connection::Session.new(transport, options)
|
248
257
|
if block_given?
|
@@ -62,9 +62,9 @@ module Net
|
|
62
62
|
|
63
63
|
# Instantiates a new agent object, connects to a running SSH agent,
|
64
64
|
# negotiates the agent protocol version, and returns the agent object.
|
65
|
-
def self.connect(logger=nil, agent_socket_factory = nil)
|
65
|
+
def self.connect(logger=nil, agent_socket_factory = nil, identity_agent = nil)
|
66
66
|
agent = new(logger)
|
67
|
-
agent.connect!(agent_socket_factory)
|
67
|
+
agent.connect!(agent_socket_factory, identity_agent)
|
68
68
|
agent.negotiate!
|
69
69
|
agent
|
70
70
|
end
|
@@ -79,11 +79,13 @@ module Net
|
|
79
79
|
# given by the attribute writers. If the agent on the other end of the
|
80
80
|
# socket reports that it is an SSH2-compatible agent, this will fail
|
81
81
|
# (it only supports the ssh-agent distributed by OpenSSH).
|
82
|
-
def connect!(agent_socket_factory = nil)
|
82
|
+
def connect!(agent_socket_factory = nil, identity_agent = nil)
|
83
83
|
debug { "connecting to ssh-agent" }
|
84
84
|
@socket =
|
85
85
|
if agent_socket_factory
|
86
86
|
agent_socket_factory.call
|
87
|
+
elsif identity_agent
|
88
|
+
unix_socket_class.open(identity_agent)
|
87
89
|
elsif ENV['SSH_AUTH_SOCK'] && unix_socket_class
|
88
90
|
unix_socket_class.open(ENV['SSH_AUTH_SOCK'])
|
89
91
|
elsif Gem.win_platform? && RUBY_ENGINE != "jruby"
|
@@ -124,6 +126,10 @@ module Net
|
|
124
126
|
comment_str = body.read_string
|
125
127
|
begin
|
126
128
|
key = Buffer.new(key_str).read_key
|
129
|
+
if key.nil?
|
130
|
+
error { "ignoring invalid key: #{comment_str}" }
|
131
|
+
next
|
132
|
+
end
|
127
133
|
key.extend(Comment)
|
128
134
|
key.comment = comment_str
|
129
135
|
identities.push key
|
@@ -31,7 +31,16 @@ module Net
|
|
31
31
|
cert.key_id = buffer.read_string
|
32
32
|
cert.valid_principals = buffer.read_buffer.read_all(&:read_string)
|
33
33
|
cert.valid_after = Time.at(buffer.read_int64)
|
34
|
-
|
34
|
+
|
35
|
+
cert.valid_before = if RUBY_PLATFORM == "java"
|
36
|
+
# 0x20c49ba5e353f7 = 0x7fffffffffffffff/1000, the largest value possible for JRuby
|
37
|
+
# JRuby Time.at multiplies the arg by 1000, and then stores it in a signed long.
|
38
|
+
# 0x20c49ba5e353f7 = 292278994-08-17 01:12:55 -0600
|
39
|
+
Time.at([0x20c49ba5e353f7, buffer.read_int64].min)
|
40
|
+
else
|
41
|
+
Time.at(buffer.read_int64)
|
42
|
+
end
|
43
|
+
|
35
44
|
cert.critical_options = read_options(buffer)
|
36
45
|
cert.extensions = read_options(buffer)
|
37
46
|
cert.reserved = buffer.read_string
|
@@ -22,51 +22,26 @@ module Net
|
|
22
22
|
end
|
23
23
|
end
|
24
24
|
|
25
|
-
class
|
26
|
-
include Net::SSH::Authentication::PubKeyFingerprint
|
27
|
-
|
28
|
-
attr_reader :verify_key
|
29
|
-
|
30
|
-
def initialize(data)
|
31
|
-
@verify_key = ::Ed25519::VerifyKey.new(data)
|
32
|
-
end
|
33
|
-
|
34
|
-
def self.read_keyblob(buffer)
|
35
|
-
PubKey.new(buffer.read_string)
|
36
|
-
end
|
37
|
-
|
38
|
-
def to_blob
|
39
|
-
Net::SSH::Buffer.from(:mstring,"ssh-ed25519",:string,@verify_key.to_bytes).to_s
|
40
|
-
end
|
41
|
-
|
42
|
-
def ssh_type
|
43
|
-
"ssh-ed25519"
|
44
|
-
end
|
45
|
-
|
46
|
-
def ssh_signature_type
|
47
|
-
ssh_type
|
48
|
-
end
|
49
|
-
|
50
|
-
def ssh_do_verify(sig,data)
|
51
|
-
@verify_key.verify(sig,data)
|
52
|
-
end
|
53
|
-
|
54
|
-
def to_pem
|
55
|
-
# TODO this is not pem
|
56
|
-
ssh_type + Base64.encode64(@verify_key.to_bytes)
|
57
|
-
end
|
58
|
-
end
|
59
|
-
|
60
|
-
class PrivKey
|
25
|
+
class OpenSSHPrivateKeyLoader
|
61
26
|
CipherFactory = Net::SSH::Transport::CipherFactory
|
62
27
|
|
63
28
|
MBEGIN = "-----BEGIN OPENSSH PRIVATE KEY-----\n"
|
64
|
-
MEND = "-----END OPENSSH PRIVATE KEY
|
29
|
+
MEND = "-----END OPENSSH PRIVATE KEY-----"
|
65
30
|
MAGIC = "openssh-key-v1"
|
66
31
|
|
67
|
-
|
32
|
+
class DecryptError < ArgumentError
|
33
|
+
def initialize(message, encrypted_key: false)
|
34
|
+
super(message)
|
35
|
+
@encrypted_key = encrypted_key
|
36
|
+
end
|
68
37
|
|
69
|
-
|
38
|
+
def encrypted_key?
|
39
|
+
return @encrypted_key
|
40
|
+
end
|
41
|
+
end
|
42
|
+
|
43
|
+
def self.read(datafull, password)
|
44
|
+
datafull = datafull.strip
|
70
45
|
raise ArgumentError.new("Expected #{MBEGIN} at start of private key") unless datafull.start_with?(MBEGIN)
|
71
46
|
raise ArgumentError.new("Expected #{MEND} at end of private key") unless datafull.end_with?(MEND)
|
72
47
|
datab64 = datafull[MBEGIN.size...-MEND.size]
|
@@ -111,12 +86,66 @@ module Net
|
|
111
86
|
check1 = decoded.read_long
|
112
87
|
check2 = decoded.read_long
|
113
88
|
|
114
|
-
raise
|
89
|
+
raise DecryptError.new("Decrypt failed on private key", encrypted_key: kdfname == 'bcrypt') if (check1 != check2)
|
90
|
+
|
91
|
+
type_name = decoded.read_string
|
92
|
+
case type_name
|
93
|
+
when "ssh-ed25519"
|
94
|
+
PrivKey.new(decoded)
|
95
|
+
else
|
96
|
+
decoded.read_private_keyblob(type_name)
|
97
|
+
end
|
98
|
+
end
|
99
|
+
end
|
100
|
+
|
101
|
+
class PubKey
|
102
|
+
include Net::SSH::Authentication::PubKeyFingerprint
|
103
|
+
|
104
|
+
attr_reader :verify_key
|
105
|
+
|
106
|
+
def initialize(data)
|
107
|
+
@verify_key = ::Ed25519::VerifyKey.new(data)
|
108
|
+
end
|
109
|
+
|
110
|
+
def self.read_keyblob(buffer)
|
111
|
+
PubKey.new(buffer.read_string)
|
112
|
+
end
|
113
|
+
|
114
|
+
def to_blob
|
115
|
+
Net::SSH::Buffer.from(:mstring,"ssh-ed25519",:string,@verify_key.to_bytes).to_s
|
116
|
+
end
|
117
|
+
|
118
|
+
def ssh_type
|
119
|
+
"ssh-ed25519"
|
120
|
+
end
|
121
|
+
|
122
|
+
def ssh_signature_type
|
123
|
+
ssh_type
|
124
|
+
end
|
125
|
+
|
126
|
+
def ssh_do_verify(sig,data)
|
127
|
+
@verify_key.verify(sig,data)
|
128
|
+
end
|
129
|
+
|
130
|
+
def to_pem
|
131
|
+
# TODO this is not pem
|
132
|
+
ssh_type + Base64.encode64(@verify_key.to_bytes)
|
133
|
+
end
|
134
|
+
end
|
135
|
+
|
136
|
+
class PrivKey
|
137
|
+
CipherFactory = Net::SSH::Transport::CipherFactory
|
138
|
+
|
139
|
+
MBEGIN = "-----BEGIN OPENSSH PRIVATE KEY-----\n"
|
140
|
+
MEND = "-----END OPENSSH PRIVATE KEY-----\n"
|
141
|
+
MAGIC = "openssh-key-v1"
|
142
|
+
|
143
|
+
attr_reader :sign_key
|
115
144
|
|
116
|
-
|
117
|
-
pk =
|
118
|
-
sk =
|
119
|
-
_comment =
|
145
|
+
def initialize(buffer)
|
146
|
+
pk = buffer.read_string
|
147
|
+
sk = buffer.read_string
|
148
|
+
_comment = buffer.read_string
|
120
149
|
|
121
150
|
@pk = pk
|
122
151
|
@sign_key = SigningKeyFromFile.new(pk,sk)
|
@@ -142,8 +171,8 @@ module Net
|
|
142
171
|
@sign_key.sign(data)
|
143
172
|
end
|
144
173
|
|
145
|
-
def self.read(data,password)
|
146
|
-
|
174
|
+
def self.read(data, password)
|
175
|
+
OpenSSHPrivateKeyLoader.read(data, password)
|
147
176
|
end
|
148
177
|
end
|
149
178
|
end
|
@@ -30,6 +30,9 @@ module Net
|
|
30
30
|
# The list of user key data that will be examined
|
31
31
|
attr_reader :key_data
|
32
32
|
|
33
|
+
# The list of user key certificate files that will be examined
|
34
|
+
attr_reader :keycert_files
|
35
|
+
|
33
36
|
# The map of loaded identities
|
34
37
|
attr_reader :known_identities
|
35
38
|
|
@@ -43,6 +46,7 @@ module Net
|
|
43
46
|
self.logger = logger
|
44
47
|
@key_files = []
|
45
48
|
@key_data = []
|
49
|
+
@keycert_files = []
|
46
50
|
@use_agent = options[:use_agent] != false
|
47
51
|
@known_identities = {}
|
48
52
|
@agent = nil
|
@@ -66,6 +70,12 @@ module Net
|
|
66
70
|
self
|
67
71
|
end
|
68
72
|
|
73
|
+
# Add the given keycert_file to the list of keycert files that will be used.
|
74
|
+
def add_keycert(keycert_file)
|
75
|
+
keycert_files.push(File.expand_path(keycert_file)).uniq!
|
76
|
+
self
|
77
|
+
end
|
78
|
+
|
69
79
|
# Add the given key_file to the list of keys that will be used.
|
70
80
|
def add_key_data(key_data_)
|
71
81
|
key_data.push(key_data_).uniq!
|
@@ -108,7 +118,7 @@ module Net
|
|
108
118
|
user_identities.delete(corresponding_user_identity) if corresponding_user_identity
|
109
119
|
|
110
120
|
if !options[:keys_only] || corresponding_user_identity
|
111
|
-
known_identities[key] = { from: :agent }
|
121
|
+
known_identities[key] = { from: :agent, identity: key }
|
112
122
|
yield key
|
113
123
|
end
|
114
124
|
end
|
@@ -122,6 +132,21 @@ module Net
|
|
122
132
|
yield key
|
123
133
|
end
|
124
134
|
|
135
|
+
known_identity_blobs = known_identities.keys.map(&:to_blob)
|
136
|
+
keycert_files.each do |keycert_file|
|
137
|
+
keycert = KeyFactory.load_public_key(keycert_file)
|
138
|
+
next if known_identity_blobs.include?(keycert.to_blob)
|
139
|
+
|
140
|
+
(_, corresponding_identity) = known_identities.detect { |public_key, _|
|
141
|
+
public_key.to_pem == keycert.to_pem
|
142
|
+
}
|
143
|
+
|
144
|
+
if corresponding_identity
|
145
|
+
known_identities[keycert] = corresponding_identity
|
146
|
+
yield keycert
|
147
|
+
end
|
148
|
+
end
|
149
|
+
|
125
150
|
self
|
126
151
|
end
|
127
152
|
|
@@ -139,7 +164,7 @@ module Net
|
|
139
164
|
|
140
165
|
if info[:key].nil? && info[:from] == :file
|
141
166
|
begin
|
142
|
-
info[:key] = KeyFactory.load_private_key(info[:file], options[:passphrase], !options[:non_interactive])
|
167
|
+
info[:key] = KeyFactory.load_private_key(info[:file], options[:passphrase], !options[:non_interactive], options[:password_prompt])
|
143
168
|
rescue OpenSSL::OpenSSLError, Exception => e
|
144
169
|
raise KeyManagerError, "the given identity is known, but the private key could not be loaded: #{e.class} (#{e.message})"
|
145
170
|
end
|
@@ -152,7 +177,7 @@ module Net
|
|
152
177
|
|
153
178
|
if info[:from] == :agent
|
154
179
|
raise KeyManagerError, "the agent is no longer available" unless agent
|
155
|
-
return agent.sign(identity, data.to_s)
|
180
|
+
return agent.sign(info[:identity], data.to_s)
|
156
181
|
end
|
157
182
|
|
158
183
|
raise KeyManagerError, "[BUG] can't determine identity origin (#{info.inspect})"
|
@@ -176,7 +201,7 @@ module Net
|
|
176
201
|
# or if the agent is otherwise not available.
|
177
202
|
def agent
|
178
203
|
return unless use_agent?
|
179
|
-
@agent ||= Agent.connect(logger, options[:agent_socket_factory])
|
204
|
+
@agent ||= Agent.connect(logger, options[:agent_socket_factory], options[:identity_agent])
|
180
205
|
rescue AgentNotAvailable
|
181
206
|
@use_agent = false
|
182
207
|
nil
|
@@ -229,11 +254,15 @@ module Net
|
|
229
254
|
key = KeyFactory.load_public_key(identity[:pubkey_file])
|
230
255
|
{ public_key: key, from: :file, file: identity[:privkey_file] }
|
231
256
|
when :privkey_file
|
232
|
-
private_key = KeyFactory.load_private_key(
|
257
|
+
private_key = KeyFactory.load_private_key(
|
258
|
+
identity[:privkey_file], options[:passphrase], ask_passphrase, options[:password_prompt]
|
259
|
+
)
|
233
260
|
key = private_key.send(:public_key)
|
234
261
|
{ public_key: key, from: :file, file: identity[:privkey_file], key: private_key }
|
235
262
|
when :data
|
236
|
-
private_key = KeyFactory.load_data_private_key(
|
263
|
+
private_key = KeyFactory.load_data_private_key(
|
264
|
+
identity[:data], options[:passphrase], ask_passphrase, "<key in memory>", options[:password_prompt]
|
265
|
+
)
|
237
266
|
key = private_key.send(:public_key)
|
238
267
|
{ public_key: key, from: :key_data, data: identity[:data], key: private_key }
|
239
268
|
else
|
@@ -40,7 +40,9 @@ module Net
|
|
40
40
|
instruction = message.read_string
|
41
41
|
debug { "keyboard-interactive info request" }
|
42
42
|
|
43
|
-
|
43
|
+
if password.nil? && interactive? && prompter.nil?
|
44
|
+
prompter = prompt.start(type: 'keyboard-interactive', name: name, instruction: instruction)
|
45
|
+
end
|
44
46
|
|
45
47
|
_ = message.read_string # lang_tag
|
46
48
|
responses = []
|
@@ -63,6 +63,7 @@ module Net
|
|
63
63
|
|
64
64
|
key_manager = KeyManager.new(logger, options)
|
65
65
|
keys.each { |key| key_manager.add(key) } unless keys.empty?
|
66
|
+
keycerts.each { |keycert| key_manager.add_keycert(keycert) } unless keycerts.empty?
|
66
67
|
key_data.each { |key2| key_manager.add_key_data(key2) } unless key_data.empty?
|
67
68
|
default_keys.each { |key| key_manager.add(key) } unless options.key?(:keys) || options.key?(:key_data)
|
68
69
|
|
@@ -136,12 +137,8 @@ module Net
|
|
136
137
|
# Returns an array of paths to the key files usually defined
|
137
138
|
# by system default.
|
138
139
|
def default_keys
|
139
|
-
|
140
|
-
|
141
|
-
~/.ssh2/id_ed25519 ~/.ssh2/id_rsa ~/.ssh2/id_dsa ~/.ssh2/id_ecdsa]
|
142
|
-
else
|
143
|
-
%w[~/.ssh/id_dsa ~/.ssh/id_rsa ~/.ssh2/id_dsa ~/.ssh2/id_rsa]
|
144
|
-
end
|
140
|
+
%w[~/.ssh/id_ed25519 ~/.ssh/id_rsa ~/.ssh/id_dsa ~/.ssh/id_ecdsa
|
141
|
+
~/.ssh2/id_ed25519 ~/.ssh2/id_rsa ~/.ssh2/id_dsa ~/.ssh2/id_ecdsa]
|
145
142
|
end
|
146
143
|
|
147
144
|
# Returns an array of paths to the key files that should be used when
|
@@ -150,6 +147,12 @@ module Net
|
|
150
147
|
Array(options[:keys])
|
151
148
|
end
|
152
149
|
|
150
|
+
# Returns an array of paths to the keycert files that should be used when
|
151
|
+
# attempting any key-based authentication mechanism.
|
152
|
+
def keycerts
|
153
|
+
Array(options[:keycerts])
|
154
|
+
end
|
155
|
+
|
153
156
|
# Returns an array of the key data that should be used when
|
154
157
|
# attempting any key-based authentication mechanism.
|
155
158
|
def key_data
|