Welcome! Log In Create A New Profile

Advanced

Re: [PATCH] mail_{ssl, auth_http}_module: add support for SSL client certificates

Sven Peter
January 13, 2014 10:30AM
Hi again,


Here's an updated version of the patch. Sorry for not using hg email,
but I couldn't figure out how to convince it to reply to an existing thread.
This will probably screw something up, so I attached the mbox file to be sure.



Sven


# HG changeset patch
# User Sven Peter <sven@ha.cki.ng>
# Date 1389626052 -3600
# Mon Jan 13 16:14:12 2014 +0100
# Node ID a444733105e8eb96212f142533e714532a23cddf
# Parent 4aa64f6950313311e0d322a2af1788edeb7f036c
mail_{ssl,auth_http}_module: add support for SSL client certificates

This patch adds support for SSL client certificates to the mail proxy
capabilities of nginx both for STARTTLS and SSL mode.
Just like the HTTP SSL module a root CA is defined in the mail section
of the configuration file. Verification can be optional or mandatory.
Additionally, the result of the verification is exposed to the
auth http backend via the SSL-Verify, SSL-Subject-DN, SSL-Issuer-DN
and SSL-Serial HTTP headers.

diff -r 4aa64f695031 -r a444733105e8 src/mail/ngx_mail_auth_http_module.c
--- a/src/mail/ngx_mail_auth_http_module.c Sat Jan 04 03:32:22 2014 +0400
+++ b/src/mail/ngx_mail_auth_http_module.c Mon Jan 13 16:14:12 2014 +0100
@@ -1145,6 +1145,16 @@
ngx_str_t login, passwd;
ngx_mail_core_srv_conf_t *cscf;

+#if (NGX_MAIL_SSL)
+ ngx_str_t ssl_client_verify;
+ ngx_str_t ssl_client_raw_s_dn;
+ ngx_str_t ssl_client_raw_i_dn;
+ ngx_str_t ssl_client_raw_serial;
+ ngx_str_t ssl_client_s_dn;
+ ngx_str_t ssl_client_i_dn;
+ ngx_str_t ssl_client_serial;
+#endif
+
if (ngx_mail_auth_http_escape(pool, &s->login, &login) != NGX_OK) {
return NULL;
}
@@ -1153,6 +1163,51 @@
return NULL;
}

+#if (NGX_MAIL_SSL)
+ if (s->connection->ssl) {
+ /* ssl_client_verify comes from nginx itself - no need to escape */
+ if (ngx_ssl_get_client_verify(s->connection, pool,
+ &ssl_client_verify) != NGX_OK) {
+ return NULL;
+ }
+
+ if (ngx_ssl_get_subject_dn(s->connection, pool,
+ &ssl_client_raw_s_dn) != NGX_OK) {
+ return NULL;
+ }
+
+ if (ngx_ssl_get_issuer_dn(s->connection, pool,
+ &ssl_client_raw_i_dn) != NGX_OK) {
+ return NULL;
+ }
+
+ if (ngx_ssl_get_serial_number(s->connection, pool,
+ &ssl_client_raw_serial) != NGX_OK) {
+ return NULL;
+ }
+
+ if (ngx_mail_auth_http_escape(pool, &ssl_client_raw_s_dn,
+ &ssl_client_s_dn) != NGX_OK) {
+ return NULL;
+ }
+
+ if (ngx_mail_auth_http_escape(pool, &ssl_client_raw_i_dn,
+ &ssl_client_i_dn) != NGX_OK) {
+ return NULL;
+ }
+
+ if (ngx_mail_auth_http_escape(pool, &ssl_client_raw_serial,
+ &ssl_client_serial) != NGX_OK) {
+ return NULL;
+ }
+ } else {
+ ngx_str_set(&ssl_client_verify, "NONE");
+ ssl_client_i_dn.len = 0;
+ ssl_client_s_dn.len = 0;
+ ssl_client_serial.len = 0;
+ }
+#endif
+
cscf = ngx_mail_get_module_srv_conf(s, ngx_mail_core_module);

