<div dir="ltr"><div><div>Hello,<br><br>I've forgotten to use the raw certificate and escape it. I'll re-submit<br></div>Thanks to Filipe for the review.<br><br></div>Franck.<br></div><div class="gmail_extra"><br><br>
<div class="gmail_quote">2014-02-21 11:11 GMT+01:00 <span dir="ltr"><<a href="mailto:flevionnois@gmail.com" target="_blank">flevionnois@gmail.com</a>></span>:<br><blockquote class="gmail_quote" style="margin:0 0 0 .8ex;border-left:1px #ccc solid;padding-left:1ex">
# HG changeset patch<br>
# User Franck Levionnois <<a href="mailto:flevionnois@gmail.com">flevionnois@gmail.com</a>><br>
<div class=""># Date 1390577176 -3600<br>
# Fri Jan 24 16:26:16 2014 +0100<br>
</div># Node ID 0a3fd2d54154c3d56131ee5053df0939db32d7b4<br>
# Parent 4dee5ad51e9e5b49085011e8785001e2d6c02b0d<br>
<div class="">Mail: added support for SSL client certificate.<br>
<br>
</div>Add support for SSL Mutual Authentification like in mail module.<br>
<div class=""><br>
Added mail configuration directives (like http):<br>
ssl_verify_client, ssl_verify_depth, ssl_client_certificate,<br>
</div>ssl_trusted_certificate, ssl_crl.<br>
<br>
Added http auth headers:<br>
Auth-Certificate, Auth-Verify, Auth-Issuer-DN, Auth-Subject-DN,<br>
Auth-Subject-Serial.<br>
<br>
diff -r 4dee5ad51e9e -r 0a3fd2d54154 src/mail/ngx_mail_auth_http_module.c<br>
--- a/src/mail/ngx_mail_auth_http_module.c Thu Feb 20 13:48:40 2014 +0400<br>
<div class="">+++ b/src/mail/ngx_mail_auth_http_module.c Fri Jan 24 16:26:16 2014 +0100<br>
</div>@@ -1143,6 +1143,9 @@ ngx_mail_auth_http_create_request(ngx_ma<br>
<div class=""> size_t len;<br>
ngx_buf_t *b;<br>
ngx_str_t login, passwd;<br>
+#if (NGX_MAIL_SSL)<br>
</div>+ ngx_str_t cert, verify, subject, issuer, serial;<br>
<div class="">+#endif<br>
ngx_mail_core_srv_conf_t *cscf;<br>
<br>
if (ngx_mail_auth_http_escape(pool, &s->login, &login) != NGX_OK) {<br>
</div>@@ -1155,6 +1158,41 @@ ngx_mail_auth_http_create_request(ngx_ma<br>
<br>
cscf = ngx_mail_get_module_srv_conf(s, ngx_mail_core_module);<br>
<br>
<div class="">+#if (NGX_MAIL_SSL)<br>
+ if (s->connection->ssl) {<br>
</div>+ if (ngx_ssl_get_client_verify(s->connection, pool, &verify) != NGX_OK)<br>
<div class="">+ {<br>
+ return NULL;<br>
+ }<br>
+<br>
</div>+ if (ngx_ssl_get_subject_dn(s->connection, pool,<br>
+ &subject) != NGX_OK) {<br>
<div class="">+ return NULL;<br>
+ }<br>
+<br>
</div>+ if (ngx_ssl_get_issuer_dn(s->connection, pool,<br>
+ &issuer) != NGX_OK) {<br>
<div class="">+ return NULL;<br>
+ }<br>
+<br>
+ if (ngx_ssl_get_serial_number(s->connection, pool,<br>
</div>+ &serial) != NGX_OK) {<br>
<div class="">+ return NULL;<br>
+ }<br>
+<br>
</div>+ if (ngx_ssl_get_certificate(s->connection, pool,<br>
+ &cert) != NGX_OK) {<br>
+ return NULL;<br>
+ }<br>
+ } else {<br>
+ verify.len = 0;<br>
+ issuer.len = 0;<br>
+ subject.len = 0;<br>
+ serial.len = 0;<br>
+ cert.len = 0;<br>
<div class="">+ }<br>
+#endif<br>
+<br>
len = sizeof("GET ") - 1 + ahcf->uri.len + sizeof(" HTTP/1.0" CRLF) - 1<br>
+ sizeof("Host: ") - 1 + ahcf->host_header.len + sizeof(CRLF) - 1<br>
+ sizeof("Auth-Method: ") - 1<br>
</div>@@ -1163,6 +1201,14 @@ ngx_mail_auth_http_create_request(ngx_ma<br>
<div class=""> + sizeof("Auth-User: ") - 1 + login.len + sizeof(CRLF) - 1<br>
+ sizeof("Auth-Pass: ") - 1 + passwd.len + sizeof(CRLF) - 1<br>
+ sizeof("Auth-Salt: ") - 1 + s->salt.len<br>
+#if (NGX_MAIL_SSL)<br>
</div>+ + sizeof("Auth-Certificate: ") - 1 + cert.len + sizeof(CRLF) - 1<br>
+ + sizeof("Auth-Verify: ") - 1 + verify.len + sizeof(CRLF) - 1<br>
+ + sizeof("Auth-Issuer-DN: ") - 1 + issuer.len + sizeof(CRLF) - 1<br>
+ + sizeof("Auth-Subject-DN: ") - 1 + subject.len + sizeof(CRLF) - 1<br>
+ + sizeof("Auth-Subject-Serial: ") - 1 + serial.len<br>
<div class="">+ + sizeof(CRLF) - 1<br>
+#endif<br>
+ sizeof("Auth-Protocol: ") - 1 + cscf->protocol->name.len<br>
+ sizeof(CRLF) - 1<br>
+ sizeof("Auth-Login-Attempt: ") - 1 + NGX_INT_T_LEN<br>
</div>@@ -1213,6 +1259,44 @@ ngx_mail_auth_http_create_request(ngx_ma<br>
<div class=""> s->passwd.data = NULL;<br>
}<br>
<br>
+#if (NGX_MAIL_SSL)<br>
</div>+ if (cert.len) {<br>
<div class="">+ b->last = ngx_cpymem(b->last, "Auth-Certificate: ",<br>
+ sizeof("Auth-Certificate: ") - 1);<br>
</div>+ b->last = ngx_copy(b->last, cert.data, cert.len);<br>
<div class="">+ *b->last++ = CR; *b->last++ = LF;<br>
+ }<br>
+<br>
</div>+ if (verify.len) {<br>
+ b->last = ngx_cpymem(b->last, "Auth-Verify: ",<br>
+ sizeof("Auth-Verify: ") - 1);<br>
+ b->last = ngx_copy(b->last, verify.data, verify.len);<br>
<div class="">+ *b->last++ = CR; *b->last++ = LF;<br>
+ }<br>
+<br>
</div>+ if (issuer.len) {<br>
<div class="">+ b->last = ngx_cpymem(b->last, "Auth-Issuer-DN: ",<br>
+ sizeof("Auth-Issuer-DN: ") - 1);<br>
</div>+ b->last = ngx_copy(b->last, issuer.data, issuer.len);<br>
<div class="">+ *b->last++ = CR; *b->last++ = LF;<br>
+ }<br>
+<br>
</div>+ if (subject.len) {<br>
<div class="">+ b->last = ngx_cpymem(b->last, "Auth-Subject-DN: ",<br>
+ sizeof("Auth-Subject-DN: ") - 1);<br>
</div>+ b->last = ngx_copy(b->last, subject.data, subject.len);<br>
<div class="">+ *b->last++ = CR; *b->last++ = LF;<br>
+ }<br>
+<br>
</div>+ if (serial.len) {<br>
<div class="">+ b->last = ngx_cpymem(b->last, "Auth-Subject-Serial: ",<br>
+ sizeof("Auth-Subject-Serial: ") - 1);<br>
</div>+ b->last = ngx_copy(b->last, serial.data, serial.len);<br>
<div class="">+ *b->last++ = CR; *b->last++ = LF;<br>
+ }<br>
+<br>
+#endif<br>
+<br>
b->last = ngx_cpymem(b->last, "Auth-Protocol: ",<br>
sizeof("Auth-Protocol: ") - 1);<br>
b->last = ngx_cpymem(b->last, cscf->protocol->name.data,<br>
</div>diff -r 4dee5ad51e9e -r 0a3fd2d54154 src/mail/ngx_mail_handler.c<br>
--- a/src/mail/ngx_mail_handler.c Thu Feb 20 13:48:40 2014 +0400<br>
+++ b/src/mail/ngx_mail_handler.c Fri Jan 24 16:26:16 2014 +0100<br>
@@ -236,11 +236,60 @@ ngx_mail_ssl_handshake_handler(ngx_conne<br>
<div><div class="h5"> {<br>
ngx_mail_session_t *s;<br>
ngx_mail_core_srv_conf_t *cscf;<br>
+#if (NGX_MAIL_SSL)<br>
+ ngx_mail_ssl_conf_t *sslcf;<br>
+#endif<br>
+<br>
+ ngx_log_debug1(NGX_LOG_DEBUG_MAIL, c->log, 0,<br>
+ "ngx_mail_ssl_handshake_handler handshaked: %d",<br>
+ c->ssl->handshaked);<br>
<br>
if (c->ssl->handshaked) {<br>
<br>
s = c->data;<br>
<br>
+#if (NGX_MAIL_SSL)<br>
+ sslcf = ngx_mail_get_module_srv_conf(s, ngx_mail_ssl_module);<br>
+ if (sslcf->verify) {<br>
+ long rc;<br>
+<br>
+ rc = SSL_get_verify_result(c->ssl->connection);<br>
+<br>
+ if (rc != X509_V_OK<br>
+ && (sslcf->verify != 3 || !ngx_ssl_verify_error_optional(rc)))<br>
+ {<br>
+ ngx_log_error(NGX_LOG_INFO, c->log, 0,<br>
+ "client SSL certificate verify error: (%l:%s)",<br>
+ rc, X509_verify_cert_error_string(rc));<br>
+<br>
</div></div>+ ngx_ssl_remove_cached_session(sslcf->ssl.ctx,<br>
<div class="">+ (SSL_get0_session(c->ssl->connection)));<br>
+<br>
+ ngx_mail_close_connection(c);<br>
+ return;<br>
+ }<br>
+<br>
+ if (sslcf->verify == 1) {<br>
+ X509 *cert;<br>
+ cert = SSL_get_peer_certificate(c->ssl->connection);<br>
+<br>
+ if (cert == NULL) {<br>
+ ngx_log_error(NGX_LOG_INFO, c->log, 0,<br>
+ "client sent no required SSL certificate");<br>
+<br>
</div>+ ngx_ssl_remove_cached_session(sslcf->ssl.ctx,<br>
<div class="">+ (SSL_get0_session(c->ssl->connection)));<br>
+<br>
+ ngx_mail_close_connection(c);<br>
+ return;<br>
+ }<br>
+<br>
+ X509_free(cert);<br>
+ }<br>
+ }<br>
+<br>
+#endif<br>
+<br>
if (s->starttls) {<br>
cscf = ngx_mail_get_module_srv_conf(s, ngx_mail_core_module);<br>
<br>
</div>diff -r 4dee5ad51e9e -r 0a3fd2d54154 src/mail/ngx_mail_ssl_module.c<br>
--- a/src/mail/ngx_mail_ssl_module.c Thu Feb 20 13:48:40 2014 +0400<br>
<div><div class="h5">+++ b/src/mail/ngx_mail_ssl_module.c Fri Jan 24 16:26:16 2014 +0100<br>
@@ -43,6 +43,14 @@ static ngx_conf_bitmask_t ngx_mail_ssl_<br>
{ ngx_null_string, 0 }<br>
};<br>
<br>
+static ngx_conf_enum_t ngx_mail_ssl_verify[] = {<br>
+ { ngx_string("off"), 0 },<br>
+ { ngx_string("on"), 1 },<br>
+ { ngx_string("optional"), 2 },<br>
+ { ngx_string("optional_no_ca"), 3 },<br>
+ { ngx_null_string, 0 }<br>
+};<br>
+<br>
<br>
static ngx_command_t ngx_mail_ssl_commands[] = {<br>
<br>
@@ -102,6 +110,34 @@ static ngx_command_t ngx_mail_ssl_comma<br>
offsetof(ngx_mail_ssl_conf_t, ciphers),<br>
NULL },<br>
<br>
+ { ngx_string("ssl_verify_client"),<br>
+ NGX_MAIL_MAIN_CONF|NGX_MAIL_SRV_CONF|NGX_CONF_TAKE1,<br>
+ ngx_conf_set_enum_slot,<br>
+ NGX_MAIL_SRV_CONF_OFFSET,<br>
+ offsetof(ngx_mail_ssl_conf_t, verify),<br>
+ &ngx_mail_ssl_verify },<br>
+<br>
+ { ngx_string("ssl_verify_depth"),<br>
+ NGX_MAIL_MAIN_CONF|NGX_MAIL_SRV_CONF|NGX_CONF_TAKE1,<br>
+ ngx_conf_set_num_slot,<br>
+ NGX_MAIL_SRV_CONF_OFFSET,<br>
+ offsetof(ngx_mail_ssl_conf_t, verify_depth),<br>
+ NULL },<br>
+<br>
+ { ngx_string("ssl_client_certificate"),<br>
+ NGX_MAIL_MAIN_CONF|NGX_MAIL_SRV_CONF|NGX_CONF_TAKE1,<br>
+ ngx_conf_set_str_slot,<br>
+ NGX_MAIL_SRV_CONF_OFFSET,<br>
+ offsetof(ngx_mail_ssl_conf_t, client_certificate),<br>
+ NULL },<br>
+<br>
+ { ngx_string("ssl_trusted_certificate"),<br>
+ NGX_MAIL_MAIN_CONF|NGX_MAIL_SRV_CONF|NGX_CONF_TAKE1,<br>
+ ngx_conf_set_str_slot,<br>
+ NGX_MAIL_SRV_CONF_OFFSET,<br>
+ offsetof(ngx_mail_ssl_conf_t, trusted_certificate),<br>
+ NULL },<br>
+<br>
{ ngx_string("ssl_prefer_server_ciphers"),<br>
NGX_MAIL_MAIN_CONF|NGX_MAIL_SRV_CONF|NGX_CONF_FLAG,<br>
ngx_conf_set_flag_slot,<br>
@@ -137,6 +173,13 @@ static ngx_command_t ngx_mail_ssl_comma<br>
offsetof(ngx_mail_ssl_conf_t, session_timeout),<br>
NULL },<br>
<br>
+ { ngx_string("ssl_crl"),<br>
+ NGX_MAIL_MAIN_CONF|NGX_MAIL_SRV_CONF|NGX_CONF_TAKE1,<br>
+ ngx_conf_set_str_slot,<br>
+ NGX_MAIL_SRV_CONF_OFFSET,<br>
+ offsetof(ngx_mail_ssl_conf_t, crl),<br>
+ NULL },<br>
+<br>
ngx_null_command<br>
};<br>
<br>
@@ -189,6 +232,9 @@ ngx_mail_ssl_create_conf(ngx_conf_t *cf)<br>
* scf->certificate_key = { 0, NULL };<br>
* scf->dhparam = { 0, NULL };<br>
* scf->ecdh_curve = { 0, NULL };<br>
+ * scf->client_certificate = { 0, NULL };<br>
+ * scf->trusted_certificate = { 0, NULL };<br>
+ * scf->crl = { 0, NULL };<br>
* scf->ciphers = { 0, NULL };<br>
* scf->shm_zone = NULL;<br>
*/<br>
@@ -196,6 +242,8 @@ ngx_mail_ssl_create_conf(ngx_conf_t *cf)<br>
scf->enable = NGX_CONF_UNSET;<br>
scf->starttls = NGX_CONF_UNSET_UINT;<br>
scf->prefer_server_ciphers = NGX_CONF_UNSET;<br>
+ scf->verify = NGX_CONF_UNSET_UINT;<br>
+ scf->verify_depth = NGX_CONF_UNSET_UINT;<br>
scf->builtin_session_cache = NGX_CONF_UNSET;<br>
scf->session_timeout = NGX_CONF_UNSET;<br>
scf->session_tickets = NGX_CONF_UNSET;<br>
@@ -228,11 +276,20 @@ ngx_mail_ssl_merge_conf(ngx_conf_t *cf,<br>
(NGX_CONF_BITMASK_SET|NGX_SSL_SSLv3|NGX_SSL_TLSv1<br>
|NGX_SSL_TLSv1_1|NGX_SSL_TLSv1_2));<br>
<br>
+ ngx_conf_merge_uint_value(conf->verify, prev->verify, 0);<br>
+ ngx_conf_merge_uint_value(conf->verify_depth, prev->verify_depth, 1);<br>
+<br>
ngx_conf_merge_str_value(conf->certificate, prev->certificate, "");<br>
ngx_conf_merge_str_value(conf->certificate_key, prev->certificate_key, "");<br>
<br>
ngx_conf_merge_str_value(conf->dhparam, prev->dhparam, "");<br>
<br>
+ ngx_conf_merge_str_value(conf->client_certificate, prev->client_certificate,<br>
+ "");<br>
+ ngx_conf_merge_str_value(conf->trusted_certificate,<br>
+ prev->trusted_certificate, "");<br>
+ ngx_conf_merge_str_value(conf->crl, prev->crl, "");<br>
+<br>
ngx_conf_merge_str_value(conf->ecdh_curve, prev->ecdh_curve,<br>
NGX_DEFAULT_ECDH_CURVE);<br>
<br>
@@ -318,6 +375,35 @@ ngx_mail_ssl_merge_conf(ngx_conf_t *cf,<br>
return NGX_CONF_ERROR;<br>
}<br>
<br>
+ if (conf->verify) {<br>
+<br>
+ if (conf->client_certificate.len == 0 && conf->verify != 3) {<br>
+ ngx_log_error(NGX_LOG_EMERG, cf->log, 0,<br>
+ "no ssl_client_certificate for ssl_client_verify");<br>
+ return NGX_CONF_ERROR;<br>
+ }<br>
+<br>
+ if (ngx_ssl_client_certificate(cf, &conf->ssl,<br>
+ &conf->client_certificate,<br>
+ conf->verify_depth)<br>
+ != NGX_OK)<br>
+ {<br>
+ return NGX_CONF_ERROR;<br>
+ }<br>
+ }<br>
+<br>
+ if (ngx_ssl_trusted_certificate(cf, &conf->ssl,<br>
+ &conf->trusted_certificate,<br>
+ conf->verify_depth)<br>
+ != NGX_OK)<br>
+ {<br>
+ return NGX_CONF_ERROR;<br>
+ }<br>
+<br>
+ if (ngx_ssl_crl(cf, &conf->ssl, &conf->crl) != NGX_OK) {<br>
+ return NGX_CONF_ERROR;<br>
+ }<br>
+<br>
if (conf->prefer_server_ciphers) {<br>
SSL_CTX_set_options(conf->ssl.ctx, SSL_OP_CIPHER_SERVER_PREFERENCE);<br>
}<br>
</div></div>diff -r 4dee5ad51e9e -r 0a3fd2d54154 src/mail/ngx_mail_ssl_module.h<br>
--- a/src/mail/ngx_mail_ssl_module.h Thu Feb 20 13:48:40 2014 +0400<br>
<div class="HOEnZb"><div class="h5">+++ b/src/mail/ngx_mail_ssl_module.h Fri Jan 24 16:26:16 2014 +0100<br>
@@ -28,6 +28,8 @@ typedef struct {<br>
ngx_uint_t starttls;<br>
ngx_uint_t protocols;<br>
<br>
+ ngx_uint_t verify;<br>
+ ngx_uint_t verify_depth;<br>
ssize_t builtin_session_cache;<br>
<br>
time_t session_timeout;<br>
@@ -36,6 +38,9 @@ typedef struct {<br>
ngx_str_t certificate_key;<br>
ngx_str_t dhparam;<br>
ngx_str_t ecdh_curve;<br>
+ ngx_str_t client_certificate;<br>
+ ngx_str_t trusted_certificate;<br>
+ ngx_str_t crl;<br>
<br>
ngx_str_t ciphers;<br>
<br>
</div></div></blockquote></div><br></div>