From hongyi.zhao at gmail.com Sun May 2 14:11:50 2021 From: hongyi.zhao at gmail.com (Hongyi Zhao) Date: Sun, 2 May 2021 22:11:50 +0800 Subject: Failed to make nginx master on Ubuntu 20.04. Message-ID: On Ubuntu 20.04, I try to make git master version of nginx, but failed with the following errors: $ git log -1 commit f02e2a734ef472f0dcf83ab2e8ce96d1acead8a5 (HEAD -> master, origin/master, origin/branches/default, origin/HEAD) Author: Ruslan Ermilov Date: Thu Apr 22 16:12:52 2021 +0300 Restored zeroing of ngx_channel_t in ngx_pass_open_channel(). Due to structure's alignment, some uninitialized memory contents may have been passed between processes. Zeroing was removed in 0215ec9aaa8a. Reported by Johnny Wang. $ ./auto/configure $(./auto/configure --help | egrep -o -- '--with[^= ]+ ' | xargs) $ make make -f objs/Makefile make[1]: Entering directory '/home/werner/Public/repo/github.com/nginx/nginx.git' cc -c -pipe -O -W -Wall -Wpointer-arith -Wno-unused-parameter -Werror -g -I src/core -I src/event -I src/event/modules -I src/os/unix -I objs -I src/mail -I src/stream \ -o objs/src/misc/ngx_cpp_test_module.o \ src/misc/ngx_cpp_test_module.cpp src/misc/ngx_cpp_test_module.cpp:11:12: fatal error: ngx_http.h: No such file or directory 11 | #include | ^~~~~~~~~~~~ compilation terminated. make[1]: *** [objs/Makefile:1060: objs/src/misc/ngx_cpp_test_module.o] Error 1 make[1]: Leaving directory '/home/werner/Public/repo/github.com/nginx/nginx.git' make: *** [Makefile:10: build] Error 2 Any hints for solving this problem will be highly appreciated. Regards -- Assoc. Prof. Hongyi Zhao Theory and Simulation of Materials Hebei Vocational University of Technology and Engineering NO. 552 North Gangtie Road, Xingtai, China From mdounin at mdounin.ru Sun May 2 22:03:58 2021 From: mdounin at mdounin.ru (Maxim Dounin) Date: Mon, 3 May 2021 01:03:58 +0300 Subject: Failed to make nginx master on Ubuntu 20.04. In-Reply-To: References: Message-ID: Hello! On Sun, May 02, 2021 at 10:11:50PM +0800, Hongyi Zhao wrote: > On Ubuntu 20.04, I try to make git master version of nginx, but failed > with the following errors: [...] > $ ./auto/configure $(./auto/configure --help | egrep -o -- '--with[^= > ]+ ' | xargs) You may want to be more specific about which configure arguments you want to use. Just trying to automatically extract all possible configure arguments from the human-readable help isn't going to work. -- Maxim Dounin http://mdounin.ru/ From hongyi.zhao at gmail.com Mon May 3 06:48:05 2021 From: hongyi.zhao at gmail.com (Hongyi Zhao) Date: Mon, 3 May 2021 14:48:05 +0800 Subject: Failed to make nginx master on Ubuntu 20.04. In-Reply-To: References: Message-ID: On Mon, May 3, 2021 at 6:04 AM Maxim Dounin wrote: > > Hello! > > On Sun, May 02, 2021 at 10:11:50PM +0800, Hongyi Zhao wrote: > > > On Ubuntu 20.04, I try to make git master version of nginx, but failed > > with the following errors: > > [...] > > > $ ./auto/configure $(./auto/configure --help | egrep -o -- '--with[^= > > ]+ ' | xargs) > > You may want to be more specific about which configure arguments > you want to use. Just trying to automatically extract all > possible configure arguments from the human-readable help isn't > going to work. There are too many configuration parameters, I just want to use them as much as possible. > > -- > Maxim Dounin > http://mdounin.ru/ > _______________________________________________ > nginx-devel mailing list > nginx-devel at nginx.org > http://mailman.nginx.org/mailman/listinfo/nginx-devel -- Assoc. Prof. Hongyi Zhao Theory and Simulation of Materials Hebei Vocational University of Technology and Engineering NO. 552 North Gangtie Road, Xingtai, China From alfred at huji.fr Tue May 4 14:11:34 2021 From: alfred at huji.fr (Alfred Sawaya) Date: Tue, 4 May 2021 16:11:34 +0200 Subject: Subrequest without returning to nginx Message-ID: <2baf95f1-e2bb-0ffa-50b2-3a42fcaf3bc6@huji.fr> Hello, I am currently converting an Apache module to Nginx. This module uses subrequests and needs (for now) to execute the subrequest without unwinding the stack (ie without returning to nginx). I tried to call ngx_http_run_posted_requests by hand, but it does not work as the upstream socket needs to get polled some time. So I wonder, is there any way to do this ? Of course I know that I shouldn't do it like this, but the current module is not reentrant and poorly architectured. I will eventually refactor it but later. Thanks, From serg.brester at sebres.de Tue May 4 14:32:12 2021 From: serg.brester at sebres.de (Dipl. Ing. Sergey Brester) Date: Tue, 04 May 2021 16:32:12 +0200 Subject: Subrequest without returning to nginx In-Reply-To: <2baf95f1-e2bb-0ffa-50b2-3a42fcaf3bc6@huji.fr> References: <2baf95f1-e2bb-0ffa-50b2-3a42fcaf3bc6@huji.fr> Message-ID: <467b847ee14aa5e66d9b5a7011b5047f@sebres.de> Hi, see how the directive mirror [2] or post_action doing this. Also take a look at njs [3], how it can make a detached subrequest. Regards, Serg. 04.05.2021 16:11, Alfred Sawaya wrote: > Hello, > > I am currently converting an Apache module to Nginx. This module uses > subrequests and needs (for now) to execute the subrequest without > unwinding the stack (ie without returning to nginx). > > I tried to call ngx_http_run_posted_requests by hand, but it does not > work as the upstream socket needs to get polled some time. > > So I wonder, is there any way to do this ? > > Of course I know that I shouldn't do it like this, but the current > module is not reentrant and poorly architectured. I will eventually > refactor it but later. > > Thanks, > > _______________________________________________ > nginx-devel mailing list > nginx-devel at nginx.org > http://mailman.nginx.org/mailman/listinfo/nginx-devel [1] Links: ------ [1] http://mailman.nginx.org/mailman/listinfo/nginx-devel [2] https://nginx.org/en/docs/http/ngx_http_mirror_module.html [3] http://nginx.org/en/docs/njs/reference.html -------------- next part -------------- An HTML attachment was scrubbed... URL: From ranier.vf at gmail.com Tue May 4 14:35:08 2021 From: ranier.vf at gmail.com (Ranier Vilela) Date: Tue, 4 May 2021 11:35:08 -0300 Subject: Subrequest without returning to nginx In-Reply-To: <2baf95f1-e2bb-0ffa-50b2-3a42fcaf3bc6@huji.fr> References: <2baf95f1-e2bb-0ffa-50b2-3a42fcaf3bc6@huji.fr> Message-ID: Em ter., 4 de mai. de 2021 ?s 11:11, Alfred Sawaya escreveu: > Hello, > > > I am currently converting an Apache module to Nginx. This module uses > subrequests and needs (for now) to execute the subrequest without > unwinding the stack (ie without returning to nginx). > > I tried to call ngx_http_run_posted_requests by hand, but it does not > work as the upstream socket needs to get polled some time. > > > So I wonder, is there any way to do this ? > You can try: ngx_http_internal_redirect ngx_http_internal_redirect(r, &uri, NULL); regards, Ranier Vilela -------------- next part -------------- An HTML attachment was scrubbed... URL: From alfred at huji.fr Tue May 4 14:49:06 2021 From: alfred at huji.fr (Alfred Sawaya) Date: Tue, 4 May 2021 16:49:06 +0200 Subject: Subrequest without returning to nginx In-Reply-To: <467b847ee14aa5e66d9b5a7011b5047f@sebres.de> References: <2baf95f1-e2bb-0ffa-50b2-3a42fcaf3bc6@huji.fr> <467b847ee14aa5e66d9b5a7011b5047f@sebres.de> Message-ID: <78fdc859-8e24-65aa-dde4-9d90e79adae1@huji.fr> mirror and post_action both return to nginx to complete the subrequest. njs also does an event-driven subrequest (ie gives back a promise and set a callback), so it also returns to nginx to complete the subrequest. On 04/05/2021 16:32, Dipl. Ing. Sergey Brester wrote: > > Hi, > > see how the directive mirror > or > |post_action| doing this. > > Also take a look at njs , > how it can make a detached subrequest. > > Regards, > Serg. > > 04.05.2021 16:11, Alfred Sawaya wrote: > >> Hello, >> >> >> I am currently converting an Apache module to Nginx. This module uses >> subrequests and needs (for now) to execute the subrequest without >> unwinding the stack (ie without returning to nginx). >> >> I tried to call ngx_http_run_posted_requests by hand, but it does not >> work as the upstream socket needs to get polled some time. >> >> >> So I wonder, is there any way to do this ? >> >> >> Of course I know that I shouldn't do it like this, but the current >> module is not reentrant and poorly architectured. I will eventually >> refactor it but later. >> >> >> Thanks, >> >> >> _______________________________________________ >> 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: From mdounin at mdounin.ru Tue May 4 14:59:44 2021 From: mdounin at mdounin.ru (Maxim Dounin) Date: Tue, 4 May 2021 17:59:44 +0300 Subject: Subrequest without returning to nginx In-Reply-To: <2baf95f1-e2bb-0ffa-50b2-3a42fcaf3bc6@huji.fr> References: <2baf95f1-e2bb-0ffa-50b2-3a42fcaf3bc6@huji.fr> Message-ID: Hello! On Tue, May 04, 2021 at 04:11:34PM +0200, Alfred Sawaya wrote: > I am currently converting an Apache module to Nginx. This module uses > subrequests and needs (for now) to execute the subrequest without > unwinding the stack (ie without returning to nginx). > > I tried to call ngx_http_run_posted_requests by hand, but it does not > work as the upstream socket needs to get polled some time. > > So I wonder, is there any way to do this ? No. Since nginx is event-driven, you essentially cannot do anything without returning control back to nginx to execute the event loop. > Of course I know that I shouldn't do it like this, but the current > module is not reentrant and poorly architectured. I will eventually > refactor it but later. You may want to start with throwing away the module, and writing another one for nginx from scratch. "Converting" rarely works even for simple and well-written modules. -- Maxim Dounin http://mdounin.ru/ From alfred at huji.fr Tue May 4 14:59:46 2021 From: alfred at huji.fr (Alfred Sawaya) Date: Tue, 4 May 2021 16:59:46 +0200 Subject: Subrequest without returning to nginx In-Reply-To: References: <2baf95f1-e2bb-0ffa-50b2-3a42fcaf3bc6@huji.fr> Message-ID: ngx_http_internal_redirect ultimatly calls ngx_http_handler, which I tried by calling subrequest->write_event_handler after ngx_http_request. Actually I don't want to redirect the current request, juste do a subrequest, collects the response status, body and headers, and continue the processing of the module without returning to nginx. The usual way is : * call ngx_http_subrequest * return NGX_AGAIN (so it stops ngx_http_core_run_phases until the subrequest reactive the request) * When the subrequest is completed, it reactive the main request, which makes r->write_event_handle (ie ngx_http_core_run_phases) to be triggered * Get the subrequest from the main request, and process the response. The way I am trying to achieve is : * call ngx_http_subrequest * wait or call some functions in order to complete the subrequest * collects the response and continue the processing without returning from the function that create the subrequest. Thank you for your help On 04/05/2021 16:35, Ranier Vilela wrote: > Em ter., 4 de mai. de 2021 ?s 11:11, Alfred Sawaya > escreveu: > > Hello, > > > I am currently converting an Apache module to Nginx. This module uses > subrequests and needs (for now) to execute the subrequest without > unwinding the stack (ie without returning to nginx). > > I tried to call ngx_http_run_posted_requests by hand, but it does not > work as the upstream socket needs to get polled some time. > > > So I wonder, is there any way to do this ? > > You can try: ngx_http_internal_redirect > ngx_http_internal_redirect(r, &uri, NULL); > > regards, > Ranier Vilela > > _______________________________________________ > 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: From serg.brester at sebres.de Tue May 4 15:03:05 2021 From: serg.brester at sebres.de (Dipl. Ing. Sergey Brester) Date: Tue, 04 May 2021 17:03:05 +0200 Subject: Subrequest without returning to nginx In-Reply-To: <78fdc859-8e24-65aa-dde4-9d90e79adae1@huji.fr> References: <2baf95f1-e2bb-0ffa-50b2-3a42fcaf3bc6@huji.fr> <467b847ee14aa5e66d9b5a7011b5047f@sebres.de> <78fdc859-8e24-65aa-dde4-9d90e79adae1@huji.fr> Message-ID: <2dd4e9fed9f57b3716932bb8d6ccf8e4@sebres.de> What do you mean as "return to nginx"? Or with other words why it should not? Or how you need to guarantee that a subrequest would take place at all and will be considered on another side? As for njs and "it also returns to nginx", either I don't really understand your approach or you simply missed the word "detached" in my answer (and njs subrequest documentation). 04.05.2021 16:49, Alfred Sawaya wrote: > mirror and post_action both return to nginx to complete the subrequest. > > njs also does an event-driven subrequest (ie gives back a promise and set a callback), so it also returns to nginx to complete the subrequest. > > On 04/05/2021 16:32, Dipl. Ing. Sergey Brester wrote: > > Hi, > > see how the directive mirror [2] or post_action doing this. > > Also take a look at njs [3], how it can make a detached subrequest. > > Regards, > Serg. > > 04.05.2021 16:11, Alfred Sawaya wrote: > > Hello, > > I am currently converting an Apache module to Nginx. This module uses > subrequests and needs (for now) to execute the subrequest without > unwinding the stack (ie without returning to nginx). > > I tried to call ngx_http_run_posted_requests by hand, but it does not > work as the upstream socket needs to get polled some time. > > So I wonder, is there any way to do this ? > > Of course I know that I shouldn't do it like this, but the current > module is not reentrant and poorly architectured. I will eventually > refactor it but later. > > Thanks, > > _______________________________________________ > nginx-devel mailing list > nginx-devel at nginx.org > http://mailman.nginx.org/mailman/listinfo/nginx-devel [1] Links: ------ [1] http://mailman.nginx.org/mailman/listinfo/nginx-devel [2] https://nginx.org/en/docs/http/ngx_http_mirror_module.html [3] http://nginx.org/en/docs/njs/reference.html -------------- next part -------------- An HTML attachment was scrubbed... URL: From alfred at huji.fr Tue May 4 15:14:50 2021 From: alfred at huji.fr (Alfred Sawaya) Date: Tue, 4 May 2021 17:14:50 +0200 Subject: Subrequest without returning to nginx In-Reply-To: <2dd4e9fed9f57b3716932bb8d6ccf8e4@sebres.de> References: <2baf95f1-e2bb-0ffa-50b2-3a42fcaf3bc6@huji.fr> <467b847ee14aa5e66d9b5a7011b5047f@sebres.de> <78fdc859-8e24-65aa-dde4-9d90e79adae1@huji.fr> <2dd4e9fed9f57b3716932bb8d6ccf8e4@sebres.de> Message-ID: <265fa9c1-f279-a90a-33d3-62704b95a123@huji.fr> I read the njs source code for a detached subrequest (in ngx_http_js_ext_subrequest) and it creates the subrequest, the promise, and returns to nginx. By "returning to nginx" I mean "stepping out of the module". Returning to the phase handler. My approach is basically wrong, I am looking for a temporary (I hope) ugly workaround to execute a subrequest without returning from the function that creates the subrequest. Why I need to not return to nginx : because in the module I work on, there is contextual data that are stored on the stack. So returning to nginx means unwinding all stack frames that the module created so far. Why it should not : it should :) Thank you for you answer On 04/05/2021 17:03, Dipl. Ing. Sergey Brester wrote: > > What do you mean as "return to nginx"? Or with other words why it > should not? Or how you need to guarantee that a subrequest would take > place at all and will be considered on another side? > > As for njs and "it also returns to nginx", either I don't really > understand your approach or you simply missed the word "detached" in > my answer (and njs subrequest documentation). > > ? > > 04.05.2021 16:49, Alfred Sawaya wrote: > >> mirror and post_action both return to nginx to complete the subrequest. >> >> njs also does an event-driven subrequest (ie gives back a promise and >> set a callback), so it also returns to nginx to complete the subrequest. >> >> ? >> >> On 04/05/2021 16:32, Dipl. Ing. Sergey Brester wrote: >>> >>> Hi, >>> >>> see how the directive mirror >>> or >>> |post_action| doing this. >>> >>> Also take a look at njs >>> , how it can make a >>> detached subrequest. >>> >>> Regards, >>> Serg. >>> >>> 04.05.2021 16:11, Alfred Sawaya wrote: >>> >>> Hello, >>> >>> >>> I am currently converting an Apache module to Nginx. This module uses >>> subrequests and needs (for now) to execute the subrequest without >>> unwinding the stack (ie without returning to nginx). >>> >>> I tried to call ngx_http_run_posted_requests by hand, but it does not >>> work as the upstream socket needs to get polled some time. >>> >>> >>> So I wonder, is there any way to do this ? >>> >>> >>> Of course I know that I shouldn't do it like this, but the current >>> module is not reentrant and poorly architectured. I will eventually >>> refactor it but later. >>> >>> >>> Thanks, >>> >>> >>> _______________________________________________ >>> 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: From alfred at huji.fr Tue May 4 15:25:02 2021 From: alfred at huji.fr (Alfred Sawaya) Date: Tue, 4 May 2021 17:25:02 +0200 Subject: Subrequest without returning to nginx In-Reply-To: References: <2baf95f1-e2bb-0ffa-50b2-3a42fcaf3bc6@huji.fr> Message-ID: <9c1f5a86-d390-345e-7a8f-406773e63682@huji.fr> Ah, I felt it. I needed to read it from someone that knows better. So... Big refactor time :) Thank you Maxim On 04/05/2021 16:59, Maxim Dounin wrote: > Hello! > > On Tue, May 04, 2021 at 04:11:34PM +0200, Alfred Sawaya wrote: > >> I am currently converting an Apache module to Nginx. This module uses >> subrequests and needs (for now) to execute the subrequest without >> unwinding the stack (ie without returning to nginx). >> >> I tried to call ngx_http_run_posted_requests by hand, but it does not >> work as the upstream socket needs to get polled some time. >> >> So I wonder, is there any way to do this ? > No. Since nginx is event-driven, you essentially cannot do > anything without returning control back to nginx to execute the > event loop. > >> Of course I know that I shouldn't do it like this, but the current >> module is not reentrant and poorly architectured. I will eventually >> refactor it but later. > You may want to start with throwing away the module, and writing > another one for nginx from scratch. "Converting" rarely works > even for simple and well-written modules. > From mdounin at mdounin.ru Wed May 5 23:43:59 2021 From: mdounin at mdounin.ru (Maxim Dounin) Date: Wed, 05 May 2021 23:43:59 +0000 Subject: [nginx] Changed complex value slots to use NGX_CONF_UNSET_PTR. Message-ID: details: https://hg.nginx.org/nginx/rev/bdd4d89370a7 branches: changeset: 7831:bdd4d89370a7 user: Maxim Dounin date: Thu May 06 02:22:03 2021 +0300 description: Changed complex value slots to use NGX_CONF_UNSET_PTR. With this change, it is now possible to use ngx_conf_merge_ptr_value() to merge complex values. This change follows much earlier changes in ngx_conf_merge_ptr_value() and ngx_conf_set_str_array_slot() in 1452:cd586e963db0 (0.6.10) and 1701:40d004d95d88 (0.6.22), and the change in ngx_conf_set_keyval_slot() (7728:485dba3e2a01, 1.19.4). To preserve compatibility with existing 3rd party modules, both NULL and NGX_CONF_UNSET_PTR are accepted for now. diffstat: src/http/modules/ngx_http_auth_basic_module.c | 6 +++--- src/http/modules/ngx_http_grpc_module.c | 8 +++----- src/http/modules/ngx_http_proxy_module.c | 20 +++++++++----------- src/http/modules/ngx_http_secure_link_module.c | 17 ++++++++--------- src/http/modules/ngx_http_uwsgi_module.c | 7 +++---- src/http/ngx_http_core_module.c | 14 +++++--------- src/http/ngx_http_script.c | 2 +- src/stream/ngx_stream_proxy_module.c | 20 +++++++------------- src/stream/ngx_stream_script.c | 2 +- 9 files changed, 40 insertions(+), 56 deletions(-) diffs (317 lines): diff -r f2ff291bbdac -r bdd4d89370a7 src/http/modules/ngx_http_auth_basic_module.c --- a/src/http/modules/ngx_http_auth_basic_module.c Thu Apr 22 16:12:52 2021 +0300 +++ b/src/http/modules/ngx_http_auth_basic_module.c Thu May 06 02:22:03 2021 +0300 @@ -357,6 +357,8 @@ ngx_http_auth_basic_create_loc_conf(ngx_ return NULL; } + conf->realm = NGX_CONF_UNSET_PTR; + return conf; } @@ -367,9 +369,7 @@ ngx_http_auth_basic_merge_loc_conf(ngx_c ngx_http_auth_basic_loc_conf_t *prev = parent; ngx_http_auth_basic_loc_conf_t *conf = child; - if (conf->realm == NULL) { - conf->realm = prev->realm; - } + ngx_conf_merge_ptr_value(conf->realm, prev->realm, NULL); if (conf->user_file.value.data == NULL) { conf->user_file = prev->user_file; diff -r f2ff291bbdac -r bdd4d89370a7 src/http/modules/ngx_http_grpc_module.c --- a/src/http/modules/ngx_http_grpc_module.c Thu Apr 22 16:12:52 2021 +0300 +++ b/src/http/modules/ngx_http_grpc_module.c Thu May 06 02:22:03 2021 +0300 @@ -4331,7 +4331,6 @@ ngx_http_grpc_create_loc_conf(ngx_conf_t * conf->upstream.ignore_headers = 0; * conf->upstream.next_upstream = 0; * conf->upstream.hide_headers_hash = { NULL, 0 }; - * conf->upstream.ssl_name = NULL; * * conf->headers.lengths = NULL; * conf->headers.values = NULL; @@ -4364,6 +4363,7 @@ ngx_http_grpc_create_loc_conf(ngx_conf_t #if (NGX_HTTP_SSL) conf->upstream.ssl_session_reuse = NGX_CONF_UNSET; + conf->upstream.ssl_name = NGX_CONF_UNSET_PTR; conf->upstream.ssl_server_name = NGX_CONF_UNSET; conf->upstream.ssl_verify = NGX_CONF_UNSET; conf->ssl_verify_depth = NGX_CONF_UNSET_UINT; @@ -4459,10 +4459,8 @@ ngx_http_grpc_merge_loc_conf(ngx_conf_t ngx_conf_merge_str_value(conf->ssl_ciphers, prev->ssl_ciphers, "DEFAULT"); - if (conf->upstream.ssl_name == NULL) { - conf->upstream.ssl_name = prev->upstream.ssl_name; - } - + ngx_conf_merge_ptr_value(conf->upstream.ssl_name, + prev->upstream.ssl_name, NULL); ngx_conf_merge_value(conf->upstream.ssl_server_name, prev->upstream.ssl_server_name, 0); ngx_conf_merge_value(conf->upstream.ssl_verify, diff -r f2ff291bbdac -r bdd4d89370a7 src/http/modules/ngx_http_proxy_module.c --- a/src/http/modules/ngx_http_proxy_module.c Thu Apr 22 16:12:52 2021 +0300 +++ b/src/http/modules/ngx_http_proxy_module.c Thu May 06 02:22:03 2021 +0300 @@ -3327,9 +3327,7 @@ ngx_http_proxy_create_loc_conf(ngx_conf_ * conf->upstream.hide_headers_hash = { NULL, 0 }; * conf->upstream.store_lengths = NULL; * conf->upstream.store_values = NULL; - * conf->upstream.ssl_name = NULL; * - * conf->method = NULL; * conf->location = NULL; * conf->url = { 0, NULL }; * conf->headers.lengths = NULL; @@ -3400,6 +3398,7 @@ ngx_http_proxy_create_loc_conf(ngx_conf_ #if (NGX_HTTP_SSL) conf->upstream.ssl_session_reuse = NGX_CONF_UNSET; + conf->upstream.ssl_name = NGX_CONF_UNSET_PTR; conf->upstream.ssl_server_name = NGX_CONF_UNSET; conf->upstream.ssl_verify = NGX_CONF_UNSET; conf->ssl_verify_depth = NGX_CONF_UNSET_UINT; @@ -3410,10 +3409,13 @@ ngx_http_proxy_create_loc_conf(ngx_conf_ /* "proxy_cyclic_temp_file" is disabled */ conf->upstream.cyclic_temp_file = 0; + conf->upstream.change_buffering = 1; + conf->headers_source = NGX_CONF_UNSET_PTR; + conf->method = NGX_CONF_UNSET_PTR; + conf->redirect = NGX_CONF_UNSET; - conf->upstream.change_buffering = 1; conf->cookie_domains = NGX_CONF_UNSET_PTR; conf->cookie_paths = NGX_CONF_UNSET_PTR; @@ -3708,10 +3710,6 @@ ngx_http_proxy_merge_loc_conf(ngx_conf_t #endif - if (conf->method == NULL) { - conf->method = prev->method; - } - ngx_conf_merge_value(conf->upstream.pass_request_headers, prev->upstream.pass_request_headers, 1); ngx_conf_merge_value(conf->upstream.pass_request_body, @@ -3732,10 +3730,8 @@ ngx_http_proxy_merge_loc_conf(ngx_conf_t ngx_conf_merge_str_value(conf->ssl_ciphers, prev->ssl_ciphers, "DEFAULT"); - if (conf->upstream.ssl_name == NULL) { - conf->upstream.ssl_name = prev->upstream.ssl_name; - } - + ngx_conf_merge_ptr_value(conf->upstream.ssl_name, + prev->upstream.ssl_name, NULL); ngx_conf_merge_value(conf->upstream.ssl_server_name, prev->upstream.ssl_server_name, 0); ngx_conf_merge_value(conf->upstream.ssl_verify, @@ -3761,6 +3757,8 @@ ngx_http_proxy_merge_loc_conf(ngx_conf_t #endif + ngx_conf_merge_ptr_value(conf->method, prev->method, NULL); + ngx_conf_merge_value(conf->redirect, prev->redirect, 1); if (conf->redirect) { diff -r f2ff291bbdac -r bdd4d89370a7 src/http/modules/ngx_http_secure_link_module.c --- a/src/http/modules/ngx_http_secure_link_module.c Thu Apr 22 16:12:52 2021 +0300 +++ b/src/http/modules/ngx_http_secure_link_module.c Thu May 06 02:22:03 2021 +0300 @@ -302,11 +302,12 @@ ngx_http_secure_link_create_conf(ngx_con /* * set by ngx_pcalloc(): * - * conf->variable = NULL; - * conf->md5 = NULL; * conf->secret = { 0, NULL }; */ + conf->variable = NGX_CONF_UNSET_PTR; + conf->md5 = NGX_CONF_UNSET_PTR; + return conf; } @@ -318,6 +319,9 @@ ngx_http_secure_link_merge_conf(ngx_conf ngx_http_secure_link_conf_t *conf = child; if (conf->secret.data) { + ngx_conf_init_ptr_value(conf->variable, NULL); + ngx_conf_init_ptr_value(conf->md5, NULL); + if (conf->variable || conf->md5) { ngx_conf_log_error(NGX_LOG_EMERG, cf, 0, "\"secure_link_secret\" cannot be mixed with " @@ -328,13 +332,8 @@ ngx_http_secure_link_merge_conf(ngx_conf return NGX_CONF_OK; } - if (conf->variable == NULL) { - conf->variable = prev->variable; - } - - if (conf->md5 == NULL) { - conf->md5 = prev->md5; - } + ngx_conf_merge_ptr_value(conf->variable, prev->variable, NULL); + ngx_conf_merge_ptr_value(conf->md5, prev->md5, NULL); if (conf->variable == NULL && conf->md5 == NULL) { conf->secret = prev->secret; diff -r f2ff291bbdac -r bdd4d89370a7 src/http/modules/ngx_http_uwsgi_module.c --- a/src/http/modules/ngx_http_uwsgi_module.c Thu Apr 22 16:12:52 2021 +0300 +++ b/src/http/modules/ngx_http_uwsgi_module.c Thu May 06 02:22:03 2021 +0300 @@ -1509,6 +1509,7 @@ ngx_http_uwsgi_create_loc_conf(ngx_conf_ #if (NGX_HTTP_SSL) conf->upstream.ssl_session_reuse = NGX_CONF_UNSET; + conf->upstream.ssl_name = NGX_CONF_UNSET_PTR; conf->upstream.ssl_server_name = NGX_CONF_UNSET; conf->upstream.ssl_verify = NGX_CONF_UNSET; conf->ssl_verify_depth = NGX_CONF_UNSET_UINT; @@ -1824,10 +1825,8 @@ ngx_http_uwsgi_merge_loc_conf(ngx_conf_t ngx_conf_merge_str_value(conf->ssl_ciphers, prev->ssl_ciphers, "DEFAULT"); - if (conf->upstream.ssl_name == NULL) { - conf->upstream.ssl_name = prev->upstream.ssl_name; - } - + ngx_conf_merge_ptr_value(conf->upstream.ssl_name, + prev->upstream.ssl_name, NULL); ngx_conf_merge_value(conf->upstream.ssl_server_name, prev->upstream.ssl_server_name, 0); ngx_conf_merge_value(conf->upstream.ssl_verify, diff -r f2ff291bbdac -r bdd4d89370a7 src/http/ngx_http_core_module.c --- a/src/http/ngx_http_core_module.c Thu Apr 22 16:12:52 2021 +0300 +++ b/src/http/ngx_http_core_module.c Thu May 06 02:22:03 2021 +0300 @@ -3479,8 +3479,6 @@ ngx_http_core_create_loc_conf(ngx_conf_t * clcf->exact_match = 0; * clcf->auto_redirect = 0; * clcf->alias = 0; - * clcf->limit_rate = NULL; - * clcf->limit_rate_after = NULL; * clcf->gzip_proxied = 0; * clcf->keepalive_disable = 0; */ @@ -3512,6 +3510,8 @@ ngx_http_core_create_loc_conf(ngx_conf_t clcf->send_timeout = NGX_CONF_UNSET_MSEC; clcf->send_lowat = NGX_CONF_UNSET_SIZE; clcf->postpone_output = NGX_CONF_UNSET_SIZE; + clcf->limit_rate = NGX_CONF_UNSET_PTR; + clcf->limit_rate_after = NGX_CONF_UNSET_PTR; clcf->keepalive_time = NGX_CONF_UNSET_MSEC; clcf->keepalive_timeout = NGX_CONF_UNSET_MSEC; clcf->keepalive_header = NGX_CONF_UNSET; @@ -3743,13 +3743,9 @@ ngx_http_core_merge_loc_conf(ngx_conf_t ngx_conf_merge_size_value(conf->postpone_output, prev->postpone_output, 1460); - if (conf->limit_rate == NULL) { - conf->limit_rate = prev->limit_rate; - } - - if (conf->limit_rate_after == NULL) { - conf->limit_rate_after = prev->limit_rate_after; - } + ngx_conf_merge_ptr_value(conf->limit_rate, prev->limit_rate, NULL); + ngx_conf_merge_ptr_value(conf->limit_rate_after, + prev->limit_rate_after, NULL); ngx_conf_merge_msec_value(conf->keepalive_time, prev->keepalive_time, 3600000); diff -r f2ff291bbdac -r bdd4d89370a7 src/http/ngx_http_script.c --- a/src/http/ngx_http_script.c Thu Apr 22 16:12:52 2021 +0300 +++ b/src/http/ngx_http_script.c Thu May 06 02:22:03 2021 +0300 @@ -250,7 +250,7 @@ ngx_http_set_complex_value_slot(ngx_conf cv = (ngx_http_complex_value_t **) (p + cmd->offset); - if (*cv != NULL) { + if (*cv != NGX_CONF_UNSET_PTR && *cv != NULL) { return "is duplicate"; } diff -r f2ff291bbdac -r bdd4d89370a7 src/stream/ngx_stream_proxy_module.c --- a/src/stream/ngx_stream_proxy_module.c Thu Apr 22 16:12:52 2021 +0300 +++ b/src/stream/ngx_stream_proxy_module.c Thu May 06 02:22:03 2021 +0300 @@ -1977,14 +1977,11 @@ ngx_stream_proxy_create_srv_conf(ngx_con * * conf->ssl_protocols = 0; * conf->ssl_ciphers = { 0, NULL }; - * conf->ssl_name = NULL; * conf->ssl_trusted_certificate = { 0, NULL }; * conf->ssl_crl = { 0, NULL }; * conf->ssl_certificate = { 0, NULL }; * conf->ssl_certificate_key = { 0, NULL }; * - * conf->upload_rate = NULL; - * conf->download_rate = NULL; * conf->ssl = NULL; * conf->upstream = NULL; * conf->upstream_value = NULL; @@ -1994,6 +1991,8 @@ ngx_stream_proxy_create_srv_conf(ngx_con conf->timeout = NGX_CONF_UNSET_MSEC; conf->next_upstream_timeout = NGX_CONF_UNSET_MSEC; conf->buffer_size = NGX_CONF_UNSET_SIZE; + conf->upload_rate = NGX_CONF_UNSET_PTR; + conf->download_rate = NGX_CONF_UNSET_PTR; conf->requests = NGX_CONF_UNSET_UINT; conf->responses = NGX_CONF_UNSET_UINT; conf->next_upstream_tries = NGX_CONF_UNSET_UINT; @@ -2005,6 +2004,7 @@ ngx_stream_proxy_create_srv_conf(ngx_con #if (NGX_STREAM_SSL) conf->ssl_enable = NGX_CONF_UNSET; conf->ssl_session_reuse = NGX_CONF_UNSET; + conf->ssl_name = NGX_CONF_UNSET_PTR; conf->ssl_server_name = NGX_CONF_UNSET; conf->ssl_verify = NGX_CONF_UNSET; conf->ssl_verify_depth = NGX_CONF_UNSET_UINT; @@ -2034,13 +2034,9 @@ ngx_stream_proxy_merge_srv_conf(ngx_conf ngx_conf_merge_size_value(conf->buffer_size, prev->buffer_size, 16384); - if (conf->upload_rate == NULL) { - conf->upload_rate = prev->upload_rate; - } - - if (conf->download_rate == NULL) { - conf->download_rate = prev->download_rate; - } + ngx_conf_merge_ptr_value(conf->upload_rate, prev->upload_rate, NULL); + + ngx_conf_merge_ptr_value(conf->download_rate, prev->download_rate, NULL); ngx_conf_merge_uint_value(conf->requests, prev->requests, 0); @@ -2073,9 +2069,7 @@ ngx_stream_proxy_merge_srv_conf(ngx_conf ngx_conf_merge_str_value(conf->ssl_ciphers, prev->ssl_ciphers, "DEFAULT"); - if (conf->ssl_name == NULL) { - conf->ssl_name = prev->ssl_name; - } + ngx_conf_merge_ptr_value(conf->ssl_name, prev->ssl_name, NULL); ngx_conf_merge_value(conf->ssl_server_name, prev->ssl_server_name, 0); diff -r f2ff291bbdac -r bdd4d89370a7 src/stream/ngx_stream_script.c --- a/src/stream/ngx_stream_script.c Thu Apr 22 16:12:52 2021 +0300 +++ b/src/stream/ngx_stream_script.c Thu May 06 02:22:03 2021 +0300 @@ -252,7 +252,7 @@ ngx_stream_set_complex_value_slot(ngx_co cv = (ngx_stream_complex_value_t **) (p + cmd->offset); - if (*cv != NULL) { + if (*cv != NGX_CONF_UNSET_PTR && *cv != NULL) { return "is duplicate"; } From mdounin at mdounin.ru Wed May 5 23:44:02 2021 From: mdounin at mdounin.ru (Maxim Dounin) Date: Wed, 05 May 2021 23:44:02 +0000 Subject: [nginx] Auth basic: changed alcf->user_file to be a pointer. Message-ID: details: https://hg.nginx.org/nginx/rev/be82e72c9af8 branches: changeset: 7832:be82e72c9af8 user: Maxim Dounin date: Thu May 06 02:22:07 2021 +0300 description: Auth basic: changed alcf->user_file to be a pointer. This saves some memory in typical case when auth_basic_user_file is not explicitly set, and unifies the code with alcf->realm. diffstat: src/http/modules/ngx_http_auth_basic_module.c | 21 ++++++++++++--------- 1 files changed, 12 insertions(+), 9 deletions(-) diffs (75 lines): diff -r bdd4d89370a7 -r be82e72c9af8 src/http/modules/ngx_http_auth_basic_module.c --- a/src/http/modules/ngx_http_auth_basic_module.c Thu May 06 02:22:03 2021 +0300 +++ b/src/http/modules/ngx_http_auth_basic_module.c Thu May 06 02:22:07 2021 +0300 @@ -16,7 +16,7 @@ typedef struct { ngx_http_complex_value_t *realm; - ngx_http_complex_value_t user_file; + ngx_http_complex_value_t *user_file; } ngx_http_auth_basic_loc_conf_t; @@ -107,7 +107,7 @@ ngx_http_auth_basic_handler(ngx_http_req alcf = ngx_http_get_module_loc_conf(r, ngx_http_auth_basic_module); - if (alcf->realm == NULL || alcf->user_file.value.data == NULL) { + if (alcf->realm == NULL || alcf->user_file == NULL) { return NGX_DECLINED; } @@ -133,7 +133,7 @@ ngx_http_auth_basic_handler(ngx_http_req return NGX_HTTP_INTERNAL_SERVER_ERROR; } - if (ngx_http_complex_value(r, &alcf->user_file, &user_file) != NGX_OK) { + if (ngx_http_complex_value(r, alcf->user_file, &user_file) != NGX_OK) { return NGX_ERROR; } @@ -358,6 +358,7 @@ ngx_http_auth_basic_create_loc_conf(ngx_ } conf->realm = NGX_CONF_UNSET_PTR; + conf->user_file = NGX_CONF_UNSET_PTR; return conf; } @@ -370,10 +371,7 @@ ngx_http_auth_basic_merge_loc_conf(ngx_c ngx_http_auth_basic_loc_conf_t *conf = child; ngx_conf_merge_ptr_value(conf->realm, prev->realm, NULL); - - if (conf->user_file.value.data == NULL) { - conf->user_file = prev->user_file; - } + ngx_conf_merge_ptr_value(conf->user_file, prev->user_file, NULL); return NGX_CONF_OK; } @@ -406,17 +404,22 @@ ngx_http_auth_basic_user_file(ngx_conf_t ngx_str_t *value; ngx_http_compile_complex_value_t ccv; - if (alcf->user_file.value.data) { + if (alcf->user_file != NGX_CONF_UNSET_PTR) { return "is duplicate"; } + alcf->user_file = ngx_palloc(cf->pool, sizeof(ngx_http_complex_value_t)); + if (alcf->user_file == NULL) { + return NGX_CONF_ERROR; + } + value = cf->args->elts; ngx_memzero(&ccv, sizeof(ngx_http_compile_complex_value_t)); ccv.cf = cf; ccv.value = &value[1]; - ccv.complex_value = &alcf->user_file; + ccv.complex_value = alcf->user_file; ccv.zero = 1; ccv.conf_prefix = 1; From mdounin at mdounin.ru Wed May 5 23:44:05 2021 From: mdounin at mdounin.ru (Maxim Dounin) Date: Wed, 05 May 2021 23:44:05 +0000 Subject: [nginx] Upstream: variables support in certificates. Message-ID: details: https://hg.nginx.org/nginx/rev/3ab8e1e2f0f7 branches: changeset: 7833:3ab8e1e2f0f7 user: Maxim Dounin date: Thu May 06 02:22:09 2021 +0300 description: Upstream: variables support in certificates. diffstat: src/http/modules/ngx_http_grpc_module.c | 66 +++++++++++------- src/http/modules/ngx_http_proxy_module.c | 66 +++++++++++------- src/http/modules/ngx_http_uwsgi_module.c | 64 +++++++++++------- src/http/ngx_http_script.c | 38 +++++++++++ src/http/ngx_http_script.h | 2 + src/http/ngx_http_upstream.c | 51 ++++++++++++++ src/http/ngx_http_upstream.h | 4 + src/stream/ngx_stream_proxy_module.c | 106 +++++++++++++++++++++++++----- src/stream/ngx_stream_script.c | 38 +++++++++++ src/stream/ngx_stream_script.h | 2 + 10 files changed, 339 insertions(+), 98 deletions(-) diffs (790 lines): diff -r be82e72c9af8 -r 3ab8e1e2f0f7 src/http/modules/ngx_http_grpc_module.c --- a/src/http/modules/ngx_http_grpc_module.c Thu May 06 02:22:07 2021 +0300 +++ b/src/http/modules/ngx_http_grpc_module.c Thu May 06 02:22:09 2021 +0300 @@ -37,9 +37,6 @@ typedef struct { ngx_uint_t ssl_verify_depth; ngx_str_t ssl_trusted_certificate; ngx_str_t ssl_crl; - ngx_str_t ssl_certificate; - ngx_str_t ssl_certificate_key; - ngx_array_t *ssl_passwords; ngx_array_t *ssl_conf_commands; #endif } ngx_http_grpc_loc_conf_t; @@ -425,16 +422,16 @@ static ngx_command_t ngx_http_grpc_comm { ngx_string("grpc_ssl_certificate"), NGX_HTTP_MAIN_CONF|NGX_HTTP_SRV_CONF|NGX_HTTP_LOC_CONF|NGX_CONF_TAKE1, - ngx_conf_set_str_slot, + ngx_http_set_complex_value_zero_slot, NGX_HTTP_LOC_CONF_OFFSET, - offsetof(ngx_http_grpc_loc_conf_t, ssl_certificate), + offsetof(ngx_http_grpc_loc_conf_t, upstream.ssl_certificate), NULL }, { ngx_string("grpc_ssl_certificate_key"), NGX_HTTP_MAIN_CONF|NGX_HTTP_SRV_CONF|NGX_HTTP_LOC_CONF|NGX_CONF_TAKE1, - ngx_conf_set_str_slot, + ngx_http_set_complex_value_zero_slot, NGX_HTTP_LOC_CONF_OFFSET, - offsetof(ngx_http_grpc_loc_conf_t, ssl_certificate_key), + offsetof(ngx_http_grpc_loc_conf_t, upstream.ssl_certificate_key), NULL }, { ngx_string("grpc_ssl_password_file"), @@ -4342,8 +4339,6 @@ ngx_http_grpc_create_loc_conf(ngx_conf_t * conf->ssl_ciphers = { 0, NULL }; * conf->ssl_trusted_certificate = { 0, NULL }; * conf->ssl_crl = { 0, NULL }; - * conf->ssl_certificate = { 0, NULL }; - * conf->ssl_certificate_key = { 0, NULL }; */ conf->upstream.local = NGX_CONF_UNSET_PTR; @@ -4367,7 +4362,9 @@ ngx_http_grpc_create_loc_conf(ngx_conf_t conf->upstream.ssl_server_name = NGX_CONF_UNSET; conf->upstream.ssl_verify = NGX_CONF_UNSET; conf->ssl_verify_depth = NGX_CONF_UNSET_UINT; - conf->ssl_passwords = NGX_CONF_UNSET_PTR; + 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_conf_commands = NGX_CONF_UNSET_PTR; #endif @@ -4471,11 +4468,12 @@ ngx_http_grpc_merge_loc_conf(ngx_conf_t prev->ssl_trusted_certificate, ""); ngx_conf_merge_str_value(conf->ssl_crl, prev->ssl_crl, ""); - ngx_conf_merge_str_value(conf->ssl_certificate, - prev->ssl_certificate, ""); - ngx_conf_merge_str_value(conf->ssl_certificate_key, - prev->ssl_certificate_key, ""); - ngx_conf_merge_ptr_value(conf->ssl_passwords, prev->ssl_passwords, NULL); + ngx_conf_merge_ptr_value(conf->upstream.ssl_certificate, + 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_conf_commands, prev->ssl_conf_commands, NULL); @@ -4831,15 +4829,15 @@ ngx_http_grpc_ssl_password_file(ngx_conf ngx_str_t *value; - if (glcf->ssl_passwords != NGX_CONF_UNSET_PTR) { + if (glcf->upstream.ssl_passwords != NGX_CONF_UNSET_PTR) { return "is duplicate"; } value = cf->args->elts; - glcf->ssl_passwords = ngx_ssl_read_password_file(cf, &value[1]); - - if (glcf->ssl_passwords == NULL) { + glcf->upstream.ssl_passwords = ngx_ssl_read_password_file(cf, &value[1]); + + if (glcf->upstream.ssl_passwords == NULL) { return NGX_CONF_ERROR; } @@ -4885,20 +4883,34 @@ ngx_http_grpc_set_ssl(ngx_conf_t *cf, ng cln->handler = ngx_ssl_cleanup_ctx; cln->data = glcf->upstream.ssl; - if (glcf->ssl_certificate.len) { - - if (glcf->ssl_certificate_key.len == 0) { + if (glcf->upstream.ssl_certificate) { + + if (glcf->upstream.ssl_certificate_key == NULL) { ngx_log_error(NGX_LOG_EMERG, cf->log, 0, "no \"grpc_ssl_certificate_key\" is defined " - "for certificate \"%V\"", &glcf->ssl_certificate); + "for certificate \"%V\"", + &glcf->upstream.ssl_certificate->value); return NGX_ERROR; } - if (ngx_ssl_certificate(cf, glcf->upstream.ssl, &glcf->ssl_certificate, - &glcf->ssl_certificate_key, glcf->ssl_passwords) - != NGX_OK) + if (glcf->upstream.ssl_certificate->lengths + || glcf->upstream.ssl_certificate_key->lengths) { - return NGX_ERROR; + glcf->upstream.ssl_passwords = + ngx_ssl_preserve_passwords(cf, glcf->upstream.ssl_passwords); + if (glcf->upstream.ssl_passwords == NULL) { + return NGX_ERROR; + } + + } else { + if (ngx_ssl_certificate(cf, glcf->upstream.ssl, + &glcf->upstream.ssl_certificate->value, + &glcf->upstream.ssl_certificate_key->value, + glcf->upstream.ssl_passwords) + != NGX_OK) + { + return NGX_ERROR; + } } } diff -r be82e72c9af8 -r 3ab8e1e2f0f7 src/http/modules/ngx_http_proxy_module.c --- a/src/http/modules/ngx_http_proxy_module.c Thu May 06 02:22:07 2021 +0300 +++ b/src/http/modules/ngx_http_proxy_module.c Thu May 06 02:22:09 2021 +0300 @@ -124,9 +124,6 @@ typedef struct { ngx_uint_t ssl_verify_depth; ngx_str_t ssl_trusted_certificate; ngx_str_t ssl_crl; - ngx_str_t ssl_certificate; - ngx_str_t ssl_certificate_key; - ngx_array_t *ssl_passwords; ngx_array_t *ssl_conf_commands; #endif } ngx_http_proxy_loc_conf_t; @@ -753,16 +750,16 @@ static ngx_command_t ngx_http_proxy_com { ngx_string("proxy_ssl_certificate"), NGX_HTTP_MAIN_CONF|NGX_HTTP_SRV_CONF|NGX_HTTP_LOC_CONF|NGX_CONF_TAKE1, - ngx_conf_set_str_slot, + ngx_http_set_complex_value_zero_slot, NGX_HTTP_LOC_CONF_OFFSET, - offsetof(ngx_http_proxy_loc_conf_t, ssl_certificate), + offsetof(ngx_http_proxy_loc_conf_t, upstream.ssl_certificate), NULL }, { ngx_string("proxy_ssl_certificate_key"), NGX_HTTP_MAIN_CONF|NGX_HTTP_SRV_CONF|NGX_HTTP_LOC_CONF|NGX_CONF_TAKE1, - ngx_conf_set_str_slot, + ngx_http_set_complex_value_zero_slot, NGX_HTTP_LOC_CONF_OFFSET, - offsetof(ngx_http_proxy_loc_conf_t, ssl_certificate_key), + offsetof(ngx_http_proxy_loc_conf_t, upstream.ssl_certificate_key), NULL }, { ngx_string("proxy_ssl_password_file"), @@ -3345,8 +3342,6 @@ ngx_http_proxy_create_loc_conf(ngx_conf_ * conf->ssl_ciphers = { 0, NULL }; * conf->ssl_trusted_certificate = { 0, NULL }; * conf->ssl_crl = { 0, NULL }; - * conf->ssl_certificate = { 0, NULL }; - * conf->ssl_certificate_key = { 0, NULL }; */ conf->upstream.store = NGX_CONF_UNSET; @@ -3401,8 +3396,10 @@ ngx_http_proxy_create_loc_conf(ngx_conf_ conf->upstream.ssl_name = NGX_CONF_UNSET_PTR; conf->upstream.ssl_server_name = NGX_CONF_UNSET; conf->upstream.ssl_verify = NGX_CONF_UNSET; + 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_verify_depth = NGX_CONF_UNSET_UINT; - conf->ssl_passwords = NGX_CONF_UNSET_PTR; conf->ssl_conf_commands = NGX_CONF_UNSET_PTR; #endif @@ -3742,11 +3739,12 @@ ngx_http_proxy_merge_loc_conf(ngx_conf_t prev->ssl_trusted_certificate, ""); ngx_conf_merge_str_value(conf->ssl_crl, prev->ssl_crl, ""); - ngx_conf_merge_str_value(conf->ssl_certificate, - prev->ssl_certificate, ""); - ngx_conf_merge_str_value(conf->ssl_certificate_key, - prev->ssl_certificate_key, ""); - ngx_conf_merge_ptr_value(conf->ssl_passwords, prev->ssl_passwords, NULL); + ngx_conf_merge_ptr_value(conf->upstream.ssl_certificate, + 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_conf_commands, prev->ssl_conf_commands, NULL); @@ -4857,15 +4855,15 @@ ngx_http_proxy_ssl_password_file(ngx_con ngx_str_t *value; - if (plcf->ssl_passwords != NGX_CONF_UNSET_PTR) { + if (plcf->upstream.ssl_passwords != NGX_CONF_UNSET_PTR) { return "is duplicate"; } value = cf->args->elts; - plcf->ssl_passwords = ngx_ssl_read_password_file(cf, &value[1]); - - if (plcf->ssl_passwords == NULL) { + plcf->upstream.ssl_passwords = ngx_ssl_read_password_file(cf, &value[1]); + + if (plcf->upstream.ssl_passwords == NULL) { return NGX_CONF_ERROR; } @@ -4944,20 +4942,34 @@ ngx_http_proxy_set_ssl(ngx_conf_t *cf, n cln->handler = ngx_ssl_cleanup_ctx; cln->data = plcf->upstream.ssl; - if (plcf->ssl_certificate.len) { - - if (plcf->ssl_certificate_key.len == 0) { + if (plcf->upstream.ssl_certificate) { + + if (plcf->upstream.ssl_certificate_key == NULL) { ngx_log_error(NGX_LOG_EMERG, cf->log, 0, "no \"proxy_ssl_certificate_key\" is defined " - "for certificate \"%V\"", &plcf->ssl_certificate); + "for certificate \"%V\"", + &plcf->upstream.ssl_certificate->value); return NGX_ERROR; } - if (ngx_ssl_certificate(cf, plcf->upstream.ssl, &plcf->ssl_certificate, - &plcf->ssl_certificate_key, plcf->ssl_passwords) - != NGX_OK) + if (plcf->upstream.ssl_certificate->lengths + || plcf->upstream.ssl_certificate_key->lengths) { - return NGX_ERROR; + plcf->upstream.ssl_passwords = + ngx_ssl_preserve_passwords(cf, plcf->upstream.ssl_passwords); + if (plcf->upstream.ssl_passwords == NULL) { + return NGX_ERROR; + } + + } else { + if (ngx_ssl_certificate(cf, plcf->upstream.ssl, + &plcf->upstream.ssl_certificate->value, + &plcf->upstream.ssl_certificate_key->value, + plcf->upstream.ssl_passwords) + != NGX_OK) + { + return NGX_ERROR; + } } } diff -r be82e72c9af8 -r 3ab8e1e2f0f7 src/http/modules/ngx_http_uwsgi_module.c --- a/src/http/modules/ngx_http_uwsgi_module.c Thu May 06 02:22:07 2021 +0300 +++ b/src/http/modules/ngx_http_uwsgi_module.c Thu May 06 02:22:09 2021 +0300 @@ -54,9 +54,6 @@ typedef struct { ngx_uint_t ssl_verify_depth; ngx_str_t ssl_trusted_certificate; ngx_str_t ssl_crl; - ngx_str_t ssl_certificate; - ngx_str_t ssl_certificate_key; - ngx_array_t *ssl_passwords; ngx_array_t *ssl_conf_commands; #endif } ngx_http_uwsgi_loc_conf_t; @@ -548,16 +545,16 @@ static ngx_command_t ngx_http_uwsgi_comm { ngx_string("uwsgi_ssl_certificate"), NGX_HTTP_MAIN_CONF|NGX_HTTP_SRV_CONF|NGX_HTTP_LOC_CONF|NGX_CONF_TAKE1, - ngx_conf_set_str_slot, + ngx_http_set_complex_value_zero_slot, NGX_HTTP_LOC_CONF_OFFSET, - offsetof(ngx_http_uwsgi_loc_conf_t, ssl_certificate), + offsetof(ngx_http_uwsgi_loc_conf_t, upstream.ssl_certificate), NULL }, { ngx_string("uwsgi_ssl_certificate_key"), NGX_HTTP_MAIN_CONF|NGX_HTTP_SRV_CONF|NGX_HTTP_LOC_CONF|NGX_CONF_TAKE1, - ngx_conf_set_str_slot, + ngx_http_set_complex_value_zero_slot, NGX_HTTP_LOC_CONF_OFFSET, - offsetof(ngx_http_uwsgi_loc_conf_t, ssl_certificate_key), + offsetof(ngx_http_uwsgi_loc_conf_t, upstream.ssl_certificate_key), NULL }, { ngx_string("uwsgi_ssl_password_file"), @@ -1513,7 +1510,9 @@ ngx_http_uwsgi_create_loc_conf(ngx_conf_ conf->upstream.ssl_server_name = NGX_CONF_UNSET; conf->upstream.ssl_verify = NGX_CONF_UNSET; conf->ssl_verify_depth = NGX_CONF_UNSET_UINT; - conf->ssl_passwords = NGX_CONF_UNSET_PTR; + 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_conf_commands = NGX_CONF_UNSET_PTR; #endif @@ -1837,11 +1836,12 @@ ngx_http_uwsgi_merge_loc_conf(ngx_conf_t prev->ssl_trusted_certificate, ""); ngx_conf_merge_str_value(conf->ssl_crl, prev->ssl_crl, ""); - ngx_conf_merge_str_value(conf->ssl_certificate, - prev->ssl_certificate, ""); - ngx_conf_merge_str_value(conf->ssl_certificate_key, - prev->ssl_certificate_key, ""); - ngx_conf_merge_ptr_value(conf->ssl_passwords, prev->ssl_passwords, NULL); + ngx_conf_merge_ptr_value(conf->upstream.ssl_certificate, + 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_conf_commands, prev->ssl_conf_commands, NULL); @@ -2376,15 +2376,15 @@ ngx_http_uwsgi_ssl_password_file(ngx_con ngx_str_t *value; - if (uwcf->ssl_passwords != NGX_CONF_UNSET_PTR) { + if (uwcf->upstream.ssl_passwords != NGX_CONF_UNSET_PTR) { return "is duplicate"; } value = cf->args->elts; - uwcf->ssl_passwords = ngx_ssl_read_password_file(cf, &value[1]); - - if (uwcf->ssl_passwords == NULL) { + uwcf->upstream.ssl_passwords = ngx_ssl_read_password_file(cf, &value[1]); + + if (uwcf->upstream.ssl_passwords == NULL) { return NGX_CONF_ERROR; } @@ -2430,20 +2430,34 @@ ngx_http_uwsgi_set_ssl(ngx_conf_t *cf, n cln->handler = ngx_ssl_cleanup_ctx; cln->data = uwcf->upstream.ssl; - if (uwcf->ssl_certificate.len) { - - if (uwcf->ssl_certificate_key.len == 0) { + if (uwcf->upstream.ssl_certificate) { + + if (uwcf->upstream.ssl_certificate_key == NULL) { ngx_log_error(NGX_LOG_EMERG, cf->log, 0, "no \"uwsgi_ssl_certificate_key\" is defined " - "for certificate \"%V\"", &uwcf->ssl_certificate); + "for certificate \"%V\"", + &uwcf->upstream.ssl_certificate->value); return NGX_ERROR; } - if (ngx_ssl_certificate(cf, uwcf->upstream.ssl, &uwcf->ssl_certificate, - &uwcf->ssl_certificate_key, uwcf->ssl_passwords) - != NGX_OK) + if (uwcf->upstream.ssl_certificate->lengths + || uwcf->upstream.ssl_certificate_key->lengths) { - return NGX_ERROR; + uwcf->upstream.ssl_passwords = + ngx_ssl_preserve_passwords(cf, uwcf->upstream.ssl_passwords); + if (uwcf->upstream.ssl_passwords == NULL) { + return NGX_ERROR; + } + + } else { + if (ngx_ssl_certificate(cf, uwcf->upstream.ssl, + &uwcf->upstream.ssl_certificate->value, + &uwcf->upstream.ssl_certificate_key->value, + uwcf->upstream.ssl_passwords) + != NGX_OK) + { + return NGX_ERROR; + } } } diff -r be82e72c9af8 -r 3ab8e1e2f0f7 src/http/ngx_http_script.c --- a/src/http/ngx_http_script.c Thu May 06 02:22:07 2021 +0300 +++ b/src/http/ngx_http_script.c Thu May 06 02:22:09 2021 +0300 @@ -276,6 +276,44 @@ ngx_http_set_complex_value_slot(ngx_conf char * +ngx_http_set_complex_value_zero_slot(ngx_conf_t *cf, ngx_command_t *cmd, + void *conf) +{ + char *p = conf; + + ngx_str_t *value; + ngx_http_complex_value_t **cv; + ngx_http_compile_complex_value_t ccv; + + cv = (ngx_http_complex_value_t **) (p + cmd->offset); + + if (*cv != NGX_CONF_UNSET_PTR) { + return "is duplicate"; + } + + *cv = ngx_palloc(cf->pool, sizeof(ngx_http_complex_value_t)); + if (*cv == NULL) { + return NGX_CONF_ERROR; + } + + value = cf->args->elts; + + ngx_memzero(&ccv, sizeof(ngx_http_compile_complex_value_t)); + + ccv.cf = cf; + ccv.value = &value[1]; + ccv.complex_value = *cv; + ccv.zero = 1; + + if (ngx_http_compile_complex_value(&ccv) != NGX_OK) { + return NGX_CONF_ERROR; + } + + return NGX_CONF_OK; +} + + +char * ngx_http_set_complex_value_size_slot(ngx_conf_t *cf, ngx_command_t *cmd, void *conf) { diff -r be82e72c9af8 -r 3ab8e1e2f0f7 src/http/ngx_http_script.h --- a/src/http/ngx_http_script.h Thu May 06 02:22:07 2021 +0300 +++ b/src/http/ngx_http_script.h Thu May 06 02:22:09 2021 +0300 @@ -216,6 +216,8 @@ size_t ngx_http_complex_value_size(ngx_h ngx_int_t ngx_http_compile_complex_value(ngx_http_compile_complex_value_t *ccv); char *ngx_http_set_complex_value_slot(ngx_conf_t *cf, ngx_command_t *cmd, void *conf); +char *ngx_http_set_complex_value_zero_slot(ngx_conf_t *cf, ngx_command_t *cmd, + void *conf); char *ngx_http_set_complex_value_size_slot(ngx_conf_t *cf, ngx_command_t *cmd, void *conf); diff -r be82e72c9af8 -r 3ab8e1e2f0f7 src/http/ngx_http_upstream.c --- a/src/http/ngx_http_upstream.c Thu May 06 02:22:07 2021 +0300 +++ b/src/http/ngx_http_upstream.c Thu May 06 02:22:09 2021 +0300 @@ -187,6 +187,8 @@ static void ngx_http_upstream_ssl_handsh static void ngx_http_upstream_ssl_save_session(ngx_connection_t *c); static ngx_int_t ngx_http_upstream_ssl_name(ngx_http_request_t *r, ngx_http_upstream_t *u, ngx_connection_t *c); +static ngx_int_t ngx_http_upstream_ssl_certificate(ngx_http_request_t *r, + ngx_http_upstream_t *u, ngx_connection_t *c); #endif @@ -1692,6 +1694,16 @@ ngx_http_upstream_ssl_init_connection(ng } } + if (u->conf->ssl_certificate && (u->conf->ssl_certificate->lengths + || u->conf->ssl_certificate_key->lengths)) + { + if (ngx_http_upstream_ssl_certificate(r, u, c) != NGX_OK) { + ngx_http_upstream_finalize_request(r, u, + NGX_HTTP_INTERNAL_SERVER_ERROR); + return; + } + } + if (u->conf->ssl_session_reuse) { c->ssl->save_session = ngx_http_upstream_ssl_save_session; @@ -1912,6 +1924,45 @@ done: return NGX_OK; } + +static ngx_int_t +ngx_http_upstream_ssl_certificate(ngx_http_request_t *r, + ngx_http_upstream_t *u, ngx_connection_t *c) +{ + ngx_str_t cert, key; + + if (ngx_http_complex_value(r, u->conf->ssl_certificate, &cert) + != NGX_OK) + { + return NGX_ERROR; + } + + ngx_log_debug1(NGX_LOG_DEBUG_HTTP, c->log, 0, + "http upstream ssl cert: \"%s\"", cert.data); + + if (*cert.data == '\0') { + return NGX_OK; + } + + if (ngx_http_complex_value(r, u->conf->ssl_certificate_key, &key) + != NGX_OK) + { + return NGX_ERROR; + } + + ngx_log_debug1(NGX_LOG_DEBUG_HTTP, c->log, 0, + "http upstream ssl key: \"%s\"", key.data); + + if (ngx_ssl_connection_certificate(c, r->pool, &cert, &key, + u->conf->ssl_passwords) + != NGX_OK) + { + return NGX_ERROR; + } + + return NGX_OK; +} + #endif diff -r be82e72c9af8 -r 3ab8e1e2f0f7 src/http/ngx_http_upstream.h --- a/src/http/ngx_http_upstream.h Thu May 06 02:22:07 2021 +0300 +++ b/src/http/ngx_http_upstream.h Thu May 06 02:22:09 2021 +0300 @@ -234,6 +234,10 @@ typedef struct { ngx_http_complex_value_t *ssl_name; ngx_flag_t ssl_server_name; ngx_flag_t ssl_verify; + + ngx_http_complex_value_t *ssl_certificate; + ngx_http_complex_value_t *ssl_certificate_key; + ngx_array_t *ssl_passwords; #endif ngx_str_t module; diff -r be82e72c9af8 -r 3ab8e1e2f0f7 src/stream/ngx_stream_proxy_module.c --- a/src/stream/ngx_stream_proxy_module.c Thu May 06 02:22:07 2021 +0300 +++ b/src/stream/ngx_stream_proxy_module.c Thu May 06 02:22:09 2021 +0300 @@ -46,8 +46,8 @@ typedef struct { ngx_uint_t ssl_verify_depth; ngx_str_t ssl_trusted_certificate; ngx_str_t ssl_crl; - ngx_str_t ssl_certificate; - ngx_str_t ssl_certificate_key; + ngx_stream_complex_value_t *ssl_certificate; + ngx_stream_complex_value_t *ssl_certificate_key; ngx_array_t *ssl_passwords; ngx_array_t *ssl_conf_commands; @@ -101,6 +101,7 @@ static void ngx_stream_proxy_ssl_init_co static void ngx_stream_proxy_ssl_handshake(ngx_connection_t *pc); static void ngx_stream_proxy_ssl_save_session(ngx_connection_t *c); static ngx_int_t ngx_stream_proxy_ssl_name(ngx_stream_session_t *s); +static ngx_int_t ngx_stream_proxy_ssl_certificate(ngx_stream_session_t *s); static ngx_int_t ngx_stream_proxy_set_ssl(ngx_conf_t *cf, ngx_stream_proxy_srv_conf_t *pscf); @@ -318,14 +319,14 @@ static ngx_command_t ngx_stream_proxy_c { ngx_string("proxy_ssl_certificate"), NGX_STREAM_MAIN_CONF|NGX_STREAM_SRV_CONF|NGX_CONF_TAKE1, - ngx_conf_set_str_slot, + ngx_stream_set_complex_value_zero_slot, NGX_STREAM_SRV_CONF_OFFSET, offsetof(ngx_stream_proxy_srv_conf_t, ssl_certificate), NULL }, { ngx_string("proxy_ssl_certificate_key"), NGX_STREAM_MAIN_CONF|NGX_STREAM_SRV_CONF|NGX_CONF_TAKE1, - ngx_conf_set_str_slot, + ngx_stream_set_complex_value_zero_slot, NGX_STREAM_SRV_CONF_OFFSET, offsetof(ngx_stream_proxy_srv_conf_t, ssl_certificate_key), NULL }, @@ -1060,6 +1061,15 @@ ngx_stream_proxy_ssl_init_connection(ngx } } + if (pscf->ssl_certificate && (pscf->ssl_certificate->lengths + || pscf->ssl_certificate_key->lengths)) + { + if (ngx_stream_proxy_ssl_certificate(s) != NGX_OK) { + ngx_stream_proxy_finalize(s, NGX_STREAM_INTERNAL_SERVER_ERROR); + return; + } + } + if (pscf->ssl_session_reuse) { pc->ssl->save_session = ngx_stream_proxy_ssl_save_session; @@ -1247,6 +1257,50 @@ done: return NGX_OK; } + +static ngx_int_t +ngx_stream_proxy_ssl_certificate(ngx_stream_session_t *s) +{ + ngx_str_t cert, key; + ngx_connection_t *c; + ngx_stream_proxy_srv_conf_t *pscf; + + c = s->upstream->peer.connection; + + pscf = ngx_stream_get_module_srv_conf(s, ngx_stream_proxy_module); + + if (ngx_stream_complex_value(s, pscf->ssl_certificate, &cert) + != NGX_OK) + { + return NGX_ERROR; + } + + ngx_log_debug1(NGX_LOG_DEBUG_STREAM, c->log, 0, + "stream upstream ssl cert: \"%s\"", cert.data); + + if (*cert.data == '\0') { + return NGX_OK; + } + + if (ngx_stream_complex_value(s, pscf->ssl_certificate_key, &key) + != NGX_OK) + { + return NGX_ERROR; + } + + ngx_log_debug1(NGX_LOG_DEBUG_STREAM, c->log, 0, + "stream upstream ssl key: \"%s\"", key.data); + + if (ngx_ssl_connection_certificate(c, c->pool, &cert, &key, + pscf->ssl_passwords) + != NGX_OK) + { + return NGX_ERROR; + } + + return NGX_OK; +} + #endif @@ -1979,8 +2033,6 @@ ngx_stream_proxy_create_srv_conf(ngx_con * conf->ssl_ciphers = { 0, NULL }; * conf->ssl_trusted_certificate = { 0, NULL }; * conf->ssl_crl = { 0, NULL }; - * conf->ssl_certificate = { 0, NULL }; - * conf->ssl_certificate_key = { 0, NULL }; * * conf->ssl = NULL; * conf->upstream = NULL; @@ -2008,6 +2060,8 @@ ngx_stream_proxy_create_srv_conf(ngx_con conf->ssl_server_name = NGX_CONF_UNSET; conf->ssl_verify = NGX_CONF_UNSET; conf->ssl_verify_depth = NGX_CONF_UNSET_UINT; + conf->ssl_certificate = NGX_CONF_UNSET_PTR; + conf->ssl_certificate_key = NGX_CONF_UNSET_PTR; conf->ssl_passwords = NGX_CONF_UNSET_PTR; conf->ssl_conf_commands = NGX_CONF_UNSET_PTR; #endif @@ -2083,11 +2137,11 @@ ngx_stream_proxy_merge_srv_conf(ngx_conf ngx_conf_merge_str_value(conf->ssl_crl, prev->ssl_crl, ""); - ngx_conf_merge_str_value(conf->ssl_certificate, - prev->ssl_certificate, ""); - - ngx_conf_merge_str_value(conf->ssl_certificate_key, - prev->ssl_certificate_key, ""); + ngx_conf_merge_ptr_value(conf->ssl_certificate, + prev->ssl_certificate, NULL); + + ngx_conf_merge_ptr_value(conf->ssl_certificate_key, + prev->ssl_certificate_key, NULL); ngx_conf_merge_ptr_value(conf->ssl_passwords, prev->ssl_passwords, NULL); @@ -2131,20 +2185,34 @@ ngx_stream_proxy_set_ssl(ngx_conf_t *cf, cln->handler = ngx_ssl_cleanup_ctx; cln->data = pscf->ssl; - if (pscf->ssl_certificate.len) { - - if (pscf->ssl_certificate_key.len == 0) { + if (pscf->ssl_certificate) { + + if (pscf->ssl_certificate_key == NULL) { ngx_log_error(NGX_LOG_EMERG, cf->log, 0, "no \"proxy_ssl_certificate_key\" is defined " - "for certificate \"%V\"", &pscf->ssl_certificate); + "for certificate \"%V\"", + &pscf->ssl_certificate->value); return NGX_ERROR; } - if (ngx_ssl_certificate(cf, pscf->ssl, &pscf->ssl_certificate, - &pscf->ssl_certificate_key, pscf->ssl_passwords) - != NGX_OK) + if (pscf->ssl_certificate->lengths + || pscf->ssl_certificate_key->lengths) { - return NGX_ERROR; + pscf->ssl_passwords = + ngx_ssl_preserve_passwords(cf, pscf->ssl_passwords); + if (pscf->ssl_passwords == NULL) { + return NGX_ERROR; + } + + } else { + if (ngx_ssl_certificate(cf, pscf->ssl, + &pscf->ssl_certificate->value, + &pscf->ssl_certificate_key->value, + pscf->ssl_passwords) + != NGX_OK) + { + return NGX_ERROR; + } } } diff -r be82e72c9af8 -r 3ab8e1e2f0f7 src/stream/ngx_stream_script.c --- a/src/stream/ngx_stream_script.c Thu May 06 02:22:07 2021 +0300 +++ b/src/stream/ngx_stream_script.c Thu May 06 02:22:09 2021 +0300 @@ -278,6 +278,44 @@ ngx_stream_set_complex_value_slot(ngx_co char * +ngx_stream_set_complex_value_zero_slot(ngx_conf_t *cf, ngx_command_t *cmd, + void *conf) +{ + char *p = conf; + + ngx_str_t *value; + ngx_stream_complex_value_t **cv; + ngx_stream_compile_complex_value_t ccv; + + cv = (ngx_stream_complex_value_t **) (p + cmd->offset); + + if (*cv != NGX_CONF_UNSET_PTR) { + return "is duplicate"; + } + + *cv = ngx_palloc(cf->pool, sizeof(ngx_stream_complex_value_t)); + if (*cv == NULL) { + return NGX_CONF_ERROR; + } + + value = cf->args->elts; + + ngx_memzero(&ccv, sizeof(ngx_stream_compile_complex_value_t)); + + ccv.cf = cf; + ccv.value = &value[1]; + ccv.complex_value = *cv; + ccv.zero = 1; + + if (ngx_stream_compile_complex_value(&ccv) != NGX_OK) { + return NGX_CONF_ERROR; + } + + return NGX_CONF_OK; +} + + +char * ngx_stream_set_complex_value_size_slot(ngx_conf_t *cf, ngx_command_t *cmd, void *conf) { diff -r be82e72c9af8 -r 3ab8e1e2f0f7 src/stream/ngx_stream_script.h --- a/src/stream/ngx_stream_script.h Thu May 06 02:22:07 2021 +0300 +++ b/src/stream/ngx_stream_script.h Thu May 06 02:22:09 2021 +0300 @@ -112,6 +112,8 @@ ngx_int_t ngx_stream_compile_complex_val ngx_stream_compile_complex_value_t *ccv); char *ngx_stream_set_complex_value_slot(ngx_conf_t *cf, ngx_command_t *cmd, void *conf); +char *ngx_stream_set_complex_value_zero_slot(ngx_conf_t *cf, ngx_command_t *cmd, + void *conf); char *ngx_stream_set_complex_value_size_slot(ngx_conf_t *cf, ngx_command_t *cmd, void *conf); From alexander.borisov at nginx.com Thu May 6 13:18:34 2021 From: alexander.borisov at nginx.com (Alexander Borisov) Date: Thu, 06 May 2021 13:18:34 +0000 Subject: [njs] Fixed typo introduced in 27a4a52621d5 and f58a06be33dc. Message-ID: details: https://hg.nginx.org/njs/rev/a0bb54faa1b2 branches: changeset: 1633:a0bb54faa1b2 user: Alexander Borisov date: Thu May 06 16:07:05 2021 +0300 description: Fixed typo introduced in 27a4a52621d5 and f58a06be33dc. diffstat: src/njs_scope.h | 2 +- src/njs_vmcode.c | 2 +- src/test/njs_unit_test.c | 46 +++++++++++++++++++++++----------------------- 3 files changed, 25 insertions(+), 25 deletions(-) diffs (192 lines): diff -r f58a06be33dc -r a0bb54faa1b2 src/njs_scope.h --- a/src/njs_scope.h Fri Apr 30 16:02:34 2021 +0300 +++ b/src/njs_scope.h Thu May 06 16:07:05 2021 +0300 @@ -83,7 +83,7 @@ njs_scope_valid_value(njs_vm_t *vm, njs_ if (!njs_is_valid(value)) { if (njs_scope_index_var(index) <= NJS_VARIABLE_LET) { - njs_reference_error(vm, "cannot access to variable " + njs_reference_error(vm, "cannot access variable " "before initialization"); return NULL; } diff -r f58a06be33dc -r a0bb54faa1b2 src/njs_vmcode.c --- a/src/njs_vmcode.c Fri Apr 30 16:02:34 2021 +0300 +++ b/src/njs_vmcode.c Thu May 06 16:07:05 2021 +0300 @@ -930,7 +930,7 @@ next: /* Fall through. */ case NJS_VMCODE_NOT_INITIALIZED: - njs_reference_error(vm, "cannot access to variable " + njs_reference_error(vm, "cannot access variable " "before initialization"); goto error; diff -r f58a06be33dc -r a0bb54faa1b2 src/test/njs_unit_test.c --- a/src/test/njs_unit_test.c Fri Apr 30 16:02:34 2021 +0300 +++ b/src/test/njs_unit_test.c Thu May 06 16:07:05 2021 +0300 @@ -19809,22 +19809,22 @@ static njs_unit_test_t njs_test[] = njs_str("[object Function]") }, { njs_str("let x = (() => x)()"), - njs_str("ReferenceError: cannot access to variable before initialization") }, + njs_str("ReferenceError: cannot access variable before initialization") }, { njs_str("x; let x"), - njs_str("ReferenceError: cannot access to variable before initialization") }, + njs_str("ReferenceError: cannot access variable before initialization") }, { njs_str("x; let x = 123"), - njs_str("ReferenceError: cannot access to variable before initialization") }, + njs_str("ReferenceError: cannot access variable before initialization") }, { njs_str("let x = x + 123"), - njs_str("ReferenceError: cannot access to variable before initialization") }, + njs_str("ReferenceError: cannot access variable before initialization") }, { njs_str("let x = (x, 1)"), - njs_str("ReferenceError: cannot access to variable before initialization") }, + njs_str("ReferenceError: cannot access variable before initialization") }, { njs_str("let x = x"), - njs_str("ReferenceError: cannot access to variable before initialization") }, + njs_str("ReferenceError: cannot access variable before initialization") }, { njs_str("let x; var x"), njs_str("SyntaxError: \"x\" has already been declared in 1") }, @@ -19870,7 +19870,7 @@ static njs_unit_test_t njs_test[] = { njs_str("function func() {return x}" "func();" "let x = 123"), - njs_str("ReferenceError: cannot access to variable before initialization") }, + njs_str("ReferenceError: cannot access variable before initialization") }, { njs_str("function func() {return () => x}" "let x = 123;" @@ -19883,7 +19883,7 @@ static njs_unit_test_t njs_test[] = { njs_str("function func() {return () => x}" "func()();" "let x = 123;"), - njs_str("ReferenceError: cannot access to variable before initialization") }, + njs_str("ReferenceError: cannot access variable before initialization") }, { njs_str("var arr = [];" "" @@ -19914,7 +19914,7 @@ static njs_unit_test_t njs_test[] = { njs_str("for (let i = 0; i < 1; i++) {" " let i = i + 2;" "}"), - njs_str("ReferenceError: cannot access to variable before initialization") }, + njs_str("ReferenceError: cannot access variable before initialization") }, { njs_str("let arr = [], res = [];" "for (let i = 0, f = function() { return i }; i < 5; i++) {" @@ -19960,14 +19960,14 @@ static njs_unit_test_t njs_test[] = { njs_str("for (let n in [1,2,3]) {" " let n = n + 1;" "}"), - njs_str("ReferenceError: cannot access to variable before initialization") }, + njs_str("ReferenceError: cannot access variable before initialization") }, { njs_str("for (let n in [1,2,3]) {}" "n"), njs_str("ReferenceError: \"n\" is not defined") }, { njs_str("for (let n in [1,n,3]) {}"), - njs_str("ReferenceError: cannot access to variable before initialization") }, + njs_str("ReferenceError: cannot access variable before initialization") }, { njs_str("(function() {" "function f() {return x + 1}" @@ -19975,10 +19975,10 @@ static njs_unit_test_t njs_test[] = "abc();" "let x;" "}())"), - njs_str("ReferenceError: cannot access to variable before initialization") }, + njs_str("ReferenceError: cannot access variable before initialization") }, { njs_str("function func() {var x = 1; {let x = x + 1} } func()"), - njs_str("ReferenceError: cannot access to variable before initialization") }, + njs_str("ReferenceError: cannot access variable before initialization") }, { njs_str("if (false) let x = 1"), njs_str("SyntaxError: let declaration cannot appear in a single-statement context in 1") }, @@ -19998,7 +19998,7 @@ static njs_unit_test_t njs_test[] = njs_str("1,2") }, { njs_str("switch(true) {case false: let x = 1; default: x = 2}"), - njs_str("ReferenceError: cannot access to variable before initialization") }, + njs_str("ReferenceError: cannot access variable before initialization") }, { njs_str("let res;" "switch(true) {case true: let x = 1; default: x = 2; res = x} res"), @@ -20017,7 +20017,7 @@ static njs_unit_test_t njs_test[] = njs_str("undefined") }, { njs_str("if (false) {x = 2} else {x = 1} let x;"), - njs_str("ReferenceError: cannot access to variable before initialization") }, + njs_str("ReferenceError: cannot access variable before initialization") }, { njs_str("let let"), njs_str("SyntaxError: Unexpected token \"let\" in 1") }, @@ -20052,13 +20052,13 @@ static njs_unit_test_t njs_test[] = njs_str("[object Function]") }, { njs_str("const x = (() => x)()"), - njs_str("ReferenceError: cannot access to variable before initialization") }, + njs_str("ReferenceError: cannot access variable before initialization") }, { njs_str("x; const x = 123"), - njs_str("ReferenceError: cannot access to variable before initialization") }, + njs_str("ReferenceError: cannot access variable before initialization") }, { njs_str("const x = x + 123"), - njs_str("ReferenceError: cannot access to variable before initialization") }, + njs_str("ReferenceError: cannot access variable before initialization") }, { njs_str("const x; var x"), njs_str("SyntaxError: \"x\" has already been declared in 1") }, @@ -20102,7 +20102,7 @@ static njs_unit_test_t njs_test[] = { njs_str("function func() {return x}" "func();" "const x = 123"), - njs_str("ReferenceError: cannot access to variable before initialization") }, + njs_str("ReferenceError: cannot access variable before initialization") }, { njs_str("function func() {return () => x}" "const x = 123;" @@ -20146,14 +20146,14 @@ static njs_unit_test_t njs_test[] = { njs_str("for (const n in [1,2,3]) {" " let n = n + 1;" "}"), - njs_str("ReferenceError: cannot access to variable before initialization") }, + njs_str("ReferenceError: cannot access variable before initialization") }, { njs_str("for (const n in [1,2,3]) {}" "n"), njs_str("ReferenceError: \"n\" is not defined") }, { njs_str("for (const n in [1,n,3]) {}"), - njs_str("ReferenceError: cannot access to variable before initialization") }, + njs_str("ReferenceError: cannot access variable before initialization") }, { njs_str("(function() {" "function f() {return x + 1}" @@ -20161,7 +20161,7 @@ static njs_unit_test_t njs_test[] = "abc();" "const x = 1;" "}())"), - njs_str("ReferenceError: cannot access to variable before initialization") }, + njs_str("ReferenceError: cannot access variable before initialization") }, { njs_str("if (false) const x = 1"), njs_str("SyntaxError: const declaration cannot appear in a single-statement context in 1") }, @@ -20197,7 +20197,7 @@ static njs_unit_test_t njs_test[] = njs_str("undefined") }, { njs_str("if (false) {x = 2} else {x = 1} const x = 0"), - njs_str("ReferenceError: cannot access to variable before initialization") }, + njs_str("ReferenceError: cannot access variable before initialization") }, { njs_str("const const"), njs_str("SyntaxError: Unexpected token \"const\" in 1") }, From alexander.borisov at nginx.com Thu May 6 13:18:36 2021 From: alexander.borisov at nginx.com (Alexander Borisov) Date: Thu, 06 May 2021 13:18:36 +0000 Subject: [njs] Removed unnecessary NULL checks introduced in 0a2a0b5a74f4. Message-ID: details: https://hg.nginx.org/njs/rev/5563f2cbce5b branches: changeset: 1634:5563f2cbce5b user: Alexander Borisov date: Thu May 06 16:07:06 2021 +0300 description: Removed unnecessary NULL checks introduced in 0a2a0b5a74f4. Found by Coverity (CID 1478008). diffstat: src/njs_variable.c | 10 ++++------ 1 files changed, 4 insertions(+), 6 deletions(-) diffs (34 lines): diff -r a0bb54faa1b2 -r 5563f2cbce5b src/njs_variable.c --- a/src/njs_variable.c Thu May 06 16:07:05 2021 +0300 +++ b/src/njs_variable.c Thu May 06 16:07:06 2021 +0300 @@ -437,7 +437,7 @@ njs_variable_closure(njs_vm_t *vm, njs_v njs_index_t index, prev_index, *idx; njs_level_type_t type; njs_rbtree_node_t *rb_node; - njs_parser_scope_t **p, *root; + njs_parser_scope_t **p; njs_parser_rbtree_node_t *parse_node, ref_node; #define NJS_VAR_MAX_DEPTH 32 njs_parser_scope_t *list[NJS_VAR_MAX_DEPTH]; @@ -482,18 +482,16 @@ njs_variable_closure(njs_vm_t *vm, njs_v } } - root = njs_function_scope(scope); - - if (type != NJS_LEVEL_CLOSURE && root == scope) { + if (type != NJS_LEVEL_CLOSURE) { /* Create new closure for scope. */ - index = njs_scope_index(root->type, root->closures->items, + index = njs_scope_index(scope->type, scope->closures->items, NJS_LEVEL_CLOSURE, var->type); if (njs_slow_path(index == NJS_INDEX_ERROR)) { return NJS_INDEX_ERROR; } - idx = njs_arr_add(root->closures); + idx = njs_arr_add(scope->closures); if (njs_slow_path(idx == NULL)) { return NJS_INDEX_ERROR; } From alexander.borisov at nginx.com Thu May 6 13:18:37 2021 From: alexander.borisov at nginx.com (Alexander Borisov) Date: Thu, 06 May 2021 13:18:37 +0000 Subject: [njs] Removed unnecessary NULL checks introduced in 0a2a0b5a74f4. Message-ID: details: https://hg.nginx.org/njs/rev/c1829352e49c branches: changeset: 1635:c1829352e49c user: Alexander Borisov date: Thu May 06 16:07:08 2021 +0300 description: Removed unnecessary NULL checks introduced in 0a2a0b5a74f4. Found by Coverity (CID 1478004). diffstat: src/njs_parser.c | 2 +- 1 files changed, 1 insertions(+), 1 deletions(-) diffs (12 lines): diff -r 5563f2cbce5b -r c1829352e49c src/njs_parser.c --- a/src/njs_parser.c Thu May 06 16:07:06 2021 +0300 +++ b/src/njs_parser.c Thu May 06 16:07:08 2021 +0300 @@ -7827,7 +7827,7 @@ njs_parser_reference(njs_parser_t *parse scope = njs_function_scope(scope->parent); } - if (scope == NULL || scope->type == NJS_SCOPE_GLOBAL) { + if (scope->type == NJS_SCOPE_GLOBAL) { njs_parser_syntax_error(parser, "\"%V\" object in global scope", &token->text); return NULL; From alexander.borisov at nginx.com Thu May 6 13:18:39 2021 From: alexander.borisov at nginx.com (Alexander Borisov) Date: Thu, 06 May 2021 13:18:39 +0000 Subject: [njs] Removed check variable type for CLI completions. Message-ID: details: https://hg.nginx.org/njs/rev/637bc81166a6 branches: changeset: 1636:637bc81166a6 user: Alexander Borisov date: Thu May 06 16:07:09 2021 +0300 description: Removed check variable type for CLI completions. Found by Coverity (CID 1478003). diffstat: src/njs_builtin.c | 2 +- 1 files changed, 1 insertions(+), 1 deletions(-) diffs (12 lines): diff -r c1829352e49c -r 637bc81166a6 src/njs_builtin.c --- a/src/njs_builtin.c Thu May 06 16:07:08 2021 +0300 +++ b/src/njs_builtin.c Thu May 06 16:07:09 2021 +0300 @@ -639,7 +639,7 @@ njs_vm_expression_completions(njs_vm_t * } var = ((njs_variable_node_t *) node)->variable; - value = njs_scope_valid_value(vm, var->index); + value = njs_scope_value(vm, var->index); if (!njs_is_object(value)) { return NULL; From sander at hoentjen.eu Thu May 6 20:14:43 2021 From: sander at hoentjen.eu (Sander Hoentjen) Date: Thu, 6 May 2021 22:14:43 +0200 Subject: [PATCH] Added support for proxying managesieve protocol In-Reply-To: References: <58016a3a-c11d-bb31-2b05-916cb8124598@hoentjen.eu> <89afc309-4185-e0a1-d6d3-e9f25f65235a@hoentjen.eu> <911a2e90-5002-3e1c-eb9a-6be3f4e329fc@nginx.com> Message-ID: <0aa27eba-7662-b164-d409-08710ed5a23e@hoentjen.eu> It is now May, albeit a year later ;) Any chance of this being accepted? If so I can bring it up to date on github. In the meantime we are using this for 18 months now, without issues. Kind regards, Sander On 16-04-2020 19:49, Sander Hoentjen wrote: > Hi Maxim, > > Thanks for your response! I will wait till you have time to properly > review my code. That is more important than getting it in fast. > > The code is available at > https://github.com/AntagonistHQ/nginx/tree/sieve_v2, so at least it is > out in the public for anyone interested. > > For now, I'll just wait and see what will happen in May. > > Thank you, > > Sander > > > On 4/15/20 8:56 PM, Maxim Konovalov wrote: >> Hi Sander, >> >> First of all, thanks for your code contribution and your work done on >> it. >> >> Among with other tasks we are now in a preparation for a new development >> branch 1.19 and don't have much developers resources to make a proper >> review of the code. >> >> I'd suggest to put the module somewhere on external repo for now, e.g. >> on github.? I hope we'll be able to return to this topic later in May. >> >> Thanks, >> >> Maxim >> >> On 14.04.2020 21:27, Sander Hoentjen wrote: >>> Hello list, >>> >>> Since the Nginx development procedure is unknown to me: Did i do the >>> right things to get my submission to be considered? What are the next >>> steps? Will somebody review this, or reject it? Or is it possible that >>> it just won't get any attention, and that this will mean it will not be >>> considered? I hope I will at least get some feedback, even if it is a >>> rejection :) >>> >>> Kind regards, >>> >>> Sander >>> >>> On 4/8/20 8:33 PM, Sander Hoentjen wrote: >>>> Hello list, >>>> >>>> This is my attempt at adding support for the managesieve protocol. I >>>> hope this is something that you would consider to add. Comments on the >>>> code are very welcome! Also, I hope I submitted this the right way. If >>>> I need to change anything, please let me know. >>>> >>>> Kind regards, >>>> >>>> Sander Hoentjen >>>> >>>> On 4/8/20 8:26 PM, Sander Hoentjen wrote: >>>>> # HG changeset patch >>>>> # User Sander Hoentjen >>>>> # Date 1586369831 -7200 >>>>> # Wed Apr 08 20:17:11 2020 +0200 >>>>> # Node ID f1dffaf619688aaab90caf31781ebe27c3f79598 >>>>> # Parent 0cb942c1c1aa98118076e72e0b89940e85e6291c >>>>> Added support for proxying managesieve protocol >>>>> >> [...] >> >> > _______________________________________________ > nginx-devel mailing list > nginx-devel at nginx.org > http://mailman.nginx.org/mailman/listinfo/nginx-devel > From mdounin at mdounin.ru Sat May 8 17:32:02 2021 From: mdounin at mdounin.ru (Maxim Dounin) Date: Sat, 08 May 2021 17:32:02 +0000 Subject: [nginx] MIME: added application/wasm type (ticket #1606). Message-ID: details: https://hg.nginx.org/nginx/rev/b3f4d83d6fd0 branches: changeset: 7834:b3f4d83d6fd0 user: Maxim Dounin date: Sat May 08 20:31:03 2021 +0300 description: MIME: added application/wasm type (ticket #1606). diffstat: conf/mime.types | 1 + 1 files changed, 1 insertions(+), 0 deletions(-) diffs (11 lines): diff -r 3ab8e1e2f0f7 -r b3f4d83d6fd0 conf/mime.types --- a/conf/mime.types Thu May 06 02:22:09 2021 +0300 +++ b/conf/mime.types Sat May 08 20:31:03 2021 +0300 @@ -51,6 +51,7 @@ types { application/vnd.openxmlformats-officedocument.wordprocessingml.document docx; application/vnd.wap.wmlc wmlc; + application/wasm wasm; application/x-7z-compressed 7z; application/x-cocoa cco; application/x-java-archive-diff jardiff; From awiens at mail.uni-paderborn.de Sun May 9 00:50:14 2021 From: awiens at mail.uni-paderborn.de (Alex Wiens) Date: Sun, 9 May 2021 02:50:14 +0200 Subject: [PATCH] http_image_filter_module: Add HEIC and AVIF support / Add output format option Message-ID: <6983ead5-f535-b607-2ae8-f2ac0a49a550@mail.uni-paderborn.de> Hi, here are two patches for the image_filter module. The first patch adds HEIC and AVIF support after libgd also added support for this image formats. The second patch adds an option to change the output format. This also allows to simply convert the image to a different format without applying an operation. Kind regards, Alex Wiens -------------- next part -------------- # HG changeset patch # User Alex Wiens # Date 1620489773 -7200 # Sat May 08 18:02:53 2021 +0200 # Node ID 08373a6af4f3c6d0757253afb121466f25f4e743 # Parent 0d0a29bb3c2fb4ae8a0f49e889f368f741dfe0f0 http_image_filter_module: Add output format option This change makes it possible to specify the output format of the generated images. The option can be used in combination with other filters or standalone to simply convert the image. As such one can generate images in more efficiently compressed image formats without manually convert and store all format files. This allows to serve multiple image formats and specify the alternatives in an HTML picture tag. The browser can then select an appropriate format. A caching server can be used to avoid reconverting the same image multiple times. The following filter command allows to configure the output format: * image_filter convert TYPE If no other filter is set, then the unchanged image will be converted to the output format. Possible values for TYPE: input, jpeg, gif, png, webp, heic, avif. The default value is: input. For the value `input` the format of the input file is used, which is the behavior before the change. diff -r 0d0a29bb3c2f -r 08373a6af4f3 contrib/vim/syntax/nginx.vim --- a/contrib/vim/syntax/nginx.vim Sat May 08 18:02:29 2021 +0200 +++ b/contrib/vim/syntax/nginx.vim Sat May 08 18:02:53 2021 +0200 @@ -328,6 +328,7 @@ syn keyword ngxDirective contained image_filter_heic_quality syn keyword ngxDirective contained image_filter_avif_quality syn keyword ngxDirective contained image_filter_avif_speed +syn keyword ngxDirective contained image_filter_output_format syn keyword ngxDirective contained imap_auth syn keyword ngxDirective contained imap_capabilities syn keyword ngxDirective contained imap_client_buffer diff -r 0d0a29bb3c2f -r 08373a6af4f3 src/http/modules/ngx_http_image_filter_module.c --- a/src/http/modules/ngx_http_image_filter_module.c Sat May 08 18:02:29 2021 +0200 +++ b/src/http/modules/ngx_http_image_filter_module.c Sat May 08 18:02:53 2021 +0200 @@ -18,6 +18,7 @@ #define NGX_HTTP_IMAGE_RESIZE 3 #define NGX_HTTP_IMAGE_CROP 4 #define NGX_HTTP_IMAGE_ROTATE 5 +#define NGX_HTTP_IMAGE_CONVERT 6 #define NGX_HTTP_IMAGE_START 0 @@ -50,6 +51,7 @@ ngx_int_t avif_quality; ngx_int_t avif_speed; ngx_uint_t sharpen; + ngx_uint_t output_format; ngx_flag_t transparency; ngx_flag_t interlace; @@ -63,6 +65,7 @@ ngx_http_complex_value_t *aqcv; ngx_http_complex_value_t *ascv; ngx_http_complex_value_t *shcv; + ngx_http_complex_value_t *ofcv; size_t buffer_size; } ngx_http_image_filter_conf_t; @@ -82,6 +85,7 @@ ngx_uint_t phase; ngx_uint_t type; + ngx_uint_t output_type; ngx_uint_t force; } ngx_http_image_filter_ctx_t; @@ -110,6 +114,8 @@ static void ngx_http_image_cleanup(void *data); static ngx_uint_t ngx_http_image_filter_get_value(ngx_http_request_t *r, ngx_http_complex_value_t *cv, ngx_uint_t v); +static ngx_uint_t ngx_http_image_filter_get_output_format(ngx_http_request_t *r, + ngx_http_complex_value_t *cv, ngx_uint_t v); static ngx_uint_t ngx_http_image_filter_value(ngx_str_t *value); @@ -253,6 +259,16 @@ ngx_string("image/avif") }; +static ngx_str_t ngx_http_image_output_types[] = { + ngx_string("input"), + ngx_string("jpeg"), + ngx_string("gif"), + ngx_string("png"), + ngx_string("webp"), + ngx_string("heic"), + ngx_string("avif") +}; + static ngx_int_t ngx_http_image_header_filter(ngx_http_request_t *r) @@ -373,8 +389,15 @@ } /* override content type */ - - ct = &ngx_http_image_types[ctx->type - 1]; + ctx->output_type = ngx_http_image_filter_get_output_format(r, + conf->ofcv, conf->output_format); + if (ctx->output_type == NGX_HTTP_IMAGE_NONE + || ctx->output_type == NGX_CONF_UNSET_UINT) { + + ctx->output_type = ctx->type; + } + + ct = &ngx_http_image_types[ctx->output_type - 1]; r->headers_out.content_type_len = ct->len; r->headers_out.content_type = *ct; r->headers_out.content_type_lowcase = NULL; @@ -639,6 +662,17 @@ return ngx_http_image_resize(r, ctx); } + if (conf->filter == NGX_HTTP_IMAGE_CONVERT) { + + if (ctx->output_type == ctx->type) { + + /* No conversion necessary */ + return ngx_http_image_asis(r, ctx); + } + + return ngx_http_image_resize(r, ctx); + } + ctx->max_width = ngx_http_image_filter_get_value(r, conf->wcv, conf->width); if (ctx->max_width == 0) { return NULL; @@ -1126,7 +1160,8 @@ if (!ctx->force && ctx->angle == 0 && (ngx_uint_t) sx <= ctx->max_width - && (ngx_uint_t) sy <= ctx->max_height) + && (ngx_uint_t) sy <= ctx->max_height + && conf->filter != NGX_HTTP_IMAGE_CONVERT) { gdImageDestroy(src); return ngx_http_image_asis(r, ctx); @@ -1157,6 +1192,12 @@ gdImageColorTransparent(src, -1); + /* no operation, just convert untouched image */ + if (conf->filter == NGX_HTTP_IMAGE_CONVERT) { + dst = src; + goto output; + } + dx = sx; dy = sy; @@ -1332,7 +1373,8 @@ gdImageInterlace(dst, (int) conf->interlace); - out = ngx_http_image_out(r, ctx->type, dst, &size); +output: + out = ngx_http_image_out(r, ctx->output_type, dst, &size); ngx_log_debug3(NGX_LOG_DEBUG_HTTP, r->connection->log, 0, "image: %d x %d %d", sx, sy, colors); @@ -1611,6 +1653,35 @@ } +static ngx_uint_t +ngx_http_image_filter_get_output_format(ngx_http_request_t *r, + ngx_http_complex_value_t *cv, ngx_uint_t v) +{ + ngx_str_t val; + ngx_uint_t of = NGX_CONF_UNSET_UINT; + + if (cv == NULL) { + return v; + } + + if (ngx_http_complex_value(r, cv, &val) != NGX_OK) { + return v; + } + for (uint i = 0; i < 7; i++) { + if (val.len == ngx_http_image_output_types[i].len + && ngx_strncmp(ngx_http_image_output_types[i].data, val.data, + ngx_http_image_output_types[i].len) == 0) { + of = i; + break; + } + } + if (of == NGX_CONF_UNSET_UINT) { + return v; + } + return of; +} + + static void * ngx_http_image_filter_create_conf(ngx_conf_t *cf) { @@ -1633,6 +1704,7 @@ * conf->jqcv = NULL; * conf->wqcv = NULL; * conf->shcv = NULL; + * conf->ofcv = NULL; */ conf->filter = NGX_CONF_UNSET_UINT; @@ -1645,6 +1717,7 @@ conf->transparency = NGX_CONF_UNSET; conf->interlace = NGX_CONF_UNSET; conf->buffer_size = NGX_CONF_UNSET_SIZE; + conf->output_format = NGX_CONF_UNSET_UINT; return conf; } @@ -1727,6 +1800,16 @@ } } + if (conf->output_format == NGX_CONF_UNSET_UINT) { + ngx_conf_merge_uint_value(conf->output_format, prev->output_format, + NGX_HTTP_IMAGE_NONE); + + if (conf->ofcv == NULL) { + conf->ofcv = prev->ofcv; + } + } + + ngx_conf_merge_value(conf->transparency, prev->transparency, 1); ngx_conf_merge_value(conf->interlace, prev->interlace, 0); @@ -1809,6 +1892,56 @@ return NGX_CONF_OK; + } else if (ngx_strcmp(value[i].data, "convert") == 0) { + + /* set filter to convert if no other filter is active */ + if (imcf->filter == NGX_CONF_UNSET_UINT + || imcf->filter == NGX_HTTP_IMAGE_OFF) { + + imcf->filter = NGX_HTTP_IMAGE_CONVERT; + } + + /* check output format parameter */ + ngx_memzero(&ccv, sizeof(ngx_http_compile_complex_value_t)); + + ccv.cf = cf; + ccv.value = &value[++i]; + ccv.complex_value = &cv; + + if (ngx_http_compile_complex_value(&ccv) != NGX_OK) { + return NGX_CONF_ERROR; + } + + if (cv.lengths == NULL) { + + n = NGX_CONF_UNSET; + for (uint j = 0; j < 7; j++) { + if (ngx_strncmp(ngx_http_image_output_types[j].data, value[i].data, + ngx_http_image_output_types[j].len) == 0) { + n = j; + break; + } + } + if (n == NGX_CONF_UNSET) { + + ngx_conf_log_error(NGX_LOG_EMERG, cf, 0, "invalid parameter \"%V\"", + &value[i]); + + return NGX_CONF_ERROR; + } + imcf->output_format = (ngx_uint_t) n; + + } else { + imcf->ofcv = ngx_palloc(cf->pool, sizeof(ngx_http_complex_value_t)); + if (imcf->ofcv == NULL) { + return NGX_CONF_ERROR; + } + + *imcf->ofcv = cv; + } + + return NGX_CONF_OK; + } else { goto failed; } -------------- next part -------------- # HG changeset patch # User Alex Wiens # Date 1620489749 -7200 # Sat May 08 18:02:29 2021 +0200 # Node ID 0d0a29bb3c2fb4ae8a0f49e889f368f741dfe0f0 # Parent 3ab8e1e2f0f7ec6527003047565f4470e1e294b8 http_image_filter_module: Add HEIC and AVIF support Libgd added support for HEIC (HEVC encoded images in HEIF containers) and AVIF (AV1 encoded images in HEIF containers). Support for this formats is added to the image_filter_module similarly as with the WebP format. HEIC is used as the name for the fileformat containing HEVC inside HEIF containers to avoid confusion between HEIF, HEIC and AVIF. These new formats improve compression efficiency over older formats such as JPEG. At the moment browser support is in development and it is unclear if and which format will dominate usage on the web. Therefore, support for both formats is added, which is straightforward when using libgd. The following new configuration commands are added: * image_filter_heic_quality: 0-100 or 200 for lossless Larger values result in better quality and larger file size. * image_filter_avif_quality: 0-100 Larger values result in better quality and larger file size. * image_filter_avif_speed: 0-10 Larger values result in faster encoding and lower compression ratio. If the options are not set, -1 is passed to libgd to use the default value. The autotools tests for WebP, HEIC and AVIF support in libgd have been fixed. Libgd without support for these formats includes the API functions, but calling them always results in an error. Therefore, the test compilation always succeeds even if the format is not supported. The new test must be executed and calls the libgd check for filetype support. diff -r 3ab8e1e2f0f7 -r 0d0a29bb3c2f auto/lib/libgd/conf --- a/auto/lib/libgd/conf Thu May 06 02:22:09 2021 +0300 +++ b/auto/lib/libgd/conf Sat May 08 18:02:29 2021 +0200 @@ -77,8 +77,21 @@ ngx_feature="GD WebP support" ngx_feature_name="NGX_HAVE_GD_WEBP" - ngx_feature_test="gdImagePtr img = gdImageCreateFromWebpPtr(1, NULL); - (void) img" + ngx_feature_run=yes + ngx_feature_test="return ! gdSupportsFileType(\"test.webp\", 1)" + + . auto/feature + + ngx_feature="GD HEIC support" + ngx_feature_name="NGX_HAVE_GD_HEIC" + ngx_feature_run=yes + ngx_feature_test="return ! gdSupportsFileType(\"test.heic\", 1)" + . auto/feature + + ngx_feature="GD AVIF support" + ngx_feature_name="NGX_HAVE_GD_AVIF" + ngx_feature_run=yes + ngx_feature_test="return ! gdSupportsFileType(\"test.avif\", 1)" . auto/feature else diff -r 3ab8e1e2f0f7 -r 0d0a29bb3c2f contrib/vim/syntax/nginx.vim --- a/contrib/vim/syntax/nginx.vim Thu May 06 02:22:09 2021 +0300 +++ b/contrib/vim/syntax/nginx.vim Sat May 08 18:02:29 2021 +0200 @@ -325,6 +325,9 @@ syn keyword ngxDirective contained image_filter_sharpen syn keyword ngxDirective contained image_filter_transparency syn keyword ngxDirective contained image_filter_webp_quality +syn keyword ngxDirective contained image_filter_heic_quality +syn keyword ngxDirective contained image_filter_avif_quality +syn keyword ngxDirective contained image_filter_avif_speed syn keyword ngxDirective contained imap_auth syn keyword ngxDirective contained imap_capabilities syn keyword ngxDirective contained imap_client_buffer diff -r 3ab8e1e2f0f7 -r 0d0a29bb3c2f src/http/modules/ngx_http_image_filter_module.c --- a/src/http/modules/ngx_http_image_filter_module.c Thu May 06 02:22:09 2021 +0300 +++ b/src/http/modules/ngx_http_image_filter_module.c Sat May 08 18:02:29 2021 +0200 @@ -32,6 +32,8 @@ #define NGX_HTTP_IMAGE_GIF 2 #define NGX_HTTP_IMAGE_PNG 3 #define NGX_HTTP_IMAGE_WEBP 4 +#define NGX_HTTP_IMAGE_HEIC 5 +#define NGX_HTTP_IMAGE_AVIF 6 #define NGX_HTTP_IMAGE_BUFFERED 0x08 @@ -44,6 +46,9 @@ ngx_uint_t angle; ngx_uint_t jpeg_quality; ngx_uint_t webp_quality; + ngx_int_t heic_quality; + ngx_int_t avif_quality; + ngx_int_t avif_speed; ngx_uint_t sharpen; ngx_flag_t transparency; @@ -54,6 +59,9 @@ ngx_http_complex_value_t *acv; ngx_http_complex_value_t *jqcv; ngx_http_complex_value_t *wqcv; + ngx_http_complex_value_t *hqcv; + ngx_http_complex_value_t *aqcv; + ngx_http_complex_value_t *ascv; ngx_http_complex_value_t *shcv; size_t buffer_size; @@ -114,6 +122,12 @@ ngx_command_t *cmd, void *conf); static char *ngx_http_image_filter_webp_quality(ngx_conf_t *cf, ngx_command_t *cmd, void *conf); +static char *ngx_http_image_filter_heic_quality(ngx_conf_t *cf, + ngx_command_t *cmd, void *conf); +static char *ngx_http_image_filter_avif_quality(ngx_conf_t *cf, + ngx_command_t *cmd, void *conf); +static char *ngx_http_image_filter_avif_speed(ngx_conf_t *cf, + ngx_command_t *cmd, void *conf); static char *ngx_http_image_filter_sharpen(ngx_conf_t *cf, ngx_command_t *cmd, void *conf); static ngx_int_t ngx_http_image_filter_init(ngx_conf_t *cf); @@ -142,6 +156,27 @@ 0, NULL }, + { ngx_string("image_filter_heic_quality"), + NGX_HTTP_MAIN_CONF|NGX_HTTP_SRV_CONF|NGX_HTTP_LOC_CONF|NGX_CONF_TAKE1, + ngx_http_image_filter_heic_quality, + NGX_HTTP_LOC_CONF_OFFSET, + 0, + NULL }, + + { ngx_string("image_filter_avif_quality"), + NGX_HTTP_MAIN_CONF|NGX_HTTP_SRV_CONF|NGX_HTTP_LOC_CONF|NGX_CONF_TAKE1, + ngx_http_image_filter_avif_quality, + NGX_HTTP_LOC_CONF_OFFSET, + 0, + NULL }, + + { ngx_string("image_filter_avif_speed"), + NGX_HTTP_MAIN_CONF|NGX_HTTP_SRV_CONF|NGX_HTTP_LOC_CONF|NGX_CONF_TAKE1, + ngx_http_image_filter_avif_speed, + NGX_HTTP_LOC_CONF_OFFSET, + 0, + NULL }, + { ngx_string("image_filter_sharpen"), NGX_HTTP_MAIN_CONF|NGX_HTTP_SRV_CONF|NGX_HTTP_LOC_CONF|NGX_CONF_TAKE1, ngx_http_image_filter_sharpen, @@ -213,7 +248,9 @@ ngx_string("image/jpeg"), ngx_string("image/gif"), ngx_string("image/png"), - ngx_string("image/webp") + ngx_string("image/webp"), + ngx_string("image/heic"), + ngx_string("image/avif") }; @@ -423,7 +460,9 @@ static ngx_uint_t ngx_http_image_test(ngx_http_request_t *r, ngx_chain_t *in) { - u_char *p; + u_char *p; + uint32_t heif_ftyp_len; + uint32_t heif_brand_offset; p = in->buf->pos; @@ -461,6 +500,55 @@ /* WebP */ return NGX_HTTP_IMAGE_WEBP; + } else if (p[4] == 'f' && p[5] == 't' && p[6] == 'y' && p[7] == 'p') + { + /* HEIF container for HEIC and AVIF */ + + if (p[8] == 'h' && p[9] == 'e' && p[10] == 'i' && p[11] == 'c') { + + /* main brand HEIC */ + return NGX_HTTP_IMAGE_HEIC; + } + + if (p[8] == 'a' && p[9] == 'v' && p[10] == 'i' && p[11] == 'f') { + + /* main brand AVIF */ + return NGX_HTTP_IMAGE_AVIF; + } + + + heif_ftyp_len = (p[0] << 24) | (p[1] << 16) | + (p[2] << 8) | (p[3]); + + if (in->buf->last - p < heif_ftyp_len) { + return NGX_HTTP_IMAGE_NONE; + } + + /* iterate over compatible brands */ + heif_brand_offset = 16; + while (heif_brand_offset+3 < heif_ftyp_len) { + + if (p[heif_brand_offset] == 'h' + && p[heif_brand_offset+1] == 'e' + && p[heif_brand_offset+2] == 'i' + && p[heif_brand_offset+3] == 'c') { + + return NGX_HTTP_IMAGE_HEIC; + } + + if (p[heif_brand_offset] == 'a' + && p[heif_brand_offset+1] == 'v' + && p[heif_brand_offset+2] == 'i' + && p[heif_brand_offset+3] == 'f') { + + return NGX_HTTP_IMAGE_AVIF; + } + + heif_brand_offset += 4; + } + + /* HEIC or AVIF not found in compatible brand list */ + } return NGX_HTTP_IMAGE_NONE; @@ -668,6 +756,11 @@ u_char *p, *last; size_t len, app; ngx_uint_t width, height; + int heif_compatible; + uint64_t heif_box_len; + uint64_t heif_box_offset; + uint64_t heif_sub_len; + uint64_t heif_sub_offset; p = ctx->image; @@ -801,6 +894,196 @@ break; + case NGX_HTTP_IMAGE_HEIC: + case NGX_HTTP_IMAGE_AVIF: + { + + if (ctx->length < 12) { + return NGX_DECLINED; + } + + /* check ftyp box */ + heif_box_len = (p[0] << 24) | (p[1] << 16) | + (p[2] << 8) | (p[3]); + if (ctx->length < heif_box_len || heif_box_len < 12) { + return NGX_DECLINED; + } + + if (p[4] != 'f' || p[5] != 't' || p[6] != 'y' || p[7] != 'p') { + + return NGX_DECLINED; + } + + heif_compatible = 0; + + /* check file brand HEIC */ + if ((ctx->type == NGX_HTTP_IMAGE_HEIC) && + (p[8] == 'h') && (p[9] == 'e') && (p[10] == 'i') && (p[11] == 'c')) + { + heif_compatible = 1; + } + + /* check file brand AVIF */ + if ((ctx->type == NGX_HTTP_IMAGE_AVIF) && + (p[8] == 'a') && (p[9] == 'v') && (p[10] == 'i') && (p[11] == 'f')) + { + heif_compatible = 1; + } + + if (heif_compatible == 0) { + + /* check compatbile brand */ + + /* iterate over compatible brands */ + heif_box_offset = 16; + while (heif_box_offset+3 < heif_box_len) { + + if (ctx->type == NGX_HTTP_IMAGE_HEIC + && p[heif_box_offset] == 'h' + && p[heif_box_offset+1] == 'e' + && p[heif_box_offset+2] == 'i' + && p[heif_box_offset+3] == 'c') { + + heif_compatible = 1; + break; + } + + if (ctx->type == NGX_HTTP_IMAGE_AVIF + && p[heif_box_offset] == 'a' + && p[heif_box_offset+1] == 'v' + && p[heif_box_offset+2] == 'i' + && p[heif_box_offset+3] == 'f') { + + heif_compatible = 1; + break; + } + + heif_box_offset += 4; + } + + if (heif_compatible == 0) { + return NGX_DECLINED; + } + } + + if (ctx->length < heif_box_len + 8) { + return NGX_DECLINED; + } + + /* continue with boxes after ftyp */ + + heif_box_offset = heif_box_len; + heif_box_len = 0; + /* skip boxes until meta box */ + while (heif_box_offset+8 < ctx->length) { + + /* read box length */ + heif_box_len = (p[heif_box_offset] << 24) + | (p[heif_box_offset+1] << 16) + | (p[heif_box_offset+2] << 8) + | (p[heif_box_offset+3]); + /* check for extended length */ + if (heif_box_len == 1) { + if (heif_box_offset+16 >= ctx->length) { + return NGX_DECLINED; + } + heif_box_len = (((uint64_t) p[heif_box_offset+8]) << 56) + | (((uint64_t) p[heif_box_offset+9]) << 48) + | (((uint64_t) p[heif_box_offset+10]) << 40) + | (((uint64_t) p[heif_box_offset+11]) << 32) + | (p[heif_box_offset+12] << 24) + | (p[heif_box_offset+13] << 16) + | (p[heif_box_offset+14] << 8) + | (p[heif_box_offset+15]); + } + /* check for box type, if meta box break loop */ + if ((p[heif_box_offset+4] == 'm') + && (p[heif_box_offset+5] == 'e') + && (p[heif_box_offset+6] == 't') + && (p[heif_box_offset+7] == 'a')) { + + break; + } + /* skip box */ + heif_box_offset += heif_box_len; + } + /* check if meta box len is included in buffer */ + if (ctx->length < heif_box_offset + heif_box_len || heif_box_len < 12) { + return NGX_DECLINED; + } + /* iterate over meta subboxes */ + heif_sub_offset = heif_box_offset + 12; /* offset of first subbox */ + /* check if ispe subbox fits in meta box */ + while (heif_sub_offset + 19 < heif_box_offset + heif_box_len) { + + heif_sub_len = (p[heif_sub_offset] << 24) + | (p[heif_sub_offset+1] << 16) + | (p[heif_sub_offset+2] << 8) + | (p[heif_sub_offset+3]); + + /* ispe - image spatial extents */ + if ((p[heif_sub_offset+4] == 'i') + && (p[heif_sub_offset+5] == 's') + && (p[heif_sub_offset+6] == 'p') + && (p[heif_sub_offset+7] == 'e')) { + + width = (p[heif_sub_offset+12] << 24) + | (p[heif_sub_offset+13] << 16) + | (p[heif_sub_offset+14] << 8) + | (p[heif_sub_offset+15]); + height = (p[heif_sub_offset+16] << 24) + | (p[heif_sub_offset+17] << 16) + | (p[heif_sub_offset+18] << 8) + | (p[heif_sub_offset+19]); + break; + } + + /* iprp */ + if ((p[heif_sub_offset+4] == 'i') + && (p[heif_sub_offset+5] == 'p') + && (p[heif_sub_offset+6] == 'r') + && (p[heif_sub_offset+7] == 'p')) { + + /* ignore container box header, continue reading box children */ + heif_sub_offset += 8; + + } else + if ((p[heif_sub_offset+4] == 'i') + && (p[heif_sub_offset+5] == 'p') + && (p[heif_sub_offset+6] == 'c') + && (p[heif_sub_offset+7] == 'o')) { + + /* ignore container box header, continue reading box children */ + heif_sub_offset += 8; + + } else + if (heif_sub_len != 0) { + /* skip to next subbox */ + if (heif_sub_len == 1) { + /* box length is extended */ + /* read and skip extended length */ + heif_sub_offset += + (((uint64_t) p[heif_sub_offset+8]) << 56) + | (((uint64_t) p[heif_sub_offset+9]) << 48) + | (((uint64_t) p[heif_sub_offset+10]) << 40) + | (((uint64_t) p[heif_sub_offset+11]) << 32) + | (p[heif_sub_offset+12] << 24) + | (p[heif_sub_offset+13] << 16) + | (p[heif_sub_offset+14] << 8) + | (p[heif_sub_offset+15]); + } else { + heif_sub_offset += heif_sub_len; + } + } else { + /* box with zero length continues until EOF */ + return NGX_DECLINED; + } + } + if (heif_sub_offset + 19 >= heif_box_offset + heif_box_len) { + return NGX_DECLINED; + } + break; + } default: return NGX_DECLINED; @@ -1122,6 +1405,24 @@ #endif break; + case NGX_HTTP_IMAGE_HEIC: +#if (NGX_HAVE_GD_HEIC) + img = gdImageCreateFromHeifPtr(ctx->length, ctx->image); + failed = "gdImageCreateFromHeifPtr() failed"; +#else + failed = "nginx was built without GD HEIC support"; +#endif + break; + + case NGX_HTTP_IMAGE_AVIF: +#if (NGX_HAVE_GD_AVIF) + img = gdImageCreateFromAvifPtr(ctx->length, ctx->image); + failed = "gdImageCreateFromAvifPtr() failed"; +#else + failed = "nginx was built without GD AVIF support"; +#endif + break; + default: failed = "unknown image type"; break; @@ -1170,6 +1471,7 @@ char *failed; u_char *out; ngx_int_t q; + ngx_int_t s; ngx_http_image_filter_conf_t *conf; out = NULL; @@ -1214,6 +1516,44 @@ #endif break; + case NGX_HTTP_IMAGE_HEIC: +#if (NGX_HAVE_GD_HEIC) + conf = ngx_http_get_module_loc_conf(r, ngx_http_image_filter_module); + + q = ngx_http_image_filter_get_value(r, conf->hqcv, conf->heic_quality); + if (q != -1 && q != 200 && ( q < 0 || q > 100 ) ) { + return NULL; + } + + out = gdImageHeifPtrEx(img, size, q, GD_HEIF_CODEC_HEVC, + GD_HEIF_CHROMA_444); + failed = "gdImageHeifPtrEx() failed"; +#else + failed = "nginx was built without GD HEIC support"; +#endif + break; + + case NGX_HTTP_IMAGE_AVIF: +#if (NGX_HAVE_GD_AVIF) + conf = ngx_http_get_module_loc_conf(r, ngx_http_image_filter_module); + + q = ngx_http_image_filter_get_value(r, conf->aqcv, conf->avif_quality); + if (q != -1 && ( q < 0 || q > 100 ) ) { + return NULL; + } + s = ngx_http_image_filter_get_value(r, conf->ascv, conf->avif_speed); + if (s != -1 && ( s < 0 || s > 10 ) ) { + return NULL; + } + + out = gdImageAvifPtrEx(img, size, q, s); + failed = "gdImageAvifPtrEx() failed"; +#else + failed = "nginx was built without GD AVIF support"; +#endif + break; + + default: failed = "unknown image type"; break; @@ -1298,6 +1638,9 @@ conf->filter = NGX_CONF_UNSET_UINT; conf->jpeg_quality = NGX_CONF_UNSET_UINT; conf->webp_quality = NGX_CONF_UNSET_UINT; + conf->heic_quality = NGX_CONF_UNSET; + conf->avif_quality = NGX_CONF_UNSET; + conf->avif_speed = NGX_CONF_UNSET; conf->sharpen = NGX_CONF_UNSET_UINT; conf->transparency = NGX_CONF_UNSET; conf->interlace = NGX_CONF_UNSET; @@ -1349,6 +1692,33 @@ } } + if (conf->heic_quality == NGX_CONF_UNSET) { + ngx_conf_merge_value(conf->heic_quality, prev->heic_quality, + NGX_CONF_UNSET); + + if (conf->hqcv == NULL) { + conf->hqcv = prev->hqcv; + } + } + + if (conf->avif_quality == NGX_CONF_UNSET) { + ngx_conf_merge_value(conf->avif_quality, prev->avif_quality, + NGX_CONF_UNSET); + + if (conf->aqcv == NULL) { + conf->aqcv = prev->aqcv; + } + } + + if (conf->avif_speed == NGX_CONF_UNSET) { + ngx_conf_merge_value(conf->avif_speed, prev->avif_speed, + NGX_CONF_UNSET); + + if (conf->ascv == NULL) { + conf->ascv = prev->ascv; + } + } + if (conf->sharpen == NGX_CONF_UNSET_UINT) { ngx_conf_merge_uint_value(conf->sharpen, prev->sharpen, 0); @@ -1616,6 +1986,147 @@ static char * +ngx_http_image_filter_heic_quality(ngx_conf_t *cf, ngx_command_t *cmd, + void *conf) +{ + ngx_http_image_filter_conf_t *imcf = conf; + + ngx_str_t *value; + ngx_int_t n; + ngx_http_complex_value_t cv; + ngx_http_compile_complex_value_t ccv; + + value = cf->args->elts; + + ngx_memzero(&ccv, sizeof(ngx_http_compile_complex_value_t)); + + ccv.cf = cf; + ccv.value = &value[1]; + ccv.complex_value = &cv; + + if (ngx_http_compile_complex_value(&ccv) != NGX_OK) { + return NGX_CONF_ERROR; + } + + if (cv.lengths == NULL) { + n = ngx_http_image_filter_value(&value[1]); + + if (n != 200 && (n < 0 || n > 100)) { + ngx_conf_log_error(NGX_LOG_EMERG, cf, 0, + "invalid value \"%V\"", &value[1]); + return NGX_CONF_ERROR; + } + + imcf->heic_quality = n; + + } else { + imcf->hqcv = ngx_palloc(cf->pool, sizeof(ngx_http_complex_value_t)); + if (imcf->hqcv == NULL) { + return NGX_CONF_ERROR; + } + + *imcf->hqcv = cv; + } + + return NGX_CONF_OK; +} + + +static char * +ngx_http_image_filter_avif_quality(ngx_conf_t *cf, ngx_command_t *cmd, + void *conf) +{ + ngx_http_image_filter_conf_t *imcf = conf; + + ngx_str_t *value; + ngx_int_t n; + ngx_http_complex_value_t cv; + ngx_http_compile_complex_value_t ccv; + + value = cf->args->elts; + + ngx_memzero(&ccv, sizeof(ngx_http_compile_complex_value_t)); + + ccv.cf = cf; + ccv.value = &value[1]; + ccv.complex_value = &cv; + + if (ngx_http_compile_complex_value(&ccv) != NGX_OK) { + return NGX_CONF_ERROR; + } + + if (cv.lengths == NULL) { + n = ngx_http_image_filter_value(&value[1]); + + if (n < 0 || n > 100) { + ngx_conf_log_error(NGX_LOG_EMERG, cf, 0, + "invalid value \"%V\"", &value[1]); + return NGX_CONF_ERROR; + } + + imcf->avif_quality = n; + + } else { + imcf->aqcv = ngx_palloc(cf->pool, sizeof(ngx_http_complex_value_t)); + if (imcf->aqcv == NULL) { + return NGX_CONF_ERROR; + } + + *imcf->aqcv = cv; + } + + return NGX_CONF_OK; +} + + +static char * +ngx_http_image_filter_avif_speed(ngx_conf_t *cf, ngx_command_t *cmd, + void *conf) +{ + ngx_http_image_filter_conf_t *imcf = conf; + + ngx_str_t *value; + ngx_int_t n; + ngx_http_complex_value_t cv; + ngx_http_compile_complex_value_t ccv; + + value = cf->args->elts; + + ngx_memzero(&ccv, sizeof(ngx_http_compile_complex_value_t)); + + ccv.cf = cf; + ccv.value = &value[1]; + ccv.complex_value = &cv; + + if (ngx_http_compile_complex_value(&ccv) != NGX_OK) { + return NGX_CONF_ERROR; + } + + if (cv.lengths == NULL) { + n = ngx_http_image_filter_value(&value[1]); + + if (n < 0 || n > 10) { + ngx_conf_log_error(NGX_LOG_EMERG, cf, 0, + "invalid value \"%V\"", &value[1]); + return NGX_CONF_ERROR; + } + + imcf->avif_speed = n; + + } else { + imcf->ascv = ngx_palloc(cf->pool, sizeof(ngx_http_complex_value_t)); + if (imcf->ascv == NULL) { + return NGX_CONF_ERROR; + } + + *imcf->ascv = cv; + } + + return NGX_CONF_OK; +} + + +static char * ngx_http_image_filter_sharpen(ngx_conf_t *cf, ngx_command_t *cmd, void *conf) { From chipitsine at gmail.com Sun May 9 09:28:52 2021 From: chipitsine at gmail.com (=?UTF-8?B?0JjQu9GM0Y8g0KjQuNC/0LjRhtC40L0=?=) Date: Sun, 9 May 2021 14:28:52 +0500 Subject: nginx-tests: replace non posix "which" with posix "command" Message-ID: Hello, please find attached patch. it improves experience by using generally available posix "command" instead of "which" thanks, Ilya -------------- next part -------------- An HTML attachment was scrubbed... URL: -------------- next part -------------- A non-text attachment was scrubbed... Name: 0001-use-command-instead-of-which-for-better-POSIX-compat.patch Type: text/x-patch Size: 705 bytes Desc: not available URL: From mdounin at mdounin.ru Sun May 9 14:54:00 2021 From: mdounin at mdounin.ru (Maxim Dounin) Date: Sun, 9 May 2021 17:54:00 +0300 Subject: nginx-tests: replace non posix "which" with posix "command" In-Reply-To: References: Message-ID: Hello! On Sun, May 09, 2021 at 02:28:52PM +0500, ???? ??????? wrote: > please find attached patch. > it improves experience by using generally available posix "command" instead > of "which" The last time I've tried it, it didn't work due to no "command" binary on Linux: changeset: 232:4c43b3a0117c user: Maxim Dounin date: Mon Sep 10 19:55:12 2012 +0400 files: lib/Test/Nginx.pm description: Tests: revert 5db96b64cead, use "which" instead of "command -v". It turns out that Linux doesn't have "command -v" (there are shell builtins, but no standalone binary). Use "which" instead, and provide a special case for Solaris. (http://hg.nginx.org/nginx-tests/rev/4c43b3a0117c) It's still the case at least on Ubuntu 20.10, leading to tests being incorrectly skipped on Linux if "command -v" is used instead of "which". -- Maxim Dounin http://mdounin.ru/ From dave.brennan at ultra-cpg.com Tue May 11 10:08:59 2021 From: dave.brennan at ultra-cpg.com (Dave Brennan) Date: Tue, 11 May 2021 10:08:59 +0000 Subject: Latest NGINX not available in RPM repos Message-ID: <105612b1191942789d0d9cb0fce18424@ultra-cpg.com> The latest version of NGINX 1.20.0 is not available in the Centos repos. Dave Brennan CORVID Protect Holdings Limited, trading as CORVID Protect, is registered in Guernsey, company number FC034204, whose registered office is at Royal Bank Place, 1 Glategny Esplanade, St Peter Port, Guernsey GY1 4ND. CORVID Protect Holdings Limited is a subsidiary company of Ultra Electronics Holdings plc registered in England and Wales, company number 02830397, whose registered office is at 35 Portman Square, London W1H 6LR. Ultra Electronics is committed to safeguarding the privacy of all personal data: data privacy notice. Email communications may be monitored by us, as permitted by applicable law and regulations. This email is confidential and may also be privileged. If you have received this message in error you should notify the sender immediately by reply e-mail and delete the message from your system. -------------- next part -------------- An HTML attachment was scrubbed... URL: From teward at thomas-ward.net Tue May 11 13:04:14 2021 From: teward at thomas-ward.net (Thomas Ward) Date: Tue, 11 May 2021 09:04:14 -0400 Subject: Latest NGINX not available in RPM repos In-Reply-To: <105612b1191942789d0d9cb0fce18424@ultra-cpg.com> References: <105612b1191942789d0d9cb0fce18424@ultra-cpg.com> Message-ID: I believe that, like Ubuntu, this is not an nginx.org issue - the CentOS versions are managed by people who are not necessarily the NGINX upstream team.? You might want to check wtih the historic developers on the CentOS version and determine whether that's going to get updated.? Though, with CentOS getting a kill off soon, it's likely nobody's going to update. Thomas On 5/11/21 6:08 AM, Dave Brennan wrote: > > The latest version of NGINX 1.20.0 is not available in the Centos repos. > > Dave Brennan > > CORVID Protect Holdings Limited, trading as CORVID Protect, is > registered in Guernsey, company number FC034204, whose registered > office is at Royal Bank Place, 1 Glategny Esplanade, St Peter Port, > Guernsey GY1 4ND. CORVID Protect Holdings Limited is a subsidiary > company of Ultra Electronics Holdings plc registered in England and > Wales, company number 02830397, whose registered office is at 35 > Portman Square, London W1H 6LR. > > Ultra Electronics is committed to safeguarding the privacy of all > personal data: data privacy notice. Email communications may be > monitored by us, as permitted by applicable law and regulations. This > email is confidential and may also be privileged. If you have received > this message in error you should notify the sender immediately by > reply e-mail and delete the message from your system. > > _______________________________________________ > 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: From ru at nginx.com Mon May 17 13:41:52 2021 From: ru at nginx.com (Ruslan Ermilov) Date: Mon, 17 May 2021 16:41:52 +0300 Subject: [PATCH] Stream: added config option for TCP_FASTOPEN In-Reply-To: <8735vstb09.fsf@papla.net> References: <8735vstb09.fsf@papla.net> Message-ID: <20210517134152.GB42367@lo0.su> Hi, Thanks for the patch. A few comments and an updated patch below. On Wed, Apr 14, 2021 at 09:41:42PM -0700, Anbang Wen wrote: > # HG changeset patch > # User Anbang Wen > # Date 1618433103 25200 > # Wed Apr 14 13:45:03 2021 -0700 > # Node ID 495a4d1d58835f7a05b24fb1aad84027f43f90c9 > # Parent b56c45e3bd5029f98e1e847eebad75430e2cca27 > Stream: added config option for TCP_FASTOPEN > > This commit adds a "fastopen" option to stream module. The option > behaves exactly the same as the one in HTTP core module. > > diff -r b56c45e3bd50 -r 495a4d1d5883 src/stream/ngx_stream_core_module.c [...] > @@ -836,6 +840,19 @@ > continue; > } > > +#if (NGX_HAVE_TCP_FASTOPEN) > + if (ngx_strncmp(value[i].data, "fastopen=", 9) == 0) { > + ls->fastopen = ngx_atoi(value[i].data + 9, value[i].len - 9); Here, ls->bind should also be set. > + if (ls->fastopen == NGX_ERROR) { > + ngx_conf_log_error(NGX_LOG_EMERG, cf, 0, > + "invalid fastopen \"%V\"", &value[i]); > + return NGX_CONF_ERROR; > + } > + > + continue; > + } > @@ -859,6 +876,10 @@ > if (ls->proxy_protocol) { > return "\"proxy_protocol\" parameter is incompatible with \"udp\""; > } > + > + if (ls->fastopen >= 0) { Here I changed the comparison to -1 to match the initial value. I also relocated code inserts to match the http code better. # HG changeset patch # User Ruslan Ermilov # Date 1620909454 -10800 # Thu May 13 15:37:34 2021 +0300 # Node ID edb473720b4dcdb57acae615c21b1f9075d0c63f # Parent 9bb2b3dc5efe4099ce1f86da1ae3e846054836b1 Stream: the "fastopen" parameter of the "listen" directive. Based on a patch by Anbang Wen. diff --git a/src/stream/ngx_stream.c b/src/stream/ngx_stream.c --- a/src/stream/ngx_stream.c +++ b/src/stream/ngx_stream.c @@ -510,6 +510,10 @@ ngx_stream_optimize_servers(ngx_conf_t * ls->ipv6only = addr[i].opt.ipv6only; #endif +#if (NGX_HAVE_TCP_FASTOPEN) + ls->fastopen = addr[i].opt.fastopen; +#endif + #if (NGX_HAVE_REUSEPORT) ls->reuseport = addr[i].opt.reuseport; #endif diff --git a/src/stream/ngx_stream.h b/src/stream/ngx_stream.h --- a/src/stream/ngx_stream.h +++ b/src/stream/ngx_stream.h @@ -65,6 +65,9 @@ typedef struct { int backlog; int rcvbuf; int sndbuf; +#if (NGX_HAVE_TCP_FASTOPEN) + int fastopen; +#endif int type; } ngx_stream_listen_t; diff --git a/src/stream/ngx_stream_core_module.c b/src/stream/ngx_stream_core_module.c --- a/src/stream/ngx_stream_core_module.c +++ b/src/stream/ngx_stream_core_module.c @@ -615,6 +615,10 @@ ngx_stream_core_listen(ngx_conf_t *cf, n ls->type = SOCK_STREAM; ls->ctx = cf->ctx; +#if (NGX_HAVE_TCP_FASTOPEN) + ls->fastopen = -1; +#endif + #if (NGX_HAVE_INET6) ls->ipv6only = 1; #endif @@ -635,6 +639,21 @@ ngx_stream_core_listen(ngx_conf_t *cf, n continue; } +#if (NGX_HAVE_TCP_FASTOPEN) + if (ngx_strncmp(value[i].data, "fastopen=", 9) == 0) { + ls->fastopen = ngx_atoi(value[i].data + 9, value[i].len - 9); + ls->bind = 1; + + if (ls->fastopen == NGX_ERROR) { + ngx_conf_log_error(NGX_LOG_EMERG, cf, 0, + "invalid fastopen \"%V\"", &value[i]); + return NGX_CONF_ERROR; + } + + continue; + } +#endif + if (ngx_strncmp(value[i].data, "backlog=", 8) == 0) { ls->backlog = ngx_atoi(value[i].data + 8, value[i].len - 8); ls->bind = 1; @@ -859,6 +878,12 @@ ngx_stream_core_listen(ngx_conf_t *cf, n if (ls->proxy_protocol) { return "\"proxy_protocol\" parameter is incompatible with \"udp\""; } + +#if (NGX_HAVE_TCP_FASTOPEN) + if (ls->fastopen != -1) { + return "\"fastopen\" parameter is incompatible with \"udp\""; + } +#endif } als = cmcf->listen.elts; From alexander.borisov at nginx.com Mon May 17 17:36:36 2021 From: alexander.borisov at nginx.com (Alexander Borisov) Date: Mon, 17 May 2021 17:36:36 +0000 Subject: [njs] Fixed parsing case/default in an unclosed function block in switch. Message-ID: details: https://hg.nginx.org/njs/rev/7b70ee90ead8 branches: changeset: 1637:7b70ee90ead8 user: Alexander Borisov date: Mon May 17 20:35:35 2021 +0300 description: Fixed parsing case/default in an unclosed function block in switch. diffstat: src/njs_parser.c | 13 ++++++++++++- src/test/njs_unit_test.c | 18 ++++++++++++++++++ 2 files changed, 30 insertions(+), 1 deletions(-) diffs (65 lines): diff -r 637bc81166a6 -r 7b70ee90ead8 src/njs_parser.c --- a/src/njs_parser.c Thu May 06 16:07:09 2021 +0300 +++ b/src/njs_parser.c Mon May 17 20:35:35 2021 +0300 @@ -4713,7 +4713,10 @@ njs_parser_statement_list_next(njs_parse if (parser->ret != NJS_OK) { if (token->type != NJS_TOKEN_CLOSE_BRACE) { parser->node = parser->target; - return njs_parser_stack_pop(parser); + + (void) njs_parser_stack_pop(parser); + + return parser->ret; } return njs_parser_failed(parser); @@ -6098,6 +6101,10 @@ njs_parser_switch_case_block(njs_parser_ { parser->target->right->right = parser->node; + if (parser->ret != NJS_OK && parser->target->scope != parser->scope) { + return njs_parser_failed(parser); + } + njs_parser_next(parser, njs_parser_switch_case); return NJS_OK; @@ -6153,6 +6160,10 @@ njs_parser_switch_case_block_wo_def(njs_ parser->target->right = parser->node; } + if (parser->ret != NJS_OK && parser->target->scope != parser->scope) { + return njs_parser_failed(parser); + } + njs_parser_next(parser, njs_parser_switch_case_wo_def); return NJS_OK; diff -r 637bc81166a6 -r 7b70ee90ead8 src/test/njs_unit_test.c --- a/src/test/njs_unit_test.c Thu May 06 16:07:09 2021 +0300 +++ b/src/test/njs_unit_test.c Mon May 17 20:35:35 2021 +0300 @@ -2958,6 +2958,24 @@ static njs_unit_test_t njs_test[] = "map((v)=>{switch(v) { case isNaN: return 1; default: return 0;}})"), njs_str("1,0,0") }, + { njs_str("switch (1) {case 1: ii > 1; ii => default:}"), + njs_str("SyntaxError: Unexpected token \"default\" in 1") }, + + { njs_str("switch (1) {case 1: ii > 1; var a = functin () {default:}"), + njs_str("SyntaxError: Unexpected token \"{\" in 1") }, + + { njs_str("switch (1) {default: ii > 1; ii => case 2:}"), + njs_str("SyntaxError: Unexpected token \"case\" in 1") }, + + { njs_str("switch (1) {default: ii > 1; var a = functin () {case 2:}"), + njs_str("SyntaxError: Unexpected token \"{\" in 1") }, + + { njs_str("switch (1) {case 1: ii > 1; ii => case 2:}"), + njs_str("SyntaxError: Unexpected token \"case\" in 1") }, + + { njs_str("switch (1) {case 1: ii > 1; var a = functin () {case 2:}"), + njs_str("SyntaxError: Unexpected token \"{\" in 1") }, + /* continue. */ { njs_str("continue"), From mdounin at mdounin.ru Wed May 19 01:27:09 2021 From: mdounin at mdounin.ru (Maxim Dounin) Date: Wed, 19 May 2021 01:27:09 +0000 Subject: [nginx] Mail: fixed SMTP pipelining to send the response immediately. Message-ID: details: https://hg.nginx.org/nginx/rev/c72d8839f427 branches: changeset: 7835:c72d8839f427 user: Maxim Dounin date: Wed May 19 03:13:12 2021 +0300 description: Mail: fixed SMTP pipelining to send the response immediately. Previously, if there were some pipelined SMTP data in the buffer when a proxied connection with the backend was established, nginx called ngx_mail_proxy_handler() to send these data, and not tried to send the response to the last command. In most cases, this response was later sent along with the response to the pipelined command, but if for some reason client decides to wait for the response before finishing the next command this might result in a connection hang. Fix is to always call ngx_mail_proxy_handler() to send the response, and additionally post an event to send the pipelined data if needed. diffstat: src/mail/ngx_mail_proxy_module.c | 9 ++++----- 1 files changed, 4 insertions(+), 5 deletions(-) diffs (20 lines): diff -r b3f4d83d6fd0 -r c72d8839f427 src/mail/ngx_mail_proxy_module.c --- a/src/mail/ngx_mail_proxy_module.c Sat May 08 20:31:03 2021 +0300 +++ b/src/mail/ngx_mail_proxy_module.c Wed May 19 03:13:12 2021 +0300 @@ -813,12 +813,11 @@ ngx_mail_proxy_smtp_handler(ngx_event_t c->log->action = NULL; ngx_log_error(NGX_LOG_INFO, c->log, 0, "client logged in"); - if (s->buffer->pos == s->buffer->last) { - ngx_mail_proxy_handler(s->connection->write); + if (s->buffer->pos < s->buffer->last) { + ngx_post_event(c->write, &ngx_posted_events); + } - } else { - ngx_mail_proxy_handler(c->write); - } + ngx_mail_proxy_handler(s->connection->write); return; From mdounin at mdounin.ru Wed May 19 01:27:12 2021 From: mdounin at mdounin.ru (Maxim Dounin) Date: Wed, 19 May 2021 01:27:12 +0000 Subject: [nginx] Mail: fixed handling of invalid SMTP commands split between reads. Message-ID: details: https://hg.nginx.org/nginx/rev/6a81d96d3733 branches: changeset: 7836:6a81d96d3733 user: Maxim Dounin date: Wed May 19 03:13:15 2021 +0300 description: Mail: fixed handling of invalid SMTP commands split between reads. Previously, if an invalid SMTP command was split between reads, nginx failed to wait for LF before returning an error, and interpreted the rest of the command received later as a separate command. The sw_invalid state in ngx_mail_smtp_parse_command(), introduced in 04e43d03e153, did not work, since ngx_mail_smtp_auth_state() clears s->state when returning an error due to NGX_MAIL_PARSE_INVALID_COMMAND. And not clearing s->state will introduce another problem: the rest of the command would trigger duplicate error when rest of the command is received. Fix is to return NGX_AGAIN from ngx_mail_smtp_parse_command() until full command is received. diffstat: src/mail/ngx_mail_parse.c | 6 +++--- 1 files changed, 3 insertions(+), 3 deletions(-) diffs (21 lines): diff -r c72d8839f427 -r 6a81d96d3733 src/mail/ngx_mail_parse.c --- a/src/mail/ngx_mail_parse.c Wed May 19 03:13:12 2021 +0300 +++ b/src/mail/ngx_mail_parse.c Wed May 19 03:13:15 2021 +0300 @@ -846,14 +846,14 @@ invalid: for (p = s->buffer->pos; p < s->buffer->last; p++) { if (*p == LF) { s->state = sw_start; - p++; - break; + s->buffer->pos = p + 1; + return NGX_MAIL_PARSE_INVALID_COMMAND; } } s->buffer->pos = p; - return NGX_MAIL_PARSE_INVALID_COMMAND; + return NGX_AGAIN; } From mdounin at mdounin.ru Wed May 19 01:27:15 2021 From: mdounin at mdounin.ru (Maxim Dounin) Date: Wed, 19 May 2021 01:27:15 +0000 Subject: [nginx] Mail: optimized discarding invalid SMTP commands. Message-ID: details: https://hg.nginx.org/nginx/rev/ba8a8299b904 branches: changeset: 7837:ba8a8299b904 user: Maxim Dounin date: Wed May 19 03:13:17 2021 +0300 description: Mail: optimized discarding invalid SMTP commands. There is no need to scan buffer from s->buffer->pos, as we already scanned the buffer till "p" and wasn't able to find an LF. There is no real need for this change in SMTP, since it is at most a microoptimization of a non-common code path. Similar code in IMAP, however, will have to start scanning from "p" to be correct, since there can be newlines in IMAP literals. diffstat: src/mail/ngx_mail_parse.c | 2 +- 1 files changed, 1 insertions(+), 1 deletions(-) diffs (12 lines): diff -r 6a81d96d3733 -r ba8a8299b904 src/mail/ngx_mail_parse.c --- a/src/mail/ngx_mail_parse.c Wed May 19 03:13:15 2021 +0300 +++ b/src/mail/ngx_mail_parse.c Wed May 19 03:13:17 2021 +0300 @@ -843,7 +843,7 @@ invalid: /* skip invalid command till LF */ - for (p = s->buffer->pos; p < s->buffer->last; p++) { + for ( /* void */ ; p < s->buffer->last; p++) { if (*p == LF) { s->state = sw_start; s->buffer->pos = p + 1; From mdounin at mdounin.ru Wed May 19 01:27:18 2021 From: mdounin at mdounin.ru (Maxim Dounin) Date: Wed, 19 May 2021 01:27:18 +0000 Subject: [nginx] Mail: POP3 pipelining support. Message-ID: details: https://hg.nginx.org/nginx/rev/815c63581be4 branches: changeset: 7838:815c63581be4 user: Maxim Dounin date: Wed May 19 03:13:18 2021 +0300 description: Mail: POP3 pipelining support. The change is mostly the same as the SMTP one (04e43d03e153 and 3f5d0af4e40a), and ensures that nginx is able to properly handle or reject multiple POP3 commands, as required by the PIPELINING capability (RFC 2449). The s->cmd field is not really used and set for consistency. diffstat: src/mail/ngx_mail_parse.c | 32 +++++++++++++++++++++++++++++--- src/mail/ngx_mail_pop3_handler.c | 15 ++++++++++++--- src/mail/ngx_mail_proxy_module.c | 4 ++++ 3 files changed, 45 insertions(+), 6 deletions(-) diffs (128 lines): diff -r ba8a8299b904 -r 815c63581be4 src/mail/ngx_mail_parse.c --- a/src/mail/ngx_mail_parse.c Wed May 19 03:13:17 2021 +0300 +++ b/src/mail/ngx_mail_parse.c Wed May 19 03:13:18 2021 +0300 @@ -21,6 +21,8 @@ ngx_mail_pop3_parse_command(ngx_mail_ses ngx_str_t *arg; enum { sw_start = 0, + sw_command, + sw_invalid, sw_spaces_before_argument, sw_argument, sw_almost_done @@ -35,8 +37,14 @@ ngx_mail_pop3_parse_command(ngx_mail_ses /* POP3 command */ case sw_start: + s->cmd_start = p; + state = sw_command; + + /* fall through */ + + case sw_command: if (ch == ' ' || ch == CR || ch == LF) { - c = s->buffer->start; + c = s->cmd_start; if (p - c == 4) { @@ -85,6 +93,9 @@ ngx_mail_pop3_parse_command(ngx_mail_ses goto invalid; } + s->cmd.data = s->cmd_start; + s->cmd.len = p - s->cmd_start; + switch (ch) { case ' ': state = sw_spaces_before_argument; @@ -104,6 +115,9 @@ ngx_mail_pop3_parse_command(ngx_mail_ses break; + case sw_invalid: + goto invalid; + case sw_spaces_before_argument: switch (ch) { case ' ': @@ -205,10 +219,22 @@ done: invalid: - s->state = sw_start; + s->state = sw_invalid; s->arg_start = NULL; - return NGX_MAIL_PARSE_INVALID_COMMAND; + /* skip invalid command till LF */ + + for ( /* void */ ; p < s->buffer->last; p++) { + if (*p == LF) { + s->state = sw_start; + s->buffer->pos = p + 1; + return NGX_MAIL_PARSE_INVALID_COMMAND; + } + } + + s->buffer->pos = p; + + return NGX_AGAIN; } diff -r ba8a8299b904 -r 815c63581be4 src/mail/ngx_mail_pop3_handler.c --- a/src/mail/ngx_mail_pop3_handler.c Wed May 19 03:13:17 2021 +0300 +++ b/src/mail/ngx_mail_pop3_handler.c Wed May 19 03:13:18 2021 +0300 @@ -262,6 +262,10 @@ ngx_mail_pop3_auth_state(ngx_event_t *re } } + if (s->buffer->pos < s->buffer->last) { + s->blocked = 1; + } + switch (rc) { case NGX_DONE: @@ -283,11 +287,14 @@ ngx_mail_pop3_auth_state(ngx_event_t *re case NGX_OK: s->args.nelts = 0; - s->buffer->pos = s->buffer->start; - s->buffer->last = s->buffer->start; + + if (s->buffer->pos == s->buffer->last) { + s->buffer->pos = s->buffer->start; + s->buffer->last = s->buffer->start; + } if (s->state) { - s->arg_start = s->buffer->start; + s->arg_start = s->buffer->pos; } if (ngx_handle_read_event(c->read, 0) != NGX_OK) { @@ -400,6 +407,8 @@ ngx_mail_pop3_stls(ngx_mail_session_t *s if (c->ssl == NULL) { sslcf = ngx_mail_get_module_srv_conf(s, ngx_mail_ssl_module); if (sslcf->starttls) { + s->buffer->pos = s->buffer->start; + s->buffer->last = s->buffer->start; c->read->handler = ngx_mail_starttls_handler; return NGX_OK; } diff -r ba8a8299b904 -r 815c63581be4 src/mail/ngx_mail_proxy_module.c --- a/src/mail/ngx_mail_proxy_module.c Wed May 19 03:13:17 2021 +0300 +++ b/src/mail/ngx_mail_proxy_module.c Wed May 19 03:13:18 2021 +0300 @@ -327,6 +327,10 @@ ngx_mail_proxy_pop3_handler(ngx_event_t c->log->action = NULL; ngx_log_error(NGX_LOG_INFO, c->log, 0, "client logged in"); + if (s->buffer->pos < s->buffer->last) { + ngx_post_event(c->write, &ngx_posted_events); + } + ngx_mail_proxy_handler(s->connection->write); return; From mdounin at mdounin.ru Wed May 19 01:27:21 2021 From: mdounin at mdounin.ru (Maxim Dounin) Date: Wed, 19 May 2021 01:27:21 +0000 Subject: [nginx] Mail: fixed s->arg_start clearing on invalid IMAP commands. Message-ID: details: https://hg.nginx.org/nginx/rev/3974f4e56a4e branches: changeset: 7839:3974f4e56a4e user: Maxim Dounin date: Wed May 19 03:13:20 2021 +0300 description: Mail: fixed s->arg_start clearing on invalid IMAP commands. Previously, s->arg_start was left intact after invalid IMAP commands, and this might result in an argument incorrectly added to the following command. Similarly, s->backslash was left intact as well, leading to unneeded backslash removal. For example (LFs from the client are explicitly shown as ""): S: * OK IMAP4 ready C: a01 login "\ S: a01 BAD invalid command C: a0000000000\2 authenticate S: a00000000002 aBAD invalid command The backslash followed by LF generates invalid command with s->arg_start and s->backslash set, the following command incorrectly treats anything from the old s->arg_start to the space after the command as an argument, and removes the backslash from the tag. If there is no space, s->arg_end will be NULL. Both things seem to be harmless though. In particular: - This can be used to provide an incorrect argument to a command without arguments. The only command which seems to look at the single argument is AUTHENTICATE, and it checks the argument length before trying to access it. - Backslash removal uses the "end" pointer, and stops due to "src < end" condition instead of scanning all the process memory if s->arg_end is NULL (and arg[0].len is huge). - There should be no backslashes in unquoted strings. An obvious fix is to clear s->arg_start and s->backslash on invalid commands, similarly to how it is done in POP3 parsing (added in 810:e3aa8f305d21) and SMTP parsing. This, however, makes it clear that s->arg_start handling in the "done" label is wrong: s->arg_start cannot be legitimately set there, as it is expected to be cleared in all possible cases when the "done" label is reached. The relevant code is dead and will be removed by the following change. diffstat: src/mail/ngx_mail_parse.c | 2 ++ 1 files changed, 2 insertions(+), 0 deletions(-) diffs (13 lines): diff -r 815c63581be4 -r 3974f4e56a4e src/mail/ngx_mail_parse.c --- a/src/mail/ngx_mail_parse.c Wed May 19 03:13:18 2021 +0300 +++ b/src/mail/ngx_mail_parse.c Wed May 19 03:13:20 2021 +0300 @@ -637,7 +637,9 @@ done: invalid: s->state = sw_start; + s->arg_start = NULL; s->quoted = 0; + s->backslash = 0; s->no_sync_literal = 0; s->literal_len = 0; From mdounin at mdounin.ru Wed May 19 01:27:23 2021 From: mdounin at mdounin.ru (Maxim Dounin) Date: Wed, 19 May 2021 01:27:23 +0000 Subject: [nginx] Mail: removed dead s->arg_start handling. Message-ID: details: https://hg.nginx.org/nginx/rev/379d461eccf4 branches: changeset: 7840:379d461eccf4 user: Maxim Dounin date: Wed May 19 03:13:22 2021 +0300 description: Mail: removed dead s->arg_start handling. As discussed in the previous change, s->arg_start handling in the "done" labels of ngx_mail_pop3_parse_command(), ngx_mail_imap_parse_command(), and ngx_mail_smtp_parse_command() is wrong: s->arg_start cannot be set there, as it is handled and cleared on all code paths where the "done" labels are reached. The relevant code is dead and now removed. diffstat: src/mail/ngx_mail.h | 1 - src/mail/ngx_mail_parse.c | 47 ----------------------------------------------- 2 files changed, 0 insertions(+), 48 deletions(-) diffs (130 lines): diff -r 3974f4e56a4e -r 379d461eccf4 src/mail/ngx_mail.h --- a/src/mail/ngx_mail.h Wed May 19 03:13:20 2021 +0300 +++ b/src/mail/ngx_mail.h Wed May 19 03:13:22 2021 +0300 @@ -238,7 +238,6 @@ typedef struct { ngx_uint_t state; u_char *cmd_start; u_char *arg_start; - u_char *arg_end; ngx_uint_t literal_len; } ngx_mail_session_t; diff -r 3974f4e56a4e -r 379d461eccf4 src/mail/ngx_mail_parse.c --- a/src/mail/ngx_mail_parse.c Wed May 19 03:13:20 2021 +0300 +++ b/src/mail/ngx_mail_parse.c Wed May 19 03:13:22 2021 +0300 @@ -124,10 +124,8 @@ ngx_mail_pop3_parse_command(ngx_mail_ses break; case CR: state = sw_almost_done; - s->arg_end = p; break; case LF: - s->arg_end = p; goto done; default: if (s->args.nelts <= 2) { @@ -202,17 +200,6 @@ ngx_mail_pop3_parse_command(ngx_mail_ses done: s->buffer->pos = p + 1; - - if (s->arg_start) { - arg = ngx_array_push(&s->args); - if (arg == NULL) { - return NGX_ERROR; - } - arg->len = s->arg_end - s->arg_start; - arg->data = s->arg_start; - s->arg_start = NULL; - } - s->state = (s->command != NGX_POP3_AUTH) ? sw_start : sw_argument; return NGX_OK; @@ -220,7 +207,6 @@ done: invalid: s->state = sw_invalid; - s->arg_start = NULL; /* skip invalid command till LF */ @@ -436,10 +422,8 @@ ngx_mail_imap_parse_command(ngx_mail_ses break; case CR: state = sw_almost_done; - s->arg_end = p; break; case LF: - s->arg_end = p; goto done; case '"': if (s->args.nelts <= 2) { @@ -614,22 +598,6 @@ ngx_mail_imap_parse_command(ngx_mail_ses done: s->buffer->pos = p + 1; - - if (s->arg_start) { - arg = ngx_array_push(&s->args); - if (arg == NULL) { - return NGX_ERROR; - } - arg->len = s->arg_end - s->arg_start; - arg->data = s->arg_start; - - s->arg_start = NULL; - s->cmd_start = NULL; - s->quoted = 0; - s->no_sync_literal = 0; - s->literal_len = 0; - } - s->state = (s->command != NGX_IMAP_AUTHENTICATE) ? sw_start : sw_argument; return NGX_OK; @@ -637,7 +605,6 @@ done: invalid: s->state = sw_start; - s->arg_start = NULL; s->quoted = 0; s->backslash = 0; s->no_sync_literal = 0; @@ -786,10 +753,8 @@ ngx_mail_smtp_parse_command(ngx_mail_ses break; case CR: state = sw_almost_done; - s->arg_end = p; break; case LF: - s->arg_end = p; goto done; default: if (s->args.nelts <= 10) { @@ -849,17 +814,6 @@ ngx_mail_smtp_parse_command(ngx_mail_ses done: s->buffer->pos = p + 1; - - if (s->arg_start) { - arg = ngx_array_push(&s->args); - if (arg == NULL) { - return NGX_ERROR; - } - arg->len = s->arg_end - s->arg_start; - arg->data = s->arg_start; - s->arg_start = NULL; - } - s->state = (s->command != NGX_SMTP_AUTH) ? sw_start : sw_argument; return NGX_OK; @@ -867,7 +821,6 @@ done: invalid: s->state = sw_invalid; - s->arg_start = NULL; /* skip invalid command till LF */ From mdounin at mdounin.ru Wed May 19 01:27:26 2021 From: mdounin at mdounin.ru (Maxim Dounin) Date: Wed, 19 May 2021 01:27:26 +0000 Subject: [nginx] Mail: fixed backslash handling in IMAP literals. Message-ID: details: https://hg.nginx.org/nginx/rev/ccdf83bee8c1 branches: changeset: 7841:ccdf83bee8c1 user: Maxim Dounin date: Wed May 19 03:13:23 2021 +0300 description: Mail: fixed backslash handling in IMAP literals. Previously, s->backslash was set if any of the arguments was a quoted string with a backslash character. After successful command parsing this resulted in all arguments being filtered to remove backslashes. This is, however, incorrect, as backslashes should not be removed from IMAP literals. For example: S: * OK IMAP4 ready C: a01 login {9} S: + OK C: user\name "pass\"word" S: * BAD internal server error resulted in "Auth-User: username" instead of "Auth-User: user\name" as it should. Fix is to apply backslash filtering on per-argument basis during parsing. diffstat: src/mail/ngx_mail_imap_handler.c | 26 ++------------------------ src/mail/ngx_mail_parse.c | 18 +++++++++++++++++- 2 files changed, 19 insertions(+), 25 deletions(-) diffs (79 lines): diff -r 379d461eccf4 -r ccdf83bee8c1 src/mail/ngx_mail_imap_handler.c --- a/src/mail/ngx_mail_imap_handler.c Wed May 19 03:13:22 2021 +0300 +++ b/src/mail/ngx_mail_imap_handler.c Wed May 19 03:13:23 2021 +0300 @@ -101,10 +101,9 @@ ngx_mail_imap_init_protocol(ngx_event_t void ngx_mail_imap_auth_state(ngx_event_t *rev) { - u_char *p, *dst, *src, *end; - ngx_str_t *arg; + u_char *p; ngx_int_t rc; - ngx_uint_t tag, i; + ngx_uint_t tag; ngx_connection_t *c; ngx_mail_session_t *s; @@ -158,27 +157,6 @@ ngx_mail_imap_auth_state(ngx_event_t *re ngx_log_debug1(NGX_LOG_DEBUG_MAIL, c->log, 0, "imap auth command: %i", s->command); - if (s->backslash) { - - arg = s->args.elts; - - for (i = 0; i < s->args.nelts; i++) { - dst = arg[i].data; - end = dst + arg[i].len; - - for (src = dst; src < end; dst++) { - *dst = *src; - if (*src++ == '\\') { - *dst = *src++; - } - } - - arg[i].len = dst - arg[i].data; - } - - s->backslash = 0; - } - switch (s->mail_state) { case ngx_imap_start: diff -r 379d461eccf4 -r ccdf83bee8c1 src/mail/ngx_mail_parse.c --- a/src/mail/ngx_mail_parse.c Wed May 19 03:13:22 2021 +0300 +++ b/src/mail/ngx_mail_parse.c Wed May 19 03:13:23 2021 +0300 @@ -227,7 +227,7 @@ invalid: ngx_int_t ngx_mail_imap_parse_command(ngx_mail_session_t *s) { - u_char ch, *p, *c; + u_char ch, *p, *c, *dst, *src, *end; ngx_str_t *arg; enum { sw_start = 0, @@ -470,6 +470,22 @@ ngx_mail_imap_parse_command(ngx_mail_ses } arg->len = p - s->arg_start; arg->data = s->arg_start; + + if (s->backslash) { + dst = s->arg_start; + end = p; + + for (src = dst; src < end; dst++) { + *dst = *src; + if (*src++ == '\\') { + *dst = *src++; + } + } + + arg->len = dst - s->arg_start; + s->backslash = 0; + } + s->arg_start = NULL; switch (ch) { From mdounin at mdounin.ru Wed May 19 01:27:29 2021 From: mdounin at mdounin.ru (Maxim Dounin) Date: Wed, 19 May 2021 01:27:29 +0000 Subject: [nginx] Mail: stricter checking of IMAP tags. Message-ID: details: https://hg.nginx.org/nginx/rev/4b15f1b92100 branches: changeset: 7842:4b15f1b92100 user: Maxim Dounin date: Wed May 19 03:13:26 2021 +0300 description: Mail: stricter checking of IMAP tags. Only "A-Za-z0-9-._" characters now allowed (which is stricter than what RFC 3501 requires, but expected to be enough for all known clients), and tags shouldn't be longer than 32 characters. diffstat: src/mail/ngx_mail_parse.c | 11 +++++++++++ 1 files changed, 11 insertions(+), 0 deletions(-) diffs (21 lines): diff -r ccdf83bee8c1 -r 4b15f1b92100 src/mail/ngx_mail_parse.c --- a/src/mail/ngx_mail_parse.c Wed May 19 03:13:23 2021 +0300 +++ b/src/mail/ngx_mail_parse.c Wed May 19 03:13:26 2021 +0300 @@ -265,6 +265,17 @@ ngx_mail_imap_parse_command(ngx_mail_ses case LF: s->state = sw_start; return NGX_MAIL_PARSE_INVALID_COMMAND; + default: + if ((ch < 'A' || ch > 'Z') && (ch < 'a' || ch > 'z') + && (ch < '0' || ch > '9') && ch != '-' && ch != '.' + && ch != '_') + { + goto invalid; + } + if (p - s->buffer->start > 31) { + goto invalid; + } + break; } break; From mdounin at mdounin.ru Wed May 19 01:27:32 2021 From: mdounin at mdounin.ru (Maxim Dounin) Date: Wed, 19 May 2021 01:27:32 +0000 Subject: [nginx] Mail: IMAP pipelining support. Message-ID: details: https://hg.nginx.org/nginx/rev/b38728495e1a branches: changeset: 7843:b38728495e1a user: Maxim Dounin date: Wed May 19 03:13:28 2021 +0300 description: Mail: IMAP pipelining support. The change is mostly the same as the SMTP one (04e43d03e153 and 3f5d0af4e40a), and ensures that nginx is able to properly handle or reject multiple IMAP commands. The s->cmd field is not really used and set for consistency. Non-synchronizing literals handling in invalid/unknown commands is limited, so when a non-synchronizing literal is detected at the end of a discarded line, the connection is closed. diffstat: src/mail/ngx_mail.h | 1 + src/mail/ngx_mail_imap_handler.c | 17 +++++++--- src/mail/ngx_mail_parse.c | 61 +++++++++++++++++++++++++++++++-------- src/mail/ngx_mail_proxy_module.c | 4 ++ 4 files changed, 65 insertions(+), 18 deletions(-) diffs (190 lines): diff -r 4b15f1b92100 -r b38728495e1a src/mail/ngx_mail.h --- a/src/mail/ngx_mail.h Wed May 19 03:13:26 2021 +0300 +++ b/src/mail/ngx_mail.h Wed May 19 03:13:28 2021 +0300 @@ -236,6 +236,7 @@ typedef struct { /* used to parse POP3/IMAP/SMTP command */ ngx_uint_t state; + u_char *tag_start; u_char *cmd_start; u_char *arg_start; ngx_uint_t literal_len; diff -r 4b15f1b92100 -r b38728495e1a src/mail/ngx_mail_imap_handler.c --- a/src/mail/ngx_mail_imap_handler.c Wed May 19 03:13:26 2021 +0300 +++ b/src/mail/ngx_mail_imap_handler.c Wed May 19 03:13:28 2021 +0300 @@ -226,6 +226,10 @@ ngx_mail_imap_auth_state(ngx_event_t *re ngx_str_set(&s->out, imap_next); } + if (s->buffer->pos < s->buffer->last) { + s->blocked = 1; + } + switch (rc) { case NGX_DONE: @@ -275,13 +279,14 @@ ngx_mail_imap_auth_state(ngx_event_t *re if (s->state) { /* preserve tag */ - s->arg_start = s->buffer->start + s->tag.len; - s->buffer->pos = s->arg_start; - s->buffer->last = s->arg_start; + s->arg_start = s->buffer->pos; } else { - s->buffer->pos = s->buffer->start; - s->buffer->last = s->buffer->start; + if (s->buffer->pos == s->buffer->last) { + s->buffer->pos = s->buffer->start; + s->buffer->last = s->buffer->start; + } + s->tag.len = 0; } } @@ -459,6 +464,8 @@ ngx_mail_imap_starttls(ngx_mail_session_ if (c->ssl == NULL) { sslcf = ngx_mail_get_module_srv_conf(s, ngx_mail_ssl_module); if (sslcf->starttls) { + s->buffer->pos = s->buffer->start; + s->buffer->last = s->buffer->start; c->read->handler = ngx_mail_starttls_handler; return NGX_OK; } diff -r 4b15f1b92100 -r b38728495e1a src/mail/ngx_mail_parse.c --- a/src/mail/ngx_mail_parse.c Wed May 19 03:13:26 2021 +0300 +++ b/src/mail/ngx_mail_parse.c Wed May 19 03:13:28 2021 +0300 @@ -231,6 +231,8 @@ ngx_mail_imap_parse_command(ngx_mail_ses ngx_str_t *arg; enum { sw_start = 0, + sw_tag, + sw_invalid, sw_spaces_before_command, sw_command, sw_spaces_before_argument, @@ -253,18 +255,21 @@ ngx_mail_imap_parse_command(ngx_mail_ses /* IMAP tag */ case sw_start: + s->tag_start = p; + state = sw_tag; + + /* fall through */ + + case sw_tag: switch (ch) { case ' ': - s->tag.len = p - s->buffer->start + 1; - s->tag.data = s->buffer->start; + s->tag.len = p - s->tag_start + 1; + s->tag.data = s->tag_start; state = sw_spaces_before_command; break; case CR: - s->state = sw_start; - return NGX_MAIL_PARSE_INVALID_COMMAND; case LF: - s->state = sw_start; - return NGX_MAIL_PARSE_INVALID_COMMAND; + goto invalid; default: if ((ch < 'A' || ch > 'Z') && (ch < 'a' || ch > 'z') && (ch < '0' || ch > '9') && ch != '-' && ch != '.' @@ -272,23 +277,23 @@ ngx_mail_imap_parse_command(ngx_mail_ses { goto invalid; } - if (p - s->buffer->start > 31) { + if (p - s->tag_start > 31) { goto invalid; } break; } break; + case sw_invalid: + goto invalid; + case sw_spaces_before_command: switch (ch) { case ' ': break; case CR: - s->state = sw_start; - return NGX_MAIL_PARSE_INVALID_COMMAND; case LF: - s->state = sw_start; - return NGX_MAIL_PARSE_INVALID_COMMAND; + goto invalid; default: s->cmd_start = p; state = sw_command; @@ -408,6 +413,9 @@ ngx_mail_imap_parse_command(ngx_mail_ses goto invalid; } + s->cmd.data = s->cmd_start; + s->cmd.len = p - s->cmd_start; + switch (ch) { case ' ': state = sw_spaces_before_argument; @@ -631,13 +639,40 @@ done: invalid: - s->state = sw_start; + s->state = sw_invalid; s->quoted = 0; s->backslash = 0; s->no_sync_literal = 0; s->literal_len = 0; - return NGX_MAIL_PARSE_INVALID_COMMAND; + /* skip invalid command till LF */ + + for ( /* void */ ; p < s->buffer->last; p++) { + if (*p == LF) { + s->state = sw_start; + s->buffer->pos = p + 1; + + /* detect non-synchronizing literals */ + + if ((size_t) (p - s->buffer->start) > sizeof("{1+}") - 1) { + p--; + + if (*p == CR) { + p--; + } + + if (*p == '}' && *(p - 1) == '+') { + s->quit = 1; + } + } + + return NGX_MAIL_PARSE_INVALID_COMMAND; + } + } + + s->buffer->pos = p; + + return NGX_AGAIN; } diff -r 4b15f1b92100 -r b38728495e1a src/mail/ngx_mail_proxy_module.c --- a/src/mail/ngx_mail_proxy_module.c Wed May 19 03:13:26 2021 +0300 +++ b/src/mail/ngx_mail_proxy_module.c Wed May 19 03:13:28 2021 +0300 @@ -486,6 +486,10 @@ ngx_mail_proxy_imap_handler(ngx_event_t c->log->action = NULL; ngx_log_error(NGX_LOG_INFO, c->log, 0, "client logged in"); + if (s->buffer->pos < s->buffer->last) { + ngx_post_event(c->write, &ngx_posted_events); + } + ngx_mail_proxy_handler(s->connection->write); return; From mdounin at mdounin.ru Wed May 19 01:27:35 2021 From: mdounin at mdounin.ru (Maxim Dounin) Date: Wed, 19 May 2021 01:27:35 +0000 Subject: [nginx] Mail: max_errors directive. Message-ID: details: https://hg.nginx.org/nginx/rev/ec1071830799 branches: changeset: 7844:ec1071830799 user: Maxim Dounin date: Wed May 19 03:13:31 2021 +0300 description: Mail: max_errors directive. Similarly to smtpd_hard_error_limit in Postfix and smtp_max_unknown_commands in Exim, specifies the number of errors after which the connection is closed. diffstat: src/mail/ngx_mail.h | 3 +++ src/mail/ngx_mail_core_module.c | 10 ++++++++++ src/mail/ngx_mail_handler.c | 15 ++++++++++++++- 3 files changed, 27 insertions(+), 1 deletions(-) diffs (79 lines): diff -r b38728495e1a -r ec1071830799 src/mail/ngx_mail.h --- a/src/mail/ngx_mail.h Wed May 19 03:13:28 2021 +0300 +++ b/src/mail/ngx_mail.h Wed May 19 03:13:31 2021 +0300 @@ -115,6 +115,8 @@ typedef struct { ngx_msec_t timeout; ngx_msec_t resolver_timeout; + ngx_uint_t max_errors; + ngx_str_t server_name; u_char *file_name; @@ -231,6 +233,7 @@ typedef struct { ngx_uint_t command; ngx_array_t args; + ngx_uint_t errors; ngx_uint_t login_attempt; /* used to parse POP3/IMAP/SMTP command */ diff -r b38728495e1a -r ec1071830799 src/mail/ngx_mail_core_module.c --- a/src/mail/ngx_mail_core_module.c Wed May 19 03:13:28 2021 +0300 +++ b/src/mail/ngx_mail_core_module.c Wed May 19 03:13:31 2021 +0300 @@ -85,6 +85,13 @@ static ngx_command_t ngx_mail_core_comm offsetof(ngx_mail_core_srv_conf_t, resolver_timeout), NULL }, + { ngx_string("max_errors"), + NGX_MAIL_MAIN_CONF|NGX_MAIL_SRV_CONF|NGX_CONF_TAKE1, + ngx_conf_set_num_slot, + NGX_MAIL_SRV_CONF_OFFSET, + offsetof(ngx_mail_core_srv_conf_t, max_errors), + NULL }, + ngx_null_command }; @@ -163,6 +170,8 @@ ngx_mail_core_create_srv_conf(ngx_conf_t cscf->timeout = NGX_CONF_UNSET_MSEC; cscf->resolver_timeout = NGX_CONF_UNSET_MSEC; + cscf->max_errors = NGX_CONF_UNSET_UINT; + cscf->resolver = NGX_CONF_UNSET_PTR; cscf->file_name = cf->conf_file->file.name.data; @@ -182,6 +191,7 @@ ngx_mail_core_merge_srv_conf(ngx_conf_t ngx_conf_merge_msec_value(conf->resolver_timeout, prev->resolver_timeout, 30000); + ngx_conf_merge_uint_value(conf->max_errors, prev->max_errors, 5); ngx_conf_merge_str_value(conf->server_name, prev->server_name, ""); diff -r b38728495e1a -r ec1071830799 src/mail/ngx_mail_handler.c --- a/src/mail/ngx_mail_handler.c Wed May 19 03:13:28 2021 +0300 +++ b/src/mail/ngx_mail_handler.c Wed May 19 03:13:31 2021 +0300 @@ -874,7 +874,20 @@ ngx_mail_read_command(ngx_mail_session_t return NGX_MAIL_PARSE_INVALID_COMMAND; } - if (rc == NGX_IMAP_NEXT || rc == NGX_MAIL_PARSE_INVALID_COMMAND) { + if (rc == NGX_MAIL_PARSE_INVALID_COMMAND) { + + s->errors++; + + if (s->errors >= cscf->max_errors) { + ngx_log_error(NGX_LOG_INFO, c->log, 0, + "client sent too many invalid commands"); + s->quit = 1; + } + + return rc; + } + + if (rc == NGX_IMAP_NEXT) { return rc; } From ru at nginx.com Wed May 19 13:24:40 2021 From: ru at nginx.com (Ruslan Ermilov) Date: Wed, 19 May 2021 13:24:40 +0000 Subject: [nginx] Core: fixed comment about msie_refresh escaping. Message-ID: details: https://hg.nginx.org/nginx/rev/5772da03faf8 branches: changeset: 7845:5772da03faf8 user: Ruslan Ermilov date: Wed May 19 16:24:13 2021 +0300 description: Core: fixed comment about msie_refresh escaping. After 12a656452ad1, the "%" character is no longer escaped by ngx_escape_uri(NGX_ESCAPE_REFRESH). diffstat: src/core/ngx_string.c | 2 +- 1 files changed, 1 insertions(+), 1 deletions(-) diffs (12 lines): diff -r ec1071830799 -r 5772da03faf8 src/core/ngx_string.c --- a/src/core/ngx_string.c Wed May 19 03:13:31 2021 +0300 +++ b/src/core/ngx_string.c Wed May 19 16:24:13 2021 +0300 @@ -1573,7 +1573,7 @@ ngx_escape_uri(u_char *dst, u_char *src, 0xffffffff /* 1111 1111 1111 1111 1111 1111 1111 1111 */ }; - /* " ", """, "%", "'", %00-%1F, %7F-%FF */ + /* " ", """, "'", %00-%1F, %7F-%FF */ static uint32_t refresh[] = { 0xffffffff, /* 1111 1111 1111 1111 1111 1111 1111 1111 */ From liu.yub at trip.com Thu May 20 10:00:01 2021 From: liu.yub at trip.com (=?gb2312?B?WXUgTGl1IKOowfXT7qOpo6hGVS1JQlWjqaOoufq8ytK1zvHR0Leisr+jqQ==?=) Date: Thu, 20 May 2021 10:00:01 +0000 Subject: [nginx-quic] fix the infinite loop issue for quic branch Message-ID: Hi Team, We tried nginx-quic on our server and found a problem. Please refer to the changeset below. Regards, Yu Liu # HG changeset patch # User Yu Liu > # Date 1621502282 -28800 # Thu May 20 17:18:02 2021 +0800 # Branch quic # Node ID 4055a366b23e29215f3b4eb1d104303e33266cd4 # Parent 557dc6a06ba6ea7e78444067c4b8fbb022f7b191 Fix the infinite loop issue When bits is greater than or equal to 3, value is always shifted 62 bits to the right. So when the input number is greater than 2 to the power of 62, this method will loop endlessly. diff -r 557dc6a06ba6 -r 4055a366b23e src/event/quic/ngx_event_quic_transport.c --- a/src/event/quic/ngx_event_quic_transport.c Tue May 18 18:17:25 2021 +0300 +++ b/src/event/quic/ngx_event_quic_transport.c Thu May 20 17:18:02 2021 +0800 @@ -250,7 +250,7 @@ ngx_uint_t bits; bits = 0; - while (value >> ((8 << bits) - 2)) { + while (bits <=3 && (value >> ((8 << bits) - 2))) { bits++; } -------------- next part -------------- An HTML attachment was scrubbed... URL: From ru at nginx.com Thu May 20 17:02:44 2021 From: ru at nginx.com (Ruslan Ermilov) Date: Thu, 20 May 2021 17:02:44 +0000 Subject: [nginx] Stream: the "fastopen" parameter of the "listen" directive. Message-ID: details: https://hg.nginx.org/nginx/rev/2ab7b55ae4a0 branches: changeset: 7846:2ab7b55ae4a0 user: Ruslan Ermilov date: Thu May 20 19:59:16 2021 +0300 description: Stream: the "fastopen" parameter of the "listen" directive. Based on a patch by Anbang Wen. diffstat: src/stream/ngx_stream.c | 4 ++++ src/stream/ngx_stream.h | 3 +++ src/stream/ngx_stream_core_module.c | 25 +++++++++++++++++++++++++ 3 files changed, 32 insertions(+), 0 deletions(-) diffs (76 lines): diff -r 5772da03faf8 -r 2ab7b55ae4a0 src/stream/ngx_stream.c --- a/src/stream/ngx_stream.c Wed May 19 16:24:13 2021 +0300 +++ b/src/stream/ngx_stream.c Thu May 20 19:59:16 2021 +0300 @@ -510,6 +510,10 @@ ngx_stream_optimize_servers(ngx_conf_t * ls->ipv6only = addr[i].opt.ipv6only; #endif +#if (NGX_HAVE_TCP_FASTOPEN) + ls->fastopen = addr[i].opt.fastopen; +#endif + #if (NGX_HAVE_REUSEPORT) ls->reuseport = addr[i].opt.reuseport; #endif diff -r 5772da03faf8 -r 2ab7b55ae4a0 src/stream/ngx_stream.h --- a/src/stream/ngx_stream.h Wed May 19 16:24:13 2021 +0300 +++ b/src/stream/ngx_stream.h Thu May 20 19:59:16 2021 +0300 @@ -65,6 +65,9 @@ typedef struct { int backlog; int rcvbuf; int sndbuf; +#if (NGX_HAVE_TCP_FASTOPEN) + int fastopen; +#endif int type; } ngx_stream_listen_t; diff -r 5772da03faf8 -r 2ab7b55ae4a0 src/stream/ngx_stream_core_module.c --- a/src/stream/ngx_stream_core_module.c Wed May 19 16:24:13 2021 +0300 +++ b/src/stream/ngx_stream_core_module.c Thu May 20 19:59:16 2021 +0300 @@ -615,6 +615,10 @@ ngx_stream_core_listen(ngx_conf_t *cf, n ls->type = SOCK_STREAM; ls->ctx = cf->ctx; +#if (NGX_HAVE_TCP_FASTOPEN) + ls->fastopen = -1; +#endif + #if (NGX_HAVE_INET6) ls->ipv6only = 1; #endif @@ -635,6 +639,21 @@ ngx_stream_core_listen(ngx_conf_t *cf, n continue; } +#if (NGX_HAVE_TCP_FASTOPEN) + if (ngx_strncmp(value[i].data, "fastopen=", 9) == 0) { + ls->fastopen = ngx_atoi(value[i].data + 9, value[i].len - 9); + ls->bind = 1; + + if (ls->fastopen == NGX_ERROR) { + ngx_conf_log_error(NGX_LOG_EMERG, cf, 0, + "invalid fastopen \"%V\"", &value[i]); + return NGX_CONF_ERROR; + } + + continue; + } +#endif + if (ngx_strncmp(value[i].data, "backlog=", 8) == 0) { ls->backlog = ngx_atoi(value[i].data + 8, value[i].len - 8); ls->bind = 1; @@ -859,6 +878,12 @@ ngx_stream_core_listen(ngx_conf_t *cf, n if (ls->proxy_protocol) { return "\"proxy_protocol\" parameter is incompatible with \"udp\""; } + +#if (NGX_HAVE_TCP_FASTOPEN) + if (ls->fastopen != -1) { + return "\"fastopen\" parameter is incompatible with \"udp\""; + } +#endif } als = cmcf->listen.elts; From sunzhiyong3210 at gmail.com Mon May 24 03:13:08 2021 From: sunzhiyong3210 at gmail.com (sun edward) Date: Mon, 24 May 2021 11:13:08 +0800 Subject: fix index type when looking up dynamic table Message-ID: # HG changeset patch # User Zhiyong Sun # Date 1621825861 14400 # Sun May 23 23:11:01 2021 -0400 # Branch quic # Node ID be8115b87d5abbd8d5e6afdccbcf2c0c2016113c # Parent 557dc6a06ba6ea7e78444067c4b8fbb022f7b191 convert qpack absolute index to relative index when lookup dynamic table diff -r 557dc6a06ba6 -r be8115b87d5a src/http/v3/ngx_http_v3_tables.c --- a/src/http/v3/ngx_http_v3_tables.c Tue May 18 18:17:25 2021 +0300 +++ b/src/http/v3/ngx_http_v3_tables.c Sun May 23 23:11:01 2021 -0400 @@ -159,9 +159,19 @@ ngx_http_v3_ref_insert(ngx_connection_t *c, ngx_uint_t dynamic, ngx_uint_t index, ngx_str_t *value) { + ngx_http_v3_connection_t *h3c; + ngx_http_v3_dynamic_table_t *dt; ngx_str_t name; if (dynamic) { + h3c = c->quic->parent->data; + dt = &h3c->table; + + if (dt->base + dt->nelts <= index) { + return NGX_HTTP_V3_ERR_ENCODER_STREAM_ERROR; + } + + index = dt->base + dt->nelts - 1 - index; ngx_log_debug2(NGX_LOG_DEBUG_HTTP, c->log, 0, "http3 ref insert dynamic[%ui] \"%V\"", index, value); -------------- next part -------------- An HTML attachment was scrubbed... URL: From sunzhiyong3210 at gmail.com Mon May 24 03:34:04 2021 From: sunzhiyong3210 at gmail.com (sun edward) Date: Mon, 24 May 2021 11:34:04 +0800 Subject: [nginx-quic] fix qpack index issue when lookingup dynamic table Message-ID: description: when qpack header insert with name reference, if it is dynamic table, the index should be the relative index, as described in drafts: https://quicwg.org/base-drafts/draft-ietf-quic-qpack.html#name-insert-with-name-reference # HG changeset patch # User Zhiyong Sun # Date 1621825861 14400 # Sun May 23 23:11:01 2021 -0400 # Branch quic # Node ID be8115b87d5abbd8d5e6afdccbcf2c0c2016113c # Parent 557dc6a06ba6ea7e78444067c4b8fbb022f7b191 convert qpack absolute index to relative index when lookup dynamic table diff -r 557dc6a06ba6 -r be8115b87d5a src/http/v3/ngx_http_v3_tables.c --- a/src/http/v3/ngx_http_v3_tables.c Tue May 18 18:17:25 2021 +0300 +++ b/src/http/v3/ngx_http_v3_tables.c Sun May 23 23:11:01 2021 -0400 @@ -159,9 +159,19 @@ ngx_http_v3_ref_insert(ngx_connection_t *c, ngx_uint_t dynamic, ngx_uint_t index, ngx_str_t *value) { + ngx_http_v3_connection_t *h3c; + ngx_http_v3_dynamic_table_t *dt; ngx_str_t name; if (dynamic) { + h3c = c->quic->parent->data; + dt = &h3c->table; + + if (dt->base + dt->nelts <= index) { + return NGX_HTTP_V3_ERR_ENCODER_STREAM_ERROR; + } + + index = dt->base + dt->nelts - 1 - index; ngx_log_debug2(NGX_LOG_DEBUG_HTTP, c->log, 0, "http3 ref insert dynamic[%ui] \"%V\"", index, value); -------------- next part -------------- An HTML attachment was scrubbed... URL: From xeioex at nginx.com Mon May 24 10:52:20 2021 From: xeioex at nginx.com (Dmitry Volyntsev) Date: Mon, 24 May 2021 10:52:20 +0000 Subject: [njs] Fixed undefined behaviour in njs_number_to_integer(). Message-ID: details: https://hg.nginx.org/njs/rev/87f91ff16931 branches: changeset: 1638:87f91ff16931 user: Dmitry Volyntsev date: Mon May 24 10:51:47 2021 +0000 description: Fixed undefined behaviour in njs_number_to_integer(). C11: 6.3.1.4 ... If the value of the integral part cannot be represented by the integer type, the behavior is undefined. Found by OSS-Fuzz. diffstat: src/njs_number.h | 14 +++++++------- src/test/njs_unit_test.c | 3 +++ 2 files changed, 10 insertions(+), 7 deletions(-) diffs (42 lines): diff -r 7b70ee90ead8 -r 87f91ff16931 src/njs_number.h --- a/src/njs_number.h Mon May 17 20:35:35 2021 +0300 +++ b/src/njs_number.h Mon May 24 10:51:47 2021 +0000 @@ -56,18 +56,18 @@ njs_key_is_integer_index(double num, con njs_inline int64_t njs_number_to_integer(double num) { - if (njs_slow_path(isinf(num))) { - if (num < 0) { + if (njs_fast_path(!isnan(num))) { + if (num < INT64_MIN) { return INT64_MIN; + + } else if (num > INT64_MAX) { + return INT64_MAX; } - return INT64_MAX; - - } else if (njs_slow_path(isnan(num))) { - return 0; + return num; } - return trunc(num) + 0.0; + return 0; } diff -r 7b70ee90ead8 -r 87f91ff16931 src/test/njs_unit_test.c --- a/src/test/njs_unit_test.c Mon May 17 20:35:35 2021 +0300 +++ b/src/test/njs_unit_test.c Mon May 24 10:51:47 2021 +0000 @@ -8882,6 +8882,9 @@ static njs_unit_test_t njs_test[] = { njs_str("''.repeat(2147483648)"), njs_str("") }, + { njs_str("'aaaaaaaa'.repeat(2**64+1)"), + njs_str("RangeError") }, + { njs_str("''.repeat(Infinity)"), njs_str("RangeError") }, From xeioex at nginx.com Mon May 24 10:52:22 2021 From: xeioex at nginx.com (Dmitry Volyntsev) Date: Mon, 24 May 2021 10:52:22 +0000 Subject: [njs] Simplified String.prototype.repeat() to match the spec. Message-ID: details: https://hg.nginx.org/njs/rev/f1e8e753417d branches: changeset: 1639:f1e8e753417d user: Dmitry Volyntsev date: Mon May 24 10:51:48 2021 +0000 description: Simplified String.prototype.repeat() to match the spec. diffstat: src/njs_string.c | 7 ++----- 1 files changed, 2 insertions(+), 5 deletions(-) diffs (32 lines): diff -r 87f91ff16931 -r f1e8e753417d src/njs_string.c --- a/src/njs_string.c Mon May 24 10:51:47 2021 +0000 +++ b/src/njs_string.c Mon May 24 10:51:48 2021 +0000 @@ -2924,7 +2924,6 @@ njs_string_prototype_repeat(njs_vm_t *vm njs_index_t unused) { u_char *p; - double count; int64_t n, max; uint64_t size, length; njs_int_t ret; @@ -2944,18 +2943,16 @@ njs_string_prototype_repeat(njs_vm_t *vm return ret; } - ret = njs_value_to_number(vm, njs_arg(args, nargs, 1), &count); + ret = njs_value_to_integer(vm, njs_arg(args, nargs, 1), &n); if (njs_slow_path(ret != NJS_OK)) { return ret; } - if (njs_slow_path(!isnan(count) && (count < 0 || isinf(count)))) { + if (njs_slow_path(n < 0 || n == INT64_MAX)) { njs_range_error(vm, NULL); return NJS_ERROR; } - n = njs_number_to_integer(count); - (void) njs_string_prop(&string, this); if (njs_slow_path(n == 0 || string.size == 0)) { From xeioex at nginx.com Mon May 24 12:35:27 2021 From: xeioex at nginx.com (Dmitry Volyntsev) Date: Mon, 24 May 2021 12:35:27 +0000 Subject: [njs] Suppressed spurious compilation warning with gcc-7 and older. Message-ID: details: https://hg.nginx.org/njs/rev/55d405b30979 branches: changeset: 1640:55d405b30979 user: Dmitry Volyntsev date: Mon May 24 12:33:36 2021 +0000 description: Suppressed spurious compilation warning with gcc-7 and older. src/njs_regexp.c:1335:19: error: ?pos? may be used uninitialized in this function [-Werror=maybe-uninitialized] pos = njs_string_offset(s.start, s.start + s.size, pos) - s.start; diffstat: src/njs_regexp.c | 1 + 1 files changed, 1 insertions(+), 0 deletions(-) diffs (11 lines): diff -r f1e8e753417d -r 55d405b30979 src/njs_regexp.c --- a/src/njs_regexp.c Mon May 24 10:51:48 2021 +0000 +++ b/src/njs_regexp.c Mon May 24 12:33:36 2021 +0000 @@ -1301,6 +1301,7 @@ njs_regexp_prototype_symbol_replace(njs_ } i = 0; + pos = 0; next_pos = 0; while (i < results.items) { From xeioex at nginx.com Mon May 24 12:35:29 2021 From: xeioex at nginx.com (Dmitry Volyntsev) Date: Mon, 24 May 2021 12:35:29 +0000 Subject: [njs] Fixed implicit long to double conversion warning. Message-ID: details: https://hg.nginx.org/njs/rev/98f436565ddf branches: changeset: 1641:98f436565ddf user: Dmitry Volyntsev date: Mon May 24 12:33:43 2021 +0000 description: Fixed implicit long to double conversion warning. error: implicit conversion from 'long' to 'double' changes value from 9223372036854775807 to 9223372036854775808. diffstat: src/njs_number.h | 8 +++++--- 1 files changed, 5 insertions(+), 3 deletions(-) diffs (27 lines): diff -r 55d405b30979 -r 98f436565ddf src/njs_number.h --- a/src/njs_number.h Mon May 24 12:33:36 2021 +0000 +++ b/src/njs_number.h Mon May 24 12:33:43 2021 +0000 @@ -8,7 +8,9 @@ #define _NJS_NUMBER_H_INCLUDED_ -#define NJS_MAX_LENGTH (0x1fffffffffffffLL) +#define NJS_MAX_LENGTH (0x1fffffffffffffLL) +#define NJS_INT64_DBL_MIN (-9.223372036854776e+18) /* closest to INT64_MIN */ +#define NJS_INT64_DBL_MAX (9.223372036854776e+18) /* closest to INT64_MAX */ double njs_key_to_index(const njs_value_t *value); @@ -57,10 +59,10 @@ njs_inline int64_t njs_number_to_integer(double num) { if (njs_fast_path(!isnan(num))) { - if (num < INT64_MIN) { + if (num < NJS_INT64_DBL_MIN) { return INT64_MIN; - } else if (num > INT64_MAX) { + } else if (num > NJS_INT64_DBL_MAX) { return INT64_MAX; } From xeioex at nginx.com Mon May 24 14:18:47 2021 From: xeioex at nginx.com (Dmitry Volyntsev) Date: Mon, 24 May 2021 14:18:47 +0000 Subject: [njs] Fixed integer-overflow in ToInt32(). Message-ID: details: https://hg.nginx.org/njs/rev/a33a16ec5aa0 branches: changeset: 1642:a33a16ec5aa0 user: Dmitry Volyntsev date: Mon May 24 14:17:59 2021 +0000 description: Fixed integer-overflow in ToInt32(). error: negation of -2147483648 cannot be represented in type 'int32_t'. Found by OSS-Fuzz. diffstat: src/njs_number.h | 2 +- 1 files changed, 1 insertions(+), 1 deletions(-) diffs (12 lines): diff -r 98f436565ddf -r a33a16ec5aa0 src/njs_number.h --- a/src/njs_number.h Mon May 24 12:33:43 2021 +0000 +++ b/src/njs_number.h Mon May 24 14:17:59 2021 +0000 @@ -76,7 +76,7 @@ njs_number_to_integer(double num) njs_inline int32_t njs_number_to_int32(double num) { - int32_t r; + uint32_t r; uint64_t v; njs_int_t exp; njs_diyfp_conv_t conv; From xeioex at nginx.com Mon May 24 14:18:49 2021 From: xeioex at nginx.com (Dmitry Volyntsev) Date: Mon, 24 May 2021 14:18:49 +0000 Subject: [njs] Fixed ToInt32() with values >= 2**(53+30). Message-ID: details: https://hg.nginx.org/njs/rev/801e2dbc79c9 branches: changeset: 1643:801e2dbc79c9 user: Dmitry Volyntsev date: Mon May 24 14:18:15 2021 +0000 description: Fixed ToInt32() with values >= 2**(53+30). diffstat: src/njs_number.h | 6 ++-- src/test/njs_unit_test.c | 65 ++++++++++++++++++++++++++++++++++++++++++++++++ 2 files changed, 68 insertions(+), 3 deletions(-) diffs (109 lines): diff -r a33a16ec5aa0 -r 801e2dbc79c9 src/njs_number.h --- a/src/njs_number.h Mon May 24 14:17:59 2021 +0000 +++ b/src/njs_number.h Mon May 24 14:18:15 2021 +0000 @@ -85,12 +85,12 @@ njs_number_to_int32(double num) exp = (conv.u64 & NJS_DBL_EXPONENT_MASK) >> NJS_DBL_SIGNIFICAND_SIZE; - if (njs_fast_path(exp < (NJS_DBL_EXPONENT_OFFSET + 30))) { + if (njs_fast_path(exp < (NJS_DBL_EXPONENT_OFFSET + 31))) { /* |num| < 2**31. */ return num; } - if (exp < (NJS_DBL_EXPONENT_OFFSET + 30 + 53)) { + if (exp < (NJS_DBL_EXPONENT_OFFSET + 31 + 53)) { v = (conv.u64 & NJS_DBL_SIGNIFICAND_MASK) | NJS_DBL_HIDDEN_BIT; v <<= (exp - NJS_DBL_EXPONENT_BIAS + 32); r = v >> 32; @@ -105,7 +105,7 @@ njs_number_to_int32(double num) /* * ES5.1: integer must be modulo 2^32. * The distance between larger doubles - * (exp >= NJS_DBL_EXPONENT_OFFSET + 30 + 53) is a multiple of 2**32 => 0. + * (exp >= NJS_DBL_EXPONENT_OFFSET + 31 + 53) is a multiple of 2**32 => 0. * This also handles NaN and Inf. */ diff -r a33a16ec5aa0 -r 801e2dbc79c9 src/test/njs_unit_test.c --- a/src/test/njs_unit_test.c Mon May 24 14:17:59 2021 +0000 +++ b/src/test/njs_unit_test.c Mon May 24 14:18:15 2021 +0000 @@ -22304,6 +22304,69 @@ njs_string_to_index_test(njs_vm_t *vm, n static njs_int_t +njs_to_int32_test(njs_vm_t *vm, njs_opts_t *opts, njs_stat_t *stat) +{ + int32_t i32, second; + njs_uint_t i; + + static const struct { + double value; + int32_t expected; + } tests[] = { + { -1.0, -1 }, + { 0.0, 0 }, + { 0.001, 0 }, + { 1.0, 1 }, + { 2147483647.0, 2147483647 }, + { 2147483648.0, -2147483648 }, + { 2147483649.0, -2147483647 }, + { -1844674406941458432.0, -2147483648 }, + { 4.835703278458518e+24 /* 2**(53+29) + 2**30 */, 1073741824 }, + { 9.671406556917036e+24 /* 2**(53+30) + 2**31 */, -2147483648 }, + }; + + for (i = 0; i < njs_nitems(tests); i++) { + i32 = njs_number_to_int32(tests[i].value); + + if (i32 != tests[i].expected) { + njs_printf("njs_to_int32_test(%f):\n" + "expected: %D\n got: %D\n", + tests[i].value, tests[i].expected, i32); + + stat->failed++; + continue; + } + + second = njs_number_to_int32(i32); + + if (i32 != second) { + njs_printf("njs_to_int32_test(%f): not idempodent\n" + "expected: %D\n got: %D\n", + tests[i].value, i32, second); + + stat->failed++; + continue; + } + + second = njs_number_to_int32(njs_number_to_uint32(tests[i].value)); + + if (i32 != second) { + njs_printf("ToInt32(%f) != ToInt32(ToUint32(%f))\n" + "left: %D\n right: %D\n", + tests[i].value, tests[i].value, i32, second); + + stat->failed++; + continue; + } + + stat->passed++; + } + + return NJS_OK; +} + + +static njs_int_t njs_vm_internal_api_test(njs_unit_test_t unused[], size_t num, njs_str_t *name, njs_opts_t *opts, njs_stat_t *stat) { @@ -22329,6 +22392,8 @@ njs_vm_internal_api_test(njs_unit_test_t njs_str("njs_sort_test") }, { njs_string_to_index_test, njs_str("njs_string_to_index_test") }, + { njs_to_int32_test, + njs_str("njs_to_int32_test") }, }; vm = NULL; From mdounin at mdounin.ru Mon May 24 15:24:44 2021 From: mdounin at mdounin.ru (Maxim Dounin) Date: Mon, 24 May 2021 15:24:44 +0000 Subject: [nginx] Fixed log action when using SSL certificates with variables. Message-ID: details: https://hg.nginx.org/nginx/rev/1336a33cff33 branches: changeset: 7847:1336a33cff33 user: Maxim Dounin date: Mon May 24 18:23:42 2021 +0300 description: Fixed log action when using SSL certificates with variables. When variables are used in ssl_certificate or ssl_certificate_key, a request is created in the certificate callback to evaluate the variables, and then freed. Freeing it, however, updates c->log->action to "closing request", resulting in confusing error messages like "client timed out ... while closing request" when a client times out during the SSL handshake. Fix is to restore c->log->action after calling ngx_http_free_request(). diffstat: src/http/ngx_http_request.c | 2 ++ 1 files changed, 2 insertions(+), 0 deletions(-) diffs (18 lines): diff -r 2ab7b55ae4a0 -r 1336a33cff33 src/http/ngx_http_request.c --- a/src/http/ngx_http_request.c Thu May 20 19:59:16 2021 +0300 +++ b/src/http/ngx_http_request.c Mon May 24 18:23:42 2021 +0300 @@ -1043,12 +1043,14 @@ ngx_http_ssl_certificate(ngx_ssl_conn_t } ngx_http_free_request(r, 0); + c->log->action = "SSL handshaking"; c->destroyed = 0; return 1; failed: ngx_http_free_request(r, 0); + c->log->action = "SSL handshaking"; c->destroyed = 0; return 0; } From pluknet at nginx.com Mon May 24 15:45:03 2021 From: pluknet at nginx.com (Sergey Kandaurov) Date: Mon, 24 May 2021 18:45:03 +0300 Subject: [nginx-quic] fix the infinite loop issue for quic branch In-Reply-To: References: Message-ID: > On 20 May 2021, at 13:00, Yu Liu ?????FU-IBU?????????? wrote: > > Hi Team, > > We tried nginx-quic on our server and found a problem. Please refer to the changeset below. > > Regards, > Yu Liu A different patch was committed. It should be fixed now, thanks. http://hg.nginx.org/nginx-quic/rev/81d491f0dc8c -- Sergey Kandaurov From ru at nginx.com Mon May 24 18:57:10 2021 From: ru at nginx.com (Ruslan Ermilov) Date: Mon, 24 May 2021 18:57:10 +0000 Subject: [nginx] Location header escaping in redirects (ticket #882). Message-ID: details: https://hg.nginx.org/nginx/rev/1bde031b59ff branches: changeset: 7848:1bde031b59ff user: Ruslan Ermilov date: Mon May 24 21:55:20 2021 +0300 description: Location header escaping in redirects (ticket #882). The header is escaped in redirects based on request URI or location name (auto redirect). diffstat: src/http/modules/ngx_http_dav_module.c | 25 ++++++++++++++++++++- src/http/modules/ngx_http_static_module.c | 17 +++++++++++-- src/http/ngx_http.c | 37 +++++++++++++++++++++++++++++++ src/http/ngx_http_core_module.c | 7 +++-- src/http/ngx_http_core_module.h | 1 + 5 files changed, 80 insertions(+), 7 deletions(-) diffs (187 lines): diff -r 1336a33cff33 -r 1bde031b59ff src/http/modules/ngx_http_dav_module.c --- a/src/http/modules/ngx_http_dav_module.c Mon May 24 18:23:42 2021 +0300 +++ b/src/http/modules/ngx_http_dav_module.c Mon May 24 21:55:20 2021 +0300 @@ -1072,6 +1072,10 @@ ngx_http_dav_error(ngx_log_t *log, ngx_e static ngx_int_t ngx_http_dav_location(ngx_http_request_t *r) { + u_char *p; + size_t len; + uintptr_t escape; + r->headers_out.location = ngx_list_push(&r->headers_out.headers); if (r->headers_out.location == NULL) { return NGX_ERROR; @@ -1079,7 +1083,26 @@ ngx_http_dav_location(ngx_http_request_t r->headers_out.location->hash = 1; ngx_str_set(&r->headers_out.location->key, "Location"); - r->headers_out.location->value = r->uri; + + escape = 2 * ngx_escape_uri(NULL, r->uri.data, r->uri.len, NGX_ESCAPE_URI); + + if (escape) { + len = r->uri.len + escape; + + p = ngx_pnalloc(r->pool, len); + if (p == NULL) { + ngx_http_clear_location(r); + return NGX_ERROR; + } + + r->headers_out.location->value.len = len; + r->headers_out.location->value.data = p; + + ngx_escape_uri(p, r->uri.data, r->uri.len, NGX_ESCAPE_URI); + + } else { + r->headers_out.location->value = r->uri; + } return NGX_OK; } diff -r 1336a33cff33 -r 1bde031b59ff src/http/modules/ngx_http_static_module.c --- a/src/http/modules/ngx_http_static_module.c Mon May 24 18:23:42 2021 +0300 +++ b/src/http/modules/ngx_http_static_module.c Mon May 24 21:55:20 2021 +0300 @@ -50,6 +50,7 @@ ngx_http_static_handler(ngx_http_request { u_char *last, *location; size_t root, len; + uintptr_t escape; ngx_str_t path; ngx_int_t rc; ngx_uint_t level; @@ -155,14 +156,18 @@ ngx_http_static_handler(ngx_http_request return NGX_HTTP_INTERNAL_SERVER_ERROR; } - len = r->uri.len + 1; + escape = 2 * ngx_escape_uri(NULL, r->uri.data, r->uri.len, + NGX_ESCAPE_URI); - if (!clcf->alias && r->args.len == 0) { + if (!clcf->alias && r->args.len == 0 && escape == 0) { + len = r->uri.len + 1; location = path.data + root; *last = '/'; } else { + len = r->uri.len + escape + 1; + if (r->args.len) { len += r->args.len + 1; } @@ -173,7 +178,13 @@ ngx_http_static_handler(ngx_http_request return NGX_HTTP_INTERNAL_SERVER_ERROR; } - last = ngx_copy(location, r->uri.data, r->uri.len); + if (escape) { + last = (u_char *) ngx_escape_uri(location, r->uri.data, + r->uri.len, NGX_ESCAPE_URI); + + } else { + last = ngx_copy(location, r->uri.data, r->uri.len); + } *last = '/'; diff -r 1336a33cff33 -r 1bde031b59ff src/http/ngx_http.c --- a/src/http/ngx_http.c Mon May 24 18:23:42 2021 +0300 +++ b/src/http/ngx_http.c Mon May 24 21:55:20 2021 +0300 @@ -37,6 +37,8 @@ static ngx_int_t ngx_http_init_locations ngx_http_core_srv_conf_t *cscf, ngx_http_core_loc_conf_t *pclcf); static ngx_int_t ngx_http_init_static_location_trees(ngx_conf_t *cf, ngx_http_core_loc_conf_t *pclcf); +static ngx_int_t ngx_http_escape_location_name(ngx_conf_t *cf, + ngx_http_core_loc_conf_t *clcf); static ngx_int_t ngx_http_cmp_locations(const ngx_queue_t *one, const ngx_queue_t *two); static ngx_int_t ngx_http_join_exact_locations(ngx_conf_t *cf, @@ -882,6 +884,41 @@ ngx_http_add_location(ngx_conf_t *cf, ng ngx_queue_insert_tail(*locations, &lq->queue); + if (ngx_http_escape_location_name(cf, clcf) != NGX_OK) { + return NGX_ERROR; + } + + return NGX_OK; +} + + +static ngx_int_t +ngx_http_escape_location_name(ngx_conf_t *cf, ngx_http_core_loc_conf_t *clcf) +{ + u_char *p; + size_t len; + uintptr_t escape; + + escape = 2 * ngx_escape_uri(NULL, clcf->name.data, clcf->name.len, + NGX_ESCAPE_URI); + + if (escape) { + len = clcf->name.len + escape; + + p = ngx_pnalloc(cf->pool, len); + if (p == NULL) { + return NGX_ERROR; + } + + clcf->escaped_name.len = len; + clcf->escaped_name.data = p; + + ngx_escape_uri(p, clcf->name.data, clcf->name.len, NGX_ESCAPE_URI); + + } else { + clcf->escaped_name = clcf->name; + } + return NGX_OK; } diff -r 1336a33cff33 -r 1bde031b59ff src/http/ngx_http_core_module.c --- a/src/http/ngx_http_core_module.c Mon May 24 18:23:42 2021 +0300 +++ b/src/http/ngx_http_core_module.c Mon May 24 21:55:20 2021 +0300 @@ -1010,10 +1010,10 @@ ngx_http_core_find_config_phase(ngx_http ngx_str_set(&r->headers_out.location->key, "Location"); if (r->args.len == 0) { - r->headers_out.location->value = clcf->name; + r->headers_out.location->value = clcf->escaped_name; } else { - len = clcf->name.len + 1 + r->args.len; + len = clcf->escaped_name.len + 1 + r->args.len; p = ngx_pnalloc(r->pool, len); if (p == NULL) { @@ -1025,7 +1025,7 @@ ngx_http_core_find_config_phase(ngx_http r->headers_out.location->value.len = len; r->headers_out.location->value.data = p; - p = ngx_cpymem(p, clcf->name.data, clcf->name.len); + p = ngx_cpymem(p, clcf->escaped_name.data, clcf->escaped_name.len); *p++ = '?'; ngx_memcpy(p, r->args.data, r->args.len); } @@ -3467,6 +3467,7 @@ ngx_http_core_create_loc_conf(ngx_conf_t /* * set by ngx_pcalloc(): * + * clcf->escaped_name = { 0, NULL }; * clcf->root = { 0, NULL }; * clcf->limit_except = 0; * clcf->post_action = { 0, NULL }; diff -r 1336a33cff33 -r 1bde031b59ff src/http/ngx_http_core_module.h --- a/src/http/ngx_http_core_module.h Mon May 24 18:23:42 2021 +0300 +++ b/src/http/ngx_http_core_module.h Mon May 24 21:55:20 2021 +0300 @@ -299,6 +299,7 @@ typedef struct { struct ngx_http_core_loc_conf_s { ngx_str_t name; /* location name */ + ngx_str_t escaped_name; #if (NGX_PCRE) ngx_http_regex_t *regex; From mdounin at mdounin.ru Tue May 25 15:33:14 2021 From: mdounin at mdounin.ru (Maxim Dounin) Date: Tue, 25 May 2021 15:33:14 +0000 Subject: [nginx] Resolver: fixed off-by-one write in ngx_resolver_copy(). Message-ID: details: https://hg.nginx.org/nginx/rev/2fd40ee19c20 branches: changeset: 7849:2fd40ee19c20 user: Maxim Dounin date: Tue May 25 15:17:36 2021 +0300 description: Resolver: fixed off-by-one write in ngx_resolver_copy(). Reported by Luis Merino, Markus Vervier, Eric Sesterhenn, X41 D-Sec GmbH. diffstat: src/core/ngx_resolver.c | 8 ++++---- 1 files changed, 4 insertions(+), 4 deletions(-) diffs (23 lines): diff -r 1bde031b59ff -r 2fd40ee19c20 src/core/ngx_resolver.c --- a/src/core/ngx_resolver.c Mon May 24 21:55:20 2021 +0300 +++ b/src/core/ngx_resolver.c Tue May 25 15:17:36 2021 +0300 @@ -4008,15 +4008,15 @@ done: n = *src++; } else { + if (dst != name->data) { + *dst++ = '.'; + } + ngx_strlow(dst, src, n); dst += n; src += n; n = *src++; - - if (n != 0) { - *dst++ = '.'; - } } if (n == 0) { From mdounin at mdounin.ru Tue May 25 15:33:17 2021 From: mdounin at mdounin.ru (Maxim Dounin) Date: Tue, 25 May 2021 15:33:17 +0000 Subject: [nginx] Resolver: fixed off-by-one read in ngx_resolver_copy(). Message-ID: details: https://hg.nginx.org/nginx/rev/a093dd4ce154 branches: changeset: 7850:a093dd4ce154 user: Maxim Dounin date: Tue May 25 15:17:38 2021 +0300 description: Resolver: fixed off-by-one read in ngx_resolver_copy(). It is believed to be harmless, and in the worst case it uses some uninitialized memory as a part of the compression pointer length, eventually leading to the "name is out of DNS response" error. diffstat: src/core/ngx_resolver.c | 5 +++++ 1 files changed, 5 insertions(+), 0 deletions(-) diffs (15 lines): diff -r 2fd40ee19c20 -r a093dd4ce154 src/core/ngx_resolver.c --- a/src/core/ngx_resolver.c Tue May 25 15:17:36 2021 +0300 +++ b/src/core/ngx_resolver.c Tue May 25 15:17:38 2021 +0300 @@ -3958,6 +3958,11 @@ ngx_resolver_copy(ngx_resolver_t *r, ngx } if (n & 0xc0) { + if (p >= last) { + err = "name is out of DNS response"; + goto invalid; + } + n = ((n & 0x3f) << 8) + *p; p = &buf[n]; From mdounin at mdounin.ru Tue May 25 15:33:20 2021 From: mdounin at mdounin.ru (Maxim Dounin) Date: Tue, 25 May 2021 15:33:20 +0000 Subject: [nginx] Resolver: fixed label types handling in ngx_resolver_copy(). Message-ID: details: https://hg.nginx.org/nginx/rev/aa5f8825f24d branches: changeset: 7851:aa5f8825f24d user: Maxim Dounin date: Tue May 25 15:17:41 2021 +0300 description: Resolver: fixed label types handling in ngx_resolver_copy(). Previously, anything with any of the two high bits set were interpreted as compression pointers. This is incorrect, as RFC 1035 clearly states that "The 10 and 01 combinations are reserved for future use". Further, the 01 combination is actually allocated for EDNS extended label type (see RFC 2671 and RFC 6891), not really used though. Fix is to reject unrecognized label types rather than misinterpreting them as compression pointers. diffstat: src/core/ngx_resolver.c | 5 +++++ 1 files changed, 5 insertions(+), 0 deletions(-) diffs (15 lines): diff -r a093dd4ce154 -r aa5f8825f24d src/core/ngx_resolver.c --- a/src/core/ngx_resolver.c Tue May 25 15:17:38 2021 +0300 +++ b/src/core/ngx_resolver.c Tue May 25 15:17:41 2021 +0300 @@ -3958,6 +3958,11 @@ ngx_resolver_copy(ngx_resolver_t *r, ngx } if (n & 0xc0) { + if ((n & 0xc0) != 0xc0) { + err = "invalid label type in DNS response"; + goto invalid; + } + if (p >= last) { err = "name is out of DNS response"; goto invalid; From mdounin at mdounin.ru Tue May 25 15:33:23 2021 From: mdounin at mdounin.ru (Maxim Dounin) Date: Tue, 25 May 2021 15:33:23 +0000 Subject: [nginx] Resolver: reworked ngx_resolver_copy() copy loop. Message-ID: details: https://hg.nginx.org/nginx/rev/771743838cbd branches: changeset: 7852:771743838cbd user: Maxim Dounin date: Tue May 25 15:17:43 2021 +0300 description: Resolver: reworked ngx_resolver_copy() copy loop. To make the code easier to read, reworked the ngx_resolver_copy() copy loop to match the one used to calculate length. No functional changes. diffstat: src/core/ngx_resolver.c | 18 +++++++----------- 1 files changed, 7 insertions(+), 11 deletions(-) diffs (40 lines): diff -r aa5f8825f24d -r 771743838cbd src/core/ngx_resolver.c --- a/src/core/ngx_resolver.c Tue May 25 15:17:41 2021 +0300 +++ b/src/core/ngx_resolver.c Tue May 25 15:17:43 2021 +0300 @@ -4008,15 +4008,18 @@ done: name->data = dst; - n = *src++; - for ( ;; ) { + n = *src++; + + if (n == 0) { + name->len = dst - name->data; + return NGX_OK; + } + if (n & 0xc0) { n = ((n & 0x3f) << 8) + *src; src = &buf[n]; - n = *src++; - } else { if (dst != name->data) { *dst++ = '.'; @@ -4025,13 +4028,6 @@ done: ngx_strlow(dst, src, n); dst += n; src += n; - - n = *src++; - } - - if (n == 0) { - name->len = dst - name->data; - return NGX_OK; } } } From mdounin at mdounin.ru Tue May 25 15:33:26 2021 From: mdounin at mdounin.ru (Maxim Dounin) Date: Tue, 25 May 2021 15:33:26 +0000 Subject: [nginx] Resolver: simplified ngx_resolver_copy(). Message-ID: details: https://hg.nginx.org/nginx/rev/4ebe1251a8c3 branches: changeset: 7853:4ebe1251a8c3 user: Maxim Dounin date: Tue May 25 15:17:45 2021 +0300 description: Resolver: simplified ngx_resolver_copy(). Instead of checking on each label if we need to place a dot or not, now it always adds a dot after a label, and reduces the resulting length afterwards. diffstat: src/core/ngx_resolver.c | 13 +++++-------- 1 files changed, 5 insertions(+), 8 deletions(-) diffs (50 lines): diff -r 771743838cbd -r 4ebe1251a8c3 src/core/ngx_resolver.c --- a/src/core/ngx_resolver.c Tue May 25 15:17:43 2021 +0300 +++ b/src/core/ngx_resolver.c Tue May 25 15:17:45 2021 +0300 @@ -3939,11 +3939,11 @@ ngx_resolver_copy(ngx_resolver_t *r, ngx { char *err; u_char *p, *dst; - ssize_t len; + size_t len; ngx_uint_t i, n; p = src; - len = -1; + len = 0; /* * compression pointers allow to create endless loop, so we set limit; @@ -3996,7 +3996,7 @@ done: return NGX_OK; } - if (len == -1) { + if (len == 0) { ngx_str_null(name); return NGX_OK; } @@ -4012,7 +4012,7 @@ done: n = *src++; if (n == 0) { - name->len = dst - name->data; + name->len = dst - name->data - 1; return NGX_OK; } @@ -4021,13 +4021,10 @@ done: src = &buf[n]; } else { - if (dst != name->data) { - *dst++ = '.'; - } - ngx_strlow(dst, src, n); dst += n; src += n; + *dst++ = '.'; } } } From mdounin at mdounin.ru Tue May 25 15:33:29 2021 From: mdounin at mdounin.ru (Maxim Dounin) Date: Tue, 25 May 2021 15:33:29 +0000 Subject: [nginx] Resolver: explicit check for compression pointers in question. Message-ID: details: https://hg.nginx.org/nginx/rev/4364b39de407 branches: changeset: 7854:4364b39de407 user: Maxim Dounin date: Tue May 25 15:17:50 2021 +0300 description: Resolver: explicit check for compression pointers in question. Since nginx always uses exactly one entry in the question section of a DNS query, and never uses compression pointers in this entry, parsing of a DNS response in ngx_resolver_process_response() does not expect compression pointers to appear in the question section of the DNS response. Indeed, compression pointers in the first name of a DNS response hardly make sense, do not seem to be allowed by RFC 1035 (which says "a pointer to a prior occurance of the same name", note "prior"), and were never observed in practice. Added an explicit check to ngx_resolver_process_response()'s parsing of the question section to properly report an error if compression pointers nevertheless appear in the question section. diffstat: src/core/ngx_resolver.c | 6 ++++++ 1 files changed, 6 insertions(+), 0 deletions(-) diffs (16 lines): diff -r 4ebe1251a8c3 -r 4364b39de407 src/core/ngx_resolver.c --- a/src/core/ngx_resolver.c Tue May 25 15:17:45 2021 +0300 +++ b/src/core/ngx_resolver.c Tue May 25 15:17:50 2021 +0300 @@ -1798,6 +1798,12 @@ ngx_resolver_process_response(ngx_resolv i = sizeof(ngx_resolver_hdr_t); while (i < (ngx_uint_t) n) { + + if (buf[i] & 0xc0) { + err = "unexpected compression pointer in DNS response"; + goto done; + } + if (buf[i] == '\0') { goto found; } From mdounin at mdounin.ru Tue May 25 15:33:33 2021 From: mdounin at mdounin.ru (Maxim Dounin) Date: Tue, 25 May 2021 15:33:33 +0000 Subject: [nginx] nginx-1.21.0-RELEASE Message-ID: details: https://hg.nginx.org/nginx/rev/df34dcc9ac07 branches: changeset: 7855:df34dcc9ac07 user: Maxim Dounin date: Tue May 25 15:28:55 2021 +0300 description: nginx-1.21.0-RELEASE diffstat: docs/xml/nginx/changes.xml | 94 ++++++++++++++++++++++++++++++++++++++++++++++ 1 files changed, 94 insertions(+), 0 deletions(-) diffs (104 lines): diff -r 4364b39de407 -r df34dcc9ac07 docs/xml/nginx/changes.xml --- a/docs/xml/nginx/changes.xml Tue May 25 15:17:50 2021 +0300 +++ b/docs/xml/nginx/changes.xml Tue May 25 15:28:55 2021 +0300 @@ -5,6 +5,100 @@ + + + + +??? ????????????? ????????? resolver +?? ????? ????????? ?????? DNS-??????? +????? ??????????? ?????????? ?????? ????? ??????, +??? ????????? ??????????, +???????? ??????????? ??????????? UDP-?????? ?? DNS-???????, +??????? ??????? ???????? ???????? +???, ????????????, ?????????? ????????????? ???? (CVE-2021-23017). + + +1-byte memory overwrite might occur +during DNS server response processing +if the "resolver" directive was used, +allowing an attacker +who is able to forge UDP packets from the DNS server +to cause worker process crash +or, potentially, arbitrary code execution (CVE-2021-23017). + + + + + +????????? proxy_ssl_certificate, proxy_ssl_certificate_key, +grpc_ssl_certificate, grpc_ssl_certificate_key, +uwsgi_ssl_certificate ? uwsgi_ssl_certificate_key +???????????? ??????????. + + +variables support +in the "proxy_ssl_certificate", "proxy_ssl_certificate_key" +"grpc_ssl_certificate", "grpc_ssl_certificate_key", +"uwsgi_ssl_certificate", and "uwsgi_ssl_certificate_key" directives. + + + + + +????????? max_errors ? ???????? ??????-???????. + + +the "max_errors" directive in the mail proxy module. + + + + + +???????? ??????-?????? ???????????? POP3 ? IMAP pipelining. + + +the mail proxy module supports POP3 and IMAP pipelining. + + + + + +???????? fastopen ????????? listen ? ?????? stream.
+??????? Anbang Wen. +
+ +the "fastopen" parameter of the "listen" directive in the stream module.
+Thanks to Anbang Wen. +
+
+ + + +??????????? ??????? ?? ?????????????? +??? ?????????????? ??????????????? ? ??????????? ???????????? ?????. + + +special characters were not escaped +during automatic redirect with appended trailing slash. + + + + + +??? ????????????? SMTP pipelining +?????????? ? ????????? ? ???????? ??????-??????? +????? ?????????? ???????????. + + +connections with clients in the mail proxy module +might be closed unexpectedly +when using SMTP pipelining. + + + +
+ + From mdounin at mdounin.ru Tue May 25 15:33:36 2021 From: mdounin at mdounin.ru (Maxim Dounin) Date: Tue, 25 May 2021 15:33:36 +0000 Subject: [nginx] release-1.21.0 tag Message-ID: details: https://hg.nginx.org/nginx/rev/f5de03f308a6 branches: changeset: 7856:f5de03f308a6 user: Maxim Dounin date: Tue May 25 15:28:56 2021 +0300 description: release-1.21.0 tag diffstat: .hgtags | 1 + 1 files changed, 1 insertions(+), 0 deletions(-) diffs (8 lines): diff -r df34dcc9ac07 -r f5de03f308a6 .hgtags --- a/.hgtags Tue May 25 15:28:55 2021 +0300 +++ b/.hgtags Tue May 25 15:28:56 2021 +0300 @@ -460,3 +460,4 @@ 3fa6e2095a7a51acc630517e1c27a7b7ac41f7b3 8c65d21464aaa5923775f80c32474adc7a320068 release-1.19.8 da571b8eaf8f30f36c43b3c9b25e01e31f47149c release-1.19.9 ffcbb9980ee2bad27b4d7b1cd680b14ff47b29aa release-1.19.10 +df34dcc9ac072ffd0945e5a1f3eb7987e8275375 release-1.21.0 From mdounin at mdounin.ru Tue May 25 15:34:07 2021 From: mdounin at mdounin.ru (Maxim Dounin) Date: Tue, 25 May 2021 15:34:07 +0000 Subject: [nginx] Version bump. Message-ID: details: https://hg.nginx.org/nginx/rev/76871d1340ea branches: stable-1.20 changeset: 7857:76871d1340ea user: Maxim Dounin date: Tue May 25 15:29:54 2021 +0300 description: Version bump. diffstat: src/core/nginx.h | 4 ++-- 1 files changed, 2 insertions(+), 2 deletions(-) diffs (14 lines): diff -r 3ebf8a5fb670 -r 76871d1340ea src/core/nginx.h --- a/src/core/nginx.h Tue Apr 20 16:35:47 2021 +0300 +++ b/src/core/nginx.h Tue May 25 15:29:54 2021 +0300 @@ -9,8 +9,8 @@ #define _NGINX_H_INCLUDED_ -#define nginx_version 1020000 -#define NGINX_VERSION "1.20.0" +#define nginx_version 1020001 +#define NGINX_VERSION "1.20.1" #define NGINX_VER "nginx/" NGINX_VERSION #ifdef NGX_BUILD From mdounin at mdounin.ru Tue May 25 15:34:10 2021 From: mdounin at mdounin.ru (Maxim Dounin) Date: Tue, 25 May 2021 15:34:10 +0000 Subject: [nginx] Resolver: fixed off-by-one write in ngx_resolver_copy(). Message-ID: details: https://hg.nginx.org/nginx/rev/7f702d35ac38 branches: stable-1.20 changeset: 7858:7f702d35ac38 user: Maxim Dounin date: Tue May 25 15:17:36 2021 +0300 description: Resolver: fixed off-by-one write in ngx_resolver_copy(). Reported by Luis Merino, Markus Vervier, Eric Sesterhenn, X41 D-Sec GmbH. diffstat: src/core/ngx_resolver.c | 8 ++++---- 1 files changed, 4 insertions(+), 4 deletions(-) diffs (23 lines): diff -r 76871d1340ea -r 7f702d35ac38 src/core/ngx_resolver.c --- a/src/core/ngx_resolver.c Tue May 25 15:29:54 2021 +0300 +++ b/src/core/ngx_resolver.c Tue May 25 15:17:36 2021 +0300 @@ -4008,15 +4008,15 @@ done: n = *src++; } else { + if (dst != name->data) { + *dst++ = '.'; + } + ngx_strlow(dst, src, n); dst += n; src += n; n = *src++; - - if (n != 0) { - *dst++ = '.'; - } } if (n == 0) { From mdounin at mdounin.ru Tue May 25 15:34:13 2021 From: mdounin at mdounin.ru (Maxim Dounin) Date: Tue, 25 May 2021 15:34:13 +0000 Subject: [nginx] Resolver: fixed off-by-one read in ngx_resolver_copy(). Message-ID: details: https://hg.nginx.org/nginx/rev/5d561a77502e branches: stable-1.20 changeset: 7859:5d561a77502e user: Maxim Dounin date: Tue May 25 15:17:38 2021 +0300 description: Resolver: fixed off-by-one read in ngx_resolver_copy(). It is believed to be harmless, and in the worst case it uses some uninitialized memory as a part of the compression pointer length, eventually leading to the "name is out of DNS response" error. diffstat: src/core/ngx_resolver.c | 5 +++++ 1 files changed, 5 insertions(+), 0 deletions(-) diffs (15 lines): diff -r 7f702d35ac38 -r 5d561a77502e src/core/ngx_resolver.c --- a/src/core/ngx_resolver.c Tue May 25 15:17:36 2021 +0300 +++ b/src/core/ngx_resolver.c Tue May 25 15:17:38 2021 +0300 @@ -3958,6 +3958,11 @@ ngx_resolver_copy(ngx_resolver_t *r, ngx } if (n & 0xc0) { + if (p >= last) { + err = "name is out of DNS response"; + goto invalid; + } + n = ((n & 0x3f) << 8) + *p; p = &buf[n]; From mdounin at mdounin.ru Tue May 25 15:34:16 2021 From: mdounin at mdounin.ru (Maxim Dounin) Date: Tue, 25 May 2021 15:34:16 +0000 Subject: [nginx] Resolver: fixed label types handling in ngx_resolver_copy(). Message-ID: details: https://hg.nginx.org/nginx/rev/a45b6a206cfc branches: stable-1.20 changeset: 7860:a45b6a206cfc user: Maxim Dounin date: Tue May 25 15:17:41 2021 +0300 description: Resolver: fixed label types handling in ngx_resolver_copy(). Previously, anything with any of the two high bits set were interpreted as compression pointers. This is incorrect, as RFC 1035 clearly states that "The 10 and 01 combinations are reserved for future use". Further, the 01 combination is actually allocated for EDNS extended label type (see RFC 2671 and RFC 6891), not really used though. Fix is to reject unrecognized label types rather than misinterpreting them as compression pointers. diffstat: src/core/ngx_resolver.c | 5 +++++ 1 files changed, 5 insertions(+), 0 deletions(-) diffs (15 lines): diff -r 5d561a77502e -r a45b6a206cfc src/core/ngx_resolver.c --- a/src/core/ngx_resolver.c Tue May 25 15:17:38 2021 +0300 +++ b/src/core/ngx_resolver.c Tue May 25 15:17:41 2021 +0300 @@ -3958,6 +3958,11 @@ ngx_resolver_copy(ngx_resolver_t *r, ngx } if (n & 0xc0) { + if ((n & 0xc0) != 0xc0) { + err = "invalid label type in DNS response"; + goto invalid; + } + if (p >= last) { err = "name is out of DNS response"; goto invalid; From mdounin at mdounin.ru Tue May 25 15:34:21 2021 From: mdounin at mdounin.ru (Maxim Dounin) Date: Tue, 25 May 2021 15:34:21 +0000 Subject: [nginx] Resolver: reworked ngx_resolver_copy() copy loop. Message-ID: details: https://hg.nginx.org/nginx/rev/0b884e47bb79 branches: stable-1.20 changeset: 7861:0b884e47bb79 user: Maxim Dounin date: Tue May 25 15:17:43 2021 +0300 description: Resolver: reworked ngx_resolver_copy() copy loop. To make the code easier to read, reworked the ngx_resolver_copy() copy loop to match the one used to calculate length. No functional changes. diffstat: src/core/ngx_resolver.c | 18 +++++++----------- 1 files changed, 7 insertions(+), 11 deletions(-) diffs (40 lines): diff -r a45b6a206cfc -r 0b884e47bb79 src/core/ngx_resolver.c --- a/src/core/ngx_resolver.c Tue May 25 15:17:41 2021 +0300 +++ b/src/core/ngx_resolver.c Tue May 25 15:17:43 2021 +0300 @@ -4008,15 +4008,18 @@ done: name->data = dst; - n = *src++; - for ( ;; ) { + n = *src++; + + if (n == 0) { + name->len = dst - name->data; + return NGX_OK; + } + if (n & 0xc0) { n = ((n & 0x3f) << 8) + *src; src = &buf[n]; - n = *src++; - } else { if (dst != name->data) { *dst++ = '.'; @@ -4025,13 +4028,6 @@ done: ngx_strlow(dst, src, n); dst += n; src += n; - - n = *src++; - } - - if (n == 0) { - name->len = dst - name->data; - return NGX_OK; } } } From mdounin at mdounin.ru Tue May 25 15:34:24 2021 From: mdounin at mdounin.ru (Maxim Dounin) Date: Tue, 25 May 2021 15:34:24 +0000 Subject: [nginx] Resolver: simplified ngx_resolver_copy(). Message-ID: details: https://hg.nginx.org/nginx/rev/60a1d97bedfe branches: stable-1.20 changeset: 7862:60a1d97bedfe user: Maxim Dounin date: Tue May 25 15:17:45 2021 +0300 description: Resolver: simplified ngx_resolver_copy(). Instead of checking on each label if we need to place a dot or not, now it always adds a dot after a label, and reduces the resulting length afterwards. diffstat: src/core/ngx_resolver.c | 13 +++++-------- 1 files changed, 5 insertions(+), 8 deletions(-) diffs (50 lines): diff -r 0b884e47bb79 -r 60a1d97bedfe src/core/ngx_resolver.c --- a/src/core/ngx_resolver.c Tue May 25 15:17:43 2021 +0300 +++ b/src/core/ngx_resolver.c Tue May 25 15:17:45 2021 +0300 @@ -3939,11 +3939,11 @@ ngx_resolver_copy(ngx_resolver_t *r, ngx { char *err; u_char *p, *dst; - ssize_t len; + size_t len; ngx_uint_t i, n; p = src; - len = -1; + len = 0; /* * compression pointers allow to create endless loop, so we set limit; @@ -3996,7 +3996,7 @@ done: return NGX_OK; } - if (len == -1) { + if (len == 0) { ngx_str_null(name); return NGX_OK; } @@ -4012,7 +4012,7 @@ done: n = *src++; if (n == 0) { - name->len = dst - name->data; + name->len = dst - name->data - 1; return NGX_OK; } @@ -4021,13 +4021,10 @@ done: src = &buf[n]; } else { - if (dst != name->data) { - *dst++ = '.'; - } - ngx_strlow(dst, src, n); dst += n; src += n; + *dst++ = '.'; } } } From mdounin at mdounin.ru Tue May 25 15:34:27 2021 From: mdounin at mdounin.ru (Maxim Dounin) Date: Tue, 25 May 2021 15:34:27 +0000 Subject: [nginx] Resolver: explicit check for compression pointers in question. Message-ID: details: https://hg.nginx.org/nginx/rev/3e78c12d4f37 branches: stable-1.20 changeset: 7863:3e78c12d4f37 user: Maxim Dounin date: Tue May 25 15:17:50 2021 +0300 description: Resolver: explicit check for compression pointers in question. Since nginx always uses exactly one entry in the question section of a DNS query, and never uses compression pointers in this entry, parsing of a DNS response in ngx_resolver_process_response() does not expect compression pointers to appear in the question section of the DNS response. Indeed, compression pointers in the first name of a DNS response hardly make sense, do not seem to be allowed by RFC 1035 (which says "a pointer to a prior occurance of the same name", note "prior"), and were never observed in practice. Added an explicit check to ngx_resolver_process_response()'s parsing of the question section to properly report an error if compression pointers nevertheless appear in the question section. diffstat: src/core/ngx_resolver.c | 6 ++++++ 1 files changed, 6 insertions(+), 0 deletions(-) diffs (16 lines): diff -r 60a1d97bedfe -r 3e78c12d4f37 src/core/ngx_resolver.c --- a/src/core/ngx_resolver.c Tue May 25 15:17:45 2021 +0300 +++ b/src/core/ngx_resolver.c Tue May 25 15:17:50 2021 +0300 @@ -1798,6 +1798,12 @@ ngx_resolver_process_response(ngx_resolv i = sizeof(ngx_resolver_hdr_t); while (i < (ngx_uint_t) n) { + + if (buf[i] & 0xc0) { + err = "unexpected compression pointer in DNS response"; + goto done; + } + if (buf[i] == '\0') { goto found; } From mdounin at mdounin.ru Tue May 25 15:34:30 2021 From: mdounin at mdounin.ru (Maxim Dounin) Date: Tue, 25 May 2021 15:34:30 +0000 Subject: [nginx] nginx-1.20.1-RELEASE Message-ID: details: https://hg.nginx.org/nginx/rev/39a422cf9876 branches: stable-1.20 changeset: 7864:39a422cf9876 user: Maxim Dounin date: Tue May 25 15:35:38 2021 +0300 description: nginx-1.20.1-RELEASE diffstat: docs/xml/nginx/changes.xml | 26 ++++++++++++++++++++++++++ 1 files changed, 26 insertions(+), 0 deletions(-) diffs (36 lines): diff -r 3e78c12d4f37 -r 39a422cf9876 docs/xml/nginx/changes.xml --- a/docs/xml/nginx/changes.xml Tue May 25 15:17:50 2021 +0300 +++ b/docs/xml/nginx/changes.xml Tue May 25 15:35:38 2021 +0300 @@ -5,6 +5,32 @@ + + + + +??? ????????????? ????????? resolver +?? ????? ????????? ?????? DNS-??????? +????? ??????????? ?????????? ?????? ????? ??????, +??? ????????? ??????????, +???????? ??????????? ??????????? UDP-?????? ?? DNS-???????, +??????? ??????? ???????? ???????? +???, ????????????, ?????????? ????????????? ???? (CVE-2021-23017). + + +1-byte memory overwrite might occur +during DNS server response processing +if the "resolver" directive was used, +allowing an attacker +who is able to forge UDP packets from the DNS server +to cause worker process crash +or, potentially, arbitrary code execution (CVE-2021-23017). + + + + + + From mdounin at mdounin.ru Tue May 25 15:34:32 2021 From: mdounin at mdounin.ru (Maxim Dounin) Date: Tue, 25 May 2021 15:34:32 +0000 Subject: [nginx] release-1.20.1 tag Message-ID: details: https://hg.nginx.org/nginx/rev/c14b92e0e626 branches: stable-1.20 changeset: 7865:c14b92e0e626 user: Maxim Dounin date: Tue May 25 15:35:38 2021 +0300 description: release-1.20.1 tag diffstat: .hgtags | 1 + 1 files changed, 1 insertions(+), 0 deletions(-) diffs (8 lines): diff -r 39a422cf9876 -r c14b92e0e626 .hgtags --- a/.hgtags Tue May 25 15:35:38 2021 +0300 +++ b/.hgtags Tue May 25 15:35:38 2021 +0300 @@ -461,3 +461,4 @@ 8c65d21464aaa5923775f80c32474adc7a320068 da571b8eaf8f30f36c43b3c9b25e01e31f47149c release-1.19.9 ffcbb9980ee2bad27b4d7b1cd680b14ff47b29aa release-1.19.10 1df854b66534be699b0b9bbe337d4f799ebf5d13 release-1.20.0 +39a422cf9876828e917c3b75747a6c276100976d release-1.20.1 From gmm at csdoc.com Wed May 26 20:42:59 2021 From: gmm at csdoc.com (Gena Makhomed) Date: Wed, 26 May 2021 23:42:59 +0300 Subject: [PATCH] Variable $time_short. Message-ID: # HG changeset patch # User Gena Makhomed # Date 1622061379 -10800 # Wed May 26 23:36:19 2021 +0300 # Node ID b3c942ec8a13bc8f6cd4b3e2385acb8c14502c0d # Parent f5de03f308a6d7864b7d5108a968db56585b9a9b Variable $time_short. Variable $time_short in form "1970/09/28 12:00:00". Added to ngx_http_core_module, ngx_http_log_module, and ngx_stream_core_module. diff -r f5de03f308a6 -r b3c942ec8a13 src/http/modules/ngx_http_log_module.c --- a/src/http/modules/ngx_http_log_module.c Tue May 25 15:28:56 2021 +0300 +++ b/src/http/modules/ngx_http_log_module.c Wed May 26 23:36:19 2021 +0300 @@ -115,6 +115,8 @@ ngx_http_log_op_t *op); static u_char *ngx_http_log_time(ngx_http_request_t *r, u_char *buf, ngx_http_log_op_t *op); +static u_char *ngx_http_log_time_short(ngx_http_request_t *r, u_char *buf, + ngx_http_log_op_t *op); static u_char *ngx_http_log_iso8601(ngx_http_request_t *r, u_char *buf, ngx_http_log_op_t *op); static u_char *ngx_http_log_msec(ngx_http_request_t *r, u_char *buf, @@ -234,6 +236,8 @@ { ngx_string("pipe"), 1, ngx_http_log_pipe }, { ngx_string("time_local"), sizeof("28/Sep/1970:12:00:00 +0600") - 1, ngx_http_log_time }, + { ngx_string("time_short"), sizeof("1970/09/28 12:00:00") - 1, + ngx_http_log_time_short }, { ngx_string("time_iso8601"), sizeof("1970-09-28T12:00:00+06:00") - 1, ngx_http_log_iso8601 }, { ngx_string("msec"), NGX_TIME_T_LEN + 4, ngx_http_log_msec }, @@ -817,6 +821,13 @@ } static u_char * +ngx_http_log_time_short(ngx_http_request_t *r, u_char *buf, ngx_http_log_op_t *op) +{ + return ngx_cpymem(buf, ngx_cached_err_log_time.data, + ngx_cached_err_log_time.len); +} + +static u_char * ngx_http_log_iso8601(ngx_http_request_t *r, u_char *buf, ngx_http_log_op_t *op) { return ngx_cpymem(buf, ngx_cached_http_log_iso8601.data, diff -r f5de03f308a6 -r b3c942ec8a13 src/http/ngx_http_variables.c --- a/src/http/ngx_http_variables.c Tue May 25 15:28:56 2021 +0300 +++ b/src/http/ngx_http_variables.c Wed May 26 23:36:19 2021 +0300 @@ -142,6 +142,8 @@ ngx_http_variable_value_t *v, uintptr_t data); static ngx_int_t ngx_http_variable_time_iso8601(ngx_http_request_t *r, ngx_http_variable_value_t *v, uintptr_t data); +static ngx_int_t ngx_http_variable_time_short(ngx_http_request_t *r, + ngx_http_variable_value_t *v, uintptr_t data); static ngx_int_t ngx_http_variable_time_local(ngx_http_request_t *r, ngx_http_variable_value_t *v, uintptr_t data); @@ -362,6 +364,9 @@ { ngx_string("time_iso8601"), NULL, ngx_http_variable_time_iso8601, 0, NGX_HTTP_VAR_NOCACHEABLE, 0 }, + { ngx_string("time_short"), NULL, ngx_http_variable_time_short, + 0, NGX_HTTP_VAR_NOCACHEABLE, 0 }, + { ngx_string("time_local"), NULL, ngx_http_variable_time_local, 0, NGX_HTTP_VAR_NOCACHEABLE, 0 }, @@ -2380,6 +2385,29 @@ static ngx_int_t +ngx_http_variable_time_short(ngx_http_request_t *r, + ngx_http_variable_value_t *v, uintptr_t data) +{ + u_char *p; + + p = ngx_pnalloc(r->pool, ngx_cached_err_log_time.len); + if (p == NULL) { + return NGX_ERROR; + } + + ngx_memcpy(p, ngx_cached_err_log_time.data, ngx_cached_err_log_time.len); + + v->len = ngx_cached_err_log_time.len; + v->valid = 1; + v->no_cacheable = 0; + v->not_found = 0; + v->data = p; + + return NGX_OK; +} + + +static ngx_int_t ngx_http_variable_time_local(ngx_http_request_t *r, ngx_http_variable_value_t *v, uintptr_t data) { diff -r f5de03f308a6 -r b3c942ec8a13 src/stream/ngx_stream_variables.c --- a/src/stream/ngx_stream_variables.c Tue May 25 15:28:56 2021 +0300 +++ b/src/stream/ngx_stream_variables.c Wed May 26 23:36:19 2021 +0300 @@ -46,6 +46,8 @@ ngx_stream_variable_value_t *v, uintptr_t data); static ngx_int_t ngx_stream_variable_time_iso8601(ngx_stream_session_t *s, ngx_stream_variable_value_t *v, uintptr_t data); +static ngx_int_t ngx_stream_variable_time_short(ngx_stream_session_t *s, + ngx_stream_variable_value_t *v, uintptr_t data); static ngx_int_t ngx_stream_variable_time_local(ngx_stream_session_t *s, ngx_stream_variable_value_t *v, uintptr_t data); static ngx_int_t ngx_stream_variable_protocol(ngx_stream_session_t *s, @@ -115,6 +117,9 @@ { ngx_string("time_iso8601"), NULL, ngx_stream_variable_time_iso8601, 0, NGX_STREAM_VAR_NOCACHEABLE, 0 }, + { ngx_string("time_short"), NULL, ngx_stream_variable_time_short, + 0, NGX_STREAM_VAR_NOCACHEABLE, 0 }, + { ngx_string("time_local"), NULL, ngx_stream_variable_time_local, 0, NGX_STREAM_VAR_NOCACHEABLE, 0 }, @@ -875,6 +880,29 @@ static ngx_int_t +ngx_stream_variable_time_short(ngx_stream_session_t *s, + ngx_stream_variable_value_t *v, uintptr_t data) +{ + u_char *p; + + p = ngx_pnalloc(s->connection->pool, ngx_cached_err_log_time.len); + if (p == NULL) { + return NGX_ERROR; + } + + ngx_memcpy(p, ngx_cached_err_log_time.data, ngx_cached_err_log_time.len); + + v->len = ngx_cached_err_log_time.len; + v->valid = 1; + v->no_cacheable = 0; + v->not_found = 0; + v->data = p; + + return NGX_OK; +} + + +static ngx_int_t ngx_stream_variable_time_local(ngx_stream_session_t *s, ngx_stream_variable_value_t *v, uintptr_t data) { From pluknet at nginx.com Thu May 27 10:44:15 2021 From: pluknet at nginx.com (Sergey Kandaurov) Date: Thu, 27 May 2021 13:44:15 +0300 Subject: [nginx-quic] fix qpack index issue when lookingup dynamic table In-Reply-To: References: Message-ID: <434F773C-CC2A-4C24-A67A-EAC2B6A1D104@nginx.com> > On 24 May 2021, at 06:34, sun edward wrote: > > description: > when qpack header insert with name reference, if it is dynamic table, the index should be the relative index, as described in drafts: > https://quicwg.org/base-drafts/draft-ietf-quic-qpack.html#name-insert-with-name-reference Committed, thanks. https://hg.nginx.org/nginx-quic/rev/e6c26cb4d38b [..] -- Sergey Kandaurov From i at morfi.ru Thu May 27 12:16:49 2021 From: i at morfi.ru (=?iso-8859-1?q?Andrey_Kolyshkin?=) Date: Thu, 27 May 2021 15:16:49 +0300 Subject: [PATCH] [nginx-quic] fix error code when reached maximum number of requests or timeout Message-ID: # HG changeset patch # User Andrey Kolyshkin # Date 1622115662 -10800 # Thu May 27 14:41:02 2021 +0300 # Branch quic # Node ID cfb1ac5fa0f6e2b86d4e4ce51e9ce0b33f959d66 # Parent e6c26cb4d38b8cecb89f26e002bfacf11eafe4a1 fix error code when reached maximum number of requests or timeout chrome has marked quic connection as broken after getting NGX_HTTP_V3_ERR_NO_ERROR (0x100) as code instead of NGX_QUIC_ERR_NO_ERROR (0x0) QUIC_SESSION_CONNECTION_CLOSE_FRAME_RECEIVED --> close_type = "Application" --> details = "reached maximum number of requests" --> quic_error = 122 (QUIC_IETF_GQUIC_ERROR_MISSING) --> quic_wire_error = 256 diff -r e6c26cb4d38b -r cfb1ac5fa0f6 src/event/quic/ngx_event_quic.c --- a/src/event/quic/ngx_event_quic.c Thu May 27 13:29:00 2021 +0300 +++ b/src/event/quic/ngx_event_quic.c Thu May 27 14:41:02 2021 +0300 @@ -607,7 +607,7 @@ void -ngx_quic_finalize_connection(ngx_connection_t *c, ngx_uint_t err, +ngx_quic_finalize_connection(ngx_connection_t *c, ngx_int_t rc, ngx_uint_t err, const char *reason) { ngx_quic_connection_t *qc; @@ -618,12 +618,12 @@ qc->error_app = 1; qc->error_ftype = 0; - ngx_quic_close_connection(c, NGX_ERROR); + ngx_quic_close_connection(c, rc); } void -ngx_quic_shutdown_connection(ngx_connection_t *c, ngx_uint_t err, +ngx_quic_shutdown_connection(ngx_connection_t *c, ngx_int_t rc, ngx_uint_t err, const char *reason) { ngx_quic_connection_t *qc; @@ -633,7 +633,7 @@ qc->shutdown_code = err; qc->shutdown_reason = reason; - ngx_quic_shutdown_quic(c); + ngx_quic_shutdown_quic(c, rc); } @@ -1369,7 +1369,7 @@ void -ngx_quic_shutdown_quic(ngx_connection_t *c) +ngx_quic_shutdown_quic(ngx_connection_t *c, ngx_int_t rc) { ngx_rbtree_t *tree; ngx_rbtree_node_t *node; @@ -1397,7 +1397,7 @@ } } - ngx_quic_finalize_connection(c, qc->shutdown_code, qc->shutdown_reason); + ngx_quic_finalize_connection(c, rc, qc->shutdown_code, qc->shutdown_reason); } diff -r e6c26cb4d38b -r cfb1ac5fa0f6 src/event/quic/ngx_event_quic.h --- a/src/event/quic/ngx_event_quic.h Thu May 27 13:29:00 2021 +0300 +++ b/src/event/quic/ngx_event_quic.h Thu May 27 14:41:02 2021 +0300 @@ -88,9 +88,9 @@ void ngx_quic_run(ngx_connection_t *c, ngx_quic_conf_t *conf); ngx_connection_t *ngx_quic_open_stream(ngx_connection_t *c, ngx_uint_t bidi); -void ngx_quic_finalize_connection(ngx_connection_t *c, ngx_uint_t err, +void ngx_quic_finalize_connection(ngx_connection_t *c, ngx_int_t rc, ngx_uint_t err, const char *reason); -void ngx_quic_shutdown_connection(ngx_connection_t *c, ngx_uint_t err, +void ngx_quic_shutdown_connection(ngx_connection_t *c, ngx_int_t rc, ngx_uint_t err, const char *reason); ngx_int_t ngx_quic_reset_stream(ngx_connection_t *c, ngx_uint_t err); uint32_t ngx_quic_version(ngx_connection_t *c); diff -r e6c26cb4d38b -r cfb1ac5fa0f6 src/event/quic/ngx_event_quic_connection.h --- a/src/event/quic/ngx_event_quic_connection.h Thu May 27 13:29:00 2021 +0300 +++ b/src/event/quic/ngx_event_quic_connection.h Thu May 27 14:41:02 2021 +0300 @@ -251,7 +251,7 @@ void ngx_quic_discard_ctx(ngx_connection_t *c, enum ssl_encryption_level_t level); void ngx_quic_close_connection(ngx_connection_t *c, ngx_int_t rc); -void ngx_quic_shutdown_quic(ngx_connection_t *c); +void ngx_quic_shutdown_quic(ngx_connection_t *c, ngx_int_t rc); #if (NGX_DEBUG) void ngx_quic_connstate_dbg(ngx_connection_t *c); diff -r e6c26cb4d38b -r cfb1ac5fa0f6 src/event/quic/ngx_event_quic_streams.c --- a/src/event/quic/ngx_event_quic_streams.c Thu May 27 13:29:00 2021 +0300 +++ b/src/event/quic/ngx_event_quic_streams.c Thu May 27 14:41:02 2021 +0300 @@ -803,7 +803,7 @@ (void) ngx_quic_output(pc); if (qc->shutdown) { - ngx_quic_shutdown_quic(pc); + ngx_quic_shutdown_quic(pc, NGX_ERROR); } } diff -r e6c26cb4d38b -r cfb1ac5fa0f6 src/http/v3/ngx_http_v3.c --- a/src/http/v3/ngx_http_v3.c Thu May 27 13:29:00 2021 +0300 +++ b/src/http/v3/ngx_http_v3.c Thu May 27 14:41:02 2021 +0300 @@ -69,7 +69,7 @@ ngx_log_debug0(NGX_LOG_DEBUG_HTTP, c->log, 0, "http3 keepalive handler"); - ngx_quic_finalize_connection(c, NGX_HTTP_V3_ERR_NO_ERROR, + ngx_quic_finalize_connection(c, NGX_OK, NGX_HTTP_V3_ERR_NO_ERROR, "keepalive timeout"); } diff -r e6c26cb4d38b -r cfb1ac5fa0f6 src/http/v3/ngx_http_v3.h --- a/src/http/v3/ngx_http_v3.h Thu May 27 13:29:00 2021 +0300 +++ b/src/http/v3/ngx_http_v3.h Thu May 27 14:41:02 2021 +0300 @@ -89,10 +89,10 @@ module) #define ngx_http_v3_finalize_connection(c, code, reason) \ - ngx_quic_finalize_connection(c->quic->parent, code, reason) + ngx_quic_finalize_connection(c->quic->parent, ((code == NGX_HTTP_V3_ERR_NO_ERROR) ? NGX_OK : NGX_ERROR), code, reason) #define ngx_http_v3_shutdown_connection(c, code, reason) \ - ngx_quic_shutdown_connection(c->quic->parent, code, reason) + ngx_quic_shutdown_connection(c->quic->parent, ((code == NGX_HTTP_V3_ERR_NO_ERROR) ? NGX_OK : NGX_ERROR), code, reason) typedef struct { From pluknet at nginx.com Thu May 27 12:58:55 2021 From: pluknet at nginx.com (Sergey Kandaurov) Date: Thu, 27 May 2021 15:58:55 +0300 Subject: [PATCH] [nginx-quic] fix error code when reached maximum number of requests or timeout In-Reply-To: References: Message-ID: <0257E796-43CA-4A2C-954B-BFD853E35BF9@nginx.com> > On 27 May 2021, at 15:16, Andrey Kolyshkin wrote: > > # HG changeset patch > # User Andrey Kolyshkin > # Date 1622115662 -10800 > # Thu May 27 14:41:02 2021 +0300 > # Branch quic > # Node ID cfb1ac5fa0f6e2b86d4e4ce51e9ce0b33f959d66 > # Parent e6c26cb4d38b8cecb89f26e002bfacf11eafe4a1 > fix error code when reached maximum number of requests or timeout > > chrome has marked quic connection as broken after > getting NGX_HTTP_V3_ERR_NO_ERROR (0x100) as code instead of NGX_QUIC_ERR_NO_ERROR (0x0) > > QUIC_SESSION_CONNECTION_CLOSE_FRAME_RECEIVED > --> close_type = "Application" > --> details = "reached maximum number of requests" > --> quic_error = 122 (QUIC_IETF_GQUIC_ERROR_MISSING) > --> quic_wire_error = 256 It looks like a bug in Chrome. Per quic-http draft 34, 5.2. Connection Shutdown: Once all accepted requests and pushes have been processed, the endpoint can permit the connection to become idle, or MAY initiate an immediate closure of the connection. An endpoint that completes a graceful shutdown SHOULD use the H3_NO_ERROR error code when closing the connection. The graceful shutdown is what happens with nginx. Also, 8.1. HTTP/3 Error Codes: The following error codes are defined for use when abruptly terminating streams, aborting reading of streams, or immediately closing *HTTP/3 connections*. H3_NO_ERROR (0x100): No error. This is used when the connection or stream needs to be closed, but there is no error to signal. So, it should be perfectly fine to send CC(0x1d)/H3_NO_ERROR. -- Sergey Kandaurov From mdounin at mdounin.ru Thu May 27 17:25:09 2021 From: mdounin at mdounin.ru (Maxim Dounin) Date: Thu, 27 May 2021 20:25:09 +0300 Subject: [PATCH] Variable $time_short. In-Reply-To: References: Message-ID: Hello! On Wed, May 26, 2021 at 11:42:59PM +0300, Gena Makhomed wrote: > # HG changeset patch > # User Gena Makhomed > # Date 1622061379 -10800 > # Wed May 26 23:36:19 2021 +0300 > # Node ID b3c942ec8a13bc8f6cd4b3e2385acb8c14502c0d > # Parent f5de03f308a6d7864b7d5108a968db56585b9a9b > Variable $time_short. > > Variable $time_short in form "1970/09/28 12:00:00". > Added to ngx_http_core_module, ngx_http_log_module, > and ngx_stream_core_module. You may want to be more specific about expected use cases, and why existing time variables are not enough. [...] -- Maxim Dounin http://mdounin.ru/ From gmm at csdoc.com Thu May 27 18:48:41 2021 From: gmm at csdoc.com (Gena Makhomed) Date: Thu, 27 May 2021 21:48:41 +0300 Subject: [PATCH] Variable $time_short. In-Reply-To: References: Message-ID: On 27.05.2021 20:25, Maxim Dounin wrote: >> Variable $time_short. >> >> Variable $time_short in form "1970/09/28 12:00:00". >> Added to ngx_http_core_module, ngx_http_log_module, >> and ngx_stream_core_module. > You may want to be more specific about expected use cases, and why > existing time variables are not enough. Main purpose of variable $time_short is usage for logging, access.log. Existing variables $time_iso8601 and $time_local has bad readability, because these variables contains timezone after seconds and it has no space between date and time fields. Compare readability: 27/May/2021:21:19:12 +0300 27/May/2021:21:19:18 +0300 27/May/2021:21:19:25 +0300 27/May/2021:21:19:32 +0300 27/May/2021:21:19:43 +0300 2021-05-27T21:19:12+03:00 2021-05-27T21:19:18+03:00 2021-05-27T21:19:25+03:00 2021-05-27T21:19:32+03:00 2021-05-27T21:19:43+03:00 2021/05/27 21:19:12 2021/05/27 21:19:18 2021/05/27 21:19:25 2021/05/27 21:19:32 2021/05/27 21:19:43 But only proposed variable $time_short has excellent readability, also this variable is very short, and contains no visual garbage. If name $time_short is not very good - I can rewrite my patch and rename it to just $time variable name. P.S. log_format standalone '$time_short\t$geoip_country_code\t$remote_addr' '\t$upstream_cache_status\t$upstream_response_time' '\t$status\t$scheme\t$host\t$request_method\t$request_uri' '\t$body_bytes_sent\t$http_referer\t$http_user_agent'; -- Best regards, Gena From sunzhiyong3210 at gmail.com Fri May 28 04:02:30 2021 From: sunzhiyong3210 at gmail.com (sun edward) Date: Fri, 28 May 2021 12:02:30 +0800 Subject: [nginx-quic] fix qpack header null value issue Message-ID: description: when header with a null value,need to reset st->value,otherwise it is taking previous header field's value # HG changeset patch # User Zhiyong Sun # Date 1622174245 14400 # Thu May 27 23:57:25 2021 -0400 # Branch quic # Node ID 93a08c9a9d05a0ba529b369c741baa84defdd832 # Parent e6c26cb4d38b8cecb89f26e002bfacf11eafe4a1 fix qpack null value issue,when header with a null value,need to reset st->value,otherwise it is taking previous header field's value diff -r e6c26cb4d38b -r 93a08c9a9d05 src/http/v3/ngx_http_v3_parse.c --- a/src/http/v3/ngx_http_v3_parse.c Thu May 27 13:29:00 2021 +0300 +++ b/src/http/v3/ngx_http_v3_parse.c Thu May 27 23:57:25 2021 -0400 @@ -1470,6 +1470,8 @@ st->literal.length = st->pint.value; if (st->literal.length == 0) { + st->value.len = 0; + st->value.data = NULL; goto done; } -------------- next part -------------- An HTML attachment was scrubbed... URL: From xeioex at nginx.com Fri May 28 14:42:58 2021 From: xeioex at nginx.com (Dmitry Volyntsev) Date: Fri, 28 May 2021 14:42:58 +0000 Subject: [njs] Fixed heap-buffer-overflow in String.prototype.lastIndexOf(). Message-ID: details: https://hg.nginx.org/njs/rev/f3eac82832aa branches: changeset: 1644:f3eac82832aa user: Dmitry Volyntsev date: Fri May 28 14:00:04 2021 +0000 description: Fixed heap-buffer-overflow in String.prototype.lastIndexOf(). Previously, the issue occurred when the searchValue is shorter in character length than "this" string, but longer in byte length. diffstat: src/njs_string.c | 148 ++++++++++++++++++++-------------------------- src/test/njs_unit_test.c | 26 +++++++- 2 files changed, 89 insertions(+), 85 deletions(-) diffs (225 lines): diff -r 801e2dbc79c9 -r f3eac82832aa src/njs_string.c --- a/src/njs_string.c Mon May 24 14:18:15 2021 +0000 +++ b/src/njs_string.c Fri May 28 14:00:04 2021 +0000 @@ -2230,114 +2230,94 @@ njs_string_prototype_last_index_of(njs_v njs_uint_t nargs, njs_index_t unused) { double pos; - ssize_t index, start, length, search_length; + int64_t index, start, length, search_length; njs_int_t ret; - njs_value_t *value, *search_string, lvalue; + njs_value_t *this, *search, search_lvalue; const u_char *p, *end; - njs_string_prop_t string, search; - - ret = njs_string_object_validate(vm, njs_arg(args, nargs, 0)); + njs_string_prop_t string, s; + + this = njs_argument(args, 0); + + if (njs_slow_path(njs_is_null_or_undefined(this))) { + njs_type_error(vm, "cannot convert \"%s\"to object", + njs_type_string(this->type)); + return NJS_ERROR; + } + + ret = njs_value_to_string(vm, this, this); + if (njs_slow_path(ret != NJS_OK)) { + return NJS_ERROR; + } + + search = njs_lvalue_arg(&search_lvalue, args, nargs, 1); + ret = njs_value_to_string(vm, search, search); + if (njs_slow_path(ret != NJS_OK)) { + return ret; + } + + ret = njs_value_to_number(vm, njs_arg(args, nargs, 2), &pos); if (njs_slow_path(ret != NJS_OK)) { return ret; } - index = -1; - - length = njs_string_prop(&string, njs_argument(args, 0)); - - search_string = njs_lvalue_arg(&lvalue, args, nargs, 1); - - if (njs_slow_path(!njs_is_string(search_string))) { - ret = njs_value_to_string(vm, search_string, search_string); - if (njs_slow_path(ret != NJS_OK)) { - return ret; - } - } - - search_length = njs_string_prop(&search, search_string); - - if (length < search_length) { - goto done; - } - - value = njs_arg(args, nargs, 2); - - if (njs_slow_path(!njs_is_number(value))) { - ret = njs_value_to_number(vm, value, &pos); - if (njs_slow_path(ret != NJS_OK)) { - return ret; - } + if (!isnan(pos)) { + start = njs_number_to_integer(pos); } else { - pos = njs_number(value); + start = INT64_MAX; } - if (isnan(pos)) { - index = NJS_STRING_MAX_LENGTH; - - } else { - index = njs_number_to_integer(pos); - - if (index < 0) { - index = 0; - } + length = njs_string_prop(&string, this); + + start = njs_min(njs_max(start, 0), length); + + search_length = njs_string_prop(&s, search); + + index = length - search_length; + + if (index > start) { + index = start; } - if (search_length == 0) { - index = njs_min(index, length); - goto done; - } - - if (index >= length) { - index = length - 1; - } + end = string.start + string.size; if (string.size == (size_t) length) { /* Byte or ASCII string. */ - start = length - search.size; - - if (index > start) { - index = start; + p = &string.start[index]; + + if (p > end - s.size) { + p = end - s.size; + } + + for (; p >= string.start; p--) { + if (memcmp(p, s.start, s.size) == 0) { + index = p - string.start; + goto done; + } } - p = string.start + index; - - do { - if (memcmp(p, search.start, search.size) == 0) { + index = -1; + + } else { + /* UTF-8 string. */ + + if (index < 0 || index == length) { + index = (search_length == 0) ? index : -1; + goto done; + } + + p = njs_string_offset(string.start, end, index); + + for (; p >= string.start; p = njs_utf8_prev(p)) { + if ((p + s.size) <= end && memcmp(p, s.start, s.size) == 0) { goto done; } index--; - p--; - - } while (p >= string.start); - - } else { - /* UTF-8 string. */ - - end = string.start + string.size; - p = njs_string_offset(string.start, end, index); - end -= search.size; - - while (p > end) { - index--; - p = njs_utf8_prev(p); } - for ( ;; ) { - if (memcmp(p, search.start, search.size) == 0) { - goto done; - } - - index--; - - if (p <= string.start) { - break; - } - - p = njs_utf8_prev(p); - } + index = -1; } done: diff -r 801e2dbc79c9 -r f3eac82832aa src/test/njs_unit_test.c --- a/src/test/njs_unit_test.c Mon May 24 14:18:15 2021 +0000 +++ b/src/test/njs_unit_test.c Fri May 28 14:00:04 2021 +0000 @@ -8008,7 +8008,28 @@ static njs_unit_test_t njs_test[] = { njs_str("'a a'.toUTF8().indexOf('a', 1)"), njs_str("2") }, - { njs_str("'abc'.lastIndexOf('abcdef')"), + { njs_str("'aaa'.lastIndexOf()"), + njs_str("-1") }, + + { njs_str("'aaa'.lastIndexOf('')"), + njs_str("3") }, + + { njs_str("'aaa'.lastIndexOf('a')"), + njs_str("2") }, + + { njs_str("'aaa'.lastIndexOf('aa')"), + njs_str("1") }, + + { njs_str("'aaa'.lastIndexOf('aaa')"), + njs_str("0") }, + + { njs_str("'aaa'.lastIndexOf('aaaa')"), + njs_str("-1") }, + + { njs_str("'a'.repeat(16).lastIndexOf(String.fromCodePoint(65533).repeat(15))"), + njs_str("-1") }, + + { njs_str("('?'+'a'.repeat(15)).lastIndexOf(String.fromCodePoint(65533).repeat(15))"), njs_str("-1") }, { njs_str("'abc abc abc abc'.lastIndexOf('abc')"), @@ -8077,6 +8098,9 @@ static njs_unit_test_t njs_test[] = { njs_str("'?'.repeat(32).lastIndexOf('?')"), njs_str("31") }, + { njs_str("'?'.repeat(32).lastIndexOf('?'.repeat(32))"), + njs_str("0") }, + { njs_str("'?'.repeat(32).lastIndexOf``"), njs_str("32") }, From mdounin at mdounin.ru Fri May 28 21:55:40 2021 From: mdounin at mdounin.ru (Maxim Dounin) Date: Sat, 29 May 2021 00:55:40 +0300 Subject: [PATCH] Variable $time_short. In-Reply-To: References: Message-ID: Hello! On Thu, May 27, 2021 at 09:48:41PM +0300, Gena Makhomed wrote: > On 27.05.2021 20:25, Maxim Dounin wrote: > > >> Variable $time_short. > >> > >> Variable $time_short in form "1970/09/28 12:00:00". > >> Added to ngx_http_core_module, ngx_http_log_module, > >> and ngx_stream_core_module. > > > You may want to be more specific about expected use cases, and why > > existing time variables are not enough. > > Main purpose of variable $time_short is usage for logging, access.log. > > Existing variables $time_iso8601 and $time_local has bad readability, > because these variables contains timezone after seconds and it has > no space between date and time fields. > > Compare readability: > > 27/May/2021:21:19:12 +0300 > 27/May/2021:21:19:18 +0300 > 27/May/2021:21:19:25 +0300 > 27/May/2021:21:19:32 +0300 > 27/May/2021:21:19:43 +0300 > > 2021-05-27T21:19:12+03:00 > 2021-05-27T21:19:18+03:00 > 2021-05-27T21:19:25+03:00 > 2021-05-27T21:19:32+03:00 > 2021-05-27T21:19:43+03:00 > > 2021/05/27 21:19:12 > 2021/05/27 21:19:18 > 2021/05/27 21:19:25 > 2021/05/27 21:19:32 > 2021/05/27 21:19:43 > > But only proposed variable $time_short has excellent readability, > also this variable is very short, and contains no visual garbage. Well, if you want to improve readability and don't need a timezone in your logs, something like this might work instead: map $time_iso8601 $time { "~([0-9-]+)T([0-9:]+)" "$1 $2"; volatile; } I don't think that introducing additional builtin variables for additional data/time formats is a good idea. -- Maxim Dounin http://mdounin.ru/ From gmm at csdoc.com Sun May 30 09:29:19 2021 From: gmm at csdoc.com (Gena Makhomed) Date: Sun, 30 May 2021 12:29:19 +0300 Subject: [PATCH] Contrib: vim syntax, update core and 3rd party module directives. Message-ID: <7a3c71b8-2fde-1a29-3423-1d3fd9f29256@csdoc.com> # HG changeset patch # User Gena Makhomed # Date 1622366760 -10800 # Sun May 30 12:26:00 2021 +0300 # Node ID e3c137f6caa6c6b979e8eb8647d00a293fe1f112 # Parent f5de03f308a6d7864b7d5108a968db56585b9a9b Contrib: vim syntax, update core and 3rd party module directives. diff -r f5de03f308a6 -r e3c137f6caa6 contrib/vim/syntax/nginx.vim --- a/contrib/vim/syntax/nginx.vim Tue May 25 15:28:56 2021 +0300 +++ b/contrib/vim/syntax/nginx.vim Sun May 30 12:26:00 2021 +0300 @@ -152,6 +152,7 @@ syn keyword ngxDirective contained auth_jwt_key_file syn keyword ngxDirective contained auth_jwt_key_request syn keyword ngxDirective contained auth_jwt_leeway +syn keyword ngxDirective contained auth_jwt_type syn keyword ngxDirective contained auth_request syn keyword ngxDirective contained auth_request_set syn keyword ngxDirective contained autoindex @@ -332,16 +333,20 @@ syn keyword ngxDirective contained iocp_threads syn keyword ngxDirective contained ip_hash syn keyword ngxDirective contained js_access +syn keyword ngxDirective contained js_body_filter syn keyword ngxDirective contained js_content syn keyword ngxDirective contained js_filter +syn keyword ngxDirective contained js_header_filter syn keyword ngxDirective contained js_import syn keyword ngxDirective contained js_include syn keyword ngxDirective contained js_path syn keyword ngxDirective contained js_preread syn keyword ngxDirective contained js_set +syn keyword ngxDirective contained js_var syn keyword ngxDirective contained keepalive syn keyword ngxDirective contained keepalive_disable syn keyword ngxDirective contained keepalive_requests +syn keyword ngxDirective contained keepalive_time syn keyword ngxDirective contained keepalive_timeout syn keyword ngxDirective contained keyval syn keyword ngxDirective contained keyval_zone @@ -373,6 +378,7 @@ syn keyword ngxDirective contained map_hash_bucket_size syn keyword ngxDirective contained map_hash_max_size syn keyword ngxDirective contained master_process +syn keyword ngxDirective contained max_errors syn keyword ngxDirective contained max_ranges syn keyword ngxDirective contained memcached_bind syn keyword ngxDirective contained memcached_buffer_size @@ -1080,6 +1086,8 @@ syn keyword ngxDirectiveThirdParty contained nchan_subscribe_request syn keyword ngxDirectiveThirdParty contained nchan_subscriber_first_message syn keyword ngxDirectiveThirdParty contained nchan_subscriber_http_raw_stream_separator +syn keyword ngxDirectiveThirdParty contained nchan_subscriber_info +syn keyword ngxDirectiveThirdParty contained nchan_subscriber_info_string syn keyword ngxDirectiveThirdParty contained nchan_subscriber_last_message_id syn keyword ngxDirectiveThirdParty contained nchan_subscriber_location syn keyword ngxDirectiveThirdParty contained nchan_subscriber_message_id_custom_etag_header @@ -2368,9 +2376,9 @@ " IP2Location Nginx " https://github.com/ip2location/ip2location-nginx -syn keyword ngxDirectiveThirdParty contained ip2location_proxy -syn keyword ngxDirectiveThirdParty contained ip2location_proxy_recursive +syn keyword ngxDirectiveThirdParty contained ip2location_addresstype syn keyword ngxDirectiveThirdParty contained ip2location_areacode +syn keyword ngxDirectiveThirdParty contained ip2location_category syn keyword ngxDirectiveThirdParty contained ip2location_city syn keyword ngxDirectiveThirdParty contained ip2location_country_long syn keyword ngxDirectiveThirdParty contained ip2location_country_short @@ -2384,6 +2392,8 @@ syn keyword ngxDirectiveThirdParty contained ip2location_mnc syn keyword ngxDirectiveThirdParty contained ip2location_mobilebrand syn keyword ngxDirectiveThirdParty contained ip2location_netspeed +syn keyword ngxDirectiveThirdParty contained ip2location_proxy +syn keyword ngxDirectiveThirdParty contained ip2location_proxy_recursive syn keyword ngxDirectiveThirdParty contained ip2location_region syn keyword ngxDirectiveThirdParty contained ip2location_timezone syn keyword ngxDirectiveThirdParty contained ip2location_usagetype @@ -2403,6 +2413,7 @@ syn keyword ngxDirectiveThirdParty contained ip2proxy_isp syn keyword ngxDirectiveThirdParty contained ip2proxy_is_proxy syn keyword ngxDirectiveThirdParty contained ip2proxy_last_seen +syn keyword ngxDirectiveThirdParty contained ip2proxy_provider syn keyword ngxDirectiveThirdParty contained ip2proxy_proxy syn keyword ngxDirectiveThirdParty contained ip2proxy_proxy_recursive syn keyword ngxDirectiveThirdParty contained ip2proxy_proxy_type From gmm at csdoc.com Sun May 30 10:02:24 2021 From: gmm at csdoc.com (Gena Makhomed) Date: Sun, 30 May 2021 13:02:24 +0300 Subject: [PATCH] Variable $time_short. In-Reply-To: References: Message-ID: On 29.05.2021 0:55, Maxim Dounin wrote: >> Main purpose of variable $time_short is usage for logging, access.log. >> >> Existing variables $time_iso8601 and $time_local has bad readability, >> because these variables contains timezone after seconds and it has >> no space between date and time fields. >> >> Compare readability: >> >> 27/May/2021:21:19:12 +0300 >> 27/May/2021:21:19:18 +0300 >> 27/May/2021:21:19:25 +0300 >> 27/May/2021:21:19:32 +0300 >> 27/May/2021:21:19:43 +0300 >> >> 2021-05-27T21:19:12+03:00 >> 2021-05-27T21:19:18+03:00 >> 2021-05-27T21:19:25+03:00 >> 2021-05-27T21:19:32+03:00 >> 2021-05-27T21:19:43+03:00 >> >> 2021/05/27 21:19:12 >> 2021/05/27 21:19:18 >> 2021/05/27 21:19:25 >> 2021/05/27 21:19:32 >> 2021/05/27 21:19:43 >> >> But only proposed variable $time_short has excellent readability, >> also this variable is very short, and contains no visual garbage. > > Well, if you want to improve readability and don't need a timezone > in your logs, something like this might work instead: > > map $time_iso8601 $time { > "~([0-9-]+)T([0-9:]+)" "$1 $2"; > volatile; > } > > I don't think that introducing additional builtin variables for > additional data/time formats is a good idea. Using map directive for creating $time variable indeed allow us improve readability of log files, but this method is not cheap, - regular expressions runs for every record in access.log file. On busy servers (under DDoS attacks) can be hundreds of records per second and this regexp in map directive will just eat CPU. Human-readable variable $time / $time_short intended to use on busy servers, under DDoS-attacks, with Load Average 60 and more. See https://github.com/makhomed/autofilter for details about this. > I don't think that introducing additional builtin variables for > additional data/time formats is a good idea. Why not? Builtin variable ngx_cached_err_log_time already exists in nginx, patch for ngx_http_log_module is very small, just few lines of code: + { ngx_string("time_short"), sizeof("1970/09/28 12:00:00") - 1, + ngx_http_log_time_short }, +static u_char * +ngx_http_log_time_short(ngx_http_request_t *r, u_char *buf, ngx_http_log_op_t *op) +{ + return ngx_cpymem(buf, ngx_cached_err_log_time.data, + ngx_cached_err_log_time.len); +} -- Best regards, Gena From xeioex at nginx.com Mon May 31 07:22:25 2021 From: xeioex at nginx.com (Dmitry Volyntsev) Date: Mon, 31 May 2021 07:22:25 +0000 Subject: [njs] Style. Message-ID: details: https://hg.nginx.org/njs/rev/fc510b2e4f3a branches: changeset: 1645:fc510b2e4f3a user: Dmitry Volyntsev date: Fri May 28 15:23:03 2021 +0000 description: Style. diffstat: auto/clang | 6 +++--- 1 files changed, 3 insertions(+), 3 deletions(-) diffs (16 lines): diff -r f3eac82832aa -r fc510b2e4f3a auto/clang --- a/auto/clang Fri May 28 14:00:04 2021 +0000 +++ b/auto/clang Fri May 28 15:23:03 2021 +0000 @@ -123,9 +123,9 @@ njs_feature_path= njs_feature_libs= njs_feature_test="int n __attribute__ ((aligned(64))); - int main(void) { - return 0; - }" + int main(void) { + return 0; + }" . auto/feature From xeioex at nginx.com Mon May 31 07:22:27 2021 From: xeioex at nginx.com (Dmitry Volyntsev) Date: Mon, 31 May 2021 07:22:27 +0000 Subject: [njs] Removing the requirement of "aligned" attribute support. Message-ID: details: https://hg.nginx.org/njs/rev/7d835eb234e1 branches: changeset: 1646:7d835eb234e1 user: Dmitry Volyntsev date: Mon May 31 06:55:32 2021 +0000 description: Removing the requirement of "aligned" attribute support. Before 0a2a0b5a74f4, the address of values used in runtime had to be the multiple of 16, because the address of a variable was used as its VM index. The first 4 bits of an index signified the scope of a varible. This is no longer the case, after 0a2a0b5a74f4 the address of a variable is never used as its VM index. diffstat: src/njs_value.h | 4 ---- 1 files changed, 0 insertions(+), 4 deletions(-) diffs (14 lines): diff -r fc510b2e4f3a -r 7d835eb234e1 src/njs_value.h --- a/src/njs_value.h Fri May 28 15:23:03 2021 +0000 +++ b/src/njs_value.h Mon May 31 06:55:32 2021 +0000 @@ -105,10 +105,6 @@ typedef struct njs_property_next_s nj typedef struct njs_object_init_s njs_object_init_t; -#if (!NJS_HAVE_GCC_ATTRIBUTE_ALIGNED) -#error "aligned attribute is required" -#endif - union njs_value_s { /* * The njs_value_t size is 16 bytes and must be aligned to 16 bytes From xeioex at nginx.com Mon May 31 07:22:29 2021 From: xeioex at nginx.com (Dmitry Volyntsev) Date: Mon, 31 May 2021 07:22:29 +0000 Subject: [njs] Fixed misaligned reading and writing. Message-ID: details: https://hg.nginx.org/njs/rev/de189c66c757 branches: changeset: 1647:de189c66c757 user: Dmitry Volyntsev date: Mon May 31 06:55:34 2021 +0000 description: Fixed misaligned reading and writing. error: load of misaligned address 0x62500de0ab11 for type 'uint16_t', which requires 2 byte alignment. Found by UndefinedBehaviorSanitizer. diffstat: auto/clang | 13 +++++++++++++ src/njs_buffer.c | 14 +++++++------- src/njs_clang.h | 8 ++++++++ src/njs_typed_array.c | 16 ++++++++-------- src/njs_utils.h | 49 +++++++++++++++++++++++++++++++++++++++++++++++++ 5 files changed, 85 insertions(+), 15 deletions(-) diffs (246 lines): diff -r 7d835eb234e1 -r de189c66c757 auto/clang --- a/auto/clang Mon May 31 06:55:32 2021 +0000 +++ b/auto/clang Mon May 31 06:55:34 2021 +0000 @@ -129,6 +129,19 @@ njs_feature_test="int n __attribute__ (( . auto/feature +njs_feature="GCC __attribute__ packed" +njs_feature_name=NJS_HAVE_GCC_ATTRIBUTE_PACKED +njs_feature_run=no +njs_feature_path= +njs_feature_libs= +njs_feature_test="struct __attribute__((packed)) s { char v; }; + + int main(void) { + return 0; + }" +. auto/feature + + njs_feature="Address sanitizer" njs_feature_name=NJS_HAVE_ADDRESS_SANITIZER njs_feature_run=no diff -r 7d835eb234e1 -r de189c66c757 src/njs_buffer.c --- a/src/njs_buffer.c Mon May 31 06:55:32 2021 +0000 +++ b/src/njs_buffer.c Mon May 31 06:55:34 2021 +0000 @@ -989,7 +989,7 @@ njs_buffer_prototype_read_int(njs_vm_t * break; case 2: - u32 = *((uint16_t *) u8); + u32 = njs_get_u16(u8); if (swap) { u32 = njs_bswap_u16(u32); @@ -1028,7 +1028,7 @@ njs_buffer_prototype_read_int(njs_vm_t * break; case 4: - u32 = *((uint32_t *) u8); + u32 = njs_get_u32(u8); if (swap) { u32 = njs_bswap_u32(u32); @@ -1273,7 +1273,7 @@ njs_buffer_prototype_write_int(njs_vm_t u32 = njs_bswap_u16(u32); } - *((uint16_t *) u8) = u32; + njs_set_u16(u8, u32); break; case 3: @@ -1299,7 +1299,7 @@ njs_buffer_prototype_write_int(njs_vm_t u32 = njs_bswap_u32(u32); } - *((uint32_t *) u8) = u32; + njs_set_u32(u8, u32); break; case 5: @@ -2153,14 +2153,14 @@ njs_buffer_prototype_swap(njs_vm_t *vm, switch (size) { case 2: for (; p < end; p += 2) { - *((uint16_t *) p) = njs_bswap_u16(*((uint16_t *) p)); + njs_set_u16(p, njs_bswap_u16(njs_get_u16(p))); } break; case 4: for (; p < end; p += 4) { - *((uint32_t *) p) = njs_bswap_u32(*((uint32_t *) p)); + njs_set_u32(p, njs_bswap_u32(njs_get_u32(p))); } break; @@ -2168,7 +2168,7 @@ njs_buffer_prototype_swap(njs_vm_t *vm, case 8: default: for (; p < end; p += 8) { - *((uint64_t *) p) = njs_bswap_u64(*((uint64_t *) p)); + njs_set_u64(p, njs_bswap_u64(njs_get_u64(p))); } } diff -r 7d835eb234e1 -r de189c66c757 src/njs_clang.h --- a/src/njs_clang.h Mon May 31 06:55:32 2021 +0000 +++ b/src/njs_clang.h Mon May 31 06:55:34 2021 +0000 @@ -138,6 +138,14 @@ njs_leading_zeros64(uint64_t x) #endif +#if (NJS_HAVE_GCC_ATTRIBUTE_PACKED) +#define NJS_PACKED __attribute__((packed)) + +#else +#define NJS_PACKED +#endif + + #if (NJS_HAVE_GCC_ATTRIBUTE_MALLOC) #define NJS_MALLOC_LIKE __attribute__((__malloc__)) diff -r 7d835eb234e1 -r de189c66c757 src/njs_typed_array.c --- a/src/njs_typed_array.c Mon May 31 06:55:32 2021 +0000 +++ b/src/njs_typed_array.c Mon May 31 06:55:34 2021 +0000 @@ -2736,7 +2736,7 @@ njs_data_view_prototype_get(njs_vm_t *vm break; case NJS_OBJ_TYPE_UINT16_ARRAY: - u32 = *((uint16_t *) u8); + u32 = njs_get_u16(u8); if (swap) { u32 = njs_bswap_u16(u32); @@ -2746,7 +2746,7 @@ njs_data_view_prototype_get(njs_vm_t *vm break; case NJS_OBJ_TYPE_INT16_ARRAY: - u32 = *((uint16_t *) u8); + u32 = njs_get_u16(u8); if (swap) { u32 = njs_bswap_u16(u32); @@ -2758,7 +2758,7 @@ njs_data_view_prototype_get(njs_vm_t *vm case NJS_OBJ_TYPE_UINT32_ARRAY: case NJS_OBJ_TYPE_INT32_ARRAY: case NJS_OBJ_TYPE_FLOAT32_ARRAY: - u32 = *((uint32_t *) u8); + u32 = njs_get_u32(u8); if (swap) { u32 = njs_bswap_u32(u32); @@ -2783,7 +2783,7 @@ njs_data_view_prototype_get(njs_vm_t *vm default: /* NJS_OBJ_TYPE_FLOAT64_ARRAY. */ - conv_f64.u = *((uint64_t *) u8); + conv_f64.u = njs_get_u64(u8); if (swap) { conv_f64.u = njs_bswap_u64(conv_f64.u); @@ -2865,7 +2865,7 @@ njs_data_view_prototype_set(njs_vm_t *vm u32 = njs_bswap_u16(u32); } - *((uint16_t *) u8) = u32; + njs_set_u16(u8, u32); break; case NJS_OBJ_TYPE_UINT32_ARRAY: @@ -2876,7 +2876,7 @@ njs_data_view_prototype_set(njs_vm_t *vm u32 = njs_bswap_u32(u32); } - *((uint32_t *) u8) = u32; + njs_set_u32(u8, u32); break; case NJS_OBJ_TYPE_FLOAT32_ARRAY: @@ -2886,7 +2886,7 @@ njs_data_view_prototype_set(njs_vm_t *vm conv_f32.u = njs_bswap_u32(conv_f32.u); } - *((uint32_t *) u8) = conv_f32.u; + njs_set_u32(u8, conv_f32.u); break; default: @@ -2898,7 +2898,7 @@ njs_data_view_prototype_set(njs_vm_t *vm conv_f64.u = njs_bswap_u64(conv_f64.u); } - *((uint64_t *) u8) = conv_f64.u; + njs_set_u64(u8, conv_f64.u); } njs_set_undefined(&vm->retval); diff -r 7d835eb234e1 -r de189c66c757 src/njs_utils.h --- a/src/njs_utils.h Mon May 31 06:55:32 2021 +0000 +++ b/src/njs_utils.h Mon May 31 06:55:34 2021 +0000 @@ -20,6 +20,19 @@ typedef union { } njs_conv_f64_t; +struct NJS_PACKED njs_packed_u16_t { + uint16_t v; +}; + +struct NJS_PACKED njs_packed_u32_t { + uint32_t v; +}; + +struct NJS_PACKED njs_packed_u64_t { + uint64_t v; +}; + + typedef int (*njs_sort_cmp_t)(const void *, const void *, void *ctx); void njs_qsort(void *base, size_t n, size_t size, njs_sort_cmp_t cmp, @@ -115,5 +128,41 @@ njs_bswap_u64(uint64_t u64) | ((u64 & 0x00000000000000ffULL) << 56); } +njs_inline uint16_t +njs_get_u16(const uint8_t *p) +{ + return ((const struct njs_packed_u16_t *) p)->v; +} + +njs_inline uint32_t +njs_get_u32(const uint8_t *p) +{ + return ((const struct njs_packed_u32_t *) p)->v; +} + +njs_inline uint64_t +njs_get_u64(const uint8_t *p) +{ + return ((const struct njs_packed_u64_t *) p)->v; +} + +njs_inline void +njs_set_u16(uint8_t *p, uint16_t val) +{ + ((struct njs_packed_u16_t *) p)->v = val; +} + +njs_inline void +njs_set_u32(uint8_t *p, uint32_t val) +{ + ((struct njs_packed_u32_t *) p)->v = val; +} + +njs_inline void +njs_set_u64(uint8_t *p, uint64_t val) +{ + ((struct njs_packed_u64_t *) p)->v = val; +} + #endif /* _NJS_UTILS_H_INCLUDED_ */ From mdounin at mdounin.ru Mon May 31 14:39:49 2021 From: mdounin at mdounin.ru (Maxim Dounin) Date: Mon, 31 May 2021 14:39:49 +0000 Subject: [nginx] Version bump. Message-ID: details: https://hg.nginx.org/nginx/rev/7e4aeb464642 branches: changeset: 7866:7e4aeb464642 user: Maxim Dounin date: Mon May 31 16:36:12 2021 +0300 description: Version bump. diffstat: src/core/nginx.h | 4 ++-- 1 files changed, 2 insertions(+), 2 deletions(-) diffs (14 lines): diff -r f5de03f308a6 -r 7e4aeb464642 src/core/nginx.h --- a/src/core/nginx.h Tue May 25 15:28:56 2021 +0300 +++ b/src/core/nginx.h Mon May 31 16:36:12 2021 +0300 @@ -9,8 +9,8 @@ #define _NGINX_H_INCLUDED_ -#define nginx_version 1021000 -#define NGINX_VERSION "1.21.0" +#define nginx_version 1021001 +#define NGINX_VERSION "1.21.1" #define NGINX_VER "nginx/" NGINX_VERSION #ifdef NGX_BUILD From mdounin at mdounin.ru Mon May 31 14:39:52 2021 From: mdounin at mdounin.ru (Maxim Dounin) Date: Mon, 31 May 2021 14:39:52 +0000 Subject: [nginx] Core: disabled cloning sockets when testing config (ticket #2188). Message-ID: details: https://hg.nginx.org/nginx/rev/c860f0b7010c branches: changeset: 7867:c860f0b7010c user: Maxim Dounin date: Mon May 31 16:36:37 2021 +0300 description: Core: disabled cloning sockets when testing config (ticket #2188). Since we anyway do not set SO_REUSEPORT when testing configuration (see ecb5cd305b06), trying to open additional sockets does not make much sense, as all these additional sockets are expected to result in EADDRINUSE errors from bind(). On the other hand, there are reports that trying to open these sockets takes significant time under load: total configuration testing time greater than 15s was observed in ticket #2188, compared to less than 1s without load. With this change, no additional sockets are opened during testing configuration. diffstat: src/event/ngx_event.c | 27 +++++++++++++++------------ 1 files changed, 15 insertions(+), 12 deletions(-) diffs (39 lines): diff -r 7e4aeb464642 -r c860f0b7010c src/event/ngx_event.c --- a/src/event/ngx_event.c Mon May 31 16:36:12 2021 +0300 +++ b/src/event/ngx_event.c Mon May 31 16:36:37 2021 +0300 @@ -441,20 +441,23 @@ ngx_event_init_conf(ngx_cycle_t *cycle, #if (NGX_HAVE_REUSEPORT) - ls = cycle->listening.elts; - for (i = 0; i < cycle->listening.nelts; i++) { - - if (!ls[i].reuseport || ls[i].worker != 0) { - continue; - } - - if (ngx_clone_listening(cycle, &ls[i]) != NGX_OK) { - return NGX_CONF_ERROR; - } - - /* cloning may change cycle->listening.elts */ + if (!ngx_test_config) { ls = cycle->listening.elts; + for (i = 0; i < cycle->listening.nelts; i++) { + + if (!ls[i].reuseport || ls[i].worker != 0) { + continue; + } + + if (ngx_clone_listening(cycle, &ls[i]) != NGX_OK) { + return NGX_CONF_ERROR; + } + + /* cloning may change cycle->listening.elts */ + + ls = cycle->listening.elts; + } } #endif From mdounin at mdounin.ru Mon May 31 14:39:54 2021 From: mdounin at mdounin.ru (Maxim Dounin) Date: Mon, 31 May 2021 14:39:54 +0000 Subject: [nginx] Core: disabled SO_REUSEADDR on UDP sockets while testing config. Message-ID: details: https://hg.nginx.org/nginx/rev/46815874bcc6 branches: changeset: 7868:46815874bcc6 user: Maxim Dounin date: Mon May 31 16:36:51 2021 +0300 description: Core: disabled SO_REUSEADDR on UDP sockets while testing config. On Linux, SO_REUSEADDR allows completely duplicate UDP sockets, so using SO_REUSEADDR when testing configuration results in packets being dropped if there is an existing traffic on the sockets being tested (ticket #2187). While dropped packets are expected with UDP, it is better to avoid this when possible. With this change, SO_REUSEADDR is no longer set on datagram sockets when testing configuration. diffstat: src/core/ngx_connection.c | 25 ++++++++++++++----------- 1 files changed, 14 insertions(+), 11 deletions(-) diffs (39 lines): diff -r c860f0b7010c -r 46815874bcc6 src/core/ngx_connection.c --- a/src/core/ngx_connection.c Mon May 31 16:36:37 2021 +0300 +++ b/src/core/ngx_connection.c Mon May 31 16:36:51 2021 +0300 @@ -495,21 +495,24 @@ ngx_open_listening_sockets(ngx_cycle_t * return NGX_ERROR; } - if (setsockopt(s, SOL_SOCKET, SO_REUSEADDR, - (const void *) &reuseaddr, sizeof(int)) - == -1) - { - ngx_log_error(NGX_LOG_EMERG, log, ngx_socket_errno, - "setsockopt(SO_REUSEADDR) %V failed", - &ls[i].addr_text); + if (ls[i].type != SOCK_DGRAM || !ngx_test_config) { - if (ngx_close_socket(s) == -1) { + if (setsockopt(s, SOL_SOCKET, SO_REUSEADDR, + (const void *) &reuseaddr, sizeof(int)) + == -1) + { ngx_log_error(NGX_LOG_EMERG, log, ngx_socket_errno, - ngx_close_socket_n " %V failed", + "setsockopt(SO_REUSEADDR) %V failed", &ls[i].addr_text); - } - return NGX_ERROR; + if (ngx_close_socket(s) == -1) { + ngx_log_error(NGX_LOG_EMERG, log, ngx_socket_errno, + ngx_close_socket_n " %V failed", + &ls[i].addr_text); + } + + return NGX_ERROR; + } } #if (NGX_HAVE_REUSEPORT) From mdounin at mdounin.ru Mon May 31 14:39:57 2021 From: mdounin at mdounin.ru (Maxim Dounin) Date: Mon, 31 May 2021 14:39:57 +0000 Subject: [nginx] Contrib: vim syntax, update core and 3rd party module directives. Message-ID: details: https://hg.nginx.org/nginx/rev/d61d590ac826 branches: changeset: 7869:d61d590ac826 user: Gena Makhomed date: Sun May 30 12:26:00 2021 +0300 description: Contrib: vim syntax, update core and 3rd party module directives. diffstat: contrib/vim/syntax/nginx.vim | 15 +++++++++++++-- 1 files changed, 13 insertions(+), 2 deletions(-) diffs (78 lines): diff -r 46815874bcc6 -r d61d590ac826 contrib/vim/syntax/nginx.vim --- a/contrib/vim/syntax/nginx.vim Mon May 31 16:36:51 2021 +0300 +++ b/contrib/vim/syntax/nginx.vim Sun May 30 12:26:00 2021 +0300 @@ -152,6 +152,7 @@ syn keyword ngxDirective contained auth_ syn keyword ngxDirective contained auth_jwt_key_file syn keyword ngxDirective contained auth_jwt_key_request syn keyword ngxDirective contained auth_jwt_leeway +syn keyword ngxDirective contained auth_jwt_type syn keyword ngxDirective contained auth_request syn keyword ngxDirective contained auth_request_set syn keyword ngxDirective contained autoindex @@ -332,16 +333,20 @@ syn keyword ngxDirective contained index syn keyword ngxDirective contained iocp_threads syn keyword ngxDirective contained ip_hash syn keyword ngxDirective contained js_access +syn keyword ngxDirective contained js_body_filter syn keyword ngxDirective contained js_content syn keyword ngxDirective contained js_filter +syn keyword ngxDirective contained js_header_filter syn keyword ngxDirective contained js_import syn keyword ngxDirective contained js_include syn keyword ngxDirective contained js_path syn keyword ngxDirective contained js_preread syn keyword ngxDirective contained js_set +syn keyword ngxDirective contained js_var syn keyword ngxDirective contained keepalive syn keyword ngxDirective contained keepalive_disable syn keyword ngxDirective contained keepalive_requests +syn keyword ngxDirective contained keepalive_time syn keyword ngxDirective contained keepalive_timeout syn keyword ngxDirective contained keyval syn keyword ngxDirective contained keyval_zone @@ -373,6 +378,7 @@ syn keyword ngxDirective contained log_s syn keyword ngxDirective contained map_hash_bucket_size syn keyword ngxDirective contained map_hash_max_size syn keyword ngxDirective contained master_process +syn keyword ngxDirective contained max_errors syn keyword ngxDirective contained max_ranges syn keyword ngxDirective contained memcached_bind syn keyword ngxDirective contained memcached_buffer_size @@ -1080,6 +1086,8 @@ syn keyword ngxDirectiveThirdParty conta syn keyword ngxDirectiveThirdParty contained nchan_subscribe_request syn keyword ngxDirectiveThirdParty contained nchan_subscriber_first_message syn keyword ngxDirectiveThirdParty contained nchan_subscriber_http_raw_stream_separator +syn keyword ngxDirectiveThirdParty contained nchan_subscriber_info +syn keyword ngxDirectiveThirdParty contained nchan_subscriber_info_string syn keyword ngxDirectiveThirdParty contained nchan_subscriber_last_message_id syn keyword ngxDirectiveThirdParty contained nchan_subscriber_location syn keyword ngxDirectiveThirdParty contained nchan_subscriber_message_id_custom_etag_header @@ -2368,9 +2376,9 @@ syn keyword ngxDirectiveThirdParty conta " IP2Location Nginx " https://github.com/ip2location/ip2location-nginx -syn keyword ngxDirectiveThirdParty contained ip2location_proxy -syn keyword ngxDirectiveThirdParty contained ip2location_proxy_recursive +syn keyword ngxDirectiveThirdParty contained ip2location_addresstype syn keyword ngxDirectiveThirdParty contained ip2location_areacode +syn keyword ngxDirectiveThirdParty contained ip2location_category syn keyword ngxDirectiveThirdParty contained ip2location_city syn keyword ngxDirectiveThirdParty contained ip2location_country_long syn keyword ngxDirectiveThirdParty contained ip2location_country_short @@ -2384,6 +2392,8 @@ syn keyword ngxDirectiveThirdParty conta syn keyword ngxDirectiveThirdParty contained ip2location_mnc syn keyword ngxDirectiveThirdParty contained ip2location_mobilebrand syn keyword ngxDirectiveThirdParty contained ip2location_netspeed +syn keyword ngxDirectiveThirdParty contained ip2location_proxy +syn keyword ngxDirectiveThirdParty contained ip2location_proxy_recursive syn keyword ngxDirectiveThirdParty contained ip2location_region syn keyword ngxDirectiveThirdParty contained ip2location_timezone syn keyword ngxDirectiveThirdParty contained ip2location_usagetype @@ -2403,6 +2413,7 @@ syn keyword ngxDirectiveThirdParty conta syn keyword ngxDirectiveThirdParty contained ip2proxy_isp syn keyword ngxDirectiveThirdParty contained ip2proxy_is_proxy syn keyword ngxDirectiveThirdParty contained ip2proxy_last_seen +syn keyword ngxDirectiveThirdParty contained ip2proxy_provider syn keyword ngxDirectiveThirdParty contained ip2proxy_proxy syn keyword ngxDirectiveThirdParty contained ip2proxy_proxy_recursive syn keyword ngxDirectiveThirdParty contained ip2proxy_proxy_type From mdounin at mdounin.ru Mon May 31 14:40:18 2021 From: mdounin at mdounin.ru (Maxim Dounin) Date: Mon, 31 May 2021 17:40:18 +0300 Subject: [PATCH] Contrib: vim syntax, update core and 3rd party module directives. In-Reply-To: <7a3c71b8-2fde-1a29-3423-1d3fd9f29256@csdoc.com> References: <7a3c71b8-2fde-1a29-3423-1d3fd9f29256@csdoc.com> Message-ID: Hello! On Sun, May 30, 2021 at 12:29:19PM +0300, Gena Makhomed wrote: > # HG changeset patch > # User Gena Makhomed > # Date 1622366760 -10800 > # Sun May 30 12:26:00 2021 +0300 > # Node ID e3c137f6caa6c6b979e8eb8647d00a293fe1f112 > # Parent f5de03f308a6d7864b7d5108a968db56585b9a9b > Contrib: vim syntax, update core and 3rd party module directives. [...] Committed, thnx. -- Maxim Dounin http://mdounin.ru/ From Steffen.Kiess at ipvs.uni-stuttgart.de Mon May 31 16:00:13 2021 From: Steffen.Kiess at ipvs.uni-stuttgart.de (=?UTF-8?Q?Steffen_Kie=c3=9f?=) Date: Mon, 31 May 2021 18:00:13 +0200 Subject: [PATCH] SSL: export channel binding values as variables Message-ID: # HG changeset patch # User Steffen Kie? # Date 1622475202 -7200 # Mon May 31 17:33:22 2021 +0200 # Node ID a877e63832c8b373edac1f4ca7d09621204b05b9 # Parent d61d590ac82643bf7dbc7842e5baced7a9f11480 SSL: export channel binding values as variables. Export the channel binding values for tls-unique and tls-server-end-point as ssl_channel_binding_tls_unique and ssl_channel_binding_tls_server_end_point. The values are hex-encoded and are without the prefix. See RFC5929 for more information. diff -r d61d590ac826 -r a877e63832c8 src/event/ngx_event_openssl.c --- a/src/event/ngx_event_openssl.c Sun May 30 12:26:00 2021 +0300 +++ b/src/event/ngx_event_openssl.c Mon May 31 17:33:22 2021 +0200 @@ -12,6 +12,8 @@ #define NGX_SSL_PASSWORD_BUFFER_SIZE 4096 +#define NGX_SSL_MAX_CHANNEL_BINDING_SIZE 128 + typedef struct { ngx_uint_t engine; /* unsigned engine:1; */ @@ -4608,6 +4610,104 @@ ngx_int_t +ngx_ssl_get_channel_binding_tls_unique(ngx_connection_t *c, ngx_pool_t *pool, + ngx_str_t *s) +{ + size_t len; + u_char buf[NGX_SSL_MAX_CHANNEL_BINDING_SIZE]; + + /* https://datatracker.ietf.org/doc/html/rfc5929#section-3.1 */ + if (SSL_session_reused(c->ssl->connection)) { + /* abbreviated handshake, use message sent by the server (i.e. us) */ + len = SSL_get_finished(c->ssl->connection, buf, + NGX_SSL_MAX_CHANNEL_BINDING_SIZE); + } else { + /* full handshake, use message sent by the client (i.e. peer) */ + len = SSL_get_peer_finished(c->ssl->connection, buf, + NGX_SSL_MAX_CHANNEL_BINDING_SIZE); + } + + if (len == 0) { + s->len = 0; + return NGX_OK; + } + + s->len = 2 * len; + s->data = ngx_pnalloc(pool, 2 * len); + if (s->data == NULL) { + return NGX_ERROR; + } + + ngx_hex_dump(s->data, buf, len); + + return NGX_OK; +} + + +ngx_int_t +ngx_ssl_get_channel_binding_tls_server_end_point(ngx_connection_t *c, + ngx_pool_t *pool, ngx_str_t *s) +{ + /* required for X509_get_signature_nid support */ +#if OPENSSL_VERSION_NUMBER > 0x10100000L + int algo_nid; + X509 *server_cert; + const char *algo_name; + const EVP_MD *algo_type; + unsigned int len; + u_char buf[EVP_MAX_MD_SIZE]; + + server_cert = SSL_get_certificate(c->ssl->connection); + if (server_cert == NULL) { + /* no server certificate */ + s->len = 0; + return NGX_OK; + } + + if (!OBJ_find_sigid_algs(X509_get_signature_nid(server_cert), &algo_nid, + NULL)) { + ngx_log_error(NGX_LOG_ERR, c->log, 0, + "unable to find digest NID for certificate signature algorithm"); + return NGX_ERROR; + } + + /* https://datatracker.ietf.org/doc/html/rfc5929#section-4.1 */ + if (algo_nid == NID_md5 || algo_nid == NID_sha1) { + algo_type = EVP_sha256(); + } else { + algo_type = EVP_get_digestbynid(algo_nid); + if (algo_type == NULL) { + algo_name = OBJ_nid2sn(algo_nid); + ngx_log_error(NGX_LOG_ERR, c->log, 0, + "could not find digest algorithm %s (NID %d)", + algo_name ? algo_name : "(null)", algo_nid); + return NGX_ERROR; + } + } + + if (!X509_digest(server_cert, algo_type, buf, &len)) { + ngx_ssl_error(NGX_LOG_ERR, c->log, 0, "X509_digest() failed"); + return NGX_ERROR; + } + + s->len = 2 * len; + s->data = ngx_pnalloc(pool, 2 * len); + if (s->data == NULL) { + return NGX_ERROR; + } + + ngx_hex_dump(s->data, buf, len); + + return NGX_OK; +#else + ngx_ssl_error(NGX_LOG_ERR, c->log, 0, + "nginx compiled without X509_get_signature_nid support"); + return NGX_ERROR; +#endif +} + + +ngx_int_t ngx_ssl_get_session_reused(ngx_connection_t *c, ngx_pool_t *pool, ngx_str_t *s) { if (SSL_session_reused(c->ssl->connection)) { diff -r d61d590ac826 -r a877e63832c8 src/event/ngx_event_openssl.h --- a/src/event/ngx_event_openssl.h Sun May 30 12:26:00 2021 +0300 +++ b/src/event/ngx_event_openssl.h Mon May 31 17:33:22 2021 +0200 @@ -247,6 +247,10 @@ ngx_str_t *s); ngx_int_t ngx_ssl_get_curves(ngx_connection_t *c, ngx_pool_t *pool, ngx_str_t *s); +ngx_int_t ngx_ssl_get_channel_binding_tls_unique(ngx_connection_t *c, + ngx_pool_t *pool, ngx_str_t *s); +ngx_int_t ngx_ssl_get_channel_binding_tls_server_end_point(ngx_connection_t *c, + ngx_pool_t *pool, ngx_str_t *s); ngx_int_t ngx_ssl_get_session_id(ngx_connection_t *c, ngx_pool_t *pool, ngx_str_t *s); ngx_int_t ngx_ssl_get_session_reused(ngx_connection_t *c, ngx_pool_t *pool, diff -r d61d590ac826 -r a877e63832c8 src/http/modules/ngx_http_ssl_module.c --- a/src/http/modules/ngx_http_ssl_module.c Sun May 30 12:26:00 2021 +0300 +++ b/src/http/modules/ngx_http_ssl_module.c Mon May 31 17:33:22 2021 +0200 @@ -350,6 +350,15 @@ { ngx_string("ssl_curves"), NULL, ngx_http_ssl_variable, (uintptr_t) ngx_ssl_get_curves, NGX_HTTP_VAR_CHANGEABLE, 0 }, + { ngx_string("ssl_channel_binding_tls_unique"), NULL, ngx_http_ssl_variable, + (uintptr_t) ngx_ssl_get_channel_binding_tls_unique, + NGX_HTTP_VAR_CHANGEABLE, 0 }, + + { ngx_string("ssl_channel_binding_tls_server_end_point"), NULL, + ngx_http_ssl_variable, + (uintptr_t) ngx_ssl_get_channel_binding_tls_server_end_point, + NGX_HTTP_VAR_CHANGEABLE, 0 }, + { ngx_string("ssl_session_id"), NULL, ngx_http_ssl_variable, (uintptr_t) ngx_ssl_get_session_id, NGX_HTTP_VAR_CHANGEABLE, 0 }, diff -r d61d590ac826 -r a877e63832c8 src/stream/ngx_stream_ssl_module.c --- a/src/stream/ngx_stream_ssl_module.c Sun May 30 12:26:00 2021 +0300 +++ b/src/stream/ngx_stream_ssl_module.c Mon May 31 17:33:22 2021 +0200 @@ -257,6 +257,16 @@ { ngx_string("ssl_curves"), NULL, ngx_stream_ssl_variable, (uintptr_t) ngx_ssl_get_curves, NGX_STREAM_VAR_CHANGEABLE, 0 }, + { ngx_string("ssl_channel_binding_tls_unique"), NULL, + ngx_stream_ssl_variable, + (uintptr_t) ngx_ssl_get_channel_binding_tls_unique, + NGX_STREAM_VAR_CHANGEABLE, 0 }, + + { ngx_string("ssl_channel_binding_tls_server_end_point"), NULL, + ngx_stream_ssl_variable, + (uintptr_t) ngx_ssl_get_channel_binding_tls_server_end_point, + NGX_STREAM_VAR_CHANGEABLE, 0 }, + { ngx_string("ssl_session_id"), NULL, ngx_stream_ssl_variable, (uintptr_t) ngx_ssl_get_session_id, NGX_STREAM_VAR_CHANGEABLE, 0 }, From mdounin at mdounin.ru Mon May 31 16:06:26 2021 From: mdounin at mdounin.ru (Maxim Dounin) Date: Mon, 31 May 2021 19:06:26 +0300 Subject: [PATCH] Variable $time_short. In-Reply-To: References: Message-ID: Hello! On Sun, May 30, 2021 at 01:02:24PM +0300, Gena Makhomed wrote: > On 29.05.2021 0:55, Maxim Dounin wrote: > > >> Main purpose of variable $time_short is usage for logging, access.log. > >> > >> Existing variables $time_iso8601 and $time_local has bad readability, > >> because these variables contains timezone after seconds and it has > >> no space between date and time fields. > >> > >> Compare readability: > >> > >> 27/May/2021:21:19:12 +0300 > >> 27/May/2021:21:19:18 +0300 > >> 27/May/2021:21:19:25 +0300 > >> 27/May/2021:21:19:32 +0300 > >> 27/May/2021:21:19:43 +0300 > >> > >> 2021-05-27T21:19:12+03:00 > >> 2021-05-27T21:19:18+03:00 > >> 2021-05-27T21:19:25+03:00 > >> 2021-05-27T21:19:32+03:00 > >> 2021-05-27T21:19:43+03:00 > >> > >> 2021/05/27 21:19:12 > >> 2021/05/27 21:19:18 > >> 2021/05/27 21:19:25 > >> 2021/05/27 21:19:32 > >> 2021/05/27 21:19:43 > >> > >> But only proposed variable $time_short has excellent readability, > >> also this variable is very short, and contains no visual garbage. > > > > Well, if you want to improve readability and don't need a timezone > > in your logs, something like this might work instead: > > > > map $time_iso8601 $time { > > "~([0-9-]+)T([0-9:]+)" "$1 $2"; > > volatile; > > } > > > > I don't think that introducing additional builtin variables for > > additional data/time formats is a good idea. > > Using map directive for creating $time variable indeed allow us > improve readability of log files, but this method is not cheap, > - regular expressions runs for every record in access.log file. > > On busy servers (under DDoS attacks) can be hundreds of records > per second and this regexp in map directive will just eat CPU. > > Human-readable variable $time / $time_short intended to use on > busy servers, under DDoS-attacks, with Load Average 60 and more. > See https://github.com/makhomed/autofilter for details about this. While native implementation is by no means cheaper than a map-based one, it's hardly comparable even with a single syscall. Not to mention parsing the log line from a Python code you are referring to. As long as you don't introduce catastrophic backtracking in your regular expression, changing time format with a regular expression should be good enough. On the other hand, there are certainly other time formats to introduce as well. And we certainly don't want to support many native variables with all possible time formats. We already have three - $time_local, $time_iso8601, and $msec. > > I don't think that introducing additional builtin variables for > > additional data/time formats is a good idea. > > Why not? > > Builtin variable ngx_cached_err_log_time already exists in nginx, > patch for ngx_http_log_module is very small, just few lines of code: The error log time format is to be used in error logs. Exposing it as a variable leaves us two basic options: - Document the variable as data/time in the "1970/09/28 12:00:00" format. That is, if we'll ever consider changing the error log time format, for example, to add milliseconds as already asked multiple times, we'll have to introduce a separate builtin time format for the variable. - Document it as matching the format used for error log. That is, if we'll change the error log format, the change will as sell break the setup using the variable. Both options do not look attractive to me. Especially given that we already have time in three different formats available, and, as outlined above, it's trivial to introduce additional time formats by using map. -- Maxim Dounin http://mdounin.ru/ From mdounin at mdounin.ru Mon May 31 16:36:06 2021 From: mdounin at mdounin.ru (Maxim Dounin) Date: Mon, 31 May 2021 19:36:06 +0300 Subject: [PATCH] SSL: export channel binding values as variables In-Reply-To: References: Message-ID: Hello! On Mon, May 31, 2021 at 06:00:13PM +0200, Steffen Kie? wrote: > # HG changeset patch > # User Steffen Kie? > # Date 1622475202 -7200 > # Mon May 31 17:33:22 2021 +0200 > # Node ID a877e63832c8b373edac1f4ca7d09621204b05b9 > # Parent d61d590ac82643bf7dbc7842e5baced7a9f11480 > SSL: export channel binding values as variables. > > Export the channel binding values for tls-unique and tls-server-end-point as > ssl_channel_binding_tls_unique and ssl_channel_binding_tls_server_end_point. > The values are hex-encoded and are without the prefix. > > See RFC5929 for more information. Thanks for the patch. You may want to elaborate a bit more on how do you expect these variables to be used. [...] -- Maxim Dounin http://mdounin.ru/ From Steffen.Kiess at ipvs.uni-stuttgart.de Mon May 31 19:41:42 2021 From: Steffen.Kiess at ipvs.uni-stuttgart.de (=?UTF-8?Q?Steffen_Kie=c3=9f?=) Date: Mon, 31 May 2021 21:41:42 +0200 Subject: [PATCH] SSL: export channel binding values as variables In-Reply-To: References: Message-ID: <6c52eeee-107d-1582-9ada-9e10cb9518c0@ipvs.uni-stuttgart.de> Hello, On 31.05.21 18:36, Maxim Dounin wrote: > > Thanks for the patch. You may want to elaborate a bit more on how > do you expect these variables to be used. > > [...] > These variables can be used to implement authentication with channel binding in an http application. There are two channel binding types: - tls-unique: This is a value which will be different for every connection. Even if an attacker manages to perform a MitM attack (e.g. because he stole the private key of the server) the tls-unique value for the connections client<->attacker and for the connections attacker<->server will be different. This means an authentication protocol which uses channel binding will detect the attacker. This is used e.g. by RFC8120: https://datatracker.ietf.org/doc/html/rfc8120#section-7 - tls-server-end-point: This is a hash over the server certificate. Unlike tls-unique this will not detect an attack where the attacker has stolen the server key, but it will detect e.g. when a CA was compromised or when the user asked the browser to connect despite the certificate being invalid. tls-server-end-point is also used e.g. by SPNEGO-based HTTP authentication (https://datatracker.ietf.org/doc/html/rfc4559, often used single-sign-on in web application using Kerberos). Unlike tls-unique tls-server-end-point can be implemented without support by NGINX (by putting the server certificate into the configuration of the web application), but this is fragile (e.g. when the server certificate is changed) and will not work at all when the server is configured with multiple certificates (because the web application cannot know which one was used). I've attached a flask application + a client which shows how this can be used, the required configuration in NGINX (when using fastcgi) is: fastcgi_param SSL_CHANNEL_BINDING_TLS_UNIQUE $ssl_channel_binding_tls_unique; fastcgi_param SSL_CHANNEL_BINDING_TLS_SERVER_END_POINT $ssl_channel_binding_tls_server_end_point; Running the client will print: python3 client.py https://localhost:1443 Client tls-unique b'AF6E9B00BE510405DEA0EC53' Client tls-server-end-point 8cedd6e65cae9d1304163e0331a3e9bc8e0312bee92ac4f1ac5f972ceaddf08e Repsonse from server b'{"SSL_CHANNEL_BINDING_TLS_SERVER_END_POINT":"8cedd6e65cae9d1304163e0331a3e9bc8e0312bee92ac4f1ac5f972ceaddf08e","SSL_CHANNEL_BINDING_TLS_UNIQUE":"af6e9b00be510405dea0ec53"}\n' (And the values seen by the client and the server should be the same.) Best regards, Steffen Kie? -------------- next part -------------- A non-text attachment was scrubbed... Name: application.py Type: text/x-python Size: 457 bytes Desc: not available URL: -------------- next part -------------- A non-text attachment was scrubbed... Name: client.py Type: text/x-python Size: 1142 bytes Desc: not available URL: From mdounin at mdounin.ru Mon May 31 23:08:40 2021 From: mdounin at mdounin.ru (Maxim Dounin) Date: Tue, 1 Jun 2021 02:08:40 +0300 Subject: [PATCH] SSL: export channel binding values as variables In-Reply-To: <6c52eeee-107d-1582-9ada-9e10cb9518c0@ipvs.uni-stuttgart.de> References: <6c52eeee-107d-1582-9ada-9e10cb9518c0@ipvs.uni-stuttgart.de> Message-ID: Hello! On Mon, May 31, 2021 at 09:41:42PM +0200, Steffen Kie? wrote: > On 31.05.21 18:36, Maxim Dounin wrote: > > > > Thanks for the patch. You may want to elaborate a bit more on how > > do you expect these variables to be used. > > > > [...] > > > > These variables can be used to implement authentication with channel > binding in an http application. [...] > I've attached a flask application + a client which shows how this can be > used, the required configuration in NGINX (when using fastcgi) is: So, you expect these variables to be used by application developers to implement some (currently not implemented) authentication with channel binding in HTTP, and that's the only use case you consider, correct? Note that HTTP provides no guarantees about channels, that is, connections, and trying to use channel binding is expected to break operation over HTTP, especially in complex setups when using proxies or reverse proxies, such as nginx. Further, invalid assumptions about guarantees in HTTP can easily cause security issues, by incorrectly authenticating unrelated requests on the connection. Basically the same set of issues as already seen with Microsoft's mis-designed NTLM authentication which doesn't work through proxies. Given that, it might not be a good idea to provide such variables. -- Maxim Dounin http://mdounin.ru/