Add new, corporate friendly, SSL client certificate variables.
Dave Bevan
dave.bevan at bbc.co.uk
Mon Feb 20 10:20:07 UTC 2017
# HG changeset patch
# User Dave Bevan <dave.bevan at bbc.co.uk>
# Date 1487584846 0
# Mon Feb 20 10:00:46 2017 +0000
# Node ID 06bd70321e25e01574e406095ff5f21f56b571da
# Parent 87cf6ddb41c216876d13cffa5e637a61b159362c
Add new, corporate friendly, SSL client certificate variables.
Introduce three new SSL variables:
* ssl_client_ms_upn (extracts Microsoft UserPrincipleName from client cert)
* ssl_client_email (extracts email from client cert)
* ssl_client_s_cn (extracts Subject Common Name from client cert)
These are particularly useful in corporate environments, and bring some parity
with Apache facilities (particularly ms_upn extract).
diff -r 87cf6ddb41c2 -r 06bd70321e25 src/event/ngx_event_openssl.c
--- a/src/event/ngx_event_openssl.c Fri Feb 17 17:01:27 2017 +0300
+++ b/src/event/ngx_event_openssl.c Mon Feb 20 10:00:46 2017 +0000
@@ -4081,6 +4081,150 @@
}
+ngx_int_t
+ngx_ssl_get_client_ms_upn(ngx_connection_t *c, ngx_pool_t *pool, ngx_str_t *s)
+{
+ int i;
+ BIO *bio;
+ X509 *cert;
+ GENERAL_NAME *altname;
+ STACK_OF(GENERAL_NAME) *altnames;
+
+ s->len = 0;
+
+ cert = SSL_get_peer_certificate(c->ssl->connection);
+ if (cert == NULL) {
+ return NGX_OK;
+ }
+
+ bio = BIO_new(BIO_s_mem());
+ if (bio == NULL) {
+ X509_free(cert);
+ return NGX_ERROR;
+ }
+
+ altnames = X509_get_ext_d2i(cert, NID_subject_alt_name, NULL, NULL);
+
+ if (altnames) {
+ for (i = 0; i < sk_GENERAL_NAME_num(altnames); i++) {
+ altname = sk_GENERAL_NAME_value(altnames, i);
+
+ if (altname->type != GEN_OTHERNAME) {
+ continue;
+ }
+
+ if (NID_ms_upn != OBJ_obj2nid(altname->d.otherName->type_id)) {
+ continue;
+ }
+
+ BIO_printf(bio, "%s",
+ (char*)ASN1_STRING_data(altname->d.otherName->value->value.asn1_string));
+ }
+ }
+
+ s->len = BIO_pending(bio);
+ s->data = ngx_pnalloc(pool, s->len);
+
+ BIO_read(bio, s->data, s->len);
+ BIO_free(bio);
+ X509_free(cert);
+ GENERAL_NAMES_free(altnames);
+
+ return NGX_OK;
+}
+
+
+ngx_int_t
+ngx_ssl_get_client_email(ngx_connection_t *c, ngx_pool_t *pool, ngx_str_t *s)
+{
+ unsigned int i;
+ BIO *bio;
+ X509 *cert;
+ STACK_OF(OPENSSL_STRING) *emails;
+
+ s->len = 0;
+
+ cert = SSL_get_peer_certificate(c->ssl->connection);
+ if (cert == NULL) {
+ return NGX_OK;
+ }
+
+ bio = BIO_new(BIO_s_mem());
+ if (bio == NULL) {
+ X509_free(cert);
+ return NGX_ERROR;
+ }
+
+ emails = X509_get1_email(cert);
+
+ for (i = 0; i < (unsigned int)sk_OPENSSL_STRING_num(emails); i++) {
+ BIO_printf(bio, "%s",
+ sk_OPENSSL_STRING_value(emails, i));
+ break;
+ }
+
+ s->len = BIO_pending(bio);
+ s->data = ngx_pnalloc(pool, s->len);
+
+ BIO_read(bio, s->data, s->len);
+ BIO_free(bio);
+ X509_free(cert);
+ X509_email_free(emails);
+
+ return NGX_OK;
+}
+
+
+ngx_int_t
+ngx_ssl_get_client_s_cn(ngx_connection_t *c, ngx_pool_t *pool, ngx_str_t *s)
+{
+ int i;
+ BIO *bio;
+ X509 *cert;
+ X509_NAME *name;
+ X509_NAME_ENTRY *cn;
+
+ s->len = 0;
+
+ cert = SSL_get_peer_certificate(c->ssl->connection);
+ if (cert == NULL) {
+ return NGX_OK;
+ }
+
+ bio = BIO_new(BIO_s_mem());
+ if (bio == NULL) {
+ X509_free(cert);
+ return NGX_ERROR;
+ }
+
+ name = X509_get_subject_name(cert);
+
+ if (name != NULL) {
+ i = -1;
+ for ( ;; ) {
+ i = X509_NAME_get_index_by_NID(name, NID_commonName, i);
+
+ if (i < 0) {
+ break;
+ }
+
+ cn = X509_NAME_get_entry(name, i);
+ BIO_printf(bio, "%s",
+ ASN1_STRING_data(X509_NAME_ENTRY_get_data(cn)));
+ }
+ }
+
+ s->len = BIO_pending(bio);
+ s->data = ngx_pnalloc(pool, s->len);
+
+ BIO_read(bio, s->data, s->len);
+ BIO_free(bio);
+ X509_free(cert);
+
+ return NGX_OK;
+}
+
+
static time_t
ngx_ssl_parse_time(
#if OPENSSL_VERSION_NUMBER > 0x10100000L
diff -r 87cf6ddb41c2 -r 06bd70321e25 src/event/ngx_event_openssl.h
--- a/src/event/ngx_event_openssl.h Fri Feb 17 17:01:27 2017 +0300
+++ b/src/event/ngx_event_openssl.h Mon Feb 20 10:00:46 2017 +0000
@@ -226,6 +226,12 @@
ngx_str_t *s);
ngx_int_t ngx_ssl_get_client_v_remain(ngx_connection_t *c, ngx_pool_t *pool,
ngx_str_t *s);
+ngx_int_t ngx_ssl_get_client_ms_upn(ngx_connection_t *c, ngx_pool_t *pool,
+ ngx_str_t *s);
+ngx_int_t ngx_ssl_get_client_email(ngx_connection_t *c, ngx_pool_t *pool,
+ ngx_str_t *s);
+ngx_int_t ngx_ssl_get_client_s_cn(ngx_connection_t *c, ngx_pool_t *pool,
+ ngx_str_t *s);
ngx_int_t ngx_ssl_handshake(ngx_connection_t *c);
diff -r 87cf6ddb41c2 -r 06bd70321e25 src/http/modules/ngx_http_ssl_module.c
--- a/src/http/modules/ngx_http_ssl_module.c Fri Feb 17 17:01:27 2017 +0300
+++ b/src/http/modules/ngx_http_ssl_module.c Mon Feb 20 10:00:46 2017 +0000
@@ -328,6 +328,15 @@
{ ngx_string("ssl_client_v_remain"), NULL, ngx_http_ssl_variable,
(uintptr_t) ngx_ssl_get_client_v_remain, NGX_HTTP_VAR_CHANGEABLE, 0 },
+ { ngx_string("ssl_client_ms_upn"), NULL, ngx_http_ssl_variable,
+ (uintptr_t) ngx_ssl_get_client_ms_upn, NGX_HTTP_VAR_CHANGEABLE, 0 },
+
+ { ngx_string("ssl_client_email"), NULL, ngx_http_ssl_variable,
+ (uintptr_t) ngx_ssl_get_client_email, NGX_HTTP_VAR_CHANGEABLE, 0 },
+
+ { ngx_string("ssl_client_s_cn"), NULL, ngx_http_ssl_variable,
+ (uintptr_t) ngx_ssl_get_client_s_cn, NGX_HTTP_VAR_CHANGEABLE, 0 },
+
{ ngx_null_string, NULL, NULL, 0, 0, 0 }
};
diff -r 87cf6ddb41c2 -r 06bd70321e25 src/stream/ngx_stream_ssl_module.c
--- a/src/stream/ngx_stream_ssl_module.c Fri Feb 17 17:01:27 2017 +0300
+++ b/src/stream/ngx_stream_ssl_module.c Mon Feb 20 10:00:46 2017 +0000
@@ -272,6 +272,15 @@
{ ngx_string("ssl_client_v_remain"), NULL, ngx_stream_ssl_variable,
(uintptr_t) ngx_ssl_get_client_v_remain, NGX_STREAM_VAR_CHANGEABLE, 0 },
+ { ngx_string("ssl_client_ms_upn"), NULL, ngx_stream_ssl_variable,
+ (uintptr_t) ngx_ssl_get_client_ms_upn, NGX_STREAM_VAR_CHANGEABLE, 0 },
+
+ { ngx_string("ssl_client_email"), NULL, ngx_stream_ssl_variable,
+ (uintptr_t) ngx_ssl_get_client_email, NGX_STREAM_VAR_CHANGEABLE, 0 },
+
+ { ngx_string("ssl_client_s_cn"), NULL, ngx_stream_ssl_variable,
+ (uintptr_t) ngx_ssl_get_client_s_cn, NGX_STREAM_VAR_CHANGEABLE, 0 },
+
{ ngx_null_string, NULL, NULL, 0, 0, 0 }
};
More information about the nginx-devel
mailing list