net-ssh 4.0.0.alpha1 → 4.0.0.alpha2

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.
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