net-ssh 3.2.0.rc2 → 7.1.0

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 (204) hide show
  1. checksums.yaml +5 -5
  2. checksums.yaml.gz.sig +2 -2
  3. data/.dockerignore +6 -0
  4. data/.github/config/rubocop_linter_action.yml +4 -0
  5. data/.github/workflows/ci-with-docker.yml +44 -0
  6. data/.github/workflows/ci.yml +87 -0
  7. data/.github/workflows/rubocop.yml +16 -0
  8. data/.gitignore +13 -0
  9. data/.rubocop.yml +22 -0
  10. data/.rubocop_todo.yml +1081 -0
  11. data/CHANGES.txt +228 -7
  12. data/Dockerfile +27 -0
  13. data/Dockerfile.openssl3 +17 -0
  14. data/Gemfile +13 -0
  15. data/Gemfile.noed25519 +12 -0
  16. data/ISSUE_TEMPLATE.md +30 -0
  17. data/Manifest +4 -5
  18. data/README.md +297 -0
  19. data/Rakefile +125 -74
  20. data/SECURITY.md +4 -0
  21. data/appveyor.yml +58 -0
  22. data/docker-compose.yml +23 -0
  23. data/lib/net/ssh/authentication/agent.rb +279 -18
  24. data/lib/net/ssh/authentication/certificate.rb +183 -0
  25. data/lib/net/ssh/authentication/constants.rb +17 -15
  26. data/lib/net/ssh/authentication/ed25519.rb +186 -0
  27. data/lib/net/ssh/authentication/ed25519_loader.rb +31 -0
  28. data/lib/net/ssh/authentication/key_manager.rb +86 -39
  29. data/lib/net/ssh/authentication/methods/abstract.rb +67 -48
  30. data/lib/net/ssh/authentication/methods/hostbased.rb +34 -37
  31. data/lib/net/ssh/authentication/methods/keyboard_interactive.rb +13 -13
  32. data/lib/net/ssh/authentication/methods/none.rb +16 -19
  33. data/lib/net/ssh/authentication/methods/password.rb +27 -17
  34. data/lib/net/ssh/authentication/methods/publickey.rb +96 -55
  35. data/lib/net/ssh/authentication/pageant.rb +471 -367
  36. data/lib/net/ssh/authentication/pub_key_fingerprint.rb +43 -0
  37. data/lib/net/ssh/authentication/session.rb +131 -121
  38. data/lib/net/ssh/buffer.rb +399 -300
  39. data/lib/net/ssh/buffered_io.rb +154 -150
  40. data/lib/net/ssh/config.rb +308 -185
  41. data/lib/net/ssh/connection/channel.rb +635 -613
  42. data/lib/net/ssh/connection/constants.rb +29 -29
  43. data/lib/net/ssh/connection/event_loop.rb +123 -0
  44. data/lib/net/ssh/connection/keepalive.rb +55 -51
  45. data/lib/net/ssh/connection/session.rb +620 -551
  46. data/lib/net/ssh/connection/term.rb +125 -123
  47. data/lib/net/ssh/errors.rb +101 -99
  48. data/lib/net/ssh/key_factory.rb +197 -105
  49. data/lib/net/ssh/known_hosts.rb +214 -127
  50. data/lib/net/ssh/loggable.rb +50 -49
  51. data/lib/net/ssh/packet.rb +83 -79
  52. data/lib/net/ssh/prompt.rb +50 -81
  53. data/lib/net/ssh/proxy/command.rb +105 -90
  54. data/lib/net/ssh/proxy/errors.rb +12 -10
  55. data/lib/net/ssh/proxy/http.rb +82 -79
  56. data/lib/net/ssh/proxy/https.rb +50 -0
  57. data/lib/net/ssh/proxy/jump.rb +54 -0
  58. data/lib/net/ssh/proxy/socks4.rb +2 -6
  59. data/lib/net/ssh/proxy/socks5.rb +14 -17
  60. data/lib/net/ssh/service/forward.rb +370 -317
  61. data/lib/net/ssh/test/channel.rb +145 -136
  62. data/lib/net/ssh/test/extensions.rb +131 -110
  63. data/lib/net/ssh/test/kex.rb +34 -32
  64. data/lib/net/ssh/test/local_packet.rb +46 -44
  65. data/lib/net/ssh/test/packet.rb +89 -70
  66. data/lib/net/ssh/test/remote_packet.rb +32 -30
  67. data/lib/net/ssh/test/script.rb +156 -142
  68. data/lib/net/ssh/test/socket.rb +49 -48
  69. data/lib/net/ssh/test.rb +82 -77
  70. data/lib/net/ssh/transport/algorithms.rb +441 -360
  71. data/lib/net/ssh/transport/cipher_factory.rb +96 -98
  72. data/lib/net/ssh/transport/constants.rb +32 -24
  73. data/lib/net/ssh/transport/ctr.rb +42 -22
  74. data/lib/net/ssh/transport/hmac/abstract.rb +81 -63
  75. data/lib/net/ssh/transport/hmac/md5.rb +0 -2
  76. data/lib/net/ssh/transport/hmac/md5_96.rb +0 -2
  77. data/lib/net/ssh/transport/hmac/none.rb +0 -2
  78. data/lib/net/ssh/transport/hmac/ripemd160.rb +0 -2
  79. data/lib/net/ssh/transport/hmac/sha1.rb +0 -2
  80. data/lib/net/ssh/transport/hmac/sha1_96.rb +0 -2
  81. data/lib/net/ssh/transport/hmac/sha2_256.rb +7 -11
  82. data/lib/net/ssh/transport/hmac/sha2_256_96.rb +4 -8
  83. data/lib/net/ssh/transport/hmac/sha2_256_etm.rb +12 -0
  84. data/lib/net/ssh/transport/hmac/sha2_512.rb +6 -9
  85. data/lib/net/ssh/transport/hmac/sha2_512_96.rb +4 -8
  86. data/lib/net/ssh/transport/hmac/sha2_512_etm.rb +12 -0
  87. data/lib/net/ssh/transport/hmac.rb +14 -12
  88. data/lib/net/ssh/transport/identity_cipher.rb +54 -52
  89. data/lib/net/ssh/transport/kex/abstract.rb +130 -0
  90. data/lib/net/ssh/transport/kex/abstract5656.rb +72 -0
  91. data/lib/net/ssh/transport/kex/curve25519_sha256.rb +39 -0
  92. data/lib/net/ssh/transport/kex/curve25519_sha256_loader.rb +30 -0
  93. data/lib/net/ssh/transport/kex/diffie_hellman_group14_sha1.rb +33 -40
  94. data/lib/net/ssh/transport/kex/diffie_hellman_group14_sha256.rb +11 -0
  95. data/lib/net/ssh/transport/kex/diffie_hellman_group1_sha1.rb +119 -213
  96. data/lib/net/ssh/transport/kex/diffie_hellman_group_exchange_sha1.rb +53 -61
  97. data/lib/net/ssh/transport/kex/diffie_hellman_group_exchange_sha256.rb +5 -9
  98. data/lib/net/ssh/transport/kex/ecdh_sha2_nistp256.rb +36 -90
  99. data/lib/net/ssh/transport/kex/ecdh_sha2_nistp384.rb +18 -10
  100. data/lib/net/ssh/transport/kex/ecdh_sha2_nistp521.rb +18 -10
  101. data/lib/net/ssh/transport/kex.rb +15 -12
  102. data/lib/net/ssh/transport/key_expander.rb +24 -20
  103. data/lib/net/ssh/transport/openssl.rb +161 -124
  104. data/lib/net/ssh/transport/packet_stream.rb +225 -185
  105. data/lib/net/ssh/transport/server_version.rb +55 -56
  106. data/lib/net/ssh/transport/session.rb +306 -255
  107. data/lib/net/ssh/transport/state.rb +178 -176
  108. data/lib/net/ssh/verifiers/accept_new.rb +33 -0
  109. data/lib/net/ssh/verifiers/accept_new_or_local_tunnel.rb +33 -0
  110. data/lib/net/ssh/verifiers/always.rb +58 -0
  111. data/lib/net/ssh/verifiers/never.rb +19 -0
  112. data/lib/net/ssh/version.rb +55 -53
  113. data/lib/net/ssh.rb +110 -47
  114. data/net-ssh-public_cert.pem +18 -18
  115. data/net-ssh.gemspec +36 -205
  116. data/support/ssh_tunnel_bug.rb +5 -5
  117. data.tar.gz.sig +0 -0
  118. metadata +153 -118
  119. metadata.gz.sig +0 -0
  120. data/.travis.yml +0 -18
  121. data/README.rdoc +0 -182
  122. data/lib/net/ssh/authentication/agent/java_pageant.rb +0 -85
  123. data/lib/net/ssh/authentication/agent/socket.rb +0 -178
  124. data/lib/net/ssh/ruby_compat.rb +0 -46
  125. data/lib/net/ssh/verifiers/lenient.rb +0 -30
  126. data/lib/net/ssh/verifiers/null.rb +0 -12
  127. data/lib/net/ssh/verifiers/secure.rb +0 -52
  128. data/lib/net/ssh/verifiers/strict.rb +0 -24
  129. data/setup.rb +0 -1585
  130. data/support/arcfour_check.rb +0 -20
  131. data/test/README.txt +0 -18
  132. data/test/authentication/methods/common.rb +0 -28
  133. data/test/authentication/methods/test_abstract.rb +0 -51
  134. data/test/authentication/methods/test_hostbased.rb +0 -114
  135. data/test/authentication/methods/test_keyboard_interactive.rb +0 -121
  136. data/test/authentication/methods/test_none.rb +0 -41
  137. data/test/authentication/methods/test_password.rb +0 -95
  138. data/test/authentication/methods/test_publickey.rb +0 -148
  139. data/test/authentication/test_agent.rb +0 -232
  140. data/test/authentication/test_key_manager.rb +0 -240
  141. data/test/authentication/test_session.rb +0 -107
  142. data/test/common.rb +0 -125
  143. data/test/configs/auth_off +0 -5
  144. data/test/configs/auth_on +0 -4
  145. data/test/configs/empty +0 -0
  146. data/test/configs/eqsign +0 -3
  147. data/test/configs/exact_match +0 -8
  148. data/test/configs/host_plus +0 -10
  149. data/test/configs/multihost +0 -4
  150. data/test/configs/negative_match +0 -6
  151. data/test/configs/nohost +0 -19
  152. data/test/configs/numeric_host +0 -4
  153. data/test/configs/proxy_remote_user +0 -2
  154. data/test/configs/send_env +0 -2
  155. data/test/configs/substitutes +0 -8
  156. data/test/configs/wild_cards +0 -14
  157. data/test/connection/test_channel.rb +0 -487
  158. data/test/connection/test_session.rb +0 -564
  159. data/test/integration/README.txt +0 -17
  160. data/test/integration/Vagrantfile +0 -12
  161. data/test/integration/common.rb +0 -63
  162. data/test/integration/playbook.yml +0 -56
  163. data/test/integration/test_forward.rb +0 -637
  164. data/test/integration/test_id_rsa_keys.rb +0 -96
  165. data/test/integration/test_proxy.rb +0 -93
  166. data/test/known_hosts/github +0 -1
  167. data/test/known_hosts/github_hash +0 -1
  168. data/test/manual/test_pageant.rb +0 -37
  169. data/test/start/test_connection.rb +0 -53
  170. data/test/start/test_options.rb +0 -57
  171. data/test/start/test_transport.rb +0 -28
  172. data/test/start/test_user_nil.rb +0 -27
  173. data/test/test_all.rb +0 -12
  174. data/test/test_buffer.rb +0 -433
  175. data/test/test_buffered_io.rb +0 -63
  176. data/test/test_config.rb +0 -268
  177. data/test/test_key_factory.rb +0 -191
  178. data/test/test_known_hosts.rb +0 -66
  179. data/test/transport/hmac/test_md5.rb +0 -41
  180. data/test/transport/hmac/test_md5_96.rb +0 -27
  181. data/test/transport/hmac/test_none.rb +0 -34
  182. data/test/transport/hmac/test_ripemd160.rb +0 -36
  183. data/test/transport/hmac/test_sha1.rb +0 -36
  184. data/test/transport/hmac/test_sha1_96.rb +0 -27
  185. data/test/transport/hmac/test_sha2_256.rb +0 -37
  186. data/test/transport/hmac/test_sha2_256_96.rb +0 -27
  187. data/test/transport/hmac/test_sha2_512.rb +0 -37
  188. data/test/transport/hmac/test_sha2_512_96.rb +0 -27
  189. data/test/transport/kex/test_diffie_hellman_group14_sha1.rb +0 -13
  190. data/test/transport/kex/test_diffie_hellman_group1_sha1.rb +0 -150
  191. data/test/transport/kex/test_diffie_hellman_group_exchange_sha1.rb +0 -96
  192. data/test/transport/kex/test_diffie_hellman_group_exchange_sha256.rb +0 -19
  193. data/test/transport/kex/test_ecdh_sha2_nistp256.rb +0 -161
  194. data/test/transport/kex/test_ecdh_sha2_nistp384.rb +0 -38
  195. data/test/transport/kex/test_ecdh_sha2_nistp521.rb +0 -38
  196. data/test/transport/test_algorithms.rb +0 -328
  197. data/test/transport/test_cipher_factory.rb +0 -443
  198. data/test/transport/test_hmac.rb +0 -34
  199. data/test/transport/test_identity_cipher.rb +0 -40
  200. data/test/transport/test_packet_stream.rb +0 -1762
  201. data/test/transport/test_server_version.rb +0 -74
  202. data/test/transport/test_session.rb +0 -331
  203. data/test/transport/test_state.rb +0 -181
  204. data/test/verifiers/test_secure.rb +0 -40
