net-ssh 5.0.2 → 6.1.0
Sign up to get free protection for your applications and to get access to all the features.
- 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
|