Mercurial > hg > nginx-tests
comparison ssl.t @ 1829:a78c32419f02
Tests: separate SSL session reuse tests.
Instead of being mixed with generic SSL tests, session reuse variants
are now tested in a separate file.
In the generic SSL tests only basic session reuse is now tested,
notably with session tickets enabled and a shared SSL session cache.
This should make it possible to reuse sessions in all cases (except
when it's not supported, such as with LibreSSL with TLSv1.3).
Note that session reuse with tickets implies that $ssl_session_id
is selected by the client and therefore is not available on the
initial connection. Relevant test is modified to handle this.
Further, BoringSSL does not use legacy session ID with TLSv1.3 even
if it is sent by the client. In contrast, OpenSSL always generates
an unique legacy session id, so it is available with TLSv1.3 even if
session resumption does not work (such as with old Net::SSLeay and
IO::Socket::SSL modules).
author | Maxim Dounin <mdounin@mdounin.ru> |
---|---|
date | Thu, 23 Mar 2023 19:49:47 +0300 |
parents | 84b6bb8d74e5 |
children | 8dec885fa3da |
comparison
equal
deleted
inserted
replaced
1828:835630547d35 | 1829:a78c32419f02 |
---|---|
29 plan(skip_all => 'IO::Socket::SSL not installed') if $@; | 29 plan(skip_all => 'IO::Socket::SSL not installed') if $@; |
30 eval { IO::Socket::SSL::SSL_VERIFY_NONE(); }; | 30 eval { IO::Socket::SSL::SSL_VERIFY_NONE(); }; |
31 plan(skip_all => 'IO::Socket::SSL too old') if $@; | 31 plan(skip_all => 'IO::Socket::SSL too old') if $@; |
32 | 32 |
33 my $t = Test::Nginx->new()->has(qw/http http_ssl rewrite proxy/) | 33 my $t = Test::Nginx->new()->has(qw/http http_ssl rewrite proxy/) |
34 ->has_daemon('openssl')->plan(28); | 34 ->has_daemon('openssl')->plan(21); |
35 | 35 |
36 $t->write_file_expand('nginx.conf', <<'EOF'); | 36 $t->write_file_expand('nginx.conf', <<'EOF'); |
37 | 37 |
38 %%TEST_GLOBALS%% | 38 %%TEST_GLOBALS%% |
39 | 39 |
45 http { | 45 http { |
46 %%TEST_GLOBALS_HTTP%% | 46 %%TEST_GLOBALS_HTTP%% |
47 | 47 |
48 ssl_certificate_key localhost.key; | 48 ssl_certificate_key localhost.key; |
49 ssl_certificate localhost.crt; | 49 ssl_certificate localhost.crt; |
50 ssl_session_tickets off; | |
51 | 50 |
52 log_format ssl $ssl_protocol; | 51 log_format ssl $ssl_protocol; |
53 | 52 |
54 server { | 53 server { |
55 listen 127.0.0.1:8085 ssl; | 54 listen 127.0.0.1:8085 ssl; |
57 server_name localhost; | 56 server_name localhost; |
58 | 57 |
59 ssl_certificate_key inner.key; | 58 ssl_certificate_key inner.key; |
60 ssl_certificate inner.crt; | 59 ssl_certificate inner.crt; |
61 ssl_session_cache shared:SSL:1m; | 60 ssl_session_cache shared:SSL:1m; |
61 ssl_session_tickets on; | |
62 ssl_verify_client optional_no_ca; | 62 ssl_verify_client optional_no_ca; |
63 | 63 |
64 keepalive_requests 1000; | 64 keepalive_requests 1000; |
65 | 65 |
66 location / { | 66 location / { |
98 access_log %%TESTDIR%%/ssl.log ssl; | 98 access_log %%TESTDIR%%/ssl.log ssl; |
99 } | 99 } |
100 } | 100 } |
101 | 101 |
102 server { | 102 server { |
103 listen 127.0.0.1:8081; | |
104 server_name localhost; | |
105 | |
106 # Special case for enabled "ssl" directive. | |
107 | |
108 ssl on; | |
109 ssl_session_cache builtin; | |
110 | |
111 location / { | |
112 return 200 "body $ssl_session_reused"; | |
113 } | |
114 } | |
115 | |
116 server { | |
117 listen 127.0.0.1:8082 ssl; | |
118 server_name localhost; | |
119 | |
120 ssl_session_cache builtin:1000; | |
121 | |
122 location / { | |
123 return 200 "body $ssl_session_reused"; | |
124 } | |
125 } | |
126 | |
127 server { | |
128 listen 127.0.0.1:8083 ssl; | |
129 server_name localhost; | |
130 | |
131 ssl_session_cache none; | |
132 | |
133 location / { | |
134 return 200 "body $ssl_session_reused"; | |
135 } | |
136 } | |
137 | |
138 server { | |
139 listen 127.0.0.1:8084 ssl; | |
140 server_name localhost; | |
141 | |
142 ssl_session_cache off; | |
143 | |
144 location / { | |
145 return 200 "body $ssl_session_reused"; | |
146 } | |
147 } | |
148 | |
149 server { | |
150 listen 127.0.0.1:8086 ssl; | 103 listen 127.0.0.1:8086 ssl; |
151 server_name localhost; | 104 server_name localhost; |
152 | 105 |
153 ssl_session_cache shared:SSL:1m; | 106 ssl_session_cache shared:SSL:1m; |
107 ssl_session_tickets on; | |
154 ssl_session_timeout 1; | 108 ssl_session_timeout 1; |
155 | 109 |
156 location / { | 110 location / { |
157 return 200 "body $ssl_session_reused"; | 111 return 200 "body $ssl_session_reused"; |
158 } | 112 } |
214 . "-out $d/$name.crt -keyout $d/$name.key " | 168 . "-out $d/$name.crt -keyout $d/$name.key " |
215 . ">>$d/openssl.out 2>&1") == 0 | 169 . ">>$d/openssl.out 2>&1") == 0 |
216 or die "Can't create certificate for $name: $!\n"; | 170 or die "Can't create certificate for $name: $!\n"; |
217 } | 171 } |
218 | 172 |
219 # suppress deprecation warning | |
220 | |
221 open OLDERR, ">&", \*STDERR; close STDERR; | |
222 $t->run(); | 173 $t->run(); |
223 open STDERR, ">&", \*OLDERR; | 174 |
224 | 175 ############################################################################### |
225 ############################################################################### | 176 |
226 | 177 # ssl session reuse |
227 my $ctx; | 178 |
228 | 179 my $ctx = get_ssl_context(); |
229 SKIP: { | 180 |
230 skip 'no TLS 1.3 sessions', 6 if get('/protocol', 8085) =~ /TLSv1.3/ | 181 like(get('/', 8085, $ctx), qr/^body \.$/m, 'session'); |
231 && ($Net::SSLeay::VERSION < 1.88 || $IO::Socket::SSL::VERSION < 2.061); | 182 |
232 | 183 TODO: { |
233 $ctx = get_ssl_context(); | 184 local $TODO = 'no TLSv1.3 sessions, old Net::SSLeay' |
234 | 185 if $Net::SSLeay::VERSION < 1.88 && test_tls13(); |
235 like(get('/', 8085, $ctx), qr/^body \.$/m, 'cache shared'); | 186 local $TODO = 'no TLSv1.3 sessions, old IO::Socket::SSL' |
236 like(get('/', 8085, $ctx), qr/^body r$/m, 'cache shared reused'); | 187 if $IO::Socket::SSL::VERSION < 2.061 && test_tls13(); |
237 | 188 |
238 $ctx = get_ssl_context(); | 189 like(get('/', 8085, $ctx), qr/^body r$/m, 'session reused'); |
239 | 190 |
240 like(get('/', 8081, $ctx), qr/^body \.$/m, 'cache builtin'); | 191 } |
241 like(get('/', 8081, $ctx), qr/^body r$/m, 'cache builtin reused'); | |
242 | |
243 $ctx = get_ssl_context(); | |
244 | |
245 like(get('/', 8082, $ctx), qr/^body \.$/m, 'cache builtin size'); | |
246 like(get('/', 8082, $ctx), qr/^body r$/m, 'cache builtin size reused'); | |
247 | |
248 } | |
249 | |
250 $ctx = get_ssl_context(); | |
251 | |
252 like(get('/', 8083, $ctx), qr/^body \.$/m, 'cache none'); | |
253 like(get('/', 8083, $ctx), qr/^body \.$/m, 'cache none not reused'); | |
254 | |
255 $ctx = get_ssl_context(); | |
256 | |
257 like(get('/', 8084, $ctx), qr/^body \.$/m, 'cache off'); | |
258 like(get('/', 8084, $ctx), qr/^body \.$/m, 'cache off not reused'); | |
259 | 192 |
260 # ssl certificate inheritance | 193 # ssl certificate inheritance |
261 | 194 |
262 my $s = get_ssl_socket(8081); | 195 my $s = get_ssl_socket(8086); |
263 like($s->dump_peer_certificate(), qr/CN=localhost/, 'CN'); | 196 like($s->dump_peer_certificate(), qr/CN=localhost/, 'CN'); |
264 | |
265 $s->close(); | |
266 | 197 |
267 $s = get_ssl_socket(8085); | 198 $s = get_ssl_socket(8085); |
268 like($s->dump_peer_certificate(), qr/CN=inner/, 'CN inner'); | 199 like($s->dump_peer_certificate(), qr/CN=inner/, 'CN inner'); |
269 | 200 |
270 $s->close(); | |
271 | |
272 # session timeout | 201 # session timeout |
273 | 202 |
274 $ctx = get_ssl_context(); | 203 $ctx = get_ssl_context(); |
275 | 204 |
276 get('/', 8086, $ctx); | 205 get('/', 8086, $ctx); |
278 | 207 |
279 like(get('/', 8086, $ctx), qr/^body \.$/m, 'session timeout'); | 208 like(get('/', 8086, $ctx), qr/^body \.$/m, 'session timeout'); |
280 | 209 |
281 # embedded variables | 210 # embedded variables |
282 | 211 |
283 like(get('/id', 8085), qr/^body \w{64}$/m, 'session id'); | 212 $ctx = get_ssl_context(); |
213 like(get('/id', 8085, $ctx), qr/^body (\w{64})?$/m, 'session id'); | |
214 like(get('/id', 8085, $ctx), qr/^body \w{64}$/m, 'session id reused'); | |
215 | |
284 unlike(http_get('/id'), qr/body \w/, 'session id no ssl'); | 216 unlike(http_get('/id'), qr/body \w/, 'session id no ssl'); |
217 | |
285 like(get('/cipher', 8085), qr/^body [\w-]+$/m, 'cipher'); | 218 like(get('/cipher', 8085), qr/^body [\w-]+$/m, 'cipher'); |
286 | 219 |
287 SKIP: { | 220 SKIP: { |
288 skip 'BoringSSL', 1 if $t->has_module('BoringSSL'); | 221 skip 'BoringSSL', 1 if $t->has_module('BoringSSL'); |
289 | 222 |
331 'log ssl variable on lingering close'); | 264 'log ssl variable on lingering close'); |
332 | 265 |
333 like(`grep -F '[crit]' ${\($t->testdir())}/error.log`, qr/^$/s, 'no crit'); | 266 like(`grep -F '[crit]' ${\($t->testdir())}/error.log`, qr/^$/s, 'no crit'); |
334 | 267 |
335 ############################################################################### | 268 ############################################################################### |
269 | |
270 sub test_tls13 { | |
271 return get('/protocol', 8085) =~ /TLSv1.3/; | |
272 } | |
336 | 273 |
337 sub get { | 274 sub get { |
338 my ($uri, $port, $ctx) = @_; | 275 my ($uri, $port, $ctx) = @_; |
339 my $s = get_ssl_socket($port, $ctx) or return; | 276 my $s = get_ssl_socket($port, $ctx) or return; |
340 my $r = http_get($uri, socket => $s); | 277 my $r = http_get($uri, socket => $s); |