Mercurial > hg > nginx-tests
comparison ssl_certificates.t @ 1865:0e1865aa9b33
Tests: reworked http SSL tests to use IO::Socket::SSL.
Relevant infrastructure is provided in Test::Nginx http() functions.
This also ensures that SSL handshake and various read and write operations
are guarded with timeouts.
The ssl_sni_reneg.t test uses IO::Socket::SSL::_get_ssl_object() to access
the Net::SSLeay object directly and trigger renegotation. While
not exactly correct, this seems to be good enough for tests.
Similarly, IO::Socket::SSL::_get_ssl_object() is used in ssl_stapling.t,
since SSL_ocsp_staple_callback is called with the socket instead of the
Net::SSLeay object.
Similarly, IO::Socket::SSL::_get_ssl_object() is used in ssl_verify_client.t,
since there seems to be no way to obtain CA list with IO::Socket::SSL.
Notable change to http() request interface is that http_end() now closes
the socket. This is to make sure that SSL connections are properly
closed and SSL sessions are not removed from the IO::Socket::SSL session
cache. This affected access_log.t, which was modified accordingly.
author | Maxim Dounin <mdounin@mdounin.ru> |
---|---|
date | Thu, 18 May 2023 18:07:17 +0300 |
parents | dbce8fb5f5f8 |
children | 1ba5108b6c24 |
comparison
equal
deleted
inserted
replaced
1864:46351d990aee | 1865:0e1865aa9b33 |
---|---|
20 ############################################################################### | 20 ############################################################################### |
21 | 21 |
22 select STDERR; $| = 1; | 22 select STDERR; $| = 1; |
23 select STDOUT; $| = 1; | 23 select STDOUT; $| = 1; |
24 | 24 |
25 eval { | 25 my $t = Test::Nginx->new()->has(qw/http http_ssl socket_ssl/) |
26 require Net::SSLeay; | 26 ->has_daemon('openssl'); |
27 Net::SSLeay::load_error_strings(); | |
28 Net::SSLeay::SSLeay_add_ssl_algorithms(); | |
29 Net::SSLeay::randomize(); | |
30 Net::SSLeay::SSLeay(); | |
31 }; | |
32 plan(skip_all => 'Net::SSLeay not installed or too old') if $@; | |
33 | |
34 my $t = Test::Nginx->new()->has(qw/http http_ssl/)->has_daemon('openssl'); | |
35 | 27 |
36 plan(skip_all => 'no multiple certificates') if $t->has_module('BoringSSL'); | 28 plan(skip_all => 'no multiple certificates') if $t->has_module('BoringSSL'); |
37 | 29 |
38 $t->write_file_expand('nginx.conf', <<'EOF'); | 30 $t->write_file_expand('nginx.conf', <<'EOF'); |
39 | 31 |
49 | 41 |
50 ssl_certificate_key rsa.key; | 42 ssl_certificate_key rsa.key; |
51 ssl_certificate rsa.crt; | 43 ssl_certificate rsa.crt; |
52 ssl_ciphers DEFAULT:ECCdraft; | 44 ssl_ciphers DEFAULT:ECCdraft; |
53 | 45 |
46 add_header X-SSL-Protocol $ssl_protocol; | |
47 | |
54 server { | 48 server { |
55 listen 127.0.0.1:8080 ssl; | 49 listen 127.0.0.1:8443 ssl; |
56 server_name localhost; | 50 server_name localhost; |
57 | 51 |
58 ssl_certificate_key ec.key; | 52 ssl_certificate_key ec.key; |
59 ssl_certificate ec.crt; | 53 ssl_certificate ec.crt; |
60 | 54 |
89 . "-out $d/$name.crt -keyout $d/$name.key " | 83 . "-out $d/$name.crt -keyout $d/$name.key " |
90 . ">>$d/openssl.out 2>&1") == 0 | 84 . ">>$d/openssl.out 2>&1") == 0 |
91 or die "Can't create certificate for $name: $!\n"; | 85 or die "Can't create certificate for $name: $!\n"; |
92 } | 86 } |
93 | 87 |
88 $t->write_file('index.html', ''); | |
89 | |
94 $t->run()->plan(2); | 90 $t->run()->plan(2); |
95 | 91 |
96 ############################################################################### | 92 ############################################################################### |
97 | 93 |
98 like(get_cert('RSA'), qr/CN=rsa/, 'ssl cert RSA'); | 94 TODO: { |
99 like(get_cert('ECDSA'), qr/CN=ec/, 'ssl cert ECDSA'); | 95 local $TODO = 'broken TLSv1.3 sigalgs in LibreSSL' |
96 if $t->has_module('LibreSSL') && test_tls13(); | |
97 | |
98 like(cert('RSA'), qr/CN=rsa/, 'ssl cert RSA'); | |
99 | |
100 } | |
101 | |
102 like(cert('ECDSA'), qr/CN=ec/, 'ssl cert ECDSA'); | |
100 | 103 |
101 ############################################################################### | 104 ############################################################################### |
102 | 105 |
103 sub get_version { | 106 sub test_tls13 { |
104 my ($s, $ssl) = get_ssl_socket(); | 107 return http_get('/', SSL => 1) =~ /TLSv1.3/; |
105 return Net::SSLeay::version($ssl); | |
106 } | 108 } |
107 | 109 |
108 sub get_cert { | 110 sub cert { |
109 my ($type) = @_; | 111 my $s = get_socket(@_) || return; |
110 $type = 'PSS' if $type eq 'RSA' && get_version() > 0x0303; | 112 return $s->dump_peer_certificate(); |
111 my ($s, $ssl) = get_ssl_socket($type); | |
112 my $cipher = Net::SSLeay::get_cipher($ssl); | |
113 Test::Nginx::log_core('||', "cipher: $cipher"); | |
114 return Net::SSLeay::dump_peer_certificate($ssl); | |
115 } | 113 } |
116 | 114 |
117 sub get_ssl_socket { | 115 sub get_socket { |
118 my ($type) = @_; | 116 my ($type) = @_; |
119 my $s; | |
120 | 117 |
121 eval { | 118 my $ctx_cb = sub { |
122 local $SIG{ALRM} = sub { die "timeout\n" }; | 119 my $ctx = shift; |
123 local $SIG{PIPE} = sub { die "sigpipe\n" }; | 120 return unless defined $type; |
124 alarm(8); | 121 my $ssleay = Net::SSLeay::SSLeay(); |
125 $s = IO::Socket::INET->new('127.0.0.1:' . port(8080)); | 122 return if ($ssleay < 0x1000200f || $ssleay == 0x20000000); |
126 alarm(0); | 123 my $sigalgs = 'RSA+SHA256:PSS+SHA256'; |
124 $sigalgs = $type . '+SHA256' unless $type eq 'RSA'; | |
125 # SSL_CTRL_SET_SIGALGS_LIST | |
126 Net::SSLeay::CTX_ctrl($ctx, 98, 0, $sigalgs) | |
127 or die("Failed to set sigalgs"); | |
127 }; | 128 }; |
128 alarm(0); | |
129 | 129 |
130 if ($@) { | 130 return http_get( |
131 log_in("died: $@"); | 131 '/', start => 1, |
132 return undef; | 132 SSL => 1, |
133 } | 133 SSL_cipher_list => $type, |
134 | 134 SSL_create_ctx_callback => $ctx_cb |
135 my $ctx = Net::SSLeay::CTX_new() or die("Failed to create SSL_CTX $!"); | 135 ); |
136 | |
137 if (defined $type) { | |
138 my $ssleay = Net::SSLeay::SSLeay(); | |
139 if ($ssleay < 0x1000200f || $ssleay == 0x20000000) { | |
140 Net::SSLeay::CTX_set_cipher_list($ctx, $type) | |
141 or die("Failed to set cipher list"); | |
142 } else { | |
143 # SSL_CTRL_SET_SIGALGS_LIST | |
144 Net::SSLeay::CTX_ctrl($ctx, 98, 0, $type . '+SHA256') | |
145 or die("Failed to set sigalgs"); | |
146 } | |
147 } | |
148 | |
149 my $ssl = Net::SSLeay::new($ctx) or die("Failed to create SSL $!"); | |
150 Net::SSLeay::set_fd($ssl, fileno($s)); | |
151 Net::SSLeay::connect($ssl) or die("ssl connect"); | |
152 return ($s, $ssl); | |
153 } | 136 } |
154 | 137 |
155 ############################################################################### | 138 ############################################################################### |