net-ssh 3.0.1 → 3.0.2.rc1
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 +1 -1
- data.tar.gz.sig +0 -0
- data/CHANGES.txt +4 -0
- data/README.rdoc +1 -1
- data/Rakefile +5 -1
- data/lib/net/ssh.rb +5 -2
- data/lib/net/ssh/authentication/key_manager.rb +1 -4
- data/lib/net/ssh/connection/channel.rb +26 -7
- data/lib/net/ssh/connection/session.rb +11 -2
- data/lib/net/ssh/proxy/command.rb +17 -2
- data/lib/net/ssh/version.rb +2 -2
- data/net-ssh-public_cert.pem +15 -15
- data/net-ssh.gemspec +7 -5
- data/test/README.txt +0 -22
- data/test/connection/test_channel.rb +3 -0
- data/test/connection/test_session.rb +14 -5
- data/test/integration/README.txt +2 -4
- data/test/integration/common.rb +6 -0
- data/test/integration/playbook.yml +8 -0
- data/test/integration/test_forward.rb +435 -0
- data/test/integration/test_id_rsa_keys.rb +18 -6
- data/test/integration/test_proxy.rb +93 -0
- data/test/start/test_user_nil.rb +27 -0
- data/test/test_all.rb +1 -1
- metadata +22 -20
- metadata.gz.sig +0 -0
- data/test/manual/test_forward.rb +0 -285
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA1:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: 93524ab10733902b604b76acc36193d8bcf4ca1b
|
4
|
+
data.tar.gz: 88e5c681181e9011458adb039bc2853b4f31310b
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: afbd93ffc5d6ce03bdd1e4a311baf4b7341ab46d0048fe165c32ab7d6de403c6070ae9d5be78cd7ebbebf71d0dd03cc42ab2b2602f453c013cba92ece19c87db
|
7
|
+
data.tar.gz: 0a1f1f8cdd3abc441295acba9ff48b7149bd7625aa9d0fa53a505c62b697d87b8661ca02324047b2fbc348b02f5039bd0b9e8239413de708edfa6ae9c5e8228b
|
checksums.yaml.gz.sig
CHANGED
@@ -1 +1 @@
|
|
1
|
-
|
1
|
+
�?�.���$�?\��dË��(��h�Qڛ���J�s&(/�W��C1AaWͩkEF��} �S�����������g)"��i7o �I�ĩ�<JCY0?}��&qt"��_��+i1*`�I�ޞ�f9����ژ�X*�9��<�晚���.
|
data.tar.gz.sig
CHANGED
Binary file
|
data/CHANGES.txt
CHANGED
@@ -1,3 +1,7 @@
|
|
1
|
+
* fixed rare WaitWritable error with proxy commands [Miklos Fazkas, Andre Meij]]
|
2
|
+
* if Net::SSH.start user is nil and config has no entry we default to Etc.getlogin
|
3
|
+
* Bugfix: CHANNEL_CLOSE was sent before draining ouput buffer #280 [Christopher F. Auston]
|
4
|
+
|
1
5
|
=== 3.0.1
|
2
6
|
=== 3.0.1.rc1
|
3
7
|
|
data/README.rdoc
CHANGED
data/Rakefile
CHANGED
@@ -74,7 +74,11 @@ end
|
|
74
74
|
|
75
75
|
require 'rake/testtask'
|
76
76
|
Rake::TestTask.new do |t|
|
77
|
-
|
77
|
+
if ENV['NET_SSH_RUN_INTEGRATION_TESTS']
|
78
|
+
t.libs = ["lib","test","test/integration"]
|
79
|
+
else
|
80
|
+
t.libs = ["lib", "test"]
|
81
|
+
end
|
78
82
|
end
|
79
83
|
|
80
84
|
Rake::TestTask.new(:'integration-test') do |t|
|
data/lib/net/ssh.rb
CHANGED
@@ -188,7 +188,10 @@ module Net
|
|
188
188
|
# password auth method
|
189
189
|
# * :non_interactive => non interactive applications should set it to true
|
190
190
|
# to prefer failing a password/etc auth methods vs asking for password
|
191
|
-
|
191
|
+
#
|
192
|
+
# If +user+ parameter is nil it defaults to USER from ssh_config, or
|
193
|
+
# local username
|
194
|
+
def self.start(host, user=nil, options={}, &block)
|
192
195
|
invalid_options = options.keys - VALID_OPTIONS
|
193
196
|
if invalid_options.any?
|
194
197
|
raise ArgumentError, "invalid option(s): #{invalid_options.join(', ')}"
|
@@ -222,7 +225,7 @@ module Net
|
|
222
225
|
transport = Transport::Session.new(host, options)
|
223
226
|
auth = Authentication::Session.new(transport, options)
|
224
227
|
|
225
|
-
user = options.fetch(:user, user)
|
228
|
+
user = options.fetch(:user, user) || Etc.getlogin
|
226
229
|
if auth.authenticate("ssh-connection", user, options[:password])
|
227
230
|
connection = Connection::Session.new(transport, options)
|
228
231
|
if block_given?
|
@@ -232,16 +232,13 @@ module Net
|
|
232
232
|
identity
|
233
233
|
end
|
234
234
|
|
235
|
-
rescue OpenSSL::PKey::RSAError, OpenSSL::PKey::DSAError, OpenSSL::PKey::ECError => e
|
235
|
+
rescue OpenSSL::PKey::RSAError, OpenSSL::PKey::DSAError, OpenSSL::PKey::ECError, ArgumentError => e
|
236
236
|
if ignore_decryption_errors
|
237
237
|
identity
|
238
238
|
else
|
239
239
|
process_identity_loading_error(identity, e)
|
240
240
|
nil
|
241
241
|
end
|
242
|
-
rescue ArgumentError => e
|
243
|
-
process_identity_loading_error(identity, e)
|
244
|
-
nil
|
245
242
|
rescue Exception => e
|
246
243
|
process_identity_loading_error(identity, e)
|
247
244
|
nil
|
@@ -126,7 +126,7 @@ module Net; module SSH; module Connection
|
|
126
126
|
@pending_requests = []
|
127
127
|
@on_open_failed = @on_data = @on_extended_data = @on_process = @on_close = @on_eof = nil
|
128
128
|
@on_request = {}
|
129
|
-
@closing = @eof = @sent_eof = false
|
129
|
+
@closing = @eof = @sent_eof = @local_closed = @remote_closed = false
|
130
130
|
end
|
131
131
|
|
132
132
|
# A shortcut for accessing properties of the channel (see #properties).
|
@@ -269,14 +269,28 @@ module Net; module SSH; module Connection
|
|
269
269
|
connection.loop { active? }
|
270
270
|
end
|
271
271
|
|
272
|
-
#
|
273
|
-
#
|
274
|
-
#
|
275
|
-
#
|
272
|
+
# True if close() has been called; NOTE: if the channel has data waiting to
|
273
|
+
# be sent then the channel will close after all the data is sent. See
|
274
|
+
# closed?() to determine if we have actually sent CHANNEL_CLOSE to server.
|
275
|
+
# This may be true for awhile before closed? returns true if we are still
|
276
|
+
# sending buffered output to server.
|
276
277
|
def closing?
|
277
278
|
@closing
|
278
279
|
end
|
279
280
|
|
281
|
+
# True if we have sent CHANNEL_CLOSE to the remote server.
|
282
|
+
def local_closed?
|
283
|
+
@local_closed
|
284
|
+
end
|
285
|
+
|
286
|
+
def remote_closed?
|
287
|
+
@remote_closed
|
288
|
+
end
|
289
|
+
|
290
|
+
def remote_closed!
|
291
|
+
@remote_closed = true
|
292
|
+
end
|
293
|
+
|
280
294
|
# Requests that the channel be closed. If the channel is already closing,
|
281
295
|
# this does nothing, nor does it do anything if the channel has not yet
|
282
296
|
# been confirmed open (see #do_open_confirmation). Otherwise, it sends a
|
@@ -285,7 +299,6 @@ module Net; module SSH; module Connection
|
|
285
299
|
return if @closing
|
286
300
|
if remote_id
|
287
301
|
@closing = true
|
288
|
-
connection.send_message(Buffer.from(:byte, CHANNEL_CLOSE, :long, remote_id))
|
289
302
|
end
|
290
303
|
end
|
291
304
|
|
@@ -311,10 +324,16 @@ module Net; module SSH; module Connection
|
|
311
324
|
@on_process.call(self) if @on_process
|
312
325
|
enqueue_pending_output
|
313
326
|
|
314
|
-
if @eof and not @sent_eof and output.empty? and remote_id
|
327
|
+
if @eof and not @sent_eof and output.empty? and remote_id and not @local_closed
|
315
328
|
connection.send_message(Buffer.from(:byte, CHANNEL_EOF, :long, remote_id))
|
316
329
|
@sent_eof = true
|
317
330
|
end
|
331
|
+
|
332
|
+
if @closing and not @local_closed and output.empty? and remote_id
|
333
|
+
connection.send_message(Buffer.from(:byte, CHANNEL_CLOSE, :long, remote_id))
|
334
|
+
@local_closed = true
|
335
|
+
connection.cleanup_channel(self)
|
336
|
+
end
|
318
337
|
end
|
319
338
|
|
320
339
|
# Registers a callback to be invoked when data packets are received by the
|
@@ -220,7 +220,7 @@ module Net; module SSH; module Connection
|
|
220
220
|
def preprocess
|
221
221
|
return false if block_given? && !yield(self)
|
222
222
|
dispatch_incoming_packets
|
223
|
-
channels.each { |id, channel| channel.process unless channel.
|
223
|
+
channels.each { |id, channel| channel.process unless channel.local_closed? }
|
224
224
|
return false if block_given? && !yield(self)
|
225
225
|
return true
|
226
226
|
end
|
@@ -455,6 +455,14 @@ module Net; module SSH; module Connection
|
|
455
455
|
old
|
456
456
|
end
|
457
457
|
|
458
|
+
def cleanup_channel(channel)
|
459
|
+
if channel.local_closed? and channel.remote_closed?
|
460
|
+
info { "#{host} delete channel #{channel.local_id} which closed locally and remotely" }
|
461
|
+
channels.delete(channel.local_id)
|
462
|
+
end
|
463
|
+
end
|
464
|
+
|
465
|
+
|
458
466
|
private
|
459
467
|
|
460
468
|
# Read all pending packets from the connection and dispatch them as
|
@@ -583,9 +591,10 @@ module Net; module SSH; module Connection
|
|
583
591
|
info { "channel_close: #{packet[:local_id]}" }
|
584
592
|
|
585
593
|
channel = channels[packet[:local_id]]
|
594
|
+
channel.remote_closed!
|
586
595
|
channel.close
|
587
596
|
|
588
|
-
|
597
|
+
cleanup_channel(channel)
|
589
598
|
channel.do_close
|
590
599
|
end
|
591
600
|
|
@@ -79,11 +79,26 @@ module Net; module SSH; module Proxy
|
|
79
79
|
end
|
80
80
|
else
|
81
81
|
def io.send(data, flag)
|
82
|
-
|
82
|
+
begin
|
83
|
+
result = write_nonblock(data)
|
84
|
+
rescue IO::WaitWritable, Errno::EINTR
|
85
|
+
IO.select(nil, [self])
|
86
|
+
retry
|
87
|
+
end
|
88
|
+
result
|
83
89
|
end
|
84
90
|
|
85
91
|
def io.recv(size)
|
86
|
-
|
92
|
+
begin
|
93
|
+
result = read_nonblock(size)
|
94
|
+
rescue IO::WaitReadable, Errno::EINTR
|
95
|
+
timeout_in_seconds = 20
|
96
|
+
if IO.select([self], nil, [self], timeout_in_seconds) == nil
|
97
|
+
raise "Unexpected spurious read wakeup"
|
98
|
+
end
|
99
|
+
retry
|
100
|
+
end
|
101
|
+
result
|
87
102
|
end
|
88
103
|
end
|
89
104
|
io
|
data/lib/net/ssh/version.rb
CHANGED
@@ -51,11 +51,11 @@ module Net; module SSH
|
|
51
51
|
MINOR = 0
|
52
52
|
|
53
53
|
# The tiny component of this version of the Net::SSH library
|
54
|
-
TINY =
|
54
|
+
TINY = 2
|
55
55
|
|
56
56
|
# The prerelease component of this version of the Net::SSH library
|
57
57
|
# nil allowed
|
58
|
-
PRE =
|
58
|
+
PRE = "rc1"
|
59
59
|
|
60
60
|
# The current version of the Net::SSH library as a Version instance
|
61
61
|
CURRENT = new(*[MAJOR, MINOR, TINY, PRE].compact)
|
data/net-ssh-public_cert.pem
CHANGED
@@ -1,20 +1,20 @@
|
|
1
1
|
-----BEGIN CERTIFICATE-----
|
2
2
|
MIIDODCCAiCgAwIBAgIBADANBgkqhkiG9w0BAQUFADBCMRAwDgYDVQQDDAduZXQt
|
3
3
|
c3NoMRkwFwYKCZImiZPyLGQBGRYJc29sdXRpb3VzMRMwEQYKCZImiZPyLGQBGRYD
|
4
|
-
|
4
|
+
Y29tMB4XDTE1MTIwNjIxMDYyNFoXDTE2MTIwNTIxMDYyNFowQjEQMA4GA1UEAwwH
|
5
5
|
bmV0LXNzaDEZMBcGCgmSJomT8ixkARkWCXNvbHV0aW91czETMBEGCgmSJomT8ixk
|
6
|
-
|
7
|
-
|
8
|
-
|
9
|
-
|
10
|
-
|
11
|
-
|
12
|
-
|
13
|
-
|
14
|
-
|
15
|
-
|
16
|
-
|
17
|
-
|
18
|
-
|
19
|
-
|
6
|
+
ARkWA2NvbTCCASIwDQYJKoZIhvcNAQEBBQADggEPADCCAQoCggEBAMYnhNtn0f6p
|
7
|
+
nTylB8mE8lMdoMLJC8KwpMWsvk73Pe2WVDsH/OSwwwz6oUGk1i70cJyDjIEBNpwT
|
8
|
+
88GpVXJSumvqVsf9fCg3mWNeb5t0J+aeNm9MIvYVMTqj5tydoXQiwnILRDYHV9tZ
|
9
|
+
1c3o59/VlahSTpZ7YEgzVufpAkvEGkbJiG849exiipK7MN/ZIkMOxYVnyRXk43Xc
|
10
|
+
6GYlsHOfSgPwcXwW5g57DCwLQLWrjDsTka28dxDmO7B5Lv5EqzINxVxWsu43OgZG
|
11
|
+
21Io/jIyf5PNpeKPKNGDuAQJ8mvdMYBJoDhtCwgsUYbl0BZzA7g4ytl51HtIeP+j
|
12
|
+
Qp/eAvs/RrECAwEAAaM5MDcwCQYDVR0TBAIwADAdBgNVHQ4EFgQUBfKiwO2eM4NE
|
13
|
+
iRrVG793qEPLYyMwCwYDVR0PBAQDAgSwMA0GCSqGSIb3DQEBBQUAA4IBAQCfZFdb
|
14
|
+
p4jzkfIzGDbiOxd0R8sdqJoC4nMLEgnQ7dLulawwA3IXe3sHAKgA5kmH3prsKc5H
|
15
|
+
zVmM5NlH2P1nRbegIkQTYiIod1hZQCNxdmVG/fprMqPq0ybpUOjjrP5pj0OtszE1
|
16
|
+
F2dQia1hOEstMR+n0nAtWII9HJAEyeZjVV0s2Cl7Pt85XJ3hxFcCKwzqsK5xRI7a
|
17
|
+
B3vwh3/JJYrFonIohQ//Lg9qTZASEkoKLlq1/hFeICoCGGIGLq45ZB7CzXLooCKi
|
18
|
+
s/ZUKye79ELwFYKJOhjW5g725OL3hy+llhEleytwKRwgXFQBPTC4f5UkdxZVVWGH
|
19
|
+
e2C9M1m/2odPZo8h
|
20
20
|
-----END CERTIFICATE-----
|
data/net-ssh.gemspec
CHANGED
@@ -2,17 +2,17 @@
|
|
2
2
|
# DO NOT EDIT THIS FILE DIRECTLY
|
3
3
|
# Instead, edit Jeweler::Tasks in Rakefile, and run 'rake gemspec'
|
4
4
|
# -*- encoding: utf-8 -*-
|
5
|
-
# stub: net-ssh 3.0.
|
5
|
+
# stub: net-ssh 3.0.2.rc1 ruby lib
|
6
6
|
|
7
7
|
Gem::Specification.new do |s|
|
8
8
|
s.name = "net-ssh"
|
9
|
-
s.version = "3.0.
|
9
|
+
s.version = "3.0.2.rc1"
|
10
10
|
|
11
|
-
s.required_rubygems_version = Gem::Requirement.new("
|
11
|
+
s.required_rubygems_version = Gem::Requirement.new("> 1.3.1") if s.respond_to? :required_rubygems_version=
|
12
12
|
s.require_paths = ["lib"]
|
13
13
|
s.authors = ["Jamis Buck", "Delano Mandelbaum", "Mikl\u{f3}s Fazekas"]
|
14
14
|
s.cert_chain = ["net-ssh-public_cert.pem"]
|
15
|
-
s.date = "2015-
|
15
|
+
s.date = "2015-12-10"
|
16
16
|
s.description = "Net::SSH: a pure-Ruby implementation of the SSH2 client protocol. It allows you to write programs that invoke and interact with processes on remote servers, via SSH2."
|
17
17
|
s.email = "net-ssh@solutious.com"
|
18
18
|
s.extra_rdoc_files = [
|
@@ -144,14 +144,16 @@ Gem::Specification.new do |s|
|
|
144
144
|
"test/integration/Vagrantfile",
|
145
145
|
"test/integration/common.rb",
|
146
146
|
"test/integration/playbook.yml",
|
147
|
+
"test/integration/test_forward.rb",
|
147
148
|
"test/integration/test_id_rsa_keys.rb",
|
149
|
+
"test/integration/test_proxy.rb",
|
148
150
|
"test/known_hosts/github",
|
149
151
|
"test/known_hosts/github_hash",
|
150
|
-
"test/manual/test_forward.rb",
|
151
152
|
"test/manual/test_pageant.rb",
|
152
153
|
"test/start/test_connection.rb",
|
153
154
|
"test/start/test_options.rb",
|
154
155
|
"test/start/test_transport.rb",
|
156
|
+
"test/start/test_user_nil.rb",
|
155
157
|
"test/test_all.rb",
|
156
158
|
"test/test_buffer.rb",
|
157
159
|
"test/test_buffered_io.rb",
|
data/test/README.txt
CHANGED
@@ -16,25 +16,3 @@ INTEGRATION TESTS
|
|
16
16
|
|
17
17
|
brew install ansible ; ansible-galaxy install rvm_io.rvm1-ruby ; vagrant up ; vagrant ssh
|
18
18
|
cd /net-ssh ; rake integration-test
|
19
|
-
|
20
|
-
PORT FORWARDING TESTS
|
21
|
-
|
22
|
-
ruby -Ilib -Itest -rrubygems test/manual/test_forward.rb
|
23
|
-
|
24
|
-
test_forward.rb must be run separately from the test suite because
|
25
|
-
it requires authorizing your public SSH keys on you localhost.
|
26
|
-
|
27
|
-
If you already have keys you can do this:
|
28
|
-
|
29
|
-
cat ~/.ssh/id_rsa.pub >> ~/.ssh/authorized_keys
|
30
|
-
|
31
|
-
If you don't have keys see:
|
32
|
-
|
33
|
-
http://kimmo.suominen.com/docs/ssh/#ssh-keygen
|
34
|
-
|
35
|
-
You should now be able to login to your localhost with out
|
36
|
-
bring prompted for a password:
|
37
|
-
|
38
|
-
ssh localhost
|
39
|
-
|
40
|
-
-Delano
|
@@ -74,8 +74,11 @@ module Connection
|
|
74
74
|
assert !channel.closing?
|
75
75
|
|
76
76
|
connection.expect { |t,packet| assert_equal CHANNEL_CLOSE, packet.type }
|
77
|
+
connection.expects(:cleanup_channel).with(channel)
|
77
78
|
channel.close
|
78
79
|
|
80
|
+
channel.process
|
81
|
+
|
79
82
|
assert channel.closing?
|
80
83
|
end
|
81
84
|
|
@@ -117,14 +117,14 @@ module Connection
|
|
117
117
|
end
|
118
118
|
|
119
119
|
def test_process_should_exit_after_processing_if_block_is_true_then_false
|
120
|
-
session.channels[0] = stub("channel", :
|
120
|
+
session.channels[0] = stub("channel", :local_closed? => false)
|
121
121
|
session.channels[0].expects(:process)
|
122
122
|
IO.expects(:select).never
|
123
123
|
process_times(2)
|
124
124
|
end
|
125
125
|
|
126
126
|
def test_process_should_not_process_channels_that_are_closing
|
127
|
-
session.channels[0] = stub("channel", :
|
127
|
+
session.channels[0] = stub("channel", :local_closed? => true)
|
128
128
|
session.channels[0].expects(:process).never
|
129
129
|
IO.expects(:select).never
|
130
130
|
process_times(2)
|
@@ -299,8 +299,17 @@ module Connection
|
|
299
299
|
end
|
300
300
|
|
301
301
|
def test_channel_close_packet_should_be_routed_to_corresponding_channel_and_channel_should_be_closed_and_removed
|
302
|
-
|
303
|
-
|
302
|
+
session.channels[14] = stub("channel") do
|
303
|
+
# this simulates the case where we closed the channel first, sent
|
304
|
+
# CHANNEL_CLOSE to server and are waiting for server's response.
|
305
|
+
expects(:local_closed?).returns(true)
|
306
|
+
expects(:do_close)
|
307
|
+
expects(:close).with()
|
308
|
+
expects(:remote_closed!).with()
|
309
|
+
expects(:remote_closed?).with().returns(true)
|
310
|
+
expects(:local_id).returns(14)
|
311
|
+
end
|
312
|
+
|
304
313
|
transport.return(CHANNEL_CLOSE, :long, 14)
|
305
314
|
process_times(2)
|
306
315
|
assert session.channels.empty?
|
@@ -526,7 +535,7 @@ module Connection
|
|
526
535
|
end
|
527
536
|
|
528
537
|
def channel_at(local_id)
|
529
|
-
session.channels[local_id] = stub("channel", :process => true, :
|
538
|
+
session.channels[local_id] = stub("channel", :process => true, :local_closed? => false)
|
530
539
|
end
|
531
540
|
|
532
541
|
def transport(options={})
|
data/test/integration/README.txt
CHANGED
data/test/integration/common.rb
CHANGED
@@ -14,6 +14,12 @@ module IntegrationTestHelpers
|
|
14
14
|
raise "Command: #{command} failed:#{status.exitstatus}" unless res
|
15
15
|
end
|
16
16
|
|
17
|
+
def tmpdir(&block)
|
18
|
+
Dir.mktmpdir do |dir|
|
19
|
+
yield(dir)
|
20
|
+
end
|
21
|
+
end
|
22
|
+
|
17
23
|
def set_authorized_key(user,pubkey)
|
18
24
|
authorized_key = "/home/#{user}/.ssh/authorized_keys"
|
19
25
|
sh "sudo cp #{pubkey} #{authorized_key}"
|
@@ -34,6 +34,14 @@
|
|
34
34
|
- name: sshd debug
|
35
35
|
lineinfile: dest='/etc/ssh/sshd_config' line='LogLevel DEBUG' regexp=LogLevel
|
36
36
|
notify: restart sshd
|
37
|
+
- name: put NET_SSH_RUN_INTEGRATION_TESTS=YES environment
|
38
|
+
lineinfile: dest='/etc/environment' line='NET_SSH_RUN_INTEGRATION_TESTS=YES'
|
39
|
+
- name: change dir in bashrc
|
40
|
+
lineinfile: dest=/home/vagrant/.bashrc owner=vagrant mode=0644
|
41
|
+
regexp='^cd ' line='cd /net-ssh'
|
42
|
+
- apt: name="{{item}}" state=present
|
43
|
+
with_items:
|
44
|
+
- pv
|
37
45
|
- gem: name="{{item}}" state=present executable=/usr/local/rvm/rubies/ruby-{{ruby_version}}/bin/gem
|
38
46
|
with_items:
|
39
47
|
- byebug
|