net-ssh 5.0.2 → 7.0.1
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/.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 +13 -0
- data/.gitignore +3 -0
- data/.rubocop.yml +19 -2
- data/.rubocop_todo.yml +623 -511
- data/CHANGES.txt +76 -0
- data/Dockerfile +27 -0
- data/Dockerfile.openssl3 +17 -0
- data/Gemfile +2 -0
- data/Gemfile.noed25519 +2 -0
- data/Manifest +0 -1
- data/README.md +293 -0
- data/Rakefile +6 -2
- data/appveyor.yml +4 -2
- data/docker-compose.yml +23 -0
- data/lib/net/ssh/authentication/agent.rb +36 -14
- data/lib/net/ssh/authentication/certificate.rb +19 -7
- data/lib/net/ssh/authentication/constants.rb +0 -1
- data/lib/net/ssh/authentication/ed25519.rb +83 -50
- data/lib/net/ssh/authentication/ed25519_loader.rb +5 -8
- data/lib/net/ssh/authentication/key_manager.rb +74 -33
- 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 +5 -3
- 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 +58 -16
- data/lib/net/ssh/authentication/pageant.rb +97 -97
- data/lib/net/ssh/authentication/pub_key_fingerprint.rb +2 -3
- data/lib/net/ssh/authentication/session.rb +27 -23
- data/lib/net/ssh/buffer.rb +91 -40
- data/lib/net/ssh/buffered_io.rb +24 -26
- data/lib/net/ssh/config.rb +99 -53
- data/lib/net/ssh/connection/channel.rb +101 -87
- data/lib/net/ssh/connection/constants.rb +0 -4
- data/lib/net/ssh/connection/event_loop.rb +30 -25
- data/lib/net/ssh/connection/keepalive.rb +12 -12
- data/lib/net/ssh/connection/session.rb +115 -111
- data/lib/net/ssh/connection/term.rb +56 -58
- data/lib/net/ssh/errors.rb +12 -12
- data/lib/net/ssh/key_factory.rb +108 -22
- data/lib/net/ssh/known_hosts.rb +120 -36
- data/lib/net/ssh/loggable.rb +10 -11
- data/lib/net/ssh/packet.rb +1 -1
- data/lib/net/ssh/prompt.rb +9 -11
- data/lib/net/ssh/proxy/command.rb +1 -2
- 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 -6
- data/lib/net/ssh/service/forward.rb +9 -8
- data/lib/net/ssh/test/channel.rb +24 -26
- data/lib/net/ssh/test/extensions.rb +37 -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 +12 -12
- data/lib/net/ssh/transport/algorithms.rb +177 -118
- data/lib/net/ssh/transport/cipher_factory.rb +34 -50
- data/lib/net/ssh/transport/constants.rb +13 -9
- data/lib/net/ssh/transport/ctr.rb +8 -14
- data/lib/net/ssh/transport/hmac/abstract.rb +20 -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/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/hmac.rb +13 -11
- data/lib/net/ssh/transport/identity_cipher.rb +11 -13
- data/lib/net/ssh/transport/kex/abstract.rb +130 -0
- data/lib/net/ssh/transport/kex/abstract5656.rb +72 -0
- data/lib/net/ssh/transport/kex/curve25519_sha256.rb +39 -0
- data/lib/net/ssh/transport/kex/curve25519_sha256_loader.rb +30 -0
- data/lib/net/ssh/transport/kex/diffie_hellman_group14_sha1.rb +5 -19
- data/lib/net/ssh/transport/kex/diffie_hellman_group14_sha256.rb +11 -0
- data/lib/net/ssh/transport/kex/diffie_hellman_group1_sha1.rb +30 -139
- data/lib/net/ssh/transport/kex/diffie_hellman_group_exchange_sha1.rb +1 -8
- data/lib/net/ssh/transport/kex/diffie_hellman_group_exchange_sha256.rb +5 -9
- data/lib/net/ssh/transport/kex/ecdh_sha2_nistp256.rb +20 -81
- 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/kex.rb +15 -10
- data/lib/net/ssh/transport/key_expander.rb +7 -8
- data/lib/net/ssh/transport/openssl.rb +149 -111
- data/lib/net/ssh/transport/packet_stream.rb +53 -22
- data/lib/net/ssh/transport/server_version.rb +17 -16
- data/lib/net/ssh/transport/session.rb +35 -11
- data/lib/net/ssh/transport/state.rb +44 -44
- data/lib/net/ssh/verifiers/accept_new.rb +7 -2
- data/lib/net/ssh/verifiers/accept_new_or_local_tunnel.rb +1 -2
- data/lib/net/ssh/verifiers/always.rb +10 -4
- data/lib/net/ssh/verifiers/never.rb +4 -2
- data/lib/net/ssh/version.rb +2 -2
- data/lib/net/ssh.rb +17 -9
- data/net-ssh-public_cert.pem +18 -19
- data/net-ssh.gemspec +9 -7
- data/support/ssh_tunnel_bug.rb +3 -3
- data.tar.gz.sig +0 -0
- metadata +65 -41
- metadata.gz.sig +0 -0
- data/.travis.yml +0 -52
- 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
|
@@ -11,7 +11,6 @@ require 'net/ssh/authentication/methods/keyboard_interactive'
|
|
|
11
11
|
module Net
|
|
12
12
|
module SSH
|
|
13
13
|
module Authentication
|
|
14
|
-
|
|
15
14
|
# Raised if the current authentication method is not allowed
|
|
16
15
|
class DisallowedMethod < Net::SSH::Exception
|
|
17
16
|
end
|
|
@@ -42,7 +41,7 @@ module Net
|
|
|
42
41
|
|
|
43
42
|
# Instantiates a new Authentication::Session object over the given
|
|
44
43
|
# transport layer abstraction.
|
|
45
|
-
def initialize(transport, options={})
|
|
44
|
+
def initialize(transport, options = {})
|
|
46
45
|
self.logger = transport.logger
|
|
47
46
|
@transport = transport
|
|
48
47
|
|
|
@@ -55,7 +54,7 @@ module Net
|
|
|
55
54
|
# Attempts to authenticate the given user, in preparation for the next
|
|
56
55
|
# service request. Returns true if an authentication method succeeds in
|
|
57
56
|
# authenticating the user, and false otherwise.
|
|
58
|
-
def authenticate(next_service, username, password=nil)
|
|
57
|
+
def authenticate(next_service, username, password = nil)
|
|
59
58
|
debug { "beginning authentication of `#{username}'" }
|
|
60
59
|
|
|
61
60
|
transport.send_message(transport.service_request("ssh-userauth"))
|
|
@@ -63,28 +62,30 @@ module Net
|
|
|
63
62
|
|
|
64
63
|
key_manager = KeyManager.new(logger, options)
|
|
65
64
|
keys.each { |key| key_manager.add(key) } unless keys.empty?
|
|
65
|
+
keycerts.each { |keycert| key_manager.add_keycert(keycert) } unless keycerts.empty?
|
|
66
66
|
key_data.each { |key2| key_manager.add_key_data(key2) } unless key_data.empty?
|
|
67
67
|
default_keys.each { |key| key_manager.add(key) } unless options.key?(:keys) || options.key?(:key_data)
|
|
68
68
|
|
|
69
69
|
attempted = []
|
|
70
70
|
|
|
71
71
|
@auth_methods.each do |name|
|
|
72
|
+
next unless @allowed_auth_methods.include?(name)
|
|
73
|
+
|
|
74
|
+
attempted << name
|
|
75
|
+
|
|
76
|
+
debug { "trying #{name}" }
|
|
72
77
|
begin
|
|
73
|
-
|
|
74
|
-
|
|
75
|
-
|
|
76
|
-
|
|
77
|
-
|
|
78
|
-
|
|
79
|
-
|
|
80
|
-
rescue NameError
|
|
81
|
-
debug {"Mechanism #{name} was requested, but isn't a known type. Ignoring it."}
|
|
82
|
-
next
|
|
83
|
-
end
|
|
84
|
-
|
|
85
|
-
return true if method.authenticate(next_service, username, password)
|
|
86
|
-
rescue Net::SSH::Authentication::DisallowedMethod
|
|
78
|
+
auth_class = Methods.const_get(name.split(/\W+/).map { |p| p.capitalize }.join)
|
|
79
|
+
method = auth_class.new(self,
|
|
80
|
+
key_manager: key_manager, password_prompt: options[:password_prompt],
|
|
81
|
+
pubkey_algorithms: options[:pubkey_algorithms] || nil)
|
|
82
|
+
rescue NameError
|
|
83
|
+
debug {"Mechanism #{name} was requested, but isn't a known type. Ignoring it."}
|
|
84
|
+
next
|
|
87
85
|
end
|
|
86
|
+
|
|
87
|
+
return true if method.authenticate(next_service, username, password)
|
|
88
|
+
rescue Net::SSH::Authentication::DisallowedMethod
|
|
88
89
|
end
|
|
89
90
|
|
|
90
91
|
error { "all authorization methods failed (tried #{attempted.join(', ')})" }
|
|
@@ -128,6 +129,7 @@ module Net
|
|
|
128
129
|
def expect_message(type)
|
|
129
130
|
message = next_message
|
|
130
131
|
raise Net::SSH::Exception, "expected #{type}, got #{message.type} (#{message})" unless message.type == type
|
|
132
|
+
|
|
131
133
|
message
|
|
132
134
|
end
|
|
133
135
|
|
|
@@ -136,12 +138,8 @@ module Net
|
|
|
136
138
|
# Returns an array of paths to the key files usually defined
|
|
137
139
|
# by system default.
|
|
138
140
|
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
|
|
141
|
+
%w[~/.ssh/id_ed25519 ~/.ssh/id_rsa ~/.ssh/id_dsa ~/.ssh/id_ecdsa
|
|
142
|
+
~/.ssh2/id_ed25519 ~/.ssh2/id_rsa ~/.ssh2/id_dsa ~/.ssh2/id_ecdsa]
|
|
145
143
|
end
|
|
146
144
|
|
|
147
145
|
# Returns an array of paths to the key files that should be used when
|
|
@@ -150,6 +148,12 @@ module Net
|
|
|
150
148
|
Array(options[:keys])
|
|
151
149
|
end
|
|
152
150
|
|
|
151
|
+
# Returns an array of paths to the keycert files that should be used when
|
|
152
|
+
# attempting any key-based authentication mechanism.
|
|
153
|
+
def keycerts
|
|
154
|
+
Array(options[:keycerts])
|
|
155
|
+
end
|
|
156
|
+
|
|
153
157
|
# Returns an array of the key data that should be used when
|
|
154
158
|
# attempting any key-based authentication mechanism.
|
|
155
159
|
def key_data
|
data/lib/net/ssh/buffer.rb
CHANGED
|
@@ -1,4 +1,3 @@
|
|
|
1
|
-
require 'net/ssh/ruby_compat'
|
|
2
1
|
require 'net/ssh/transport/openssl'
|
|
3
2
|
|
|
4
3
|
require 'net/ssh/authentication/certificate'
|
|
@@ -6,7 +5,6 @@ require 'net/ssh/authentication/ed25519_loader'
|
|
|
6
5
|
|
|
7
6
|
module Net
|
|
8
7
|
module SSH
|
|
9
|
-
|
|
10
8
|
# Net::SSH::Buffer is a flexible class for building and parsing binary
|
|
11
9
|
# data packets. It provides a stream-like interface for sequentially
|
|
12
10
|
# reading data items from the buffer, as well as a useful helper method
|
|
@@ -72,7 +70,7 @@ module Net
|
|
|
72
70
|
|
|
73
71
|
# Creates a new buffer, initialized to the given content. The position
|
|
74
72
|
# is initialized to the beginning of the buffer.
|
|
75
|
-
def initialize(content=
|
|
73
|
+
def initialize(content = String.new)
|
|
76
74
|
@content = content.to_s
|
|
77
75
|
@position = 0
|
|
78
76
|
end
|
|
@@ -119,7 +117,7 @@ module Net
|
|
|
119
117
|
# Resets the buffer, making it empty. Also, resets the read position to
|
|
120
118
|
# 0.
|
|
121
119
|
def clear!
|
|
122
|
-
@content =
|
|
120
|
+
@content = String.new
|
|
123
121
|
@position = 0
|
|
124
122
|
end
|
|
125
123
|
|
|
@@ -130,12 +128,12 @@ module Net
|
|
|
130
128
|
# would otherwise tend to grow without bound.
|
|
131
129
|
#
|
|
132
130
|
# Returns the buffer object itself.
|
|
133
|
-
def consume!(n=position)
|
|
131
|
+
def consume!(n = position)
|
|
134
132
|
if n >= length
|
|
135
133
|
# optimize for a fairly common case
|
|
136
134
|
clear!
|
|
137
135
|
elsif n > 0
|
|
138
|
-
@content = @content[n..-1] ||
|
|
136
|
+
@content = @content[n..-1] || String.new
|
|
139
137
|
@position -= n
|
|
140
138
|
@position = 0 if @position < 0
|
|
141
139
|
end
|
|
@@ -173,7 +171,7 @@ module Net
|
|
|
173
171
|
# Reads and returns the next +count+ bytes from the buffer, starting from
|
|
174
172
|
# the read position. If +count+ is +nil+, this will return all remaining
|
|
175
173
|
# text in the buffer. This method will increment the pointer.
|
|
176
|
-
def read(count=nil)
|
|
174
|
+
def read(count = nil)
|
|
177
175
|
count ||= length
|
|
178
176
|
count = length - @position if @position + count > length
|
|
179
177
|
@position += count
|
|
@@ -182,7 +180,7 @@ module Net
|
|
|
182
180
|
|
|
183
181
|
# Reads (as #read) and returns the given number of bytes from the buffer,
|
|
184
182
|
# and then consumes (as #consume!) all data up to the new read position.
|
|
185
|
-
def read!(count=nil)
|
|
183
|
+
def read!(count = nil)
|
|
186
184
|
data = read(count)
|
|
187
185
|
consume!
|
|
188
186
|
data
|
|
@@ -238,6 +236,7 @@ module Net
|
|
|
238
236
|
def read_bignum
|
|
239
237
|
data = read_string
|
|
240
238
|
return unless data
|
|
239
|
+
|
|
241
240
|
OpenSSL::BN.new(data, 2)
|
|
242
241
|
end
|
|
243
242
|
|
|
@@ -249,6 +248,48 @@ module Net
|
|
|
249
248
|
return (type ? read_keyblob(type) : nil)
|
|
250
249
|
end
|
|
251
250
|
|
|
251
|
+
def read_private_keyblob(type)
|
|
252
|
+
case type
|
|
253
|
+
when /^ssh-rsa$/
|
|
254
|
+
key = OpenSSL::PKey::RSA.new
|
|
255
|
+
n = read_bignum
|
|
256
|
+
e = read_bignum
|
|
257
|
+
d = read_bignum
|
|
258
|
+
iqmp = read_bignum
|
|
259
|
+
p = read_bignum
|
|
260
|
+
q = read_bignum
|
|
261
|
+
_unkown1 = read_bignum
|
|
262
|
+
_unkown2 = read_bignum
|
|
263
|
+
dmp1 = d % (p - 1)
|
|
264
|
+
dmq1 = d % (q - 1)
|
|
265
|
+
if key.respond_to?(:set_key)
|
|
266
|
+
key.set_key(n, e, d)
|
|
267
|
+
else
|
|
268
|
+
key.e = e
|
|
269
|
+
key.n = n
|
|
270
|
+
key.d = d
|
|
271
|
+
end
|
|
272
|
+
if key.respond_to?(:set_factors)
|
|
273
|
+
key.set_factors(p, q)
|
|
274
|
+
else
|
|
275
|
+
key.p = p
|
|
276
|
+
key.q = q
|
|
277
|
+
end
|
|
278
|
+
if key.respond_to?(:set_crt_params)
|
|
279
|
+
key.set_crt_params(dmp1, dmq1, iqmp)
|
|
280
|
+
else
|
|
281
|
+
key.dmp1 = dmp1
|
|
282
|
+
key.dmq1 = dmq1
|
|
283
|
+
key.iqmp = iqmp
|
|
284
|
+
end
|
|
285
|
+
key
|
|
286
|
+
when /^ecdsa\-sha2\-(\w*)$/
|
|
287
|
+
OpenSSL::PKey::EC.read_keyblob($1, self)
|
|
288
|
+
else
|
|
289
|
+
raise Exception, "Cannot decode private key of type #{type}"
|
|
290
|
+
end
|
|
291
|
+
end
|
|
292
|
+
|
|
252
293
|
# Read a keyblob of the given type from the buffer, and return it as
|
|
253
294
|
# a key. Only RSA, DSA, and ECDSA keys are supported.
|
|
254
295
|
def read_keyblob(type)
|
|
@@ -256,42 +297,47 @@ module Net
|
|
|
256
297
|
when /^(.*)-cert-v01@openssh\.com$/
|
|
257
298
|
key = Net::SSH::Authentication::Certificate.read_certblob(self, $1)
|
|
258
299
|
when /^ssh-dss$/
|
|
259
|
-
|
|
260
|
-
|
|
261
|
-
|
|
262
|
-
|
|
263
|
-
|
|
264
|
-
|
|
265
|
-
|
|
266
|
-
|
|
267
|
-
|
|
268
|
-
|
|
269
|
-
|
|
270
|
-
|
|
271
|
-
|
|
300
|
+
p = read_bignum
|
|
301
|
+
q = read_bignum
|
|
302
|
+
g = read_bignum
|
|
303
|
+
pub_key = read_bignum
|
|
304
|
+
|
|
305
|
+
asn1 = OpenSSL::ASN1::Sequence.new(
|
|
306
|
+
[
|
|
307
|
+
OpenSSL::ASN1::Sequence.new(
|
|
308
|
+
[
|
|
309
|
+
OpenSSL::ASN1::ObjectId.new('DSA'),
|
|
310
|
+
OpenSSL::ASN1::Sequence.new(
|
|
311
|
+
[
|
|
312
|
+
OpenSSL::ASN1::Integer.new(p),
|
|
313
|
+
OpenSSL::ASN1::Integer.new(q),
|
|
314
|
+
OpenSSL::ASN1::Integer.new(g)
|
|
315
|
+
]
|
|
316
|
+
)
|
|
317
|
+
]
|
|
318
|
+
),
|
|
319
|
+
OpenSSL::ASN1::BitString.new(OpenSSL::ASN1::Integer.new(pub_key).to_der)
|
|
320
|
+
]
|
|
321
|
+
)
|
|
322
|
+
|
|
323
|
+
key = OpenSSL::PKey::DSA.new(asn1.to_der)
|
|
272
324
|
when /^ssh-rsa$/
|
|
273
|
-
|
|
274
|
-
|
|
275
|
-
|
|
276
|
-
|
|
277
|
-
|
|
278
|
-
|
|
279
|
-
|
|
280
|
-
|
|
281
|
-
|
|
325
|
+
e = read_bignum
|
|
326
|
+
n = read_bignum
|
|
327
|
+
|
|
328
|
+
asn1 = OpenSSL::ASN1::Sequence(
|
|
329
|
+
[
|
|
330
|
+
OpenSSL::ASN1::Integer(n),
|
|
331
|
+
OpenSSL::ASN1::Integer(e)
|
|
332
|
+
]
|
|
333
|
+
)
|
|
334
|
+
|
|
335
|
+
key = OpenSSL::PKey::RSA.new(asn1.to_der)
|
|
282
336
|
when /^ssh-ed25519$/
|
|
283
337
|
Net::SSH::Authentication::ED25519Loader.raiseUnlessLoaded("unsupported key type `#{type}'")
|
|
284
338
|
key = Net::SSH::Authentication::ED25519::PubKey.read_keyblob(self)
|
|
285
339
|
when /^ecdsa\-sha2\-(\w*)$/
|
|
286
|
-
|
|
287
|
-
raise NotImplementedError, "unsupported key type `#{type}'"
|
|
288
|
-
else
|
|
289
|
-
begin
|
|
290
|
-
key = OpenSSL::PKey::EC.read_keyblob($1, self)
|
|
291
|
-
rescue OpenSSL::PKey::ECError
|
|
292
|
-
raise NotImplementedError, "unsupported key type `#{type}'"
|
|
293
|
-
end
|
|
294
|
-
end
|
|
340
|
+
key = OpenSSL::PKey::EC.read_keyblob($1, self)
|
|
295
341
|
else
|
|
296
342
|
raise NotImplementedError, "unsupported key type `#{type}'"
|
|
297
343
|
end
|
|
@@ -315,7 +361,12 @@ module Net
|
|
|
315
361
|
# Optimized version of write where the caller gives up ownership of string
|
|
316
362
|
# to the method. This way we can mutate the string.
|
|
317
363
|
def write_moved(string)
|
|
318
|
-
@content <<
|
|
364
|
+
@content <<
|
|
365
|
+
if string.frozen?
|
|
366
|
+
string.dup.force_encoding('BINARY')
|
|
367
|
+
else
|
|
368
|
+
string.force_encoding('BINARY')
|
|
369
|
+
end
|
|
319
370
|
self
|
|
320
371
|
end
|
|
321
372
|
|
data/lib/net/ssh/buffered_io.rb
CHANGED
|
@@ -1,10 +1,8 @@
|
|
|
1
1
|
require 'net/ssh/buffer'
|
|
2
2
|
require 'net/ssh/loggable'
|
|
3
|
-
require 'net/ssh/ruby_compat'
|
|
4
3
|
|
|
5
|
-
module Net
|
|
4
|
+
module Net
|
|
6
5
|
module SSH
|
|
7
|
-
|
|
8
6
|
# This module is used to extend sockets and other IO objects, to allow
|
|
9
7
|
# them to be buffered for both read and write. This abstraction makes it
|
|
10
8
|
# quite easy to write a select-based event loop
|
|
@@ -49,19 +47,19 @@ module Net
|
|
|
49
47
|
# end
|
|
50
48
|
module BufferedIo
|
|
51
49
|
include Loggable
|
|
52
|
-
|
|
50
|
+
|
|
53
51
|
# Called when the #extend is called on an object, with this module as the
|
|
54
52
|
# argument. It ensures that the modules instance variables are all properly
|
|
55
53
|
# initialized.
|
|
56
|
-
def self.extended(object)
|
|
54
|
+
def self.extended(object) # :nodoc:
|
|
57
55
|
# need to use __send__ because #send is overridden in Socket
|
|
58
56
|
object.__send__(:initialize_buffered_io)
|
|
59
57
|
end
|
|
60
|
-
|
|
58
|
+
|
|
61
59
|
# Tries to read up to +n+ bytes of data from the remote end, and appends
|
|
62
60
|
# the data to the input buffer. It returns the number of bytes read, or 0
|
|
63
61
|
# if no data was available to be read.
|
|
64
|
-
def fill(n=8192)
|
|
62
|
+
def fill(n = 8192)
|
|
65
63
|
input.consume!
|
|
66
64
|
data = recv(n)
|
|
67
65
|
debug { "read #{data.length} bytes" }
|
|
@@ -71,31 +69,31 @@ module Net
|
|
|
71
69
|
@input_errors << e
|
|
72
70
|
return 0
|
|
73
71
|
end
|
|
74
|
-
|
|
72
|
+
|
|
75
73
|
# Read up to +length+ bytes from the input buffer. If +length+ is nil,
|
|
76
74
|
# all available data is read from the buffer. (See #available.)
|
|
77
|
-
def read_available(length=nil)
|
|
75
|
+
def read_available(length = nil)
|
|
78
76
|
input.read(length || available)
|
|
79
77
|
end
|
|
80
|
-
|
|
78
|
+
|
|
81
79
|
# Returns the number of bytes available to be read from the input buffer.
|
|
82
80
|
# (See #read_available.)
|
|
83
81
|
def available
|
|
84
82
|
input.available
|
|
85
83
|
end
|
|
86
|
-
|
|
84
|
+
|
|
87
85
|
# Enqueues data in the output buffer, to be written when #send_pending
|
|
88
86
|
# is called. Note that the data is _not_ sent immediately by this method!
|
|
89
87
|
def enqueue(data)
|
|
90
88
|
output.append(data)
|
|
91
89
|
end
|
|
92
|
-
|
|
90
|
+
|
|
93
91
|
# Returns +true+ if there is data waiting in the output buffer, and
|
|
94
92
|
# +false+ otherwise.
|
|
95
93
|
def pending_write?
|
|
96
94
|
output.length > 0
|
|
97
95
|
end
|
|
98
|
-
|
|
96
|
+
|
|
99
97
|
# Sends as much of the pending output as possible. Returns +true+ if any
|
|
100
98
|
# data was sent, and +false+ otherwise.
|
|
101
99
|
def send_pending
|
|
@@ -108,7 +106,7 @@ module Net
|
|
|
108
106
|
return false
|
|
109
107
|
end
|
|
110
108
|
end
|
|
111
|
-
|
|
109
|
+
|
|
112
110
|
# Calls #send_pending repeatedly, if necessary, blocking until the output
|
|
113
111
|
# buffer is empty.
|
|
114
112
|
def wait_for_pending_sends
|
|
@@ -116,31 +114,32 @@ module Net
|
|
|
116
114
|
while output.length > 0
|
|
117
115
|
result = IO.select(nil, [self]) or next
|
|
118
116
|
next unless result[1].any?
|
|
117
|
+
|
|
119
118
|
send_pending
|
|
120
119
|
end
|
|
121
120
|
end
|
|
122
|
-
|
|
121
|
+
|
|
123
122
|
public # these methods are primarily for use in tests
|
|
124
|
-
|
|
125
|
-
def write_buffer
|
|
123
|
+
|
|
124
|
+
def write_buffer # :nodoc:
|
|
126
125
|
output.to_s
|
|
127
126
|
end
|
|
128
|
-
|
|
129
|
-
def read_buffer
|
|
127
|
+
|
|
128
|
+
def read_buffer # :nodoc:
|
|
130
129
|
input.to_s
|
|
131
130
|
end
|
|
132
|
-
|
|
131
|
+
|
|
133
132
|
private
|
|
134
|
-
|
|
133
|
+
|
|
135
134
|
#--
|
|
136
135
|
# Can't use attr_reader here (after +private+) without incurring the
|
|
137
136
|
# wrath of "ruby -w". We hates it.
|
|
138
137
|
#++
|
|
139
|
-
|
|
138
|
+
|
|
140
139
|
def input; @input; end
|
|
141
140
|
|
|
142
141
|
def output; @output; end
|
|
143
|
-
|
|
142
|
+
|
|
144
143
|
# Initializes the intput and output buffers for this object. This method
|
|
145
144
|
# is called automatically when the module is mixed into an object via
|
|
146
145
|
# Object#extend (see Net::SSH::BufferedIo.extended), but must be called
|
|
@@ -167,7 +166,7 @@ module Net
|
|
|
167
166
|
# http://github.com/net-ssh/net-ssh/tree/portfwfix
|
|
168
167
|
#
|
|
169
168
|
module ForwardedBufferedIo
|
|
170
|
-
def fill(n=8192)
|
|
169
|
+
def fill(n = 8192)
|
|
171
170
|
begin
|
|
172
171
|
super(n)
|
|
173
172
|
rescue Errno::ECONNRESET => e
|
|
@@ -182,7 +181,7 @@ module Net
|
|
|
182
181
|
end
|
|
183
182
|
end
|
|
184
183
|
end
|
|
185
|
-
|
|
184
|
+
|
|
186
185
|
def send_pending
|
|
187
186
|
begin
|
|
188
187
|
super
|
|
@@ -199,6 +198,5 @@ module Net
|
|
|
199
198
|
end
|
|
200
199
|
end
|
|
201
200
|
end
|
|
202
|
-
|
|
203
201
|
end
|
|
204
202
|
end
|