blob: 69919020a00e94ee26e935e0aa605650c040332f [file] [log] [blame]
Sergey Kandaurov2b62d0f2016-09-15 14:06:24 +03001#!/usr/bin/perl
2
3# (C) Sergey Kandaurov
4# (C) Nginx, Inc.
5
6# Tests for stream_ssl_preread module.
7
8###############################################################################
9
10use warnings;
11use strict;
12
13use Test::More;
14
15BEGIN { use FindBin; chdir($FindBin::Bin); }
16
17use lib 'lib';
18use Test::Nginx;
Sergey Kandaurov391e3a42017-07-31 14:24:38 +030019use Test::Nginx::Stream qw/ stream /;
Sergey Kandaurov2b62d0f2016-09-15 14:06:24 +030020
21###############################################################################
22
23select STDERR; $| = 1;
24select STDOUT; $| = 1;
25
26my $t = Test::Nginx->new()->has(qw/stream stream_map stream_ssl_preread/)
Sergey Kandaurov391e3a42017-07-31 14:24:38 +030027 ->has(qw/stream_ssl stream_return/)->has_daemon('openssl')
Sergey Kandaurov2b62d0f2016-09-15 14:06:24 +030028 ->write_file_expand('nginx.conf', <<'EOF');
29
30%%TEST_GLOBALS%%
31
32daemon off;
33
34events {
35}
36
37stream {
38 log_format status $status;
39
40 map $ssl_preread_server_name $name {
41 "" 127.0.0.1:8093;
42 default $ssl_preread_server_name;
43 }
44
45 upstream foo {
46 server 127.0.0.1:8091;
47 }
48
49 upstream bar {
50 server 127.0.0.1:8092;
51 }
52
Andrey Zelenkov939a5af2017-07-26 16:42:48 +030053 upstream next {
54 server 127.0.0.1:8094;
55 server 127.0.0.1:8080;
56 }
57
Sergey Kandaurov2b62d0f2016-09-15 14:06:24 +030058 ssl_preread on;
59
60 server {
61 listen 127.0.0.1:8080;
Sergey Kandaurov391e3a42017-07-31 14:24:38 +030062 return $name;
Sergey Kandaurov2b62d0f2016-09-15 14:06:24 +030063 }
64
65 server {
66 listen 127.0.0.1:8081;
67 proxy_pass $name;
Sergey Kandaurov2b62d0f2016-09-15 14:06:24 +030068 }
69
Sergey Kandaurov2b62d0f2016-09-15 14:06:24 +030070 server {
Sergey Kandaurov391e3a42017-07-31 14:24:38 +030071 listen 127.0.0.1:8082;
Sergey Kandaurov2b62d0f2016-09-15 14:06:24 +030072 proxy_pass $name;
Sergey Kandaurov391e3a42017-07-31 14:24:38 +030073 ssl_preread off;
Sergey Kandaurov2b62d0f2016-09-15 14:06:24 +030074 }
75
76 server {
77 listen 127.0.0.1:8083;
78 proxy_pass $name;
79
80 preread_timeout 2s;
81 preread_buffer_size 42;
82
83 access_log %%TESTDIR%%/status.log status;
84 }
Sergey Kandaurov207349f2016-12-19 14:38:56 +030085
Andrey Zelenkov939a5af2017-07-26 16:42:48 +030086 server {
87 listen 127.0.0.1:8084;
88 proxy_pass next;
89
90 proxy_connect_timeout 2s;
91 preread_buffer_size 8;
92 }
93
Sergey Kandaurov2b62d0f2016-09-15 14:06:24 +030094 ssl_certificate_key localhost.key;
95 ssl_certificate localhost.crt;
96
97 server {
98 listen 127.0.0.1:8091 ssl;
99 listen 127.0.0.1:8092 ssl;
100 listen 127.0.0.1:8093 ssl;
Sergey Kandaurov391e3a42017-07-31 14:24:38 +0300101 ssl_preread off;
102 return $server_port;
Sergey Kandaurov2b62d0f2016-09-15 14:06:24 +0300103 }
104}
105
106EOF
107
108eval { require IO::Socket::SSL; die if $IO::Socket::SSL::VERSION < 1.56; };
109plan(skip_all => 'IO::Socket::SSL version >= 1.56 required') if $@;
110
111eval {
112 if (IO::Socket::SSL->can('can_client_sni')) {
113 IO::Socket::SSL->can_client_sni() or die;
114 }
115};
116plan(skip_all => 'IO::Socket::SSL with OpenSSL SNI support required') if $@;
117
118eval {
119 my $ctx = Net::SSLeay::CTX_new() or die;
120 my $ssl = Net::SSLeay::new($ctx) or die;
121 Net::SSLeay::set_tlsext_host_name($ssl, 'example.org') == 1 or die;
122};
123plan(skip_all => 'Net::SSLeay with OpenSSL SNI support required') if $@;
124
Sergey Kandaurov0a539822018-03-30 18:08:23 +0300125$t->plan(13);
Sergey Kandaurov2b62d0f2016-09-15 14:06:24 +0300126
127$t->write_file('openssl.conf', <<EOF);
128[ req ]
Sergey Kandaurov571b1a52019-07-09 13:37:55 +0300129default_bits = 2048
Sergey Kandaurov2b62d0f2016-09-15 14:06:24 +0300130encrypt_key = no
131distinguished_name = req_distinguished_name
132[ req_distinguished_name ]
133EOF
134
135my $d = $t->testdir();
136
137foreach my $name ('localhost') {
138 system('openssl req -x509 -new '
Sergey Kandaurov2225e6e2017-09-20 14:46:51 +0300139 . "-config $d/openssl.conf -subj /CN=$name/ "
140 . "-out $d/$name.crt -keyout $d/$name.key "
Sergey Kandaurov2b62d0f2016-09-15 14:06:24 +0300141 . ">>$d/openssl.out 2>&1") == 0
142 or die "Can't create certificate for $name: $!\n";
143}
144
145$t->run();
146
147###############################################################################
148
Andrey Zelenkov939a5af2017-07-26 16:42:48 +0300149my ($p1, $p2, $p3, $p4) = (port(8091), port(8092), port(8093), port(8084));
Sergey Kandaurov2b62d0f2016-09-15 14:06:24 +0300150
Sergey Kandaurov391e3a42017-07-31 14:24:38 +0300151is(get_ssl('foo', 8081), $p1, 'sni');
152is(get_ssl('foo', 8081), $p1, 'sni again');
Sergey Kandaurov2b62d0f2016-09-15 14:06:24 +0300153
Sergey Kandaurov391e3a42017-07-31 14:24:38 +0300154is(get_ssl('bar', 8081), $p2, 'sni 2');
155is(get_ssl('bar', 8081), $p2, 'sni 2 again');
Sergey Kandaurov2b62d0f2016-09-15 14:06:24 +0300156
157# fallback to an empty value for some reason
158
Sergey Kandaurov391e3a42017-07-31 14:24:38 +0300159is(get_ssl('', 8081), $p3, 'no sni');
160is(get_ssl('foo', 8082), $p3, 'preread off');
161is(get_ssl('foo', 8083), undef, 'preread buffer full');
Andrey Zelenkov426d12f2017-10-26 16:36:13 +0300162is(stream('127.0.0.1:' . port(8080))->io('x' x 1000), "127.0.0.1:$p3",
163 'not a handshake');
Sergey Kandaurov2b62d0f2016-09-15 14:06:24 +0300164
Sergey Kandaurov38bbbe32017-10-21 01:07:48 +0300165# ticket #1317
Andrey Zelenkov939a5af2017-07-26 16:42:48 +0300166
167is(stream("127.0.0.1:$p4")->io('x' x 16), "127.0.0.1:$p3",
168 'pending buffers on next upstream');
169
Sergey Kandaurov207349f2016-12-19 14:38:56 +0300170# no junk in variable due to short ClientHello length value
171
Sergey Kandaurov391e3a42017-07-31 14:24:38 +0300172is(get_short(), "127.0.0.1:$p3", 'short client hello');
Sergey Kandaurov207349f2016-12-19 14:38:56 +0300173
174# allow record with older SSL version, such as 3.0
175
176is(get_oldver(), 'foo', 'older version in ssl record');
177
Sergey Kandaurov0a539822018-03-30 18:08:23 +0300178# SNI "foo|f" fragmented across TLS records
179
180is(get_frag(), 'foof', 'handshake fragment split on SNI');
181
Sergey Kandaurov2b62d0f2016-09-15 14:06:24 +0300182$t->stop();
183
184is($t->read_file('status.log'), "400\n", 'preread buffer full - log');
185
186###############################################################################
187
Sergey Kandaurov0a539822018-03-30 18:08:23 +0300188sub get_frag {
189 my $r = pack("N*", 0x16030100, 0x3b010000, 0x380303ac,
190 0x8c8678a0, 0xaa1e7eed, 0x3644eed6, 0xc3bd2c69,
191 0x7bc7deda, 0x249db0e3, 0x0c339eba, 0xa80b7600,
192 0x00020000, 0x0100000d, 0x00000009, 0x00070000,
193 0x04666f6f, 0x16030100);
194 $r .= pack("n", 0x0166);
195
196 http($r);
197}
198
Sergey Kandaurov207349f2016-12-19 14:38:56 +0300199sub get_short {
Sergey Kandaurov207349f2016-12-19 14:38:56 +0300200 my $r = pack("N*", 0x16030100, 0x38010000, 0x330303eb);
201 $r .= pack("N*", 0x6357cdba, 0xa6b8d853, 0xf1f6ac0f);
202 $r .= pack("N*", 0xdf03178c, 0x0ae41824, 0xe7643682);
203 $r .= pack("N*", 0x3c1b273f, 0xbfde4b00, 0x00000000);
204 $r .= pack("CN3", 0x0c, 0x00000008, 0x00060000, 0x03666f6f);
205
Sergey Kandaurov391e3a42017-07-31 14:24:38 +0300206 http($r);
Sergey Kandaurov207349f2016-12-19 14:38:56 +0300207}
208
209sub get_oldver {
Sergey Kandaurov207349f2016-12-19 14:38:56 +0300210 my $r = pack("N*", 0x16030000, 0x38010000, 0x340303eb);
211 $r .= pack("N*", 0x6357cdba, 0xa6b8d853, 0xf1f6ac0f);
212 $r .= pack("N*", 0xdf03178c, 0x0ae41824, 0xe7643682);
213 $r .= pack("N*", 0x3c1b273f, 0xbfde4b00, 0x00000000);
214 $r .= pack("CN3", 0x0c, 0x00000008, 0x00060000, 0x03666f6f);
215
Sergey Kandaurov391e3a42017-07-31 14:24:38 +0300216 http($r);
Sergey Kandaurov207349f2016-12-19 14:38:56 +0300217}
218
Sergey Kandaurov391e3a42017-07-31 14:24:38 +0300219sub get_ssl {
Sergey Kandaurov2b62d0f2016-09-15 14:06:24 +0300220 my ($host, $port) = @_;
Sergey Kandaurov92fa9162017-08-03 17:29:54 +0300221 my $s = stream('127.0.0.1:' . port($port));
Sergey Kandaurov2b62d0f2016-09-15 14:06:24 +0300222
223 eval {
224 local $SIG{ALRM} = sub { die "timeout\n" };
225 local $SIG{PIPE} = sub { die "sigpipe\n" };
Sergey Kandaurov4aa9b912018-12-24 14:24:51 +0300226 alarm(8);
Sergey Kandaurov391e3a42017-07-31 14:24:38 +0300227 IO::Socket::SSL->start_SSL($s->{_socket},
Sergey Kandaurov2b62d0f2016-09-15 14:06:24 +0300228 SSL_hostname => $host,
229 SSL_verify_mode => IO::Socket::SSL::SSL_VERIFY_NONE(),
230 SSL_error_trap => sub { die $_[1] }
231 );
232 alarm(0);
233 };
234 alarm(0);
235
236 if ($@) {
237 log_in("died: $@");
238 return undef;
239 }
240
Sergey Kandaurov391e3a42017-07-31 14:24:38 +0300241 return $s->read();
Sergey Kandaurov2b62d0f2016-09-15 14:06:24 +0300242}
243
244###############################################################################