aboutsummaryrefslogtreecommitdiff
path: root/src/mail/ngx_mail_handler.c
diff options
context:
space:
mode:
authorMaxim Dounin <mdounin@mdounin.ru>2015-02-25 17:48:05 +0300
committerMaxim Dounin <mdounin@mdounin.ru>2015-02-25 17:48:05 +0300
commitfaec5477710c4ca15fd2588ee168d8fb2348ef6d (patch)
tree389954c725bba33fc08cd44f73a8ed3eedad6379 /src/mail/ngx_mail_handler.c
parent78e1a8ed7f33c55e7a24cbf4d0155bea6430dd59 (diff)
downloadnginx-faec5477710c4ca15fd2588ee168d8fb2348ef6d.tar.gz
nginx-faec5477710c4ca15fd2588ee168d8fb2348ef6d.zip
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.
Diffstat (limited to 'src/mail/ngx_mail_handler.c')
-rw-r--r--src/mail/ngx_mail_handler.c71
1 files changed, 71 insertions, 0 deletions
diff --git a/src/mail/ngx_mail_handler.c b/src/mail/ngx_mail_handler.c
index 57b69b564..870b5eeed 100644
--- a/src/mail/ngx_mail_handler.c
+++ b/src/mail/ngx_mail_handler.c
@@ -16,6 +16,8 @@ static void ngx_mail_init_session(ngx_connection_t *c);
#if (NGX_MAIL_SSL)
static void ngx_mail_ssl_init_connection(ngx_ssl_t *ssl, ngx_connection_t *c);
static void ngx_mail_ssl_handshake_handler(ngx_connection_t *c);
+static ngx_int_t ngx_mail_verify_cert(ngx_mail_session_t *s,
+ ngx_connection_t *c);
#endif
@@ -247,6 +249,10 @@ ngx_mail_ssl_handshake_handler(ngx_connection_t *c)
s = c->data;
+ if (ngx_mail_verify_cert(s, c) != NGX_OK) {
+ return;
+ }
+
if (s->starttls) {
cscf = ngx_mail_get_module_srv_conf(s, ngx_mail_core_module);
@@ -267,6 +273,71 @@ ngx_mail_ssl_handshake_handler(ngx_connection_t *c)
ngx_mail_close_connection(c);
}
+
+static ngx_int_t
+ngx_mail_verify_cert(ngx_mail_session_t *s, ngx_connection_t *c)
+{
+ long rc;
+ X509 *cert;
+ ngx_mail_ssl_conf_t *sslcf;
+ ngx_mail_core_srv_conf_t *cscf;
+
+ sslcf = ngx_mail_get_module_srv_conf(s, ngx_mail_ssl_module);
+
+ if (!sslcf->verify) {
+ return NGX_OK;
+ }
+
+ rc = SSL_get_verify_result(c->ssl->connection);
+
+ if (rc != X509_V_OK
+ && (sslcf->verify != 3 || !ngx_ssl_verify_error_optional(rc)))
+ {
+ ngx_log_error(NGX_LOG_INFO, c->log, 0,
+ "client SSL certificate verify error: (%l:%s)",
+ rc, X509_verify_cert_error_string(rc));
+
+ ngx_ssl_remove_cached_session(sslcf->ssl.ctx,
+ (SSL_get0_session(c->ssl->connection)));
+
+ cscf = ngx_mail_get_module_srv_conf(s, ngx_mail_core_module);
+
+ s->out = cscf->protocol->cert_error;
+ s->quit = 1;
+
+ c->write->handler = ngx_mail_send;
+
+ ngx_mail_send(s->connection->write);
+ return NGX_ERROR;
+ }
+
+ if (sslcf->verify == 1) {
+ cert = SSL_get_peer_certificate(c->ssl->connection);
+
+ if (cert == NULL) {
+ ngx_log_error(NGX_LOG_INFO, c->log, 0,
+ "client sent no required SSL certificate");
+
+ ngx_ssl_remove_cached_session(sslcf->ssl.ctx,
+ (SSL_get0_session(c->ssl->connection)));
+
+ cscf = ngx_mail_get_module_srv_conf(s, ngx_mail_core_module);
+
+ s->out = cscf->protocol->no_cert;
+ s->quit = 1;
+
+ c->write->handler = ngx_mail_send;
+
+ ngx_mail_send(s->connection->write);
+ return NGX_ERROR;
+ }
+
+ X509_free(cert);
+ }
+
+ return NGX_OK;
+}
+
#endif