git ssb

0+

cel / sslh



Tree: ca461ea077d748dde25eb6610e66514fa0151baf

Files: ca461ea077d748dde25eb6610e66514fa0151baf / t

10849 bytesRaw
1#! /usr/bin/perl -w
2
3# Test script for sslh
4
5use strict;
6use IO::Socket::INET6;
7use Test::More qw/no_plan/;
8
9# We use ports 9000, 9001 and 9002 -- hope that won't clash
10# with anything...
11my $ssh_address = "ip6-localhost:9000";
12my $ssl_address = "ip6-localhost:9001";
13my $sslh_port = 9002;
14my $no_listen = 9003; # Port on which no-one listens
15my $pidfile = "/tmp/sslh_test.pid";
16
17# Which tests do we run
18my $SSL_CNX = 1;
19my $SSH_SHY_CNX = 1;
20my $SSH_BOLD_CNX = 1;
21my $SSH_PROBE_AGAIN = 1;
22my $SSL_MIX_SSH = 1;
23my $SSH_MIX_SSL = 1;
24my $BIG_MSG = 0; # This test is unreliable
25my $STALL_CNX = 0; # This test needs fixing
26
27# Robustness tests. These are mostly to achieve full test
28# coverage, but do not necessarily result in an actual test
29# (e.g. some tests need to be run with valgrind to check all
30# memory management code).
31my $RB_CNX_NOSERVER = 1;
32my $RB_PARAM_NOHOST = 1;
33my $RB_WRONG_USERNAME = 1;
34my $RB_OPEN_PID_FILE = 1;
35my $RB_BIND_ADDRESS = 1;
36my $RB_RESOLVE_ADDRESS = 1;
37
38`lcov --directory . --zerocounters`;
39
40
41my ($ssh_pid, $ssl_pid);
42
43if (!($ssh_pid = fork)) {
44 exec "./echosrv --listen $ssh_address --prefix 'ssh: '";
45}
46
47if (!($ssl_pid = fork)) {
48 exec "./echosrv --listen $ssl_address --prefix 'ssl: '";
49}
50
51my @binaries = ('sslh-select', 'sslh-fork');
52for my $binary (@binaries) {
53 warn "Testing $binary\n";
54
55# Start sslh with the right plumbing
56 my $sslh_pid;
57 if (!($sslh_pid = fork)) {
58 my $user = (getpwuid $<)[0]; # Run under current username
59 my $cmd = "./$binary -v -f -u $user --listen localhost:$sslh_port --ssh $ssh_address --ssl $ssl_address -P $pidfile";
60 warn "$cmd\n";
61 #exec $cmd;
62 exec "valgrind --leak-check=full ./$binary -v -f -u $user --listen localhost:$sslh_port --ssh $ssh_address -ssl $ssl_address -P $pidfile";
63 exit 0;
64 }
65 warn "spawned $sslh_pid\n";
66 sleep 5; # valgrind can be heavy -- wait 5 seconds
67
68
69 my $test_data = "hello world\n";
70# my $ssl_test_data = (pack 'n', ((length $test_data) + 2)) . $test_data;
71 my $ssl_test_data = "\x16\x03\x03$test_data\n";
72
73# Test: SSL connection
74 if ($SSL_CNX) {
75 print "***Test: SSL connection\n";
76 my $cnx_l = new IO::Socket::INET(PeerHost => "localhost:$sslh_port");
77 warn "$!\n" unless $cnx_l;
78 if (defined $cnx_l) {
79 print $cnx_l $ssl_test_data;
80 my $data;
81 my $n = sysread $cnx_l, $data, 1024;
82 is($data, "ssl: $ssl_test_data", "SSL connection");
83 }
84 }
85
86# Test: Shy SSH connection
87 if ($SSH_SHY_CNX) {
88 print "***Test: Shy SSH connection\n";
89 my $cnx_h = new IO::Socket::INET(PeerHost => "localhost:$sslh_port");
90 warn "$!\n" unless $cnx_h;
91 if (defined $cnx_h) {
92 sleep 3;
93 print $cnx_h $test_data;
94 my $data = <$cnx_h>;
95 is($data, "ssh: $test_data", "Shy SSH connection");
96 }
97 }
98
99# Test: Bold SSH connection
100 if ($SSH_BOLD_CNX) {
101 print "***Test: Bold SSH connection\n";
102 my $cnx_h = new IO::Socket::INET(PeerHost => "localhost:$sslh_port");
103 warn "$!\n" unless $cnx_h;
104 if (defined $cnx_h) {
105 my $td = "SSH-2.0 testsuite\t$test_data";
106 print $cnx_h $td;
107 my $data = <$cnx_h>;
108 is($data, "ssh: $td", "Bold SSH connection");
109 }
110 }
111
112# Test: PROBE_AGAIN, incomplete first frame
113 if ($SSH_PROBE_AGAIN) {
114 print "***Test: incomplete SSH first frame\n";
115 my $cnx_h = new IO::Socket::INET(PeerHost => "localhost:$sslh_port");
116 warn "$!\n" unless $cnx_h;
117 if (defined $cnx_h) {
118 my $td = "SSH-2.0 testsuite\t$test_data";
119 print $cnx_h substr $td, 0, 2;
120 sleep 1;
121 print $cnx_h substr $td, 2;
122 my $data = <$cnx_h>;
123 is($data, "ssh: $td", "Incomplete first SSH frame");
124 }
125 }
126
127
128# Test: One SSL half-started then one SSH
129 if ($SSL_MIX_SSH) {
130 print "***Test: One SSL half-started then one SSH\n";
131 my $cnx_l = new IO::Socket::INET(PeerHost => "localhost:$sslh_port");
132 warn "$!\n" unless $cnx_l;
133 if (defined $cnx_l) {
134 print $cnx_l $ssl_test_data;
135 my $cnx_h= new IO::Socket::INET(PeerHost => "localhost:$sslh_port");
136 warn "$!\n" unless $cnx_h;
137 if (defined $cnx_h) {
138 sleep 3;
139 print $cnx_h $test_data;
140 my $data_h = <$cnx_h>;
141 is($data_h, "ssh: $test_data", "SSH during SSL being established");
142 }
143 my $data;
144 my $n = sysread $cnx_l, $data, 1024;
145 is($data, "ssl: $ssl_test_data", "SSL connection interrupted by SSH");
146 }
147 }
148
149# Test: One SSH half-started then one SSL
150 if ($SSH_MIX_SSL) {
151 print "***Test: One SSH half-started then one SSL\n";
152 my $cnx_h = new IO::Socket::INET(PeerHost => "localhost:$sslh_port");
153 warn "$!\n" unless $cnx_h;
154 if (defined $cnx_h) {
155 sleep 3;
156 my $cnx_l = new IO::Socket::INET(PeerHost => "localhost:$sslh_port");
157 warn "$!\n" unless $cnx_l;
158 if (defined $cnx_l) {
159 print $cnx_l $ssl_test_data;
160 my $data;
161 my $n = sysread $cnx_l, $data, 1024;
162 is($data, "ssl: $ssl_test_data", "SSL during SSH being established");
163 }
164 print $cnx_h $test_data;
165 my $data = <$cnx_h>;
166 is($data, "ssh: $test_data", "SSH connection interrupted by SSL");
167 }
168 }
169
170
171# Test: Big messages (careful: don't go over echosrv's buffer limit (1M))
172 if ($BIG_MSG) {
173 print "***Test: big message\n";
174 my $cnx_l = new IO::Socket::INET(PeerHost => "localhost:$sslh_port");
175 warn "$!\n" unless $cnx_l;
176 my $rept = 1000;
177 my $test_data2 = $ssl_test_data . ("helloworld"x$rept);
178 if (defined $cnx_l) {
179 my $n = syswrite $cnx_l, $test_data2;
180 my ($data);
181 $n = sysread $cnx_l, $data, 1 << 20;
182 is($data, "ssl: ". $test_data2, "Big message");
183 }
184 }
185
186# Test: Stalled connection
187# Create two connections, stall one, check the other one
188# works, unstall first and check it works fine
189# This test needs fixing.
190# Now that echosrv no longer works on "lines" (finishing
191# with '\n'), it may cut blocks randomly with prefixes.
192# The whole thing needs to be re-thought as it'll only
193# work by chance.
194 if ($STALL_CNX) {
195 print "***Test: Stalled connection\n";
196 my $cnx_1 = new IO::Socket::INET(PeerHost => "localhost:$sslh_port");
197 warn "$!\n" unless defined $cnx_1;
198 my $cnx_2 = new IO::Socket::INET(PeerHost => "localhost:$sslh_port");
199 warn "$!\n" unless defined $cnx_2;
200 my $test_data2 = "helloworld";
201 sleep 4;
202 my $rept = 1000;
203 if (defined $cnx_1 and defined $cnx_2) {
204 print $cnx_1 ($test_data2 x $rept);
205 print $cnx_1 "\n";
206 print $cnx_2 ($test_data2 x $rept);
207 print $cnx_2 "\n";
208 my $data = <$cnx_2>;
209 is($data, "ssh: " . ($test_data2 x $rept) . "\n", "Stalled connection (1)");
210 print $cnx_2 ($test_data2 x $rept);
211 print $cnx_2 "\n";
212 $data = <$cnx_2>;
213 is($data, "ssh: " . ($test_data2 x $rept) . "\n", "Stalled connection (2)");
214 $data = <$cnx_1>;
215 is($data, "ssh: " . ($test_data2 x $rept) . "\n", "Stalled connection (3)");
216
217 }
218 }
219
220 my $pid = `cat $pidfile`;
221 warn "killing $pid\n";
222 kill TERM => $pid or warn "kill process: $!\n";
223 sleep 1;
224}
225
226# Robustness: Connecting to non-existant server
227if ($RB_CNX_NOSERVER) {
228 print "***Test: Connecting to non-existant server\n";
229 my $sslh_pid;
230 if (!($sslh_pid = fork)) {
231 my $user = (getpwuid $<)[0]; # Run under current username
232 exec "./sslh-select -v -f -u $user --listen localhost:$sslh_port --ssh localhost:$no_listen --ssl localhost:$no_listen -P $pidfile";
233 }
234 warn "spawned $sslh_pid\n";
235
236 sleep 1;
237
238 my $cnx_h = new IO::Socket::INET(PeerHost => "localhost:$sslh_port");
239 warn "$!\n" unless $cnx_h;
240 if (defined $cnx_h) {
241 sleep 1;
242 my $test_data = "hello";
243 print $cnx_h $test_data;
244 }
245 # Ideally we should check a log is emitted.
246
247 kill TERM => `cat $pidfile` or warn "kill: $!\n";
248 sleep 1;
249}
250
251
252# Robustness: No hostname in address
253if ($RB_PARAM_NOHOST) {
254 print "***Test: No hostname in address\n";
255 my $sslh_pid;
256 if (!($sslh_pid = fork)) {
257 my $user = (getpwuid $<)[0]; # Run under current username
258 exec "./sslh-select -v -f -u $user --listen $sslh_port --ssh $ssh_address --ssl $ssl_address -P $pidfile";
259 }
260 warn "spawned $sslh_pid\n";
261 waitpid $sslh_pid, 0;
262 my $code = $? >> 8;
263 warn "exited with $code\n";
264 is($code, 1, "Exit status on illegal option");
265}
266
267# Robustness: User does not exist
268if ($RB_WRONG_USERNAME) {
269 print "***Test: Changing to non-existant username\n";
270 my $sslh_pid;
271 if (!($sslh_pid = fork)) {
272 my $user = (getpwuid $<)[0]; # Run under current username
273 exec "./sslh-select -v -f -u ${user}_doesnt_exist --listen localhost:$sslh_port --ssh $ssh_address --ssl $ssl_address -P $pidfile";
274 }
275 warn "spawned $sslh_pid\n";
276 waitpid $sslh_pid, 0;
277 my $code = $? >> 8;
278 warn "exited with $code\n";
279 is($code, 2, "Exit status on non-existant username");
280}
281
282# Robustness: Can't open PID file
283if ($RB_OPEN_PID_FILE) {
284 print "***Test: Can't open PID file\n";
285 my $sslh_pid;
286 if (!($sslh_pid = fork)) {
287 my $user = (getpwuid $<)[0]; # Run under current username
288 exec "./sslh-select -v -f -u $user --listen localhost:$sslh_port --ssh $ssh_address --ssl $ssl_address -P /dont_exist/$pidfile";
289 # You don't have a /dont_exist/ directory, do you?!
290 }
291 warn "spawned $sslh_pid\n";
292 waitpid $sslh_pid, 0;
293 my $code = $? >> 8;
294 warn "exited with $code\n";
295 is($code, 3, "Exit status if can't open PID file");
296}
297
298# Robustness: Can't resolve address
299if ($RB_RESOLVE_ADDRESS) {
300 print "***Test: Can't resolve address\n";
301 my $sslh_pid;
302 if (!($sslh_pid = fork)) {
303 my $user = (getpwuid $<)[0]; # Run under current username
304 exec "./sslh-select -v -f -u $user --listen blahblah.dontexist:9000 --ssh $ssh_address --ssl $ssl_address -P $pidfile";
305 }
306 warn "spawned $sslh_pid\n";
307 waitpid $sslh_pid, 0;
308 my $code = $? >> 8;
309 warn "exited with $code\n";
310 is($code, 4, "Exit status if can't resolve address");
311}
312
313`lcov --directory . --capture --output-file sslh_cov.info`;
314`genhtml sslh_cov.info`;
315
316`killall echosrv`;
317
318

Built with git-ssb-web