freenginx-1.27.6 changes draft
Hello! Below are CHANGES draft for the upcoming freenginx release, 1.27.6. Review and comments are welcome. Changes with freenginx 1.27.615 Apr 2025 *) Workaround: the X25519MLKEM768 group name was not shown in the $ssl_curve and $ssl_curves variables when using OpenSSL 3.5. *) Bugfix: a segmentation fault might occur in a worker process if the "proxy_ssl_password_file" directive was used along with variables in the "proxy_ssl_certificate" or "proxy_ssl_certificate_key" directives; the bug had appeared in 1.23.1. Изменения в freenginx 1.27.6 15.04.2025 *) Изменение: при использовании OpenSSL 3.5 в переменных $ssl_curve и $ssl_curves не отображалось название группы X25519MLKEM768. *) Исправление: в рабочем процессе мог произойти segmentation fault, если использовалась директива proxy_ssl_password_file, а в директивах proxy_ssl_certificate или proxy_ssl_certificate_key использовались переменные; ошибка появилась в 1.23.1. -- Maxim Dounin http://mdounin.ru/
[nginx] Upstream: fixed SSL certificate password prompt in compl...
details: http://freenginx.org/hg/nginx/rev/1fc37359eb2b branches: changeset: 9344:1fc37359eb2b user: Maxim Dounin date: Tue Apr 15 02:20:14 2025 +0300 description: Upstream: fixed SSL certificate password prompt in complex configs. Variables support in certificates introduced in 7833:3ab8e1e2f0f7 (1.21.0) inadvertently broke password prompt for static SSL certificates, such as in the following configuration: location / { proxy_ssl_certificate $foo.crt; proxy_ssl_certificate_key $foo.key; proxy_pass https://u; location /static/ { proxy_ssl_certificate static.crt; proxy_ssl_certificate_key static.key; proxy_pass https://u; } } Fix is to restore the conf->ssl_passwords field as previously used for initial password reading and configuration inheritance, and only use the conf->upstream.ssl_passwords field for passwords preserved for run time usage. diffstat: src/http/modules/ngx_http_grpc_module.c | 23 --- src/http/modules/ngx_http_proxy_module.c | 23 --- src/http/modules/ngx_http_uwsgi_module.c | 23 --- 3 files changed, 36 insertions(+), 33 deletions(-) diffs (261 lines): diff --git a/src/http/modules/ngx_http_grpc_module.c b/src/http/modules/ngx_http_grpc_module.c --- a/src/http/modules/ngx_http_grpc_module.c +++ b/src/http/modules/ngx_http_grpc_module.c @@ -37,6 +37,7 @@ typedef struct { ngx_uint_t ssl_verify_depth; ngx_str_t ssl_trusted_certificate; ngx_str_t ssl_crl; +ngx_array_t *ssl_passwords; ngx_array_t *ssl_conf_commands; #endif } ngx_http_grpc_loc_conf_t; @@ -4383,7 +4384,7 @@ ngx_http_grpc_create_loc_conf(ngx_conf_t conf->ssl_verify_depth = NGX_CONF_UNSET_UINT; conf->upstream.ssl_certificate = NGX_CONF_UNSET_PTR; conf->upstream.ssl_certificate_key = NGX_CONF_UNSET_PTR; -conf->upstream.ssl_passwords = NGX_CONF_UNSET_PTR; +conf->ssl_passwords = NGX_CONF_UNSET_PTR; conf->ssl_conf_commands = NGX_CONF_UNSET_PTR; #endif @@ -4496,8 +4497,8 @@ ngx_http_grpc_merge_loc_conf(ngx_conf_t prev->upstream.ssl_certificate, NULL); ngx_conf_merge_ptr_value(conf->upstream.ssl_certificate_key, prev->upstream.ssl_certificate_key, NULL); -ngx_conf_merge_ptr_value(conf->upstream.ssl_passwords, - prev->upstream.ssl_passwords, NULL); +ngx_conf_merge_ptr_value(conf->ssl_passwords, + prev->ssl_passwords, NULL); ngx_conf_merge_ptr_value(conf->ssl_conf_commands, prev->ssl_conf_commands, NULL); @@ -4853,15 +4854,15 @@ ngx_http_grpc_ssl_password_file(ngx_conf ngx_str_t *value; -if (glcf->upstream.ssl_passwords != NGX_CONF_UNSET_PTR) { +if (glcf->ssl_passwords != NGX_CONF_UNSET_PTR) { return "is duplicate"; } value = cf->args->elts; -glcf->upstream.ssl_passwords = ngx_ssl_read_password_file(cf, &value[1]); - -if (glcf->upstream.ssl_passwords == NULL) { +glcf->ssl_passwords = ngx_ssl_read_password_file(cf, &value[1]); + +if (glcf->ssl_passwords == NULL) { return NGX_CONF_ERROR; } @@ -4890,7 +4891,7 @@ ngx_http_grpc_merge_ssl(ngx_conf_t *cf, && conf->ssl_ciphers.data == NULL && conf->upstream.ssl_certificate == NGX_CONF_UNSET_PTR && conf->upstream.ssl_certificate_key == NGX_CONF_UNSET_PTR -&& conf->upstream.ssl_passwords == NGX_CONF_UNSET_PTR +&& conf->ssl_passwords == NGX_CONF_UNSET_PTR && conf->upstream.ssl_verify == NGX_CONF_UNSET && conf->ssl_verify_depth == NGX_CONF_UNSET_UINT && conf->ssl_trusted_certificate.data == NULL @@ -4942,7 +4943,7 @@ ngx_http_grpc_set_ssl(ngx_conf_t *cf, ng || glcf->upstream.ssl_certificate_key->lengths)) { glcf->upstream.ssl_passwords = - ngx_ssl_preserve_passwords(cf, glcf->upstream.ssl_passwords); + ngx_ssl_preserve_passwords(cf, glcf->ssl_passwords); if (glcf->upstream.ssl_passwords == NULL) { return NGX_ERROR; } @@ -4987,7 +4988,7 @@ ngx_http_grpc_set_ssl(ngx_conf_t *cf, ng || glcf->upstream.ssl_certificate_key->lengths) { glcf->upstream.ssl_passwords = - ngx_ssl_preserve_passwords(cf, glcf->upstream.ssl_passwords); + ngx_ssl_preserve_passwords(cf, glcf->ssl_passwords); if (glcf->upstream.ssl_passwords == NULL) { return NGX_ERROR; } @@ -4996,7 +4997,7 @@ ngx_http_grpc_set_ssl(ngx_conf_t *cf, ng if (ngx_ssl_certificate(cf, glcf->upstream.ssl, &glcf->upstream.ssl_certificate->value,
[nginx] Version bump.
details: http://freenginx.org/hg/nginx/rev/aeaee7ffdb78 branches: changeset: 9342:aeaee7ffdb78 user: Maxim Dounin date: Tue Apr 15 02:19:07 2025 +0300 description: Version bump. diffstat: src/core/nginx.h | 4 ++-- 1 files changed, 2 insertions(+), 2 deletions(-) diffs (14 lines): diff --git a/src/core/nginx.h b/src/core/nginx.h --- a/src/core/nginx.h +++ b/src/core/nginx.h @@ -9,8 +9,8 @@ #define _NGINX_H_INCLUDED_ -#define nginx_version 1027005 -#define NGINX_VERSION "1.27.5" +#define nginx_version 1027006 +#define NGINX_VERSION "1.27.6" #define NGINX_NAME "freenginx" #define NGINX_VER NGINX_NAME "/" NGINX_VERSION
[nginx] Upstream: fixed passwords usage for certificates with va...
details: http://freenginx.org/hg/nginx/rev/4f20c52c5f1b branches: changeset: 9343:4f20c52c5f1b user: Maxim Dounin date: Tue Apr 15 02:20:08 2025 +0300 description: Upstream: fixed passwords usage for certificates with variables. SSL certificate passwords are stored separately from the SSL context created for SSL proxying, yet modified when the context is created if certificates with variables are used (to ensure passwords will be available at run time). Optimizations introduced in 8053:9d98d524bd02 (1.23.1) did not take this into account, and might end up using at run time passwords which weren't preserved to be usable at run time, such as in the following configuration: server { proxy_ssl_certificate $crt; proxy_ssl_certificate_key $key; proxy_ssl_password_file foo; location /1/ { proxy_pass https://u; } location /2/ { proxy_pass https://u; } } Fix is to preserve passwords if needed when using an inherited SSL context. diffstat: src/http/modules/ngx_http_grpc_module.c | 13 + src/http/modules/ngx_http_proxy_module.c | 13 + src/http/modules/ngx_http_uwsgi_module.c | 13 + 3 files changed, 39 insertions(+), 0 deletions(-) diffs (69 lines): diff --git a/src/http/modules/ngx_http_grpc_module.c b/src/http/modules/ngx_http_grpc_module.c --- a/src/http/modules/ngx_http_grpc_module.c +++ b/src/http/modules/ngx_http_grpc_module.c @@ -4935,6 +4935,19 @@ ngx_http_grpc_set_ssl(ngx_conf_t *cf, ng ngx_pool_cleanup_t *cln; if (glcf->upstream.ssl->ctx) { + +if (glcf->upstream.ssl_certificate +&& glcf->upstream.ssl_certificate->value.len +&& (glcf->upstream.ssl_certificate->lengths +|| glcf->upstream.ssl_certificate_key->lengths)) +{ +glcf->upstream.ssl_passwords = + ngx_ssl_preserve_passwords(cf, glcf->upstream.ssl_passwords); +if (glcf->upstream.ssl_passwords == NULL) { +return NGX_ERROR; +} +} + return NGX_OK; } diff --git a/src/http/modules/ngx_http_proxy_module.c b/src/http/modules/ngx_http_proxy_module.c --- a/src/http/modules/ngx_http_proxy_module.c +++ b/src/http/modules/ngx_http_proxy_module.c @@ -4987,6 +4987,19 @@ ngx_http_proxy_set_ssl(ngx_conf_t *cf, n ngx_pool_cleanup_t *cln; if (plcf->upstream.ssl->ctx) { + +if (plcf->upstream.ssl_certificate +&& plcf->upstream.ssl_certificate->value.len +&& (plcf->upstream.ssl_certificate->lengths +|| plcf->upstream.ssl_certificate_key->lengths)) +{ +plcf->upstream.ssl_passwords = + ngx_ssl_preserve_passwords(cf, plcf->upstream.ssl_passwords); +if (plcf->upstream.ssl_passwords == NULL) { +return NGX_ERROR; +} +} + return NGX_OK; } diff --git a/src/http/modules/ngx_http_uwsgi_module.c b/src/http/modules/ngx_http_uwsgi_module.c --- a/src/http/modules/ngx_http_uwsgi_module.c +++ b/src/http/modules/ngx_http_uwsgi_module.c @@ -2519,6 +2519,19 @@ ngx_http_uwsgi_set_ssl(ngx_conf_t *cf, n ngx_pool_cleanup_t *cln; if (uwcf->upstream.ssl->ctx) { + +if (uwcf->upstream.ssl_certificate +&& uwcf->upstream.ssl_certificate->value.len +&& (uwcf->upstream.ssl_certificate->lengths +|| uwcf->upstream.ssl_certificate_key->lengths)) +{ +uwcf->upstream.ssl_passwords = + ngx_ssl_preserve_passwords(cf, uwcf->upstream.ssl_passwords); +if (uwcf->upstream.ssl_passwords == NULL) { +return NGX_ERROR; +} +} + return NGX_OK; }
[nginx-tests] Tests: tests for proxy_ssl_password_file issue.
details: http://freenginx.org/hg/nginx-tests/rev/0a913a10945b branches: changeset: 2007:0a913a10945b user: Maxim Dounin date: Sun Apr 13 05:13:42 2025 +0300 description: Tests: tests for proxy_ssl_password_file issue. diffstat: proxy_ssl_certificate_vars.t | 27 ++- 1 files changed, 26 insertions(+), 1 deletions(-) diffs (49 lines): diff --git a/proxy_ssl_certificate_vars.t b/proxy_ssl_certificate_vars.t --- a/proxy_ssl_certificate_vars.t +++ b/proxy_ssl_certificate_vars.t @@ -61,6 +61,20 @@ http { proxy_ssl_certificate $arg_cert; proxy_ssl_certificate_key $arg_cert; } + +location /complex/ { +proxy_ssl_certificate $arg_cert.example.com.crt; +proxy_ssl_certificate_key $arg_cert.example.com.key; +proxy_ssl_password_file password; + +location /complex/1 { +proxy_pass https://127.0.0.1:8082/; +} + +location /complex/2 { +proxy_pass https://127.0.0.1:8082/; +} +} } server { @@ -133,7 +147,7 @@ sleep 1 if $^O eq 'MSWin32'; $t->write_file('password', '3.example.com'); $t->write_file('index.html', ''); -$t->run()->plan(4); +$t->run()->plan(6); ### @@ -146,4 +160,15 @@ like(http_get('/encrypted?cert=3'), like(http_get('/none'), qr/X-Verify: NONE/ms, 'variable - no certificate'); +like(http_get('/complex/1?cert=3'), + qr/X-Verify: SUCCESS/ms, 'variable - inherited encrypted key 1st'); + +SKIP: { +skip 'leaves coredump', 1 unless $t->has_version('1.27.6') + or $ENV{TEST_NGINX_UNSAFE}; + +like(http_get('/complex/2?cert=3'), + qr/X-Verify: SUCCESS/ms, 'variable - inherited encrypted key 2nd'); +} + ###
[nginx] SSL: improved handling of $ssl_curve and $ssl_curves var...
details: http://freenginx.org/hg/nginx/rev/22e6a225f605 branches: changeset: 9341:22e6a225f605 user: Maxim Dounin date: Tue Apr 15 02:09:29 2025 +0300 description: SSL: improved handling of $ssl_curve and $ssl_curves variables. Now both $ssl_curve and $ssl_curves try to use SSL_group_to_name() if available and no NID is found. Notably, this makes it possible to see the name of the X25519MLKEM768 group as supported by OpenSSL 3.5.0. diffstat: src/event/ngx_event_openssl.c | 72 -- 1 files changed, 61 insertions(+), 11 deletions(-) diffs (108 lines): diff --git a/src/event/ngx_event_openssl.c b/src/event/ngx_event_openssl.c --- a/src/event/ngx_event_openssl.c +++ b/src/event/ngx_event_openssl.c @@ -5270,6 +5270,26 @@ ngx_ssl_get_curve(ngx_connection_t *c, n return NGX_OK; } +#if OPENSSL_VERSION_NUMBER >= 0x3000L +{ +u_char *name; + +name = (u_char *) SSL_group_to_name(c->ssl->connection, nid); + +if (name) { +s->len = ngx_strlen(name); + +s->data = ngx_pnalloc(pool, s->len); +if (s->data == NULL) { +return NGX_ERROR; +} + +ngx_memcpy(s->data, name, s->len); +return NGX_OK; +} +} +#endif + s->len = sizeof("0x") - 1; s->data = ngx_pnalloc(pool, s->len); @@ -5292,10 +5312,13 @@ ngx_ssl_get_curve(ngx_connection_t *c, n ngx_int_t ngx_ssl_get_curves(ngx_connection_t *c, ngx_pool_t *pool, ngx_str_t *s) { -#ifdef SSL_CTRL_GET_CURVES +#ifdef SSL_get1_curves int *curves, n, i, nid; u_char *p; +#if OPENSSL_VERSION_NUMBER >= 0x3000L +u_char *name; +#endif size_t len; n = SSL_get1_curves(c->ssl->connection, NULL); @@ -5316,12 +5339,25 @@ ngx_ssl_get_curves(ngx_connection_t *c, for (i = 0; i < n; i++) { nid = curves[i]; -if (nid & TLSEXT_nid_unknown) { -len += sizeof("0x") - 1; - -} else { +if ((nid & TLSEXT_nid_unknown) == 0) { len += ngx_strlen(OBJ_nid2sn(nid)); -} +goto next_length; +} + +#if OPENSSL_VERSION_NUMBER >= 0x3000L + +name = (u_char *) SSL_group_to_name(c->ssl->connection, nid); + +if (name) { +len += ngx_strlen(name); +goto next_length; +} + +#endif + +len += sizeof("0x") - 1; + +next_length: len += sizeof(":") - 1; } @@ -5336,12 +5372,26 @@ ngx_ssl_get_curves(ngx_connection_t *c, for (i = 0; i < n; i++) { nid = curves[i]; -if (nid & TLSEXT_nid_unknown) { -p = ngx_sprintf(p, "0x%04xd", nid & 0x); - -} else { +if ((nid & TLSEXT_nid_unknown) == 0) { p = ngx_sprintf(p, "%s", OBJ_nid2sn(nid)); -} +goto next_value; + +} + +#if OPENSSL_VERSION_NUMBER >= 0x3000L + +name = (u_char *) SSL_group_to_name(c->ssl->connection, nid); + +if (name) { +p = ngx_sprintf(p, "%s", name); +goto next_value; +} + +#endif + +p = ngx_sprintf(p, "0x%04xd", nid & 0x); + +next_value: *p++ = ':'; }