comparison ssl_sni_sessions.t @ 751:f17f83b3d8c9

Tests: session resumption with SNI.
author Maxim Dounin <mdounin@mdounin.ru>
date Fri, 23 Oct 2015 23:00:09 +0300
parents
children 80e17d44088c
comparison
equal deleted inserted replaced
750:71dfce15bbba 751:f17f83b3d8c9
1 #!/usr/bin/perl
2
3 # (C) Maxim Dounin
4
5 # Tests for SSL session resumption with SNI.
6
7 ###############################################################################
8
9 use warnings;
10 use strict;
11
12 use Test::More;
13
14 BEGIN { use FindBin; chdir($FindBin::Bin); }
15
16 use lib 'lib';
17 use Test::Nginx;
18
19 ###############################################################################
20
21 select STDERR; $| = 1;
22 select STDOUT; $| = 1;
23
24 my $t = Test::Nginx->new()->has(qw/http http_ssl sni rewrite/)
25 ->has_daemon('openssl')
26 ->write_file_expand('nginx.conf', <<'EOF');
27
28 %%TEST_GLOBALS%%
29
30 daemon off;
31
32 events {
33 }
34
35 http {
36 %%TEST_GLOBALS_HTTP%%
37
38 ssl_certificate_key localhost.key;
39 ssl_certificate localhost.crt;
40
41 server {
42 listen 127.0.0.1:8443 ssl;
43 server_name default;
44
45 ssl_session_tickets off;
46 ssl_session_cache shared:cache1:1m;
47
48 location / {
49 return 200 $ssl_server_name:$ssl_session_reused;
50 }
51 }
52
53 server {
54 listen 127.0.0.1:8443;
55 server_name nocache;
56
57 ssl_session_tickets off;
58 ssl_session_cache shared:cache2:1m;
59
60 location / {
61 return 200 $ssl_server_name:$ssl_session_reused;
62 }
63 }
64
65 server {
66 listen 127.0.0.1:8444 ssl;
67 server_name default;
68
69 ssl_session_ticket_key ticket1.key;
70
71 location / {
72 return 200 $ssl_server_name:$ssl_session_reused;
73 }
74 }
75
76 server {
77 listen 127.0.0.1:8444;
78 server_name tickets;
79
80 ssl_session_ticket_key ticket2.key;
81
82 location / {
83 return 200 $ssl_server_name:$ssl_session_reused;
84 }
85 }
86 }
87
88 EOF
89
90 eval { require IO::Socket::SSL; die if $IO::Socket::SSL::VERSION < 1.56; };
91 plan(skip_all => 'IO::Socket::SSL version >= 1.56 required') if $@;
92
93 eval {
94 if (IO::Socket::SSL->can('can_client_sni')) {
95 IO::Socket::SSL->can_client_sni() or die;
96 }
97 };
98 plan(skip_all => 'IO::Socket::SSL with OpenSSL SNI support required') if $@;
99
100 eval {
101 my $ctx = Net::SSLeay::CTX_new() or die;
102 my $ssl = Net::SSLeay::new($ctx) or die;
103 Net::SSLeay::set_tlsext_host_name($ssl, 'example.org') == 1 or die;
104 };
105 plan(skip_all => 'Net::SSLeay with OpenSSL SNI support required') if $@;
106
107 $t->plan(6);
108
109 $t->write_file('openssl.conf', <<EOF);
110 [ req ]
111 default_bits = 2048
112 encrypt_key = no
113 distinguished_name = req_distinguished_name
114 [ req_distinguished_name ]
115 EOF
116
117 my $d = $t->testdir();
118
119 foreach my $name ('localhost') {
120 system('openssl req -x509 -new '
121 . "-config '$d/openssl.conf' -subj '/CN=$name/' "
122 . "-out '$d/$name.crt' -keyout '$d/$name.key' "
123 . ">>$d/openssl.out 2>&1") == 0
124 or die "Can't create certificate for $name: $!\n";
125 }
126
127 $t->write_file('ticket1.key', '1' x 48);
128 $t->write_file('ticket2.key', '2' x 48);
129
130 $t->run();
131
132 ###############################################################################
133
134 my $ctx = IO::Socket::SSL::SSL_Context->new(
135 SSL_verify_mode => IO::Socket::SSL::SSL_VERIFY_NONE(),
136 SSL_session_cache_size => 100
137 );
138
139 # check that everything works fine with default server
140
141 like(get('default', 8443, $ctx), qr!default:\.!, 'default server');
142 like(get('default', 8443, $ctx), qr!default:r!, 'default server reused');
143
144 TODO: {
145 local $TODO = 'not yet' unless $t->has_version('1.9.6');
146
147 # check that sessions are still properly saved and restored
148 # when using an SNI-based virtual server with different session cache;
149 # as session resumption happens before SNI, only default server
150 # settings are expected to matter
151
152 # this didn't work before nginx 1.9.6 (and caused segfaults if no session
153 # cache was configured the SNI-based virtual server), because OpenSSL, when
154 # creating new sessions, uses callbacks from the default server context, but
155 # provides access to the SNI-selected server context only (ticket #235)
156
157 like(get('nocache', 8443, $ctx), qr!nocache:\.!, 'without cache');
158 like(get('nocache', 8443, $ctx), qr!nocache:r!, 'without cache reused');
159
160 # make sure tickets can be used if an SNI-based virtual server
161 # uses a different set of session ticket keys explicitly set
162
163 like(get('tickets', 8444, $ctx), qr!tickets:\.!, 'tickets');
164 like(get('tickets', 8444, $ctx), qr!tickets:r!, 'tickets reused');
165
166 }
167
168 ###############################################################################
169
170 sub get_ssl_socket {
171 my ($host, $port, $ctx) = @_;
172 my $s;
173
174 eval {
175 local $SIG{ALRM} = sub { die "timeout\n" };
176 local $SIG{PIPE} = sub { die "sigpipe\n" };
177 alarm(2);
178 $s = IO::Socket::SSL->new(
179 Proto => 'tcp',
180 PeerAddr => '127.0.0.1',
181 PeerPort => $port,
182 SSL_hostname => $host,
183 SSL_session_key => "$host:$port",
184 SSL_reuse_ctx => $ctx,
185 SSL_error_trap => sub { die $_[1] }
186 );
187 alarm(0);
188 };
189 alarm(0);
190
191 if ($@) {
192 log_in("died: $@");
193 return undef;
194 }
195
196 return $s;
197 }
198
199 sub get {
200 my ($host, $port, $ctx) = @_;
201
202 return http(<<EOF, socket => get_ssl_socket($host, $port, $ctx));
203 GET / HTTP/1.0
204 Host: $host
205
206 EOF
207 }
208
209 ###############################################################################