<html xmlns:v="urn:schemas-microsoft-com:vml" xmlns:o="urn:schemas-microsoft-com:office:office" xmlns:w="urn:schemas-microsoft-com:office:word" xmlns:m="http://schemas.microsoft.com/office/2004/12/omml" xmlns="http://www.w3.org/TR/REC-html40">
<head>
<meta http-equiv="Content-Type" content="text/html; charset=us-ascii">
<meta name="Generator" content="Microsoft Word 15 (filtered medium)">
<style><!--
/* Font Definitions */
@font-face
        {font-family:"Cambria Math";
        panose-1:2 4 5 3 5 4 6 3 2 4;}
@font-face
        {font-family:Calibri;
        panose-1:2 15 5 2 2 2 4 3 2 4;}
/* Style Definitions */
p.MsoNormal, li.MsoNormal, div.MsoNormal
        {margin:0in;
        margin-bottom:.0001pt;
        font-size:11.0pt;
        font-family:"Calibri",sans-serif;}
a:link, span.MsoHyperlink
        {mso-style-priority:99;
        color:#0563C1;
        text-decoration:underline;}
a:visited, span.MsoHyperlinkFollowed
        {mso-style-priority:99;
        color:#954F72;
        text-decoration:underline;}
span.EmailStyle17
        {mso-style-type:personal-compose;
        font-family:"Calibri",sans-serif;
        color:windowtext;}
.MsoChpDefault
        {mso-style-type:export-only;
        font-family:"Calibri",sans-serif;}
@page WordSection1
        {size:8.5in 11.0in;
        margin:1.0in 1.0in 1.0in 1.0in;}
div.WordSection1
        {page:WordSection1;}
