changeset 9324:03cdd806c0f2

SSL: added SHA-256 fingerprints. In http and stream modules, the $ssl_client_fingerprint_sha256 variable now provides client certificate SHA-256 fingerprint, in addition to the $ssl_client_fingerprint variable with SHA-1 fingerprint. In mail proxy, the "Auth-SSL-Fingerprint-SHA256" header was added.
author Maxim Dounin <mdounin@mdounin.ru>
date Sat, 31 Aug 2024 00:30:42 +0300
parents 8ebb4e488aa4
children 0086f8da5d8d
files src/event/ngx_event_openssl.c src/event/ngx_event_openssl.h src/http/modules/ngx_http_ssl_module.c src/mail/ngx_mail_auth_http_module.c src/stream/ngx_stream_ssl_module.c
diffstat 5 files changed, 61 insertions(+), 1 deletions(-) [+]
line wrap: on
line diff
--- a/src/event/ngx_event_openssl.c
+++ b/src/event/ngx_event_openssl.c
@@ -5749,6 +5749,42 @@ ngx_ssl_get_fingerprint(ngx_connection_t
 
 
 ngx_int_t
+ngx_ssl_get_fingerprint_sha256(ngx_connection_t *c, ngx_pool_t *pool,
+    ngx_str_t *s)
+{
+    X509          *cert;
+    unsigned int   len;
+    u_char         buf[EVP_MAX_MD_SIZE];
+
+    s->len = 0;
+
+    cert = SSL_get_peer_certificate(c->ssl->connection);
+    if (cert == NULL) {
+        return NGX_OK;
+    }
+
+    if (!X509_digest(cert, EVP_sha256(), buf, &len)) {
+        ngx_ssl_error(NGX_LOG_ALERT, c->log, 0, "X509_digest() failed");
+        X509_free(cert);
+        return NGX_ERROR;
+    }
+
+    s->len = 2 * len;
+    s->data = ngx_pnalloc(pool, 2 * len);
+    if (s->data == NULL) {
+        X509_free(cert);
+        return NGX_ERROR;
+    }
+
+    ngx_hex_dump(s->data, buf, len);
+
+    X509_free(cert);
+
+    return NGX_OK;
+}
+
+
+ngx_int_t
 ngx_ssl_get_client_verify(ngx_connection_t *c, ngx_pool_t *pool, ngx_str_t *s)
 {
     X509        *cert;
--- a/src/event/ngx_event_openssl.h
+++ b/src/event/ngx_event_openssl.h
@@ -299,6 +299,8 @@ ngx_int_t ngx_ssl_get_serial_number(ngx_
     ngx_str_t *s);
 ngx_int_t ngx_ssl_get_fingerprint(ngx_connection_t *c, ngx_pool_t *pool,
     ngx_str_t *s);
+ngx_int_t ngx_ssl_get_fingerprint_sha256(ngx_connection_t *c, ngx_pool_t *pool,
+    ngx_str_t *s);
 ngx_int_t ngx_ssl_get_client_verify(ngx_connection_t *c, ngx_pool_t *pool,
     ngx_str_t *s);
 ngx_int_t ngx_ssl_get_client_v_start(ngx_connection_t *c, ngx_pool_t *pool,
--- a/src/http/modules/ngx_http_ssl_module.c
+++ b/src/http/modules/ngx_http_ssl_module.c
@@ -387,6 +387,9 @@ static ngx_http_variable_t  ngx_http_ssl
     { ngx_string("ssl_client_fingerprint"), NULL, ngx_http_ssl_variable,
       (uintptr_t) ngx_ssl_get_fingerprint, NGX_HTTP_VAR_CHANGEABLE, 0 },
 
+    { ngx_string("ssl_client_fingerprint_sha256"), NULL, ngx_http_ssl_variable,
+      (uintptr_t) ngx_ssl_get_fingerprint_sha256, NGX_HTTP_VAR_CHANGEABLE, 0 },
+
     { ngx_string("ssl_client_verify"), NULL, ngx_http_ssl_variable,
       (uintptr_t) ngx_ssl_get_client_verify, NGX_HTTP_VAR_CHANGEABLE, 0 },
 
--- a/src/mail/ngx_mail_auth_http_module.c
+++ b/src/mail/ngx_mail_auth_http_module.c
@@ -1213,7 +1213,8 @@ ngx_mail_auth_http_create_request(ngx_ma
     ngx_connection_t          *c;
 #if (NGX_MAIL_SSL)
     ngx_str_t                  protocol, cipher, verify, subject, issuer,
-                               serial, fingerprint, raw_cert, cert;
+                               serial, fingerprint, fingerprint2, raw_cert,
+                               cert;
     ngx_mail_ssl_conf_t       *sslcf;
 #endif
     ngx_mail_core_srv_conf_t  *cscf;
@@ -1275,6 +1276,10 @@ ngx_mail_auth_http_create_request(ngx_ma
             return NULL;
         }
 
+        if (ngx_ssl_get_fingerprint_sha256(c, pool, &fingerprint2) != NGX_OK) {
+            return NULL;
+        }
+
         if (ahcf->pass_client_cert) {
 
             /* certificate itself, if configured */
@@ -1297,6 +1302,7 @@ ngx_mail_auth_http_create_request(ngx_ma
         ngx_str_null(&issuer);
         ngx_str_null(&serial);
         ngx_str_null(&fingerprint);
+        ngx_str_null(&fingerprint2);
         ngx_str_null(&cert);
     }
 
@@ -1360,6 +1366,8 @@ ngx_mail_auth_http_create_request(ngx_ma
                      + sizeof(CRLF) - 1
                + sizeof("Auth-SSL-Fingerprint: ") - 1 + fingerprint.len
                      + sizeof(CRLF) - 1
+               + sizeof("Auth-SSL-Fingerprint-SHA256: ") - 1 + fingerprint2.len
+                     + sizeof(CRLF) - 1
                + sizeof("Auth-SSL-Cert: ") - 1 + cert.len
                      + sizeof(CRLF) - 1;
     }
@@ -1520,6 +1528,13 @@ ngx_mail_auth_http_create_request(ngx_ma
             *b->last++ = CR; *b->last++ = LF;
         }
 
+        if (fingerprint2.len) {
+            b->last = ngx_cpymem(b->last, "Auth-SSL-Fingerprint-SHA256: ",
+                                 sizeof("Auth-SSL-Fingerprint-SHA256: ") - 1);
+            b->last = ngx_copy(b->last, fingerprint2.data, fingerprint2.len);
+            *b->last++ = CR; *b->last++ = LF;
+        }
+
         if (cert.len) {
             b->last = ngx_cpymem(b->last, "Auth-SSL-Cert: ",
                                  sizeof("Auth-SSL-Cert: ") - 1);
--- a/src/stream/ngx_stream_ssl_module.c
+++ b/src/stream/ngx_stream_ssl_module.c
@@ -310,6 +310,10 @@ static ngx_stream_variable_t  ngx_stream
     { ngx_string("ssl_client_fingerprint"), NULL, ngx_stream_ssl_variable,
       (uintptr_t) ngx_ssl_get_fingerprint, NGX_STREAM_VAR_CHANGEABLE, 0 },
 
+    { ngx_string("ssl_client_fingerprint_sha256"), NULL,
+      ngx_stream_ssl_variable, (uintptr_t) ngx_ssl_get_fingerprint_sha256,
+      NGX_STREAM_VAR_CHANGEABLE, 0 },
+
     { ngx_string("ssl_client_verify"), NULL, ngx_stream_ssl_variable,
       (uintptr_t) ngx_ssl_get_client_verify, NGX_STREAM_VAR_CHANGEABLE, 0 },