<html><head><meta http-equiv="Content-Type" content="text/html; charset=us-ascii"></head><body style="word-wrap: break-word; -webkit-nbsp-mode: space; line-break: after-white-space;" class=""><div class="">The very first try to submit the early development of this patch here, got this response:</div><div class=""><br class=""></div><div class=""><a href="http://mailman.nginx.org/pipermail/nginx-devel/2017-August/010426.html" class="">http://mailman.nginx.org/pipermail/nginx-devel/2017-August/010426.html</a></div><div class=""><br class=""></div><div class=""><br class=""></div><div class="">Thanx </div><div class=""><br class=""></div><br class=""><div><br class=""><blockquote type="cite" class=""><div class="">On 24 Apr 2020, at 17:25, Garret Reece <<a href="mailto:garret@trailofbits.com" class="">garret@trailofbits.com</a>> wrote:</div><br class="Apple-interchange-newline"><div class=""><div class="">More or less, yes--we had a request from a customer to take just the<br class="">extensions and the elliptic curve format points data from your patch<br class="">and make them available in the main package<br class=""><br class="">On Fri, Apr 24, 2020 at 11:17 AM Paulo Pacheco <<a href="mailto:fooinha@gmail.com" class="">fooinha@gmail.com</a>> wrote:<br class=""><blockquote type="cite" class=""><br class="">Hello, this looks very similar with what I've done here.<br class=""><br class=""><a href="https://github.com/fooinha/nginx-ssl-ja3/blob/master/patches/nginx.1.17.1.ssl.extensions.patch" class="">https://github.com/fooinha/nginx-ssl-ja3/blob/master/patches/nginx.1.17.1.ssl.extensions.patch</a><br class=""><br class="">Is this the same code?<br class=""><br class=""><br class="">Thanx.<br class=""><br class=""><br class=""><br class=""><br class=""><br class=""><br class="">On 24 Apr 2020, at 16:17, Garret Reece <garret@trailofbits.com> wrote:<br class=""><br class=""># HG changeset patch<br class=""># User Garret Reece <garret@trailofbits.com><br class=""># Date 1587691836 18000<br class="">#      Thu Apr 23 20:30:36 2020 -0500<br class=""># Node ID 86d2f46807f597249fa59072b920a389f8c082ee<br class=""># Parent  716eddd74bc2831537f5b3f7ecd16ad3e516d043<br class="">Expose additional SSL variables.<br class=""><br class="">Expose the ssl extensions and elliptic curve point formats provided by client.<br class="">This enables ja3 fingerprinting of TLS connections.<br class=""><br class="">diff -r 716eddd74bc2 -r 86d2f46807f5 src/event/ngx_event_openssl.c<br class="">--- a/src/event/ngx_event_openssl.c Thu Apr 23 15:10:26 2020 +0300<br class="">+++ b/src/event/ngx_event_openssl.c Thu Apr 23 20:30:36 2020 -0500<br class="">@@ -1588,6 +1588,100 @@<br class="">    return NGX_OK;<br class="">}<br class=""><br class="">+#if OPENSSL_VERSION_NUMBER >= 0x10101000L<br class="">+<br class="">+void<br class="">+ngx_SSL_client_features(ngx_connection_t *c)<br class="">+{<br class="">+    unsigned short                *ciphers_out = NULL;<br class="">+    int                           *curves_out = NULL;<br class="">+    int                           *point_formats_out = NULL;<br class="">+    size_t                         len = 0;<br class="">+    SSL                           *s = NULL;<br class="">+<br class="">+    if (c == NULL) {<br class="">+        return;<br class="">+    }<br class="">+    s = c->ssl->connection;<br class="">+<br class="">+    /* Cipher suites */<br class="">+    c->ssl->ciphers = NULL;<br class="">+    c->ssl->ciphers_sz = SSL_get0_raw_cipherlist(s, &ciphers_out);<br class="">+    c->ssl->ciphers_sz /= 2;<br class="">+<br class="">+    if (c->ssl->ciphers_sz && ciphers_out) {<br class="">+        len = c->ssl->ciphers_sz * sizeof(unsigned short);<br class="">+        c->ssl->ciphers = ngx_pnalloc(c->pool, len);<br class="">+        ngx_memcpy(c->ssl->ciphers, ciphers_out, len);<br class="">+    }<br class="">+<br class="">+    /* Elliptic curve points */<br class="">+    c->ssl->curves_sz = SSL_get1_curves(s, NULL);<br class="">+    if (c->ssl->curves_sz) {<br class="">+        curves_out = OPENSSL_malloc(c->ssl->curves_sz * sizeof(int));<br class="">+        if (curves_out != NULL) {<br class="">+            SSL_get1_curves(s, curves_out);<br class="">+            len = c->ssl->curves_sz * sizeof(unsigned short);<br class="">+            c->ssl->curves = ngx_pnalloc(c->pool, len);<br class="">+            if (c->ssl->curves != NULL) {<br class="">+                for (size_t i = 0; i < c->ssl->curves_sz; i++) {<br class="">+                     c->ssl->curves[i] = curves_out[i];<br class="">+                }<br class="">+            }<br class="">+            OPENSSL_free(curves_out);<br class="">+        }<br class="">+    }<br class="">+<br class="">+    /* Elliptic curve point formats */<br class="">+    c->ssl->point_formats_sz = SSL_get0_ec_point_formats(s,<br class="">+                                        &point_formats_out);<br class="">+    if (c->ssl->point_formats_sz && point_formats_out != NULL) {<br class="">+        len = c->ssl->point_formats_sz * sizeof(unsigned char);<br class="">+        c->ssl->point_formats = ngx_pnalloc(c->pool, len);<br class="">+        if (c->ssl->point_formats != NULL) {<br class="">+            ngx_memcpy(c->ssl->point_formats, point_formats_out, len);<br class="">+        }<br class="">+    }<br class="">+}<br class="">+<br class="">+int<br class="">+ngx_SSL_early_cb_fn(SSL *s, int *al, void *arg)<br class="">+{<br class="">+    int                            got_extensions;<br class="">+    int                           *ext_out;<br class="">+    size_t                         ext_len;<br class="">+    ngx_connection_t              *c;<br class="">+<br class="">+    c = arg;<br class="">+<br class="">+    if (c == NULL) {<br class="">+        return 1;<br class="">+    }<br class="">+<br class="">+    if (c->ssl == NULL) {<br class="">+        return 1;<br class="">+    }<br class="">+<br class="">+    c->ssl->extensions_size = 0;<br class="">+    c->ssl->extensions = NULL;<br class="">+    got_extensions = SSL_client_hello_get1_extensions_present(s,<br class="">+                                                       &ext_out,<br class="">+                                                       &ext_len);<br class="">+    if (got_extensions) {<br class="">+        if (ext_out && ext_len) {<br class="">+            c->ssl->extensions =<br class="">+                ngx_palloc(c->pool, sizeof(int) * ext_len);<br class="">+            if (c->ssl->extensions != NULL) {<br class="">+                c->ssl->extensions_size = ext_len;<br class="">+                ngx_memcpy(c->ssl->extensions, ext_out, sizeof(int) * ext_len);<br class="">+                OPENSSL_free(ext_out);<br class="">+            }<br class="">+        }<br class="">+    }<br class="">+<br class="">+    return 1;<br class="">+}<br class="">+#endif<br class=""><br class="">ngx_int_t<br class="">ngx_ssl_handshake(ngx_connection_t *c)<br class="">@@ -1603,6 +1697,10 @@<br class=""><br class="">    ngx_ssl_clear_error(c->log);<br class=""><br class="">+#if OPENSSL_VERSION_NUMBER >= 0x10101000L<br class="">+    SSL_CTX_set_client_hello_cb(c->ssl->session_ctx, ngx_SSL_early_cb_fn, c);<br class="">+#endif<br class="">+<br class="">    n = SSL_do_handshake(c->ssl->connection);<br class=""><br class="">    ngx_log_debug1(NGX_LOG_DEBUG_EVENT, c->log, 0, "SSL_do_handshake: %d", n);<br class="">@@ -1623,6 +1721,10 @@<br class=""><br class="">        c->ssl->handshaked = 1;<br class=""><br class="">+#if OPENSSL_VERSION_NUMBER >= 0x10101000L<br class="">+        ngx_SSL_client_features(c);<br class="">+#endif<br class="">+<br class="">        c->recv = ngx_ssl_recv;<br class="">        c->send = ngx_ssl_write;<br class="">        c->recv_chain = ngx_ssl_recv_chain;<br class="">@@ -5044,6 +5146,86 @@<br class="">    return NGX_OK;<br class="">}<br class=""><br class="">+#if OPENSSL_VERSION_NUMBER >= 0x10101000L<br class="">+<br class="">+ngx_int_t<br class="">+ngx_ssl_get_extensions(ngx_connection_t *c, ngx_pool_t *pool, ngx_str_t *s)<br class="">+{<br class="">+    size_t   len;<br class="">+    u_char  *p;<br class="">+<br class="">+    len = 0;<br class="">+    s->len = 0;<br class="">+<br class="">+    if (c->ssl->extensions_size && c->ssl->extensions) {<br class="">+        for (int n = c->ssl->extensions[0]; n > 9; n /= 10) {<br class="">+            len += 1;<br class="">+        }<br class="">+        len += 1;<br class="">+        for (size_t i = 1; i < c->ssl->extensions_size; ++i) {<br class="">+            len += 1; /* for the '-' separator */<br class="">+            for (int n = c->ssl->extensions[i]; n > 9; n /= 10) {<br class="">+                len += 1;<br class="">+            }<br class="">+            len += 1;<br class="">+        }<br class="">+<br class="">+        s->data = ngx_pnalloc(pool, len+1);<br class="">+        if (s->data == NULL) {<br class="">+            return NGX_ERROR;<br class="">+        }<br class="">+        s->len = len;<br class="">+<br class="">+        p = ngx_sprintf(s->data, "%d", c->ssl->extensions[0]);<br class="">+        for (size_t i = 1; i < c->ssl->extensions_size; ++i) {<br class="">+            p = ngx_sprintf(p, "-%d", c->ssl->extensions[i]);<br class="">+        }<br class="">+<br class="">+    }<br class="">+    return NGX_OK;<br class="">+}<br class="">+<br class="">+<br class="">+ngx_int_t<br class="">+ngx_ssl_get_ec_point_formats(ngx_connection_t *c, ngx_pool_t *pool,<br class="">+    ngx_str_t *s)<br class="">+{<br class="">+    size_t   len;<br class="">+    u_char  *p;<br class="">+<br class="">+    len = 0;<br class="">+    s->len = 0;<br class="">+<br class="">+    if (c->ssl->point_formats_sz && c->ssl->point_formats) {<br class="">+        for (unsigned char n = c->ssl->point_formats[0]; n > 9; n /= 10) {<br class="">+            len += 1;<br class="">+        }<br class="">+        len += 1;<br class="">+        for (size_t i = 1; i < c->ssl->point_formats_sz; ++i) {<br class="">+            len += 1; /* for the '-' separator */<br class="">+            for (unsigned char n = c->ssl->point_formats[i]; n > 9; n /= 10) {<br class="">+                len += 1;<br class="">+            }<br class="">+            len += 1;<br class="">+        }<br class="">+<br class="">+        s->data = ngx_pnalloc(pool, len+1);<br class="">+        if (s->data == NULL) {<br class="">+            return NGX_ERROR;<br class="">+        }<br class="">+        s->len = len;<br class="">+<br class="">+        p = ngx_sprintf(s->data, "%d", c->ssl->point_formats[0]);<br class="">+        for (size_t i = 1; i < c->ssl->point_formats_sz; ++i) {<br class="">+            p = ngx_sprintf(p, "-%d", c->ssl->point_formats[i]);<br class="">+        }<br class="">+    }<br class="">+<br class="">+    return NGX_OK;<br class="">+}<br class="">+<br class="">+#endif<br class="">+<br class=""><br class="">static time_t<br class="">ngx_ssl_parse_time(<br class="">diff -r 716eddd74bc2 -r 86d2f46807f5 src/event/ngx_event_openssl.h<br class="">--- a/src/event/ngx_event_openssl.h Thu Apr 23 15:10:26 2020 +0300<br class="">+++ b/src/event/ngx_event_openssl.h Thu Apr 23 20:30:36 2020 -0500<br class="">@@ -99,6 +99,21 @@<br class="">    unsigned                    in_early:1;<br class="">    unsigned                    early_preread:1;<br class="">    unsigned                    write_blocked:1;<br class="">+<br class="">+#if OPENSSL_VERSION_NUMBER >= 0x10101000L<br class="">+<br class="">+    size_t                      ciphers_sz;<br class="">+    unsigned short             *ciphers;<br class="">+<br class="">+    size_t                      extensions_size;<br class="">+    int                        *extensions;<br class="">+<br class="">+    size_t                      curves_sz;<br class="">+    unsigned short             *curves;<br class="">+<br class="">+    size_t                      point_formats_sz;<br class="">+    unsigned char              *point_formats;<br class="">+#endif<br class="">};<br class=""><br class=""><br class="">@@ -263,6 +278,14 @@<br class="">ngx_int_t ngx_ssl_get_client_v_remain(ngx_connection_t *c, ngx_pool_t *pool,<br class="">    ngx_str_t *s);<br class=""><br class="">+#if OPENSSL_VERSION_NUMBER >= 0x10101000L<br class="">+<br class="">+ngx_int_t ngx_ssl_get_extensions(ngx_connection_t *c, ngx_pool_t *pool,<br class="">+    ngx_str_t *s);<br class="">+ngx_int_t ngx_ssl_get_ec_point_formats(ngx_connection_t *c, ngx_pool_t *pool,<br class="">+    ngx_str_t *s);<br class="">+<br class="">+#endif<br class=""><br class="">ngx_int_t ngx_ssl_handshake(ngx_connection_t *c);<br class="">ssize_t ngx_ssl_recv(ngx_connection_t *c, u_char *buf, size_t size);<br class="">diff -r 716eddd74bc2 -r 86d2f46807f5 src/http/modules/ngx_http_ssl_module.c<br class="">--- a/src/http/modules/ngx_http_ssl_module.c Thu Apr 23 15:10:26 2020 +0300<br class="">+++ b/src/http/modules/ngx_http_ssl_module.c Thu Apr 23 20:30:36 2020 -0500<br class="">@@ -352,6 +352,17 @@<br class="">    { ngx_string("ssl_client_v_remain"), NULL, ngx_http_ssl_variable,<br class="">      (uintptr_t) ngx_ssl_get_client_v_remain, NGX_HTTP_VAR_CHANGEABLE, 0 },<br class=""><br class="">+#if OPENSSL_VERSION_NUMBER >= 0x10101000L<br class="">+<br class="">+    { ngx_string("ssl_extensions"), NULL, ngx_http_ssl_variable,<br class="">+      (uintptr_t) ngx_ssl_get_extensions, NGX_HTTP_VAR_CHANGEABLE, 0 },<br class="">+<br class="">+    { ngx_string("ssl_elliptic_curve_point_formats"), NULL,<br class="">+      ngx_http_ssl_variable, (uintptr_t) ngx_ssl_get_ec_point_formats,<br class="">+      NGX_HTTP_VAR_CHANGEABLE, 0 },<br class="">+<br class="">+#endif<br class="">+<br class="">      ngx_http_null_variable<br class="">};<br class="">_______________________________________________<br class="">nginx-devel mailing list<br class="">nginx-devel@nginx.org<br class="">http://mailman.nginx.org/mailman/listinfo/nginx-devel<br class=""><br class=""><br class=""></blockquote></div></div></blockquote></div><br class=""></body></html>