Hello, The patch below has been submited some months ago. It do about the same, and it support to return a name by the auth script.
Kind regards Franck Levionnois. ---------- Forwarded message ---------- From: <[email protected]> Date: 2014-01-24 21:40 GMT+01:00 Subject: [PATCH 1 of 1] Mail: added support for SSL client certificate To: [email protected] # HG changeset patch # User Franck Levionnois <[email protected]> # Date 1390577176 -3600 # Fri Jan 24 16:26:16 2014 +0100 # Node ID d7b8381c200e300c2b6729574f4c2a b537804f56 # Parent a387ce36744aa36b50e8171dbf01ef716748327e Mail: added support for SSL client certificate Add support for SSL module like HTTP. Added mail configuration directives (like http): ssl_verify_client, ssl_verify_depth, ssl_client_certificate, ssl_trusted_certificate, ssl_crl Added headers: Auth-Certificate, Auth-Certificate-Verify, Auth-Issuer-DN, Auth-Subject-DN, Auth-Subject-Serial diff -r a387ce36744a -r d7b8381c200e src/mail/ngx_mail_auth_http_module.c --- a/src/mail/ngx_mail_auth_http_module.c Thu Jan 23 22:09:59 2014 +0900 +++ b/src/mail/ngx_mail_auth_http_module.c Fri Jan 24 16:26:16 2014 +0100 @@ -1135,6 +1135,32 @@ "mail auth http dummy handler"); } +#if (NGX_MAIL_SSL) +static ngx_int_t +ngx_ssl_get_certificate_oneline(ngx_connection_t *c, ngx_pool_t *pool, + ngx_str_t *b64_cert) +{ + ngx_str_t pemCert; + if (ngx_ssl_get_raw_certificate(c, pool, &pemCert) != NGX_OK) { + return NGX_ERROR; + } + + if (pemCert.len == 0) { + b64_cert->len = 0; + return NGX_OK; + } + + b64_cert->len = ngx_base64_encoded_length(pemCert.len); + b64_cert->data = ngx_palloc( pool, b64_cert->len); + if (b64_cert->data == NULL) { + b64_cert->len = 0; + return NGX_ERROR; + } + ngx_encode_base64(b64_cert, &pemCert); + + return NGX_OK; +} +#endif static ngx_buf_t * ngx_mail_auth_http_create_request(ngx_mail_session_t *s, ngx_pool_t *pool, @@ -1142,7 +1168,9 @@ { size_t len; ngx_buf_t *b; - ngx_str_t login, passwd; + ngx_str_t login, passwd, client_cert, client_verify, + client_subject, client_issuer, + client_serial; ngx_mail_core_srv_conf_t *cscf; if (ngx_mail_auth_http_escape(pool, &s->login, &login) != NGX_OK) { @@ -1155,6 +1183,42 @@ cscf = ngx_mail_get_module_srv_conf(s, ngx_mail_core_module); +#if (NGX_MAIL_SSL) + if (s->connection->ssl) { + if (ngx_ssl_get_client_verify(s->connection, pool, + &client_verify) != NGX_OK) { + return NULL; + } + + if (ngx_ssl_get_subject_dn(s->connection, pool, + &client_subject) != NGX_OK) { + return NULL; + } + + if (ngx_ssl_get_issuer_dn(s->connection, pool, + &client_issuer) != NGX_OK) { + return NULL; + } + + if (ngx_ssl_get_serial_number(s->connection, pool, + &client_serial) != NGX_OK) { + return NULL; + } + + if (ngx_ssl_get_certificate_oneline(s->connection, pool, + &client_cert) != NGX_OK) { + return NULL; + } + } else { + client_verify.len = 0; + client_issuer.len = 0; + client_subject.len = 0; + client_serial.len = 0; + client_cert.len = 0; + } + +#endif + len = sizeof("GET ") - 1 + ahcf->uri.len + sizeof(" HTTP/1.0" CRLF) - 1 + sizeof("Host: ") - 1 + ahcf->host_header.len + sizeof(CRLF) - 1 + sizeof("Auth-Method: ") - 1 @@ -1163,6 +1227,18 @@ + sizeof("Auth-User: ") - 1 + login.len + sizeof(CRLF) - 1 + sizeof("Auth-Pass: ") - 1 + passwd.len + sizeof(CRLF) - 1 + sizeof("Auth-Salt: ") - 1 + s->salt.len +#if (NGX_MAIL_SSL) + + sizeof("Auth-Certificate: ") - 1 + client_cert.len + + sizeof(CRLF) - 1 + + sizeof("Auth-Certificate-Verify: ") - 1 + client_verify.len + + sizeof(CRLF) - 1 + + sizeof("Auth-Issuer-DN: ") - 1 + client_issuer.len + + sizeof(CRLF) - 1 + + sizeof("Auth-Subject-DN: ") - 1 + client_subject.len + + sizeof(CRLF) - 1 + + sizeof("Auth-Subject-Serial: ") - 1 + client_serial.len + + sizeof(CRLF) - 1 +#endif + sizeof("Auth-Protocol: ") - 1 + cscf->protocol->name.len + sizeof(CRLF) - 1 + sizeof("Auth-Login-Attempt: ") - 1 + NGX_INT_T_LEN @@ -1212,7 +1288,43 @@ s->passwd.data = NULL; } - +#if (NGX_MAIL_SSL) + if ( client_cert.len ) + { + b->last = ngx_cpymem(b->last, "Auth-Certificate: ", + sizeof("Auth-Certificate: ") - 1); + b->last = ngx_copy(b->last, client_cert.data, client_cert.len); + *b->last++ = CR; *b->last++ = LF; + } + if ( client_verify.len ) + { + b->last = ngx_cpymem(b->last, "Auth-Certificate-Verify: ", + sizeof("Auth-Certificate-Verify: ") - 1); + b->last = ngx_copy(b->last, client_verify.data, client_verify.len); + *b->last++ = CR; *b->last++ = LF; + } + if ( client_issuer.len ) + { + b->last = ngx_cpymem(b->last, "Auth-Issuer-DN: ", + sizeof("Auth-Issuer-DN: ") - 1); + b->last = ngx_copy(b->last, client_issuer.data, client_issuer.len); + *b->last++ = CR; *b->last++ = LF; + } + if ( client_subject.len ) + { + b->last = ngx_cpymem(b->last, "Auth-Subject-DN: ", + sizeof("Auth-Subject-DN: ") - 1); + b->last = ngx_copy(b->last, client_subject.data, client_subject.len); + *b->last++ = CR; *b->last++ = LF; + } + if ( client_serial.len ) + { + b->last = ngx_cpymem(b->last, "Auth-Subject-Serial: ", + sizeof("Auth-Subject-Serial: ") - 1); + b->last = ngx_copy(b->last, client_serial.data, client_serial.len); + *b->last++ = CR; *b->last++ = LF; + } +#endif b->last = ngx_cpymem(b->last, "Auth-Protocol: ", sizeof("Auth-Protocol: ") - 1); b->last = ngx_cpymem(b->last, cscf->protocol->name.data, diff -r a387ce36744a -r d7b8381c200e src/mail/ngx_mail_handler.c --- a/src/mail/ngx_mail_handler.c Thu Jan 23 22:09:59 2014 +0900 +++ b/src/mail/ngx_mail_handler.c Fri Jan 24 16:26:16 2014 +0100 @@ -236,11 +236,59 @@ { ngx_mail_session_t *s; ngx_mail_core_srv_conf_t *cscf; +#if (NGX_MAIL_SSL) + ngx_mail_ssl_conf_t *sslcf; +#endif + + ngx_log_debug1(NGX_LOG_DEBUG_MAIL, c->log, 0, + "ngx_mail_ssl_handshake_handler handshaked: %d ", + c->ssl->handshaked ); if (c->ssl->handshaked) { s = c->data; +#if (NGX_MAIL_SSL) + sslcf = ngx_mail_get_module_srv_conf(s, ngx_mail_ssl_module); + if (sslcf->verify) { + long rc; + + 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))); + + ngx_mail_close_connection(c); + return; + } + + if (sslcf->verify == 1) { + 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_ssl_remove_cached_session(sslcf->ssl.ctx, + (SSL_get0_session(c->ssl->connection))); + + ngx_mail_close_connection(c); + return; + } + + X509_free(cert); + } + } +#endif + if (s->starttls) { cscf = ngx_mail_get_module_srv_conf(s, ngx_mail_core_module); @@ -276,6 +324,10 @@ s->protocol = cscf->protocol->type; + ngx_log_debug1(NGX_LOG_DEBUG_MAIL, c->log, 0, + "ngx_mail_init_session protocol: %d ", + cscf->protocol->type ); + s->ctx = ngx_pcalloc(c->pool, sizeof(void *) * ngx_mail_max_module); if (s->ctx == NULL) { ngx_mail_session_internal_server_error(s); diff -r a387ce36744a -r d7b8381c200e src/mail/ngx_mail_ssl_module.c --- a/src/mail/ngx_mail_ssl_module.c Thu Jan 23 22:09:59 2014 +0900 +++ b/src/mail/ngx_mail_ssl_module.c Fri Jan 24 16:26:16 2014 +0100 @@ -43,6 +43,13 @@ { ngx_null_string, 0 } }; +static ngx_conf_enum_t ngx_mail_ssl_verify[] = { + { ngx_string("off"), 0 }, + { ngx_string("on"), 1 }, + { ngx_string("optional"), 2 }, + { ngx_string("optional_no_ca"), 3 }, + { ngx_null_string, 0 } +}; static ngx_command_t ngx_mail_ssl_commands[] = { @@ -102,6 +109,34 @@ offsetof(ngx_mail_ssl_conf_t, ciphers), NULL }, + { 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_string("ssl_prefer_server_ciphers"), NGX_MAIL_MAIN_CONF|NGX_MAIL_SRV_CONF|NGX_CONF_FLAG, ngx_conf_set_flag_slot, @@ -137,6 +172,13 @@ offsetof(ngx_mail_ssl_conf_t, session_timeout), NULL }, + { ngx_string("ssl_crl"), + 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, crl), + NULL }, + ngx_null_command }; @@ -196,6 +238,8 @@ scf->enable = NGX_CONF_UNSET; scf->starttls = NGX_CONF_UNSET_UINT; scf->prefer_server_ciphers = NGX_CONF_UNSET; + scf->verify = NGX_CONF_UNSET_UINT; + scf->verify_depth = NGX_CONF_UNSET_UINT; scf->builtin_session_cache = NGX_CONF_UNSET; scf->session_timeout = NGX_CONF_UNSET; scf->session_tickets = NGX_CONF_UNSET; @@ -228,11 +272,20 @@ (NGX_CONF_BITMASK_SET|NGX_SSL_SSLv3|NGX_SSL_TLSv1 |NGX_SSL_TLSv1_1|NGX_SSL_TLSv1_2)); + ngx_conf_merge_uint_value(conf->verify, prev->verify, 0); + ngx_conf_merge_uint_value(conf->verify_depth, prev->verify_depth, 1); + ngx_conf_merge_str_value(conf->certificate, prev->certificate, ""); ngx_conf_merge_str_value(conf->certificate_key, prev->certificate_key, ""); ngx_conf_merge_str_value(conf->dhparam, prev->dhparam, ""); + ngx_conf_merge_str_value(conf->client_certificate, prev->client_certificate, + ""); + ngx_conf_merge_str_value(conf->trusted_certificate, + prev->trusted_certificate, ""); + ngx_conf_merge_str_value(conf->crl, prev->crl, ""); + ngx_conf_merge_str_value(conf->ecdh_curve, prev->ecdh_curve, NGX_DEFAULT_ECDH_CURVE); @@ -318,6 +371,35 @@ return NGX_CONF_ERROR; } + if (conf->verify) { + + if (conf->client_certificate.len == 0 && conf->verify != 3) { + 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 (ngx_ssl_trusted_certificate(cf, &conf->ssl, + &conf->trusted_certificate, + conf->verify_depth) + != NGX_OK) + { + return NGX_CONF_ERROR; + } + + if (ngx_ssl_crl(cf, &conf->ssl, &conf->crl) != 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 a387ce36744a -r d7b8381c200e src/mail/ngx_mail_ssl_module.h --- a/src/mail/ngx_mail_ssl_module.h Thu Jan 23 22:09:59 2014 +0900 +++ b/src/mail/ngx_mail_ssl_module.h Fri Jan 24 16:26:16 2014 +0100 @@ -28,6 +28,8 @@ ngx_uint_t starttls; ngx_uint_t protocols; + ngx_uint_t verify; + ngx_uint_t verify_depth; ssize_t builtin_session_cache; time_t session_timeout; @@ -36,6 +38,9 @@ ngx_str_t certificate_key; ngx_str_t dhparam; ngx_str_t ecdh_curve; + ngx_str_t client_certificate; + ngx_str_t trusted_certificate; + ngx_str_t crl; ngx_str_t ciphers; 2014-09-17 2:23 GMT+02:00 Kunal Pariani <[email protected]>: > I guess these diffs can still be applied with limitation of having the > same ssl setting for all upstreams until the support to return a name by > the auth script is added later ? > > Thanks > -Kunal > > ----- Original Message ----- > From: "Maxim Dounin" <[email protected]> > To: "nginx-devel" <[email protected]> > Sent: Tuesday, September 16, 2014 5:03:06 AM > Subject: Re: [PATCH] SSL support for the mail proxy module > > Hello! > > On Tue, Sep 16, 2014 at 02:30:17AM -0500, Kunal Pariani wrote: > > > Updated the diffs after addressing the first 2 issues. > > Regarding the 3rd comment, you are correct. Only 1 set of ssl > > settings for all the mail backends with my patch. I guess this > > will be a limitation with the current mail proxy workflow ? Am > > not sure of the exact changes that will be required to address > > this issue completely. > > Probably, returning a name by the auth script is a way to go. > > -- > Maxim Dounin > http://nginx.org/ > > _______________________________________________ > nginx-devel mailing list > [email protected] > http://mailman.nginx.org/mailman/listinfo/nginx-devel > > _______________________________________________ > nginx-devel mailing list > [email protected] > http://mailman.nginx.org/mailman/listinfo/nginx-devel >
_______________________________________________ nginx-devel mailing list [email protected] http://mailman.nginx.org/mailman/listinfo/nginx-devel
