Mercurial > hg > nginx-tests
comparison mail_ssl.t @ 1861:7b7b64569f55
Tests: reworked mail SSL tests to use IO::Socket::SSL.
Relevant infrastructure is provided in Test::Nginx::IMAP (and also POP3
and SMTP for completeness). This also ensures that SSL handshake and
various read operations are guarded with timeouts.
author | Maxim Dounin <mdounin@mdounin.ru> |
---|---|
date | Thu, 18 May 2023 18:07:08 +0300 |
parents | 58951cf933e1 |
children | 7a27a4e4fdae |
comparison
equal
deleted
inserted
replaced
1860:58951cf933e1 | 1861:7b7b64569f55 |
---|---|
25 select STDERR; $| = 1; | 25 select STDERR; $| = 1; |
26 select STDOUT; $| = 1; | 26 select STDOUT; $| = 1; |
27 | 27 |
28 local $SIG{PIPE} = 'IGNORE'; | 28 local $SIG{PIPE} = 'IGNORE'; |
29 | 29 |
30 eval { | 30 my $t = Test::Nginx->new()->has(qw/mail mail_ssl imap pop3 smtp socket_ssl/) |
31 require Net::SSLeay; | 31 ->has_daemon('openssl')->plan(19); |
32 Net::SSLeay::load_error_strings(); | |
33 Net::SSLeay::SSLeay_add_ssl_algorithms(); | |
34 Net::SSLeay::randomize(); | |
35 }; | |
36 plan(skip_all => 'Net::SSLeay not installed') if $@; | |
37 | |
38 eval { exists &Net::SSLeay::P_alpn_selected or die; }; | |
39 plan(skip_all => 'Net::SSLeay with OpenSSL ALPN support required') if $@; | |
40 | |
41 my $t = Test::Nginx->new()->has(qw/mail mail_ssl imap pop3 smtp/) | |
42 ->has_daemon('openssl')->plan(18); | |
43 | 32 |
44 $t->write_file_expand('nginx.conf', <<'EOF'); | 33 $t->write_file_expand('nginx.conf', <<'EOF'); |
45 | 34 |
46 %%TEST_GLOBALS%% | 35 %%TEST_GLOBALS%% |
47 | 36 |
141 . "-key $d/$name.key -passin pass:localhost" | 130 . "-key $d/$name.key -passin pass:localhost" |
142 . ">>$d/openssl.out 2>&1") == 0 | 131 . ">>$d/openssl.out 2>&1") == 0 |
143 or die "Can't create certificate for $name: $!\n"; | 132 or die "Can't create certificate for $name: $!\n"; |
144 } | 133 } |
145 | 134 |
146 my $ctx = Net::SSLeay::CTX_new() or die("Failed to create SSL_CTX $!"); | |
147 $t->write_file('password', 'localhost'); | 135 $t->write_file('password', 'localhost'); |
148 | 136 |
149 open OLDERR, ">&", \*STDERR; close STDERR; | 137 open OLDERR, ">&", \*STDERR; close STDERR; |
150 $t->run(); | 138 $t->run(); |
151 open STDERR, ">&", \*OLDERR; | 139 open STDERR, ">&", \*OLDERR; |
162 $s->send('1 AUTHENTICATE LOGIN'); | 150 $s->send('1 AUTHENTICATE LOGIN'); |
163 $s->check(qr/\+ VXNlcm5hbWU6/, 'login'); | 151 $s->check(qr/\+ VXNlcm5hbWU6/, 'login'); |
164 | 152 |
165 # ssl_certificate inheritance | 153 # ssl_certificate inheritance |
166 | 154 |
167 ($s, $ssl) = get_ssl_socket(8145); | 155 $s = Test::Nginx::IMAP->new(PeerAddr => '127.0.0.1:' . port(8145), SSL => 1); |
168 like(Net::SSLeay::dump_peer_certificate($ssl), qr/CN=localhost/, 'CN'); | 156 $s->ok('greeting ssl'); |
169 | 157 |
170 ($s, $ssl) = get_ssl_socket(8148); | 158 like($s->socket()->dump_peer_certificate(), qr/CN=localhost/, 'CN'); |
171 like(Net::SSLeay::dump_peer_certificate($ssl), qr/CN=inherits/, 'CN inner'); | 159 |
160 $s = Test::Nginx::IMAP->new(PeerAddr => '127.0.0.1:' . port(8148), SSL => 1); | |
161 $s->read(); | |
162 | |
163 like($s->socket()->dump_peer_certificate(), qr/CN=inherits/, 'CN inner'); | |
172 | 164 |
173 # alpn | 165 # alpn |
174 | 166 |
175 ok(get_ssl_socket(8148, ['imap']), 'alpn'); | 167 $s = Test::Nginx::IMAP->new( |
168 PeerAddr => '127.0.0.1:' . port(8148), | |
169 SSL => 1, | |
170 SSL_alpn_protocols => [ 'imap' ] | |
171 ); | |
172 $s->ok('alpn'); | |
176 | 173 |
177 SKIP: { | 174 SKIP: { |
178 skip 'LibreSSL too old', 1 | 175 skip 'LibreSSL too old', 1 |
179 if $t->has_module('LibreSSL') | 176 if $t->has_module('LibreSSL') |
180 and not $t->has_feature('libressl:3.4.0'); | 177 and not $t->has_feature('libressl:3.4.0'); |
182 if $t->has_module('OpenSSL') | 179 if $t->has_module('OpenSSL') |
183 and not $t->has_feature('openssl:1.1.0'); | 180 and not $t->has_feature('openssl:1.1.0'); |
184 | 181 |
185 TODO: { | 182 TODO: { |
186 local $TODO = 'not yet' unless $t->has_version('1.21.4'); | 183 local $TODO = 'not yet' unless $t->has_version('1.21.4'); |
187 | 184 local $TODO = 'no ALPN support in IO::Socket::SSL' |
188 ok(!get_ssl_socket(8148, ['unknown']), 'alpn rejected'); | 185 unless $t->has_feature('socket_ssl_alpn'); |
186 | |
187 $s = Test::Nginx::IMAP->new( | |
188 PeerAddr => '127.0.0.1:' . port(8148), | |
189 SSL => 1, | |
190 SSL_alpn_protocols => [ 'unknown' ] | |
191 ); | |
192 ok(!$s->read(), 'alpn rejected'); | |
189 | 193 |
190 } | 194 } |
191 | 195 |
192 } | 196 } |
193 | 197 |
268 | 272 |
269 $s->send('STARTTLS'); | 273 $s->send('STARTTLS'); |
270 $s->ok('smtp starttls only'); | 274 $s->ok('smtp starttls only'); |
271 | 275 |
272 ############################################################################### | 276 ############################################################################### |
273 | |
274 sub get_ssl_socket { | |
275 my ($port, $alpn) = @_; | |
276 | |
277 my $s = IO::Socket::INET->new('127.0.0.1:' . port($port)); | |
278 my $ssl = Net::SSLeay::new($ctx) or die("Failed to create SSL $!"); | |
279 Net::SSLeay::set_alpn_protos($ssl, $alpn) if defined $alpn; | |
280 Net::SSLeay::set_fd($ssl, fileno($s)); | |
281 Net::SSLeay::connect($ssl) == 1 or return; | |
282 return ($s, $ssl); | |
283 } | |
284 | |
285 ############################################################################### |