[PATCH] Expose additional SSL variables

Paulo Pacheco fooinha at gmail.com
Fri Apr 24 16:17:28 UTC 2020


Hello, this looks very similar with what I've done here.

https://github.com/fooinha/nginx-ssl-ja3/blob/master/patches/nginx.1.17.1.ssl.extensions.patch <https://github.com/fooinha/nginx-ssl-ja3/blob/master/patches/nginx.1.17.1.ssl.extensions.patch>

Is this the same code?


Thanx.






> On 24 Apr 2020, at 16:17, Garret Reece <garret at trailofbits.com> wrote:
> 
> # HG changeset patch
> # User Garret Reece <garret at trailofbits.com>
> # Date 1587691836 18000
> #      Thu Apr 23 20:30:36 2020 -0500
> # Node ID 86d2f46807f597249fa59072b920a389f8c082ee
> # Parent  716eddd74bc2831537f5b3f7ecd16ad3e516d043
> Expose additional SSL variables.
> 
> Expose the ssl extensions and elliptic curve point formats provided by client.
> This enables ja3 fingerprinting of TLS connections.
> 
> diff -r 716eddd74bc2 -r 86d2f46807f5 src/event/ngx_event_openssl.c
> --- a/src/event/ngx_event_openssl.c Thu Apr 23 15:10:26 2020 +0300
> +++ b/src/event/ngx_event_openssl.c Thu Apr 23 20:30:36 2020 -0500
> @@ -1588,6 +1588,100 @@
>     return NGX_OK;
> }
> 
> +#if OPENSSL_VERSION_NUMBER >= 0x10101000L
> +
> +void
> +ngx_SSL_client_features(ngx_connection_t *c)
> +{
> +    unsigned short                *ciphers_out = NULL;
> +    int                           *curves_out = NULL;
> +    int                           *point_formats_out = NULL;
> +    size_t                         len = 0;
> +    SSL                           *s = NULL;
> +
> +    if (c == NULL) {
> +        return;
> +    }
> +    s = c->ssl->connection;
> +
> +    /* Cipher suites */
> +    c->ssl->ciphers = NULL;
> +    c->ssl->ciphers_sz = SSL_get0_raw_cipherlist(s, &ciphers_out);
> +    c->ssl->ciphers_sz /= 2;
> +
> +    if (c->ssl->ciphers_sz && ciphers_out) {
> +        len = c->ssl->ciphers_sz * sizeof(unsigned short);
> +        c->ssl->ciphers = ngx_pnalloc(c->pool, len);
> +        ngx_memcpy(c->ssl->ciphers, ciphers_out, len);
> +    }
> +
> +    /* Elliptic curve points */
> +    c->ssl->curves_sz = SSL_get1_curves(s, NULL);
> +    if (c->ssl->curves_sz) {
> +        curves_out = OPENSSL_malloc(c->ssl->curves_sz * sizeof(int));
> +        if (curves_out != NULL) {
> +            SSL_get1_curves(s, curves_out);
> +            len = c->ssl->curves_sz * sizeof(unsigned short);
> +            c->ssl->curves = ngx_pnalloc(c->pool, len);
> +            if (c->ssl->curves != NULL) {
> +                for (size_t i = 0; i < c->ssl->curves_sz; i++) {
> +                     c->ssl->curves[i] = curves_out[i];
> +                }
> +            }
> +            OPENSSL_free(curves_out);
> +        }
> +    }
> +
> +    /* Elliptic curve point formats */
> +    c->ssl->point_formats_sz = SSL_get0_ec_point_formats(s,
> +                                        &point_formats_out);
> +    if (c->ssl->point_formats_sz && point_formats_out != NULL) {
> +        len = c->ssl->point_formats_sz * sizeof(unsigned char);
> +        c->ssl->point_formats = ngx_pnalloc(c->pool, len);
> +        if (c->ssl->point_formats != NULL) {
> +            ngx_memcpy(c->ssl->point_formats, point_formats_out, len);
> +        }
> +    }
> +}
> +
> +int
> +ngx_SSL_early_cb_fn(SSL *s, int *al, void *arg)
> +{
> +    int                            got_extensions;
> +    int                           *ext_out;
> +    size_t                         ext_len;
> +    ngx_connection_t              *c;
> +
> +    c = arg;
> +
> +    if (c == NULL) {
> +        return 1;
> +    }
> +
> +    if (c->ssl == NULL) {
> +        return 1;
> +    }
> +
> +    c->ssl->extensions_size = 0;
> +    c->ssl->extensions = NULL;
> +    got_extensions = SSL_client_hello_get1_extensions_present(s,
> +                                                       &ext_out,
> +                                                       &ext_len);
> +    if (got_extensions) {
> +        if (ext_out && ext_len) {
> +            c->ssl->extensions =
> +                ngx_palloc(c->pool, sizeof(int) * ext_len);
> +            if (c->ssl->extensions != NULL) {
> +                c->ssl->extensions_size = ext_len;
> +                ngx_memcpy(c->ssl->extensions, ext_out, sizeof(int) * ext_len);
> +                OPENSSL_free(ext_out);
> +            }
> +        }
> +    }
> +
> +    return 1;
> +}
> +#endif
> 
> ngx_int_t
> ngx_ssl_handshake(ngx_connection_t *c)
> @@ -1603,6 +1697,10 @@
> 
>     ngx_ssl_clear_error(c->log);
> 
> +#if OPENSSL_VERSION_NUMBER >= 0x10101000L
> +    SSL_CTX_set_client_hello_cb(c->ssl->session_ctx, ngx_SSL_early_cb_fn, c);
> +#endif
> +
>     n = SSL_do_handshake(c->ssl->connection);
> 
>     ngx_log_debug1(NGX_LOG_DEBUG_EVENT, c->log, 0, "SSL_do_handshake: %d", n);
> @@ -1623,6 +1721,10 @@
> 
>         c->ssl->handshaked = 1;
> 
> +#if OPENSSL_VERSION_NUMBER >= 0x10101000L
> +        ngx_SSL_client_features(c);
> +#endif
> +
>         c->recv = ngx_ssl_recv;
>         c->send = ngx_ssl_write;
>         c->recv_chain = ngx_ssl_recv_chain;
> @@ -5044,6 +5146,86 @@
>     return NGX_OK;
> }
> 
> +#if OPENSSL_VERSION_NUMBER >= 0x10101000L
> +
> +ngx_int_t
> +ngx_ssl_get_extensions(ngx_connection_t *c, ngx_pool_t *pool, ngx_str_t *s)
> +{
> +    size_t   len;
> +    u_char  *p;
> +
> +    len = 0;
> +    s->len = 0;
> +
> +    if (c->ssl->extensions_size && c->ssl->extensions) {
> +        for (int n = c->ssl->extensions[0]; n > 9; n /= 10) {
> +            len += 1;
> +        }
> +        len += 1;
> +        for (size_t i = 1; i < c->ssl->extensions_size; ++i) {
> +            len += 1; /* for the '-' separator */
> +            for (int n = c->ssl->extensions[i]; n > 9; n /= 10) {
> +                len += 1;
> +            }
> +            len += 1;
> +        }
> +
> +        s->data = ngx_pnalloc(pool, len+1);
> +        if (s->data == NULL) {
> +            return NGX_ERROR;
> +        }
> +        s->len = len;
> +
> +        p = ngx_sprintf(s->data, "%d", c->ssl->extensions[0]);
> +        for (size_t i = 1; i < c->ssl->extensions_size; ++i) {
> +            p = ngx_sprintf(p, "-%d", c->ssl->extensions[i]);
> +        }
> +
> +    }
> +    return NGX_OK;
> +}
> +
> +
> +ngx_int_t
> +ngx_ssl_get_ec_point_formats(ngx_connection_t *c, ngx_pool_t *pool,
> +    ngx_str_t *s)
> +{
> +    size_t   len;
> +    u_char  *p;
> +
> +    len = 0;
> +    s->len = 0;
> +
> +    if (c->ssl->point_formats_sz && c->ssl->point_formats) {
> +        for (unsigned char n = c->ssl->point_formats[0]; n > 9; n /= 10) {
> +            len += 1;
> +        }
> +        len += 1;
> +        for (size_t i = 1; i < c->ssl->point_formats_sz; ++i) {
> +            len += 1; /* for the '-' separator */
> +            for (unsigned char n = c->ssl->point_formats[i]; n > 9; n /= 10) {
> +                len += 1;
> +            }
> +            len += 1;
> +        }
> +
> +        s->data = ngx_pnalloc(pool, len+1);
> +        if (s->data == NULL) {
> +            return NGX_ERROR;
> +        }
> +        s->len = len;
> +
> +        p = ngx_sprintf(s->data, "%d", c->ssl->point_formats[0]);
> +        for (size_t i = 1; i < c->ssl->point_formats_sz; ++i) {
> +            p = ngx_sprintf(p, "-%d", c->ssl->point_formats[i]);
> +        }
> +    }
> +
> +    return NGX_OK;
> +}
> +
> +#endif
> +
> 
> static time_t
> ngx_ssl_parse_time(
> diff -r 716eddd74bc2 -r 86d2f46807f5 src/event/ngx_event_openssl.h
> --- a/src/event/ngx_event_openssl.h Thu Apr 23 15:10:26 2020 +0300
> +++ b/src/event/ngx_event_openssl.h Thu Apr 23 20:30:36 2020 -0500
> @@ -99,6 +99,21 @@
>     unsigned                    in_early:1;
>     unsigned                    early_preread:1;
>     unsigned                    write_blocked:1;
> +
> +#if OPENSSL_VERSION_NUMBER >= 0x10101000L
> +
> +    size_t                      ciphers_sz;
> +    unsigned short             *ciphers;
> +
> +    size_t                      extensions_size;
> +    int                        *extensions;
> +
> +    size_t                      curves_sz;
> +    unsigned short             *curves;
> +
> +    size_t                      point_formats_sz;
> +    unsigned char              *point_formats;
> +#endif
> };
> 
> 
> @@ -263,6 +278,14 @@
> ngx_int_t ngx_ssl_get_client_v_remain(ngx_connection_t *c, ngx_pool_t *pool,
>     ngx_str_t *s);
> 
> +#if OPENSSL_VERSION_NUMBER >= 0x10101000L
> +
> +ngx_int_t ngx_ssl_get_extensions(ngx_connection_t *c, ngx_pool_t *pool,
> +    ngx_str_t *s);
> +ngx_int_t ngx_ssl_get_ec_point_formats(ngx_connection_t *c, ngx_pool_t *pool,
> +    ngx_str_t *s);
> +
> +#endif
> 
> ngx_int_t ngx_ssl_handshake(ngx_connection_t *c);
> ssize_t ngx_ssl_recv(ngx_connection_t *c, u_char *buf, size_t size);
> diff -r 716eddd74bc2 -r 86d2f46807f5 src/http/modules/ngx_http_ssl_module.c
> --- a/src/http/modules/ngx_http_ssl_module.c Thu Apr 23 15:10:26 2020 +0300
> +++ b/src/http/modules/ngx_http_ssl_module.c Thu Apr 23 20:30:36 2020 -0500
> @@ -352,6 +352,17 @@
>     { ngx_string("ssl_client_v_remain"), NULL, ngx_http_ssl_variable,
>       (uintptr_t) ngx_ssl_get_client_v_remain, NGX_HTTP_VAR_CHANGEABLE, 0 },
> 
> +#if OPENSSL_VERSION_NUMBER >= 0x10101000L
> +
> +    { ngx_string("ssl_extensions"), NULL, ngx_http_ssl_variable,
> +      (uintptr_t) ngx_ssl_get_extensions, NGX_HTTP_VAR_CHANGEABLE, 0 },
> +
> +    { ngx_string("ssl_elliptic_curve_point_formats"), NULL,
> +      ngx_http_ssl_variable, (uintptr_t) ngx_ssl_get_ec_point_formats,
> +      NGX_HTTP_VAR_CHANGEABLE, 0 },
> +
> +#endif
> +
>       ngx_http_null_variable
> };
> _______________________________________________
> nginx-devel mailing list
> nginx-devel at nginx.org
> http://mailman.nginx.org/mailman/listinfo/nginx-devel

-------------- next part --------------
An HTML attachment was scrubbed...
URL: <http://mailman.nginx.org/pipermail/nginx-devel/attachments/20200424/84f0eafd/attachment-0001.htm>


More information about the nginx-devel mailing list