Mercurial > hg > nginx-tests
comparison ssl_verify_depth.t @ 1610:bad6aa24ec10
Tests: reworked ssl_verify_depth tests.
Full matrix of various verify depths and chains is now tested.
Incompatible behaviour of OpenSSL 1.1.0+, which now limits the total
length of a chain instead of maximum number of signatures checked,
is explained in the comments. Attempts to incorrectly use
client-provided intermediate certificates, introduced in aa5a61d1254b,
are removed.
author | Maxim Dounin <mdounin@mdounin.ru> |
---|---|
date | Tue, 17 Nov 2020 06:53:45 +0300 |
parents | aa5a61d1254b |
children | b28f88e352dd |
comparison
equal
deleted
inserted
replaced
1609:f3ba4c74de31 | 1610:bad6aa24ec10 |
---|---|
26 plan(skip_all => 'IO::Socket::SSL not installed') if $@; | 26 plan(skip_all => 'IO::Socket::SSL not installed') if $@; |
27 eval { IO::Socket::SSL::SSL_VERIFY_NONE(); }; | 27 eval { IO::Socket::SSL::SSL_VERIFY_NONE(); }; |
28 plan(skip_all => 'IO::Socket::SSL too old') if $@; | 28 plan(skip_all => 'IO::Socket::SSL too old') if $@; |
29 | 29 |
30 my $t = Test::Nginx->new()->has(qw/http http_ssl/) | 30 my $t = Test::Nginx->new()->has(qw/http http_ssl/) |
31 ->has_daemon('openssl')->plan(2); | 31 ->has_daemon('openssl')->plan(9); |
32 | 32 |
33 $t->write_file_expand('nginx.conf', <<'EOF'); | 33 $t->write_file_expand('nginx.conf', <<'EOF'); |
34 | 34 |
35 %%TEST_GLOBALS%% | 35 %%TEST_GLOBALS%% |
36 | 36 |
40 } | 40 } |
41 | 41 |
42 http { | 42 http { |
43 %%TEST_GLOBALS_HTTP%% | 43 %%TEST_GLOBALS_HTTP%% |
44 | 44 |
45 ssl_certificate_key localhost.key; | |
46 ssl_certificate localhost.crt; | 45 ssl_certificate localhost.crt; |
46 ssl_certificate_key localhost.key; | |
47 | 47 |
48 ssl_verify_client on; | 48 ssl_verify_client on; |
49 ssl_client_certificate root.crt; | 49 ssl_client_certificate root-int.crt; |
50 | 50 |
51 add_header X-Client $ssl_client_s_dn always; | |
51 add_header X-Verify $ssl_client_verify always; | 52 add_header X-Verify $ssl_client_verify always; |
52 | 53 |
53 server { | 54 server { |
54 listen 127.0.0.1:8080 ssl; | 55 listen 127.0.0.1:8080 ssl; |
55 server_name localhost; | 56 server_name localhost; |
56 ssl_verify_depth 3; | 57 ssl_verify_depth 0; |
57 } | 58 } |
58 | 59 |
59 server { | 60 server { |
60 listen 127.0.0.1:8081 ssl; | 61 listen 127.0.0.1:8081 ssl; |
61 server_name localhost; | 62 server_name localhost; |
63 ssl_verify_depth 1; | |
64 } | |
65 | |
66 server { | |
67 listen 127.0.0.1:8082 ssl; | |
68 server_name localhost; | |
69 ssl_verify_depth 2; | |
62 } | 70 } |
63 } | 71 } |
64 | 72 |
65 EOF | 73 EOF |
66 | 74 |
100 . "-out $d/$name.crt -keyout $d/$name.key " | 108 . "-out $d/$name.crt -keyout $d/$name.key " |
101 . ">>$d/openssl.out 2>&1") == 0 | 109 . ">>$d/openssl.out 2>&1") == 0 |
102 or die "Can't create certificate for $name: $!\n"; | 110 or die "Can't create certificate for $name: $!\n"; |
103 } | 111 } |
104 | 112 |
105 foreach my $name ('int', 'int2', 'end') { | 113 foreach my $name ('int', 'end') { |
106 system("openssl req -new " | 114 system("openssl req -new " |
107 . "-config $d/openssl.conf -subj /CN=$name/ " | 115 . "-config $d/openssl.conf -subj /CN=$name/ " |
108 . "-out $d/$name.csr -keyout $d/$name.key " | 116 . "-out $d/$name.csr -keyout $d/$name.key " |
109 . ">>$d/openssl.out 2>&1") == 0 | 117 . ">>$d/openssl.out 2>&1") == 0 |
110 or die "Can't create certificate for $name: $!\n"; | 118 or die "Can't create certificate for $name: $!\n"; |
119 . ">>$d/openssl.out 2>&1") == 0 | 127 . ">>$d/openssl.out 2>&1") == 0 |
120 or die "Can't sign certificate for int: $!\n"; | 128 or die "Can't sign certificate for int: $!\n"; |
121 | 129 |
122 system("openssl ca -batch -config $d/ca.conf " | 130 system("openssl ca -batch -config $d/ca.conf " |
123 . "-keyfile $d/int.key -cert $d/int.crt " | 131 . "-keyfile $d/int.key -cert $d/int.crt " |
124 . "-subj /CN=int2/ -in $d/int2.csr -out $d/int2.crt " | |
125 . ">>$d/openssl.out 2>&1") == 0 | |
126 or die "Can't sign certificate for int2: $!\n"; | |
127 | |
128 system("openssl ca -batch -config $d/ca.conf " | |
129 . "-keyfile $d/int2.key -cert $d/int2.crt " | |
130 . "-subj /CN=end/ -in $d/end.csr -out $d/end.crt " | 132 . "-subj /CN=end/ -in $d/end.csr -out $d/end.crt " |
131 . ">>$d/openssl.out 2>&1") == 0 | 133 . ">>$d/openssl.out 2>&1") == 0 |
132 or die "Can't sign certificate for end: $!\n"; | 134 or die "Can't sign certificate for end: $!\n"; |
133 | 135 |
134 $t->write_file('client.key', $t->read_file('end.key') . | 136 $t->write_file('root-int.crt', $t->read_file('root.crt') |
135 $t->read_file('int.key') . $t->read_file('int2.key')); | 137 . $t->read_file('int.crt')); |
136 $t->write_file('client.crt', $t->read_file('end.crt') . | |
137 $t->read_file('int.crt') . $t->read_file('int2.crt')); | |
138 | 138 |
139 $t->write_file('t', ''); | 139 $t->write_file('t', ''); |
140 $t->run(); | 140 $t->run(); |
141 | 141 |
142 ############################################################################### | 142 ############################################################################### |
143 | 143 |
144 like(get(8080, 'client'), qr/SUCCESS/, 'verify depth'); | 144 # with verify depth 0, only self-signed certificates should |
145 like(get(8081, 'client'), qr/FAILED/, 'verify depth limited'); | 145 # be allowed |
146 | |
147 # OpenSSL 1.1.0+ instead limits the number of intermediate certs allowed; | |
148 # as a result, it is not possible to limit certificate checking | |
149 # to self-signed certificates only when using OpenSSL 1.1.0+ | |
150 | |
151 like(get(8080, 'root'), qr/SUCCESS/, 'verify depth 0 - root'); | |
152 like(get(8080, 'int'), qr/FAI|SUC/, 'verify depth 0 - no int'); | |
153 like(get(8080, 'end'), qr/FAILED/, 'verify depth 0 - no end'); | |
154 | |
155 # with verify depth 1 (the default), one signature is | |
156 # expected to be checked, so certificates directly signed | |
157 # by the root cert are allowed, but nothing more | |
158 | |
159 # OpenSSL 1.1.0+ instead limits the number of intermediate certs allowed; | |
160 # so with depth 1 it is possible to validate not only directly signed | |
161 # certificates, but also chains with one intermediate certificate | |
162 | |
163 like(get(8081, 'root'), qr/SUCCESS/, 'verify depth 1 - root'); | |
164 like(get(8081, 'int'), qr/SUCCESS/, 'verify depth 1 - int'); | |
165 like(get(8081, 'end'), qr/FAI|SUC/, 'verify depth 1 - no end'); | |
166 | |
167 # with verify depth 2 it is also possible to validate up to two signatures, | |
168 # so chains with one intermediate certificate are allowed | |
169 | |
170 like(get(8082, 'root'), qr/SUCCESS/, 'verify depth 2 - root'); | |
171 like(get(8082, 'int'), qr/SUCCESS/, 'verify depth 2 - int'); | |
172 like(get(8082, 'end'), qr/SUCCESS/, 'verify depth 2 - end'); | |
146 | 173 |
147 ############################################################################### | 174 ############################################################################### |
148 | 175 |
149 sub get { | 176 sub get { |
150 my ($port, $cert) = @_; | 177 my ($port, $cert) = @_; |
151 my $s = get_ssl_socket($port, $cert) or return; | 178 my $s = get_ssl_socket($port, $cert) or return; |
152 http_get('/t', socket => $s); | 179 http_get("/t?$cert", socket => $s); |
153 } | 180 } |
154 | 181 |
155 sub get_ssl_socket { | 182 sub get_ssl_socket { |
156 my ($port, $cert) = @_; | 183 my ($port, $cert) = @_; |
157 my ($s); | 184 my ($s); |