net-ssh 3.2.0 → 7.2.0.rc1

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 (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,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