net-ssh 3.2.0.rc2 → 7.1.0

Sign up to get free protection for your applications and to get access to all the features.
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,564 +0,0 @@
1
- require 'common'
2
- require 'net/ssh/connection/session'
3
-
4
- module Connection
5
-
6
- class TestSession < Test::Unit::TestCase
7
- include Net::SSH::Connection::Constants
8
-
9
- def test_constructor_should_set_defaults
10
- assert session.channels.empty?
11
- assert session.pending_requests.empty?
12
- assert_equal({ socket => nil }, session.listeners)
13
- end
14
-
15
- def test_on_open_channel_should_register_block_with_given_channel_type
16
- flag = false
17
- session.on_open_channel("testing") { flag = true }
18
- assert_not_nil session.channel_open_handlers["testing"]
19
- session.channel_open_handlers["testing"].call
20
- assert flag, "callback should have been invoked"
21
- end
22
-
23
- def test_forward_should_create_and_cache_instance_of_forward_service
24
- assert_instance_of Net::SSH::Service::Forward, session.forward
25
- assert_equal session.forward.object_id, session.forward.object_id
26
- end
27
-
28
- def test_listen_to_without_callback_should_add_argument_as_listener
29
- io = stub("io")
30
- session.listen_to(io)
31
- assert session.listeners.key?(io)
32
- assert_nil session.listeners[io]
33
- end
34
-
35
- def test_listen_to_should_add_argument_to_listeners_list_if_block_is_given
36
- io = stub("io", :pending_write? => true)
37
- flag = false
38
- session.listen_to(io) { flag = true }
39
- assert !flag, "callback should not be invoked immediately"
40
- assert session.listeners.key?(io)
41
- session.listeners[io].call
42
- assert flag, "callback should have been invoked"
43
- end
44
-
45
- def test_stop_listening_to_should_remove_argument_from_listeners
46
- io = stub("io", :pending_write? => true)
47
-
48
- session.listen_to(io)
49
- assert session.listeners.key?(io)
50
-
51
- session.stop_listening_to(io)
52
- assert !session.listeners.key?(io)
53
- end
54
-
55
- def test_send_message_should_enqueue_message_at_transport_layer
56
- packet = P(:byte, REQUEST_SUCCESS)
57
- session.send_message(packet)
58
- assert_equal packet.to_s, socket.write_buffer
59
- end
60
-
61
- def test_open_channel_defaults_should_use_session_channel
62
- flag = false
63
- channel = session.open_channel { flag = true }
64
- assert !flag, "callback should not be invoked immediately"
65
- channel.do_open_confirmation(1,2,3)
66
- assert flag, "callback should have been invoked"
67
- assert_equal "session", channel.type
68
- assert_equal 0, channel.local_id
69
- assert_equal channel, session.channels[channel.local_id]
70
-
71
- packet = P(:byte, CHANNEL_OPEN, :string, "session", :long, channel.local_id,
72
- :long, channel.local_maximum_window_size, :long, channel.local_maximum_packet_size)
73
- assert_equal packet.to_s, socket.write_buffer
74
- end
75
-
76
- def test_open_channel_with_type_should_use_type
77
- channel = session.open_channel("direct-tcpip")
78
- assert_equal "direct-tcpip", channel.type
79
- packet = P(:byte, CHANNEL_OPEN, :string, "direct-tcpip", :long, channel.local_id,
80
- :long, channel.local_maximum_window_size, :long, channel.local_maximum_packet_size)
81
- assert_equal packet.to_s, socket.write_buffer
82
- end
83
-
84
- def test_open_channel_with_extras_should_append_extras_to_packet
85
- channel = session.open_channel("direct-tcpip", :string, "other.host", :long, 1234)
86
- packet = P(:byte, CHANNEL_OPEN, :string, "direct-tcpip", :long, channel.local_id,
87
- :long, channel.local_maximum_window_size, :long, channel.local_maximum_packet_size,
88
- :string, "other.host", :long, 1234)
89
- assert_equal packet.to_s, socket.write_buffer
90
- end
91
-
92
- def test_send_global_request_without_callback_should_not_expect_reply
93
- packet = P(:byte, GLOBAL_REQUEST, :string, "testing", :bool, false)
94
- session.send_global_request("testing")
95
- assert_equal packet.to_s, socket.write_buffer
96
- assert session.pending_requests.empty?
97
- end
98
-
99
- def test_send_global_request_with_callback_should_expect_reply
100
- packet = P(:byte, GLOBAL_REQUEST, :string, "testing", :bool, true)
101
- proc = Proc.new {}
102
- session.send_global_request("testing", &proc)
103
- assert_equal packet.to_s, socket.write_buffer
104
- assert_equal [proc], session.pending_requests
105
- end
106
-
107
- def test_send_global_request_with_extras_should_append_extras_to_packet
108
- packet = P(:byte, GLOBAL_REQUEST, :string, "testing", :bool, false, :string, "other.host", :long, 1234)
109
- session.send_global_request("testing", :string, "other.host", :long, 1234)
110
- assert_equal packet.to_s, socket.write_buffer
111
- end
112
-
113
- def test_process_should_exit_immediately_if_block_is_false
114
- session.channels[0] = stub("channel", :closing? => false)
115
- session.channels[0].expects(:process).never
116
- process_times(0)
117
- end
118
-
119
- def test_process_should_exit_after_processing_if_block_is_true_then_false
120
- session.channels[0] = stub("channel", :local_closed? => false)
121
- session.channels[0].expects(:process)
122
- IO.expects(:select).never
123
- process_times(2)
124
- end
125
-
126
- def test_process_should_not_process_channels_that_are_closing
127
- session.channels[0] = stub("channel", :local_closed? => true)
128
- session.channels[0].expects(:process).never
129
- IO.expects(:select).never
130
- process_times(2)
131
- end
132
-
133
- def test_global_request_packets_should_be_silently_handled_if_no_handler_exists_for_them
134
- transport.return(GLOBAL_REQUEST, :string, "testing", :bool, false)
135
- process_times(2)
136
- assert transport.queue.empty?
137
- assert !socket.pending_write?
138
- end
139
-
140
- def test_global_request_packets_should_be_auto_replied_to_even_if_no_handler_exists
141
- transport.return(GLOBAL_REQUEST, :string, "testing", :bool, true)
142
- process_times(2)
143
- assert_equal P(:byte, REQUEST_FAILURE).to_s, socket.write_buffer
144
- end
145
-
146
- def test_global_request_handler_should_not_trigger_auto_reply_if_no_reply_is_wanted
147
- flag = false
148
- session.on_global_request("testing") { flag = true }
149
- assert !flag, "callback should not be invoked yet"
150
- transport.return(GLOBAL_REQUEST, :string, "testing", :bool, false)
151
- process_times(2)
152
- assert transport.queue.empty?
153
- assert !socket.pending_write?
154
- assert flag, "callback should have been invoked"
155
- end
156
-
157
- def test_global_request_handler_returning_true_should_trigger_success_auto_reply
158
- flag = false
159
- session.on_global_request("testing") { flag = true }
160
- transport.return(GLOBAL_REQUEST, :string, "testing", :bool, true)
161
- process_times(2)
162
- assert_equal P(:byte, REQUEST_SUCCESS).to_s, socket.write_buffer
163
- assert flag
164
- end
165
-
166
- def test_global_request_handler_returning_false_should_trigger_failure_auto_reply
167
- flag = false
168
- session.on_global_request("testing") { flag = true; false }
169
- transport.return(GLOBAL_REQUEST, :string, "testing", :bool, true)
170
- process_times(2)
171
- assert_equal P(:byte, REQUEST_FAILURE).to_s, socket.write_buffer
172
- assert flag
173
- end
174
-
175
- def test_global_request_handler_returning_sent_should_not_trigger_auto_reply
176
- flag = false
177
- session.on_global_request("testing") { flag = true; :sent }
178
- transport.return(GLOBAL_REQUEST, :string, "testing", :bool, true)
179
- process_times(2)
180
- assert !socket.pending_write?
181
- assert flag
182
- end
183
-
184
- def test_global_request_handler_returning_other_value_should_raise_error
185
- transport.expects(:closed?).at_least_once.returns(false)
186
- session.on_global_request("testing") { "bug" }
187
- transport.return(GLOBAL_REQUEST, :string, "testing", :bool, true)
188
- assert_raises(RuntimeError) { process_times(2) }
189
- end
190
-
191
- def test_request_success_packets_should_invoke_next_pending_request_with_true
192
- result = nil
193
- session.pending_requests << Proc.new { |*args| result = args }
194
- transport.return(REQUEST_SUCCESS)
195
- process_times(2)
196
- assert_equal [true, P(:byte, REQUEST_SUCCESS)], result
197
- assert session.pending_requests.empty?
198
- end
199
-
200
- def test_request_failure_packets_should_invoke_next_pending_request_with_false
201
- result = nil
202
- session.pending_requests << Proc.new { |*args| result = args }
203
- transport.return(REQUEST_FAILURE)
204
- process_times(2)
205
- assert_equal [false, P(:byte, REQUEST_FAILURE)], result
206
- assert session.pending_requests.empty?
207
- end
208
-
209
- def test_channel_open_packet_without_corresponding_channel_open_handler_should_result_in_channel_open_failure
210
- transport.return(CHANNEL_OPEN, :string, "auth-agent", :long, 14, :long, 0x20000, :long, 0x10000)
211
- process_times(2)
212
- assert_equal P(:byte, CHANNEL_OPEN_FAILURE, :long, 14, :long, 3, :string, "unknown channel type auth-agent", :string, "").to_s, socket.write_buffer
213
- end
214
-
215
- def test_channel_open_packet_with_corresponding_handler_should_result_in_channel_open_failure_when_handler_returns_an_error
216
- transport.return(CHANNEL_OPEN, :string, "auth-agent", :long, 14, :long, 0x20000, :long, 0x10000)
217
- session.on_open_channel "auth-agent" do |s, ch, p|
218
- raise Net::SSH::ChannelOpenFailed.new(1234, "we iz in ur channelz!")
219
- end
220
- process_times(2)
221
- assert_equal P(:byte, CHANNEL_OPEN_FAILURE, :long, 14, :long, 1234, :string, "we iz in ur channelz!", :string, "").to_s, socket.write_buffer
222
- end
223
-
224
- def test_channel_open_packet_with_corresponding_handler_should_result_in_channel_open_confirmation_when_handler_succeeds
225
- transport.return(CHANNEL_OPEN, :string, "auth-agent", :long, 14, :long, 0x20001, :long, 0x10001)
226
- result = nil
227
- session.on_open_channel("auth-agent") { |*args| result = args }
228
- process_times(2)
229
- assert_equal P(:byte, CHANNEL_OPEN_CONFIRMATION, :long, 14, :long, 0, :long, 0x20000, :long, 0x8000).to_s, socket.write_buffer
230
- assert_not_nil(ch = session.channels[0])
231
- assert_equal [session, ch, P(:byte, CHANNEL_OPEN, :string, "auth-agent", :long, 14, :long, 0x20001, :long, 0x10001)], result
232
- assert_equal 0, ch.local_id
233
- assert_equal 14, ch.remote_id
234
- assert_equal 0x20001, ch.remote_maximum_window_size
235
- assert_equal 0x10001, ch.remote_maximum_packet_size
236
- assert_equal 0x20000, ch.local_maximum_window_size
237
- assert_equal 0x8000, ch.local_maximum_packet_size
238
- assert_equal "auth-agent", ch.type
239
- end
240
-
241
- def test_channel_open_failure_should_remove_channel_and_tell_channel_that_open_failed
242
- session.channels[1] = stub("channel")
243
- session.channels[1].expects(:do_open_failed).with(1234, "some reason")
244
- transport.return(CHANNEL_OPEN_FAILURE, :long, 1, :long, 1234, :string, "some reason", :string, "lang tag")
245
- process_times(2)
246
- assert session.channels.empty?
247
- end
248
-
249
- def test_channel_open_confirmation_packet_should_be_routed_to_corresponding_channel
250
- channel_at(14).expects(:do_open_confirmation).with(1234, 0x20001, 0x10001)
251
- transport.return(CHANNEL_OPEN_CONFIRMATION, :long, 14, :long, 1234, :long, 0x20001, :long, 0x10001)
252
- process_times(2)
253
- end
254
-
255
- def test_channel_window_adjust_packet_should_be_routed_to_corresponding_channel
256
- channel_at(14).expects(:do_window_adjust).with(5000)
257
- transport.return(CHANNEL_WINDOW_ADJUST, :long, 14, :long, 5000)
258
- process_times(2)
259
- end
260
-
261
- def test_channel_request_for_nonexistant_channel_should_be_ignored
262
- transport.return(CHANNEL_REQUEST, :long, 14, :string, "testing", :bool, false)
263
- assert_nothing_raised { process_times(2) }
264
- end
265
-
266
- def test_channel_request_packet_should_be_routed_to_corresponding_channel
267
- channel_at(14).expects(:do_request).with("testing", false, Net::SSH::Buffer.new)
268
- transport.return(CHANNEL_REQUEST, :long, 14, :string, "testing", :bool, false)
269
- process_times(2)
270
- end
271
-
272
- def test_channel_data_packet_should_be_routed_to_corresponding_channel
273
- channel_at(14).expects(:do_data).with("bring it on down")
274
- transport.return(CHANNEL_DATA, :long, 14, :string, "bring it on down")
275
- process_times(2)
276
- end
277
-
278
- def test_channel_extended_data_packet_should_be_routed_to_corresponding_channel
279
- channel_at(14).expects(:do_extended_data).with(1, "bring it on down")
280
- transport.return(CHANNEL_EXTENDED_DATA, :long, 14, :long, 1, :string, "bring it on down")
281
- process_times(2)
282
- end
283
-
284
- def test_channel_eof_packet_should_be_routed_to_corresponding_channel
285
- channel_at(14).expects(:do_eof).with()
286
- transport.return(CHANNEL_EOF, :long, 14)
287
- process_times(2)
288
- end
289
-
290
- def test_channel_success_packet_should_be_routed_to_corresponding_channel
291
- channel_at(14).expects(:do_success).with()
292
- transport.return(CHANNEL_SUCCESS, :long, 14)
293
- process_times(2)
294
- end
295
-
296
- def test_channel_failure_packet_should_be_routed_to_corresponding_channel
297
- channel_at(14).expects(:do_failure).with()
298
- transport.return(CHANNEL_FAILURE, :long, 14)
299
- process_times(2)
300
- end
301
-
302
- def test_channel_close_packet_should_be_routed_to_corresponding_channel_and_channel_should_be_closed_and_removed
303
- session.channels[14] = stub("channel") do
304
- # this simulates the case where we closed the channel first, sent
305
- # CHANNEL_CLOSE to server and are waiting for server's response.
306
- expects(:local_closed?).returns(true)
307
- expects(:do_close)
308
- expects(:close).with()
309
- expects(:remote_closed!).with()
310
- expects(:remote_closed?).with().returns(true)
311
- expects(:local_id).returns(14)
312
- end
313
-
314
- transport.return(CHANNEL_CLOSE, :long, 14)
315
- process_times(2)
316
- assert session.channels.empty?
317
- end
318
-
319
- def test_multiple_pending_dispatches_should_be_dispatched_together
320
- channel_at(14).expects(:do_eof).with()
321
- session.channels[14].expects(:do_success).with()
322
- transport.return(CHANNEL_SUCCESS, :long, 14)
323
- transport.return(CHANNEL_EOF, :long, 14)
324
- process_times(2)
325
- end
326
-
327
- def test_writers_without_pending_writes_should_not_be_considered_for_select
328
- IO.expects(:select).with([socket],[],nil,nil).returns([[],[],[]])
329
- session.process
330
- end
331
-
332
- def test_writers_with_pending_writes_should_be_considered_for_select
333
- socket.enqueue("laksdjflasdkf")
334
- IO.expects(:select).with([socket],[socket],nil,nil).returns([[],[],[]])
335
- session.process
336
- end
337
-
338
- def test_ready_readers_should_be_filled
339
- socket.expects(:recv).returns("this is some data")
340
- IO.expects(:select).with([socket],[],nil,nil).returns([[socket],[],[]])
341
- session.process
342
- assert_equal [socket], session.listeners.keys
343
- end
344
-
345
- def test_ready_readers_that_cant_be_filled_should_be_removed
346
- socket.expects(:recv).returns("")
347
- socket.expects(:close)
348
- IO.expects(:select).with([socket],[],nil,nil).returns([[socket],[],[]])
349
- session.process
350
- assert session.listeners.empty?
351
- end
352
-
353
- def test_ready_readers_that_are_registered_with_a_block_should_call_block_instead_of_fill
354
- io = stub("io", :pending_write? => false)
355
- flag = false
356
- session.stop_listening_to(socket) # so that we only have to test the presence of a single IO object
357
- session.listen_to(io) { flag = true }
358
- IO.expects(:select).with([io],[],nil,nil).returns([[io],[],[]])
359
- session.process
360
- assert flag, "callback should have been invoked"
361
- end
362
-
363
- def test_ready_writers_should_call_send_pending
364
- socket.enqueue("laksdjflasdkf")
365
- socket.expects(:send).with("laksdjflasdkf", 0).returns(13)
366
- IO.expects(:select).with([socket],[socket],nil,nil).returns([[],[socket],[]])
367
- session.process
368
- end
369
-
370
- def test_process_should_call_rekey_as_needed
371
- transport.expects(:rekey_as_needed)
372
- IO.expects(:select).with([socket],[],nil,nil).returns([[],[],[]])
373
- session.process
374
- end
375
-
376
- def test_process_should_call_enqueue_message_if_io_select_timed_out
377
- timeout = Net::SSH::Connection::Session::DEFAULT_IO_SELECT_TIMEOUT
378
- options = { :keepalive => true }
379
- expected_packet = P(:byte, Net::SSH::Packet::GLOBAL_REQUEST, :string, "keepalive@openssh.com", :bool, true)
380
- IO.stubs(:select).with([socket],[],nil,timeout).returns(nil)
381
- transport.expects(:enqueue_message).with{ |msg| msg.content == expected_packet.content }
382
- session(options).process
383
- end
384
-
385
- def test_process_should_raise_if_keepalives_not_answered
386
- timeout = Net::SSH::Connection::Session::DEFAULT_IO_SELECT_TIMEOUT
387
- options = { :keepalive => true, :keepalive_interval => 300, :keepalive_maxcount => 3 }
388
- expected_packet = P(:byte, Net::SSH::Packet::GLOBAL_REQUEST, :string, "keepalive@openssh.com", :bool, true)
389
- [1,2,3].each do |i|
390
- Time.stubs(:now).returns(Time.at(i*300))
391
- IO.stubs(:select).with([socket],[],nil,timeout).returns(nil)
392
- transport.expects(:enqueue_message).with{ |msg| msg.content == expected_packet.content }
393
- session(options).process
394
- end
395
-
396
- Time.stubs(:now).returns(Time.at(4*300))
397
- IO.stubs(:select).with([socket],[],nil,timeout).returns(nil)
398
- transport.expects(:enqueue_message).with{ |msg| msg.content == expected_packet.content }
399
- assert_raises(Net::SSH::Timeout) { session(options).process }
400
- end
401
-
402
- def test_process_should_not_call_enqueue_message_unless_io_select_timed_out
403
- timeout = Net::SSH::Connection::Session::DEFAULT_IO_SELECT_TIMEOUT
404
- options = { :keepalive => true }
405
- IO.stubs(:select).with([socket],[],nil,timeout).returns([[],[],[]])
406
- transport.expects(:enqueue_message).never
407
- session(options).process
408
- end
409
-
410
- def test_process_should_not_call_enqueue_message_unless_keepalive_interval_not_go_on
411
- timeout = 10
412
- options = { :keepalive => true, :keepalive_interval => timeout }
413
- Time.stubs(:now).returns(Time.at(0), Time.at(9), Time.at(timeout))
414
- IO.stubs(:select).with([socket],[],nil,timeout).returns(nil)
415
- transport.expects(:enqueue_message).times(2)
416
- 3.times { session(options).process }
417
- end
418
-
419
- def test_process_should_call_io_select_with_nil_as_last_arg_if_keepalive_disabled
420
- IO.expects(:select).with([socket],[],nil,nil).returns([[],[],[]])
421
- session.process
422
- end
423
-
424
- def test_process_should_call_io_select_with_interval_as_last_arg_if_keepalive_interval_passed
425
- timeout = 10
426
- options = { :keepalive => true, :keepalive_interval => timeout }
427
- IO.expects(:select).with([socket],[],nil,timeout).returns([[],[],[]])
428
- session(options).process
429
- end
430
-
431
- def test_process_should_call_io_select_with_wait_if_provided_and_minimum
432
- timeout = 10
433
- wait = 5
434
- options = { :keepalive => true, :keepalive_interval => timeout }
435
- IO.expects(:select).with([socket],[],nil,wait).returns([[],[],[]])
436
- session(options).process(wait)
437
- end
438
-
439
- def test_loop_should_call_process_until_process_returns_false
440
- IO.stubs(:select).with([socket],[],nil,nil).returns([[],[],[]])
441
- session.expects(:process).with(nil).times(4).returns(true,true,true,false).yields
442
- n = 0
443
- session.loop { n += 1 }
444
- assert_equal 4, n
445
- end
446
-
447
- def test_exec_should_open_channel_and_configure_default_callbacks
448
- prep_exec("ls", :stdout, "data packet", :stderr, "extended data packet")
449
-
450
- call = :first
451
- session.exec "ls" do |channel, type, data|
452
- if call == :first
453
- assert_equal :stdout, type
454
- assert_equal "data packet", data
455
- call = :second
456
- elsif call == :second
457
- assert_equal :stderr, type
458
- assert_equal "extended data packet", data
459
- call = :third
460
- else
461
- flunk "should never get here, call == #{call.inspect}"
462
- end
463
- end
464
-
465
- session.loop
466
- assert_equal :third, call
467
- end
468
-
469
- def test_exec_without_block_should_use_print_to_display_result
470
- prep_exec("ls", :stdout, "data packet", :stderr, "extended data packet")
471
- $stdout.expects(:print).with("data packet")
472
- $stderr.expects(:print).with("extended data packet")
473
-
474
- session.exec "ls"
475
- session.loop
476
- end
477
-
478
- def test_exec_bang_should_block_until_command_finishes
479
- prep_exec("ls", :stdout, "some data")
480
- called = false
481
- session.exec! "ls" do |channel, type, data|
482
- called = true
483
- assert_equal :stdout, type
484
- assert_equal "some data", data
485
- end
486
- assert called
487
- end
488
-
489
- def test_exec_bang_without_block_should_return_data_as_string
490
- prep_exec("ls", :stdout, "some data")
491
- assert_equal "some data", session.exec!("ls")
492
- end
493
-
494
- def test_exec_bang_without_block_should_return_empty_string_for_empty_command_output
495
- prep_exec('ls', :stdout, '')
496
- assert_equal "", session.exec!('ls')
497
- end
498
-
499
- private
500
-
501
- def prep_exec(command, *data)
502
- transport.mock_enqueue = true
503
- transport.expect do |t, p|
504
- assert_equal CHANNEL_OPEN, p.type
505
- t.return(CHANNEL_OPEN_CONFIRMATION, :long, p[:remote_id], :long, 0, :long, 0x20000, :long, 0x10000)
506
- t.expect do |t2, p2|
507
- assert_equal CHANNEL_REQUEST, p2.type
508
- assert_equal "exec", p2[:request]
509
- assert_equal true, p2[:want_reply]
510
- assert_equal "ls", p2.read_string
511
-
512
- t2.return(CHANNEL_SUCCESS, :long, p[:remote_id])
513
-
514
- data.each_slice(2) do |type, datum|
515
- next if datum.empty?
516
- if type == :stdout
517
- t2.return(CHANNEL_DATA, :long, p[:remote_id], :string, datum)
518
- else
519
- t2.return(CHANNEL_EXTENDED_DATA, :long, p[:remote_id], :long, 1, :string, datum)
520
- end
521
- end
522
-
523
- t2.return(CHANNEL_CLOSE, :long, p[:remote_id])
524
- t2.expect { |t3,p3| assert_equal CHANNEL_CLOSE, p3.type }
525
- end
526
- end
527
- end
528
-
529
- module MockSocket
530
- # so that we can easily test the contents that were enqueued, without
531
- # worrying about all the packet stream overhead
532
- def enqueue_packet(message)
533
- enqueue(message.to_s)
534
- end
535
- end
536
-
537
- def socket
538
- @socket ||= begin
539
- socket ||= Object.new
540
- socket.extend(Net::SSH::Transport::PacketStream)
541
- socket.extend(MockSocket)
542
- socket
543
- end
544
- end
545
-
546
- def channel_at(local_id)
547
- session.channels[local_id] = stub("channel", :process => true, :local_closed? => false)
548
- end
549
-
550
- def transport(options={})
551
- @transport ||= MockTransport.new(options.merge(:socket => socket))
552
- end
553
-
554
- def session(options={})
555
- @session ||= Net::SSH::Connection::Session.new(transport, options)
556
- end
557
-
558
- def process_times(n)
559
- i = 0
560
- session.process { (i += 1) < n }
561
- end
562
- end
563
-
564
- end
@@ -1,17 +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
- rake test
13
-
14
- # TODO
15
-
16
- * get it running on ci (probalby needs docker)
17
- * 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,63 +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
- def sh command
11
- puts "$ #{command}"
12
- res = system(command)
13
- status = $?
14
- raise "Command: #{command} failed:#{status.exitstatus}" unless res
15
- end
16
-
17
- def tmpdir(&block)
18
- Dir.mktmpdir do |dir|
19
- yield(dir)
20
- end
21
- end
22
-
23
- def set_authorized_key(user,pubkey)
24
- authorized_key = "/home/#{user}/.ssh/authorized_keys"
25
- sh "sudo cp #{pubkey} #{authorized_key}"
26
- sh "sudo chown #{user} #{authorized_key}"
27
- sh "sudo chmod 0744 #{authorized_key}"
28
- end
29
-
30
- def with_agent(&block)
31
- puts "/usr/bin/ssh-agent -c"
32
- agent_out = `/usr/bin/ssh-agent -c`
33
- agent_out.split("\n").each do |line|
34
- if line =~ /setenv (\S+) (\S+);/
35
- ENV[$1] = $2
36
- puts "ENV[#{$1}]=#{$2}"
37
- end
38
- end
39
- begin
40
- yield
41
- ensure
42
- sh "/usr/bin/ssh-agent -k"
43
- end
44
- end
45
-
46
- def ssh_add(key,password)
47
- command = "ssh-add #{key}"
48
- status = nil
49
- PTY.spawn(command) do |reader, writer, pid|
50
- begin
51
- reader.expect(/Enter passphrase for .*:/) { |data| puts data }
52
- writer.puts(password)
53
- until reader.eof? do
54
- puts reader.readline
55
- end
56
- rescue Errno::EIO => e
57
- end
58
- pid, status = Process.wait2 pid
59
- end
60
- raise "Command: #{command} failed:#{status.exitstatus}" unless status
61
- status.exitstatus
62
- end
63
- end