net-ssh 4.1.0 → 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 +5 -5
- checksums.yaml.gz.sig +0 -0
- data.tar.gz.sig +0 -0
- data/.gitignore +5 -0
- data/.rubocop.yml +8 -2
- data/.rubocop_todo.yml +405 -552
- data/.travis.yml +23 -22
- data/CHANGES.txt +112 -1
- data/Gemfile +1 -7
- data/{Gemfile.norbnacl → Gemfile.noed25519} +1 -1
- data/Manifest +4 -5
- data/README.md +287 -0
- data/Rakefile +40 -29
- data/appveyor.yml +12 -6
- data/lib/net/ssh.rb +68 -32
- data/lib/net/ssh/authentication/agent.rb +234 -222
- data/lib/net/ssh/authentication/certificate.rb +175 -164
- data/lib/net/ssh/authentication/constants.rb +17 -14
- data/lib/net/ssh/authentication/ed25519.rb +162 -141
- data/lib/net/ssh/authentication/ed25519_loader.rb +32 -29
- data/lib/net/ssh/authentication/key_manager.rb +40 -9
- data/lib/net/ssh/authentication/methods/abstract.rb +53 -47
- data/lib/net/ssh/authentication/methods/hostbased.rb +32 -33
- data/lib/net/ssh/authentication/methods/keyboard_interactive.rb +1 -1
- data/lib/net/ssh/authentication/methods/none.rb +10 -10
- data/lib/net/ssh/authentication/methods/password.rb +13 -13
- data/lib/net/ssh/authentication/methods/publickey.rb +56 -55
- data/lib/net/ssh/authentication/pageant.rb +468 -465
- data/lib/net/ssh/authentication/pub_key_fingerprint.rb +43 -0
- data/lib/net/ssh/authentication/session.rb +130 -122
- data/lib/net/ssh/buffer.rb +345 -312
- data/lib/net/ssh/buffered_io.rb +163 -163
- data/lib/net/ssh/config.rb +316 -238
- data/lib/net/ssh/connection/channel.rb +670 -650
- data/lib/net/ssh/connection/constants.rb +30 -26
- data/lib/net/ssh/connection/event_loop.rb +108 -105
- data/lib/net/ssh/connection/keepalive.rb +54 -50
- data/lib/net/ssh/connection/session.rb +682 -671
- data/lib/net/ssh/connection/term.rb +180 -176
- data/lib/net/ssh/errors.rb +101 -99
- data/lib/net/ssh/key_factory.rb +195 -108
- data/lib/net/ssh/known_hosts.rb +161 -152
- data/lib/net/ssh/loggable.rb +57 -55
- data/lib/net/ssh/packet.rb +82 -78
- data/lib/net/ssh/prompt.rb +55 -53
- data/lib/net/ssh/proxy/command.rb +104 -89
- data/lib/net/ssh/proxy/errors.rb +12 -8
- data/lib/net/ssh/proxy/http.rb +93 -91
- data/lib/net/ssh/proxy/https.rb +42 -39
- data/lib/net/ssh/proxy/jump.rb +50 -47
- data/lib/net/ssh/proxy/socks4.rb +0 -2
- data/lib/net/ssh/proxy/socks5.rb +11 -12
- data/lib/net/ssh/service/forward.rb +370 -317
- data/lib/net/ssh/test.rb +83 -77
- data/lib/net/ssh/test/channel.rb +146 -142
- data/lib/net/ssh/test/extensions.rb +150 -146
- data/lib/net/ssh/test/kex.rb +35 -31
- data/lib/net/ssh/test/local_packet.rb +48 -44
- data/lib/net/ssh/test/packet.rb +87 -84
- data/lib/net/ssh/test/remote_packet.rb +35 -31
- data/lib/net/ssh/test/script.rb +173 -171
- data/lib/net/ssh/test/socket.rb +59 -55
- data/lib/net/ssh/transport/algorithms.rb +430 -364
- data/lib/net/ssh/transport/cipher_factory.rb +95 -91
- data/lib/net/ssh/transport/constants.rb +33 -25
- data/lib/net/ssh/transport/ctr.rb +33 -11
- data/lib/net/ssh/transport/hmac.rb +15 -13
- data/lib/net/ssh/transport/hmac/abstract.rb +82 -63
- 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/identity_cipher.rb +55 -51
- data/lib/net/ssh/transport/kex.rb +14 -13
- 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 +33 -40
- data/lib/net/ssh/transport/kex/diffie_hellman_group1_sha1.rb +112 -217
- data/lib/net/ssh/transport/kex/diffie_hellman_group_exchange_sha1.rb +53 -62
- data/lib/net/ssh/transport/kex/diffie_hellman_group_exchange_sha256.rb +5 -9
- data/lib/net/ssh/transport/kex/ecdh_sha2_nistp256.rb +36 -90
- data/lib/net/ssh/transport/kex/ecdh_sha2_nistp384.rb +18 -10
- data/lib/net/ssh/transport/kex/ecdh_sha2_nistp521.rb +18 -10
- data/lib/net/ssh/transport/key_expander.rb +29 -25
- data/lib/net/ssh/transport/openssl.rb +116 -116
- data/lib/net/ssh/transport/packet_stream.rb +223 -190
- data/lib/net/ssh/transport/server_version.rb +64 -66
- data/lib/net/ssh/transport/session.rb +306 -257
- data/lib/net/ssh/transport/state.rb +198 -196
- data/lib/net/ssh/verifiers/accept_new.rb +35 -0
- data/lib/net/ssh/verifiers/accept_new_or_local_tunnel.rb +34 -0
- data/lib/net/ssh/verifiers/always.rb +56 -0
- data/lib/net/ssh/verifiers/never.rb +21 -0
- data/lib/net/ssh/version.rb +55 -53
- data/net-ssh-public_cert.pem +18 -19
- data/net-ssh.gemspec +12 -11
- data/support/ssh_tunnel_bug.rb +2 -2
- metadata +86 -75
- metadata.gz.sig +0 -0
- data/Gemfile.norbnacl.lock +0 -41
- data/README.rdoc +0 -169
- data/lib/net/ssh/ruby_compat.rb +0 -24
- data/lib/net/ssh/verifiers/lenient.rb +0 -30
- data/lib/net/ssh/verifiers/null.rb +0 -12
- data/lib/net/ssh/verifiers/secure.rb +0 -52
- data/lib/net/ssh/verifiers/strict.rb +0 -24
- data/support/arcfour_check.rb +0 -20
@@ -1,31 +1,34 @@
|
|
1
|
-
module Net
|
2
|
-
|
3
|
-
|
4
|
-
# rbnacl, bcrypt_pbkdf
|
5
|
-
module ED25519Loader
|
6
|
-
|
7
|
-
begin
|
8
|
-
require 'net/ssh/authentication/ed25519'
|
9
|
-
LOADED = true
|
10
|
-
ERROR = nil
|
11
|
-
rescue LoadError => e
|
12
|
-
ERROR = e
|
13
|
-
LOADED = false
|
14
|
-
end
|
15
|
-
|
16
|
-
def self.raiseUnlessLoaded(message)
|
17
|
-
description = ERROR.is_a?(LoadError) ? dependenciesRequiredForED25519 : ''
|
18
|
-
description << "#{ERROR.class} : \"#{ERROR.message}\"\n" if ERROR
|
19
|
-
raise NotImplementedError, "#{message}\n#{description}" unless LOADED
|
20
|
-
end
|
21
|
-
|
22
|
-
def self.dependenciesRequiredForED25519
|
23
|
-
result = "net-ssh requires the following gems for ed25519 support:\n"
|
24
|
-
result << " * rbnacl (>= 3.2, < 5.0)\n"
|
25
|
-
result << " * rbnacl-libsodium, if your system doesn't have libsodium installed.\n"
|
26
|
-
result << " * bcrypt_pbkdf (>= 1.0, < 2.0)\n" unless RUBY_PLATFORM == "java"
|
27
|
-
result << "See https://github.com/net-ssh/net-ssh/issues/478 for more information\n"
|
28
|
-
end
|
1
|
+
module Net
|
2
|
+
module SSH
|
3
|
+
module Authentication
|
29
4
|
|
5
|
+
# Loads ED25519 support which requires optinal dependecies like
|
6
|
+
# ed25519, bcrypt_pbkdf
|
7
|
+
module ED25519Loader
|
8
|
+
|
9
|
+
begin
|
10
|
+
require 'net/ssh/authentication/ed25519'
|
11
|
+
LOADED = true
|
12
|
+
ERROR = nil
|
13
|
+
rescue LoadError => e
|
14
|
+
ERROR = e
|
15
|
+
LOADED = false
|
16
|
+
end
|
17
|
+
|
18
|
+
def self.raiseUnlessLoaded(message)
|
19
|
+
description = ERROR.is_a?(LoadError) ? dependenciesRequiredForED25519 : ''
|
20
|
+
description << "#{ERROR.class} : \"#{ERROR.message}\"\n" if ERROR
|
21
|
+
raise NotImplementedError, "#{message}\n#{description}" unless LOADED
|
22
|
+
end
|
23
|
+
|
24
|
+
def self.dependenciesRequiredForED25519
|
25
|
+
result = "net-ssh requires the following gems for ed25519 support:\n"
|
26
|
+
result << " * ed25519 (>= 1.2, < 2.0)\n"
|
27
|
+
result << " * bcrypt_pbkdf (>= 1.0, < 2.0)\n" unless RUBY_PLATFORM == "java"
|
28
|
+
result << "See https://github.com/net-ssh/net-ssh/issues/565 for more information\n"
|
29
|
+
end
|
30
|
+
|
31
|
+
end
|
32
|
+
end
|
33
|
+
end
|
30
34
|
end
|
31
|
-
end; end; 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,7 +46,8 @@ module Net
|
|
43
46
|
self.logger = logger
|
44
47
|
@key_files = []
|
45
48
|
@key_data = []
|
46
|
-
@
|
49
|
+
@keycert_files = []
|
50
|
+
@use_agent = options[:use_agent] != false
|
47
51
|
@known_identities = {}
|
48
52
|
@agent = nil
|
49
53
|
@options = options
|
@@ -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,12 +201,16 @@ 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
|
183
208
|
end
|
184
209
|
|
210
|
+
def no_keys?
|
211
|
+
key_files.empty? && key_data.empty?
|
212
|
+
end
|
213
|
+
|
185
214
|
private
|
186
215
|
|
187
216
|
# Prepares identities from user key_files for loading, preserving their order and sources.
|
@@ -225,17 +254,20 @@ module Net
|
|
225
254
|
key = KeyFactory.load_public_key(identity[:pubkey_file])
|
226
255
|
{ public_key: key, from: :file, file: identity[:privkey_file] }
|
227
256
|
when :privkey_file
|
228
|
-
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
|
+
)
|
229
260
|
key = private_key.send(:public_key)
|
230
261
|
{ public_key: key, from: :file, file: identity[:privkey_file], key: private_key }
|
231
262
|
when :data
|
232
|
-
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
|
+
)
|
233
266
|
key = private_key.send(:public_key)
|
234
267
|
{ public_key: key, from: :key_data, data: identity[:data], key: private_key }
|
235
268
|
else
|
236
269
|
identity
|
237
270
|
end
|
238
|
-
|
239
271
|
rescue OpenSSL::PKey::RSAError, OpenSSL::PKey::DSAError, OpenSSL::PKey::ECError, OpenSSL::PKey::PKeyError, ArgumentError => e
|
240
272
|
if ignore_decryption_errors
|
241
273
|
identity
|
@@ -260,7 +292,6 @@ module Net
|
|
260
292
|
raise e
|
261
293
|
end
|
262
294
|
end
|
263
|
-
|
264
295
|
end
|
265
296
|
end
|
266
297
|
end
|
@@ -3,62 +3,68 @@ require 'net/ssh/errors'
|
|
3
3
|
require 'net/ssh/loggable'
|
4
4
|
require 'net/ssh/authentication/constants'
|
5
5
|
|
6
|
-
module Net
|
6
|
+
module Net
|
7
|
+
module SSH
|
8
|
+
module Authentication
|
9
|
+
module Methods
|
7
10
|
|
8
|
-
|
9
|
-
|
10
|
-
|
11
|
-
|
11
|
+
# The base class of all user authentication methods. It provides a few
|
12
|
+
# bits of common functionality.
|
13
|
+
class Abstract
|
14
|
+
include Loggable
|
15
|
+
include Constants
|
12
16
|
|
13
|
-
|
14
|
-
|
17
|
+
# The authentication session object
|
18
|
+
attr_reader :session
|
15
19
|
|
16
|
-
|
17
|
-
|
18
|
-
|
20
|
+
# The key manager object. Not all authentication methods will require
|
21
|
+
# this.
|
22
|
+
attr_reader :key_manager
|
19
23
|
|
20
|
-
|
21
|
-
|
22
|
-
|
23
|
-
|
24
|
-
|
25
|
-
|
26
|
-
|
27
|
-
|
24
|
+
# Instantiates a new authentication method.
|
25
|
+
def initialize(session, options={})
|
26
|
+
@session = session
|
27
|
+
@key_manager = options[:key_manager]
|
28
|
+
@options = options
|
29
|
+
@prompt = options[:password_prompt]
|
30
|
+
self.logger = session.logger
|
31
|
+
end
|
28
32
|
|
29
|
-
|
30
|
-
|
31
|
-
|
32
|
-
|
33
|
-
|
33
|
+
# Returns the session-id, as generated during the first key exchange of
|
34
|
+
# an SSH connection.
|
35
|
+
def session_id
|
36
|
+
session.transport.algorithms.session_id
|
37
|
+
end
|
34
38
|
|
35
|
-
|
36
|
-
|
37
|
-
|
38
|
-
|
39
|
-
|
39
|
+
# Sends a message via the underlying transport layer abstraction. This
|
40
|
+
# will block until the message is completely sent.
|
41
|
+
def send_message(msg)
|
42
|
+
session.transport.send_message(msg)
|
43
|
+
end
|
40
44
|
|
41
|
-
|
42
|
-
|
43
|
-
|
44
|
-
|
45
|
-
|
46
|
-
|
45
|
+
# Creates a new USERAUTH_REQUEST packet. The extra arguments on the end
|
46
|
+
# must be either boolean values or strings, and are tacked onto the end
|
47
|
+
# of the packet. The new packet is returned, ready for sending.
|
48
|
+
def userauth_request(username, next_service, auth_method, *others)
|
49
|
+
buffer = Net::SSH::Buffer.from(:byte, USERAUTH_REQUEST,
|
50
|
+
:string, username, :string, next_service, :string, auth_method)
|
47
51
|
|
48
|
-
|
49
|
-
|
50
|
-
|
51
|
-
|
52
|
-
|
53
|
-
|
54
|
-
|
52
|
+
others.each do |value|
|
53
|
+
case value
|
54
|
+
when true, false then buffer.write_bool(value)
|
55
|
+
when String then buffer.write_string(value)
|
56
|
+
else raise ArgumentError, "don't know how to write #{value.inspect}"
|
57
|
+
end
|
58
|
+
end
|
55
59
|
|
56
|
-
|
57
|
-
|
60
|
+
buffer
|
61
|
+
end
|
58
62
|
|
59
|
-
|
63
|
+
private
|
60
64
|
|
61
|
-
|
65
|
+
attr_reader :prompt
|
66
|
+
end
|
67
|
+
end
|
68
|
+
end
|
62
69
|
end
|
63
|
-
|
64
|
-
end; end; end; end
|
70
|
+
end
|
@@ -24,49 +24,48 @@ module Net
|
|
24
24
|
|
25
25
|
private
|
26
26
|
|
27
|
-
|
28
|
-
|
29
|
-
|
30
|
-
|
31
|
-
|
32
|
-
# Attempts to perform host-based authentication of the user, using
|
33
|
-
# the given host identity (key).
|
34
|
-
def authenticate_with(identity, next_service, username, key_manager)
|
35
|
-
debug { "trying hostbased (#{identity.fingerprint})" }
|
36
|
-
client_username = ENV['USER'] || username
|
27
|
+
# Returns the hostname as reported by the underlying socket.
|
28
|
+
def hostname
|
29
|
+
session.transport.socket.client_name
|
30
|
+
end
|
37
31
|
|
38
|
-
|
39
|
-
|
32
|
+
# Attempts to perform host-based authentication of the user, using
|
33
|
+
# the given host identity (key).
|
34
|
+
def authenticate_with(identity, next_service, username, key_manager)
|
35
|
+
debug { "trying hostbased (#{identity.fingerprint})" }
|
36
|
+
client_username = ENV['USER'] || username
|
40
37
|
|
41
|
-
|
38
|
+
req = build_request(identity, next_service, username, "#{hostname}.", client_username)
|
39
|
+
sig_data = Buffer.from(:string, session_id, :raw, req)
|
42
40
|
|
43
|
-
|
41
|
+
sig = key_manager.sign(identity, sig_data.to_s)
|
44
42
|
|
45
|
-
|
46
|
-
message = session.next_message
|
43
|
+
message = Buffer.from(:raw, req, :string, sig)
|
47
44
|
|
48
|
-
|
49
|
-
|
50
|
-
info { "hostbased succeeded (#{identity.fingerprint})" }
|
51
|
-
return true
|
52
|
-
when USERAUTH_FAILURE
|
53
|
-
info { "hostbased failed (#{identity.fingerprint})" }
|
45
|
+
send_message(message)
|
46
|
+
message = session.next_message
|
54
47
|
|
55
|
-
|
56
|
-
|
48
|
+
case message.type
|
49
|
+
when USERAUTH_SUCCESS
|
50
|
+
info { "hostbased succeeded (#{identity.fingerprint})" }
|
51
|
+
return true
|
52
|
+
when USERAUTH_FAILURE
|
53
|
+
info { "hostbased failed (#{identity.fingerprint})" }
|
57
54
|
|
58
|
-
|
59
|
-
|
60
|
-
raise Net::SSH::Exception, "unexpected server response to USERAUTH_REQUEST: #{message.type} (#{message.inspect})"
|
61
|
-
end
|
62
|
-
end
|
55
|
+
raise Net::SSH::Authentication::DisallowedMethod unless
|
56
|
+
message[:authentications].split(/,/).include? 'hostbased'
|
63
57
|
|
64
|
-
|
65
|
-
|
66
|
-
|
67
|
-
Buffer.from(:key, identity).to_s, hostname, client_username).to_s
|
58
|
+
return false
|
59
|
+
else
|
60
|
+
raise Net::SSH::Exception, "unexpected server response to USERAUTH_REQUEST: #{message.type} (#{message.inspect})"
|
68
61
|
end
|
62
|
+
end
|
69
63
|
|
64
|
+
# Build the "core" hostbased request string.
|
65
|
+
def build_request(identity, next_service, username, hostname, client_username)
|
66
|
+
userauth_request(username, next_service, "hostbased", identity.ssh_type,
|
67
|
+
Buffer.from(:key, identity).to_s, hostname, client_username).to_s
|
68
|
+
end
|
70
69
|
end
|
71
70
|
|
72
71
|
end
|
@@ -14,18 +14,18 @@ module Net
|
|
14
14
|
message = session.next_message
|
15
15
|
|
16
16
|
case message.type
|
17
|
-
|
18
|
-
|
19
|
-
|
20
|
-
|
21
|
-
|
17
|
+
when USERAUTH_SUCCESS
|
18
|
+
debug { "none succeeded" }
|
19
|
+
return true
|
20
|
+
when USERAUTH_FAILURE
|
21
|
+
debug { "none failed" }
|
22
22
|
|
23
|
-
|
24
|
-
|
23
|
+
raise Net::SSH::Authentication::DisallowedMethod unless
|
24
|
+
message[:authentications].split(/,/).include? 'none'
|
25
25
|
|
26
|
-
|
27
|
-
|
28
|
-
|
26
|
+
return false
|
27
|
+
else
|
28
|
+
raise Net::SSH::Exception, "unexpected reply to USERAUTH_REQUEST: #{message.type} (#{message.inspect})"
|
29
29
|
end
|
30
30
|
|
31
31
|
end
|
@@ -14,7 +14,7 @@ module Net
|
|
14
14
|
def authenticate(next_service, username, password=nil)
|
15
15
|
clear_prompter!
|
16
16
|
retries = 0
|
17
|
-
max_retries =
|
17
|
+
max_retries = get_max_retries
|
18
18
|
return false if !password && max_retries == 0
|
19
19
|
|
20
20
|
begin
|
@@ -34,17 +34,17 @@ module Net
|
|
34
34
|
end until (message.type != USERAUTH_FAILURE || retries >= max_retries)
|
35
35
|
|
36
36
|
case message.type
|
37
|
-
|
38
|
-
|
39
|
-
|
40
|
-
|
41
|
-
|
42
|
-
|
43
|
-
|
44
|
-
|
45
|
-
|
46
|
-
|
47
|
-
|
37
|
+
when USERAUTH_SUCCESS
|
38
|
+
debug { "password succeeded" }
|
39
|
+
@prompter.success if @prompter
|
40
|
+
return true
|
41
|
+
when USERAUTH_FAILURE
|
42
|
+
return false
|
43
|
+
when USERAUTH_PASSWD_CHANGEREQ
|
44
|
+
debug { "password change request received, failing" }
|
45
|
+
return false
|
46
|
+
else
|
47
|
+
raise Net::SSH::Exception, "unexpected reply to USERAUTH_REQUEST: #{message.type} (#{message.inspect})"
|
48
48
|
end
|
49
49
|
end
|
50
50
|
|
@@ -59,7 +59,7 @@ module Net
|
|
59
59
|
|
60
60
|
def ask_password(username)
|
61
61
|
host = session.transport.host
|
62
|
-
prompt_info = {type: 'password', user: username, host: host}
|
62
|
+
prompt_info = { type: 'password', user: username, host: host }
|
63
63
|
if @prompt_info != prompt_info
|
64
64
|
@prompt_info = prompt_info
|
65
65
|
@prompter = prompt.start(prompt_info)
|