Welcome! Log In Create A New Profile

Advanced

[PATCH] Stream: client SSL certificate support

Lukas Prettenthaler
November 06, 2015 03:36PM
# HG changeset patch
# User Lukas Prettenthaler <lukas.prettenthaler@bwinparty.com>
# Date 1446841055 -3600
# Fri Nov 06 21:17:35 2015 +0100
# Node ID e34abe30ed6d749deb12b768c15059165b56f9c5
# Parent 909b5b191f25d0f9e03667a10d23f6ef27d014a3
Stream: client SSL certificate 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 the stream module.

If there is no required certificate provided during an SSL handshake
or certificate verification fails then the connection is simply closed.

diff -r 909b5b191f25 -r e34abe30ed6d src/stream/ngx_stream_handler.c
--- a/src/stream/ngx_stream_handler.c Thu Nov 05 15:01:09 2015 +0300
+++ b/src/stream/ngx_stream_handler.c Fri Nov 06 21:17:35 2015 +0100
@@ -17,6 +17,8 @@
#if (NGX_STREAM_SSL)
static void ngx_stream_ssl_init_connection(ngx_ssl_t *ssl, ngx_connection_t *c);
static void ngx_stream_ssl_handshake_handler(ngx_connection_t *c);
+static ngx_int_t ngx_stream_verify_cert(ngx_stream_session_t *s,
+ ngx_connection_t *c);
#endif


@@ -265,11 +267,20 @@
static void
ngx_stream_ssl_handshake_handler(ngx_connection_t *c)
{
+ ngx_stream_session_t *s;
+
if (!c->ssl->handshaked) {
ngx_stream_close_connection(c);
return;
}

+ s = c->data;
+
+ if (ngx_stream_verify_cert(s, c) != NGX_OK) {
+ ngx_stream_close_connection(c);
+ return;
+ }
+
if (c->read->timer_set) {
ngx_del_timer(c->read);
}
@@ -277,6 +288,53 @@
ngx_stream_init_session(c);
}

+static ngx_int_t
+ngx_stream_verify_cert(ngx_stream_session_t *s, ngx_connection_t *c)
+{
+ long rc;
+ X509 *cert;
+ ngx_stream_ssl_conf_t *sslcf;
+
+ sslcf = ngx_stream_get_module_srv_conf(s, ngx_stream_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)));
+
+ 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)));
+
+ return NGX_ERROR;
+ }
+
+ X509_free(cert);
+ }
+
+ return NGX_OK;
+}
+
#endif


diff -r 909b5b191f25 -r e34abe30ed6d src/stream/ngx_stream_ssl_module.c
--- a/src/stream/ngx_stream_ssl_module.c Thu Nov 05 15:01:09 2015 +0300
+++ b/src/stream/ngx_stream_ssl_module.c Fri Nov 06 21:17:35 2015 +0100
@@ -33,6 +33,13 @@
{ ngx_null_string, 0 }
};

+static ngx_conf_enum_t ngx_stream_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_stream_ssl_commands[] = {

@@ -127,6 +134,41 @@
offsetof(ngx_stream_ssl_conf_t, session_timeout),
NULL },

+ { ngx_string("ssl_verify_client"),
+ NGX_STREAM_MAIN_CONF|NGX_STREAM_SRV_CONF|NGX_CONF_TAKE1,
+ ngx_conf_set_enum_slot,
+ NGX_STREAM_SRV_CONF_OFFSET,
+ offsetof(ngx_stream_ssl_conf_t, verify),
+ &ngx_stream_ssl_verify },
+
+ { ngx_string("ssl_verify_depth"),
+ NGX_STREAM_MAIN_CONF|NGX_STREAM_SRV_CONF|NGX_CONF_TAKE1,
+ ngx_conf_set_num_slot,
+ NGX_STREAM_SRV_CONF_OFFSET,
+ offsetof(ngx_stream_ssl_conf_t, verify_depth),
+ NULL },
+
+ { ngx_string("ssl_client_certificate"),
+ NGX_STREAM_MAIN_CONF|NGX_STREAM_SRV_CONF|NGX_CONF_TAKE1,
+ ngx_conf_set_str_slot,
+ NGX_STREAM_SRV_CONF_OFFSET,
+ offsetof(ngx_stream_ssl_conf_t, client_certificate),
+ NULL },
+
+ { ngx_string("ssl_trusted_certificate"),
+ NGX_STREAM_MAIN_CONF|NGX_STREAM_SRV_CONF|NGX_CONF_TAKE1,
+ ngx_conf_set_str_slot,
+ NGX_STREAM_SRV_CONF_OFFSET,
+ offsetof(ngx_stream_ssl_conf_t, trusted_certificate),
+ NULL },
+
+ { ngx_string("ssl_crl"),
+ NGX_STREAM_MAIN_CONF|NGX_STREAM_SRV_CONF|NGX_CONF_TAKE1,
+ ngx_conf_set_str_slot,
+ NGX_STREAM_SRV_CONF_OFFSET,
+ offsetof(ngx_stream_ssl_conf_t, crl),
+ NULL },
+
ngx_null_command
};

@@ -179,6 +221,9 @@
* scf->certificate_key = { 0, NULL };
* scf->dhparam = { 0, NULL };
* scf->ecdh_curve = { 0, NULL };
+ * scf->client_certificate = { 0, NULL };
+ * scf->trusted_certificate = { 0, NULL };
+ * scf->crl = { 0, NULL };
* scf->ciphers = { 0, NULL };
* scf->shm_zone = NULL;
*/
@@ -186,6 +231,8 @@
scf->handshake_timeout = NGX_CONF_UNSET_MSEC;
scf->passwords = NGX_CONF_UNSET_PTR;
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;
@@ -216,6 +263,9 @@
(NGX_CONF_BITMASK_SET|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, "");

@@ -226,6 +276,12 @@
ngx_conf_merge_str_value(conf->ecdh_curve, prev->ecdh_curve,
NGX_DEFAULT_ECDH_CURVE);

+ 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->ciphers, prev->ciphers, NGX_DEFAULT_CIPHERS);


@@ -262,6 +318,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 (SSL_CTX_set_cipher_list(conf->ssl.ctx,
(const char *) conf->ciphers.data)
== 0)
diff -r 909b5b191f25 -r e34abe30ed6d src/stream/ngx_stream_ssl_module.h
--- a/src/stream/ngx_stream_ssl_module.h Thu Nov 05 15:01:09 2015 +0300
+++ b/src/stream/ngx_stream_ssl_module.h Fri Nov 06 21:17:35 2015 +0100
@@ -23,6 +23,9 @@

ngx_uint_t protocols;

+ ngx_uint_t verify;
+ ngx_uint_t verify_depth;
+
ssize_t builtin_session_cache;

time_t session_timeout;
@@ -31,6 +34,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;


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

[PATCH] Stream: client SSL certificate support

Lukas Prettenthaler 910 November 06, 2015 03:36PM



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

Online Users

Guests: 296
Record Number of Users: 8 on April 13, 2023
Record Number of Guests: 421 on December 02, 2018
Powered by nginx      Powered by FreeBSD      PHP Powered      Powered by MariaDB      ipv6 ready