From phil at firstecu.com Sat Jul 1 17:39:20 2017 From: phil at firstecu.com (Phil H) Date: Sat, 1 Jul 2017 11:39:20 -0600 Subject: SCGI Request format bug Message-ID: I've got an SCGI project I'm working on. My setup: buildroot, arm, 1.10.3. I'm using auth_request to authorize any restricted resources, auth_request uses SCGI to my auth client. 99% of the time, I get normal, expected behavior. Randomly an http resource will have a bad SCGI request format from Nginx to my auth client, which causes that resource to get denied. It appears that Nginx has a problem formatting the SCGI request, has an invalid size at the front (per SCGI spec), which is typically 6-8 bytes larger than the bytes sent over the socket. Looks like a string handling bug. Here are some SCGI requests that come in bad ( 2 examples, each one has good on top, bad below) https://paste.ngx.cc/386b Thanks, -Phil -------------- next part -------------- An HTML attachment was scrubbed... URL: From peter at linss.com Sun Jul 2 01:21:03 2017 From: peter at linss.com (Peter Linss) Date: Sat, 01 Jul 2017 18:21:03 -0700 Subject: [PATCH] Enable multiple ssl_stapling_file configuration directives Message-ID: <0580b76366e8540973e0.1498958463@elemental-dev.linss.com> # HG changeset patch # User Peter Linss # Date 1498957095 25200 # Sat Jul 01 17:58:15 2017 -0700 # Node ID 0580b76366e8540973e0ed884d0cec9fc4a7e488 # Parent a1c6685e80cba59284fc5e500818ea3b871403eb Enable multiple ssl_stapling_file configuration directives When using OCSP stapling files with multiple certificates, each certificate must have its own ssl_stapling_file. Changes ssl_stapling_file to store an array, and sets individual staples per certificate. Generates an error if ssl_stapling_file is specified but not the same number of times as certificates. diff --git a/src/event/ngx_event_openssl.h b/src/event/ngx_event_openssl.h --- a/src/event/ngx_event_openssl.h +++ b/src/event/ngx_event_openssl.h @@ -154,17 +154,17 @@ ngx_int_t ngx_ssl_certificate(ngx_conf_t ngx_int_t ngx_ssl_ciphers(ngx_conf_t *cf, ngx_ssl_t *ssl, ngx_str_t *ciphers, ngx_uint_t prefer_server_ciphers); ngx_int_t ngx_ssl_client_certificate(ngx_conf_t *cf, ngx_ssl_t *ssl, ngx_str_t *cert, ngx_int_t depth); ngx_int_t ngx_ssl_trusted_certificate(ngx_conf_t *cf, ngx_ssl_t *ssl, ngx_str_t *cert, ngx_int_t depth); ngx_int_t ngx_ssl_crl(ngx_conf_t *cf, ngx_ssl_t *ssl, ngx_str_t *crl); ngx_int_t ngx_ssl_stapling(ngx_conf_t *cf, ngx_ssl_t *ssl, - ngx_str_t *file, ngx_str_t *responder, ngx_uint_t verify); + ngx_array_t *files, ngx_str_t *responder, ngx_uint_t verify); ngx_int_t ngx_ssl_stapling_resolver(ngx_conf_t *cf, ngx_ssl_t *ssl, ngx_resolver_t *resolver, ngx_msec_t resolver_timeout); RSA *ngx_ssl_rsa512_key_callback(ngx_ssl_conn_t *ssl_conn, int is_export, int key_length); ngx_array_t *ngx_ssl_read_password_file(ngx_conf_t *cf, ngx_str_t *file); ngx_int_t ngx_ssl_dhparam(ngx_conf_t *cf, ngx_ssl_t *ssl, ngx_str_t *file); ngx_int_t ngx_ssl_ecdh_curve(ngx_conf_t *cf, ngx_ssl_t *ssl, ngx_str_t *name); ngx_int_t ngx_ssl_session_cache(ngx_ssl_t *ssl, ngx_str_t *sess_ctx, diff --git a/src/event/ngx_event_openssl_stapling.c b/src/event/ngx_event_openssl_stapling.c --- a/src/event/ngx_event_openssl_stapling.c +++ b/src/event/ngx_event_openssl_stapling.c @@ -120,29 +120,47 @@ static ngx_int_t ngx_ssl_ocsp_parse_stat static ngx_int_t ngx_ssl_ocsp_process_headers(ngx_ssl_ocsp_ctx_t *ctx); static ngx_int_t ngx_ssl_ocsp_parse_header_line(ngx_ssl_ocsp_ctx_t *ctx); static ngx_int_t ngx_ssl_ocsp_process_body(ngx_ssl_ocsp_ctx_t *ctx); static u_char *ngx_ssl_ocsp_log_error(ngx_log_t *log, u_char *buf, size_t len); ngx_int_t -ngx_ssl_stapling(ngx_conf_t *cf, ngx_ssl_t *ssl, ngx_str_t *file, +ngx_ssl_stapling(ngx_conf_t *cf, ngx_ssl_t *ssl, ngx_array_t *files, ngx_str_t *responder, ngx_uint_t verify) { - X509 *cert; + X509 *cert; + ngx_str_t *file; + ngx_uint_t i; - for (cert = SSL_CTX_get_ex_data(ssl->ctx, ngx_ssl_certificate_index); - cert; - cert = X509_get_ex_data(cert, ngx_ssl_next_certificate_index)) + if (files == NULL) { - if (ngx_ssl_stapling_certificate(cf, ssl, cert, file, responder, verify) - != NGX_OK) + for (cert = SSL_CTX_get_ex_data(ssl->ctx, ngx_ssl_certificate_index); + cert; + cert = X509_get_ex_data(cert, ngx_ssl_next_certificate_index)) { - return NGX_ERROR; + if (ngx_ssl_stapling_certificate(cf, ssl, cert, NULL, responder, verify) + != NGX_OK) + { + return NGX_ERROR; + } + } + } else { + file = files->elts; + + for (cert = SSL_CTX_get_ex_data(ssl->ctx, ngx_ssl_certificate_index), i = files->nelts - 1; + cert; + cert = X509_get_ex_data(cert, ngx_ssl_next_certificate_index), i--) + { + if (ngx_ssl_stapling_certificate(cf, ssl, cert, &file[i], responder, verify) + != NGX_OK) + { + return NGX_ERROR; + } } } SSL_CTX_set_tlsext_status_cb(ssl->ctx, ngx_ssl_certificate_status_callback); return NGX_OK; } @@ -175,17 +193,17 @@ ngx_ssl_stapling_certificate(ngx_conf_t staple->ssl_ctx = ssl->ctx; staple->timeout = 60000; staple->verify = verify; staple->cert = cert; staple->name = X509_get_ex_data(staple->cert, ngx_ssl_certificate_name_index); - if (file->len) { + if (file && file->len) { /* use OCSP response from the file */ if (ngx_ssl_stapling_file(cf, ssl, staple, file) != NGX_OK) { return NGX_ERROR; } return NGX_OK; } @@ -1866,17 +1884,17 @@ ngx_ssl_ocsp_log_error(ngx_log_t *log, u return p; } #else ngx_int_t -ngx_ssl_stapling(ngx_conf_t *cf, ngx_ssl_t *ssl, ngx_str_t *file, +ngx_ssl_stapling(ngx_conf_t *cf, ngx_ssl_t *ssl, ngx_array_t *files, ngx_str_t *responder, ngx_uint_t verify) { ngx_log_error(NGX_LOG_WARN, ssl->log, 0, "\"ssl_stapling\" ignored, not supported"); return NGX_OK; } diff --git a/src/http/modules/ngx_http_ssl_module.c b/src/http/modules/ngx_http_ssl_module.c --- a/src/http/modules/ngx_http_ssl_module.c +++ b/src/http/modules/ngx_http_ssl_module.c @@ -210,19 +210,19 @@ static ngx_command_t ngx_http_ssl_comma NGX_HTTP_MAIN_CONF|NGX_HTTP_SRV_CONF|NGX_CONF_FLAG, ngx_conf_set_flag_slot, NGX_HTTP_SRV_CONF_OFFSET, offsetof(ngx_http_ssl_srv_conf_t, stapling), NULL }, { ngx_string("ssl_stapling_file"), NGX_HTTP_MAIN_CONF|NGX_HTTP_SRV_CONF|NGX_CONF_TAKE1, - ngx_conf_set_str_slot, + ngx_conf_set_str_array_slot, NGX_HTTP_SRV_CONF_OFFSET, - offsetof(ngx_http_ssl_srv_conf_t, stapling_file), + offsetof(ngx_http_ssl_srv_conf_t, stapling_files), NULL }, { ngx_string("ssl_stapling_responder"), NGX_HTTP_MAIN_CONF|NGX_HTTP_SRV_CONF|NGX_CONF_TAKE1, ngx_conf_set_str_slot, NGX_HTTP_SRV_CONF_OFFSET, offsetof(ngx_http_ssl_srv_conf_t, stapling_responder), NULL }, @@ -532,33 +532,33 @@ ngx_http_ssl_create_srv_conf(ngx_conf_t * sscf->protocols = 0; * sscf->dhparam = { 0, NULL }; * sscf->ecdh_curve = { 0, NULL }; * sscf->client_certificate = { 0, NULL }; * sscf->trusted_certificate = { 0, NULL }; * sscf->crl = { 0, NULL }; * sscf->ciphers = { 0, NULL }; * sscf->shm_zone = NULL; - * sscf->stapling_file = { 0, NULL }; * sscf->stapling_responder = { 0, NULL }; */ sscf->enable = NGX_CONF_UNSET; sscf->prefer_server_ciphers = NGX_CONF_UNSET; sscf->buffer_size = NGX_CONF_UNSET_SIZE; sscf->verify = NGX_CONF_UNSET_UINT; sscf->verify_depth = NGX_CONF_UNSET_UINT; sscf->certificates = NGX_CONF_UNSET_PTR; sscf->certificate_keys = NGX_CONF_UNSET_PTR; sscf->passwords = NGX_CONF_UNSET_PTR; sscf->builtin_session_cache = NGX_CONF_UNSET; sscf->session_timeout = NGX_CONF_UNSET; sscf->session_tickets = NGX_CONF_UNSET; sscf->session_ticket_keys = NGX_CONF_UNSET_PTR; sscf->stapling = NGX_CONF_UNSET; + sscf->stapling_files = NGX_CONF_UNSET_PTR; sscf->stapling_verify = NGX_CONF_UNSET; return sscf; } static char * ngx_http_ssl_merge_srv_conf(ngx_conf_t *cf, void *parent, void *child) @@ -611,17 +611,17 @@ ngx_http_ssl_merge_srv_conf(ngx_conf_t * ngx_conf_merge_str_value(conf->ecdh_curve, prev->ecdh_curve, NGX_DEFAULT_ECDH_CURVE); ngx_conf_merge_str_value(conf->ciphers, prev->ciphers, NGX_DEFAULT_CIPHERS); ngx_conf_merge_value(conf->stapling, prev->stapling, 0); ngx_conf_merge_value(conf->stapling_verify, prev->stapling_verify, 0); - ngx_conf_merge_str_value(conf->stapling_file, prev->stapling_file, ""); + ngx_conf_merge_ptr_value(conf->stapling_files, prev->stapling_files, NULL); ngx_conf_merge_str_value(conf->stapling_responder, prev->stapling_responder, ""); conf->ssl.log = cf->log; if (conf->enable) { if (conf->certificates == NULL) { @@ -662,16 +662,28 @@ ngx_http_ssl_merge_srv_conf(ngx_conf_t * { ngx_log_error(NGX_LOG_EMERG, cf->log, 0, "no \"ssl_certificate_key\" is defined " "for certificate \"%V\"", ((ngx_str_t *) conf->certificates->elts) + conf->certificates->nelts - 1); return NGX_CONF_ERROR; } + + if ((conf->stapling_files) && + (conf->stapling_files->nelts != conf->certificates->nelts)) + { + ngx_log_error(NGX_LOG_EMERG, cf->log, 0, + "no \"ssl_stapling_file\" is defined " + "for certificate \"%V\"", + ((ngx_str_t *) conf->certificates->elts) + + conf->certificates->nelts - 1); + return NGX_CONF_ERROR; + } + } if (ngx_ssl_create(&conf->ssl, conf->protocols, conf) != NGX_OK) { return NGX_CONF_ERROR; } #ifdef SSL_CTRL_SET_TLSEXT_HOSTNAME @@ -786,17 +798,17 @@ ngx_http_ssl_merge_srv_conf(ngx_conf_t * if (ngx_ssl_session_ticket_keys(cf, &conf->ssl, conf->session_ticket_keys) != NGX_OK) { return NGX_CONF_ERROR; } if (conf->stapling) { - if (ngx_ssl_stapling(cf, &conf->ssl, &conf->stapling_file, + if (ngx_ssl_stapling(cf, &conf->ssl, conf->stapling_files, &conf->stapling_responder, conf->stapling_verify) != NGX_OK) { return NGX_CONF_ERROR; } } diff --git a/src/http/modules/ngx_http_ssl_module.h b/src/http/modules/ngx_http_ssl_module.h --- a/src/http/modules/ngx_http_ssl_module.h +++ b/src/http/modules/ngx_http_ssl_module.h @@ -47,17 +47,17 @@ typedef struct { ngx_shm_zone_t *shm_zone; ngx_flag_t session_tickets; ngx_array_t *session_ticket_keys; ngx_flag_t stapling; ngx_flag_t stapling_verify; - ngx_str_t stapling_file; + ngx_array_t *stapling_files; ngx_str_t stapling_responder; u_char *file; ngx_uint_t line; } ngx_http_ssl_srv_conf_t; extern ngx_module_t ngx_http_ssl_module; From mdounin at mdounin.ru Mon Jul 3 12:56:22 2017 From: mdounin at mdounin.ru (Maxim Dounin) Date: Mon, 3 Jul 2017 15:56:22 +0300 Subject: SCGI Request format bug In-Reply-To: References: Message-ID: <20170703125622.GS55433@mdounin.ru> Hello! On Sat, Jul 01, 2017 at 11:39:20AM -0600, Phil H wrote: > I've got an SCGI project I'm working on. My setup: buildroot, arm, > 1.10.3. I'm using auth_request to authorize any restricted resources, > auth_request uses SCGI to my auth client. 99% of the time, I get normal, > expected behavior. Randomly an http resource will have a bad SCGI request > format from Nginx to my auth client, which causes that resource to get > denied. It appears that Nginx has a problem formatting the SCGI request, > has an invalid size at the front (per SCGI spec), which is typically 6-8 > bytes larger than the bytes sent over the socket. Looks like a string > handling bug. Here are some SCGI requests that come in bad ( 2 examples, > each one has good on top, bad below) > > https://paste.ngx.cc/386b Please provide: - "nginx -V" output; - full configuration which triggers the problem (a minimal configuration enough to reproduce the problem would be a plus); - a debugging log (http://nginx.org/en/docs/debugging_log.html); - dump of the traffic between nginx and the backend for a problematic request ("tcpdump -Xs0" should be fine). -- Maxim Dounin http://nginx.org/ From vbart at nginx.com Mon Jul 3 13:58:47 2017 From: vbart at nginx.com (Valentin V. Bartenev) Date: Mon, 03 Jul 2017 16:58:47 +0300 Subject: [PATCH 03 of 14] HTTP/2: add debug logging of control frames In-Reply-To: <22d178a11e30c4a8576c.1498163587@piotrsikora.sfo.corp.google.com> References: <5f5d70428655db0889a2.1498163585@piotrsikora.sfo.corp.google.com> <22d178a11e30c4a8576c.1498163587@piotrsikora.sfo.corp.google.com> Message-ID: <18284940.HFE4rYao7p@vbart-workstation> On Thursday 22 June 2017 13:33:07 Piotr Sikora via nginx-devel wrote: > # HG changeset patch > # User Piotr Sikora > # Date 1490516711 25200 > # Sun Mar 26 01:25:11 2017 -0700 > # Node ID 22d178a11e30c4a8576c3ce28859dfe1cc8adec0 > # Parent a147dd50ee3fb8628b79f4482c552c7c2852a732 > HTTP/2: add debug logging of control frames. > > Signed-off-by: Piotr Sikora > [..] I suggest to make messages a bit more readable this way: diff -r ee638caf7f73 src/http/v2/ngx_http_v2.c --- a/src/http/v2/ngx_http_v2.c Sun Mar 26 01:25:11 2017 -0700 +++ b/src/http/v2/ngx_http_v2.c Mon Jul 03 16:56:01 2017 +0300 @@ -1949,7 +1949,7 @@ ngx_http_v2_state_settings(ngx_http_v2_c } ngx_log_debug0(NGX_LOG_DEBUG_HTTP, h2c->connection->log, 0, - "http2 SETTINGS frame ack:1"); + "http2 SETTINGS ACK frame"); h2c->settings_ack = 1; @@ -1965,7 +1965,7 @@ ngx_http_v2_state_settings(ngx_http_v2_c } ngx_log_debug1(NGX_LOG_DEBUG_HTTP, h2c->connection->log, 0, - "http2 SETTINGS frame params:%uz", + "http2 SETTINGS frame with %uz params", h2c->state.length / NGX_HTTP_V2_SETTINGS_PARAM_SIZE); return ngx_http_v2_state_settings_params(h2c, pos, end); @@ -1998,21 +1998,21 @@ ngx_http_v2_state_settings_params(ngx_ht case NGX_HTTP_V2_HEADER_TABLE_SIZE_SETTING: ngx_log_debug1(NGX_LOG_DEBUG_HTTP, h2c->connection->log, 0, - "http2 SETTINGS param HEADER_TABLE_SIZE:%ui " + "http2 SETTINGS param HEADER_TABLE_SIZE: %ui " "(ignored)", value); break; case NGX_HTTP_V2_ENABLE_PUSH_SETTING: ngx_log_debug1(NGX_LOG_DEBUG_HTTP, h2c->connection->log, 0, - "http2 SETTINGS param ENABLE_PUSH:%ui " + "http2 SETTINGS param ENABLE_PUSH: %ui " "(ignored)", value); break; case NGX_HTTP_V2_MAX_STREAMS_SETTING: ngx_log_debug1(NGX_LOG_DEBUG_HTTP, h2c->connection->log, 0, - "http2 SETTINGS param MAX_CONCURRENT_STREAMS:%ui " + "http2 SETTINGS param MAX_CONCURRENT_STREAMS: %ui " "(ignored)", value); break; @@ -2028,7 +2028,7 @@ ngx_http_v2_state_settings_params(ngx_ht } ngx_log_debug1(NGX_LOG_DEBUG_HTTP, h2c->connection->log, 0, - "http2 SETTINGS param INITIAL_WINDOW_SIZE:%ui", + "http2 SETTINGS param INITIAL_WINDOW_SIZE: %ui", value); window_delta = value - h2c->init_window; @@ -2050,7 +2050,7 @@ ngx_http_v2_state_settings_params(ngx_ht } ngx_log_debug1(NGX_LOG_DEBUG_HTTP, h2c->connection->log, 0, - "http2 SETTINGS param MAX_FRAME_SIZE:%ui", + "http2 SETTINGS param MAX_FRAME_SIZE: %ui", value); h2c->frame_size = value; @@ -2059,15 +2059,15 @@ ngx_http_v2_state_settings_params(ngx_ht case NGX_HTTP_V2_HEADER_LIST_SIZE_SETTING: ngx_log_debug1(NGX_LOG_DEBUG_HTTP, h2c->connection->log, 0, - "http2 SETTINGS param MAX_HEADER_LIST_SIZE:%ui " + "http2 SETTINGS param MAX_HEADER_LIST_SIZE: %ui " "(ignored)", value); break; default: ngx_log_debug2(NGX_LOG_DEBUG_HTTP, h2c->connection->log, 0, - "http2 SETTINGS param 0x%Xi:%ui " - "(ignored)", id, value); + "http2 unknown SETTINGS param id:0x%Xi value:%ui", + id, value); break; } @@ -2075,7 +2075,7 @@ ngx_http_v2_state_settings_params(ngx_ht } ngx_log_debug0(NGX_LOG_DEBUG_HTTP, h2c->connection->log, 0, - "http2 send SETTINGS frame ack:1"); + "http2 send SETTINGS ACK frame"); frame = ngx_http_v2_get_frame(h2c, NGX_HTTP_V2_SETTINGS_ACK_SIZE, NGX_HTTP_V2_SETTINGS_FRAME, @@ -2126,16 +2126,18 @@ ngx_http_v2_state_ping(ngx_http_v2_conne return ngx_http_v2_state_save(h2c, pos, end, ngx_http_v2_state_ping); } - ngx_log_debug1(NGX_LOG_DEBUG_HTTP, h2c->connection->log, 0, - "http2 PING frame ack:%ud", - h2c->state.flags & NGX_HTTP_V2_ACK_FLAG ? 1 : 0); - if (h2c->state.flags & NGX_HTTP_V2_ACK_FLAG) { + ngx_log_debug0(NGX_LOG_DEBUG_HTTP, h2c->connection->log, 0, + "http2 PING ACK frame", + return ngx_http_v2_state_skip(h2c, pos, end); } ngx_log_debug0(NGX_LOG_DEBUG_HTTP, h2c->connection->log, 0, - "http2 send PING frame ack:1"); + "http2 PING frame", + + ngx_log_debug0(NGX_LOG_DEBUG_HTTP, h2c->connection->log, 0, + "http2 send PING ACK frame"); frame = ngx_http_v2_get_frame(h2c, NGX_HTTP_V2_PING_SIZE, NGX_HTTP_V2_PING_FRAME, @@ -2551,7 +2553,7 @@ ngx_http_v2_send_settings(ngx_http_v2_co len = NGX_HTTP_V2_SETTINGS_PARAM_SIZE * 3; ngx_log_debug1(NGX_LOG_DEBUG_HTTP, h2c->connection->log, 0, - "http2 send SETTINGS frame params:%uz", + "http2 send SETTINGS frame with %uz params", len / NGX_HTTP_V2_SETTINGS_PARAM_SIZE); frame = ngx_palloc(h2c->pool, sizeof(ngx_http_v2_out_frame_t)); @@ -2594,7 +2596,7 @@ ngx_http_v2_send_settings(ngx_http_v2_co ngx_http_v2_module); ngx_log_debug1(NGX_LOG_DEBUG_HTTP, h2c->connection->log, 0, - "http2 send SETTINGS param MAX_CONCURRENT_STREAMS:%ui", + "http2 send SETTINGS param MAX_CONCURRENT_STREAMS: %ui", h2scf->concurrent_streams); buf->last = ngx_http_v2_write_uint16(buf->last, @@ -2603,7 +2605,7 @@ ngx_http_v2_send_settings(ngx_http_v2_co h2scf->concurrent_streams); ngx_log_debug1(NGX_LOG_DEBUG_HTTP, h2c->connection->log, 0, - "http2 send SETTINGS param INITIAL_WINDOW_SIZE:%uz", + "http2 send SETTINGS param INITIAL_WINDOW_SIZE: %uz", h2scf->preread_size); buf->last = ngx_http_v2_write_uint16(buf->last, @@ -2611,7 +2613,7 @@ ngx_http_v2_send_settings(ngx_http_v2_co buf->last = ngx_http_v2_write_uint32(buf->last, h2scf->preread_size); ngx_log_debug1(NGX_LOG_DEBUG_HTTP, h2c->connection->log, 0, - "http2 send SETTINGS param MAX_FRAME_SIZE:%ud", + "http2 send SETTINGS param MAX_FRAME_SIZE: %ud", NGX_HTTP_V2_MAX_FRAME_SIZE); buf->last = ngx_http_v2_write_uint16(buf->last, From mdounin at mdounin.ru Mon Jul 3 14:19:20 2017 From: mdounin at mdounin.ru (Maxim Dounin) Date: Mon, 03 Jul 2017 14:19:20 +0000 Subject: [nginx] Version bump. Message-ID: details: http://hg.nginx.org/nginx/rev/d635505cd29e branches: changeset: 7046:d635505cd29e user: Maxim Dounin date: Mon Jul 03 16:58:08 2017 +0300 description: Version bump. diffstat: src/core/nginx.h | 4 ++-- 1 files changed, 2 insertions(+), 2 deletions(-) diffs (14 lines): diff --git a/src/core/nginx.h b/src/core/nginx.h --- a/src/core/nginx.h +++ b/src/core/nginx.h @@ -9,8 +9,8 @@ #define _NGINX_H_INCLUDED_ -#define nginx_version 1013002 -#define NGINX_VERSION "1.13.2" +#define nginx_version 1013003 +#define NGINX_VERSION "1.13.3" #define NGINX_VER "nginx/" NGINX_VERSION #ifdef NGX_BUILD From mdounin at mdounin.ru Mon Jul 3 14:19:29 2017 From: mdounin at mdounin.ru (Maxim Dounin) Date: Mon, 03 Jul 2017 14:19:29 +0000 Subject: [nginx] Proxy: split configured header names and values. Message-ID: details: http://hg.nginx.org/nginx/rev/3fef8c5caa75 branches: changeset: 7047:3fef8c5caa75 user: Piotr Sikora date: Wed Mar 15 15:55:35 2017 -0700 description: Proxy: split configured header names and values. Previously, each configured header was represented in one of two ways, depending on whether or not its value included any variables. If the value didn't include any variables, then it would be represented as as a single script that contained complete header line with HTTP/1.1 delimiters, i.e.: "Header: value\r\n" But if the value included any variables, then it would be represented as a series of three scripts: first contained header name and the ": " delimiter, second evaluated to header value, and third contained only "\r\n", i.e.: "Header: " "$value" "\r\n" This commit changes that, so that each configured header is represented as a series of two scripts: first contains only header name, and second contains (or evaluates to) only header value, i.e.: "Header" "$value" or "Header" "value" This not only makes things more consistent, but also allows header name and value to be accessed separately. Signed-off-by: Piotr Sikora diffstat: src/http/modules/ngx_http_proxy_module.c | 185 +++++++++++------------------- 1 files changed, 69 insertions(+), 116 deletions(-) diffs (232 lines): diff --git a/src/http/modules/ngx_http_proxy_module.c b/src/http/modules/ngx_http_proxy_module.c --- a/src/http/modules/ngx_http_proxy_module.c +++ b/src/http/modules/ngx_http_proxy_module.c @@ -1143,7 +1143,8 @@ ngx_http_proxy_create_key(ngx_http_reque static ngx_int_t ngx_http_proxy_create_request(ngx_http_request_t *r) { - size_t len, uri_len, loc_len, body_len; + size_t len, uri_len, loc_len, body_len, + key_len, val_len; uintptr_t escape; ngx_buf_t *b; ngx_str_t method; @@ -1258,11 +1259,20 @@ ngx_http_proxy_create_request(ngx_http_r le.flushed = 1; while (*(uintptr_t *) le.ip) { - while (*(uintptr_t *) le.ip) { + + lcode = *(ngx_http_script_len_code_pt *) le.ip; + key_len = lcode(&le); + + for (val_len = 0; *(uintptr_t *) le.ip; val_len += lcode(&le)) { lcode = *(ngx_http_script_len_code_pt *) le.ip; - len += lcode(&le); } le.ip += sizeof(uintptr_t); + + if (val_len == 0) { + continue; + } + + len += key_len + sizeof(": ") - 1 + val_len + sizeof(CRLF) - 1; } @@ -1362,30 +1372,41 @@ ngx_http_proxy_create_request(ngx_http_r le.ip = headers->lengths->elts; while (*(uintptr_t *) le.ip) { + lcode = *(ngx_http_script_len_code_pt *) le.ip; - - /* skip the header line name length */ (void) lcode(&le); - if (*(ngx_http_script_len_code_pt *) le.ip) { - - for (len = 0; *(uintptr_t *) le.ip; len += lcode(&le)) { - lcode = *(ngx_http_script_len_code_pt *) le.ip; + for (val_len = 0; *(uintptr_t *) le.ip; val_len += lcode(&le)) { + lcode = *(ngx_http_script_len_code_pt *) le.ip; + } + le.ip += sizeof(uintptr_t); + + if (val_len == 0) { + e.skip = 1; + + while (*(uintptr_t *) e.ip) { + code = *(ngx_http_script_code_pt *) e.ip; + code((ngx_http_script_engine_t *) &e); } - - e.skip = (len == sizeof(CRLF) - 1) ? 1 : 0; - - } else { + e.ip += sizeof(uintptr_t); + e.skip = 0; + + continue; } - le.ip += sizeof(uintptr_t); + code = *(ngx_http_script_code_pt *) e.ip; + code((ngx_http_script_engine_t *) &e); + + *e.pos++ = ':'; *e.pos++ = ' '; while (*(uintptr_t *) e.ip) { code = *(ngx_http_script_code_pt *) e.ip; code((ngx_http_script_engine_t *) &e); } e.ip += sizeof(uintptr_t); + + *e.pos++ = CR; *e.pos++ = LF; } b->last = e.pos; @@ -3498,108 +3519,40 @@ ngx_http_proxy_init_headers(ngx_conf_t * continue; } - if (ngx_http_script_variables_count(&src[i].value) == 0) { - copy = ngx_array_push_n(headers->lengths, - sizeof(ngx_http_script_copy_code_t)); - if (copy == NULL) { - return NGX_ERROR; - } - - copy->code = (ngx_http_script_code_pt) - ngx_http_script_copy_len_code; - copy->len = src[i].key.len + sizeof(": ") - 1 - + src[i].value.len + sizeof(CRLF) - 1; - - - size = (sizeof(ngx_http_script_copy_code_t) - + src[i].key.len + sizeof(": ") - 1 - + src[i].value.len + sizeof(CRLF) - 1 - + sizeof(uintptr_t) - 1) - & ~(sizeof(uintptr_t) - 1); - - copy = ngx_array_push_n(headers->values, size); - if (copy == NULL) { - return NGX_ERROR; - } - - copy->code = ngx_http_script_copy_code; - copy->len = src[i].key.len + sizeof(": ") - 1 - + src[i].value.len + sizeof(CRLF) - 1; - - p = (u_char *) copy + sizeof(ngx_http_script_copy_code_t); - - p = ngx_cpymem(p, src[i].key.data, src[i].key.len); - *p++ = ':'; *p++ = ' '; - p = ngx_cpymem(p, src[i].value.data, src[i].value.len); - *p++ = CR; *p = LF; - - } else { - copy = ngx_array_push_n(headers->lengths, - sizeof(ngx_http_script_copy_code_t)); - if (copy == NULL) { - return NGX_ERROR; - } - - copy->code = (ngx_http_script_code_pt) - ngx_http_script_copy_len_code; - copy->len = src[i].key.len + sizeof(": ") - 1; - - - size = (sizeof(ngx_http_script_copy_code_t) - + src[i].key.len + sizeof(": ") - 1 + sizeof(uintptr_t) - 1) - & ~(sizeof(uintptr_t) - 1); - - copy = ngx_array_push_n(headers->values, size); - if (copy == NULL) { - return NGX_ERROR; - } - - copy->code = ngx_http_script_copy_code; - copy->len = src[i].key.len + sizeof(": ") - 1; - - p = (u_char *) copy + sizeof(ngx_http_script_copy_code_t); - p = ngx_cpymem(p, src[i].key.data, src[i].key.len); - *p++ = ':'; *p = ' '; - - - ngx_memzero(&sc, sizeof(ngx_http_script_compile_t)); - - sc.cf = cf; - sc.source = &src[i].value; - sc.flushes = &headers->flushes; - sc.lengths = &headers->lengths; - sc.values = &headers->values; - - if (ngx_http_script_compile(&sc) != NGX_OK) { - return NGX_ERROR; - } - - - copy = ngx_array_push_n(headers->lengths, - sizeof(ngx_http_script_copy_code_t)); - if (copy == NULL) { - return NGX_ERROR; - } - - copy->code = (ngx_http_script_code_pt) - ngx_http_script_copy_len_code; - copy->len = sizeof(CRLF) - 1; - - - size = (sizeof(ngx_http_script_copy_code_t) - + sizeof(CRLF) - 1 + sizeof(uintptr_t) - 1) - & ~(sizeof(uintptr_t) - 1); - - copy = ngx_array_push_n(headers->values, size); - if (copy == NULL) { - return NGX_ERROR; - } - - copy->code = ngx_http_script_copy_code; - copy->len = sizeof(CRLF) - 1; - - p = (u_char *) copy + sizeof(ngx_http_script_copy_code_t); - *p++ = CR; *p = LF; + copy = ngx_array_push_n(headers->lengths, + sizeof(ngx_http_script_copy_code_t)); + if (copy == NULL) { + return NGX_ERROR; + } + + copy->code = (ngx_http_script_code_pt) ngx_http_script_copy_len_code; + copy->len = src[i].key.len; + + size = (sizeof(ngx_http_script_copy_code_t) + + src[i].key.len + sizeof(uintptr_t) - 1) + & ~(sizeof(uintptr_t) - 1); + + copy = ngx_array_push_n(headers->values, size); + if (copy == NULL) { + return NGX_ERROR; + } + + copy->code = ngx_http_script_copy_code; + copy->len = src[i].key.len; + + p = (u_char *) copy + sizeof(ngx_http_script_copy_code_t); + ngx_memcpy(p, src[i].key.data, src[i].key.len); + + ngx_memzero(&sc, sizeof(ngx_http_script_compile_t)); + + sc.cf = cf; + sc.source = &src[i].value; + sc.flushes = &headers->flushes; + sc.lengths = &headers->lengths; + sc.values = &headers->values; + + if (ngx_http_script_compile(&sc) != NGX_OK) { + return NGX_ERROR; } code = ngx_array_push_n(headers->lengths, sizeof(uintptr_t)); From mdounin at mdounin.ru Mon Jul 3 14:19:38 2017 From: mdounin at mdounin.ru (Maxim Dounin) Date: Mon, 3 Jul 2017 17:19:38 +0300 Subject: [PATCH 11 of 14] Proxy: split configured header names and values In-Reply-To: <0637acdb51e29e1f68f5.1498163595@piotrsikora.sfo.corp.google.com> References: <5f5d70428655db0889a2.1498163585@piotrsikora.sfo.corp.google.com> <0637acdb51e29e1f68f5.1498163595@piotrsikora.sfo.corp.google.com> Message-ID: <20170703141938.GV55433@mdounin.ru> Hello! On Thu, Jun 22, 2017 at 01:33:15PM -0700, Piotr Sikora via nginx-devel wrote: > # HG changeset patch > # User Piotr Sikora > # Date 1489618535 25200 > # Wed Mar 15 15:55:35 2017 -0700 > # Node ID 0637acdb51e29e1f68f5f3e762115c702cab4e72 > # Parent 068381014f256ad6e2dc490bacc2529cebbb0462 > Proxy: split configured header names and values. > > Previously, each configured header was represented in one of two ways, > depending on whether or not its value included any variables. > > If the value didn't include any variables, then it would be represented > as as a single script that contained complete header line with HTTP/1.1 > delimiters, i.e.: > > "Header: value\r\n" > > But if the value included any variables, then it would be represented > as a series of three scripts: first contained header name and the ": " > delimiter, second evaluated to header value, and third contained only > "\r\n", i.e.: > > "Header: " > "$value" > "\r\n" > > This commit changes that, so that each configured header is represented > as a series of two scripts: first contains only header name, and second > contains (or evaluates to) only header value, i.e.: > > "Header" > "$value" > > or > > "Header" > "value" > > This not only makes things more consistent, but also allows header name > and value to be accessed separately. > > Signed-off-by: Piotr Sikora As suggested during previous review iteration, it would be interesting to see some benchmarks. Here they are. With 1000 static headers "proxy_set_header X-Foo foo;" the new variant is slightly slower (numbers are in requests per second, higher is better): $ ministat t.current.n t.patched.n x t.current.n + t.patched.n +------------------------------------------------------------------------------+ |+ + + + ++ + + x x x x xx x| | |___________A_____M_____| |_______A__M____| | +------------------------------------------------------------------------------+ N Min Max Median Avg Stddev x 7 793.883 820.497 811.498 807.94229 10.111563 + 8 725.285 770.099 759.39 752.68988 15.026166 Difference at 95.0% confidence -55.2524 +/- 14.5227 -6.83866% +/- 1.7975% (Student's t, pooled s = 12.991) It is considerably faster when using variables though, again with 1000 headers "proxy_set_header X-Foo $request_uri;": $ ministat t.current.vars.n t.patched.vars.n x t.current.vars.n + t.patched.vars.n +------------------------------------------------------------------------------+ | x ++ + | |x xxx x + + ++ + | | |___A__| |______A_M___|| +------------------------------------------------------------------------------+ N Min Max Median Avg Stddev x 8 365.499 415.19 385.856 386.026 14.078621 + 8 605.499 690.492 681.396 671.80087 27.852872 Difference at 95.0% confidence 285.775 +/- 23.6679 74.03% +/- 6.13117% (Student's t, pooled s = 22.068) Given that using variables is much more common, overral the patch looks clearly beneficial. > diff -r 068381014f25 -r 0637acdb51e2 src/http/modules/ngx_http_proxy_module.c > --- a/src/http/modules/ngx_http_proxy_module.c > +++ b/src/http/modules/ngx_http_proxy_module.c > @@ -1151,6 +1151,7 @@ static ngx_int_t > ngx_http_proxy_create_request(ngx_http_request_t *r) > { > size_t len, uri_len, loc_len, body_len; > + size_t key_len, val_len; Style, should be only one type instead: - size_t len, uri_len, loc_len, body_len; - size_t key_len, val_len; + size_t len, uri_len, loc_len, body_len, + key_len, val_len; [...] Committed with the above change, thanks. -- Maxim Dounin http://nginx.org/ From mdounin at mdounin.ru Tue Jul 4 14:28:25 2017 From: mdounin at mdounin.ru (Maxim Dounin) Date: Tue, 4 Jul 2017 17:28:25 +0300 Subject: [PATCH] Enable multiple ssl_stapling_file configuration directives In-Reply-To: <0580b76366e8540973e0.1498958463@elemental-dev.linss.com> References: <0580b76366e8540973e0.1498958463@elemental-dev.linss.com> Message-ID: <20170704142825.GZ55433@mdounin.ru> Hello! On Sat, Jul 01, 2017 at 06:21:03PM -0700, Peter Linss wrote: > # HG changeset patch > # User Peter Linss > # Date 1498957095 25200 > # Sat Jul 01 17:58:15 2017 -0700 > # Node ID 0580b76366e8540973e0ed884d0cec9fc4a7e488 > # Parent a1c6685e80cba59284fc5e500818ea3b871403eb > Enable multiple ssl_stapling_file configuration directives There should be "SSL: " prefix and a dot after the sentence. For more examples, consider looking at "hg log -v". > > When using OCSP stapling files with multiple certificates, > each certificate must have its own ssl_stapling_file. > Changes ssl_stapling_file to store an array, and sets individual > staples per certificate. > Generates an error if ssl_stapling_file is specified but not > the same number of times as certificates. > > diff --git a/src/event/ngx_event_openssl.h b/src/event/ngx_event_openssl.h > --- a/src/event/ngx_event_openssl.h > +++ b/src/event/ngx_event_openssl.h > @@ -154,17 +154,17 @@ ngx_int_t ngx_ssl_certificate(ngx_conf_t > ngx_int_t ngx_ssl_ciphers(ngx_conf_t *cf, ngx_ssl_t *ssl, ngx_str_t *ciphers, > ngx_uint_t prefer_server_ciphers); > ngx_int_t ngx_ssl_client_certificate(ngx_conf_t *cf, ngx_ssl_t *ssl, > ngx_str_t *cert, ngx_int_t depth); > ngx_int_t ngx_ssl_trusted_certificate(ngx_conf_t *cf, ngx_ssl_t *ssl, > ngx_str_t *cert, ngx_int_t depth); > ngx_int_t ngx_ssl_crl(ngx_conf_t *cf, ngx_ssl_t *ssl, ngx_str_t *crl); > ngx_int_t ngx_ssl_stapling(ngx_conf_t *cf, ngx_ssl_t *ssl, > - ngx_str_t *file, ngx_str_t *responder, ngx_uint_t verify); > + ngx_array_t *files, ngx_str_t *responder, ngx_uint_t verify); > ngx_int_t ngx_ssl_stapling_resolver(ngx_conf_t *cf, ngx_ssl_t *ssl, > ngx_resolver_t *resolver, ngx_msec_t resolver_timeout); > RSA *ngx_ssl_rsa512_key_callback(ngx_ssl_conn_t *ssl_conn, int is_export, > int key_length); > ngx_array_t *ngx_ssl_read_password_file(ngx_conf_t *cf, ngx_str_t *file); > ngx_int_t ngx_ssl_dhparam(ngx_conf_t *cf, ngx_ssl_t *ssl, ngx_str_t *file); > ngx_int_t ngx_ssl_ecdh_curve(ngx_conf_t *cf, ngx_ssl_t *ssl, ngx_str_t *name); > ngx_int_t ngx_ssl_session_cache(ngx_ssl_t *ssl, ngx_str_t *sess_ctx, > diff --git a/src/event/ngx_event_openssl_stapling.c b/src/event/ngx_event_openssl_stapling.c > --- a/src/event/ngx_event_openssl_stapling.c > +++ b/src/event/ngx_event_openssl_stapling.c > @@ -120,29 +120,47 @@ static ngx_int_t ngx_ssl_ocsp_parse_stat > static ngx_int_t ngx_ssl_ocsp_process_headers(ngx_ssl_ocsp_ctx_t *ctx); > static ngx_int_t ngx_ssl_ocsp_parse_header_line(ngx_ssl_ocsp_ctx_t *ctx); > static ngx_int_t ngx_ssl_ocsp_process_body(ngx_ssl_ocsp_ctx_t *ctx); > > static u_char *ngx_ssl_ocsp_log_error(ngx_log_t *log, u_char *buf, size_t len); > > > ngx_int_t > -ngx_ssl_stapling(ngx_conf_t *cf, ngx_ssl_t *ssl, ngx_str_t *file, > +ngx_ssl_stapling(ngx_conf_t *cf, ngx_ssl_t *ssl, ngx_array_t *files, > ngx_str_t *responder, ngx_uint_t verify) > { > - X509 *cert; > + X509 *cert; > + ngx_str_t *file; > + ngx_uint_t i; > > - for (cert = SSL_CTX_get_ex_data(ssl->ctx, ngx_ssl_certificate_index); > - cert; > - cert = X509_get_ex_data(cert, ngx_ssl_next_certificate_index)) > + if (files == NULL) > { > - if (ngx_ssl_stapling_certificate(cf, ssl, cert, file, responder, verify) > - != NGX_OK) > + for (cert = SSL_CTX_get_ex_data(ssl->ctx, ngx_ssl_certificate_index); > + cert; > + cert = X509_get_ex_data(cert, ngx_ssl_next_certificate_index)) > { > - return NGX_ERROR; > + if (ngx_ssl_stapling_certificate(cf, ssl, cert, NULL, responder, verify) > + != NGX_OK) > + { > + return NGX_ERROR; > + } > + } > + } else { > + file = files->elts; > + > + for (cert = SSL_CTX_get_ex_data(ssl->ctx, ngx_ssl_certificate_index), i = files->nelts - 1; > + cert; > + cert = X509_get_ex_data(cert, ngx_ssl_next_certificate_index), i--) > + { > + if (ngx_ssl_stapling_certificate(cf, ssl, cert, &file[i], responder, verify) > + != NGX_OK) > + { > + return NGX_ERROR; > + } > } > } This looks overcomplicated and should be rewritten. Instead, consider preserving a single loop over certificates available, and providing appropriate parameters to ngx_ssl_stapling_certificate() inside the loop. > > SSL_CTX_set_tlsext_status_cb(ssl->ctx, ngx_ssl_certificate_status_callback); > > return NGX_OK; > } > > @@ -175,17 +193,17 @@ ngx_ssl_stapling_certificate(ngx_conf_t > > staple->ssl_ctx = ssl->ctx; > staple->timeout = 60000; > staple->verify = verify; > staple->cert = cert; > staple->name = X509_get_ex_data(staple->cert, > ngx_ssl_certificate_name_index); > > - if (file->len) { > + if (file && file->len) { > /* use OCSP response from the file */ > > if (ngx_ssl_stapling_file(cf, ssl, staple, file) != NGX_OK) { > return NGX_ERROR; > } > > return NGX_OK; > } > @@ -1866,17 +1884,17 @@ ngx_ssl_ocsp_log_error(ngx_log_t *log, u > return p; > } > > > #else > > > ngx_int_t > -ngx_ssl_stapling(ngx_conf_t *cf, ngx_ssl_t *ssl, ngx_str_t *file, > +ngx_ssl_stapling(ngx_conf_t *cf, ngx_ssl_t *ssl, ngx_array_t *files, > ngx_str_t *responder, ngx_uint_t verify) > { > ngx_log_error(NGX_LOG_WARN, ssl->log, 0, > "\"ssl_stapling\" ignored, not supported"); > > return NGX_OK; > } > > diff --git a/src/http/modules/ngx_http_ssl_module.c b/src/http/modules/ngx_http_ssl_module.c > --- a/src/http/modules/ngx_http_ssl_module.c > +++ b/src/http/modules/ngx_http_ssl_module.c > @@ -210,19 +210,19 @@ static ngx_command_t ngx_http_ssl_comma > NGX_HTTP_MAIN_CONF|NGX_HTTP_SRV_CONF|NGX_CONF_FLAG, > ngx_conf_set_flag_slot, > NGX_HTTP_SRV_CONF_OFFSET, > offsetof(ngx_http_ssl_srv_conf_t, stapling), > NULL }, > > { ngx_string("ssl_stapling_file"), > NGX_HTTP_MAIN_CONF|NGX_HTTP_SRV_CONF|NGX_CONF_TAKE1, > - ngx_conf_set_str_slot, > + ngx_conf_set_str_array_slot, > NGX_HTTP_SRV_CONF_OFFSET, > - offsetof(ngx_http_ssl_srv_conf_t, stapling_file), > + offsetof(ngx_http_ssl_srv_conf_t, stapling_files), > NULL }, > > { ngx_string("ssl_stapling_responder"), > NGX_HTTP_MAIN_CONF|NGX_HTTP_SRV_CONF|NGX_CONF_TAKE1, > ngx_conf_set_str_slot, > NGX_HTTP_SRV_CONF_OFFSET, > offsetof(ngx_http_ssl_srv_conf_t, stapling_responder), > NULL }, > @@ -532,33 +532,33 @@ ngx_http_ssl_create_srv_conf(ngx_conf_t > * sscf->protocols = 0; > * sscf->dhparam = { 0, NULL }; > * sscf->ecdh_curve = { 0, NULL }; > * sscf->client_certificate = { 0, NULL }; > * sscf->trusted_certificate = { 0, NULL }; > * sscf->crl = { 0, NULL }; > * sscf->ciphers = { 0, NULL }; > * sscf->shm_zone = NULL; > - * sscf->stapling_file = { 0, NULL }; > * sscf->stapling_responder = { 0, NULL }; > */ > > sscf->enable = NGX_CONF_UNSET; > sscf->prefer_server_ciphers = NGX_CONF_UNSET; > sscf->buffer_size = NGX_CONF_UNSET_SIZE; > sscf->verify = NGX_CONF_UNSET_UINT; > sscf->verify_depth = NGX_CONF_UNSET_UINT; > sscf->certificates = NGX_CONF_UNSET_PTR; > sscf->certificate_keys = NGX_CONF_UNSET_PTR; > sscf->passwords = NGX_CONF_UNSET_PTR; > sscf->builtin_session_cache = NGX_CONF_UNSET; > sscf->session_timeout = NGX_CONF_UNSET; > sscf->session_tickets = NGX_CONF_UNSET; > sscf->session_ticket_keys = NGX_CONF_UNSET_PTR; > sscf->stapling = NGX_CONF_UNSET; > + sscf->stapling_files = NGX_CONF_UNSET_PTR; > sscf->stapling_verify = NGX_CONF_UNSET; > > return sscf; > } > > > static char * > ngx_http_ssl_merge_srv_conf(ngx_conf_t *cf, void *parent, void *child) > @@ -611,17 +611,17 @@ ngx_http_ssl_merge_srv_conf(ngx_conf_t * > > ngx_conf_merge_str_value(conf->ecdh_curve, prev->ecdh_curve, > NGX_DEFAULT_ECDH_CURVE); > > ngx_conf_merge_str_value(conf->ciphers, prev->ciphers, NGX_DEFAULT_CIPHERS); > > ngx_conf_merge_value(conf->stapling, prev->stapling, 0); > ngx_conf_merge_value(conf->stapling_verify, prev->stapling_verify, 0); > - ngx_conf_merge_str_value(conf->stapling_file, prev->stapling_file, ""); > + ngx_conf_merge_ptr_value(conf->stapling_files, prev->stapling_files, NULL); > ngx_conf_merge_str_value(conf->stapling_responder, > prev->stapling_responder, ""); > > conf->ssl.log = cf->log; > > if (conf->enable) { > > if (conf->certificates == NULL) { > @@ -662,16 +662,28 @@ ngx_http_ssl_merge_srv_conf(ngx_conf_t * > { > ngx_log_error(NGX_LOG_EMERG, cf->log, 0, > "no \"ssl_certificate_key\" is defined " > "for certificate \"%V\"", > ((ngx_str_t *) conf->certificates->elts) > + conf->certificates->nelts - 1); > return NGX_CONF_ERROR; > } > + > + if ((conf->stapling_files) && > + (conf->stapling_files->nelts != conf->certificates->nelts)) > + { > + ngx_log_error(NGX_LOG_EMERG, cf->log, 0, > + "no \"ssl_stapling_file\" is defined " > + "for certificate \"%V\"", > + ((ngx_str_t *) conf->certificates->elts) > + + conf->certificates->nelts - 1); > + return NGX_CONF_ERROR; Certainly an error here is too restrictive, I would rather recommend preserving the current behaviour (or may be emitting a warning instead). > + } > + > } Style, there should be no empty line here. > > if (ngx_ssl_create(&conf->ssl, conf->protocols, conf) != NGX_OK) { > return NGX_CONF_ERROR; > } > > #ifdef SSL_CTRL_SET_TLSEXT_HOSTNAME > > @@ -786,17 +798,17 @@ ngx_http_ssl_merge_srv_conf(ngx_conf_t * > if (ngx_ssl_session_ticket_keys(cf, &conf->ssl, conf->session_ticket_keys) > != NGX_OK) > { > return NGX_CONF_ERROR; > } > > if (conf->stapling) { > > - if (ngx_ssl_stapling(cf, &conf->ssl, &conf->stapling_file, > + if (ngx_ssl_stapling(cf, &conf->ssl, conf->stapling_files, > &conf->stapling_responder, conf->stapling_verify) > != NGX_OK) > { > return NGX_CONF_ERROR; > } > > } > > diff --git a/src/http/modules/ngx_http_ssl_module.h b/src/http/modules/ngx_http_ssl_module.h > --- a/src/http/modules/ngx_http_ssl_module.h > +++ b/src/http/modules/ngx_http_ssl_module.h > @@ -47,17 +47,17 @@ typedef struct { > > ngx_shm_zone_t *shm_zone; > > ngx_flag_t session_tickets; > ngx_array_t *session_ticket_keys; > > ngx_flag_t stapling; > ngx_flag_t stapling_verify; > - ngx_str_t stapling_file; > + ngx_array_t *stapling_files; > ngx_str_t stapling_responder; > > u_char *file; > ngx_uint_t line; > } ngx_http_ssl_srv_conf_t; > > > extern ngx_module_t ngx_http_ssl_module; > _______________________________________________ > nginx-devel mailing list > nginx-devel at nginx.org > http://mailman.nginx.org/mailman/listinfo/nginx-devel -- Maxim Dounin http://nginx.org/ From mdounin at mdounin.ru Tue Jul 4 14:41:44 2017 From: mdounin at mdounin.ru (Maxim Dounin) Date: Tue, 4 Jul 2017 17:41:44 +0300 Subject: Fwd: Patch. Add new directive '2square' for image_filter In-Reply-To: References: Message-ID: <20170704144144.GA55433@mdounin.ru> Hello! On Wed, Jun 28, 2017 at 11:33:05PM +0300, ???? ?????? wrote: > Add new directive '2square' to image_filter, which resizes and converts > image in square and add white border. It's cood be usefull for convert > image for facebook banners. > > In attach: > nginx.patch - patch for main repo (http://hg.nginx.org/nginx), > image_filter_2square.t - file with tests for (http://hg.nginx.org/nginx- > tests) > nginx_org.patch - docs for (http://hg.nginx.org/nginx.org/) Thanks you for your patches. Could you please clarify how this functionality is expected to be used? >From the description and the code it looks very specific for a particular use case, and it might be a good idea to introduce something more generic instead and/or use existing functions combined with HTML rendering to achieve the same effect. -- Maxim Dounin http://nginx.org/ From arut at nginx.com Tue Jul 4 15:26:23 2017 From: arut at nginx.com (Roman Arutyunyan) Date: Tue, 04 Jul 2017 15:26:23 +0000 Subject: [nginx] Resolver: fixed possible use-after-free while resolving SRV. Message-ID: details: http://hg.nginx.org/nginx/rev/80224192163c branches: changeset: 7048:80224192163c user: Roman Arutyunyan date: Tue Jul 04 18:07:29 2017 +0300 description: Resolver: fixed possible use-after-free while resolving SRV. Resolving an SRV record includes resolving its host names in subrequests. Previously, if memory allocation failed while reporting a subrequest result after receiving a response from a DNS server, the SRV resolve handler was called immediately with the NGX_ERROR state. However, if the SRV record included another copy of the resolved name, it was reported once again. This could trigger the use-after-free memory access after SRV resolve handler freed the resolve context by calling ngx_resolve_name_done(). Now the SRV resolve handler is called only when all its subrequests are completed. diffstat: src/core/ngx_resolver.c | 38 +++++++++++++++++++------------------- 1 files changed, 19 insertions(+), 19 deletions(-) diffs (76 lines): diff -r 3fef8c5caa75 -r 80224192163c src/core/ngx_resolver.c --- a/src/core/ngx_resolver.c Wed Mar 15 15:55:35 2017 -0700 +++ b/src/core/ngx_resolver.c Tue Jul 04 18:07:29 2017 +0300 @@ -3034,25 +3034,15 @@ ngx_resolver_srv_names_handler(ngx_resol addrs = ngx_resolver_calloc(r, cctx->naddrs * sizeof(ngx_addr_t)); if (addrs == NULL) { - ngx_resolve_name_done(cctx); - - ctx->state = NGX_ERROR; - ctx->valid = ngx_time() + (r->valid ? r->valid : 10); - - ctx->handler(ctx); - return; + srv->state = NGX_ERROR; + goto done; } sockaddr = ngx_resolver_alloc(r, cctx->naddrs * sizeof(ngx_sockaddr_t)); if (sockaddr == NULL) { ngx_resolver_free(r, addrs); - ngx_resolve_name_done(cctx); - - ctx->state = NGX_ERROR; - ctx->valid = ngx_time() + (r->valid ? r->valid : 10); - - ctx->handler(ctx); - return; + srv->state = NGX_ERROR; + goto done; } for (i = 0; i < cctx->naddrs; i++) { @@ -3069,6 +3059,8 @@ ngx_resolver_srv_names_handler(ngx_resol srv->naddrs = cctx->naddrs; } +done: + ngx_resolve_name_done(cctx); if (ctx->count == 0) { @@ -4254,10 +4246,21 @@ ngx_resolver_report_srv(ngx_resolver_t * ngx_resolver_addr_t *addrs; ngx_resolver_srv_name_t *srvs; + srvs = ctx->srvs; + nsrvs = ctx->nsrvs; + naddrs = 0; - for (i = 0; i < ctx->nsrvs; i++) { - naddrs += ctx->srvs[i].naddrs; + for (i = 0; i < nsrvs; i++) { + if (srvs[i].state == NGX_ERROR) { + ctx->state = NGX_ERROR; + ctx->valid = ngx_time() + (r->valid ? r->valid : 10); + + ctx->handler(ctx); + return; + } + + naddrs += srvs[i].naddrs; } if (naddrs == 0) { @@ -4277,9 +4280,6 @@ ngx_resolver_report_srv(ngx_resolver_t * return; } - srvs = ctx->srvs; - nsrvs = ctx->nsrvs; - i = 0; n = 0; From ru at nginx.com Tue Jul 4 15:37:06 2017 From: ru at nginx.com (Ruslan Ermilov) Date: Tue, 04 Jul 2017 15:37:06 +0000 Subject: [nginx] Slab: style. Message-ID: details: http://hg.nginx.org/nginx/rev/94f30939545a branches: changeset: 7049:94f30939545a user: Ruslan Ermilov date: Tue Jul 04 18:32:28 2017 +0300 description: Slab: style. diffstat: src/core/ngx_slab.c | 20 ++++++++++---------- 1 files changed, 10 insertions(+), 10 deletions(-) diffs (79 lines): diff -r 80224192163c -r 94f30939545a src/core/ngx_slab.c --- a/src/core/ngx_slab.c Tue Jul 04 18:07:29 2017 +0300 +++ b/src/core/ngx_slab.c Tue Jul 04 18:32:28 2017 +0300 @@ -181,8 +181,8 @@ void * ngx_slab_alloc_locked(ngx_slab_pool_t *pool, size_t size) { size_t s; - uintptr_t p, n, m, mask, *bitmap; - ngx_uint_t i, slot, shift, map; + uintptr_t p, m, mask, *bitmap; + ngx_uint_t i, n, slot, shift, map; ngx_slab_page_t *page, *prev, *slots; if (size > ngx_slab_max_size) { @@ -226,7 +226,7 @@ ngx_slab_alloc_locked(ngx_slab_pool_t *p bitmap = (uintptr_t *) ngx_slab_page_addr(pool, page); - map = (ngx_pagesize >> shift) / (sizeof(uintptr_t) * 8); + map = (ngx_pagesize >> shift) / (8 * sizeof(uintptr_t)); for (n = 0; n < map; n++) { @@ -239,7 +239,7 @@ ngx_slab_alloc_locked(ngx_slab_pool_t *p bitmap[n] |= m; - i = (n * sizeof(uintptr_t) * 8 + i) << shift; + i = (n * 8 * sizeof(uintptr_t) + i) << shift; p = (uintptr_t) bitmap + i; @@ -341,7 +341,7 @@ ngx_slab_alloc_locked(ngx_slab_pool_t *p /* "n" elements for bitmap, plus one requested */ bitmap[0] = ((uintptr_t) 2 << n) - 1; - map = (ngx_pagesize >> shift) / (sizeof(uintptr_t) * 8); + map = (ngx_pagesize >> shift) / (8 * sizeof(uintptr_t)); for (i = 1; i < map; i++) { bitmap[i] = 0; @@ -369,7 +369,7 @@ ngx_slab_alloc_locked(ngx_slab_pool_t *p slots[slot].next = page; - pool->stats[slot].total += sizeof(uintptr_t) * 8; + pool->stats[slot].total += 8 * sizeof(uintptr_t); p = ngx_slab_page_addr(pool, page); @@ -480,8 +480,8 @@ ngx_slab_free_locked(ngx_slab_pool_t *po } n = ((uintptr_t) p & (ngx_pagesize - 1)) >> shift; - m = (uintptr_t) 1 << (n % (sizeof(uintptr_t) * 8)); - n /= sizeof(uintptr_t) * 8; + m = (uintptr_t) 1 << (n % (8 * sizeof(uintptr_t))); + n /= 8 * sizeof(uintptr_t); bitmap = (uintptr_t *) ((uintptr_t) p & ~((uintptr_t) ngx_pagesize - 1)); @@ -510,7 +510,7 @@ ngx_slab_free_locked(ngx_slab_pool_t *po goto done; } - map = (ngx_pagesize >> shift) / (sizeof(uintptr_t) * 8); + map = (ngx_pagesize >> shift) / (8 * sizeof(uintptr_t)); for (i = 1; i < map; i++) { if (bitmap[i]) { @@ -558,7 +558,7 @@ ngx_slab_free_locked(ngx_slab_pool_t *po ngx_slab_free_pages(pool, page, 1); - pool->stats[slot].total -= sizeof(uintptr_t) * 8; + pool->stats[slot].total -= 8 * sizeof(uintptr_t); goto done; } From ru at nginx.com Tue Jul 4 15:37:09 2017 From: ru at nginx.com (Ruslan Ermilov) Date: Tue, 04 Jul 2017 15:37:09 +0000 Subject: [nginx] Slab: fixed small allocations on systems with large pagesize. Message-ID: details: http://hg.nginx.org/nginx/rev/8c5e3cc21332 branches: changeset: 7050:8c5e3cc21332 user: Ruslan Ermilov date: Tue Jul 04 18:32:30 2017 +0300 description: Slab: fixed small allocations on systems with large pagesize. Notably, on ppc64 with 64k pagesize, slab 0 (of size 8) requires 128 64-bit elements for bitmasks. The code bogusly assumed that one uintptr_t is enough for bitmasks plus at least one free slot. diffstat: src/core/ngx_slab.c | 17 +++++++++++++---- 1 files changed, 13 insertions(+), 4 deletions(-) diffs (42 lines): diff -r 94f30939545a -r 8c5e3cc21332 src/core/ngx_slab.c --- a/src/core/ngx_slab.c Tue Jul 04 18:32:28 2017 +0300 +++ b/src/core/ngx_slab.c Tue Jul 04 18:32:30 2017 +0300 @@ -339,11 +339,17 @@ ngx_slab_alloc_locked(ngx_slab_pool_t *p } /* "n" elements for bitmap, plus one requested */ - bitmap[0] = ((uintptr_t) 2 << n) - 1; + + for (i = 0; i < (n + 1) / (8 * sizeof(uintptr_t)); i++) { + bitmap[i] = NGX_SLAB_BUSY; + } + + m = ((uintptr_t) 1 << ((n + 1) % (8 * sizeof(uintptr_t)))) - 1; + bitmap[i] = m; map = (ngx_pagesize >> shift) / (8 * sizeof(uintptr_t)); - for (i = 1; i < map; i++) { + for (i = i + 1; i < map; i++) { bitmap[i] = 0; } @@ -506,13 +512,16 @@ ngx_slab_free_locked(ngx_slab_pool_t *po n = 1; } - if (bitmap[0] & ~(((uintptr_t) 1 << n) - 1)) { + i = n / (8 * sizeof(uintptr_t)); + m = ((uintptr_t) 1 << (n % (8 * sizeof(uintptr_t)))) - 1; + + if (bitmap[i] & ~m) { goto done; } map = (ngx_pagesize >> shift) / (8 * sizeof(uintptr_t)); - for (i = 1; i < map; i++) { + for (i = i + 1; i < map; i++) { if (bitmap[i]) { goto done; } From mdounin at mdounin.ru Tue Jul 4 16:48:23 2017 From: mdounin at mdounin.ru (Maxim Dounin) Date: Tue, 4 Jul 2017 19:48:23 +0300 Subject: [PATCH 10 of 14] Proxy: always emit "Host" header first In-Reply-To: <068381014f256ad6e2dc.1498163594@piotrsikora.sfo.corp.google.com> References: <5f5d70428655db0889a2.1498163585@piotrsikora.sfo.corp.google.com> <068381014f256ad6e2dc.1498163594@piotrsikora.sfo.corp.google.com> Message-ID: <20170704164822.GC55433@mdounin.ru> Hello! On Thu, Jun 22, 2017 at 01:33:14PM -0700, Piotr Sikora via nginx-devel wrote: > # HG changeset patch > # User Piotr Sikora > # Date 1489618489 25200 > # Wed Mar 15 15:54:49 2017 -0700 > # Node ID 068381014f256ad6e2dc490bacc2529cebbb0462 > # Parent 96075d4cd2a6e8bd67caf1d7b78f8e87d757c48d > Proxy: always emit "Host" header first. > > Signed-off-by: Piotr Sikora > > diff -r 96075d4cd2a6 -r 068381014f25 src/http/modules/ngx_http_proxy_module.c > --- a/src/http/modules/ngx_http_proxy_module.c > +++ b/src/http/modules/ngx_http_proxy_module.c > @@ -3422,7 +3422,7 @@ ngx_http_proxy_init_headers(ngx_conf_t * > uintptr_t *code; > ngx_uint_t i; > ngx_array_t headers_names, headers_merged; > - ngx_keyval_t *src, *s, *h; > + ngx_keyval_t *host, *src, *s, *h; > ngx_hash_key_t *hk; > ngx_hash_init_t hash; > ngx_http_script_compile_t sc; > @@ -3454,11 +3454,33 @@ ngx_http_proxy_init_headers(ngx_conf_t * > return NGX_ERROR; > } > > + h = default_headers; > + > + if (h->key.len != sizeof("Host") - 1 > + || ngx_strcasecmp(h->key.data, (u_char *) "Host") != 0) > + { > + return NGX_ERROR; > + } > + > + host = ngx_array_push(&headers_merged); > + if (host == NULL) { > + return NGX_ERROR; > + } > + > + *host = *h++; > + > if (conf->headers_source) { > > src = conf->headers_source->elts; > for (i = 0; i < conf->headers_source->nelts; i++) { > > + if (src[i].key.len == sizeof("Host") - 1 > + && ngx_strcasecmp(src[i].key.data, (u_char *) "Host") == 0) > + { > + *host = src[i]; > + continue; > + } > + > s = ngx_array_push(&headers_merged); > if (s == NULL) { > return NGX_ERROR; > @@ -3468,8 +3490,6 @@ ngx_http_proxy_init_headers(ngx_conf_t * > } > } > > - h = default_headers; > - > while (h->key.len) { > > src = headers_merged.elts; As already outlined in the review here: http://mailman.nginx.org/pipermail/nginx-devel/2017-June/010087.html the approach taken looks very fragile. There should be a better way to do this. -- Maxim Dounin http://nginx.org/ From ru at nginx.com Tue Jul 4 16:52:29 2017 From: ru at nginx.com (Ruslan Ermilov) Date: Tue, 04 Jul 2017 16:52:29 +0000 Subject: [nginx] Resolver: factored out setting a timer for resolver timeout. Message-ID: details: http://hg.nginx.org/nginx/rev/137c5be7df09 branches: changeset: 7051:137c5be7df09 user: Sergey Kandaurov date: Tue Jul 04 18:46:30 2017 +0300 description: Resolver: factored out setting a timer for resolver timeout. No functional changes. diffstat: src/core/ngx_resolver.c | 83 +++++++++++++++++++----------------------------- 1 files changed, 33 insertions(+), 50 deletions(-) diffs (128 lines): diff -r 8c5e3cc21332 -r 137c5be7df09 src/core/ngx_resolver.c --- a/src/core/ngx_resolver.c Tue Jul 04 18:32:30 2017 +0300 +++ b/src/core/ngx_resolver.c Tue Jul 04 18:46:30 2017 +0300 @@ -105,6 +105,8 @@ static void ngx_resolver_rbtree_insert_v ngx_rbtree_node_t *node, ngx_rbtree_node_t *sentinel); static ngx_int_t ngx_resolver_copy(ngx_resolver_t *r, ngx_str_t *name, u_char *buf, u_char *src, u_char *last); +static ngx_int_t ngx_resolver_set_timeout(ngx_resolver_t *r, + ngx_resolver_ctx_t *ctx); static void ngx_resolver_timeout_handler(ngx_event_t *ev); static void ngx_resolver_free_node(ngx_resolver_t *r, ngx_resolver_node_t *rn); static void *ngx_resolver_alloc(ngx_resolver_t *r, size_t size); @@ -728,19 +730,8 @@ ngx_resolve_name_locked(ngx_resolver_t * } if (rn->waiting) { - - if (ctx->event == NULL && ctx->timeout) { - ctx->event = ngx_resolver_calloc(r, sizeof(ngx_event_t)); - if (ctx->event == NULL) { - return NGX_ERROR; - } - - ctx->event->handler = ngx_resolver_timeout_handler; - ctx->event->data = ctx; - ctx->event->log = r->log; - ctx->ident = -1; - - ngx_add_timer(ctx->event, ctx->timeout); + if (ngx_resolver_set_timeout(r, ctx) != NGX_OK) { + return NGX_ERROR; } last->next = rn->waiting; @@ -864,18 +855,8 @@ ngx_resolve_name_locked(ngx_resolver_t * goto failed; } - if (ctx->event == NULL && ctx->timeout) { - ctx->event = ngx_resolver_calloc(r, sizeof(ngx_event_t)); - if (ctx->event == NULL) { - goto failed; - } - - ctx->event->handler = ngx_resolver_timeout_handler; - ctx->event->data = ctx; - ctx->event->log = r->log; - ctx->ident = -1; - - ngx_add_timer(ctx->event, ctx->timeout); + if (ngx_resolver_set_timeout(r, ctx) != NGX_OK) { + goto failed; } if (ngx_resolver_resend_empty(r)) { @@ -1007,19 +988,8 @@ ngx_resolve_addr(ngx_resolver_ctx_t *ctx } if (rn->waiting) { - - if (ctx->event == NULL && ctx->timeout) { - ctx->event = ngx_resolver_calloc(r, sizeof(ngx_event_t)); - if (ctx->event == NULL) { - return NGX_ERROR; - } - - ctx->event->handler = ngx_resolver_timeout_handler; - ctx->event->data = ctx; - ctx->event->log = r->log; - ctx->ident = -1; - - ngx_add_timer(ctx->event, ctx->timeout); + if (ngx_resolver_set_timeout(r, ctx) != NGX_OK) { + return NGX_ERROR; } ctx->next = rn->waiting; @@ -1089,18 +1059,8 @@ ngx_resolve_addr(ngx_resolver_ctx_t *ctx goto failed; } - if (ctx->event == NULL && ctx->timeout) { - ctx->event = ngx_resolver_calloc(r, sizeof(ngx_event_t)); - if (ctx->event == NULL) { - goto failed; - } - - ctx->event->handler = ngx_resolver_timeout_handler; - ctx->event->data = ctx; - ctx->event->log = r->log; - ctx->ident = -1; - - ngx_add_timer(ctx->event, ctx->timeout); + if (ngx_resolver_set_timeout(r, ctx) != NGX_OK) { + goto failed; } if (ngx_resolver_resend_empty(r)) { @@ -4033,6 +3993,29 @@ done: } +static ngx_int_t +ngx_resolver_set_timeout(ngx_resolver_t *r, ngx_resolver_ctx_t *ctx) +{ + if (ctx->event || ctx->timeout == 0) { + return NGX_OK; + } + + ctx->event = ngx_resolver_calloc(r, sizeof(ngx_event_t)); + if (ctx->event == NULL) { + return NGX_ERROR; + } + + ctx->event->handler = ngx_resolver_timeout_handler; + ctx->event->data = ctx; + ctx->event->log = r->log; + ctx->ident = -1; + + ngx_add_timer(ctx->event, ctx->timeout); + + return NGX_OK; +} + + static void ngx_resolver_timeout_handler(ngx_event_t *ev) { From ru at nginx.com Tue Jul 4 16:52:32 2017 From: ru at nginx.com (Ruslan Ermilov) Date: Tue, 04 Jul 2017 16:52:32 +0000 Subject: [nginx] Resolver: cancelable resend timer event. Message-ID: details: http://hg.nginx.org/nginx/rev/70e65bf8dfd7 branches: changeset: 7052:70e65bf8dfd7 user: Ruslan Ermilov date: Tue Jul 04 18:50:41 2017 +0300 description: Resolver: cancelable resend timer event. It is safe because re-sending still works during graceful shutdown as long as resolving takes place (and resolve tasks set their own timeouts that are not cancelable). Also, the new ctx->cancelable flag can be set to make resolve task's timeout event cancelable. diffstat: src/core/ngx_resolver.c | 2 ++ src/core/ngx_resolver.h | 1 + 2 files changed, 3 insertions(+), 0 deletions(-) diffs (30 lines): diff -r 137c5be7df09 -r 70e65bf8dfd7 src/core/ngx_resolver.c --- a/src/core/ngx_resolver.c Tue Jul 04 18:46:30 2017 +0300 +++ b/src/core/ngx_resolver.c Tue Jul 04 18:50:41 2017 +0300 @@ -191,6 +191,7 @@ ngx_resolver_create(ngx_conf_t *cf, ngx_ r->event->handler = ngx_resolver_resend_handler; r->event->data = r; r->event->log = &cf->cycle->new_log; + r->event->cancelable = 1; r->ident = -1; r->resend_timeout = 5; @@ -4008,6 +4009,7 @@ ngx_resolver_set_timeout(ngx_resolver_t ctx->event->handler = ngx_resolver_timeout_handler; ctx->event->data = ctx; ctx->event->log = r->log; + ctx->event->cancelable = ctx->cancelable; ctx->ident = -1; ngx_add_timer(ctx->event, ctx->timeout); diff -r 137c5be7df09 -r 70e65bf8dfd7 src/core/ngx_resolver.h --- a/src/core/ngx_resolver.h Tue Jul 04 18:46:30 2017 +0300 +++ b/src/core/ngx_resolver.h Tue Jul 04 18:50:41 2017 +0300 @@ -220,6 +220,7 @@ struct ngx_resolver_ctx_s { unsigned quick:1; unsigned async:1; + unsigned cancelable:1; ngx_uint_t recursion; ngx_event_t *event; }; From peter at linss.com Tue Jul 4 18:51:10 2017 From: peter at linss.com (Peter Linss) Date: Tue, 4 Jul 2017 11:51:10 -0700 Subject: [PATCH] Enable multiple ssl_stapling_file configuration directives In-Reply-To: <20170704142825.GZ55433@mdounin.ru> References: <0580b76366e8540973e0.1498958463@elemental-dev.linss.com> <20170704142825.GZ55433@mdounin.ru> Message-ID: <12BFC85A-4C6D-40D6-96B5-15DFE2C21363@linss.com> > On Jul 4, 2017, at 7:28 AM, Maxim Dounin wrote: > > Hello! > > On Sat, Jul 01, 2017 at 06:21:03PM -0700, Peter Linss wrote: > >> # HG changeset patch >> # User Peter Linss > >> # Date 1498957095 25200 >> # Sat Jul 01 17:58:15 2017 -0700 >> # Node ID 0580b76366e8540973e0ed884d0cec9fc4a7e488 >> # Parent a1c6685e80cba59284fc5e500818ea3b871403eb >> Enable multiple ssl_stapling_file configuration directives > > There should be "SSL: " prefix and a dot after the sentence. For > more examples, consider looking at "hg log -v?. Ok, will do. > >> >> When using OCSP stapling files with multiple certificates, >> each certificate must have its own ssl_stapling_file. >> Changes ssl_stapling_file to store an array, and sets individual >> staples per certificate. >> Generates an error if ssl_stapling_file is specified but not >> the same number of times as certificates. >> >> diff --git a/src/event/ngx_event_openssl.h b/src/event/ngx_event_openssl.h >> --- a/src/event/ngx_event_openssl.h >> +++ b/src/event/ngx_event_openssl.h >> @@ -154,17 +154,17 @@ ngx_int_t ngx_ssl_certificate(ngx_conf_t >> ngx_int_t ngx_ssl_ciphers(ngx_conf_t *cf, ngx_ssl_t *ssl, ngx_str_t *ciphers, >> ngx_uint_t prefer_server_ciphers); >> ngx_int_t ngx_ssl_client_certificate(ngx_conf_t *cf, ngx_ssl_t *ssl, >> ngx_str_t *cert, ngx_int_t depth); >> ngx_int_t ngx_ssl_trusted_certificate(ngx_conf_t *cf, ngx_ssl_t *ssl, >> ngx_str_t *cert, ngx_int_t depth); >> ngx_int_t ngx_ssl_crl(ngx_conf_t *cf, ngx_ssl_t *ssl, ngx_str_t *crl); >> ngx_int_t ngx_ssl_stapling(ngx_conf_t *cf, ngx_ssl_t *ssl, >> - ngx_str_t *file, ngx_str_t *responder, ngx_uint_t verify); >> + ngx_array_t *files, ngx_str_t *responder, ngx_uint_t verify); >> ngx_int_t ngx_ssl_stapling_resolver(ngx_conf_t *cf, ngx_ssl_t *ssl, >> ngx_resolver_t *resolver, ngx_msec_t resolver_timeout); >> RSA *ngx_ssl_rsa512_key_callback(ngx_ssl_conn_t *ssl_conn, int is_export, >> int key_length); >> ngx_array_t *ngx_ssl_read_password_file(ngx_conf_t *cf, ngx_str_t *file); >> ngx_int_t ngx_ssl_dhparam(ngx_conf_t *cf, ngx_ssl_t *ssl, ngx_str_t *file); >> ngx_int_t ngx_ssl_ecdh_curve(ngx_conf_t *cf, ngx_ssl_t *ssl, ngx_str_t *name); >> ngx_int_t ngx_ssl_session_cache(ngx_ssl_t *ssl, ngx_str_t *sess_ctx, >> diff --git a/src/event/ngx_event_openssl_stapling.c b/src/event/ngx_event_openssl_stapling.c >> --- a/src/event/ngx_event_openssl_stapling.c >> +++ b/src/event/ngx_event_openssl_stapling.c >> @@ -120,29 +120,47 @@ static ngx_int_t ngx_ssl_ocsp_parse_stat >> static ngx_int_t ngx_ssl_ocsp_process_headers(ngx_ssl_ocsp_ctx_t *ctx); >> static ngx_int_t ngx_ssl_ocsp_parse_header_line(ngx_ssl_ocsp_ctx_t *ctx); >> static ngx_int_t ngx_ssl_ocsp_process_body(ngx_ssl_ocsp_ctx_t *ctx); >> >> static u_char *ngx_ssl_ocsp_log_error(ngx_log_t *log, u_char *buf, size_t len); >> >> >> ngx_int_t >> -ngx_ssl_stapling(ngx_conf_t *cf, ngx_ssl_t *ssl, ngx_str_t *file, >> +ngx_ssl_stapling(ngx_conf_t *cf, ngx_ssl_t *ssl, ngx_array_t *files, >> ngx_str_t *responder, ngx_uint_t verify) >> { >> - X509 *cert; >> + X509 *cert; >> + ngx_str_t *file; >> + ngx_uint_t i; >> >> - for (cert = SSL_CTX_get_ex_data(ssl->ctx, ngx_ssl_certificate_index); >> - cert; >> - cert = X509_get_ex_data(cert, ngx_ssl_next_certificate_index)) >> + if (files == NULL) >> { >> - if (ngx_ssl_stapling_certificate(cf, ssl, cert, file, responder, verify) >> - != NGX_OK) >> + for (cert = SSL_CTX_get_ex_data(ssl->ctx, ngx_ssl_certificate_index); >> + cert; >> + cert = X509_get_ex_data(cert, ngx_ssl_next_certificate_index)) >> { >> - return NGX_ERROR; >> + if (ngx_ssl_stapling_certificate(cf, ssl, cert, NULL, responder, verify) >> + != NGX_OK) >> + { >> + return NGX_ERROR; >> + } >> + } >> + } else { >> + file = files->elts; >> + >> + for (cert = SSL_CTX_get_ex_data(ssl->ctx, ngx_ssl_certificate_index), i = files->nelts - 1; >> + cert; >> + cert = X509_get_ex_data(cert, ngx_ssl_next_certificate_index), i--) >> + { >> + if (ngx_ssl_stapling_certificate(cf, ssl, cert, &file[i], responder, verify) >> + != NGX_OK) >> + { >> + return NGX_ERROR; >> + } >> } >> } > > This looks overcomplicated and should be rewritten. Instead, > consider preserving a single loop over certificates available, and > providing appropriate parameters to ngx_ssl_stapling_certificate() > inside the loop. Will do. I wasn?t happy this this myself, but was trying to match existing code style as much as possible in the use of the files array. Doing this in a single loop my default approach would be to use a conditional operator to handle the file parameter, but given that files can be NULL it gets a bit ugly without the additional setup. Do you prefer this approach? (untested at this point, but will test before resubmitting, just checking style) ngx_int_t ngx_ssl_stapling(ngx_conf_t *cf, ngx_ssl_t *ssl, ngx_array_t *files, ngx_str_t *responder, ngx_uint_t verify) { X509 *cert; ngx_uint_t i; for (cert = SSL_CTX_get_ex_data(ssl->ctx, ngx_ssl_certificate_index, i = 1); cert; cert = X509_get_ex_data(cert, ngx_ssl_next_certificate_index), i++) { if (ngx_ssl_stapling_certificate(cf, ssl, cert, files ? &(files->elts[files->nelts - i]) : NULL, responder, verify) != NGX_OK) { return NGX_ERROR; } } SSL_CTX_set_tlsext_status_cb(ssl->ctx, ngx_ssl_certificate_status_callback); return NGX_OK; } Also, matching the staple file to the certificate based on the certificate order feels a bit fragile to me. Have a suggestion for a more robust approach? Or is the certificate order stable enough? (Nothing obvious jumped out at me without changing a bunch of other setup logic and I wanted to keep the impact of this change minimal.) > >> >> SSL_CTX_set_tlsext_status_cb(ssl->ctx, ngx_ssl_certificate_status_callback); >> >> return NGX_OK; >> } >> >> @@ -175,17 +193,17 @@ ngx_ssl_stapling_certificate(ngx_conf_t >> >> staple->ssl_ctx = ssl->ctx; >> staple->timeout = 60000; >> staple->verify = verify; >> staple->cert = cert; >> staple->name = X509_get_ex_data(staple->cert, >> ngx_ssl_certificate_name_index); >> >> - if (file->len) { >> + if (file && file->len) { >> /* use OCSP response from the file */ >> >> if (ngx_ssl_stapling_file(cf, ssl, staple, file) != NGX_OK) { >> return NGX_ERROR; >> } >> >> return NGX_OK; >> } >> @@ -1866,17 +1884,17 @@ ngx_ssl_ocsp_log_error(ngx_log_t *log, u >> return p; >> } >> >> >> #else >> >> >> ngx_int_t >> -ngx_ssl_stapling(ngx_conf_t *cf, ngx_ssl_t *ssl, ngx_str_t *file, >> +ngx_ssl_stapling(ngx_conf_t *cf, ngx_ssl_t *ssl, ngx_array_t *files, >> ngx_str_t *responder, ngx_uint_t verify) >> { >> ngx_log_error(NGX_LOG_WARN, ssl->log, 0, >> "\"ssl_stapling\" ignored, not supported"); >> >> return NGX_OK; >> } >> >> diff --git a/src/http/modules/ngx_http_ssl_module.c b/src/http/modules/ngx_http_ssl_module.c >> --- a/src/http/modules/ngx_http_ssl_module.c >> +++ b/src/http/modules/ngx_http_ssl_module.c >> @@ -210,19 +210,19 @@ static ngx_command_t ngx_http_ssl_comma >> NGX_HTTP_MAIN_CONF|NGX_HTTP_SRV_CONF|NGX_CONF_FLAG, >> ngx_conf_set_flag_slot, >> NGX_HTTP_SRV_CONF_OFFSET, >> offsetof(ngx_http_ssl_srv_conf_t, stapling), >> NULL }, >> >> { ngx_string("ssl_stapling_file"), >> NGX_HTTP_MAIN_CONF|NGX_HTTP_SRV_CONF|NGX_CONF_TAKE1, >> - ngx_conf_set_str_slot, >> + ngx_conf_set_str_array_slot, >> NGX_HTTP_SRV_CONF_OFFSET, >> - offsetof(ngx_http_ssl_srv_conf_t, stapling_file), >> + offsetof(ngx_http_ssl_srv_conf_t, stapling_files), >> NULL }, >> >> { ngx_string("ssl_stapling_responder"), >> NGX_HTTP_MAIN_CONF|NGX_HTTP_SRV_CONF|NGX_CONF_TAKE1, >> ngx_conf_set_str_slot, >> NGX_HTTP_SRV_CONF_OFFSET, >> offsetof(ngx_http_ssl_srv_conf_t, stapling_responder), >> NULL }, >> @@ -532,33 +532,33 @@ ngx_http_ssl_create_srv_conf(ngx_conf_t >> * sscf->protocols = 0; >> * sscf->dhparam = { 0, NULL }; >> * sscf->ecdh_curve = { 0, NULL }; >> * sscf->client_certificate = { 0, NULL }; >> * sscf->trusted_certificate = { 0, NULL }; >> * sscf->crl = { 0, NULL }; >> * sscf->ciphers = { 0, NULL }; >> * sscf->shm_zone = NULL; >> - * sscf->stapling_file = { 0, NULL }; >> * sscf->stapling_responder = { 0, NULL }; >> */ >> >> sscf->enable = NGX_CONF_UNSET; >> sscf->prefer_server_ciphers = NGX_CONF_UNSET; >> sscf->buffer_size = NGX_CONF_UNSET_SIZE; >> sscf->verify = NGX_CONF_UNSET_UINT; >> sscf->verify_depth = NGX_CONF_UNSET_UINT; >> sscf->certificates = NGX_CONF_UNSET_PTR; >> sscf->certificate_keys = NGX_CONF_UNSET_PTR; >> sscf->passwords = NGX_CONF_UNSET_PTR; >> sscf->builtin_session_cache = NGX_CONF_UNSET; >> sscf->session_timeout = NGX_CONF_UNSET; >> sscf->session_tickets = NGX_CONF_UNSET; >> sscf->session_ticket_keys = NGX_CONF_UNSET_PTR; >> sscf->stapling = NGX_CONF_UNSET; >> + sscf->stapling_files = NGX_CONF_UNSET_PTR; >> sscf->stapling_verify = NGX_CONF_UNSET; >> >> return sscf; >> } >> >> >> static char * >> ngx_http_ssl_merge_srv_conf(ngx_conf_t *cf, void *parent, void *child) >> @@ -611,17 +611,17 @@ ngx_http_ssl_merge_srv_conf(ngx_conf_t * >> >> ngx_conf_merge_str_value(conf->ecdh_curve, prev->ecdh_curve, >> NGX_DEFAULT_ECDH_CURVE); >> >> ngx_conf_merge_str_value(conf->ciphers, prev->ciphers, NGX_DEFAULT_CIPHERS); >> >> ngx_conf_merge_value(conf->stapling, prev->stapling, 0); >> ngx_conf_merge_value(conf->stapling_verify, prev->stapling_verify, 0); >> - ngx_conf_merge_str_value(conf->stapling_file, prev->stapling_file, ""); >> + ngx_conf_merge_ptr_value(conf->stapling_files, prev->stapling_files, NULL); >> ngx_conf_merge_str_value(conf->stapling_responder, >> prev->stapling_responder, ""); >> >> conf->ssl.log = cf->log; >> >> if (conf->enable) { >> >> if (conf->certificates == NULL) { >> @@ -662,16 +662,28 @@ ngx_http_ssl_merge_srv_conf(ngx_conf_t * >> { >> ngx_log_error(NGX_LOG_EMERG, cf->log, 0, >> "no \"ssl_certificate_key\" is defined " >> "for certificate \"%V\"", >> ((ngx_str_t *) conf->certificates->elts) >> + conf->certificates->nelts - 1); >> return NGX_CONF_ERROR; >> } >> + >> + if ((conf->stapling_files) && >> + (conf->stapling_files->nelts != conf->certificates->nelts)) >> + { >> + ngx_log_error(NGX_LOG_EMERG, cf->log, 0, >> + "no \"ssl_stapling_file\" is defined " >> + "for certificate \"%V\"", >> + ((ngx_str_t *) conf->certificates->elts) >> + + conf->certificates->nelts - 1); >> + return NGX_CONF_ERROR; > > Certainly an error here is too restrictive, I would rather > recommend preserving the current behaviour (or may be emitting a > warning instead). The current behavior is to serve the wrong OCSP staple for one (or more) of the certificates. I don?t think this is desirable as it can cause clients that validate OCSP staples to reject the TLS connection (especially if the certificate has Must-Staple). That seemed like a significant issue to me, but I can make it a warning if you prefer. As a server admin, I personally prefer the error if my ssl config can lead to client side issues, like not being able to reach my site, and it may not be something I see in testing my server if I don?t test against all clients (this stuff is hard enough to get right in the first place). (FWIW, trying to set multiple stapling files currently gives an error due to a duplicate ssl_stapling_file directive.) It was also unclear to me if the check needed to be repeated in the if (conf->enable) block as well as the else block, guidance appreciated as I don?t really get the point of that logic. > >> + } >> + >> } > > Style, there should be no empty line here. Will fix all the above and resubmit shortly. Thanks for the review! (also, I?m currently running the original patch on a production server with dual RSA/ECDSA certificates and a bot keeping the stapling files current at https://elemental.software/ if you want to test against a running instance) Peter > >> >> if (ngx_ssl_create(&conf->ssl, conf->protocols, conf) != NGX_OK) { >> return NGX_CONF_ERROR; >> } >> >> #ifdef SSL_CTRL_SET_TLSEXT_HOSTNAME >> >> @@ -786,17 +798,17 @@ ngx_http_ssl_merge_srv_conf(ngx_conf_t * >> if (ngx_ssl_session_ticket_keys(cf, &conf->ssl, conf->session_ticket_keys) >> != NGX_OK) >> { >> return NGX_CONF_ERROR; >> } >> >> if (conf->stapling) { >> >> - if (ngx_ssl_stapling(cf, &conf->ssl, &conf->stapling_file, >> + if (ngx_ssl_stapling(cf, &conf->ssl, conf->stapling_files, >> &conf->stapling_responder, conf->stapling_verify) >> != NGX_OK) >> { >> return NGX_CONF_ERROR; >> } >> >> } >> >> diff --git a/src/http/modules/ngx_http_ssl_module.h b/src/http/modules/ngx_http_ssl_module.h >> --- a/src/http/modules/ngx_http_ssl_module.h >> +++ b/src/http/modules/ngx_http_ssl_module.h >> @@ -47,17 +47,17 @@ typedef struct { >> >> ngx_shm_zone_t *shm_zone; >> >> ngx_flag_t session_tickets; >> ngx_array_t *session_ticket_keys; >> >> ngx_flag_t stapling; >> ngx_flag_t stapling_verify; >> - ngx_str_t stapling_file; >> + ngx_array_t *stapling_files; >> ngx_str_t stapling_responder; >> >> u_char *file; >> ngx_uint_t line; >> } ngx_http_ssl_srv_conf_t; >> >> >> extern ngx_module_t ngx_http_ssl_module; >> _______________________________________________ >> nginx-devel mailing list >> nginx-devel at nginx.org >> http://mailman.nginx.org/mailman/listinfo/nginx-devel > > -- > Maxim Dounin > http://nginx.org/ > _______________________________________________ > 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 Jul 4 19:58:44 2017 From: mdounin at mdounin.ru (Maxim Dounin) Date: Tue, 4 Jul 2017 22:58:44 +0300 Subject: [PATCH] Enable multiple ssl_stapling_file configuration directives In-Reply-To: <12BFC85A-4C6D-40D6-96B5-15DFE2C21363@linss.com> References: <0580b76366e8540973e0.1498958463@elemental-dev.linss.com> <20170704142825.GZ55433@mdounin.ru> <12BFC85A-4C6D-40D6-96B5-15DFE2C21363@linss.com> Message-ID: <20170704195844.GD55433@mdounin.ru> Hello! On Tue, Jul 04, 2017 at 11:51:10AM -0700, Peter Linss wrote: [...] > > This looks overcomplicated and should be rewritten. Instead, > > consider preserving a single loop over certificates available, and > > providing appropriate parameters to ngx_ssl_stapling_certificate() > > inside the loop. > > Will do. I wasn?t happy this this myself, but was trying to > match existing code style as much as possible in the use of the > files array. > > Doing this in a single loop my default approach would be to use > a conditional operator to handle the file parameter, but given > that files can be NULL it gets a bit ugly without the additional > setup. Do you prefer this approach? (untested at this point, but > will test before resubmitting, just checking style) > > ngx_int_t > ngx_ssl_stapling(ngx_conf_t *cf, ngx_ssl_t *ssl, ngx_array_t *files, > ngx_str_t *responder, ngx_uint_t verify) > { > X509 *cert; > ngx_uint_t i; > > for (cert = SSL_CTX_get_ex_data(ssl->ctx, ngx_ssl_certificate_index, i = 1); > cert; > cert = X509_get_ex_data(cert, ngx_ssl_next_certificate_index), i++) > { > if (ngx_ssl_stapling_certificate(cf, ssl, cert, files ? &(files->elts[files->nelts - i]) : NULL, > responder, verify) > != NGX_OK) > { > return NGX_ERROR; > } > } > > SSL_CTX_set_tlsext_status_cb(ssl->ctx, ngx_ssl_certificate_status_callback); > > return NGX_OK; > } The particular example doesn't look acceptable either (and doesn't look working due to syntax errors), though it looks better. Using a separate variable for a file might improve code readability here. > Also, matching the staple file to the certificate based on the > certificate order feels a bit fragile to me. Have a suggestion > for a more robust approach? Or is the certificate order stable > enough? (Nothing obvious jumped out at me without changing a > bunch of other setup logic and I wanted to keep the impact of > this change minimal.) This is one of the main reasons why I generally against the feature in general. Order-based matching is not perfect even for certificates and keys, and extending it to other directives looks even more fragile. As previously suggested, it might be better idea to avoid trying to support multiple ssl_certificate_file directives, see https://trac.nginx.org/nginx/ticket/990#comment:5. An alternative solution that will still allow to provide custom OCSP response would be to support OCSP responses in the certificate file in PEM format. This is actually a solution I would prefer to see, but this will require additional support in OpenSSL, as currently it is not able to work with OCSP responses in PEM format. Or we can instead focus on improving persistence of OCSP responses obtained automatically. [...] > >> + if ((conf->stapling_files) && > >> + (conf->stapling_files->nelts != conf->certificates->nelts)) > >> + { > >> + ngx_log_error(NGX_LOG_EMERG, cf->log, 0, > >> + "no \"ssl_stapling_file\" is defined " > >> + "for certificate \"%V\"", > >> + ((ngx_str_t *) conf->certificates->elts) > >> + + conf->certificates->nelts - 1); > >> + return NGX_CONF_ERROR; > > > > Certainly an error here is too restrictive, I would rather > > recommend preserving the current behaviour (or may be emitting a > > warning instead). > > The current behavior is to serve the wrong OCSP staple for one > (or more) of the certificates. I don?t think this is desirable > as it can cause clients that validate OCSP staples to reject the > TLS connection (especially if the certificate has Must-Staple). > That seemed like a significant issue to me, but I can make it a > warning if you prefer. As a server admin, I personally prefer > the error if my ssl config can lead to client side issues, like > not being able to reach my site, and it may not be something I > see in testing my server if I don?t test against all clients > (this stuff is hard enough to get right in the first place). The current behaviour is much more complicated than that. In particular, consider the following cases: - RSA and ECDSA certificates are provided, ssl_stapling_file is set, but ssl_stapling is switched off. - Two RSA certificates are provided, and ssl_stapling_file provided as well. - RSA and DSA certificates are provided, ssl_stapling_file is set, and DSA ciphers are disabled using ssl_ciphers. In all of the above cases the current behaviour will be perfectly correct. On the other hand, the error you've introduced will break such potentially existing and correctly working configurations. > (FWIW, trying to set multiple stapling files currently gives an > error due to a duplicate ssl_stapling_file directive.) > > It was also unclear to me if the check needed to be repeated in > the if (conf->enable) block as well as the else block, guidance > appreciated as I don?t really get the point of that logic. The conf->enable flag is set when "ssl on" is used in the configuration. Using "listen ... ssl" is recommended instead. Proper checking should not depend on a configuration method used, so adding the check to only one code path is a bad idea. On the other hand, adding a check there might not be a good idea in general, a better place might be in ngx_ssl_stapling() or just before the call. -- Maxim Dounin http://nginx.org/ From orgads at gmail.com Wed Jul 5 08:51:06 2017 From: orgads at gmail.com (Orgad Shaneh) Date: Wed, 5 Jul 2017 11:51:06 +0300 Subject: [PATCH] Fix flag detection on MinGW Message-ID: --- auto/cc/conf | 24 +++++++++++++----------- 1 file changed, 13 insertions(+), 11 deletions(-) diff --git a/auto/cc/conf b/auto/cc/conf index afbca62b..2d062c31 100644 --- a/auto/cc/conf +++ b/auto/cc/conf @@ -144,7 +144,7 @@ fi CFLAGS="$CFLAGS $NGX_CC_OPT" NGX_TEST_LD_OPT="$NGX_LD_OPT" -if [ "$NGX_PLATFORM" != win32 ]; then +if [ "$NGX_PLATFORM" != win32 -o "$NGX_CC_NAME" = "gcc" -o "$NGX_CC_NAME" = "clang" ]; then if test -n "$NGX_LD_OPT"; then ngx_feature=--with-ld-opt=\"$NGX_LD_OPT\" @@ -164,17 +164,19 @@ if [ "$NGX_PLATFORM" != win32 ]; then fi - ngx_feature="-Wl,-E switch" - ngx_feature_name= - ngx_feature_run=no - ngx_feature_incs= - ngx_feature_path= - ngx_feature_libs=-Wl,-E - ngx_feature_test= - . auto/feature + if [ "$NGX_PLATFORM" != win32 ]; then + ngx_feature="-Wl,-E switch" + ngx_feature_name= + ngx_feature_run=no + ngx_feature_incs= + ngx_feature_path= + ngx_feature_libs=-Wl,-E + ngx_feature_test= + . auto/feature - if [ $ngx_found = yes ]; then - MAIN_LINK="-Wl,-E" + if [ $ngx_found = yes ]; then + MAIN_LINK="-Wl,-E" + fi fi -- 2.13.1.windows.2.4.g8d91d34115 From piotrsikora at google.com Wed Jul 5 10:02:55 2017 From: piotrsikora at google.com (Piotr Sikora) Date: Wed, 5 Jul 2017 03:02:55 -0700 Subject: [PATCH 03 of 14] HTTP/2: add debug logging of control frames In-Reply-To: <18284940.HFE4rYao7p@vbart-workstation> References: <5f5d70428655db0889a2.1498163585@piotrsikora.sfo.corp.google.com> <22d178a11e30c4a8576c.1498163587@piotrsikora.sfo.corp.google.com> <18284940.HFE4rYao7p@vbart-workstation> Message-ID: Hey Valentin, comments below. I commented only on the first occurrence, but obviously those comments apply to all similar changes. > ngx_log_debug0(NGX_LOG_DEBUG_HTTP, h2c->connection->log, 0, > - "http2 SETTINGS frame ack:1"); > + "http2 SETTINGS ACK frame"); I don't particularly like this change, since it makes it look like this is a "SETTINGS ACK" frame, not a "SETTINGS" frame with ACK flag set. This is even more confusing since QUIC drafts had "SETTINGS_ACK" frame at some point. Maybe "http2 SETTINGS frame ACK" would be more acceptable? > ngx_log_debug1(NGX_LOG_DEBUG_HTTP, h2c->connection->log, 0, > - "http2 SETTINGS frame params:%uz", > + "http2 SETTINGS frame with %uz params", > h2c->state.length / NGX_HTTP_V2_SETTINGS_PARAM_SIZE); The extra "with" doesn't add any information, and it doesn't seem to be inline with other debug logs, but I don't mind this change too much. > ngx_log_debug1(NGX_LOG_DEBUG_HTTP, h2c->connection->log, 0, > - "http2 SETTINGS param HEADER_TABLE_SIZE:%ui " > + "http2 SETTINGS param HEADER_TABLE_SIZE: %ui " > "(ignored)", value); This is fine with me, but again, the extra space doesn't seem to be inline with other debug logs, which usually don't include space between "key:" and "value". > ngx_log_debug2(NGX_LOG_DEBUG_HTTP, h2c->connection->log, 0, > - "http2 SETTINGS param 0x%Xi:%ui " > - "(ignored)", id, value); > + "http2 unknown SETTINGS param id:0x%Xi value:%ui", > + id, value); I'd prefer if we could stick to the "http2 SETTINGS" prefix here, otherwise it won't look like part of the same frame, i.e.: http2 SETTINGS frame with 3 params http2 SETTINGS param HEADER_TABLE_SIZE: 4096 http2 SETTINGS param INITIAL_WINDOW_SIZE: 65536 http2 unknown SETTINGS param id:0xAA value:1234 Also, " (ignored)" part was removed, which makes it inconsistent with other ignored parameters. Maybe "http2 SETTINGS unknown param id:0x%Xi value:%ui (ignored)" or "http2 SETTINGS param id:0x%Xi value:%ui (unknown, ignored)"? Thanks! Best regards, Piotr Sikora From piotrsikora at google.com Wed Jul 5 10:29:15 2017 From: piotrsikora at google.com (Piotr Sikora) Date: Wed, 5 Jul 2017 03:29:15 -0700 Subject: [PATCH 10 of 14] Proxy: always emit "Host" header first In-Reply-To: <20170704164822.GC55433@mdounin.ru> References: <5f5d70428655db0889a2.1498163585@piotrsikora.sfo.corp.google.com> <068381014f256ad6e2dc.1498163594@piotrsikora.sfo.corp.google.com> <20170704164822.GC55433@mdounin.ru> Message-ID: Hey Maxim, > As already outlined in the review here: > > http://mailman.nginx.org/pipermail/nginx-devel/2017-June/010087.html > > the approach taken looks very fragile. There should be a better > way to do this. I disagree. The change is minimal (which is something that you seem to always prefer) and works perfectly fine. Yes, it's based on the assumption that "Host" header is the first of default headers, but I don't think that's bad and I can't imagine the order magically changing by itself... Also, the check if the first key is "Host" could be probably removed. As for your suggested alternatives: Emitting default headers first, would - just like you mentioned - lose the benefit of order defined by "proxy_set_header" directives, and as such would change the order on the wire, so I'd rather avoid this solution. Emitting "Host" header separately, via different means, would require more drastic code changes, for little to no benefit. Anyway, you're more than welcome to provide alternative patch, but I don't see anything wrong with the current approach, so I'm unlikely to rewrite it myself. Best regards, Piotr Sikora From mdounin at mdounin.ru Wed Jul 5 17:49:48 2017 From: mdounin at mdounin.ru (Maxim Dounin) Date: Wed, 5 Jul 2017 20:49:48 +0300 Subject: [PATCH] Fix flag detection on MinGW In-Reply-To: References: Message-ID: <20170705174948.GF55433@mdounin.ru> Hello! On Wed, Jul 05, 2017 at 11:51:06AM +0300, Orgad Shaneh wrote: > --- > auto/cc/conf | 24 +++++++++++++----------- > 1 file changed, 13 insertions(+), 11 deletions(-) > > diff --git a/auto/cc/conf b/auto/cc/conf > index afbca62b..2d062c31 100644 > --- a/auto/cc/conf > +++ b/auto/cc/conf > @@ -144,7 +144,7 @@ fi > CFLAGS="$CFLAGS $NGX_CC_OPT" > NGX_TEST_LD_OPT="$NGX_LD_OPT" > > -if [ "$NGX_PLATFORM" != win32 ]; then > +if [ "$NGX_PLATFORM" != win32 -o "$NGX_CC_NAME" = "gcc" -o > "$NGX_CC_NAME" = "clang" ]; then > > if test -n "$NGX_LD_OPT"; then > ngx_feature=--with-ld-opt=\"$NGX_LD_OPT\" > @@ -164,17 +164,19 @@ if [ "$NGX_PLATFORM" != win32 ]; then > fi > > > - ngx_feature="-Wl,-E switch" > - ngx_feature_name= > - ngx_feature_run=no > - ngx_feature_incs= > - ngx_feature_path= > - ngx_feature_libs=-Wl,-E > - ngx_feature_test= > - . auto/feature > + if [ "$NGX_PLATFORM" != win32 ]; then > + ngx_feature="-Wl,-E switch" > + ngx_feature_name= > + ngx_feature_run=no > + ngx_feature_incs= > + ngx_feature_path= > + ngx_feature_libs=-Wl,-E > + ngx_feature_test= > + . auto/feature > > - if [ $ngx_found = yes ]; then > - MAIN_LINK="-Wl,-E" > + if [ $ngx_found = yes ]; then > + MAIN_LINK="-Wl,-E" > + fi > fi No, thanks. We generally avoid any feature tests on win32, as we support cross-compilation for win32, and feature tests, especially ones with ngx_feature_run=yes, can easily produce wrong results or fail. Most of the information is defined in the src/os/win32/ngx_win32_config.h instead, and some in auto/os/win32. -- Maxim Dounin http://nginx.org/ From xeioex at nginx.com Thu Jul 6 16:07:08 2017 From: xeioex at nginx.com (Dmitry Volyntsev) Date: Thu, 06 Jul 2017 16:07:08 +0000 Subject: [njs] Removed unused njs_vm_export_functions(). Message-ID: details: http://hg.nginx.org/njs/rev/f8f7540383f2 branches: changeset: 382:f8f7540383f2 user: Dmitry Volyntsev date: Wed Jun 28 15:31:36 2017 +0300 description: Removed unused njs_vm_export_functions(). diffstat: nginx/ngx_http_js_module.c | 4 +- nginx/ngx_stream_js_module.c | 4 +- njs/njs_variable.c | 56 -------------------------------------------- njs/njs_variable.h | 2 - njs/njscript.c | 7 +---- njs/njscript.h | 3 +- njs/test/njs_unit_test.c | 9 +++--- 7 files changed, 10 insertions(+), 75 deletions(-) diffs (197 lines): diff -r 63d7430291f2 -r f8f7540383f2 nginx/ngx_http_js_module.c --- a/nginx/ngx_http_js_module.c Tue Jun 27 17:03:16 2017 +0300 +++ b/nginx/ngx_http_js_module.c Wed Jun 28 15:31:36 2017 +0300 @@ -1230,7 +1230,7 @@ ngx_http_js_include(ngx_conf_t *cf, ngx_ ngx_fd_t fd; ngx_str_t *value, file; nxt_int_t rc; - nxt_str_t text, ext, *export; + nxt_str_t text, ext; nxt_lvlhsh_t externals; ngx_file_info_t fi; njs_vm_shared_t *shared; @@ -1327,7 +1327,7 @@ ngx_http_js_include(ngx_conf_t *cf, ngx_ return NGX_CONF_ERROR; } - rc = njs_vm_compile(jlcf->vm, &start, end, &export); + rc = njs_vm_compile(jlcf->vm, &start, end); if (rc != NJS_OK) { njs_vm_exception(jlcf->vm, &text); diff -r 63d7430291f2 -r f8f7540383f2 nginx/ngx_stream_js_module.c --- a/nginx/ngx_stream_js_module.c Tue Jun 27 17:03:16 2017 +0300 +++ b/nginx/ngx_stream_js_module.c Wed Jun 28 15:31:36 2017 +0300 @@ -940,7 +940,7 @@ ngx_stream_js_include(ngx_conf_t *cf, ng ngx_fd_t fd; ngx_str_t *value, file; nxt_int_t rc; - nxt_str_t text, ext, *export; + nxt_str_t text, ext; nxt_lvlhsh_t externals; ngx_file_info_t fi; njs_vm_shared_t *shared; @@ -1037,7 +1037,7 @@ ngx_stream_js_include(ngx_conf_t *cf, ng return NGX_CONF_ERROR; } - rc = njs_vm_compile(jscf->vm, &start, end, &export); + rc = njs_vm_compile(jscf->vm, &start, end); if (rc != NJS_OK) { njs_vm_exception(jscf->vm, &text); diff -r 63d7430291f2 -r f8f7540383f2 njs/njs_variable.c --- a/njs/njs_variable.c Tue Jun 27 17:03:16 2017 +0300 +++ b/njs/njs_variable.c Wed Jun 28 15:31:36 2017 +0300 @@ -489,62 +489,6 @@ njs_name_copy(njs_vm_t *vm, nxt_str_t *d } -nxt_str_t * -njs_vm_export_functions(njs_vm_t *vm) -{ - size_t n; - nxt_str_t *ex, *export; - njs_value_t *value; - njs_variable_t *var; - nxt_lvlhsh_each_t lhe; - - n = 1; - - nxt_lvlhsh_each_init(&lhe, &njs_variables_hash_proto); - - for ( ;; ) { - var = nxt_lvlhsh_each(&vm->variables_hash, &lhe); - if (var == NULL) { - break; - } - - value = njs_global_variable_value(vm, var); - - if (njs_is_function(value) && !value->data.u.function->native) { - n++; - } - } - - export = nxt_mem_cache_alloc(vm->mem_cache_pool, n * sizeof(nxt_str_t)); - if (nxt_slow_path(export == NULL)) { - return NULL; - } - - nxt_lvlhsh_each_init(&lhe, &njs_variables_hash_proto); - - ex = export; - - for ( ;; ) { - var = nxt_lvlhsh_each(&vm->variables_hash, &lhe); - if (var == NULL) { - break; - } - - value = njs_global_variable_value(vm, var); - - if (njs_is_function(value) && !value->data.u.function->native) { - *ex = var->name; - ex++; - } - } - - ex->length = 0; - ex->start = NULL; - - return export; -} - - njs_function_t * njs_vm_function(njs_vm_t *vm, nxt_str_t *name) { diff -r 63d7430291f2 -r f8f7540383f2 njs/njs_variable.h --- a/njs/njs_variable.h Tue Jun 27 17:03:16 2017 +0300 +++ b/njs/njs_variable.h Wed Jun 28 15:31:36 2017 +0300 @@ -42,8 +42,6 @@ njs_ret_t njs_variables_scope_reference( njs_parser_scope_t *scope); njs_ret_t njs_name_copy(njs_vm_t *vm, nxt_str_t *dst, nxt_str_t *src); -nxt_str_t *njs_vm_export_functions(njs_vm_t *vm); - extern const nxt_lvlhsh_proto_t njs_variables_hash_proto; diff -r 63d7430291f2 -r f8f7540383f2 njs/njscript.c --- a/njs/njscript.c Tue Jun 27 17:03:16 2017 +0300 +++ b/njs/njscript.c Wed Jun 28 15:31:36 2017 +0300 @@ -184,7 +184,7 @@ njs_vm_destroy(njs_vm_t *vm) nxt_int_t -njs_vm_compile(njs_vm_t *vm, u_char **start, u_char *end, nxt_str_t **export) +njs_vm_compile(njs_vm_t *vm, u_char **start, u_char *end) { nxt_int_t ret; njs_lexer_t *lexer; @@ -237,11 +237,6 @@ njs_vm_compile(njs_vm_t *vm, u_char **st vm->parser = NULL; - *export = njs_vm_export_functions(vm); - if (nxt_slow_path(*export == NULL)) { - return NJS_ERROR; - } - return NJS_OK; } diff -r 63d7430291f2 -r f8f7540383f2 njs/njscript.h --- a/njs/njscript.h Tue Jun 27 17:03:16 2017 +0300 +++ b/njs/njscript.h Wed Jun 28 15:31:36 2017 +0300 @@ -83,8 +83,7 @@ NXT_EXPORT njs_vm_t *njs_vm_create(nxt_m njs_vm_shared_t **shared, nxt_lvlhsh_t *externals); NXT_EXPORT void njs_vm_destroy(njs_vm_t *vm); -NXT_EXPORT nxt_int_t njs_vm_compile(njs_vm_t *vm, u_char **start, u_char *end, - nxt_str_t **export); +NXT_EXPORT nxt_int_t njs_vm_compile(njs_vm_t *vm, u_char **start, u_char *end); NXT_EXPORT njs_vm_t *njs_vm_clone(njs_vm_t *vm, nxt_mem_cache_pool_t *mcp, void **external); NXT_EXPORT nxt_int_t njs_vm_call(njs_vm_t *vm, njs_function_t *function, diff -r 63d7430291f2 -r f8f7540383f2 njs/test/njs_unit_test.c --- a/njs/test/njs_unit_test.c Tue Jun 27 17:03:16 2017 +0300 +++ b/njs/test/njs_unit_test.c Wed Jun 28 15:31:36 2017 +0300 @@ -8118,7 +8118,7 @@ njs_unit_test(nxt_bool_t disassemble) u_char *start; njs_vm_t *vm, *nvm; nxt_int_t ret; - nxt_str_t s, *export; + nxt_str_t s; nxt_uint_t i; nxt_bool_t success; nxt_lvlhsh_t externals; @@ -8164,8 +8164,7 @@ njs_unit_test(nxt_bool_t disassemble) start = njs_test[i].script.start; - ret = njs_vm_compile(vm, &start, start + njs_test[i].script.length, - &export); + ret = njs_vm_compile(vm, &start, start + njs_test[i].script.length); if (ret == NXT_OK) { if (disassemble) { @@ -8232,7 +8231,7 @@ njs_unit_test_benchmark(nxt_str_t *scrip njs_vm_t *vm, *nvm; uint64_t us; nxt_int_t ret; - nxt_str_t s, *export; + nxt_str_t s; nxt_uint_t i; nxt_bool_t success; nxt_lvlhsh_t externals; @@ -8266,7 +8265,7 @@ njs_unit_test_benchmark(nxt_str_t *scrip start = script->start; - ret = njs_vm_compile(vm, &start, start + script->length, &export); + ret = njs_vm_compile(vm, &start, start + script->length); if (ret != NXT_OK) { return NXT_ERROR; } From xeioex at nginx.com Thu Jul 6 16:08:36 2017 From: xeioex at nginx.com (Dmitry Volyntsev) Date: Thu, 06 Jul 2017 16:08:36 +0000 Subject: [njs] Passing all args to njs_vm_create() through njs_vm_opt_t struct. Message-ID: details: http://hg.nginx.org/njs/rev/57bd01817edb branches: changeset: 383:57bd01817edb user: Dmitry Volyntsev date: Thu Jul 06 19:07:41 2017 +0300 description: Passing all args to njs_vm_create() through njs_vm_opt_t struct. diffstat: nginx/ngx_http_js_module.c | 10 ++++++---- nginx/ngx_stream_js_module.c | 10 ++++++---- njs/njscript.c | 18 +++++++++--------- njs/njscript.h | 9 +++++++-- njs/test/njs_unit_test.c | 20 ++++++++++++-------- 5 files changed, 40 insertions(+), 27 deletions(-) diffs (215 lines): diff -r f8f7540383f2 -r 57bd01817edb nginx/ngx_http_js_module.c --- a/nginx/ngx_http_js_module.c Wed Jun 28 15:31:36 2017 +0300 +++ b/nginx/ngx_http_js_module.c Thu Jul 06 19:07:41 2017 +0300 @@ -1231,9 +1231,9 @@ ngx_http_js_include(ngx_conf_t *cf, ngx_ ngx_str_t *value, file; nxt_int_t rc; nxt_str_t text, ext; + njs_vm_opt_t options; nxt_lvlhsh_t externals; ngx_file_info_t fi; - njs_vm_shared_t *shared; ngx_pool_cleanup_t *cln; nxt_mem_cache_pool_t *mcp; @@ -1309,8 +1309,6 @@ ngx_http_js_include(ngx_conf_t *cf, ngx_ cln->handler = ngx_http_js_cleanup_mem_cache_pool; cln->data = mcp; - shared = NULL; - nxt_lvlhsh_init(&externals); if (njs_vm_external_add(&externals, mcp, 0, ngx_http_js_externals, @@ -1321,7 +1319,11 @@ ngx_http_js_include(ngx_conf_t *cf, ngx_ return NGX_CONF_ERROR; } - jlcf->vm = njs_vm_create(mcp, &shared, &externals); + options.mcp = mcp; + options.shared = NULL; + options.externals = &externals; + + jlcf->vm = njs_vm_create(&options); if (jlcf->vm == NULL) { ngx_conf_log_error(NGX_LOG_EMERG, cf, 0, "failed to create JS VM"); return NGX_CONF_ERROR; diff -r f8f7540383f2 -r 57bd01817edb nginx/ngx_stream_js_module.c --- a/nginx/ngx_stream_js_module.c Wed Jun 28 15:31:36 2017 +0300 +++ b/nginx/ngx_stream_js_module.c Thu Jul 06 19:07:41 2017 +0300 @@ -941,9 +941,9 @@ ngx_stream_js_include(ngx_conf_t *cf, ng ngx_str_t *value, file; nxt_int_t rc; nxt_str_t text, ext; + njs_vm_opt_t options; nxt_lvlhsh_t externals; ngx_file_info_t fi; - njs_vm_shared_t *shared; ngx_pool_cleanup_t *cln; nxt_mem_cache_pool_t *mcp; @@ -1019,8 +1019,6 @@ ngx_stream_js_include(ngx_conf_t *cf, ng cln->handler = ngx_stream_js_cleanup_mem_cache_pool; cln->data = mcp; - shared = NULL; - nxt_lvlhsh_init(&externals); if (njs_vm_external_add(&externals, mcp, 0, ngx_stream_js_externals, @@ -1031,7 +1029,11 @@ ngx_stream_js_include(ngx_conf_t *cf, ng return NGX_CONF_ERROR; } - jscf->vm = njs_vm_create(mcp, &shared, &externals); + options.mcp = mcp; + options.shared = NULL; + options.externals = &externals; + + jscf->vm = njs_vm_create(&options); if (jscf->vm == NULL) { ngx_conf_log_error(NGX_LOG_EMERG, cf, 0, "failed to create JS VM"); return NGX_CONF_ERROR; diff -r f8f7540383f2 -r 57bd01817edb njs/njscript.c --- a/njs/njscript.c Wed Jun 28 15:31:36 2017 +0300 +++ b/njs/njscript.c Thu Jul 06 19:07:41 2017 +0300 @@ -99,13 +99,15 @@ const nxt_mem_proto_t njs_array_mem_pro njs_vm_t * -njs_vm_create(nxt_mem_cache_pool_t *mcp, njs_vm_shared_t **shared, - nxt_lvlhsh_t *externals) +njs_vm_create(njs_vm_opt_t *options) { njs_vm_t *vm; nxt_int_t ret; + nxt_mem_cache_pool_t *mcp; njs_regexp_pattern_t *pattern; + mcp = options->mcp; + if (mcp == NULL) { mcp = nxt_mem_cache_pool_create(&njs_vm_mem_cache_pool_proto, NULL, NULL, 2 * nxt_pagesize(), 128, 512, 16); @@ -124,8 +126,8 @@ njs_vm_create(nxt_mem_cache_pool_t *mcp, return NULL; } - if (shared != NULL && *shared != NULL) { - vm->shared = *shared; + if (options->shared != NULL) { + vm->shared = options->shared; } else { vm->shared = nxt_mem_cache_zalloc(mcp, sizeof(njs_vm_shared_t)); @@ -133,9 +135,7 @@ njs_vm_create(nxt_mem_cache_pool_t *mcp, return NULL; } - if (shared != NULL) { - *shared = vm->shared; - } + options->shared = vm->shared; nxt_lvlhsh_init(&vm->shared->keywords_hash); @@ -162,8 +162,8 @@ njs_vm_create(nxt_mem_cache_pool_t *mcp, nxt_lvlhsh_init(&vm->values_hash); - if (externals != NULL) { - vm->externals_hash = *externals; + if (options->externals != NULL) { + vm->externals_hash = *options->externals; } vm->trace.level = NXT_LEVEL_TRACE; diff -r f8f7540383f2 -r 57bd01817edb njs/njscript.h --- a/njs/njscript.h Wed Jun 28 15:31:36 2017 +0300 +++ b/njs/njscript.h Thu Jul 06 19:07:41 2017 +0300 @@ -65,6 +65,12 @@ struct njs_external_s { uintptr_t data; }; +typedef struct { + nxt_lvlhsh_t *externals; + njs_vm_shared_t *shared; + nxt_mem_cache_pool_t *mcp; +} njs_vm_opt_t; + #define NJS_OK NXT_OK #define NJS_ERROR NXT_ERROR @@ -79,8 +85,7 @@ NXT_EXPORT nxt_int_t njs_vm_external_add NXT_EXPORT nxt_int_t njs_vm_external(njs_vm_t *vm, njs_opaque_value_t *object, nxt_str_t *property, njs_opaque_value_t *value); -NXT_EXPORT njs_vm_t *njs_vm_create(nxt_mem_cache_pool_t *mcp, - njs_vm_shared_t **shared, nxt_lvlhsh_t *externals); +NXT_EXPORT njs_vm_t *njs_vm_create(njs_vm_opt_t *options); NXT_EXPORT void njs_vm_destroy(njs_vm_t *vm); NXT_EXPORT nxt_int_t njs_vm_compile(njs_vm_t *vm, u_char **start, u_char *end); diff -r f8f7540383f2 -r 57bd01817edb njs/test/njs_unit_test.c --- a/njs/test/njs_unit_test.c Wed Jun 28 15:31:36 2017 +0300 +++ b/njs/test/njs_unit_test.c Thu Jul 06 19:07:41 2017 +0300 @@ -8121,8 +8121,8 @@ njs_unit_test(nxt_bool_t disassemble) nxt_str_t s; nxt_uint_t i; nxt_bool_t success; + njs_vm_opt_t options; nxt_lvlhsh_t externals; - njs_vm_shared_t *shared; njs_unit_test_req r; nxt_mem_cache_pool_t *mcp; @@ -8133,8 +8133,6 @@ njs_unit_test(nxt_bool_t disassemble) (void) putenv((char *) "TZ=Pacific/Chatham"); tzset(); - shared = NULL; - mcp = nxt_mem_cache_pool_create(&njs_mem_cache_pool_proto, NULL, NULL, 2 * nxt_pagesize(), 128, 512, 16); if (nxt_slow_path(mcp == NULL)) { @@ -8157,7 +8155,11 @@ njs_unit_test(nxt_bool_t disassemble) (int) njs_test[i].script.length, njs_test[i].script.start); fflush(stdout); - vm = njs_vm_create(mcp, &shared, &externals); + options.mcp = mcp; + options.shared = NULL; + options.externals = &externals; + + vm = njs_vm_create(&options); if (vm == NULL) { return NXT_ERROR; } @@ -8235,13 +8237,11 @@ njs_unit_test_benchmark(nxt_str_t *scrip nxt_uint_t i; nxt_bool_t success; nxt_lvlhsh_t externals; + njs_vm_opt_t options; struct rusage usage; - njs_vm_shared_t *shared; njs_unit_test_req r; nxt_mem_cache_pool_t *mcp; - shared = NULL; - mcp = nxt_mem_cache_pool_create(&njs_mem_cache_pool_proto, NULL, NULL, 2 * nxt_pagesize(), 128, 512, 16); if (nxt_slow_path(mcp == NULL)) { @@ -8258,7 +8258,11 @@ njs_unit_test_benchmark(nxt_str_t *scrip return NXT_ERROR; } - vm = njs_vm_create(mcp, &shared, &externals); + options.mcp = mcp; + options.shared = NULL; + options.externals = &externals; + + vm = njs_vm_create(&options); if (vm == NULL) { return NXT_ERROR; } From xeioex at nginx.com Thu Jul 6 16:15:27 2017 From: xeioex at nginx.com (Dmitry Volyntsev) Date: Thu, 06 Jul 2017 16:15:27 +0000 Subject: [njs] Moving VM initialization from njs_vm_clone() to njs_vm_init(). Message-ID: details: http://hg.nginx.org/njs/rev/d09638142829 branches: changeset: 384:d09638142829 user: Dmitry Volyntsev date: Thu Jul 06 19:09:56 2017 +0300 description: Moving VM initialization from njs_vm_clone() to njs_vm_init(). diffstat: njs/njscript.c | 102 +++++++++++++++++++++++++++++++++----------------------- 1 files changed, 60 insertions(+), 42 deletions(-) diffs (144 lines): diff -r 57bd01817edb -r d09638142829 njs/njscript.c --- a/njs/njscript.c Thu Jul 06 19:07:41 2017 +0300 +++ b/njs/njscript.c Thu Jul 06 19:09:56 2017 +0300 @@ -26,6 +26,9 @@ #include +static nxt_int_t njs_vm_init(njs_vm_t *vm); + + static void * njs_alloc(void *mem, size_t size) { @@ -244,11 +247,8 @@ njs_vm_compile(njs_vm_t *vm, u_char **st njs_vm_t * njs_vm_clone(njs_vm_t *vm, nxt_mem_cache_pool_t *mcp, void **external) { - u_char *values; - size_t size, scope_size; njs_vm_t *nvm; nxt_int_t ret; - njs_frame_t *frame; nxt_mem_cache_pool_t *nmcp; nxt_thread_log_debug("CLONE:"); @@ -274,54 +274,17 @@ njs_vm_clone(njs_vm_t *vm, nxt_mem_cache nvm->values_hash = vm->values_hash; nvm->externals_hash = vm->externals_hash; - nvm->retval = njs_value_void; nvm->current = vm->current; nvm->external = external; nvm->global_scope = vm->global_scope; - scope_size = vm->scope_size; - nvm->scope_size = scope_size; - scope_size += NJS_INDEX_GLOBAL_OFFSET; - - size = NJS_GLOBAL_FRAME_SIZE + scope_size + NJS_FRAME_SPARE_SIZE; - size = nxt_align_size(size, NJS_FRAME_SPARE_SIZE); - - frame = nxt_mem_cache_align(nmcp, sizeof(njs_value_t), size); - if (nxt_slow_path(frame == NULL)) { - goto fail; - } - - memset(frame, 0, NJS_GLOBAL_FRAME_SIZE); + nvm->scope_size = vm->scope_size; - nvm->top_frame = &frame->native; - nvm->active_frame = frame; - - frame->native.size = size; - frame->native.free_size = size - (NJS_GLOBAL_FRAME_SIZE + scope_size); - - values = (u_char *) frame + NJS_GLOBAL_FRAME_SIZE; - - frame->native.free = values + scope_size; - - nvm->scopes[NJS_SCOPE_GLOBAL] = (njs_value_t *) values; - memcpy(values + NJS_INDEX_GLOBAL_OFFSET, vm->global_scope, - vm->scope_size); - - ret = njs_regexp_init(nvm); + ret = njs_vm_init(nvm); if (nxt_slow_path(ret != NXT_OK)) { goto fail; } - ret = njs_builtin_objects_clone(nvm); - if (nxt_slow_path(ret != NXT_OK)) { - goto fail; - } - - nvm->trace.level = NXT_LEVEL_TRACE; - nvm->trace.size = 2048; - nvm->trace.handler = njs_parser_trace_handler; - nvm->trace.data = nvm; - return nvm; } @@ -335,6 +298,61 @@ fail: } +static nxt_int_t +njs_vm_init(njs_vm_t *vm) +{ + size_t size, scope_size; + u_char *values; + nxt_int_t ret; + njs_frame_t *frame; + + scope_size = vm->scope_size + NJS_INDEX_GLOBAL_OFFSET; + + size = NJS_GLOBAL_FRAME_SIZE + scope_size + NJS_FRAME_SPARE_SIZE; + size = nxt_align_size(size, NJS_FRAME_SPARE_SIZE); + + frame = nxt_mem_cache_align(vm->mem_cache_pool, sizeof(njs_value_t), size); + if (nxt_slow_path(frame == NULL)) { + return NXT_ERROR; + } + + memset(frame, 0, NJS_GLOBAL_FRAME_SIZE); + + vm->top_frame = &frame->native; + vm->active_frame = frame; + + frame->native.size = size; + frame->native.free_size = size - (NJS_GLOBAL_FRAME_SIZE + scope_size); + + values = (u_char *) frame + NJS_GLOBAL_FRAME_SIZE; + + frame->native.free = values + scope_size; + + vm->scopes[NJS_SCOPE_GLOBAL] = (njs_value_t *) values; + memcpy(values + NJS_INDEX_GLOBAL_OFFSET, vm->global_scope, + vm->scope_size); + + ret = njs_regexp_init(vm); + if (nxt_slow_path(ret != NXT_OK)) { + return NXT_ERROR; + } + + ret = njs_builtin_objects_clone(vm); + if (nxt_slow_path(ret != NXT_OK)) { + return NXT_ERROR; + } + + vm->retval = njs_value_void; + + vm->trace.level = NXT_LEVEL_TRACE; + vm->trace.size = 2048; + vm->trace.handler = njs_parser_trace_handler; + vm->trace.data = vm; + + return NXT_OK; +} + + nxt_int_t njs_vm_call(njs_vm_t *vm, njs_function_t *function, njs_opaque_value_t *args, nxt_uint_t nargs) From spencer at kogosoftwarellc.com Fri Jul 7 00:29:51 2017 From: spencer at kogosoftwarellc.com (Joseph Spencer) Date: Thu, 6 Jul 2017 17:29:51 -0700 Subject: Module Development Consulting Message-ID: Hi, I'm willing to pay someone familiar with nginx module development to spend an hour or 2 with me on google hangouts. The easiest method for me is to send payment via paypal. Is there anyone interested in this? -- Thanks, Joe Spencer (member) Kogo Software LLC -------------- next part -------------- An HTML attachment was scrubbed... URL: From ru at nginx.com Fri Jul 7 11:36:50 2017 From: ru at nginx.com (Ruslan Ermilov) Date: Fri, 07 Jul 2017 11:36:50 +0000 Subject: [nginx] Variables: use ngx_http_variable_null_value where appropriate. Message-ID: details: http://hg.nginx.org/nginx/rev/7f480434c7f2 branches: changeset: 7053:7f480434c7f2 user: Ruslan Ermilov date: Fri Jul 07 14:34:21 2017 +0300 description: Variables: use ngx_http_variable_null_value where appropriate. diffstat: src/http/ngx_http_variables.c | 16 +++++----------- 1 files changed, 5 insertions(+), 11 deletions(-) diffs (38 lines): diff -r 70e65bf8dfd7 -r 7f480434c7f2 src/http/ngx_http_variables.c --- a/src/http/ngx_http_variables.c Tue Jul 04 18:50:41 2017 +0300 +++ b/src/http/ngx_http_variables.c Fri Jul 07 14:34:21 2017 +0300 @@ -1463,17 +1463,15 @@ static ngx_int_t ngx_http_variable_is_args(ngx_http_request_t *r, ngx_http_variable_value_t *v, uintptr_t data) { - v->valid = 1; - v->no_cacheable = 0; - v->not_found = 0; - if (r->args.len == 0) { - v->len = 0; - v->data = NULL; + *v = ngx_http_variable_null_value; return NGX_OK; } v->len = 1; + v->valid = 1; + v->no_cacheable = 0; + v->not_found = 0; v->data = (u_char *) "?"; return NGX_OK; @@ -1990,11 +1988,7 @@ ngx_http_variable_request_completion(ngx return NGX_OK; } - v->len = 0; - v->valid = 1; - v->no_cacheable = 0; - v->not_found = 0; - v->data = (u_char *) ""; + *v = ngx_http_variable_null_value; return NGX_OK; } From cornelis.bos at gmail.com Fri Jul 7 13:38:02 2017 From: cornelis.bos at gmail.com (Kees Bos) Date: Fri, 07 Jul 2017 15:38:02 +0200 Subject: [PATCH] Add proxy_protocol option to mail listener Message-ID: <1499434682.21080.97.camel@gmail.com> # HG changeset patch # User Kees Bos # Date 1499422505 0 #??????Fri Jul 07 10:15:05 2017 +0000 # Node ID bc79b2baf494aabb889de1e5dbe3184ff0cb9bfa # Parent??70e65bf8dfd7a8d39aae8ac3a209d426e6947735 Add proxy_protocol option to mail listener Add support for the mail handlers. This enables the use of an upstream loadbalancer/proxy (like haproxy) that connects with the proxy protocol. The original ip (as exposed with the proxy protocol) will be used as parameter for the 'Client-IP' in the authentication call. Example config: mail { ????server_name mail.example.com; ????auth_http???localhost:9000/; ????server { ????????listen 143 proxy_protocol; ????????protocol imap; ????} } diff -r 70e65bf8dfd7 -r bc79b2baf494 src/mail/ngx_mail.c --- a/src/mail/ngx_mail.c Tue Jul 04 18:50:41 2017 +0300 +++ b/src/mail/ngx_mail.c Fri Jul 07 10:15:05 2017 +0000 @@ -408,6 +408,7 @@ ?#if (NGX_MAIL_SSL) ?????????addrs[i].conf.ssl = addr[i].opt.ssl; ?#endif +????????addrs[i].conf.proxy_protocol = addr[i].opt.proxy_protocol; ? ?????????len = ngx_sock_ntop(&addr[i].opt.sockaddr.sockaddr, addr[i].opt.socklen, ?????????????????????????????buf, NGX_SOCKADDR_STRLEN, 1); @@ -457,6 +458,7 @@ ?#if (NGX_MAIL_SSL) ?????????addrs6[i].conf.ssl = addr[i].opt.ssl; ?#endif +????????addrs6[i].conf.proxy_protocol = addr[i].opt.proxy_protocol; ? ?????????len = ngx_sock_ntop(&addr[i].opt.sockaddr.sockaddr, addr[i].opt.socklen, ?????????????????????????????buf, NGX_SOCKADDR_STRLEN, 1); diff -r 70e65bf8dfd7 -r bc79b2baf494 src/mail/ngx_mail.h --- a/src/mail/ngx_mail.h Tue Jul 04 18:50:41 2017 +0300 +++ b/src/mail/ngx_mail.h Fri Jul 07 10:15:05 2017 +0000 @@ -40,6 +40,7 @@ ?????unsigned????????????????ipv6only:1; ?#endif ?????unsigned????????????????so_keepalive:2; +????unsigned????????????????proxy_protocol:1; ?#if (NGX_HAVE_KEEPALIVE_TUNABLE) ?????int?????????????????????tcp_keepidle; ?????int?????????????????????tcp_keepintvl; @@ -55,6 +56,7 @@ ?????ngx_mail_conf_ctx_t????*ctx; ?????ngx_str_t???????????????addr_text; ?????ngx_uint_t??????????????ssl;????/* unsigned???ssl:1; */ +????unsigned????????????????proxy_protocol:1; ?} ngx_mail_addr_conf_t; ? ?typedef struct { @@ -204,6 +206,8 @@ ?????unsigned????????????????esmtp:1; ?????unsigned????????????????auth_method:3; ?????unsigned????????????????auth_wait:1; +????unsigned????????????????ssl:1; +????unsigned????????????????proxy_protocol:1; ? ?????ngx_str_t???????????????login; ?????ngx_str_t???????????????passwd; diff -r 70e65bf8dfd7 -r bc79b2baf494 src/mail/ngx_mail_auth_http_module.c --- a/src/mail/ngx_mail_auth_http_module.c Tue Jul 04 18:50:41 2017 +0300 +++ b/src/mail/ngx_mail_auth_http_module.c Fri Jul 07 10:15:05 2017 +0000 @@ -1142,6 +1142,7 @@ ?????ngx_mail_ssl_conf_t???????*sslcf; ?#endif ?????ngx_mail_core_srv_conf_t??*cscf; +????ngx_str_t?????????????????*client_addr; ? ?????if (ngx_mail_auth_http_escape(pool, &s->login, &login) != NGX_OK) { ?????????return NULL; @@ -1208,6 +1209,11 @@ ?#endif ? ?????cscf = ngx_mail_get_module_srv_conf(s, ngx_mail_core_module); +????if (s->connection->proxy_protocol_addr.len) { +????????client_addr = &s->connection->proxy_protocol_addr; +????} else { +????????client_addr = &s->connection->addr_text; +????} ? ?????len = sizeof("GET ") - 1 + ahcf->uri.len + sizeof(" HTTP/1.0" CRLF) - 1 ???????????+ sizeof("Host: ") - 1 + ahcf->host_header.len + sizeof(CRLF) - 1 @@ -1221,7 +1227,7 @@ ?????????????????+ sizeof(CRLF) - 1 ???????????+ sizeof("Auth-Login-Attempt: ") - 1 + NGX_INT_T_LEN ?????????????????+ sizeof(CRLF) - 1 -??????????+ sizeof("Client-IP: ") - 1 + s->connection->addr_text.len +??????????+ sizeof("Client-IP: ") - 1 + client_addr->len ?????????????????+ sizeof(CRLF) - 1 ???????????+ sizeof("Client-Host: ") - 1 + s->host.len + sizeof(CRLF) - 1 ???????????+ sizeof("Auth-SMTP-Helo: ") - 1 + s->smtp_helo.len + sizeof(CRLF) - 1 @@ -1287,8 +1293,7 @@ ???????????????????????????s->login_attempt); ? ?????b->last = ngx_cpymem(b->last, "Client-IP: ", sizeof("Client-IP: ") - 1); -????b->last = ngx_copy(b->last, s->connection->addr_text.data, -???????????????????????s->connection->addr_text.len); +????b->last = ngx_copy(b->last, client_addr->data, client_addr->len); ?????*b->last++ = CR; *b->last++ = LF; ? ?????if (s->host.len) { diff -r 70e65bf8dfd7 -r bc79b2baf494 src/mail/ngx_mail_core_module.c --- a/src/mail/ngx_mail_core_module.c Tue Jul 04 18:50:41 2017 +0300 +++ b/src/mail/ngx_mail_core_module.c Fri Jul 07 10:15:05 2017 +0000 @@ -574,6 +574,11 @@ ?#endif ?????????} ? +????????if (ngx_strcmp(value[i].data, "proxy_protocol") == 0) { +????????????ls->proxy_protocol = 1; +????????????continue; +????????} + ?????????ngx_conf_log_error(NGX_LOG_EMERG, cf, 0, ????????????????????????????"the invalid \"%V\" parameter", &value[i]); ?????????return NGX_CONF_ERROR; diff -r 70e65bf8dfd7 -r bc79b2baf494 src/mail/ngx_mail_handler.c --- a/src/mail/ngx_mail_handler.c Tue Jul 04 18:50:41 2017 +0300 +++ b/src/mail/ngx_mail_handler.c Fri Jul 07 10:15:05 2017 +0000 @@ -12,7 +12,7 @@ ? ? ?static void ngx_mail_init_session(ngx_connection_t *c); - +static void ngx_mail_proxy_protocol_handler(ngx_event_t *rev); ?#if (NGX_MAIL_SSL) ?static void ngx_mail_ssl_init_connection(ngx_ssl_t *ssl, ngx_connection_t *c); ?static void ngx_mail_ssl_handshake_handler(ngx_connection_t *c); @@ -143,6 +143,7 @@ ?????ngx_log_error(NGX_LOG_INFO, c->log, 0, "*%uA client %*s connected to %V", ???????????????????c->number, len, text, s->addr_text); ? +????s->proxy_protocol = addr_conf->proxy_protocol; ?????ctx = ngx_palloc(c->pool, sizeof(ngx_mail_log_ctx_t)); ?????if (ctx == NULL) { ?????????ngx_mail_close_connection(c); @@ -165,16 +166,11 @@ ? ?????sslcf = ngx_mail_get_module_srv_conf(s, ngx_mail_ssl_module); ? +????s->ssl = 0; ?????if (sslcf->enable) { -????????c->log->action = "SSL handshaking"; - -????????ngx_mail_ssl_init_connection(&sslcf->ssl, c); -????????return; -????} - -????if (addr_conf->ssl) { - -????????c->log->action = "SSL handshaking"; +????????s->ssl = 1; +????} else if (addr_conf->ssl) { +????????s->ssl = 1; ? ?????????if (sslcf->ssl.ctx == NULL) { ?????????????ngx_log_error(NGX_LOG_ERR, c->log, 0, @@ -183,11 +179,78 @@ ?????????????ngx_mail_close_connection(c); ?????????????return; ?????????} +????} ? +????} +#endif + +????if (s->proxy_protocol) { +????????c->log->action = "reading PROXY protocol"; +????????ngx_add_timer(c->read, cscf->timeout); +????????c->read->handler = ngx_mail_proxy_protocol_handler; +????????if (ngx_handle_read_event(c->read, 0) != NGX_OK) { +????????????ngx_mail_close_connection(c); +????????} +????????return; +????} + +#if (NGX_MAIL_SSL) +????if (s->ssl) { +????????ngx_mail_ssl_conf_t??*sslcf; +????????c->log->action = "SSL handshaking"; +????????sslcf = ngx_mail_get_module_srv_conf(s, ngx_mail_ssl_module); ?????????ngx_mail_ssl_init_connection(&sslcf->ssl, c); ?????????return; ?????} +# endif ? +????ngx_mail_init_session(c); +} + + +void +ngx_mail_proxy_protocol_handler(ngx_event_t *rev) +{ +????u_char????????????????????*p, buf[NGX_PROXY_PROTOCOL_MAX_HEADER + 1]; +????size_t?????????????????????size; +????ssize_t????????????????????n; +????ngx_err_t??????????????????err; +????ngx_connection_t??????????*c; +????ngx_mail_session_t???*s; + +????size = sizeof(buf); +????c = rev->data; + +????n = recv(c->fd, (char *) buf, size, MSG_PEEK); +????err = ngx_socket_errno; + +????if (n == -1) { +????????ngx_connection_error(c, err, "recv() failed"); +????????ngx_mail_close_connection(c); +????????return; +????} +????p = ngx_proxy_protocol_read(c, buf, buf + n); +????if (p == NULL) { +????????ngx_mail_close_connection(c); +????????return; +????} +????size = p - buf; +????if (c->recv(c, buf, size) != (ssize_t) size) { +????????ngx_mail_close_connection(c); +????????return; +????} +????s = c->data; +????s->proxy_protocol = 0; + +#if (NGX_MAIL_SSL) +????{ +????ngx_mail_ssl_conf_t??*sslcf; +????if (s->ssl) { +????????c->log->action = "SSL handshaking"; +????????sslcf = ngx_mail_get_module_srv_conf(s, ngx_mail_ssl_module); +????????ngx_mail_ssl_init_connection(&sslcf->ssl, c); +????????return; +????} ?????} ?#endif ? @@ -222,6 +285,20 @@ ?????ngx_mail_session_t????????*s; ?????ngx_mail_core_srv_conf_t??*cscf; ? +????s = c->data; +????cscf = ngx_mail_get_module_srv_conf(s, ngx_mail_core_module); + +????if (s->proxy_protocol) { +????????ngx_log_error(NGX_LOG_INFO, c->log, 0, "Has proxy_protocol"); +????????c->log->action = "reading PROXY protocol"; +????????ngx_add_timer(c->read, cscf->timeout); +????????c->read->handler = ngx_mail_proxy_protocol_handler; +????????if (ngx_handle_read_event(c->read, 0) != NGX_OK) { +????????????ngx_mail_close_connection(c); +????????} +????????return; +????} + ?????if (ngx_ssl_create_connection(ssl, c, 0) != NGX_OK) { ?????????ngx_mail_close_connection(c); ?????????return; @@ -229,10 +306,6 @@ ? ?????if (ngx_ssl_handshake(c) == NGX_AGAIN) { ? -????????s = c->data; - -????????cscf = ngx_mail_get_module_srv_conf(s, ngx_mail_core_module); - ?????????ngx_add_timer(c->read, cscf->timeout); ? ?????????c->ssl->handler = ngx_mail_ssl_handshake_handler; From xeioex at nginx.com Fri Jul 7 16:17:25 2017 From: xeioex at nginx.com (Dmitry Volyntsev) Date: Fri, 07 Jul 2017 16:17:25 +0000 Subject: [njs] Splitting unit tests and benchmark. Message-ID: details: http://hg.nginx.org/njs/rev/0ad7f75f9dbf branches: changeset: 385:0ad7f75f9dbf user: Dmitry Volyntsev date: Fri Jul 07 19:17:26 2017 +0300 description: Splitting unit tests and benchmark. diffstat: Makefile | 12 ++ njs/test/njs_benchmark.c | 220 +++++++++++++++++++++++++++++++++++++++++++++++ njs/test/njs_unit_test.c | 153 -------------------------------- 3 files changed, 232 insertions(+), 153 deletions(-) diffs (424 lines): diff -r d09638142829 -r 0ad7f75f9dbf Makefile --- a/Makefile Thu Jul 06 19:09:56 2017 +0300 +++ b/Makefile Fri Jul 07 19:17:26 2017 +0300 @@ -76,6 +76,7 @@ all: test lib_test test: \ $(NXT_BUILDDIR)/njs_unit_test \ + $(NXT_BUILDDIR)/njs_benchmark \ $(NXT_BUILDDIR)/njs_unit_test d @@ -396,4 +397,15 @@ dist: $(NXT_BUILDDIR)/libnjs.a \ -lm $(NXT_PCRE_LIB) +$(NXT_BUILDDIR)/njs_benchmark: \ + $(NXT_BUILDDIR)/libnxt.a \ + $(NXT_BUILDDIR)/libnjs.a \ + njs/test/njs_benchmark.c \ + + $(NXT_CC) -o $(NXT_BUILDDIR)/njs_benchmark $(NXT_CFLAGS) \ + -I$(NXT_LIB) -Injs \ + njs/test/njs_benchmark.c \ + $(NXT_BUILDDIR)/libnjs.a \ + -lm $(NXT_PCRE_LIB) + include $(NXT_LIB)/Makefile diff -r d09638142829 -r 0ad7f75f9dbf njs/test/njs_benchmark.c --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/njs/test/njs_benchmark.c Fri Jul 07 19:17:26 2017 +0300 @@ -0,0 +1,220 @@ + +/* + * Copyright (C) Igor Sysoev + * Copyright (C) NGINX, Inc. + */ + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + + +static void * +njs_alloc(void *mem, size_t size) +{ + return nxt_malloc(size); +} + + +static void * +njs_zalloc(void *mem, size_t size) +{ + void *p; + + p = nxt_malloc(size); + + if (p != NULL) { + memset(p, 0, size); + } + + return p; +} + + +static void * +njs_align(void *mem, size_t alignment, size_t size) +{ + return nxt_memalign(alignment, size); +} + + +static void +njs_free(void *mem, void *p) +{ + nxt_free(p); +} + + +static const nxt_mem_proto_t njs_mem_cache_pool_proto = { + njs_alloc, + njs_zalloc, + njs_align, + NULL, + njs_free, + NULL, + NULL, +}; + + +static nxt_int_t +njs_unit_test_benchmark(nxt_str_t *script, nxt_str_t *result, const char *msg, + nxt_uint_t n) +{ + u_char *start; + njs_vm_t *vm, *nvm; + uint64_t us; + nxt_int_t ret; + nxt_str_t s; + nxt_uint_t i; + nxt_bool_t success; + njs_vm_opt_t options; + struct rusage usage; + nxt_mem_cache_pool_t *mcp; + + mcp = nxt_mem_cache_pool_create(&njs_mem_cache_pool_proto, NULL, NULL, + 2 * nxt_pagesize(), 128, 512, 16); + if (nxt_slow_path(mcp == NULL)) { + return NXT_ERROR; + } + + options.mcp = mcp; + options.shared = NULL; + options.externals = NULL; + + vm = njs_vm_create(&options); + if (vm == NULL) { + return NXT_ERROR; + } + + start = script->start; + + ret = njs_vm_compile(vm, &start, start + script->length); + if (ret != NXT_OK) { + return NXT_ERROR; + } + + for (i = 0; i < n; i++) { + + nvm = njs_vm_clone(vm, NULL, NULL); + if (nvm == NULL) { + return NXT_ERROR; + } + + if (njs_vm_run(nvm) == NXT_OK) { + if (njs_vm_retval(nvm, &s) != NXT_OK) { + return NXT_ERROR; + } + + } else { + njs_vm_exception(nvm, &s); + } + + success = nxt_strstr_eq(result, &s); + + if (!success) { + return NXT_ERROR; + } + + njs_vm_destroy(nvm); + } + + nxt_mem_cache_pool_destroy(mcp); + + getrusage(RUSAGE_SELF, &usage); + + us = usage.ru_utime.tv_sec * 1000000 + usage.ru_utime.tv_usec + + usage.ru_stime.tv_sec * 1000000 + usage.ru_stime.tv_usec; + + if (n == 1) { + printf("%s: %.3fs\n", msg, (double) us / 1000000); + + } else { + printf("%s: %.3f?s, %d times/s\n", + msg, (double) us / n, (int) ((uint64_t) n * 1000000 / us)); + } + + return NXT_OK; +} + + +int nxt_cdecl +main(int argc, char **argv) +{ + static nxt_str_t script = nxt_string("null"); + static nxt_str_t result = nxt_string("null"); + + static nxt_str_t fibo_number = nxt_string( + "function fibo(n) {" + " if (n > 1)" + " return fibo(n - 1) + fibo(n - 2)" + " return 1" + "}" + "fibo(32)"); + + static nxt_str_t fibo_ascii = nxt_string( + "function fibo(n) {" + " if (n > 1)" + " return fibo(n - 1) + fibo(n - 2)" + " return '.'" + "}" + "fibo(32).length"); + + static nxt_str_t fibo_bytes = nxt_string( + "var a = '\\x80'.toBytes();" + "function fibo(n) {" + " if (n > 1)" + " return fibo(n - 1) + fibo(n - 2)" + " return a" + "}" + "fibo(32).length"); + + static nxt_str_t fibo_utf8 = nxt_string( + "function fibo(n) {" + " if (n > 1)" + " return fibo(n - 1) + fibo(n - 2)" + " return '?'" + "}" + "fibo(32).length"); + + static nxt_str_t fibo_result = nxt_string("3524578"); + + + if (argc > 1) { + switch (argv[1][0]) { + + case 'v': + return njs_unit_test_benchmark(&script, &result, + "nJSVM clone/destroy", 1000000); + + case 'n': + return njs_unit_test_benchmark(&fibo_number, &fibo_result, + "fibobench numbers", 1); + + case 'a': + return njs_unit_test_benchmark(&fibo_ascii, &fibo_result, + "fibobench ascii strings", 1); + + case 'b': + return njs_unit_test_benchmark(&fibo_bytes, &fibo_result, + "fibobench byte strings", 1); + + case 'u': + return njs_unit_test_benchmark(&fibo_utf8, &fibo_result, + "fibobench utf8 strings", 1); + } + } + + printf("unknown agrument\n"); + return EXIT_FAILURE; +} diff -r d09638142829 -r 0ad7f75f9dbf njs/test/njs_unit_test.c --- a/njs/test/njs_unit_test.c Thu Jul 06 19:09:56 2017 +0300 +++ b/njs/test/njs_unit_test.c Fri Jul 07 19:17:26 2017 +0300 @@ -8224,169 +8224,16 @@ njs_unit_test(nxt_bool_t disassemble) } -static nxt_int_t -njs_unit_test_benchmark(nxt_str_t *script, nxt_str_t *result, const char *msg, - nxt_uint_t n) -{ - void *ext_object; - u_char *start; - njs_vm_t *vm, *nvm; - uint64_t us; - nxt_int_t ret; - nxt_str_t s; - nxt_uint_t i; - nxt_bool_t success; - nxt_lvlhsh_t externals; - njs_vm_opt_t options; - struct rusage usage; - njs_unit_test_req r; - nxt_mem_cache_pool_t *mcp; - - mcp = nxt_mem_cache_pool_create(&njs_mem_cache_pool_proto, NULL, NULL, - 2 * nxt_pagesize(), 128, 512, 16); - if (nxt_slow_path(mcp == NULL)) { - return NXT_ERROR; - } - - r.mem_cache_pool = mcp; - r.uri.length = 6; - r.uri.start = (u_char *) "???"; - - ext_object = &r; - - if (njs_unit_test_externals(&externals, mcp) != NXT_OK) { - return NXT_ERROR; - } - - options.mcp = mcp; - options.shared = NULL; - options.externals = &externals; - - vm = njs_vm_create(&options); - if (vm == NULL) { - return NXT_ERROR; - } - - start = script->start; - - ret = njs_vm_compile(vm, &start, start + script->length); - if (ret != NXT_OK) { - return NXT_ERROR; - } - - for (i = 0; i < n; i++) { - - nvm = njs_vm_clone(vm, NULL, &ext_object); - if (nvm == NULL) { - return NXT_ERROR; - } - - if (njs_vm_run(nvm) == NXT_OK) { - if (njs_vm_retval(nvm, &s) != NXT_OK) { - return NXT_ERROR; - } - - } else { - njs_vm_exception(nvm, &s); - } - - success = nxt_strstr_eq(result, &s); - - if (!success) { - return NXT_ERROR; - } - - njs_vm_destroy(nvm); - } - - nxt_mem_cache_pool_destroy(mcp); - - getrusage(RUSAGE_SELF, &usage); - - us = usage.ru_utime.tv_sec * 1000000 + usage.ru_utime.tv_usec - + usage.ru_stime.tv_sec * 1000000 + usage.ru_stime.tv_usec; - - if (n == 1) { - printf("%s: %.3fs\n", msg, (double) us / 1000000); - - } else { - printf("%s: %.3f?s, %d times/s\n", - msg, (double) us / n, (int) ((uint64_t) n * 1000000 / us)); - } - - return NXT_OK; -} - - int nxt_cdecl main(int argc, char **argv) { nxt_bool_t disassemble; - static nxt_str_t script = nxt_string("null"); - static nxt_str_t result = nxt_string("null"); - - static nxt_str_t fibo_number = nxt_string( - "function fibo(n) {" - " if (n > 1)" - " return fibo(n - 1) + fibo(n - 2)" - " return 1" - "}" - "fibo(32)"); - - static nxt_str_t fibo_ascii = nxt_string( - "function fibo(n) {" - " if (n > 1)" - " return fibo(n - 1) + fibo(n - 2)" - " return '.'" - "}" - "fibo(32).length"); - - static nxt_str_t fibo_bytes = nxt_string( - "var a = '\\x80'.toBytes();" - "function fibo(n) {" - " if (n > 1)" - " return fibo(n - 1) + fibo(n - 2)" - " return a" - "}" - "fibo(32).length"); - - static nxt_str_t fibo_utf8 = nxt_string( - "function fibo(n) {" - " if (n > 1)" - " return fibo(n - 1) + fibo(n - 2)" - " return '?'" - "}" - "fibo(32).length"); - - static nxt_str_t fibo_result = nxt_string("3524578"); - - disassemble = 0; if (argc > 1) { switch (argv[1][0]) { - case 'v': - return njs_unit_test_benchmark(&script, &result, - "nJSVM clone/destroy", 1000000); - - case 'n': - return njs_unit_test_benchmark(&fibo_number, &fibo_result, - "fibobench numbers", 1); - - case 'a': - return njs_unit_test_benchmark(&fibo_ascii, &fibo_result, - "fibobench ascii strings", 1); - - case 'b': - return njs_unit_test_benchmark(&fibo_bytes, &fibo_result, - "fibobench byte strings", 1); - - case 'u': - return njs_unit_test_benchmark(&fibo_utf8, &fibo_result, - "fibobench utf8 strings", 1); - case 'd': disassemble = 1; break; From donatas.abraitis at gmail.com Fri Jul 7 19:28:42 2017 From: donatas.abraitis at gmail.com (Donatas Abraitis) Date: Fri, 7 Jul 2017 22:28:42 +0300 Subject: Variables: Socket cookie variable for debugging purposes Message-ID: Hi, this looks promising when new 4.12 kernel introduced SO_COOKIE socket option which is able to generate a cookie for the socket. More information and implementation is here: https://git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git/commit/?id=5daab9db7b65df87da26fd8cfa695fb9546a1ddb Waiting for comments. # HG changeset patch # User Donatas Abraitis # Date 1499424023 -10800 # Fri Jul 07 13:40:23 2017 +0300 # Node ID 55b401978df27f1a1ab4eee4e50615b7551e3c0b # Parent 70e65bf8dfd7a8d39aae8ac3a209d426e6947735 Add new `socket_cookie` variable This would be useful for tracking connections by cookie, not only by request_id as we have it right now. Related: https://git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git/commit/?id=5daab9db7b65df87da26fd8cfa695fb9546a1ddb diff -r 70e65bf8dfd7 -r 55b401978df2 auto/unix --- a/auto/unix Tue Jul 04 18:50:41 2017 +0300 +++ b/auto/unix Fri Jul 07 13:40:23 2017 +0300 @@ -331,6 +331,16 @@ ngx_feature_test="setsockopt(0, SOL_SOCKET, SO_REUSEPORT, NULL, 0)" . auto/feature +ngx_feature="SO_COOKIE" +ngx_feature_name="NGX_HAVE_SOCKET_COOKIE" +ngx_feature_run=no +ngx_feature_incs="#include " +ngx_feature_path= +ngx_feature_libs= +ngx_feature_test="uint64_t cookie; + socklen_t cookie_len = sizeof(cookie); + getsockopt(0, SOL_SOCKET, SO_COOKIE, &cookie, &cookie_len)" +. auto/feature ngx_feature="SO_ACCEPTFILTER" ngx_feature_name="NGX_HAVE_DEFERRED_ACCEPT" diff -r 70e65bf8dfd7 -r 55b401978df2 src/http/ngx_http_variables.c --- a/src/http/ngx_http_variables.c Tue Jul 04 18:50:41 2017 +0300 +++ b/src/http/ngx_http_variables.c Fri Jul 07 13:40:23 2017 +0300 @@ -46,6 +46,10 @@ ngx_http_variable_value_t *v, uintptr_t data); static ngx_int_t ngx_http_variable_argument(ngx_http_request_t *r, ngx_http_variable_value_t *v, uintptr_t data); +#if (NGX_HAVE_SOCKET_COOKIE) +static ngx_int_t ngx_http_variable_socket_cookie(ngx_http_request_t *r, + ngx_http_variable_value_t *v, uintptr_t data); +#endif #if (NGX_HAVE_TCP_INFO) static ngx_int_t ngx_http_variable_tcpinfo(ngx_http_request_t *r, ngx_http_variable_value_t *v, uintptr_t data); @@ -346,7 +350,10 @@ { ngx_string("time_local"), NULL, ngx_http_variable_time_local, 0, NGX_HTTP_VAR_NOCACHEABLE, 0 }, - +#if (NGX_HAVE_SOCKET_COOKIE) + { ngx_string("socket_cookie"), NULL, ngx_http_variable_socket_cookie, + 0, NGX_HTTP_VAR_NOCACHEABLE, 0 }, +#endif #if (NGX_HAVE_TCP_INFO) { ngx_string("tcpinfo_rtt"), NULL, ngx_http_variable_tcpinfo, 0, NGX_HTTP_VAR_NOCACHEABLE, 0 }, @@ -1098,6 +1105,28 @@ return NGX_OK; } +#if (NGX_HAVE_SOCKET_COOKIE) +static ngx_int_t +ngx_http_variable_socket_cookie(ngx_http_request_t *r, ngx_http_variable_value_t *v, + uintptr_t data) +{ + uint64_t cookie; + socklen_t cookie_len = sizeof(cookie);; + + if (getsockopt(0, SOL_SOCKET, SO_COOKIE, &cookie, &cookie_len) == -1) { + v->not_found = 1; + return NGX_OK; + } + + v->data = cookie; + v->len = cookie_len; + v->valid = 1; + v->no_cacheable = 0; + v->not_found = 0; + + return NGX_OK; +} +#endif #if (NGX_HAVE_TCP_INFO) -- Donatas From vbart at nginx.com Mon Jul 10 15:26:23 2017 From: vbart at nginx.com (Valentin V. Bartenev) Date: Mon, 10 Jul 2017 18:26:23 +0300 Subject: [PATCH 03 of 14] HTTP/2: add debug logging of control frames In-Reply-To: References: <5f5d70428655db0889a2.1498163585@piotrsikora.sfo.corp.google.com> <18284940.HFE4rYao7p@vbart-workstation> Message-ID: <1559042.dVZZclmnl0@vbart-workstation> On Wednesday 05 July 2017 03:02:55 Piotr Sikora via nginx-devel wrote: > Hey Valentin, > comments below. I commented only on the first occurrence, but > obviously those comments apply to all similar changes. > > > ngx_log_debug0(NGX_LOG_DEBUG_HTTP, h2c->connection->log, 0, > > - "http2 SETTINGS frame ack:1"); > > + "http2 SETTINGS ACK frame"); > > I don't particularly like this change, since it makes it look like > this is a "SETTINGS ACK" frame, not a "SETTINGS" frame with ACK flag > set. This is even more confusing since QUIC drafts had "SETTINGS_ACK" > frame at some point. > > Maybe "http2 SETTINGS frame ACK" would be more acceptable? Yes, "http2 SETTINGS frame ACK" looks good. > > > ngx_log_debug1(NGX_LOG_DEBUG_HTTP, h2c->connection->log, 0, > > - "http2 SETTINGS frame params:%uz", > > + "http2 SETTINGS frame with %uz params", > > h2c->state.length / NGX_HTTP_V2_SETTINGS_PARAM_SIZE); > > The extra "with" doesn't add any information, and it doesn't seem to > be inline with other debug logs, but I don't mind this change too > much. > > > ngx_log_debug1(NGX_LOG_DEBUG_HTTP, h2c->connection->log, 0, > > - "http2 SETTINGS param HEADER_TABLE_SIZE:%ui " > > + "http2 SETTINGS param HEADER_TABLE_SIZE: %ui " > > "(ignored)", value); > > This is fine with me, but again, the extra space doesn't seem to be > inline with other debug logs, which usually don't include space > between "key:" and "value". This is similar to headers debug lines. No space is usually used in cases when there are multiple small parameters. > > > ngx_log_debug2(NGX_LOG_DEBUG_HTTP, h2c->connection->log, 0, > > - "http2 SETTINGS param 0x%Xi:%ui " > > - "(ignored)", id, value); > > + "http2 unknown SETTINGS param id:0x%Xi value:%ui", > > + id, value); > > I'd prefer if we could stick to the "http2 SETTINGS" prefix here, > otherwise it won't look like part of the same frame, i.e.: > > http2 SETTINGS frame with 3 params > http2 SETTINGS param HEADER_TABLE_SIZE: 4096 > http2 SETTINGS param INITIAL_WINDOW_SIZE: 65536 > http2 unknown SETTINGS param id:0xAA value:1234 > > Also, " (ignored)" part was removed, which makes it inconsistent with > other ignored parameters. > > Maybe "http2 SETTINGS unknown param id:0x%Xi value:%ui (ignored)" or [..] This one looks good enough, but I think that "(ignored)" is excessive information. There's nothing else to do with unknown parameter anyway. wbr, Valentin V. Bartenev From mdounin at mdounin.ru Tue Jul 11 15:12:03 2017 From: mdounin at mdounin.ru (Maxim Dounin) Date: Tue, 11 Jul 2017 18:12:03 +0300 Subject: [PATCH] Add proxy_protocol option to mail listener In-Reply-To: <1499434682.21080.97.camel@gmail.com> References: <1499434682.21080.97.camel@gmail.com> Message-ID: <20170711151203.GV55433@mdounin.ru> Hello! On Fri, Jul 07, 2017 at 03:38:02PM +0200, Kees Bos wrote: > # HG changeset patch > # User Kees Bos > # Date 1499422505 0 > #??????Fri Jul 07 10:15:05 2017 +0000 > # Node ID bc79b2baf494aabb889de1e5dbe3184ff0cb9bfa > # Parent??70e65bf8dfd7a8d39aae8ac3a209d426e6947735 > Add proxy_protocol option to mail listener > > Add support for the mail handlers. This enables the use of an upstream > loadbalancer/proxy (like haproxy) that connects with the proxy protocol. > > The original ip (as exposed with the proxy protocol) will be used as > parameter for the 'Client-IP' in the authentication call. > > Example config: > mail { > ????server_name mail.example.com; > ????auth_http???localhost:9000/; > > ????server { > ????????listen 143 proxy_protocol; > ????????protocol imap; > ????} > } I see at least the following problems in this patch: 1. The implementation is not complete compared to other modules (http, stream): it only tries to change the address passed as Client-IP in auth_http, but not the address used for logging and/or for XCLIENT. 2. It unconditionally trusts all clients who can connect to the port in question. This doesn't look wise. Just for the reference, here is a review of an earlier attempt to introduce proxy_protocol support in the mail proxy: http://mailman.nginx.org/pipermail/nginx-devel/2016-November/009084.html [...] > @@ -55,6 +56,7 @@ > ?????ngx_mail_conf_ctx_t????*ctx; > ?????ngx_str_t???????????????addr_text; > ?????ngx_uint_t??????????????ssl;????/* unsigned???ssl:1; */ > +????unsigned????????????????proxy_protocol:1; Note that "/* unsigned???ssl:1; */" comment here means that if we are going to add other bitfield options, the ssl field should be changed to appthis should be changed to appropriate bitfield. [...] -- Maxim Dounin http://nginx.org/ From mdounin at mdounin.ru Tue Jul 11 15:20:27 2017 From: mdounin at mdounin.ru (Maxim Dounin) Date: Tue, 11 Jul 2017 18:20:27 +0300 Subject: Variables: Socket cookie variable for debugging purposes In-Reply-To: References: Message-ID: <20170711152027.GW55433@mdounin.ru> Hello! On Fri, Jul 07, 2017 at 10:28:42PM +0300, Donatas Abraitis wrote: > this looks promising when new 4.12 kernel introduced SO_COOKIE socket > option which is able to generate a cookie for the socket. > > More information and implementation is here: > https://git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git/commit/?id=5daab9db7b65df87da26fd8cfa695fb9546a1ddb > > Waiting for comments. > > # HG changeset patch > # User Donatas Abraitis > # Date 1499424023 -10800 > # Fri Jul 07 13:40:23 2017 +0300 > # Node ID 55b401978df27f1a1ab4eee4e50615b7551e3c0b > # Parent 70e65bf8dfd7a8d39aae8ac3a209d426e6947735 > Add new `socket_cookie` variable > > This would be useful for tracking connections by cookie, not only by > request_id as we have it right now. Related: > https://git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git/commit/?id=5daab9db7b65df87da26fd8cfa695fb9546a1ddb It is not clear if such a variable is indeed beneficial, and how it can be used. Shouldn't client's address with port be good enough to identify a connection, at least in most practical cases? If you think it worth adding, please elaborate a bit more on how it is expected to be used. Alternatively, consider providing a module which exposes the variable, it should be trivial to implement. [...] -- Maxim Dounin http://nginx.org/ From mdounin at mdounin.ru Tue Jul 11 15:41:57 2017 From: mdounin at mdounin.ru (Maxim Dounin) Date: Tue, 11 Jul 2017 15:41:57 +0000 Subject: [nginx] Range filter: protect from total size overflows. Message-ID: details: http://hg.nginx.org/nginx/rev/e02555553d0b branches: changeset: 7054:e02555553d0b user: Maxim Dounin date: Tue Jul 11 16:06:23 2017 +0300 description: Range filter: protect from total size overflows. The overflow can be used to circumvent the restriction on total size of ranges introduced in c2a91088b0c0 (1.1.2). Additionally, overflow allows producing ranges with negative start (such ranges can be created by using a suffix, "bytes=-100"; normally this results in 200 due to the total size check). These can result in the following errors in logs: [crit] ... pread() ... failed (22: Invalid argument) [alert] ... sendfile() failed (22: Invalid argument) When using cache, it can be also used to reveal cache file header. It is believed that there are no other negative effects, at least with standard nginx modules. In theory, this can also result in memory disclosure and/or segmentation faults if multiple ranges are allowed, and the response is returned in a single in-memory buffer. This never happens with standard nginx modules though, as well as known 3rd party modules. Fix is to properly protect from possible overflow when incrementing size. diffstat: src/http/modules/ngx_http_range_filter_module.c | 4 ++++ 1 files changed, 4 insertions(+), 0 deletions(-) diffs (14 lines): diff --git a/src/http/modules/ngx_http_range_filter_module.c b/src/http/modules/ngx_http_range_filter_module.c --- a/src/http/modules/ngx_http_range_filter_module.c +++ b/src/http/modules/ngx_http_range_filter_module.c @@ -377,6 +377,10 @@ ngx_http_range_parse(ngx_http_request_t range->start = start; range->end = end; + if (size > NGX_MAX_OFF_T_VALUE - (end - start)) { + return NGX_HTTP_RANGE_NOT_SATISFIABLE; + } + size += end - start; if (ranges-- == 0) { From mdounin at mdounin.ru Tue Jul 11 15:42:00 2017 From: mdounin at mdounin.ru (Maxim Dounin) Date: Tue, 11 Jul 2017 15:42:00 +0000 Subject: [nginx] Range filter: avoid negative range start. Message-ID: details: http://hg.nginx.org/nginx/rev/887c8c58ffeb branches: changeset: 7055:887c8c58ffeb user: Maxim Dounin date: Tue Jul 11 16:06:26 2017 +0300 description: Range filter: avoid negative range start. Suffix ranges no longer allowed to set negative start values, to prevent ranges with negative start from appearing even if total size protection will be removed. diffstat: src/http/modules/ngx_http_range_filter_module.c | 2 +- 1 files changed, 1 insertions(+), 1 deletions(-) diffs (12 lines): diff --git a/src/http/modules/ngx_http_range_filter_module.c b/src/http/modules/ngx_http_range_filter_module.c --- a/src/http/modules/ngx_http_range_filter_module.c +++ b/src/http/modules/ngx_http_range_filter_module.c @@ -355,7 +355,7 @@ ngx_http_range_parse(ngx_http_request_t } if (suffix) { - start = content_length - end; + start = (end < content_length) ? content_length - end : 0; end = content_length - 1; } From mdounin at mdounin.ru Tue Jul 11 15:42:03 2017 From: mdounin at mdounin.ru (Maxim Dounin) Date: Tue, 11 Jul 2017 15:42:03 +0000 Subject: [nginx] nginx-1.13.3-RELEASE Message-ID: details: http://hg.nginx.org/nginx/rev/8457ce87640f branches: changeset: 7056:8457ce87640f user: Maxim Dounin date: Tue Jul 11 16:18:30 2017 +0300 description: nginx-1.13.3-RELEASE diffstat: docs/xml/nginx/changes.xml | 20 ++++++++++++++++++++ 1 files changed, 20 insertions(+), 0 deletions(-) diffs (30 lines): diff --git a/docs/xml/nginx/changes.xml b/docs/xml/nginx/changes.xml --- a/docs/xml/nginx/changes.xml +++ b/docs/xml/nginx/changes.xml @@ -5,6 +5,26 @@ + + + + +?????????? ????????? ?????? ??? ??????? ????????????? ???????????? +? range-??????? ? ??????????? ???????????? ????????? ??????????? ??????????, +??? ???????????? ????? ???????? ? ?????? ???????????????? ?????????? +(CVE-2017-7529). + + +a specially crafted request might result in an integer overflow +and incorrect processing of ranges in the range filter, +potentially resulting in sensitive information leak +(CVE-2017-7529). + + + + + + From mdounin at mdounin.ru Tue Jul 11 15:42:05 2017 From: mdounin at mdounin.ru (Maxim Dounin) Date: Tue, 11 Jul 2017 15:42:05 +0000 Subject: [nginx] release-1.13.3 tag Message-ID: details: http://hg.nginx.org/nginx/rev/b005ff2ce688 branches: changeset: 7057:b005ff2ce688 user: Maxim Dounin date: Tue Jul 11 16:18:31 2017 +0300 description: release-1.13.3 tag diffstat: .hgtags | 1 + 1 files changed, 1 insertions(+), 0 deletions(-) diffs (8 lines): diff --git a/.hgtags b/.hgtags --- a/.hgtags +++ b/.hgtags @@ -415,3 +415,4 @@ 3d0e8655f897959e48cc74e87670bb5492a58871 3671096a45bce570a2afa20b9faf42c7fb0f7e66 release-1.13.0 539f7893ecb96bee60965528c8958d7eb2f1ce6b release-1.13.1 5be2b25bdc65775a85f18f68a4be4f58c7384415 release-1.13.2 +8457ce87640f9bfe6221c4ac4466ced20e03bebe release-1.13.3 From mdounin at mdounin.ru Tue Jul 11 15:42:08 2017 From: mdounin at mdounin.ru (Maxim Dounin) Date: Tue, 11 Jul 2017 15:42:08 +0000 Subject: [nginx] Version bump. Message-ID: details: http://hg.nginx.org/nginx/rev/b2c14a9ef70e branches: stable-1.12 changeset: 7058:b2c14a9ef70e user: Maxim Dounin date: Tue Jul 11 16:19:05 2017 +0300 description: Version bump. diffstat: src/core/nginx.h | 4 ++-- 1 files changed, 2 insertions(+), 2 deletions(-) diffs (14 lines): diff --git a/src/core/nginx.h b/src/core/nginx.h --- a/src/core/nginx.h +++ b/src/core/nginx.h @@ -9,8 +9,8 @@ #define _NGINX_H_INCLUDED_ -#define nginx_version 1012000 -#define NGINX_VERSION "1.12.0" +#define nginx_version 1012001 +#define NGINX_VERSION "1.12.1" #define NGINX_VER "nginx/" NGINX_VERSION #ifdef NGX_BUILD From mdounin at mdounin.ru Tue Jul 11 15:42:10 2017 From: mdounin at mdounin.ru (Maxim Dounin) Date: Tue, 11 Jul 2017 15:42:10 +0000 Subject: [nginx] Updated OpenSSL used for win32 builds. Message-ID: details: http://hg.nginx.org/nginx/rev/f38e906c8166 branches: stable-1.12 changeset: 7059:f38e906c8166 user: Maxim Dounin date: Tue May 30 17:14:00 2017 +0300 description: Updated OpenSSL used for win32 builds. diffstat: misc/GNUmakefile | 2 +- 1 files changed, 1 insertions(+), 1 deletions(-) diffs (12 lines): diff --git a/misc/GNUmakefile b/misc/GNUmakefile --- a/misc/GNUmakefile +++ b/misc/GNUmakefile @@ -6,7 +6,7 @@ TEMP = tmp CC = cl OBJS = objs.msvc8 -OPENSSL = openssl-1.0.2k +OPENSSL = openssl-1.0.2l ZLIB = zlib-1.2.11 PCRE = pcre-8.40 From mdounin at mdounin.ru Tue Jul 11 15:42:13 2017 From: mdounin at mdounin.ru (Maxim Dounin) Date: Tue, 11 Jul 2017 15:42:13 +0000 Subject: [nginx] Range filter: protect from total size overflows. Message-ID: details: http://hg.nginx.org/nginx/rev/1adc6b0d5eaa branches: stable-1.12 changeset: 7060:1adc6b0d5eaa user: Maxim Dounin date: Tue Jul 11 16:06:23 2017 +0300 description: Range filter: protect from total size overflows. The overflow can be used to circumvent the restriction on total size of ranges introduced in c2a91088b0c0 (1.1.2). Additionally, overflow allows producing ranges with negative start (such ranges can be created by using a suffix, "bytes=-100"; normally this results in 200 due to the total size check). These can result in the following errors in logs: [crit] ... pread() ... failed (22: Invalid argument) [alert] ... sendfile() failed (22: Invalid argument) When using cache, it can be also used to reveal cache file header. It is believed that there are no other negative effects, at least with standard nginx modules. In theory, this can also result in memory disclosure and/or segmentation faults if multiple ranges are allowed, and the response is returned in a single in-memory buffer. This never happens with standard nginx modules though, as well as known 3rd party modules. Fix is to properly protect from possible overflow when incrementing size. diffstat: src/http/modules/ngx_http_range_filter_module.c | 4 ++++ 1 files changed, 4 insertions(+), 0 deletions(-) diffs (14 lines): diff --git a/src/http/modules/ngx_http_range_filter_module.c b/src/http/modules/ngx_http_range_filter_module.c --- a/src/http/modules/ngx_http_range_filter_module.c +++ b/src/http/modules/ngx_http_range_filter_module.c @@ -377,6 +377,10 @@ ngx_http_range_parse(ngx_http_request_t range->start = start; range->end = end; + if (size > NGX_MAX_OFF_T_VALUE - (end - start)) { + return NGX_HTTP_RANGE_NOT_SATISFIABLE; + } + size += end - start; if (ranges-- == 0) { From mdounin at mdounin.ru Tue Jul 11 15:42:15 2017 From: mdounin at mdounin.ru (Maxim Dounin) Date: Tue, 11 Jul 2017 15:42:15 +0000 Subject: [nginx] nginx-1.12.1-RELEASE Message-ID: details: http://hg.nginx.org/nginx/rev/08b443b6b59d branches: stable-1.12 changeset: 7061:08b443b6b59d user: Maxim Dounin date: Tue Jul 11 16:24:04 2017 +0300 description: nginx-1.12.1-RELEASE diffstat: docs/xml/nginx/changes.xml | 20 ++++++++++++++++++++ 1 files changed, 20 insertions(+), 0 deletions(-) diffs (30 lines): diff --git a/docs/xml/nginx/changes.xml b/docs/xml/nginx/changes.xml --- a/docs/xml/nginx/changes.xml +++ b/docs/xml/nginx/changes.xml @@ -5,6 +5,26 @@ + + + + +?????????? ????????? ?????? ??? ??????? ????????????? ???????????? +? range-??????? ? ??????????? ???????????? ????????? ??????????? ??????????, +??? ???????????? ????? ???????? ? ?????? ???????????????? ?????????? +(CVE-2017-7529). + + +a specially crafted request might result in an integer overflow +and incorrect processing of ranges in the range filter, +potentially resulting in sensitive information leak +(CVE-2017-7529). + + + + + + From mdounin at mdounin.ru Tue Jul 11 15:42:18 2017 From: mdounin at mdounin.ru (Maxim Dounin) Date: Tue, 11 Jul 2017 15:42:18 +0000 Subject: [nginx] release-1.12.1 tag Message-ID: details: http://hg.nginx.org/nginx/rev/7e661410c076 branches: stable-1.12 changeset: 7062:7e661410c076 user: Maxim Dounin date: Tue Jul 11 16:24:05 2017 +0300 description: release-1.12.1 tag diffstat: .hgtags | 1 + 1 files changed, 1 insertions(+), 0 deletions(-) diffs (8 lines): diff --git a/.hgtags b/.hgtags --- a/.hgtags +++ b/.hgtags @@ -413,3 +413,4 @@ d8b321a876d6254e9e98795e3b194ef053290354 7f394e433f0003222aa6531931ecc0b24740d5e4 release-1.11.12 3d0e8655f897959e48cc74e87670bb5492a58871 release-1.11.13 e265d962841f90f1fa148c8f4eed4a4d3a9b0208 release-1.12.0 +08b443b6b59dbe5d02354047c649a00c40e7b748 release-1.12.1 From mdounin at mdounin.ru Tue Jul 11 17:18:06 2017 From: mdounin at mdounin.ru (Maxim Dounin) Date: Tue, 11 Jul 2017 17:18:06 +0000 Subject: [nginx] Version bump. Message-ID: details: http://hg.nginx.org/nginx/rev/0434f71164f4 branches: changeset: 7063:0434f71164f4 user: Maxim Dounin date: Tue Jul 11 19:59:16 2017 +0300 description: Version bump. diffstat: src/core/nginx.h | 4 ++-- 1 files changed, 2 insertions(+), 2 deletions(-) diffs (14 lines): diff --git a/src/core/nginx.h b/src/core/nginx.h --- a/src/core/nginx.h +++ b/src/core/nginx.h @@ -9,8 +9,8 @@ #define _NGINX_H_INCLUDED_ -#define nginx_version 1013003 -#define NGINX_VERSION "1.13.3" +#define nginx_version 1013004 +#define NGINX_VERSION "1.13.4" #define NGINX_VER "nginx/" NGINX_VERSION #ifdef NGX_BUILD From mdounin at mdounin.ru Tue Jul 11 17:18:09 2017 From: mdounin at mdounin.ru (Maxim Dounin) Date: Tue, 11 Jul 2017 17:18:09 +0000 Subject: [nginx] Core: disabled SO_REUSEPORT when testing config (ticket #1300). Message-ID: details: http://hg.nginx.org/nginx/rev/ecb5cd305b06 branches: changeset: 7064:ecb5cd305b06 user: Maxim Dounin date: Tue Jul 11 19:59:56 2017 +0300 description: Core: disabled SO_REUSEPORT when testing config (ticket #1300). When closing a socket with SO_REUSEPORT, Linux drops all connections waiting in this socket's listen queue. Previously, it was believed to only result in connection resets when reconfiguring nginx to use smaller number of worker processes. It also results in connection resets during configuration testing though. Workaround is to avoid using SO_REUSEPORT when testing configuration. It should prevent listening sockets from being created if a conflicting socket already exists, while still preserving detection of other possible errors. It should also cover UDP sockets. The only downside of this approach seems to be that a configuration testing won't be able to properly report the case when nginx was compiled with SO_REUSEPORT, but the kernel is not able to set it. Such errors will be reported on a real start instead. diffstat: src/core/ngx_connection.c | 2 +- 1 files changed, 1 insertions(+), 1 deletions(-) diffs (12 lines): diff --git a/src/core/ngx_connection.c b/src/core/ngx_connection.c --- a/src/core/ngx_connection.c +++ b/src/core/ngx_connection.c @@ -473,7 +473,7 @@ ngx_open_listening_sockets(ngx_cycle_t * #if (NGX_HAVE_REUSEPORT) - if (ls[i].reuseport) { + if (ls[i].reuseport && !ngx_test_config) { int reuseport; reuseport = 1; From mdounin at mdounin.ru Tue Jul 11 17:18:12 2017 From: mdounin at mdounin.ru (Maxim Dounin) Date: Tue, 11 Jul 2017 17:18:12 +0000 Subject: [nginx] Core: fixed error message on setsockopt(SO_REUSEPORT) failure. Message-ID: details: http://hg.nginx.org/nginx/rev/c0d89f602d08 branches: changeset: 7065:c0d89f602d08 user: Maxim Dounin date: Tue Jul 11 20:06:52 2017 +0300 description: Core: fixed error message on setsockopt(SO_REUSEPORT) failure. The error is fatal when configuring a new socket, so the ", ignored" part is not appropriate and was removed. diffstat: src/core/ngx_connection.c | 2 +- 1 files changed, 1 insertions(+), 1 deletions(-) diffs (12 lines): diff --git a/src/core/ngx_connection.c b/src/core/ngx_connection.c --- a/src/core/ngx_connection.c +++ b/src/core/ngx_connection.c @@ -483,7 +483,7 @@ ngx_open_listening_sockets(ngx_cycle_t * == -1) { ngx_log_error(NGX_LOG_EMERG, log, ngx_socket_errno, - "setsockopt(SO_REUSEPORT) %V failed, ignored", + "setsockopt(SO_REUSEPORT) %V failed", &ls[i].addr_text); if (ngx_close_socket(s) == -1) { From utkarsh.tewari at sjsu.edu Tue Jul 11 18:00:50 2017 From: utkarsh.tewari at sjsu.edu (Utkarsh Tewari) Date: Tue, 11 Jul 2017 11:00:50 -0700 Subject: SSL: Accepting early data in TLSv1.3 Message-ID: Hello, I am using OpenSSL s_client to send early data during resumption over a TLS1.3 connection. However, the server rejects it as shown below. Reused, TLSv1.3, Cipher is TLS13-AES-128-GCM-SHA256 Server public key is 2048 bit Secure Renegotiation IS NOT supported Compression: NONE Expansion: NONE No ALPN negotiated *Early data was rejected* SSL-Session: Protocol : TLSv1.3 Cipher : TLS13-AES-128-GCM-SHA256 Is there any way to accept early data on the server? I am using a basic server config: worker_processes 1; > events {worker_connections 1024; > } > http { > include mime.types; > default_type application/octet-stream; > sendfile on; > keepalive_timeout 10m; > server { > listen 127.0.0.1:443; > ssl on; > ssl_prefer_server_ciphers on; > ssl_protocols TLSv1.3; > ssl_ciphers TLS13-AES-128-GCM-SHA256; > #ssl_ecdh_curve secp384r1:X25519; > ssl_certificate /usr/local/nginx/certs/nginx-selfsigned.crt; > ssl_certificate_key /usr/local/nginx/certs/nginx-selfsigned.key; > # ssl_dhparam /usr/local/nginx/ssl/certs/dhparam.pem; > ssl_session_tickets on; > ssl_session_cache shared:SSL:10m; > ssl_session_timeout 10m; > keepalive_timeout 7200s; > location / {root html; > index index.html index.htm; > } > } > } Cheers, Utkarsh ? -------------- next part -------------- An HTML attachment was scrubbed... URL: From mdounin at mdounin.ru Tue Jul 11 18:33:24 2017 From: mdounin at mdounin.ru (Maxim Dounin) Date: Tue, 11 Jul 2017 21:33:24 +0300 Subject: SSL: Accepting early data in TLSv1.3 In-Reply-To: References: Message-ID: <20170711183324.GP55433@mdounin.ru> Hello! On Tue, Jul 11, 2017 at 11:00:50AM -0700, Utkarsh Tewari wrote: > Hello, > > I am using OpenSSL s_client to send early data during resumption over a > TLS1.3 connection. However, the server rejects it as shown below. > > > Reused, TLSv1.3, Cipher is TLS13-AES-128-GCM-SHA256 > Server public key is 2048 bit > Secure Renegotiation IS NOT supported > Compression: NONE > Expansion: NONE > No ALPN negotiated > *Early data was rejected* > SSL-Session: > Protocol : TLSv1.3 > Cipher : TLS13-AES-128-GCM-SHA256 > > > Is there any way to accept early data on the server? No. As of now, early data is not supported by nginx. Note well that early data requires special handling and using it implies different security guarantees from the protocol - notably, there is no replay protection. If/when supported, early data will not be enabled by default, but instead will require an explicit configuration option to enable it. -- Maxim Dounin http://nginx.org/ From donatas.abraitis at gmail.com Tue Jul 11 19:18:00 2017 From: donatas.abraitis at gmail.com (Donatas Abraitis) Date: Tue, 11 Jul 2017 22:18:00 +0300 Subject: Variables: Socket cookie variable for debugging purposes In-Reply-To: <20170711152027.GW55433@mdounin.ru> References: <20170711152027.GW55433@mdounin.ru> Message-ID: In short, it provides unique socket identifier. * It would be simpler to identify connections and filter them out by $socket_cookie only. As an example could be a custom response header `X-Request: $socket_cookie:$request_id`, or just `X-Socket-Id: $socket_cookie`. * Another example could be to use some other fancy stuff like load balancing (hashing) by $socket_cookie. At the moment at 000webhost.com we are using $request_id to identify requests for clients, but $socket_cookie would be helpful too. On Tue, Jul 11, 2017 at 6:20 PM, Maxim Dounin wrote: > Hello! > > On Fri, Jul 07, 2017 at 10:28:42PM +0300, Donatas Abraitis wrote: > >> this looks promising when new 4.12 kernel introduced SO_COOKIE socket >> option which is able to generate a cookie for the socket. >> >> More information and implementation is here: >> https://git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git/commit/?id=5daab9db7b65df87da26fd8cfa695fb9546a1ddb >> >> Waiting for comments. >> >> # HG changeset patch >> # User Donatas Abraitis >> # Date 1499424023 -10800 >> # Fri Jul 07 13:40:23 2017 +0300 >> # Node ID 55b401978df27f1a1ab4eee4e50615b7551e3c0b >> # Parent 70e65bf8dfd7a8d39aae8ac3a209d426e6947735 >> Add new `socket_cookie` variable >> >> This would be useful for tracking connections by cookie, not only by >> request_id as we have it right now. Related: >> https://git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git/commit/?id=5daab9db7b65df87da26fd8cfa695fb9546a1ddb > > It is not clear if such a variable is indeed beneficial, and how > it can be used. Shouldn't client's address with port be good > enough to identify a connection, at least in most practical cases? > > If you think it worth adding, please elaborate a bit more on how > it is expected to be used. > > Alternatively, consider providing a module which exposes the > variable, it should be trivial to implement. > > [...] > > -- > Maxim Dounin > http://nginx.org/ > _______________________________________________ > nginx-devel mailing list > nginx-devel at nginx.org > http://mailman.nginx.org/mailman/listinfo/nginx-devel -- Donatas From mdounin at mdounin.ru Tue Jul 11 19:58:26 2017 From: mdounin at mdounin.ru (Maxim Dounin) Date: Tue, 11 Jul 2017 22:58:26 +0300 Subject: Variables: Socket cookie variable for debugging purposes In-Reply-To: References: <20170711152027.GW55433@mdounin.ru> Message-ID: <20170711195826.GQ55433@mdounin.ru> Hello! On Tue, Jul 11, 2017 at 10:18:00PM +0300, Donatas Abraitis wrote: > In short, it provides unique socket identifier. > > * It would be simpler to identify connections and filter them out by > $socket_cookie only. As an example could be a custom response header > `X-Request: $socket_cookie:$request_id`, or just `X-Socket-Id: > $socket_cookie`. So how do you expect to use it? And why you need $socket_cookie if there is $request_id and/or $connection? > * Another example could be to use some other fancy stuff like load > balancing (hashing) by $socket_cookie. I see no difference with using $connection, $request_id, or any other number. If you think there is a difference, please elaborate. > At the moment at 000webhost.com we are using $request_id to identify > requests for clients, but $socket_cookie would be helpful too. Note that $socket_cookie cannot be used to identify requests, it can only be used to identify connections. There may be multiple requests in a connection. Overral, it is still not clear if proposed variable is beneficial and how it is expected to be used. If you think it is useful, consider writing a module which provides the variable. -- Maxim Dounin http://nginx.org/ From donatas.abraitis at gmail.com Tue Jul 11 20:06:08 2017 From: donatas.abraitis at gmail.com (Donatas Abraitis) Date: Tue, 11 Jul 2017 23:06:08 +0300 Subject: Variables: Socket cookie variable for debugging purposes In-Reply-To: <20170711195826.GQ55433@mdounin.ru> References: <20170711152027.GW55433@mdounin.ru> <20170711195826.GQ55433@mdounin.ru> Message-ID: I haven't seen $connection before. Dunno how I missed it. On Tue, Jul 11, 2017 at 10:58 PM, Maxim Dounin wrote: > Hello! > > On Tue, Jul 11, 2017 at 10:18:00PM +0300, Donatas Abraitis wrote: > >> In short, it provides unique socket identifier. >> >> * It would be simpler to identify connections and filter them out by >> $socket_cookie only. As an example could be a custom response header >> `X-Request: $socket_cookie:$request_id`, or just `X-Socket-Id: >> $socket_cookie`. > > So how do you expect to use it? And why you need $socket_cookie > if there is $request_id and/or $connection? > >> * Another example could be to use some other fancy stuff like load >> balancing (hashing) by $socket_cookie. > > I see no difference with using $connection, $request_id, or any > other number. If you think there is a difference, please > elaborate. > >> At the moment at 000webhost.com we are using $request_id to identify >> requests for clients, but $socket_cookie would be helpful too. > > Note that $socket_cookie cannot be used to identify requests, it > can only be used to identify connections. There may be multiple > requests in a connection. > > Overral, it is still not clear if proposed variable is beneficial > and how it is expected to be used. If you think it is useful, > consider writing a module which provides the variable. > > -- > Maxim Dounin > http://nginx.org/ > _______________________________________________ > nginx-devel mailing list > nginx-devel at nginx.org > http://mailman.nginx.org/mailman/listinfo/nginx-devel -- Donatas From ru at nginx.com Wed Jul 12 08:34:37 2017 From: ru at nginx.com (Ruslan Ermilov) Date: Wed, 12 Jul 2017 08:34:37 +0000 Subject: [nginx] Style: aligned ngx_null_command. Message-ID: details: http://hg.nginx.org/nginx/rev/a27e0c7e198c branches: changeset: 7066:a27e0c7e198c user: Ruslan Ermilov date: Wed Jul 12 11:34:04 2017 +0300 description: Style: aligned ngx_null_command. diffstat: src/misc/ngx_google_perftools_module.c | 2 +- 1 files changed, 1 insertions(+), 1 deletions(-) diffs (12 lines): diff -r c0d89f602d08 -r a27e0c7e198c src/misc/ngx_google_perftools_module.c --- a/src/misc/ngx_google_perftools_module.c Tue Jul 11 20:06:52 2017 +0300 +++ b/src/misc/ngx_google_perftools_module.c Wed Jul 12 11:34:04 2017 +0300 @@ -36,7 +36,7 @@ static ngx_command_t ngx_google_perftoo offsetof(ngx_google_perftools_conf_t, profiles), NULL }, - ngx_null_command + ngx_null_command }; From cornelis.bos at gmail.com Wed Jul 12 12:08:31 2017 From: cornelis.bos at gmail.com (Kees Bos) Date: Wed, 12 Jul 2017 14:08:31 +0200 Subject: [PATCH] Add proxy_protocol option to mail listener In-Reply-To: <20170711151203.GV55433@mdounin.ru> References: <1499434682.21080.97.camel@gmail.com> <20170711151203.GV55433@mdounin.ru> Message-ID: <1499861311.25851.54.camel@gmail.com> On di, 2017-07-11 at 18:12 +0300, Maxim Dounin wrote: > Hello! > > On Fri, Jul 07, 2017 at 03:38:02PM +0200, Kees Bos wrote: > > > > > # HG changeset patch > > # User Kees Bos > > # Date 1499422505 0 > > #??????Fri Jul 07 10:15:05 2017 +0000 > > # Node ID bc79b2baf494aabb889de1e5dbe3184ff0cb9bfa > > # Parent??70e65bf8dfd7a8d39aae8ac3a209d426e6947735 > > Add proxy_protocol option to mail listener > > > > Add support for the mail handlers. This enables the use of an > > upstream > > loadbalancer/proxy (like haproxy) that connects with the proxy > > protocol. > > > > The original ip (as exposed with the proxy protocol) will be used > > as > > parameter for the 'Client-IP' in the authentication call. > > > > Example config: > > mail { > > ????server_name mail.example.com; > > ????auth_http???localhost:9000/; > > > > ????server { > > ????????listen 143 proxy_protocol; > > ????????protocol imap; > > ????} > > } > I see at least the following problems in this patch: Thanks for the comments. I wasn't aware of a previous attempt (just started to look at nginx code etc). Apparently I'm not the only one interested in proxy_protocol for the mail module :-) > > 1. The implementation is not complete compared to other modules? > (http, stream): it only tries to change the address passed as? > Client-IP in auth_http, but not the address used for logging? > and/or for XCLIENT. I'll handle that. > > 2. It unconditionally trusts all clients who can connect to the? > port in question.??This doesn't look wise. I'm not sure what you mean here. There's no way to verify the correctness of the proxy protocol (that's also true so for the http/stream implementation). If a proxy protocol claims to originate from 1.1.1.1:1 and that the connection was originally to 2.2.2.2:2 the listener has no way to know that that's correct (or not). From mdounin at mdounin.ru Wed Jul 12 12:56:36 2017 From: mdounin at mdounin.ru (Maxim Dounin) Date: Wed, 12 Jul 2017 15:56:36 +0300 Subject: [PATCH] Add proxy_protocol option to mail listener In-Reply-To: <1499861311.25851.54.camel@gmail.com> References: <1499434682.21080.97.camel@gmail.com> <20170711151203.GV55433@mdounin.ru> <1499861311.25851.54.camel@gmail.com> Message-ID: <20170712125636.GT55433@mdounin.ru> Hello! On Wed, Jul 12, 2017 at 02:08:31PM +0200, Kees Bos wrote: > On di, 2017-07-11 at 18:12 +0300, Maxim Dounin wrote: > > Hello! > > > > On Fri, Jul 07, 2017 at 03:38:02PM +0200, Kees Bos wrote: > > > > > > > > # HG changeset patch > > > # User Kees Bos > > > # Date 1499422505 0 > > > #??????Fri Jul 07 10:15:05 2017 +0000 > > > # Node ID bc79b2baf494aabb889de1e5dbe3184ff0cb9bfa > > > # Parent??70e65bf8dfd7a8d39aae8ac3a209d426e6947735 > > > Add proxy_protocol option to mail listener > > > > > > Add support for the mail handlers. This enables the use of an > > > upstream > > > loadbalancer/proxy (like haproxy) that connects with the proxy > > > protocol. > > > > > > The original ip (as exposed with the proxy protocol) will be used > > > as > > > parameter for the 'Client-IP' in the authentication call. > > > > > > Example config: > > > mail { > > > ????server_name mail.example.com; > > > ????auth_http???localhost:9000/; > > > > > > ????server { > > > ????????listen 143 proxy_protocol; > > > ????????protocol imap; > > > ????} > > > } > > I see at least the following problems in this patch: > > Thanks for the comments. I wasn't aware of a previous attempt (just > started to look at nginx code etc). Apparently I'm not the only one > interested in proxy_protocol for the mail module :-) Well, I've provided the link when you asked about it in April in the nginx@ mailing list: http://mailman.nginx.org/pipermail/nginx/2017-April/053582.html > > 1. The implementation is not complete compared to other modules? > > (http, stream): it only tries to change the address passed as? > > Client-IP in auth_http, but not the address used for logging? > > and/or for XCLIENT. > > I'll handle that. > > > > > 2. It unconditionally trusts all clients who can connect to the? > > port in question.??This doesn't look wise. > > I'm not sure what you mean here. > > There's no way to verify the correctness of the proxy protocol (that's > also true so for the http/stream implementation). If a proxy protocol > claims to originate from 1.1.1.1:1 and that the connection was > originally to 2.2.2.2:2 the listener has no way to know that that's > correct (or not). Obviously enough, you can't verify the information provided. But you can trust or do not trust to the particular client. For example, in the ngx_http_realip_module this is done using the set_real_ip_from directive (http://nginx.org/r/set_real_ip_from) - you can explicitly configure address blocks you want to allow to set client's address based on the provided header or PROXY protocol. The link I've provided in the previous message contains an example with set_real_ip_from as part of the review. -- Maxim Dounin http://nginx.org/ From cornelis.bos at gmail.com Wed Jul 12 13:01:11 2017 From: cornelis.bos at gmail.com (Kees Bos) Date: Wed, 12 Jul 2017 15:01:11 +0200 Subject: [PATCH] Add proxy_protocol option to mail listener In-Reply-To: <20170712125636.GT55433@mdounin.ru> References: <1499434682.21080.97.camel@gmail.com> <20170711151203.GV55433@mdounin.ru> <1499861311.25851.54.camel@gmail.com> <20170712125636.GT55433@mdounin.ru> Message-ID: <1499864471.25851.56.camel@gmail.com> On wo, 2017-07-12 at 15:56 +0300, Maxim Dounin wrote: > On Wed, Jul 12, 2017 at 02:08:31PM +0200, Kees Bos wrote: > On di, 2017-07-11 at 18:12 +0300, Maxim Dounin wrote: > > > On Fri, Jul 07, 2017 at 03:38:02PM +0200, Kees Bos wrote: > > > 2. It unconditionally trusts all clients who can connect to the? > > > port in question.??This doesn't look wise. > > I'm not sure what you mean here. > > > > There's no way to verify the correctness of the proxy protocol > > (that's > > also true so for the http/stream implementation). If a proxy > > protocol > > claims to originate from 1.1.1.1:1 and that the connection was > > originally to 2.2.2.2:2 the listener has no way to know that that's > > correct (or not). > Obviously enough, you can't verify the information provided.??But? > you can trust or do not trust to the particular client.??For? > example, in the ngx_http_realip_module this is done using the? > set_real_ip_from directive (http://nginx.org/r/set_real_ip_from) -? > you can explicitly configure address blocks you want to allow to? > set client's address based on the provided header or PROXY? > protocol. Yes. That's clear. Now (I think) I understand what you mean. > > The link I've provided in the previous message contains an example? > with set_real_ip_from as part of the review. > From pluknet at nginx.com Wed Jul 12 14:07:44 2017 From: pluknet at nginx.com (Sergey Kandaurov) Date: Wed, 12 Jul 2017 17:07:44 +0300 Subject: SSL: Accepting early data in TLSv1.3 In-Reply-To: References: Message-ID: > On 11 Jul 2017, at 21:00, Utkarsh Tewari wrote: > > Hello, > > I am using OpenSSL s_client to send early data during resumption over a TLS1.3 connection. However, the server rejects it as shown below. > > [..] > > Is there any way to accept early data on the server? There?s ongoing work to address TLS1.3 early data support in nginx. No ETA yet. -- Sergey Kandaurov From mdounin at mdounin.ru Thu Jul 13 16:29:19 2017 From: mdounin at mdounin.ru (Maxim Dounin) Date: Thu, 13 Jul 2017 19:29:19 +0300 Subject: [PATCH 09 of 14] Proxy: add "proxy_ssl_alpn" directive In-Reply-To: <96075d4cd2a6e8bd67ca.1498163593@piotrsikora.sfo.corp.google.com> References: <5f5d70428655db0889a2.1498163585@piotrsikora.sfo.corp.google.com> <96075d4cd2a6e8bd67ca.1498163593@piotrsikora.sfo.corp.google.com> Message-ID: <20170713162919.GA93611@mdounin.ru> Hello! On Thu, Jun 22, 2017 at 01:33:13PM -0700, Piotr Sikora via nginx-devel wrote: > # HG changeset patch > # User Piotr Sikora > # Date 1489621682 25200 > # Wed Mar 15 16:48:02 2017 -0700 > # Node ID 96075d4cd2a6e8bd67caf1d7b78f8e87d757c48d > # Parent 154ca6c5e62a1931a616e9f2b99ef2553b7c2c8b > Proxy: add "proxy_ssl_alpn" directive. > > ALPN is used here only to indicate which version of the HTTP protocol > is going to be used and we doesn't verify that upstream agreed to it. > > Please note that upstream is allowed to reject SSL connection with a > fatal "no_application_protocol" alert if it doesn't support it. Looking at this patch again in the HTTP/2-to-upstreams series context, I don't see how it adds any value. Using ALPN doesn't seem to be needed when working with normal HTTP. On the other hand, we probably should use ALPN automatically when connecting to a HTTP/2 backend over SSL, as per RFC7540 (https://tools.ietf.org/html/rfc7540#section-3.4, "implementations that support HTTP/2 over TLS MUST use protocol negotiation in TLS"). Requiring a user to use an additional option looks strange, not to mention it is non-compliant. [...] -- Maxim Dounin http://nginx.org/ From s.martin49 at gmail.com Fri Jul 14 10:08:45 2017 From: s.martin49 at gmail.com (Samuel Martin) Date: Fri, 14 Jul 2017 12:08:45 +0200 Subject: [PATCH] auto/lib/conf: fix PCRE condition WRT the http and http_rewrite options Message-ID: <20170714100845.4077-1-s.martin49@gmail.com> http_rewrite module cannot be selected when http server is disabled, so fix the PCRE check condition to avoid irrelevant check failure. Fixes: http://autobuild.buildroot.net/results/bc7/bc7458b97a88785653845afd30fe9d5f3a69905b/build-end.log Signed-off-by: Samuel Martin --- auto/lib/conf | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/auto/lib/conf b/auto/lib/conf index 0b8545a3..2c7af104 100644 --- a/auto/lib/conf +++ b/auto/lib/conf @@ -7,7 +7,7 @@ if [ $USE_PCRE = YES -o $PCRE != NONE ]; then . auto/lib/pcre/conf else - if [ $USE_PCRE = DISABLED -a $HTTP_REWRITE = YES ]; then + if [ $USE_PCRE = DISABLED -a $HTTP = YES -a $HTTP_REWRITE = YES ]; then cat << END -- 2.13.2 From mdounin at mdounin.ru Fri Jul 14 10:25:13 2017 From: mdounin at mdounin.ru (Maxim Dounin) Date: Fri, 14 Jul 2017 13:25:13 +0300 Subject: [PATCH] auto/lib/conf: fix PCRE condition WRT the http and http_rewrite options In-Reply-To: <20170714100845.4077-1-s.martin49@gmail.com> References: <20170714100845.4077-1-s.martin49@gmail.com> Message-ID: <20170714102512.GB93611@mdounin.ru> Hello! On Fri, Jul 14, 2017 at 12:08:45PM +0200, Samuel Martin wrote: > http_rewrite module cannot be selected when http server is disabled, so > fix the PCRE check condition to avoid irrelevant check failure. > > Fixes: > http://autobuild.buildroot.net/results/bc7/bc7458b97a88785653845afd30fe9d5f3a69905b/build-end.log > > Signed-off-by: Samuel Martin > --- > auto/lib/conf | 2 +- > 1 file changed, 1 insertion(+), 1 deletion(-) > > diff --git a/auto/lib/conf b/auto/lib/conf > index 0b8545a3..2c7af104 100644 > --- a/auto/lib/conf > +++ b/auto/lib/conf > @@ -7,7 +7,7 @@ if [ $USE_PCRE = YES -o $PCRE != NONE ]; then > . auto/lib/pcre/conf > > else > - if [ $USE_PCRE = DISABLED -a $HTTP_REWRITE = YES ]; then > + if [ $USE_PCRE = DISABLED -a $HTTP = YES -a $HTTP_REWRITE = YES ]; then > > cat << END > Seems to be a regression from 4d874b4d82ed (1.11.11), http://hg.nginx.org/nginx/rev/4d874b4d82ed. Ruslan, please take a look. -- Maxim Dounin http://nginx.org/ From ru at nginx.com Sat Jul 15 10:37:19 2017 From: ru at nginx.com (Ruslan Ermilov) Date: Sat, 15 Jul 2017 13:37:19 +0300 Subject: [PATCH] auto/lib/conf: fix PCRE condition WRT the http and http_rewrite options In-Reply-To: <20170714102512.GB93611@mdounin.ru> References: <20170714100845.4077-1-s.martin49@gmail.com> <20170714102512.GB93611@mdounin.ru> Message-ID: <20170715103719.GA30107@lo0.su> On Fri, Jul 14, 2017 at 01:25:13PM +0300, Maxim Dounin wrote: > On Fri, Jul 14, 2017 at 12:08:45PM +0200, Samuel Martin wrote: > > > http_rewrite module cannot be selected when http server is disabled, so > > fix the PCRE check condition to avoid irrelevant check failure. > > > > Fixes: > > http://autobuild.buildroot.net/results/bc7/bc7458b97a88785653845afd30fe9d5f3a69905b/build-end.log > > > > Signed-off-by: Samuel Martin > > --- > > auto/lib/conf | 2 +- > > 1 file changed, 1 insertion(+), 1 deletion(-) > > > > diff --git a/auto/lib/conf b/auto/lib/conf > > index 0b8545a3..2c7af104 100644 > > --- a/auto/lib/conf > > +++ b/auto/lib/conf > > @@ -7,7 +7,7 @@ if [ $USE_PCRE = YES -o $PCRE != NONE ]; then > > . auto/lib/pcre/conf > > > > else > > - if [ $USE_PCRE = DISABLED -a $HTTP_REWRITE = YES ]; then > > + if [ $USE_PCRE = DISABLED -a $HTTP = YES -a $HTTP_REWRITE = YES ]; then > > > > cat << END > > > > Seems to be a regression from 4d874b4d82ed (1.11.11), > http://hg.nginx.org/nginx/rev/4d874b4d82ed. > > Ruslan, please take a look. Suggest to commit the following: # HG changeset patch # User Ruslan Ermilov # Date 1500114987 -10800 # Sat Jul 15 13:36:27 2017 +0300 # Node ID 207fda85a217a950875540633c4adb72a2f24dfe # Parent a27e0c7e198ce989a181fba3c22d0c17e18f84a0 Configure: fixed PCRE requirement check by ngx_http_rewrite_module. The http_rewrite module cannot be selected when http is disabled. Fixed the PCRE check condition to avoid irrelevant check failure. This is a regression from 4d874b4d82ed. Signed-off-by: Samuel Martin diff --git a/auto/lib/conf b/auto/lib/conf --- a/auto/lib/conf +++ b/auto/lib/conf @@ -7,7 +7,7 @@ if [ $USE_PCRE = YES -o $PCRE != NONE ]; . auto/lib/pcre/conf else - if [ $USE_PCRE = DISABLED -a $HTTP_REWRITE = YES ]; then + if [ $USE_PCRE = DISABLED -a $HTTP = YES -a $HTTP_REWRITE = YES ]; then cat << END From igor at sysoev.ru Mon Jul 17 11:53:56 2017 From: igor at sysoev.ru (Igor Sysoev) Date: Mon, 17 Jul 2017 11:53:56 +0000 Subject: [njs] Trailer content after script is optional. Message-ID: details: http://hg.nginx.org/njs/rev/bef6842774f6 branches: changeset: 386:bef6842774f6 user: Igor Sysoev date: Mon Jul 17 14:46:35 2017 +0300 description: Trailer content after script is optional. diffstat: njs/njs_parser.c | 16 ++++++++++++---- njs/njs_vm.h | 2 ++ njs/njscript.c | 2 ++ njs/njscript.h | 2 ++ njs/test/njs_unit_test.c | 10 ++++++++-- 5 files changed, 26 insertions(+), 6 deletions(-) diffs (110 lines): diff -r 0ad7f75f9dbf -r bef6842774f6 njs/njs_parser.c --- a/njs/njs_parser.c Fri Jul 07 19:17:26 2017 +0300 +++ b/njs/njs_parser.c Mon Jul 17 14:46:35 2017 +0300 @@ -115,7 +115,7 @@ njs_parser(njs_vm_t *vm, njs_parser_t *p return NULL; } - if (token == NJS_TOKEN_CLOSE_BRACE) { + if (token == NJS_TOKEN_CLOSE_BRACE && vm->trailer) { parser->lexer->start--; break; } @@ -332,9 +332,13 @@ njs_parser_statement(njs_vm_t *vm, njs_p return njs_parser_block_statement(vm, parser); case NJS_TOKEN_CLOSE_BRACE: - parser->node = NULL; - nxt_thread_log_debug("BLOCK END"); - return token; + if (vm->trailer) { + parser->node = NULL; + nxt_thread_log_debug("BLOCK END"); + return token; + } + + /* Fall through. */ default: token = njs_parser_expression(vm, parser, token); @@ -1043,6 +1047,10 @@ njs_parser_switch_statement(njs_vm_t *vm parser->node = NULL; + if (token == NJS_TOKEN_CLOSE_BRACE) { + break; + } + } else if (branch == NULL) { /* The first switch statment is not "case/default" keyword. */ return NJS_TOKEN_ILLEGAL; diff -r 0ad7f75f9dbf -r bef6842774f6 njs/njs_vm.h --- a/njs/njs_vm.h Fri Jul 07 19:17:26 2017 +0300 +++ b/njs/njs_vm.h Mon Jul 17 14:46:35 2017 +0300 @@ -902,6 +902,8 @@ struct njs_vm_s { nxt_trace_t trace; nxt_random_t random; + + uint8_t trailer; /* 1 bit */ }; diff -r 0ad7f75f9dbf -r bef6842774f6 njs/njscript.c --- a/njs/njscript.c Fri Jul 07 19:17:26 2017 +0300 +++ b/njs/njscript.c Mon Jul 17 14:46:35 2017 +0300 @@ -173,6 +173,8 @@ njs_vm_create(njs_vm_opt_t *options) vm->trace.size = 2048; vm->trace.handler = njs_parser_trace_handler; vm->trace.data = vm; + + vm->trailer = options->trailer; } return vm; diff -r 0ad7f75f9dbf -r bef6842774f6 njs/njscript.h --- a/njs/njscript.h Fri Jul 07 19:17:26 2017 +0300 +++ b/njs/njscript.h Mon Jul 17 14:46:35 2017 +0300 @@ -69,6 +69,8 @@ typedef struct { nxt_lvlhsh_t *externals; njs_vm_shared_t *shared; nxt_mem_cache_pool_t *mcp; + + uint8_t trailer; /* 1 bit */ } njs_vm_opt_t; diff -r 0ad7f75f9dbf -r bef6842774f6 njs/test/njs_unit_test.c --- a/njs/test/njs_unit_test.c Fri Jul 07 19:17:26 2017 +0300 +++ b/njs/test/njs_unit_test.c Mon Jul 17 14:46:35 2017 +0300 @@ -28,6 +28,12 @@ typedef struct { static njs_unit_test_t njs_test[] = { + { nxt_string("}"), + nxt_string("SyntaxError: Unexpected token \"}\" in 1") }, + + { nxt_string("1}"), + nxt_string("SyntaxError: Unexpected token \"}\" in 1") }, + /* Variable declarations. */ { nxt_string("var x"), @@ -1898,7 +1904,7 @@ static njs_unit_test_t njs_test[] = { nxt_string("var a = 3; if (true) if (false); else; a = 2; a"), nxt_string("2") }, - { nxt_string("var a = [3], b; if (1==1||2==2) { b = '1'+'2'+a[0] }; b }"), + { nxt_string("var a = [3], b; if (1==1||2==2) { b = '1'+'2'+a[0] }; b"), nxt_string("123") }, { nxt_string("(function(){ if(true) return 1 else return 0; })()"), @@ -2122,7 +2128,7 @@ static njs_unit_test_t njs_test[] = nxt_string("10") }, { nxt_string("var a = [1,2,3,4,5]; var s = 0, i;" - "for (i in a) if (a[i] > 4) break; s += a[i] } s"), + "for (i in a) if (a[i] > 4) break; s += a[i]; s"), nxt_string("5") }, /**/ From xeioex at nginx.com Mon Jul 17 13:06:47 2017 From: xeioex at nginx.com (Dmitry Volyntsev) Date: Mon, 17 Jul 2017 13:06:47 +0000 Subject: [njs] Initialize njs_vm_opt_t structs to 0 to simplify options adding. Message-ID: details: http://hg.nginx.org/njs/rev/182d765687ee branches: changeset: 387:182d765687ee user: Dmitry Volyntsev date: Mon Jul 17 15:29:02 2017 +0300 description: Initialize njs_vm_opt_t structs to 0 to simplify options adding. diffstat: nginx/ngx_http_js_module.c | 3 ++- nginx/ngx_stream_js_module.c | 3 ++- njs/test/njs_benchmark.c | 4 ++-- njs/test/njs_unit_test.c | 3 ++- 4 files changed, 8 insertions(+), 5 deletions(-) diffs (57 lines): diff -r bef6842774f6 -r 182d765687ee nginx/ngx_http_js_module.c --- a/nginx/ngx_http_js_module.c Mon Jul 17 14:46:35 2017 +0300 +++ b/nginx/ngx_http_js_module.c Mon Jul 17 15:29:02 2017 +0300 @@ -1319,8 +1319,9 @@ ngx_http_js_include(ngx_conf_t *cf, ngx_ return NGX_CONF_ERROR; } + ngx_memzero(&options, sizeof(njs_vm_opt_t)); + options.mcp = mcp; - options.shared = NULL; options.externals = &externals; jlcf->vm = njs_vm_create(&options); diff -r bef6842774f6 -r 182d765687ee nginx/ngx_stream_js_module.c --- a/nginx/ngx_stream_js_module.c Mon Jul 17 14:46:35 2017 +0300 +++ b/nginx/ngx_stream_js_module.c Mon Jul 17 15:29:02 2017 +0300 @@ -1029,8 +1029,9 @@ ngx_stream_js_include(ngx_conf_t *cf, ng return NGX_CONF_ERROR; } + ngx_memzero(&options, sizeof(njs_vm_opt_t)); + options.mcp = mcp; - options.shared = NULL; options.externals = &externals; jscf->vm = njs_vm_create(&options); diff -r bef6842774f6 -r 182d765687ee njs/test/njs_benchmark.c --- a/njs/test/njs_benchmark.c Mon Jul 17 14:46:35 2017 +0300 +++ b/njs/test/njs_benchmark.c Mon Jul 17 15:29:02 2017 +0300 @@ -88,9 +88,9 @@ njs_unit_test_benchmark(nxt_str_t *scrip return NXT_ERROR; } + memset(&options, 0, sizeof(njs_vm_opt_t)); + options.mcp = mcp; - options.shared = NULL; - options.externals = NULL; vm = njs_vm_create(&options); if (vm == NULL) { diff -r bef6842774f6 -r 182d765687ee njs/test/njs_unit_test.c --- a/njs/test/njs_unit_test.c Mon Jul 17 14:46:35 2017 +0300 +++ b/njs/test/njs_unit_test.c Mon Jul 17 15:29:02 2017 +0300 @@ -8161,8 +8161,9 @@ njs_unit_test(nxt_bool_t disassemble) (int) njs_test[i].script.length, njs_test[i].script.start); fflush(stdout); + memset(&options, 0, sizeof(njs_vm_opt_t)); + options.mcp = mcp; - options.shared = NULL; options.externals = &externals; vm = njs_vm_create(&options); From vbart at nginx.com Mon Jul 17 14:24:25 2017 From: vbart at nginx.com (Valentin Bartenev) Date: Mon, 17 Jul 2017 14:24:25 +0000 Subject: [nginx] Parenthesized ASCII-related calculations. Message-ID: details: http://hg.nginx.org/nginx/rev/e3723f2a11b7 branches: changeset: 7067:e3723f2a11b7 user: Valentin Bartenev date: Mon Jul 17 17:23:51 2017 +0300 description: Parenthesized ASCII-related calculations. This also fixes potential undefined behaviour in the range and slice filter modules, caused by local overflows of signed integers in expressions. diffstat: src/core/ngx_parse_time.c | 16 ++++++++-------- src/core/ngx_string.c | 8 ++++---- src/event/ngx_event_openssl_stapling.c | 2 +- src/http/modules/ngx_http_range_filter_module.c | 4 ++-- src/http/modules/ngx_http_slice_filter_module.c | 8 ++++---- src/http/ngx_http_parse.c | 14 +++++++------- src/http/ngx_http_upstream.c | 6 +++--- 7 files changed, 29 insertions(+), 29 deletions(-) diffs (282 lines): diff -r a27e0c7e198c -r e3723f2a11b7 src/core/ngx_parse_time.c --- a/src/core/ngx_parse_time.c Wed Jul 12 11:34:04 2017 +0300 +++ b/src/core/ngx_parse_time.c Mon Jul 17 17:23:51 2017 +0300 @@ -58,7 +58,7 @@ ngx_parse_http_time(u_char *value, size_ return NGX_ERROR; } - day = (*p - '0') * 10 + *(p + 1) - '0'; + day = (*p - '0') * 10 + (*(p + 1) - '0'); p += 2; if (*p == ' ') { @@ -132,7 +132,7 @@ ngx_parse_http_time(u_char *value, size_ } year = (*p - '0') * 1000 + (*(p + 1) - '0') * 100 - + (*(p + 2) - '0') * 10 + *(p + 3) - '0'; + + (*(p + 2) - '0') * 10 + (*(p + 3) - '0'); p += 4; } else if (fmt == rfc850) { @@ -140,7 +140,7 @@ ngx_parse_http_time(u_char *value, size_ return NGX_ERROR; } - year = (*p - '0') * 10 + *(p + 1) - '0'; + year = (*p - '0') * 10 + (*(p + 1) - '0'); year += (year < 70) ? 2000 : 1900; p += 2; } @@ -161,7 +161,7 @@ ngx_parse_http_time(u_char *value, size_ return NGX_ERROR; } - day = day * 10 + *p++ - '0'; + day = day * 10 + (*p++ - '0'); } if (end - p < 14) { @@ -177,7 +177,7 @@ ngx_parse_http_time(u_char *value, size_ return NGX_ERROR; } - hour = (*p - '0') * 10 + *(p + 1) - '0'; + hour = (*p - '0') * 10 + (*(p + 1) - '0'); p += 2; if (*p++ != ':') { @@ -188,7 +188,7 @@ ngx_parse_http_time(u_char *value, size_ return NGX_ERROR; } - min = (*p - '0') * 10 + *(p + 1) - '0'; + min = (*p - '0') * 10 + (*(p + 1) - '0'); p += 2; if (*p++ != ':') { @@ -199,7 +199,7 @@ ngx_parse_http_time(u_char *value, size_ return NGX_ERROR; } - sec = (*p - '0') * 10 + *(p + 1) - '0'; + sec = (*p - '0') * 10 + (*(p + 1) - '0'); if (fmt == isoc) { p += 2; @@ -216,7 +216,7 @@ ngx_parse_http_time(u_char *value, size_ } year = (*p - '0') * 1000 + (*(p + 1) - '0') * 100 - + (*(p + 2) - '0') * 10 + *(p + 3) - '0'; + + (*(p + 2) - '0') * 10 + (*(p + 3) - '0'); } if (hour > 23 || min > 59 || sec > 59) { diff -r a27e0c7e198c -r e3723f2a11b7 src/core/ngx_string.c --- a/src/core/ngx_string.c Wed Jul 12 11:34:04 2017 +0300 +++ b/src/core/ngx_string.c Mon Jul 17 17:23:51 2017 +0300 @@ -178,7 +178,7 @@ ngx_vslprintf(u_char *buf, u_char *last, slen = (size_t) -1; while (*fmt >= '0' && *fmt <= '9') { - width = width * 10 + *fmt++ - '0'; + width = width * 10 + (*fmt++ - '0'); } @@ -211,7 +211,7 @@ ngx_vslprintf(u_char *buf, u_char *last, fmt++; while (*fmt >= '0' && *fmt <= '9') { - frac_width = frac_width * 10 + *fmt++ - '0'; + frac_width = frac_width * 10 + (*fmt++ - '0'); } break; @@ -1655,7 +1655,7 @@ ngx_unescape_uri(u_char **dst, u_char ** state = sw_usual; if (ch >= '0' && ch <= '9') { - ch = (u_char) ((decoded << 4) + ch - '0'); + ch = (u_char) ((decoded << 4) + (ch - '0')); if (type & NGX_UNESCAPE_REDIRECT) { if (ch > '%' && ch < 0x7f) { @@ -1675,7 +1675,7 @@ ngx_unescape_uri(u_char **dst, u_char ** c = (u_char) (ch | 0x20); if (c >= 'a' && c <= 'f') { - ch = (u_char) ((decoded << 4) + c - 'a' + 10); + ch = (u_char) ((decoded << 4) + (c - 'a') + 10); if (type & NGX_UNESCAPE_URI) { if (ch == '?') { diff -r a27e0c7e198c -r e3723f2a11b7 src/event/ngx_event_openssl_stapling.c --- a/src/event/ngx_event_openssl_stapling.c Wed Jul 12 11:34:04 2017 +0300 +++ b/src/event/ngx_event_openssl_stapling.c Mon Jul 17 17:23:51 2017 +0300 @@ -1486,7 +1486,7 @@ ngx_ssl_ocsp_parse_status_line(ngx_ssl_o return NGX_ERROR; } - ctx->code = ctx->code * 10 + ch - '0'; + ctx->code = ctx->code * 10 + (ch - '0'); if (++ctx->count == 3) { state = sw_space_after_status; diff -r a27e0c7e198c -r e3723f2a11b7 src/http/modules/ngx_http_range_filter_module.c --- a/src/http/modules/ngx_http_range_filter_module.c Wed Jul 12 11:34:04 2017 +0300 +++ b/src/http/modules/ngx_http_range_filter_module.c Mon Jul 17 17:23:51 2017 +0300 @@ -315,7 +315,7 @@ ngx_http_range_parse(ngx_http_request_t return NGX_HTTP_RANGE_NOT_SATISFIABLE; } - start = start * 10 + *p++ - '0'; + start = start * 10 + (*p++ - '0'); } while (*p == ' ') { p++; } @@ -345,7 +345,7 @@ ngx_http_range_parse(ngx_http_request_t return NGX_HTTP_RANGE_NOT_SATISFIABLE; } - end = end * 10 + *p++ - '0'; + end = end * 10 + (*p++ - '0'); } while (*p == ' ') { p++; } diff -r a27e0c7e198c -r e3723f2a11b7 src/http/modules/ngx_http_slice_filter_module.c --- a/src/http/modules/ngx_http_slice_filter_module.c Wed Jul 12 11:34:04 2017 +0300 +++ b/src/http/modules/ngx_http_slice_filter_module.c Mon Jul 17 17:23:51 2017 +0300 @@ -317,7 +317,7 @@ ngx_http_slice_parse_content_range(ngx_h return NGX_ERROR; } - start = start * 10 + *p++ - '0'; + start = start * 10 + (*p++ - '0'); } while (*p == ' ') { p++; } @@ -337,7 +337,7 @@ ngx_http_slice_parse_content_range(ngx_h return NGX_ERROR; } - end = end * 10 + *p++ - '0'; + end = end * 10 + (*p++ - '0'); } end++; @@ -362,7 +362,7 @@ ngx_http_slice_parse_content_range(ngx_h return NGX_ERROR; } - complete_length = complete_length * 10 + *p++ - '0'; + complete_length = complete_length * 10 + (*p++ - '0'); } } else { @@ -479,7 +479,7 @@ ngx_http_slice_get_start(ngx_http_reques return 0; } - start = start * 10 + *p++ - '0'; + start = start * 10 + (*p++ - '0'); } return start; diff -r a27e0c7e198c -r e3723f2a11b7 src/http/ngx_http_parse.c --- a/src/http/ngx_http_parse.c Wed Jul 12 11:34:04 2017 +0300 +++ b/src/http/ngx_http_parse.c Mon Jul 17 17:23:51 2017 +0300 @@ -742,7 +742,7 @@ ngx_http_parse_request_line(ngx_http_req return NGX_HTTP_PARSE_INVALID_REQUEST; } - r->http_major = r->http_major * 10 + ch - '0'; + r->http_major = r->http_major * 10 + (ch - '0'); if (r->http_major > 1) { return NGX_HTTP_PARSE_INVALID_VERSION; @@ -784,7 +784,7 @@ ngx_http_parse_request_line(ngx_http_req return NGX_HTTP_PARSE_INVALID_REQUEST; } - r->http_minor = r->http_minor * 10 + ch - '0'; + r->http_minor = r->http_minor * 10 + (ch - '0'); break; case sw_spaces_after_digit: @@ -1518,7 +1518,7 @@ ngx_http_parse_complex_uri(ngx_http_requ case sw_quoted_second: if (ch >= '0' && ch <= '9') { - ch = (u_char) ((decoded << 4) + ch - '0'); + ch = (u_char) ((decoded << 4) + (ch - '0')); if (ch == '%' || ch == '#') { state = sw_usual; @@ -1536,7 +1536,7 @@ ngx_http_parse_complex_uri(ngx_http_requ c = (u_char) (ch | 0x20); if (c >= 'a' && c <= 'f') { - ch = (u_char) ((decoded << 4) + c - 'a' + 10); + ch = (u_char) ((decoded << 4) + (c - 'a') + 10); if (ch == '?') { state = sw_usual; @@ -1701,7 +1701,7 @@ ngx_http_parse_status_line(ngx_http_requ return NGX_ERROR; } - r->http_major = r->http_major * 10 + ch - '0'; + r->http_major = r->http_major * 10 + (ch - '0'); break; /* the first digit of minor HTTP version */ @@ -1729,7 +1729,7 @@ ngx_http_parse_status_line(ngx_http_requ return NGX_ERROR; } - r->http_minor = r->http_minor * 10 + ch - '0'; + r->http_minor = r->http_minor * 10 + (ch - '0'); break; /* HTTP status code */ @@ -1742,7 +1742,7 @@ ngx_http_parse_status_line(ngx_http_requ return NGX_ERROR; } - status->code = status->code * 10 + ch - '0'; + status->code = status->code * 10 + (ch - '0'); if (++status->count == 3) { state = sw_space_after_status; diff -r a27e0c7e198c -r e3723f2a11b7 src/http/ngx_http_upstream.c --- a/src/http/ngx_http_upstream.c Wed Jul 12 11:34:04 2017 +0300 +++ b/src/http/ngx_http_upstream.c Mon Jul 17 17:23:51 2017 +0300 @@ -4503,7 +4503,7 @@ ngx_http_upstream_process_cache_control( } if (*p >= '0' && *p <= '9') { - n = n * 10 + *p - '0'; + n = n * 10 + (*p - '0'); continue; } @@ -4531,7 +4531,7 @@ ngx_http_upstream_process_cache_control( } if (*p >= '0' && *p <= '9') { - n = n * 10 + *p - '0'; + n = n * 10 + (*p - '0'); continue; } @@ -4554,7 +4554,7 @@ ngx_http_upstream_process_cache_control( } if (*p >= '0' && *p <= '9') { - n = n * 10 + *p - '0'; + n = n * 10 + (*p - '0'); continue; } From xeioex at nginx.com Mon Jul 17 18:01:34 2017 From: xeioex at nginx.com (Dmitry Volyntsev) Date: Mon, 17 Jul 2017 18:01:34 +0000 Subject: [njs] Interactive shell. Message-ID: details: http://hg.nginx.org/njs/rev/f2ecbe1c2261 branches: changeset: 388:f2ecbe1c2261 user: Dmitry Volyntsev date: Mon Jul 17 20:38:00 2017 +0300 description: Interactive shell. diffstat: Makefile | 26 ++ njs/njs.c | 466 ++++++++++++++++++++++++++++++++++++++++ njs/njs_array.c | 2 + njs/njs_boolean.c | 2 + njs/njs_builtin.c | 235 +++++++++++++++++-- njs/njs_date.c | 2 + njs/njs_function.c | 3 + njs/njs_lexer_keyword.c | 9 +- njs/njs_math.c | 1 + njs/njs_number.c | 2 + njs/njs_object.c | 2 + njs/njs_object.h | 1 + njs/njs_parser.c | 45 +++- njs/njs_parser.h | 13 +- njs/njs_regexp.c | 2 + njs/njs_string.c | 2 + njs/njs_variable.c | 47 ++- njs/njs_vm.h | 1 + njs/njscript.c | 43 +++- njs/njscript.h | 7 +- njs/test/njs_interactive_test.c | 197 ++++++++++++++++ nxt/auto/configure | 1 + nxt/auto/editline | 25 ++ 23 files changed, 1071 insertions(+), 63 deletions(-) diffs (truncated from 1569 to 1000 lines): diff -r 182d765687ee -r f2ecbe1c2261 Makefile --- a/Makefile Mon Jul 17 15:29:02 2017 +0300 +++ b/Makefile Mon Jul 17 20:38:00 2017 +0300 @@ -74,11 +74,15 @@ NXT_BUILDDIR = build all: test lib_test +njs: $(NXT_BUILDDIR)/njs + test: \ $(NXT_BUILDDIR)/njs_unit_test \ + $(NXT_BUILDDIR)/njs_interactive_test \ $(NXT_BUILDDIR)/njs_benchmark \ $(NXT_BUILDDIR)/njs_unit_test d + $(NXT_BUILDDIR)/njs_interactive_test clean: rm -rf $(NXT_BUILDDIR) @@ -386,6 +390,17 @@ dist: -I$(NXT_LIB) -Injs \ njs/njs_disassembler.c +$(NXT_BUILDDIR)/njs: \ + $(NXT_BUILDDIR)/libnxt.a \ + $(NXT_BUILDDIR)/libnjs.a \ + njs/njs.c \ + + $(NXT_CC) -o $(NXT_BUILDDIR)/njs $(NXT_CFLAGS) \ + -I$(NXT_LIB) -Injs \ + njs/njs.c \ + $(NXT_BUILDDIR)/libnjs.a \ + -lm $(NXT_PCRE_LIB) $(NXT_EDITLINE_LIB) + $(NXT_BUILDDIR)/njs_unit_test: \ $(NXT_BUILDDIR)/libnxt.a \ $(NXT_BUILDDIR)/libnjs.a \ @@ -397,6 +412,17 @@ dist: $(NXT_BUILDDIR)/libnjs.a \ -lm $(NXT_PCRE_LIB) +$(NXT_BUILDDIR)/njs_interactive_test: \ + $(NXT_BUILDDIR)/libnxt.a \ + $(NXT_BUILDDIR)/libnjs.a \ + njs/test/njs_interactive_test.c \ + + $(NXT_CC) -o $(NXT_BUILDDIR)/njs_interactive_test $(NXT_CFLAGS) \ + -I$(NXT_LIB) -Injs \ + njs/test/njs_interactive_test.c \ + $(NXT_BUILDDIR)/libnjs.a \ + -lm $(NXT_PCRE_LIB) + $(NXT_BUILDDIR)/njs_benchmark: \ $(NXT_BUILDDIR)/libnxt.a \ $(NXT_BUILDDIR)/libnjs.a \ diff -r 182d765687ee -r f2ecbe1c2261 njs/njs.c --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/njs/njs.c Mon Jul 17 20:38:00 2017 +0300 @@ -0,0 +1,466 @@ + +/* + * Copyright (C) Dmitry Volyntsev + * Copyright (C) NGINX, Inc. + */ + +#include +#include +#include +#include +#include +#include +#include + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include + + +typedef enum { + NJS_COMPLETION_GLOBAL = 0, + NJS_COMPLETION_SUFFIX, +} njs_completion_phase_t; + + +typedef struct { + char *file; + nxt_int_t disassemble; + nxt_int_t interactive; +} njs_opts_t; + + +typedef struct { + size_t index; + size_t length; + njs_vm_t *vm; + const char **completions; + nxt_lvlhsh_each_t lhe; + njs_completion_phase_t phase; +} njs_completion_t; + + +static nxt_int_t njs_get_options(njs_opts_t *opts, int argc, char **argv); +static nxt_int_t njs_interactive_shell(njs_opts_t *opts, + njs_vm_opt_t *vm_options); +static nxt_int_t njs_process_file(njs_opts_t *opts, njs_vm_opt_t *vm_options); +static nxt_int_t njs_process_script(njs_vm_t *vm, njs_opts_t *opts, + const nxt_str_t *script, nxt_str_t *out); +static nxt_int_t njs_editline_init(njs_vm_t *vm); +static char **njs_completion_handler(const char *text, int start, int end); +static char *njs_completion_generator(const char *text, int state); + + +static njs_completion_t njs_completion; + + +int +main(int argc, char **argv) +{ + nxt_int_t ret; + njs_opts_t opts; + njs_vm_opt_t vm_options; + nxt_mem_cache_pool_t *mcp; + + memset(&opts, 0, sizeof(njs_opts_t)); + opts.interactive = 1; + + ret = njs_get_options(&opts, argc, argv); + if (ret != NXT_OK) { + return (ret == NXT_DONE) ? EXIT_SUCCESS : EXIT_FAILURE; + } + + mcp = nxt_mem_cache_pool_create(&njs_vm_mem_cache_pool_proto, NULL, + NULL, 2 * nxt_pagesize(), 128, 512, 16); + if (nxt_slow_path(mcp == NULL)) { + return EXIT_FAILURE; + } + + memset(&vm_options, 0, sizeof(njs_vm_opt_t)); + + vm_options.mcp = mcp; + vm_options.accumulative = 1; + + if (opts.interactive) { + ret = njs_interactive_shell(&opts, &vm_options); + + } else { + ret = njs_process_file(&opts, &vm_options); + } + + return (ret == NXT_OK) ? EXIT_SUCCESS : EXIT_FAILURE; +} + + +static nxt_int_t +njs_get_options(njs_opts_t *opts, int argc, char** argv) +{ + char *p; + nxt_int_t i, ret; + + ret = NXT_DONE; + + for (i = 1; i < argc; i++) { + + p = argv[i]; + + if (p[0] != '-' || (p[0] == '-' && p[1] == '\0')) { + opts->interactive = 0; + opts->file = argv[i]; + continue; + } + + p++; + + switch (*p) { + case 'd': + opts->disassemble = 1; + break; + + default: + fprintf(stderr, "Unknown argument: \"%s\"\n", argv[i]); + ret = NXT_ERROR; + + /* Fall through. */ + + case 'h': + case '?': + printf("Usage: %s [|-] [-d]\n", argv[0]); + return ret; + } + } + + return NXT_OK; +} + + +static nxt_int_t +njs_interactive_shell(njs_opts_t *opts, njs_vm_opt_t *vm_options) +{ + njs_vm_t *vm; + nxt_int_t ret; + nxt_str_t line, out; + + vm = njs_vm_create(vm_options); + if (vm == NULL) { + fprintf(stderr, "failed to create vm\n"); + return NXT_ERROR; + } + + if (njs_editline_init(vm) != NXT_OK) { + fprintf(stderr, "failed to init completions\n"); + return NXT_ERROR; + } + + printf("interactive njscript\n"); + + for ( ;; ) { + line.start = (u_char *) readline(">> "); + if (line.start == NULL) { + break; + } + + line.length = strlen((char *) line.start); + if (line.length == 0) { + continue; + } + + add_history((char *) line.start); + + ret = njs_process_script(vm, opts, &line, &out); + if (ret != NXT_OK) { + printf("njs_process_script() failed\n"); + return NXT_ERROR; + } + + printf("%.*s\n", (int) out.length, out.start); + + /* editline allocs a new buffer every time. */ + free(line.start); + } + + return NXT_OK; +} + + +static nxt_int_t +njs_process_file(njs_opts_t *opts, njs_vm_opt_t *vm_options) +{ + int fd; + char *file; + u_char buf[4096], *p, *end; + size_t size; + ssize_t n; + njs_vm_t *vm; + nxt_int_t ret; + nxt_str_t out, script; + struct stat sb; + + file = opts->file; + + if (file[0] == '-' && file[1] == '\0') { + fd = STDIN_FILENO; + + } else { + fd = open(file, O_RDONLY); + if (fd == -1) { + fprintf(stderr, "failed to open file: '%s' (%s)\n", + file, strerror(errno)); + return NXT_ERROR; + } + } + + fstat(fd, &sb); + + size = sizeof(buf); + + if (S_ISREG(sb.st_mode) && sb.st_size) { + size = sb.st_size; + } + + script.length = 0; + script.start = realloc(NULL, size); + if (script.start == NULL) { + fprintf(stderr, "alloc failed while reading '%s'\n", file); + return NXT_ERROR; + } + + p = script.start; + end = p + size; + + for ( ;; ) { + n = read(fd, buf, sizeof(buf)); + + if (n == 0) { + break; + } + + if (n < 0) { + fprintf(stderr, "failed to read file: '%s' (%s)\n", + file, strerror(errno)); + return NXT_ERROR; + } + + if (p + n > end) { + size *= 2; + + script.start = realloc(script.start, size); + if (script.start == NULL) { + fprintf(stderr, "alloc failed while reading '%s'\n", file); + return NXT_ERROR; + } + + p = script.start; + end = p + size; + } + + memcpy(p, buf, n); + + p += n; + script.length += n; + } + + vm = njs_vm_create(vm_options); + if (vm == NULL) { + fprintf(stderr, "failed to create vm\n"); + return NXT_ERROR; + } + + ret = njs_process_script(vm, opts, &script, &out); + if (ret != NXT_OK) { + fprintf(stderr, "njs_process_script() failed\n"); + return NXT_ERROR; + } + + if (!opts->disassemble) { + printf("%.*s\n", (int) out.length, out.start); + } + + return NXT_OK; +} + + +static nxt_int_t +njs_process_script(njs_vm_t *vm, njs_opts_t *opts, const nxt_str_t *script, + nxt_str_t *out) +{ + u_char *start; + nxt_int_t ret; + + start = script->start; + + ret = njs_vm_compile(vm, &start, start + script->length); + + if (ret == NXT_OK) { + if (opts->disassemble) { + njs_disassembler(vm); + printf("\n"); + } + + ret = njs_vm_run(vm); + + if (ret == NXT_OK) { + if (njs_vm_retval(vm, out) != NXT_OK) { + return NXT_ERROR; + } + + } else { + njs_vm_exception(vm, out); + } + + } else { + njs_vm_exception(vm, out); + } + + return NXT_OK; +} + + +static nxt_int_t +njs_editline_init(njs_vm_t *vm) +{ + rl_completion_append_character = '\0'; + rl_attempted_completion_function = njs_completion_handler; + rl_basic_word_break_characters = (char *) " \t\n\"\\'`@$><=;,|&{("; + + njs_completion.completions = njs_vm_completions(vm); + if (njs_completion.completions == NULL) { + return NXT_ERROR; + } + + njs_completion.vm = vm; + + return NXT_OK; +} + + +static char ** +njs_completion_handler(const char *text, int start, int end) +{ + rl_attempted_completion_over = 1; + + return rl_completion_matches(text, njs_completion_generator); +} + + +static char * +njs_completion_generator(const char *text, int state) +{ + char *completion; + size_t len; + const char *name, *p; + njs_variable_t *var; + njs_completion_t *cmpl; + + cmpl = &njs_completion; + + if (state == 0) { + cmpl->index = 0; + cmpl->length = strlen(text); + cmpl->phase = NJS_COMPLETION_GLOBAL; + + nxt_lvlhsh_each_init(&cmpl->lhe, &njs_variables_hash_proto); + } + + if (cmpl->phase == NJS_COMPLETION_GLOBAL) { + for ( ;; ) { + name = cmpl->completions[cmpl->index]; + if (name == NULL) { + break; + } + + cmpl->index++; + + if (name[0] == '.') { + continue; + } + + if (strncmp(name, text, cmpl->length) == 0) { + /* editline frees the buffer every time. */ + return strdup(name); + } + } + + if (cmpl->vm->parser != NULL) { + for ( ;; ) { + var = nxt_lvlhsh_each(&cmpl->vm->parser->scope->variables, + &cmpl->lhe); + if (var == NULL) { + break; + } + + if (strncmp((char *) var->name.start, text, cmpl->length) + == 0) + { + completion = malloc(var->name.length + 1); + if (completion == NULL) { + return NULL; + } + + memcpy(completion, var->name.start, var->name.length); + completion[var->name.length] = '\0'; + + return completion; + } + } + } + + if (cmpl->length == 0) { + return NULL; + } + + cmpl->index = 0; + cmpl->phase = NJS_COMPLETION_SUFFIX; + } + + len = 1; + p = &text[cmpl->length - 1]; + + while (p > text && *p != '.') { + p--; + len++; + } + + if (*p != '.') { + return NULL; + } + + for ( ;; ) { + name = cmpl->completions[cmpl->index++]; + if (name == NULL) { + break; + } + + if (name[0] != '.') { + continue; + } + + if (strncmp(name, p, len) != 0) { + continue; + } + + len = strlen(name) + (p - text) + 2; + completion = malloc(len); + if (completion == NULL) { + return NULL; + } + + snprintf(completion, len, "%.*s%s", (int) (p - text), text, name); + return completion; + } + + return NULL; +} diff -r 182d765687ee -r f2ecbe1c2261 njs/njs_array.c --- a/njs/njs_array.c Mon Jul 17 15:29:02 2017 +0300 +++ b/njs/njs_array.c Mon Jul 17 20:38:00 2017 +0300 @@ -373,6 +373,7 @@ static const njs_object_prop_t njs_arra const njs_object_init_t njs_array_constructor_init = { + nxt_string("Array"), njs_array_constructor_properties, nxt_nitems(njs_array_constructor_properties), }; @@ -2234,6 +2235,7 @@ static const njs_object_prop_t njs_arra const njs_object_init_t njs_array_prototype_init = { + nxt_string("Array"), njs_array_prototype_properties, nxt_nitems(njs_array_prototype_properties), }; diff -r 182d765687ee -r f2ecbe1c2261 njs/njs_boolean.c --- a/njs/njs_boolean.c Mon Jul 17 15:29:02 2017 +0300 +++ b/njs/njs_boolean.c Mon Jul 17 20:38:00 2017 +0300 @@ -78,6 +78,7 @@ static const njs_object_prop_t njs_bool const njs_object_init_t njs_boolean_constructor_init = { + nxt_string("Boolean"), njs_boolean_constructor_properties, nxt_nitems(njs_boolean_constructor_properties), }; @@ -156,6 +157,7 @@ static const njs_object_prop_t njs_bool const njs_object_init_t njs_boolean_prototype_init = { + nxt_string("Boolean"), njs_boolean_prototype_properties, nxt_nitems(njs_boolean_prototype_properties), }; diff -r 182d765687ee -r f2ecbe1c2261 njs/njs_builtin.c --- a/njs/njs_builtin.c Mon Jul 17 15:29:02 2017 +0300 +++ b/njs/njs_builtin.c Mon Jul 17 20:38:00 2017 +0300 @@ -27,6 +27,7 @@ #include #include #include +#include typedef struct { @@ -35,6 +36,40 @@ typedef struct { } njs_function_init_t; +static nxt_int_t njs_builtin_completions(njs_vm_t *vm, size_t *size, + const char **completions); + + +static const njs_object_init_t *object_init[] = { + NULL, /* global this */ + &njs_math_object_init, /* Math */ +}; + + +static const njs_object_init_t *prototype_init[] = { + &njs_object_prototype_init, + &njs_array_prototype_init, + &njs_boolean_prototype_init, + &njs_number_prototype_init, + &njs_string_prototype_init, + &njs_function_prototype_init, + &njs_regexp_prototype_init, + &njs_date_prototype_init, +}; + + +static const njs_object_init_t *constructor_init[] = { + &njs_object_constructor_init, + &njs_array_constructor_init, + &njs_boolean_constructor_init, + &njs_number_constructor_init, + &njs_string_constructor_init, + &njs_function_constructor_init, + &njs_regexp_constructor_init, + &njs_date_constructor_init, +}; + + static njs_ret_t njs_prototype_function(njs_vm_t *vm, njs_value_t *args, nxt_uint_t nargs, njs_index_t unused) @@ -54,17 +89,6 @@ njs_builtin_objects_create(njs_vm_t *vm) njs_function_t *functions, *constructors; njs_object_prototype_t *prototypes; - static const njs_object_init_t *prototype_init[] = { - &njs_object_prototype_init, - &njs_array_prototype_init, - &njs_boolean_prototype_init, - &njs_number_prototype_init, - &njs_string_prototype_init, - &njs_function_prototype_init, - &njs_regexp_prototype_init, - &njs_date_prototype_init, - }; - static const njs_object_prototype_t prototype_values[] = { /* * GCC 4 complains about uninitialized .shared field, @@ -97,17 +121,6 @@ njs_builtin_objects_create(njs_vm_t *vm) .object = { .type = NJS_DATE } } }, }; - static const njs_object_init_t *constructor_init[] = { - &njs_object_constructor_init, - &njs_array_constructor_init, - &njs_boolean_constructor_init, - &njs_number_constructor_init, - &njs_string_constructor_init, - &njs_function_constructor_init, - &njs_regexp_constructor_init, - &njs_date_constructor_init, - }; - static const njs_function_init_t native_constructors[] = { /* SunC does not allow empty array initialization. */ { njs_object_constructor, { 0 } }, @@ -121,11 +134,6 @@ njs_builtin_objects_create(njs_vm_t *vm) { njs_date_constructor, { 0 } }, }; - static const njs_object_init_t *object_init[] = { - NULL, /* global this */ - &njs_math_object_init, /* Math */ - }; - static const njs_object_init_t *function_init[] = { &njs_eval_function_init, /* eval */ NULL, /* toString */ @@ -333,3 +341,176 @@ njs_builtin_objects_clone(njs_vm_t *vm) return NXT_OK; } + + +const char ** +njs_vm_completions(njs_vm_t *vm) +{ + size_t size; + const char **completions; + + if (njs_builtin_completions(vm, &size, NULL) != NXT_OK) { + return NULL; + } + + completions = nxt_mem_cache_zalloc(vm->mem_cache_pool, + sizeof(char *) * (size + 1)); + + if (completions == NULL) { + return NULL; + } + + if (njs_builtin_completions(vm, NULL, completions) != NXT_OK) { + return NULL; + } + + return completions; +} + + +static nxt_int_t +njs_builtin_completions(njs_vm_t *vm, size_t *size, const char **completions) +{ + char *compl; + size_t n, len; + nxt_str_t string; + nxt_uint_t i, k; + njs_object_t *objects; + njs_keyword_t *keyword; + njs_function_t *constructors; + njs_object_prop_t *prop; + nxt_lvlhsh_each_t lhe; + njs_object_prototype_t *prototypes; + + n = 0; + + nxt_lvlhsh_each_init(&lhe, &njs_keyword_hash_proto); + + for ( ;; ) { + keyword = nxt_lvlhsh_each(&vm->shared->keywords_hash, &lhe); + + if (keyword == NULL) { + break; + } + + if (completions != NULL) { + completions[n++] = (char *) keyword->name.start; + + } else { + n++; + } + } + + objects = vm->shared->objects; + + for (i = NJS_OBJECT_THIS; i < NJS_OBJECT_MAX; i++) { + if (object_init[i] == NULL) { + continue; + } + + nxt_lvlhsh_each_init(&lhe, &njs_object_hash_proto); + + for ( ;; ) { + prop = nxt_lvlhsh_each(&objects[i].shared_hash, &lhe); + + if (prop == NULL) { + break; + } + + if (completions != NULL) { + njs_string_get(&prop->name, &string); + len = object_init[i]->name.length + string.length + 2; + + compl = nxt_mem_cache_zalloc(vm->mem_cache_pool, len); + if (compl == NULL) { + return NXT_ERROR; + } + + snprintf(compl, len, "%s.%s", object_init[i]->name.start, + string.start); + + completions[n++] = (char *) compl; + + } else { + n++; + } + } + } + + prototypes = vm->shared->prototypes; + + for (i = NJS_PROTOTYPE_OBJECT; i < NJS_PROTOTYPE_MAX; i++) { + nxt_lvlhsh_each_init(&lhe, &njs_object_hash_proto); + + for ( ;; ) { + prop = nxt_lvlhsh_each(&prototypes[i].object.shared_hash, &lhe); + + if (prop == NULL) { + break; + } + + if (completions != NULL) { + njs_string_get(&prop->name, &string); + len = string.length + 2; + + compl = nxt_mem_cache_zalloc(vm->mem_cache_pool, len); + if (compl == NULL) { + return NXT_ERROR; + } + + snprintf(compl, len, ".%s", string.start); + + for (k = 0; k < n; k++) { + if (strncmp(completions[k], compl, len) == 0) { + break; + } + } + + if (k == n) { + completions[n++] = (char *) compl; + } + + } else { + n++; + } + } + } + + constructors = vm->shared->constructors; + + for (i = NJS_CONSTRUCTOR_OBJECT; i < NJS_CONSTRUCTOR_MAX; i++) { + nxt_lvlhsh_each_init(&lhe, &njs_object_hash_proto); + + for ( ;; ) { + prop = nxt_lvlhsh_each(&constructors[i].object.shared_hash, &lhe); + + if (prop == NULL) { + break; + } + + if (completions != NULL) { + njs_string_get(&prop->name, &string); + len = constructor_init[i]->name.length + string.length + 2; + + compl = nxt_mem_cache_zalloc(vm->mem_cache_pool, len); + if (compl == NULL) { + return NXT_ERROR; + } + + snprintf(compl, len, "%s.%s", constructor_init[i]->name.start, + string.start); + + completions[n++] = (char *) compl; + + } else { + n++; + } + } + } + + if (size) { + *size = n; + } + + return NXT_OK; +} diff -r 182d765687ee -r f2ecbe1c2261 njs/njs_date.c --- a/njs/njs_date.c Mon Jul 17 15:29:02 2017 +0300 +++ b/njs/njs_date.c Mon Jul 17 20:38:00 2017 +0300 @@ -931,6 +931,7 @@ static const njs_object_prop_t njs_date const njs_object_init_t njs_date_constructor_init = { + nxt_string("Date"), njs_date_constructor_properties, nxt_nitems(njs_date_constructor_properties), }; @@ -2244,6 +2245,7 @@ static const njs_object_prop_t njs_date const njs_object_init_t njs_date_prototype_init = { + nxt_string("Date"), njs_date_prototype_properties, nxt_nitems(njs_date_prototype_properties), }; diff -r 182d765687ee -r f2ecbe1c2261 njs/njs_function.c --- a/njs/njs_function.c Mon Jul 17 15:29:02 2017 +0300 +++ b/njs/njs_function.c Mon Jul 17 20:38:00 2017 +0300 @@ -497,6 +497,7 @@ static const njs_object_prop_t njs_func const njs_object_init_t njs_function_constructor_init = { + nxt_string("Function"), njs_function_constructor_properties, nxt_nitems(njs_function_constructor_properties), }; @@ -692,6 +693,7 @@ static const njs_object_prop_t njs_func const njs_object_init_t njs_function_prototype_init = { + nxt_string("Function"), njs_function_prototype_properties, nxt_nitems(njs_function_prototype_properties), }; @@ -724,6 +726,7 @@ static const njs_object_prop_t njs_eval const njs_object_init_t njs_eval_function_init = { + nxt_string("Function"), njs_eval_function_properties, nxt_nitems(njs_eval_function_properties), }; diff -r 182d765687ee -r f2ecbe1c2261 njs/njs_lexer_keyword.c --- a/njs/njs_lexer_keyword.c Mon Jul 17 15:29:02 2017 +0300 +++ b/njs/njs_lexer_keyword.c Mon Jul 17 20:38:00 2017 +0300 @@ -23,13 +23,6 @@ #include -typedef struct { - nxt_str_t name; - njs_token_t token; - double number; -} njs_keyword_t; - - static const njs_keyword_t njs_keywords[] = { /* Values. */ @@ -150,7 +143,7 @@ njs_keyword_hash_test(nxt_lvlhsh_query_t } -static const nxt_lvlhsh_proto_t njs_keyword_hash_proto +const nxt_lvlhsh_proto_t njs_keyword_hash_proto nxt_aligned(64) = { NXT_LVLHSH_DEFAULT, diff -r 182d765687ee -r f2ecbe1c2261 njs/njs_math.c --- a/njs/njs_math.c Mon Jul 17 15:29:02 2017 +0300 +++ b/njs/njs_math.c Mon Jul 17 20:38:00 2017 +0300 @@ -1088,6 +1088,7 @@ static const njs_object_prop_t njs_math const njs_object_init_t njs_math_object_init = { + nxt_string("Math"), njs_math_object_properties, nxt_nitems(njs_math_object_properties), }; diff -r 182d765687ee -r f2ecbe1c2261 njs/njs_number.c --- a/njs/njs_number.c Mon Jul 17 15:29:02 2017 +0300 +++ b/njs/njs_number.c Mon Jul 17 20:38:00 2017 +0300 @@ -528,6 +528,7 @@ static const njs_object_prop_t njs_numb const njs_object_init_t njs_number_constructor_init = { + nxt_string("Number"), njs_number_constructor_properties, nxt_nitems(njs_number_constructor_properties), }; @@ -687,6 +688,7 @@ static const njs_object_prop_t njs_numb const njs_object_init_t njs_number_prototype_init = { + nxt_string("Number"), njs_number_prototype_properties, nxt_nitems(njs_number_prototype_properties), }; diff -r 182d765687ee -r f2ecbe1c2261 njs/njs_object.c --- a/njs/njs_object.c Mon Jul 17 15:29:02 2017 +0300 +++ b/njs/njs_object.c Mon Jul 17 20:38:00 2017 +0300 @@ -1153,6 +1153,7 @@ static const njs_object_prop_t njs_obje const njs_object_init_t njs_object_constructor_init = { + nxt_string("Object"), njs_object_constructor_properties, nxt_nitems(njs_object_constructor_properties), }; @@ -1477,6 +1478,7 @@ static const njs_object_prop_t njs_obje const njs_object_init_t njs_object_prototype_init = { + nxt_string("Object"), njs_object_prototype_properties, nxt_nitems(njs_object_prototype_properties), }; diff -r 182d765687ee -r f2ecbe1c2261 njs/njs_object.h --- a/njs/njs_object.h Mon Jul 17 15:29:02 2017 +0300 +++ b/njs/njs_object.h Mon Jul 17 20:38:00 2017 +0300 @@ -32,6 +32,7 @@ typedef struct { struct njs_object_init_s { + nxt_str_t name; const njs_object_prop_t *properties; nxt_uint_t items; }; diff -r 182d765687ee -r f2ecbe1c2261 njs/njs_parser.c --- a/njs/njs_parser.c Mon Jul 17 15:29:02 2017 +0300 +++ b/njs/njs_parser.c Mon Jul 17 20:38:00 2017 +0300 @@ -14,6 +14,7 @@ #include #include #include +#include #include #include #include @@ -95,17 +96,53 @@ static njs_token_t njs_parser_unexpected njs_parser_node_t * -njs_parser(njs_vm_t *vm, njs_parser_t *parser) +njs_parser(njs_vm_t *vm, njs_parser_t *parser, njs_parser_t *prev) { - njs_ret_t ret; - njs_token_t token; - njs_parser_node_t *node; + njs_ret_t ret; + njs_token_t token; + nxt_lvlhsh_t *variables, *prev_variables; + njs_variable_t *var; + njs_parser_node_t *node; + nxt_lvlhsh_each_t lhe; + nxt_lvlhsh_query_t lhq; From cornelis.bos at gmail.com Tue Jul 18 10:06:09 2017 From: cornelis.bos at gmail.com (Kees Bos) Date: Tue, 18 Jul 2017 12:06:09 +0200 Subject: [PATCH] Add proxy_protocol option to mail listener In-Reply-To: <20170712125636.GT55433@mdounin.ru> References: <1499434682.21080.97.camel@gmail.com> <20170711151203.GV55433@mdounin.ru> <1499861311.25851.54.camel@gmail.com> <20170712125636.GT55433@mdounin.ru> Message-ID: <1500372369.24044.27.camel@gmail.com> # HG changeset patch # User Kees Bos # Date 1500371531 0 #??????Tue Jul 18 09:52:11 2017 +0000 # Node ID 8dd6050ca6858d9bea139067611ca5c69cfe8f18 # Parent??e3723f2a11b7ec1c196d59c331739bc21d9d9afd Add proxy_protocol option to mail listener Add support for the mail handlers. This enables the use of an upstream loadbalancer/proxy (like haproxy) that connects with the proxy protocol. The original ip (as exposed with the proxy protocol) will be used as parameter for the 'Client-IP' in the authentication call and as address in the XCLIENT call. Optionally (if set), the real ips from the client that are using the proxy protocol can be restricted with "set_real_ip_from". Example config: mail { ????server_name mail.example.com; ????auth_http???localhost:9000/; ????server { ????????listen 143 proxy_protocol; ????????protocol imap; ????} ????server { ????????listen 25 proxy_protocol; ????????protocol smtp; ????????set_real_ip_from 127.0.0.0/8; ????????set_real_ip_from ::/128; ????} } diff -r e3723f2a11b7 -r 8dd6050ca685 auto/modules --- a/auto/modules??????Mon Jul 17 17:23:51 2017 +0300 +++ b/auto/modules??????Tue Jul 18 09:52:11 2017 +0000 @@ -954,6 +954,12 @@ ?????ngx_module_srcs=src/mail/ngx_mail_proxy_module.c ? ?????. auto/module + +????ngx_module_name=ngx_mail_realip_module +????ngx_module_deps= +????ngx_module_srcs=src/mail/ngx_mail_realip_module.c + +????. auto/module ?fi ? ? diff -r e3723f2a11b7 -r 8dd6050ca685 src/mail/ngx_mail.c --- a/src/mail/ngx_mail.c???????Mon Jul 17 17:23:51 2017 +0300 +++ b/src/mail/ngx_mail.c???????Tue Jul 18 09:52:11 2017 +0000 @@ -408,6 +408,7 @@ ?#if (NGX_MAIL_SSL) ?????????addrs[i].conf.ssl = addr[i].opt.ssl; ?#endif +????????addrs[i].conf.proxy_protocol = addr[i].opt.proxy_protocol; ? ?????????len = ngx_sock_ntop(&addr[i].opt.sockaddr.sockaddr, addr[i].opt.socklen, ?????????????????????????????buf, NGX_SOCKADDR_STRLEN, 1); @@ -457,6 +458,7 @@ ?#if (NGX_MAIL_SSL) ?????????addrs6[i].conf.ssl = addr[i].opt.ssl; ?#endif +????????addrs6[i].conf.proxy_protocol = addr[i].opt.proxy_protocol; ? ?????????len = ngx_sock_ntop(&addr[i].opt.sockaddr.sockaddr, addr[i].opt.socklen, ?????????????????????????????buf, NGX_SOCKADDR_STRLEN, 1); diff -r e3723f2a11b7 -r 8dd6050ca685 src/mail/ngx_mail.h --- a/src/mail/ngx_mail.h???????Mon Jul 17 17:23:51 2017 +0300 +++ b/src/mail/ngx_mail.h???????Tue Jul 18 09:52:11 2017 +0000 @@ -40,6 +40,7 @@ ?????unsigned????????????????ipv6only:1; ?#endif ?????unsigned????????????????so_keepalive:2; +????unsigned????????????????proxy_protocol:1; ?#if (NGX_HAVE_KEEPALIVE_TUNABLE) ?????int?????????????????????tcp_keepidle; ?????int?????????????????????tcp_keepintvl; @@ -54,7 +55,8 @@ ?typedef struct { ?????ngx_mail_conf_ctx_t????*ctx; ?????ngx_str_t???????????????addr_text; -????ngx_uint_t??????????????ssl;????/* unsigned???ssl:1; */ +????unsigned????????????????ssl:1; +????unsigned????????????????proxy_protocol:1; ?} ngx_mail_addr_conf_t; ? ?typedef struct { @@ -204,6 +206,8 @@ ?????unsigned????????????????esmtp:1; ?????unsigned????????????????auth_method:3; ?????unsigned????????????????auth_wait:1; +????unsigned????????????????ssl:1; +????unsigned????????????????proxy_protocol:1; ? ?????ngx_str_t???????????????login; ?????ngx_str_t???????????????passwd; diff -r e3723f2a11b7 -r 8dd6050ca685 src/mail/ngx_mail_auth_http_module.c --- a/src/mail/ngx_mail_auth_http_module.c??????Mon Jul 17 17:23:51 2017 +0300 +++ b/src/mail/ngx_mail_auth_http_module.c??????Tue Jul 18 09:52:11 2017 +0000 @@ -1142,6 +1142,7 @@ ?????ngx_mail_ssl_conf_t???????*sslcf; ?#endif ?????ngx_mail_core_srv_conf_t??*cscf; +????ngx_str_t?????????????????*client_addr; ? ?????if (ngx_mail_auth_http_escape(pool, &s->login, &login) != NGX_OK) { ?????????return NULL; @@ -1208,6 +1209,11 @@ ?#endif ? ?????cscf = ngx_mail_get_module_srv_conf(s, ngx_mail_core_module); +????if (s->connection->proxy_protocol_addr.len) { +????????client_addr = &s->connection->proxy_protocol_addr; +????} else { +????????client_addr = &s->connection->addr_text; +????} ? ?????len = sizeof("GET ") - 1 + ahcf->uri.len + sizeof(" HTTP/1.0" CRLF) - 1 ???????????+ sizeof("Host: ") - 1 + ahcf->host_header.len + sizeof(CRLF) - 1 @@ -1221,7 +1227,7 @@ ?????????????????+ sizeof(CRLF) - 1 ???????????+ sizeof("Auth-Login-Attempt: ") - 1 + NGX_INT_T_LEN ?????????????????+ sizeof(CRLF) - 1 -??????????+ sizeof("Client-IP: ") - 1 + s->connection->addr_text.len +??????????+ sizeof("Client-IP: ") - 1 + client_addr->len ?????????????????+ sizeof(CRLF) - 1 ???????????+ sizeof("Client-Host: ") - 1 + s->host.len + sizeof(CRLF) - 1 ???????????+ sizeof("Auth-SMTP-Helo: ") - 1 + s->smtp_helo.len + sizeof(CRLF) - 1 @@ -1287,8 +1293,7 @@ ???????????????????????????s->login_attempt); ? ?????b->last = ngx_cpymem(b->last, "Client-IP: ", sizeof("Client-IP: ") - 1); -????b->last = ngx_copy(b->last, s->connection->addr_text.data, -???????????????????????s->connection->addr_text.len); +????b->last = ngx_copy(b->last, client_addr->data, client_addr->len); ?????*b->last++ = CR; *b->last++ = LF; ? ?????if (s->host.len) { diff -r e3723f2a11b7 -r 8dd6050ca685 src/mail/ngx_mail_core_module.c --- a/src/mail/ngx_mail_core_module.c???Mon Jul 17 17:23:51 2017 +0300 +++ b/src/mail/ngx_mail_core_module.c???Tue Jul 18 09:52:11 2017 +0000 @@ -574,6 +574,11 @@ ?#endif ?????????} ? +????????if (ngx_strcmp(value[i].data, "proxy_protocol") == 0) { +????????????ls->proxy_protocol = 1; +????????????continue; +????????} + ?????????ngx_conf_log_error(NGX_LOG_EMERG, cf, 0, ????????????????????????????"the invalid \"%V\" parameter", &value[i]); ?????????return NGX_CONF_ERROR; diff -r e3723f2a11b7 -r 8dd6050ca685 src/mail/ngx_mail_handler.c --- a/src/mail/ngx_mail_handler.c???????Mon Jul 17 17:23:51 2017 +0300 +++ b/src/mail/ngx_mail_handler.c???????Tue Jul 18 09:52:11 2017 +0000 @@ -12,13 +12,14 @@ ? ? ?static void ngx_mail_init_session(ngx_connection_t *c); - +static void ngx_mail_proxy_protocol_handler(ngx_event_t *rev); ?#if (NGX_MAIL_SSL) ?static void ngx_mail_ssl_init_connection(ngx_ssl_t *ssl, ngx_connection_t *c); ?static void ngx_mail_ssl_handshake_handler(ngx_connection_t *c); ?static ngx_int_t ngx_mail_verify_cert(ngx_mail_session_t *s, ?????ngx_connection_t *c); ?#endif +ngx_int_t ngx_mail_realip_handler(ngx_mail_session_t *s); ? ? ?void @@ -138,11 +139,7 @@ ? ?????ngx_set_connection_log(c, cscf->error_log); ? -????len = ngx_sock_ntop(c->sockaddr, c->socklen, text, NGX_SOCKADDR_STRLEN, 1); - -????ngx_log_error(NGX_LOG_INFO, c->log, 0, "*%uA client %*s connected to %V", -??????????????????c->number, len, text, s->addr_text); - +????s->proxy_protocol = addr_conf->proxy_protocol; ?????ctx = ngx_palloc(c->pool, sizeof(ngx_mail_log_ctx_t)); ?????if (ctx == NULL) { ?????????ngx_mail_close_connection(c); @@ -165,16 +162,11 @@ ? ?????sslcf = ngx_mail_get_module_srv_conf(s, ngx_mail_ssl_module); ? +????s->ssl = 0; ?????if (sslcf->enable) { -????????c->log->action = "SSL handshaking"; - -????????ngx_mail_ssl_init_connection(&sslcf->ssl, c); -????????return; -????} - -????if (addr_conf->ssl) { - -????????c->log->action = "SSL handshaking"; +????????s->ssl = 1; +????} else if (addr_conf->ssl) { +????????s->ssl = 1; ? ?????????if (sslcf->ssl.ctx == NULL) { ?????????????ngx_log_error(NGX_LOG_ERR, c->log, 0, @@ -183,11 +175,99 @@ ?????????????ngx_mail_close_connection(c); ?????????????return; ?????????} +????} ? +????} +#endif + +????if (s->proxy_protocol) { +????????c->log->action = "reading PROXY protocol"; +????????ngx_add_timer(c->read, cscf->timeout); +????????c->read->handler = ngx_mail_proxy_protocol_handler; +????????if (ngx_handle_read_event(c->read, 0) != NGX_OK) { +????????????ngx_mail_close_connection(c); +????????} +????????return; +????} + +????len = ngx_sock_ntop(c->sockaddr, c->socklen, text, NGX_SOCKADDR_STRLEN, 1); + +????ngx_log_error(NGX_LOG_INFO, c->log, 0, "*%uA client %*s connected to %V", +??????????????????c->number, len, text, s->addr_text); + +#if (NGX_MAIL_SSL) +????if (s->ssl) { +????????ngx_mail_ssl_conf_t??*sslcf; +????????c->log->action = "SSL handshaking"; +????????sslcf = ngx_mail_get_module_srv_conf(s, ngx_mail_ssl_module); ?????????ngx_mail_ssl_init_connection(&sslcf->ssl, c); ?????????return; ?????} +# endif ? +????ngx_mail_init_session(c); +} + + +void +ngx_mail_proxy_protocol_handler(ngx_event_t *rev) +{ +????u_char????????????????????*p, buf[NGX_PROXY_PROTOCOL_MAX_HEADER + 1]; +????size_t?????????????????????size, len; +????ssize_t????????????????????n; +????ngx_err_t??????????????????err; +????ngx_connection_t??????????*c; +????ngx_mail_session_t????????*s; +????u_char?????????????????????text[NGX_SOCKADDR_STRLEN]; +????ngx_mail_log_ctx_t????????*ctx; + +????size = sizeof(buf); +????c = rev->data; + +????n = recv(c->fd, (char *) buf, size, MSG_PEEK); +????err = ngx_socket_errno; + +????if (n == -1) { +????????ngx_connection_error(c, err, "recv() failed"); +????????ngx_mail_close_connection(c); +????????return; +????} +????p = ngx_proxy_protocol_read(c, buf, buf + n); +????if (p == NULL) { +????????ngx_mail_close_connection(c); +????????return; +????} +????size = p - buf; +????if (c->recv(c, buf, size) != (ssize_t) size) { +????????ngx_mail_close_connection(c); +????????return; +????} +????s = c->data; +????s->proxy_protocol = 0; + +????ctx = c->log->data; +????ctx->client = &c->proxy_protocol_addr; +????len = ngx_sock_ntop(c->sockaddr, c->socklen, text, NGX_SOCKADDR_STRLEN, 1); +????ngx_log_error(NGX_LOG_INFO, c->log, 0, +????????"*%uA client %*s (real %*s:%d) connected to %V", +????????c->number, len, text, +????????c->proxy_protocol_addr.len, c->proxy_protocol_addr.data, +????????c->proxy_protocol_port, s->addr_text); + +????if (ngx_mail_realip_handler(s) != NGX_OK) { +????????ngx_mail_close_connection(c); +????????return; +????} + +#if (NGX_MAIL_SSL) +????{ +????ngx_mail_ssl_conf_t??*sslcf; +????if (s->ssl) { +????????c->log->action = "SSL handshaking"; +????????sslcf = ngx_mail_get_module_srv_conf(s, ngx_mail_ssl_module); +????????ngx_mail_ssl_init_connection(&sslcf->ssl, c); +????????return; +????} ?????} ?#endif ? @@ -222,6 +302,19 @@ ?????ngx_mail_session_t????????*s; ?????ngx_mail_core_srv_conf_t??*cscf; ? +????s = c->data; +????cscf = ngx_mail_get_module_srv_conf(s, ngx_mail_core_module); + +????if (s->proxy_protocol) { +????????c->log->action = "reading PROXY protocol"; +????????ngx_add_timer(c->read, cscf->timeout); +????????c->read->handler = ngx_mail_proxy_protocol_handler; +????????if (ngx_handle_read_event(c->read, 0) != NGX_OK) { +????????????ngx_mail_close_connection(c); +????????} +????????return; +????} + ?????if (ngx_ssl_create_connection(ssl, c, 0) != NGX_OK) { ?????????ngx_mail_close_connection(c); ?????????return; @@ -229,10 +322,6 @@ ? ?????if (ngx_ssl_handshake(c) == NGX_AGAIN) { ? -????????s = c->data; - -????????cscf = ngx_mail_get_module_srv_conf(s, ngx_mail_core_module); - ?????????ngx_add_timer(c->read, cscf->timeout); ? ?????????c->ssl->handler = ngx_mail_ssl_handshake_handler; diff -r e3723f2a11b7 -r 8dd6050ca685 src/mail/ngx_mail_proxy_module.c --- a/src/mail/ngx_mail_proxy_module.c??Mon Jul 17 17:23:51 2017 +0300 +++ b/src/mail/ngx_mail_proxy_module.c??Tue Jul 18 09:52:11 2017 +0000 @@ -456,6 +456,7 @@ ?????ngx_mail_session_t????????*s; ?????ngx_mail_proxy_conf_t?????*pcf; ?????ngx_mail_core_srv_conf_t??*cscf; +????ngx_str_t?????????????????*client_addr; ? ?????ngx_log_debug0(NGX_LOG_DEBUG_MAIL, rev->log, 0, ????????????????????"mail proxy smtp auth handler"); @@ -523,11 +524,17 @@ ?????????ngx_log_debug0(NGX_LOG_DEBUG_MAIL, rev->log, 0, ????????????????????????"mail proxy send xclient"); ? +????????if (s->connection->proxy_protocol_addr.len) { +????????????client_addr = &s->connection->proxy_protocol_addr; +????????} else { +????????????client_addr = &s->connection->addr_text; +????????} + ?????????s->connection->log->action = "sending XCLIENT to upstream"; ? ?????????line.len = sizeof("XCLIENT ADDR= LOGIN= NAME=" ???????????????????????????CRLF) - 1 -???????????????????+ s->connection->addr_text.len + s->login.len + s->host.len; +???????????????????+ client_addr->len + s->login.len + s->host.len; ? ?#if (NGX_HAVE_INET6) ?????????if (s->connection->sockaddr->sa_family == AF_INET6) { @@ -549,8 +556,7 @@ ?????????} ?#endif ? -????????p = ngx_copy(p, s->connection->addr_text.data, -?????????????????????s->connection->addr_text.len); +????????p = ngx_copy(p, client_addr->data, client_addr->len); ? ?????????if (s->login.len) { ?????????????p = ngx_cpymem(p, " LOGIN=", sizeof(" LOGIN=") - 1); diff -r e3723f2a11b7 -r 8dd6050ca685 src/mail/ngx_mail_realip_module.c --- /dev/null???Thu Jan 01 00:00:00 1970 +0000 +++ b/src/mail/ngx_mail_realip_module.c Tue Jul 18 09:52:11 2017 +0000 @@ -0,0 +1,239 @@ + +/* + * Copyright (C) Igor Sysoev + * Copyright (C) Nginx, Inc. + */ + + +#include +#include +#include + + +typedef struct { +????ngx_array_t???????*from;?????/* array of ngx_cidr_t */ +} ngx_mail_realip_srv_conf_t; + + +typedef struct { +????struct sockaddr???*sockaddr; +????socklen_t??????????socklen; +????ngx_str_t??????????addr_text; +} ngx_mail_realip_ctx_t; + + +ngx_int_t ngx_mail_realip_handler(ngx_mail_session_t *s); +static char *ngx_mail_realip_from(ngx_conf_t *cf, ngx_command_t *cmd, +????void *conf); +static void *ngx_mail_realip_create_srv_conf(ngx_conf_t *cf); +static char *ngx_mail_realip_merge_srv_conf(ngx_conf_t *cf, void *parent, +????void *child); +//static ngx_int_t ngx_mail_realip_init(ngx_conf_t *cf); + + +static ngx_command_t??ngx_mail_realip_commands[] = { + +????{ ngx_string("set_real_ip_from"), +??????NGX_MAIL_MAIN_CONF|NGX_MAIL_SRV_CONF|NGX_CONF_TAKE1, +??????ngx_mail_realip_from, +??????NGX_MAIL_SRV_CONF_OFFSET, +??????0, +??????NULL }, + +??????ngx_null_command +}; + + +static ngx_mail_module_t??ngx_mail_realip_module_ctx = { +????NULL,??????????????????????????????????/* protocol */ + +????NULL,??????????????????????????????????/* create main configuration */ +????NULL,??????????????????????????????????/* init main configuration */ + +????ngx_mail_realip_create_srv_conf,???????/* create server configuration */ +????ngx_mail_realip_merge_srv_conf?????????/* merge server configuration */ +}; + + +ngx_module_t??ngx_mail_realip_module = { +????NGX_MODULE_V1, +????&ngx_mail_realip_module_ctx,???????????/* module context */ +????ngx_mail_realip_commands,??????????????/* module directives */ +????NGX_MAIL_MODULE,???????????????????????/* module type */ +????NULL,??????????????????????????????????/* init master */ +????NULL,??????????????????????????????????/* init module */ +????NULL,??????????????????????????????????/* init process */ +????NULL,??????????????????????????????????/* init thread */ +????NULL,??????????????????????????????????/* exit thread */ +????NULL,??????????????????????????????????/* exit process */ +????NULL,??????????????????????????????????/* exit master */ +????NGX_MODULE_V1_PADDING +}; + + +ngx_int_t +ngx_mail_realip_handler(ngx_mail_session_t *s) +{ +????ngx_connection_t??????????????*c; +????ngx_mail_realip_srv_conf_t????*rscf; +????u_char?????????????????????????text[NGX_SOCKADDR_STRLEN]; + +????c = s->connection; + +????rscf = ngx_mail_get_module_srv_conf(s, ngx_mail_realip_module); + +????if (rscf->from == NULL) { +????????// No set_real_ip_from defined. Allow all. +????} else if (ngx_cidr_match(c->sockaddr, rscf->from) != NGX_OK) { +????????size_t len = ngx_sock_ntop(c->sockaddr, c->socklen, text, NGX_SOCKADDR_STRLEN, 1); +????????ngx_log_error(NGX_LOG_INFO, c->log, 0, +????????????"*%uA Unauthorized client %*s", c->number, len, text); +????????return NGX_DECLINED; +????} + +????if (c->proxy_protocol_addr.len == 0) { +????????size_t len = ngx_sock_ntop(c->sockaddr, c->socklen, text, NGX_SOCKADDR_STRLEN, 1); +????????ngx_log_error(NGX_LOG_INFO, c->log, 0, +????????????"*%uA No proxy_protocol %*s", c->number, len, text); +????????return NGX_DECLINED; +????} + +????return NGX_OK; +} + + +static char * +ngx_mail_realip_from(ngx_conf_t *cf, ngx_command_t *cmd, void *conf) +{ +????ngx_mail_realip_srv_conf_t *rscf = conf; + +????ngx_int_t?????????????rc; +????ngx_str_t????????????*value; +????ngx_url_t?????????????u; +????ngx_cidr_t????????????c, *cidr; +????ngx_uint_t????????????i; +????struct sockaddr_in???*sin; +#if (NGX_HAVE_INET6) +????struct sockaddr_in6??*sin6; +#endif + +????value = cf->args->elts; + +????if (rscf->from == NULL) { +????????rscf->from = ngx_array_create(cf->pool, 2, +??????????????????????????????????????sizeof(ngx_cidr_t)); +????????if (rscf->from == NULL) { +????????????return NGX_CONF_ERROR; +????????} +????} + +#if (NGX_HAVE_UNIX_DOMAIN) + +????if (ngx_strcmp(value[1].data, "unix:") == 0) { +????????cidr = ngx_array_push(rscf->from); +????????if (cidr == NULL) { +????????????return NGX_CONF_ERROR; +????????} + +????????cidr->family = AF_UNIX; +????????return NGX_CONF_OK; +????} + +#endif + +????rc = ngx_ptocidr(&value[1], &c); + +????if (rc != NGX_ERROR) { +????????if (rc == NGX_DONE) { +????????????ngx_conf_log_error(NGX_LOG_WARN, cf, 0, +???????????????????????????????"low address bits of %V are meaningless", +???????????????????????????????&value[1]); +????????} + +????????cidr = ngx_array_push(rscf->from); +????????if (cidr == NULL) { +????????????return NGX_CONF_ERROR; +????????} + +????????*cidr = c; + +????????return NGX_CONF_OK; +????} + +????ngx_memzero(&u, sizeof(ngx_url_t)); +????u.host = value[1]; + +????if (ngx_inet_resolve_host(cf->pool, &u) != NGX_OK) { +????????if (u.err) { +????????????ngx_conf_log_error(NGX_LOG_EMERG, cf, 0, +???????????????????????????????"%s in set_real_ip_from \"%V\"", +???????????????????????????????u.err, &u.host); +????????} + +????????return NGX_CONF_ERROR; +????} + +????cidr = ngx_array_push_n(rscf->from, u.naddrs); +????if (cidr == NULL) { +????????return NGX_CONF_ERROR; +????} + +????ngx_memzero(cidr, u.naddrs * sizeof(ngx_cidr_t)); + +????for (i = 0; i < u.naddrs; i++) { +????????cidr[i].family = u.addrs[i].sockaddr->sa_family; + +????????switch (cidr[i].family) { + +#if (NGX_HAVE_INET6) +????????case AF_INET6: +????????????sin6 = (struct sockaddr_in6 *) u.addrs[i].sockaddr; +????????????cidr[i].u.in6.addr = sin6->sin6_addr; +????????????ngx_memset(cidr[i].u.in6.mask.s6_addr, 0xff, 16); +????????????break; +#endif + +????????default: /* AF_INET */ +????????????sin = (struct sockaddr_in *) u.addrs[i].sockaddr; +????????????cidr[i].u.in.addr = sin->sin_addr.s_addr; +????????????cidr[i].u.in.mask = 0xffffffff; +????????????break; +????????} +????} + +????return NGX_CONF_OK; +} + + +static void * +ngx_mail_realip_create_srv_conf(ngx_conf_t *cf) +{ +????ngx_mail_realip_srv_conf_t??*conf; + +????conf = ngx_pcalloc(cf->pool, sizeof(ngx_mail_realip_srv_conf_t)); +????if (conf == NULL) { +????????return NULL; +????} + +????/* +?????* set by ngx_pcalloc(): +?????* +?????*?????conf->from = NULL; +?????*/ + +????return conf; +} + + +static char * +ngx_mail_realip_merge_srv_conf(ngx_conf_t *cf, void *parent, void *child) +{ +????ngx_mail_realip_srv_conf_t *prev = parent; +????ngx_mail_realip_srv_conf_t *conf = child; + +????if (conf->from == NULL) { +????????conf->from = prev->from; +????} + +????return NGX_CONF_OK; +} From xeioex at nginx.com Tue Jul 18 11:27:28 2017 From: xeioex at nginx.com (Dmitry Volyntsev) Date: Tue, 18 Jul 2017 11:27:28 +0000 Subject: [njs] Fixed missing extern qualifier. Message-ID: details: http://hg.nginx.org/njs/rev/ce44f3320fdf branches: changeset: 389:ce44f3320fdf user: Dmitry Volyntsev date: Tue Jul 18 14:22:16 2017 +0300 description: Fixed missing extern qualifier. diffstat: njs/njscript.h | 2 +- 1 files changed, 1 insertions(+), 1 deletions(-) diffs (11 lines): diff -r f2ecbe1c2261 -r ce44f3320fdf njs/njscript.h --- a/njs/njscript.h Mon Jul 17 20:38:00 2017 +0300 +++ b/njs/njscript.h Tue Jul 18 14:22:16 2017 +0300 @@ -117,6 +117,6 @@ NXT_EXPORT nxt_int_t njs_value_string_co NXT_EXPORT const char **njs_vm_completions(njs_vm_t *vm); -const nxt_mem_proto_t njs_vm_mem_cache_pool_proto; +extern const nxt_mem_proto_t njs_vm_mem_cache_pool_proto; #endif /* _NJSCRIPT_H_INCLUDED_ */ From mdounin at mdounin.ru Tue Jul 18 12:56:42 2017 From: mdounin at mdounin.ru (Maxim Dounin) Date: Tue, 18 Jul 2017 15:56:42 +0300 Subject: [PATCH] Add proxy_protocol option to mail listener In-Reply-To: <1500372369.24044.27.camel@gmail.com> References: <1499434682.21080.97.camel@gmail.com> <20170711151203.GV55433@mdounin.ru> <1499861311.25851.54.camel@gmail.com> <20170712125636.GT55433@mdounin.ru> <1500372369.24044.27.camel@gmail.com> Message-ID: <20170718125642.GK93611@mdounin.ru> Hello! On Tue, Jul 18, 2017 at 12:06:09PM +0200, Kees Bos wrote: > # HG changeset patch > # User Kees Bos > # Date 1500371531 0 > #??????Tue Jul 18 09:52:11 2017 +0000 > # Node ID 8dd6050ca6858d9bea139067611ca5c69cfe8f18 > # Parent??e3723f2a11b7ec1c196d59c331739bc21d9d9afd > Add proxy_protocol option to mail listener > > Add support for the mail handlers. This enables the use of an upstream > loadbalancer/proxy (like haproxy) that connects with the proxy protocol. > > The original ip (as exposed with the proxy protocol) will be used as > parameter for the 'Client-IP' in the authentication call and as address > in the XCLIENT call. > > Optionally (if set), the real ips from the client that are using the > proxy protocol can be restricted with "set_real_ip_from". This approach looks unsafe and counter-intuitive. Instead, address should be changed if and only if there is set_real_ip_from and it lists a particular client address, much like it is done in http and stream modules. > > Example config: > mail { > ????server_name mail.example.com; > ????auth_http???localhost:9000/; > > ????server { > ????????listen 143 proxy_protocol; > ????????protocol imap; > ????} That is, only parsing of PROXY protocol header should happen here. > > ????server { > ????????listen 25 proxy_protocol; > ????????protocol smtp; > ????????set_real_ip_from 127.0.0.0/8; > ????????set_real_ip_from ::/128; And here we can change client's address if a connection was from listed addresses. We may also consider sending the information from the header in separate auth_http headers (something like Proxy-Protocol-IP, Proxy-Protocol-Port?) regardless of set_real_ip_from. But clearly this should be a separate header from Client-IP to make it possible for auth_http script to decide if this information should be trusted or not. (There are also multiple style issues in the code. Some are outlined below, though I haven't focused on this as the code logic is to be changed anyway. Most of the comments apply to more than one place.) [...] > --- a/src/mail/ngx_mail_auth_http_module.c??????Mon Jul 17 17:23:51 2017 +0300 > +++ b/src/mail/ngx_mail_auth_http_module.c??????Tue Jul 18 09:52:11 2017 +0000 > @@ -1142,6 +1142,7 @@ > ?????ngx_mail_ssl_conf_t???????*sslcf; > ?#endif > ?????ngx_mail_core_srv_conf_t??*cscf; > +????ngx_str_t?????????????????*client_addr; Style: variables should be sorted from shortest type to longest. Moreover, there are other ngx_str_t variables, so it should be added to the already existing list instead. > --- a/src/mail/ngx_mail_handler.c???????Mon Jul 17 17:23:51 2017 +0300 > +++ b/src/mail/ngx_mail_handler.c???????Tue Jul 18 09:52:11 2017 +0000 > @@ -12,13 +12,14 @@ > ? > ? > ?static void ngx_mail_init_session(ngx_connection_t *c); > - > +static void ngx_mail_proxy_protocol_handler(ngx_event_t *rev); > ?#if (NGX_MAIL_SSL) The whitespace change looks wrong. SSL-related functions are listed separately for a reason. [...] > -????ngx_log_error(NGX_LOG_INFO, c->log, 0, "*%uA client %*s connected to %V", > -??????????????????c->number, len, text, s->addr_text); Removing a logging right after a connection is established might be a bad idea. Instead, it might be a better option to introduce additional logging if / when the address is changed. > +????if (s->proxy_protocol) { > +????????c->log->action = "reading PROXY protocol"; > +????????ngx_add_timer(c->read, cscf->timeout); > +????????c->read->handler = ngx_mail_proxy_protocol_handler; > +????????if (ngx_handle_read_event(c->read, 0) != NGX_OK) { > +????????????ngx_mail_close_connection(c); > +????????} > +????????return; > +????} Style: this clearly needs more empty lines. You may want to take a look at the relevant code at the src/stream/ngx_stream_handler.c for an example. [...] > +????ngx_log_error(NGX_LOG_INFO, c->log, 0, > +????????"*%uA client %*s (real %*s:%d) connected to %V", > +????????c->number, len, text, > +????????c->proxy_protocol_addr.len, c->proxy_protocol_addr.data, > +????????c->proxy_protocol_port, s->addr_text); Style: indentation is wrong. Instead, continuation lines should be aligned to the first function argument instead. [...] > +static void *ngx_mail_realip_create_srv_conf(ngx_conf_t *cf); > +static char *ngx_mail_realip_merge_srv_conf(ngx_conf_t *cf, void *parent, > +????void *child); > +//static ngx_int_t ngx_mail_realip_init(ngx_conf_t *cf); No C99-style comments please. [...] -- Maxim Dounin http://nginx.org/ From cornelis.bos at gmail.com Tue Jul 18 13:13:21 2017 From: cornelis.bos at gmail.com (Kees Bos) Date: Tue, 18 Jul 2017 15:13:21 +0200 Subject: [PATCH] Add proxy_protocol option to mail listener In-Reply-To: <20170718125642.GK93611@mdounin.ru> References: <1499434682.21080.97.camel@gmail.com> <20170711151203.GV55433@mdounin.ru> <1499861311.25851.54.camel@gmail.com> <20170712125636.GT55433@mdounin.ru> <1500372369.24044.27.camel@gmail.com> <20170718125642.GK93611@mdounin.ru> Message-ID: <1500383601.24044.36.camel@gmail.com> Some inline stuff just to be sure I do understand what you mean. On di, 2017-07-18 at 15:56 +0300, Maxim Dounin wrote: > Hello! > > On Tue, Jul 18, 2017 at 12:06:09PM +0200, Kees Bos wrote: > > > > > # HG changeset patch > > # User Kees Bos > > # Date 1500371531 0 > > #??????Tue Jul 18 09:52:11 2017 +0000 > > # Node ID 8dd6050ca6858d9bea139067611ca5c69cfe8f18 > > # Parent??e3723f2a11b7ec1c196d59c331739bc21d9d9afd > > Add proxy_protocol option to mail listener > > > > Add support for the mail handlers. This enables the use of an > > upstream > > loadbalancer/proxy (like haproxy) that connects with the proxy > > protocol. > > > > The original ip (as exposed with the proxy protocol) will be used > > as > > parameter for the 'Client-IP' in the authentication call and as > > address > > in the XCLIENT call. > > > > Optionally (if set), the real ips from the client that are using > > the > > proxy protocol can be restricted with "set_real_ip_from". > This approach looks unsafe and counter-intuitive. > > Instead, address should be changed if and only if there is? > set_real_ip_from and it lists a particular client address, much? > like it is done in http and stream modules. So, "set_real_ip_from" is required as soon as "proxy_protocol" is used in the listen directive. Correct? > > > > > > > Example config: > > mail { > > ????server_name mail.example.com; > > ????auth_http???localhost:9000/; > > > > ????server { > > ????????listen 143 proxy_protocol; > > ????????protocol imap; > > ????} > That is, only parsing of PROXY protocol header should happen here. And the connection will be closed since "set_real_ip_from" is missing. Correct? > > > > > > ????server { > > ????????listen 25 proxy_protocol; > > ????????protocol smtp; > > ????????set_real_ip_from 127.0.0.0/8; > > ????????set_real_ip_from ::/128; > And here we can change client's address if a connection was from? > listed addresses. > > We may also consider sending the information from the header in? > separate auth_http headers (something like Proxy-Protocol-IP,? > Proxy-Protocol-Port?) regardless of set_real_ip_from.??But clearly? > this should be a separate header from Client-IP to make it? > possible for auth_http script to decide if this information should? > be trusted or not. Would an additional?Client-Real-IP and Client-Real-Port be better? > (There are also multiple style issues in the code.??Some are? > outlined below, though I haven't focused on this as the code logic? > is to be changed anyway.??Most of the comments apply to more than? > one place.) Tnx From mdounin at mdounin.ru Tue Jul 18 15:02:37 2017 From: mdounin at mdounin.ru (Maxim Dounin) Date: Tue, 18 Jul 2017 18:02:37 +0300 Subject: [PATCH] Add proxy_protocol option to mail listener In-Reply-To: <1500383601.24044.36.camel@gmail.com> References: <1499434682.21080.97.camel@gmail.com> <20170711151203.GV55433@mdounin.ru> <1499861311.25851.54.camel@gmail.com> <20170712125636.GT55433@mdounin.ru> <1500372369.24044.27.camel@gmail.com> <20170718125642.GK93611@mdounin.ru> <1500383601.24044.36.camel@gmail.com> Message-ID: <20170718150237.GL93611@mdounin.ru> Hello! On Tue, Jul 18, 2017 at 03:13:21PM +0200, Kees Bos wrote: > Some inline stuff just to be sure I do understand what you mean. > > On di, 2017-07-18 at 15:56 +0300, Maxim Dounin wrote: > > Hello! > > > > On Tue, Jul 18, 2017 at 12:06:09PM +0200, Kees Bos wrote: > > > > > > > > # HG changeset patch > > > # User Kees Bos > > > # Date 1500371531 0 > > > #??????Tue Jul 18 09:52:11 2017 +0000 > > > # Node ID 8dd6050ca6858d9bea139067611ca5c69cfe8f18 > > > # Parent??e3723f2a11b7ec1c196d59c331739bc21d9d9afd > > > Add proxy_protocol option to mail listener > > > > > > Add support for the mail handlers. This enables the use of an > > > upstream > > > loadbalancer/proxy (like haproxy) that connects with the proxy > > > protocol. > > > > > > The original ip (as exposed with the proxy protocol) will be used > > > as > > > parameter for the 'Client-IP' in the authentication call and as > > > address > > > in the XCLIENT call. > > > > > > Optionally (if set), the real ips from the client that are using > > > the > > > proxy protocol can be restricted with "set_real_ip_from". > > This approach looks unsafe and counter-intuitive. > > > > Instead, address should be changed if and only if there is? > > set_real_ip_from and it lists a particular client address, much? > > like it is done in http and stream modules. > > So, "set_real_ip_from" is required as soon as "proxy_protocol" is used > in the listen directive. > > Correct? > > > > > > > > > > > > > Example config: > > > mail { > > > ????server_name mail.example.com; > > > ????auth_http???localhost:9000/; > > > > > > ????server { > > > ????????listen 143 proxy_protocol; > > > ????????protocol imap; > > > ????} > > That is, only parsing of PROXY protocol header should happen here. > > And the connection will be closed since "set_real_ip_from" is missing. > > Correct? > No. Try looking at http and/or stream modules: "listen ... proxy_protocol" means that nginx will accept PROXY protocol header, and will make its contents available via the $proxy_protocol_addr and $proxy_protocol_port variables. When "set_real_ip_from ...; real_ip_header proxy_protocol;" is additionally used, the address obtained from the PROXY protocol header will be used as a client address. > > > ????server { > > > ????????listen 25 proxy_protocol; > > > ????????protocol smtp; > > > ????????set_real_ip_from 127.0.0.0/8; > > > ????????set_real_ip_from ::/128; > > And here we can change client's address if a connection was from? > > listed addresses. > > > > We may also consider sending the information from the header in? > > separate auth_http headers (something like Proxy-Protocol-IP,? > > Proxy-Protocol-Port?) regardless of set_real_ip_from.??But clearly? > > this should be a separate header from Client-IP to make it? > > possible for auth_http script to decide if this information should? > > be trusted or not. > > Would an additional?Client-Real-IP and Client-Real-Port be better? I don't think so. The word "Real" is misleading. We don't know if it's real or not, it is up to the script to decide if the address should be trusted to use PROXY protocol. Additionally, it doesn't describe the source of the information, so it is a) not clear how Client-IP is different from Client-Real-IP, and b) if a different source will be introduced (for example, XCLIENT), we will have to invent another way to name things. The Proxy-Protocol-IP as proposed above is an attempt to provide something similar to $proxy_protocol_addr and Client-IP at the same time. (Given that we currently don't provide Client-Port in auth_http, Proxy-Protocol-Port probably is a bad idea.) -- Maxim Dounin http://nginx.org/ From xeioex at nginx.com Tue Jul 18 16:28:05 2017 From: xeioex at nginx.com (Dmitry Volyntsev) Date: Tue, 18 Jul 2017 16:28:05 +0000 Subject: [njs] Fixed temporary variables handling in accumulative mode. Message-ID: details: http://hg.nginx.org/njs/rev/c347ea0bbdd6 branches: changeset: 390:c347ea0bbdd6 user: Dmitry Volyntsev date: Tue Jul 18 19:25:50 2017 +0300 description: Fixed temporary variables handling in accumulative mode. diffstat: njs/njs_generator.c | 33 ++++++++++++++++++++++++++------- njs/test/njs_interactive_test.c | 21 +++++++++++++++++++++ njs/test/njs_unit_test.c | 6 ++++++ 3 files changed, 53 insertions(+), 7 deletions(-) diffs (94 lines): diff -r ce44f3320fdf -r c347ea0bbdd6 njs/njs_generator.c --- a/njs/njs_generator.c Tue Jul 18 14:22:16 2017 +0300 +++ b/njs/njs_generator.c Tue Jul 18 19:25:50 2017 +0300 @@ -2540,17 +2540,36 @@ njs_generator_temp_index_get(njs_vm_t *v scope = scope->parent; } - value = nxt_array_add(scope->values[0], &njs_array_mem_proto, - vm->mem_cache_pool); - if (nxt_slow_path(value == NULL)) { - return NJS_INDEX_ERROR; + if (vm->accumulative && scope->type == NJS_SCOPE_GLOBAL) { + + /* + * When non-clonable VM runs in accumulative mode + * all global variables are allocated in absolute scope + * to simplify global scope handling. + */ + + value = nxt_mem_cache_align(vm->mem_cache_pool, sizeof(njs_value_t), + sizeof(njs_value_t)); + if (nxt_slow_path(value == NULL)) { + return NJS_INDEX_ERROR; + } + + index = (njs_index_t) value; + + } else { + + value = nxt_array_add(scope->values[0], &njs_array_mem_proto, + vm->mem_cache_pool); + if (nxt_slow_path(value == NULL)) { + return NJS_INDEX_ERROR; + } + + index = scope->next_index[0]; + scope->next_index[0] += sizeof(njs_value_t); } *value = njs_value_invalid; - index = scope->next_index[0]; - scope->next_index[0] += sizeof(njs_value_t); - return index; } diff -r ce44f3320fdf -r c347ea0bbdd6 njs/test/njs_interactive_test.c --- a/njs/test/njs_interactive_test.c Tue Jul 18 14:22:16 2017 +0300 +++ b/njs/test/njs_interactive_test.c Tue Jul 18 19:25:50 2017 +0300 @@ -63,6 +63,27 @@ static njs_interactive_test_t njs_test[ "sq(function () { return 3 })" ENTER), nxt_string("9") }, + /* Temporary indexes */ + + { nxt_string("var a = [1,2,3], i; for (i in a) {Object.seal({});}" ENTER), + nxt_string("undefined") }, + + { nxt_string("var i; for (i in [1,2,3]) {Object.seal({});}" ENTER), + nxt_string("undefined") }, + + { nxt_string("var a = 'A'; switch (a) {" + "case 0: a += '0';" + "case 1: a += '1';" + "}; a" ENTER), + nxt_string("A") }, + + { nxt_string("var a = 0; try { a = 5 }" + "catch (e) { a = 9 } finally { a++ } a" ENTER), + nxt_string("6") }, + + { nxt_string("/abc/i.test('ABC')" ENTER), + nxt_string("true") }, + /* Error handling */ { nxt_string("var a = ;" ENTER diff -r ce44f3320fdf -r c347ea0bbdd6 njs/test/njs_unit_test.c --- a/njs/test/njs_unit_test.c Tue Jul 18 14:22:16 2017 +0300 +++ b/njs/test/njs_unit_test.c Tue Jul 18 19:25:50 2017 +0300 @@ -2069,6 +2069,12 @@ static njs_unit_test_t njs_test[] = { nxt_string("var a; for (a = 1; a; a--) switch (a) { case 0: continue }"), nxt_string("undefined") }, + { nxt_string("var a = [1,2,3], i; for (i in a) {Object.seal({})}"), + nxt_string("undefined") }, + + { nxt_string("var i; for (i in [1,2,3]) {Object.seal({});}"), + nxt_string("undefined") }, + /* break. */ { nxt_string("break"), From fangpeng1986 at gmail.com Wed Jul 19 05:18:47 2017 From: fangpeng1986 at gmail.com (Peng Fang) Date: Wed, 19 Jul 2017 13:18:47 +0800 Subject: Inconsistency about cache's valid_sec Message-ID: Hello, Maxim and other developers, In the latest official release, ngx_http_file_cache_set_header will be called in ngx_http_upstream_send_response to realy set a cached file's valid_sec. before calling ngx_http_file_cache_set_header, there will be a chance for user defined modules to change the valid_sec in their header filter hooks,no matter what the value is set by Cache-Control/Expires/X-Accel-Expires previously. And that's reasonable. When a cached file is expired, that logic will work fine too. Inconsistency happens, however, when proxy_cache_revalidate is enabled. when we enable proxy_cache_revalidate , ngx_http_file_cache_update_header will be called in ngx_http_upstream_test_next. And in ngx_http_upstream_test_next, there is no chance for user defined modules to change the valid_sec finally in their header filter hooks. Because before calling ngx_http_upstream_cache_send in ngx_http_upstream_test_next, valid_sec will be cached firstly, and set to a cached file after calling ngx_http_upstream_cache_send and ngx_http_file_cache_update_header. If we get valid_sec after ngx_http_upstream_cache_send in ngx_http_upstream_test_next, user defined module's modification of valid_sec will take effect.And the consistency will be kept. I don't konw if i missed something, so what do you think about this situation? Thanks. -------------- next part -------------- An HTML attachment was scrubbed... URL: From ru at nginx.com Wed Jul 19 09:06:42 2017 From: ru at nginx.com (Ruslan Ermilov) Date: Wed, 19 Jul 2017 09:06:42 +0000 Subject: [nginx] Configure: fixed PCRE requirement check by ngx_http_rewrite_module. Message-ID: details: http://hg.nginx.org/nginx/rev/cc7ff76df927 branches: changeset: 7068:cc7ff76df927 user: Samuel Martin date: Wed Jul 19 12:05:50 2017 +0300 description: Configure: fixed PCRE requirement check by ngx_http_rewrite_module. The http_rewrite module cannot be selected when http is disabled. Fixed the PCRE check condition to avoid irrelevant check failure. This is a regression from 4d874b4d82ed. Signed-off-by: Samuel Martin diffstat: auto/lib/conf | 2 +- 1 files changed, 1 insertions(+), 1 deletions(-) diffs (12 lines): diff -r e3723f2a11b7 -r cc7ff76df927 auto/lib/conf --- a/auto/lib/conf Mon Jul 17 17:23:51 2017 +0300 +++ b/auto/lib/conf Wed Jul 19 12:05:50 2017 +0300 @@ -7,7 +7,7 @@ if [ $USE_PCRE = YES -o $PCRE != NONE ]; . auto/lib/pcre/conf else - if [ $USE_PCRE = DISABLED -a $HTTP_REWRITE = YES ]; then + if [ $USE_PCRE = DISABLED -a $HTTP = YES -a $HTTP_REWRITE = YES ]; then cat << END From ru at nginx.com Wed Jul 19 09:10:17 2017 From: ru at nginx.com (Ruslan Ermilov) Date: Wed, 19 Jul 2017 12:10:17 +0300 Subject: [PATCH] auto/lib/conf: fix PCRE condition WRT the http and http_rewrite options In-Reply-To: <20170715103719.GA30107@lo0.su> References: <20170714100845.4077-1-s.martin49@gmail.com> <20170714102512.GB93611@mdounin.ru> <20170715103719.GA30107@lo0.su> Message-ID: <20170719091017.GB10516@lo0.su> http://hg.nginx.org/nginx/rev/cc7ff76df927 On Sat, Jul 15, 2017 at 01:37:19PM +0300, Ruslan Ermilov wrote: > On Fri, Jul 14, 2017 at 01:25:13PM +0300, Maxim Dounin wrote: > > On Fri, Jul 14, 2017 at 12:08:45PM +0200, Samuel Martin wrote: > > > > > http_rewrite module cannot be selected when http server is disabled, so > > > fix the PCRE check condition to avoid irrelevant check failure. [...] > > Seems to be a regression from 4d874b4d82ed (1.11.11), > > http://hg.nginx.org/nginx/rev/4d874b4d82ed. > > > > Ruslan, please take a look. > > Suggest to commit the following: > > # HG changeset patch > # User Ruslan Ermilov > # Date 1500114987 -10800 > # Sat Jul 15 13:36:27 2017 +0300 > # Node ID 207fda85a217a950875540633c4adb72a2f24dfe > # Parent a27e0c7e198ce989a181fba3c22d0c17e18f84a0 > Configure: fixed PCRE requirement check by ngx_http_rewrite_module. > > The http_rewrite module cannot be selected when http is disabled. > Fixed the PCRE check condition to avoid irrelevant check failure. > This is a regression from 4d874b4d82ed. > > Signed-off-by: Samuel Martin > > diff --git a/auto/lib/conf b/auto/lib/conf > --- a/auto/lib/conf > +++ b/auto/lib/conf > @@ -7,7 +7,7 @@ if [ $USE_PCRE = YES -o $PCRE != NONE ]; > . auto/lib/pcre/conf > > else > - if [ $USE_PCRE = DISABLED -a $HTTP_REWRITE = YES ]; then > + if [ $USE_PCRE = DISABLED -a $HTTP = YES -a $HTTP_REWRITE = YES ]; then > > cat << END -- Ruslan Ermilov Join us at nginx.conf, Sep. 6-8, Portland, OR https://www.nginx.com/nginxconf From mdounin at mdounin.ru Wed Jul 19 12:34:46 2017 From: mdounin at mdounin.ru (Maxim Dounin) Date: Wed, 19 Jul 2017 15:34:46 +0300 Subject: Inconsistency about cache's valid_sec In-Reply-To: References: Message-ID: <20170719123446.GN93611@mdounin.ru> Hello! On Wed, Jul 19, 2017 at 01:18:47PM +0800, Peng Fang wrote: > Hello, Maxim and other developers, > > In the latest official release, ngx_http_file_cache_set_header will be > called in ngx_http_upstream_send_response to realy set a cached file's > valid_sec. > before calling ngx_http_file_cache_set_header, there will be a chance for > user defined modules to change the valid_sec in their header filter > hooks,no matter what the value is set by > Cache-Control/Expires/X-Accel-Expires previously. > > And that's reasonable. > > When a cached file is expired, that logic will work fine too. > > Inconsistency happens, however, when proxy_cache_revalidate > > is enabled. when we enable proxy_cache_revalidate > , > ngx_http_file_cache_update_header will be called in > ngx_http_upstream_test_next. And in ngx_http_upstream_test_next, there is > no chance for user defined modules to change the valid_sec finally in their > header filter hooks. Because before calling ngx_http_upstream_cache_send in > ngx_http_upstream_test_next, valid_sec will be cached firstly, and set to a > cached file after calling ngx_http_upstream_cache_send and > ngx_http_file_cache_update_header. > > If we get valid_sec after ngx_http_upstream_cache_send in > ngx_http_upstream_test_next, user defined module's modification of > valid_sec will take effect.And the consistency will be kept. > > I don't konw if i missed something, so what do you think about this > situation? Trying to modify valid_sec from header filters looks like a bug to me. It will expectedly lead to a wrong result in multiple cases, including the one you've described. Don't do that. And no, the proposed solution won't work. The goal of the code is to use cache validity as calculated based on the 304 response returned if it is available. After ngx_http_upstream_cache_send() valid_sec will be based on the original cached response, and can be different. -- Maxim Dounin http://nginx.org/ From zchao1995 at gmail.com Wed Jul 19 13:54:22 2017 From: zchao1995 at gmail.com (Zhang Chao) Date: Wed, 19 Jul 2017 06:54:22 -0700 Subject: [PATCH] Phase_handler: style. Message-ID: # HG changeset patch # User Alex Zhang # Date 1500471580 -28800 # Wed Jul 19 21:39:40 2017 +0800 # Node ID 9744b6eb0e04e53346f3e02aa16cbea1d3dfce72 # Parent cc7ff76df9270a239ce615f0dcff280eb6dfd2ba Phase_handler: style. Signed-off-by: Alex Zhang diff -r cc7ff76df927 -r 9744b6eb0e04 src/http/ngx_http.c --- a/src/http/ngx_http.c Wed Jul 19 12:05:50 2017 +0300 +++ b/src/http/ngx_http.c Wed Jul 19 21:39:40 2017 +0800 @@ -548,7 +548,7 @@ n += cmcf->phases[i].handlers.nelts; - for (j = cmcf->phases[i].handlers.nelts - 1; j >=0; j--) { + for (j = cmcf->phases[i].handlers.nelts - 1; j >= 0; j--) { ph->checker = checker; ph->handler = h[j]; ph->next = n; -------------- next part -------------- An HTML attachment was scrubbed... URL: From mdounin at mdounin.ru Wed Jul 19 14:34:30 2017 From: mdounin at mdounin.ru (Maxim Dounin) Date: Wed, 19 Jul 2017 17:34:30 +0300 Subject: [PATCH 12 of 14] Proxy: add HTTP/2 support In-Reply-To: <7eb807b056da7abe9c67.1498163596@piotrsikora.sfo.corp.google.com> References: <5f5d70428655db0889a2.1498163585@piotrsikora.sfo.corp.google.com> <7eb807b056da7abe9c67.1498163596@piotrsikora.sfo.corp.google.com> Message-ID: <20170719143430.GO93611@mdounin.ru> Hello! On Thu, Jun 22, 2017 at 01:33:16PM -0700, Piotr Sikora via nginx-devel wrote: > # HG changeset patch > # User Piotr Sikora > # Date 1490769087 25200 > # Tue Mar 28 23:31:27 2017 -0700 > # Node ID 7eb807b056da7abe9c679b59e94595d59a1406e6 > # Parent 0637acdb51e29e1f68f5f3e762115c702cab4e72 > Proxy: add HTTP/2 support. > > Signed-off-by: Piotr Sikora [...] There are serious concerns about this and with other patches. Most generic ones are outlined below. 1. Server-side HTTP/2 code complexity concerns. As per discussion with Valentin, introducing client-related code paths in the server HTTP/2 code seems to complicate things. Given that the complexity of the code is already high, it might be better idea to implement separate client-side processing instead. 2. Different protocols in proxy module. You've introduced a completely different protocol in the proxy module, which contradicts the established practice of using separate modules for different protocols. Reasons for having all (or at least may of) the protocols available in the proxy module instead are well understood, and there is a long-term plan to revise current practice. The plan is to preserve protocol-specific modules as a separate entities, but let them share the common configuration directives, similar to how it is currently done with upstream{} blocks and the overall upstream infrastructure. So one can write something like proxy_pass fastcgi://127.0.0.1:9000; and get an expected result. While benefits of having all protocols sharing the same user-visible interface are understood, approach taken with HTTP/2 implementation is considered suboptimal, and will likely lead to something hard to maintain. I see two possible solutions here: - make HTTP/2-to-upstreams a separate full-featured upstream-based module, similar to proxy or fastcgi; - start working on the different protocols in the proxy module, and introduce HTTP/2 proxying after this work is done. Additionally, there are also some minor / related comments: - Parts of the code, tightly coupled with upstream infrastructure, notably ngx_http_v2_upstream_output_filter(), are placed into v2/ directory. Instead, they seem to belong to the HTTP/2-to-upstream module implementation, as suggested in (1). - Upstream infrastructure as available in src/http/ngx_http_upstream.c is expected to be protocol-agnostic. Introducing calls like ngx_http_v2_init_connection() there is a layering violation. Instead, there should be something more generic. - Doing protocol parsing elsewhere instead of parsing things based on what nginx got from the connection results in some generic upstream mechanisms rendered not working - notably, it is no longer possible to simply write headers to a cache file. Serialization introduced instead, at least in its current form, looks more like a bandaid. -- Maxim Dounin http://nginx.org/ From ru at nginx.com Wed Jul 19 19:59:57 2017 From: ru at nginx.com (Ruslan Ermilov) Date: Wed, 19 Jul 2017 19:59:57 +0000 Subject: [nginx] Style. Message-ID: details: http://hg.nginx.org/nginx/rev/863b862534d7 branches: changeset: 7069:863b862534d7 user: Alex Zhang date: Wed Jul 19 21:39:40 2017 +0800 description: Style. Signed-off-by: Alex Zhang diffstat: src/http/ngx_http.c | 2 +- 1 files changed, 1 insertions(+), 1 deletions(-) diffs (12 lines): diff -r cc7ff76df927 -r 863b862534d7 src/http/ngx_http.c --- a/src/http/ngx_http.c Wed Jul 19 12:05:50 2017 +0300 +++ b/src/http/ngx_http.c Wed Jul 19 21:39:40 2017 +0800 @@ -548,7 +548,7 @@ ngx_http_init_phase_handlers(ngx_conf_t n += cmcf->phases[i].handlers.nelts; - for (j = cmcf->phases[i].handlers.nelts - 1; j >=0; j--) { + for (j = cmcf->phases[i].handlers.nelts - 1; j >= 0; j--) { ph->checker = checker; ph->handler = h[j]; ph->next = n; From ru at nginx.com Wed Jul 19 20:05:02 2017 From: ru at nginx.com (Ruslan Ermilov) Date: Wed, 19 Jul 2017 23:05:02 +0300 Subject: [PATCH] Phase_handler: style. In-Reply-To: References: Message-ID: <20170719200502.GE10516@lo0.su> On Wed, Jul 19, 2017 at 06:54:22AM -0700, Zhang Chao wrote: > # HG changeset patch > # User Alex Zhang > # Date 1500471580 -28800 > # Wed Jul 19 21:39:40 2017 +0800 > # Node ID 9744b6eb0e04e53346f3e02aa16cbea1d3dfce72 > # Parent cc7ff76df9270a239ce615f0dcff280eb6dfd2ba > Phase_handler: style. > > Signed-off-by: Alex Zhang > > diff -r cc7ff76df927 -r 9744b6eb0e04 src/http/ngx_http.c > --- a/src/http/ngx_http.c Wed Jul 19 12:05:50 2017 +0300 > +++ b/src/http/ngx_http.c Wed Jul 19 21:39:40 2017 +0800 > @@ -548,7 +548,7 @@ > > n += cmcf->phases[i].handlers.nelts; > > - for (j = cmcf->phases[i].handlers.nelts - 1; j >=0; j--) { > + for (j = cmcf->phases[i].handlers.nelts - 1; j >= 0; j--) { > ph->checker = checker; > ph->handler = h[j]; > ph->next = n; http://hg.nginx.org/nginx/rev/863b862534d7 From fangpeng1986 at gmail.com Thu Jul 20 02:22:46 2017 From: fangpeng1986 at gmail.com (Peng Fang) Date: Thu, 20 Jul 2017 10:22:46 +0800 Subject: Inconsistency about cache's valid_sec In-Reply-To: <20170719123446.GN93611@mdounin.ru> References: <20170719123446.GN93611@mdounin.ru> Message-ID: Thaks for your reply. I totally agree with you that modify valid_sec in header filters sound buggy. >From my side, this is a compromise for reality. Because not all upstream servers are controlled by ourselves, especially for a 3rd CDN provider. There are many customers who want to get highly customized expiration settings, for example, 10 senconds for */a.jpg, 1 minite for */b.jpg, 10 minites for *.zip and so on,but they don't what to control thsese settings by sending Cache-Control family headers. So we have implemented a delicate logic in header filters supportting these requirements for every request. Since it does not meet the standards, there is indeed no reson for you to change the existed code logic. We coud totaly ignore and hide cache-control family headers for these customuers, and keep on setting valid_sec in header filters. Woud you mind giving some advices for this kind of scenario? Thanks very much. 2017-07-19 20:34 GMT+08:00 Maxim Dounin : > Hello! > > On Wed, Jul 19, 2017 at 01:18:47PM +0800, Peng Fang wrote: > > > Hello, Maxim and other developers, > > > > In the latest official release, ngx_http_file_cache_set_header will be > > called in ngx_http_upstream_send_response to realy set a cached file's > > valid_sec. > > before calling ngx_http_file_cache_set_header, there will be a chance > for > > user defined modules to change the valid_sec in their header filter > > hooks,no matter what the value is set by > > Cache-Control/Expires/X-Accel-Expires previously. > > > > And that's reasonable. > > > > When a cached file is expired, that logic will work fine too. > > > > Inconsistency happens, however, when proxy_cache_revalidate > > html#proxy_cache_revalidate> > > is enabled. when we enable proxy_cache_revalidate > > html#proxy_cache_revalidate>, > > ngx_http_file_cache_update_header will be called in > > ngx_http_upstream_test_next. And in ngx_http_upstream_test_next, there is > > no chance for user defined modules to change the valid_sec finally in > their > > header filter hooks. Because before calling ngx_http_upstream_cache_send > in > > ngx_http_upstream_test_next, valid_sec will be cached firstly, and set > to a > > cached file after calling ngx_http_upstream_cache_send and > > ngx_http_file_cache_update_header. > > > > If we get valid_sec after ngx_http_upstream_cache_send in > > ngx_http_upstream_test_next, user defined module's modification of > > valid_sec will take effect.And the consistency will be kept. > > > > I don't konw if i missed something, so what do you think about this > > situation? > > Trying to modify valid_sec from header filters looks like a bug to > me. It will expectedly lead to a wrong result in multiple cases, > including the one you've described. Don't do that. > > And no, the proposed solution won't work. The goal of the code is > to use cache validity as calculated based on the 304 response > returned if it is available. After ngx_http_upstream_cache_send() > valid_sec will be based on the original cached response, and can > be different. > > -- > Maxim Dounin > http://nginx.org/ > _______________________________________________ > 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 cornelis.bos at gmail.com Thu Jul 20 07:52:08 2017 From: cornelis.bos at gmail.com (Kees Bos) Date: Thu, 20 Jul 2017 09:52:08 +0200 Subject: [PATCH] Add proxy_protocol option to mail listener In-Reply-To: <20170718150237.GL93611@mdounin.ru> References: <1499434682.21080.97.camel@gmail.com> <20170711151203.GV55433@mdounin.ru> <1499861311.25851.54.camel@gmail.com> <20170712125636.GT55433@mdounin.ru> <1500372369.24044.27.camel@gmail.com> <20170718125642.GK93611@mdounin.ru> <1500383601.24044.36.camel@gmail.com> <20170718150237.GL93611@mdounin.ru> Message-ID: <1500537128.19807.5.camel@gmail.com> On di, 2017-07-18 at 18:02 +0300, Maxim Dounin wrote: > Hello! > > On Tue, Jul 18, 2017 at 03:13:21PM +0200, Kees Bos wrote: > > > > > Some inline stuff just to be sure I do understand what you mean. > > > > On di, 2017-07-18 at 15:56 +0300, Maxim Dounin wrote: > > > > > > Hello! > > > > > > On Tue, Jul 18, 2017 at 12:06:09PM +0200, Kees Bos wrote: > > > > > > > > > > > > > > > # HG changeset patch > > > > # User Kees Bos > > > > # Date 1500371531 0 > > > > #??????Tue Jul 18 09:52:11 2017 +0000 > > > > # Node ID 8dd6050ca6858d9bea139067611ca5c69cfe8f18 > > > > # Parent??e3723f2a11b7ec1c196d59c331739bc21d9d9afd > > > > Add proxy_protocol option to mail listener > > > > > > > > Add support for the mail handlers. This enables the use of an > > > > upstream > > > > loadbalancer/proxy (like haproxy) that connects with the proxy > > > > protocol. > > > > > > > > The original ip (as exposed with the proxy protocol) will be > > > > used > > > > as > > > > parameter for the 'Client-IP' in the authentication call and as > > > > address > > > > in the XCLIENT call. > > > > > > > > Optionally (if set), the real ips from the client that are > > > > using > > > > the > > > > proxy protocol can be restricted with "set_real_ip_from". > > > This approach looks unsafe and counter-intuitive. > > > > > > Instead, address should be changed if and only if there is? > > > set_real_ip_from and it lists a particular client address, much? > > > like it is done in http and stream modules. > > So, "set_real_ip_from" is required as soon as "proxy_protocol" is > > used > > in the listen directive. > > > > Correct? > > > > > > > > > > > > > > > > > > > > > > > > > > Example config: > > > > mail { > > > > ????server_name mail.example.com; > > > > ????auth_http???localhost:9000/; > > > > > > > > ????server { > > > > ????????listen 143 proxy_protocol; > > > > ????????protocol imap; > > > > ????} > > > That is, only parsing of PROXY protocol header should happen > > > here. > > And the connection will be closed since "set_real_ip_from" is > > missing. > > > > Correct? > > > No. > > Try looking at http and/or stream modules: "listen ...?? > proxy_protocol" means that nginx will accept PROXY protocol? > header, and will make its contents available via the? > $proxy_protocol_addr and $proxy_protocol_port variables. > > When "set_real_ip_from ...; real_ip_header proxy_protocol;" is? > additionally used, the address obtained from the PROXY protocol? > header will be used as a client address. > > > > > > > > > > > > > > ????server { > > > > ????????listen 25 proxy_protocol; > > > > ????????protocol smtp; > > > > ????????set_real_ip_from 127.0.0.0/8; > > > > ????????set_real_ip_from ::/128; > > > And here we can change client's address if a connection was from? > > > listed addresses. > > > > > > We may also consider sending the information from the header in? > > > separate auth_http headers (something like Proxy-Protocol-IP,? > > > Proxy-Protocol-Port?) regardless of set_real_ip_from.??But > > > clearly? > > > this should be a separate header from Client-IP to make it? > > > possible for auth_http script to decide if this information > > > should? > > > be trusted or not. > > Would an additional?Client-Real-IP and Client-Real-Port be better? > I don't think so. > > The word "Real" is misleading.??We don't know if it's real or not,? > it is up to the script to decide if the address should be trusted? > to use PROXY protocol. > > Additionally, it doesn't describe the source of the information,? > so it is a) not clear how Client-IP is different from? > Client-Real-IP, and b) if a different source will be introduced? > (for example, XCLIENT), we will have to invent another way to name? > things. > > The Proxy-Protocol-IP as proposed above is an attempt to provide? > something similar to $proxy_protocol_addr and Client-IP at the? > same time. > > (Given that we currently don't provide Client-Port in auth_http,? > Proxy-Protocol-Port probably is a bad idea.) Maybe it would be a bit future proof (in case some other mangling protocols will be invented) to use (iff proxy-protocol ip address is set) something like: Proxy-IP: Original-IP: From mdounin at mdounin.ru Thu Jul 20 13:11:28 2017 From: mdounin at mdounin.ru (Maxim Dounin) Date: Thu, 20 Jul 2017 16:11:28 +0300 Subject: Inconsistency about cache's valid_sec In-Reply-To: References: <20170719123446.GN93611@mdounin.ru> Message-ID: <20170720131128.GW93611@mdounin.ru> Hello! On Thu, Jul 20, 2017 at 10:22:46AM +0800, Peng Fang wrote: > From my side, this is a compromise for reality. Because not all upstream > servers are controlled by ourselves, especially for a 3rd CDN provider. > There are many customers who want to get highly customized expiration > settings, for example, 10 senconds for */a.jpg, 1 minite for */b.jpg, 10 > minites for *.zip and so on,but they don't what to control thsese settings > by sending Cache-Control family headers. So we have implemented a delicate > logic in header filters supportting these requirements for every request. > > Since it does not meet the standards, there is indeed no reson for you to > change the existed code logic. We coud totaly ignore and hide cache-control > family headers for these customuers, and keep on setting valid_sec in > header filters. > > Woud you mind giving some advices for this kind of scenario? Thanks very > much. An obvious though suboptimal solution would be to use a separate proxy layer which will add appropriate headers to control caching. -- Maxim Dounin http://nginx.org/ From mdounin at mdounin.ru Thu Jul 20 13:22:15 2017 From: mdounin at mdounin.ru (Maxim Dounin) Date: Thu, 20 Jul 2017 16:22:15 +0300 Subject: [PATCH] Add proxy_protocol option to mail listener In-Reply-To: <1500537128.19807.5.camel@gmail.com> References: <1499434682.21080.97.camel@gmail.com> <20170711151203.GV55433@mdounin.ru> <1499861311.25851.54.camel@gmail.com> <20170712125636.GT55433@mdounin.ru> <1500372369.24044.27.camel@gmail.com> <20170718125642.GK93611@mdounin.ru> <1500383601.24044.36.camel@gmail.com> <20170718150237.GL93611@mdounin.ru> <1500537128.19807.5.camel@gmail.com> Message-ID: <20170720132215.GX93611@mdounin.ru> Hello! On Thu, Jul 20, 2017 at 09:52:08AM +0200, Kees Bos wrote: > On di, 2017-07-18 at 18:02 +0300, Maxim Dounin wrote: > > Hello! > > > > On Tue, Jul 18, 2017 at 03:13:21PM +0200, Kees Bos wrote: > > > > > > > > Some inline stuff just to be sure I do understand what you mean. > > > > > > On di, 2017-07-18 at 15:56 +0300, Maxim Dounin wrote: > > > > > > > > Hello! > > > > > > > > On Tue, Jul 18, 2017 at 12:06:09PM +0200, Kees Bos wrote: > > > > > > > > > > > > > > > > > > > # HG changeset patch > > > > > # User Kees Bos > > > > > # Date 1500371531 0 > > > > > #??????Tue Jul 18 09:52:11 2017 +0000 > > > > > # Node ID 8dd6050ca6858d9bea139067611ca5c69cfe8f18 > > > > > # Parent??e3723f2a11b7ec1c196d59c331739bc21d9d9afd > > > > > Add proxy_protocol option to mail listener > > > > > > > > > > Add support for the mail handlers. This enables the use of an > > > > > upstream > > > > > loadbalancer/proxy (like haproxy) that connects with the proxy > > > > > protocol. > > > > > > > > > > The original ip (as exposed with the proxy protocol) will be > > > > > used > > > > > as > > > > > parameter for the 'Client-IP' in the authentication call and as > > > > > address > > > > > in the XCLIENT call. > > > > > > > > > > Optionally (if set), the real ips from the client that are > > > > > using > > > > > the > > > > > proxy protocol can be restricted with "set_real_ip_from". > > > > This approach looks unsafe and counter-intuitive. > > > > > > > > Instead, address should be changed if and only if there is? > > > > set_real_ip_from and it lists a particular client address, much? > > > > like it is done in http and stream modules. > > > So, "set_real_ip_from" is required as soon as "proxy_protocol" is > > > used > > > in the listen directive. > > > > > > Correct? > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > Example config: > > > > > mail { > > > > > ????server_name mail.example.com; > > > > > ????auth_http???localhost:9000/; > > > > > > > > > > ????server { > > > > > ????????listen 143 proxy_protocol; > > > > > ????????protocol imap; > > > > > ????} > > > > That is, only parsing of PROXY protocol header should happen > > > > here. > > > And the connection will be closed since "set_real_ip_from" is > > > missing. > > > > > > Correct? > > > > > No. > > > > Try looking at http and/or stream modules: "listen ...?? > > proxy_protocol" means that nginx will accept PROXY protocol? > > header, and will make its contents available via the? > > $proxy_protocol_addr and $proxy_protocol_port variables. > > > > When "set_real_ip_from ...; real_ip_header proxy_protocol;" is? > > additionally used, the address obtained from the PROXY protocol? > > header will be used as a client address. > > > > > > > > > > > > > > > > > > > ????server { > > > > > ????????listen 25 proxy_protocol; > > > > > ????????protocol smtp; > > > > > ????????set_real_ip_from 127.0.0.0/8; > > > > > ????????set_real_ip_from ::/128; > > > > And here we can change client's address if a connection was from? > > > > listed addresses. > > > > > > > > We may also consider sending the information from the header in? > > > > separate auth_http headers (something like Proxy-Protocol-IP,? > > > > Proxy-Protocol-Port?) regardless of set_real_ip_from.??But > > > > clearly? > > > > this should be a separate header from Client-IP to make it? > > > > possible for auth_http script to decide if this information > > > > should? > > > > be trusted or not. > > > Would an additional?Client-Real-IP and Client-Real-Port be better? > > I don't think so. > > > > The word "Real" is misleading.??We don't know if it's real or not,? > > it is up to the script to decide if the address should be trusted? > > to use PROXY protocol. > > > > Additionally, it doesn't describe the source of the information,? > > so it is a) not clear how Client-IP is different from? > > Client-Real-IP, and b) if a different source will be introduced? > > (for example, XCLIENT), we will have to invent another way to name? > > things. > > > > The Proxy-Protocol-IP as proposed above is an attempt to provide? > > something similar to $proxy_protocol_addr and Client-IP at the? > > same time. > > > > (Given that we currently don't provide Client-Port in auth_http,? > > Proxy-Protocol-Port probably is a bad idea.) > > > Maybe it would be a bit future proof (in case some other mangling > protocols will be invented) to use (iff proxy-protocol ip address is > set) something like: > > Proxy-IP: > Original-IP: I don't see how it resolves the same disadvanteges as outline for the Client-Real-IP header. Much like in the Client-Real-IP case, - "Original" is misleading, and - it will conflict if we'll have an IP address from a different source (for example, the XCLIENT SMTP command). Additionally, I don't see reasons to introduce Proxy-IP instead of currently used Client-IP. It looks unneeded (we already have Client-IP for the very same data, no?) and also confusing (it can be easily interpreted as $proxy_protocol_addr instead, at least this is what I initially tought when reading your messages). -- Maxim Dounin http://nginx.org/ From fangpeng1986 at gmail.com Thu Jul 20 14:24:29 2017 From: fangpeng1986 at gmail.com (Peng Fang) Date: Thu, 20 Jul 2017 22:24:29 +0800 Subject: Inconsistency about cache's valid_sec In-Reply-To: <20170720131128.GW93611@mdounin.ru> References: <20170719123446.GN93611@mdounin.ru> <20170720131128.GW93611@mdounin.ru> Message-ID: got it, thank you. 2017-07-20 21:11 GMT+08:00 Maxim Dounin : > Hello! > > On Thu, Jul 20, 2017 at 10:22:46AM +0800, Peng Fang wrote: > > > From my side, this is a compromise for reality. Because not all upstream > > servers are controlled by ourselves, especially for a 3rd CDN provider. > > There are many customers who want to get highly customized expiration > > settings, for example, 10 senconds for */a.jpg, 1 minite for */b.jpg, 10 > > minites for *.zip and so on,but they don't what to control thsese > settings > > by sending Cache-Control family headers. So we have implemented a > delicate > > logic in header filters supportting these requirements for every request. > > > > Since it does not meet the standards, there is indeed no reson for you to > > change the existed code logic. We coud totaly ignore and hide > cache-control > > family headers for these customuers, and keep on setting valid_sec in > > header filters. > > > > Woud you mind giving some advices for this kind of scenario? Thanks very > > much. > > An obvious though suboptimal solution would be to use a separate > proxy layer which will add appropriate headers to control caching. > > -- > Maxim Dounin > http://nginx.org/ > _______________________________________________ > 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 cornelis.bos at gmail.com Thu Jul 20 15:43:09 2017 From: cornelis.bos at gmail.com (Kees Bos) Date: Thu, 20 Jul 2017 17:43:09 +0200 Subject: [PATCH] Add proxy_protocol option to mail listener In-Reply-To: <20170720132215.GX93611@mdounin.ru> References: <1499434682.21080.97.camel@gmail.com> <20170711151203.GV55433@mdounin.ru> <1499861311.25851.54.camel@gmail.com> <20170712125636.GT55433@mdounin.ru> <1500372369.24044.27.camel@gmail.com> <20170718125642.GK93611@mdounin.ru> <1500383601.24044.36.camel@gmail.com> <20170718150237.GL93611@mdounin.ru> <1500537128.19807.5.camel@gmail.com> <20170720132215.GX93611@mdounin.ru> Message-ID: <1500565389.19807.17.camel@gmail.com> From arut at nginx.com Thu Jul 20 17:03:33 2017 From: arut at nginx.com (Roman Arutyunyan) Date: Thu, 20 Jul 2017 17:03:33 +0000 Subject: [nginx] Upstream: keep request body file from removal if requested. Message-ID: details: http://hg.nginx.org/nginx/rev/f583559aadc7 branches: changeset: 7070:f583559aadc7 user: Roman Arutyunyan date: Wed Jul 19 20:38:17 2017 +0300 description: Upstream: keep request body file from removal if requested. The new request flag "preserve_body" indicates that the request body file should not be removed by the upstream module because it may be used later by a subrequest. The flag is set by the SSI (ticket #585), addition and slice modules. Additionally, it is also set by the upstream module when a background cache update subrequest is started to prevent the request body file removal after an internal redirect. Only the main request is now allowed to remove the file. diffstat: src/http/modules/ngx_http_addition_filter_module.c | 2 ++ src/http/modules/ngx_http_slice_filter_module.c | 2 ++ src/http/modules/ngx_http_ssi_filter_module.c | 2 ++ src/http/ngx_http_request.h | 1 + src/http/ngx_http_upstream.c | 8 +++++++- 5 files changed, 14 insertions(+), 1 deletions(-) diffs (72 lines): diff -r 863b862534d7 -r f583559aadc7 src/http/modules/ngx_http_addition_filter_module.c --- a/src/http/modules/ngx_http_addition_filter_module.c Wed Jul 19 21:39:40 2017 +0800 +++ b/src/http/modules/ngx_http_addition_filter_module.c Wed Jul 19 20:38:17 2017 +0300 @@ -123,6 +123,8 @@ ngx_http_addition_header_filter(ngx_http ngx_http_clear_accept_ranges(r); ngx_http_weak_etag(r); + r->preserve_body = 1; + return ngx_http_next_header_filter(r); } diff -r 863b862534d7 -r f583559aadc7 src/http/modules/ngx_http_slice_filter_module.c --- a/src/http/modules/ngx_http_slice_filter_module.c Wed Jul 19 21:39:40 2017 +0800 +++ b/src/http/modules/ngx_http_slice_filter_module.c Wed Jul 19 20:38:17 2017 +0300 @@ -190,6 +190,8 @@ ngx_http_slice_header_filter(ngx_http_re return rc; } + r->preserve_body = 1; + if (r->headers_out.status == NGX_HTTP_PARTIAL_CONTENT) { if (ctx->start + (off_t) slcf->size <= r->headers_out.content_offset) { ctx->start = slcf->size diff -r 863b862534d7 -r f583559aadc7 src/http/modules/ngx_http_ssi_filter_module.c --- a/src/http/modules/ngx_http_ssi_filter_module.c Wed Jul 19 21:39:40 2017 +0800 +++ b/src/http/modules/ngx_http_ssi_filter_module.c Wed Jul 19 20:38:17 2017 +0300 @@ -370,6 +370,8 @@ ngx_http_ssi_header_filter(ngx_http_requ ngx_http_clear_content_length(r); ngx_http_clear_accept_ranges(r); + r->preserve_body = 1; + if (!slcf->last_modified) { ngx_http_clear_last_modified(r); ngx_http_clear_etag(r); diff -r 863b862534d7 -r f583559aadc7 src/http/ngx_http_request.h --- a/src/http/ngx_http_request.h Wed Jul 19 21:39:40 2017 +0800 +++ b/src/http/ngx_http_request.h Wed Jul 19 20:38:17 2017 +0300 @@ -537,6 +537,7 @@ struct ngx_http_request_s { unsigned main_filter_need_in_memory:1; unsigned filter_need_in_memory:1; unsigned filter_need_temporary:1; + unsigned preserve_body:1; unsigned allow_ranges:1; unsigned subrequest_ranges:1; unsigned single_range:1; diff -r 863b862534d7 -r f583559aadc7 src/http/ngx_http_upstream.c --- a/src/http/ngx_http_upstream.c Wed Jul 19 21:39:40 2017 +0800 +++ b/src/http/ngx_http_upstream.c Wed Jul 19 20:38:17 2017 +0300 @@ -1077,6 +1077,10 @@ ngx_http_upstream_cache_background_updat return NGX_OK; } + if (r == r->main) { + r->preserve_body = 1; + } + if (ngx_http_subrequest(r, &r->uri, &r->args, &sr, NULL, NGX_HTTP_SUBREQUEST_CLONE |NGX_HTTP_SUBREQUEST_BACKGROUND) @@ -2857,7 +2861,9 @@ ngx_http_upstream_send_response(ngx_http u->pipe->downstream_error = 1; } - if (r->request_body && r->request_body->temp_file) { + if (r->request_body && r->request_body->temp_file + && r == r->main && !r->preserve_body) + { ngx_pool_run_cleanup_file(r->pool, r->request_body->temp_file->file.fd); r->request_body->temp_file->file.fd = NGX_INVALID_FILE; } From arut at nginx.com Thu Jul 20 17:03:36 2017 From: arut at nginx.com (Roman Arutyunyan) Date: Thu, 20 Jul 2017 17:03:36 +0000 Subject: [nginx] Precontent phase. Message-ID: details: http://hg.nginx.org/nginx/rev/cce6936ed2f4 branches: changeset: 7071:cce6936ed2f4 user: Roman Arutyunyan date: Thu Jul 20 15:51:11 2017 +0300 description: Precontent phase. The phase is added instead of the try_files phase. Unlike the old phase, the new one supports registering multiple handlers. The try_files implementation is moved to a separate ngx_http_try_files_module, which now registers a precontent phase handler. diffstat: auto/modules | 11 + src/http/modules/ngx_http_try_files_module.c | 404 +++++++++++++++++++++++++++ src/http/ngx_http.c | 19 +- src/http/ngx_http_core_module.c | 310 -------------------- src/http/ngx_http_core_module.h | 18 +- 5 files changed, 425 insertions(+), 337 deletions(-) diffs (876 lines): diff -r f583559aadc7 -r cce6936ed2f4 auto/modules --- a/auto/modules Wed Jul 19 20:38:17 2017 +0300 +++ b/auto/modules Thu Jul 20 15:51:11 2017 +0300 @@ -506,6 +506,17 @@ if [ $HTTP = YES ]; then . auto/module fi + if :; then + ngx_module_name=ngx_http_try_files_module + ngx_module_incs= + ngx_module_deps= + ngx_module_srcs=src/http/modules/ngx_http_try_files_module.c + ngx_module_libs= + ngx_module_link=YES + + . auto/module + fi + if [ $HTTP_AUTH_REQUEST = YES ]; then ngx_module_name=ngx_http_auth_request_module ngx_module_incs= diff -r f583559aadc7 -r cce6936ed2f4 src/http/modules/ngx_http_try_files_module.c --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/src/http/modules/ngx_http_try_files_module.c Thu Jul 20 15:51:11 2017 +0300 @@ -0,0 +1,404 @@ + +/* + * Copyright (C) Igor Sysoev + * Copyright (C) Nginx, Inc. + */ + + +#include +#include +#include + + +typedef struct { + ngx_array_t *lengths; + ngx_array_t *values; + ngx_str_t name; + + unsigned code:10; + unsigned test_dir:1; +} ngx_http_try_file_t; + + +typedef struct { + ngx_http_try_file_t *try_files; +} ngx_http_try_files_loc_conf_t; + + +static ngx_int_t ngx_http_try_files_handler(ngx_http_request_t *r); +static char *ngx_http_try_files(ngx_conf_t *cf, ngx_command_t *cmd, void *conf); +static void *ngx_http_try_files_create_loc_conf(ngx_conf_t *cf); +static ngx_int_t ngx_http_try_files_init(ngx_conf_t *cf); + + +static ngx_command_t ngx_http_try_files_commands[] = { + + { ngx_string("try_files"), + NGX_HTTP_SRV_CONF|NGX_HTTP_LOC_CONF|NGX_CONF_2MORE, + ngx_http_try_files, + NGX_HTTP_LOC_CONF_OFFSET, + 0, + NULL }, + + ngx_null_command +}; + + +static ngx_http_module_t ngx_http_try_files_module_ctx = { + NULL, /* preconfiguration */ + ngx_http_try_files_init, /* postconfiguration */ + + NULL, /* create main configuration */ + NULL, /* init main configuration */ + + NULL, /* create server configuration */ + NULL, /* merge server configuration */ + + ngx_http_try_files_create_loc_conf, /* create location configuration */ + NULL /* merge location configuration */ +}; + + +ngx_module_t ngx_http_try_files_module = { + NGX_MODULE_V1, + &ngx_http_try_files_module_ctx, /* module context */ + ngx_http_try_files_commands, /* module directives */ + NGX_HTTP_MODULE, /* module type */ + NULL, /* init master */ + NULL, /* init module */ + NULL, /* init process */ + NULL, /* init thread */ + NULL, /* exit thread */ + NULL, /* exit process */ + NULL, /* exit master */ + NGX_MODULE_V1_PADDING +}; + + +static ngx_int_t +ngx_http_try_files_handler(ngx_http_request_t *r) +{ + size_t len, root, alias, reserve, allocated; + u_char *p, *name; + ngx_str_t path, args; + ngx_uint_t test_dir; + ngx_http_try_file_t *tf; + ngx_open_file_info_t of; + ngx_http_script_code_pt code; + ngx_http_script_engine_t e; + ngx_http_core_loc_conf_t *clcf; + ngx_http_script_len_code_pt lcode; + ngx_http_try_files_loc_conf_t *tlcf; + + tlcf = ngx_http_get_module_loc_conf(r, ngx_http_try_files_module); + + if (tlcf->try_files == NULL) { + return NGX_DECLINED; + } + + ngx_log_debug0(NGX_LOG_DEBUG_HTTP, r->connection->log, 0, + "try files handler"); + + allocated = 0; + root = 0; + name = NULL; + /* suppress MSVC warning */ + path.data = NULL; + + tf = tlcf->try_files; + + clcf = ngx_http_get_module_loc_conf(r, ngx_http_core_module); + + alias = clcf->alias; + + for ( ;; ) { + + if (tf->lengths) { + ngx_memzero(&e, sizeof(ngx_http_script_engine_t)); + + e.ip = tf->lengths->elts; + e.request = r; + + /* 1 is for terminating '\0' as in static names */ + len = 1; + + while (*(uintptr_t *) e.ip) { + lcode = *(ngx_http_script_len_code_pt *) e.ip; + len += lcode(&e); + } + + } else { + len = tf->name.len; + } + + if (!alias) { + reserve = len > r->uri.len ? len - r->uri.len : 0; + + } else if (alias == NGX_MAX_SIZE_T_VALUE) { + reserve = len; + + } else { + reserve = len > r->uri.len - alias ? len - (r->uri.len - alias) : 0; + } + + if (reserve > allocated || !allocated) { + + /* 16 bytes are preallocation */ + allocated = reserve + 16; + + if (ngx_http_map_uri_to_path(r, &path, &root, allocated) == NULL) { + return NGX_HTTP_INTERNAL_SERVER_ERROR; + } + + name = path.data + root; + } + + if (tf->values == NULL) { + + /* tf->name.len includes the terminating '\0' */ + + ngx_memcpy(name, tf->name.data, tf->name.len); + + path.len = (name + tf->name.len - 1) - path.data; + + } else { + e.ip = tf->values->elts; + e.pos = name; + e.flushed = 1; + + while (*(uintptr_t *) e.ip) { + code = *(ngx_http_script_code_pt *) e.ip; + code((ngx_http_script_engine_t *) &e); + } + + path.len = e.pos - path.data; + + *e.pos = '\0'; + + if (alias && alias != NGX_MAX_SIZE_T_VALUE + && ngx_strncmp(name, r->uri.data, alias) == 0) + { + ngx_memmove(name, name + alias, len - alias); + path.len -= alias; + } + } + + test_dir = tf->test_dir; + + tf++; + + ngx_log_debug3(NGX_LOG_DEBUG_HTTP, r->connection->log, 0, + "trying to use %s: \"%s\" \"%s\"", + test_dir ? "dir" : "file", name, path.data); + + if (tf->lengths == NULL && tf->name.len == 0) { + + if (tf->code) { + return tf->code; + } + + path.len -= root; + path.data += root; + + if (path.data[0] == '@') { + (void) ngx_http_named_location(r, &path); + + } else { + ngx_http_split_args(r, &path, &args); + + (void) ngx_http_internal_redirect(r, &path, &args); + } + + ngx_http_finalize_request(r, NGX_DONE); + return NGX_DONE; + } + + ngx_memzero(&of, sizeof(ngx_open_file_info_t)); + + of.read_ahead = clcf->read_ahead; + of.directio = clcf->directio; + of.valid = clcf->open_file_cache_valid; + of.min_uses = clcf->open_file_cache_min_uses; + of.test_only = 1; + of.errors = clcf->open_file_cache_errors; + of.events = clcf->open_file_cache_events; + + if (ngx_http_set_disable_symlinks(r, clcf, &path, &of) != NGX_OK) { + return NGX_HTTP_INTERNAL_SERVER_ERROR; + } + + if (ngx_open_cached_file(clcf->open_file_cache, &path, &of, r->pool) + != NGX_OK) + { + if (of.err == 0) { + return NGX_HTTP_INTERNAL_SERVER_ERROR; + } + + if (of.err != NGX_ENOENT + && of.err != NGX_ENOTDIR + && of.err != NGX_ENAMETOOLONG) + { + ngx_log_error(NGX_LOG_CRIT, r->connection->log, of.err, + "%s \"%s\" failed", of.failed, path.data); + } + + continue; + } + + if (of.is_dir != test_dir) { + continue; + } + + path.len -= root; + path.data += root; + + if (!alias) { + r->uri = path; + + } else if (alias == NGX_MAX_SIZE_T_VALUE) { + if (!test_dir) { + r->uri = path; + r->add_uri_to_alias = 1; + } + + } else { + name = r->uri.data; + + r->uri.len = alias + path.len; + r->uri.data = ngx_pnalloc(r->pool, r->uri.len); + if (r->uri.data == NULL) { + r->uri.len = 0; + return NGX_HTTP_INTERNAL_SERVER_ERROR; + } + + p = ngx_copy(r->uri.data, name, alias); + ngx_memcpy(p, path.data, path.len); + } + + ngx_http_set_exten(r); + + ngx_log_debug1(NGX_LOG_DEBUG_HTTP, r->connection->log, 0, + "try file uri: \"%V\"", &r->uri); + + return NGX_DECLINED; + } + + /* not reached */ +} + + +static char * +ngx_http_try_files(ngx_conf_t *cf, ngx_command_t *cmd, void *conf) +{ + ngx_http_try_files_loc_conf_t *tlcf = conf; + + ngx_str_t *value; + ngx_int_t code; + ngx_uint_t i, n; + ngx_http_try_file_t *tf; + ngx_http_script_compile_t sc; + + if (tlcf->try_files) { + return "is duplicate"; + } + + tf = ngx_pcalloc(cf->pool, cf->args->nelts * sizeof(ngx_http_try_file_t)); + if (tf == NULL) { + return NGX_CONF_ERROR; + } + + tlcf->try_files = tf; + + value = cf->args->elts; + + for (i = 0; i < cf->args->nelts - 1; i++) { + + tf[i].name = value[i + 1]; + + if (tf[i].name.len > 0 + && tf[i].name.data[tf[i].name.len - 1] == '/' + && i + 2 < cf->args->nelts) + { + tf[i].test_dir = 1; + tf[i].name.len--; + tf[i].name.data[tf[i].name.len] = '\0'; + } + + n = ngx_http_script_variables_count(&tf[i].name); + + if (n) { + ngx_memzero(&sc, sizeof(ngx_http_script_compile_t)); + + sc.cf = cf; + sc.source = &tf[i].name; + sc.lengths = &tf[i].lengths; + sc.values = &tf[i].values; + sc.variables = n; + sc.complete_lengths = 1; + sc.complete_values = 1; + + if (ngx_http_script_compile(&sc) != NGX_OK) { + return NGX_CONF_ERROR; + } + + } else { + /* add trailing '\0' to length */ + tf[i].name.len++; + } + } + + if (tf[i - 1].name.data[0] == '=') { + + code = ngx_atoi(tf[i - 1].name.data + 1, tf[i - 1].name.len - 2); + + if (code == NGX_ERROR || code > 999) { + ngx_conf_log_error(NGX_LOG_EMERG, cf, 0, + "invalid code \"%*s\"", + tf[i - 1].name.len - 1, tf[i - 1].name.data); + return NGX_CONF_ERROR; + } + + tf[i].code = code; + } + + return NGX_CONF_OK; +} + + +static void * +ngx_http_try_files_create_loc_conf(ngx_conf_t *cf) +{ + ngx_http_try_files_loc_conf_t *tlcf; + + tlcf = ngx_pcalloc(cf->pool, sizeof(ngx_http_try_files_loc_conf_t)); + if (tlcf == NULL) { + return NULL; + } + + /* + * set by ngx_pcalloc(): + * + * tlcf->try_files = NULL; + */ + + return tlcf; +} + + +static ngx_int_t +ngx_http_try_files_init(ngx_conf_t *cf) +{ + ngx_http_handler_pt *h; + ngx_http_core_main_conf_t *cmcf; + + cmcf = ngx_http_conf_get_module_main_conf(cf, ngx_http_core_module); + + h = ngx_array_push(&cmcf->phases[NGX_HTTP_PRECONTENT_PHASE].handlers); + if (h == NULL) { + return NGX_ERROR; + } + + *h = ngx_http_try_files_handler; + + return NGX_OK; +} diff -r f583559aadc7 -r cce6936ed2f4 src/http/ngx_http.c --- a/src/http/ngx_http.c Wed Jul 19 20:38:17 2017 +0300 +++ b/src/http/ngx_http.c Thu Jul 20 15:51:11 2017 +0300 @@ -382,6 +382,13 @@ ngx_http_init_phases(ngx_conf_t *cf, ngx return NGX_ERROR; } + if (ngx_array_init(&cmcf->phases[NGX_HTTP_PRECONTENT_PHASE].handlers, + cf->pool, 2, sizeof(ngx_http_handler_pt)) + != NGX_OK) + { + return NGX_ERROR; + } + if (ngx_array_init(&cmcf->phases[NGX_HTTP_CONTENT_PHASE].handlers, cf->pool, 4, sizeof(ngx_http_handler_pt)) != NGX_OK) @@ -459,8 +466,7 @@ ngx_http_init_phase_handlers(ngx_conf_t n = 1 /* find config phase */ + use_rewrite /* post rewrite phase */ - + use_access /* post access phase */ - + cmcf->try_files; + + use_access; /* post access phase */ for (i = 0; i < NGX_HTTP_LOG_PHASE; i++) { n += cmcf->phases[i].handlers.nelts; @@ -529,15 +535,6 @@ ngx_http_init_phase_handlers(ngx_conf_t continue; - case NGX_HTTP_TRY_FILES_PHASE: - if (cmcf->try_files) { - ph->checker = ngx_http_core_try_files_phase; - n++; - ph++; - } - - continue; - case NGX_HTTP_CONTENT_PHASE: checker = ngx_http_core_content_phase; break; diff -r f583559aadc7 -r cce6936ed2f4 src/http/ngx_http_core_module.c --- a/src/http/ngx_http_core_module.c Wed Jul 19 20:38:17 2017 +0300 +++ b/src/http/ngx_http_core_module.c Thu Jul 20 15:51:11 2017 +0300 @@ -61,8 +61,6 @@ static char *ngx_http_core_directio(ngx_ void *conf); static char *ngx_http_core_error_page(ngx_conf_t *cf, ngx_command_t *cmd, void *conf); -static char *ngx_http_core_try_files(ngx_conf_t *cf, ngx_command_t *cmd, - void *conf); static char *ngx_http_core_open_file_cache(ngx_conf_t *cf, ngx_command_t *cmd, void *conf); static char *ngx_http_core_error_log(ngx_conf_t *cf, ngx_command_t *cmd, @@ -649,13 +647,6 @@ static ngx_command_t ngx_http_core_comm 0, NULL }, - { ngx_string("try_files"), - NGX_HTTP_SRV_CONF|NGX_HTTP_LOC_CONF|NGX_CONF_2MORE, - ngx_http_core_try_files, - NGX_HTTP_LOC_CONF_OFFSET, - 0, - NULL }, - { ngx_string("post_action"), NGX_HTTP_MAIN_CONF|NGX_HTTP_SRV_CONF|NGX_HTTP_LOC_CONF|NGX_HTTP_LIF_CONF |NGX_CONF_TAKE1, @@ -1159,223 +1150,6 @@ ngx_http_core_post_access_phase(ngx_http ngx_int_t -ngx_http_core_try_files_phase(ngx_http_request_t *r, - ngx_http_phase_handler_t *ph) -{ - size_t len, root, alias, reserve, allocated; - u_char *p, *name; - ngx_str_t path, args; - ngx_uint_t test_dir; - ngx_http_try_file_t *tf; - ngx_open_file_info_t of; - ngx_http_script_code_pt code; - ngx_http_script_engine_t e; - ngx_http_core_loc_conf_t *clcf; - ngx_http_script_len_code_pt lcode; - - ngx_log_debug1(NGX_LOG_DEBUG_HTTP, r->connection->log, 0, - "try files phase: %ui", r->phase_handler); - - clcf = ngx_http_get_module_loc_conf(r, ngx_http_core_module); - - if (clcf->try_files == NULL) { - r->phase_handler++; - return NGX_AGAIN; - } - - allocated = 0; - root = 0; - name = NULL; - /* suppress MSVC warning */ - path.data = NULL; - - tf = clcf->try_files; - - alias = clcf->alias; - - for ( ;; ) { - - if (tf->lengths) { - ngx_memzero(&e, sizeof(ngx_http_script_engine_t)); - - e.ip = tf->lengths->elts; - e.request = r; - - /* 1 is for terminating '\0' as in static names */ - len = 1; - - while (*(uintptr_t *) e.ip) { - lcode = *(ngx_http_script_len_code_pt *) e.ip; - len += lcode(&e); - } - - } else { - len = tf->name.len; - } - - if (!alias) { - reserve = len > r->uri.len ? len - r->uri.len : 0; - - } else if (alias == NGX_MAX_SIZE_T_VALUE) { - reserve = len; - - } else { - reserve = len > r->uri.len - alias ? len - (r->uri.len - alias) : 0; - } - - if (reserve > allocated || !allocated) { - - /* 16 bytes are preallocation */ - allocated = reserve + 16; - - if (ngx_http_map_uri_to_path(r, &path, &root, allocated) == NULL) { - ngx_http_finalize_request(r, NGX_HTTP_INTERNAL_SERVER_ERROR); - return NGX_OK; - } - - name = path.data + root; - } - - if (tf->values == NULL) { - - /* tf->name.len includes the terminating '\0' */ - - ngx_memcpy(name, tf->name.data, tf->name.len); - - path.len = (name + tf->name.len - 1) - path.data; - - } else { - e.ip = tf->values->elts; - e.pos = name; - e.flushed = 1; - - while (*(uintptr_t *) e.ip) { - code = *(ngx_http_script_code_pt *) e.ip; - code((ngx_http_script_engine_t *) &e); - } - - path.len = e.pos - path.data; - - *e.pos = '\0'; - - if (alias && alias != NGX_MAX_SIZE_T_VALUE - && ngx_strncmp(name, r->uri.data, alias) == 0) - { - ngx_memmove(name, name + alias, len - alias); - path.len -= alias; - } - } - - test_dir = tf->test_dir; - - tf++; - - ngx_log_debug3(NGX_LOG_DEBUG_HTTP, r->connection->log, 0, - "trying to use %s: \"%s\" \"%s\"", - test_dir ? "dir" : "file", name, path.data); - - if (tf->lengths == NULL && tf->name.len == 0) { - - if (tf->code) { - ngx_http_finalize_request(r, tf->code); - return NGX_OK; - } - - path.len -= root; - path.data += root; - - if (path.data[0] == '@') { - (void) ngx_http_named_location(r, &path); - - } else { - ngx_http_split_args(r, &path, &args); - - (void) ngx_http_internal_redirect(r, &path, &args); - } - - ngx_http_finalize_request(r, NGX_DONE); - return NGX_OK; - } - - ngx_memzero(&of, sizeof(ngx_open_file_info_t)); - - of.read_ahead = clcf->read_ahead; - of.directio = clcf->directio; - of.valid = clcf->open_file_cache_valid; - of.min_uses = clcf->open_file_cache_min_uses; - of.test_only = 1; - of.errors = clcf->open_file_cache_errors; - of.events = clcf->open_file_cache_events; - - if (ngx_http_set_disable_symlinks(r, clcf, &path, &of) != NGX_OK) { - ngx_http_finalize_request(r, NGX_HTTP_INTERNAL_SERVER_ERROR); - return NGX_OK; - } - - if (ngx_open_cached_file(clcf->open_file_cache, &path, &of, r->pool) - != NGX_OK) - { - if (of.err == 0) { - ngx_http_finalize_request(r, NGX_HTTP_INTERNAL_SERVER_ERROR); - return NGX_OK; - } - - if (of.err != NGX_ENOENT - && of.err != NGX_ENOTDIR - && of.err != NGX_ENAMETOOLONG) - { - ngx_log_error(NGX_LOG_CRIT, r->connection->log, of.err, - "%s \"%s\" failed", of.failed, path.data); - } - - continue; - } - - if (of.is_dir != test_dir) { - continue; - } - - path.len -= root; - path.data += root; - - if (!alias) { - r->uri = path; - - } else if (alias == NGX_MAX_SIZE_T_VALUE) { - if (!test_dir) { - r->uri = path; - r->add_uri_to_alias = 1; - } - - } else { - name = r->uri.data; - - r->uri.len = alias + path.len; - r->uri.data = ngx_pnalloc(r->pool, r->uri.len); - if (r->uri.data == NULL) { - r->uri.len = 0; - ngx_http_finalize_request(r, NGX_HTTP_INTERNAL_SERVER_ERROR); - return NGX_OK; - } - - p = ngx_copy(r->uri.data, name, alias); - ngx_memcpy(p, path.data, path.len); - } - - ngx_http_set_exten(r); - - ngx_log_debug1(NGX_LOG_DEBUG_HTTP, r->connection->log, 0, - "try file uri: \"%V\"", &r->uri); - - r->phase_handler++; - return NGX_AGAIN; - } - - /* not reached */ -} - - -ngx_int_t ngx_http_core_content_phase(ngx_http_request_t *r, ngx_http_phase_handler_t *ph) { @@ -3561,7 +3335,6 @@ ngx_http_core_create_loc_conf(ngx_conf_t * clcf->default_type = { 0, NULL }; * clcf->error_log = NULL; * clcf->error_pages = NULL; - * clcf->try_files = NULL; * clcf->client_body_path = NULL; * clcf->regex = NULL; * clcf->exact_match = 0; @@ -4885,89 +4658,6 @@ ngx_http_core_error_page(ngx_conf_t *cf, static char * -ngx_http_core_try_files(ngx_conf_t *cf, ngx_command_t *cmd, void *conf) -{ - ngx_http_core_loc_conf_t *clcf = conf; - - ngx_str_t *value; - ngx_int_t code; - ngx_uint_t i, n; - ngx_http_try_file_t *tf; - ngx_http_script_compile_t sc; - ngx_http_core_main_conf_t *cmcf; - - if (clcf->try_files) { - return "is duplicate"; - } - - cmcf = ngx_http_conf_get_module_main_conf(cf, ngx_http_core_module); - - cmcf->try_files = 1; - - tf = ngx_pcalloc(cf->pool, cf->args->nelts * sizeof(ngx_http_try_file_t)); - if (tf == NULL) { - return NGX_CONF_ERROR; - } - - clcf->try_files = tf; - - value = cf->args->elts; - - for (i = 0; i < cf->args->nelts - 1; i++) { - - tf[i].name = value[i + 1]; - - if (tf[i].name.len > 0 - && tf[i].name.data[tf[i].name.len - 1] == '/' - && i + 2 < cf->args->nelts) - { - tf[i].test_dir = 1; - tf[i].name.len--; - tf[i].name.data[tf[i].name.len] = '\0'; - } - - n = ngx_http_script_variables_count(&tf[i].name); - - if (n) { - ngx_memzero(&sc, sizeof(ngx_http_script_compile_t)); - - sc.cf = cf; - sc.source = &tf[i].name; - sc.lengths = &tf[i].lengths; - sc.values = &tf[i].values; - sc.variables = n; - sc.complete_lengths = 1; - sc.complete_values = 1; - - if (ngx_http_script_compile(&sc) != NGX_OK) { - return NGX_CONF_ERROR; - } - - } else { - /* add trailing '\0' to length */ - tf[i].name.len++; - } - } - - if (tf[i - 1].name.data[0] == '=') { - - code = ngx_atoi(tf[i - 1].name.data + 1, tf[i - 1].name.len - 2); - - if (code == NGX_ERROR || code > 999) { - ngx_conf_log_error(NGX_LOG_EMERG, cf, 0, - "invalid code \"%*s\"", - tf[i - 1].name.len - 1, tf[i - 1].name.data); - return NGX_CONF_ERROR; - } - - tf[i].code = code; - } - - return NGX_CONF_OK; -} - - -static char * ngx_http_core_open_file_cache(ngx_conf_t *cf, ngx_command_t *cmd, void *conf) { ngx_http_core_loc_conf_t *clcf = conf; diff -r f583559aadc7 -r cce6936ed2f4 src/http/ngx_http_core_module.h --- a/src/http/ngx_http_core_module.h Wed Jul 19 20:38:17 2017 +0300 +++ b/src/http/ngx_http_core_module.h Thu Jul 20 15:51:11 2017 +0300 @@ -119,7 +119,8 @@ typedef enum { NGX_HTTP_ACCESS_PHASE, NGX_HTTP_POST_ACCESS_PHASE, - NGX_HTTP_TRY_FILES_PHASE, + NGX_HTTP_PRECONTENT_PHASE, + NGX_HTTP_CONTENT_PHASE, NGX_HTTP_LOG_PHASE @@ -172,8 +173,6 @@ typedef struct { ngx_array_t *ports; - ngx_uint_t try_files; /* unsigned try_files:1 */ - ngx_http_phase_t phases[NGX_HTTP_LOG_PHASE + 1]; } ngx_http_core_main_conf_t; @@ -296,16 +295,6 @@ typedef struct { } ngx_http_err_page_t; -typedef struct { - ngx_array_t *lengths; - ngx_array_t *values; - ngx_str_t name; - - unsigned code:10; - unsigned test_dir:1; -} ngx_http_try_file_t; - - struct ngx_http_core_loc_conf_s { ngx_str_t name; /* location name */ @@ -425,7 +414,6 @@ struct ngx_http_core_loc_conf_s { #endif ngx_array_t *error_pages; /* error_page */ - ngx_http_try_file_t *try_files; /* try_files */ ngx_path_t *client_body_temp_path; /* client_body_temp_path */ @@ -486,8 +474,6 @@ ngx_int_t ngx_http_core_access_phase(ngx ngx_http_phase_handler_t *ph); ngx_int_t ngx_http_core_post_access_phase(ngx_http_request_t *r, ngx_http_phase_handler_t *ph); -ngx_int_t ngx_http_core_try_files_phase(ngx_http_request_t *r, - ngx_http_phase_handler_t *ph); ngx_int_t ngx_http_core_content_phase(ngx_http_request_t *r, ngx_http_phase_handler_t *ph); From arut at nginx.com Thu Jul 20 17:03:39 2017 From: arut at nginx.com (Roman Arutyunyan) Date: Thu, 20 Jul 2017 17:03:39 +0000 Subject: [nginx] Mirror module. Message-ID: details: http://hg.nginx.org/nginx/rev/0bb747b2d7cb branches: changeset: 7072:0bb747b2d7cb user: Roman Arutyunyan date: Thu Jul 20 08:50:49 2017 +0300 description: Mirror module. diffstat: auto/modules | 11 + auto/options | 3 + src/http/modules/ngx_http_mirror_module.c | 223 ++++++++++++++++++++++++++++++ 3 files changed, 237 insertions(+), 0 deletions(-) diffs (275 lines): diff -r cce6936ed2f4 -r 0bb747b2d7cb auto/modules --- a/auto/modules Thu Jul 20 15:51:11 2017 +0300 +++ b/auto/modules Thu Jul 20 08:50:49 2017 +0300 @@ -506,6 +506,17 @@ if [ $HTTP = YES ]; then . auto/module fi + if [ $HTTP_MIRROR = YES ]; then + ngx_module_name=ngx_http_mirror_module + ngx_module_incs= + ngx_module_deps= + ngx_module_srcs=src/http/modules/ngx_http_mirror_module.c + ngx_module_libs= + ngx_module_link=$HTTP_MIRROR + + . auto/module + fi + if :; then ngx_module_name=ngx_http_try_files_module ngx_module_incs= diff -r cce6936ed2f4 -r 0bb747b2d7cb auto/options --- a/auto/options Thu Jul 20 15:51:11 2017 +0300 +++ b/auto/options Thu Jul 20 08:50:49 2017 +0300 @@ -70,6 +70,7 @@ HTTP_DAV=NO HTTP_ACCESS=YES HTTP_AUTH_BASIC=YES HTTP_AUTH_REQUEST=NO +HTTP_MIRROR=YES HTTP_USERID=YES HTTP_SLICE=NO HTTP_AUTOINDEX=YES @@ -249,6 +250,7 @@ do --without-http_userid_module) HTTP_USERID=NO ;; --without-http_access_module) HTTP_ACCESS=NO ;; --without-http_auth_basic_module) HTTP_AUTH_BASIC=NO ;; + --without-http_mirror_module) HTTP_MIRROR=NO ;; --without-http_autoindex_module) HTTP_AUTOINDEX=NO ;; --without-http_status_module) HTTP_STATUS=NO ;; --without-http_geo_module) HTTP_GEO=NO ;; @@ -458,6 +460,7 @@ cat << END --without-http_userid_module disable ngx_http_userid_module --without-http_access_module disable ngx_http_access_module --without-http_auth_basic_module disable ngx_http_auth_basic_module + --without-http_mirror_module disable ngx_http_mirror_module --without-http_autoindex_module disable ngx_http_autoindex_module --without-http_geo_module disable ngx_http_geo_module --without-http_map_module disable ngx_http_map_module diff -r cce6936ed2f4 -r 0bb747b2d7cb src/http/modules/ngx_http_mirror_module.c --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/src/http/modules/ngx_http_mirror_module.c Thu Jul 20 08:50:49 2017 +0300 @@ -0,0 +1,223 @@ + +/* + * Copyright (C) Roman Arutyunyan + * Copyright (C) Nginx, Inc. + */ + + +#include +#include +#include + + +typedef struct { + ngx_array_t *mirror; + ngx_flag_t request_body; +} ngx_http_mirror_loc_conf_t; + + +typedef struct { + ngx_int_t status; +} ngx_http_mirror_ctx_t; + + +static ngx_int_t ngx_http_mirror_handler(ngx_http_request_t *r); +static void ngx_http_mirror_body_handler(ngx_http_request_t *r); +static ngx_int_t ngx_http_mirror_handler_internal(ngx_http_request_t *r); +static void *ngx_http_mirror_create_loc_conf(ngx_conf_t *cf); +static char *ngx_http_mirror_merge_loc_conf(ngx_conf_t *cf, void *parent, + void *child); +static ngx_int_t ngx_http_mirror_init(ngx_conf_t *cf); + + +static ngx_command_t ngx_http_mirror_commands[] = { + + { ngx_string("mirror"), + NGX_HTTP_MAIN_CONF|NGX_HTTP_SRV_CONF|NGX_HTTP_LOC_CONF|NGX_CONF_TAKE1, + ngx_conf_set_str_array_slot, + NGX_HTTP_LOC_CONF_OFFSET, + offsetof(ngx_http_mirror_loc_conf_t, mirror), + NULL }, + + { ngx_string("mirror_request_body"), + NGX_HTTP_MAIN_CONF|NGX_HTTP_SRV_CONF|NGX_HTTP_LOC_CONF|NGX_CONF_FLAG, + ngx_conf_set_flag_slot, + NGX_HTTP_LOC_CONF_OFFSET, + offsetof(ngx_http_mirror_loc_conf_t, request_body), + NULL }, + + ngx_null_command +}; + + +static ngx_http_module_t ngx_http_mirror_module_ctx = { + NULL, /* preconfiguration */ + ngx_http_mirror_init, /* postconfiguration */ + + NULL, /* create main configuration */ + NULL, /* init main configuration */ + + NULL, /* create server configuration */ + NULL, /* merge server configuration */ + + ngx_http_mirror_create_loc_conf, /* create location configuration */ + ngx_http_mirror_merge_loc_conf /* merge location configuration */ +}; + + +ngx_module_t ngx_http_mirror_module = { + NGX_MODULE_V1, + &ngx_http_mirror_module_ctx, /* module context */ + ngx_http_mirror_commands, /* module directives */ + NGX_HTTP_MODULE, /* module type */ + NULL, /* init master */ + NULL, /* init module */ + NULL, /* init process */ + NULL, /* init thread */ + NULL, /* exit thread */ + NULL, /* exit process */ + NULL, /* exit master */ + NGX_MODULE_V1_PADDING +}; + + +static ngx_int_t +ngx_http_mirror_handler(ngx_http_request_t *r) +{ + ngx_int_t rc; + ngx_http_mirror_ctx_t *ctx; + ngx_http_mirror_loc_conf_t *mlcf; + + if (r != r->main) { + return NGX_DECLINED; + } + + mlcf = ngx_http_get_module_loc_conf(r, ngx_http_mirror_module); + + if (mlcf->mirror == NULL) { + return NGX_DECLINED; + } + + ngx_log_debug0(NGX_LOG_DEBUG_HTTP, r->connection->log, 0, "mirror handler"); + + if (mlcf->request_body) { + ctx = ngx_http_get_module_ctx(r, ngx_http_mirror_module); + + if (ctx) { + return ctx->status; + } + + ctx = ngx_pcalloc(r->pool, sizeof(ngx_http_mirror_ctx_t)); + if (ctx == NULL) { + return NGX_ERROR; + } + + ctx->status = NGX_DONE; + + ngx_http_set_ctx(r, ctx, ngx_http_mirror_module); + + rc = ngx_http_read_client_request_body(r, ngx_http_mirror_body_handler); + if (rc >= NGX_HTTP_SPECIAL_RESPONSE) { + return rc; + } + + ngx_http_finalize_request(r, NGX_DONE); + return NGX_DONE; + } + + return ngx_http_mirror_handler_internal(r); +} + + +static void +ngx_http_mirror_body_handler(ngx_http_request_t *r) +{ + ngx_http_mirror_ctx_t *ctx; + + ctx = ngx_http_get_module_ctx(r, ngx_http_mirror_module); + + ctx->status = ngx_http_mirror_handler_internal(r); + + r->preserve_body = 1; + + r->write_event_handler = ngx_http_core_run_phases; + ngx_http_core_run_phases(r); +} + + +static ngx_int_t +ngx_http_mirror_handler_internal(ngx_http_request_t *r) +{ + ngx_str_t *name; + ngx_uint_t i; + ngx_http_request_t *sr; + ngx_http_mirror_loc_conf_t *mlcf; + + mlcf = ngx_http_get_module_loc_conf(r, ngx_http_mirror_module); + + name = mlcf->mirror->elts; + + for (i = 0; i < mlcf->mirror->nelts; i++) { + if (ngx_http_subrequest(r, &name[i], &r->args, &sr, NULL, + NGX_HTTP_SUBREQUEST_BACKGROUND) + != NGX_OK) + { + return NGX_HTTP_INTERNAL_SERVER_ERROR; + } + + sr->header_only = 1; + sr->method = r->method; + sr->method_name = r->method_name; + } + + return NGX_DECLINED; +} + + +static void * +ngx_http_mirror_create_loc_conf(ngx_conf_t *cf) +{ + ngx_http_mirror_loc_conf_t *mlcf; + + mlcf = ngx_pcalloc(cf->pool, sizeof(ngx_http_mirror_loc_conf_t)); + if (mlcf == NULL) { + return NULL; + } + + mlcf->mirror = NGX_CONF_UNSET_PTR; + mlcf->request_body = NGX_CONF_UNSET; + + return mlcf; +} + + +static char * +ngx_http_mirror_merge_loc_conf(ngx_conf_t *cf, void *parent, void *child) +{ + ngx_http_mirror_loc_conf_t *prev = parent; + ngx_http_mirror_loc_conf_t *conf = child; + + ngx_conf_merge_ptr_value(conf->mirror, prev->mirror, NULL); + ngx_conf_merge_value(conf->request_body, prev->request_body, 1); + + return NGX_CONF_OK; +} + + +static ngx_int_t +ngx_http_mirror_init(ngx_conf_t *cf) +{ + ngx_http_handler_pt *h; + ngx_http_core_main_conf_t *cmcf; + + cmcf = ngx_http_conf_get_module_main_conf(cf, ngx_http_core_module); + + h = ngx_array_push(&cmcf->phases[NGX_HTTP_PRECONTENT_PHASE].handlers); + if (h == NULL) { + return NGX_ERROR; + } + + *h = ngx_http_mirror_handler; + + return NGX_OK; +} From sepherosa at gmail.com Fri Jul 21 02:55:59 2017 From: sepherosa at gmail.com (Sepherosa Ziehau) Date: Fri, 21 Jul 2017 10:55:59 +0800 Subject: [nginx] Core: disabled SO_REUSEPORT when testing config (ticket #1300). In-Reply-To: References: Message-ID: Heh, interesting discover :) On Wed, Jul 12, 2017 at 1:18 AM, Maxim Dounin wrote: > details: http://hg.nginx.org/nginx/rev/ecb5cd305b06 > branches: > changeset: 7064:ecb5cd305b06 > user: Maxim Dounin > date: Tue Jul 11 19:59:56 2017 +0300 > description: > Core: disabled SO_REUSEPORT when testing config (ticket #1300). > > When closing a socket with SO_REUSEPORT, Linux drops all connections waiting > in this socket's listen queue. Previously, it was believed to only result > in connection resets when reconfiguring nginx to use smaller number of worker > processes. It also results in connection resets during configuration > testing though. > > Workaround is to avoid using SO_REUSEPORT when testing configuration. It > should prevent listening sockets from being created if a conflicting socket > already exists, while still preserving detection of other possible errors. > It should also cover UDP sockets. > > The only downside of this approach seems to be that a configuration testing > won't be able to properly report the case when nginx was compiled with > SO_REUSEPORT, but the kernel is not able to set it. Such errors will be > reported on a real start instead. > > diffstat: > > src/core/ngx_connection.c | 2 +- > 1 files changed, 1 insertions(+), 1 deletions(-) > > diffs (12 lines): > > diff --git a/src/core/ngx_connection.c b/src/core/ngx_connection.c > --- a/src/core/ngx_connection.c > +++ b/src/core/ngx_connection.c > @@ -473,7 +473,7 @@ ngx_open_listening_sockets(ngx_cycle_t * > > #if (NGX_HAVE_REUSEPORT) > > - if (ls[i].reuseport) { > + if (ls[i].reuseport && !ngx_test_config) { > int reuseport; > > reuseport = 1; > _______________________________________________ > nginx-devel mailing list > nginx-devel at nginx.org > http://mailman.nginx.org/mailman/listinfo/nginx-devel -- Tomorrow Will Never Die From arut at nginx.com Fri Jul 21 19:12:52 2017 From: arut at nginx.com (Roman Arutyunyan) Date: Fri, 21 Jul 2017 19:12:52 +0000 Subject: [nginx] Mirror: "off" paramater of the "mirror" directive. Message-ID: details: http://hg.nginx.org/nginx/rev/230d16d35ebc branches: changeset: 7073:230d16d35ebc user: Roman Arutyunyan date: Fri Jul 21 19:47:56 2017 +0300 description: Mirror: "off" paramater of the "mirror" directive. diffstat: src/http/modules/ngx_http_mirror_module.c | 45 +++++++++++++++++++++++++++++- 1 files changed, 43 insertions(+), 2 deletions(-) diffs (70 lines): diff -r 0bb747b2d7cb -r 230d16d35ebc src/http/modules/ngx_http_mirror_module.c --- a/src/http/modules/ngx_http_mirror_module.c Thu Jul 20 08:50:49 2017 +0300 +++ b/src/http/modules/ngx_http_mirror_module.c Fri Jul 21 19:47:56 2017 +0300 @@ -27,6 +27,7 @@ static ngx_int_t ngx_http_mirror_handler static void *ngx_http_mirror_create_loc_conf(ngx_conf_t *cf); static char *ngx_http_mirror_merge_loc_conf(ngx_conf_t *cf, void *parent, void *child); +static char *ngx_http_mirror(ngx_conf_t *cf, ngx_command_t *cmd, void *conf); static ngx_int_t ngx_http_mirror_init(ngx_conf_t *cf); @@ -34,9 +35,9 @@ static ngx_command_t ngx_http_mirror_co { ngx_string("mirror"), NGX_HTTP_MAIN_CONF|NGX_HTTP_SRV_CONF|NGX_HTTP_LOC_CONF|NGX_CONF_TAKE1, - ngx_conf_set_str_array_slot, + ngx_http_mirror, NGX_HTTP_LOC_CONF_OFFSET, - offsetof(ngx_http_mirror_loc_conf_t, mirror), + 0, NULL }, { ngx_string("mirror_request_body"), @@ -204,6 +205,46 @@ ngx_http_mirror_merge_loc_conf(ngx_conf_ } +static char * +ngx_http_mirror(ngx_conf_t *cf, ngx_command_t *cmd, void *conf) +{ + ngx_http_mirror_loc_conf_t *mlcf = conf; + + ngx_str_t *value, *s; + + value = cf->args->elts; + + if (ngx_strcmp(value[1].data, "off") == 0) { + if (mlcf->mirror != NGX_CONF_UNSET_PTR) { + return "is duplicate"; + } + + mlcf->mirror = NULL; + return NGX_CONF_OK; + } + + if (mlcf->mirror == NULL) { + return "is duplicate"; + } + + if (mlcf->mirror == NGX_CONF_UNSET_PTR) { + mlcf->mirror = ngx_array_create(cf->pool, 4, sizeof(ngx_str_t)); + if (mlcf->mirror == NULL) { + return NGX_CONF_ERROR; + } + } + + s = ngx_array_push(mlcf->mirror); + if (s == NULL) { + return NGX_CONF_ERROR; + } + + *s = value[1]; + + return NGX_CONF_OK; +} + + static ngx_int_t ngx_http_mirror_init(ngx_conf_t *cf) { From eran.kornblau at kaltura.com Mon Jul 24 10:08:20 2017 From: eran.kornblau at kaltura.com (Eran Kornblau) Date: Mon, 24 Jul 2017 10:08:20 +0000 Subject: [nginx] Fixed background requests with asynchronous operations. In-Reply-To: References: Message-ID: Hi Roman, I got a GitHub issue opened few days ago, that my module doesn't work following this commit - https://github.com/kaltura/nginx-vod-module/issues/645#issuecomment-317027706 The situation is as follows - 1. My module's content phase handler runs and performs an async read request - a. It calls ngx_file_aio_read which returns NGX_AGAIN b. Increments r->blocked c. Sets r->aio to 1 (code here - https://github.com/kaltura/nginx-vod-module/blob/master/ngx_file_reader.c#L392) 2. The NGX_AGAIN status propagates up to ngx_http_core_content_phase which calls ngx_http_finalize_request with this status. 3. r->buffered, c->buffered, and r->postponed are all false, so this if: https://github.com/nginx/nginx/blob/master/src/http/ngx_http_request.c#L2456 is skipped (it used to enter before the patch since r->blocked is 1) In addition, r == c->data, so at the end, ngx_http_finalize_request calls ngx_http_finalize_connection 4. Since r->main->count == 1 and r->keepalive == 1, this function calls ngx_http_set_keepalive 5. ngx_http_set_keepalive calls ngx_http_free_request which destroys the pool even though it has aio pending. Please let me know if you think I'm doing something wrong here (I can, for example, increment r->main->count, but this is not done in any of the other places that do blocked++) Thank you! Eran -----Original Message----- From: nginx-devel [mailto:nginx-devel-bounces at nginx.org] On Behalf Of Roman Arutyunyan Sent: Monday, May 29, 2017 11:40 PM To: nginx-devel at nginx.org Subject: [nginx] Fixed background requests with asynchronous operations. details: http://hg.nginx.org/nginx/rev/5e05118678af branches: changeset: 7011:5e05118678af user: Roman Arutyunyan date: Mon May 29 23:33:38 2017 +0300 description: Fixed background requests with asynchronous operations. If the main request was finalized while a background request performed an asynchronous operation, the main request ended up in ngx_http_writer() and was not finalized until a network event or a timeout. For example, cache background update with aio enabled made nginx unable to process further client requests or close the connection, keeping it open until client closes it. Now regular finalization of the main request is not suspended because of an asynchronous operation in another request. If a background request was terminated while an asynchronous operation was in progress, background request's write event handler was changed to ngx_http_request_finalizer() and never called again. Now, whenever a request is terminated while an asynchronous operation is in progress, connection error flag is set to make further finalizations of any request with this connection lead to termination. These issues appeared in 1aeaae6e9446 (not yet released). diffstat: src/http/ngx_http_request.c | 8 +++----- 1 files changed, 3 insertions(+), 5 deletions(-) diffs (32 lines): diff -r c1524829af3d -r 5e05118678af src/http/ngx_http_request.c --- a/src/http/ngx_http_request.c Mon May 29 16:48:30 2017 +0300 +++ b/src/http/ngx_http_request.c Mon May 29 23:33:38 2017 +0300 @@ -2331,10 +2331,6 @@ ngx_http_finalize_request(ngx_http_reque return; } - if (r->main->blocked) { - r->write_event_handler = ngx_http_request_finalizer; - } - ngx_http_terminate_request(r, rc); return; } @@ -2449,7 +2445,7 @@ ngx_http_finalize_request(ngx_http_reque return; } - if (r->buffered || c->buffered || r->postponed || r->blocked) { + if (r->buffered || c->buffered || r->postponed) { if (ngx_http_set_write_handler(r) != NGX_OK) { ngx_http_terminate_request(r, 0); @@ -2530,6 +2526,8 @@ ngx_http_terminate_request(ngx_http_requ if (mr->write_event_handler) { if (mr->blocked) { + r->connection->error = 1; + r->write_event_handler = ngx_http_request_finalizer; return; } _______________________________________________ nginx-devel mailing list nginx-devel at nginx.org http://mailman.nginx.org/mailman/listinfo/nginx-devel From vbart at nginx.com Mon Jul 24 18:42:06 2017 From: vbart at nginx.com (Valentin V. Bartenev) Date: Mon, 24 Jul 2017 21:42:06 +0300 Subject: [PATCH] HTTP/2: add support for HPACK encoding In-Reply-To: <895cea03ac21fb18d2c2.1498181026@debian> References: <895cea03ac21fb18d2c2.1498181026@debian> Message-ID: <3984662.pLCZ41GGmU@vbart-workstation> On Thursday 22 June 2017 18:23:46 Vlad Krasnov via nginx-devel wrote: > # HG changeset patch > # User Vlad Krasnov > # Date 1498167669 25200 > # Thu Jun 22 14:41:09 2017 -0700 > # Node ID 895cea03ac21fb18d2c2ba32389cd67dc74ddbd0 > # Parent a39bc74873faf9e5bea616561b43f6ecc55229f9 > HTTP/2: add support for HPACK encoding > > Add support for full HPACK encoding as per RFC7541. > This modification improves header compression ratio by 5-10% for the first > response, and by 40-95% for consequential responses on the connection. > The implementation is similar to the one used by Cloudflare. > First of all, there's no way for a patch to be committed with so many style issues. Please, examine how existing nginx sources are formatted and mimic this style. > diff -r a39bc74873fa -r 895cea03ac21 auto/modules > --- a/auto/modules Mon Jun 19 14:25:42 2017 +0300 > +++ b/auto/modules Thu Jun 22 14:41:09 2017 -0700 > @@ -436,6 +436,10 @@ > . auto/module > fi > > + if [ $HTTP_V2_HPACK_ENC = YES ]; then > + have=NGX_HTTP_V2_HPACK_ENC . auto/have > + fi > + > if :; then > ngx_module_name=ngx_http_static_module > ngx_module_incs= > diff -r a39bc74873fa -r 895cea03ac21 auto/options > --- a/auto/options Mon Jun 19 14:25:42 2017 +0300 > +++ b/auto/options Thu Jun 22 14:41:09 2017 -0700 > @@ -59,6 +59,7 @@ > HTTP_GZIP=YES > HTTP_SSL=NO > HTTP_V2=NO > +HTTP_V2_HPACK_ENC=NO > HTTP_SSI=YES > HTTP_POSTPONE=NO > HTTP_REALIP=NO > @@ -221,6 +222,7 @@ > > --with-http_ssl_module) HTTP_SSL=YES ;; > --with-http_v2_module) HTTP_V2=YES ;; > + --with-http_v2_hpack_enc) HTTP_V2_HPACK_ENC=YES ;; What's the reason for conditional compilation? > --with-http_realip_module) HTTP_REALIP=YES ;; > --with-http_addition_module) HTTP_ADDITION=YES ;; > --with-http_xslt_module) HTTP_XSLT=YES ;; > @@ -430,6 +432,7 @@ > > --with-http_ssl_module enable ngx_http_ssl_module > --with-http_v2_module enable ngx_http_v2_module > + --with-http_v2_hpack_enc enable ngx_http_v2_hpack_enc > --with-http_realip_module enable ngx_http_realip_module > --with-http_addition_module enable ngx_http_addition_module > --with-http_xslt_module enable ngx_http_xslt_module > diff -r a39bc74873fa -r 895cea03ac21 src/core/ngx_murmurhash.c > --- a/src/core/ngx_murmurhash.c Mon Jun 19 14:25:42 2017 +0300 > +++ b/src/core/ngx_murmurhash.c Thu Jun 22 14:41:09 2017 -0700 > @@ -50,3 +50,63 @@ > > return h; > } > + > + > +uint64_t > +ngx_murmur_hash2_64(u_char *data, size_t len, uint64_t seed) > +{ > + uint64_t h, k; > + > + h = seed ^ len; > + > + while (len >= 8) { > + k = data[0]; > + k |= data[1] << 8; > + k |= data[2] << 16; > + k |= data[3] << 24; > + k |= (uint64_t)data[4] << 32; > + k |= (uint64_t)data[5] << 40; > + k |= (uint64_t)data[6] << 48; > + k |= (uint64_t)data[7] << 56; > + > + k *= 0xc6a4a7935bd1e995ull; > + k ^= k >> 47; > + k *= 0xc6a4a7935bd1e995ull; > + > + h ^= k; > + h *= 0xc6a4a7935bd1e995ull; > + > + data += 8; > + len -= 8; > + } > + > + switch (len) { > + case 7: > + h ^= (uint64_t)data[6] << 48; > + /* fall through */ > + case 6: > + h ^= (uint64_t)data[5] << 40; > + /* fall through */ > + case 5: > + h ^= (uint64_t)data[4] << 32; > + /* fall through */ > + case 4: > + h ^= data[3] << 24; > + /* fall through */ > + case 3: > + h ^= data[2] << 16; > + /* fall through */ > + case 2: > + h ^= data[1] << 8; > + /* fall through */ > + case 1: > + h ^= data[0]; > + h *= 0xc6a4a7935bd1e995ull; > + } > + > + h ^= h >> 47; > + h *= 0xc6a4a7935bd1e995ull; > + h ^= h >> 47; > + > + return h; > +} > diff -r a39bc74873fa -r 895cea03ac21 src/core/ngx_murmurhash.h > --- a/src/core/ngx_murmurhash.h Mon Jun 19 14:25:42 2017 +0300 > +++ b/src/core/ngx_murmurhash.h Thu Jun 22 14:41:09 2017 -0700 > @@ -15,5 +15,7 @@ > > uint32_t ngx_murmur_hash2(u_char *data, size_t len); > > +uint64_t ngx_murmur_hash2_64(u_char *data, size_t len, uint64_t seed); > + > > #endif /* _NGX_MURMURHASH_H_INCLUDED_ */ > diff -r a39bc74873fa -r 895cea03ac21 src/http/v2/ngx_http_v2.c > --- a/src/http/v2/ngx_http_v2.c Mon Jun 19 14:25:42 2017 +0300 > +++ b/src/http/v2/ngx_http_v2.c Thu Jun 22 14:41:09 2017 -0700 > @@ -245,6 +245,8 @@ > > h2c->frame_size = NGX_HTTP_V2_DEFAULT_FRAME_SIZE; > > + h2c->max_hpack_table_size = NGX_HTTP_V2_DEFAULT_HPACK_TABLE_SIZE; > + > h2scf = ngx_http_get_module_srv_conf(hc->conf_ctx, ngx_http_v2_module); > > h2c->pool = ngx_create_pool(h2scf->pool_size, h2c->connection->log); > @@ -2018,6 +2020,17 @@ > h2c->frame_size = value; > break; > > + case NGX_HTTP_V2_HEADER_TABLE_SIZE_SETTING: > + > + if (value > NGX_HTTP_V2_MAX_HPACK_TABLE_SIZE) { > + h2c->max_hpack_table_size = NGX_HTTP_V2_MAX_HPACK_TABLE_SIZE; > + } else { > + h2c->max_hpack_table_size = value; > + } > + > + h2c->indicate_resize = 1; > + break; > + > default: > break; > } > diff -r a39bc74873fa -r 895cea03ac21 src/http/v2/ngx_http_v2.h > --- a/src/http/v2/ngx_http_v2.h Mon Jun 19 14:25:42 2017 +0300 > +++ b/src/http/v2/ngx_http_v2.h Thu Jun 22 14:41:09 2017 -0700 > @@ -49,6 +49,13 @@ > #define NGX_HTTP_V2_MAX_WINDOW ((1U << 31) - 1) > #define NGX_HTTP_V2_DEFAULT_WINDOW 65535 > > +#define HPACK_ENC_HTABLE_SZ 128 /* better to keep a PoT < 64k */ > +#define HPACK_ENC_HTABLE_ENTRIES ((HPACK_ENC_HTABLE_SZ * 100) / 128) > +#define HPACK_ENC_DYNAMIC_KEY_TBL_SZ 10 /* 10 is sufficient for most */ > +#define HPACK_ENC_MAX_ENTRY 512 /* longest header size to match */ > + > +#define NGX_HTTP_V2_DEFAULT_HPACK_TABLE_SIZE 4096 > +#define NGX_HTTP_V2_MAX_HPACK_TABLE_SIZE 16384 /* < 64k */ > > typedef struct ngx_http_v2_connection_s ngx_http_v2_connection_t; > typedef struct ngx_http_v2_node_s ngx_http_v2_node_t; > @@ -110,6 +117,46 @@ > } ngx_http_v2_hpack_t; > > > +#if (NGX_HTTP_V2_HPACK_ENC) > +typedef struct { > + uint64_t hash_val; > + uint32_t index; > + uint16_t pos; > + uint16_t klen, vlen; > + uint16_t size; > + uint16_t next; > +} ngx_http_v2_hpack_enc_entry_t; > + > + > +typedef struct { > + uint64_t hash_val; > + uint32_t index; > + uint16_t pos; > + uint16_t klen; > +} ngx_http_v2_hpack_name_entry_t; > + > + > +typedef struct { > + size_t size; /* size as defined in RFC 7541 */ > + uint32_t top; /* the last entry */ > + uint32_t pos; > + uint16_t n_elems; /* number of elements */ > + uint16_t base; /* index of the oldest entry */ > + uint16_t last; /* index of the newest entry */ > + > + /* hash table for dynamic entries, instead using a generic hash table, > + which would be too slow to process a significant amount of headers, > + this table is not determenistic, and might ocasionally fail to insert > + a value, at the cost of slightly worse compression, but significantly > + faster performance */ Have you considered rbtree as an option? > + ngx_http_v2_hpack_enc_entry_t htable[HPACK_ENC_HTABLE_SZ]; > + ngx_http_v2_hpack_name_entry_t heads[HPACK_ENC_DYNAMIC_KEY_TBL_SZ]; > + u_char storage[NGX_HTTP_V2_MAX_HPACK_TABLE_SIZE + > + HPACK_ENC_MAX_ENTRY]; > +} ngx_http_v2_hpack_enc_t; > +#endif > + > + Well, it means that even idle connection will consume 18+ KB more memory than before. That doesn't look like a generic solution suitable for most of our users. It should be at least configurable. wbr, Valentin V. Bartenev From vlad at cloudflare.com Mon Jul 24 19:33:55 2017 From: vlad at cloudflare.com (Vlad Krasnov) Date: Mon, 24 Jul 2017 12:33:55 -0700 Subject: [PATCH] HTTP/2: add support for HPACK encoding In-Reply-To: <3984662.pLCZ41GGmU@vbart-workstation> References: <895cea03ac21fb18d2c2.1498181026@debian> <3984662.pLCZ41GGmU@vbart-workstation> Message-ID: <1D346FE5-9813-4C10-8530-BAC7760D8F1B@cloudflare.com> > On Jul 24, 2017, at 11:42 AM, Valentin V. Bartenev wrote: > > On Thursday 22 June 2017 18:23:46 Vlad Krasnov via nginx-devel wrote: >> # HG changeset patch >> # User Vlad Krasnov > >> # Date 1498167669 25200 >> # Thu Jun 22 14:41:09 2017 -0700 >> # Node ID 895cea03ac21fb18d2c2ba32389cd67dc74ddbd0 >> # Parent a39bc74873faf9e5bea616561b43f6ecc55229f9 >> HTTP/2: add support for HPACK encoding >> >> Add support for full HPACK encoding as per RFC7541. >> This modification improves header compression ratio by 5-10% for the first >> response, and by 40-95% for consequential responses on the connection. >> The implementation is similar to the one used by Cloudflare. >> > > First of all, there's no way for a patch to be committed with so > many style issues. > > Please, examine how existing nginx sources are formatted and mimic > this style. OK. > > > >> diff -r a39bc74873fa -r 895cea03ac21 auto/modules >> --- a/auto/modules Mon Jun 19 14:25:42 2017 +0300 >> +++ b/auto/modules Thu Jun 22 14:41:09 2017 -0700 >> @@ -436,6 +436,10 @@ >> . auto/module >> fi >> >> + if [ $HTTP_V2_HPACK_ENC = YES ]; then >> + have=NGX_HTTP_V2_HPACK_ENC . auto/have >> + fi >> + >> if :; then >> ngx_module_name=ngx_http_static_module >> ngx_module_incs= >> diff -r a39bc74873fa -r 895cea03ac21 auto/options >> --- a/auto/options Mon Jun 19 14:25:42 2017 +0300 >> +++ b/auto/options Thu Jun 22 14:41:09 2017 -0700 >> @@ -59,6 +59,7 @@ >> HTTP_GZIP=YES >> HTTP_SSL=NO >> HTTP_V2=NO >> +HTTP_V2_HPACK_ENC=NO >> HTTP_SSI=YES >> HTTP_POSTPONE=NO >> HTTP_REALIP=NO >> @@ -221,6 +222,7 @@ >> >> --with-http_ssl_module) HTTP_SSL=YES ;; >> --with-http_v2_module) HTTP_V2=YES ;; >> + --with-http_v2_hpack_enc) HTTP_V2_HPACK_ENC=YES ;; > > What's the reason for conditional compilation? Internal reasons, but I decided to keep it in the patch, because maybe not everyone wants that overhead. > > >> --with-http_realip_module) HTTP_REALIP=YES ;; >> --with-http_addition_module) HTTP_ADDITION=YES ;; >> --with-http_xslt_module) HTTP_XSLT=YES ;; >> @@ -430,6 +432,7 @@ >> >> --with-http_ssl_module enable ngx_http_ssl_module >> --with-http_v2_module enable ngx_http_v2_module >> + --with-http_v2_hpack_enc enable ngx_http_v2_hpack_enc >> --with-http_realip_module enable ngx_http_realip_module >> --with-http_addition_module enable ngx_http_addition_module >> --with-http_xslt_module enable ngx_http_xslt_module >> diff -r a39bc74873fa -r 895cea03ac21 src/core/ngx_murmurhash.c >> --- a/src/core/ngx_murmurhash.c Mon Jun 19 14:25:42 2017 +0300 >> +++ b/src/core/ngx_murmurhash.c Thu Jun 22 14:41:09 2017 -0700 >> @@ -50,3 +50,63 @@ >> >> return h; >> } >> + >> + >> +uint64_t >> +ngx_murmur_hash2_64(u_char *data, size_t len, uint64_t seed) >> +{ >> + uint64_t h, k; >> + >> + h = seed ^ len; >> + >> + while (len >= 8) { >> + k = data[0]; >> + k |= data[1] << 8; >> + k |= data[2] << 16; >> + k |= data[3] << 24; >> + k |= (uint64_t)data[4] << 32; >> + k |= (uint64_t)data[5] << 40; >> + k |= (uint64_t)data[6] << 48; >> + k |= (uint64_t)data[7] << 56; >> + >> + k *= 0xc6a4a7935bd1e995ull; >> + k ^= k >> 47; >> + k *= 0xc6a4a7935bd1e995ull; >> + >> + h ^= k; >> + h *= 0xc6a4a7935bd1e995ull; >> + >> + data += 8; >> + len -= 8; >> + } >> + >> + switch (len) { >> + case 7: >> + h ^= (uint64_t)data[6] << 48; >> + /* fall through */ >> + case 6: >> + h ^= (uint64_t)data[5] << 40; >> + /* fall through */ >> + case 5: >> + h ^= (uint64_t)data[4] << 32; >> + /* fall through */ >> + case 4: >> + h ^= data[3] << 24; >> + /* fall through */ >> + case 3: >> + h ^= data[2] << 16; >> + /* fall through */ >> + case 2: >> + h ^= data[1] << 8; >> + /* fall through */ >> + case 1: >> + h ^= data[0]; >> + h *= 0xc6a4a7935bd1e995ull; >> + } >> + >> + h ^= h >> 47; >> + h *= 0xc6a4a7935bd1e995ull; >> + h ^= h >> 47; >> + >> + return h; >> +} >> diff -r a39bc74873fa -r 895cea03ac21 src/core/ngx_murmurhash.h >> --- a/src/core/ngx_murmurhash.h Mon Jun 19 14:25:42 2017 +0300 >> +++ b/src/core/ngx_murmurhash.h Thu Jun 22 14:41:09 2017 -0700 >> @@ -15,5 +15,7 @@ >> >> uint32_t ngx_murmur_hash2(u_char *data, size_t len); >> >> +uint64_t ngx_murmur_hash2_64(u_char *data, size_t len, uint64_t seed); >> + >> >> #endif /* _NGX_MURMURHASH_H_INCLUDED_ */ >> diff -r a39bc74873fa -r 895cea03ac21 src/http/v2/ngx_http_v2.c >> --- a/src/http/v2/ngx_http_v2.c Mon Jun 19 14:25:42 2017 +0300 >> +++ b/src/http/v2/ngx_http_v2.c Thu Jun 22 14:41:09 2017 -0700 >> @@ -245,6 +245,8 @@ >> >> h2c->frame_size = NGX_HTTP_V2_DEFAULT_FRAME_SIZE; >> >> + h2c->max_hpack_table_size = NGX_HTTP_V2_DEFAULT_HPACK_TABLE_SIZE; >> + >> h2scf = ngx_http_get_module_srv_conf(hc->conf_ctx, ngx_http_v2_module); >> >> h2c->pool = ngx_create_pool(h2scf->pool_size, h2c->connection->log); >> @@ -2018,6 +2020,17 @@ >> h2c->frame_size = value; >> break; >> >> + case NGX_HTTP_V2_HEADER_TABLE_SIZE_SETTING: >> + >> + if (value > NGX_HTTP_V2_MAX_HPACK_TABLE_SIZE) { >> + h2c->max_hpack_table_size = NGX_HTTP_V2_MAX_HPACK_TABLE_SIZE; >> + } else { >> + h2c->max_hpack_table_size = value; >> + } >> + >> + h2c->indicate_resize = 1; >> + break; >> + >> default: >> break; >> } >> diff -r a39bc74873fa -r 895cea03ac21 src/http/v2/ngx_http_v2.h >> --- a/src/http/v2/ngx_http_v2.h Mon Jun 19 14:25:42 2017 +0300 >> +++ b/src/http/v2/ngx_http_v2.h Thu Jun 22 14:41:09 2017 -0700 >> @@ -49,6 +49,13 @@ >> #define NGX_HTTP_V2_MAX_WINDOW ((1U << 31) - 1) >> #define NGX_HTTP_V2_DEFAULT_WINDOW 65535 >> >> +#define HPACK_ENC_HTABLE_SZ 128 /* better to keep a PoT < 64k */ >> +#define HPACK_ENC_HTABLE_ENTRIES ((HPACK_ENC_HTABLE_SZ * 100) / 128) >> +#define HPACK_ENC_DYNAMIC_KEY_TBL_SZ 10 /* 10 is sufficient for most */ >> +#define HPACK_ENC_MAX_ENTRY 512 /* longest header size to match */ >> + >> +#define NGX_HTTP_V2_DEFAULT_HPACK_TABLE_SIZE 4096 >> +#define NGX_HTTP_V2_MAX_HPACK_TABLE_SIZE 16384 /* < 64k */ >> >> typedef struct ngx_http_v2_connection_s ngx_http_v2_connection_t; >> typedef struct ngx_http_v2_node_s ngx_http_v2_node_t; >> @@ -110,6 +117,46 @@ >> } ngx_http_v2_hpack_t; >> >> >> +#if (NGX_HTTP_V2_HPACK_ENC) >> +typedef struct { >> + uint64_t hash_val; >> + uint32_t index; >> + uint16_t pos; >> + uint16_t klen, vlen; >> + uint16_t size; >> + uint16_t next; >> +} ngx_http_v2_hpack_enc_entry_t; >> + >> + >> +typedef struct { >> + uint64_t hash_val; >> + uint32_t index; >> + uint16_t pos; >> + uint16_t klen; >> +} ngx_http_v2_hpack_name_entry_t; >> + >> + >> +typedef struct { >> + size_t size; /* size as defined in RFC 7541 */ >> + uint32_t top; /* the last entry */ >> + uint32_t pos; >> + uint16_t n_elems; /* number of elements */ >> + uint16_t base; /* index of the oldest entry */ >> + uint16_t last; /* index of the newest entry */ >> + >> + /* hash table for dynamic entries, instead using a generic hash table, >> + which would be too slow to process a significant amount of headers, >> + this table is not determenistic, and might ocasionally fail to insert >> + a value, at the cost of slightly worse compression, but significantly >> + faster performance */ > > Have you considered rbtree as an option? Yeah, I don?t think it would be faster. > > >> + ngx_http_v2_hpack_enc_entry_t htable[HPACK_ENC_HTABLE_SZ]; >> + ngx_http_v2_hpack_name_entry_t heads[HPACK_ENC_DYNAMIC_KEY_TBL_SZ]; >> + u_char storage[NGX_HTTP_V2_MAX_HPACK_TABLE_SIZE + >> + HPACK_ENC_MAX_ENTRY]; >> +} ngx_http_v2_hpack_enc_t; >> +#endif >> + >> + > > Well, it means that even idle connection will consume 18+ KB more > memory than before. > > That doesn't look like a generic solution suitable for most of our users. > It should be at least configurable. > I can make it configurable fairly easily, but then it will require an extra allocation. Cheers, Vlad > wbr, Valentin V. Bartenev > > _______________________________________________ > 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 vbart at nginx.com Mon Jul 24 23:26:44 2017 From: vbart at nginx.com (Valentin V. Bartenev) Date: Tue, 25 Jul 2017 02:26:44 +0300 Subject: [PATCH] HTTP/2: add support for HPACK encoding In-Reply-To: <1D346FE5-9813-4C10-8530-BAC7760D8F1B@cloudflare.com> References: <895cea03ac21fb18d2c2.1498181026@debian> <3984662.pLCZ41GGmU@vbart-workstation> <1D346FE5-9813-4C10-8530-BAC7760D8F1B@cloudflare.com> Message-ID: <1759142.kXPVlifeFX@vbart-laptop> On Monday 24 July 2017 12:33:55 Vlad Krasnov via nginx-devel wrote: [..] > >> + ngx_http_v2_hpack_enc_entry_t htable[HPACK_ENC_HTABLE_SZ]; > >> + ngx_http_v2_hpack_name_entry_t heads[HPACK_ENC_DYNAMIC_KEY_TBL_SZ]; > >> + u_char storage[NGX_HTTP_V2_MAX_HPACK_TABLE_SIZE + > >> + HPACK_ENC_MAX_ENTRY]; > >> +} ngx_http_v2_hpack_enc_t; > >> +#endif > >> + > >> + > > > > Well, it means that even idle connection will consume 18+ KB more > > memory than before. > > > > That doesn't look like a generic solution suitable for most of our users. > > It should be at least configurable. > > > > I can make it configurable fairly easily, but then it will require an extra allocation. > With your current patch ngx_http_v2_connection_s doesn't fit into memory pool anymore and requires an extra allocation anyway. wbr, Valentin V. Bartenev From pluknet at nginx.com Tue Jul 25 14:34:56 2017 From: pluknet at nginx.com (Sergey Kandaurov) Date: Tue, 25 Jul 2017 14:34:56 +0000 Subject: [nginx] SSL: fixed typo in the error message. Message-ID: details: http://hg.nginx.org/nginx/rev/07a49cce21ca branches: changeset: 7074:07a49cce21ca user: Sergey Kandaurov date: Tue Jul 25 17:21:59 2017 +0300 description: SSL: fixed typo in the error message. diffstat: src/event/ngx_event_openssl.c | 2 +- 1 files changed, 1 insertions(+), 1 deletions(-) diffs (12 lines): diff -r 230d16d35ebc -r 07a49cce21ca src/event/ngx_event_openssl.c --- a/src/event/ngx_event_openssl.c Fri Jul 21 19:47:56 2017 +0300 +++ b/src/event/ngx_event_openssl.c Tue Jul 25 17:21:59 2017 +0300 @@ -3128,7 +3128,7 @@ ngx_ssl_session_ticket_keys(ngx_conf_t * { if (paths) { ngx_log_error(NGX_LOG_WARN, ssl->log, 0, - "\"ssl_session_ticket_keys\" ignored, not supported"); + "\"ssl_session_ticket_key\" ignored, not supported"); } return NGX_OK; From Nate.Karstens at garmin.com Tue Jul 25 19:00:45 2017 From: Nate.Karstens at garmin.com (Karstens, Nate) Date: Tue, 25 Jul 2017 19:00:45 +0000 Subject: [PATCH 1 of 3] PSK: connection support In-Reply-To: <20170630115808.GR55433@mdounin.ru> References: <145451D4E6785E4DA4DFA353A58CB7B2015E16FAA8@OLAWPA-EXMB03.ad.garmin.com> <20170629210836.GO55433@mdounin.ru> <145451D4E6785E4DA4DFA353A58CB7B2015E17251F@OLAWPA-EXMB03.ad.garmin.com> <20170630115808.GR55433@mdounin.ru> Message-ID: <145451D4E6785E4DA4DFA353A58CB7B2015E177CB3@OLAWPA-EXMB03.ad.garmin.com> Maxim, I'm starting to get back to this now and wanted to follow up on your comments in http://mailman.nginx.org/pipermail/nginx-devel/2017-June/010247.html to see if you had a preference on when the PSKs should be read from the file. I believe we have two options: 1) At startup into a hash. Advantages: Faster lookups, PSK file can be read-only by root, can warn on syntax errors Disadvantages: Must reload to add/remove PSKs, more config options (for the hash max size and bucket size) 2) As needed. This is what was done in the last patch, but changed to no longer check for syntax errors at startup. Advantages: Do not need to reload to add/remove users, can control access using groups Disadvantages: Slower lookups (linear, but this can be improved using a RAM disk) Thanks, Nate -----Original Message----- From: nginx-devel [mailto:nginx-devel-bounces at nginx.org] On Behalf Of Maxim Dounin Sent: Friday, June 30, 2017 6:58 AM To: nginx-devel at nginx.org Subject: Re: [PATCH 1 of 3] PSK: connection support Hello! On Thu, Jun 29, 2017 at 10:00:45PM +0000, Karstens, Nate wrote: > Thanks for the comments. I'll try to start on those in a couple of > days. Just to make it clear: there is no need to hurry. Likely I won't be able to review new patches in at least a couple of weeks, so feel free to spend more time polishing the patches. > My company uses Outlook/Exchange for email, so I don't think I'll be > able to use hg email, do you have any other suggestions? Thanks also > for your patience, I've used Git quite a bit but am new to Mercurial. The "hg email" command can work with any SMTP server, including Exchange. Or you can ensure proper threading manually by using a "reply" function. > Utkarsh sounds like he is trying to use PSK for TLS v1.3 session > resumption. Given that each TLS connection could potentially result in > a new PSK I think only reading them at startup could result in too > many refreshes. I think there might be some benefit to the original > approach in regards to storing each PSK in its own file in a > designated directory. Benefits include: TLS v1.3 session resumption uses PSK internally, but it is very different from internal usage point of view. It is handled well enough with existing session cache / session tickets mechanisms. [...] > > +ngx_int_t > > +ngx_ssl_psk_file(ngx_conf_t *cf, ngx_ssl_t *ssl, ngx_str_t *file) > > + > > +{ > > Style: extra empty line. > > > + ngx_int_t rc; > > + > > + if (SSL_CTX_set_ex_data(ssl->ctx, ngx_ssl_psk_index, file) == 0) { > > + ngx_ssl_error(NGX_LOG_ALERT, ssl->log, 0, > > + "SSL_CTX_set_ex_data() failed"); > > + return NGX_ERROR; > > + } > > + > > + rc = ngx_ssl_psk_read(file, NULL, NULL, 0); > > + > > + return rc == 0 ? NGX_OK : NGX_ERROR; } [...] > > @@ -800,6 +810,12 @@ > > > > } > > > > + if (ngx_ssl_psk_file(cf, &conf->ssl, &conf->psk_file) > > + != NGX_OK) > > + { > > + return NGX_CONF_ERROR; > > + } Note: this calls ngx_ssl_psk_file() unconditionally, and ngx_ssl_psk_file() also doesn't check if a file is configured. As a result, a configuration without ssl_psk_file fails. -- Maxim Dounin http://nginx.org/ _______________________________________________ nginx-devel mailing list nginx-devel at nginx.org http://mailman.nginx.org/mailman/listinfo/nginx-devel ________________________________ CONFIDENTIALITY NOTICE: This email and any attachments are for the sole use of the intended recipient(s) and contain information that may be Garmin confidential and/or Garmin legally privileged. If you have received this email in error, please notify the sender by reply email and delete the message. Any disclosure, copying, distribution or use of this communication (including attachments) by someone other than the intended recipient is prohibited. Thank you. From piotrsikora at google.com Wed Jul 26 01:28:16 2017 From: piotrsikora at google.com (Piotr Sikora) Date: Tue, 25 Jul 2017 18:28:16 -0700 Subject: [PATCH 12 of 14] Proxy: add HTTP/2 support In-Reply-To: <20170719143430.GO93611@mdounin.ru> References: <5f5d70428655db0889a2.1498163585@piotrsikora.sfo.corp.google.com> <7eb807b056da7abe9c67.1498163596@piotrsikora.sfo.corp.google.com> <20170719143430.GO93611@mdounin.ru> Message-ID: Hey Maxim, > There are serious concerns about this and with other patches. > Most generic ones are outlined below. > > 1. Server-side HTTP/2 code complexity concerns. > > As per discussion with Valentin, introducing client-related code > paths in the server HTTP/2 code seems to complicate things. Given > that the complexity of the code is already high, it might be > better idea to implement separate client-side processing instead. I strongly disagree. Changes introduced to ngx_http_v2.c and ngx_http_v2_filter_module.c are minimal. Also, having separate client-side and server-side code would result in thousands of lines of duplicated code, for no reason, really. > 2. Different protocols in proxy module. > > You've introduced a completely different protocol in the proxy > module, which contradicts the established practice of using > separate modules for different protocols. > > Reasons for having all (or at least may of) the protocols > available in the proxy module instead are well understood, and > there is a long-term plan to revise current practice. The plan is > to preserve protocol-specific modules as a separate entities, but > let them share the common configuration directives, similar to how > it is currently done with upstream{} blocks and the overall > upstream infrastructure. So one can write something like > > proxy_pass fastcgi://127.0.0.1:9000; > > and get an expected result. > > While benefits of having all protocols sharing the same > user-visible interface are understood, approach taken with HTTP/2 > implementation is considered suboptimal, and will likely lead to > something hard to maintain. > > I see two possible solutions here: > > - make HTTP/2-to-upstreams a separate full-featured upstream-based > module, similar to proxy or fastcgi; But that's basically: cat ngx_http_proxy_module.c \ | sed 's/ngx_http_proxy/ngx_http_proxy_v2/g' \ > ngx_http_proxy_v2_module.c I don't see how copying ~4500 lines of code is a good idea. Also, as mentioned elsewhere, one of the reasons for adding HTTP/2 code to the proxy module was the ability to negotiate HTTP/1.1 or HTTP/2 via ALPN. Creating a separate HTTP/2-to-upstreams module won't allow to add such feature in the future. > - start working on the different protocols in the proxy module, > and introduce HTTP/2 proxying after this work is done. How is that even an option here? It's going to take forever before such rewrite is done, and I have no desire nor time to work on that. > Additionally, there are also some minor / related comments: > > - Parts of the code, tightly coupled with upstream infrastructure, > notably ngx_http_v2_upstream_output_filter(), are placed into > v2/ directory. Instead, they seem to belong to the > HTTP/2-to-upstream module implementation, as suggested in (1). Sure, this and a few other functions could be added to different files. > - Upstream infrastructure as available in > src/http/ngx_http_upstream.c is expected to be > protocol-agnostic. Introducing calls like > ngx_http_v2_init_connection() there is a layering violation. > Instead, there should be something more generic. I agree that ngx_http_v2_init_connection() isn't perfect, however, fake connections are an abstraction layer that needs to be added somewhere. The same is done for SSL, and it's somehow acceptable. I'm happy to use whatever generic mechanism is available, but there is none at the moment, and I don't see how adding even more code and complexity to this already big patchset is going to get us anywhere. > - Doing protocol parsing elsewhere instead of parsing things based > on what nginx got from the connection results in some generic > upstream mechanisms rendered not working - notably, it is no > longer possible to simply write headers to a cache file. > Serialization introduced instead, at least in its current form, > looks more like a bandaid. Except that HTTP/2 headers as read from the wire, even if parsed in separate module, couldn't be simply written to a cache file, because of stateful HPACK encoding, so serialization would need to be done anyway. Anyway, it appears that your "serious concerns" are mostly about organization of the code, and not the code itself. What's unclear to me is how much of the code review this patchset actually received, i.e. if the existing code would be moved to a separate HTTP/2-to-upstreams module, would it be acceptable or do you have other issues with the code? Best regards, Piotr Sikora From nginx at nedharvey.com Wed Jul 26 19:09:07 2017 From: nginx at nedharvey.com (Edward Ned Harvey (nginx)) Date: Wed, 26 Jul 2017 19:09:07 +0000 Subject: Official drupal recipe for nginx Message-ID: Hi, I'm a sysadmin at a large organization, where we use a lot of drupal on nginx (hundreds of sites). Recently, we encountered two bugs related to drupal 8 vs nginx config. I reached out to some friends of mine who are drupal core developers, and essentially it boils down to this: They don't have an official nginx config, so they don't test drupal releases on nginx except manually, only in response to bug reports. So nginx-related bugs tend to get released to the public, and they tend to take a long time before they're resolved. This is a major problem for anybody running drupal on nginx, because any drupal security updates that come out can't be applied as long as some other drupal-nginx bug is show-stopping. Case in point: The incident that recently forced me into all this was when one of our site maintainers tried to update drupal core 8.2.7 to 8.3.5 in order to get security fixes released in 8.3.4, but after the update, the site ended up completely broken. The root cause of that one is related to nginx config - and that issue is solved by updating to the latest nginx drupal 8 recipe (https://www.nginx.com/resources/wiki/start/topics/recipes/drupal/). Unfortunately, the new recipe causes Responsive Images to break, so we still can't publish the updated website to production. So now I'm reaching out to all you lovely nginx developers to find out if there's any chance of improving this. It would mean some of you (probably whoever wrote the drupal 8 nginx recipe) working with drupal developers probably on an ongoing basis, to create and maintain an official nginx config that they test on. The conversation I had with drupal developers is here: https://drupal.slack.com/archives/C06GX3K08/p1501090066425123 And the related drupal bug report for my particular issue is here: https://www.drupal.org/node/2897637 Important points: * Some drupal updates between 8.2.7 and 8.3.5 require the nginx recipe to be updated from the old drupal7 nginx recipe to the new drupal8 nginx recipe. Or else the site is completely nonfunctional. * Unfortunately, something in the new drupal8 nginx recipe causes Responsive Images to break, which is also show-stopping. * Either way, drupal 8.3.5 doesn't work on nginx. * In order for them to test drupal releases on nginx, they need help setting up the official nginx config, and docker environment. * If this doesn't happen, it's likely to force a lot of people, like us, into using apache (which we don't want). Thanks for your feedback... -------------- next part -------------- An HTML attachment was scrubbed... URL: From mdounin at mdounin.ru Thu Jul 27 08:54:25 2017 From: mdounin at mdounin.ru (Maxim Dounin) Date: Thu, 27 Jul 2017 11:54:25 +0300 Subject: [nginx] Fixed background requests with asynchronous operations. In-Reply-To: References: Message-ID: <20170727085425.GJ93611@mdounin.ru> Hello! On Mon, Jul 24, 2017 at 10:08:20AM +0000, Eran Kornblau wrote: > Hi Roman, > > I got a GitHub issue opened few days ago, that my module doesn't work following this commit - > https://github.com/kaltura/nginx-vod-module/issues/645#issuecomment-317027706 > > The situation is as follows - > 1. My module's content phase handler runs and performs an async read request - > a. It calls ngx_file_aio_read which returns NGX_AGAIN > b. Increments r->blocked > c. Sets r->aio to 1 > (code here - https://github.com/kaltura/nginx-vod-module/blob/master/ngx_file_reader.c#L392) > 2. The NGX_AGAIN status propagates up to ngx_http_core_content_phase which calls ngx_http_finalize_request > with this status. > 3. r->buffered, c->buffered, and r->postponed are all false, so this if: > https://github.com/nginx/nginx/blob/master/src/http/ngx_http_request.c#L2456 > is skipped (it used to enter before the patch since r->blocked is 1) > In addition, r == c->data, so at the end, ngx_http_finalize_request calls ngx_http_finalize_connection > 4. Since r->main->count == 1 and r->keepalive == 1, this function calls ngx_http_set_keepalive > 5. ngx_http_set_keepalive calls ngx_http_free_request which destroys the pool even though it has aio pending. > > Please let me know if you think I'm doing something wrong here (I can, for example, increment r->main->count, > but this is not done in any of the other places that do blocked++) The NGX_AGAIN returned from a content phase handler when you started an AIO operation looks wrong: it means that nginx is already writing a response and was blocked by a full socket buffer. In this case nginx will assume it should continue writing based on socket's write events, and will close the connection as long as everything is written (no r->buffered, c->buffered is set). Before the Roman's patch the situation was the same: there is not r->blocking check in ngx_http_writer(), so it would close the connection as long as a write event happen for some reason. Rather, you should use NGX_DONE and increment r->count if you want to wait for an AIO operation result and continue processing yourself. [...] -- Maxim Dounin http://nginx.org/ From eran.kornblau at kaltura.com Thu Jul 27 09:43:45 2017 From: eran.kornblau at kaltura.com (Eran Kornblau) Date: Thu, 27 Jul 2017 09:43:45 +0000 Subject: [nginx] Fixed background requests with asynchronous operations. In-Reply-To: <20170727085425.GJ93611@mdounin.ru> References: <20170727085425.GJ93611@mdounin.ru> Message-ID: > -----Original Message----- > From: nginx-devel [mailto:nginx-devel-bounces at nginx.org] On Behalf Of Maxim Dounin > Sent: Thursday, July 27, 2017 11:54 AM > To: nginx-devel at nginx.org > Subject: Re: [nginx] Fixed background requests with asynchronous operations. > > The NGX_AGAIN returned from a content phase handler when you started an AIO operation looks wrong: it means that nginx is already writing a response and was blocked by a full socket buffer. In this case nginx will assume it should continue writing based on socket's write events, and will close the connection as long as everything is written (no r->buffered, c->buffered is set). Before the Roman's patch the situation was the same: > there is not r->blocking check in ngx_http_writer(), so it would close the connection as long as a write event happen for some reason. > > Rather, you should use NGX_DONE and increment r->count if you want to wait for an AIO operation result and continue processing yourself. > > [...] Thank you, Maxim, ran a quick test and returning NGX_DONE & r->main->count++ indeed solves the crash. I'm quite sure that's what my code used to do few years ago, but then I changed it to return NGX_AGAIN, don't remember why... Anyway, I will test it more thoroughly and update this thread if anything comes up. Thanks, Eran > > -- > Maxim Dounin > http://nginx.org/ > _______________________________________________ > nginx-devel mailing list > nginx-devel at nginx.org > http://mailman.nginx.org/mailman/listinfo/nginx-devel > From ru at nginx.com Thu Jul 27 20:26:51 2017 From: ru at nginx.com (Ruslan Ermilov) Date: Thu, 27 Jul 2017 20:26:51 +0000 Subject: [nginx] Cache: fixed max_size on win32. Message-ID: details: http://hg.nginx.org/nginx/rev/72d3aefc2993 branches: changeset: 7075:72d3aefc2993 user: Ruslan Ermilov date: Wed Jul 26 13:13:51 2017 +0300 description: Cache: fixed max_size on win32. diffstat: src/http/ngx_http_file_cache.c | 1 + 1 files changed, 1 insertions(+), 0 deletions(-) diffs (11 lines): diff -r 07a49cce21ca -r 72d3aefc2993 src/http/ngx_http_file_cache.c --- a/src/http/ngx_http_file_cache.c Tue Jul 25 17:21:59 2017 +0300 +++ b/src/http/ngx_http_file_cache.c Wed Jul 26 13:13:51 2017 +0300 @@ -129,6 +129,7 @@ ngx_http_file_cache_init(ngx_shm_zone_t if (shm_zone->shm.exists) { cache->sh = cache->shpool->data; cache->bsize = ngx_fs_bsize(cache->path->name.data); + cache->max_size /= cache->bsize; return NGX_OK; } From nate.karstens at garmin.com Fri Jul 28 18:45:35 2017 From: nate.karstens at garmin.com (Nate Karstens) Date: Fri, 28 Jul 2017 13:45:35 -0500 Subject: [PATCH 0 of 2] [PATCH 1+2 of 4] In-Reply-To: <010247> References: <010247> Message-ID: ________________________________ CONFIDENTIALITY NOTICE: This email and any attachments are for the sole use of the intended recipient(s) and contain information that may be Garmin confidential and/or Garmin legally privileged. If you have received this email in error, please notify the sender by reply email and delete the message. Any disclosure, copying, distribution or use of this communication (including attachments) by someone other than the intended recipient is prohibited. Thank you. From nate.karstens at garmin.com Fri Jul 28 18:45:37 2017 From: nate.karstens at garmin.com (Nate Karstens) Date: Fri, 28 Jul 2017 13:45:37 -0500 Subject: [PATCH 2 of 2] SSL: add connection support In-Reply-To: References: Message-ID: <9537b7d299131e41a3f5.1501267537@OLA-6J5NNS1.ad.garmin.com> # HG changeset patch # User Nate Karstens # Date 1501265849 18000 # Fri Jul 28 13:17:29 2017 -0500 # Node ID 9537b7d299131e41a3f5993257000d328e28b117 # Parent 7e10e1dc1fae0f538a0a74fd6783f9b33a905933 SSL: add connection support. Adds support for TLS connections using PSK cipher suites. A new configuration directive, ssl_psk_file, specifies the file that contains a list of identities and associated PSKs. Each line of the file begins with the identity, followed by a colon character (':'), and ending with the PSK. As required by RFC 4279 section 5.4, PSKs may be entered either as plain text or using hexadecimal encoding. Hexadecimal PSKs must begin with "{HEX}". PSKs without this prefix are assumed to be plain text, but they may optionally begin with "{PLAIN}" to denote this. Some examples: gary:plain_text_password min:{PLAIN}another_text_password cliff:{HEX}ab0123CD PSK functionality can be easily tested with the OpenSSL s_client using the "-psk" and "-psk_identity" options. Signed-off-by: Nate Karstens diff -r 7e10e1dc1fae -r 9537b7d29913 contrib/vim/syntax/nginx.vim --- a/contrib/vim/syntax/nginx.vim Fri Jul 28 13:16:27 2017 -0500 +++ b/contrib/vim/syntax/nginx.vim Fri Jul 28 13:17:29 2017 -0500 @@ -550,6 +550,7 @@ syn keyword ngxDirective contained ssl_p syn keyword ngxDirective contained ssl_prefer_server_ciphers syn keyword ngxDirective contained ssl_preread syn keyword ngxDirective contained ssl_protocols +syn keyword ngxDirective contained ssl_psk_file syn keyword ngxDirective contained ssl_session_cache syn keyword ngxDirective contained ssl_session_ticket_key syn keyword ngxDirective contained ssl_session_tickets diff -r 7e10e1dc1fae -r 9537b7d29913 src/event/ngx_event_openssl.c --- a/src/event/ngx_event_openssl.c Fri Jul 28 13:16:27 2017 -0500 +++ b/src/event/ngx_event_openssl.c Fri Jul 28 13:17:29 2017 -0500 @@ -11,6 +11,7 @@ #define NGX_SSL_PASSWORD_BUFFER_SIZE 4096 +#define NGX_SSL_PSK_BUFFER_SIZE 4096 typedef struct { @@ -23,6 +24,8 @@ static int ngx_ssl_password_callback(cha static int ngx_ssl_verify_callback(int ok, X509_STORE_CTX *x509_store); static void ngx_ssl_info_callback(const ngx_ssl_conn_t *ssl_conn, int where, int ret); +static unsigned int ngx_ssl_psk_callback(ngx_ssl_conn_t *ssl_conn, + const char *identity, unsigned char *psk, unsigned int max_psk_len); static void ngx_ssl_passwords_cleanup(void *data); static void ngx_ssl_handshake_handler(ngx_event_t *ev); static ngx_int_t ngx_ssl_handle_recv(ngx_connection_t *c, int n); @@ -114,6 +117,7 @@ int ngx_ssl_certificate_index; int ngx_ssl_next_certificate_index; int ngx_ssl_certificate_name_index; int ngx_ssl_stapling_index; +int ngx_ssl_psk_index; ngx_int_t @@ -225,6 +229,13 @@ ngx_ssl_init(ngx_log_t *log) return NGX_ERROR; } + ngx_ssl_psk_index = SSL_get_ex_new_index(0, NULL, NULL, NULL, NULL); + + if (ngx_ssl_psk_index == -1) { + ngx_ssl_error(NGX_LOG_ALERT, log, 0, "SSL_get_ex_new_index() failed"); + return NGX_ERROR; + } + return NGX_OK; } @@ -875,6 +886,138 @@ ngx_ssl_info_callback(const ngx_ssl_conn } +static unsigned int +ngx_ssl_psk_callback(ngx_ssl_conn_t *ssl_conn, const char *identity, + unsigned char *psk, unsigned int max_psk_len) +{ + u_char *p, *last, *end, *psk_ptr; + size_t len; + ssize_t n; + SSL_CTX *ssl_ctx; + ngx_fd_t fd; + ngx_str_t *psk_file; + ngx_int_t psk_len; + ngx_connection_t *c; + u_char buf[NGX_SSL_PSK_BUFFER_SIZE]; + + c = ngx_ssl_get_connection(ssl_conn); + + ssl_ctx = c->ssl->session_ctx; + psk_file = SSL_CTX_get_ex_data(ssl_ctx, ngx_ssl_psk_index); + + if (psk_file == NULL) { + return 0; + } + + fd = ngx_open_file(psk_file->data, NGX_FILE_RDONLY, NGX_FILE_OPEN, 0); + if (fd == NGX_INVALID_FILE) { + ngx_ssl_error(NGX_LOG_ERR, c->log, ngx_errno, + ngx_open_file_n " \"%V\" failed", psk_file); + return 0; + } + + len = 0; + last = buf; + + do { + n = ngx_read_fd(fd, last, NGX_SSL_PSK_BUFFER_SIZE - len); + + if (n == -1) { + ngx_ssl_error(NGX_LOG_ERR, c->log, ngx_errno, + ngx_read_fd_n " \"%V\" failed", psk_file); + psk_len = 0; + goto cleanup; + } + + end = last + n; + + if (len && n == 0) { + *end++ = LF; + } + + for (p = buf; /* void */; p = last) { + last = ngx_strlchr(last, end, LF); + + if (last == NULL) { + break; + } + + len = last++ - p; + + if (len && p[len - 1] == CR) { + len--; + } + + if (len == 0) { + continue; + } + + psk_ptr = (u_char *) ngx_strlchr(p, p + len, ':'); + + if (psk_ptr == NULL) { + continue; + } + + *psk_ptr = '\0'; + psk_ptr++; + + if (ngx_strcmp(p, identity) != 0) { + continue; + } + + if (ngx_strncmp(psk_ptr, "{HEX}", ngx_strlen("{HEX}")) == 0) { + psk_ptr += ngx_strlen("{HEX}"); + psk_len = ngx_hex_decode(psk, max_psk_len, psk_ptr, + p + len - psk_ptr); + if (psk_len == NGX_ERROR) { + ngx_memzero(psk, max_psk_len); + psk_len = 0; + } + goto cleanup; + } else if (ngx_strncmp(psk_ptr, "{PLAIN}", + ngx_strlen("{PLAIN}")) == 0) { + psk_ptr += ngx_strlen("{PLAIN}"); + } + + psk_len = last - 1 - psk_ptr; + + if (psk_len > max_psk_len) { + psk_len = 0; + goto cleanup; + } + + ngx_memcpy(psk, psk_ptr, psk_len); + goto cleanup; + } + + len = end - p; + + if (len == NGX_SSL_PSK_BUFFER_SIZE) { + ngx_ssl_error(NGX_LOG_ERR, c->log, 0, + "too long line in \"%V\"", psk_file); + psk_len = 0; + goto cleanup; + } + + ngx_memmove(buf, p, len); + last = buf + len; + + } while (n != 0); + +cleanup: + + if (ngx_close_file(fd) == NGX_FILE_ERROR) { + ngx_ssl_error(NGX_LOG_ALERT, c->log, ngx_errno, + ngx_close_file_n " %V failed", psk_file); + psk_len = 0; + } + + ngx_memzero(buf, NGX_SSL_PSK_BUFFER_SIZE); + + return psk_len; +} + + RSA * ngx_ssl_rsa512_key_callback(ngx_ssl_conn_t *ssl_conn, int is_export, int key_length) @@ -3137,6 +3280,23 @@ ngx_ssl_session_ticket_keys(ngx_conf_t * #endif +ngx_int_t +ngx_ssl_psk_file(ngx_conf_t *cf, ngx_ssl_t *ssl, ngx_str_t *file) +{ +#if OPENSSL_VERSION_NUMBER >= 0x1000000fL + if (SSL_CTX_set_ex_data(ssl->ctx, ngx_ssl_psk_index, file) == 0) { + ngx_ssl_error(NGX_LOG_ALERT, ssl->log, 0, + "SSL_CTX_set_ex_data() failed"); + return NGX_ERROR; + } + + SSL_CTX_set_psk_server_callback(ssl->ctx, ngx_ssl_psk_callback); +#endif + + return NGX_OK; +} + + void ngx_ssl_cleanup_ctx(void *data) { diff -r 7e10e1dc1fae -r 9537b7d29913 src/event/ngx_event_openssl.h --- a/src/event/ngx_event_openssl.h Fri Jul 28 13:16:27 2017 -0500 +++ b/src/event/ngx_event_openssl.h Fri Jul 28 13:17:29 2017 -0500 @@ -171,6 +171,7 @@ ngx_int_t ngx_ssl_session_cache(ngx_ssl_ ssize_t builtin_session_cache, ngx_shm_zone_t *shm_zone, time_t timeout); ngx_int_t ngx_ssl_session_ticket_keys(ngx_conf_t *cf, ngx_ssl_t *ssl, ngx_array_t *paths); +ngx_int_t ngx_ssl_psk_file(ngx_conf_t *cf, ngx_ssl_t *ssl, ngx_str_t *file); ngx_int_t ngx_ssl_session_cache_init(ngx_shm_zone_t *shm_zone, void *data); ngx_int_t ngx_ssl_create_connection(ngx_ssl_t *ssl, ngx_connection_t *c, ngx_uint_t flags); @@ -255,6 +256,7 @@ extern int ngx_ssl_certificate_index; extern int ngx_ssl_next_certificate_index; extern int ngx_ssl_certificate_name_index; extern int ngx_ssl_stapling_index; +extern int ngx_ssl_psk_index; #endif /* _NGX_EVENT_OPENSSL_H_INCLUDED_ */ diff -r 7e10e1dc1fae -r 9537b7d29913 src/http/modules/ngx_http_ssl_module.c --- a/src/http/modules/ngx_http_ssl_module.c Fri Jul 28 13:16:27 2017 -0500 +++ b/src/http/modules/ngx_http_ssl_module.c Fri Jul 28 13:17:29 2017 -0500 @@ -234,6 +234,13 @@ static ngx_command_t ngx_http_ssl_comma offsetof(ngx_http_ssl_srv_conf_t, stapling_verify), NULL }, + { ngx_string("ssl_psk_file"), + NGX_HTTP_MAIN_CONF|NGX_HTTP_SRV_CONF|NGX_CONF_TAKE1, + ngx_conf_set_str_slot, + NGX_HTTP_SRV_CONF_OFFSET, + offsetof(ngx_http_ssl_srv_conf_t, psk_file), + NULL }, + ngx_null_command }; @@ -539,6 +546,7 @@ ngx_http_ssl_create_srv_conf(ngx_conf_t * sscf->shm_zone = NULL; * sscf->stapling_file = { 0, NULL }; * sscf->stapling_responder = { 0, NULL }; + * sscf->psk_file = { 0, NULL }; */ sscf->enable = NGX_CONF_UNSET; @@ -620,6 +628,8 @@ ngx_http_ssl_merge_srv_conf(ngx_conf_t * ngx_conf_merge_str_value(conf->stapling_responder, prev->stapling_responder, ""); + ngx_conf_merge_str_value(conf->psk_file, prev->psk_file, ""); + conf->ssl.log = cf->log; if (conf->enable) { @@ -800,6 +810,12 @@ ngx_http_ssl_merge_srv_conf(ngx_conf_t * } + if (ngx_ssl_psk_file(cf, &conf->ssl, &conf->psk_file) + != NGX_OK) + { + return NGX_CONF_ERROR; + } + return NGX_CONF_OK; } diff -r 7e10e1dc1fae -r 9537b7d29913 src/http/modules/ngx_http_ssl_module.h --- a/src/http/modules/ngx_http_ssl_module.h Fri Jul 28 13:16:27 2017 -0500 +++ b/src/http/modules/ngx_http_ssl_module.h Fri Jul 28 13:17:29 2017 -0500 @@ -55,6 +55,8 @@ typedef struct { ngx_str_t stapling_file; ngx_str_t stapling_responder; + ngx_str_t psk_file; + u_char *file; ngx_uint_t line; } ngx_http_ssl_srv_conf_t; ________________________________ CONFIDENTIALITY NOTICE: This email and any attachments are for the sole use of the intended recipient(s) and contain information that may be Garmin confidential and/or Garmin legally privileged. If you have received this email in error, please notify the sender by reply email and delete the message. Any disclosure, copying, distribution or use of this communication (including attachments) by someone other than the intended recipient is prohibited. Thank you. From nate.karstens at garmin.com Fri Jul 28 18:45:36 2017 From: nate.karstens at garmin.com (Nate Karstens) Date: Fri, 28 Jul 2017 13:45:36 -0500 Subject: [PATCH 1 of 2] Core: add function to decode hexadecimal strings In-Reply-To: References: Message-ID: <7e10e1dc1fae0f538a0a.1501267536@OLA-6J5NNS1.ad.garmin.com> # HG changeset patch # User Nate Karstens # Date 1501265787 18000 # Fri Jul 28 13:16:27 2017 -0500 # Node ID 7e10e1dc1fae0f538a0a74fd6783f9b33a905933 # Parent 72d3aefc2993a639cc8cddc94aefc7c4390ee252 Core: add function to decode hexadecimal strings. Adds functionality to convert a hexadecimal string into binary data. This will be used to decode PSKs stored in hexadecimal representation. Signed-off-by: Nate Karstens diff -r 72d3aefc2993 -r 7e10e1dc1fae src/core/ngx_string.c --- a/src/core/ngx_string.c Wed Jul 26 13:13:51 2017 +0300 +++ b/src/core/ngx_string.c Fri Jul 28 13:16:27 2017 -0500 @@ -1104,6 +1104,54 @@ ngx_hextoi(u_char *line, size_t n) } +ngx_int_t +ngx_hex_decode(u_char *dst, size_t dlen, u_char *src, size_t slen) +{ + u_char c, ch; + ngx_int_t len; + + if ((slen & 1) || (dlen < (slen / 2))) { + return NGX_ERROR; + } + + len = slen / 2; + + while (slen > 0) { + ch = *src; + c = (u_char) (ch | 0x20); + + if (ch >= '0' && ch <= '9') { + *dst = ch - '0'; + } else if (c >= 'a' && c <= 'f') { + *dst = c - 'a' + 10; + } else { + return NGX_ERROR; + } + + *dst <<= 4; + src++; + + ch = *src; + c = (u_char) (ch | 0x20); + + if (ch >= '0' && ch <= '9') { + *dst |= ch - '0'; + } else if (c >= 'a' && c <= 'f') { + *dst |= c - 'a' + 10; + } else { + return NGX_ERROR; + } + + dst++; + src++; + + slen -= 2; + } + + return len; +} + + u_char * ngx_hex_dump(u_char *dst, u_char *src, size_t len) { diff -r 72d3aefc2993 -r 7e10e1dc1fae src/core/ngx_string.h --- a/src/core/ngx_string.h Wed Jul 26 13:13:51 2017 +0300 +++ b/src/core/ngx_string.h Fri Jul 28 13:16:27 2017 -0500 @@ -176,6 +176,7 @@ off_t ngx_atoof(u_char *line, size_t n); time_t ngx_atotm(u_char *line, size_t n); ngx_int_t ngx_hextoi(u_char *line, size_t n); +ngx_int_t ngx_hex_decode(u_char *dst, size_t dlen, u_char *src, size_t slen); u_char *ngx_hex_dump(u_char *dst, u_char *src, size_t len); ________________________________ CONFIDENTIALITY NOTICE: This email and any attachments are for the sole use of the intended recipient(s) and contain information that may be Garmin confidential and/or Garmin legally privileged. If you have received this email in error, please notify the sender by reply email and delete the message. Any disclosure, copying, distribution or use of this communication (including attachments) by someone other than the intended recipient is prohibited. Thank you. From nate.karstens at garmin.com Fri Jul 28 18:49:13 2017 From: nate.karstens at garmin.com (Nate Karstens) Date: Fri, 28 Jul 2017 13:49:13 -0500 Subject: [PATCH] SSL: add PSK identity variable In-Reply-To: <010248> References: <010248> Message-ID: <00a1466fe33b8969ef76.1501267753@OLA-6J5NNS1.ad.garmin.com> # HG changeset patch # User Nate Karstens # Date 1501265895 18000 # Fri Jul 28 13:18:15 2017 -0500 # Node ID 00a1466fe33b8969ef765d8d0547dfbc7c97dd4e # Parent 9537b7d299131e41a3f5993257000d328e28b117 SSL: add PSK identity variable. Adds the variable $ssl_psk_identity to get the PSK identity used in a connnection secured with a PSK cipher suite. Signed-off-by: Nate Karstens diff -r 9537b7d29913 -r 00a1466fe33b src/event/ngx_event_openssl.c --- a/src/event/ngx_event_openssl.c Fri Jul 28 13:17:29 2017 -0500 +++ b/src/event/ngx_event_openssl.c Fri Jul 28 13:18:15 2017 -0500 @@ -4249,6 +4249,22 @@ ngx_ssl_get_client_v_remain(ngx_connecti } +ngx_int_t +ngx_ssl_get_psk_identity(ngx_connection_t *c, ngx_pool_t *pool, ngx_str_t *s) +{ + const char *identity; + + identity = SSL_get_psk_identity(c->ssl->connection); + + if (identity) { + s->data = (u_char *) identity; + s->len = ngx_strlen(identity); + } + + return NGX_OK; +} + + static time_t ngx_ssl_parse_time( #if OPENSSL_VERSION_NUMBER > 0x10100000L diff -r 9537b7d29913 -r 00a1466fe33b src/event/ngx_event_openssl.h --- a/src/event/ngx_event_openssl.h Fri Jul 28 13:17:29 2017 -0500 +++ b/src/event/ngx_event_openssl.h Fri Jul 28 13:18:15 2017 -0500 @@ -233,6 +233,8 @@ ngx_int_t ngx_ssl_get_client_v_end(ngx_c ngx_str_t *s); ngx_int_t ngx_ssl_get_client_v_remain(ngx_connection_t *c, ngx_pool_t *pool, ngx_str_t *s); +ngx_int_t ngx_ssl_get_psk_identity(ngx_connection_t *c, ngx_pool_t *pool, + ngx_str_t *s); ngx_int_t ngx_ssl_handshake(ngx_connection_t *c); diff -r 9537b7d29913 -r 00a1466fe33b src/http/modules/ngx_http_ssl_module.c --- a/src/http/modules/ngx_http_ssl_module.c Fri Jul 28 13:17:29 2017 -0500 +++ b/src/http/modules/ngx_http_ssl_module.c Fri Jul 28 13:18:15 2017 -0500 @@ -336,6 +336,9 @@ static ngx_http_variable_t ngx_http_ssl { ngx_string("ssl_client_v_remain"), NULL, ngx_http_ssl_variable, (uintptr_t) ngx_ssl_get_client_v_remain, NGX_HTTP_VAR_CHANGEABLE, 0 }, + { ngx_string("ssl_psk_identity"), NULL, ngx_http_ssl_variable, + (uintptr_t) ngx_ssl_get_psk_identity, NGX_HTTP_VAR_CHANGEABLE, 0 }, + { ngx_null_string, NULL, NULL, 0, 0, 0 } }; ________________________________ CONFIDENTIALITY NOTICE: This email and any attachments are for the sole use of the intended recipient(s) and contain information that may be Garmin confidential and/or Garmin legally privileged. If you have received this email in error, please notify the sender by reply email and delete the message. Any disclosure, copying, distribution or use of this communication (including attachments) by someone other than the intended recipient is prohibited. Thank you. From nate.karstens at garmin.com Fri Jul 28 18:50:44 2017 From: nate.karstens at garmin.com (Nate Karstens) Date: Fri, 28 Jul 2017 13:50:44 -0500 Subject: [PATCH] SSL: add identity hint config directive In-Reply-To: <010249> References: <010249> Message-ID: # HG changeset patch # User Nate Karstens # Date 1501265943 18000 # Fri Jul 28 13:19:03 2017 -0500 # Node ID d47b57ebf82c1eedb4236a661b9d786dfd06b468 # Parent 00a1466fe33b8969ef765d8d0547dfbc7c97dd4e SSL: add identity hint config directive. Adds the directive "ssl_psk_identity_hint" to the ngx_http_ssl_module. This allows the user to specify the PSK identity hint given to the connecting client. Signed-off-by: Nate Karstens diff -r 00a1466fe33b -r d47b57ebf82c contrib/vim/syntax/nginx.vim --- a/contrib/vim/syntax/nginx.vim Fri Jul 28 13:18:15 2017 -0500 +++ b/contrib/vim/syntax/nginx.vim Fri Jul 28 13:19:03 2017 -0500 @@ -551,6 +551,7 @@ syn keyword ngxDirective contained ssl_p syn keyword ngxDirective contained ssl_preread syn keyword ngxDirective contained ssl_protocols syn keyword ngxDirective contained ssl_psk_file +syn keyword ngxDirective contained ssl_psk_identity_hint syn keyword ngxDirective contained ssl_session_cache syn keyword ngxDirective contained ssl_session_ticket_key syn keyword ngxDirective contained ssl_session_tickets diff -r 00a1466fe33b -r d47b57ebf82c src/event/ngx_event_openssl.c --- a/src/event/ngx_event_openssl.c Fri Jul 28 13:18:15 2017 -0500 +++ b/src/event/ngx_event_openssl.c Fri Jul 28 13:19:03 2017 -0500 @@ -3281,7 +3281,8 @@ ngx_ssl_session_ticket_keys(ngx_conf_t * ngx_int_t -ngx_ssl_psk_file(ngx_conf_t *cf, ngx_ssl_t *ssl, ngx_str_t *file) +ngx_ssl_psk_file(ngx_conf_t *cf, ngx_ssl_t *ssl, ngx_str_t *file, + ngx_str_t *identity_hint) { #if OPENSSL_VERSION_NUMBER >= 0x1000000fL if (SSL_CTX_set_ex_data(ssl->ctx, ngx_ssl_psk_index, file) == 0) { @@ -3290,6 +3291,13 @@ ngx_ssl_psk_file(ngx_conf_t *cf, ngx_ssl return NGX_ERROR; } + if (SSL_CTX_use_psk_identity_hint(ssl->ctx, + (char *) identity_hint->data) == 0) { + ngx_ssl_error(NGX_LOG_ALERT, ssl->log, 0, + "SSL_CTX_use_psk_identity_hint() failed"); + return NGX_ERROR; + } + SSL_CTX_set_psk_server_callback(ssl->ctx, ngx_ssl_psk_callback); #endif diff -r 00a1466fe33b -r d47b57ebf82c src/event/ngx_event_openssl.h --- a/src/event/ngx_event_openssl.h Fri Jul 28 13:18:15 2017 -0500 +++ b/src/event/ngx_event_openssl.h Fri Jul 28 13:19:03 2017 -0500 @@ -171,7 +171,8 @@ ngx_int_t ngx_ssl_session_cache(ngx_ssl_ ssize_t builtin_session_cache, ngx_shm_zone_t *shm_zone, time_t timeout); ngx_int_t ngx_ssl_session_ticket_keys(ngx_conf_t *cf, ngx_ssl_t *ssl, ngx_array_t *paths); -ngx_int_t ngx_ssl_psk_file(ngx_conf_t *cf, ngx_ssl_t *ssl, ngx_str_t *file); +ngx_int_t ngx_ssl_psk_file(ngx_conf_t *cf, ngx_ssl_t *ssl, ngx_str_t *file, + ngx_str_t *identity_hint); ngx_int_t ngx_ssl_session_cache_init(ngx_shm_zone_t *shm_zone, void *data); ngx_int_t ngx_ssl_create_connection(ngx_ssl_t *ssl, ngx_connection_t *c, ngx_uint_t flags); diff -r 00a1466fe33b -r d47b57ebf82c src/http/modules/ngx_http_ssl_module.c --- a/src/http/modules/ngx_http_ssl_module.c Fri Jul 28 13:18:15 2017 -0500 +++ b/src/http/modules/ngx_http_ssl_module.c Fri Jul 28 13:19:03 2017 -0500 @@ -241,6 +241,13 @@ static ngx_command_t ngx_http_ssl_comma offsetof(ngx_http_ssl_srv_conf_t, psk_file), NULL }, + { ngx_string("ssl_psk_identity_hint"), + NGX_HTTP_MAIN_CONF|NGX_HTTP_SRV_CONF|NGX_CONF_TAKE1, + ngx_conf_set_str_slot, + NGX_HTTP_SRV_CONF_OFFSET, + offsetof(ngx_http_ssl_srv_conf_t, psk_identity_hint), + NULL }, + ngx_null_command }; @@ -550,6 +557,7 @@ ngx_http_ssl_create_srv_conf(ngx_conf_t * sscf->stapling_file = { 0, NULL }; * sscf->stapling_responder = { 0, NULL }; * sscf->psk_file = { 0, NULL }; + * sscf->psk_identity_hint = { 0, NULL }; */ sscf->enable = NGX_CONF_UNSET; @@ -632,6 +640,7 @@ ngx_http_ssl_merge_srv_conf(ngx_conf_t * prev->stapling_responder, ""); ngx_conf_merge_str_value(conf->psk_file, prev->psk_file, ""); + ngx_conf_merge_str_value(conf->psk_identity_hint, prev->psk_identity_hint, ""); conf->ssl.log = cf->log; @@ -813,7 +822,8 @@ ngx_http_ssl_merge_srv_conf(ngx_conf_t * } - if (ngx_ssl_psk_file(cf, &conf->ssl, &conf->psk_file) + if (ngx_ssl_psk_file(cf, &conf->ssl, &conf->psk_file, + &conf->psk_identity_hint) != NGX_OK) { return NGX_CONF_ERROR; diff -r 00a1466fe33b -r d47b57ebf82c src/http/modules/ngx_http_ssl_module.h --- a/src/http/modules/ngx_http_ssl_module.h Fri Jul 28 13:18:15 2017 -0500 +++ b/src/http/modules/ngx_http_ssl_module.h Fri Jul 28 13:19:03 2017 -0500 @@ -56,6 +56,7 @@ typedef struct { ngx_str_t stapling_responder; ngx_str_t psk_file; + ngx_str_t psk_identity_hint; u_char *file; ngx_uint_t line; ________________________________ CONFIDENTIALITY NOTICE: This email and any attachments are for the sole use of the intended recipient(s) and contain information that may be Garmin confidential and/or Garmin legally privileged. If you have received this email in error, please notify the sender by reply email and delete the message. Any disclosure, copying, distribution or use of this communication (including attachments) by someone other than the intended recipient is prohibited. Thank you. From mdounin at mdounin.ru Sat Jul 29 23:31:35 2017 From: mdounin at mdounin.ru (Maxim Dounin) Date: Sun, 30 Jul 2017 02:31:35 +0300 Subject: Official drupal recipe for nginx In-Reply-To: References: Message-ID: <20170729233135.GS93611@mdounin.ru> Hello! On Wed, Jul 26, 2017 at 07:09:07PM +0000, Edward Ned Harvey (nginx) wrote: > I'm a sysadmin at a large organization, where we use a lot of > drupal on nginx (hundreds of sites). > > Recently, we encountered two bugs related to drupal 8 vs nginx > config. I reached out to some friends of mine who are drupal > core developers, and essentially it boils down to this: They > don't have an official nginx config, so they don't test drupal > releases on nginx except manually, only in response to bug > reports. So nginx-related bugs tend to get released to the > public, and they tend to take a long time before they're > resolved. This is a major problem for anybody running drupal on > nginx, because any drupal security updates that come out can't > be applied as long as some other drupal-nginx bug is > show-stopping. Case in point: The incident that recently forced > me into all this was when one of our site maintainers tried to > update drupal core 8.2.7 to 8.3.5 in order to get security fixes > released in 8.3.4, but after the update, the site ended up > completely broken. The root cause of that one is related to > nginx config - and that issue is solved by updating to the > latest nginx drupal 8 recipe > (https://www.nginx.com/resources/wiki/start/topics/recipes/drupal/). > Unfortunately, the new recipe causes Responsive Images to break, > so we still can't publish the updated website to production. > > So now I'm reaching out to all you lovely nginx developers to > find out if there's any chance of improving this. It would mean > some of you (probably whoever wrote the drupal 8 nginx recipe) > working with drupal developers probably on an ongoing basis, to > create and maintain an official nginx config that they test on. The recipes as found in the wiki are user-contributed, much like all the wiki contents. Please don't expect that nginx developers understand anything about Drupal and/or worked on these recipes. If you have anything to improve in the recipe, feel free to contribute. -- Maxim Dounin http://nginx.org/ From piotrsikora at google.com Mon Jul 31 22:04:55 2017 From: piotrsikora at google.com (Piotr Sikora) Date: Mon, 31 Jul 2017 15:04:55 -0700 Subject: [PATCH 12 of 14] Proxy: add HTTP/2 support In-Reply-To: References: <5f5d70428655db0889a2.1498163585@piotrsikora.sfo.corp.google.com> <7eb807b056da7abe9c67.1498163596@piotrsikora.sfo.corp.google.com> <20170719143430.GO93611@mdounin.ru> Message-ID: Hey Maxim, On Tue, Jul 25, 2017 at 6:28 PM, Piotr Sikora wrote: > Hey Maxim, > >> There are serious concerns about this and with other patches. >> Most generic ones are outlined below. >> >> 1. Server-side HTTP/2 code complexity concerns. >> >> As per discussion with Valentin, introducing client-related code >> paths in the server HTTP/2 code seems to complicate things. Given >> that the complexity of the code is already high, it might be >> better idea to implement separate client-side processing instead. > > I strongly disagree. Changes introduced to ngx_http_v2.c and > ngx_http_v2_filter_module.c are minimal. > > Also, having separate client-side and server-side code would result in > thousands of lines of duplicated code, for no reason, really. > >> 2. Different protocols in proxy module. >> >> You've introduced a completely different protocol in the proxy >> module, which contradicts the established practice of using >> separate modules for different protocols. >> >> Reasons for having all (or at least may of) the protocols >> available in the proxy module instead are well understood, and >> there is a long-term plan to revise current practice. The plan is >> to preserve protocol-specific modules as a separate entities, but >> let them share the common configuration directives, similar to how >> it is currently done with upstream{} blocks and the overall >> upstream infrastructure. So one can write something like >> >> proxy_pass fastcgi://127.0.0.1:9000; >> >> and get an expected result. >> >> While benefits of having all protocols sharing the same >> user-visible interface are understood, approach taken with HTTP/2 >> implementation is considered suboptimal, and will likely lead to >> something hard to maintain. >> >> I see two possible solutions here: >> >> - make HTTP/2-to-upstreams a separate full-featured upstream-based >> module, similar to proxy or fastcgi; > > But that's basically: > > cat ngx_http_proxy_module.c \ > | sed 's/ngx_http_proxy/ngx_http_proxy_v2/g' \ > > ngx_http_proxy_v2_module.c > > I don't see how copying ~4500 lines of code is a good idea. > > Also, as mentioned elsewhere, one of the reasons for adding HTTP/2 > code to the proxy module was the ability to negotiate HTTP/1.1 or > HTTP/2 via ALPN. Creating a separate HTTP/2-to-upstreams module won't > allow to add such feature in the future. > >> - start working on the different protocols in the proxy module, >> and introduce HTTP/2 proxying after this work is done. > > How is that even an option here? It's going to take forever before > such rewrite is done, and I have no desire nor time to work on that. > >> Additionally, there are also some minor / related comments: >> >> - Parts of the code, tightly coupled with upstream infrastructure, >> notably ngx_http_v2_upstream_output_filter(), are placed into >> v2/ directory. Instead, they seem to belong to the >> HTTP/2-to-upstream module implementation, as suggested in (1). > > Sure, this and a few other functions could be added to different files. > >> - Upstream infrastructure as available in >> src/http/ngx_http_upstream.c is expected to be >> protocol-agnostic. Introducing calls like >> ngx_http_v2_init_connection() there is a layering violation. >> Instead, there should be something more generic. > > I agree that ngx_http_v2_init_connection() isn't perfect, however, > fake connections are an abstraction layer that needs to be added > somewhere. The same is done for SSL, and it's somehow acceptable. > > I'm happy to use whatever generic mechanism is available, but there is > none at the moment, and I don't see how adding even more code and > complexity to this already big patchset is going to get us anywhere. > >> - Doing protocol parsing elsewhere instead of parsing things based >> on what nginx got from the connection results in some generic >> upstream mechanisms rendered not working - notably, it is no >> longer possible to simply write headers to a cache file. >> Serialization introduced instead, at least in its current form, >> looks more like a bandaid. > > Except that HTTP/2 headers as read from the wire, even if parsed in > separate module, couldn't be simply written to a cache file, because > of stateful HPACK encoding, so serialization would need to be done > anyway. > > Anyway, it appears that your "serious concerns" are mostly about > organization of the code, and not the code itself. What's unclear to > me is how much of the code review this patchset actually received, > i.e. if the existing code would be moved to a separate > HTTP/2-to-upstreams module, would it be acceptable or do you have > other issues with the code? Ping. Best regards, Piotr Sikora