net-ssh 2.9.1 → 2.9.2
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 +7 -0
- checksums.yaml.gz.sig +0 -0
- data/CHANGES.txt +17 -0
- data/README.rdoc +5 -0
- data/Rakefile +17 -4
- data/lib/net/ssh/authentication/agent/socket.rb +10 -4
- data/lib/net/ssh/authentication/methods/password.rb +35 -10
- data/lib/net/ssh/buffer.rb +1 -1
- data/lib/net/ssh/config.rb +4 -2
- data/lib/net/ssh/connection/channel.rb +1 -1
- data/lib/net/ssh/connection/keepalive.rb +55 -0
- data/lib/net/ssh/connection/session.rb +5 -23
- data/lib/net/ssh/errors.rb +4 -0
- data/lib/net/ssh/known_hosts.rb +2 -10
- data/lib/net/ssh/service/forward.rb +52 -12
- data/lib/net/ssh/transport/algorithms.rb +11 -11
- data/lib/net/ssh/transport/cipher_factory.rb +0 -3
- data/lib/net/ssh/transport/packet_stream.rb +3 -1
- data/lib/net/ssh/transport/session.rb +7 -2
- data/lib/net/ssh/version.rb +11 -7
- data/lib/net/ssh.rb +10 -5
- data/net-ssh-public_cert.pem +20 -0
- data/net-ssh.gemspec +11 -9
- data/test/authentication/methods/test_password.rb +43 -0
- data/test/authentication/test_agent.rb +19 -0
- data/test/connection/test_session.rb +19 -2
- data/test/manual/test_forward.rb +76 -27
- data/test/start/test_options.rb +7 -0
- data/test/test_config.rb +3 -1
- data/test/transport/test_algorithms.rb +40 -45
- data/test/transport/test_packet_stream.rb +7 -1
- data/test/transport/test_session.rb +12 -0
- data.tar.gz.sig +0 -0
- metadata +39 -50
- metadata.gz.sig +0 -0
- data/gem-public_cert.pem +0 -20
data/lib/net/ssh.rb
CHANGED
|
@@ -63,12 +63,12 @@ module Net
|
|
|
63
63
|
VALID_OPTIONS = [
|
|
64
64
|
:auth_methods, :bind_address, :compression, :compression_level, :config,
|
|
65
65
|
:encryption, :forward_agent, :hmac, :host_key,
|
|
66
|
-
:keepalive, :keepalive_interval, :kex, :keys, :key_data,
|
|
66
|
+
:keepalive, :keepalive_interval, :keepalive_maxcount, :kex, :keys, :key_data,
|
|
67
67
|
:languages, :logger, :paranoid, :password, :port, :proxy,
|
|
68
68
|
:rekey_blocks_limit,:rekey_limit, :rekey_packet_limit, :timeout, :verbose,
|
|
69
69
|
:global_known_hosts_file, :user_known_hosts_file, :host_key_alias,
|
|
70
70
|
:host_name, :user, :properties, :passphrase, :keys_only, :max_pkt_size,
|
|
71
|
-
:max_win_size, :send_env, :use_agent
|
|
71
|
+
:max_win_size, :send_env, :use_agent, :number_of_password_prompts
|
|
72
72
|
]
|
|
73
73
|
|
|
74
74
|
# The standard means of starting a new SSH connection. When used with a
|
|
@@ -125,11 +125,12 @@ module Net
|
|
|
125
125
|
# specified in an SSH configuration file. It lets you specify an
|
|
126
126
|
# "alias", similarly to adding an entry in /etc/hosts but without needing
|
|
127
127
|
# to modify /etc/hosts.
|
|
128
|
-
#
|
|
128
|
+
# * :keepalive => set to +true+ to send a keepalive packet to the SSH server
|
|
129
129
|
# when there's no traffic between the SSH server and Net::SSH client for
|
|
130
130
|
# the keepalive_interval seconds. Defaults to +false+.
|
|
131
|
-
#
|
|
131
|
+
# * :keepalive_interval => the interval seconds for keepalive.
|
|
132
132
|
# Defaults to +300+ seconds.
|
|
133
|
+
# * :keepalive_maxcount => the maximun number of keepalive packet miss allowed.
|
|
133
134
|
# * :kex => the key exchange algorithm (or algorithms) to use
|
|
134
135
|
# * :keys => an array of file names of private keys to use for publickey
|
|
135
136
|
# and hostbased authentication
|
|
@@ -146,7 +147,11 @@ module Net
|
|
|
146
147
|
# * :max_win_size => maximum size we tell the other side that is supported for
|
|
147
148
|
# the window.
|
|
148
149
|
# * :paranoid => either false, true, :very, or :secure specifying how
|
|
149
|
-
# strict host-key verification should be (in increasing order here)
|
|
150
|
+
# strict host-key verification should be (in increasing order here).
|
|
151
|
+
# You can also provide an own Object which responds to +verify+. The argument
|
|
152
|
+
# given to +verify+ is a hash consisting of the +:key+, the +:key_blob+,
|
|
153
|
+
# the +:fingerprint+ and the +:session+. Returning true accepts the host key,
|
|
154
|
+
# returning false declines it and closes the connection.
|
|
150
155
|
# * :passphrase => the passphrase to use when loading a private key (default
|
|
151
156
|
# is +nil+, for no passphrase)
|
|
152
157
|
# * :password => the password to use to login
|
|
@@ -0,0 +1,20 @@
|
|
|
1
|
+
-----BEGIN CERTIFICATE-----
|
|
2
|
+
MIIDODCCAiCgAwIBAgIBADANBgkqhkiG9w0BAQUFADBCMRAwDgYDVQQDDAduZXQt
|
|
3
|
+
c3NoMRkwFwYKCZImiZPyLGQBGRYJc29sdXRpb3VzMRMwEQYKCZImiZPyLGQBGRYD
|
|
4
|
+
Y29tMB4XDTE0MTIwMjE3MzkyMFoXDTE1MTIwMjE3MzkyMFowQjEQMA4GA1UEAwwH
|
|
5
|
+
bmV0LXNzaDEZMBcGCgmSJomT8ixkARkWCXNvbHV0aW91czETMBEGCgmSJomT8ixk
|
|
6
|
+
ARkWA2NvbTCCASIwDQYJKoZIhvcNAQEBBQADggEPADCCAQoCggEBAJ0qnw4JV5JN
|
|
7
|
+
MWelqu7pnW2z6GZJ7+zLFYJQNETJyF0U5zo7aCRK08OeUxnpu/TCCXK8iQVkNLfz
|
|
8
|
+
9pVIhF+X8pMEIruAkYGwBt1aWfuSNeyodyMk0vpZdxBHbOTJ4qBRUc6qOtNOeOzv
|
|
9
|
+
8ObYUX52P/EMMaeXTRU+e7MGkB9pb6FvPPNx5akxwIaoRvtcMsc/hJnQuP5r96w6
|
|
10
|
+
t06MgKbXhWAX6gev0RVlrQqzxXst6iuvsrgZGjFqzob5wbTiX9M0+bFAB0EI7tJC
|
|
11
|
+
sv5keEbtNRaU7p3ZbMm4wTHHJLOtD+BpUCSzwv4ToNj9mZtJBMYw2Eeo7z1DklEG
|
|
12
|
+
mr95zbe+zNMCAwEAAaM5MDcwCQYDVR0TBAIwADAdBgNVHQ4EFgQU1bTfpzmitXwv
|
|
13
|
+
LmTXi0IO5vd8NGYwCwYDVR0PBAQDAgSwMA0GCSqGSIb3DQEBBQUAA4IBAQA0Aps8
|
|
14
|
+
UPINGa8XUUtrZtzrgX0/iyXNkKY1ld85g1N3WKEAVLfQI7TlGr0Qv2Ekx6RqlxbR
|
|
15
|
+
Vyq08pytSnghW2otR3bIGMGQzqxAeRLb25cjEwH7YIJ32n7ZC1fpMnBZOBDmueWA
|
|
16
|
+
B9EonmoO3ne7AJSgIvBbZzBPhzM4HrQGRW8LsPFsuj+dcJI43HOQwkmv2TRz0+t6
|
|
17
|
+
mGZldmqLcK0abv4JepLfB9XTue3kuyA29NGBibqyvRwlKckLpvKfHZX6Jxad8xxm
|
|
18
|
+
MbvRpzgROzyfw1qYi4dnIyMwTtXFFcZ0a2jpxHPkcTYFK6TzvFgDLAP0Y/u9jqUQ
|
|
19
|
+
eZ7/3CdSi/isZHEw
|
|
20
|
+
-----END CERTIFICATE-----
|
data/net-ssh.gemspec
CHANGED
|
@@ -2,15 +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 2.9.2 ruby lib
|
|
5
6
|
|
|
6
7
|
Gem::Specification.new do |s|
|
|
7
8
|
s.name = "net-ssh"
|
|
8
|
-
s.version = "2.9.
|
|
9
|
+
s.version = "2.9.2"
|
|
9
10
|
|
|
10
11
|
s.required_rubygems_version = Gem::Requirement.new(">= 0") if s.respond_to? :required_rubygems_version=
|
|
11
|
-
s.
|
|
12
|
-
s.
|
|
13
|
-
s.
|
|
12
|
+
s.require_paths = ["lib"]
|
|
13
|
+
s.authors = ["Jamis Buck", "Delano Mandelbaum", "Mikl\u{f3}s Fazekas"]
|
|
14
|
+
s.cert_chain = ["net-ssh-public_cert.pem"]
|
|
15
|
+
s.date = "2015-01-09"
|
|
14
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."
|
|
15
17
|
s.email = "net-ssh@solutious.com"
|
|
16
18
|
s.extra_rdoc_files = [
|
|
@@ -26,7 +28,6 @@ Gem::Specification.new do |s|
|
|
|
26
28
|
"Rakefile",
|
|
27
29
|
"Rudyfile",
|
|
28
30
|
"THANKS.txt",
|
|
29
|
-
"gem-public_cert.pem",
|
|
30
31
|
"lib/net/ssh.rb",
|
|
31
32
|
"lib/net/ssh/authentication/agent.rb",
|
|
32
33
|
"lib/net/ssh/authentication/agent/java_pageant.rb",
|
|
@@ -46,6 +47,7 @@ Gem::Specification.new do |s|
|
|
|
46
47
|
"lib/net/ssh/config.rb",
|
|
47
48
|
"lib/net/ssh/connection/channel.rb",
|
|
48
49
|
"lib/net/ssh/connection/constants.rb",
|
|
50
|
+
"lib/net/ssh/connection/keepalive.rb",
|
|
49
51
|
"lib/net/ssh/connection/session.rb",
|
|
50
52
|
"lib/net/ssh/connection/term.rb",
|
|
51
53
|
"lib/net/ssh/errors.rb",
|
|
@@ -106,6 +108,7 @@ Gem::Specification.new do |s|
|
|
|
106
108
|
"lib/net/ssh/verifiers/secure.rb",
|
|
107
109
|
"lib/net/ssh/verifiers/strict.rb",
|
|
108
110
|
"lib/net/ssh/version.rb",
|
|
111
|
+
"net-ssh-public_cert.pem",
|
|
109
112
|
"net-ssh.gemspec",
|
|
110
113
|
"setup.rb",
|
|
111
114
|
"support/arcfour_check.rb",
|
|
@@ -177,14 +180,13 @@ Gem::Specification.new do |s|
|
|
|
177
180
|
]
|
|
178
181
|
s.homepage = "https://github.com/net-ssh/net-ssh"
|
|
179
182
|
s.licenses = ["MIT"]
|
|
180
|
-
s.require_paths = ["lib"]
|
|
181
183
|
s.rubyforge_project = "net-ssh"
|
|
182
|
-
s.rubygems_version = "
|
|
183
|
-
s.signing_key = "/mnt/gem/
|
|
184
|
+
s.rubygems_version = "2.2.2"
|
|
185
|
+
s.signing_key = "/mnt/gem/net-ssh-private_key.pem"
|
|
184
186
|
s.summary = "Net::SSH: a pure-Ruby implementation of the SSH2 client protocol."
|
|
185
187
|
|
|
186
188
|
if s.respond_to? :specification_version then
|
|
187
|
-
s.specification_version =
|
|
189
|
+
s.specification_version = 4
|
|
188
190
|
|
|
189
191
|
if Gem::Version.new(Gem::VERSION) >= Gem::Version.new('1.2.0') then
|
|
190
192
|
s.add_development_dependency(%q<test-unit>, [">= 0"])
|
|
@@ -1,7 +1,9 @@
|
|
|
1
1
|
require 'common'
|
|
2
2
|
require 'net/ssh/authentication/methods/password'
|
|
3
|
+
require 'net/ssh/authentication/session'
|
|
3
4
|
require 'authentication/methods/common'
|
|
4
5
|
|
|
6
|
+
|
|
5
7
|
module Authentication; module Methods
|
|
6
8
|
|
|
7
9
|
class TestPassword < Test::Unit::TestCase
|
|
@@ -24,6 +26,47 @@ module Authentication; module Methods
|
|
|
24
26
|
end
|
|
25
27
|
end
|
|
26
28
|
|
|
29
|
+
def test_authenticate_ask_for_password_for_second_time_when_password_is_incorrect
|
|
30
|
+
transport.expect do |t,packet|
|
|
31
|
+
assert_equal USERAUTH_REQUEST, packet.type
|
|
32
|
+
assert_equal "jamis", packet.read_string
|
|
33
|
+
assert_equal "ssh-connection", packet.read_string
|
|
34
|
+
assert_equal "password", packet.read_string
|
|
35
|
+
assert_equal false, packet.read_bool
|
|
36
|
+
assert_equal "the-password", packet.read_string
|
|
37
|
+
t.return(USERAUTH_FAILURE, :string, "publickey,password")
|
|
38
|
+
|
|
39
|
+
t.expect do |t2, packet2|
|
|
40
|
+
assert_equal USERAUTH_REQUEST, packet2.type
|
|
41
|
+
assert_equal "jamis", packet2.read_string
|
|
42
|
+
assert_equal "ssh-connection", packet2.read_string
|
|
43
|
+
assert_equal "password", packet2.read_string
|
|
44
|
+
assert_equal false, packet2.read_bool
|
|
45
|
+
assert_equal "the-password-2", packet2.read_string
|
|
46
|
+
t.return(USERAUTH_SUCCESS)
|
|
47
|
+
end
|
|
48
|
+
end
|
|
49
|
+
|
|
50
|
+
subject.expects(:prompt).with("jamis@'s password:", false).returns("the-password-2")
|
|
51
|
+
subject.authenticate("ssh-connection", "jamis", "the-password")
|
|
52
|
+
end
|
|
53
|
+
|
|
54
|
+
def test_authenticate_ask_for_password_if_not_given
|
|
55
|
+
transport.expect do |t,packet|
|
|
56
|
+
assert_equal USERAUTH_REQUEST, packet.type
|
|
57
|
+
assert_equal "bill", packet.read_string
|
|
58
|
+
assert_equal "ssh-connection", packet.read_string
|
|
59
|
+
assert_equal "password", packet.read_string
|
|
60
|
+
assert_equal false, packet.read_bool
|
|
61
|
+
assert_equal "good-password", packet.read_string
|
|
62
|
+
t.return(USERAUTH_SUCCESS)
|
|
63
|
+
end
|
|
64
|
+
|
|
65
|
+
transport.instance_eval { @host='testhost' }
|
|
66
|
+
subject.expects(:prompt).with("bill@testhost's password:", false).returns("good-password")
|
|
67
|
+
subject.authenticate("ssh-connection", "bill", nil)
|
|
68
|
+
end
|
|
69
|
+
|
|
27
70
|
def test_authenticate_when_password_is_acceptible_should_return_true
|
|
28
71
|
transport.expect do |t,packet|
|
|
29
72
|
assert_equal USERAUTH_REQUEST, packet.type
|
|
@@ -110,6 +110,25 @@ module Authentication
|
|
|
110
110
|
assert_equal "Okay, but not the best", result.last.comment
|
|
111
111
|
end
|
|
112
112
|
|
|
113
|
+
def test_identities_should_ignore_unimplemented_ones
|
|
114
|
+
key1 = key
|
|
115
|
+
key2 = OpenSSL::PKey::DSA.new(512)
|
|
116
|
+
key2.to_blob[0..5]='badkey'
|
|
117
|
+
key3 = OpenSSL::PKey::DSA.new(512)
|
|
118
|
+
|
|
119
|
+
socket.expect do |s, type, buffer|
|
|
120
|
+
assert_equal SSH2_AGENT_REQUEST_IDENTITIES, type
|
|
121
|
+
s.return(SSH2_AGENT_IDENTITIES_ANSWER, :long, 3, :string, Net::SSH::Buffer.from(:key, key1), :string, "My favorite key", :string, Net::SSH::Buffer.from(:key, key2), :string, "bad", :string, Net::SSH::Buffer.from(:key, key3), :string, "Okay, but not the best")
|
|
122
|
+
end
|
|
123
|
+
|
|
124
|
+
result = agent.identities
|
|
125
|
+
assert_equal 2,result.size
|
|
126
|
+
assert_equal key1.to_blob, result.first.to_blob
|
|
127
|
+
assert_equal key3.to_blob, result.last.to_blob
|
|
128
|
+
assert_equal "My favorite key", result.first.comment
|
|
129
|
+
assert_equal "Okay, but not the best", result.last.comment
|
|
130
|
+
end
|
|
131
|
+
|
|
113
132
|
def test_close_should_close_socket
|
|
114
133
|
socket.expects(:close)
|
|
115
134
|
agent.close
|
|
@@ -366,12 +366,29 @@ module Connection
|
|
|
366
366
|
def test_process_should_call_enqueue_message_if_io_select_timed_out
|
|
367
367
|
timeout = Net::SSH::Connection::Session::DEFAULT_IO_SELECT_TIMEOUT
|
|
368
368
|
options = { :keepalive => true }
|
|
369
|
-
expected_packet = P(:byte, Net::SSH::Packet::
|
|
369
|
+
expected_packet = P(:byte, Net::SSH::Packet::GLOBAL_REQUEST, :string, "keepalive@openssh.com", :bool, true)
|
|
370
370
|
IO.stubs(:select).with([socket],[],nil,timeout).returns(nil)
|
|
371
|
-
transport.expects(:enqueue_message).with{ |msg| msg.content == expected_packet.content
|
|
371
|
+
transport.expects(:enqueue_message).with{ |msg| msg.content == expected_packet.content }
|
|
372
372
|
session(options).process
|
|
373
373
|
end
|
|
374
374
|
|
|
375
|
+
def test_process_should_raise_if_keepalives_not_answered
|
|
376
|
+
timeout = Net::SSH::Connection::Session::DEFAULT_IO_SELECT_TIMEOUT
|
|
377
|
+
options = { :keepalive => true, :keepalive_interval => 300, :keepalive_maxcount => 3 }
|
|
378
|
+
expected_packet = P(:byte, Net::SSH::Packet::GLOBAL_REQUEST, :string, "keepalive@openssh.com", :bool, true)
|
|
379
|
+
[1,2,3].each do |i|
|
|
380
|
+
Time.stubs(:now).returns(i*300)
|
|
381
|
+
IO.stubs(:select).with([socket],[],nil,timeout).returns(nil)
|
|
382
|
+
transport.expects(:enqueue_message).with{ |msg| msg.content == expected_packet.content }
|
|
383
|
+
session(options).process
|
|
384
|
+
end
|
|
385
|
+
|
|
386
|
+
Time.stubs(:now).returns(4*300)
|
|
387
|
+
IO.stubs(:select).with([socket],[],nil,timeout).returns(nil)
|
|
388
|
+
transport.expects(:enqueue_message).with{ |msg| msg.content == expected_packet.content }
|
|
389
|
+
assert_raises(Net::SSH::Timeout) { session(options).process }
|
|
390
|
+
end
|
|
391
|
+
|
|
375
392
|
def test_process_should_not_call_enqueue_message_unless_io_select_timed_out
|
|
376
393
|
timeout = Net::SSH::Connection::Session::DEFAULT_IO_SELECT_TIMEOUT
|
|
377
394
|
options = { :keepalive => true }
|
data/test/manual/test_forward.rb
CHANGED
|
@@ -3,15 +3,15 @@
|
|
|
3
3
|
# Tests for the following patch:
|
|
4
4
|
#
|
|
5
5
|
# http://github.com/net-ssh/net-ssh/tree/portfwfix
|
|
6
|
-
#
|
|
6
|
+
#
|
|
7
7
|
# It fixes 3 issues, regarding closing forwarded ports:
|
|
8
|
-
#
|
|
8
|
+
#
|
|
9
9
|
# 1.) if client closes a forwarded connection, but the server is reading, net-ssh terminates with IOError socket closed.
|
|
10
10
|
# 2.) if client force closes (RST) a forwarded connection, but server is reading, net-ssh terminates with
|
|
11
11
|
# 3.) if server closes the sending side, the on_eof is not handled.
|
|
12
|
-
#
|
|
12
|
+
#
|
|
13
13
|
# More info:
|
|
14
|
-
#
|
|
14
|
+
#
|
|
15
15
|
# http://net-ssh.lighthouseapp.com/projects/36253/tickets/7
|
|
16
16
|
|
|
17
17
|
require 'common'
|
|
@@ -21,26 +21,26 @@ require 'timeout'
|
|
|
21
21
|
require 'tempfile'
|
|
22
22
|
|
|
23
23
|
class TestForward < Test::Unit::TestCase
|
|
24
|
-
|
|
24
|
+
|
|
25
25
|
def localhost
|
|
26
26
|
'localhost'
|
|
27
27
|
end
|
|
28
|
-
|
|
28
|
+
|
|
29
29
|
def ssh_start_params
|
|
30
30
|
[localhost ,ENV['USER'], {:keys => "~/.ssh/id_rsa", :verbose => :debug}]
|
|
31
31
|
end
|
|
32
|
-
|
|
32
|
+
|
|
33
33
|
def start_server_sending_lot_of_data(exceptions)
|
|
34
34
|
server = TCPServer.open(0)
|
|
35
35
|
Thread.start do
|
|
36
36
|
loop do
|
|
37
37
|
Thread.start(server.accept) do |client|
|
|
38
38
|
begin
|
|
39
|
-
10000.times do |i|
|
|
39
|
+
10000.times do |i|
|
|
40
40
|
client.puts "item#{i}"
|
|
41
41
|
end
|
|
42
42
|
client.close
|
|
43
|
-
rescue
|
|
43
|
+
rescue
|
|
44
44
|
exceptions << $!
|
|
45
45
|
raise
|
|
46
46
|
end
|
|
@@ -49,14 +49,14 @@ class TestForward < Test::Unit::TestCase
|
|
|
49
49
|
end
|
|
50
50
|
return server
|
|
51
51
|
end
|
|
52
|
-
|
|
52
|
+
|
|
53
53
|
def start_server_closing_soon(exceptions=nil)
|
|
54
54
|
server = TCPServer.open(0)
|
|
55
55
|
Thread.start do
|
|
56
56
|
loop do
|
|
57
57
|
Thread.start(server.accept) do |client|
|
|
58
58
|
begin
|
|
59
|
-
client.recv(1024)
|
|
59
|
+
client.recv(1024)
|
|
60
60
|
client.setsockopt(Socket::SOL_SOCKET, Socket::SO_LINGER, [1, 0].pack("ii"))
|
|
61
61
|
client.close
|
|
62
62
|
rescue
|
|
@@ -68,20 +68,20 @@ class TestForward < Test::Unit::TestCase
|
|
|
68
68
|
end
|
|
69
69
|
return server
|
|
70
70
|
end
|
|
71
|
-
|
|
71
|
+
|
|
72
72
|
def test_local_ephemeral_port_should_work_correctly
|
|
73
73
|
session = Net::SSH.start(*ssh_start_params)
|
|
74
|
-
|
|
74
|
+
|
|
75
75
|
assert_nothing_raised do
|
|
76
76
|
assigned_port = session.forward.local(0, localhost, 22)
|
|
77
77
|
assert_not_nil assigned_port
|
|
78
78
|
assert_operator assigned_port, :>, 0
|
|
79
79
|
end
|
|
80
80
|
end
|
|
81
|
-
|
|
81
|
+
|
|
82
82
|
def test_remote_ephemeral_port_should_work_correctly
|
|
83
83
|
session = Net::SSH.start(*ssh_start_params)
|
|
84
|
-
|
|
84
|
+
|
|
85
85
|
assert_nothing_raised do
|
|
86
86
|
session.forward.remote(22, localhost, 0, localhost)
|
|
87
87
|
session.loop { !(session.forward.active_remotes.length > 0) }
|
|
@@ -90,9 +90,58 @@ class TestForward < Test::Unit::TestCase
|
|
|
90
90
|
assert_operator assigned_port, :>, 0
|
|
91
91
|
end
|
|
92
92
|
end
|
|
93
|
-
|
|
93
|
+
|
|
94
|
+
def test_remote_callback_should_fire
|
|
95
|
+
session = Net::SSH.start(*ssh_start_params)
|
|
96
|
+
|
|
97
|
+
assert_nothing_raised do
|
|
98
|
+
got_port = nil
|
|
99
|
+
session.forward.remote(22, localhost, 0, localhost) do |port|
|
|
100
|
+
got_port = port
|
|
101
|
+
end
|
|
102
|
+
session.loop { !(session.forward.active_remotes.length > 0) }
|
|
103
|
+
assert_operator session.forward.active_remote_destinations.length, :==, 1
|
|
104
|
+
assert_operator session.forward.active_remote_destinations.keys.first, :==, [ 22, localhost ]
|
|
105
|
+
assert_operator session.forward.active_remote_destinations.values.first, :==, [ got_port, localhost ]
|
|
106
|
+
assert_operator session.forward.active_remotes.first, :==, [ got_port, localhost ]
|
|
107
|
+
assigned_port = session.forward.active_remotes.first[0]
|
|
108
|
+
assert_operator got_port, :==, assigned_port
|
|
109
|
+
assert_not_nil assigned_port
|
|
110
|
+
assert_operator assigned_port, :>, 0
|
|
111
|
+
end
|
|
112
|
+
end
|
|
113
|
+
|
|
114
|
+
def test_remote_callback_should_fire_on_error_and_still_throw_exception
|
|
115
|
+
session = Net::SSH.start(*ssh_start_params)
|
|
116
|
+
|
|
117
|
+
assert_nothing_raised do
|
|
118
|
+
session.forward.remote(22, localhost, 22, localhost) do |port|
|
|
119
|
+
assert_operator port, :==, :error
|
|
120
|
+
end
|
|
121
|
+
end
|
|
122
|
+
assert_raises(Net::SSH::Exception) do
|
|
123
|
+
session.loop { true }
|
|
124
|
+
end
|
|
125
|
+
end
|
|
126
|
+
|
|
127
|
+
def test_remote_callback_should_fire_on_error_but_not_throw_exception_if_asked_not_to
|
|
128
|
+
session = Net::SSH.start(*ssh_start_params)
|
|
129
|
+
|
|
130
|
+
assert_nothing_raised do
|
|
131
|
+
got_port = nil
|
|
132
|
+
session.forward.remote(22, localhost, 22, localhost) do |port|
|
|
133
|
+
assert_operator port, :==, :error
|
|
134
|
+
got_port = port
|
|
135
|
+
:no_exception
|
|
136
|
+
end
|
|
137
|
+
session.loop { !got_port }
|
|
138
|
+
assert_operator port, :==, :error
|
|
139
|
+
assert_operator session.forward.active_remotes.length, :==, 0
|
|
140
|
+
end
|
|
141
|
+
end
|
|
142
|
+
|
|
94
143
|
def test_loop_should_not_abort_when_local_side_of_forward_is_closed
|
|
95
|
-
session = Net::SSH.start(*ssh_start_params)
|
|
144
|
+
session = Net::SSH.start(*ssh_start_params)
|
|
96
145
|
server_exc = Queue.new
|
|
97
146
|
server = start_server_sending_lot_of_data(server_exc)
|
|
98
147
|
remote_port = server.addr[1]
|
|
@@ -112,10 +161,10 @@ class TestForward < Test::Unit::TestCase
|
|
|
112
161
|
session.loop(0.1) { client_done.empty? }
|
|
113
162
|
assert_equal "Broken pipe", "#{server_exc.pop}" unless server_exc.empty?
|
|
114
163
|
end
|
|
115
|
-
|
|
164
|
+
|
|
116
165
|
def test_loop_should_not_abort_when_local_side_of_forward_is_reset
|
|
117
166
|
session = Net::SSH.start(*ssh_start_params)
|
|
118
|
-
server_exc = Queue.new
|
|
167
|
+
server_exc = Queue.new
|
|
119
168
|
server = start_server_sending_lot_of_data(server_exc)
|
|
120
169
|
remote_port = server.addr[1]
|
|
121
170
|
local_port = 0 # request ephemeral port
|
|
@@ -143,9 +192,9 @@ class TestForward < Test::Unit::TestCase
|
|
|
143
192
|
yield UNIXServer.open(path)
|
|
144
193
|
File.delete(path)
|
|
145
194
|
end if defined?(UNIXServer)
|
|
146
|
-
|
|
195
|
+
|
|
147
196
|
def test_forward_local_unix_socket_to_remote_port
|
|
148
|
-
session = Net::SSH.start(*ssh_start_params)
|
|
197
|
+
session = Net::SSH.start(*ssh_start_params)
|
|
149
198
|
server_exc = Queue.new
|
|
150
199
|
server = start_server_sending_lot_of_data(server_exc)
|
|
151
200
|
remote_port = server.addr[1]
|
|
@@ -174,7 +223,7 @@ class TestForward < Test::Unit::TestCase
|
|
|
174
223
|
end if defined?(UNIXSocket)
|
|
175
224
|
|
|
176
225
|
def test_loop_should_not_abort_when_server_side_of_forward_is_closed
|
|
177
|
-
session = Net::SSH.start(*ssh_start_params)
|
|
226
|
+
session = Net::SSH.start(*ssh_start_params)
|
|
178
227
|
server = start_server_closing_soon
|
|
179
228
|
remote_port = server.addr[1]
|
|
180
229
|
local_port = 0 # request ephemeral port
|
|
@@ -183,18 +232,18 @@ class TestForward < Test::Unit::TestCase
|
|
|
183
232
|
Thread.start do
|
|
184
233
|
begin
|
|
185
234
|
client = TCPSocket.new(localhost, local_port)
|
|
186
|
-
1.times do |i|
|
|
235
|
+
1.times do |i|
|
|
187
236
|
client.puts "item#{i}"
|
|
188
237
|
end
|
|
189
238
|
client.close
|
|
190
239
|
sleep(0.1)
|
|
191
|
-
ensure
|
|
240
|
+
ensure
|
|
192
241
|
client_done << true
|
|
193
242
|
end
|
|
194
243
|
end
|
|
195
244
|
session.loop(0.1) { client_done.empty? }
|
|
196
245
|
end
|
|
197
|
-
|
|
246
|
+
|
|
198
247
|
def start_server
|
|
199
248
|
server = TCPServer.open(0)
|
|
200
249
|
Thread.start do
|
|
@@ -206,9 +255,9 @@ class TestForward < Test::Unit::TestCase
|
|
|
206
255
|
end
|
|
207
256
|
return server
|
|
208
257
|
end
|
|
209
|
-
|
|
258
|
+
|
|
210
259
|
def test_server_eof_should_be_handled
|
|
211
|
-
session = Net::SSH.start(*ssh_start_params)
|
|
260
|
+
session = Net::SSH.start(*ssh_start_params)
|
|
212
261
|
server = start_server do |client|
|
|
213
262
|
client.write "This is a small message!"
|
|
214
263
|
client.close
|
data/test/start/test_options.rb
CHANGED
|
@@ -31,6 +31,13 @@ module NetSSH
|
|
|
31
31
|
Net::SSH.start('localhost', 'testuser', options)
|
|
32
32
|
end
|
|
33
33
|
end
|
|
34
|
+
|
|
35
|
+
def test_star_should_accept_number_of_password_prompts_option
|
|
36
|
+
assert_nothing_raised do
|
|
37
|
+
options = { :number_of_password_prompts => 2 }
|
|
38
|
+
Net::SSH.start('localhost', 'testuser', options)
|
|
39
|
+
end
|
|
40
|
+
end
|
|
34
41
|
end
|
|
35
42
|
end
|
|
36
43
|
|
data/test/test_config.rb
CHANGED
|
@@ -93,7 +93,8 @@ class TestConfig < Test::Unit::TestCase
|
|
|
93
93
|
'port' => 1234,
|
|
94
94
|
'pubkeyauthentication' => true,
|
|
95
95
|
'rekeylimit' => 1024,
|
|
96
|
-
'sendenv' => "LC_*"
|
|
96
|
+
'sendenv' => "LC_*",
|
|
97
|
+
'numberofpasswordprompts' => '123'
|
|
97
98
|
}
|
|
98
99
|
|
|
99
100
|
net_ssh = Net::SSH::Config.translate(open_ssh)
|
|
@@ -111,6 +112,7 @@ class TestConfig < Test::Unit::TestCase
|
|
|
111
112
|
assert_equal 1024, net_ssh[:rekey_limit]
|
|
112
113
|
assert_equal "127.0.0.1", net_ssh[:bind_address]
|
|
113
114
|
assert_equal [/^LC_.*$/], net_ssh[:send_env]
|
|
115
|
+
assert_equal 123, net_ssh[:number_of_password_prompts]
|
|
114
116
|
end
|
|
115
117
|
|
|
116
118
|
def test_translate_should_turn_off_authentication_methods
|