len = sizeof("GET ") - 1 + ahcf->uri.len + sizeof(" HTTP/1.0" CRLF) - 1
@@ -1173,6 +1228,16 @@
+ sizeof("Auth-SMTP-Helo: ") - 1 + s->smtp_helo.len
+ sizeof("Auth-SMTP-From: ") - 1 + s->smtp_from.len
+ sizeof("Auth-SMTP-To: ") - 1 + s->smtp_to.len
+#if (NGX_MAIL_SSL)
+ + sizeof("SSL-Verify: ") - 1 + ssl_client_verify.len
+ + sizeof(CRLF) - 1
+ + sizeof("SSL-Subject-DN: ") - 1 + ssl_client_s_dn.len
+ + sizeof(CRLF) - 1
+ + sizeof("SSL-Issuer-DN: ") - 1 + ssl_client_i_dn.len
+ + sizeof(CRLF) - 1
+ + sizeof("SSL-Serial: ") - 1 + ssl_client_serial.len
+ + sizeof(CRLF) - 1
+#endif
+ ahcf->header.len
+ sizeof(CRLF) - 1;

@@ -1255,6 +1320,34 @@

}

+#if (NGX_MAIL_SSL)
+ if (ssl_client_verify.len) {
+ b->last = ngx_cpymem(b->last, "SSL-Verify: ",
+ sizeof("SSL-Verify: ") - 1);
+ b->last = ngx_copy(b->last, ssl_client_verify.data,
+ ssl_client_verify.len);
+ *b->last++ = CR; *b->last++ = LF;
+
+ b->last = ngx_cpymem(b->last, "SSL-Subject-DN: ",
+ sizeof("SSL-Subject-DN: ") - 1);
+ b->last = ngx_copy(b->last, ssl_client_s_dn.data,
+ ssl_client_s_dn.len);
+ *b->last++ = CR; *b->last++ = LF;
+
+ b->last = ngx_cpymem(b->last, "SSL-Issuer-DN: ",
+ sizeof("SSL-Issuer-DN: ") - 1);
+ b->last = ngx_copy(b->last, ssl_client_i_dn.data,
+ ssl_client_i_dn.len);
+ *b->last++ = CR; *b->last++ = LF;
+
+ b->last = ngx_cpymem(b->last, "SSL-Serial: ",
+ sizeof("SSL-Serial: ") - 1);
+ b->last = ngx_copy(b->last, ssl_client_serial.data,
+ ssl_client_serial.len);
+ *b->last++ = CR; *b->last++ = LF;
+ }
+#endif
+
if (ahcf->header.len) {
b->last = ngx_copy(b->last, ahcf->header.data, ahcf->header.len);
}
diff -r 4aa64f695031 -r a444733105e8 src/mail/ngx_mail_handler.c
--- a/src/mail/ngx_mail_handler.c Sat Jan 04 03:32:22 2014 +0400
+++ b/src/mail/ngx_mail_handler.c Mon Jan 13 16:14:12 2014 +0100
@@ -236,11 +236,40 @@
{
ngx_mail_session_t *s;
ngx_mail_core_srv_conf_t *cscf;
+ ngx_mail_ssl_conf_t *sslcf;

if (c->ssl->handshaked) {

s = c->data;

+ sslcf = ngx_mail_get_module_srv_conf(s, ngx_mail_ssl_module);
+ if (sslcf->verify != NGX_MAIL_SSL_VERIFY_OFF) {
+ long rc;
+ rc = SSL_get_verify_result(c->ssl->connection);
+
+ if (rc != X509_V_OK &&
+ (sslcf->verify != NGX_MAIL_SSL_VERIFY_OPTIONAL_NO_CA && 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_mail_close_connection(c);
+ return;
+ }
+
+ if (sslcf->verify == NGX_MAIL_SSL_VERIFY_ON) {
+ X509 *cert;
+ 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_mail_close_connection(c);
+ return;
+ }
+ X509_free(cert);
+ }
+ }
+
if (s->starttls) {
cscf = ngx_mail_get_module_srv_conf(s, ngx_mail_core_module);

diff -r 4aa64f695031 -r a444733105e8 src/mail/ngx_mail_ssl_module.c
--- a/src/mail/ngx_mail_ssl_module.c Sat Jan 04 03:32:22 2014 +0400
+++ b/src/mail/ngx_mail_ssl_module.c Mon Jan 13 16:14:12 2014 +0100
@@ -43,6 +43,13 @@
{ ngx_null_string, 0 }
};

+static ngx_conf_enum_t ngx_mail_ssl_verify[] = {
+ { ngx_string("off"), NGX_MAIL_SSL_VERIFY_OFF },
+ { ngx_string("on"), NGX_MAIL_SSL_VERIFY_ON },
+ { ngx_string("optional"), NGX_MAIL_SSL_VERIFY_OPTIONAL },
+ { ngx_string("optional_no_ca"), NGX_MAIL_SSL_VERIFY_OPTIONAL_NO_CA },
+ { ngx_null_string, 0 }
+};

static ngx_command_t ngx_mail_ssl_commands[] = {

@@ -130,7 +137,40 @@
offsetof(ngx_mail_ssl_conf_t, session_timeout),
NULL },

- ngx_null_command
+ {
+ ngx_string("ssl_verify_client"),
+ NGX_MAIL_MAIN_CONF|NGX_MAIL_SRV_CONF|NGX_CONF_TAKE1,
+ ngx_conf_set_enum_slot,
+ NGX_MAIL_SRV_CONF_OFFSET,
+ offsetof(ngx_mail_ssl_conf_t, verify),
+ &ngx_mail_ssl_verify
+ },
+ {
+ ngx_string("ssl_verify_depth"),
+ NGX_MAIL_MAIN_CONF|NGX_MAIL_SRV_CONF|NGX_CONF_1MORE,
+ ngx_conf_set_num_slot,
+ NGX_MAIL_SRV_CONF_OFFSET,
+ offsetof(ngx_mail_ssl_conf_t, verify_depth),
+ NULL
+ },
+ {
+ ngx_string("ssl_client_certificate"),
+ NGX_MAIL_MAIN_CONF|NGX_MAIL_SRV_CONF|NGX_CONF_TAKE1,
+ ngx_conf_set_str_slot,
+ NGX_MAIL_SRV_CONF_OFFSET,
+ offsetof(ngx_mail_ssl_conf_t, client_certificate),
+ NULL
+ },
+ {
+ ngx_string("ssl_trusted_certificate"),
+ NGX_MAIL_MAIN_CONF|NGX_MAIL_SRV_CONF|NGX_CONF_TAKE1,
+ ngx_conf_set_str_slot,
+ NGX_MAIL_SRV_CONF_OFFSET,
+ offsetof(ngx_mail_ssl_conf_t, trusted_certificate),
+ NULL
+ },
+
+ ngx_null_command
};


@@ -184,6 +224,8 @@
* scf->ecdh_curve = { 0, NULL };
* scf->ciphers = { 0, NULL };
* scf->shm_zone = NULL;
+ * scf->client_certificate = { 0, NULL };
+ * scf->trusted_certificate = { 0, NULL };
*/

scf->enable = NGX_CONF_UNSET;
@@ -192,6 +234,8 @@
scf->builtin_session_cache = NGX_CONF_UNSET;
scf->session_timeout = NGX_CONF_UNSET;
scf->session_ticket_keys = NGX_CONF_UNSET_PTR;
+ scf->verify = NGX_CONF_UNSET_UINT;
+ scf->verify_depth = NGX_CONF_UNSET_UINT;

return scf;
}
@@ -230,6 +274,11 @@

