Mercurial > hg > nginx-tests
comparison ssl_verify_client.t @ 1114:c5df4742ad40
Tests: more http/stream ssl_verify_client tests borrowed from mail.
Additionally, this includes test for ssl_trusted_certificate.
author | Sergey Kandaurov <pluknet@nginx.com> |
---|---|
date | Thu, 19 Jan 2017 16:59:20 +0300 |
parents | efccab043dd3 |
children | 8ef51dbb5d69 |
comparison
equal
deleted
inserted
replaced
1113:41690e007ad8 | 1114:c5df4742ad40 |
---|---|
10 use warnings; | 10 use warnings; |
11 use strict; | 11 use strict; |
12 | 12 |
13 use Test::More; | 13 use Test::More; |
14 | 14 |
15 use Socket qw/ :DEFAULT CRLF /; | |
16 | |
15 BEGIN { use FindBin; chdir($FindBin::Bin); } | 17 BEGIN { use FindBin; chdir($FindBin::Bin); } |
16 | 18 |
17 use lib 'lib'; | 19 use lib 'lib'; |
18 use Test::Nginx; | 20 use Test::Nginx; |
19 | 21 |
20 ############################################################################### | 22 ############################################################################### |
21 | 23 |
22 select STDERR; $| = 1; | 24 select STDERR; $| = 1; |
23 select STDOUT; $| = 1; | 25 select STDOUT; $| = 1; |
24 | 26 |
25 eval { require IO::Socket::SSL; }; | 27 eval { |
26 plan(skip_all => 'IO::Socket::SSL not installed') if $@; | 28 require Net::SSLeay; |
27 eval { IO::Socket::SSL->can_client_sni() or die; }; | 29 Net::SSLeay::load_error_strings(); |
28 plan(skip_all => 'IO::Socket::SSL with OpenSSL SNI support required') if $@; | 30 Net::SSLeay::SSLeay_add_ssl_algorithms(); |
31 Net::SSLeay::randomize(); | |
32 }; | |
33 plan(skip_all => 'Net::SSLeay not installed') if $@; | |
34 | |
35 eval { | |
36 my $ctx = Net::SSLeay::CTX_new() or die; | |
37 my $ssl = Net::SSLeay::new($ctx) or die; | |
38 Net::SSLeay::set_tlsext_host_name($ssl, 'example.org') == 1 or die; | |
39 }; | |
40 plan(skip_all => 'Net::SSLeay with OpenSSL SNI support required') if $@; | |
29 | 41 |
30 my $t = Test::Nginx->new()->has(qw/http http_ssl sni/) | 42 my $t = Test::Nginx->new()->has(qw/http http_ssl sni/) |
31 ->has_daemon('openssl')->plan(3); | 43 ->has_daemon('openssl')->plan(10); |
32 | 44 |
33 $t->write_file_expand('nginx.conf', <<'EOF'); | 45 $t->write_file_expand('nginx.conf', <<'EOF'); |
34 | 46 |
35 %%TEST_GLOBALS%% | 47 %%TEST_GLOBALS%% |
36 | 48 |
40 } | 52 } |
41 | 53 |
42 http { | 54 http { |
43 %%TEST_GLOBALS_HTTP%% | 55 %%TEST_GLOBALS_HTTP%% |
44 | 56 |
45 ssl_certificate_key localhost.key; | 57 add_header X-Verify x$ssl_client_verify:${ssl_client_cert}x; |
46 ssl_certificate localhost.crt; | |
47 | 58 |
48 ssl_verify_client optional_no_ca; | 59 ssl_certificate_key 1.example.com.key; |
49 | 60 ssl_certificate 1.example.com.crt; |
50 add_header X-Verify $ssl_client_verify; | |
51 | 61 |
52 server { | 62 server { |
53 listen 127.0.0.1:8080 ssl; | 63 listen 127.0.0.1:8080; |
54 server_name localhost; | 64 server_name localhost; |
55 | 65 |
56 ssl_client_certificate client.crt; | 66 ssl_verify_client on; |
57 | 67 ssl_client_certificate 2.example.com.crt; |
58 location / { } | |
59 } | 68 } |
60 | 69 |
61 server { | 70 server { |
62 listen 127.0.0.1:8080 ssl; | 71 listen 127.0.0.1:8081 ssl; |
63 server_name example.com; | 72 server_name on; |
64 | 73 |
65 location / { } | 74 ssl_verify_client on; |
75 ssl_client_certificate 2.example.com.crt; | |
76 } | |
77 | |
78 server { | |
79 listen 127.0.0.1:8081 ssl; | |
80 server_name optional; | |
81 | |
82 ssl_verify_client optional; | |
83 ssl_client_certificate 2.example.com.crt; | |
84 ssl_trusted_certificate 3.example.com.crt; | |
85 } | |
86 | |
87 server { | |
88 listen 127.0.0.1:8081 ssl; | |
89 server_name optional_no_ca; | |
90 | |
91 ssl_verify_client optional_no_ca; | |
92 ssl_client_certificate 2.example.com.crt; | |
66 } | 93 } |
67 } | 94 } |
68 | 95 |
69 EOF | 96 EOF |
70 | 97 |
76 [ req_distinguished_name ] | 103 [ req_distinguished_name ] |
77 EOF | 104 EOF |
78 | 105 |
79 my $d = $t->testdir(); | 106 my $d = $t->testdir(); |
80 | 107 |
81 foreach my $name ('localhost', 'client') { | 108 foreach my $name ('1.example.com', '2.example.com', '3.example.com') { |
82 system('openssl req -x509 -new ' | 109 system('openssl req -x509 -new ' |
83 . "-config '$d/openssl.conf' -subj '/CN=$name/' " | 110 . "-config '$d/openssl.conf' -subj '/CN=$name/' " |
84 . "-out '$d/$name.crt' -keyout '$d/$name.key' " | 111 . "-out '$d/$name.crt' -keyout '$d/$name.key' " |
85 . ">>$d/openssl.out 2>&1") == 0 | 112 . ">>$d/openssl.out 2>&1") == 0 |
86 or die "Can't create certificate for $name: $!\n"; | 113 or die "Can't create certificate for $name: $!\n"; |
90 | 117 |
91 $t->run(); | 118 $t->run(); |
92 | 119 |
93 ############################################################################### | 120 ############################################################################### |
94 | 121 |
95 like(get('localhost'), qr/SUCCESS/, 'success'); | 122 like(http_get('/t'), qr/x:x/, 'plain connection'); |
96 like(get('example.com'), qr/FAILED/, 'failed'); | 123 like(get('on'), qr/400 Bad Request/, 'no cert'); |
97 like(get('localhost', 'example.com'), qr/421 Misdirected/, 'misdirected'); | 124 like(get('optional'), qr/NONE:x/, 'no optional cert'); |
125 like(get('optional', '1.example.com'), qr/400 Bad/, 'bad optional cert'); | |
126 like(get('optional_no_ca', '1.example.com'), qr/FAILED.*BEGIN/, | |
127 'bad optional_no_ca cert'); | |
128 | |
129 like(get('localhost', '2.example.com'), qr/SUCCESS.*BEGIN/, 'good cert'); | |
130 like(get('optional', '2.example.com'), qr/SUCCESS.*BEGI/, 'good cert optional'); | |
131 like(get('optional', '3.example.com'), qr/SUCCESS.*BEGIN/, 'good cert trusted'); | |
132 | |
133 SKIP: { | |
134 skip 'Net::SSLeay version >= 1.36 required', 1 if $Net::SSLeay::VERSION < 1.36; | |
135 | |
136 my $ca = join ' ', get('optional', '3.example.com'); | |
137 is($ca, '/CN=2.example.com', 'no trusted sent'); | |
138 | |
139 } | |
140 | |
141 like(get('optional', undef, 'localhost'), qr/421 Misdirected/, 'misdirected'); | |
98 | 142 |
99 ############################################################################### | 143 ############################################################################### |
100 | 144 |
101 sub get { | 145 sub get { |
102 my ($sni, $host) = @_; | 146 my ($sni, $cert, $host) = @_; |
103 my $s; | |
104 | 147 |
105 $host = $sni if !defined $host; | 148 $host = $sni if !defined $host; |
106 | 149 |
107 eval { | 150 my $dest_ip = inet_aton('127.0.0.1'); |
108 local $SIG{ALRM} = sub { die "timeout\n" }; | 151 my $dest_serv_params = sockaddr_in(port(8081), $dest_ip); |
109 local $SIG{PIPE} = sub { die "sigpipe\n" }; | |
110 alarm(2); | |
111 $s = IO::Socket::SSL->new( | |
112 Proto => 'tcp', | |
113 PeerAddr => '127.0.0.1', | |
114 PeerPort => port(8080), | |
115 SSL_verify_mode => IO::Socket::SSL::SSL_VERIFY_NONE(), | |
116 SSL_hostname => $sni, | |
117 SSL_cert_file => "$d/client.crt", | |
118 SSL_key_file => "$d/client.key", | |
119 SSL_error_trap => sub { die $_[1] } | |
120 ); | |
121 alarm(0); | |
122 }; | |
123 alarm(0); | |
124 | 152 |
125 if ($@) { | 153 socket(my $s, &AF_INET, &SOCK_STREAM, 0) or die "socket: $!"; |
126 log_in("died: $@"); | 154 connect($s, $dest_serv_params) or die "connect: $!"; |
127 return undef; | 155 |
156 my $ctx = Net::SSLeay::CTX_new() or die("Failed to create SSL_CTX $!"); | |
157 Net::SSLeay::set_cert_and_key($ctx, "$d/$cert.crt", "$d/$cert.key") | |
158 or die if $cert; | |
159 my $ssl = Net::SSLeay::new($ctx) or die("Failed to create SSL $!"); | |
160 Net::SSLeay::set_tlsext_host_name($ssl, $sni) == 1 or die; | |
161 Net::SSLeay::set_fd($ssl, fileno($s)); | |
162 Net::SSLeay::connect($ssl) or die("ssl connect"); | |
163 | |
164 Net::SSLeay::write($ssl, 'GET /t HTTP/1.0' . CRLF); | |
165 Net::SSLeay::write($ssl, "Host: $host" . CRLF . CRLF); | |
166 my $buf = Net::SSLeay::read($ssl); | |
167 log_in($buf); | |
168 return $buf unless wantarray(); | |
169 | |
170 my $list = Net::SSLeay::get_client_CA_list($ssl); | |
171 my @names; | |
172 for my $i (0 .. Net::SSLeay::sk_X509_NAME_num($list) - 1) { | |
173 my $name = Net::SSLeay::sk_X509_NAME_value($list, $i); | |
174 push @names, Net::SSLeay::X509_NAME_oneline($name); | |
128 } | 175 } |
129 | 176 return @names; |
130 return http(<<EOF, socket => $s); | |
131 GET /t HTTP/1.0 | |
132 Host: $host | |
133 | |
134 EOF | |
135 } | 177 } |
136 | 178 |
137 ############################################################################### | 179 ############################################################################### |