net-ssh 3.2.0 → 7.2.0.rc1

Sign up to get free protection for your applications and to get access to all the features.
Files changed (210) hide show
  1. checksums.yaml +5 -5
  2. checksums.yaml.gz.sig +0 -0
  3. data/.dockerignore +6 -0
  4. data/.github/FUNDING.yml +1 -0
  5. data/.github/config/rubocop_linter_action.yml +4 -0
  6. data/.github/workflows/ci-with-docker.yml +44 -0
  7. data/.github/workflows/ci.yml +93 -0
  8. data/.github/workflows/rubocop.yml +16 -0
  9. data/.gitignore +13 -0
  10. data/.rubocop.yml +22 -0
  11. data/.rubocop_todo.yml +1081 -0
  12. data/CHANGES.txt +237 -7
  13. data/DEVELOPMENT.md +23 -0
  14. data/Dockerfile +27 -0
  15. data/Dockerfile.openssl3 +17 -0
  16. data/Gemfile +13 -0
  17. data/Gemfile.noed25519 +12 -0
  18. data/Gemfile.norbnacl +12 -0
  19. data/ISSUE_TEMPLATE.md +30 -0
  20. data/Manifest +4 -5
  21. data/README.md +298 -0
  22. data/Rakefile +125 -74
  23. data/SECURITY.md +4 -0
  24. data/appveyor.yml +58 -0
  25. data/docker-compose.yml +23 -0
  26. data/lib/net/ssh/authentication/agent.rb +279 -18
  27. data/lib/net/ssh/authentication/certificate.rb +183 -0
  28. data/lib/net/ssh/authentication/constants.rb +17 -15
  29. data/lib/net/ssh/authentication/ed25519.rb +186 -0
  30. data/lib/net/ssh/authentication/ed25519_loader.rb +31 -0
  31. data/lib/net/ssh/authentication/key_manager.rb +86 -39
  32. data/lib/net/ssh/authentication/methods/abstract.rb +67 -48
  33. data/lib/net/ssh/authentication/methods/hostbased.rb +34 -37
  34. data/lib/net/ssh/authentication/methods/keyboard_interactive.rb +13 -13
  35. data/lib/net/ssh/authentication/methods/none.rb +16 -19
  36. data/lib/net/ssh/authentication/methods/password.rb +27 -17
  37. data/lib/net/ssh/authentication/methods/publickey.rb +96 -55
  38. data/lib/net/ssh/authentication/pageant.rb +471 -367
  39. data/lib/net/ssh/authentication/pub_key_fingerprint.rb +43 -0
  40. data/lib/net/ssh/authentication/session.rb +131 -121
  41. data/lib/net/ssh/buffer.rb +399 -300
  42. data/lib/net/ssh/buffered_io.rb +154 -150
  43. data/lib/net/ssh/config.rb +308 -185
  44. data/lib/net/ssh/connection/channel.rb +635 -613
  45. data/lib/net/ssh/connection/constants.rb +29 -29
  46. data/lib/net/ssh/connection/event_loop.rb +123 -0
  47. data/lib/net/ssh/connection/keepalive.rb +55 -51
  48. data/lib/net/ssh/connection/session.rb +620 -551
  49. data/lib/net/ssh/connection/term.rb +125 -123
  50. data/lib/net/ssh/errors.rb +101 -99
  51. data/lib/net/ssh/key_factory.rb +197 -105
  52. data/lib/net/ssh/known_hosts.rb +214 -127
  53. data/lib/net/ssh/loggable.rb +50 -49
  54. data/lib/net/ssh/packet.rb +83 -79
  55. data/lib/net/ssh/prompt.rb +50 -81
  56. data/lib/net/ssh/proxy/command.rb +105 -90
  57. data/lib/net/ssh/proxy/errors.rb +12 -10
  58. data/lib/net/ssh/proxy/http.rb +82 -79
  59. data/lib/net/ssh/proxy/https.rb +50 -0
  60. data/lib/net/ssh/proxy/jump.rb +54 -0
  61. data/lib/net/ssh/proxy/socks4.rb +2 -6
  62. data/lib/net/ssh/proxy/socks5.rb +14 -17
  63. data/lib/net/ssh/service/forward.rb +370 -317
  64. data/lib/net/ssh/test/channel.rb +145 -136
  65. data/lib/net/ssh/test/extensions.rb +131 -110
  66. data/lib/net/ssh/test/kex.rb +34 -32
  67. data/lib/net/ssh/test/local_packet.rb +46 -44
  68. data/lib/net/ssh/test/packet.rb +89 -70
  69. data/lib/net/ssh/test/remote_packet.rb +32 -30
  70. data/lib/net/ssh/test/script.rb +156 -142
  71. data/lib/net/ssh/test/socket.rb +49 -48
  72. data/lib/net/ssh/test.rb +82 -77
  73. data/lib/net/ssh/transport/algorithms.rb +462 -359
  74. data/lib/net/ssh/transport/chacha20_poly1305_cipher.rb +117 -0
  75. data/lib/net/ssh/transport/chacha20_poly1305_cipher_loader.rb +17 -0
  76. data/lib/net/ssh/transport/cipher_factory.rb +122 -99
  77. data/lib/net/ssh/transport/constants.rb +32 -24
  78. data/lib/net/ssh/transport/ctr.rb +42 -22
  79. data/lib/net/ssh/transport/hmac/abstract.rb +81 -63
  80. data/lib/net/ssh/transport/hmac/md5.rb +0 -2
  81. data/lib/net/ssh/transport/hmac/md5_96.rb +0 -2
  82. data/lib/net/ssh/transport/hmac/none.rb +0 -2
  83. data/lib/net/ssh/transport/hmac/ripemd160.rb +0 -2
  84. data/lib/net/ssh/transport/hmac/sha1.rb +0 -2
  85. data/lib/net/ssh/transport/hmac/sha1_96.rb +0 -2
  86. data/lib/net/ssh/transport/hmac/sha2_256.rb +7 -11
  87. data/lib/net/ssh/transport/hmac/sha2_256_96.rb +4 -8
  88. data/lib/net/ssh/transport/hmac/sha2_256_etm.rb +12 -0
  89. data/lib/net/ssh/transport/hmac/sha2_512.rb +6 -9
  90. data/lib/net/ssh/transport/hmac/sha2_512_96.rb +4 -8
  91. data/lib/net/ssh/transport/hmac/sha2_512_etm.rb +12 -0
  92. data/lib/net/ssh/transport/hmac.rb +14 -12
  93. data/lib/net/ssh/transport/identity_cipher.rb +54 -44
  94. data/lib/net/ssh/transport/kex/abstract.rb +130 -0
  95. data/lib/net/ssh/transport/kex/abstract5656.rb +72 -0
  96. data/lib/net/ssh/transport/kex/curve25519_sha256.rb +39 -0
  97. data/lib/net/ssh/transport/kex/curve25519_sha256_loader.rb +30 -0
  98. data/lib/net/ssh/transport/kex/diffie_hellman_group14_sha1.rb +33 -40
  99. data/lib/net/ssh/transport/kex/diffie_hellman_group14_sha256.rb +11 -0
  100. data/lib/net/ssh/transport/kex/diffie_hellman_group1_sha1.rb +119 -213
  101. data/lib/net/ssh/transport/kex/diffie_hellman_group_exchange_sha1.rb +53 -61
  102. data/lib/net/ssh/transport/kex/diffie_hellman_group_exchange_sha256.rb +5 -9
  103. data/lib/net/ssh/transport/kex/ecdh_sha2_nistp256.rb +36 -90
  104. data/lib/net/ssh/transport/kex/ecdh_sha2_nistp384.rb +18 -10
  105. data/lib/net/ssh/transport/kex/ecdh_sha2_nistp521.rb +18 -10
  106. data/lib/net/ssh/transport/kex.rb +15 -12
  107. data/lib/net/ssh/transport/key_expander.rb +24 -20
  108. data/lib/net/ssh/transport/openssl.rb +161 -124
  109. data/lib/net/ssh/transport/openssl_cipher_extensions.rb +8 -0
  110. data/lib/net/ssh/transport/packet_stream.rb +246 -185
  111. data/lib/net/ssh/transport/server_version.rb +55 -56
  112. data/lib/net/ssh/transport/session.rb +306 -255
  113. data/lib/net/ssh/transport/state.rb +178 -176
  114. data/lib/net/ssh/verifiers/accept_new.rb +33 -0
  115. data/lib/net/ssh/verifiers/accept_new_or_local_tunnel.rb +33 -0
  116. data/lib/net/ssh/verifiers/always.rb +58 -0
  117. data/lib/net/ssh/verifiers/never.rb +19 -0
  118. data/lib/net/ssh/version.rb +55 -53
  119. data/lib/net/ssh.rb +111 -47
  120. data/net-ssh-public_cert.pem +18 -18
  121. data/net-ssh.gemspec +38 -205
  122. data/support/ssh_tunnel_bug.rb +5 -5
  123. data.tar.gz.sig +0 -0
  124. metadata +173 -118
  125. metadata.gz.sig +0 -0
  126. data/.travis.yml +0 -18
  127. data/README.rdoc +0 -182
  128. data/lib/net/ssh/authentication/agent/java_pageant.rb +0 -85
  129. data/lib/net/ssh/authentication/agent/socket.rb +0 -178
  130. data/lib/net/ssh/ruby_compat.rb +0 -46
  131. data/lib/net/ssh/verifiers/lenient.rb +0 -30
  132. data/lib/net/ssh/verifiers/null.rb +0 -12
  133. data/lib/net/ssh/verifiers/secure.rb +0 -52
  134. data/lib/net/ssh/verifiers/strict.rb +0 -24
  135. data/setup.rb +0 -1585
  136. data/support/arcfour_check.rb +0 -20
  137. data/test/README.txt +0 -18
  138. data/test/authentication/methods/common.rb +0 -28
  139. data/test/authentication/methods/test_abstract.rb +0 -51
  140. data/test/authentication/methods/test_hostbased.rb +0 -114
  141. data/test/authentication/methods/test_keyboard_interactive.rb +0 -121
  142. data/test/authentication/methods/test_none.rb +0 -41
  143. data/test/authentication/methods/test_password.rb +0 -95
  144. data/test/authentication/methods/test_publickey.rb +0 -148
  145. data/test/authentication/test_agent.rb +0 -232
  146. data/test/authentication/test_key_manager.rb +0 -240
  147. data/test/authentication/test_session.rb +0 -107
  148. data/test/common.rb +0 -125
  149. data/test/configs/auth_off +0 -5
  150. data/test/configs/auth_on +0 -4
  151. data/test/configs/empty +0 -0
  152. data/test/configs/eqsign +0 -3
  153. data/test/configs/exact_match +0 -8
  154. data/test/configs/host_plus +0 -10
  155. data/test/configs/multihost +0 -4
  156. data/test/configs/negative_match +0 -6
  157. data/test/configs/nohost +0 -19
  158. data/test/configs/numeric_host +0 -4
  159. data/test/configs/proxy_remote_user +0 -2
  160. data/test/configs/send_env +0 -2
  161. data/test/configs/substitutes +0 -8
  162. data/test/configs/wild_cards +0 -14
  163. data/test/connection/test_channel.rb +0 -487
  164. data/test/connection/test_session.rb +0 -564
  165. data/test/integration/README.txt +0 -17
  166. data/test/integration/Vagrantfile +0 -12
  167. data/test/integration/common.rb +0 -63
  168. data/test/integration/playbook.yml +0 -56
  169. data/test/integration/test_forward.rb +0 -637
  170. data/test/integration/test_id_rsa_keys.rb +0 -96
  171. data/test/integration/test_proxy.rb +0 -93
  172. data/test/known_hosts/github +0 -1
  173. data/test/known_hosts/github_hash +0 -1
  174. data/test/manual/test_pageant.rb +0 -37
  175. data/test/start/test_connection.rb +0 -53
  176. data/test/start/test_options.rb +0 -57
  177. data/test/start/test_transport.rb +0 -28
  178. data/test/start/test_user_nil.rb +0 -27
  179. data/test/test_all.rb +0 -12
  180. data/test/test_buffer.rb +0 -433
  181. data/test/test_buffered_io.rb +0 -63
  182. data/test/test_config.rb +0 -268
  183. data/test/test_key_factory.rb +0 -191
  184. data/test/test_known_hosts.rb +0 -66
  185. data/test/transport/hmac/test_md5.rb +0 -41
  186. data/test/transport/hmac/test_md5_96.rb +0 -27
  187. data/test/transport/hmac/test_none.rb +0 -34
  188. data/test/transport/hmac/test_ripemd160.rb +0 -36
  189. data/test/transport/hmac/test_sha1.rb +0 -36
  190. data/test/transport/hmac/test_sha1_96.rb +0 -27
  191. data/test/transport/hmac/test_sha2_256.rb +0 -37
  192. data/test/transport/hmac/test_sha2_256_96.rb +0 -27
  193. data/test/transport/hmac/test_sha2_512.rb +0 -37
  194. data/test/transport/hmac/test_sha2_512_96.rb +0 -27
  195. data/test/transport/kex/test_diffie_hellman_group14_sha1.rb +0 -13
  196. data/test/transport/kex/test_diffie_hellman_group1_sha1.rb +0 -150
  197. data/test/transport/kex/test_diffie_hellman_group_exchange_sha1.rb +0 -96
  198. data/test/transport/kex/test_diffie_hellman_group_exchange_sha256.rb +0 -19
  199. data/test/transport/kex/test_ecdh_sha2_nistp256.rb +0 -161
  200. data/test/transport/kex/test_ecdh_sha2_nistp384.rb +0 -38
  201. data/test/transport/kex/test_ecdh_sha2_nistp521.rb +0 -38
  202. data/test/transport/test_algorithms.rb +0 -328
  203. data/test/transport/test_cipher_factory.rb +0 -443
  204. data/test/transport/test_hmac.rb +0 -34
  205. data/test/transport/test_identity_cipher.rb +0 -40
  206. data/test/transport/test_packet_stream.rb +0 -1762
  207. data/test/transport/test_server_version.rb +0 -74
  208. data/test/transport/test_session.rb +0 -331
  209. data/test/transport/test_state.rb +0 -181
  210. 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