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 ###############################################################################