blob: 33d09cfa2910fcc7a8089330a93460f55c586433 [file] [log] [blame]
Sergey Kandaurov235df362015-04-03 17:53:04 +03001#!/usr/bin/perl
2
3# (C) Maxim Dounin
4# (C) Sergey Kandaurov
5# (C) Nginx, Inc.
6
7# Tests for nginx mail imap module with ssl.
8
9###############################################################################
10
11use warnings;
12use strict;
13
14use Test::More;
15
Sergey Kandaurov235df362015-04-03 17:53:04 +030016use MIME::Base64;
17
18BEGIN { use FindBin; chdir($FindBin::Bin); }
19
20use lib 'lib';
21use Test::Nginx;
22use Test::Nginx::IMAP;
23
24###############################################################################
25
26select STDERR; $| = 1;
27select STDOUT; $| = 1;
28
29eval { require IO::Socket::SSL; };
30plan(skip_all => 'IO::Socket::SSL not installed') if $@;
31eval { IO::Socket::SSL::SSL_VERIFY_NONE(); };
32plan(skip_all => 'IO::Socket::SSL too old') if $@;
33
34local $SIG{PIPE} = 'IGNORE';
35
36my $t = Test::Nginx->new()
37 ->has(qw/mail mail_ssl imap http rewrite/)->has_daemon('openssl')
Sergey Kandaurov7649cdb2015-12-09 13:52:37 +030038 ->run_daemon(\&Test::Nginx::IMAP::imap_test_daemon)->plan(12);
39
40$t->todo_alerts() if $^O eq 'solaris';
41
42$t->write_file_expand('nginx.conf', <<'EOF');
Sergey Kandaurov235df362015-04-03 17:53:04 +030043
44%%TEST_GLOBALS%%
45
46daemon off;
47
48events {
49}
50
51mail {
52 proxy_pass_error_message on;
53 auth_http http://127.0.0.1:8080/mail/auth;
54 auth_http_pass_client_cert on;
55
56 ssl_certificate_key 1.example.com.key;
57 ssl_certificate 1.example.com.crt;
58
59 server {
60 listen 127.0.0.1:8142;
61 protocol imap;
62 }
63
64 server {
65 listen 127.0.0.1:8143 ssl;
66 protocol imap;
67
68 ssl_verify_client on;
69 ssl_client_certificate 2.example.com.crt;
70 }
71
72 server {
73 listen 127.0.0.1:8145 ssl;
74 protocol imap;
75
76 ssl_verify_client optional;
77 ssl_client_certificate 2.example.com.crt;
78 }
79
80 server {
81 listen 127.0.0.1:8146 ssl;
82 protocol imap;
83
84 ssl_verify_client optional;
85 ssl_client_certificate 2.example.com.crt;
86 ssl_trusted_certificate 3.example.com.crt;
87 }
88
89 server {
90 listen 127.0.0.1:8147 ssl;
91 protocol imap;
92
93 ssl_verify_client optional_no_ca;
94 ssl_client_certificate 2.example.com.crt;
95 }
96}
97
98http {
99 %%TEST_GLOBALS_HTTP%%
100
101 log_format test '$http_auth_ssl:$http_auth_ssl_verify:'
102 '$http_auth_ssl_subject:$http_auth_ssl_issuer:'
103 '$http_auth_ssl_serial:$http_auth_ssl_fingerprint:'
104 '$http_auth_ssl_cert';
105
106 server {
107 listen 127.0.0.1:8080;
108 server_name localhost;
109
110 location = /mail/auth {
111 access_log auth.log test;
112
113 add_header Auth-Status OK;
114 add_header Auth-Server 127.0.0.1;
115 add_header Auth-Port 8144;
116 add_header Auth-Wait 1;
117 return 204;
118 }
119 }
120}
121
122EOF
123
124$t->write_file('openssl.conf', <<EOF);
125[ req ]
126default_bits = 1024
127encrypt_key = no
128distinguished_name = req_distinguished_name
129[ req_distinguished_name ]
130EOF
131
132my $d = $t->testdir();
133
134foreach my $name ('1.example.com', '2.example.com', '3.example.com') {
135 system('openssl req -x509 -new '
136 . "-config '$d/openssl.conf' -subj '/CN=$name/' "
137 . "-out '$d/$name.crt' -keyout '$d/$name.key' "
138 . ">>$d/openssl.out 2>&1") == 0
139 or die "Can't create certificate for $name: $!\n";
140}
141
Sergey Kandaurov66f73d22015-05-03 12:45:09 +0300142$t->run();
Sergey Kandaurov235df362015-04-03 17:53:04 +0300143
144###############################################################################
145
146my $cred = encode_base64("\0test\@example.com\0secret", '');
147my %ssl = (
Sergey Kandaurov9a706c82015-10-27 18:26:22 +0300148 SSL => 1,
149 SSL_verify_mode => IO::Socket::SSL::SSL_VERIFY_NONE(),
150 SSL_error_trap => sub { die $_[1] },
Sergey Kandaurov235df362015-04-03 17:53:04 +0300151);
152
153# no ssl connection
154
155my $s = Test::Nginx::IMAP->new(PeerAddr => '127.0.0.1:8142');
156$s->ok('plain connection');
157$s->send('1 AUTHENTICATE PLAIN ' . $cred);
158
159# no cert
160
161$s = Test::Nginx::IMAP->new(PeerAddr => '127.0.0.1:8143', %ssl);
162$s->check(qr/BYE No required SSL certificate/, 'no cert');
163
164# no cert with ssl_verify_client optional
165
166$s = Test::Nginx::IMAP->new(PeerAddr => '127.0.0.1:8145', %ssl);
167$s->ok('no optional cert');
168$s->send('1 AUTHENTICATE PLAIN ' . $cred);
169
170# wrong cert with ssl_verify_client optional
171
172$s = Test::Nginx::IMAP->new(
173 PeerAddr => '127.0.0.1:8145',
174 SSL_cert_file => "$d/1.example.com.crt",
175 SSL_key_file => "$d/1.example.com.key",
176 %ssl,
177);
178$s->check(qr/BYE SSL certificate error/, 'bad optional cert');
179
180# wrong cert with ssl_verify_client optional_no_ca
181
182$s = Test::Nginx::IMAP->new(
183 PeerAddr => '127.0.0.1:8147',
184 SSL_cert_file => "$d/1.example.com.crt",
185 SSL_key_file => "$d/1.example.com.key",
186 %ssl,
187);
188$s->ok('bad optional_no_ca cert');
189$s->send('1 AUTHENTICATE PLAIN ' . $cred);
190
191# matching cert with ssl_verify_client optional
192
193$s = Test::Nginx::IMAP->new(
194 PeerAddr => '127.0.0.1:8145',
195 SSL_cert_file => "$d/2.example.com.crt",
196 SSL_key_file => "$d/2.example.com.key",
197 %ssl,
198);
199$s->ok('good cert');
200$s->send('1 AUTHENTICATE PLAIN ' . $cred);
201
202# trusted cert with ssl_verify_client optional
203
204$s = Test::Nginx::IMAP->new(
205 PeerAddr => '127.0.0.1:8146',
206 SSL_cert_file => "$d/3.example.com.crt",
207 SSL_key_file => "$d/3.example.com.key",
208 %ssl,
209);
210$s->ok('trusted cert');
211$s->send('1 AUTHENTICATE PLAIN ' . $cred);
212$s->read();
213
214# test auth_http request header fields with access_log
215
216$t->stop();
217
218open my $f, '<', $t->testdir() . '/' . 'auth.log'
219 or die "Can't open auth.log: $!";
220
221like($f->getline(), qr/^-:-:-:-:-:-:-\x0d?\x0a?$/, 'log - plain connection');
222like($f->getline(), qr/^on:NONE:-:-:-:-:-\x0d?\x0a?$/,
223 'log - no cert');
224like($f->getline(),
225 qr!^on:FAILED:/CN=1.example.com:/CN=1.example.com:\w+:\w+:[^:]+$!,
226 'log - bad cert');
227like($f->getline(),
228 qr!^on:SUCCESS:/CN=2.example.com:/CN=2.example.com:\w+:\w+:[^:]+$!,
229 'log - good cert');
230like($f->getline(),
231 qr!^on:SUCCESS:/CN=3.example.com:/CN=3.example.com:\w+:\w+:[^:]+$!,
232 'log - trusted cert');
233
234###############################################################################