--></style><!--[if gte mso 9]><xml>
<o:shapedefaults v:ext="edit" spidmax="1026" />
</xml><![endif]--><!--[if gte mso 9]><xml>
<o:shapelayout v:ext="edit">
<o:idmap v:ext="edit" data="1" />
</o:shapelayout></xml><![endif]-->
</head>
<body lang="EN-US" link="#0563C1" vlink="#954F72">
<div class="WordSection1">
<p class="MsoNormal"># HG changeset patch<o:p></o:p></p>
<p class="MsoNormal"># User Mandeep Singh Chhabra <mandeep-singh.chhabra@thalesgroup.com><o:p></o:p></p>
<p class="MsoNormal"># Date 1640691269 -19800<o:p></o:p></p>
<p class="MsoNormal">#      Tue Dec 28 17:04:29 2021 +0530<o:p></o:p></p>
<p class="MsoNormal"># Node ID 9baaef976ac80f05107b60801ebe6559cdb2cbc6<o:p></o:p></p>
<p class="MsoNormal"># Parent  b002ad258f1d70924dc13d8f4bc0cc44362f0d0a<o:p></o:p></p>
<p class="MsoNormal">Add provision to fetch certificate chain from Nginx<o:p></o:p></p>
<p class="MsoNormal"><o:p> </o:p></p>
<p class="MsoNormal">The change adds a new variable ('ssl_client_cert_chain') to the<o:p></o:p></p>
<p class="MsoNormal">existing set of variables. It is being part of the http's SSL<o:p></o:p></p>
<p class="MsoNormal">module. With this, the middleware can fetch the certificate chain<o:p></o:p></p>
<p class="MsoNormal">from Nginx using the variable mentioned. The variable returns<o:p></o:p></p>
<p class="MsoNormal">a verified chain of certificates.<o:p></o:p></p>
<p class="MsoNormal">If the trust anchor is a root certificate (self signed) which has<o:p></o:p></p>
<p class="MsoNormal">issued an intermediate certificate and the client certificate is<o:p></o:p></p>
<p class="MsoNormal">issued by the intermediate certificate. The variable ('ssl_client_cert_chain')<o:p></o:p></p>
<p class="MsoNormal">will return three certificates (rootCert -> intermediateCert -> clientCert)<o:p></o:p></p>
<p class="MsoNormal"><o:p> </o:p></p>
<p class="MsoNormal">diff -r b002ad258f1d -r 9baaef976ac8 src/event/ngx_event_openssl.c<o:p></o:p></p>
<p class="MsoNormal">--- a/src/event/ngx_event_openssl.c         Mon Dec 27 19:49:26 2021 +0300<o:p></o:p></p>
<p class="MsoNormal">+++ b/src/event/ngx_event_openssl.c      Tue Dec 28 17:04:29 2021 +0530<o:p></o:p></p>
<p class="MsoNormal">@@ -5048,6 +5048,99 @@<o:p></o:p></p>
<p class="MsoNormal">     return NGX_ERROR;<o:p></o:p></p>
<p class="MsoNormal">}<o:p></o:p></p>
<p class="MsoNormal"><o:p></o:p></p>
<p class="MsoNormal">+ngx_int_t<o:p></o:p></p>
<p class="MsoNormal">+ngx_ssl_get_verified_certificate_chain(ngx_connection_t *c, ngx_pool_t *pool, ngx_str_t *s)<o:p></o:p></p>
<p class="MsoNormal">+{<o:p></o:p></p>
<p class="MsoNormal">+    size_t   len;<o:p></o:p></p>
<p class="MsoNormal">+    BIO     *bio;<o:p></o:p></p>
<p class="MsoNormal">+    X509    *cert;<o:p></o:p></p>
<p class="MsoNormal">+    STACK_OF(X509)    *certs;<o:p></o:p></p>
<p class="MsoNormal">+<o:p></o:p></p>
<p class="MsoNormal">+    s->len = 0;<o:p></o:p></p>
<p class="MsoNormal">+<o:p></o:p></p>
<p class="MsoNormal">+    bio = BIO_new(BIO_s_mem());<o:p></o:p></p>
<p class="MsoNormal">+    if (bio == NULL) {<o:p></o:p></p>
<p class="MsoNormal">+        ngx_ssl_error(NGX_LOG_ALERT, c->log, 0, "BIO_new() failed");<o:p></o:p></p>
<p class="MsoNormal">+        return NGX_ERROR;<o:p></o:p></p>
<p class="MsoNormal">+    }<o:p></o:p></p>
<p class="MsoNormal">+    <o:p></o:p></p>
<p class="MsoNormal">+    certs = SSL_get0_verified_chain(c->ssl->connection);<o:p></o:p></p>
<p class="MsoNormal">+    if (certs == NULL) {<o:p></o:p></p>
<p class="MsoNormal">+        ngx_ssl_error(NGX_LOG_ERR, c->log, 0, "SSL_get0_verified_chain failed");<o:p></o:p></p>
<p class="MsoNormal">+        goto failed;<o:p></o:p></p>
<p class="MsoNormal">+    } else {<o:p></o:p></p>
<p class="MsoNormal">+        for (int i = 0; i < sk_X509_num(certs); i++) {<o:p></o:p></p>
<p class="MsoNormal">+            cert = sk_X509_value(certs, i);<o:p></o:p></p>
<p class="MsoNormal">+    <o:p></o:p></p>
<p class="MsoNormal">+            if (PEM_write_bio_X509(bio, cert) == 0) {<o:p></o:p></p>
<p class="MsoNormal">+                ngx_ssl_error(NGX_LOG_ALERT, c->log, 0, "PEM_write_bio_X509() failed");<o:p></o:p></p>
<p class="MsoNormal">+                goto failed;<o:p></o:p></p>
<p class="MsoNormal">+            }<o:p></o:p></p>
<p class="MsoNormal">+        }<o:p></o:p></p>
<p class="MsoNormal">+    }<o:p></o:p></p>
<p class="MsoNormal">+<o:p></o:p></p>
<p class="MsoNormal">+    len = BIO_pending(bio);<o:p></o:p></p>
<p class="MsoNormal">+    s->len = len;<o:p></o:p></p>
<p class="MsoNormal">+<o:p></o:p></p>
<p class="MsoNormal">+    s->data = ngx_pnalloc(pool, len);<o:p></o:p></p>
<p class="MsoNormal">+    if (s->data == NULL) {<o:p></o:p></p>
<p class="MsoNormal">+        goto failed;<o:p></o:p></p>
<p class="MsoNormal">+    }<o:p></o:p></p>
<p class="MsoNormal">+<o:p></o:p></p>
<p class="MsoNormal">+    BIO_read(bio, s->data, len);<o:p></o:p></p>
<p class="MsoNormal">+    BIO_free(bio);<o:p></o:p></p>
<p class="MsoNormal">+<o:p></o:p></p>
<p class="MsoNormal">+    return NGX_OK;<o:p></o:p></p>
<p class="MsoNormal">+<o:p></o:p></p>
<p class="MsoNormal">+failed:<o:p></o:p></p>
<p class="MsoNormal">+    BIO_free(bio);<o:p></o:p></p>
<p class="MsoNormal">+    <o:p></o:p></p>
<p class="MsoNormal">+    return NGX_ERROR;<o:p></o:p></p>
<p class="MsoNormal"><span lang="FR">+}<o:p></o:p></span></p>
<p class="MsoNormal"><span lang="FR">+<o:p></o:p></span></p>
<p class="MsoNormal"><span lang="FR">+ngx_int_t<o:p></o:p></span></p>
<p class="MsoNormal"><span lang="FR">+ngx_ssl_get_client_certificate_chain(ngx_connection_t *c, ngx_pool_t *pool, ngx_str_t *s)<o:p></o:p></span></p>
<p class="MsoNormal"><span lang="FR">+{<o:p></o:p></span></p>
<p class="MsoNormal"><span lang="FR">+    u_char      *p;<o:p></o:p></span></p>
<p class="MsoNormal"><span lang="FR">+    size_t       len;<o:p></o:p></span></p>
<p class="MsoNormal"><span lang="FR">+    ngx_uint_t   i;<o:p></o:p></span></p>
<p class="MsoNormal"><span lang="FR">+    ngx_str_t    cert_chain;<o:p></o:p></span></p>
<p class="MsoNormal">+<o:p></o:p></p>
<p class="MsoNormal">+    if (ngx_ssl_get_verified_certificate_chain(c, pool, &cert_chain) != NGX_OK) {<o:p></o:p></p>
<p class="MsoNormal">+        return NGX_ERROR;<o:p></o:p></p>
<p class="MsoNormal">+    }<o:p></o:p></p>
<p class="MsoNormal">+<o:p></o:p></p>
<p class="MsoNormal">+    if (cert_chain.len == 0) {<o:p></o:p></p>
<p class="MsoNormal">+        s->len = 0;<o:p></o:p></p>
<p class="MsoNormal">+        return NGX_OK;<o:p></o:p></p>
<p class="MsoNormal">+    }<o:p></o:p></p>
<p class="MsoNormal">+<o:p></o:p></p>
<p class="MsoNormal">+    len = cert_chain.len - 1;<o:p></o:p></p>
<p class="MsoNormal">+<o:p></o:p></p>
<p class="MsoNormal">+    for (i = 0; i < cert_chain.len - 1; i++) {<o:p></o:p></p>
<p class="MsoNormal">+        if (cert_chain.data[i] == LF) {<o:p></o:p></p>
<p class="MsoNormal">+            len++;<o:p></o:p></p>
<p class="MsoNormal">+        }<o:p></o:p></p>
<p class="MsoNormal">+    }<o:p></o:p></p>
<p class="MsoNormal">+<o:p></o:p></p>
<p class="MsoNormal">+    s->len = len;<o:p></o:p></p>
<p class="MsoNormal">+    s->data = ngx_pnalloc(pool, len);<o:p></o:p></p>
<p class="MsoNormal">+    if (s->data == NULL) {<o:p></o:p></p>
<p class="MsoNormal">+        ngx_ssl_error(NGX_LOG_ERR, c->log, 0, "ngx_pnalloc failed");<o:p></o:p></p>
<p class="MsoNormal">+        return NGX_ERROR;<o:p></o:p></p>
<p class="MsoNormal">+    }<o:p></o:p></p>
<p class="MsoNormal">+<o:p></o:p></p>
<p class="MsoNormal">+    p = s->data;<o:p></o:p></p>
<p class="MsoNormal">+<o:p></o:p></p>
<p class="MsoNormal">+    for (i = 0; i < cert_chain.len - 1; i++) {<o:p></o:p></p>
<p class="MsoNormal">+        *p++ = cert_chain.data[i];<o:p></o:p></p>
<p class="MsoNormal">+        if (cert_chain.data[i] == LF) {<o:p></o:p></p>
<p class="MsoNormal">+            *p++ = '\t';<o:p></o:p></p>
<p class="MsoNormal">+        }<o:p></o:p></p>
<p class="MsoNormal">+    }<o:p></o:p></p>
<p class="MsoNormal">+<o:p></o:p></p>
<p class="MsoNormal">+    return NGX_OK;<o:p></o:p></p>
<p class="MsoNormal">+}<o:p></o:p></p>
<p class="MsoNormal"><o:p></o:p></p>
<p class="MsoNormal"> ngx_int_t<o:p></o:p></p>
<p class="MsoNormal">ngx_ssl_get_certificate(ngx_connection_t *c, ngx_pool_t *pool, ngx_str_t *s)<o:p></o:p></p>
<p class="MsoNormal">diff -r b002ad258f1d -r 9baaef976ac8 src/event/ngx_event_openssl.h<o:p></o:p></p>
<p class="MsoNormal">--- a/src/event/ngx_event_openssl.h        Mon Dec 27 19:49:26 2021 +0300<o:p></o:p></p>
<p class="MsoNormal">+++ b/src/event/ngx_event_openssl.h     Tue Dec 28 17:04:29 2021 +0530<o:p></o:p></p>
<p class="MsoNormal">@@ -276,6 +276,8 @@<o:p></o:p></p>
<p class="MsoNormal">     ngx_str_t *s);<o:p></o:p></p>
<p class="MsoNormal">ngx_int_t ngx_ssl_get_escaped_certificate(ngx_connection_t *c, ngx_pool_t *pool,<o:p></o:p></p>
<p class="MsoNormal">     ngx_str_t *s);<o:p></o:p></p>
<p class="MsoNormal"><span lang="FR">+ngx_int_t ngx_ssl_get_client_certificate_chain(ngx_connection_t *c, ngx_pool_t *pool,<o:p></o:p></span></p>
<p class="MsoNormal"><span lang="FR">+    ngx_str_t *s);<o:p></o:p></span></p>
<p class="MsoNormal"><span lang="FR">ngx_int_t ngx_ssl_get_subject_dn(ngx_connection_t *c, ngx_pool_t *pool,<o:p></o:p></span></p>
<p class="MsoNormal"><span lang="FR">     ngx_str_t *s);<o:p></o:p></span></p>
<p class="MsoNormal"><span lang="FR">ngx_int_t ngx_ssl_get_issuer_dn(ngx_connection_t *c, ngx_pool_t *pool,<o:p></o:p></span></p>
<p class="MsoNormal">diff -r b002ad258f1d -r 9baaef976ac8 src/http/modules/ngx_http_ssl_module.c<o:p></o:p></p>
<p class="MsoNormal">--- a/src/http/modules/ngx_http_ssl_module.c    Mon Dec 27 19:49:26 2021 +0300<o:p></o:p></p>
<p class="MsoNormal">+++ b/src/http/modules/ngx_http_ssl_module.c                Tue Dec 28 17:04:29 2021 +0530<o:p></o:p></p>
<p class="MsoNormal">@@ -370,6 +370,10 @@<o:p></o:p></p>
<p class="MsoNormal">     { ngx_string("ssl_client_raw_cert"), NULL, ngx_http_ssl_variable,<o:p></o:p></p>
<p class="MsoNormal">       (uintptr_t) ngx_ssl_get_raw_certificate,<o:p></o:p></p>
<p class="MsoNormal">       <span lang="FR">NGX_HTTP_VAR_CHANGEABLE, 0 },<o:p></o:p></span></p>
<p class="MsoNormal"><span lang="FR">+    <o:p></o:p></span></p>
<p class="MsoNormal"><span lang="FR">+    { ngx_string("ssl_client_cert_chain"), NULL, ngx_http_ssl_variable,<o:p></o:p></span></p>
<p class="MsoNormal"><span lang="FR">+      (uintptr_t) ngx_ssl_get_client_certificate_chain,<o:p></o:p></span></p>
<p class="MsoNormal">+      NGX_HTTP_VAR_CHANGEABLE, 0 },<o:p></o:p></p>
<p class="MsoNormal"><o:p></o:p></p>
<p class="MsoNormal">     { ngx_string("ssl_client_escaped_cert"), NULL, ngx_http_ssl_variable,<o:p></o:p></p>
<p class="MsoNormal">       (uintptr_t) ngx_ssl_get_escaped_certificate,<o:p></o:p></p>
</div>
</body>
</html>