net-ssh 4.0.0.alpha1 → 4.0.0.alpha2

Sign up to get free protection for your applications and to get access to all the features.
Files changed (91) hide show
  1. checksums.yaml +4 -4
  2. checksums.yaml.gz.sig +0 -0
  3. data.tar.gz.sig +0 -0
  4. data/.gitignore +6 -0
  5. data/.travis.yml +10 -7
  6. data/CHANGES.txt +4 -0
  7. data/Gemfile +2 -15
  8. data/README.rdoc +6 -37
  9. data/Rakefile +5 -57
  10. data/lib/net/ssh/connection/session.rb +13 -0
  11. data/lib/net/ssh/ruby_compat.rb +2 -24
  12. data/lib/net/ssh/version.rb +1 -1
  13. data/net-ssh.gemspec +34 -225
  14. metadata +26 -100
  15. metadata.gz.sig +0 -0
  16. data/test/README.txt +0 -18
  17. data/test/authentication/methods/common.rb +0 -28
  18. data/test/authentication/methods/test_abstract.rb +0 -51
  19. data/test/authentication/methods/test_hostbased.rb +0 -114
  20. data/test/authentication/methods/test_keyboard_interactive.rb +0 -121
  21. data/test/authentication/methods/test_none.rb +0 -41
  22. data/test/authentication/methods/test_password.rb +0 -95
  23. data/test/authentication/methods/test_publickey.rb +0 -148
  24. data/test/authentication/test_agent.rb +0 -224
  25. data/test/authentication/test_ed25519.rb +0 -77
  26. data/test/authentication/test_key_manager.rb +0 -240
  27. data/test/authentication/test_session.rb +0 -107
  28. data/test/common.rb +0 -109
  29. data/test/configs/auth_off +0 -5
  30. data/test/configs/auth_on +0 -4
  31. data/test/configs/empty +0 -0
  32. data/test/configs/eqsign +0 -3
  33. data/test/configs/exact_match +0 -8
  34. data/test/configs/host_plus +0 -10
  35. data/test/configs/multihost +0 -4
  36. data/test/configs/negative_match +0 -6
  37. data/test/configs/nohost +0 -19
  38. data/test/configs/numeric_host +0 -4
  39. data/test/configs/proxy_remote_user +0 -2
  40. data/test/configs/send_env +0 -2
  41. data/test/configs/substitutes +0 -8
  42. data/test/configs/wild_cards +0 -14
  43. data/test/connection/test_channel.rb +0 -487
  44. data/test/connection/test_session.rb +0 -563
  45. data/test/integration/README.md +0 -18
  46. data/test/integration/Vagrantfile +0 -12
  47. data/test/integration/common.rb +0 -65
  48. data/test/integration/playbook.yml +0 -57
  49. data/test/integration/test_ed25519_pkeys.rb +0 -70
  50. data/test/integration/test_forward.rb +0 -532
  51. data/test/integration/test_id_rsa_keys.rb +0 -96
  52. data/test/integration/test_proxy.rb +0 -93
  53. data/test/known_hosts/github +0 -1
  54. data/test/known_hosts/github_hash +0 -1
  55. data/test/manual/test_pageant.rb +0 -37
  56. data/test/start/test_connection.rb +0 -53
  57. data/test/start/test_options.rb +0 -57
  58. data/test/start/test_transport.rb +0 -28
  59. data/test/start/test_user_nil.rb +0 -27
  60. data/test/test_all.rb +0 -12
  61. data/test/test_buffer.rb +0 -433
  62. data/test/test_buffered_io.rb +0 -63
  63. data/test/test_config.rb +0 -268
  64. data/test/test_key_factory.rb +0 -191
  65. data/test/test_known_hosts.rb +0 -66
  66. data/test/transport/hmac/test_md5.rb +0 -41
  67. data/test/transport/hmac/test_md5_96.rb +0 -27
  68. data/test/transport/hmac/test_none.rb +0 -34
  69. data/test/transport/hmac/test_ripemd160.rb +0 -36
  70. data/test/transport/hmac/test_sha1.rb +0 -36
  71. data/test/transport/hmac/test_sha1_96.rb +0 -27
  72. data/test/transport/hmac/test_sha2_256.rb +0 -37
  73. data/test/transport/hmac/test_sha2_256_96.rb +0 -27
  74. data/test/transport/hmac/test_sha2_512.rb +0 -37
  75. data/test/transport/hmac/test_sha2_512_96.rb +0 -27
  76. data/test/transport/kex/test_diffie_hellman_group14_sha1.rb +0 -13
  77. data/test/transport/kex/test_diffie_hellman_group1_sha1.rb +0 -150
  78. data/test/transport/kex/test_diffie_hellman_group_exchange_sha1.rb +0 -96
  79. data/test/transport/kex/test_diffie_hellman_group_exchange_sha256.rb +0 -19
  80. data/test/transport/kex/test_ecdh_sha2_nistp256.rb +0 -161
  81. data/test/transport/kex/test_ecdh_sha2_nistp384.rb +0 -38
  82. data/test/transport/kex/test_ecdh_sha2_nistp521.rb +0 -38
  83. data/test/transport/test_algorithms.rb +0 -328
  84. data/test/transport/test_cipher_factory.rb +0 -324
  85. data/test/transport/test_hmac.rb +0 -34
  86. data/test/transport/test_identity_cipher.rb +0 -40
  87. data/test/transport/test_packet_stream.rb +0 -1186
  88. data/test/transport/test_server_version.rb +0 -74
  89. data/test/transport/test_session.rb +0 -331
  90. data/test/transport/test_state.rb +0 -181
  91. data/test/verifiers/test_secure.rb +0 -40