@@ -1,56 +0,0 @@
1
- ---
2
- - hosts: all
3
- sudo: yes
4
- vars:
5
- ruby_version: '2.0.0-p598'
6
- rvm_install_path: '/usr/local/rvm'
7
- foopwd: "$6$mhOzf/yapZwS$3RwDl4GfWZ5VcfcsHrK9xNNTxyzLOJBsmMttDNaegIbXxMahV86.v/5HsNtit16MEl0EFf5CSW8Dz2yXV.8GB0"
8
- foo2pwd: "$6$JiB7y7.M0yI$Abt.ZGIc4DwkRWeI6nKxzzPUZcux7hLRXSdpoKoZvswJz1SZyg5GRQWn9pGID0dgC6e4wFglfW6ev/qZoTqGk/"
9
- pre_tasks:
10
- - name: get currently installed ruby version
11
- command: "{{rvm_install_path}}/rubies/ruby-{{ruby_version}}/bin/ruby -e 'puts \"#{RUBY_VERSION}-p#{RUBY_PATCHLEVEL}\"'"
12
- register: current_ruby_version
13
- ignore_errors: True
14
- roles:
15
- - { role: rvm_io.rvm1-ruby,
16
- tags: ruby, sudo: True,
17
- rvm1_rubies: ["ruby-{{ruby_version}}","ruby-2.3.0"],
18
- rvm1_install_path: "{{rvm_install_path}}",
19
- rvm1_gpg_key_server: pool.sks-keyservers.net,
20
- when: "'{{current_ruby_version.stdout|default()}}' != '{{ruby_version}}'" }
21
- tasks:
22
- - user: name=net_ssh_1 password="{{foopwd}}" group=vagrant state=present
23
- - user: name=net_ssh_2 password="{{foo2pwd}}" group=vagrant state=present
24
- - file: dest=/home/net_ssh_1/.ssh/ state=directory mode=0740 owner=net_ssh_1
25
- - file: dest=/home/net_ssh_2/.ssh/ state=directory mode=0740 owner=net_ssh_2
26
- - lineinfile: dest=/etc/sudoers.d/net_ssh_1 mode=0440 state=present create=yes
27
- line='net_ssh_1 ALL=(ALL) NOPASSWD:ALL' regexp=net_ssh_1
28
- - lineinfile: dest=/etc/sudoers.d/net_ssh_1 mode=0440 state=present create=yes
29
- line='net_ssh_2 ALL=(ALL) NOPASSWD:ALL' regexp=net_ssh_2
30
- - command: ssh-keygen -A
31
- args:
32
- creates: /etc/ssh/ssh_host_ed25519_key
33
- notify: restart sshd
34
- - name: sshd debug
35
- lineinfile: dest='/etc/ssh/sshd_config' line='LogLevel DEBUG' regexp=LogLevel
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
45
- - gem: name="{{item}}" state=present executable=/usr/local/rvm/rubies/ruby-{{ruby_version}}/bin/gem
46
- with_items:
47
- - byebug
48
- - jeweler
49
- - mocha
50
- - rbnacl
51
- - rbnacl-libsodium
52
- - copy: content='echo "cd /net-ssh ; rake integration-test"' dest=/etc/update-motd.d/99-net-ssh-tests mode=0755
53
- handlers:
54
- - name: restart sshd
55
- service: name=ssh state=restarted
56
-
@@ -1,637 +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 'net/ssh/proxy/command'
21
- require 'timeout'
22
- require 'tempfile'
23
-
24
- class TestForward < Test::Unit::TestCase
25
- include IntegrationTestHelpers
26
-
27
- def localhost
28
- 'localhost'
29
- end
30
-
31
- def user
32
- 'net_ssh_1'
33
- end
34
-
35
- def ssh_start_params(options = {})
36
- [localhost ,user , {:keys => @key_id_rsa}.merge(options)]
37
- end
38
-
39
- def setup_ssh_env(&block)
40
- tmpdir do |dir|
41
- @key_id_rsa = "#{dir}/id_rsa"
42
- sh "rm -rf #{@key_id_rsa} #{@key_id_rsa}.pub"
43
- sh "ssh-keygen -f #{@key_id_rsa} -t rsa -N ''"
44
- set_authorized_key(user,"#{@key_id_rsa}.pub")
45
- yield
46
- end
47
- end
48
-
49
- def start_server_sending_lot_of_data(exceptions)
50
- server = TCPServer.open(0)
51
- Thread.start do
52
- loop do
53
- Thread.start(server.accept) do |client|
54
- begin
55
- 10000.times do |i|
56
- client.puts "item#{i}"
57
- end
58
- client.close
59
- rescue
60
- exceptions << $!
61
- raise
62
- end
63
- end
64
- end
65
- end
66
- return server
67
- end
68
-
69
- def start_server_closing_soon(exceptions=nil)
70
- server = TCPServer.open(0)
71
- Thread.start do
72
- loop do
73
- Thread.start(server.accept) do |client|
74
- begin
75
- client.recv(1024)
76
- client.setsockopt(Socket::SOL_SOCKET, Socket::SO_LINGER, [1, 0].pack("ii"))
77
- client.close
78
- rescue
79
- exceptions << $!
80
- raise
81
- end
82
- end
83
- end
84
- end
85
- return server
86
- end
87
-
88
- def test_in_file_no_password
89
- setup_ssh_env do
90
- ret = Net::SSH.start(*ssh_start_params) do |ssh|
91
- #ret = Net::SSH.start("localhost", "net_ssh_1", {keys: @key_id_rsa}) do |ssh|
92
- ssh.exec! 'echo "hello from:$USER"'
93
- end
94
- assert_equal "hello from:net_ssh_1\n", ret
95
- end
96
- end
97
-
98
- def test_local_ephemeral_port_should_work_correctly
99
- setup_ssh_env do
100
- session = Net::SSH.start(*ssh_start_params)
101
-
102
- assert_nothing_raised do
103
- assigned_port = session.forward.local(0, localhost, 22)
104
- assert_not_nil assigned_port
105
- assert_operator assigned_port, :>, 0
106
- end
107
- end
108
- end
109
-
110
- def test_remote_ephemeral_port_should_work_correctly
111
- setup_ssh_env do
112
- session = Net::SSH.start(*ssh_start_params)
113
-
114
- assert_nothing_raised do
115
- session.forward.remote(22, localhost, 0, localhost)
116
- session.loop { !(session.forward.active_remotes.length > 0) }
117
- assigned_port = session.forward.active_remotes.first[0]
118
- assert_not_nil assigned_port
119
- assert_operator assigned_port, :>, 0
120
- end
121
- end
122
- end
123
-
124
- def test_remote_callback_should_fire
125
- setup_ssh_env do
126
- session = Net::SSH.start(*ssh_start_params)
127
-
128
- assert_nothing_raised do
129
- got_port = nil
130
- session.forward.remote(22, localhost, 0, localhost) do |port|
131
- got_port = port
132
- end
133
- session.loop { !(session.forward.active_remotes.length > 0) }
134
- assert_operator session.forward.active_remote_destinations.length, :==, 1
135
- assert_operator session.forward.active_remote_destinations.keys.first, :==, [ 22, localhost ]
136
- assert_operator session.forward.active_remote_destinations.values.first, :==, [ got_port, localhost ]
137
- assert_operator session.forward.active_remotes.first, :==, [ got_port, localhost ]
138
- assigned_port = session.forward.active_remotes.first[0]
139
- assert_operator got_port, :==, assigned_port
140
- assert_not_nil assigned_port
141
- assert_operator assigned_port, :>, 0
142
- end
143
- end
144
- end
145
-
146
- def test_remote_callback_should_fire_on_error_and_still_throw_exception
147
- setup_ssh_env do
148
- session = Net::SSH.start(*ssh_start_params)
149
-
150
- assert_nothing_raised do
151
- session.forward.remote(22, localhost, 22, localhost) do |port|
152
- assert_operator port, :==, :error
153
- end
154
- end
155
- assert_raises(Net::SSH::Exception) do
156
- session.loop { true }
157
- end
158
- end
159
- end
160
-
161
- def test_remote_callback_should_fire_on_error_but_not_throw_exception_if_asked_not_to
162
- setup_ssh_env do
163
- session = Net::SSH.start(*ssh_start_params)
164
-
165
- assert_nothing_raised do
166
- got_port = nil
167
- session.forward.remote(22, localhost, 22, localhost) do |port|
168
- assert_operator port, :==, :error
169
- got_port = port
170
- :no_exception
171
- end
172
- session.loop { !got_port }
173
- assert_operator got_port, :==, :error
174
- assert_operator session.forward.active_remotes.length, :==, 0
175
- end
176
- end
177
- end
178
-
179
- def test_loop_should_not_abort_when_local_side_of_forward_is_closed
180
- setup_ssh_env do
181
- session = Net::SSH.start(*ssh_start_params)
182
- server_exc = Queue.new
183
- server = start_server_sending_lot_of_data(server_exc)
184
- remote_port = server.addr[1]
185
- local_port = 0 # request ephemeral port
186
- session.forward.local(local_port, localhost, remote_port)
187
- client_done = Queue.new
188
- Thread.start do
189
- begin
190
- client = TCPSocket.new(localhost, local_port)
191
- client.recv(1024)
192
- client.close
193
- sleep(0.2)
194
- ensure
195
- client_done << true
196
- end
197
- end
198
- session.loop(0.1) { client_done.empty? }
199
- assert_equal "Broken pipe", "#{server_exc.pop}" unless server_exc.empty?
200
- end
201
- end
202
-
203
- def test_loop_should_not_abort_when_local_side_of_forward_is_reset
204
- setup_ssh_env do
205
- session = Net::SSH.start(*ssh_start_params)
206
- server_exc = Queue.new
207
- server = start_server_sending_lot_of_data(server_exc)
208
- remote_port = server.addr[1]
209
- local_port = 0 # request ephemeral port
210
- session.forward.local(local_port, localhost, remote_port)
211
- client_done = Queue.new
212
- Thread.start do
213
- begin
214
- client = TCPSocket.new(localhost, local_port)
215
- client.recv(1024)
216
- client.setsockopt(Socket::SOL_SOCKET, Socket::SO_LINGER, [1, 0].pack("ii"))
217
- client.close
218
- sleep(0.1)
219
- ensure
220
- client_done << true
221
- end
222
- end
223
- session.loop(0.1) { client_done.empty? }
224
- assert_equal "Broken pipe", "#{server_exc.pop}" unless server_exc.empty?
225
- end
226
- end
227
-
228
- def create_local_socket(&blk)
229
- tempfile = Tempfile.new("net_ssh_forward_test")
230
- path = tempfile.path
231
- tempfile.delete
232
- yield UNIXServer.open(path)
233
- File.delete(path)
234
- end if defined?(UNIXServer)
235
-
236
- def test_forward_local_unix_socket_to_remote_port
237
- setup_ssh_env do
238
- session = Net::SSH.start(*ssh_start_params)
239
- server_exc = Queue.new
240
- server = start_server_sending_lot_of_data(server_exc)
241
- remote_port = server.addr[1]
242
- client_data = nil
243
-
244
- create_local_socket do |local_socket|
245
- session.forward.local(local_socket, localhost, remote_port)
246
- client_done = Queue.new
247
-
248
- Thread.start do
249
- begin
250
- client = UNIXSocket.new(local_socket.path)
251
- client_data = client.recv(1024)
252
- client.close
253
- sleep(0.2)
254
- ensure
255
- client_done << true
256
- end
257
- end
258
-
259
- session.loop(0.1) { client_done.empty? }
260
- end
261
-
262
- assert_not_nil(client_data, "client should have received data")
263
- assert(client_data.match(/item\d/), 'client should have received the string item')
264
- end
265
- end if defined?(UNIXSocket)
266
-
267
- def test_loop_should_not_abort_when_server_side_of_forward_is_closed
268
- setup_ssh_env do
269
- session = Net::SSH.start(*ssh_start_params)
270
- server = start_server_closing_soon
271
- remote_port = server.addr[1]
272
- local_port = 0 # request ephemeral port
273
- session.forward.local(local_port, localhost, remote_port)
274
- client_done = Queue.new
275
- Thread.start do
276
- begin
277
- client = TCPSocket.new(localhost, local_port)
278
- 1.times do |i|
279
- client.puts "item#{i}"
280
- end
281
- client.close
282
- sleep(0.1)
283
- ensure
284
- client_done << true
285
- end
286
- end
287
- session.loop(0.1) { client_done.empty? }
288
- end
289
- end
290
-
291
- def start_server(server = nil, &block)
292
- server ||= TCPServer.open(0)
293
- Thread.start do
294
- loop do
295
- Thread.start(server.accept) do |client|
296
- yield(client)
297
- end
298
- end
299
- end
300
- return server
301
- end
302
-
303
- def test_client_close_should_be_handled_remote
304
- setup_ssh_env do
305
- message = "This is a small message!"*1000
306
- session = Net::SSH.start(*ssh_start_params)
307
- server_done = Queue.new
308
- server = start_server do |client|
309
- begin
310
- data = client.read message.size
311
- server_done << data
312
- client.close
313
- rescue
314
- server_done << $!
315
- end
316
- end
317
- client_done = Queue.new
318
- got_remote_port = Queue.new
319
- local_port = server.addr[1]
320
- session.forward.remote(0, localhost, local_port) do |actual_remote_port|
321
- got_remote_port << actual_remote_port
322
- end
323
- session.loop(0.1) { got_remote_port.empty? }
324
- remote_port = got_remote_port.pop
325
- Thread.start do
326
- begin
327
- client = TCPSocket.new(localhost, remote_port)
328
- client.write(message)
329
- client.close
330
- client_done << true
331
- rescue
332
- client_done << $!
333
- end
334
- end
335
- timeout(5) do
336
- session.loop(0.1) { server_done.empty? }
337
- assert_equal message, server_done.pop
338
- end
339
- end
340
- end
341
-
342
- class TCPProxy
343
- def initialize()
344
- @sockets = []
345
- end
346
- attr_reader :sockets
347
-
348
- def open(host, port, connection_options = nil)
349
- socket = TCPSocket.new(host,port)
350
- @sockets << socket
351
- socket
352
- end
353
-
354
- def close_all
355
- sockets.each do |socket|
356
- socket.close
357
- end
358
- end
359
- end
360
-
361
- def test_transport_close_should_closes_channels_with_tcps
362
- setup_ssh_env do
363
- server = start_server do |client|
364
- client.puts "Hello"
365
- sleep(100)
366
- client.puts "Hallo"
367
- end
368
- proxy = TCPProxy.new()
369
- session = Net::SSH.start(*ssh_start_params(proxy: proxy))
370
- remote_port = server.addr[1]
371
- local_port = session.forward.local(0, localhost, remote_port)
372
-
373
- # read on forwarded port
374
- client_done = Queue.new
375
- Thread.start do
376
- begin
377
- client = TCPSocket.new(localhost, local_port)
378
- client.read(6)
379
- proxy.close_all
380
- client.read(7)
381
- client.close
382
- client_done << true
383
- rescue
384
- client_done << $!
385
- end
386
- end
387
- Timeout.timeout(5) do
388
- begin
389
- session.loop(0.1) { true }
390
- rescue EOFError, IOError
391
- #puts "Error: #{$!} #{$!.backtrace.join("\n")}"
392
- end
393
- end
394
- begin
395
- Timeout.timeout(5) do
396
- assert_equal true, client_done.pop
397
- end
398
- rescue
399
- puts "Server error: #{server_error.class} #{server_error} bt:#{server_error.backtrace.join("\n")}"
400
- raise
401
- end
402
- end
403
- end
404
-
405
- def todo_test_transport_close_should_closes_channels_with_proxy
406
- setup_ssh_env do
407
- server = start_server do |client|
408
- client.puts "Hello"
409
- sleep(100)
410
- client.puts "Hallo"
411
- end
412
- proxy = Net::SSH::Proxy::Command.new("/bin/nc localhost 22")
413
- session = Net::SSH.start(*ssh_start_params(proxy: proxy))
414
- remote_port = server.addr[1]
415
- local_port = session.forward.local(0, localhost, remote_port)
416
-
417
- # read on forwarded port
418
- client_done = Queue.new
419
- Thread.start do
420
- begin
421
- client = TCPSocket.new(localhost, local_port)
422
- client.read(6)
423
- system("killall /bin/nc")
424
- client.read(7)
425
- client.close
426
- client_done << true
427
- rescue
428
- client_done << $!
429
- end
430
- end
431
- Timeout.timeout(5) do
432
- begin
433
- session.loop(0.1) { true }
434
- rescue EOFError
435
- begin
436
- session.close
437
- rescue
438
- end
439
- #puts "Error: #{$!} #{$!.backtrace.join("\n")}"
440
- end
441
- assert_equal true, client_done.pop
442
- end
443
- end
444
- end
445
-
446
- def test_client_close_should_be_handled
447
- setup_ssh_env do
448
- message = "This is a small message!"*1000
449
- session = Net::SSH.start(*ssh_start_params)
450
- server_done = Queue.new
451
- server = start_server do |client|
452
- begin
453
- data = client.read message.size
454
- server_done << data
455
- client.close
456
- rescue
457
- server_done << $!
458
- end
459
- end
460
- client_done = Queue.new
461
- remote_port = server.addr[1]
462
- local_port = session.forward.local(0, localhost, remote_port)
463
- Thread.start do
464
- begin
465
- client = TCPSocket.new(localhost, local_port)
466
- client.write(message)
467
- client.close
468
- client_done << true
469
- rescue
470
- client_done << $!
471
- end
472
- end
473
- timeout(5) do
474
- session.loop(0.1) { server_done.empty? }
475
- assert_equal message, server_done.pop
476
- end
477
- end
478
- end
479
-
480
- def test_server_eof_should_be_handled_remote
481
- setup_ssh_env do
482
- message = "This is a small message!"
483
- session = Net::SSH.start(*ssh_start_params)
484
- server = start_server do |client|
485
- client.write message
486
- client.close
487
- end
488
- client_done = Queue.new
489
- got_remote_port = Queue.new
490
- local_port = server.addr[1]
491
- session.forward.remote(0, localhost, local_port) do |actual_remote_port|
492
- got_remote_port << actual_remote_port
493
- end
494
- session.loop(0.1) { got_remote_port.empty? }
495
- remote_port = got_remote_port.pop
496
- Thread.start do
497
- begin
498
- client = TCPSocket.new(localhost, remote_port)
499
- data = client.read(4096)
500
- client.close
501
- client_done << data
502
- rescue
503
- client_done << $!
504
- end
505
- end
506
- timeout(5) do
507
- session.loop(0.1) { client_done.empty? }
508
- assert_equal message, client_done.pop
509
- end
510
- end
511
- end
512
-
513
- def test_server_eof_should_be_handled
514
- setup_ssh_env do
515
- message = "This is a small message!"
516
- session = Net::SSH.start(*ssh_start_params)
517
- server = start_server do |client|
518
- client.write message
519
- client.close
520
- end
521
- client_done = Queue.new
522
- remote_port = server.addr[1]
523
- local_port = session.forward.local(0, localhost, remote_port)
524
- Thread.start do
525
- begin
526
- client = TCPSocket.new(localhost, local_port)
527
- data = client.read(4096)
528
- client.close
529
- client_done << data
530
- rescue
531
- client_done << $!
532
- end
533
- end
534
- timeout(5) do
535
- session.loop(0.1) { client_done.empty? }
536
- assert_equal message, client_done.pop
537
- end
538
- end
539
- end
540
-
541
- def _run_reading_client(client_done, local_port)
542
- Thread.start do
543
- begin
544
- client = TCPSocket.new(localhost, local_port)
545
- data = client.read(4096)
546
- client.close
547
- client_done << data
548
- rescue
549
- client_done << $!
550
- end
551
- end
552
- end
553
-
554
- def test_cannot_open_connection_should_allow_further_connections_on_different_forward
555
- setup_ssh_env do
556
- session = Net::SSH.start(*ssh_start_params)
557
- server = start_server do |client|
558
- data = client.write "hello"
559
- client.close
560
- end
561
- # Forward to a non existing port
562
- non_existing_port = 1234
563
- local_port = session.forward.local(0, localhost, non_existing_port)
564
- # should return connection refused
565
- client_done = Queue.new
566
- _run_reading_client(client_done, local_port)
567
- timeout(5) do
568
- session.loop(0.1) { client_done.empty? }
569
- end
570
- assert_equal nil, client_done.pop
571
- assert client_done.empty?
572
- # Forward to existing port
573
- remote_port = server.addr[1]
574
- local_port = session.forward.local(0, localhost, remote_port)
575
- _run_reading_client(client_done, local_port)
576
- timeout(5) do
577
- session.loop(0.1) { client_done.empty? }
578
- end
579
- assert_equal "hello", client_done.pop
580
- assert client_done.empty?
581
- end
582
- end
583
-
584
- def test_cannot_open_connection_should_allow_further_connections_on_same
585
- setup_ssh_env do
586
- session = Net::SSH.start(*ssh_start_params)
587
- server = TCPServer.open(0)
588
- # Forward to a non existing port
589
- remote_port = server.addr[1]
590
- server.close
591
- local_port = session.forward.local(0, localhost, remote_port)
592
- # should return connection refused
593
- client_done = Queue.new
594
- _run_reading_client(client_done, local_port)
595
- timeout(5) do
596
- session.loop(0.1) { client_done.empty? }
597
- end
598
- assert_equal nil, client_done.pop
599
- assert client_done.empty?
600
- # start server
601
- server = TCPServer.open(remote_port)
602
- server = start_server(server) do |client|
603
- data = client.write "hello"
604
- client.close
605
- end
606
- _run_reading_client(client_done, local_port)
607
- timeout(5) do
608
- session.loop(0.1) { client_done.empty? }
609
- end
610
- assert_equal "hello", client_done.pop
611
- assert client_done.empty?
612
- end
613
- end
614
-
615
- def test_cancel_local
616
- setup_ssh_env do
617
- session = Net::SSH.start(*ssh_start_params)
618
- server = start_server(server) do |client|
619
- data = client.write "hello"
620
- client.close
621
- end
622
- remote_port = server.addr[1]
623
- local_port = session.forward.local(0, localhost, remote_port)
624
- # run client
625
- client_done = Queue.new
626
- _run_reading_client(client_done, local_port)
627
- timeout(5) do
628
- session.loop(0.1) { client_done.empty? }
629
- end
630
- assert_equal "hello", client_done.pop
631
- # cancel
632
- session.forward.cancel_local(local_port)
633
- session.loop(0.1)
634
- assert_equal({}, session.channels)
635
- end
636
- end
637
- end