Welcome! Log In Create A New Profile

Advanced

[PATCH] Add provision to fetch certificate chain from Nginx

CHHABRA Mandeep Singh
December 28, 2021 06:58AM
# HG changeset patch
# User Mandeep Singh Chhabra <mandeep-singh.chhabra@thalesgroup.com>
# Date 1640691269 -19800
# Tue Dec 28 17:04:29 2021 +0530
# Node ID 9baaef976ac80f05107b60801ebe6559cdb2cbc6
# Parent b002ad258f1d70924dc13d8f4bc0cc44362f0d0a
Add provision to fetch certificate chain from Nginx

The change adds a new variable ('ssl_client_cert_chain') to the
existing set of variables. It is being part of the http's SSL
module. With this, the middleware can fetch the certificate chain
from Nginx using the variable mentioned. The variable returns
a verified chain of certificates.
If the trust anchor is a root certificate (self signed) which has
issued an intermediate certificate and the client certificate is
issued by the intermediate certificate. The variable ('ssl_client_cert_chain')
will return three certificates (rootCert -> intermediateCert -> clientCert)

diff -r b002ad258f1d -r 9baaef976ac8 src/event/ngx_event_openssl.c
--- a/src/event/ngx_event_openssl.c Mon Dec 27 19:49:26 2021 +0300
+++ b/src/event/ngx_event_openssl.c Tue Dec 28 17:04:29 2021 +0530
@@ -5048,6 +5048,99 @@
return NGX_ERROR;
}
+ngx_int_t
+ngx_ssl_get_verified_certificate_chain(ngx_connection_t *c, ngx_pool_t *pool, ngx_str_t *s)
+{
+ size_t len;
+ BIO *bio;
+ X509 *cert;
+ STACK_OF(X509) *certs;
+
+ s->len = 0;
+
+ bio = BIO_new(BIO_s_mem());
+ if (bio == NULL) {
+ ngx_ssl_error(NGX_LOG_ALERT, c->log, 0, "BIO_new() failed");
+ return NGX_ERROR;
+ }
+
+ certs = SSL_get0_verified_chain(c->ssl->connection);
+ if (certs == NULL) {
+ ngx_ssl_error(NGX_LOG_ERR, c->log, 0, "SSL_get0_verified_chain failed");
+ goto failed;
+ } else {
+ for (int i = 0; i < sk_X509_num(certs); i++) {
+ cert = sk_X509_value(certs, i);
+
+ if (PEM_write_bio_X509(bio, cert) == 0) {
+ ngx_ssl_error(NGX_LOG_ALERT, c->log, 0, "PEM_write_bio_X509() failed");
+ goto failed;
+ }
+ }
+ }
+
+ len = BIO_pending(bio);
+ s->len = len;
+
+ s->data = ngx_pnalloc(pool, len);
+ if (s->data == NULL) {
+ goto failed;
+ }
+
+ BIO_read(bio, s->data, len);
+ BIO_free(bio);
+
+ return NGX_OK;
+
+failed:
+ BIO_free(bio);
+
+ return NGX_ERROR;
+}
+
+ngx_int_t
+ngx_ssl_get_client_certificate_chain(ngx_connection_t *c, ngx_pool_t *pool, ngx_str_t *s)
+{
+ u_char *p;
+ size_t len;
+ ngx_uint_t i;
+ ngx_str_t cert_chain;
+
+ if (ngx_ssl_get_verified_certificate_chain(c, pool, &cert_chain) != NGX_OK) {
+ return NGX_ERROR;
+ }
+
+ if (cert_chain.len == 0) {
+ s->len = 0;
+ return NGX_OK;
+ }
+
+ len = cert_chain.len - 1;
+
+ for (i = 0; i < cert_chain.len - 1; i++) {
+ if (cert_chain.data[i] == LF) {
+ len++;
+ }
+ }
+
+ s->len = len;
+ s->data = ngx_pnalloc(pool, len);
+ if (s->data == NULL) {
+ ngx_ssl_error(NGX_LOG_ERR, c->log, 0, "ngx_pnalloc failed");
+ return NGX_ERROR;
+ }
+
+ p = s->data;
+
+ for (i = 0; i < cert_chain.len - 1; i++) {
+ *p++ = cert_chain.data[i];
+ if (cert_chain.data[i] == LF) {
+ *p++ = '\t';
+ }
+ }
+
+ return NGX_OK;
+}
ngx_int_t
ngx_ssl_get_certificate(ngx_connection_t *c, ngx_pool_t *pool, ngx_str_t *s)
diff -r b002ad258f1d -r 9baaef976ac8 src/event/ngx_event_openssl.h
--- a/src/event/ngx_event_openssl.h Mon Dec 27 19:49:26 2021 +0300
+++ b/src/event/ngx_event_openssl.h Tue Dec 28 17:04:29 2021 +0530
@@ -276,6 +276,8 @@
ngx_str_t *s);
ngx_int_t ngx_ssl_get_escaped_certificate(ngx_connection_t *c, ngx_pool_t *pool,
ngx_str_t *s);
+ngx_int_t ngx_ssl_get_client_certificate_chain(ngx_connection_t *c, ngx_pool_t *pool,
+ ngx_str_t *s);
ngx_int_t ngx_ssl_get_subject_dn(ngx_connection_t *c, ngx_pool_t *pool,
ngx_str_t *s);
ngx_int_t ngx_ssl_get_issuer_dn(ngx_connection_t *c, ngx_pool_t *pool,
diff -r b002ad258f1d -r 9baaef976ac8 src/http/modules/ngx_http_ssl_module.c
--- a/src/http/modules/ngx_http_ssl_module.c Mon Dec 27 19:49:26 2021 +0300
+++ b/src/http/modules/ngx_http_ssl_module.c Tue Dec 28 17:04:29 2021 +0530
@@ -370,6 +370,10 @@
{ ngx_string("ssl_client_raw_cert"), NULL, ngx_http_ssl_variable,
(uintptr_t) ngx_ssl_get_raw_certificate,
NGX_HTTP_VAR_CHANGEABLE, 0 },
+
+ { ngx_string("ssl_client_cert_chain"), NULL, ngx_http_ssl_variable,
+ (uintptr_t) ngx_ssl_get_client_certificate_chain,
+ NGX_HTTP_VAR_CHANGEABLE, 0 },
{ ngx_string("ssl_client_escaped_cert"), NULL, ngx_http_ssl_variable,
(uintptr_t) ngx_ssl_get_escaped_certificate,
_______________________________________________
nginx-devel mailing list
nginx-devel@nginx.org
http://mailman.nginx.org/mailman/listinfo/nginx-devel
Subject Author Views Posted

[PATCH] Add provision to fetch certificate chain from Nginx

CHHABRA Mandeep Singh 167 December 28, 2021 06:58AM

Re: [PATCH] Add provision to fetch certificate chain from Nginx

Maxim Dounin 25 December 28, 2021 11:00AM

RE: [PATCH] Add provision to fetch certificate chain from Nginx

CHHABRA Mandeep Singh 22 December 30, 2021 04:36AM

RE: [PATCH] Add provision to fetch certificate chain from Nginx

CHHABRA Mandeep Singh 15 January 06, 2022 06:54AM

Re: [PATCH] Add provision to fetch certificate chain from Nginx

Maxim Dounin 17 January 11, 2022 03:42PM



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

Online Users

Guests: 51
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