@@ -1,18 +0,0 @@
1
- # Integration tests with vagrant
2
-
3
- Requirements:
4
-
5
- * Vagrant (https://www.vagrantup.com/)
6
- * Ansible (http://docs.ansible.com/intro_installation.html)
7
-
8
- Setup:
9
-
10
- ansible-galaxy install rvm_io.rvm1-ruby
11
- vagrant up ; vagrant ssh
12
- rvm all do bundle
13
- rvm all do rake test
14
-
15
- # TODO
16
-
17
- * get it running on ci (probalby needs docker)
18
- * could not get gem install jeweler to work
@@ -1,12 +0,0 @@
1
- VAGRANTFILE_API_VERSION = "2"
2
-
3
- Vagrant.configure(VAGRANTFILE_API_VERSION) do |config|
4
- config.vm.box = "ubuntu/trusty64"
5
- config.vm.provision "ansible" do |ansible|
6
- ansible.playbook = "./playbook.yml"
7
- ansible.sudo = true
8
- ansible.verbose ='vvvv'
9
- end
10
-
11
- config.vm.synced_folder "../..", "/net-ssh"
12
- end
@@ -1,65 +0,0 @@
1
- $LOAD_PATH.unshift "#{File.dirname(__FILE__)}/../../lib"
2
- gem "test-unit" # http://rubyforge.org/pipermail/test-unit-tracker/2009-July/000075.html
3
- gem 'mocha'
4
- require 'test/unit'
5
- require 'mocha/setup'
6
- require 'pty'
7
- require 'expect'
8
-
9
- module IntegrationTestHelpers
10
- VERBOSE = false
11
- def sh command
12
- puts "$ #{command}" if VERBOSE
13
- res = system(command)
14
- status = $?
15
- raise "Command: #{command} failed:#{status.exitstatus}" unless res
16
- end
17
-
18
- def tmpdir(&block)
19
- Dir.mktmpdir do |dir|
20
- yield(dir)
21
- end
22
- end
23
-
24
- def set_authorized_key(user,pubkey)
25
- authorized_key = "/home/#{user}/.ssh/authorized_keys"
26
- sh "sudo cp #{pubkey} #{authorized_key}"
27
- sh "sudo chown #{user} #{authorized_key}"
28
- sh "sudo chmod 0744 #{authorized_key}"
29
- end
30
-
31
- def with_agent(&block)
32
- puts "/usr/bin/ssh-agent -c" if VERBOSE
33
- agent_out = `/usr/bin/ssh-agent -c`
34
- agent_out.split("\n").each do |line|
35
- if line =~ /setenv (\S+) (\S+);/
36
- ENV[$1] = $2
37
- puts "ENV[#{$1}]=#{$2}" if VERBOSE
38
- end
39
- end
40
- begin
41
- yield
42
- ensure
43
- sh "/usr/bin/ssh-agent -k > /dev/null"
44
- end
45
- end
46
-
47
- def ssh_add(key,password)
48
- command = "ssh-add #{key}"
49
- status = nil
50
- PTY.spawn(command) do |reader, writer, pid|
51
- begin
52
- reader.expect(/Enter passphrase for .*:/) { |data| puts data }
53
- writer.puts(password)
54
- until reader.eof? do
55
- line = reader.readline
56
- puts line if VERBOSE
57
- end
58
- rescue Errno::EIO => _e
59
- end
60
- pid, status = Process.wait2 pid
61
- end
62
- raise "Command: #{command} failed:#{status.exitstatus}" unless status
63
- status.exitstatus
64
- end
65
- end
@@ -1,57 +0,0 @@
1
- ---
2
- - hosts: all
3
- sudo: yes
4
- vars:
5
- ruby_version: '2.0.0-p598'
6
- ruby_versions:
7
- - '2.0.0-p598'
8
- - '2.3.0'
9
- rvm_install_path: '/usr/local/rvm'
10
- foopwd: "$6$mhOzf/yapZwS$3RwDl4GfWZ5VcfcsHrK9xNNTxyzLOJBsmMttDNaegIbXxMahV86.v/5HsNtit16MEl0EFf5CSW8Dz2yXV.8GB0"
11
- foo2pwd: "$6$JiB7y7.M0yI$Abt.ZGIc4DwkRWeI6nKxzzPUZcux7hLRXSdpoKoZvswJz1SZyg5GRQWn9pGID0dgC6e4wFglfW6ev/qZoTqGk/"
12
- pre_tasks:
13
- - name: get currently installed ruby version
14
- command: "{{rvm_install_path}}/rubies/ruby-{{ruby_version}}/bin/ruby -e 'puts \"#{RUBY_VERSION}-p#{RUBY_PATCHLEVEL}\"'"
15
- register: current_ruby_version
16
- ignore_errors: True
17
- roles:
18
- - { role: rvm_io.rvm1-ruby,
19
- tags: ruby, sudo: True,
20
- rvm1_rubies: ["ruby-{{ruby_version}}","ruby-2.3.0"],
21
- rvm1_install_path: "{{rvm_install_path}}",
22
- rvm1_gpg_key_server: pool.sks-keyservers.net,
23
- when: "'{{current_ruby_version.stdout|default()}}' != '{{ruby_version}}'" }
24
- tasks:
25
- - user: name=net_ssh_1 password="{{foopwd}}" group=vagrant state=present
26
- - user: name=net_ssh_2 password="{{foo2pwd}}" group=vagrant state=present
27
- - file: dest=/home/net_ssh_1/.ssh/ state=directory mode=0740 owner=net_ssh_1
28
- - file: dest=/home/net_ssh_2/.ssh/ state=directory mode=0740 owner=net_ssh_2
29
- - lineinfile: dest=/etc/sudoers.d/net_ssh_1 mode=0440 state=present create=yes
30
- line='net_ssh_1 ALL=(ALL) NOPASSWD:ALL' regexp=net_ssh_1
31
- - lineinfile: dest=/etc/sudoers.d/net_ssh_1 mode=0440 state=present create=yes
32
- line='net_ssh_2 ALL=(ALL) NOPASSWD:ALL' regexp=net_ssh_2
33
- - command: ssh-keygen -A
34
- args:
35
- creates: /etc/ssh/ssh_host_ed25519_key
36
- notify: restart sshd
37
- - name: sshd debug
38
- lineinfile: dest='/etc/ssh/sshd_config' line='LogLevel DEBUG' regexp=LogLevel
39
- notify: restart sshd
40
- - name: put NET_SSH_RUN_INTEGRATION_TESTS=YES environment
41
- lineinfile: dest='/etc/environment' line='NET_SSH_RUN_INTEGRATION_TESTS=YES'
42
- - name: change dir in bashrc
43
- lineinfile: dest=/home/vagrant/.bashrc owner=vagrant mode=0644
44
- regexp='^cd ' line='cd /net-ssh'
45
- - apt: name="{{item}}" state=present
46
- with_items:
47
- - pv
48
- - libgmp3-dev
49
- - gem: name="{{ item[1] }}" state=present user_install=no executable=/usr/local/rvm/wrappers/ruby-{{ item[0] }}/gem
50
- with_nested:
51
- - "{{ruby_versions}}"
52
- - [ 'byebug', 'jeweler', 'mocha', 'rbnacl', 'rbnacl-libsodium' ]
53
- - copy: content='echo "cd /net-ssh ; rake integration-test"' dest=/etc/update-motd.d/99-net-ssh-tests mode=0755
54
- handlers:
55
- - name: restart sshd
56
- service: name=ssh state=restarted
57
-
@@ -1,70 +0,0 @@
1
- require_relative 'common'
2
- require 'fileutils'
3
- require 'tmpdir'
4
-
5
- require 'net/ssh'
6
-
7
- # see Vagrantfile,playbook for env.
8
- # we're running as net_ssh_1 user password foo
9
- # and usually connecting to net_ssh_2 user password foo2pwd
10
- class TestED25519PKeys < Test::Unit::TestCase
11
- include IntegrationTestHelpers
12
-
13
- def test_in_file_no_password
14
- Dir.mktmpdir do |dir|
15
- sh "rm -rf #{dir}/id_rsa_ed25519 #{dir}/id_rsa_ed25519.pub"
16
- sh "ssh-keygen -q -f #{dir}/id_rsa_ed25519 -t ed25519 -N ''"
17
- set_authorized_key('net_ssh_1',"#{dir}/id_rsa_ed25519.pub")
18
-
19
- # TODO: fix bug in net ssh which reads public key even if private key is there
20
- sh "mv #{dir}/id_rsa_ed25519.pub #{dir}/id_rsa_ed25519.pub.hidden"
21
-
22
- #sshopts = '-vvvv -o UserKnownHostsFile=/dev/null -o StrictHostKeyChecking=no'
23
- #sh "ssh -i #{dir}/id_rsa_ed25519 #{sshopts} net_ssh_1@localhost echo 'hello'"
24
-
25
- ret = Net::SSH.start("localhost", "net_ssh_1", {keys: "#{dir}/id_rsa_ed25519"}) do |ssh|
26
- ssh.exec! 'echo "hello from:$USER"'
27
- end
28
- assert_equal "hello from:net_ssh_1\n", ret
29
- end
30
- end
31
-
32
-
33
- def test_ssh_agent
34
- Dir.mktmpdir do |dir|
35
- with_agent do
36
- sh "rm -rf #{dir}/id_rsa_ed25519 #{dir}/id_rsa_ed25519.pub"
37
- sh "ssh-keygen -q -f #{dir}/id_rsa_ed25519 -t ed25519 -N 'pwd'"
38
- set_authorized_key('net_ssh_1',"#{dir}/id_rsa_ed25519.pub")
39
- ssh_add("#{dir}/id_rsa_ed25519","pwd")
40
-
41
- # TODO: fix bug in net ssh which reads public key even if private key is there
42
- sh "mv #{dir}/id_rsa_ed25519.pub #{dir}/id_rsa_ed25519.pub.hidden"
43
-
44
- ret = Net::SSH.start("localhost", "net_ssh_1") do |ssh|
45
- ssh.exec! 'echo "hello from:$USER"'
46
- end
47
- assert_equal "hello from:net_ssh_1\n", ret
48
- end
49
- end
50
- end
51
-
52
- def test_in_file_with_password
53
- Dir.mktmpdir do |dir|
54
- sh "rm -rf #{dir}/id_rsa_ed25519 #{dir}/id_rsa_ed25519.pub"
55
- sh "ssh-keygen -q -f #{dir}/id_rsa_ed25519 -t ed25519 -N 'pwd'"
56
- set_authorized_key('net_ssh_1',"#{dir}/id_rsa_ed25519.pub")
57
-
58
- # TODO: fix bug in net ssh which reads public key even if private key is there
59
- sh "mv #{dir}/id_rsa_ed25519.pub #{dir}/id_rsa_ed25519.pub.hidden"
60
-
61
- #sshopts = '-vvvv -o UserKnownHostsFile=/dev/null -o StrictHostKeyChecking=no'
62
- #sh "ssh -i #{dir}/id_rsa_ed25519 #{sshopts} net_ssh_1@localhost echo 'hello'"
63
-
64
- ret = Net::SSH.start("localhost", "net_ssh_1", {keys: "#{dir}/id_rsa_ed25519", passphrase:'pwd'}) do |ssh|
65
- ssh.exec! 'echo "hello from:$USER"'
66
- end
67
- assert_equal "hello from:net_ssh_1\n", ret
68
- end
69
- end
70
- end
@@ -1,532 +0,0 @@
1
- # $ ruby -Ilib -Itest -rrubygems test/manual/test_forward.rb
2
-
3
- # Tests for the following patch:
4
- #
5
- # http://github.com/net-ssh/net-ssh/tree/portfwfix
6
- #
7
- # It fixes 3 issues, regarding closing forwarded ports:
8
- #
9
- # 1.) if client closes a forwarded connection, but the server is reading, net-ssh terminates with IOError socket closed.
10
- # 2.) if client force closes (RST) a forwarded connection, but server is reading, net-ssh terminates with
11
- # 3.) if server closes the sending side, the on_eof is not handled.
12
- #
13
- # More info:
14
- #
15
- # http://net-ssh.lighthouseapp.com/projects/36253/tickets/7
16
-
17
- require_relative './common'
18
- require 'net/ssh/buffer'
19
- require 'net/ssh'
20
- require 'timeout'
21
- require 'tempfile'
22
-
23
- class TestForward < Test::Unit::TestCase
24
- include IntegrationTestHelpers
25
-
26
- def localhost
27
- 'localhost'
28
- end
29
-
30
- def user
31
- 'net_ssh_1'
32
- end
33
-
34
- def ssh_start_params
35
- [localhost ,user , {:keys => @key_id_rsa}]
36
- end
37
-
38
- def setup_ssh_env(&block)
39
- tmpdir do |dir|
40
- @key_id_rsa = "#{dir}/id_rsa"
41
- sh "rm -rf #{@key_id_rsa} #{@key_id_rsa}.pub"
42
- sh "ssh-keygen -q -f #{@key_id_rsa} -t rsa -N ''"
43
- set_authorized_key(user,"#{@key_id_rsa}.pub")
44
- yield
45
- end
46
- end
47
-
48
- def start_server_sending_lot_of_data(exceptions)
49
- server = TCPServer.open(0)
50
- Thread.start do
51
- loop do
52
- Thread.start(server.accept) do |client|
53
- begin
54
- 10000.times do |i|
55
- client.puts "item#{i}"
56
- end
57
- client.close
58
- rescue
59
- exceptions << $!
60
- raise
61
- end
62
- end
63
- end
64
- end
65
- return server
66
- end
67
-
68
- def start_server_closing_soon(exceptions=nil)
69
- server = TCPServer.open(0)
70
- Thread.start do
71
- loop do
72
- Thread.start(server.accept) do |client|
73
- begin
74
- client.recv(1024)
75
- client.setsockopt(Socket::SOL_SOCKET, Socket::SO_LINGER, [1, 0].pack("ii"))
76
- client.close
77
- rescue
78
- exceptions << $!
79
- raise
80
- end
81
- end
82
- end
83
- end
84
- return server
85
- end
86
-
87
- def test_in_file_no_password
88
- setup_ssh_env do
89
- ret = Net::SSH.start(*ssh_start_params) do |ssh|
90
- #ret = Net::SSH.start("localhost", "net_ssh_1", {keys: @key_id_rsa}) do |ssh|
91
- ssh.exec! 'echo "hello from:$USER"'
92
- end
93
- assert_equal "hello from:net_ssh_1\n", ret
94
- end
95
- end
96
-
97
- def test_local_ephemeral_port_should_work_correctly
98
- setup_ssh_env do
99
- session = Net::SSH.start(*ssh_start_params)
100
-
101
- assert_nothing_raised do
102
- assigned_port = session.forward.local(0, localhost, 22)
103
- assert_not_nil assigned_port
104
- assert_operator assigned_port, :>, 0
105
- end
106
- end
107
- end
108
-
109
- def test_remote_ephemeral_port_should_work_correctly
110
- setup_ssh_env do
111
- session = Net::SSH.start(*ssh_start_params)
112
-
113
- assert_nothing_raised do
114
- session.forward.remote(22, localhost, 0, localhost)
115
- session.loop { !(session.forward.active_remotes.length > 0) }
116
- assigned_port = session.forward.active_remotes.first[0]
117
- assert_not_nil assigned_port
118
- assert_operator assigned_port, :>, 0
119
- end
120
- end
121
- end
122
-
123
- def test_remote_callback_should_fire
124
- setup_ssh_env do
125
- session = Net::SSH.start(*ssh_start_params)
126
-
127
- assert_nothing_raised do
128
- got_port = nil
129
- session.forward.remote(22, localhost, 0, localhost) do |port|
130
- got_port = port
131
- end
132
- session.loop { !(session.forward.active_remotes.length > 0) }
133
- assert_operator session.forward.active_remote_destinations.length, :==, 1
134
- assert_operator session.forward.active_remote_destinations.keys.first, :==, [ 22, localhost ]
135
- assert_operator session.forward.active_remote_destinations.values.first, :==, [ got_port, localhost ]
136
- assert_operator session.forward.active_remotes.first, :==, [ got_port, localhost ]
137
- assigned_port = session.forward.active_remotes.first[0]
138
- assert_operator got_port, :==, assigned_port
139
- assert_not_nil assigned_port
140
- assert_operator assigned_port, :>, 0
141
- end
142
- end
143
- end
144
-
145
- def test_remote_callback_should_fire_on_error_and_still_throw_exception
146
- setup_ssh_env do
147
- session = Net::SSH.start(*ssh_start_params)
148
-
149
- assert_nothing_raised do
150
- session.forward.remote(22, localhost, 22, localhost) do |port|
151
- assert_operator port, :==, :error
152
- end
153
- end
154
- assert_raises(Net::SSH::Exception) do
155
- session.loop { true }
156
- end
157
- end
158
- end
159
-
160
- def test_remote_callback_should_fire_on_error_but_not_throw_exception_if_asked_not_to
161
- setup_ssh_env do
162
- session = Net::SSH.start(*ssh_start_params)
163
-
164
- assert_nothing_raised do
165
- got_port = nil
166
- session.forward.remote(22, localhost, 22, localhost) do |port|
167
- assert_operator port, :==, :error
168
- got_port = port
169
- :no_exception
170
- end
171
- session.loop { !got_port }
172
- assert_operator got_port, :==, :error
173
- assert_operator session.forward.active_remotes.length, :==, 0
174
- end
175
- end
176
- end
177
-
178
- def test_loop_should_not_abort_when_local_side_of_forward_is_closed
179
- setup_ssh_env do
180
- session = Net::SSH.start(*ssh_start_params)
181
- server_exc = Queue.new
182
- server = start_server_sending_lot_of_data(server_exc)
183
- remote_port = server.addr[1]
184
- local_port = 0 # request ephemeral port
185
- session.forward.local(local_port, localhost, remote_port)
186
- client_done = Queue.new
187
- Thread.start do
188
- begin
189
- client = TCPSocket.new(localhost, local_port)
190
- client.recv(1024)
191
- client.close
192
- sleep(0.2)
193
- ensure
194
- client_done << true
195
- end
196
- end
197
- session.loop(0.1) { client_done.empty? }
198
- assert_equal "Broken pipe", "#{server_exc.pop}" unless server_exc.empty?
199
- end
200
- end
201
-
202
- def test_loop_should_not_abort_when_local_side_of_forward_is_reset
203
- setup_ssh_env do
204
- session = Net::SSH.start(*ssh_start_params)
205
- server_exc = Queue.new
206
- server = start_server_sending_lot_of_data(server_exc)
207
- remote_port = server.addr[1]
208
- local_port = 0 # request ephemeral port
209
- session.forward.local(local_port, localhost, remote_port)
210
- client_done = Queue.new
211
- Thread.start do
212
- begin
213
- client = TCPSocket.new(localhost, local_port)
214
- client.recv(1024)
215
- client.setsockopt(Socket::SOL_SOCKET, Socket::SO_LINGER, [1, 0].pack("ii"))
216
- client.close
217
- sleep(0.1)
218
- ensure
219
- client_done << true
220
- end
221
- end
222
- session.loop(0.1) { client_done.empty? }
223
- assert_equal "Broken pipe", "#{server_exc.pop}" unless server_exc.empty?
224
- end
225
- end
226
-
227
- def create_local_socket(&blk)
228
- tempfile = Tempfile.new("net_ssh_forward_test")
229
- path = tempfile.path
230
- tempfile.delete
231
- yield UNIXServer.open(path)
232
- File.delete(path)
233
- end if defined?(UNIXServer)
234
-
235
- def test_forward_local_unix_socket_to_remote_port
236
- setup_ssh_env do
237
- session = Net::SSH.start(*ssh_start_params)
238
- server_exc = Queue.new
239
- server = start_server_sending_lot_of_data(server_exc)
240
- remote_port = server.addr[1]
241
- client_data = nil
242
-
243
- create_local_socket do |local_socket|
244
- session.forward.local(local_socket, localhost, remote_port)
245
- client_done = Queue.new
246
-
247
- Thread.start do
248
- begin
249
- client = UNIXSocket.new(local_socket.path)
250
- client_data = client.recv(1024)
251
- client.close
252
- sleep(0.2)
253
- ensure
254
- client_done << true
255
- end
256
- end
257
-
258
- session.loop(0.1) { client_done.empty? }
259
- end
260
-
261
- assert_not_nil(client_data, "client should have received data")
262
- assert(client_data.match(/item\d/), 'client should have received the string item')
263
- end
264
- end if defined?(UNIXSocket)
265
-
266
- def test_loop_should_not_abort_when_server_side_of_forward_is_closed
267
- setup_ssh_env do
268
- session = Net::SSH.start(*ssh_start_params)
269
- server = start_server_closing_soon
270
- remote_port = server.addr[1]
271
- local_port = 0 # request ephemeral port
272
- session.forward.local(local_port, localhost, remote_port)
273
- client_done = Queue.new
274
- Thread.start do
275
- begin
276
- client = TCPSocket.new(localhost, local_port)
277
- 1.times do |i|
278
- client.puts "item#{i}"
279
- end
280
- client.close
281
- sleep(0.1)
282
- ensure
283
- client_done << true
284
- end
285
- end
286
- session.loop(0.1) { client_done.empty? }
287
- end
288
- end
289
-
290
- def start_server(server = nil, &block)
291
- server ||= TCPServer.open(0)
292
- Thread.start do
293
- loop do
294
- Thread.start(server.accept) do |client|
295
- yield(client)
296
- end
297
- end
298
- end
299
- return server
300
- end
301
-
302
- def test_client_close_should_be_handled_remote
303
- setup_ssh_env do
304
- message = "This is a small message!"*1000
305
- session = Net::SSH.start(*ssh_start_params)
306
- server_done = Queue.new
307
- server = start_server do |client|
308
- begin
309
- data = client.read message.size
310
- server_done << data
311
- client.close
312
- rescue
313
- server_done << $!
314
- end
315
- end
316
- client_done = Queue.new
317
- got_remote_port = Queue.new
318
- local_port = server.addr[1]
319
- session.forward.remote(0, localhost, local_port) do |actual_remote_port|
320
- got_remote_port << actual_remote_port
321
- end
322
- session.loop(0.1) { got_remote_port.empty? }
323
- remote_port = got_remote_port.pop
324
- Thread.start do
325
- begin
326
- client = TCPSocket.new(localhost, remote_port)
327
- client.write(message)
328
- client.close
329
- client_done << true
330
- rescue
331
- client_done << $!
332
- end
333
- end
334
- Timeout.timeout(5) do
335
- session.loop(0.1) { server_done.empty? }
336
- assert_equal message, server_done.pop
337
- end
338
- end
339
- end
340
-
341
- def test_client_close_should_be_handled
342
- setup_ssh_env do
343
- message = "This is a small message!"*1000
344
- session = Net::SSH.start(*ssh_start_params)
345
- server_done = Queue.new
346
- server = start_server do |client|
347
- begin
348
- data = client.read message.size
349
- server_done << data
350
- client.close
351
- rescue
352
- server_done << $!
353
- end
354
- end
355
- client_done = Queue.new
356
- remote_port = server.addr[1]
357
- local_port = session.forward.local(0, localhost, remote_port)
358
- Thread.start do
359
- begin
360
- client = TCPSocket.new(localhost, local_port)
361
- client.write(message)
362
- client.close
363
- client_done << true
364
- rescue
365
- client_done << $!
366
- end
367
- end
368
- Timeout.timeout(5) do
369
- session.loop(0.1) { server_done.empty? }
370
- assert_equal message, server_done.pop
371
- end
372
- end
373
- end
374
-
375
- def test_server_eof_should_be_handled_remote
376
- setup_ssh_env do
377
- message = "This is a small message!"
378
- session = Net::SSH.start(*ssh_start_params)
379
- server = start_server do |client|
380
- client.write message
381
- client.close
382
- end
383
- client_done = Queue.new
384
- got_remote_port = Queue.new
385
- local_port = server.addr[1]
386
- session.forward.remote(0, localhost, local_port) do |actual_remote_port|
387
- got_remote_port << actual_remote_port
388
- end
389
- session.loop(0.1) { got_remote_port.empty? }
390
- remote_port = got_remote_port.pop
391
- Thread.start do
392
- begin
393
- client = TCPSocket.new(localhost, remote_port)
394
- data = client.read(4096)
395
- client.close
396
- client_done << data
397
- rescue
398
- client_done << $!
399
- end
400
- end
401
- Timeout.timeout(5) do
402
- session.loop(0.1) { client_done.empty? }
403
- assert_equal message, client_done.pop
404
- end
405
- end
406
- end
407
-
408
- def test_server_eof_should_be_handled
409
- setup_ssh_env do
410
- message = "This is a small message!"
411
- session = Net::SSH.start(*ssh_start_params)
412
- server = start_server do |client|
413
- client.write message
414
- client.close
415
- end
416
- client_done = Queue.new
417
- remote_port = server.addr[1]
418
- local_port = session.forward.local(0, localhost, remote_port)
419
- Thread.start do
420
- begin
421
- client = TCPSocket.new(localhost, local_port)
422
- data = client.read(4096)
423
- client.close
424
- client_done << data
425
- rescue
426
- client_done << $!
427
- end
428
- end
429
- Timeout.timeout(5) do
430
- session.loop(0.1) { client_done.empty? }
431
- assert_equal message, client_done.pop
432
- end
433
- end
434
- end
435
-
436
- def _run_reading_client(client_done, local_port)
437
- Thread.start do
438
- begin
439
- client = TCPSocket.new(localhost, local_port)
440
- data = client.read(4096)
441
- client.close
442
- client_done << data
443
- rescue
444
- client_done << $!
445
- end
446
- end
447
- end
448
-
449
- def test_cannot_open_connection_should_allow_further_connections_on_different_forward
450
- setup_ssh_env do
451
- session = Net::SSH.start(*ssh_start_params)
452
- server = start_server do |client|
453
- _data = client.write "hello"
454
- client.close
455
- end
456
- # Forward to a non existing port
457
- non_existing_port = 1234
458
- local_port = session.forward.local(0, localhost, non_existing_port)
459
- # should return connection refused
460
- client_done = Queue.new
461
- _run_reading_client(client_done, local_port)
462
- Timeout.timeout(5) do
463
- session.loop(0.1) { client_done.empty? }
464
- end
465
- assert_equal nil, client_done.pop
466
- assert client_done.empty?
467
- # Forward to existing port
468
- remote_port = server.addr[1]
469
- local_port = session.forward.local(0, localhost, remote_port)
470
- _run_reading_client(client_done, local_port)
471
- Timeout.timeout(5) do
472
- session.loop(0.1) { client_done.empty? }
473
- end
474
- assert_equal "hello", client_done.pop
475
- assert client_done.empty?
476
- end
477
- end
478
-
479
- def test_cannot_open_connection_should_allow_further_connections_on_same
480
- setup_ssh_env do
481
- session = Net::SSH.start(*ssh_start_params)
482
- server = TCPServer.open(0)
483
- # Forward to a non existing port
484
- remote_port = server.addr[1]
485
- server.close
486
- local_port = session.forward.local(0, localhost, remote_port)
487
- # should return connection refused
488
- client_done = Queue.new
489
- _run_reading_client(client_done, local_port)
490
- Timeout.timeout(5) do
491
- session.loop(0.1) { client_done.empty? }
492
- end
493
- assert_equal nil, client_done.pop
494
- assert client_done.empty?
495
- # start server
496
- server = TCPServer.open(remote_port)
497
- server = start_server(server) do |client|
498
- _data = client.write "hello"
499
- client.close
500
- end
501
- _run_reading_client(client_done, local_port)
502
- Timeout.timeout(5) do
503
- session.loop(0.1) { client_done.empty? }
504
- end
505
- assert_equal "hello", client_done.pop
506
- assert client_done.empty?
507
- end
508
- end
509
-
510
- def test_cancel_local
511
- setup_ssh_env do
512
- session = Net::SSH.start(*ssh_start_params)
513
- server = start_server(server) do |client|
514
- _data = client.write "hello"
515
- client.close
516
- end
517
- remote_port = server.addr[1]
518
- local_port = session.forward.local(0, localhost, remote_port)
519
- # run client
520
- client_done = Queue.new
521
- _run_reading_client(client_done, local_port)
522
- Timeout.timeout(5) do
523
- session.loop(0.1) { client_done.empty? }
524
- end
525
- assert_equal "hello", client_done.pop
526
- # cancel
527
- session.forward.cancel_local(local_port)
528
- session.loop(0.1)
529
- assert_equal({}, session.channels)
530
- end
531
- end
532
- end