ngx_conf_merge_str_value(conf->ciphers, prev->ciphers, NGX_DEFAULT_CIPHERS);

+ ngx_conf_merge_uint_value(conf->verify, prev->verify, NGX_MAIL_SSL_VERIFY_OFF);
+ ngx_conf_merge_uint_value(conf->verify_depth, prev->verify_depth, 1);
+
+ ngx_conf_merge_str_value(conf->client_certificate, prev->client_certificate, "");
+ ngx_conf_merge_str_value(conf->trusted_certificate, prev->trusted_certificate, "");

conf->ssl.log = cf->log;

@@ -310,6 +359,21 @@
return NGX_CONF_ERROR;
}

+ if (conf->verify) {
+ if (conf->client_certificate.len == 0 && conf->verify != NGX_MAIL_SSL_VERIFY_OPTIONAL_NO_CA) {
+ ngx_log_error(NGX_LOG_EMERG, cf->log, 0,
+ "no ssl_client_certificate for ssl_client_verify");
+ return NGX_CONF_ERROR;
+ }
+
+ if (ngx_ssl_client_certificate(cf, &conf->ssl,
+ &conf->client_certificate,
+ conf->verify_depth)
+ != NGX_OK) {
+ return NGX_CONF_ERROR;
+ }
+ }
+
if (conf->prefer_server_ciphers) {
SSL_CTX_set_options(conf->ssl.ctx, SSL_OP_CIPHER_SERVER_PREFERENCE);
}
diff -r 4aa64f695031 -r a444733105e8 src/mail/ngx_mail_ssl_module.h
--- a/src/mail/ngx_mail_ssl_module.h Sat Jan 04 03:32:22 2014 +0400
+++ b/src/mail/ngx_mail_ssl_module.h Mon Jan 13 16:14:12 2014 +0100
@@ -37,8 +37,14 @@
ngx_str_t dhparam;
ngx_str_t ecdh_curve;

