ddollar-net-ssh 2.0.1
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.
- data/CHANGELOG.rdoc +42 -0
- data/Manifest +101 -0
- data/README.rdoc +110 -0
- data/Rakefile +26 -0
- data/THANKS.rdoc +16 -0
- data/lib/net/ssh.rb +199 -0
- data/lib/net/ssh/authentication/agent.rb +175 -0
- data/lib/net/ssh/authentication/constants.rb +18 -0
- data/lib/net/ssh/authentication/key_manager.rb +169 -0
- data/lib/net/ssh/authentication/methods/abstract.rb +60 -0
- data/lib/net/ssh/authentication/methods/hostbased.rb +71 -0
- data/lib/net/ssh/authentication/methods/keyboard_interactive.rb +66 -0
- data/lib/net/ssh/authentication/methods/password.rb +39 -0
- data/lib/net/ssh/authentication/methods/publickey.rb +92 -0
- data/lib/net/ssh/authentication/pageant.rb +176 -0
- data/lib/net/ssh/authentication/session.rb +127 -0
- data/lib/net/ssh/buffer.rb +339 -0
- data/lib/net/ssh/buffered_io.rb +149 -0
- data/lib/net/ssh/config.rb +173 -0
- data/lib/net/ssh/connection/channel.rb +625 -0
- data/lib/net/ssh/connection/constants.rb +33 -0
- data/lib/net/ssh/connection/session.rb +569 -0
- data/lib/net/ssh/connection/term.rb +178 -0
- data/lib/net/ssh/errors.rb +85 -0
- data/lib/net/ssh/key_factory.rb +85 -0
- data/lib/net/ssh/known_hosts.rb +129 -0
- data/lib/net/ssh/loggable.rb +61 -0
- data/lib/net/ssh/packet.rb +102 -0
- data/lib/net/ssh/prompt.rb +93 -0
- data/lib/net/ssh/proxy/errors.rb +14 -0
- data/lib/net/ssh/proxy/http.rb +94 -0
- data/lib/net/ssh/proxy/socks4.rb +70 -0
- data/lib/net/ssh/proxy/socks5.rb +128 -0
- data/lib/net/ssh/service/forward.rb +267 -0
- data/lib/net/ssh/test.rb +89 -0
- data/lib/net/ssh/test/channel.rb +129 -0
- data/lib/net/ssh/test/extensions.rb +152 -0
- data/lib/net/ssh/test/kex.rb +44 -0
- data/lib/net/ssh/test/local_packet.rb +51 -0
- data/lib/net/ssh/test/packet.rb +81 -0
- data/lib/net/ssh/test/remote_packet.rb +38 -0
- data/lib/net/ssh/test/script.rb +157 -0
- data/lib/net/ssh/test/socket.rb +59 -0
- data/lib/net/ssh/transport/algorithms.rb +384 -0
- data/lib/net/ssh/transport/cipher_factory.rb +72 -0
- data/lib/net/ssh/transport/constants.rb +30 -0
- data/lib/net/ssh/transport/hmac.rb +31 -0
- data/lib/net/ssh/transport/hmac/abstract.rb +48 -0
- data/lib/net/ssh/transport/hmac/md5.rb +12 -0
- data/lib/net/ssh/transport/hmac/md5_96.rb +11 -0
- data/lib/net/ssh/transport/hmac/none.rb +15 -0
- data/lib/net/ssh/transport/hmac/sha1.rb +13 -0
- data/lib/net/ssh/transport/hmac/sha1_96.rb +11 -0
- data/lib/net/ssh/transport/identity_cipher.rb +40 -0
- data/lib/net/ssh/transport/kex.rb +13 -0
- data/lib/net/ssh/transport/kex/diffie_hellman_group1_sha1.rb +208 -0
- data/lib/net/ssh/transport/kex/diffie_hellman_group_exchange_sha1.rb +77 -0
- data/lib/net/ssh/transport/openssl.rb +128 -0
- data/lib/net/ssh/transport/packet_stream.rb +230 -0
- data/lib/net/ssh/transport/server_version.rb +61 -0
- data/lib/net/ssh/transport/session.rb +262 -0
- data/lib/net/ssh/transport/state.rb +170 -0
- data/lib/net/ssh/verifiers/lenient.rb +30 -0
- data/lib/net/ssh/verifiers/null.rb +12 -0
- data/lib/net/ssh/verifiers/strict.rb +53 -0
- data/lib/net/ssh/version.rb +60 -0
- data/net-ssh.gemspec +56 -0
- data/setup.rb +1585 -0
- data/test/authentication/methods/common.rb +28 -0
- data/test/authentication/methods/test_abstract.rb +51 -0
- data/test/authentication/methods/test_hostbased.rb +108 -0
- data/test/authentication/methods/test_keyboard_interactive.rb +98 -0
- data/test/authentication/methods/test_password.rb +50 -0
- data/test/authentication/methods/test_publickey.rb +123 -0
- data/test/authentication/test_agent.rb +205 -0
- data/test/authentication/test_key_manager.rb +100 -0
- data/test/authentication/test_session.rb +93 -0
- data/test/common.rb +106 -0
- data/test/configs/exact_match +8 -0
- data/test/configs/wild_cards +14 -0
- data/test/connection/test_channel.rb +452 -0
- data/test/connection/test_session.rb +483 -0
- data/test/test_all.rb +6 -0
- data/test/test_buffer.rb +336 -0
- data/test/test_buffered_io.rb +63 -0
- data/test/test_config.rb +78 -0
- data/test/test_key_factory.rb +67 -0
- data/test/transport/hmac/test_md5.rb +34 -0
- data/test/transport/hmac/test_md5_96.rb +25 -0
- data/test/transport/hmac/test_none.rb +34 -0
- data/test/transport/hmac/test_sha1.rb +34 -0
- data/test/transport/hmac/test_sha1_96.rb +25 -0
- data/test/transport/kex/test_diffie_hellman_group1_sha1.rb +146 -0
- data/test/transport/kex/test_diffie_hellman_group_exchange_sha1.rb +92 -0
- data/test/transport/test_algorithms.rb +302 -0
- data/test/transport/test_cipher_factory.rb +163 -0
- data/test/transport/test_hmac.rb +34 -0
- data/test/transport/test_identity_cipher.rb +40 -0
- data/test/transport/test_packet_stream.rb +433 -0
- data/test/transport/test_server_version.rb +55 -0
- data/test/transport/test_session.rb +312 -0
- data/test/transport/test_state.rb +173 -0
- metadata +222 -0
@@ -0,0 +1,55 @@
|
|
1
|
+
require 'common'
|
2
|
+
require 'net/ssh/transport/server_version'
|
3
|
+
|
4
|
+
module Transport
|
5
|
+
|
6
|
+
class TestServerVersion < Test::Unit::TestCase
|
7
|
+
|
8
|
+
def test_1_99_server_version_should_be_acceptible
|
9
|
+
s = subject(socket(true, "SSH-1.99-Testing_1.0\r\n"))
|
10
|
+
assert s.header.empty?
|
11
|
+
assert_equal "SSH-1.99-Testing_1.0", s.version
|
12
|
+
end
|
13
|
+
|
14
|
+
def test_2_0_server_version_should_be_acceptible
|
15
|
+
s = subject(socket(true, "SSH-2.0-Testing_1.0\r\n"))
|
16
|
+
assert s.header.empty?
|
17
|
+
assert_equal "SSH-2.0-Testing_1.0", s.version
|
18
|
+
end
|
19
|
+
|
20
|
+
def test_trailing_whitespace_should_be_stripped
|
21
|
+
s = subject(socket(true, "SSH-2.0-Testing_1.0 \r\n"))
|
22
|
+
assert_equal "SSH-2.0-Testing_1.0", s.version
|
23
|
+
end
|
24
|
+
|
25
|
+
def test_unacceptible_server_version_should_raise_exception
|
26
|
+
assert_raises(Net::SSH::Exception) { subject(socket(false, "SSH-1.4-Testing_1.0\r\n")) }
|
27
|
+
end
|
28
|
+
|
29
|
+
def test_header_lines_should_be_accumulated
|
30
|
+
s = subject(socket(true, "Welcome\r\n", "Another line\r\n", "SSH-2.0-Testing_1.0\r\n"))
|
31
|
+
assert_equal "Welcome\r\nAnother line\r\n", s.header
|
32
|
+
assert_equal "SSH-2.0-Testing_1.0", s.version
|
33
|
+
end
|
34
|
+
|
35
|
+
private
|
36
|
+
|
37
|
+
def socket(good, *lines)
|
38
|
+
socket = mock("socket")
|
39
|
+
socket.expects(:readline).times(lines.length).returns(*lines)
|
40
|
+
|
41
|
+
if good
|
42
|
+
socket.expects(:write).with("#{Net::SSH::Transport::ServerVersion::PROTO_VERSION}\r\n")
|
43
|
+
else
|
44
|
+
socket.expects(:write).never
|
45
|
+
end
|
46
|
+
|
47
|
+
socket
|
48
|
+
end
|
49
|
+
|
50
|
+
def subject(socket)
|
51
|
+
Net::SSH::Transport::ServerVersion.new(socket, nil)
|
52
|
+
end
|
53
|
+
end
|
54
|
+
|
55
|
+
end
|
@@ -0,0 +1,312 @@
|
|
1
|
+
require 'common'
|
2
|
+
require 'net/ssh/transport/session'
|
3
|
+
|
4
|
+
# mocha adds #verify to Object, which throws off the host-key-verifier part of
|
5
|
+
# these tests.
|
6
|
+
|
7
|
+
Object.send(:undef_method, :verify)
|
8
|
+
|
9
|
+
module Transport
|
10
|
+
|
11
|
+
class TestSession < Test::Unit::TestCase
|
12
|
+
include Net::SSH::Transport::Constants
|
13
|
+
|
14
|
+
def test_constructor_defaults
|
15
|
+
assert_equal "net.ssh.test", session.host
|
16
|
+
assert_equal 22, session.port
|
17
|
+
assert_instance_of Net::SSH::Verifiers::Lenient, session.host_key_verifier
|
18
|
+
end
|
19
|
+
|
20
|
+
def test_paranoid_true_uses_lenient_verifier
|
21
|
+
assert_instance_of Net::SSH::Verifiers::Lenient, session(:paranoid => true).host_key_verifier
|
22
|
+
end
|
23
|
+
|
24
|
+
def test_paranoid_very_uses_strict_verifier
|
25
|
+
assert_instance_of Net::SSH::Verifiers::Strict, session(:paranoid => :very).host_key_verifier
|
26
|
+
end
|
27
|
+
|
28
|
+
def test_paranoid_false_uses_null_verifier
|
29
|
+
assert_instance_of Net::SSH::Verifiers::Null, session(:paranoid => false).host_key_verifier
|
30
|
+
end
|
31
|
+
|
32
|
+
def test_unknown_paranoid_value_raises_exception_if_value_does_not_respond_to_verify
|
33
|
+
assert_raises(ArgumentError) { session(:paranoid => :bogus).host_key_verifier }
|
34
|
+
end
|
35
|
+
|
36
|
+
def test_paranoid_value_responding_to_verify_should_pass_muster
|
37
|
+
object = stub("thingy", :verify => true)
|
38
|
+
assert_equal object, session(:paranoid => object).host_key_verifier
|
39
|
+
end
|
40
|
+
|
41
|
+
def test_host_as_string_should_return_host_and_ip_when_port_is_default
|
42
|
+
session!
|
43
|
+
socket.stubs(:peer_ip).returns("1.2.3.4")
|
44
|
+
assert_equal "net.ssh.test,1.2.3.4", session.host_as_string
|
45
|
+
end
|
46
|
+
|
47
|
+
def test_host_as_string_should_return_host_and_ip_with_port_when_port_is_not_default
|
48
|
+
session(:port => 1234) # force session to be instantiated
|
49
|
+
socket.stubs(:peer_ip).returns("1.2.3.4")
|
50
|
+
assert_equal "[net.ssh.test]:1234,[1.2.3.4]:1234", session.host_as_string
|
51
|
+
end
|
52
|
+
|
53
|
+
def test_host_as_string_should_return_only_host_when_host_is_ip
|
54
|
+
session!(:host => "1.2.3.4")
|
55
|
+
socket.stubs(:peer_ip).returns("1.2.3.4")
|
56
|
+
assert_equal "1.2.3.4", session.host_as_string
|
57
|
+
end
|
58
|
+
|
59
|
+
def test_host_as_string_should_return_only_host_and_port_when_host_is_ip_and_port_is_not_default
|
60
|
+
session!(:host => "1.2.3.4", :port => 1234)
|
61
|
+
socket.stubs(:peer_ip).returns("1.2.3.4")
|
62
|
+
assert_equal "[1.2.3.4]:1234", session.host_as_string
|
63
|
+
end
|
64
|
+
|
65
|
+
def test_close_should_cleanup_and_close_socket
|
66
|
+
session!
|
67
|
+
socket.expects(:cleanup)
|
68
|
+
socket.expects(:close)
|
69
|
+
session.close
|
70
|
+
end
|
71
|
+
|
72
|
+
def test_service_request_should_return_buffer
|
73
|
+
assert_equal "\005\000\000\000\004sftp", session.service_request('sftp').to_s
|
74
|
+
end
|
75
|
+
|
76
|
+
def test_rekey_when_kex_is_pending_should_do_nothing
|
77
|
+
algorithms.stubs(:pending? => true)
|
78
|
+
algorithms.expects(:rekey!).never
|
79
|
+
session.rekey!
|
80
|
+
end
|
81
|
+
|
82
|
+
def test_rekey_when_no_kex_is_pending_should_initiate_rekey_and_block_until_it_completes
|
83
|
+
algorithms.stubs(:pending? => false)
|
84
|
+
algorithms.expects(:rekey!)
|
85
|
+
session.expects(:wait).yields
|
86
|
+
algorithms.expects(:initialized?).returns(true)
|
87
|
+
session.rekey!
|
88
|
+
end
|
89
|
+
|
90
|
+
def test_rekey_as_needed_when_kex_is_pending_should_do_nothing
|
91
|
+
session!
|
92
|
+
algorithms.stubs(:pending? => true)
|
93
|
+
socket.expects(:if_needs_rekey?).never
|
94
|
+
session.rekey_as_needed
|
95
|
+
end
|
96
|
+
|
97
|
+
def test_rekey_as_needed_when_no_kex_is_pending_and_no_rekey_is_needed_should_do_nothing
|
98
|
+
session!
|
99
|
+
algorithms.stubs(:pending? => false)
|
100
|
+
socket.stubs(:if_needs_rekey? => false)
|
101
|
+
session.expects(:rekey!).never
|
102
|
+
session.rekey_as_needed
|
103
|
+
end
|
104
|
+
|
105
|
+
def test_rekey_as_needed_when_no_kex_is_pending_and_rekey_is_needed_should_initiate_rekey_and_block
|
106
|
+
session!
|
107
|
+
algorithms.stubs(:pending? => false)
|
108
|
+
socket.expects(:if_needs_rekey?).yields
|
109
|
+
session.expects(:rekey!)
|
110
|
+
session.rekey_as_needed
|
111
|
+
end
|
112
|
+
|
113
|
+
def test_peer_should_return_hash_of_info_about_peer
|
114
|
+
session!
|
115
|
+
socket.stubs(:peer_ip => "1.2.3.4")
|
116
|
+
assert_equal({:ip => "1.2.3.4", :port => 22, :host => "net.ssh.test", :canonized => "net.ssh.test,1.2.3.4"}, session.peer)
|
117
|
+
end
|
118
|
+
|
119
|
+
def test_next_message_should_block_until_next_message_is_available
|
120
|
+
session.expects(:poll_message).with(:block)
|
121
|
+
session.next_message
|
122
|
+
end
|
123
|
+
|
124
|
+
def test_poll_message_should_query_next_packet_using_the_given_blocking_parameter
|
125
|
+
session!
|
126
|
+
socket.expects(:next_packet).with(:blocking_parameter).returns(nil)
|
127
|
+
session.poll_message(:blocking_parameter)
|
128
|
+
end
|
129
|
+
|
130
|
+
def test_poll_message_should_default_to_non_blocking
|
131
|
+
session!
|
132
|
+
socket.expects(:next_packet).with(:nonblock).returns(nil)
|
133
|
+
session.poll_message
|
134
|
+
end
|
135
|
+
|
136
|
+
def test_poll_message_should_silently_handle_disconnect_packets
|
137
|
+
session!
|
138
|
+
socket.expects(:next_packet).returns(P(:byte, DISCONNECT, :long, 1, :string, "testing", :string, ""))
|
139
|
+
assert_raises(Net::SSH::Disconnect) { session.poll_message }
|
140
|
+
end
|
141
|
+
|
142
|
+
def test_poll_message_should_silently_handle_ignore_packets
|
143
|
+
session!
|
144
|
+
socket.expects(:next_packet).times(2).returns(P(:byte, IGNORE, :string, "test"), nil)
|
145
|
+
assert_nil session.poll_message
|
146
|
+
end
|
147
|
+
|
148
|
+
def test_poll_message_should_silently_handle_unimplemented_packets
|
149
|
+
session!
|
150
|
+
socket.expects(:next_packet).times(2).returns(P(:byte, UNIMPLEMENTED, :long, 15), nil)
|
151
|
+
assert_nil session.poll_message
|
152
|
+
end
|
153
|
+
|
154
|
+
def test_poll_message_should_silently_handle_debug_packets_with_always_display
|
155
|
+
session!
|
156
|
+
socket.expects(:next_packet).times(2).returns(P(:byte, DEBUG, :bool, true, :string, "testing", :string, ""), nil)
|
157
|
+
assert_nil session.poll_message
|
158
|
+
end
|
159
|
+
|
160
|
+
def test_poll_message_should_silently_handle_debug_packets_without_always_display
|
161
|
+
session!
|
162
|
+
socket.expects(:next_packet).times(2).returns(P(:byte, DEBUG, :bool, false, :string, "testing", :string, ""), nil)
|
163
|
+
assert_nil session.poll_message
|
164
|
+
end
|
165
|
+
|
166
|
+
def test_poll_message_should_silently_handle_kexinit_packets
|
167
|
+
session!
|
168
|
+
packet = P(:byte, KEXINIT, :raw, "lasdfalksdjfa;slkdfja;slkfjsdfaklsjdfa;df")
|
169
|
+
socket.expects(:next_packet).times(2).returns(packet, nil)
|
170
|
+
algorithms.expects(:accept_kexinit).with(packet)
|
171
|
+
assert_nil session.poll_message
|
172
|
+
end
|
173
|
+
|
174
|
+
def test_poll_message_should_return_other_packets
|
175
|
+
session!
|
176
|
+
packet = P(:byte, SERVICE_ACCEPT, :string, "test")
|
177
|
+
socket.expects(:next_packet).returns(packet)
|
178
|
+
assert_equal packet, session.poll_message
|
179
|
+
end
|
180
|
+
|
181
|
+
def test_poll_message_should_enqueue_packets_when_algorithm_disallows_packet
|
182
|
+
session!
|
183
|
+
packet = P(:byte, SERVICE_ACCEPT, :string, "test")
|
184
|
+
algorithms.stubs(:allow?).with(packet).returns(false)
|
185
|
+
socket.expects(:next_packet).times(2).returns(packet, nil)
|
186
|
+
assert_nil session.poll_message
|
187
|
+
assert_equal [packet], session.queue
|
188
|
+
end
|
189
|
+
|
190
|
+
def test_poll_message_should_read_from_queue_when_next_in_queue_is_allowed_and_consume_queue_is_true
|
191
|
+
session!
|
192
|
+
packet = P(:byte, SERVICE_ACCEPT, :string, "test")
|
193
|
+
session.push(packet)
|
194
|
+
socket.expects(:next_packet).never
|
195
|
+
assert_equal packet, session.poll_message
|
196
|
+
assert session.queue.empty?
|
197
|
+
end
|
198
|
+
|
199
|
+
def test_poll_message_should_not_read_from_queue_when_next_in_queue_is_not_allowed
|
200
|
+
session!
|
201
|
+
packet = P(:byte, SERVICE_ACCEPT, :string, "test")
|
202
|
+
algorithms.stubs(:allow?).with(packet).returns(false)
|
203
|
+
session.push(packet)
|
204
|
+
socket.expects(:next_packet).returns(nil)
|
205
|
+
assert_nil session.poll_message
|
206
|
+
assert_equal [packet], session.queue
|
207
|
+
end
|
208
|
+
|
209
|
+
def test_poll_message_should_not_read_from_queue_when_consume_queue_is_false
|
210
|
+
session!
|
211
|
+
packet = P(:byte, SERVICE_ACCEPT, :string, "test")
|
212
|
+
session.push(packet)
|
213
|
+
socket.expects(:next_packet).returns(nil)
|
214
|
+
assert_nil session.poll_message(:nonblock, false)
|
215
|
+
assert_equal [packet], session.queue
|
216
|
+
end
|
217
|
+
|
218
|
+
def test_wait_with_block_should_return_immediately_if_block_returns_truth
|
219
|
+
session.expects(:poll_message).never
|
220
|
+
session.wait { true }
|
221
|
+
end
|
222
|
+
|
223
|
+
def test_wait_should_not_consume_queue_on_reads
|
224
|
+
n = 0
|
225
|
+
session.expects(:poll_message).with(:nonblock, false).returns(nil)
|
226
|
+
session.wait { (n += 1) > 1 }
|
227
|
+
end
|
228
|
+
|
229
|
+
def test_wait_without_block_should_return_after_first_read
|
230
|
+
session.expects(:poll_message).returns(nil)
|
231
|
+
session.wait
|
232
|
+
end
|
233
|
+
|
234
|
+
def test_wait_should_enqueue_packets
|
235
|
+
session!
|
236
|
+
|
237
|
+
p1 = P(:byte, SERVICE_REQUEST, :string, "test")
|
238
|
+
p2 = P(:byte, SERVICE_ACCEPT, :string, "test")
|
239
|
+
socket.expects(:next_packet).times(2).returns(p1, p2)
|
240
|
+
|
241
|
+
n = 0
|
242
|
+
session.wait { (n += 1) > 2 }
|
243
|
+
assert_equal [p1, p2], session.queue
|
244
|
+
end
|
245
|
+
|
246
|
+
def test_push_should_enqueue_packet
|
247
|
+
packet = P(:byte, SERVICE_ACCEPT, :string, "test")
|
248
|
+
session.push(packet)
|
249
|
+
assert_equal [packet], session.queue
|
250
|
+
end
|
251
|
+
|
252
|
+
def test_send_message_should_delegate_to_socket
|
253
|
+
session!
|
254
|
+
packet = P(:byte, SERVICE_ACCEPT, :string, "test")
|
255
|
+
socket.expects(:send_packet).with(packet)
|
256
|
+
session.send_message(packet)
|
257
|
+
end
|
258
|
+
|
259
|
+
def test_enqueue_message_should_delegate_to_socket
|
260
|
+
session!
|
261
|
+
packet = P(:byte, SERVICE_ACCEPT, :string, "test")
|
262
|
+
socket.expects(:enqueue_packet).with(packet)
|
263
|
+
session.enqueue_message(packet)
|
264
|
+
end
|
265
|
+
|
266
|
+
def test_configure_client_should_pass_options_to_socket_client_state
|
267
|
+
session.configure_client :compression => :standard
|
268
|
+
assert_equal :standard, socket.client.compression
|
269
|
+
end
|
270
|
+
|
271
|
+
def test_configure_server_should_pass_options_to_socket_server_state
|
272
|
+
session.configure_server :compression => :standard
|
273
|
+
assert_equal :standard, socket.server.compression
|
274
|
+
end
|
275
|
+
|
276
|
+
def test_hint_should_set_hint_on_socket
|
277
|
+
assert !socket.hints[:authenticated]
|
278
|
+
session.hint :authenticated
|
279
|
+
assert socket.hints[:authenticated]
|
280
|
+
end
|
281
|
+
|
282
|
+
private
|
283
|
+
|
284
|
+
def socket
|
285
|
+
@socket ||= stub("socket", :hints => {})
|
286
|
+
end
|
287
|
+
|
288
|
+
def server_version
|
289
|
+
@server_version ||= stub("server_version")
|
290
|
+
end
|
291
|
+
|
292
|
+
def algorithms
|
293
|
+
@algorithms ||= stub("algorithms", :initialized? => true, :allow? => true)
|
294
|
+
end
|
295
|
+
|
296
|
+
def session(options={})
|
297
|
+
@session ||= begin
|
298
|
+
host = options.delete(:host) || "net.ssh.test"
|
299
|
+
TCPSocket.stubs(:open).with(host, options[:port] || 22).returns(socket)
|
300
|
+
Net::SSH::Transport::ServerVersion.stubs(:new).returns(server_version)
|
301
|
+
Net::SSH::Transport::Algorithms.stubs(:new).returns(algorithms)
|
302
|
+
|
303
|
+
Net::SSH::Transport::Session.new(host, options)
|
304
|
+
end
|
305
|
+
end
|
306
|
+
|
307
|
+
# a simple alias to make the tests more self-documenting. the bang
|
308
|
+
# version makes it look more like the session is being instantiated
|
309
|
+
alias session! session
|
310
|
+
end
|
311
|
+
|
312
|
+
end
|
@@ -0,0 +1,173 @@
|
|
1
|
+
require 'common'
|
2
|
+
require 'net/ssh/transport/state'
|
3
|
+
|
4
|
+
module Transport
|
5
|
+
|
6
|
+
class TestState < Test::Unit::TestCase
|
7
|
+
|
8
|
+
def setup
|
9
|
+
@socket = @state = @deflater = @inflater = nil
|
10
|
+
end
|
11
|
+
|
12
|
+
def teardown
|
13
|
+
if @deflater
|
14
|
+
@deflater.finish if !@deflater.finished?
|
15
|
+
@deflater.close
|
16
|
+
end
|
17
|
+
|
18
|
+
if @inflater
|
19
|
+
@inflater.finish if !@inflater.finished?
|
20
|
+
@inflater.close
|
21
|
+
end
|
22
|
+
|
23
|
+
state.cleanup
|
24
|
+
end
|
25
|
+
|
26
|
+
def test_constructor_should_initialize_all_values
|
27
|
+
assert_equal 0, state.sequence_number
|
28
|
+
assert_equal 0, state.packets
|
29
|
+
assert_equal 0, state.blocks
|
30
|
+
|
31
|
+
assert_nil state.compression
|
32
|
+
assert_nil state.compression_level
|
33
|
+
assert_nil state.max_packets
|
34
|
+
assert_nil state.max_blocks
|
35
|
+
assert_nil state.rekey_limit
|
36
|
+
|
37
|
+
assert_equal "identity", state.cipher.name
|
38
|
+
assert_instance_of Net::SSH::Transport::HMAC::None, state.hmac
|
39
|
+
end
|
40
|
+
|
41
|
+
def test_increment_should_increment_counters
|
42
|
+
state.increment(24)
|
43
|
+
assert_equal 1, state.sequence_number
|
44
|
+
assert_equal 1, state.packets
|
45
|
+
assert_equal 3, state.blocks
|
46
|
+
end
|
47
|
+
|
48
|
+
def test_reset_should_reset_counters_and_fix_defaults_for_maximums
|
49
|
+
state.increment(24)
|
50
|
+
state.reset!
|
51
|
+
assert_equal 1, state.sequence_number
|
52
|
+
assert_equal 0, state.packets
|
53
|
+
assert_equal 0, state.blocks
|
54
|
+
assert_equal 2147483648, state.max_packets
|
55
|
+
assert_equal 134217728, state.max_blocks
|
56
|
+
end
|
57
|
+
|
58
|
+
def test_set_should_set_variables_and_reset_counters
|
59
|
+
state.expects(:reset!)
|
60
|
+
state.set :cipher => :a, :hmac => :b, :compression => :c,
|
61
|
+
:compression_level => :d, :max_packets => 500, :max_blocks => 1000,
|
62
|
+
:rekey_limit => 1500
|
63
|
+
assert_equal :a, state.cipher
|
64
|
+
assert_equal :b, state.hmac
|
65
|
+
assert_equal :c, state.compression
|
66
|
+
assert_equal :d, state.compression_level
|
67
|
+
assert_equal 500, state.max_packets
|
68
|
+
assert_equal 1000, state.max_blocks
|
69
|
+
assert_equal 1500, state.rekey_limit
|
70
|
+
end
|
71
|
+
|
72
|
+
def test_set_with_max_packets_should_respect_max_packets_setting
|
73
|
+
state.set :max_packets => 500
|
74
|
+
assert_equal 500, state.max_packets
|
75
|
+
end
|
76
|
+
|
77
|
+
def test_set_with_max_blocks_should_respect_max_blocks_setting
|
78
|
+
state.set :max_blocks => 1000
|
79
|
+
assert_equal 1000, state.max_blocks
|
80
|
+
end
|
81
|
+
|
82
|
+
def test_set_with_rekey_limit_should_include_rekey_limit_in_computation_of_max_blocks
|
83
|
+
state.set :rekey_limit => 4000
|
84
|
+
assert_equal 500, state.max_blocks
|
85
|
+
end
|
86
|
+
|
87
|
+
def test_compressor_defaults_to_default_zlib_compression
|
88
|
+
expect = deflater.deflate("hello world")
|
89
|
+
assert_equal expect, state.compressor.deflate("hello world")
|
90
|
+
end
|
91
|
+
|
92
|
+
def test_compressor_uses_compression_level_when_given
|
93
|
+
state.set :compression_level => 1
|
94
|
+
expect = deflater(1).deflate("hello world")
|
95
|
+
assert_equal expect, state.compressor.deflate("hello world")
|
96
|
+
end
|
97
|
+
|
98
|
+
def test_compress_when_no_compression_is_active_returns_text
|
99
|
+
assert_equal "hello everybody", state.compress("hello everybody")
|
100
|
+
end
|
101
|
+
|
102
|
+
def test_decompress_when_no_compression_is_active_returns_text
|
103
|
+
assert_equal "hello everybody", state.decompress("hello everybody")
|
104
|
+
end
|
105
|
+
|
106
|
+
def test_compress_when_compression_is_delayed_and_no_auth_hint_is_set_should_return_text
|
107
|
+
state.set :compression => :delayed
|
108
|
+
assert_equal "hello everybody", state.compress("hello everybody")
|
109
|
+
end
|
110
|
+
|
111
|
+
def test_decompress_when_compression_is_delayed_and_no_auth_hint_is_set_should_return_text
|
112
|
+
state.set :compression => :delayed
|
113
|
+
assert_equal "hello everybody", state.decompress("hello everybody")
|
114
|
+
end
|
115
|
+
|
116
|
+
def test_compress_when_compression_is_enabled_should_return_compressed_text
|
117
|
+
state.set :compression => :standard
|
118
|
+
assert_equal "x\234\312H\315\311\311WH-K-\252L\312O\251\004\000\000\000\377\377", state.compress("hello everybody")
|
119
|
+
end
|
120
|
+
|
121
|
+
def test_decompress_when_compression_is_enabled_should_return_decompressed_text
|
122
|
+
state.set :compression => :standard
|
123
|
+
assert_equal "hello everybody", state.decompress("x\234\312H\315\311\311WH-K-\252L\312O\251\004\000\000\000\377\377")
|
124
|
+
end
|
125
|
+
|
126
|
+
def test_compress_when_compression_is_delayed_and_auth_hint_is_set_should_return_compressed_text
|
127
|
+
socket.hints[:authenticated] = true
|
128
|
+
state.set :compression => :delayed
|
129
|
+
assert_equal "x\234\312H\315\311\311WH-K-\252L\312O\251\004\000\000\000\377\377", state.compress("hello everybody")
|
130
|
+
end
|
131
|
+
|
132
|
+
def test_decompress_when_compression_is_delayed_and_auth_hint_is_set_should_return_decompressed_text
|
133
|
+
socket.hints[:authenticated] = true
|
134
|
+
state.set :compression => :delayed
|
135
|
+
assert_equal "hello everybody", state.decompress("x\234\312H\315\311\311WH-K-\252L\312O\251\004\000\000\000\377\377")
|
136
|
+
end
|
137
|
+
|
138
|
+
def test_needs_rekey_should_be_true_if_packets_exceeds_max_packets
|
139
|
+
state.set :max_packets => 2
|
140
|
+
state.increment(8)
|
141
|
+
state.increment(8)
|
142
|
+
assert !state.needs_rekey?
|
143
|
+
state.increment(8)
|
144
|
+
assert state.needs_rekey?
|
145
|
+
end
|
146
|
+
|
147
|
+
def test_needs_rekey_should_be_true_if_blocks_exceeds_max_blocks
|
148
|
+
state.set :max_blocks => 10
|
149
|
+
assert !state.needs_rekey?
|
150
|
+
state.increment(88)
|
151
|
+
assert state.needs_rekey?
|
152
|
+
end
|
153
|
+
|
154
|
+
private
|
155
|
+
|
156
|
+
def deflater(level=Zlib::DEFAULT_COMPRESSION)
|
157
|
+
@deflater ||= Zlib::Deflate.new(level)
|
158
|
+
end
|
159
|
+
|
160
|
+
def inflater
|
161
|
+
@inflater ||= Zlib::Inflate.new(nil)
|
162
|
+
end
|
163
|
+
|
164
|
+
def socket
|
165
|
+
@socket ||= stub("socket", :hints => {})
|
166
|
+
end
|
167
|
+
|
168
|
+
def state
|
169
|
+
@state ||= Net::SSH::Transport::State.new(socket)
|
170
|
+
end
|
171
|
+
end
|
172
|
+
|
173
|
+
end
|