net-ssh 5.0.2 → 7.0.1
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/.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
|