+ ngx_str_t client_certificate;
+ ngx_str_t trusted_certificate;
+
ngx_str_t ciphers;

+ ngx_uint_t verify;
+ ngx_uint_t verify_depth;
+
ngx_shm_zone_t *shm_zone;

ngx_array_t *session_ticket_keys;
@@ -47,6 +53,13 @@
ngx_uint_t line;
} ngx_mail_ssl_conf_t;

+enum ngx_mail_ssl_verify_enum {
+ NGX_MAIL_SSL_VERIFY_OFF = 0,
+ NGX_MAIL_SSL_VERIFY_ON,
+ NGX_MAIL_SSL_VERIFY_OPTIONAL,
+ NGX_MAIL_SSL_VERIFY_OPTIONAL_NO_CA,
+};
+

extern ngx_module_t ngx_mail_ssl_module;


_______________________________________________
nginx-devel mailing list
nginx-devel@nginx.org
http://mailman.nginx.org/mailman/listinfo/nginx-devel
Subject Author Views Posted

[PATCH] mail_{ssl, auth_http}_module: add support for SSL client certificates

Sven Peter 1058 January 13, 2014 05:30AM

Re: [PATCH] mail_{ssl, auth_http}_module: add support for SSL client certificates

Filipe Da Silva 256 January 13, 2014 07:10AM

Re: [PATCH] mail_{ssl, auth_http}_module: add support for SSL client certificates

Sven Peter 248 January 13, 2014 08:12AM

Re: [PATCH] mail_{ssl, auth_http}_module: add support for SSL client certificates Attachments

Sven Peter 342 January 13, 2014 10:30AM

Re: [PATCH] mail_{ssl, auth_http}_module: add support for SSL client certificates

Maxim Dounin 265 January 14, 2014 07:10AM

Re: [PATCH] mail_{ssl, auth_http}_module: add support for SSL client certificates

Sven Peter 302 January 14, 2014 08:42AM

Re: [PATCH] mail_{ssl, auth_http}_module: add support for SSL client certificates

Maxim Dounin 324 January 14, 2014 10:32AM



Sorry, you do not have permission to post/reply in this forum.

Online Users

Guests: 71
Record Number of Users: 6 on February 13, 2018
Record Number of Guests: 421 on December 02, 2018
Powered by nginx      Powered by FreeBSD      PHP Powered      Powered by MariaDB      ipv6 ready