Mercurial > hg > nginx
comparison src/mail/ngx_mail_ssl_module.c @ 5989:ec01b1d1fff1
Mail: client SSL certificates support.
The "ssl_verify_client", "ssl_verify_depth", "ssl_client_certificate",
"ssl_trusted_certificate", and "ssl_crl" directives introduced to control
SSL client certificate verification in mail proxy module.
If there is a certificate, detail of the certificate are passed to
the auth_http script configured via Auth-SSL-Verify, Auth-SSL-Subject,
Auth-SSL-Issuer, Auth-SSL-Serial, Auth-SSL-Fingerprint headers. If
the auth_http_pass_client_cert directive is set, client certificate
in PEM format will be passed in the Auth-SSL-Cert header (urlencoded).
If there is no required certificate provided during an SSL handshake
or certificate verification fails then a protocol-specific error is
returned after the SSL handshake and the connection is closed.
Based on previous work by Sven Peter, Franck Levionnois and Filipe Da Silva.
author | Maxim Dounin <mdounin@mdounin.ru> |
---|---|
date | Wed, 25 Feb 2015 17:48:05 +0300 |
parents | 42114bf12da0 |
children | a84267233877 |
comparison
equal
deleted
inserted
replaced
5988:3b3f789655dc | 5989:ec01b1d1fff1 |
---|---|
44 { ngx_string("TLSv1.2"), NGX_SSL_TLSv1_2 }, | 44 { ngx_string("TLSv1.2"), NGX_SSL_TLSv1_2 }, |
45 { ngx_null_string, 0 } | 45 { ngx_null_string, 0 } |
46 }; | 46 }; |
47 | 47 |
48 | 48 |
49 static ngx_conf_enum_t ngx_mail_ssl_verify[] = { | |
50 { ngx_string("off"), 0 }, | |
51 { ngx_string("on"), 1 }, | |
52 { ngx_string("optional"), 2 }, | |
53 { ngx_string("optional_no_ca"), 3 }, | |
54 { ngx_null_string, 0 } | |
55 }; | |
56 | |
57 | |
49 static ngx_command_t ngx_mail_ssl_commands[] = { | 58 static ngx_command_t ngx_mail_ssl_commands[] = { |
50 | 59 |
51 { ngx_string("ssl"), | 60 { ngx_string("ssl"), |
52 NGX_MAIL_MAIN_CONF|NGX_MAIL_SRV_CONF|NGX_CONF_FLAG, | 61 NGX_MAIL_MAIN_CONF|NGX_MAIL_SRV_CONF|NGX_CONF_FLAG, |
53 ngx_mail_ssl_enable, | 62 ngx_mail_ssl_enable, |
142 { ngx_string("ssl_session_timeout"), | 151 { ngx_string("ssl_session_timeout"), |
143 NGX_MAIL_MAIN_CONF|NGX_MAIL_SRV_CONF|NGX_CONF_TAKE1, | 152 NGX_MAIL_MAIN_CONF|NGX_MAIL_SRV_CONF|NGX_CONF_TAKE1, |
144 ngx_conf_set_sec_slot, | 153 ngx_conf_set_sec_slot, |
145 NGX_MAIL_SRV_CONF_OFFSET, | 154 NGX_MAIL_SRV_CONF_OFFSET, |
146 offsetof(ngx_mail_ssl_conf_t, session_timeout), | 155 offsetof(ngx_mail_ssl_conf_t, session_timeout), |
156 NULL }, | |
157 | |
158 { ngx_string("ssl_verify_client"), | |
159 NGX_MAIL_MAIN_CONF|NGX_MAIL_SRV_CONF|NGX_CONF_TAKE1, | |
160 ngx_conf_set_enum_slot, | |
161 NGX_MAIL_SRV_CONF_OFFSET, | |
162 offsetof(ngx_mail_ssl_conf_t, verify), | |
163 &ngx_mail_ssl_verify }, | |
164 | |
165 { ngx_string("ssl_verify_depth"), | |
166 NGX_MAIL_MAIN_CONF|NGX_MAIL_SRV_CONF|NGX_CONF_TAKE1, | |
167 ngx_conf_set_num_slot, | |
168 NGX_MAIL_SRV_CONF_OFFSET, | |
169 offsetof(ngx_mail_ssl_conf_t, verify_depth), | |
170 NULL }, | |
171 | |
172 { ngx_string("ssl_client_certificate"), | |
173 NGX_MAIL_MAIN_CONF|NGX_MAIL_SRV_CONF|NGX_CONF_TAKE1, | |
174 ngx_conf_set_str_slot, | |
175 NGX_MAIL_SRV_CONF_OFFSET, | |
176 offsetof(ngx_mail_ssl_conf_t, client_certificate), | |
177 NULL }, | |
178 | |
179 { ngx_string("ssl_trusted_certificate"), | |
180 NGX_MAIL_MAIN_CONF|NGX_MAIL_SRV_CONF|NGX_CONF_TAKE1, | |
181 ngx_conf_set_str_slot, | |
182 NGX_MAIL_SRV_CONF_OFFSET, | |
183 offsetof(ngx_mail_ssl_conf_t, trusted_certificate), | |
184 NULL }, | |
185 | |
186 { ngx_string("ssl_crl"), | |
187 NGX_MAIL_MAIN_CONF|NGX_MAIL_SRV_CONF|NGX_CONF_TAKE1, | |
188 ngx_conf_set_str_slot, | |
189 NGX_MAIL_SRV_CONF_OFFSET, | |
190 offsetof(ngx_mail_ssl_conf_t, crl), | |
147 NULL }, | 191 NULL }, |
148 | 192 |
149 ngx_null_command | 193 ngx_null_command |
150 }; | 194 }; |
151 | 195 |
196 * scf->protocols = 0; | 240 * scf->protocols = 0; |
197 * scf->certificate = { 0, NULL }; | 241 * scf->certificate = { 0, NULL }; |
198 * scf->certificate_key = { 0, NULL }; | 242 * scf->certificate_key = { 0, NULL }; |
199 * scf->dhparam = { 0, NULL }; | 243 * scf->dhparam = { 0, NULL }; |
200 * scf->ecdh_curve = { 0, NULL }; | 244 * scf->ecdh_curve = { 0, NULL }; |
245 * scf->client_certificate = { 0, NULL }; | |
246 * scf->trusted_certificate = { 0, NULL }; | |
247 * scf->crl = { 0, NULL }; | |
201 * scf->ciphers = { 0, NULL }; | 248 * scf->ciphers = { 0, NULL }; |
202 * scf->shm_zone = NULL; | 249 * scf->shm_zone = NULL; |
203 */ | 250 */ |
204 | 251 |
205 scf->enable = NGX_CONF_UNSET; | 252 scf->enable = NGX_CONF_UNSET; |
206 scf->starttls = NGX_CONF_UNSET_UINT; | 253 scf->starttls = NGX_CONF_UNSET_UINT; |
207 scf->passwords = NGX_CONF_UNSET_PTR; | 254 scf->passwords = NGX_CONF_UNSET_PTR; |
208 scf->prefer_server_ciphers = NGX_CONF_UNSET; | 255 scf->prefer_server_ciphers = NGX_CONF_UNSET; |
256 scf->verify = NGX_CONF_UNSET_UINT; | |
257 scf->verify_depth = NGX_CONF_UNSET_UINT; | |
209 scf->builtin_session_cache = NGX_CONF_UNSET; | 258 scf->builtin_session_cache = NGX_CONF_UNSET; |
210 scf->session_timeout = NGX_CONF_UNSET; | 259 scf->session_timeout = NGX_CONF_UNSET; |
211 scf->session_tickets = NGX_CONF_UNSET; | 260 scf->session_tickets = NGX_CONF_UNSET; |
212 scf->session_ticket_keys = NGX_CONF_UNSET_PTR; | 261 scf->session_ticket_keys = NGX_CONF_UNSET_PTR; |
213 | 262 |
236 | 285 |
237 ngx_conf_merge_bitmask_value(conf->protocols, prev->protocols, | 286 ngx_conf_merge_bitmask_value(conf->protocols, prev->protocols, |
238 (NGX_CONF_BITMASK_SET|NGX_SSL_SSLv3|NGX_SSL_TLSv1 | 287 (NGX_CONF_BITMASK_SET|NGX_SSL_SSLv3|NGX_SSL_TLSv1 |
239 |NGX_SSL_TLSv1_1|NGX_SSL_TLSv1_2)); | 288 |NGX_SSL_TLSv1_1|NGX_SSL_TLSv1_2)); |
240 | 289 |
290 ngx_conf_merge_uint_value(conf->verify, prev->verify, 0); | |
291 ngx_conf_merge_uint_value(conf->verify_depth, prev->verify_depth, 1); | |
292 | |
241 ngx_conf_merge_str_value(conf->certificate, prev->certificate, ""); | 293 ngx_conf_merge_str_value(conf->certificate, prev->certificate, ""); |
242 ngx_conf_merge_str_value(conf->certificate_key, prev->certificate_key, ""); | 294 ngx_conf_merge_str_value(conf->certificate_key, prev->certificate_key, ""); |
243 | 295 |
244 ngx_conf_merge_ptr_value(conf->passwords, prev->passwords, NULL); | 296 ngx_conf_merge_ptr_value(conf->passwords, prev->passwords, NULL); |
245 | 297 |
246 ngx_conf_merge_str_value(conf->dhparam, prev->dhparam, ""); | 298 ngx_conf_merge_str_value(conf->dhparam, prev->dhparam, ""); |
247 | 299 |
248 ngx_conf_merge_str_value(conf->ecdh_curve, prev->ecdh_curve, | 300 ngx_conf_merge_str_value(conf->ecdh_curve, prev->ecdh_curve, |
249 NGX_DEFAULT_ECDH_CURVE); | 301 NGX_DEFAULT_ECDH_CURVE); |
302 | |
303 ngx_conf_merge_str_value(conf->client_certificate, | |
304 prev->client_certificate, ""); | |
305 ngx_conf_merge_str_value(conf->trusted_certificate, | |
306 prev->trusted_certificate, ""); | |
307 ngx_conf_merge_str_value(conf->crl, prev->crl, ""); | |
250 | 308 |
251 ngx_conf_merge_str_value(conf->ciphers, prev->ciphers, NGX_DEFAULT_CIPHERS); | 309 ngx_conf_merge_str_value(conf->ciphers, prev->ciphers, NGX_DEFAULT_CIPHERS); |
252 | 310 |
253 | 311 |
254 conf->ssl.log = cf->log; | 312 conf->ssl.log = cf->log; |
316 if (ngx_ssl_certificate(cf, &conf->ssl, &conf->certificate, | 374 if (ngx_ssl_certificate(cf, &conf->ssl, &conf->certificate, |
317 &conf->certificate_key, conf->passwords) | 375 &conf->certificate_key, conf->passwords) |
318 != NGX_OK) | 376 != NGX_OK) |
319 { | 377 { |
320 return NGX_CONF_ERROR; | 378 return NGX_CONF_ERROR; |
379 } | |
380 | |
381 if (conf->verify) { | |
382 | |
383 if (conf->client_certificate.len == 0 && conf->verify != 3) { | |
384 ngx_log_error(NGX_LOG_EMERG, cf->log, 0, | |
385 "no ssl_client_certificate for ssl_client_verify"); | |
386 return NGX_CONF_ERROR; | |
387 } | |
388 | |
389 if (ngx_ssl_client_certificate(cf, &conf->ssl, | |
390 &conf->client_certificate, | |
391 conf->verify_depth) | |
392 != NGX_OK) | |
393 { | |
394 return NGX_CONF_ERROR; | |
395 } | |
396 | |
397 if (ngx_ssl_trusted_certificate(cf, &conf->ssl, | |
398 &conf->trusted_certificate, | |
399 conf->verify_depth) | |
400 != NGX_OK) | |
401 { | |
402 return NGX_CONF_ERROR; | |
403 } | |
404 | |
405 if (ngx_ssl_crl(cf, &conf->ssl, &conf->crl) != NGX_OK) { | |
406 return NGX_CONF_ERROR; | |
407 } | |
321 } | 408 } |
322 | 409 |
323 if (SSL_CTX_set_cipher_list(conf->ssl.ctx, | 410 if (SSL_CTX_set_cipher_list(conf->ssl.ctx, |
324 (const char *) conf->ciphers.data) | 411 (const char *) conf->ciphers.data) |
325 == 0) | 412 == 0) |