Files: 80f76c6fc58f4ae5c3d25f42017a11d4918e1502 / t
7441 bytesRaw
1 | #! /usr/bin/perl -w |
2 | |
3 | # Test script for sslh |
4 | |
5 | # The principle is to create two listening sockets which |
6 | # will act as the ssh and ssl servers, and then perform a |
7 | # number of connections in various combinations to check |
8 | # that the server behaves properly. |
9 | |
10 | use strict; |
11 | use IO::Socket::INET; |
12 | use Test::More qw/no_plan/; |
13 | |
14 | # We use ports 9000, 9001 and 9002 -- hope that won't clash |
15 | # with anything... |
16 | my $ssh_port = 9000; |
17 | my $ssl_port = 9001; |
18 | my $sslh_port = 9002; |
19 | my $pidfile = "/tmp/sslh.pid"; |
20 | |
21 | # How many connections will be created during the last test |
22 | my $NUM_SSL_CNX = 20; |
23 | my $NUM_SSH_CNX = 20; |
24 | |
25 | # Which tests do we run |
26 | my $SSL_CNX = 1; |
27 | my $SSH_SHY_CNX = 1; |
28 | my $SSH_BOLD_CNX = 1; |
29 | my $SSL_MIX_SSH = 1; |
30 | my $SSH_MIX_SSL = 1; |
31 | my $BIG_MSG = 1; |
32 | my $MANY_CNX = 1; |
33 | |
34 | # the Listen parameter needs to be bigger than the max number of connexions |
35 | # we'll make during the last test (we open a bunch of SSH connexions, and |
36 | # accept them all at once afterwards) |
37 | my $ssh_listen = new IO::Socket::INET(LocalHost=> "localhost:$ssh_port", Blocking => 1, Reuse => 1, Listen => $NUM_SSH_CNX + 1); |
38 | die "error1: $!\n" unless $ssh_listen; |
39 | |
40 | my $ssl_listen = new IO::Socket::INET(LocalHost=> "localhost:$ssl_port", Blocking => 1, Reuse => 1, Listen => $NUM_SSL_CNX + 1); |
41 | die "error2: $!\n" unless $ssl_listen; |
42 | |
43 | # Start sslh with the right plumbing |
44 | my $sslh_pid; |
45 | if (!($sslh_pid = fork)) { |
46 | my $user = (getpwuid $<)[0]; # Run under current username |
47 | exec "./sslh-fork -v -u $user -p localhost:$sslh_port -s localhost:$ssh_port -l localhost:$ssl_port -P $pidfile"; |
48 | #exec "./sslh-select -v -f -u $user -p localhost:$sslh_port -s localhost:$ssh_port -l localhost:$ssl_port -P $pidfile"; |
49 | #exec "valgrind --leak-check=full ./sslh-select -v -f -u $user -p localhost:$sslh_port -s localhost:$ssh_port -l localhost:$ssl_port -P $pidfile"; |
50 | exit 0; |
51 | } |
52 | warn "spawned $sslh_pid\n"; |
53 | sleep 1; |
54 | |
55 | |
56 | my $test_data = "hello world\n"; |
57 | |
58 | # Test: SSL connection |
59 | if ($SSL_CNX) { |
60 | print "***Test: SSL connection\n"; |
61 | my $cnx_l = new IO::Socket::INET(PeerHost => "localhost:$sslh_port"); |
62 | warn "$!\n" unless $cnx_l; |
63 | if (defined $cnx_l) { |
64 | print $cnx_l $test_data; |
65 | my $ssl_data = $ssl_listen->accept; |
66 | my $data = <$ssl_data>; |
67 | is($data, $test_data, "SSL connection"); |
68 | } |
69 | } |
70 | |
71 | # Test: Shy SSH connection |
72 | if ($SSH_SHY_CNX) { |
73 | print "***Test: Shy SSH connection\n"; |
74 | my $cnx_h = new IO::Socket::INET(PeerHost => "localhost:$sslh_port"); |
75 | warn "$!\n" unless $cnx_h; |
76 | if (defined $cnx_h) { |
77 | sleep 3; |
78 | my $ssh_data = $ssh_listen->accept; |
79 | print $cnx_h $test_data; |
80 | my $data = <$ssh_data>; |
81 | is($data, $test_data, "Shy SSH connection"); |
82 | } |
83 | } |
84 | |
85 | # Test: Bold SSH connection |
86 | if ($SSH_BOLD_CNX) { |
87 | print "***Test: Bold SSH connection\n"; |
88 | my $cnx_h = new IO::Socket::INET(PeerHost => "localhost:$sslh_port"); |
89 | warn "$!\n" unless $cnx_h; |
90 | if (defined $cnx_h) { |
91 | my $td = "SSH-2.0 testsuite\n$test_data"; |
92 | print $cnx_h $td; |
93 | my $ssh_data = $ssh_listen->accept; |
94 | my $data = <$ssh_data>; |
95 | $data .= <$ssh_data>; |
96 | is($data, $td, "Bold SSH connection"); |
97 | } |
98 | } |
99 | |
100 | # Test: One SSL half-started then one SSH |
101 | if ($SSL_MIX_SSH) { |
102 | print "***Test: One SSL half-started then one SSH\n"; |
103 | my $cnx_l = new IO::Socket::INET(PeerHost => "localhost:$sslh_port"); |
104 | warn "$!\n" unless $cnx_l; |
105 | if (defined $cnx_l) { |
106 | print $cnx_l $test_data; |
107 | my $cnx_h= new IO::Socket::INET(PeerHost => "localhost:$sslh_port"); |
108 | warn "$!\n" unless $cnx_h; |
109 | if (defined $cnx_h) { |
110 | sleep 3; |
111 | my $ssh_data = $ssh_listen->accept; |
112 | print $cnx_h $test_data; |
113 | my $data_h = <$ssh_data>; |
114 | is($data_h, $test_data, "SSH during SSL being established"); |
115 | } |
116 | my $ssl_data = $ssl_listen->accept; |
117 | my $data = <$ssl_data>; |
118 | is($data, $test_data, "SSL connection interrupted by SSH"); |
119 | } |
120 | } |
121 | |
122 | # Test: One SSH half-started then one SSL |
123 | if ($SSH_MIX_SSL) { |
124 | print "***Test: One SSH half-started then one SSL\n"; |
125 | my $cnx_h = new IO::Socket::INET(PeerHost => "localhost:$sslh_port"); |
126 | warn "$!\n" unless $cnx_h; |
127 | if (defined $cnx_h) { |
128 | sleep 3; |
129 | my $cnx_l = new IO::Socket::INET(PeerHost => "localhost:$sslh_port"); |
130 | warn "$!\n" unless $cnx_l; |
131 | if (defined $cnx_l) { |
132 | print $cnx_l $test_data; |
133 | my $ssl_data = $ssl_listen->accept; |
134 | my $data = <$ssl_data>; |
135 | is($data, $test_data, "SSL during SSH being established"); |
136 | } |
137 | my $ssh_data = $ssh_listen->accept; |
138 | print $cnx_h $test_data; |
139 | my $data = <$ssh_data>; |
140 | is($data, $test_data, "SSH connection interrupted by SSL"); |
141 | } |
142 | } |
143 | |
144 | |
145 | # Test: Big messages |
146 | if ($BIG_MSG) { |
147 | print "***Test: big message\n"; |
148 | my $cnx_l = new IO::Socket::INET(PeerHost => "localhost:$sslh_port"); |
149 | warn "$!\n" unless $cnx_l; |
150 | my $test_data2 = "helloworld"; |
151 | my $rept = 10000; |
152 | if (defined $cnx_l) { |
153 | print $cnx_l ($test_data2 x $rept); |
154 | print $cnx_l "\n"; |
155 | my $ssl_data = $ssl_listen->accept; |
156 | my $data = <$ssl_data>; |
157 | is($data, $test_data2 x $rept . "\n", "Big message"); |
158 | } |
159 | } |
160 | |
161 | # Test: several connections active at once |
162 | # We start 50 SSH connexions, then open 50 SSL connexion, then accept the 50 |
163 | # SSH connexions, then we randomize the order of connexions and write 1000 |
164 | # messages on each connexion and check we get it on the other end. |
165 | if ($MANY_CNX) { |
166 | print "***Test: several connexions active at once\n"; |
167 | my (@cnx_h, @ssh_data); |
168 | for (1..$NUM_SSH_CNX) { |
169 | my $cnx_h = new IO::Socket::INET(PeerHost => "localhost:$sslh_port"); |
170 | warn "----> $!\n" unless defined $cnx_h; |
171 | if (defined $cnx_h) { |
172 | push @cnx_h, $cnx_h; |
173 | } |
174 | } |
175 | my (@cnx_l, @ssl_data); |
176 | for (1..$NUM_SSL_CNX) { |
177 | my $cnx_l = new IO::Socket::INET(PeerHost => "localhost:$sslh_port"); |
178 | warn "----> $!\n" unless defined $cnx_l; |
179 | if (defined $cnx_l) { |
180 | push @cnx_l, $cnx_l; |
181 | print $cnx_l " "; |
182 | push @ssl_data, ($ssl_listen->accept)[0]; |
183 | } |
184 | } |
185 | # give time to the connections to turn to SSH |
186 | sleep 4; |
187 | # and accept all SSH connections... |
188 | for (1..$NUM_SSH_CNX) { |
189 | push @ssh_data, $ssh_listen->accept; |
190 | } |
191 | |
192 | # Make up a random order so we don't always hit the |
193 | # connexions in the same order |
194 | |
195 | # fisher_yates_shuffle( \@array ) : generate a random permutation |
196 | # of @array in place (from |
197 | # http://docstore.mik.ua/orelly/perl/cookbook/ch04_18.htm, |
198 | # modified to shuffle two arrays in the same way) |
199 | sub fisher_yates_shuffle { |
200 | my ($array1, $array2) = @_; |
201 | my $i; |
202 | for ($i = @$array1; --$i; ) { |
203 | my $j = int rand ($i+1); |
204 | next if $i == $j; |
205 | @$array1[$i,$j] = @$array1[$j,$i]; |
206 | @$array2[$i,$j] = @$array2[$j,$i]; |
207 | } |
208 | } |
209 | |
210 | my @cnx = (@cnx_l, @cnx_l); |
211 | my @rcv = (@ssl_data, @ssl_data); |
212 | |
213 | fisher_yates_shuffle(\@rcv, \@cnx); |
214 | |
215 | # Send a bunch of messages |
216 | for my $cnt (1..1000) { |
217 | foreach (@cnx) { |
218 | print $_ "$cnt$test_data"; |
219 | } |
220 | foreach (@rcv) { |
221 | my $data = <$_>; |
222 | like($data, qr/ ?$cnt$test_data/, "Multiple messages [$cnt]"); |
223 | } |
224 | } |
225 | } |
226 | |
227 | |
228 | |
229 | kill 15, `cat $pidfile` or warn "kill: $!\n"; |
230 |
Built with git-ssb-web