comparison src/mail/ngx_mail_handler.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 8e7ee4c70a3c
children fc99323a3d79
comparison
equal deleted inserted replaced
5988:3b3f789655dc 5989:ec01b1d1fff1
14 static void ngx_mail_init_session(ngx_connection_t *c); 14 static void ngx_mail_init_session(ngx_connection_t *c);
15 15
16 #if (NGX_MAIL_SSL) 16 #if (NGX_MAIL_SSL)
17 static void ngx_mail_ssl_init_connection(ngx_ssl_t *ssl, ngx_connection_t *c); 17 static void ngx_mail_ssl_init_connection(ngx_ssl_t *ssl, ngx_connection_t *c);
18 static void ngx_mail_ssl_handshake_handler(ngx_connection_t *c); 18 static void ngx_mail_ssl_handshake_handler(ngx_connection_t *c);
19 static ngx_int_t ngx_mail_verify_cert(ngx_mail_session_t *s,
20 ngx_connection_t *c);
19 #endif 21 #endif
20 22
21 23
22 void 24 void
23 ngx_mail_init_connection(ngx_connection_t *c) 25 ngx_mail_init_connection(ngx_connection_t *c)
245 247
246 if (c->ssl->handshaked) { 248 if (c->ssl->handshaked) {
247 249
248 s = c->data; 250 s = c->data;
249 251
252 if (ngx_mail_verify_cert(s, c) != NGX_OK) {
253 return;
254 }
255
250 if (s->starttls) { 256 if (s->starttls) {
251 cscf = ngx_mail_get_module_srv_conf(s, ngx_mail_core_module); 257 cscf = ngx_mail_get_module_srv_conf(s, ngx_mail_core_module);
252 258
253 c->read->handler = cscf->protocol->init_protocol; 259 c->read->handler = cscf->protocol->init_protocol;
254 c->write->handler = ngx_mail_send; 260 c->write->handler = ngx_mail_send;
263 ngx_mail_init_session(c); 269 ngx_mail_init_session(c);
264 return; 270 return;
265 } 271 }
266 272
267 ngx_mail_close_connection(c); 273 ngx_mail_close_connection(c);
274 }
275
276
277 static ngx_int_t
278 ngx_mail_verify_cert(ngx_mail_session_t *s, ngx_connection_t *c)
279 {
280 long rc;
281 X509 *cert;
282 ngx_mail_ssl_conf_t *sslcf;
283 ngx_mail_core_srv_conf_t *cscf;
284
285 sslcf = ngx_mail_get_module_srv_conf(s, ngx_mail_ssl_module);
286
287 if (!sslcf->verify) {
288 return NGX_OK;
289 }
290
291 rc = SSL_get_verify_result(c->ssl->connection);
292
293 if (rc != X509_V_OK
294 && (sslcf->verify != 3 || !ngx_ssl_verify_error_optional(rc)))
295 {
296 ngx_log_error(NGX_LOG_INFO, c->log, 0,
297 "client SSL certificate verify error: (%l:%s)",
298 rc, X509_verify_cert_error_string(rc));
299
300 ngx_ssl_remove_cached_session(sslcf->ssl.ctx,
301 (SSL_get0_session(c->ssl->connection)));
302
303 cscf = ngx_mail_get_module_srv_conf(s, ngx_mail_core_module);
304
305 s->out = cscf->protocol->cert_error;
306 s->quit = 1;
307
308 c->write->handler = ngx_mail_send;
309
310 ngx_mail_send(s->connection->write);
311 return NGX_ERROR;
312 }
313
314 if (sslcf->verify == 1) {
315 cert = SSL_get_peer_certificate(c->ssl->connection);
316
317 if (cert == NULL) {
318 ngx_log_error(NGX_LOG_INFO, c->log, 0,
319 "client sent no required SSL certificate");
320
321 ngx_ssl_remove_cached_session(sslcf->ssl.ctx,
322 (SSL_get0_session(c->ssl->connection)));
323
324 cscf = ngx_mail_get_module_srv_conf(s, ngx_mail_core_module);
325
326 s->out = cscf->protocol->no_cert;
327 s->quit = 1;
328
329 c->write->handler = ngx_mail_send;
330
331 ngx_mail_send(s->connection->write);
332 return NGX_ERROR;
333 }
334
335 X509_free(cert);
336 }
337
338 return NGX_OK;
268 } 339 }
269 340
270 #endif 341 #endif
271 342
272 343