[PATCH] Expose additional SSL variables
Paulo Pacheco
fooinha at gmail.com
Fri Apr 24 16:32:08 UTC 2020
The very first try to submit the early development of this patch here, got this response:
http://mailman.nginx.org/pipermail/nginx-devel/2017-August/010426.html <http://mailman.nginx.org/pipermail/nginx-devel/2017-August/010426.html>
Thanx
> On 24 Apr 2020, at 17:25, Garret Reece <garret at trailofbits.com> wrote:
>
> More or less, yes--we had a request from a customer to take just the
> extensions and the elliptic curve format points data from your patch
> and make them available in the main package
>
> On Fri, Apr 24, 2020 at 11:17 AM Paulo Pacheco <fooinha at gmail.com> wrote:
>>
>> 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
>>
>> 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/4f487f64/attachment-0001.htm>
More information about the nginx-devel
mailing list