From alistair.wooldrige at bbc.co.uk Tue May 3 14:10:26 2016 From: alistair.wooldrige at bbc.co.uk (Alistair Wooldrige) Date: Tue, 3 May 2016 14:10:26 +0000 Subject: ngx_ext_rename_file: remove the target file if ngx_copy_file() fails Message-ID: Hi, In response to: http://mailman.nginx.org/pipermail/nginx-devel/2015-November/007532.html Is there any chance of getting this patch looked over and moved towards master? Thanks, Alistair ----------------------------- http://www.bbc.co.uk This e-mail (and any attachments) is confidential and may contain personal views which are not the views of the BBC unless specifically stated. If you have received it in error, please delete it from your system. Do not use, copy or disclose the information in any way nor act in reliance on it and notify the sender immediately. Please note that the BBC monitors e-mails sent or received. Further communication will signify your consent to this. ----------------------------- From ronan.jezequel at gmail.com Wed May 4 09:29:48 2016 From: ronan.jezequel at gmail.com (Ronan Jezequel) Date: Wed, 4 May 2016 17:29:48 +0800 Subject: [njs] Allow access to nginx vars via the njs $v variable Message-ID: # HG changeset patch # User Ronan Jezequel # Date 1462351563 -28800 # Wed May 04 16:46:03 2016 +0800 # Node ID 00b51c1bd9c3b92173528a109473a5cc865f507f # Parent 1c50334fbea6441d2d8740b56f881eb77290af42 Allow access to nginx vars via njs $v variable (eg: $v.geoip_city) diff -r 1c50334fbea6 -r 00b51c1bd9c3 nginx/ngx_http_js_module.c --- a/nginx/ngx_http_js_module.c Thu Apr 14 18:23:09 2016 +0300 +++ b/nginx/ngx_http_js_module.c Wed May 04 16:46:03 2016 +0800 @@ -95,6 +95,8 @@ njs_value_t *value, void *obj, uintptr_t data); static njs_ret_t ngx_http_js_ext_get_remote_address(njs_vm_t *vm, njs_value_t *value, void *obj, uintptr_t data); +static njs_ret_t ngx_http_js_ext_get_var(njs_vm_t *vm, + njs_value_t *value, void *obj, uintptr_t data); static njs_ret_t ngx_http_js_ext_get_header_in(njs_vm_t *vm, njs_value_t *value, void *obj, uintptr_t data); static njs_ret_t ngx_http_js_ext_foreach_header_in(njs_vm_t *vm, void *obj, @@ -366,6 +368,18 @@ NULL, NULL, 0 }, + + { nxt_string("$v"), + NJS_EXTERN_OBJECT, + NULL, + 0, + ngx_http_js_ext_get_var, + NULL, + NULL, + NULL, + NULL, + NULL, + 0 }, }; @@ -939,6 +953,38 @@ static njs_ret_t +ngx_http_js_ext_get_var(njs_vm_t *vm, njs_value_t *value, void *obj, + uintptr_t data) +{ + nxt_str_t *v; + ngx_http_request_t *r; + + ngx_str_t name; + ngx_uint_t hash; + ngx_http_variable_value_t *val; + + v = (nxt_str_t*)data; + if (!v) { + return njs_string_create(vm, value, NULL, 0, 0); + } + + name.len = v->len; + name.data = (u_char *) v->data; + hash = ngx_hash_key (v->data, v->len);; + + r = (ngx_http_request_t *) obj; + val = ngx_http_get_variable( r, &name, hash); + + if( val && !val->not_found && val->valid) + { + return njs_string_create(vm, value, val->data, val->len, 0); + } + + return njs_string_create(vm, value, NULL, 0, 0); +} + + +static njs_ret_t ngx_http_js_ext_get_remote_address(njs_vm_t *vm, njs_value_t *value, void *obj, uintptr_t data) { From rmind at noxt.eu Wed May 4 13:20:30 2016 From: rmind at noxt.eu (Mindaugas Rasiukevicius) Date: Wed, 4 May 2016 14:20:30 +0100 Subject: Fixing ngx_http_slice_module use with named locations Message-ID: <20160504142030.bfda7a14d949ef6536604db0@noxt.eu> Hi, There is a problem with ngx_http_slice_module when it is used together with an internal redirection to a named location. It results in Nginx workers caching incorrect content and spinning in an infinite loop. Consider the following fragment: location /foo { error_page 550 = @bar; return 550; } location @bar { slice ...; proxy_pass ...; proxy_cache ...; ... } In ngx_http_slice_body_filter(), the slice context is associated with the subrequest: ngx_http_set_ctx(sr, ctx, ngx_http_slice_filter_module); However, the location re-match is triggered for the subrequests trying to fetch each slice. In the ngx_http_named_location() function: /* clear the modules contexts */ ngx_memzero(r->ctx, sizeof(void *) * ngx_http_max_module); So, the slice context gets lost. There are several ways to fix this. Unless you want an API to preserve the context, one simple fix would be to get the context via r->parent (if ctx == NULL && r != r->main). What would be the preferred way to fix this? Thanks. -- Mindaugas From hda at hda.me Wed May 4 17:28:23 2016 From: hda at hda.me (npyxg1mg2kn7dvk0rl06) Date: Wed, 04 May 2016 19:28:23 +0200 Subject: Building ngx_postgres module as dynamic Message-ID: <1547cd04196.10e07609a75103.3030697931958292644@hda.me> I have problem with building ngx_postgres module as dynamic module >/etc/nginx/modules/ngx_postgres.so: undefined symbol: ngx_postgres https://github.com/cryptofuture/ngx_postgres/blob/808389353c88da4e641ef4b3ac6e0193191b4028/config - config file I used changes with default one - https://github.com/cryptofuture/ngx_postgres/commit/808389353c88da4e641ef4b3ac6e0193191b4028#diff-2245023265ae4cf87d02c8b6ba991139 From mdounin at mdounin.ru Wed May 4 18:46:47 2016 From: mdounin at mdounin.ru (Maxim Dounin) Date: Wed, 4 May 2016 21:46:47 +0300 Subject: Building ngx_postgres module as dynamic In-Reply-To: <1547cd04196.10e07609a75103.3030697931958292644@hda.me> References: <1547cd04196.10e07609a75103.3030697931958292644@hda.me> Message-ID: <20160504184647.GB36620@mdounin.ru> Hello! On Wed, May 04, 2016 at 07:28:23PM +0200, npyxg1mg2kn7dvk0rl06 wrote: > I have problem with building ngx_postgres module as dynamic module > >/etc/nginx/modules/ngx_postgres.so: undefined symbol: ngx_postgres > https://github.com/cryptofuture/ngx_postgres/blob/808389353c88da4e641ef4b3ac6e0193191b4028/config - config file I used > changes with default one - https://github.com/cryptofuture/ngx_postgres/commit/808389353c88da4e641ef4b3ac6e0193191b4028#diff-2245023265ae4cf87d02c8b6ba991139 For some reason you've used ngx_module_name=ngx_postgres which refers to a non-existing module. Most likely you should use ngx_postgres_module instead, as in HTTP_MODULES="$HTTP_MODULES ngx_postgres_module" in the original config file. -- Maxim Dounin http://nginx.org/ From savetherbtz at gmail.com Thu May 5 01:52:24 2016 From: savetherbtz at gmail.com (Alexey Ivanov) Date: Wed, 4 May 2016 18:52:24 -0700 Subject: [nginx] HTTP/2: rewritten handling of request body. In-Reply-To: References: Message-ID: There is a small issue with setting `SETTINGS_INITIAL_WINDOW_SIZE` to 0: now when client tries to POST data it needs to wait for an additional RTT(between `send HEADERS` and `recv WINDOW_UPDATE`) to start sending data. Here is `nghttp` output: ? ~ echo -n '{}' | nghttp -nv -d - https://www.dropbox.com [ 0.079] Connected The negotiated protocol: h2 [ 0.237] recv SETTINGS frame (niv=3) [SETTINGS_MAX_CONCURRENT_STREAMS(0x03):128] [SETTINGS_INITIAL_WINDOW_SIZE(0x04):0] [SETTINGS_MAX_FRAME_SIZE(0x05):16777215] [ 0.237] recv WINDOW_UPDATE frame (window_size_increment=2147418112) [ 0.237] send SETTINGS frame (niv=2) [SETTINGS_MAX_CONCURRENT_STREAMS(0x03):100] [SETTINGS_INITIAL_WINDOW_SIZE(0x04):65535] [ 0.237] send SETTINGS frame ; ACK (niv=0) [ 0.237] send PRIORITY frame (dep_stream_id=0, weight=201, exclusive=0) [ 0.237] send PRIORITY frame (dep_stream_id=0, weight=101, exclusive=0) [ 0.237] send PRIORITY frame (dep_stream_id=0, weight=1, exclusive=0) [ 0.237] send PRIORITY frame (dep_stream_id=7, weight=1, exclusive=0) [ 0.237] send PRIORITY frame (dep_stream_id=3, weight=1, exclusive=0) [ 0.237] send HEADERS frame ; END_HEADERS | PRIORITY (padlen=0, dep_stream_id=11, weight=16, exclusive=0) ; Open new stream :method: POST :path: / :scheme: https :authority: www.dropbox.com accept: */* accept-encoding: gzip, deflate user-agent: nghttp2/1.9.2 content-length: 2 [ 0.311] recv SETTINGS frame ; ACK (niv=0) [ 0.311] recv WINDOW_UPDATE frame (window_size_increment=2) [ 0.311] send DATA frame [ 0.386] recv WINDOW_UPDATE frame (window_size_increment=2) [ 0.386] send DATA frame ; END_STREAM [ 0.471] recv (stream_id=13) :status: 405 [ 0.471] recv (stream_id=13) server: nginx [ 0.471] recv (stream_id=13) date: Thu, 05 May 2016 00:49:19 GMT [ 0.471] recv (stream_id=13) content-type: text/html [ 0.471] recv (stream_id=13) content-length: 701 [ 0.471] recv (stream_id=13) x-dropbox-request-id: d4215cbcea76766b45b05c6aa4cb4a11 [ 0.471] recv (stream_id=13) strict-transport-security: max-age=15552000; includeSubDomains [ 0.471] recv HEADERS frame ; END_HEADERS (padlen=0) ; First response header [ 0.471] recv DATA frame [ 0.471] recv DATA frame ; END_STREAM [ 0.471] send GOAWAY frame (last_stream_id=0, error_code=NO_ERROR(0x00), opaque_data(0)=[]) Also note that `nghttp` waits for an additional RTT to send `END_STREAM` even though it a zero-length frame, despite that spec does not forbid it: Frames with zero length with the END_STREAM flag set (that is, an empty DATA frame) MAY be sent if there is no available space in either flow-control window. Therefore sending `WINDOW_UPDATE` for exactly `content-length` bytes may not be optimal for some clients. > On Apr 1, 2016, at 5:57 AM, Valentin Bartenev wrote: > > details: http://hg.nginx.org/nginx/rev/887cca40ba6a > branches: > changeset: 6496:887cca40ba6a > user: Valentin Bartenev > date: Fri Apr 01 15:56:03 2016 +0300 > description: > HTTP/2: rewritten handling of request body. > > There are two improvements: > > 1. Support for request body filters; > > 2. Receiving of request body is started only after > the ngx_http_read_client_request_body() call. > > The last one fixes the problem when the client_max_body_size value might not be > respected from the right location if the location was changed either during the > process of receiving body or after the whole body had been received. > > diffstat: > > src/http/ngx_http_request.h | 3 + > src/http/ngx_http_request_body.c | 26 +- > src/http/v2/ngx_http_v2.c | 548 ++++++++++++++++++-------------------- > src/http/v2/ngx_http_v2.h | 7 +- > 4 files changed, 282 insertions(+), 302 deletions(-) > > diffs (768 lines): > > diff -r 92464ebace8e -r 887cca40ba6a src/http/ngx_http_request.h > --- a/src/http/ngx_http_request.h Fri Apr 01 15:56:03 2016 +0300 > +++ b/src/http/ngx_http_request.h Fri Apr 01 15:56:03 2016 +0300 > @@ -284,6 +284,9 @@ typedef struct { > ngx_chain_t *bufs; > ngx_buf_t *buf; > off_t rest; > +#if (NGX_HTTP_V2) > + off_t received; > +#endif > ngx_chain_t *free; > ngx_chain_t *busy; > ngx_http_chunked_t *chunked; > diff -r 92464ebace8e -r 887cca40ba6a src/http/ngx_http_request_body.c > --- a/src/http/ngx_http_request_body.c Fri Apr 01 15:56:03 2016 +0300 > +++ b/src/http/ngx_http_request_body.c Fri Apr 01 15:56:03 2016 +0300 > @@ -40,20 +40,20 @@ ngx_http_read_client_request_body(ngx_ht > > r->main->count++; > > + if (r != r->main || r->request_body || r->discard_body) { > + r->request_body_no_buffering = 0; > + post_handler(r); > + return NGX_OK; > + } > + > #if (NGX_HTTP_V2) > - if (r->stream && r == r->main) { > + if (r->stream) { > r->request_body_no_buffering = 0; > rc = ngx_http_v2_read_request_body(r, post_handler); > goto done; > } > #endif > > - if (r != r->main || r->request_body || r->discard_body) { > - r->request_body_no_buffering = 0; > - post_handler(r); > - return NGX_OK; > - } > - > if (ngx_http_test_expect(r) != NGX_OK) { > rc = NGX_HTTP_INTERNAL_SERVER_ERROR; > goto done; > @@ -503,17 +503,17 @@ ngx_http_discard_request_body(ngx_http_r > ngx_int_t rc; > ngx_event_t *rev; > > + if (r != r->main || r->discard_body || r->request_body) { > + return NGX_OK; > + } > + > #if (NGX_HTTP_V2) > - if (r->stream && r == r->main) { > - r->stream->skip_data = NGX_HTTP_V2_DATA_DISCARD; > + if (r->stream) { > + r->stream->skip_data = 1; > return NGX_OK; > } > #endif > > - if (r != r->main || r->discard_body || r->request_body) { > - return NGX_OK; > - } > - > if (ngx_http_test_expect(r) != NGX_OK) { > return NGX_HTTP_INTERNAL_SERVER_ERROR; > } > diff -r 92464ebace8e -r 887cca40ba6a src/http/v2/ngx_http_v2.c > --- a/src/http/v2/ngx_http_v2.c Fri Apr 01 15:56:03 2016 +0300 > +++ b/src/http/v2/ngx_http_v2.c Fri Apr 01 15:56:03 2016 +0300 > @@ -51,6 +51,8 @@ > #define NGX_HTTP_V2_MAX_WINDOW ((1U << 31) - 1) > #define NGX_HTTP_V2_DEFAULT_WINDOW 65535 > > +#define NGX_HTTP_V2_INITIAL_WINDOW 0 > + > #define NGX_HTTP_V2_ROOT (void *) -1 > > > @@ -163,7 +165,9 @@ static ngx_int_t ngx_http_v2_cookie(ngx_ > ngx_http_v2_header_t *header); > static ngx_int_t ngx_http_v2_construct_cookie_header(ngx_http_request_t *r); > static void ngx_http_v2_run_request(ngx_http_request_t *r); > -static ngx_int_t ngx_http_v2_init_request_body(ngx_http_request_t *r); > +static ngx_int_t ngx_http_v2_process_request_body(ngx_http_request_t *r, > + u_char *pos, size_t size, ngx_uint_t last); > +static ngx_int_t ngx_http_v2_filter_request_body(ngx_http_request_t *r); > static void ngx_http_v2_read_client_request_body_handler(ngx_http_request_t *r); > > static ngx_int_t ngx_http_v2_terminate_stream(ngx_http_v2_connection_t *h2c, > @@ -762,8 +766,7 @@ ngx_http_v2_state_data(ngx_http_v2_conne > if (h2c->state.length == 0) { > ngx_log_error(NGX_LOG_INFO, h2c->connection->log, 0, > "client sent padded DATA frame " > - "with incorrect length: %uz", > - h2c->state.length); > + "with incorrect length: 0"); > > return ngx_http_v2_connection_error(h2c, NGX_HTTP_V2_SIZE_ERROR); > } > @@ -845,8 +848,9 @@ ngx_http_v2_state_data(ngx_http_v2_conne > > stream->recv_window -= h2c->state.length; > > - if (stream->recv_window < NGX_HTTP_V2_MAX_WINDOW / 4) { > - > + if (stream->no_flow_control > + && stream->recv_window < NGX_HTTP_V2_MAX_WINDOW / 4) > + { > if (ngx_http_v2_send_window_update(h2c, node->id, > NGX_HTTP_V2_MAX_WINDOW > - stream->recv_window) > @@ -875,6 +879,8 @@ ngx_http_v2_state_data(ngx_http_v2_conne > return ngx_http_v2_state_skip_padded(h2c, pos, end); > } > > + stream->in_closed = h2c->state.flags & NGX_HTTP_V2_END_STREAM_FLAG; > + > h2c->state.stream = stream; > > return ngx_http_v2_state_read_data(h2c, pos, end); > @@ -885,16 +891,10 @@ static u_char * > ngx_http_v2_state_read_data(ngx_http_v2_connection_t *h2c, u_char *pos, > u_char *end) > { > - size_t size; > - ssize_t n; > - ngx_buf_t *buf; > - ngx_int_t rc; > - ngx_temp_file_t *tf; > - ngx_connection_t *fc; > - ngx_http_request_t *r; > - ngx_http_v2_stream_t *stream; > - ngx_http_request_body_t *rb; > - ngx_http_core_loc_conf_t *clcf; > + size_t size; > + ngx_int_t rc; > + ngx_uint_t last; > + ngx_http_v2_stream_t *stream; > > stream = h2c->state.stream; > > @@ -903,168 +903,42 @@ ngx_http_v2_state_read_data(ngx_http_v2_ > } > > if (stream->skip_data) { > - stream->in_closed = h2c->state.flags & NGX_HTTP_V2_END_STREAM_FLAG; > - > - ngx_log_debug1(NGX_LOG_DEBUG_HTTP, h2c->connection->log, 0, > - "skipping http2 DATA frame, reason: %d", > - stream->skip_data); > + ngx_log_debug0(NGX_LOG_DEBUG_HTTP, h2c->connection->log, 0, > + "skipping http2 DATA frame"); > > return ngx_http_v2_state_skip_padded(h2c, pos, end); > } > > size = end - pos; > > - if (size > h2c->state.length) { > + if (size >= h2c->state.length) { > size = h2c->state.length; > - } > - > - r = stream->request; > - > - if (r->request_body == NULL > - && ngx_http_v2_init_request_body(r) != NGX_OK) > - { > - stream->skip_data = NGX_HTTP_V2_DATA_INTERNAL_ERROR; > - return ngx_http_v2_state_skip_padded(h2c, pos, end); > - } > - > - fc = r->connection; > - rb = r->request_body; > - tf = rb->temp_file; > - buf = rb->buf; > - > - if (size) { > - rb->rest += size; > - > - if (r->headers_in.content_length_n != -1 > - && r->headers_in.content_length_n < rb->rest) > - { > - ngx_log_error(NGX_LOG_INFO, fc->log, 0, > - "client intended to send body data " > - "larger than declared"); > - > - stream->skip_data = NGX_HTTP_V2_DATA_ERROR; > - goto error; > - > - } else { > - clcf = ngx_http_get_module_loc_conf(r, ngx_http_core_module); > - > - if (clcf->client_max_body_size > - && clcf->client_max_body_size < rb->rest) > - { > - ngx_log_error(NGX_LOG_ERR, fc->log, 0, > - "client intended to send " > - "too large chunked body: %O bytes", rb->rest); > - > - stream->skip_data = NGX_HTTP_V2_DATA_ERROR; > - goto error; > - } > - } > - > - h2c->state.length -= size; > - > - if (tf) { > - buf->start = pos; > - buf->pos = pos; > - > - pos += size; > - > - buf->end = pos; > - buf->last = pos; > - > - n = ngx_write_chain_to_temp_file(tf, rb->bufs); > - > - /* TODO: n == 0 or not complete and level event */ > - > - if (n == NGX_ERROR) { > - stream->skip_data = NGX_HTTP_V2_DATA_INTERNAL_ERROR; > - goto error; > - } > - > - tf->offset += n; > - > - } else { > - buf->last = ngx_cpymem(buf->last, pos, size); > - pos += size; > - } > - > - r->request_length += size; > - } > + last = stream->in_closed; > + > + } else { > + last = 0; > + } > + > + rc = ngx_http_v2_process_request_body(stream->request, pos, size, last); > + > + if (rc != NGX_OK) { > + stream->skip_data = 1; > + ngx_http_finalize_request(stream->request, rc); > + } > + > + pos += size; > + h2c->state.length -= size; > > if (h2c->state.length) { > - if (rb->post_handler) { > - clcf = ngx_http_get_module_loc_conf(r, ngx_http_core_module); > - ngx_add_timer(fc->read, clcf->client_body_timeout); > - } > - > return ngx_http_v2_state_save(h2c, pos, end, > ngx_http_v2_state_read_data); > } > > - if (h2c->state.flags & NGX_HTTP_V2_END_STREAM_FLAG) { > - stream->in_closed = 1; > - > - if (r->headers_in.content_length_n < 0) { > - r->headers_in.content_length_n = rb->rest; > - > - } else if (r->headers_in.content_length_n != rb->rest) { > - ngx_log_error(NGX_LOG_INFO, fc->log, 0, > - "client prematurely closed stream: " > - "only %O out of %O bytes of request body received", > - rb->rest, r->headers_in.content_length_n); > - > - stream->skip_data = NGX_HTTP_V2_DATA_ERROR; > - goto error; > - } > - > - if (tf) { > - ngx_memzero(buf, sizeof(ngx_buf_t)); > - > - buf->in_file = 1; > - buf->file_last = tf->file.offset; > - buf->file = &tf->file; > - > - rb->buf = NULL; > - } > - > - if (rb->post_handler) { > - if (fc->read->timer_set) { > - ngx_del_timer(fc->read); > - } > - > - r->read_event_handler = ngx_http_block_reading; > - rb->post_handler(r); > - } > - > - } else if (rb->post_handler) { > - clcf = ngx_http_get_module_loc_conf(r, ngx_http_core_module); > - ngx_add_timer(fc->read, clcf->client_body_timeout); > - } > - > if (h2c->state.padding) { > return ngx_http_v2_state_skip_padded(h2c, pos, end); > } > > return ngx_http_v2_state_complete(h2c, pos, end); > - > -error: > - > - if (rb->post_handler) { > - if (fc->read->timer_set) { > - ngx_del_timer(fc->read); > - } > - > - if (stream->skip_data == NGX_HTTP_V2_DATA_ERROR) { > - rc = (r->headers_in.content_length_n == -1) > - ? NGX_HTTP_REQUEST_ENTITY_TOO_LARGE : NGX_HTTP_BAD_REQUEST; > - > - } else { > - rc = NGX_HTTP_INTERNAL_SERVER_ERROR; > - } > - > - ngx_http_finalize_request(r, rc); > - } > - > - return ngx_http_v2_state_skip_padded(h2c, pos, end); > } > > > @@ -2556,7 +2430,7 @@ ngx_http_v2_send_settings(ngx_http_v2_co > buf->last = ngx_http_v2_write_uint16(buf->last, > NGX_HTTP_V2_INIT_WINDOW_SIZE_SETTING); > buf->last = ngx_http_v2_write_uint32(buf->last, > - NGX_HTTP_V2_MAX_WINDOW); > + NGX_HTTP_V2_INITIAL_WINDOW); > > buf->last = ngx_http_v2_write_uint16(buf->last, > NGX_HTTP_V2_MAX_FRAME_SIZE_SETTING); > @@ -2878,7 +2752,7 @@ ngx_http_v2_create_stream(ngx_http_v2_co > stream->connection = h2c; > > stream->send_window = h2c->init_window; > - stream->recv_window = NGX_HTTP_V2_MAX_WINDOW; > + stream->recv_window = NGX_HTTP_V2_INITIAL_WINDOW; > > h2c->processing++; > > @@ -3515,7 +3389,7 @@ ngx_http_v2_run_request(ngx_http_request > ngx_log_error(NGX_LOG_INFO, r->connection->log, 0, > "client prematurely closed stream"); > > - r->stream->skip_data = NGX_HTTP_V2_DATA_ERROR; > + r->stream->skip_data = 1; > > ngx_http_finalize_request(r, NGX_HTTP_BAD_REQUEST); > return; > @@ -3525,142 +3399,248 @@ ngx_http_v2_run_request(ngx_http_request > } > > > -static ngx_int_t > -ngx_http_v2_init_request_body(ngx_http_request_t *r) > -{ > - ngx_buf_t *buf; > - ngx_temp_file_t *tf; > - ngx_http_request_body_t *rb; > - ngx_http_core_loc_conf_t *clcf; > - > - rb = ngx_pcalloc(r->pool, sizeof(ngx_http_request_body_t)); > - if (rb == NULL) { > - return NGX_ERROR; > - } > - > - r->request_body = rb; > - > - if (r->stream->in_closed) { > - return NGX_OK; > - } > - > - rb->rest = r->headers_in.content_length_n; > - > - clcf = ngx_http_get_module_loc_conf(r, ngx_http_core_module); > - > - if (r->request_body_in_file_only > - || rb->rest > (off_t) clcf->client_body_buffer_size > - || rb->rest < 0) > - { > - tf = ngx_pcalloc(r->pool, sizeof(ngx_temp_file_t)); > - if (tf == NULL) { > - return NGX_ERROR; > - } > - > - tf->file.fd = NGX_INVALID_FILE; > - tf->file.log = r->connection->log; > - tf->path = clcf->client_body_temp_path; > - tf->pool = r->pool; > - tf->warn = "a client request body is buffered to a temporary file"; > - tf->log_level = r->request_body_file_log_level; > - tf->persistent = r->request_body_in_persistent_file; > - tf->clean = r->request_body_in_clean_file; > - > - if (r->request_body_file_group_access) { > - tf->access = 0660; > - } > - > - rb->temp_file = tf; > - > - if (r->stream->in_closed > - && ngx_create_temp_file(&tf->file, tf->path, tf->pool, > - tf->persistent, tf->clean, tf->access) > - != NGX_OK) > - { > - return NGX_ERROR; > - } > - > - buf = ngx_calloc_buf(r->pool); > - if (buf == NULL) { > - return NGX_ERROR; > - } > - > - } else { > - > - if (rb->rest == 0) { > - return NGX_OK; > - } > - > - buf = ngx_create_temp_buf(r->pool, (size_t) rb->rest); > - if (buf == NULL) { > - return NGX_ERROR; > - } > - } > - > - rb->buf = buf; > - > - rb->bufs = ngx_alloc_chain_link(r->pool); > - if (rb->bufs == NULL) { > - return NGX_ERROR; > - } > - > - rb->bufs->buf = buf; > - rb->bufs->next = NULL; > - > - rb->rest = 0; > - > - return NGX_OK; > -} > - > - > ngx_int_t > ngx_http_v2_read_request_body(ngx_http_request_t *r, > ngx_http_client_body_handler_pt post_handler) > { > + off_t len; > ngx_http_v2_stream_t *stream; > + ngx_http_request_body_t *rb; > ngx_http_core_loc_conf_t *clcf; > > - ngx_log_debug0(NGX_LOG_DEBUG_HTTP, r->connection->log, 0, > - "http2 read request body"); > - > stream = r->stream; > > - switch (stream->skip_data) { > - > - case NGX_HTTP_V2_DATA_DISCARD: > + if (stream->skip_data) { > + r->request_body_no_buffering = 0; > post_handler(r); > return NGX_OK; > - > - case NGX_HTTP_V2_DATA_ERROR: > + } > + > + rb = ngx_pcalloc(r->pool, sizeof(ngx_http_request_body_t)); > + if (rb == NULL) { > + return NGX_HTTP_INTERNAL_SERVER_ERROR; > + } > + > + /* > + * set by ngx_pcalloc(): > + * > + * rb->bufs = NULL; > + * rb->buf = NULL; > + * rb->received = 0; > + * rb->free = NULL; > + * rb->busy = NULL; > + */ > + > + rb->rest = 1; > + rb->post_handler = post_handler; > + > + r->request_body = rb; > + > + clcf = ngx_http_get_module_loc_conf(r, ngx_http_core_module); > + > + len = r->headers_in.content_length_n; > + > + if (len >= 0 && len <= (off_t) clcf->client_body_buffer_size > + && !r->request_body_in_file_only) > + { > + rb->buf = ngx_create_temp_buf(r->pool, (size_t) len); > + > + } else { > + rb->buf = ngx_calloc_buf(r->pool); > + > + if (rb->buf != NULL) { > + rb->buf->sync = 1; > + } > + } > + > + if (rb->buf == NULL) { > + return NGX_HTTP_INTERNAL_SERVER_ERROR; > + } > + > + if (stream->in_closed) { > + return ngx_http_v2_process_request_body(r, NULL, 0, 1); > + } > + > + stream->no_flow_control = 1; > + > + stream->recv_window = NGX_HTTP_V2_MAX_WINDOW; > + > + if (ngx_http_v2_send_window_update(stream->connection, stream->node->id, > + stream->recv_window) > + == NGX_ERROR) > + { > + return NGX_HTTP_INTERNAL_SERVER_ERROR; > + } > + > + ngx_add_timer(r->connection->read, clcf->client_body_timeout); > + > + r->read_event_handler = ngx_http_v2_read_client_request_body_handler; > + r->write_event_handler = ngx_http_request_empty_handler; > + > + return NGX_AGAIN; > +} > + > + > +static ngx_int_t > +ngx_http_v2_process_request_body(ngx_http_request_t *r, u_char *pos, > + size_t size, ngx_uint_t last) > +{ > + ngx_buf_t *buf; > + ngx_int_t rc; > + ngx_connection_t *fc; > + ngx_http_request_body_t *rb; > + ngx_http_core_loc_conf_t *clcf; > + > + rb = r->request_body; > + > + if (rb == NULL) { > + return NGX_OK; > + } > + > + fc = r->connection; > + buf = rb->buf; > + > + if (size) { > + if (buf->sync) { > + buf->pos = buf->start = pos; > + buf->last = buf->end = pos + size; > + > + } else { > + if (size > (size_t) (buf->end - buf->last)) { > + ngx_log_error(NGX_LOG_INFO, fc->log, 0, > + "client intended to send body data " > + "larger than declared"); > + > + return NGX_HTTP_BAD_REQUEST; > + } > + > + buf->last = ngx_cpymem(buf->last, pos, size); > + } > + } > + > + if (last) { > + rb->rest = 0; > + > + if (fc->read->timer_set) { > + ngx_del_timer(fc->read); > + } > + > + rc = ngx_http_v2_filter_request_body(r); > + > + if (rc != NGX_OK) { > + return rc; > + } > + > + if (buf->sync) { > + /* prevent reusing this buffer in the upstream module */ > + rb->buf = NULL; > + } > + > if (r->headers_in.content_length_n == -1) { > - return NGX_HTTP_REQUEST_ENTITY_TOO_LARGE; > + r->headers_in.content_length_n = rb->received; > + } > + > + r->read_event_handler = ngx_http_block_reading; > + rb->post_handler(r); > + > + return NGX_OK; > + } > + > + if (size == 0) { > + return NGX_OK; > + } > + > + clcf = ngx_http_get_module_loc_conf(r, ngx_http_core_module); > + ngx_add_timer(fc->read, clcf->client_body_timeout); > + > + if (buf->sync) { > + return ngx_http_v2_filter_request_body(r); > + } > + > + return NGX_OK; > +} > + > + > +static ngx_int_t > +ngx_http_v2_filter_request_body(ngx_http_request_t *r) > +{ > + ngx_buf_t *b, *buf; > + ngx_int_t rc; > + ngx_chain_t *cl; > + ngx_http_request_body_t *rb; > + ngx_http_core_loc_conf_t *clcf; > + > + rb = r->request_body; > + buf = rb->buf; > + > + cl = ngx_chain_get_free_buf(r->pool, &rb->free); > + if (cl == NULL) { > + return NGX_HTTP_INTERNAL_SERVER_ERROR; > + } > + > + b = cl->buf; > + > + ngx_memzero(b, sizeof(ngx_buf_t)); > + > + if (buf->pos != buf->last) { > + r->request_length += buf->last - buf->pos; > + rb->received += buf->last - buf->pos; > + > + if (r->headers_in.content_length_n != -1) { > + if (rb->received > r->headers_in.content_length_n) { > + ngx_log_error(NGX_LOG_INFO, r->connection->log, 0, > + "client intended to send body data " > + "larger than declared"); > + > + return NGX_HTTP_BAD_REQUEST; > + } > + > } else { > + clcf = ngx_http_get_module_loc_conf(r, ngx_http_core_module); > + > + if (clcf->client_max_body_size > + && rb->received > clcf->client_max_body_size) > + { > + ngx_log_error(NGX_LOG_ERR, r->connection->log, 0, > + "client intended to send too large chunked body: " > + "%O bytes", rb->received); > + > + return NGX_HTTP_REQUEST_ENTITY_TOO_LARGE; > + } > + } > + > + b->temporary = 1; > + b->pos = buf->pos; > + b->last = buf->last; > + b->start = b->pos; > + b->end = b->last; > + > + buf->pos = buf->last; > + } > + > + if (!rb->rest) { > + if (r->headers_in.content_length_n != -1 > + && r->headers_in.content_length_n != rb->received) > + { > + ngx_log_error(NGX_LOG_INFO, r->connection->log, 0, > + "client prematurely closed stream: " > + "only %O out of %O bytes of request body received", > + rb->received, r->headers_in.content_length_n); > + > return NGX_HTTP_BAD_REQUEST; > } > > - case NGX_HTTP_V2_DATA_INTERNAL_ERROR: > - return NGX_HTTP_INTERNAL_SERVER_ERROR; > - } > - > - if (!r->request_body && ngx_http_v2_init_request_body(r) != NGX_OK) { > - stream->skip_data = NGX_HTTP_V2_DATA_INTERNAL_ERROR; > - return NGX_HTTP_INTERNAL_SERVER_ERROR; > - } > - > - if (stream->in_closed) { > - post_handler(r); > - return NGX_OK; > - } > - > - r->request_body->post_handler = post_handler; > - > - r->read_event_handler = ngx_http_v2_read_client_request_body_handler; > - r->write_event_handler = ngx_http_request_empty_handler; > - > - clcf = ngx_http_get_module_loc_conf(r, ngx_http_core_module); > - ngx_add_timer(r->connection->read, clcf->client_body_timeout); > - > - return NGX_AGAIN; > + b->last_buf = 1; > + } > + > + b->tag = (ngx_buf_tag_t) &ngx_http_v2_filter_request_body; > + > + rc = ngx_http_top_request_body_filter(r, cl); > + > + ngx_chain_update_chains(r->pool, &rb->free, &rb->busy, &cl, > + (ngx_buf_tag_t) &ngx_http_v2_filter_request_body); > + > + return rc; > } > > > @@ -3678,7 +3658,7 @@ ngx_http_v2_read_client_request_body_han > ngx_log_error(NGX_LOG_INFO, fc->log, NGX_ETIMEDOUT, "client timed out"); > > fc->timedout = 1; > - r->stream->skip_data = NGX_HTTP_V2_DATA_DISCARD; > + r->stream->skip_data = 1; > > ngx_http_finalize_request(r, NGX_HTTP_REQUEST_TIME_OUT); > return; > @@ -3688,7 +3668,7 @@ ngx_http_v2_read_client_request_body_han > ngx_log_error(NGX_LOG_INFO, fc->log, 0, > "client prematurely closed stream"); > > - r->stream->skip_data = NGX_HTTP_V2_DATA_DISCARD; > + r->stream->skip_data = 1; > > ngx_http_finalize_request(r, NGX_HTTP_CLIENT_CLOSED_REQUEST); > return; > diff -r 92464ebace8e -r 887cca40ba6a src/http/v2/ngx_http_v2.h > --- a/src/http/v2/ngx_http_v2.h Fri Apr 01 15:56:03 2016 +0300 > +++ b/src/http/v2/ngx_http_v2.h Fri Apr 01 15:56:03 2016 +0300 > @@ -24,10 +24,6 @@ > #define NGX_HTTP_V2_MAX_FIELD \ > (127 + (1 << (NGX_HTTP_V2_INT_OCTETS - 1) * 7) - 1) > > -#define NGX_HTTP_V2_DATA_DISCARD 1 > -#define NGX_HTTP_V2_DATA_ERROR 2 > -#define NGX_HTTP_V2_DATA_INTERNAL_ERROR 3 > - > #define NGX_HTTP_V2_FRAME_HEADER_SIZE 9 > > /* frame types */ > @@ -195,7 +191,8 @@ struct ngx_http_v2_stream_s { > unsigned in_closed:1; > unsigned out_closed:1; > unsigned rst_sent:1; > - unsigned skip_data:2; > + unsigned no_flow_control:1; > + unsigned skip_data:1; > }; > > > > _______________________________________________ > nginx-devel mailing list > nginx-devel at nginx.org > http://mailman.nginx.org/mailman/listinfo/nginx-devel -------------- next part -------------- A non-text attachment was scrubbed... Name: signature.asc Type: application/pgp-signature Size: 842 bytes Desc: Message signed with OpenPGP using GPGMail URL: From vbart at nginx.com Thu May 5 13:41:34 2016 From: vbart at nginx.com (Valentin V. Bartenev) Date: Thu, 05 May 2016 16:41:34 +0300 Subject: [nginx] HTTP/2: rewritten handling of request body. In-Reply-To: References: Message-ID: <4230052.v1InuH4Yg1@vbart-workstation> On Wednesday 04 May 2016 18:52:24 Alexey Ivanov wrote: > There is a small issue with setting `SETTINGS_INITIAL_WINDOW_SIZE` to 0: now when client tries to POST data it needs to wait for an additional RTT(between `send HEADERS` and `recv WINDOW_UPDATE`) to start sending data. > [..] Yes, while it's not optimal from the latency point of view, such approach simplified implementation a lot. So it's a fair price, that was paid at the current stage of HTTP/2 implementation. Introducing some kind of preread buffer will the next step. > > Also note that `nghttp` waits for an additional RTT to send `END_STREAM` even though it a zero-length frame, despite that spec does not forbid it: > > Frames with zero length with the END_STREAM flag set (that is, an empty DATA frame) MAY be sent if there is no available space in either flow-control window. > > Therefore sending `WINDOW_UPDATE` for exactly `content-length` bytes may not be optimal for some clients. It would be better to report this issue to nghttp, instead of making a workaround in nginx. There can be an implementation that even don't send another WINDOW_UPDATE in this case. wbr, Valentin V. Bartenev From hda at hda.me Thu May 5 15:01:34 2016 From: hda at hda.me (npyxg1mg2kn7dvk0rl06) Date: Thu, 05 May 2016 17:01:34 +0200 Subject: Building ngx_postgres module as dynamic Message-ID: <15481703268.b01610d4114943.8677690893956982850@hda.me> On Wed, May 4, 2016, at 01:46 PM, Maxim Dounin wrote: > Hello! > > On Wed, May 04, 2016 at 07:28:23PM +0200, npyxg1mg2kn7dvk0rl06 wrote: > > > I have problem with building ngx_postgres module as dynamic module > > >/etc/nginx/modules/ngx_postgres.so: undefined symbol: ngx_postgres > > https://github.com/cryptofuture/ngx_postgres/blob/808389353c88da4e641ef4b3ac6e0193191b4028/config - config file I used > > changes with default one - https://github.com/cryptofuture/ngx_postgres/commit/808389353c88da4e641ef4b3ac6e0193191b4028#diff-2245023265ae4cf87d02c8b6ba991139 > > For some reason you've used > > ngx_module_name=ngx_postgres > > which refers to a non-existing module. Most likely you should use > ngx_postgres_module instead, as in > > HTTP_MODULES="$HTTP_MODULES ngx_postgres_module" > > in the original config file. > > -- > Maxim Dounin > http://nginx.org/ > > _______________________________________________ > nginx-devel mailing list > nginx-devel at nginx.org > http://mailman.nginx.org/mailman/listinfo/nginx-devel > I made appropriative changes and now I have undefined symbol: PQsendQuery on module loading. Not sure if PQsendQuery even should be linked. https://github.com/cryptofuture/ngx_postgres - repo with changes, in case someone will be charitable enough to look into. Also I discussed making module dynamic with dev, but looks like he just waiting for incoming pull requests. From hongzhidao at gmail.com Thu May 5 15:54:26 2016 From: hongzhidao at gmail.com (=?UTF-8?B?5rSq5b+X6YGT?=) Date: Thu, 5 May 2016 23:54:26 +0800 Subject: Monitoring nginx metrics Message-ID: Hi, Recently I upgrade nginx and wrote a module for monitoring response metrics. It?s simple but handy and useful. Maybe the nginx can support more informations like stub status module. https://github.com/hongzhidao/nginx-http-metric-module Regards. -------------- next part -------------- An HTML attachment was scrubbed... URL: From ahutchings at nginx.com Thu May 5 15:56:03 2016 From: ahutchings at nginx.com (Andrew Hutchings) Date: Thu, 5 May 2016 16:56:03 +0100 Subject: Building ngx_postgres module as dynamic In-Reply-To: <15481703268.b01610d4114943.8677690893956982850@hda.me> References: <15481703268.b01610d4114943.8677690893956982850@hda.me> Message-ID: <4b26cca4-e53b-7371-2c66-8ae447fdbbde@nginx.com> Hi, On 05/05/16 16:01, npyxg1mg2kn7dvk0rl06 wrote: > I made appropriative changes and now I have undefined symbol: PQsendQuery on module loading. Not sure if PQsendQuery even should be linked. > https://github.com/cryptofuture/ngx_postgres - repo with changes, in case someone will be charitable enough to look into. > Also I discussed making module dynamic with dev, but looks like he just waiting for incoming pull requests. Judging by a quick look at your work the problem appears to be that you are linking NGINX against libpq instead of the module. Kind Regards -- Andrew Hutchings (LinuxJedi) Technical Product Manager, NGINX Inc. From me+lists.nginx at tomthorogood.co.uk Sun May 8 10:27:06 2016 From: me+lists.nginx at tomthorogood.co.uk (Tom Thorogood) Date: Sun, 08 May 2016 19:57:06 +0930 Subject: [PATCH] HTTP: NGINX_VER_BUILD in Server header and error page tail. Message-ID: <1462703226.1314805.601366873.679532C0@webmail.messagingengine.com> Hi, This patch adds a build option to the server_tokens directive. When build is specified the Server header will have a value of NGINX_VER_BUILD. Also the tail of built in error pages will be NGINX_VER_BUILD. off and on are retained as valid values and behave as they always have. This makes it possible to specify semi-custom server tokens of the form "nginx/ ()". is specified with the --build flag for ./configure. A potential use case is including the name of a custom build for example with --build="super-nginx/0.1". This would give: nginx/1.9.15 (super-nginx/0.1). Another potential use case of this feature is to include the git revision of a parent build with --build="`git rev-parse --short HEAD`". This would give: nginx/1.9.15 (c3ebabd). In that case the feature can be used to enhance troubleshooting and/or provide more information to end users. Kind Regards, Tom Thorogood. -------------- next part -------------- A non-text attachment was scrubbed... Name: nginx-server-token-build.patch Type: text/x-patch Size: 10965 bytes Desc: not available URL: From du_nan at aol.com Sun May 8 12:15:53 2016 From: du_nan at aol.com (=?iso-2022-jp?B?GyRCRU5EeEZvGyhC?=) Date: Sun, 8 May 2016 20:15:53 +0800 Subject: nginx Message-ID: ??????? From alessandro at cloudflare.com Wed May 11 12:24:44 2016 From: alessandro at cloudflare.com (Alessandro Ghedini) Date: Wed, 11 May 2016 13:24:44 +0100 Subject: [PATCH] SSL: DH was made opaque in OpenSSL 1.1.0 Message-ID: # HG changeset patch # User Alessandro Ghedini # Date 1462967148 -3600 # Wed May 11 12:45:48 2016 +0100 # Node ID f3413937fddaaca954090e26cf92b49fdf2f9722 # Parent 2f98b5709d7965e7c97cb74b8380014179c7bf0d SSL: DH was made opaque in OpenSSL 1.1.0 DH_set0_pqg() was introduced to initialize the DH parameters. diff -r 2f98b5709d79 -r f3413937fdda src/event/ngx_event_openssl.c --- a/src/event/ngx_event_openssl.c Thu Apr 28 16:30:19 2016 +0300 +++ b/src/event/ngx_event_openssl.c Wed May 11 12:45:48 2016 +0100 @@ -915,8 +915,9 @@ ngx_ssl_passwords_cleanup(void *data) ngx_int_t ngx_ssl_dhparam(ngx_conf_t *cf, ngx_ssl_t *ssl, ngx_str_t *file) { - DH *dh; - BIO *bio; + DH *dh; + BIO *bio; + BIGNUM *p, *g; /* * -----BEGIN DH PARAMETERS----- @@ -951,15 +952,24 @@ ngx_ssl_dhparam(ngx_conf_t *cf, ngx_ssl_ return NGX_ERROR; } - dh->p = BN_bin2bn(dh1024_p, sizeof(dh1024_p), NULL); - dh->g = BN_bin2bn(dh1024_g, sizeof(dh1024_g), NULL); - - if (dh->p == NULL || dh->g == NULL) { + p = BN_bin2bn(dh1024_p, sizeof(dh1024_p), NULL); + g = BN_bin2bn(dh1024_g, sizeof(dh1024_g), NULL); + + if (p == NULL || g == NULL) { ngx_ssl_error(NGX_LOG_EMERG, ssl->log, 0, "BN_bin2bn() failed"); + BN_free(p); + BN_free(g); DH_free(dh); return NGX_ERROR; } +#if OPENSSL_VERSION_NUMBER >= 0x10100005L + DH_set0_pqg(dh, p, NULL, g); +#else + dh->p = p; + dh->g = g; +#endif + SSL_CTX_set_tmp_dh(ssl->ctx, dh); DH_free(dh); From mdounin at mdounin.ru Wed May 11 12:40:37 2016 From: mdounin at mdounin.ru (Maxim Dounin) Date: Wed, 11 May 2016 15:40:37 +0300 Subject: [PATCH] SSL: DH was made opaque in OpenSSL 1.1.0 In-Reply-To: References: Message-ID: <20160511124037.GO36620@mdounin.ru> Hello! On Wed, May 11, 2016 at 01:24:44PM +0100, Alessandro Ghedini wrote: > # HG changeset patch > # User Alessandro Ghedini > # Date 1462967148 -3600 > # Wed May 11 12:45:48 2016 +0100 > # Node ID f3413937fddaaca954090e26cf92b49fdf2f9722 > # Parent 2f98b5709d7965e7c97cb74b8380014179c7bf0d > SSL: DH was made opaque in OpenSSL 1.1.0 > > DH_set0_pqg() was introduced to initialize the DH parameters. No, thanks. See https://trac.nginx.org/nginx/ticket/860#comment:8 for details. -- Maxim Dounin http://nginx.org/ From alessandro at cloudflare.com Wed May 11 13:37:57 2016 From: alessandro at cloudflare.com (Alessandro Ghedini) Date: Wed, 11 May 2016 14:37:57 +0100 Subject: [PATCH] SSL: DH was made opaque in OpenSSL 1.1.0 In-Reply-To: <20160511124037.GO36620@mdounin.ru> References: <20160511124037.GO36620@mdounin.ru> Message-ID: <20160511133757.GA4502@mandy.local> On Wed, May 11, 2016 at 03:40:37PM +0300, Maxim Dounin wrote: > Hello! > > On Wed, May 11, 2016 at 01:24:44PM +0100, Alessandro Ghedini wrote: > > > # HG changeset patch > > # User Alessandro Ghedini > > # Date 1462967148 -3600 > > # Wed May 11 12:45:48 2016 +0100 > > # Node ID f3413937fddaaca954090e26cf92b49fdf2f9722 > > # Parent 2f98b5709d7965e7c97cb74b8380014179c7bf0d > > SSL: DH was made opaque in OpenSSL 1.1.0 > > > > DH_set0_pqg() was introduced to initialize the DH parameters. > > No, thanks. > See https://trac.nginx.org/nginx/ticket/860#comment:8 for details. Ok, thanks. Agree that DH should be removed, any ETA on that? I'm just trying to make ngx_lua build with OpenSSL master (but I can just patch NGINX locally for now). Cheers From mdounin at mdounin.ru Wed May 11 14:10:20 2016 From: mdounin at mdounin.ru (Maxim Dounin) Date: Wed, 11 May 2016 17:10:20 +0300 Subject: [PATCH] SSL: DH was made opaque in OpenSSL 1.1.0 In-Reply-To: <20160511133757.GA4502@mandy.local> References: <20160511124037.GO36620@mdounin.ru> <20160511133757.GA4502@mandy.local> Message-ID: <20160511141020.GP36620@mdounin.ru> Hello! On Wed, May 11, 2016 at 02:37:57PM +0100, Alessandro Ghedini wrote: > On Wed, May 11, 2016 at 03:40:37PM +0300, Maxim Dounin wrote: > > Hello! > > > > On Wed, May 11, 2016 at 01:24:44PM +0100, Alessandro Ghedini wrote: > > > > > # HG changeset patch > > > # User Alessandro Ghedini > > > # Date 1462967148 -3600 > > > # Wed May 11 12:45:48 2016 +0100 > > > # Node ID f3413937fddaaca954090e26cf92b49fdf2f9722 > > > # Parent 2f98b5709d7965e7c97cb74b8380014179c7bf0d > > > SSL: DH was made opaque in OpenSSL 1.1.0 > > > > > > DH_set0_pqg() was introduced to initialize the DH parameters. > > > > No, thanks. > > See https://trac.nginx.org/nginx/ticket/860#comment:8 for details. > > Ok, thanks. Agree that DH should be removed, any ETA on that? I'm just trying > to make ngx_lua build with OpenSSL master (but I can just patch NGINX locally > for now). A patch series which, in particular, removes compiled-in DH parameters, is currently under review. It's expected to be committed in a week or so. -- Maxim Dounin http://nginx.org/ From vbart at nginx.com Wed May 11 15:01:15 2016 From: vbart at nginx.com (Valentin Bartenev) Date: Wed, 11 May 2016 15:01:15 +0000 Subject: [nginx] Core: fixed port handling in ngx_parse_inet6_url(). Message-ID: details: http://hg.nginx.org/nginx/rev/b358d670c654 branches: changeset: 6533:b358d670c654 user: Valentin Bartenev date: Wed May 11 17:55:20 2016 +0300 description: Core: fixed port handling in ngx_parse_inet6_url(). This fixes buffer over-read when no port is specified in cases similar to 5df5d7d771f6, and catches missing port separator. diffstat: src/core/ngx_inet.c | 7 ++++++- 1 files changed, 6 insertions(+), 1 deletions(-) diffs (17 lines): diff -r 2f98b5709d79 -r b358d670c654 src/core/ngx_inet.c --- a/src/core/ngx_inet.c Thu Apr 28 16:30:19 2016 +0300 +++ b/src/core/ngx_inet.c Wed May 11 17:55:20 2016 +0300 @@ -861,7 +861,12 @@ ngx_parse_inet6_url(ngx_pool_t *pool, ng last = uri; } - if (*port == ':') { + if (port < last) { + if (*port != ':') { + u->err = "invalid host"; + return NGX_ERROR; + } + port++; len = last - port; From vbart at nginx.com Wed May 11 15:01:18 2016 From: vbart at nginx.com (Valentin Bartenev) Date: Wed, 11 May 2016 15:01:18 +0000 Subject: [nginx] Removed a surplus condition from ngx_parse_inet6_url(). Message-ID: details: http://hg.nginx.org/nginx/rev/19a54ba76c04 branches: changeset: 6534:19a54ba76c04 user: Ruslan Ermilov date: Wed May 11 17:55:30 2016 +0300 description: Removed a surplus condition from ngx_parse_inet6_url(). No functional changes, since the condition was always true. diffstat: src/core/ngx_inet.c | 67 +++++++++++++++++++++++++--------------------------- 1 files changed, 32 insertions(+), 35 deletions(-) diffs (88 lines): diff -r b358d670c654 -r 19a54ba76c04 src/core/ngx_inet.c --- a/src/core/ngx_inet.c Wed May 11 17:55:20 2016 +0300 +++ b/src/core/ngx_inet.c Wed May 11 17:55:30 2016 +0300 @@ -843,52 +843,49 @@ ngx_parse_inet6_url(ngx_pool_t *pool, ng return NGX_ERROR; } - if (last - p) { + port = p + 1; - port = p + 1; + uri = ngx_strlchr(port, last, '/'); - uri = ngx_strlchr(port, last, '/'); - - if (uri) { - if (u->listen || !u->uri_part) { - u->err = "invalid host"; - return NGX_ERROR; - } - - u->uri.len = last - uri; - u->uri.data = uri; - - last = uri; + if (uri) { + if (u->listen || !u->uri_part) { + u->err = "invalid host"; + return NGX_ERROR; } - if (port < last) { - if (*port != ':') { - u->err = "invalid host"; - return NGX_ERROR; - } + u->uri.len = last - uri; + u->uri.data = uri; - port++; + last = uri; + } - len = last - port; + if (port < last) { + if (*port != ':') { + u->err = "invalid host"; + return NGX_ERROR; + } - n = ngx_atoi(port, len); + port++; - if (n < 1 || n > 65535) { - u->err = "invalid port"; - return NGX_ERROR; - } + len = last - port; - u->port = (in_port_t) n; - sin6->sin6_port = htons((in_port_t) n); + n = ngx_atoi(port, len); - u->port_text.len = len; - u->port_text.data = port; + if (n < 1 || n > 65535) { + u->err = "invalid port"; + return NGX_ERROR; + } - } else { - u->no_port = 1; - u->port = u->default_port; - sin6->sin6_port = htons(u->default_port); - } + u->port = (in_port_t) n; + sin6->sin6_port = htons((in_port_t) n); + + u->port_text.len = len; + u->port_text.data = port; + + } else { + u->no_port = 1; + u->port = u->default_port; + sin6->sin6_port = htons(u->default_port); } len = p - host; From rmind at noxt.eu Wed May 11 15:44:33 2016 From: rmind at noxt.eu (Mindaugas Rasiukevicius) Date: Wed, 11 May 2016 16:44:33 +0100 Subject: Fixing ngx_http_slice_module use with named locations In-Reply-To: <20160504142030.bfda7a14d949ef6536604db0@noxt.eu> References: <20160504142030.bfda7a14d949ef6536604db0@noxt.eu> Message-ID: <20160511164433.8aba8bbc1194466eabb69f91@noxt.eu> Hi, To illustrate the fix I mentioned -- please find the patches attached. Thanks. -- Mindaugas -------------- next part -------------- An embedded and charset-unspecified text was scrubbed... Name: slice.patch URL: -------------- next part -------------- An embedded and charset-unspecified text was scrubbed... Name: slice-test.patch URL: From xeioex at nginx.com Thu May 12 13:45:13 2016 From: xeioex at nginx.com (Dmitry Volyntsev) Date: Thu, 12 May 2016 13:45:13 +0000 Subject: [nginx] Map: support of complex values in resulting strings. Message-ID: details: http://hg.nginx.org/nginx/rev/db699978a33f branches: changeset: 6535:db699978a33f user: Dmitry Volyntsev date: Thu May 12 16:43:19 2016 +0300 description: Map: support of complex values in resulting strings. diffstat: src/http/modules/ngx_http_map_module.c | 126 +++++++++++++++++--------------- 1 files changed, 67 insertions(+), 59 deletions(-) diffs (195 lines): diff -r 19a54ba76c04 -r db699978a33f src/http/modules/ngx_http_map_module.c --- a/src/http/modules/ngx_http_map_module.c Wed May 11 17:55:30 2016 +0300 +++ b/src/http/modules/ngx_http_map_module.c Thu May 12 16:43:19 2016 +0300 @@ -20,7 +20,6 @@ typedef struct { ngx_hash_keys_arrays_t keys; ngx_array_t *values_hash; - ngx_array_t var_values; #if (NGX_PCRE) ngx_array_t regexes; #endif @@ -110,7 +109,8 @@ ngx_http_map_variable(ngx_http_request_t { ngx_http_map_ctx_t *map = (ngx_http_map_ctx_t *) data; - ngx_str_t val; + ngx_str_t val, str; + ngx_http_complex_value_t *cv; ngx_http_variable_value_t *value; ngx_log_debug0(NGX_LOG_DEBUG_HTTP, r->connection->log, 0, @@ -131,15 +131,22 @@ ngx_http_map_variable(ngx_http_request_t } if (!value->valid) { - value = ngx_http_get_flushed_variable(r, (uintptr_t) value->data); + cv = (ngx_http_complex_value_t *) value->data; - if (value == NULL || value->not_found) { - value = &ngx_http_variable_null_value; + if (ngx_http_complex_value(r, cv, &str) != NGX_OK) { + return NGX_ERROR; } + + v->valid = 1; + v->no_cacheable = 0; + v->not_found = 0; + v->len = str.len; + v->data = str.data; + + } else { + *v = *value; } - *v = *value; - ngx_log_debug2(NGX_LOG_DEBUG_HTTP, r->connection->log, 0, "http map: \"%V\" \"%v\"", &val, v); @@ -246,14 +253,6 @@ ngx_http_map_block(ngx_conf_t *cf, ngx_c return NGX_CONF_ERROR; } - if (ngx_array_init(&ctx.var_values, cf->pool, 2, - sizeof(ngx_http_variable_value_t)) - != NGX_OK) - { - ngx_destroy_pool(pool); - return NGX_CONF_ERROR; - } - #if (NGX_PCRE) if (ngx_array_init(&ctx.regexes, cf->pool, 2, sizeof(ngx_http_map_regex_t)) != NGX_OK) @@ -375,11 +374,15 @@ ngx_http_map_cmp_dns_wildcards(const voi static char * ngx_http_map(ngx_conf_t *cf, ngx_command_t *dummy, void *conf) { - ngx_int_t rv, index; - ngx_str_t *value, name; - ngx_uint_t i, key; - ngx_http_map_conf_ctx_t *ctx; - ngx_http_variable_value_t *var, **vp; + u_char *data; + size_t len; + ngx_int_t rv; + ngx_str_t *value, v; + ngx_uint_t i, key; + ngx_http_map_conf_ctx_t *ctx; + ngx_http_complex_value_t cv, *cvp; + ngx_http_variable_value_t *var, **vp; + ngx_http_compile_complex_value_t ccv; ctx = cf->ctx; @@ -401,39 +404,6 @@ ngx_http_map(ngx_conf_t *cf, ngx_command return ngx_conf_include(cf, dummy, conf); } - if (value[1].data[0] == '$') { - name = value[1]; - name.len--; - name.data++; - - index = ngx_http_get_variable_index(ctx->cf, &name); - if (index == NGX_ERROR) { - return NGX_CONF_ERROR; - } - - var = ctx->var_values.elts; - - for (i = 0; i < ctx->var_values.nelts; i++) { - if (index == (intptr_t) var[i].data) { - var = &var[i]; - goto found; - } - } - - var = ngx_array_push(&ctx->var_values); - if (var == NULL) { - return NGX_CONF_ERROR; - } - - var->valid = 0; - var->no_cacheable = 0; - var->not_found = 0; - var->len = 0; - var->data = (u_char *) (intptr_t) index; - - goto found; - } - key = 0; for (i = 0; i < value[1].len; i++) { @@ -446,11 +416,22 @@ ngx_http_map(ngx_conf_t *cf, ngx_command if (vp) { for (i = 0; i < ctx->values_hash[key].nelts; i++) { - if (value[1].len != (size_t) vp[i]->len) { + + if (vp[i]->valid) { + data = vp[i]->data; + len = vp[i]->len; + + } else { + cvp = (ngx_http_complex_value_t *) vp[i]->data; + data = cvp->value.data; + len = cvp->value.len; + } + + if (value[1].len != len) { continue; } - if (ngx_strncmp(value[1].data, vp[i]->data, value[1].len) == 0) { + if (ngx_strncmp(value[1].data, data, len) == 0) { var = vp[i]; goto found; } @@ -470,13 +451,40 @@ ngx_http_map(ngx_conf_t *cf, ngx_command return NGX_CONF_ERROR; } - var->len = value[1].len; - var->data = ngx_pstrdup(ctx->keys.pool, &value[1]); - if (var->data == NULL) { + v.len = value[1].len; + v.data = ngx_pstrdup(ctx->keys.pool, &value[1]); + if (v.data == NULL) { return NGX_CONF_ERROR; } - var->valid = 1; + ngx_memzero(&ccv, sizeof(ngx_http_compile_complex_value_t)); + + ccv.cf = ctx->cf; + ccv.value = &v; + ccv.complex_value = &cv; + + if (ngx_http_compile_complex_value(&ccv) != NGX_OK) { + return NGX_CONF_ERROR; + } + + if (cv.lengths != NULL) { + cvp = ngx_palloc(ctx->keys.pool, sizeof(ngx_http_complex_value_t)); + if (cvp == NULL) { + return NGX_CONF_ERROR; + } + + *cvp = cv; + + var->len = 0; + var->data = (u_char *) cvp; + var->valid = 0; + + } else { + var->len = v.len; + var->data = v.data; + var->valid = 1; + } + var->no_cacheable = 0; var->not_found = 0; From vadim.v.panov at gmail.com Fri May 13 05:04:40 2016 From: vadim.v.panov at gmail.com (Vadim Panov) Date: Fri, 13 May 2016 13:04:40 +0800 Subject: Patch for http proxying bug with some old gcc. Message-ID: Hi Guys, Could you please review and consider including the attached patch. It fixes a bug which is only created by some gcc's, you will understand looking at it. I reproduce using nginx with openwrt on marvell platform, so I can't tell what else might be affected. How it works. upstream do something like this for(;;) { still some data something->handle_header(some data) } and proxying module changes value of handle_header to some new function inside handle_header. if we have enough data to still stay in this loop some gcc would call a wrong pointer. (this bug is floating as if data goes in slow we exit this for loop) Proposed patch only fixes consequences as it is not an upstream bug, it is a gcc bug. If there would be some trick adding volatile keyword the resulting code would be too fragile to stay cross compilable and cross platform. So checking one pointer seems a reasonable price to pay considering some gcc can do this with a loop and using this kind of loop to read remaining data is a very common pattern is the project design. regards -------------- next part -------------- An HTML attachment was scrubbed... URL: -------------- next part -------------- # HG changeset patch # User Vadim Panov # Date 1463114406 -28800 # Fri May 13 12:40:06 2016 +0800 # Node ID 66f5e8d930f7b51dea90ebda5aa90dcf7fa6fff9 # Parent db699978a33fe19d786e95e00143eb2b6a1662c0 fix http proxying on version compiled with some old gcc's diff -r db699978a33f -r 66f5e8d930f7 src/http/modules/ngx_http_proxy_module.c --- a/src/http/modules/ngx_http_proxy_module.c Thu May 12 16:43:19 2016 +0300 +++ b/src/http/modules/ngx_http_proxy_module.c Fri May 13 12:40:06 2016 +0800 @@ -1686,6 +1686,15 @@ u = r->upstream; + /* Pointer to this function seems get cached in a calling loop with + some gcc versions. Even this function change the pointer in the end, + the caller may still call this function instead of a new one */ + if (u->process_header != ngx_http_proxy_process_status_line) { + ngx_log_debug0(NGX_LOG_DEBUG_HTTP, r->connection->log, 0, + "http proxy: wrong cached u->process_header call"); + return u->process_header(r); + } + rc = ngx_http_parse_status_line(r, &u->buffer, &ctx->status); if (rc == NGX_AGAIN) { From mdounin at mdounin.ru Fri May 13 12:53:20 2016 From: mdounin at mdounin.ru (Maxim Dounin) Date: Fri, 13 May 2016 15:53:20 +0300 Subject: Patch for http proxying bug with some old gcc. In-Reply-To: References: Message-ID: <20160513125320.GU36620@mdounin.ru> Hello! On Fri, May 13, 2016 at 01:04:40PM +0800, Vadim Panov wrote: > Hi Guys, > > Could you please review and consider including the attached patch. It fixes > a bug which is only created by some gcc's, you will understand looking at > it. > > I reproduce using nginx with openwrt on marvell platform, so I can't tell > what else might be affected. > > How it works. > upstream do something like this > for(;;) { > still some data > something->handle_header(some data) > } > and proxying module changes value of handle_header to some new function > inside handle_header. if we have enough data to still stay in this loop > some gcc would call a wrong pointer. (this bug is floating as if data goes > in slow we exit this for loop) > > Proposed patch only fixes consequences as it is not an upstream bug, it is > a gcc bug. If there would be some trick adding volatile keyword the > resulting code would be too fragile to stay cross compilable and cross > platform. So checking one pointer seems a reasonable price to pay > considering some gcc can do this with a loop and using this kind of loop to > read remaining data is a very common pattern is the project design. > > regards > # HG changeset patch > # User Vadim Panov > # Date 1463114406 -28800 > # Fri May 13 12:40:06 2016 +0800 > # Node ID 66f5e8d930f7b51dea90ebda5aa90dcf7fa6fff9 > # Parent db699978a33fe19d786e95e00143eb2b6a1662c0 > fix http proxying on version compiled with some old gcc's > > diff -r db699978a33f -r 66f5e8d930f7 src/http/modules/ngx_http_proxy_module.c > --- a/src/http/modules/ngx_http_proxy_module.c Thu May 12 16:43:19 2016 +0300 > +++ b/src/http/modules/ngx_http_proxy_module.c Fri May 13 12:40:06 2016 +0800 > @@ -1686,6 +1686,15 @@ > > u = r->upstream; > > + /* Pointer to this function seems get cached in a calling loop with > + some gcc versions. Even this function change the pointer in the end, > + the caller may still call this function instead of a new one */ > + if (u->process_header != ngx_http_proxy_process_status_line) { > + ngx_log_debug0(NGX_LOG_DEBUG_HTTP, r->connection->log, 0, > + "http proxy: wrong cached u->process_header call"); > + return u->process_header(r); > + } > + > rc = ngx_http_parse_status_line(r, &u->buffer, &ctx->status); > > if (rc == NGX_AGAIN) { It looks like you are talking about the problem as observed by some on Raspberry Pi with GCC 4.9, see https://trac.nginx.org/nginx/ticket/748 https://trac.nginx.org/nginx/ticket/912 Given it's a compiler bug, and it's not eliminated by the change, but rather worked around in a way affecting other platforms as well, I don't think this patch should be considered. Rather, I would recommend to avoid using -O2 on the affected platforms, but use -O1 as nginx does by default. As per reports, it works just fine. Alternatively, you can consider upgrading to a newer GCC version. -- Maxim Dounin http://nginx.org/ From vbart at nginx.com Fri May 13 14:21:22 2016 From: vbart at nginx.com (Valentin Bartenev) Date: Fri, 13 May 2016 14:21:22 +0000 Subject: [nginx] Improved EPOLLRDHUP handling. Message-ID: details: http://hg.nginx.org/nginx/rev/f7849bfb6d21 branches: changeset: 6536:f7849bfb6d21 user: Valentin Bartenev date: Fri May 13 17:19:23 2016 +0300 description: Improved EPOLLRDHUP handling. When it's known that the kernel supports EPOLLRDHUP, there is no need in additional recv() call to get EOF or error when the flag is absent in the event generated by the kernel. A special runtime test is done at startup to detect if EPOLLRDHUP is actually supported by the kernel because epoll_ctl() silently ignores unknown flags. With this knowledge it's now possible to drop the "ready" flag for partial read. Previously, the "ready" flag was kept until the recv() returned EOF or error. In particular, this change allows the lingering close heuristics (which relies on the "ready" flag state) to actually work on Linux, and not wait for more data in most cases. The "available" flag is now used in the read event with the semantics similar to the corresponding counter in kqueue. diffstat: src/event/modules/ngx_epoll_module.c | 72 +++++++++++++++++++++++++++++++++++- src/event/ngx_event.h | 7 +++ src/http/ngx_http_request.c | 6 ++- src/http/ngx_http_upstream.c | 6 ++- src/os/unix/ngx_readv_chain.c | 32 ++++++++++++++++ src/os/unix/ngx_recv.c | 33 ++++++++++++++++ 6 files changed, 153 insertions(+), 3 deletions(-) diffs (269 lines): diff -r db699978a33f -r f7849bfb6d21 src/event/modules/ngx_epoll_module.c --- a/src/event/modules/ngx_epoll_module.c Thu May 12 16:43:19 2016 +0300 +++ b/src/event/modules/ngx_epoll_module.c Fri May 13 17:19:23 2016 +0300 @@ -123,6 +123,7 @@ static ngx_int_t ngx_epoll_process_event static void ngx_epoll_eventfd_handler(ngx_event_t *ev); #endif +static ngx_int_t ngx_epoll_module_init(ngx_cycle_t *cycle); static void *ngx_epoll_create_conf(ngx_cycle_t *cycle); static char *ngx_epoll_init_conf(ngx_cycle_t *cycle, void *conf); @@ -146,6 +147,10 @@ static ngx_connection_t ngx_eventfd_ #endif +#if (NGX_HAVE_EPOLLRDHUP) +ngx_uint_t ngx_use_epoll_rdhup; +#endif + static ngx_str_t epoll_name = ngx_string("epoll"); static ngx_command_t ngx_epoll_commands[] = { @@ -197,7 +202,7 @@ ngx_module_t ngx_epoll_module = { ngx_epoll_commands, /* module directives */ NGX_EVENT_MODULE, /* module type */ NULL, /* init master */ - NULL, /* init module */ + ngx_epoll_module_init, /* init module */ NULL, /* init process */ NULL, /* init thread */ NULL, /* exit thread */ @@ -808,6 +813,8 @@ ngx_epoll_process_events(ngx_cycle_t *cy if (revents & EPOLLRDHUP) { rev->pending_eof = 1; } + + rev->available = 1; #endif rev->ready = 1; @@ -943,6 +950,69 @@ ngx_epoll_eventfd_handler(ngx_event_t *e #endif +static ngx_int_t +ngx_epoll_module_init(ngx_cycle_t *cycle) +{ +#if (NGX_HAVE_EPOLLRDHUP) + int epfd, s[2], events; + struct epoll_event ee; + + epfd = epoll_create(1); + + if (epfd == -1) { + ngx_log_error(NGX_LOG_ALERT, cycle->log, ngx_errno, + "epoll_create() failed"); + return NGX_ERROR; + } + + if (socketpair(AF_UNIX, SOCK_STREAM, 0, s) == -1) { + ngx_log_error(NGX_LOG_ALERT, cycle->log, ngx_errno, + "socketpair() failed"); + return NGX_ERROR; + } + + ee.events = EPOLLET|EPOLLIN|EPOLLRDHUP; + + if (epoll_ctl(epfd, EPOLL_CTL_ADD, s[0], &ee) == -1) { + ngx_log_error(NGX_LOG_ALERT, cycle->log, ngx_errno, + "epoll_ctl() failed"); + return NGX_ERROR; + } + + if (close(s[1]) == -1) { + ngx_log_error(NGX_LOG_ALERT, cycle->log, ngx_errno, + "close() failed"); + return NGX_ERROR; + } + + events = epoll_wait(epfd, &ee, 1, 5000); + + if (events == -1) { + ngx_log_error(NGX_LOG_ALERT, cycle->log, ngx_errno, + "epoll_wait() failed"); + return NGX_ERROR; + } + + (void) close(s[0]); + (void) close(epfd); + + if (events) { + ngx_use_epoll_rdhup = ee.events & EPOLLRDHUP; + + } else { + ngx_log_error(NGX_LOG_ALERT, cycle->log, ngx_errno, + "epoll_wait() timedout"); + } + + ngx_log_error(NGX_LOG_NOTICE, cycle->log, 0, + "testing the EPOLLRDHUP flag: %s", + ngx_use_epoll_rdhup ? "success" : "fail"); +#endif + + return NGX_OK; +} + + static void * ngx_epoll_create_conf(ngx_cycle_t *cycle) { diff -r db699978a33f -r f7849bfb6d21 src/event/ngx_event.h --- a/src/event/ngx_event.h Thu May 12 16:43:19 2016 +0300 +++ b/src/event/ngx_event.h Fri May 13 17:19:23 2016 +0300 @@ -96,6 +96,10 @@ struct ngx_event_s { * write: available space in buffer when event is ready * or lowat when event is set with NGX_LOWAT_EVENT flag * + * epoll with EPOLLRDHUP: + * accept: 1 if accept many, 0 otherwise + * read: 1 if there can be data to read, 0 otherwise + * * iocp: TODO * * otherwise: @@ -196,6 +200,9 @@ typedef struct { extern ngx_event_actions_t ngx_event_actions; +#if (NGX_HAVE_EPOLLRDHUP) +extern ngx_uint_t ngx_use_epoll_rdhup; +#endif /* diff -r db699978a33f -r f7849bfb6d21 src/http/ngx_http_request.c --- a/src/http/ngx_http_request.c Thu May 12 16:43:19 2016 +0300 +++ b/src/http/ngx_http_request.c Fri May 13 17:19:23 2016 +0300 @@ -2752,9 +2752,13 @@ ngx_http_test_reading(ngx_http_request_t #if (NGX_HAVE_EPOLLRDHUP) - if ((ngx_event_flags & NGX_USE_EPOLL_EVENT) && rev->pending_eof) { + if ((ngx_event_flags & NGX_USE_EPOLL_EVENT) && ngx_use_epoll_rdhup) { socklen_t len; + if (!rev->pending_eof) { + return; + } + rev->eof = 1; c->error = 1; diff -r db699978a33f -r f7849bfb6d21 src/http/ngx_http_upstream.c --- a/src/http/ngx_http_upstream.c Thu May 12 16:43:19 2016 +0300 +++ b/src/http/ngx_http_upstream.c Fri May 13 17:19:23 2016 +0300 @@ -1222,9 +1222,13 @@ ngx_http_upstream_check_broken_connectio #if (NGX_HAVE_EPOLLRDHUP) - if ((ngx_event_flags & NGX_USE_EPOLL_EVENT) && ev->pending_eof) { + if ((ngx_event_flags & NGX_USE_EPOLL_EVENT) && ngx_use_epoll_rdhup) { socklen_t len; + if (!ev->pending_eof) { + return; + } + ev->eof = 1; c->error = 1; diff -r db699978a33f -r f7849bfb6d21 src/os/unix/ngx_readv_chain.c --- a/src/os/unix/ngx_readv_chain.c Thu May 12 16:43:19 2016 +0300 +++ b/src/os/unix/ngx_readv_chain.c Fri May 13 17:19:23 2016 +0300 @@ -53,6 +53,20 @@ ngx_readv_chain(ngx_connection_t *c, ngx #endif +#if (NGX_HAVE_EPOLLRDHUP) + + if (ngx_event_flags & NGX_USE_EPOLL_EVENT) { + ngx_log_debug2(NGX_LOG_DEBUG_EVENT, c->log, 0, + "readv: eof:%d, avail:%d", + rev->pending_eof, rev->available); + + if (!rev->available && !rev->pending_eof) { + return NGX_AGAIN; + } + } + +#endif + prev = NULL; iov = NULL; size = 0; @@ -151,6 +165,24 @@ ngx_readv_chain(ngx_connection_t *c, ngx #endif +#if (NGX_HAVE_EPOLLRDHUP) + + if ((ngx_event_flags & NGX_USE_EPOLL_EVENT) + && ngx_use_epoll_rdhup) + { + if (n < size) { + if (!rev->pending_eof) { + rev->ready = 0; + } + + rev->available = 0; + } + + return n; + } + +#endif + if (n < size && !(ngx_event_flags & NGX_USE_GREEDY_EVENT)) { rev->ready = 0; } diff -r db699978a33f -r f7849bfb6d21 src/os/unix/ngx_recv.c --- a/src/os/unix/ngx_recv.c Thu May 12 16:43:19 2016 +0300 +++ b/src/os/unix/ngx_recv.c Fri May 13 17:19:23 2016 +0300 @@ -50,6 +50,21 @@ ngx_unix_recv(ngx_connection_t *c, u_cha #endif +#if (NGX_HAVE_EPOLLRDHUP) + + if (ngx_event_flags & NGX_USE_EPOLL_EVENT) { + ngx_log_debug2(NGX_LOG_DEBUG_EVENT, c->log, 0, + "recv: eof:%d, avail:%d", + rev->pending_eof, rev->available); + + if (!rev->available && !rev->pending_eof) { + rev->ready = 0; + return NGX_AGAIN; + } + } + +#endif + do { n = recv(c->fd, buf, size, 0); @@ -101,6 +116,24 @@ ngx_unix_recv(ngx_connection_t *c, u_cha #endif +#if (NGX_HAVE_EPOLLRDHUP) + + if ((ngx_event_flags & NGX_USE_EPOLL_EVENT) + && ngx_use_epoll_rdhup) + { + if ((size_t) n < size) { + if (!rev->pending_eof) { + rev->ready = 0; + } + + rev->available = 0; + } + + return n; + } + +#endif + if ((size_t) n < size && !(ngx_event_flags & NGX_USE_GREEDY_EVENT)) { From bblack at wikimedia.org Sat May 14 15:22:33 2016 From: bblack at wikimedia.org (Brandon Black) Date: Sat, 14 May 2016 15:22:33 +0000 Subject: Multiple certificate support revisited In-Reply-To: References: Message-ID: On Tue, Aug 18, 2015 at 2:31 PM, Brandon Black wrote: > Hi all, > > The Wikimedia Foundation has been running nginx-1.9.3 patched for > multi-certificate support for all production TLS traffic for a few > weeks now without incident, for all inbound requests to Wikipedia and > other associated projects of the Foundation. [... http://mailman.nginx.org/pipermail/nginx-devel/2015-August/007225.html for full text] Bump! We're still running these patches for all Wikimedia sites (including Wikipedia) to serve dual ECDSA+RSA certificates. There was some feedback from some of the original author(s) privately back at the time of my last post on this in Aug 2015, but no real progress on making newer/better patches and no upstream feedback from nginx.org AFAIK so far. We had stalled out on nginx version updates at Wikimedia for a while. We stalled at 1.9.4 for months due to the SPDY-v-HTTP2 switch and real-world client support stats, etc. Eventually the stats on the switch got better as we approached the May 15 Chrome SPDY cutoff ( https://phabricator.wikimedia.org/T96848#2251633 ). On May 4th, we made the switch to nginx-1.10.0 with HTTP/2 support in place of SPDY, and thus we've now also published updated dual-cert patches. So for anyone who's still pulling in these patches manually, the correct diffs against 1.10.0 are now available as the 100x series at: https://github.com/wikimedia/operations-software-nginx/tree/wmf-1.10.0-1/debian/patches . These patches have been working fine for us functionally on a very large traffic site with a very broad mix of client UAs, with external OCSP Stapling files, for several months. I'd still like to get a conversation going on how we can get this support merged into upstream nginx, perhaps during 1.11.x? What is this patch series missing in terms of feature support, code quality, etc, to get into a mergeable state? Thanks, -- Brandon Black Sr Operations Engineer Wikimedia Foundation From fdasilvayy at gmail.com Sat May 14 22:20:36 2016 From: fdasilvayy at gmail.com (F. DA SILVA) Date: Sun, 15 May 2016 00:20:36 +0200 Subject: Multiple certificate support revisited In-Reply-To: References: Message-ID: Hi, Brandon. Shorten (by myself) answer from nginx guys , i received at beginning of May: "...(this) is work in process already, ... hope it will be finished in May." Regards, FDS >> Le 14 mai 2016 ? 17:22, Brandon Black a ?crit : >> >> On Tue, Aug 18, 2015 at 2:31 PM, Brandon Black wrote: >> Hi all, >> >> The Wikimedia Foundation has been running nginx-1.9.3 patched for >> multi-certificate support for all production TLS traffic for a few >> weeks now without incident, for all inbound requests to Wikipedia and >> other associated projects of the Foundation. > > [... http://mailman.nginx.org/pipermail/nginx-devel/2015-August/007225.html > for full text] > > Bump! > > We're still running these patches for all Wikimedia sites (including > Wikipedia) to serve dual ECDSA+RSA certificates. There was some > feedback from some of the original author(s) privately back at the > time of my last post on this in Aug 2015, but no real progress on > making newer/better patches and no upstream feedback from nginx.org > AFAIK so far. > > We had stalled out on nginx version updates at Wikimedia for a while. > We stalled at 1.9.4 for months due to the SPDY-v-HTTP2 switch and > real-world client support stats, etc. Eventually the stats on the > switch got better as we approached the May 15 Chrome SPDY cutoff ( > https://phabricator.wikimedia.org/T96848#2251633 ). On May 4th, we > made the switch to nginx-1.10.0 with HTTP/2 support in place of SPDY, > and thus we've now also published updated dual-cert patches. > > So for anyone who's still pulling in these patches manually, the > correct diffs against 1.10.0 are now available as the 100x series at: > https://github.com/wikimedia/operations-software-nginx/tree/wmf-1.10.0-1/debian/patches > . > > These patches have been working fine for us functionally on a very > large traffic site with a very broad mix of client UAs, with external > OCSP Stapling files, for several months. I'd still like to get a > conversation going on how we can get this support merged into upstream > nginx, perhaps during 1.11.x? What is this patch series missing in > terms of feature support, code quality, etc, to get into a mergeable > state? > > Thanks, > -- Brandon Black > Sr Operations Engineer > Wikimedia Foundation > > _______________________________________________ > nginx-devel mailing list > nginx-devel at nginx.org > http://mailman.nginx.org/mailman/listinfo/nginx-devel From mdounin at mdounin.ru Sun May 15 02:06:42 2016 From: mdounin at mdounin.ru (Maxim Dounin) Date: Sun, 15 May 2016 05:06:42 +0300 Subject: Multiple certificate support revisited In-Reply-To: References: Message-ID: <20160515020642.GY36620@mdounin.ru> Hello! On Sat, May 14, 2016 at 03:22:33PM +0000, Brandon Black wrote: > On Tue, Aug 18, 2015 at 2:31 PM, Brandon Black wrote: > > Hi all, > > > > The Wikimedia Foundation has been running nginx-1.9.3 patched for > > multi-certificate support for all production TLS traffic for a few > > weeks now without incident, for all inbound requests to Wikipedia and > > other associated projects of the Foundation. > > [... http://mailman.nginx.org/pipermail/nginx-devel/2015-August/007225.html > for full text] > > Bump! > > We're still running these patches for all Wikimedia sites (including > Wikipedia) to serve dual ECDSA+RSA certificates. There was some > feedback from some of the original author(s) privately back at the > time of my last post on this in Aug 2015, but no real progress on > making newer/better patches and no upstream feedback from nginx.org > AFAIK so far. Patch series to implement multiple certificates support is currently under review and is expected to be committed in a week or so. Just in case you are interested, you can find it attached. -- Maxim Dounin http://nginx.org/ -------------- next part -------------- # HG changeset patch # User Maxim Dounin # Date 1463277750 -10800 # Sun May 15 05:02:30 2016 +0300 # Node ID c88a894246015f7d7b65061785546eb368458722 # Parent db699978a33fe19d786e95e00143eb2b6a1662c0 OCSP stapling: staple provided in arguments. 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 @@ -84,10 +84,11 @@ struct ngx_ssl_ocsp_ctx_s { static ngx_int_t ngx_ssl_stapling_file(ngx_conf_t *cf, ngx_ssl_t *ssl, - ngx_str_t *file); -static ngx_int_t ngx_ssl_stapling_issuer(ngx_conf_t *cf, ngx_ssl_t *ssl); + ngx_ssl_stapling_t *staple, ngx_str_t *file); +static ngx_int_t ngx_ssl_stapling_issuer(ngx_conf_t *cf, ngx_ssl_t *ssl, + ngx_ssl_stapling_t *staple); static ngx_int_t ngx_ssl_stapling_responder(ngx_conf_t *cf, ngx_ssl_t *ssl, - ngx_str_t *responder); + ngx_ssl_stapling_t *staple, ngx_str_t *responder); static int ngx_ssl_certificate_status_callback(ngx_ssl_conn_t *ssl_conn, void *data); @@ -153,14 +154,14 @@ ngx_ssl_stapling(ngx_conf_t *cf, ngx_ssl if (file->len) { /* use OCSP response from the file */ - if (ngx_ssl_stapling_file(cf, ssl, file) != NGX_OK) { + if (ngx_ssl_stapling_file(cf, ssl, staple, file) != NGX_OK) { return NGX_ERROR; } goto done; } - rc = ngx_ssl_stapling_issuer(cf, ssl); + rc = ngx_ssl_stapling_issuer(cf, ssl, staple); if (rc == NGX_DECLINED) { return NGX_OK; @@ -170,7 +171,7 @@ ngx_ssl_stapling(ngx_conf_t *cf, ngx_ssl return NGX_ERROR; } - rc = ngx_ssl_stapling_responder(cf, ssl, responder); + rc = ngx_ssl_stapling_responder(cf, ssl, staple, responder); if (rc == NGX_DECLINED) { return NGX_OK; @@ -190,15 +191,13 @@ done: static ngx_int_t -ngx_ssl_stapling_file(ngx_conf_t *cf, ngx_ssl_t *ssl, ngx_str_t *file) +ngx_ssl_stapling_file(ngx_conf_t *cf, ngx_ssl_t *ssl, + ngx_ssl_stapling_t *staple, ngx_str_t *file) { BIO *bio; int len; u_char *p, *buf; OCSP_RESPONSE *response; - ngx_ssl_stapling_t *staple; - - staple = SSL_CTX_get_ex_data(ssl->ctx, ngx_ssl_stapling_index); if (ngx_conf_full_name(cf->cycle, file, 1) != NGX_OK) { return NGX_ERROR; @@ -259,16 +258,15 @@ failed: static ngx_int_t -ngx_ssl_stapling_issuer(ngx_conf_t *cf, ngx_ssl_t *ssl) +ngx_ssl_stapling_issuer(ngx_conf_t *cf, ngx_ssl_t *ssl, + ngx_ssl_stapling_t *staple) { int i, n, rc; X509 *cert, *issuer; X509_STORE *store; X509_STORE_CTX *store_ctx; STACK_OF(X509) *chain; - ngx_ssl_stapling_t *staple; - staple = SSL_CTX_get_ex_data(ssl->ctx, ngx_ssl_stapling_index); cert = SSL_CTX_get_ex_data(ssl->ctx, ngx_ssl_certificate_index); #if OPENSSL_VERSION_NUMBER >= 0x10001000L @@ -351,15 +349,13 @@ ngx_ssl_stapling_issuer(ngx_conf_t *cf, static ngx_int_t -ngx_ssl_stapling_responder(ngx_conf_t *cf, ngx_ssl_t *ssl, ngx_str_t *responder) +ngx_ssl_stapling_responder(ngx_conf_t *cf, ngx_ssl_t *ssl, + ngx_ssl_stapling_t *staple, ngx_str_t *responder) { ngx_url_t u; char *s; - ngx_ssl_stapling_t *staple; STACK_OF(OPENSSL_STRING) *aia; - staple = SSL_CTX_get_ex_data(ssl->ctx, ngx_ssl_stapling_index); - if (responder->len == 0) { /* extract OCSP responder URL from certificate */ # HG changeset patch # User Maxim Dounin # Date 1463277750 -10800 # Sun May 15 05:02:30 2016 +0300 # Node ID 0d2a0c36111ecb8744928f51f54a125f8e3f7776 # Parent c88a894246015f7d7b65061785546eb368458722 OCSP stapling: staple now stored in certificate, not context. diff --git a/src/event/ngx_event_openssl.c b/src/event/ngx_event_openssl.c --- a/src/event/ngx_event_openssl.c +++ b/src/event/ngx_event_openssl.c @@ -187,11 +187,10 @@ ngx_ssl_init(ngx_log_t *log) return NGX_ERROR; } - ngx_ssl_stapling_index = SSL_CTX_get_ex_new_index(0, NULL, NULL, NULL, - NULL); + ngx_ssl_stapling_index = X509_get_ex_new_index(0, NULL, NULL, NULL, NULL); + if (ngx_ssl_stapling_index == -1) { - ngx_ssl_error(NGX_LOG_ALERT, log, 0, - "SSL_CTX_get_ex_new_index() failed"); + ngx_ssl_error(NGX_LOG_ALERT, log, 0, "X509_get_ex_new_index() failed"); return NGX_ERROR; } 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 @@ -122,6 +122,7 @@ 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) { + X509 *cert; ngx_int_t rc; ngx_pool_cleanup_t *cln; ngx_ssl_stapling_t *staple; @@ -139,17 +140,17 @@ ngx_ssl_stapling(ngx_conf_t *cf, ngx_ssl cln->handler = ngx_ssl_stapling_cleanup; cln->data = staple; - if (SSL_CTX_set_ex_data(ssl->ctx, ngx_ssl_stapling_index, staple) - == 0) - { - ngx_ssl_error(NGX_LOG_EMERG, ssl->log, 0, - "SSL_CTX_set_ex_data() failed"); + cert = SSL_CTX_get_ex_data(ssl->ctx, ngx_ssl_certificate_index); + + if (X509_set_ex_data(cert, ngx_ssl_stapling_index, staple) == 0) { + ngx_ssl_error(NGX_LOG_EMERG, ssl->log, 0, "X509_set_ex_data() failed"); return NGX_ERROR; } staple->ssl_ctx = ssl->ctx; staple->timeout = 60000; staple->verify = verify; + staple->cert = cert; if (file->len) { /* use OCSP response from the file */ @@ -267,7 +268,7 @@ ngx_ssl_stapling_issuer(ngx_conf_t *cf, X509_STORE_CTX *store_ctx; STACK_OF(X509) *chain; - cert = SSL_CTX_get_ex_data(ssl->ctx, ngx_ssl_certificate_index); + cert = staple->cert; #if OPENSSL_VERSION_NUMBER >= 0x10001000L SSL_CTX_get_extra_chain_certs(ssl->ctx, &chain); @@ -292,7 +293,6 @@ ngx_ssl_stapling_issuer(ngx_conf_t *cf, ngx_log_debug1(NGX_LOG_DEBUG_EVENT, ssl->log, 0, "SSL get issuer: found %p in extra certs", issuer); - staple->cert = cert; staple->issuer = issuer; return NGX_OK; @@ -341,7 +341,6 @@ ngx_ssl_stapling_issuer(ngx_conf_t *cf, ngx_log_debug1(NGX_LOG_DEBUG_EVENT, ssl->log, 0, "SSL get issuer: found %p in cert store", issuer); - staple->cert = cert; staple->issuer = issuer; return NGX_OK; @@ -439,9 +438,11 @@ ngx_int_t ngx_ssl_stapling_resolver(ngx_conf_t *cf, ngx_ssl_t *ssl, ngx_resolver_t *resolver, ngx_msec_t resolver_timeout) { + X509 *cert; ngx_ssl_stapling_t *staple; - staple = SSL_CTX_get_ex_data(ssl->ctx, ngx_ssl_stapling_index); + cert = SSL_CTX_get_ex_data(ssl->ctx, ngx_ssl_certificate_index); + staple = X509_get_ex_data(cert, ngx_ssl_stapling_index); staple->resolver = resolver; staple->resolver_timeout = resolver_timeout; # HG changeset patch # User Maxim Dounin # Date 1463277750 -10800 # Sun May 15 05:02:30 2016 +0300 # Node ID 62bce4509292f04a8ddb24e4049cddc32996a57c # Parent 0d2a0c36111ecb8744928f51f54a125f8e3f7776 OCSP stapling: staple now extracted via SSL_get_certificate(). This makes it possible to properly return OCSP staple with multiple certificates configured. Note that it only works properly in OpenSSL 1.0.1d+, 1.0.0k, 0.9.8y+. In older versions SSL_get_certificate() fails to return correct certificate when the certificate status callback is called. 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 @@ -185,7 +185,6 @@ ngx_ssl_stapling(ngx_conf_t *cf, ngx_ssl done: SSL_CTX_set_tlsext_status_cb(ssl->ctx, ngx_ssl_certificate_status_callback); - SSL_CTX_set_tlsext_status_arg(ssl->ctx, staple); return NGX_OK; } @@ -455,6 +454,7 @@ static int ngx_ssl_certificate_status_callback(ngx_ssl_conn_t *ssl_conn, void *data) { int rc; + X509 *cert; u_char *p; ngx_connection_t *c; ngx_ssl_stapling_t *staple; @@ -464,9 +464,15 @@ ngx_ssl_certificate_status_callback(ngx_ ngx_log_debug0(NGX_LOG_DEBUG_EVENT, c->log, 0, "SSL certificate status callback"); - staple = data; rc = SSL_TLSEXT_ERR_NOACK; + cert = SSL_get_certificate(ssl_conn); + staple = X509_get_ex_data(cert, ngx_ssl_stapling_index); + + if (staple == NULL) { + return rc; + } + if (staple->staple.len && staple->valid >= ngx_time()) { # HG changeset patch # User Maxim Dounin # Date 1463277750 -10800 # Sun May 15 05:02:30 2016 +0300 # Node ID f18ad0ff562839070121aa05544cec089715ba0e # Parent 62bce4509292f04a8ddb24e4049cddc32996a57c OCSP stapling: additional function to configure stapling on a cert. 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 @@ -83,6 +83,8 @@ struct ngx_ssl_ocsp_ctx_s { }; +static ngx_int_t ngx_ssl_stapling_certificate(ngx_conf_t *cf, ngx_ssl_t *ssl, + X509 *cert, ngx_str_t *file, ngx_str_t *responder, ngx_uint_t verify); static ngx_int_t ngx_ssl_stapling_file(ngx_conf_t *cf, ngx_ssl_t *ssl, ngx_ssl_stapling_t *staple, ngx_str_t *file); static ngx_int_t ngx_ssl_stapling_issuer(ngx_conf_t *cf, ngx_ssl_t *ssl, @@ -122,10 +124,29 @@ 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) { - X509 *cert; - ngx_int_t rc; - ngx_pool_cleanup_t *cln; - ngx_ssl_stapling_t *staple; + X509 *cert; + + cert = SSL_CTX_get_ex_data(ssl->ctx, ngx_ssl_certificate_index); + + if (ngx_ssl_stapling_certificate(cf, ssl, cert, file, responder, verify) + != NGX_OK) + { + return NGX_ERROR; + } + + SSL_CTX_set_tlsext_status_cb(ssl->ctx, ngx_ssl_certificate_status_callback); + + return NGX_OK; +} + + +static ngx_int_t +ngx_ssl_stapling_certificate(ngx_conf_t *cf, ngx_ssl_t *ssl, X509 *cert, + ngx_str_t *file, ngx_str_t *responder, ngx_uint_t verify) +{ + ngx_int_t rc; + ngx_pool_cleanup_t *cln; + ngx_ssl_stapling_t *staple; staple = ngx_pcalloc(cf->pool, sizeof(ngx_ssl_stapling_t)); if (staple == NULL) { @@ -140,8 +161,6 @@ ngx_ssl_stapling(ngx_conf_t *cf, ngx_ssl cln->handler = ngx_ssl_stapling_cleanup; cln->data = staple; - cert = SSL_CTX_get_ex_data(ssl->ctx, ngx_ssl_certificate_index); - if (X509_set_ex_data(cert, ngx_ssl_stapling_index, staple) == 0) { ngx_ssl_error(NGX_LOG_EMERG, ssl->log, 0, "X509_set_ex_data() failed"); return NGX_ERROR; @@ -159,7 +178,7 @@ ngx_ssl_stapling(ngx_conf_t *cf, ngx_ssl return NGX_ERROR; } - goto done; + return NGX_OK; } rc = ngx_ssl_stapling_issuer(cf, ssl, staple); @@ -182,10 +201,6 @@ ngx_ssl_stapling(ngx_conf_t *cf, ngx_ssl return NGX_ERROR; } -done: - - SSL_CTX_set_tlsext_status_cb(ssl->ctx, ngx_ssl_certificate_status_callback); - return NGX_OK; } # HG changeset patch # User Maxim Dounin # Date 1463277750 -10800 # Sun May 15 05:02:30 2016 +0300 # Node ID 61522cf7ee72270ad214df45c9802fa89ef14339 # Parent f18ad0ff562839070121aa05544cec089715ba0e SSL: made it possible to iterate though all certificates. A pointer to a previously configured certificate now stored in a certificate, this makes it possible iterate though all certificates configured in the SSL context. This is now used to configure OCSP stapling on all certificates, and in ngx_ssl_session_id_context(). Note that in OpenSSL 1.0.2+ this can be done without storing things in exdata using the SSL_CTX_set_current_cert() and SSL_CTX_get0_certificate() functions. These are not yet available in all supported versions though, so it's easier to continue to use exdata for now. diff --git a/src/event/ngx_event_openssl.c b/src/event/ngx_event_openssl.c --- a/src/event/ngx_event_openssl.c +++ b/src/event/ngx_event_openssl.c @@ -105,6 +105,7 @@ int ngx_ssl_server_conf_index; int ngx_ssl_session_cache_index; int ngx_ssl_session_ticket_keys_index; int ngx_ssl_certificate_index; +int ngx_ssl_next_certificate_index; int ngx_ssl_stapling_index; @@ -187,6 +188,13 @@ ngx_ssl_init(ngx_log_t *log) return NGX_ERROR; } + ngx_ssl_next_certificate_index = X509_get_ex_new_index(0, NULL, NULL, NULL, + NULL); + if (ngx_ssl_next_certificate_index == -1) { + ngx_ssl_error(NGX_LOG_ALERT, log, 0, "X509_get_ex_new_index() failed"); + return NGX_ERROR; + } + ngx_ssl_stapling_index = X509_get_ex_new_index(0, NULL, NULL, NULL, NULL); if (ngx_ssl_stapling_index == -1) { @@ -214,6 +222,12 @@ ngx_ssl_create(ngx_ssl_t *ssl, ngx_uint_ return NGX_ERROR; } + if (SSL_CTX_set_ex_data(ssl->ctx, ngx_ssl_certificate_index, NULL) == 0) { + ngx_ssl_error(NGX_LOG_EMERG, ssl->log, 0, + "SSL_CTX_set_ex_data() failed"); + return NGX_ERROR; + } + ssl->buffer_size = NGX_SSL_BUFSIZE; /* client side options */ @@ -350,6 +364,16 @@ ngx_ssl_certificate(ngx_conf_t *cf, ngx_ return NGX_ERROR; } + if (X509_set_ex_data(x509, ngx_ssl_next_certificate_index, + SSL_CTX_get_ex_data(ssl->ctx, ngx_ssl_certificate_index)) + == 0) + { + ngx_ssl_error(NGX_LOG_EMERG, ssl->log, 0, "X509_set_ex_data() failed"); + X509_free(x509); + BIO_free(bio); + return NGX_ERROR; + } + if (SSL_CTX_set_ex_data(ssl->ctx, ngx_ssl_certificate_index, x509) == 0) { @@ -2163,7 +2187,7 @@ ngx_ssl_session_id_context(ngx_ssl_t *ss /* * Session ID context is set based on the string provided, - * the server certificate, and the client CA list. + * the server certificates, and the client CA list. */ md = EVP_MD_CTX_create(); @@ -2183,18 +2207,21 @@ ngx_ssl_session_id_context(ngx_ssl_t *ss goto failed; } - cert = SSL_CTX_get_ex_data(ssl->ctx, ngx_ssl_certificate_index); - - if (X509_digest(cert, EVP_sha1(), buf, &len) == 0) { - ngx_ssl_error(NGX_LOG_EMERG, ssl->log, 0, - "X509_digest() failed"); - goto failed; - } - - if (EVP_DigestUpdate(md, buf, len) == 0) { - ngx_ssl_error(NGX_LOG_EMERG, ssl->log, 0, - "EVP_DigestUpdate() failed"); - goto failed; + 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 (X509_digest(cert, EVP_sha1(), buf, &len) == 0) { + ngx_ssl_error(NGX_LOG_EMERG, ssl->log, 0, + "X509_digest() failed"); + goto failed; + } + + if (EVP_DigestUpdate(md, buf, len) == 0) { + ngx_ssl_error(NGX_LOG_EMERG, ssl->log, 0, + "EVP_DigestUpdate() failed"); + goto failed; + } } list = SSL_CTX_get_client_CA_list(ssl->ctx); 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 @@ -227,6 +227,7 @@ extern int ngx_ssl_server_conf_index; extern int ngx_ssl_session_cache_index; extern int ngx_ssl_session_ticket_keys_index; extern int ngx_ssl_certificate_index; +extern int ngx_ssl_next_certificate_index; extern int ngx_ssl_stapling_index; 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 @@ -126,12 +126,15 @@ ngx_ssl_stapling(ngx_conf_t *cf, ngx_ssl { X509 *cert; - cert = SSL_CTX_get_ex_data(ssl->ctx, ngx_ssl_certificate_index); - - 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, file, responder, verify) + != NGX_OK) + { + return NGX_ERROR; + } } SSL_CTX_set_tlsext_status_cb(ssl->ctx, ngx_ssl_certificate_status_callback); @@ -455,11 +458,14 @@ ngx_ssl_stapling_resolver(ngx_conf_t *cf X509 *cert; ngx_ssl_stapling_t *staple; - cert = SSL_CTX_get_ex_data(ssl->ctx, ngx_ssl_certificate_index); - staple = X509_get_ex_data(cert, ngx_ssl_stapling_index); - - staple->resolver = resolver; - staple->resolver_timeout = resolver_timeout; + 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)) + { + staple = X509_get_ex_data(cert, ngx_ssl_stapling_index); + staple->resolver = resolver; + staple->resolver_timeout = resolver_timeout; + } return NGX_OK; } # HG changeset patch # User Maxim Dounin # Date 1463277750 -10800 # Sun May 15 05:02:30 2016 +0300 # Node ID 61948bdc9c9170fd3714d50f712c8496ae4b13f2 # Parent 61522cf7ee72270ad214df45c9802fa89ef14339 SSL: support for per-certificate chains. The SSL_CTX_add0_chain_cert() function as introduced in OpenSSL 1.0.2 now used instead of SSL_CTX_add_extra_chain_cert(). SSL_CTX_add_extra_chain_cert() adds extra certs for all certificates in the context, while SSL_CTX_add0_chain_cert() only to a particular certificate. There is no difference unless multiple certificates are used, though it is important when using multiple certificates. Additionally, SSL_CTX_select_current_cert() is now called before using a chain to make sure correct chain will be returned. diff --git a/src/event/ngx_event_openssl.c b/src/event/ngx_event_openssl.c --- a/src/event/ngx_event_openssl.c +++ b/src/event/ngx_event_openssl.c @@ -410,6 +410,24 @@ ngx_ssl_certificate(ngx_conf_t *cf, ngx_ return NGX_ERROR; } +#ifdef SSL_CTRL_CHAIN_CERT + + /* + * SSL_CTX_add0_chain_cert() is needed to add chain to + * a parituclar certificate when multiple certificates are used; + * only available in OpenSSL 1.0.2+ + */ + + if (SSL_CTX_add0_chain_cert(ssl->ctx, x509) == 0) { + ngx_ssl_error(NGX_LOG_EMERG, ssl->log, 0, + "SSL_CTX_add0_chain_cert(\"%s\") failed", + cert->data); + X509_free(x509); + BIO_free(bio); + return NGX_ERROR; + } + +#else if (SSL_CTX_add_extra_chain_cert(ssl->ctx, x509) == 0) { ngx_ssl_error(NGX_LOG_EMERG, ssl->log, 0, "SSL_CTX_add_extra_chain_cert(\"%s\") failed", @@ -418,6 +436,7 @@ ngx_ssl_certificate(ngx_conf_t *cf, ngx_ BIO_free(bio); return NGX_ERROR; } +#endif } BIO_free(bio); 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 @@ -287,7 +287,13 @@ ngx_ssl_stapling_issuer(ngx_conf_t *cf, cert = staple->cert; -#if OPENSSL_VERSION_NUMBER >= 0x10001000L +#ifdef SSL_CTRL_SELECT_CURRENT_CERT + /* OpenSSL 1.0.2+ */ + SSL_CTX_select_current_cert(ssl->ctx, cert); +#endif + +#ifdef SSL_CTRL_GET_EXTRA_CHAIN_CERTS + /* OpenSSL 1.0.1+ */ SSL_CTX_get_extra_chain_certs(ssl->ctx, &chain); #else chain = ssl->ctx->extra_certs; @@ -621,7 +627,13 @@ ngx_ssl_stapling_ocsp_handler(ngx_ssl_oc goto error; } -#if OPENSSL_VERSION_NUMBER >= 0x10001000L +#ifdef SSL_CTRL_SELECT_CURRENT_CERT + /* OpenSSL 1.0.2+ */ + SSL_CTX_select_current_cert(staple->ssl_ctx, ctx->cert); +#endif + +#ifdef SSL_CTRL_GET_EXTRA_CHAIN_CERTS + /* OpenSSL 1.0.1+ */ SSL_CTX_get_extra_chain_certs(staple->ssl_ctx, &chain); #else chain = staple->ssl_ctx->extra_certs; # HG changeset patch # User Maxim Dounin # Date 1463277750 -10800 # Sun May 15 05:02:30 2016 +0300 # Node ID 4c8bf7080cf15f2ff754818a48fe223f2ee5812b # Parent 61948bdc9c9170fd3714d50f712c8496ae4b13f2 SSL: support for multiple certificates (ticket #814). diff --git a/src/event/ngx_event_openssl.c b/src/event/ngx_event_openssl.c --- a/src/event/ngx_event_openssl.c +++ b/src/event/ngx_event_openssl.c @@ -322,6 +322,29 @@ ngx_ssl_create(ngx_ssl_t *ssl, ngx_uint_ ngx_int_t +ngx_ssl_certificates(ngx_conf_t *cf, ngx_ssl_t *ssl, ngx_array_t *certs, + ngx_array_t *keys, ngx_array_t *passwords) +{ + ngx_str_t *cert, *key; + ngx_uint_t i; + + cert = certs->elts; + key = keys->elts; + + for (i = 0; i < certs->nelts; i++) { + + if (ngx_ssl_certificate(cf, ssl, &cert[i], &key[i], passwords) + != NGX_OK) + { + return NGX_ERROR; + } + } + + return NGX_OK; +} + + +ngx_int_t ngx_ssl_certificate(ngx_conf_t *cf, ngx_ssl_t *ssl, ngx_str_t *cert, ngx_str_t *key, ngx_array_t *passwords) { 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 @@ -142,6 +142,8 @@ ngx_int_t ngx_ssl_init(ngx_log_t *log); ngx_int_t ngx_ssl_create(ngx_ssl_t *ssl, ngx_uint_t protocols, void *data); ngx_int_t ngx_ssl_certificate(ngx_conf_t *cf, ngx_ssl_t *ssl, ngx_str_t *cert, ngx_str_t *key, ngx_array_t *passwords); +ngx_int_t ngx_ssl_certificates(ngx_conf_t *cf, ngx_ssl_t *ssl, + ngx_array_t *certs, ngx_array_t *keys, ngx_array_t *passwords); 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, 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 @@ -81,16 +81,16 @@ static ngx_command_t ngx_http_ssl_comma { ngx_string("ssl_certificate"), 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, certificate), + offsetof(ngx_http_ssl_srv_conf_t, certificates), NULL }, { ngx_string("ssl_certificate_key"), 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, certificate_key), + offsetof(ngx_http_ssl_srv_conf_t, certificate_keys), NULL }, { ngx_string("ssl_password_file"), @@ -508,8 +508,6 @@ ngx_http_ssl_create_srv_conf(ngx_conf_t * set by ngx_pcalloc(): * * sscf->protocols = 0; - * sscf->certificate = { 0, NULL }; - * sscf->certificate_key = { 0, NULL }; * sscf->dhparam = { 0, NULL }; * sscf->ecdh_curve = { 0, NULL }; * sscf->client_certificate = { 0, NULL }; @@ -526,6 +524,8 @@ ngx_http_ssl_create_srv_conf(ngx_conf_t 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; @@ -573,8 +573,9 @@ ngx_http_ssl_merge_srv_conf(ngx_conf_t * ngx_conf_merge_uint_value(conf->verify, prev->verify, 0); ngx_conf_merge_uint_value(conf->verify_depth, prev->verify_depth, 1); - ngx_conf_merge_str_value(conf->certificate, prev->certificate, ""); - ngx_conf_merge_str_value(conf->certificate_key, prev->certificate_key, ""); + ngx_conf_merge_ptr_value(conf->certificates, prev->certificates, NULL); + ngx_conf_merge_ptr_value(conf->certificate_keys, prev->certificate_keys, + NULL); ngx_conf_merge_ptr_value(conf->passwords, prev->passwords, NULL); @@ -601,7 +602,7 @@ ngx_http_ssl_merge_srv_conf(ngx_conf_t * if (conf->enable) { - if (conf->certificate.len == 0) { + if (conf->certificates == NULL) { ngx_log_error(NGX_LOG_EMERG, cf->log, 0, "no \"ssl_certificate\" is defined for " "the \"ssl\" directive in %s:%ui", @@ -609,7 +610,7 @@ ngx_http_ssl_merge_srv_conf(ngx_conf_t * return NGX_CONF_ERROR; } - if (conf->certificate_key.len == 0) { + if (conf->certificate_keys == NULL) { ngx_log_error(NGX_LOG_EMERG, cf->log, 0, "no \"ssl_certificate_key\" is defined for " "the \"ssl\" directive in %s:%ui", @@ -617,16 +618,31 @@ ngx_http_ssl_merge_srv_conf(ngx_conf_t * return NGX_CONF_ERROR; } + if (conf->certificate_keys->nelts < conf->certificates->nelts) { + ngx_log_error(NGX_LOG_EMERG, cf->log, 0, + "no \"ssl_certificate_key\" is defined " + "for certificate \"%V\" and " + "the \"ssl\" directive in %s:%ui", + ((ngx_str_t *) conf->certificates->elts) + + conf->certificates->nelts - 1, + conf->file, conf->line); + return NGX_CONF_ERROR; + } + } else { - if (conf->certificate.len == 0) { + if (conf->certificates == NULL) { return NGX_CONF_OK; } - if (conf->certificate_key.len == 0) { + if (conf->certificate_keys == NULL + || conf->certificate_keys->nelts < conf->certificates->nelts) + { ngx_log_error(NGX_LOG_EMERG, cf->log, 0, "no \"ssl_certificate_key\" is defined " - "for certificate \"%V\"", &conf->certificate); + "for certificate \"%V\"", + ((ngx_str_t *) conf->certificates->elts) + + conf->certificates->nelts - 1); return NGX_CONF_ERROR; } } @@ -666,8 +682,8 @@ ngx_http_ssl_merge_srv_conf(ngx_conf_t * cln->handler = ngx_ssl_cleanup_ctx; cln->data = &conf->ssl; - if (ngx_ssl_certificate(cf, &conf->ssl, &conf->certificate, - &conf->certificate_key, conf->passwords) + if (ngx_ssl_certificates(cf, &conf->ssl, conf->certificates, + conf->certificate_keys, conf->passwords) != 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 @@ -32,8 +32,9 @@ typedef struct { time_t session_timeout; - ngx_str_t certificate; - ngx_str_t certificate_key; + ngx_array_t *certificates; + ngx_array_t *certificate_keys; + ngx_str_t dhparam; ngx_str_t ecdh_curve; ngx_str_t client_certificate; diff --git a/src/mail/ngx_mail_ssl_module.c b/src/mail/ngx_mail_ssl_module.c --- a/src/mail/ngx_mail_ssl_module.c +++ b/src/mail/ngx_mail_ssl_module.c @@ -73,16 +73,16 @@ static ngx_command_t ngx_mail_ssl_comma { ngx_string("ssl_certificate"), NGX_MAIL_MAIN_CONF|NGX_MAIL_SRV_CONF|NGX_CONF_TAKE1, - ngx_conf_set_str_slot, + ngx_conf_set_str_array_slot, NGX_MAIL_SRV_CONF_OFFSET, - offsetof(ngx_mail_ssl_conf_t, certificate), + offsetof(ngx_mail_ssl_conf_t, certificates), NULL }, { ngx_string("ssl_certificate_key"), NGX_MAIL_MAIN_CONF|NGX_MAIL_SRV_CONF|NGX_CONF_TAKE1, - ngx_conf_set_str_slot, + ngx_conf_set_str_array_slot, NGX_MAIL_SRV_CONF_OFFSET, - offsetof(ngx_mail_ssl_conf_t, certificate_key), + offsetof(ngx_mail_ssl_conf_t, certificate_keys), NULL }, { ngx_string("ssl_password_file"), @@ -238,8 +238,6 @@ ngx_mail_ssl_create_conf(ngx_conf_t *cf) * set by ngx_pcalloc(): * * scf->protocols = 0; - * scf->certificate = { 0, NULL }; - * scf->certificate_key = { 0, NULL }; * scf->dhparam = { 0, NULL }; * scf->ecdh_curve = { 0, NULL }; * scf->client_certificate = { 0, NULL }; @@ -251,6 +249,8 @@ ngx_mail_ssl_create_conf(ngx_conf_t *cf) scf->enable = NGX_CONF_UNSET; scf->starttls = NGX_CONF_UNSET_UINT; + scf->certificates = NGX_CONF_UNSET_PTR; + scf->certificate_keys = NGX_CONF_UNSET_PTR; scf->passwords = NGX_CONF_UNSET_PTR; scf->prefer_server_ciphers = NGX_CONF_UNSET; scf->verify = NGX_CONF_UNSET_UINT; @@ -290,8 +290,9 @@ ngx_mail_ssl_merge_conf(ngx_conf_t *cf, ngx_conf_merge_uint_value(conf->verify, prev->verify, 0); ngx_conf_merge_uint_value(conf->verify_depth, prev->verify_depth, 1); - ngx_conf_merge_str_value(conf->certificate, prev->certificate, ""); - ngx_conf_merge_str_value(conf->certificate_key, prev->certificate_key, ""); + ngx_conf_merge_ptr_value(conf->certificates, prev->certificates, NULL); + ngx_conf_merge_ptr_value(conf->certificate_keys, prev->certificate_keys, + NULL); ngx_conf_merge_ptr_value(conf->passwords, prev->passwords, NULL); @@ -328,7 +329,7 @@ ngx_mail_ssl_merge_conf(ngx_conf_t *cf, if (*mode) { - if (conf->certificate.len == 0) { + if (conf->certificates == NULL) { ngx_log_error(NGX_LOG_EMERG, cf->log, 0, "no \"ssl_certificate\" is defined for " "the \"%s\" directive in %s:%ui", @@ -336,7 +337,7 @@ ngx_mail_ssl_merge_conf(ngx_conf_t *cf, return NGX_CONF_ERROR; } - if (conf->certificate_key.len == 0) { + if (conf->certificate_keys == NULL) { ngx_log_error(NGX_LOG_EMERG, cf->log, 0, "no \"ssl_certificate_key\" is defined for " "the \"%s\" directive in %s:%ui", @@ -344,17 +345,31 @@ ngx_mail_ssl_merge_conf(ngx_conf_t *cf, return NGX_CONF_ERROR; } + if (conf->certificate_keys->nelts < conf->certificates->nelts) { + ngx_log_error(NGX_LOG_EMERG, cf->log, 0, + "no \"ssl_certificate_key\" is defined " + "for certificate \"%V\" and " + "the \"ssl\" directive in %s:%ui", + ((ngx_str_t *) conf->certificates->elts) + + conf->certificates->nelts - 1, + conf->file, conf->line); + return NGX_CONF_ERROR; + } + } else { - if (conf->certificate.len == 0) { + if (conf->certificates == NULL) { return NGX_CONF_OK; } - if (conf->certificate_key.len == 0) { + if (conf->certificate_keys == NULL + || conf->certificate_keys->nelts < conf->certificates->nelts) + { ngx_log_error(NGX_LOG_EMERG, cf->log, 0, "no \"ssl_certificate_key\" is defined " "for certificate \"%V\"", - &conf->certificate); + ((ngx_str_t *) conf->certificates->elts) + + conf->certificates->nelts - 1); return NGX_CONF_ERROR; } } @@ -371,8 +386,8 @@ ngx_mail_ssl_merge_conf(ngx_conf_t *cf, cln->handler = ngx_ssl_cleanup_ctx; cln->data = &conf->ssl; - if (ngx_ssl_certificate(cf, &conf->ssl, &conf->certificate, - &conf->certificate_key, conf->passwords) + if (ngx_ssl_certificates(cf, &conf->ssl, conf->certificates, + conf->certificate_keys, conf->passwords) != NGX_OK) { return NGX_CONF_ERROR; diff --git a/src/mail/ngx_mail_ssl_module.h b/src/mail/ngx_mail_ssl_module.h --- a/src/mail/ngx_mail_ssl_module.h +++ b/src/mail/ngx_mail_ssl_module.h @@ -35,8 +35,9 @@ typedef struct { time_t session_timeout; - ngx_str_t certificate; - ngx_str_t certificate_key; + ngx_array_t *certificates; + ngx_array_t *certificate_keys; + ngx_str_t dhparam; ngx_str_t ecdh_curve; ngx_str_t client_certificate; diff --git a/src/stream/ngx_stream_ssl_module.c b/src/stream/ngx_stream_ssl_module.c --- a/src/stream/ngx_stream_ssl_module.c +++ b/src/stream/ngx_stream_ssl_module.c @@ -45,16 +45,16 @@ static ngx_command_t ngx_stream_ssl_com { ngx_string("ssl_certificate"), NGX_STREAM_MAIN_CONF|NGX_STREAM_SRV_CONF|NGX_CONF_TAKE1, - ngx_conf_set_str_slot, + ngx_conf_set_str_array_slot, NGX_STREAM_SRV_CONF_OFFSET, - offsetof(ngx_stream_ssl_conf_t, certificate), + offsetof(ngx_stream_ssl_conf_t, certificates), NULL }, { ngx_string("ssl_certificate_key"), NGX_STREAM_MAIN_CONF|NGX_STREAM_SRV_CONF|NGX_CONF_TAKE1, - ngx_conf_set_str_slot, + ngx_conf_set_str_array_slot, NGX_STREAM_SRV_CONF_OFFSET, - offsetof(ngx_stream_ssl_conf_t, certificate_key), + offsetof(ngx_stream_ssl_conf_t, certificate_keys), NULL }, { ngx_string("ssl_password_file"), @@ -175,8 +175,6 @@ ngx_stream_ssl_create_conf(ngx_conf_t *c * set by ngx_pcalloc(): * * scf->protocols = 0; - * scf->certificate = { 0, NULL }; - * scf->certificate_key = { 0, NULL }; * scf->dhparam = { 0, NULL }; * scf->ecdh_curve = { 0, NULL }; * scf->ciphers = { 0, NULL }; @@ -184,6 +182,8 @@ ngx_stream_ssl_create_conf(ngx_conf_t *c */ scf->handshake_timeout = NGX_CONF_UNSET_MSEC; + scf->certificates = NGX_CONF_UNSET_PTR; + scf->certificate_keys = NGX_CONF_UNSET_PTR; scf->passwords = NGX_CONF_UNSET_PTR; scf->prefer_server_ciphers = NGX_CONF_UNSET; scf->builtin_session_cache = NGX_CONF_UNSET; @@ -216,8 +216,9 @@ ngx_stream_ssl_merge_conf(ngx_conf_t *cf (NGX_CONF_BITMASK_SET|NGX_SSL_TLSv1 |NGX_SSL_TLSv1_1|NGX_SSL_TLSv1_2)); - ngx_conf_merge_str_value(conf->certificate, prev->certificate, ""); - ngx_conf_merge_str_value(conf->certificate_key, prev->certificate_key, ""); + ngx_conf_merge_ptr_value(conf->certificates, prev->certificates, NULL); + ngx_conf_merge_ptr_value(conf->certificate_keys, prev->certificate_keys, + NULL); ngx_conf_merge_ptr_value(conf->passwords, prev->passwords, NULL); @@ -231,15 +232,18 @@ ngx_stream_ssl_merge_conf(ngx_conf_t *cf conf->ssl.log = cf->log; - if (conf->certificate.len == 0) { + if (conf->certificates == NULL) { return NGX_CONF_OK; } - if (conf->certificate_key.len == 0) { + if (conf->certificate_keys == NULL + || conf->certificate_keys->nelts < conf->certificates->nelts) + { ngx_log_error(NGX_LOG_EMERG, cf->log, 0, "no \"ssl_certificate_key\" is defined " "for certificate \"%V\"", - &conf->certificate); + ((ngx_str_t *) conf->certificates->elts) + + conf->certificates->nelts - 1); return NGX_CONF_ERROR; } @@ -255,8 +259,8 @@ ngx_stream_ssl_merge_conf(ngx_conf_t *cf cln->handler = ngx_ssl_cleanup_ctx; cln->data = &conf->ssl; - if (ngx_ssl_certificate(cf, &conf->ssl, &conf->certificate, - &conf->certificate_key, conf->passwords) + if (ngx_ssl_certificates(cf, &conf->ssl, conf->certificates, + conf->certificate_keys, conf->passwords) != NGX_OK) { return NGX_CONF_ERROR; diff --git a/src/stream/ngx_stream_ssl_module.h b/src/stream/ngx_stream_ssl_module.h --- a/src/stream/ngx_stream_ssl_module.h +++ b/src/stream/ngx_stream_ssl_module.h @@ -27,8 +27,9 @@ typedef struct { time_t session_timeout; - ngx_str_t certificate; - ngx_str_t certificate_key; + ngx_array_t *certificates; + ngx_array_t *certificate_keys; + ngx_str_t dhparam; ngx_str_t ecdh_curve; # HG changeset patch # User Maxim Dounin # Date 1463277750 -10800 # Sun May 15 05:02:30 2016 +0300 # Node ID cb14a92f9fe51051ae4f7b8972288f9f9cd3b816 # Parent 4c8bf7080cf15f2ff754818a48fe223f2ee5812b SSL: error messages style. diff --git a/src/event/ngx_event_openssl.c b/src/event/ngx_event_openssl.c --- a/src/event/ngx_event_openssl.c +++ b/src/event/ngx_event_openssl.c @@ -1078,14 +1078,14 @@ ngx_ssl_ecdh_curve(ngx_conf_t *cf, ngx_s nid = OBJ_sn2nid((const char *) name->data); if (nid == 0) { ngx_ssl_error(NGX_LOG_EMERG, ssl->log, 0, - "Unknown curve name \"%s\"", name->data); + "OBJ_sn2nid(\"%s\") failed: unknown curve", name->data); return NGX_ERROR; } ecdh = EC_KEY_new_by_curve_name(nid); if (ecdh == NULL) { ngx_ssl_error(NGX_LOG_EMERG, ssl->log, 0, - "Unable to create curve \"%s\"", name->data); + "EC_KEY_new_by_curve_name(\"%s\") failed", name->data); return NGX_ERROR; } # HG changeset patch # User Maxim Dounin # Date 1463277750 -10800 # Sun May 15 05:02:30 2016 +0300 # Node ID ffc722edbba5bdb041b4e9a83f5b3576cb470a60 # Parent cb14a92f9fe51051ae4f7b8972288f9f9cd3b816 SSL: style. diff --git a/src/event/ngx_event_openssl.c b/src/event/ngx_event_openssl.c --- a/src/event/ngx_event_openssl.c +++ b/src/event/ngx_event_openssl.c @@ -1071,11 +1071,11 @@ ngx_ssl_ecdh_curve(ngx_conf_t *cf, ngx_s /* * Elliptic-Curve Diffie-Hellman parameters are either "named curves" * from RFC 4492 section 5.1.1, or explicitly described curves over - * binary fields. OpenSSL only supports the "named curves", which provide + * binary fields. OpenSSL only supports the "named curves", which provide * maximum interoperability. */ - nid = OBJ_sn2nid((const char *) name->data); + nid = OBJ_sn2nid((char *) name->data); if (nid == 0) { ngx_ssl_error(NGX_LOG_EMERG, ssl->log, 0, "OBJ_sn2nid(\"%s\") failed: unknown curve", name->data); @@ -2167,7 +2167,7 @@ ngx_ssl_session_cache(ngx_ssl_t *ssl, ng * session reuse (see SSL_SESS_CACHE_OFF above), then * Outlook Express fails to upload a sent email to * the Sent Items folder on the IMAP server via a separate IMAP - * connection in the background. Therefore we have a special + * connection in the background. Therefore we have a special * mode (SSL_SESS_CACHE_SERVER|SSL_SESS_CACHE_NO_INTERNAL_STORE) * where the server pretends that it supports session reuse, * but it does not actually store any session. @@ -3594,7 +3594,7 @@ ngx_openssl_engine(ngx_conf_t *cf, ngx_c value = cf->args->elts; - engine = ENGINE_by_id((const char *) value[1].data); + engine = ENGINE_by_id((char *) value[1].data); if (engine == NULL) { ngx_ssl_error(NGX_LOG_WARN, cf->log, 0, # HG changeset patch # User Maxim Dounin # Date 1463277750 -10800 # Sun May 15 05:02:30 2016 +0300 # Node ID b2690d83792594990aa8ec0cda5010e2d2e743e0 # Parent ffc722edbba5bdb041b4e9a83f5b3576cb470a60 SSL: support for multiple curves (ticket #885). OpenSSL 1.0.2+ allows configuring a curve list instead of a single curve previously supported. This allows use of different curves depending on what client support (as available via the elliptic_curves extension), and also allows use of different curves in an ECDHE key exchange and in the ECDSA certificate. The special value "auto" was introduced (now the default for ssl_ecdh_curve), which means "use an internal list of curves as available in the OpenSSL library used". For versions prior to OpenSSL 1.0.2 it maps to "prime256v1" as previously used. The default in 1.0.2b+ prefers prime256v1 as well (and X25519 in OpenSSL 1.1.0+). As client vs. server preference of curves is controlled by the same option as used for ciphers (SSL_OP_CIPHER_SERVER_PREFERENCE), the ssl_prefer_server_ciphers directive now controls both. diff --git a/src/event/ngx_event_openssl.c b/src/event/ngx_event_openssl.c --- a/src/event/ngx_event_openssl.c +++ b/src/event/ngx_event_openssl.c @@ -1065,8 +1065,6 @@ ngx_ssl_ecdh_curve(ngx_conf_t *cf, ngx_s { #if OPENSSL_VERSION_NUMBER >= 0x0090800fL #ifndef OPENSSL_NO_ECDH - int nid; - EC_KEY *ecdh; /* * Elliptic-Curve Diffie-Hellman parameters are either "named curves" @@ -1075,17 +1073,61 @@ ngx_ssl_ecdh_curve(ngx_conf_t *cf, ngx_s * maximum interoperability. */ - nid = OBJ_sn2nid((char *) name->data); +#ifdef SSL_CTRL_SET_CURVES_LIST + + /* + * OpenSSL 1.0.2+ allows configuring a curve list instead of a single + * curve previously supported. By default an internal list is used, + * with prime256v1 being preferred by server in OpenSSL 1.0.2b+ + * and X25519 in OpenSSL 1.1.0+. + * + * By default a curve preferred by the client will be used for + * key exchange. The SSL_OP_CIPHER_SERVER_PREFERENCE option can + * be used to prefer server curves instead, similar to what it + * does for ciphers. + */ + + SSL_CTX_set_options(ssl->ctx, SSL_OP_SINGLE_ECDH_USE); + +#if SSL_CTRL_SET_ECDH_AUTO + /* not needed in OpenSSL 1.1.0+ */ + SSL_CTX_set_ecdh_auto(ssl->ctx, 1); +#endif + + if (ngx_strcmp(name->data, "auto") == 0) { + return NGX_OK; + } + + if (SSL_CTX_set1_curves_list(ssl->ctx, (char *) name->data) == 0) { + ngx_ssl_error(NGX_LOG_EMERG, ssl->log, 0, + "SSL_CTX_set1_curves_list(\"%s\") failed", name->data); + return NGX_ERROR; + } + +#else + + int nid; + char *curve; + EC_KEY *ecdh; + + if (ngx_strcmp(name->data, "auto") == 0) { + curve = "prime256v1"; + + } else { + curve = (char *) name->data; + } + + nid = OBJ_sn2nid(curve); if (nid == 0) { ngx_ssl_error(NGX_LOG_EMERG, ssl->log, 0, - "OBJ_sn2nid(\"%s\") failed: unknown curve", name->data); + "OBJ_sn2nid(\"%s\") failed: unknown curve", curve); return NGX_ERROR; } ecdh = EC_KEY_new_by_curve_name(nid); if (ecdh == NULL) { ngx_ssl_error(NGX_LOG_EMERG, ssl->log, 0, - "EC_KEY_new_by_curve_name(\"%s\") failed", name->data); + "EC_KEY_new_by_curve_name(\"%s\") failed", curve); return NGX_ERROR; } @@ -1096,6 +1138,7 @@ ngx_ssl_ecdh_curve(ngx_conf_t *cf, ngx_s EC_KEY_free(ecdh); #endif #endif +#endif 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 @@ -15,7 +15,7 @@ typedef ngx_int_t (*ngx_ssl_variable_han #define NGX_DEFAULT_CIPHERS "HIGH:!aNULL:!MD5" -#define NGX_DEFAULT_ECDH_CURVE "prime256v1" +#define NGX_DEFAULT_ECDH_CURVE "auto" #define NGX_HTTP_NPN_ADVERTISE "\x08http/1.1" diff --git a/src/mail/ngx_mail_ssl_module.c b/src/mail/ngx_mail_ssl_module.c --- a/src/mail/ngx_mail_ssl_module.c +++ b/src/mail/ngx_mail_ssl_module.c @@ -11,7 +11,7 @@ #define NGX_DEFAULT_CIPHERS "HIGH:!aNULL:!MD5" -#define NGX_DEFAULT_ECDH_CURVE "prime256v1" +#define NGX_DEFAULT_ECDH_CURVE "auto" static void *ngx_mail_ssl_create_conf(ngx_conf_t *cf); diff --git a/src/stream/ngx_stream_ssl_module.c b/src/stream/ngx_stream_ssl_module.c --- a/src/stream/ngx_stream_ssl_module.c +++ b/src/stream/ngx_stream_ssl_module.c @@ -11,7 +11,7 @@ #define NGX_DEFAULT_CIPHERS "HIGH:!aNULL:!MD5" -#define NGX_DEFAULT_ECDH_CURVE "prime256v1" +#define NGX_DEFAULT_ECDH_CURVE "auto" static void *ngx_stream_ssl_create_conf(ngx_conf_t *cf); # HG changeset patch # User Maxim Dounin # Date 1463277750 -10800 # Sun May 15 05:02:30 2016 +0300 # Node ID 8da0f1ffbe318142031ae0499e1a7630a7a42f06 # Parent b2690d83792594990aa8ec0cda5010e2d2e743e0 SSL: removed default DH parameters. Using the same DH parameters on multiple servers is believed to be subject to precomputation attacks, see http://weakdh.org/. Additionally, 1024 bits are not enough in modern world as well. Let users to provide their own DH parameters with the ssl_dhparam directive if they want to use EDH ciphers. Note that SSL_CTX_set_dh_auto() as provided by OpenSSL 1.1.0 uses fixed DH parameters from RFC 5114 and RFC 3526, and therefore subject to the same precomputation attacks. We avoid using it as well. This change also fixes compilation with OpenSSL 1.1.0-pre5 (aka Beta 2), as OpenSSL developers changed their policy after releasing Beta 1 and broke API once again by making the DH struct opaque (see ticket #860). diff --git a/src/event/ngx_event_openssl.c b/src/event/ngx_event_openssl.c --- a/src/event/ngx_event_openssl.c +++ b/src/event/ngx_event_openssl.c @@ -983,52 +983,7 @@ ngx_ssl_dhparam(ngx_conf_t *cf, ngx_ssl_ DH *dh; BIO *bio; - /* - * -----BEGIN DH PARAMETERS----- - * MIGHAoGBALu8LcrYRnSQfEP89YDpz9vZWKP1aLQtSwju1OsPs1BMbAMCducQgAxc - * y7qokiYUxb7spWWl/fHSh6K8BJvmd4Bg6RqSp1fjBI9osHb302zI8pul34HcLKcl - * 7OZicMyaUDXYzs7vnqAnSmOrHlj6/UmI0PZdFGdX2gcd8EXP4WubAgEC - * -----END DH PARAMETERS----- - */ - - static unsigned char dh1024_p[] = { - 0xBB, 0xBC, 0x2D, 0xCA, 0xD8, 0x46, 0x74, 0x90, 0x7C, 0x43, 0xFC, 0xF5, - 0x80, 0xE9, 0xCF, 0xDB, 0xD9, 0x58, 0xA3, 0xF5, 0x68, 0xB4, 0x2D, 0x4B, - 0x08, 0xEE, 0xD4, 0xEB, 0x0F, 0xB3, 0x50, 0x4C, 0x6C, 0x03, 0x02, 0x76, - 0xE7, 0x10, 0x80, 0x0C, 0x5C, 0xCB, 0xBA, 0xA8, 0x92, 0x26, 0x14, 0xC5, - 0xBE, 0xEC, 0xA5, 0x65, 0xA5, 0xFD, 0xF1, 0xD2, 0x87, 0xA2, 0xBC, 0x04, - 0x9B, 0xE6, 0x77, 0x80, 0x60, 0xE9, 0x1A, 0x92, 0xA7, 0x57, 0xE3, 0x04, - 0x8F, 0x68, 0xB0, 0x76, 0xF7, 0xD3, 0x6C, 0xC8, 0xF2, 0x9B, 0xA5, 0xDF, - 0x81, 0xDC, 0x2C, 0xA7, 0x25, 0xEC, 0xE6, 0x62, 0x70, 0xCC, 0x9A, 0x50, - 0x35, 0xD8, 0xCE, 0xCE, 0xEF, 0x9E, 0xA0, 0x27, 0x4A, 0x63, 0xAB, 0x1E, - 0x58, 0xFA, 0xFD, 0x49, 0x88, 0xD0, 0xF6, 0x5D, 0x14, 0x67, 0x57, 0xDA, - 0x07, 0x1D, 0xF0, 0x45, 0xCF, 0xE1, 0x6B, 0x9B - }; - - static unsigned char dh1024_g[] = { 0x02 }; - - if (file->len == 0) { - - dh = DH_new(); - if (dh == NULL) { - ngx_ssl_error(NGX_LOG_EMERG, ssl->log, 0, "DH_new() failed"); - return NGX_ERROR; - } - - dh->p = BN_bin2bn(dh1024_p, sizeof(dh1024_p), NULL); - dh->g = BN_bin2bn(dh1024_g, sizeof(dh1024_g), NULL); - - if (dh->p == NULL || dh->g == NULL) { - ngx_ssl_error(NGX_LOG_EMERG, ssl->log, 0, "BN_bin2bn() failed"); - DH_free(dh); - return NGX_ERROR; - } - - SSL_CTX_set_tmp_dh(ssl->ctx, dh); - - DH_free(dh); - return NGX_OK; } From vbart at nginx.com Mon May 16 13:23:40 2016 From: vbart at nginx.com (Valentin Bartenev) Date: Mon, 16 May 2016 13:23:40 +0000 Subject: [nginx] Fixed an error log message about epoll_wait() timeout. Message-ID: details: http://hg.nginx.org/nginx/rev/3ad1064a3aae branches: changeset: 6537:3ad1064a3aae user: Valentin Bartenev date: Mon May 16 16:22:34 2016 +0300 description: Fixed an error log message about epoll_wait() timeout. The errno value is unset in case of epoll_wait() timeout. diffstat: src/event/modules/ngx_epoll_module.c | 4 ++-- 1 files changed, 2 insertions(+), 2 deletions(-) diffs (14 lines): diff -r f7849bfb6d21 -r 3ad1064a3aae src/event/modules/ngx_epoll_module.c --- a/src/event/modules/ngx_epoll_module.c Fri May 13 17:19:23 2016 +0300 +++ b/src/event/modules/ngx_epoll_module.c Mon May 16 16:22:34 2016 +0300 @@ -1000,8 +1000,8 @@ ngx_epoll_module_init(ngx_cycle_t *cycle ngx_use_epoll_rdhup = ee.events & EPOLLRDHUP; } else { - ngx_log_error(NGX_LOG_ALERT, cycle->log, ngx_errno, - "epoll_wait() timedout"); + ngx_log_error(NGX_LOG_ALERT, cycle->log, NGX_ETIMEDOUT, + "epoll_wait() timed out"); } ngx_log_error(NGX_LOG_NOTICE, cycle->log, 0, From mdounin at mdounin.ru Mon May 16 17:40:20 2016 From: mdounin at mdounin.ru (Maxim Dounin) Date: Mon, 16 May 2016 17:40:20 +0000 Subject: [nginx] Dav: return 501 on PUT with ranges (ticket #948). Message-ID: details: http://hg.nginx.org/nginx/rev/055cbb52ac1d branches: changeset: 6538:055cbb52ac1d user: Maxim Dounin date: Mon May 16 20:37:23 2016 +0300 description: Dav: return 501 on PUT with ranges (ticket #948). diffstat: src/http/modules/ngx_http_dav_module.c | 6 ++++++ src/http/ngx_http_request.c | 4 ++++ src/http/ngx_http_request.h | 1 + 3 files changed, 11 insertions(+), 0 deletions(-) diffs (41 lines): diff --git a/src/http/modules/ngx_http_dav_module.c b/src/http/modules/ngx_http_dav_module.c --- a/src/http/modules/ngx_http_dav_module.c +++ b/src/http/modules/ngx_http_dav_module.c @@ -161,6 +161,12 @@ ngx_http_dav_handler(ngx_http_request_t return NGX_HTTP_CONFLICT; } + if (r->headers_in.content_range) { + ngx_log_error(NGX_LOG_ERR, r->connection->log, 0, + "PUT with range is unsupported"); + return NGX_HTTP_NOT_IMPLEMENTED; + } + r->request_body_in_file_only = 1; r->request_body_in_persistent_file = 1; r->request_body_in_clean_file = 1; diff --git a/src/http/ngx_http_request.c b/src/http/ngx_http_request.c --- a/src/http/ngx_http_request.c +++ b/src/http/ngx_http_request.c @@ -110,6 +110,10 @@ ngx_http_header_t ngx_http_headers_in[] offsetof(ngx_http_headers_in_t, content_length), ngx_http_process_unique_header_line }, + { ngx_string("Content-Range"), + offsetof(ngx_http_headers_in_t, content_range), + ngx_http_process_unique_header_line }, + { ngx_string("Content-Type"), offsetof(ngx_http_headers_in_t, content_type), ngx_http_process_header_line }, diff --git a/src/http/ngx_http_request.h b/src/http/ngx_http_request.h --- a/src/http/ngx_http_request.h +++ b/src/http/ngx_http_request.h @@ -182,6 +182,7 @@ typedef struct { ngx_table_elt_t *user_agent; ngx_table_elt_t *referer; ngx_table_elt_t *content_length; + ngx_table_elt_t *content_range; ngx_table_elt_t *content_type; ngx_table_elt_t *range; From mdounin at mdounin.ru Mon May 16 17:40:22 2016 From: mdounin at mdounin.ru (Maxim Dounin) Date: Mon, 16 May 2016 17:40:22 +0000 Subject: [nginx] Cache: fixed updating bypassed cached errors (ticket #827). Message-ID: details: http://hg.nginx.org/nginx/rev/d94f57990492 branches: changeset: 6539:d94f57990492 user: Maxim Dounin date: Mon May 16 20:37:38 2016 +0300 description: Cache: fixed updating bypassed cached errors (ticket #827). diffstat: src/http/ngx_http_file_cache.c | 1 + 1 files changed, 1 insertions(+), 0 deletions(-) diffs (11 lines): diff --git a/src/http/ngx_http_file_cache.c b/src/http/ngx_http_file_cache.c --- a/src/http/ngx_http_file_cache.c +++ b/src/http/ngx_http_file_cache.c @@ -1403,6 +1403,7 @@ ngx_http_file_cache_update(ngx_http_requ ngx_shmtx_lock(&cache->shpool->mutex); c->node->count--; + c->node->error = 0; c->node->uniq = uniq; c->node->body_start = c->body_start; From kuroishi at iij.ad.jp Wed May 18 01:52:16 2016 From: kuroishi at iij.ad.jp (Kuroishi Mitsuo) Date: Wed, 18 May 2016 10:52:16 +0900 (JST) Subject: NGX_HTTP_POST_ACCESS_PHASE Message-ID: <20160518.105216.2000436503899205012.kuroishi@iij.ad.jp> Hi, I'm Mitsuo. Although I noticed using 1.9.15, NGX_HTTP_POST_ACCESS_PHASE array initialization seems not to exist. Is this intentional? I can assume that the patch below is needed. Regards, -- Kuroishi Mitsuo --- nginx-1.9.15.orig/src/http/ngx_http.c 2016-05-17 10:41:42.333782615 +0900 +++ nginx-1.9.15/src/http/ngx_http.c 2016-05-18 10:44:42.175777828 +0900 @@ -382,6 +382,13 @@ ngx_http_init_phases(ngx_conf_t *cf, ngx return NGX_ERROR; } + if (ngx_array_init(&cmcf->phases[NGX_HTTP_POST_ACCESS_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) From hongzhidao at gmail.com Wed May 18 05:35:10 2016 From: hongzhidao at gmail.com (=?UTF-8?B?5rSq5b+X6YGT?=) Date: Wed, 18 May 2016 13:35:10 +0800 Subject: No subject Message-ID: Hi Is there a way to get selected peer in upstream without sending request to backend server? upstream backend { hash $url consistent; server 192.168.1.101; server 192.168.1.102; # Assume this is selected server 192.168.1.103; } location /302 { proxy_pass http://backend; # need other config or develop custom module? } > curl http://test.com/302 -v ... Location: http://192.168.1.102/xxx ... Just get selected server, and immediately return for 302 location. Is it possible to support the feature, or give me advices, thanks so much. -------------- next part -------------- An HTML attachment was scrubbed... URL: From hongzhidao at gmail.com Wed May 18 05:35:50 2016 From: hongzhidao at gmail.com (=?UTF-8?B?5rSq5b+X6YGT?=) Date: Wed, 18 May 2016 13:35:50 +0800 Subject: upstream/302 Message-ID: Hi Is there a way to get selected peer in upstream without sending request to backend server? upstream backend { hash $url consistent; server 192.168.1.101; server 192.168.1.102; # Assume this is selected server 192.168.1.103; } location /302 { proxy_pass http://backend; # need other config or develop custom module? } > curl http://test.com/302 -v ... Location: http://192.168.1.102/xxx ... Just get selected server, and immediately return for 302 location. Is it possible to support the feature, or give me advices, thanks so much. -------------- next part -------------- An HTML attachment was scrubbed... URL: From hungnv at opensource.com.vn Wed May 18 06:07:35 2016 From: hungnv at opensource.com.vn (Hung Nguyen) Date: Wed, 18 May 2016 13:07:35 +0700 Subject: upstream/302 In-Reply-To: References: Message-ID: <39C4EC6E-8268-4A7F-B8F7-F4D0A413CEE0@opensource.com.vn> Hello, I do not not think nginx has this feature, but we can do it with lua module, at it?s exactly what I did, you can find it here: https://github.com/whatvn/nginx_redirect_balancer It works with help of following awesome module by agentzh: lua-nginx-module and lua-updstream-module - Hung From: nginx-devel on behalf of ??? Reply-To: Date: Wednesday, May 18, 2016 at 12:35 PM To: Subject: upstream/302 Hi Is there a way to get selected peer in upstream without sending request to backend server? upstream backend { hash $url consistent; server 192.168.1.101; server 192.168.1.102; # Assume this is selected server 192.168.1.103; } location /302 { proxy_pass http://backend; # need other config or develop custom module? } > curl http://test.com/302 -v ... Location: http://192.168.1.102/xxx ... Just get selected server, and immediately return for 302 location. Is it possible to support the feature, or give me advices, thanks so much. _______________________________________________ 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 hongzhidao at gmail.com Wed May 18 07:20:23 2016 From: hongzhidao at gmail.com (=?UTF-8?B?5rSq5b+X6YGT?=) Date: Wed, 18 May 2016 15:20:23 +0800 Subject: upstream/302 In-Reply-To: <39C4EC6E-8268-4A7F-B8F7-F4D0A413CEE0@opensource.com.vn> References: <39C4EC6E-8268-4A7F-B8F7-F4D0A413CEE0@opensource.com.vn> Message-ID: Thank you But it seems not the solution I really want. The selected peer/server is calculated by config in upstream, such as 'hash $url consistent'. 2016-05-18 14:07 GMT+08:00 Hung Nguyen : > Hello, > > I do not not think nginx has this feature, but we can do it with lua > module, at it?s exactly what I did, you can find it here: > https://github.com/whatvn/nginx_redirect_balancer > > *I**t works with help of following awesome module by agentzh: *lua-nginx-module > and lua-updstream-module > > > - > Hung > > > From: nginx-devel on behalf of ??? < > hongzhidao at gmail.com> > Reply-To: > Date: Wednesday, May 18, 2016 at 12:35 PM > To: > Subject: upstream/302 > > Hi > > Is there a way to get selected peer in upstream without sending request to > backend server? > > upstream backend { > hash $url consistent; > server 192.168.1.101; > server 192.168.1.102; # Assume this is selected > server 192.168.1.103; > } > > > location /302 { > proxy_pass http://backend; > # need other config or develop custom module? > } > > > > curl http://test.com/302 -v > ... > Location: http://192.168.1.102/xxx > ... > > Just get selected server, and immediately return for 302 location. > Is it possible to support the feature, or give me advices, thanks so much. > _______________________________________________ nginx-devel mailing list > nginx-devel at nginx.org > http://mailman.nginx.org/mailman/listinfo/nginx-devel > > _______________________________________________ > 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 Wed May 18 12:19:53 2016 From: mdounin at mdounin.ru (Maxim Dounin) Date: Wed, 18 May 2016 15:19:53 +0300 Subject: NGX_HTTP_POST_ACCESS_PHASE In-Reply-To: <20160518.105216.2000436503899205012.kuroishi@iij.ad.jp> References: <20160518.105216.2000436503899205012.kuroishi@iij.ad.jp> Message-ID: <20160518121952.GF36620@mdounin.ru> Hello! On Wed, May 18, 2016 at 10:52:16AM +0900, Kuroishi Mitsuo wrote: > > Hi, I'm Mitsuo. > > > Although I noticed using 1.9.15, NGX_HTTP_POST_ACCESS_PHASE > array initialization seems not to exist. > > Is this intentional? Yes. > I can assume that the patch below is needed. No. Post access phase doesn't use phase handlers. It's only used to check r->access_code after all access phase handlers and act accordingly. See ngx_http_core_post_access_phase() for details. -- Maxim Dounin http://nginx.org/ From mdounin at mdounin.ru Wed May 18 12:58:10 2016 From: mdounin at mdounin.ru (Maxim Dounin) Date: Wed, 18 May 2016 12:58:10 +0000 Subject: [nginx] Fixed work with --test-build-epoll after f7849bfb6d21. Message-ID: details: http://hg.nginx.org/nginx/rev/a01e400dd4a1 branches: changeset: 6540:a01e400dd4a1 user: Maxim Dounin date: Wed May 18 15:57:28 2016 +0300 description: Fixed work with --test-build-epoll after f7849bfb6d21. diffstat: src/event/modules/ngx_epoll_module.c | 138 ++++++++++++++++++---------------- 1 files changed, 71 insertions(+), 67 deletions(-) diffs (184 lines): diff --git a/src/event/modules/ngx_epoll_module.c b/src/event/modules/ngx_epoll_module.c --- a/src/event/modules/ngx_epoll_module.c +++ b/src/event/modules/ngx_epoll_module.c @@ -105,6 +105,9 @@ static ngx_int_t ngx_epoll_init(ngx_cycl static ngx_int_t ngx_epoll_notify_init(ngx_log_t *log); static void ngx_epoll_notify_handler(ngx_event_t *ev); #endif +#if (NGX_HAVE_EPOLLRDHUP) +static void ngx_epoll_test_rdhup(ngx_cycle_t *cycle); +#endif static void ngx_epoll_done(ngx_cycle_t *cycle); static ngx_int_t ngx_epoll_add_event(ngx_event_t *ev, ngx_int_t event, ngx_uint_t flags); @@ -123,7 +126,6 @@ static ngx_int_t ngx_epoll_process_event static void ngx_epoll_eventfd_handler(ngx_event_t *ev); #endif -static ngx_int_t ngx_epoll_module_init(ngx_cycle_t *cycle); static void *ngx_epoll_create_conf(ngx_cycle_t *cycle); static char *ngx_epoll_init_conf(ngx_cycle_t *cycle, void *conf); @@ -202,7 +204,7 @@ ngx_module_t ngx_epoll_module = { ngx_epoll_commands, /* module directives */ NGX_EVENT_MODULE, /* module type */ NULL, /* init master */ - ngx_epoll_module_init, /* init module */ + NULL, /* init module */ NULL, /* init process */ NULL, /* init thread */ NULL, /* exit thread */ @@ -339,9 +341,11 @@ ngx_epoll_init(ngx_cycle_t *cycle, ngx_m #endif #if (NGX_HAVE_FILE_AIO) + ngx_epoll_aio_init(cycle, epcf); +#endif - ngx_epoll_aio_init(cycle, epcf); - +#if (NGX_HAVE_EPOLLRDHUP) + ngx_epoll_test_rdhup(cycle); #endif } @@ -454,6 +458,69 @@ ngx_epoll_notify_handler(ngx_event_t *ev #endif +#if (NGX_HAVE_EPOLLRDHUP) + +static void +ngx_epoll_test_rdhup(ngx_cycle_t *cycle) +{ + int epfd, s[2], events; + struct epoll_event ee; + + epfd = epoll_create(1); + + if (epfd == -1) { + ngx_log_error(NGX_LOG_ALERT, cycle->log, ngx_errno, + "epoll_create() failed"); + return; + } + + if (socketpair(AF_UNIX, SOCK_STREAM, 0, s) == -1) { + ngx_log_error(NGX_LOG_ALERT, cycle->log, ngx_errno, + "socketpair() failed"); + return; + } + + ee.events = EPOLLET|EPOLLIN|EPOLLRDHUP; + + if (epoll_ctl(epfd, EPOLL_CTL_ADD, s[0], &ee) == -1) { + ngx_log_error(NGX_LOG_ALERT, cycle->log, ngx_errno, + "epoll_ctl() failed"); + return; + } + + if (close(s[1]) == -1) { + ngx_log_error(NGX_LOG_ALERT, cycle->log, ngx_errno, + "close() failed"); + return; + } + + events = epoll_wait(epfd, &ee, 1, 5000); + + if (events == -1) { + ngx_log_error(NGX_LOG_ALERT, cycle->log, ngx_errno, + "epoll_wait() failed"); + return; + } + + (void) close(s[0]); + (void) close(epfd); + + if (events) { + ngx_use_epoll_rdhup = ee.events & EPOLLRDHUP; + + } else { + ngx_log_error(NGX_LOG_ALERT, cycle->log, NGX_ETIMEDOUT, + "epoll_wait() timed out"); + } + + ngx_log_debug1(NGX_LOG_DEBUG_EVENT, cycle->log, 0, + "testing the EPOLLRDHUP flag: %s", + ngx_use_epoll_rdhup ? "success" : "fail"); +} + +#endif + + static void ngx_epoll_done(ngx_cycle_t *cycle) { @@ -950,69 +1017,6 @@ ngx_epoll_eventfd_handler(ngx_event_t *e #endif -static ngx_int_t -ngx_epoll_module_init(ngx_cycle_t *cycle) -{ -#if (NGX_HAVE_EPOLLRDHUP) - int epfd, s[2], events; - struct epoll_event ee; - - epfd = epoll_create(1); - - if (epfd == -1) { - ngx_log_error(NGX_LOG_ALERT, cycle->log, ngx_errno, - "epoll_create() failed"); - return NGX_ERROR; - } - - if (socketpair(AF_UNIX, SOCK_STREAM, 0, s) == -1) { - ngx_log_error(NGX_LOG_ALERT, cycle->log, ngx_errno, - "socketpair() failed"); - return NGX_ERROR; - } - - ee.events = EPOLLET|EPOLLIN|EPOLLRDHUP; - - if (epoll_ctl(epfd, EPOLL_CTL_ADD, s[0], &ee) == -1) { - ngx_log_error(NGX_LOG_ALERT, cycle->log, ngx_errno, - "epoll_ctl() failed"); - return NGX_ERROR; - } - - if (close(s[1]) == -1) { - ngx_log_error(NGX_LOG_ALERT, cycle->log, ngx_errno, - "close() failed"); - return NGX_ERROR; - } - - events = epoll_wait(epfd, &ee, 1, 5000); - - if (events == -1) { - ngx_log_error(NGX_LOG_ALERT, cycle->log, ngx_errno, - "epoll_wait() failed"); - return NGX_ERROR; - } - - (void) close(s[0]); - (void) close(epfd); - - if (events) { - ngx_use_epoll_rdhup = ee.events & EPOLLRDHUP; - - } else { - ngx_log_error(NGX_LOG_ALERT, cycle->log, NGX_ETIMEDOUT, - "epoll_wait() timed out"); - } - - ngx_log_error(NGX_LOG_NOTICE, cycle->log, 0, - "testing the EPOLLRDHUP flag: %s", - ngx_use_epoll_rdhup ? "success" : "fail"); -#endif - - return NGX_OK; -} - - static void * ngx_epoll_create_conf(ngx_cycle_t *cycle) { From mdounin at mdounin.ru Wed May 18 12:58:12 2016 From: mdounin at mdounin.ru (Maxim Dounin) Date: Wed, 18 May 2016 12:58:12 +0000 Subject: [nginx] Events: changed ngx_epoll_test_rdhup() to use existing epollfd. Message-ID: details: http://hg.nginx.org/nginx/rev/282448777dc2 branches: changeset: 6541:282448777dc2 user: Maxim Dounin date: Wed May 18 15:57:29 2016 +0300 description: Events: changed ngx_epoll_test_rdhup() to use existing epollfd. diffstat: src/event/modules/ngx_epoll_module.c | 15 +++------------ 1 files changed, 3 insertions(+), 12 deletions(-) diffs (48 lines): diff --git a/src/event/modules/ngx_epoll_module.c b/src/event/modules/ngx_epoll_module.c --- a/src/event/modules/ngx_epoll_module.c +++ b/src/event/modules/ngx_epoll_module.c @@ -463,17 +463,9 @@ ngx_epoll_notify_handler(ngx_event_t *ev static void ngx_epoll_test_rdhup(ngx_cycle_t *cycle) { - int epfd, s[2], events; + int s[2], events; struct epoll_event ee; - epfd = epoll_create(1); - - if (epfd == -1) { - ngx_log_error(NGX_LOG_ALERT, cycle->log, ngx_errno, - "epoll_create() failed"); - return; - } - if (socketpair(AF_UNIX, SOCK_STREAM, 0, s) == -1) { ngx_log_error(NGX_LOG_ALERT, cycle->log, ngx_errno, "socketpair() failed"); @@ -482,7 +474,7 @@ ngx_epoll_test_rdhup(ngx_cycle_t *cycle) ee.events = EPOLLET|EPOLLIN|EPOLLRDHUP; - if (epoll_ctl(epfd, EPOLL_CTL_ADD, s[0], &ee) == -1) { + if (epoll_ctl(ep, EPOLL_CTL_ADD, s[0], &ee) == -1) { ngx_log_error(NGX_LOG_ALERT, cycle->log, ngx_errno, "epoll_ctl() failed"); return; @@ -494,7 +486,7 @@ ngx_epoll_test_rdhup(ngx_cycle_t *cycle) return; } - events = epoll_wait(epfd, &ee, 1, 5000); + events = epoll_wait(ep, &ee, 1, 5000); if (events == -1) { ngx_log_error(NGX_LOG_ALERT, cycle->log, ngx_errno, @@ -503,7 +495,6 @@ ngx_epoll_test_rdhup(ngx_cycle_t *cycle) } (void) close(s[0]); - (void) close(epfd); if (events) { ngx_use_epoll_rdhup = ee.events & EPOLLRDHUP; From mdounin at mdounin.ru Wed May 18 12:58:15 2016 From: mdounin at mdounin.ru (Maxim Dounin) Date: Wed, 18 May 2016 12:58:15 +0000 Subject: [nginx] Events: close descriptors on errors in ngx_epoll_test_rdhup(). Message-ID: details: http://hg.nginx.org/nginx/rev/c93e57ba301b branches: changeset: 6542:c93e57ba301b user: Maxim Dounin date: Wed May 18 15:57:30 2016 +0300 description: Events: close descriptors on errors in ngx_epoll_test_rdhup(). diffstat: src/event/modules/ngx_epoll_module.c | 23 ++++++++++++++++++----- 1 files changed, 18 insertions(+), 5 deletions(-) diffs (54 lines): diff --git a/src/event/modules/ngx_epoll_module.c b/src/event/modules/ngx_epoll_module.c --- a/src/event/modules/ngx_epoll_module.c +++ b/src/event/modules/ngx_epoll_module.c @@ -477,25 +477,26 @@ ngx_epoll_test_rdhup(ngx_cycle_t *cycle) if (epoll_ctl(ep, EPOLL_CTL_ADD, s[0], &ee) == -1) { ngx_log_error(NGX_LOG_ALERT, cycle->log, ngx_errno, "epoll_ctl() failed"); - return; + goto failed; } if (close(s[1]) == -1) { ngx_log_error(NGX_LOG_ALERT, cycle->log, ngx_errno, "close() failed"); - return; + s[1] = -1; + goto failed; } + s[1] = -1; + events = epoll_wait(ep, &ee, 1, 5000); if (events == -1) { ngx_log_error(NGX_LOG_ALERT, cycle->log, ngx_errno, "epoll_wait() failed"); - return; + goto failed; } - (void) close(s[0]); - if (events) { ngx_use_epoll_rdhup = ee.events & EPOLLRDHUP; @@ -507,6 +508,18 @@ ngx_epoll_test_rdhup(ngx_cycle_t *cycle) ngx_log_debug1(NGX_LOG_DEBUG_EVENT, cycle->log, 0, "testing the EPOLLRDHUP flag: %s", ngx_use_epoll_rdhup ? "success" : "fail"); + +failed: + + if (s[1] != -1 && close(s[1]) == -1) { + ngx_log_error(NGX_LOG_ALERT, cycle->log, ngx_errno, + "close() failed"); + } + + if (close(s[0]) == -1) { + ngx_log_error(NGX_LOG_ALERT, cycle->log, ngx_errno, + "close() failed"); + } } #endif From mdounin at mdounin.ru Wed May 18 14:15:14 2016 From: mdounin at mdounin.ru (Maxim Dounin) Date: Wed, 18 May 2016 14:15:14 +0000 Subject: [nginx] Added overflow checks for version numbers (ticket #762). Message-ID: details: http://hg.nginx.org/nginx/rev/302ff40c9bc9 branches: changeset: 6543:302ff40c9bc9 user: Maxim Dounin date: Wed May 18 16:21:32 2016 +0300 description: Added overflow checks for version numbers (ticket #762). Both minor and major versions are now limited to 999 maximum. In case of r->http_minor, this limit is already implied by the code. Major version, r->http_major, in theory can be up to 65535 with current code, but such values are very unlikely to become real (and, additionally, such values are not allowed by RFC 7230), so the same test was used for r->http_major. diffstat: src/http/ngx_http_parse.c | 16 ++++++++++++++++ 1 files changed, 16 insertions(+), 0 deletions(-) diffs (47 lines): diff --git a/src/http/ngx_http_parse.c b/src/http/ngx_http_parse.c --- a/src/http/ngx_http_parse.c +++ b/src/http/ngx_http_parse.c @@ -737,6 +737,10 @@ ngx_http_parse_request_line(ngx_http_req return NGX_HTTP_PARSE_INVALID_REQUEST; } + if (r->http_major > 99) { + return NGX_HTTP_PARSE_INVALID_REQUEST; + } + r->http_major = r->http_major * 10 + ch - '0'; break; @@ -770,6 +774,10 @@ ngx_http_parse_request_line(ngx_http_req return NGX_HTTP_PARSE_INVALID_REQUEST; } + if (r->http_minor > 99) { + return NGX_HTTP_PARSE_INVALID_REQUEST; + } + r->http_minor = r->http_minor * 10 + ch - '0'; break; @@ -1680,6 +1688,10 @@ ngx_http_parse_status_line(ngx_http_requ return NGX_ERROR; } + if (r->http_major > 99) { + return NGX_ERROR; + } + r->http_major = r->http_major * 10 + ch - '0'; break; @@ -1704,6 +1716,10 @@ ngx_http_parse_status_line(ngx_http_requ return NGX_ERROR; } + if (r->http_minor > 99) { + return NGX_ERROR; + } + r->http_minor = r->http_minor * 10 + ch - '0'; break; From hongzhidao at gmail.com Thu May 19 05:03:14 2016 From: hongzhidao at gmail.com (=?UTF-8?B?5rSq5b+X6YGT?=) Date: Thu, 19 May 2016 13:03:14 +0800 Subject: [nginx] map module cause core dump Message-ID: Hi, It seems the following configure will cause core dump file. map $uri $s { default $s; # same var name as the var generated by map directive above } server { listen 80; location / { return 200 $s; } } [root at localhost nginx-1.10.0]# ./objs/nginx -V nginx version: nginx/1.10.0 built by gcc 4.4.7 20120313 (Red Hat 4.4.7-4) (GCC) configure arguments: --with-debug B.R. -------------- next part -------------- An HTML attachment was scrubbed... URL: From mdounin at mdounin.ru Thu May 19 11:27:01 2016 From: mdounin at mdounin.ru (Maxim Dounin) Date: Thu, 19 May 2016 14:27:01 +0300 Subject: [nginx] map module cause core dump In-Reply-To: References: Message-ID: <20160519112700.GX36620@mdounin.ru> Hello! On Thu, May 19, 2016 at 01:03:14PM +0800, ??? wrote: > Hi, > > It seems the following configure will cause core dump file. > > map $uri $s { > default $s; # same var name as the var generated by map directive > above > } > > server { > listen 80; > > location / { > return 200 $s; > } > } This is a classical example of infinite recursion. It's expected to work fine on any host with infinite amount of memory, but you've probably tried it on a host with some limited amount of memory available. Avoid writing such configurations on hosts with limited amount of memory. Jokes aside, the result is expected. We've considered adding a protection from such types of recursion (much like what we do with subrequests and internal redirections), but yet think it would be an overkill. -- Maxim Dounin http://nginx.org/ From mdounin at mdounin.ru Thu May 19 17:30:12 2016 From: mdounin at mdounin.ru (Maxim Dounin) Date: Thu, 19 May 2016 17:30:12 +0000 Subject: [nginx] OCSP stapling: staple provided in arguments. Message-ID: details: http://hg.nginx.org/nginx/rev/458e01ef46e6 branches: changeset: 6544:458e01ef46e6 user: Maxim Dounin date: Thu May 19 14:46:32 2016 +0300 description: OCSP stapling: staple provided in arguments. diffstat: src/event/ngx_event_openssl_stapling.c | 48 +++++++++++++++------------------ 1 files changed, 22 insertions(+), 26 deletions(-) diffs (108 lines): 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 @@ -84,10 +84,11 @@ struct ngx_ssl_ocsp_ctx_s { static ngx_int_t ngx_ssl_stapling_file(ngx_conf_t *cf, ngx_ssl_t *ssl, - ngx_str_t *file); -static ngx_int_t ngx_ssl_stapling_issuer(ngx_conf_t *cf, ngx_ssl_t *ssl); + ngx_ssl_stapling_t *staple, ngx_str_t *file); +static ngx_int_t ngx_ssl_stapling_issuer(ngx_conf_t *cf, ngx_ssl_t *ssl, + ngx_ssl_stapling_t *staple); static ngx_int_t ngx_ssl_stapling_responder(ngx_conf_t *cf, ngx_ssl_t *ssl, - ngx_str_t *responder); + ngx_ssl_stapling_t *staple, ngx_str_t *responder); static int ngx_ssl_certificate_status_callback(ngx_ssl_conn_t *ssl_conn, void *data); @@ -153,14 +154,14 @@ ngx_ssl_stapling(ngx_conf_t *cf, ngx_ssl if (file->len) { /* use OCSP response from the file */ - if (ngx_ssl_stapling_file(cf, ssl, file) != NGX_OK) { + if (ngx_ssl_stapling_file(cf, ssl, staple, file) != NGX_OK) { return NGX_ERROR; } goto done; } - rc = ngx_ssl_stapling_issuer(cf, ssl); + rc = ngx_ssl_stapling_issuer(cf, ssl, staple); if (rc == NGX_DECLINED) { return NGX_OK; @@ -170,7 +171,7 @@ ngx_ssl_stapling(ngx_conf_t *cf, ngx_ssl return NGX_ERROR; } - rc = ngx_ssl_stapling_responder(cf, ssl, responder); + rc = ngx_ssl_stapling_responder(cf, ssl, staple, responder); if (rc == NGX_DECLINED) { return NGX_OK; @@ -190,15 +191,13 @@ done: static ngx_int_t -ngx_ssl_stapling_file(ngx_conf_t *cf, ngx_ssl_t *ssl, ngx_str_t *file) +ngx_ssl_stapling_file(ngx_conf_t *cf, ngx_ssl_t *ssl, + ngx_ssl_stapling_t *staple, ngx_str_t *file) { - BIO *bio; - int len; - u_char *p, *buf; - OCSP_RESPONSE *response; - ngx_ssl_stapling_t *staple; - - staple = SSL_CTX_get_ex_data(ssl->ctx, ngx_ssl_stapling_index); + BIO *bio; + int len; + u_char *p, *buf; + OCSP_RESPONSE *response; if (ngx_conf_full_name(cf->cycle, file, 1) != NGX_OK) { return NGX_ERROR; @@ -259,16 +258,15 @@ failed: static ngx_int_t -ngx_ssl_stapling_issuer(ngx_conf_t *cf, ngx_ssl_t *ssl) +ngx_ssl_stapling_issuer(ngx_conf_t *cf, ngx_ssl_t *ssl, + ngx_ssl_stapling_t *staple) { - int i, n, rc; - X509 *cert, *issuer; - X509_STORE *store; - X509_STORE_CTX *store_ctx; - STACK_OF(X509) *chain; - ngx_ssl_stapling_t *staple; + int i, n, rc; + X509 *cert, *issuer; + X509_STORE *store; + X509_STORE_CTX *store_ctx; + STACK_OF(X509) *chain; - staple = SSL_CTX_get_ex_data(ssl->ctx, ngx_ssl_stapling_index); cert = SSL_CTX_get_ex_data(ssl->ctx, ngx_ssl_certificate_index); #if OPENSSL_VERSION_NUMBER >= 0x10001000L @@ -351,15 +349,13 @@ ngx_ssl_stapling_issuer(ngx_conf_t *cf, static ngx_int_t -ngx_ssl_stapling_responder(ngx_conf_t *cf, ngx_ssl_t *ssl, ngx_str_t *responder) +ngx_ssl_stapling_responder(ngx_conf_t *cf, ngx_ssl_t *ssl, + ngx_ssl_stapling_t *staple, ngx_str_t *responder) { ngx_url_t u; char *s; - ngx_ssl_stapling_t *staple; STACK_OF(OPENSSL_STRING) *aia; - staple = SSL_CTX_get_ex_data(ssl->ctx, ngx_ssl_stapling_index); - if (responder->len == 0) { /* extract OCSP responder URL from certificate */ From mdounin at mdounin.ru Thu May 19 17:30:14 2016 From: mdounin at mdounin.ru (Maxim Dounin) Date: Thu, 19 May 2016 17:30:14 +0000 Subject: [nginx] OCSP stapling: staple now stored in certificate, not SSL context. Message-ID: details: http://hg.nginx.org/nginx/rev/a873b4d9cd80 branches: changeset: 6545:a873b4d9cd80 user: Maxim Dounin date: Thu May 19 14:46:32 2016 +0300 description: OCSP stapling: staple now stored in certificate, not SSL context. diffstat: src/event/ngx_event_openssl.c | 7 +++---- src/event/ngx_event_openssl_stapling.c | 19 ++++++++++--------- 2 files changed, 13 insertions(+), 13 deletions(-) diffs (90 lines): diff --git a/src/event/ngx_event_openssl.c b/src/event/ngx_event_openssl.c --- a/src/event/ngx_event_openssl.c +++ b/src/event/ngx_event_openssl.c @@ -187,11 +187,10 @@ ngx_ssl_init(ngx_log_t *log) return NGX_ERROR; } - ngx_ssl_stapling_index = SSL_CTX_get_ex_new_index(0, NULL, NULL, NULL, - NULL); + ngx_ssl_stapling_index = X509_get_ex_new_index(0, NULL, NULL, NULL, NULL); + if (ngx_ssl_stapling_index == -1) { - ngx_ssl_error(NGX_LOG_ALERT, log, 0, - "SSL_CTX_get_ex_new_index() failed"); + ngx_ssl_error(NGX_LOG_ALERT, log, 0, "X509_get_ex_new_index() failed"); return NGX_ERROR; } 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 @@ -122,6 +122,7 @@ 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) { + X509 *cert; ngx_int_t rc; ngx_pool_cleanup_t *cln; ngx_ssl_stapling_t *staple; @@ -139,17 +140,17 @@ ngx_ssl_stapling(ngx_conf_t *cf, ngx_ssl cln->handler = ngx_ssl_stapling_cleanup; cln->data = staple; - if (SSL_CTX_set_ex_data(ssl->ctx, ngx_ssl_stapling_index, staple) - == 0) - { - ngx_ssl_error(NGX_LOG_EMERG, ssl->log, 0, - "SSL_CTX_set_ex_data() failed"); + cert = SSL_CTX_get_ex_data(ssl->ctx, ngx_ssl_certificate_index); + + if (X509_set_ex_data(cert, ngx_ssl_stapling_index, staple) == 0) { + ngx_ssl_error(NGX_LOG_EMERG, ssl->log, 0, "X509_set_ex_data() failed"); return NGX_ERROR; } staple->ssl_ctx = ssl->ctx; staple->timeout = 60000; staple->verify = verify; + staple->cert = cert; if (file->len) { /* use OCSP response from the file */ @@ -267,7 +268,7 @@ ngx_ssl_stapling_issuer(ngx_conf_t *cf, X509_STORE_CTX *store_ctx; STACK_OF(X509) *chain; - cert = SSL_CTX_get_ex_data(ssl->ctx, ngx_ssl_certificate_index); + cert = staple->cert; #if OPENSSL_VERSION_NUMBER >= 0x10001000L SSL_CTX_get_extra_chain_certs(ssl->ctx, &chain); @@ -292,7 +293,6 @@ ngx_ssl_stapling_issuer(ngx_conf_t *cf, ngx_log_debug1(NGX_LOG_DEBUG_EVENT, ssl->log, 0, "SSL get issuer: found %p in extra certs", issuer); - staple->cert = cert; staple->issuer = issuer; return NGX_OK; @@ -341,7 +341,6 @@ ngx_ssl_stapling_issuer(ngx_conf_t *cf, ngx_log_debug1(NGX_LOG_DEBUG_EVENT, ssl->log, 0, "SSL get issuer: found %p in cert store", issuer); - staple->cert = cert; staple->issuer = issuer; return NGX_OK; @@ -439,9 +438,11 @@ ngx_int_t ngx_ssl_stapling_resolver(ngx_conf_t *cf, ngx_ssl_t *ssl, ngx_resolver_t *resolver, ngx_msec_t resolver_timeout) { + X509 *cert; ngx_ssl_stapling_t *staple; - staple = SSL_CTX_get_ex_data(ssl->ctx, ngx_ssl_stapling_index); + cert = SSL_CTX_get_ex_data(ssl->ctx, ngx_ssl_certificate_index); + staple = X509_get_ex_data(cert, ngx_ssl_stapling_index); staple->resolver = resolver; staple->resolver_timeout = resolver_timeout; From mdounin at mdounin.ru Thu May 19 17:30:17 2016 From: mdounin at mdounin.ru (Maxim Dounin) Date: Thu, 19 May 2016 17:30:17 +0000 Subject: [nginx] OCSP stapling: staple now extracted via SSL_get_certificate(). Message-ID: details: http://hg.nginx.org/nginx/rev/a2d5d45f1525 branches: changeset: 6546:a2d5d45f1525 user: Maxim Dounin date: Thu May 19 14:46:32 2016 +0300 description: OCSP stapling: staple now extracted via SSL_get_certificate(). This makes it possible to properly return OCSP staple with multiple certificates configured. Note that it only works properly in OpenSSL 1.0.1d+, 1.0.0k, 0.9.8y+. In older versions SSL_get_certificate() fails to return correct certificate when the certificate status callback is called. diffstat: src/event/ngx_event_openssl_stapling.c | 10 ++++++++-- 1 files changed, 8 insertions(+), 2 deletions(-) diffs (36 lines): 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 @@ -185,7 +185,6 @@ ngx_ssl_stapling(ngx_conf_t *cf, ngx_ssl done: SSL_CTX_set_tlsext_status_cb(ssl->ctx, ngx_ssl_certificate_status_callback); - SSL_CTX_set_tlsext_status_arg(ssl->ctx, staple); return NGX_OK; } @@ -455,6 +454,7 @@ static int ngx_ssl_certificate_status_callback(ngx_ssl_conn_t *ssl_conn, void *data) { int rc; + X509 *cert; u_char *p; ngx_connection_t *c; ngx_ssl_stapling_t *staple; @@ -464,9 +464,15 @@ ngx_ssl_certificate_status_callback(ngx_ ngx_log_debug0(NGX_LOG_DEBUG_EVENT, c->log, 0, "SSL certificate status callback"); - staple = data; rc = SSL_TLSEXT_ERR_NOACK; + cert = SSL_get_certificate(ssl_conn); + staple = X509_get_ex_data(cert, ngx_ssl_stapling_index); + + if (staple == NULL) { + return rc; + } + if (staple->staple.len && staple->valid >= ngx_time()) { From mdounin at mdounin.ru Thu May 19 17:30:19 2016 From: mdounin at mdounin.ru (Maxim Dounin) Date: Thu, 19 May 2016 17:30:19 +0000 Subject: [nginx] OCSP stapling: additional function to configure stapling on a cert. Message-ID: details: http://hg.nginx.org/nginx/rev/e222a97d46c1 branches: changeset: 6547:e222a97d46c1 user: Maxim Dounin date: Thu May 19 14:46:32 2016 +0300 description: OCSP stapling: additional function to configure stapling on a cert. diffstat: src/event/ngx_event_openssl_stapling.c | 37 +++++++++++++++++++++++---------- 1 files changed, 26 insertions(+), 11 deletions(-) diffs (75 lines): 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 @@ -83,6 +83,8 @@ struct ngx_ssl_ocsp_ctx_s { }; +static ngx_int_t ngx_ssl_stapling_certificate(ngx_conf_t *cf, ngx_ssl_t *ssl, + X509 *cert, ngx_str_t *file, ngx_str_t *responder, ngx_uint_t verify); static ngx_int_t ngx_ssl_stapling_file(ngx_conf_t *cf, ngx_ssl_t *ssl, ngx_ssl_stapling_t *staple, ngx_str_t *file); static ngx_int_t ngx_ssl_stapling_issuer(ngx_conf_t *cf, ngx_ssl_t *ssl, @@ -122,10 +124,29 @@ 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) { - X509 *cert; - ngx_int_t rc; - ngx_pool_cleanup_t *cln; - ngx_ssl_stapling_t *staple; + X509 *cert; + + cert = SSL_CTX_get_ex_data(ssl->ctx, ngx_ssl_certificate_index); + + if (ngx_ssl_stapling_certificate(cf, ssl, cert, file, responder, verify) + != NGX_OK) + { + return NGX_ERROR; + } + + SSL_CTX_set_tlsext_status_cb(ssl->ctx, ngx_ssl_certificate_status_callback); + + return NGX_OK; +} + + +static ngx_int_t +ngx_ssl_stapling_certificate(ngx_conf_t *cf, ngx_ssl_t *ssl, X509 *cert, + ngx_str_t *file, ngx_str_t *responder, ngx_uint_t verify) +{ + ngx_int_t rc; + ngx_pool_cleanup_t *cln; + ngx_ssl_stapling_t *staple; staple = ngx_pcalloc(cf->pool, sizeof(ngx_ssl_stapling_t)); if (staple == NULL) { @@ -140,8 +161,6 @@ ngx_ssl_stapling(ngx_conf_t *cf, ngx_ssl cln->handler = ngx_ssl_stapling_cleanup; cln->data = staple; - cert = SSL_CTX_get_ex_data(ssl->ctx, ngx_ssl_certificate_index); - if (X509_set_ex_data(cert, ngx_ssl_stapling_index, staple) == 0) { ngx_ssl_error(NGX_LOG_EMERG, ssl->log, 0, "X509_set_ex_data() failed"); return NGX_ERROR; @@ -159,7 +178,7 @@ ngx_ssl_stapling(ngx_conf_t *cf, ngx_ssl return NGX_ERROR; } - goto done; + return NGX_OK; } rc = ngx_ssl_stapling_issuer(cf, ssl, staple); @@ -182,10 +201,6 @@ ngx_ssl_stapling(ngx_conf_t *cf, ngx_ssl return NGX_ERROR; } -done: - - SSL_CTX_set_tlsext_status_cb(ssl->ctx, ngx_ssl_certificate_status_callback); - return NGX_OK; } From mdounin at mdounin.ru Thu May 19 17:30:22 2016 From: mdounin at mdounin.ru (Maxim Dounin) Date: Thu, 19 May 2016 17:30:22 +0000 Subject: [nginx] SSL: made it possible to iterate though all certificates. Message-ID: details: http://hg.nginx.org/nginx/rev/8a34e92d8ab5 branches: changeset: 6548:8a34e92d8ab5 user: Maxim Dounin date: Thu May 19 14:46:32 2016 +0300 description: SSL: made it possible to iterate though all certificates. A pointer to a previously configured certificate now stored in a certificate. This makes it possible to iterate though all certificates configured in the SSL context. This is now used to configure OCSP stapling for all certificates, and in ngx_ssl_session_id_context(). As SSL_CTX_use_certificate() frees previously loaded certificate of the same type, and we have no way to find out if it's the case, X509_free() calls are now posponed till ngx_ssl_cleanup_ctx(). Note that in OpenSSL 1.0.2+ this can be done without storing things in exdata using the SSL_CTX_set_current_cert() and SSL_CTX_get0_certificate() functions. These are not yet available in all supported versions though, so it's easier to continue to use exdata for now. diffstat: src/event/ngx_event_openssl.c | 65 ++++++++++++++++++++++++++------- src/event/ngx_event_openssl.h | 1 + src/event/ngx_event_openssl_stapling.c | 26 ++++++++----- 3 files changed, 67 insertions(+), 25 deletions(-) diffs (179 lines): diff --git a/src/event/ngx_event_openssl.c b/src/event/ngx_event_openssl.c --- a/src/event/ngx_event_openssl.c +++ b/src/event/ngx_event_openssl.c @@ -105,6 +105,7 @@ int ngx_ssl_server_conf_index; int ngx_ssl_session_cache_index; int ngx_ssl_session_ticket_keys_index; int ngx_ssl_certificate_index; +int ngx_ssl_next_certificate_index; int ngx_ssl_stapling_index; @@ -187,6 +188,13 @@ ngx_ssl_init(ngx_log_t *log) return NGX_ERROR; } + ngx_ssl_next_certificate_index = X509_get_ex_new_index(0, NULL, NULL, NULL, + NULL); + if (ngx_ssl_next_certificate_index == -1) { + ngx_ssl_error(NGX_LOG_ALERT, log, 0, "X509_get_ex_new_index() failed"); + return NGX_ERROR; + } + ngx_ssl_stapling_index = X509_get_ex_new_index(0, NULL, NULL, NULL, NULL); if (ngx_ssl_stapling_index == -1) { @@ -214,6 +222,12 @@ ngx_ssl_create(ngx_ssl_t *ssl, ngx_uint_ return NGX_ERROR; } + if (SSL_CTX_set_ex_data(ssl->ctx, ngx_ssl_certificate_index, NULL) == 0) { + ngx_ssl_error(NGX_LOG_EMERG, ssl->log, 0, + "SSL_CTX_set_ex_data() failed"); + return NGX_ERROR; + } + ssl->buffer_size = NGX_SSL_BUFSIZE; /* client side options */ @@ -350,6 +364,16 @@ ngx_ssl_certificate(ngx_conf_t *cf, ngx_ return NGX_ERROR; } + if (X509_set_ex_data(x509, ngx_ssl_next_certificate_index, + SSL_CTX_get_ex_data(ssl->ctx, ngx_ssl_certificate_index)) + == 0) + { + ngx_ssl_error(NGX_LOG_EMERG, ssl->log, 0, "X509_set_ex_data() failed"); + X509_free(x509); + BIO_free(bio); + return NGX_ERROR; + } + if (SSL_CTX_set_ex_data(ssl->ctx, ngx_ssl_certificate_index, x509) == 0) { @@ -360,8 +384,6 @@ ngx_ssl_certificate(ngx_conf_t *cf, ngx_ return NGX_ERROR; } - X509_free(x509); - /* read rest of the chain */ for ( ;; ) { @@ -2163,7 +2185,7 @@ ngx_ssl_session_id_context(ngx_ssl_t *ss /* * Session ID context is set based on the string provided, - * the server certificate, and the client CA list. + * the server certificates, and the client CA list. */ md = EVP_MD_CTX_create(); @@ -2183,18 +2205,21 @@ ngx_ssl_session_id_context(ngx_ssl_t *ss goto failed; } - cert = SSL_CTX_get_ex_data(ssl->ctx, ngx_ssl_certificate_index); - - if (X509_digest(cert, EVP_sha1(), buf, &len) == 0) { - ngx_ssl_error(NGX_LOG_EMERG, ssl->log, 0, - "X509_digest() failed"); - goto failed; - } - - if (EVP_DigestUpdate(md, buf, len) == 0) { - ngx_ssl_error(NGX_LOG_EMERG, ssl->log, 0, - "EVP_DigestUpdate() failed"); - goto failed; + 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 (X509_digest(cert, EVP_sha1(), buf, &len) == 0) { + ngx_ssl_error(NGX_LOG_EMERG, ssl->log, 0, + "X509_digest() failed"); + goto failed; + } + + if (EVP_DigestUpdate(md, buf, len) == 0) { + ngx_ssl_error(NGX_LOG_EMERG, ssl->log, 0, + "EVP_DigestUpdate() failed"); + goto failed; + } } list = SSL_CTX_get_client_CA_list(ssl->ctx); @@ -2950,6 +2975,16 @@ ngx_ssl_cleanup_ctx(void *data) { ngx_ssl_t *ssl = data; + X509 *cert, *next; + + cert = SSL_CTX_get_ex_data(ssl->ctx, ngx_ssl_certificate_index); + + while (cert) { + next = X509_get_ex_data(cert, ngx_ssl_next_certificate_index); + X509_free(cert); + cert = next; + } + SSL_CTX_free(ssl->ctx); } 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 @@ -227,6 +227,7 @@ extern int ngx_ssl_server_conf_index; extern int ngx_ssl_session_cache_index; extern int ngx_ssl_session_ticket_keys_index; extern int ngx_ssl_certificate_index; +extern int ngx_ssl_next_certificate_index; extern int ngx_ssl_stapling_index; 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 @@ -126,12 +126,15 @@ ngx_ssl_stapling(ngx_conf_t *cf, ngx_ssl { X509 *cert; - cert = SSL_CTX_get_ex_data(ssl->ctx, ngx_ssl_certificate_index); - - 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, file, responder, verify) + != NGX_OK) + { + return NGX_ERROR; + } } SSL_CTX_set_tlsext_status_cb(ssl->ctx, ngx_ssl_certificate_status_callback); @@ -455,11 +458,14 @@ ngx_ssl_stapling_resolver(ngx_conf_t *cf X509 *cert; ngx_ssl_stapling_t *staple; - cert = SSL_CTX_get_ex_data(ssl->ctx, ngx_ssl_certificate_index); - staple = X509_get_ex_data(cert, ngx_ssl_stapling_index); - - staple->resolver = resolver; - staple->resolver_timeout = resolver_timeout; + 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)) + { + staple = X509_get_ex_data(cert, ngx_ssl_stapling_index); + staple->resolver = resolver; + staple->resolver_timeout = resolver_timeout; + } return NGX_OK; } From mdounin at mdounin.ru Thu May 19 17:30:24 2016 From: mdounin at mdounin.ru (Maxim Dounin) Date: Thu, 19 May 2016 17:30:24 +0000 Subject: [nginx] SSL: support for per-certificate chains. Message-ID: details: http://hg.nginx.org/nginx/rev/d3302eb87a0c branches: changeset: 6549:d3302eb87a0c user: Maxim Dounin date: Thu May 19 14:46:32 2016 +0300 description: SSL: support for per-certificate chains. The SSL_CTX_add0_chain_cert() function as introduced in OpenSSL 1.0.2 now used instead of SSL_CTX_add_extra_chain_cert(). SSL_CTX_add_extra_chain_cert() adds extra certs for all certificates in the context, while SSL_CTX_add0_chain_cert() only to a particular certificate. There is no difference unless multiple certificates are used, though it is important when using multiple certificates. Additionally, SSL_CTX_select_current_cert() is now called before using a chain to make sure correct chain will be returned. diffstat: src/event/ngx_event_openssl.c | 19 +++++++++++++++++++ src/event/ngx_event_openssl_stapling.c | 16 ++++++++++++++-- 2 files changed, 33 insertions(+), 2 deletions(-) diffs (69 lines): diff --git a/src/event/ngx_event_openssl.c b/src/event/ngx_event_openssl.c --- a/src/event/ngx_event_openssl.c +++ b/src/event/ngx_event_openssl.c @@ -408,6 +408,24 @@ ngx_ssl_certificate(ngx_conf_t *cf, ngx_ return NGX_ERROR; } +#ifdef SSL_CTRL_CHAIN_CERT + + /* + * SSL_CTX_add0_chain_cert() is needed to add chain to + * a particular certificate when multiple certificates are used; + * only available in OpenSSL 1.0.2+ + */ + + if (SSL_CTX_add0_chain_cert(ssl->ctx, x509) == 0) { + ngx_ssl_error(NGX_LOG_EMERG, ssl->log, 0, + "SSL_CTX_add0_chain_cert(\"%s\") failed", + cert->data); + X509_free(x509); + BIO_free(bio); + return NGX_ERROR; + } + +#else if (SSL_CTX_add_extra_chain_cert(ssl->ctx, x509) == 0) { ngx_ssl_error(NGX_LOG_EMERG, ssl->log, 0, "SSL_CTX_add_extra_chain_cert(\"%s\") failed", @@ -416,6 +434,7 @@ ngx_ssl_certificate(ngx_conf_t *cf, ngx_ BIO_free(bio); return NGX_ERROR; } +#endif } BIO_free(bio); 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 @@ -287,7 +287,13 @@ ngx_ssl_stapling_issuer(ngx_conf_t *cf, cert = staple->cert; -#if OPENSSL_VERSION_NUMBER >= 0x10001000L +#ifdef SSL_CTRL_SELECT_CURRENT_CERT + /* OpenSSL 1.0.2+ */ + SSL_CTX_select_current_cert(ssl->ctx, cert); +#endif + +#ifdef SSL_CTRL_GET_EXTRA_CHAIN_CERTS + /* OpenSSL 1.0.1+ */ SSL_CTX_get_extra_chain_certs(ssl->ctx, &chain); #else chain = ssl->ctx->extra_certs; @@ -621,7 +627,13 @@ ngx_ssl_stapling_ocsp_handler(ngx_ssl_oc goto error; } -#if OPENSSL_VERSION_NUMBER >= 0x10001000L +#ifdef SSL_CTRL_SELECT_CURRENT_CERT + /* OpenSSL 1.0.2+ */ + SSL_CTX_select_current_cert(staple->ssl_ctx, ctx->cert); +#endif + +#ifdef SSL_CTRL_GET_EXTRA_CHAIN_CERTS + /* OpenSSL 1.0.1+ */ SSL_CTX_get_extra_chain_certs(staple->ssl_ctx, &chain); #else chain = staple->ssl_ctx->extra_certs; From mdounin at mdounin.ru Thu May 19 17:30:27 2016 From: mdounin at mdounin.ru (Maxim Dounin) Date: Thu, 19 May 2016 17:30:27 +0000 Subject: [nginx] SSL: support for multiple certificates (ticket #814). Message-ID: details: http://hg.nginx.org/nginx/rev/51e1f047d15d branches: changeset: 6550:51e1f047d15d user: Maxim Dounin date: Thu May 19 14:46:32 2016 +0300 description: SSL: support for multiple certificates (ticket #814). diffstat: src/event/ngx_event_openssl.c | 23 +++++++++++++++++ src/event/ngx_event_openssl.h | 2 + src/http/modules/ngx_http_ssl_module.c | 46 ++++++++++++++++++++++----------- src/http/modules/ngx_http_ssl_module.h | 5 ++- src/mail/ngx_mail_ssl_module.c | 45 ++++++++++++++++++++++----------- src/mail/ngx_mail_ssl_module.h | 5 ++- src/stream/ngx_stream_ssl_module.c | 30 ++++++++++++--------- src/stream/ngx_stream_ssl_module.h | 5 ++- 8 files changed, 112 insertions(+), 49 deletions(-) diffs (413 lines): diff --git a/src/event/ngx_event_openssl.c b/src/event/ngx_event_openssl.c --- a/src/event/ngx_event_openssl.c +++ b/src/event/ngx_event_openssl.c @@ -322,6 +322,29 @@ ngx_ssl_create(ngx_ssl_t *ssl, ngx_uint_ ngx_int_t +ngx_ssl_certificates(ngx_conf_t *cf, ngx_ssl_t *ssl, ngx_array_t *certs, + ngx_array_t *keys, ngx_array_t *passwords) +{ + ngx_str_t *cert, *key; + ngx_uint_t i; + + cert = certs->elts; + key = keys->elts; + + for (i = 0; i < certs->nelts; i++) { + + if (ngx_ssl_certificate(cf, ssl, &cert[i], &key[i], passwords) + != NGX_OK) + { + return NGX_ERROR; + } + } + + return NGX_OK; +} + + +ngx_int_t ngx_ssl_certificate(ngx_conf_t *cf, ngx_ssl_t *ssl, ngx_str_t *cert, ngx_str_t *key, ngx_array_t *passwords) { 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 @@ -140,6 +140,8 @@ typedef struct { ngx_int_t ngx_ssl_init(ngx_log_t *log); ngx_int_t ngx_ssl_create(ngx_ssl_t *ssl, ngx_uint_t protocols, void *data); +ngx_int_t ngx_ssl_certificates(ngx_conf_t *cf, ngx_ssl_t *ssl, + ngx_array_t *certs, ngx_array_t *keys, ngx_array_t *passwords); ngx_int_t ngx_ssl_certificate(ngx_conf_t *cf, ngx_ssl_t *ssl, ngx_str_t *cert, ngx_str_t *key, ngx_array_t *passwords); ngx_int_t ngx_ssl_client_certificate(ngx_conf_t *cf, ngx_ssl_t *ssl, 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 @@ -81,16 +81,16 @@ static ngx_command_t ngx_http_ssl_comma { ngx_string("ssl_certificate"), 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, certificate), + offsetof(ngx_http_ssl_srv_conf_t, certificates), NULL }, { ngx_string("ssl_certificate_key"), 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, certificate_key), + offsetof(ngx_http_ssl_srv_conf_t, certificate_keys), NULL }, { ngx_string("ssl_password_file"), @@ -508,8 +508,6 @@ ngx_http_ssl_create_srv_conf(ngx_conf_t * set by ngx_pcalloc(): * * sscf->protocols = 0; - * sscf->certificate = { 0, NULL }; - * sscf->certificate_key = { 0, NULL }; * sscf->dhparam = { 0, NULL }; * sscf->ecdh_curve = { 0, NULL }; * sscf->client_certificate = { 0, NULL }; @@ -526,6 +524,8 @@ ngx_http_ssl_create_srv_conf(ngx_conf_t 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; @@ -573,8 +573,9 @@ ngx_http_ssl_merge_srv_conf(ngx_conf_t * ngx_conf_merge_uint_value(conf->verify, prev->verify, 0); ngx_conf_merge_uint_value(conf->verify_depth, prev->verify_depth, 1); - ngx_conf_merge_str_value(conf->certificate, prev->certificate, ""); - ngx_conf_merge_str_value(conf->certificate_key, prev->certificate_key, ""); + ngx_conf_merge_ptr_value(conf->certificates, prev->certificates, NULL); + ngx_conf_merge_ptr_value(conf->certificate_keys, prev->certificate_keys, + NULL); ngx_conf_merge_ptr_value(conf->passwords, prev->passwords, NULL); @@ -601,7 +602,7 @@ ngx_http_ssl_merge_srv_conf(ngx_conf_t * if (conf->enable) { - if (conf->certificate.len == 0) { + if (conf->certificates == NULL) { ngx_log_error(NGX_LOG_EMERG, cf->log, 0, "no \"ssl_certificate\" is defined for " "the \"ssl\" directive in %s:%ui", @@ -609,7 +610,7 @@ ngx_http_ssl_merge_srv_conf(ngx_conf_t * return NGX_CONF_ERROR; } - if (conf->certificate_key.len == 0) { + if (conf->certificate_keys == NULL) { ngx_log_error(NGX_LOG_EMERG, cf->log, 0, "no \"ssl_certificate_key\" is defined for " "the \"ssl\" directive in %s:%ui", @@ -617,16 +618,31 @@ ngx_http_ssl_merge_srv_conf(ngx_conf_t * return NGX_CONF_ERROR; } + if (conf->certificate_keys->nelts < conf->certificates->nelts) { + ngx_log_error(NGX_LOG_EMERG, cf->log, 0, + "no \"ssl_certificate_key\" is defined " + "for certificate \"%V\" and " + "the \"ssl\" directive in %s:%ui", + ((ngx_str_t *) conf->certificates->elts) + + conf->certificates->nelts - 1, + conf->file, conf->line); + return NGX_CONF_ERROR; + } + } else { - if (conf->certificate.len == 0) { + if (conf->certificates == NULL) { return NGX_CONF_OK; } - if (conf->certificate_key.len == 0) { + if (conf->certificate_keys == NULL + || conf->certificate_keys->nelts < conf->certificates->nelts) + { ngx_log_error(NGX_LOG_EMERG, cf->log, 0, "no \"ssl_certificate_key\" is defined " - "for certificate \"%V\"", &conf->certificate); + "for certificate \"%V\"", + ((ngx_str_t *) conf->certificates->elts) + + conf->certificates->nelts - 1); return NGX_CONF_ERROR; } } @@ -666,8 +682,8 @@ ngx_http_ssl_merge_srv_conf(ngx_conf_t * cln->handler = ngx_ssl_cleanup_ctx; cln->data = &conf->ssl; - if (ngx_ssl_certificate(cf, &conf->ssl, &conf->certificate, - &conf->certificate_key, conf->passwords) + if (ngx_ssl_certificates(cf, &conf->ssl, conf->certificates, + conf->certificate_keys, conf->passwords) != 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 @@ -32,8 +32,9 @@ typedef struct { time_t session_timeout; - ngx_str_t certificate; - ngx_str_t certificate_key; + ngx_array_t *certificates; + ngx_array_t *certificate_keys; + ngx_str_t dhparam; ngx_str_t ecdh_curve; ngx_str_t client_certificate; diff --git a/src/mail/ngx_mail_ssl_module.c b/src/mail/ngx_mail_ssl_module.c --- a/src/mail/ngx_mail_ssl_module.c +++ b/src/mail/ngx_mail_ssl_module.c @@ -73,16 +73,16 @@ static ngx_command_t ngx_mail_ssl_comma { ngx_string("ssl_certificate"), NGX_MAIL_MAIN_CONF|NGX_MAIL_SRV_CONF|NGX_CONF_TAKE1, - ngx_conf_set_str_slot, + ngx_conf_set_str_array_slot, NGX_MAIL_SRV_CONF_OFFSET, - offsetof(ngx_mail_ssl_conf_t, certificate), + offsetof(ngx_mail_ssl_conf_t, certificates), NULL }, { ngx_string("ssl_certificate_key"), NGX_MAIL_MAIN_CONF|NGX_MAIL_SRV_CONF|NGX_CONF_TAKE1, - ngx_conf_set_str_slot, + ngx_conf_set_str_array_slot, NGX_MAIL_SRV_CONF_OFFSET, - offsetof(ngx_mail_ssl_conf_t, certificate_key), + offsetof(ngx_mail_ssl_conf_t, certificate_keys), NULL }, { ngx_string("ssl_password_file"), @@ -238,8 +238,6 @@ ngx_mail_ssl_create_conf(ngx_conf_t *cf) * set by ngx_pcalloc(): * * scf->protocols = 0; - * scf->certificate = { 0, NULL }; - * scf->certificate_key = { 0, NULL }; * scf->dhparam = { 0, NULL }; * scf->ecdh_curve = { 0, NULL }; * scf->client_certificate = { 0, NULL }; @@ -251,6 +249,8 @@ ngx_mail_ssl_create_conf(ngx_conf_t *cf) scf->enable = NGX_CONF_UNSET; scf->starttls = NGX_CONF_UNSET_UINT; + scf->certificates = NGX_CONF_UNSET_PTR; + scf->certificate_keys = NGX_CONF_UNSET_PTR; scf->passwords = NGX_CONF_UNSET_PTR; scf->prefer_server_ciphers = NGX_CONF_UNSET; scf->verify = NGX_CONF_UNSET_UINT; @@ -290,8 +290,9 @@ ngx_mail_ssl_merge_conf(ngx_conf_t *cf, ngx_conf_merge_uint_value(conf->verify, prev->verify, 0); ngx_conf_merge_uint_value(conf->verify_depth, prev->verify_depth, 1); - ngx_conf_merge_str_value(conf->certificate, prev->certificate, ""); - ngx_conf_merge_str_value(conf->certificate_key, prev->certificate_key, ""); + ngx_conf_merge_ptr_value(conf->certificates, prev->certificates, NULL); + ngx_conf_merge_ptr_value(conf->certificate_keys, prev->certificate_keys, + NULL); ngx_conf_merge_ptr_value(conf->passwords, prev->passwords, NULL); @@ -328,7 +329,7 @@ ngx_mail_ssl_merge_conf(ngx_conf_t *cf, if (*mode) { - if (conf->certificate.len == 0) { + if (conf->certificates == NULL) { ngx_log_error(NGX_LOG_EMERG, cf->log, 0, "no \"ssl_certificate\" is defined for " "the \"%s\" directive in %s:%ui", @@ -336,7 +337,7 @@ ngx_mail_ssl_merge_conf(ngx_conf_t *cf, return NGX_CONF_ERROR; } - if (conf->certificate_key.len == 0) { + if (conf->certificate_keys == NULL) { ngx_log_error(NGX_LOG_EMERG, cf->log, 0, "no \"ssl_certificate_key\" is defined for " "the \"%s\" directive in %s:%ui", @@ -344,17 +345,31 @@ ngx_mail_ssl_merge_conf(ngx_conf_t *cf, return NGX_CONF_ERROR; } + if (conf->certificate_keys->nelts < conf->certificates->nelts) { + ngx_log_error(NGX_LOG_EMERG, cf->log, 0, + "no \"ssl_certificate_key\" is defined " + "for certificate \"%V\" and " + "the \"ssl\" directive in %s:%ui", + ((ngx_str_t *) conf->certificates->elts) + + conf->certificates->nelts - 1, + conf->file, conf->line); + return NGX_CONF_ERROR; + } + } else { - if (conf->certificate.len == 0) { + if (conf->certificates == NULL) { return NGX_CONF_OK; } - if (conf->certificate_key.len == 0) { + if (conf->certificate_keys == NULL + || conf->certificate_keys->nelts < conf->certificates->nelts) + { ngx_log_error(NGX_LOG_EMERG, cf->log, 0, "no \"ssl_certificate_key\" is defined " "for certificate \"%V\"", - &conf->certificate); + ((ngx_str_t *) conf->certificates->elts) + + conf->certificates->nelts - 1); return NGX_CONF_ERROR; } } @@ -371,8 +386,8 @@ ngx_mail_ssl_merge_conf(ngx_conf_t *cf, cln->handler = ngx_ssl_cleanup_ctx; cln->data = &conf->ssl; - if (ngx_ssl_certificate(cf, &conf->ssl, &conf->certificate, - &conf->certificate_key, conf->passwords) + if (ngx_ssl_certificates(cf, &conf->ssl, conf->certificates, + conf->certificate_keys, conf->passwords) != NGX_OK) { return NGX_CONF_ERROR; diff --git a/src/mail/ngx_mail_ssl_module.h b/src/mail/ngx_mail_ssl_module.h --- a/src/mail/ngx_mail_ssl_module.h +++ b/src/mail/ngx_mail_ssl_module.h @@ -35,8 +35,9 @@ typedef struct { time_t session_timeout; - ngx_str_t certificate; - ngx_str_t certificate_key; + ngx_array_t *certificates; + ngx_array_t *certificate_keys; + ngx_str_t dhparam; ngx_str_t ecdh_curve; ngx_str_t client_certificate; diff --git a/src/stream/ngx_stream_ssl_module.c b/src/stream/ngx_stream_ssl_module.c --- a/src/stream/ngx_stream_ssl_module.c +++ b/src/stream/ngx_stream_ssl_module.c @@ -45,16 +45,16 @@ static ngx_command_t ngx_stream_ssl_com { ngx_string("ssl_certificate"), NGX_STREAM_MAIN_CONF|NGX_STREAM_SRV_CONF|NGX_CONF_TAKE1, - ngx_conf_set_str_slot, + ngx_conf_set_str_array_slot, NGX_STREAM_SRV_CONF_OFFSET, - offsetof(ngx_stream_ssl_conf_t, certificate), + offsetof(ngx_stream_ssl_conf_t, certificates), NULL }, { ngx_string("ssl_certificate_key"), NGX_STREAM_MAIN_CONF|NGX_STREAM_SRV_CONF|NGX_CONF_TAKE1, - ngx_conf_set_str_slot, + ngx_conf_set_str_array_slot, NGX_STREAM_SRV_CONF_OFFSET, - offsetof(ngx_stream_ssl_conf_t, certificate_key), + offsetof(ngx_stream_ssl_conf_t, certificate_keys), NULL }, { ngx_string("ssl_password_file"), @@ -175,8 +175,6 @@ ngx_stream_ssl_create_conf(ngx_conf_t *c * set by ngx_pcalloc(): * * scf->protocols = 0; - * scf->certificate = { 0, NULL }; - * scf->certificate_key = { 0, NULL }; * scf->dhparam = { 0, NULL }; * scf->ecdh_curve = { 0, NULL }; * scf->ciphers = { 0, NULL }; @@ -184,6 +182,8 @@ ngx_stream_ssl_create_conf(ngx_conf_t *c */ scf->handshake_timeout = NGX_CONF_UNSET_MSEC; + scf->certificates = NGX_CONF_UNSET_PTR; + scf->certificate_keys = NGX_CONF_UNSET_PTR; scf->passwords = NGX_CONF_UNSET_PTR; scf->prefer_server_ciphers = NGX_CONF_UNSET; scf->builtin_session_cache = NGX_CONF_UNSET; @@ -216,8 +216,9 @@ ngx_stream_ssl_merge_conf(ngx_conf_t *cf (NGX_CONF_BITMASK_SET|NGX_SSL_TLSv1 |NGX_SSL_TLSv1_1|NGX_SSL_TLSv1_2)); - ngx_conf_merge_str_value(conf->certificate, prev->certificate, ""); - ngx_conf_merge_str_value(conf->certificate_key, prev->certificate_key, ""); + ngx_conf_merge_ptr_value(conf->certificates, prev->certificates, NULL); + ngx_conf_merge_ptr_value(conf->certificate_keys, prev->certificate_keys, + NULL); ngx_conf_merge_ptr_value(conf->passwords, prev->passwords, NULL); @@ -231,15 +232,18 @@ ngx_stream_ssl_merge_conf(ngx_conf_t *cf conf->ssl.log = cf->log; - if (conf->certificate.len == 0) { + if (conf->certificates == NULL) { return NGX_CONF_OK; } - if (conf->certificate_key.len == 0) { + if (conf->certificate_keys == NULL + || conf->certificate_keys->nelts < conf->certificates->nelts) + { ngx_log_error(NGX_LOG_EMERG, cf->log, 0, "no \"ssl_certificate_key\" is defined " "for certificate \"%V\"", - &conf->certificate); + ((ngx_str_t *) conf->certificates->elts) + + conf->certificates->nelts - 1); return NGX_CONF_ERROR; } @@ -255,8 +259,8 @@ ngx_stream_ssl_merge_conf(ngx_conf_t *cf cln->handler = ngx_ssl_cleanup_ctx; cln->data = &conf->ssl; - if (ngx_ssl_certificate(cf, &conf->ssl, &conf->certificate, - &conf->certificate_key, conf->passwords) + if (ngx_ssl_certificates(cf, &conf->ssl, conf->certificates, + conf->certificate_keys, conf->passwords) != NGX_OK) { return NGX_CONF_ERROR; diff --git a/src/stream/ngx_stream_ssl_module.h b/src/stream/ngx_stream_ssl_module.h --- a/src/stream/ngx_stream_ssl_module.h +++ b/src/stream/ngx_stream_ssl_module.h @@ -27,8 +27,9 @@ typedef struct { time_t session_timeout; - ngx_str_t certificate; - ngx_str_t certificate_key; + ngx_array_t *certificates; + ngx_array_t *certificate_keys; + ngx_str_t dhparam; ngx_str_t ecdh_curve; From mdounin at mdounin.ru Thu May 19 17:30:29 2016 From: mdounin at mdounin.ru (Maxim Dounin) Date: Thu, 19 May 2016 17:30:29 +0000 Subject: [nginx] SSL: error messages style. Message-ID: details: http://hg.nginx.org/nginx/rev/62f99a890754 branches: changeset: 6551:62f99a890754 user: Maxim Dounin date: Thu May 19 14:46:32 2016 +0300 description: SSL: error messages style. diffstat: src/event/ngx_event_openssl.c | 4 ++-- 1 files changed, 2 insertions(+), 2 deletions(-) diffs (20 lines): diff --git a/src/event/ngx_event_openssl.c b/src/event/ngx_event_openssl.c --- a/src/event/ngx_event_openssl.c +++ b/src/event/ngx_event_openssl.c @@ -1076,14 +1076,14 @@ ngx_ssl_ecdh_curve(ngx_conf_t *cf, ngx_s nid = OBJ_sn2nid((const char *) name->data); if (nid == 0) { ngx_ssl_error(NGX_LOG_EMERG, ssl->log, 0, - "Unknown curve name \"%s\"", name->data); + "OBJ_sn2nid(\"%s\") failed: unknown curve", name->data); return NGX_ERROR; } ecdh = EC_KEY_new_by_curve_name(nid); if (ecdh == NULL) { ngx_ssl_error(NGX_LOG_EMERG, ssl->log, 0, - "Unable to create curve \"%s\"", name->data); + "EC_KEY_new_by_curve_name(\"%s\") failed", name->data); return NGX_ERROR; } From mdounin at mdounin.ru Thu May 19 17:30:32 2016 From: mdounin at mdounin.ru (Maxim Dounin) Date: Thu, 19 May 2016 17:30:32 +0000 Subject: [nginx] SSL: style. Message-ID: details: http://hg.nginx.org/nginx/rev/addd98357629 branches: changeset: 6552:addd98357629 user: Maxim Dounin date: Thu May 19 14:46:32 2016 +0300 description: SSL: style. diffstat: src/event/ngx_event_openssl.c | 8 ++++---- 1 files changed, 4 insertions(+), 4 deletions(-) diffs (35 lines): diff --git a/src/event/ngx_event_openssl.c b/src/event/ngx_event_openssl.c --- a/src/event/ngx_event_openssl.c +++ b/src/event/ngx_event_openssl.c @@ -1069,11 +1069,11 @@ ngx_ssl_ecdh_curve(ngx_conf_t *cf, ngx_s /* * Elliptic-Curve Diffie-Hellman parameters are either "named curves" * from RFC 4492 section 5.1.1, or explicitly described curves over - * binary fields. OpenSSL only supports the "named curves", which provide + * binary fields. OpenSSL only supports the "named curves", which provide * maximum interoperability. */ - nid = OBJ_sn2nid((const char *) name->data); + nid = OBJ_sn2nid((char *) name->data); if (nid == 0) { ngx_ssl_error(NGX_LOG_EMERG, ssl->log, 0, "OBJ_sn2nid(\"%s\") failed: unknown curve", name->data); @@ -2165,7 +2165,7 @@ ngx_ssl_session_cache(ngx_ssl_t *ssl, ng * session reuse (see SSL_SESS_CACHE_OFF above), then * Outlook Express fails to upload a sent email to * the Sent Items folder on the IMAP server via a separate IMAP - * connection in the background. Therefore we have a special + * connection in the background. Therefore we have a special * mode (SSL_SESS_CACHE_SERVER|SSL_SESS_CACHE_NO_INTERNAL_STORE) * where the server pretends that it supports session reuse, * but it does not actually store any session. @@ -3602,7 +3602,7 @@ ngx_openssl_engine(ngx_conf_t *cf, ngx_c value = cf->args->elts; - engine = ENGINE_by_id((const char *) value[1].data); + engine = ENGINE_by_id((char *) value[1].data); if (engine == NULL) { ngx_ssl_error(NGX_LOG_WARN, cf->log, 0, From mdounin at mdounin.ru Thu May 19 17:30:34 2016 From: mdounin at mdounin.ru (Maxim Dounin) Date: Thu, 19 May 2016 17:30:34 +0000 Subject: [nginx] SSL: support for multiple curves (ticket #885). Message-ID: details: http://hg.nginx.org/nginx/rev/2014ed60f17f branches: changeset: 6553:2014ed60f17f user: Maxim Dounin date: Thu May 19 14:46:32 2016 +0300 description: SSL: support for multiple curves (ticket #885). OpenSSL 1.0.2+ allows configuring a curve list instead of a single curve previously supported. This allows use of different curves depending on what client supports (as available via the elliptic_curves extension), and also allows use of different curves in an ECDHE key exchange and in the ECDSA certificate. The special value "auto" was introduced (now the default for ssl_ecdh_curve), which means "use an internal list of curves as available in the OpenSSL library used". For versions prior to OpenSSL 1.0.2 it maps to "prime256v1" as previously used. The default in 1.0.2b+ prefers prime256v1 as well (and X25519 in OpenSSL 1.1.0+). As client vs. server preference of curves is controlled by the same option as used for ciphers (SSL_OP_CIPHER_SERVER_PREFERENCE), the ssl_prefer_server_ciphers directive now controls both. diffstat: src/event/ngx_event_openssl.c | 53 ++++++++++++++++++++++++++++++--- src/http/modules/ngx_http_ssl_module.c | 2 +- src/mail/ngx_mail_ssl_module.c | 2 +- src/stream/ngx_stream_ssl_module.c | 2 +- 4 files changed, 51 insertions(+), 8 deletions(-) diffs (121 lines): diff --git a/src/event/ngx_event_openssl.c b/src/event/ngx_event_openssl.c --- a/src/event/ngx_event_openssl.c +++ b/src/event/ngx_event_openssl.c @@ -1063,8 +1063,6 @@ ngx_ssl_ecdh_curve(ngx_conf_t *cf, ngx_s { #if OPENSSL_VERSION_NUMBER >= 0x0090800fL #ifndef OPENSSL_NO_ECDH - int nid; - EC_KEY *ecdh; /* * Elliptic-Curve Diffie-Hellman parameters are either "named curves" @@ -1073,17 +1071,61 @@ ngx_ssl_ecdh_curve(ngx_conf_t *cf, ngx_s * maximum interoperability. */ - nid = OBJ_sn2nid((char *) name->data); +#ifdef SSL_CTRL_SET_CURVES_LIST + + /* + * OpenSSL 1.0.2+ allows configuring a curve list instead of a single + * curve previously supported. By default an internal list is used, + * with prime256v1 being preferred by server in OpenSSL 1.0.2b+ + * and X25519 in OpenSSL 1.1.0+. + * + * By default a curve preferred by the client will be used for + * key exchange. The SSL_OP_CIPHER_SERVER_PREFERENCE option can + * be used to prefer server curves instead, similar to what it + * does for ciphers. + */ + + SSL_CTX_set_options(ssl->ctx, SSL_OP_SINGLE_ECDH_USE); + +#if SSL_CTRL_SET_ECDH_AUTO + /* not needed in OpenSSL 1.1.0+ */ + SSL_CTX_set_ecdh_auto(ssl->ctx, 1); +#endif + + if (ngx_strcmp(name->data, "auto") == 0) { + return NGX_OK; + } + + if (SSL_CTX_set1_curves_list(ssl->ctx, (char *) name->data) == 0) { + ngx_ssl_error(NGX_LOG_EMERG, ssl->log, 0, + "SSL_CTX_set1_curves_list(\"%s\") failed", name->data); + return NGX_ERROR; + } + +#else + + int nid; + char *curve; + EC_KEY *ecdh; + + if (ngx_strcmp(name->data, "auto") == 0) { + curve = "prime256v1"; + + } else { + curve = (char *) name->data; + } + + nid = OBJ_sn2nid(curve); if (nid == 0) { ngx_ssl_error(NGX_LOG_EMERG, ssl->log, 0, - "OBJ_sn2nid(\"%s\") failed: unknown curve", name->data); + "OBJ_sn2nid(\"%s\") failed: unknown curve", curve); return NGX_ERROR; } ecdh = EC_KEY_new_by_curve_name(nid); if (ecdh == NULL) { ngx_ssl_error(NGX_LOG_EMERG, ssl->log, 0, - "EC_KEY_new_by_curve_name(\"%s\") failed", name->data); + "EC_KEY_new_by_curve_name(\"%s\") failed", curve); return NGX_ERROR; } @@ -1094,6 +1136,7 @@ ngx_ssl_ecdh_curve(ngx_conf_t *cf, ngx_s EC_KEY_free(ecdh); #endif #endif +#endif 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 @@ -15,7 +15,7 @@ typedef ngx_int_t (*ngx_ssl_variable_han #define NGX_DEFAULT_CIPHERS "HIGH:!aNULL:!MD5" -#define NGX_DEFAULT_ECDH_CURVE "prime256v1" +#define NGX_DEFAULT_ECDH_CURVE "auto" #define NGX_HTTP_NPN_ADVERTISE "\x08http/1.1" diff --git a/src/mail/ngx_mail_ssl_module.c b/src/mail/ngx_mail_ssl_module.c --- a/src/mail/ngx_mail_ssl_module.c +++ b/src/mail/ngx_mail_ssl_module.c @@ -11,7 +11,7 @@ #define NGX_DEFAULT_CIPHERS "HIGH:!aNULL:!MD5" -#define NGX_DEFAULT_ECDH_CURVE "prime256v1" +#define NGX_DEFAULT_ECDH_CURVE "auto" static void *ngx_mail_ssl_create_conf(ngx_conf_t *cf); diff --git a/src/stream/ngx_stream_ssl_module.c b/src/stream/ngx_stream_ssl_module.c --- a/src/stream/ngx_stream_ssl_module.c +++ b/src/stream/ngx_stream_ssl_module.c @@ -11,7 +11,7 @@ #define NGX_DEFAULT_CIPHERS "HIGH:!aNULL:!MD5" -#define NGX_DEFAULT_ECDH_CURVE "prime256v1" +#define NGX_DEFAULT_ECDH_CURVE "auto" static void *ngx_stream_ssl_create_conf(ngx_conf_t *cf); From mdounin at mdounin.ru Thu May 19 17:30:37 2016 From: mdounin at mdounin.ru (Maxim Dounin) Date: Thu, 19 May 2016 17:30:37 +0000 Subject: [nginx] SSL: removed default DH parameters. Message-ID: details: http://hg.nginx.org/nginx/rev/1aa9650a8154 branches: changeset: 6554:1aa9650a8154 user: Maxim Dounin date: Thu May 19 14:46:32 2016 +0300 description: SSL: removed default DH parameters. Using the same DH parameters on multiple servers is believed to be subject to precomputation attacks, see http://weakdh.org/. Additionally, 1024 bits are not enough in the modern world as well. Let users provide their own DH parameters with the ssl_dhparam directive if they want to use EDH ciphers. Note that SSL_CTX_set_dh_auto() as provided by OpenSSL 1.1.0 uses fixed DH parameters from RFC 5114 and RFC 3526, and therefore subject to the same precomputation attacks. We avoid using it as well. This change also fixes compilation with OpenSSL 1.1.0-pre5 (aka Beta 2), as OpenSSL developers changed their policy after releasing Beta 1 and broke API once again by making the DH struct opaque (see ticket #860). diffstat: src/event/ngx_event_openssl.c | 45 ------------------------------------------- 1 files changed, 0 insertions(+), 45 deletions(-) diffs (56 lines): diff --git a/src/event/ngx_event_openssl.c b/src/event/ngx_event_openssl.c --- a/src/event/ngx_event_openssl.c +++ b/src/event/ngx_event_openssl.c @@ -981,52 +981,7 @@ ngx_ssl_dhparam(ngx_conf_t *cf, ngx_ssl_ DH *dh; BIO *bio; - /* - * -----BEGIN DH PARAMETERS----- - * MIGHAoGBALu8LcrYRnSQfEP89YDpz9vZWKP1aLQtSwju1OsPs1BMbAMCducQgAxc - * y7qokiYUxb7spWWl/fHSh6K8BJvmd4Bg6RqSp1fjBI9osHb302zI8pul34HcLKcl - * 7OZicMyaUDXYzs7vnqAnSmOrHlj6/UmI0PZdFGdX2gcd8EXP4WubAgEC - * -----END DH PARAMETERS----- - */ - - static unsigned char dh1024_p[] = { - 0xBB, 0xBC, 0x2D, 0xCA, 0xD8, 0x46, 0x74, 0x90, 0x7C, 0x43, 0xFC, 0xF5, - 0x80, 0xE9, 0xCF, 0xDB, 0xD9, 0x58, 0xA3, 0xF5, 0x68, 0xB4, 0x2D, 0x4B, - 0x08, 0xEE, 0xD4, 0xEB, 0x0F, 0xB3, 0x50, 0x4C, 0x6C, 0x03, 0x02, 0x76, - 0xE7, 0x10, 0x80, 0x0C, 0x5C, 0xCB, 0xBA, 0xA8, 0x92, 0x26, 0x14, 0xC5, - 0xBE, 0xEC, 0xA5, 0x65, 0xA5, 0xFD, 0xF1, 0xD2, 0x87, 0xA2, 0xBC, 0x04, - 0x9B, 0xE6, 0x77, 0x80, 0x60, 0xE9, 0x1A, 0x92, 0xA7, 0x57, 0xE3, 0x04, - 0x8F, 0x68, 0xB0, 0x76, 0xF7, 0xD3, 0x6C, 0xC8, 0xF2, 0x9B, 0xA5, 0xDF, - 0x81, 0xDC, 0x2C, 0xA7, 0x25, 0xEC, 0xE6, 0x62, 0x70, 0xCC, 0x9A, 0x50, - 0x35, 0xD8, 0xCE, 0xCE, 0xEF, 0x9E, 0xA0, 0x27, 0x4A, 0x63, 0xAB, 0x1E, - 0x58, 0xFA, 0xFD, 0x49, 0x88, 0xD0, 0xF6, 0x5D, 0x14, 0x67, 0x57, 0xDA, - 0x07, 0x1D, 0xF0, 0x45, 0xCF, 0xE1, 0x6B, 0x9B - }; - - static unsigned char dh1024_g[] = { 0x02 }; - - if (file->len == 0) { - - dh = DH_new(); - if (dh == NULL) { - ngx_ssl_error(NGX_LOG_EMERG, ssl->log, 0, "DH_new() failed"); - return NGX_ERROR; - } - - dh->p = BN_bin2bn(dh1024_p, sizeof(dh1024_p), NULL); - dh->g = BN_bin2bn(dh1024_g, sizeof(dh1024_g), NULL); - - if (dh->p == NULL || dh->g == NULL) { - ngx_ssl_error(NGX_LOG_EMERG, ssl->log, 0, "BN_bin2bn() failed"); - DH_free(dh); - return NGX_ERROR; - } - - SSL_CTX_set_tmp_dh(ssl->ctx, dh); - - DH_free(dh); - return NGX_OK; } From giovani.rinaldi at azion.com Fri May 20 12:42:03 2016 From: giovani.rinaldi at azion.com (Giovani Rinaldi) Date: Fri, 20 May 2016 09:42:03 -0300 Subject: How to retrieve information about cache expiration? Message-ID: Hello, I'm trying to retrieve information regarding the number of times a cache file is expired (either forced, due to cache pressure, or not, such as time expiration). I've noticed that the cache manager process logs this info when configured with debug level for the error.log directive. An example is the following line: [debug] 5461#5461: http file cache expire: "/data/nginx/cache/c/1b/cc1651d5d24be40ce402c4e583cd01bc" I see, currently, two possible ways of achieving such goal. One is parsing the log file (using a cyclic memory buffer configured to a tmpfs/ramfs, as described in http://nginx.org/en/docs/debugging_log.html#memory) with an external executable, in order to not increase IO ops or delay the cache processing under high load. Another option would be to develop a module that would be called by the cache manager process every time its event loop executes, so it could access to the memory log, parse it and count the amount of times an expiration occurred. Although it is my understanding that current module hooks only allow access to memory (including the log struct) allocated by the worker process, I wonder if there is any other way to hook external code into the cache manager process (maybe by overloading some global static struct that contains any function declaration pertaining to the log or cache managing module?). Is there any better way of achieving this goal? If not, are any of these two approaches doable/recommended? Any advice would be most welcome. The NGINX version I'm currently using is the 1.8.1, and altering its code (such as patching any original source code) is something I would like to avoid at all costs. Thanks in advance. Giovani. -------------- next part -------------- An HTML attachment was scrubbed... URL: From ru at nginx.com Fri May 20 14:05:24 2016 From: ru at nginx.com (Ruslan Ermilov) Date: Fri, 20 May 2016 14:05:24 +0000 Subject: [nginx] Belatedly changed the ngx_create_listening() prototype. Message-ID: details: http://hg.nginx.org/nginx/rev/090a78da4f88 branches: changeset: 6555:090a78da4f88 user: Ruslan Ermilov date: Fri May 20 17:02:04 2016 +0300 description: Belatedly changed the ngx_create_listening() prototype. The function is called only with "struct sockaddr *" since 0.7.58. diffstat: src/core/ngx_connection.c | 3 ++- src/core/ngx_connection.h | 2 +- 2 files changed, 3 insertions(+), 2 deletions(-) diffs (25 lines): diff -r 1aa9650a8154 -r 090a78da4f88 src/core/ngx_connection.c --- a/src/core/ngx_connection.c Thu May 19 14:46:32 2016 +0300 +++ b/src/core/ngx_connection.c Fri May 20 17:02:04 2016 +0300 @@ -17,7 +17,8 @@ static void ngx_drain_connections(void); ngx_listening_t * -ngx_create_listening(ngx_conf_t *cf, void *sockaddr, socklen_t socklen) +ngx_create_listening(ngx_conf_t *cf, struct sockaddr *sockaddr, + socklen_t socklen) { size_t len; ngx_listening_t *ls; diff -r 1aa9650a8154 -r 090a78da4f88 src/core/ngx_connection.h --- a/src/core/ngx_connection.h Thu May 19 14:46:32 2016 +0300 +++ b/src/core/ngx_connection.h Fri May 20 17:02:04 2016 +0300 @@ -210,7 +210,7 @@ struct ngx_connection_s { } -ngx_listening_t *ngx_create_listening(ngx_conf_t *cf, void *sockaddr, +ngx_listening_t *ngx_create_listening(ngx_conf_t *cf, struct sockaddr *sockaddr, socklen_t socklen); ngx_int_t ngx_clone_listening(ngx_conf_t *cf, ngx_listening_t *ls); ngx_int_t ngx_set_inherited_sockets(ngx_cycle_t *cycle); From vbart at nginx.com Fri May 20 15:46:08 2016 From: vbart at nginx.com (Valentin Bartenev) Date: Fri, 20 May 2016 15:46:08 +0000 Subject: [nginx] HTTP/2: the "421 Misdirected Request" response (closes #848). Message-ID: details: http://hg.nginx.org/nginx/rev/654d2dae97d3 branches: changeset: 6556:654d2dae97d3 user: Valentin Bartenev date: Fri May 20 18:41:17 2016 +0300 description: HTTP/2: the "421 Misdirected Request" response (closes #848). Since 4fbef397c753 nginx rejects with the 400 error any attempts of requesting different host over the same connection, if the relevant virtual server requires verification of a client certificate. While requesting hosts other than negotiated isn't something legal in HTTP/1.x, the HTTP/2 specification explicitly permits such requests for connection reuse and has introduced a special response code 421. According to RFC 7540 Section 9.1.2 this code can be sent by a server that is not configured to produce responses for the combination of scheme and authority that are included in the request URI. And the client may retry the request over a different connection. Now this code is used for requests that aren't authorized in current connection. After receiving the 421 response a client will be able to open a new connection, provide the required certificate and retry the request. Unfortunately, not all clients currently are able to handle it well. Notably Chrome just shows an error, while at least the latest version of Firefox retries the request over a new connection. diffstat: src/http/ngx_http_header_filter_module.c | 14 +++++++------- src/http/ngx_http_request.c | 2 +- src/http/ngx_http_request.h | 1 + src/http/ngx_http_special_response.c | 15 ++++++++++++++- 4 files changed, 23 insertions(+), 9 deletions(-) diffs (95 lines): diff -r 090a78da4f88 -r 654d2dae97d3 src/http/ngx_http_header_filter_module.c --- a/src/http/ngx_http_header_filter_module.c Fri May 20 17:02:04 2016 +0300 +++ b/src/http/ngx_http_header_filter_module.c Fri May 20 18:41:17 2016 +0300 @@ -95,17 +95,17 @@ static ngx_str_t ngx_http_status_lines[] ngx_string("414 Request-URI Too Large"), ngx_string("415 Unsupported Media Type"), ngx_string("416 Requested Range Not Satisfiable"), + ngx_null_string, /* "417 Expectation Failed" */ + ngx_null_string, /* "418 unused" */ + ngx_null_string, /* "419 unused" */ + ngx_null_string, /* "420 unused" */ + ngx_string("421 Misdirected Request"), - /* ngx_null_string, */ /* "417 Expectation Failed" */ - /* ngx_null_string, */ /* "418 unused" */ - /* ngx_null_string, */ /* "419 unused" */ - /* ngx_null_string, */ /* "420 unused" */ - /* ngx_null_string, */ /* "421 unused" */ /* ngx_null_string, */ /* "422 Unprocessable Entity" */ /* ngx_null_string, */ /* "423 Locked" */ /* ngx_null_string, */ /* "424 Failed Dependency" */ -#define NGX_HTTP_LAST_4XX 417 +#define NGX_HTTP_LAST_4XX 422 #define NGX_HTTP_OFF_5XX (NGX_HTTP_LAST_4XX - 400 + NGX_HTTP_OFF_4XX) ngx_string("500 Internal Server Error"), @@ -113,10 +113,10 @@ static ngx_str_t ngx_http_status_lines[] ngx_string("502 Bad Gateway"), ngx_string("503 Service Temporarily Unavailable"), ngx_string("504 Gateway Time-out"), - ngx_null_string, /* "505 HTTP Version Not Supported" */ ngx_null_string, /* "506 Variant Also Negotiates" */ ngx_string("507 Insufficient Storage"), + /* ngx_null_string, */ /* "508 unused" */ /* ngx_null_string, */ /* "509 unused" */ /* ngx_null_string, */ /* "510 Not Extended" */ diff -r 090a78da4f88 -r 654d2dae97d3 src/http/ngx_http_request.c --- a/src/http/ngx_http_request.c Fri May 20 17:02:04 2016 +0300 +++ b/src/http/ngx_http_request.c Fri May 20 18:41:17 2016 +0300 @@ -2069,7 +2069,7 @@ ngx_http_set_virtual_server(ngx_http_req ngx_log_error(NGX_LOG_INFO, r->connection->log, 0, "client attempted to request the server name " "different from that one was negotiated"); - ngx_http_finalize_request(r, NGX_HTTP_BAD_REQUEST); + ngx_http_finalize_request(r, NGX_HTTP_MISDIRECTED_REQUEST); return NGX_ERROR; } } diff -r 090a78da4f88 -r 654d2dae97d3 src/http/ngx_http_request.h --- a/src/http/ngx_http_request.h Fri May 20 17:02:04 2016 +0300 +++ b/src/http/ngx_http_request.h Fri May 20 18:41:17 2016 +0300 @@ -95,6 +95,7 @@ #define NGX_HTTP_REQUEST_URI_TOO_LARGE 414 #define NGX_HTTP_UNSUPPORTED_MEDIA_TYPE 415 #define NGX_HTTP_RANGE_NOT_SATISFIABLE 416 +#define NGX_HTTP_MISDIRECTED_REQUEST 421 /* Our own HTTP codes */ diff -r 090a78da4f88 -r 654d2dae97d3 src/http/ngx_http_special_response.c --- a/src/http/ngx_http_special_response.c Fri May 20 17:02:04 2016 +0300 +++ b/src/http/ngx_http_special_response.c Fri May 20 18:41:17 2016 +0300 @@ -210,6 +210,14 @@ static char ngx_http_error_416_page[] = ; +static char ngx_http_error_421_page[] = +"" CRLF +"421 Misdirected Request" CRLF +"" CRLF +"

421 Misdirected Request

" CRLF +; + + static char ngx_http_error_494_page[] = "" CRLF "400 Request Header Or Cookie Too Large" @@ -334,8 +342,13 @@ static ngx_str_t ngx_http_error_pages[] ngx_string(ngx_http_error_414_page), ngx_string(ngx_http_error_415_page), ngx_string(ngx_http_error_416_page), + ngx_null_string, /* 417 */ + ngx_null_string, /* 418 */ + ngx_null_string, /* 419 */ + ngx_null_string, /* 420 */ + ngx_string(ngx_http_error_421_page), -#define NGX_HTTP_LAST_4XX 417 +#define NGX_HTTP_LAST_4XX 422 #define NGX_HTTP_OFF_5XX (NGX_HTTP_LAST_4XX - 400 + NGX_HTTP_OFF_4XX) ngx_string(ngx_http_error_494_page), /* 494, request header too large */ From ru at nginx.com Fri May 20 16:19:09 2016 From: ru at nginx.com (Ruslan Ermilov) Date: Fri, 20 May 2016 16:19:09 +0000 Subject: [nginx] Use ngx_cmp_sockaddr() where appropriate. Message-ID: details: http://hg.nginx.org/nginx/rev/6f8254ae61b8 branches: changeset: 6557:6f8254ae61b8 user: Ruslan Ermilov date: Fri May 20 19:10:42 2016 +0300 description: Use ngx_cmp_sockaddr() where appropriate. diffstat: src/http/ngx_http.c | 37 ++--------------------- src/http/ngx_http_core_module.h | 1 - src/mail/ngx_mail.h | 1 - src/mail/ngx_mail_core_module.c | 56 +++--------------------------------- src/stream/ngx_stream.h | 1 - src/stream/ngx_stream_core_module.c | 56 +++--------------------------------- 6 files changed, 16 insertions(+), 136 deletions(-) diffs (290 lines): diff -r 654d2dae97d3 -r 6f8254ae61b8 src/http/ngx_http.c --- a/src/http/ngx_http.c Fri May 20 18:41:17 2016 +0300 +++ b/src/http/ngx_http.c Fri May 20 19:10:42 2016 +0300 @@ -1215,14 +1215,8 @@ static ngx_int_t ngx_http_add_addresses(ngx_conf_t *cf, ngx_http_core_srv_conf_t *cscf, ngx_http_conf_port_t *port, ngx_http_listen_opt_t *lsopt) { - u_char *p; - size_t len, off; ngx_uint_t i, default_server, proxy_protocol; - struct sockaddr *sa; ngx_http_conf_addr_t *addr; -#if (NGX_HAVE_UNIX_DOMAIN) - struct sockaddr_un *saun; -#endif #if (NGX_HTTP_SSL) ngx_uint_t ssl; #endif @@ -1235,37 +1229,14 @@ ngx_http_add_addresses(ngx_conf_t *cf, n * may fill some fields in inherited sockaddr struct's */ - sa = &lsopt->u.sockaddr; - - switch (sa->sa_family) { - -#if (NGX_HAVE_INET6) - case AF_INET6: - off = offsetof(struct sockaddr_in6, sin6_addr); - len = 16; - break; -#endif - -#if (NGX_HAVE_UNIX_DOMAIN) - case AF_UNIX: - off = offsetof(struct sockaddr_un, sun_path); - len = sizeof(saun->sun_path); - break; -#endif - - default: /* AF_INET */ - off = offsetof(struct sockaddr_in, sin_addr); - len = 4; - break; - } - - p = lsopt->u.sockaddr_data + off; - addr = port->addrs.elts; for (i = 0; i < port->addrs.nelts; i++) { - if (ngx_memcmp(p, addr[i].opt.u.sockaddr_data + off, len) != 0) { + if (ngx_cmp_sockaddr(&lsopt->u.sockaddr, lsopt->socklen, + &addr[i].opt.u.sockaddr, addr[i].opt.socklen, 0) + != NGX_OK) + { continue; } diff -r 654d2dae97d3 -r 6f8254ae61b8 src/http/ngx_http_core_module.h --- a/src/http/ngx_http_core_module.h Fri May 20 18:41:17 2016 +0300 +++ b/src/http/ngx_http_core_module.h Fri May 20 19:10:42 2016 +0300 @@ -67,7 +67,6 @@ typedef struct { #if (NGX_HAVE_UNIX_DOMAIN) struct sockaddr_un sockaddr_un; #endif - u_char sockaddr_data[NGX_SOCKADDRLEN]; } u; socklen_t socklen; diff -r 654d2dae97d3 -r 6f8254ae61b8 src/mail/ngx_mail.h --- a/src/mail/ngx_mail.h Fri May 20 18:41:17 2016 +0300 +++ b/src/mail/ngx_mail.h Fri May 20 19:10:42 2016 +0300 @@ -36,7 +36,6 @@ typedef struct { #if (NGX_HAVE_UNIX_DOMAIN) struct sockaddr_un sockaddr_un; #endif - u_char sockaddr_data[NGX_SOCKADDRLEN]; } u; socklen_t socklen; diff -r 654d2dae97d3 -r 6f8254ae61b8 src/mail/ngx_mail_core_module.c --- a/src/mail/ngx_mail_core_module.c Fri May 20 18:41:17 2016 +0300 +++ b/src/mail/ngx_mail_core_module.c Fri May 20 19:10:42 2016 +0300 @@ -288,19 +288,12 @@ ngx_mail_core_listen(ngx_conf_t *cf, ngx { ngx_mail_core_srv_conf_t *cscf = conf; - size_t len, off; - in_port_t port; ngx_str_t *value; ngx_url_t u; ngx_uint_t i, m; - struct sockaddr *sa; ngx_mail_listen_t *ls; ngx_mail_module_t *module; - struct sockaddr_in *sin; ngx_mail_core_main_conf_t *cmcf; -#if (NGX_HAVE_INET6) - struct sockaddr_in6 *sin6; -#endif value = cf->args->elts; @@ -325,49 +318,13 @@ ngx_mail_core_listen(ngx_conf_t *cf, ngx for (i = 0; i < cmcf->listen.nelts; i++) { - sa = &ls[i].u.sockaddr; - - if (sa->sa_family != u.family) { - continue; - } - - switch (sa->sa_family) { - -#if (NGX_HAVE_INET6) - case AF_INET6: - off = offsetof(struct sockaddr_in6, sin6_addr); - len = 16; - sin6 = &ls[i].u.sockaddr_in6; - port = ntohs(sin6->sin6_port); - break; -#endif - -#if (NGX_HAVE_UNIX_DOMAIN) - case AF_UNIX: - off = offsetof(struct sockaddr_un, sun_path); - len = sizeof(((struct sockaddr_un *) sa)->sun_path); - port = 0; - break; -#endif - - default: /* AF_INET */ - off = offsetof(struct sockaddr_in, sin_addr); - len = 4; - sin = &ls[i].u.sockaddr_in; - port = ntohs(sin->sin_port); - break; - } - - if (ngx_memcmp(ls[i].u.sockaddr_data + off, u.sockaddr + off, len) - != 0) + if (ngx_cmp_sockaddr(&ls[i].u.sockaddr, ls[i].socklen, + (struct sockaddr *) &u.sockaddr, u.socklen, 1) + != NGX_OK) { continue; } - if (port != u.port) { - continue; - } - ngx_conf_log_error(NGX_LOG_EMERG, cf, 0, "duplicate \"%V\" address and port pair", &u.url); return NGX_CONF_ERROR; @@ -434,11 +391,10 @@ ngx_mail_core_listen(ngx_conf_t *cf, ngx if (ngx_strncmp(value[i].data, "ipv6only=o", 10) == 0) { #if (NGX_HAVE_INET6 && defined IPV6_V6ONLY) + size_t len; u_char buf[NGX_SOCKADDR_STRLEN]; - sa = &ls->u.sockaddr; - - if (sa->sa_family == AF_INET6) { + if (ls->u.sockaddr.sa_family == AF_INET6) { if (ngx_strcmp(&value[i].data[10], "n") == 0) { ls->ipv6only = 1; @@ -456,7 +412,7 @@ ngx_mail_core_listen(ngx_conf_t *cf, ngx ls->bind = 1; } else { - len = ngx_sock_ntop(sa, ls->socklen, buf, + len = ngx_sock_ntop(&ls->u.sockaddr, ls->socklen, buf, NGX_SOCKADDR_STRLEN, 1); ngx_conf_log_error(NGX_LOG_EMERG, cf, 0, diff -r 654d2dae97d3 -r 6f8254ae61b8 src/stream/ngx_stream.h --- a/src/stream/ngx_stream.h Fri May 20 18:41:17 2016 +0300 +++ b/src/stream/ngx_stream.h Fri May 20 19:10:42 2016 +0300 @@ -40,7 +40,6 @@ typedef struct { #if (NGX_HAVE_UNIX_DOMAIN) struct sockaddr_un sockaddr_un; #endif - u_char sockaddr_data[NGX_SOCKADDRLEN]; } u; socklen_t socklen; diff -r 654d2dae97d3 -r 6f8254ae61b8 src/stream/ngx_stream_core_module.c --- a/src/stream/ngx_stream_core_module.c Fri May 20 18:41:17 2016 +0300 +++ b/src/stream/ngx_stream_core_module.c Fri May 20 19:10:42 2016 +0300 @@ -248,18 +248,11 @@ ngx_stream_core_server(ngx_conf_t *cf, n static char * ngx_stream_core_listen(ngx_conf_t *cf, ngx_command_t *cmd, void *conf) { - size_t len, off; - in_port_t port; ngx_str_t *value; ngx_url_t u; ngx_uint_t i, backlog; - struct sockaddr *sa; - struct sockaddr_in *sin; ngx_stream_listen_t *ls; ngx_stream_core_main_conf_t *cmcf; -#if (NGX_HAVE_INET6) - struct sockaddr_in6 *sin6; -#endif value = cf->args->elts; @@ -284,49 +277,13 @@ ngx_stream_core_listen(ngx_conf_t *cf, n for (i = 0; i < cmcf->listen.nelts; i++) { - sa = &ls[i].u.sockaddr; - - if (sa->sa_family != u.family) { - continue; - } - - switch (sa->sa_family) { - -#if (NGX_HAVE_INET6) - case AF_INET6: - off = offsetof(struct sockaddr_in6, sin6_addr); - len = 16; - sin6 = &ls[i].u.sockaddr_in6; - port = sin6->sin6_port; - break; -#endif - -#if (NGX_HAVE_UNIX_DOMAIN) - case AF_UNIX: - off = offsetof(struct sockaddr_un, sun_path); - len = sizeof(((struct sockaddr_un *) sa)->sun_path); - port = 0; - break; -#endif - - default: /* AF_INET */ - off = offsetof(struct sockaddr_in, sin_addr); - len = 4; - sin = &ls[i].u.sockaddr_in; - port = sin->sin_port; - break; - } - - if (ngx_memcmp(ls[i].u.sockaddr_data + off, u.sockaddr + off, len) - != 0) + if (ngx_cmp_sockaddr(&ls[i].u.sockaddr, ls[i].socklen, + (struct sockaddr *) &u.sockaddr, u.socklen, 1) + != NGX_OK) { continue; } - if (port != u.port) { - continue; - } - ngx_conf_log_error(NGX_LOG_EMERG, cf, 0, "duplicate \"%V\" address and port pair", &u.url); return NGX_CONF_ERROR; @@ -384,11 +341,10 @@ ngx_stream_core_listen(ngx_conf_t *cf, n if (ngx_strncmp(value[i].data, "ipv6only=o", 10) == 0) { #if (NGX_HAVE_INET6 && defined IPV6_V6ONLY) + size_t len; u_char buf[NGX_SOCKADDR_STRLEN]; - sa = &ls->u.sockaddr; - - if (sa->sa_family == AF_INET6) { + if (ls->u.sockaddr.sa_family == AF_INET6) { if (ngx_strcmp(&value[i].data[10], "n") == 0) { ls->ipv6only = 1; @@ -406,7 +362,7 @@ ngx_stream_core_listen(ngx_conf_t *cf, n ls->bind = 1; } else { - len = ngx_sock_ntop(sa, ls->socklen, buf, + len = ngx_sock_ntop(&ls->u.sockaddr, ls->socklen, buf, NGX_SOCKADDR_STRLEN, 1); ngx_conf_log_error(NGX_LOG_EMERG, cf, 0, From stephan at turbinelabs.io Fri May 20 18:24:33 2016 From: stephan at turbinelabs.io (Stephan Zuercher) Date: Fri, 20 May 2016 11:24:33 -0700 Subject: init_master patch? Message-ID: Hi, I see in the past there's been questions about ngx_module_t's init_master field never being called. I'm working on a plug-in that needs to execute code in the context of the master process (after it's forked to become a daemon) and init_master seems like the logical way to do it. If I contribute a change to call init_master, is it likely to be accepted? Or is there some fundamental reason not to do this? Thanks, Stephan -------------- next part -------------- An HTML attachment was scrubbed... URL: From alexandernst at gmail.com Sat May 21 10:11:43 2016 From: alexandernst at gmail.com (Alexander Nestorov (alexandernst)) Date: Sat, 21 May 2016 10:11:43 +0000 Subject: Image filter crop coordinates Message-ID: I'm assigned with a task at my work that would require me to implement crop coordinates/starting points. Are you willing to accept patches for such functionality or is this outside of the scope of what the images filter should be able to do? If you were to accept such patches, how should I implement such functionality? As a separate configuration directive (for example, "image_filter crop_coords x y;") or built in in the crop directive ("image_filter crop width height x y;")? Regards -------------- next part -------------- An HTML attachment was scrubbed... URL: From mdounin at mdounin.ru Sat May 21 20:22:21 2016 From: mdounin at mdounin.ru (Maxim Dounin) Date: Sat, 21 May 2016 23:22:21 +0300 Subject: init_master patch? In-Reply-To: References: Message-ID: <20160521202221.GJ36620@mdounin.ru> Hello! On Fri, May 20, 2016 at 11:24:33AM -0700, Stephan Zuercher wrote: > Hi, > > I see in the past there's been questions about ngx_module_t's init_master > field never being called. > > I'm working on a plug-in that needs to execute code in the context of the > master process (after it's forked to become a daemon) and init_master seems > like the logical way to do it. > > If I contribute a change to call init_master, is it likely to be accepted? > Or is there some fundamental reason not to do this? It's believed that init_master is a wrong thing to use in most cases. In particular, it won't work if a module will be loaded dynamically. If you think you need init_master - you may want to reconsider what you want to do and how to do it properly in nginx. -- Maxim Dounin http://nginx.org/ From pankajitbhu at gmail.com Mon May 23 07:01:00 2016 From: pankajitbhu at gmail.com (Pankaj Chaudhary) Date: Mon, 23 May 2016 12:31:00 +0530 Subject: reading config during run time Message-ID: Hi, In my module i want to read config values run time. is there method available in nginx which i can use. Please suggest. Regards, Pankaj -------------- next part -------------- An HTML attachment was scrubbed... URL: From ru at nginx.com Mon May 23 13:22:38 2016 From: ru at nginx.com (Ruslan Ermilov) Date: Mon, 23 May 2016 13:22:38 +0000 Subject: [nginx] Stream: fixed duplicate listen address detection. Message-ID: details: http://hg.nginx.org/nginx/rev/68854ce64ec7 branches: changeset: 6558:68854ce64ec7 user: Ruslan Ermilov date: Mon May 23 12:50:59 2016 +0300 description: Stream: fixed duplicate listen address detection. The 6f8254ae61b8 change inadvertently fixed the duplicate port detection similar to how it was fixed for mail in b2920b517490. It also revealed another issue: the socket type (tcp vs. udp) wasn't taken into account. diffstat: src/stream/ngx_stream_core_module.c | 37 ++++++++++++++++++++----------------- 1 files changed, 20 insertions(+), 17 deletions(-) diffs (60 lines): diff -r 6f8254ae61b8 -r 68854ce64ec7 src/stream/ngx_stream_core_module.c --- a/src/stream/ngx_stream_core_module.c Fri May 20 19:10:42 2016 +0300 +++ b/src/stream/ngx_stream_core_module.c Mon May 23 12:50:59 2016 +0300 @@ -251,7 +251,7 @@ ngx_stream_core_listen(ngx_conf_t *cf, n ngx_str_t *value; ngx_url_t u; ngx_uint_t i, backlog; - ngx_stream_listen_t *ls; + ngx_stream_listen_t *ls, *als; ngx_stream_core_main_conf_t *cmcf; value = cf->args->elts; @@ -273,22 +273,6 @@ ngx_stream_core_listen(ngx_conf_t *cf, n cmcf = ngx_stream_conf_get_module_main_conf(cf, ngx_stream_core_module); - ls = cmcf->listen.elts; - - for (i = 0; i < cmcf->listen.nelts; i++) { - - if (ngx_cmp_sockaddr(&ls[i].u.sockaddr, ls[i].socklen, - (struct sockaddr *) &u.sockaddr, u.socklen, 1) - != NGX_OK) - { - continue; - } - - ngx_conf_log_error(NGX_LOG_EMERG, cf, 0, - "duplicate \"%V\" address and port pair", &u.url); - return NGX_CONF_ERROR; - } - ls = ngx_array_push(&cmcf->listen); if (ls == NULL) { return NGX_CONF_ERROR; @@ -514,5 +498,24 @@ ngx_stream_core_listen(ngx_conf_t *cf, n } } + als = cmcf->listen.elts; + + for (i = 0; i < cmcf->listen.nelts - 1; i++) { + if (ls->type != als[i].type) { + continue; + } + + if (ngx_cmp_sockaddr(&als[i].u.sockaddr, als[i].socklen, + &ls->u.sockaddr, ls->socklen, 1) + != NGX_OK) + { + continue; + } + + ngx_conf_log_error(NGX_LOG_EMERG, cf, 0, + "duplicate \"%V\" address and port pair", &u.url); + return NGX_CONF_ERROR; + } + return NGX_CONF_OK; } From ru at nginx.com Mon May 23 13:37:57 2016 From: ru at nginx.com (Ruslan Ermilov) Date: Mon, 23 May 2016 13:37:57 +0000 Subject: [nginx] Introduced the ngx_sockaddr_t type. Message-ID: details: http://hg.nginx.org/nginx/rev/adf25b8d0431 branches: changeset: 6559:adf25b8d0431 user: Ruslan Ermilov date: Mon May 23 16:37:20 2016 +0300 description: Introduced the ngx_sockaddr_t type. It's properly aligned and can hold any supported sockaddr. diffstat: src/core/ngx_connection.c | 10 ++-- src/core/ngx_inet.c | 6 +- src/core/ngx_inet.h | 29 +++++++----- src/core/ngx_resolver.c | 42 +++++++++--------- src/event/ngx_event_accept.c | 17 +++---- src/http/modules/ngx_http_upstream_keepalive_module.c | 2 +- src/http/ngx_http_core_module.c | 2 +- src/http/ngx_http_core_module.h | 12 +---- src/mail/ngx_mail.h | 12 +---- src/mail/ngx_mail_core_module.c | 2 +- src/stream/ngx_stream.h | 12 +---- src/stream/ngx_stream_core_module.c | 2 +- 12 files changed, 60 insertions(+), 88 deletions(-) diffs (406 lines): diff -r 68854ce64ec7 -r adf25b8d0431 src/core/ngx_connection.c --- a/src/core/ngx_connection.c Mon May 23 12:50:59 2016 +0300 +++ b/src/core/ngx_connection.c Mon May 23 16:37:20 2016 +0300 @@ -151,12 +151,12 @@ ngx_set_inherited_sockets(ngx_cycle_t *c ls = cycle->listening.elts; for (i = 0; i < cycle->listening.nelts; i++) { - ls[i].sockaddr = ngx_palloc(cycle->pool, NGX_SOCKADDRLEN); + ls[i].sockaddr = ngx_palloc(cycle->pool, sizeof(ngx_sockaddr_t)); if (ls[i].sockaddr == NULL) { return NGX_ERROR; } - ls[i].socklen = NGX_SOCKADDRLEN; + ls[i].socklen = sizeof(ngx_sockaddr_t); if (getsockname(ls[i].fd, ls[i].sockaddr, &ls[i].socklen) == -1) { ngx_log_error(NGX_LOG_CRIT, cycle->log, ngx_socket_errno, "getsockname() of the inherited " @@ -1278,7 +1278,7 @@ ngx_connection_local_sockaddr(ngx_connec { socklen_t len; ngx_uint_t addr; - u_char sa[NGX_SOCKADDRLEN]; + ngx_sockaddr_t sa; struct sockaddr_in *sin; #if (NGX_HAVE_INET6) ngx_uint_t i; @@ -1316,9 +1316,9 @@ ngx_connection_local_sockaddr(ngx_connec if (addr == 0) { - len = NGX_SOCKADDRLEN; + len = sizeof(ngx_sockaddr_t); - if (getsockname(c->fd, (struct sockaddr *) &sa, &len) == -1) { + if (getsockname(c->fd, &sa.sockaddr, &len) == -1) { ngx_connection_error(c, ngx_socket_errno, "getsockname() failed"); return NGX_ERROR; } diff -r 68854ce64ec7 -r adf25b8d0431 src/core/ngx_inet.c --- a/src/core/ngx_inet.c Mon May 23 12:50:59 2016 +0300 +++ b/src/core/ngx_inet.c Mon May 23 16:37:20 2016 +0300 @@ -763,7 +763,7 @@ ngx_parse_inet_url(ngx_pool_t *pool, ngx return NGX_ERROR; } - ngx_memcpy(sin, u->sockaddr, sizeof(struct sockaddr_in)); + ngx_memcpy(sin, &u->sockaddr, sizeof(struct sockaddr_in)); u->addrs[0].sockaddr = (struct sockaddr *) sin; u->addrs[0].socklen = sizeof(struct sockaddr_in); @@ -790,7 +790,7 @@ ngx_parse_inet_url(ngx_pool_t *pool, ngx u->family = u->addrs[0].sockaddr->sa_family; u->socklen = u->addrs[0].socklen; - ngx_memcpy(u->sockaddr, u->addrs[0].sockaddr, u->addrs[0].socklen); + ngx_memcpy(&u->sockaddr, u->addrs[0].sockaddr, u->addrs[0].socklen); switch (u->family) { @@ -920,7 +920,7 @@ ngx_parse_inet6_url(ngx_pool_t *pool, ng return NGX_ERROR; } - ngx_memcpy(sin6, u->sockaddr, sizeof(struct sockaddr_in6)); + ngx_memcpy(sin6, &u->sockaddr, sizeof(struct sockaddr_in6)); u->addrs[0].sockaddr = (struct sockaddr *) sin6; u->addrs[0].socklen = sizeof(struct sockaddr_in6); diff -r 68854ce64ec7 -r adf25b8d0431 src/core/ngx_inet.h --- a/src/core/ngx_inet.h Mon May 23 12:50:59 2016 +0300 +++ b/src/core/ngx_inet.h Mon May 23 16:37:20 2016 +0300 @@ -13,14 +13,6 @@ #include -/* - * TODO: autoconfigure NGX_SOCKADDRLEN and NGX_SOCKADDR_STRLEN as - * sizeof(struct sockaddr_storage) - * sizeof(struct sockaddr_un) - * sizeof(struct sockaddr_in6) - * sizeof(struct sockaddr_in) - */ - #define NGX_INET_ADDRSTRLEN (sizeof("255.255.255.255") - 1) #define NGX_INET6_ADDRSTRLEN \ (sizeof("ffff:ffff:ffff:ffff:ffff:ffff:255.255.255.255") - 1) @@ -29,15 +21,26 @@ #if (NGX_HAVE_UNIX_DOMAIN) #define NGX_SOCKADDR_STRLEN (sizeof("unix:") - 1 + NGX_UNIX_ADDRSTRLEN) +#elif (NGX_HAVE_INET6) +#define NGX_SOCKADDR_STRLEN (NGX_INET6_ADDRSTRLEN + sizeof("[]:65535") - 1) #else -#define NGX_SOCKADDR_STRLEN (NGX_INET6_ADDRSTRLEN + sizeof("[]:65535") - 1) +#define NGX_SOCKADDR_STRLEN (NGX_INET_ADDRSTRLEN + sizeof(":65535") - 1) #endif +/* compatibility */ +#define NGX_SOCKADDRLEN sizeof(ngx_sockaddr_t) + + +typedef union { + struct sockaddr sockaddr; + struct sockaddr_in sockaddr_in; +#if (NGX_HAVE_INET6) + struct sockaddr_in6 sockaddr_in6; +#endif #if (NGX_HAVE_UNIX_DOMAIN) -#define NGX_SOCKADDRLEN sizeof(struct sockaddr_un) -#else -#define NGX_SOCKADDRLEN 512 + struct sockaddr_un sockaddr_un; #endif +} ngx_sockaddr_t; typedef struct { @@ -92,7 +95,7 @@ typedef struct { unsigned wildcard:1; socklen_t socklen; - u_char sockaddr[NGX_SOCKADDRLEN]; + ngx_sockaddr_t sockaddr; ngx_addr_t *addrs; ngx_uint_t naddrs; diff -r 68854ce64ec7 -r adf25b8d0431 src/core/ngx_resolver.c --- a/src/core/ngx_resolver.c Mon May 23 12:50:59 2016 +0300 +++ b/src/core/ngx_resolver.c Mon May 23 16:37:20 2016 +0300 @@ -2992,15 +2992,15 @@ failed: static void ngx_resolver_srv_names_handler(ngx_resolver_ctx_t *cctx) { - ngx_uint_t i; - u_char (*sockaddr)[NGX_SOCKADDRLEN]; - ngx_addr_t *addrs; - ngx_resolver_t *r; - struct sockaddr_in *sin; - ngx_resolver_ctx_t *ctx; - ngx_resolver_srv_name_t *srv; + ngx_uint_t i; + ngx_addr_t *addrs; + ngx_resolver_t *r; + ngx_sockaddr_t *sockaddr; + struct sockaddr_in *sin; + ngx_resolver_ctx_t *ctx; + ngx_resolver_srv_name_t *srv; #if (NGX_HAVE_INET6) - struct sockaddr_in6 *sin6; + struct sockaddr_in6 *sin6; #endif r = cctx->resolver; @@ -3026,7 +3026,7 @@ ngx_resolver_srv_names_handler(ngx_resol return; } - sockaddr = ngx_resolver_alloc(r, cctx->naddrs * NGX_SOCKADDRLEN); + sockaddr = ngx_resolver_alloc(r, cctx->naddrs * sizeof(ngx_sockaddr_t)); if (sockaddr == NULL) { ngx_resolver_free(r, addrs); ngx_resolve_name_done(cctx); @@ -3039,10 +3039,10 @@ ngx_resolver_srv_names_handler(ngx_resol } for (i = 0; i < cctx->naddrs; i++) { - addrs[i].sockaddr = (struct sockaddr *) sockaddr[i]; + addrs[i].sockaddr = &sockaddr[i].sockaddr; addrs[i].socklen = cctx->addrs[i].socklen; - ngx_memcpy(sockaddr[i], cctx->addrs[i].sockaddr, + ngx_memcpy(&sockaddr[i], cctx->addrs[i].sockaddr, addrs[i].socklen); switch (addrs[i].sockaddr->sa_family) { @@ -4161,14 +4161,14 @@ static ngx_resolver_addr_t * ngx_resolver_export(ngx_resolver_t *r, ngx_resolver_node_t *rn, ngx_uint_t rotate) { - ngx_uint_t d, i, j, n; - u_char (*sockaddr)[NGX_SOCKADDRLEN]; - in_addr_t *addr; - struct sockaddr_in *sin; - ngx_resolver_addr_t *dst; + ngx_uint_t d, i, j, n; + in_addr_t *addr; + ngx_sockaddr_t *sockaddr; + struct sockaddr_in *sin; + ngx_resolver_addr_t *dst; #if (NGX_HAVE_INET6) - struct in6_addr *addr6; - struct sockaddr_in6 *sin6; + struct in6_addr *addr6; + struct sockaddr_in6 *sin6; #endif n = rn->naddrs; @@ -4181,7 +4181,7 @@ ngx_resolver_export(ngx_resolver_t *r, n return NULL; } - sockaddr = ngx_resolver_calloc(r, n * NGX_SOCKADDRLEN); + sockaddr = ngx_resolver_calloc(r, n * sizeof(ngx_sockaddr_t)); if (sockaddr == NULL) { ngx_resolver_free(r, dst); return NULL; @@ -4196,7 +4196,7 @@ ngx_resolver_export(ngx_resolver_t *r, n addr = (rn->naddrs == 1) ? &rn->u.addr : rn->u.addrs; do { - sin = (struct sockaddr_in *) sockaddr[d]; + sin = &sockaddr[d].sockaddr_in; sin->sin_family = AF_INET; sin->sin_addr.s_addr = addr[j++]; dst[d].sockaddr = (struct sockaddr *) sin; @@ -4219,7 +4219,7 @@ ngx_resolver_export(ngx_resolver_t *r, n addr6 = (rn->naddrs6 == 1) ? &rn->u6.addr6 : rn->u6.addrs6; do { - sin6 = (struct sockaddr_in6 *) sockaddr[d]; + sin6 = &sockaddr[d].sockaddr_in6; sin6->sin6_family = AF_INET6; ngx_memcpy(sin6->sin6_addr.s6_addr, addr6[j++].s6_addr, 16); dst[d].sockaddr = (struct sockaddr *) sin6; diff -r 68854ce64ec7 -r adf25b8d0431 src/event/ngx_event_accept.c --- a/src/event/ngx_event_accept.c Mon May 23 12:50:59 2016 +0300 +++ b/src/event/ngx_event_accept.c Mon May 23 16:37:20 2016 +0300 @@ -28,10 +28,10 @@ ngx_event_accept(ngx_event_t *ev) ngx_uint_t level; ngx_socket_t s; ngx_event_t *rev, *wev; + ngx_sockaddr_t sa; ngx_listening_t *ls; ngx_connection_t *c, *lc; ngx_event_conf_t *ecf; - u_char sa[NGX_SOCKADDRLEN]; #if (NGX_HAVE_ACCEPT4) static ngx_uint_t use_accept4 = 1; #endif @@ -58,17 +58,16 @@ ngx_event_accept(ngx_event_t *ev) "accept on %V, ready: %d", &ls->addr_text, ev->available); do { - socklen = NGX_SOCKADDRLEN; + socklen = sizeof(ngx_sockaddr_t); #if (NGX_HAVE_ACCEPT4) if (use_accept4) { - s = accept4(lc->fd, (struct sockaddr *) sa, &socklen, - SOCK_NONBLOCK); + s = accept4(lc->fd, &sa.sockaddr, &socklen, SOCK_NONBLOCK); } else { - s = accept(lc->fd, (struct sockaddr *) sa, &socklen); + s = accept(lc->fd, &sa.sockaddr, &socklen); } #else - s = accept(lc->fd, (struct sockaddr *) sa, &socklen); + s = accept(lc->fd, &sa.sockaddr, &socklen); #endif if (s == (ngx_socket_t) -1) { @@ -171,7 +170,7 @@ ngx_event_accept(ngx_event_t *ev) return; } - ngx_memcpy(c->sockaddr, sa, socklen); + ngx_memcpy(c->sockaddr, &sa, socklen); log = ngx_palloc(c->pool, sizeof(ngx_log_t)); if (log == NULL) { @@ -328,10 +327,10 @@ ngx_event_recvmsg(ngx_event_t *ev) ngx_event_t *rev, *wev; struct iovec iov[1]; struct msghdr msg; + ngx_sockaddr_t sa; ngx_listening_t *ls; ngx_event_conf_t *ecf; ngx_connection_t *c, *lc; - u_char sa[NGX_SOCKADDRLEN]; static u_char buffer[65535]; #if (NGX_HAVE_MSGHDR_MSG_CONTROL) @@ -376,7 +375,7 @@ ngx_event_recvmsg(ngx_event_t *ev) iov[0].iov_len = sizeof(buffer); msg.msg_name = &sa; - msg.msg_namelen = sizeof(sa); + msg.msg_namelen = sizeof(ngx_sockaddr_t); msg.msg_iov = iov; msg.msg_iovlen = 1; diff -r 68854ce64ec7 -r adf25b8d0431 src/http/modules/ngx_http_upstream_keepalive_module.c --- a/src/http/modules/ngx_http_upstream_keepalive_module.c Mon May 23 12:50:59 2016 +0300 +++ b/src/http/modules/ngx_http_upstream_keepalive_module.c Mon May 23 16:37:20 2016 +0300 @@ -29,7 +29,7 @@ typedef struct { ngx_connection_t *connection; socklen_t socklen; - u_char sockaddr[NGX_SOCKADDRLEN]; + ngx_sockaddr_t sockaddr; } ngx_http_upstream_keepalive_cache_t; diff -r 68854ce64ec7 -r adf25b8d0431 src/http/ngx_http_core_module.c --- a/src/http/ngx_http_core_module.c Mon May 23 12:50:59 2016 +0300 +++ b/src/http/ngx_http_core_module.c Mon May 23 16:37:20 2016 +0300 @@ -3998,7 +3998,7 @@ ngx_http_core_listen(ngx_conf_t *cf, ngx ngx_memzero(&lsopt, sizeof(ngx_http_listen_opt_t)); - ngx_memcpy(&lsopt.u.sockaddr, u.sockaddr, u.socklen); + ngx_memcpy(&lsopt.u.sockaddr, &u.sockaddr, u.socklen); lsopt.socklen = u.socklen; lsopt.backlog = NGX_LISTEN_BACKLOG; diff -r 68854ce64ec7 -r adf25b8d0431 src/http/ngx_http_core_module.h --- a/src/http/ngx_http_core_module.h Mon May 23 12:50:59 2016 +0300 +++ b/src/http/ngx_http_core_module.h Mon May 23 16:37:20 2016 +0300 @@ -58,17 +58,7 @@ typedef struct ngx_http_core_loc_conf_s typedef struct { - union { - struct sockaddr sockaddr; - struct sockaddr_in sockaddr_in; -#if (NGX_HAVE_INET6) - struct sockaddr_in6 sockaddr_in6; -#endif -#if (NGX_HAVE_UNIX_DOMAIN) - struct sockaddr_un sockaddr_un; -#endif - } u; - + ngx_sockaddr_t u; socklen_t socklen; unsigned set:1; diff -r 68854ce64ec7 -r adf25b8d0431 src/mail/ngx_mail.h --- a/src/mail/ngx_mail.h Mon May 23 12:50:59 2016 +0300 +++ b/src/mail/ngx_mail.h Mon May 23 16:37:20 2016 +0300 @@ -27,17 +27,7 @@ typedef struct { typedef struct { - union { - struct sockaddr sockaddr; - struct sockaddr_in sockaddr_in; -#if (NGX_HAVE_INET6) - struct sockaddr_in6 sockaddr_in6; -#endif -#if (NGX_HAVE_UNIX_DOMAIN) - struct sockaddr_un sockaddr_un; -#endif - } u; - + ngx_sockaddr_t u; socklen_t socklen; /* server ctx */ diff -r 68854ce64ec7 -r adf25b8d0431 src/mail/ngx_mail_core_module.c --- a/src/mail/ngx_mail_core_module.c Mon May 23 12:50:59 2016 +0300 +++ b/src/mail/ngx_mail_core_module.c Mon May 23 16:37:20 2016 +0300 @@ -337,7 +337,7 @@ ngx_mail_core_listen(ngx_conf_t *cf, ngx ngx_memzero(ls, sizeof(ngx_mail_listen_t)); - ngx_memcpy(&ls->u.sockaddr, u.sockaddr, u.socklen); + ngx_memcpy(&ls->u.sockaddr, &u.sockaddr, u.socklen); ls->socklen = u.socklen; ls->backlog = NGX_LISTEN_BACKLOG; diff -r 68854ce64ec7 -r adf25b8d0431 src/stream/ngx_stream.h --- a/src/stream/ngx_stream.h Mon May 23 12:50:59 2016 +0300 +++ b/src/stream/ngx_stream.h Mon May 23 16:37:20 2016 +0300 @@ -31,17 +31,7 @@ typedef struct { typedef struct { - union { - struct sockaddr sockaddr; - struct sockaddr_in sockaddr_in; -#if (NGX_HAVE_INET6) - struct sockaddr_in6 sockaddr_in6; -#endif -#if (NGX_HAVE_UNIX_DOMAIN) - struct sockaddr_un sockaddr_un; -#endif - } u; - + ngx_sockaddr_t u; socklen_t socklen; /* server ctx */ diff -r 68854ce64ec7 -r adf25b8d0431 src/stream/ngx_stream_core_module.c --- a/src/stream/ngx_stream_core_module.c Mon May 23 12:50:59 2016 +0300 +++ b/src/stream/ngx_stream_core_module.c Mon May 23 16:37:20 2016 +0300 @@ -280,7 +280,7 @@ ngx_stream_core_listen(ngx_conf_t *cf, n ngx_memzero(ls, sizeof(ngx_stream_listen_t)); - ngx_memcpy(&ls->u.sockaddr, u.sockaddr, u.socklen); + ngx_memcpy(&ls->u.sockaddr, &u.sockaddr, u.socklen); ls->socklen = u.socklen; ls->backlog = NGX_LISTEN_BACKLOG; From ru at nginx.com Mon May 23 13:38:00 2016 From: ru at nginx.com (Ruslan Ermilov) Date: Mon, 23 May 2016 13:38:00 +0000 Subject: [nginx] Renamed "u" to "sockaddr" in listen options types. Message-ID: details: http://hg.nginx.org/nginx/rev/c90cf79d0e1d branches: changeset: 6560:c90cf79d0e1d user: Maxim Dounin date: Mon May 23 16:37:28 2016 +0300 description: Renamed "u" to "sockaddr" in listen options types. diffstat: src/http/ngx_http.c | 148 ++++++++++++++++++----------------- src/http/ngx_http_core_module.c | 12 +- src/http/ngx_http_core_module.h | 2 +- src/mail/ngx_mail.c | 20 ++-- src/mail/ngx_mail.h | 2 +- src/mail/ngx_mail_core_module.c | 8 +- src/stream/ngx_stream.c | 20 ++-- src/stream/ngx_stream.h | 2 +- src/stream/ngx_stream_core_module.c | 10 +- 9 files changed, 113 insertions(+), 111 deletions(-) diffs (525 lines): diff -r adf25b8d0431 -r c90cf79d0e1d src/http/ngx_http.c --- a/src/http/ngx_http.c Mon May 23 16:37:20 2016 +0300 +++ b/src/http/ngx_http.c Mon May 23 16:37:28 2016 +0300 @@ -1161,13 +1161,13 @@ ngx_http_add_listen(ngx_conf_t *cf, ngx_ } } - sa = &lsopt->u.sockaddr; + sa = &lsopt->sockaddr.sockaddr; switch (sa->sa_family) { #if (NGX_HAVE_INET6) case AF_INET6: - sin6 = &lsopt->u.sockaddr_in6; + sin6 = &lsopt->sockaddr.sockaddr_in6; p = sin6->sin6_port; break; #endif @@ -1179,7 +1179,7 @@ ngx_http_add_listen(ngx_conf_t *cf, ngx_ #endif default: /* AF_INET */ - sin = &lsopt->u.sockaddr_in; + sin = &lsopt->sockaddr.sockaddr_in; p = sin->sin_port; break; } @@ -1233,8 +1233,9 @@ ngx_http_add_addresses(ngx_conf_t *cf, n for (i = 0; i < port->addrs.nelts; i++) { - if (ngx_cmp_sockaddr(&lsopt->u.sockaddr, lsopt->socklen, - &addr[i].opt.u.sockaddr, addr[i].opt.socklen, 0) + if (ngx_cmp_sockaddr(&lsopt->sockaddr.sockaddr, lsopt->socklen, + &addr[i].opt.sockaddr.sockaddr, + addr[i].opt.socklen, 0) != NGX_OK) { continue; @@ -1727,7 +1728,8 @@ ngx_http_add_listening(ngx_conf_t *cf, n ngx_http_core_loc_conf_t *clcf; ngx_http_core_srv_conf_t *cscf; - ls = ngx_create_listening(cf, &addr->opt.u.sockaddr, addr->opt.socklen); + ls = ngx_create_listening(cf, &addr->opt.sockaddr.sockaddr, + addr->opt.socklen); if (ls == NULL) { return NULL; } @@ -1817,7 +1819,7 @@ ngx_http_add_addrs(ngx_conf_t *cf, ngx_h for (i = 0; i < hport->naddrs; i++) { - sin = &addr[i].opt.u.sockaddr_in; + sin = &addr[i].opt.sockaddr.sockaddr_in; addrs[i].addr = sin->sin_addr.s_addr; addrs[i].conf.default_server = addr[i].default_server; #if (NGX_HTTP_SSL) @@ -1846,72 +1848,7 @@ ngx_http_add_addrs(ngx_conf_t *cf, ngx_h return NGX_ERROR; } - addrs[i].conf.virtual_names = vn; - - vn->names.hash = addr[i].hash; - vn->names.wc_head = addr[i].wc_head; - vn->names.wc_tail = addr[i].wc_tail; -#if (NGX_PCRE) - vn->nregex = addr[i].nregex; - vn->regex = addr[i].regex; -#endif - } - - return NGX_OK; -} - - -#if (NGX_HAVE_INET6) - -static ngx_int_t -ngx_http_add_addrs6(ngx_conf_t *cf, ngx_http_port_t *hport, - ngx_http_conf_addr_t *addr) -{ - ngx_uint_t i; - ngx_http_in6_addr_t *addrs6; - struct sockaddr_in6 *sin6; - ngx_http_virtual_names_t *vn; - - hport->addrs = ngx_pcalloc(cf->pool, - hport->naddrs * sizeof(ngx_http_in6_addr_t)); - if (hport->addrs == NULL) { - return NGX_ERROR; - } - - addrs6 = hport->addrs; - - for (i = 0; i < hport->naddrs; i++) { - - sin6 = &addr[i].opt.u.sockaddr_in6; - addrs6[i].addr6 = sin6->sin6_addr; - addrs6[i].conf.default_server = addr[i].default_server; -#if (NGX_HTTP_SSL) - addrs6[i].conf.ssl = addr[i].opt.ssl; -#endif -#if (NGX_HTTP_V2) - addrs6[i].conf.http2 = addr[i].opt.http2; -#endif - addrs6[i].conf.proxy_protocol = addr[i].opt.proxy_protocol; - - if (addr[i].hash.buckets == NULL - && (addr[i].wc_head == NULL - || addr[i].wc_head->hash.buckets == NULL) - && (addr[i].wc_tail == NULL - || addr[i].wc_tail->hash.buckets == NULL) -#if (NGX_PCRE) - && addr[i].nregex == 0 -#endif - ) - { - continue; - } - - vn = ngx_palloc(cf->pool, sizeof(ngx_http_virtual_names_t)); - if (vn == NULL) { - return NGX_ERROR; - } - - addrs6[i].conf.virtual_names = vn; + addrs[i].conf.virtual_names = vn; vn->names.hash = addr[i].hash; vn->names.wc_head = addr[i].wc_head; @@ -1925,6 +1862,71 @@ ngx_http_add_addrs6(ngx_conf_t *cf, ngx_ return NGX_OK; } + +#if (NGX_HAVE_INET6) + +static ngx_int_t +ngx_http_add_addrs6(ngx_conf_t *cf, ngx_http_port_t *hport, + ngx_http_conf_addr_t *addr) +{ + ngx_uint_t i; + ngx_http_in6_addr_t *addrs6; + struct sockaddr_in6 *sin6; + ngx_http_virtual_names_t *vn; + + hport->addrs = ngx_pcalloc(cf->pool, + hport->naddrs * sizeof(ngx_http_in6_addr_t)); + if (hport->addrs == NULL) { + return NGX_ERROR; + } + + addrs6 = hport->addrs; + + for (i = 0; i < hport->naddrs; i++) { + + sin6 = &addr[i].opt.sockaddr.sockaddr_in6; + addrs6[i].addr6 = sin6->sin6_addr; + addrs6[i].conf.default_server = addr[i].default_server; +#if (NGX_HTTP_SSL) + addrs6[i].conf.ssl = addr[i].opt.ssl; +#endif +#if (NGX_HTTP_V2) + addrs6[i].conf.http2 = addr[i].opt.http2; +#endif + addrs6[i].conf.proxy_protocol = addr[i].opt.proxy_protocol; + + if (addr[i].hash.buckets == NULL + && (addr[i].wc_head == NULL + || addr[i].wc_head->hash.buckets == NULL) + && (addr[i].wc_tail == NULL + || addr[i].wc_tail->hash.buckets == NULL) +#if (NGX_PCRE) + && addr[i].nregex == 0 +#endif + ) + { + continue; + } + + vn = ngx_palloc(cf->pool, sizeof(ngx_http_virtual_names_t)); + if (vn == NULL) { + return NGX_ERROR; + } + + addrs6[i].conf.virtual_names = vn; + + vn->names.hash = addr[i].hash; + vn->names.wc_head = addr[i].wc_head; + vn->names.wc_tail = addr[i].wc_tail; +#if (NGX_PCRE) + vn->nregex = addr[i].nregex; + vn->regex = addr[i].regex; +#endif + } + + return NGX_OK; +} + #endif diff -r adf25b8d0431 -r c90cf79d0e1d src/http/ngx_http_core_module.c --- a/src/http/ngx_http_core_module.c Mon May 23 16:37:20 2016 +0300 +++ b/src/http/ngx_http_core_module.c Mon May 23 16:37:28 2016 +0300 @@ -3030,7 +3030,7 @@ ngx_http_core_server(ngx_conf_t *cf, ngx if (rv == NGX_CONF_OK && !cscf->listen) { ngx_memzero(&lsopt, sizeof(ngx_http_listen_opt_t)); - sin = &lsopt.u.sockaddr_in; + sin = &lsopt.sockaddr.sockaddr_in; sin->sin_family = AF_INET; #if (NGX_WIN32) @@ -3053,8 +3053,8 @@ ngx_http_core_server(ngx_conf_t *cf, ngx #endif lsopt.wildcard = 1; - (void) ngx_sock_ntop(&lsopt.u.sockaddr, lsopt.socklen, lsopt.addr, - NGX_SOCKADDR_STRLEN, 1); + (void) ngx_sock_ntop(&lsopt.sockaddr.sockaddr, lsopt.socklen, + lsopt.addr, NGX_SOCKADDR_STRLEN, 1); if (ngx_http_add_listen(cf, cscf, &lsopt) != NGX_OK) { return NGX_CONF_ERROR; @@ -3998,7 +3998,7 @@ ngx_http_core_listen(ngx_conf_t *cf, ngx ngx_memzero(&lsopt, sizeof(ngx_http_listen_opt_t)); - ngx_memcpy(&lsopt.u.sockaddr, &u.sockaddr, u.socklen); + ngx_memcpy(&lsopt.sockaddr.sockaddr, &u.sockaddr, u.socklen); lsopt.socklen = u.socklen; lsopt.backlog = NGX_LISTEN_BACKLOG; @@ -4015,7 +4015,7 @@ ngx_http_core_listen(ngx_conf_t *cf, ngx lsopt.ipv6only = 1; #endif - (void) ngx_sock_ntop(&lsopt.u.sockaddr, lsopt.socklen, lsopt.addr, + (void) ngx_sock_ntop(&lsopt.sockaddr.sockaddr, lsopt.socklen, lsopt.addr, NGX_SOCKADDR_STRLEN, 1); for (n = 2; n < cf->args->nelts; n++) { @@ -4144,7 +4144,7 @@ ngx_http_core_listen(ngx_conf_t *cf, ngx #if (NGX_HAVE_INET6 && defined IPV6_V6ONLY) struct sockaddr *sa; - sa = &lsopt.u.sockaddr; + sa = &lsopt.sockaddr.sockaddr; if (sa->sa_family == AF_INET6) { diff -r adf25b8d0431 -r c90cf79d0e1d src/http/ngx_http_core_module.h --- a/src/http/ngx_http_core_module.h Mon May 23 16:37:20 2016 +0300 +++ b/src/http/ngx_http_core_module.h Mon May 23 16:37:28 2016 +0300 @@ -58,7 +58,7 @@ typedef struct ngx_http_core_loc_conf_s typedef struct { - ngx_sockaddr_t u; + ngx_sockaddr_t sockaddr; socklen_t socklen; unsigned set:1; diff -r adf25b8d0431 -r c90cf79d0e1d src/mail/ngx_mail.c --- a/src/mail/ngx_mail.c Mon May 23 16:37:20 2016 +0300 +++ b/src/mail/ngx_mail.c Mon May 23 16:37:28 2016 +0300 @@ -235,13 +235,13 @@ ngx_mail_add_ports(ngx_conf_t *cf, ngx_a struct sockaddr_in6 *sin6; #endif - sa = &listen->u.sockaddr; + sa = &listen->sockaddr.sockaddr; switch (sa->sa_family) { #if (NGX_HAVE_INET6) case AF_INET6: - sin6 = &listen->u.sockaddr_in6; + sin6 = &listen->sockaddr.sockaddr_in6; p = sin6->sin6_port; break; #endif @@ -253,7 +253,7 @@ ngx_mail_add_ports(ngx_conf_t *cf, ngx_a #endif default: /* AF_INET */ - sin = &listen->u.sockaddr_in; + sin = &listen->sockaddr.sockaddr_in; p = sin->sin_port; break; } @@ -340,7 +340,7 @@ ngx_mail_optimize_servers(ngx_conf_t *cf continue; } - ls = ngx_create_listening(cf, &addr[i].opt.u.sockaddr, + ls = ngx_create_listening(cf, &addr[i].opt.sockaddr.sockaddr, addr[i].opt.socklen); if (ls == NULL) { return NGX_CONF_ERROR; @@ -423,7 +423,7 @@ ngx_mail_add_addrs(ngx_conf_t *cf, ngx_m for (i = 0; i < mport->naddrs; i++) { - sin = &addr[i].opt.u.sockaddr_in; + sin = &addr[i].opt.sockaddr.sockaddr_in; addrs[i].addr = sin->sin_addr.s_addr; addrs[i].conf.ctx = addr[i].opt.ctx; @@ -431,8 +431,8 @@ ngx_mail_add_addrs(ngx_conf_t *cf, ngx_m addrs[i].conf.ssl = addr[i].opt.ssl; #endif - len = ngx_sock_ntop(&addr[i].opt.u.sockaddr, addr[i].opt.socklen, buf, - NGX_SOCKADDR_STRLEN, 1); + len = ngx_sock_ntop(&addr[i].opt.sockaddr.sockaddr, addr[i].opt.socklen, + buf, NGX_SOCKADDR_STRLEN, 1); p = ngx_pnalloc(cf->pool, len); if (p == NULL) { @@ -472,7 +472,7 @@ ngx_mail_add_addrs6(ngx_conf_t *cf, ngx_ for (i = 0; i < mport->naddrs; i++) { - sin6 = &addr[i].opt.u.sockaddr_in6; + sin6 = &addr[i].opt.sockaddr.sockaddr_in6; addrs6[i].addr6 = sin6->sin6_addr; addrs6[i].conf.ctx = addr[i].opt.ctx; @@ -480,8 +480,8 @@ ngx_mail_add_addrs6(ngx_conf_t *cf, ngx_ addrs6[i].conf.ssl = addr[i].opt.ssl; #endif - len = ngx_sock_ntop(&addr[i].opt.u.sockaddr, addr[i].opt.socklen, buf, - NGX_SOCKADDR_STRLEN, 1); + len = ngx_sock_ntop(&addr[i].opt.sockaddr.sockaddr, addr[i].opt.socklen, + buf, NGX_SOCKADDR_STRLEN, 1); p = ngx_pnalloc(cf->pool, len); if (p == NULL) { diff -r adf25b8d0431 -r c90cf79d0e1d src/mail/ngx_mail.h --- a/src/mail/ngx_mail.h Mon May 23 16:37:20 2016 +0300 +++ b/src/mail/ngx_mail.h Mon May 23 16:37:28 2016 +0300 @@ -27,7 +27,7 @@ typedef struct { typedef struct { - ngx_sockaddr_t u; + ngx_sockaddr_t sockaddr; socklen_t socklen; /* server ctx */ diff -r adf25b8d0431 -r c90cf79d0e1d src/mail/ngx_mail_core_module.c --- a/src/mail/ngx_mail_core_module.c Mon May 23 16:37:20 2016 +0300 +++ b/src/mail/ngx_mail_core_module.c Mon May 23 16:37:28 2016 +0300 @@ -318,7 +318,7 @@ ngx_mail_core_listen(ngx_conf_t *cf, ngx for (i = 0; i < cmcf->listen.nelts; i++) { - if (ngx_cmp_sockaddr(&ls[i].u.sockaddr, ls[i].socklen, + if (ngx_cmp_sockaddr(&ls[i].sockaddr.sockaddr, ls[i].socklen, (struct sockaddr *) &u.sockaddr, u.socklen, 1) != NGX_OK) { @@ -337,7 +337,7 @@ ngx_mail_core_listen(ngx_conf_t *cf, ngx ngx_memzero(ls, sizeof(ngx_mail_listen_t)); - ngx_memcpy(&ls->u.sockaddr, &u.sockaddr, u.socklen); + ngx_memcpy(&ls->sockaddr.sockaddr, &u.sockaddr, u.socklen); ls->socklen = u.socklen; ls->backlog = NGX_LISTEN_BACKLOG; @@ -394,7 +394,7 @@ ngx_mail_core_listen(ngx_conf_t *cf, ngx size_t len; u_char buf[NGX_SOCKADDR_STRLEN]; - if (ls->u.sockaddr.sa_family == AF_INET6) { + if (ls->sockaddr.sockaddr.sa_family == AF_INET6) { if (ngx_strcmp(&value[i].data[10], "n") == 0) { ls->ipv6only = 1; @@ -412,7 +412,7 @@ ngx_mail_core_listen(ngx_conf_t *cf, ngx ls->bind = 1; } else { - len = ngx_sock_ntop(&ls->u.sockaddr, ls->socklen, buf, + len = ngx_sock_ntop(&ls->sockaddr.sockaddr, ls->socklen, buf, NGX_SOCKADDR_STRLEN, 1); ngx_conf_log_error(NGX_LOG_EMERG, cf, 0, diff -r adf25b8d0431 -r c90cf79d0e1d src/stream/ngx_stream.c --- a/src/stream/ngx_stream.c Mon May 23 16:37:20 2016 +0300 +++ b/src/stream/ngx_stream.c Mon May 23 16:37:28 2016 +0300 @@ -250,13 +250,13 @@ ngx_stream_add_ports(ngx_conf_t *cf, ngx struct sockaddr_in6 *sin6; #endif - sa = &listen->u.sockaddr; + sa = &listen->sockaddr.sockaddr; switch (sa->sa_family) { #if (NGX_HAVE_INET6) case AF_INET6: - sin6 = &listen->u.sockaddr_in6; + sin6 = &listen->sockaddr.sockaddr_in6; p = sin6->sin6_port; break; #endif @@ -268,7 +268,7 @@ ngx_stream_add_ports(ngx_conf_t *cf, ngx #endif default: /* AF_INET */ - sin = &listen->u.sockaddr_in; + sin = &listen->sockaddr.sockaddr_in; p = sin->sin_port; break; } @@ -359,7 +359,7 @@ ngx_stream_optimize_servers(ngx_conf_t * continue; } - ls = ngx_create_listening(cf, &addr[i].opt.u.sockaddr, + ls = ngx_create_listening(cf, &addr[i].opt.sockaddr.sockaddr, addr[i].opt.socklen); if (ls == NULL) { return NGX_CONF_ERROR; @@ -453,7 +453,7 @@ ngx_stream_add_addrs(ngx_conf_t *cf, ngx for (i = 0; i < stport->naddrs; i++) { - sin = &addr[i].opt.u.sockaddr_in; + sin = &addr[i].opt.sockaddr.sockaddr_in; addrs[i].addr = sin->sin_addr.s_addr; addrs[i].conf.ctx = addr[i].opt.ctx; @@ -461,8 +461,8 @@ ngx_stream_add_addrs(ngx_conf_t *cf, ngx addrs[i].conf.ssl = addr[i].opt.ssl; #endif - len = ngx_sock_ntop(&addr[i].opt.u.sockaddr, addr[i].opt.socklen, buf, - NGX_SOCKADDR_STRLEN, 1); + len = ngx_sock_ntop(&addr[i].opt.sockaddr.sockaddr, addr[i].opt.socklen, + buf, NGX_SOCKADDR_STRLEN, 1); p = ngx_pnalloc(cf->pool, len); if (p == NULL) { @@ -502,7 +502,7 @@ ngx_stream_add_addrs6(ngx_conf_t *cf, ng for (i = 0; i < stport->naddrs; i++) { - sin6 = &addr[i].opt.u.sockaddr_in6; + sin6 = &addr[i].opt.sockaddr.sockaddr_in6; addrs6[i].addr6 = sin6->sin6_addr; addrs6[i].conf.ctx = addr[i].opt.ctx; @@ -510,8 +510,8 @@ ngx_stream_add_addrs6(ngx_conf_t *cf, ng addrs6[i].conf.ssl = addr[i].opt.ssl; #endif - len = ngx_sock_ntop(&addr[i].opt.u.sockaddr, addr[i].opt.socklen, buf, - NGX_SOCKADDR_STRLEN, 1); + len = ngx_sock_ntop(&addr[i].opt.sockaddr.sockaddr, addr[i].opt.socklen, + buf, NGX_SOCKADDR_STRLEN, 1); p = ngx_pnalloc(cf->pool, len); if (p == NULL) { diff -r adf25b8d0431 -r c90cf79d0e1d src/stream/ngx_stream.h --- a/src/stream/ngx_stream.h Mon May 23 16:37:20 2016 +0300 +++ b/src/stream/ngx_stream.h Mon May 23 16:37:28 2016 +0300 @@ -31,7 +31,7 @@ typedef struct { typedef struct { - ngx_sockaddr_t u; + ngx_sockaddr_t sockaddr; socklen_t socklen; /* server ctx */ diff -r adf25b8d0431 -r c90cf79d0e1d src/stream/ngx_stream_core_module.c --- a/src/stream/ngx_stream_core_module.c Mon May 23 16:37:20 2016 +0300 +++ b/src/stream/ngx_stream_core_module.c Mon May 23 16:37:28 2016 +0300 @@ -280,7 +280,7 @@ ngx_stream_core_listen(ngx_conf_t *cf, n ngx_memzero(ls, sizeof(ngx_stream_listen_t)); - ngx_memcpy(&ls->u.sockaddr, &u.sockaddr, u.socklen); + ngx_memcpy(&ls->sockaddr.sockaddr, &u.sockaddr, u.socklen); ls->socklen = u.socklen; ls->backlog = NGX_LISTEN_BACKLOG; @@ -328,7 +328,7 @@ ngx_stream_core_listen(ngx_conf_t *cf, n size_t len; u_char buf[NGX_SOCKADDR_STRLEN]; - if (ls->u.sockaddr.sa_family == AF_INET6) { + if (ls->sockaddr.sockaddr.sa_family == AF_INET6) { if (ngx_strcmp(&value[i].data[10], "n") == 0) { ls->ipv6only = 1; @@ -346,7 +346,7 @@ ngx_stream_core_listen(ngx_conf_t *cf, n ls->bind = 1; } else { - len = ngx_sock_ntop(&ls->u.sockaddr, ls->socklen, buf, + len = ngx_sock_ntop(&ls->sockaddr.sockaddr, ls->socklen, buf, NGX_SOCKADDR_STRLEN, 1); ngx_conf_log_error(NGX_LOG_EMERG, cf, 0, @@ -505,8 +505,8 @@ ngx_stream_core_listen(ngx_conf_t *cf, n continue; } - if (ngx_cmp_sockaddr(&als[i].u.sockaddr, als[i].socklen, - &ls->u.sockaddr, ls->socklen, 1) + if (ngx_cmp_sockaddr(&als[i].sockaddr.sockaddr, als[i].socklen, + &ls->sockaddr.sockaddr, ls->socklen, 1) != NGX_OK) { continue; From xeioex at nginx.com Mon May 23 15:45:31 2016 From: xeioex at nginx.com (Dmitry Volyntsev) Date: Mon, 23 May 2016 15:45:31 +0000 Subject: [nginx] Added the $proxy_protocol_port variable. Message-ID: details: http://hg.nginx.org/nginx/rev/28c76d9d75b7 branches: changeset: 6561:28c76d9d75b7 user: Dmitry Volyntsev date: Mon May 23 18:44:21 2016 +0300 description: Added the $proxy_protocol_port variable. diffstat: src/core/ngx_connection.h | 1 + src/core/ngx_proxy_protocol.c | 41 +++++++++++++++++++++++++++++++++++++---- src/http/ngx_http_variables.c | 31 +++++++++++++++++++++++++++++++ 3 files changed, 69 insertions(+), 4 deletions(-) diffs (124 lines): diff -r c90cf79d0e1d -r 28c76d9d75b7 src/core/ngx_connection.h --- a/src/core/ngx_connection.h Mon May 23 16:37:28 2016 +0300 +++ b/src/core/ngx_connection.h Mon May 23 18:44:21 2016 +0300 @@ -149,6 +149,7 @@ struct ngx_connection_s { ngx_str_t addr_text; ngx_str_t proxy_protocol_addr; + in_port_t proxy_protocol_port; #if (NGX_SSL) ngx_ssl_connection_t *ssl; diff -r c90cf79d0e1d -r 28c76d9d75b7 src/core/ngx_proxy_protocol.c --- a/src/core/ngx_proxy_protocol.c Mon May 23 16:37:28 2016 +0300 +++ b/src/core/ngx_proxy_protocol.c Mon May 23 18:44:21 2016 +0300 @@ -12,8 +12,9 @@ u_char * ngx_proxy_protocol_read(ngx_connection_t *c, u_char *buf, u_char *last) { - size_t len; - u_char ch, *p, *addr; + size_t len; + u_char ch, *p, *addr, *port; + ngx_int_t n; p = buf; len = last - buf; @@ -71,8 +72,40 @@ ngx_proxy_protocol_read(ngx_connection_t ngx_memcpy(c->proxy_protocol_addr.data, addr, len); c->proxy_protocol_addr.len = len; - ngx_log_debug1(NGX_LOG_DEBUG_CORE, c->log, 0, - "PROXY protocol address: \"%V\"", &c->proxy_protocol_addr); + for ( ;; ) { + if (p == last) { + goto invalid; + } + + if (*p++ == ' ') { + break; + } + } + + port = p; + + for ( ;; ) { + if (p == last) { + goto invalid; + } + + if (*p++ == ' ') { + break; + } + } + + len = p - port - 1; + + n = ngx_atoi(port, len); + + if (n < 0 || n > 65535) { + goto invalid; + } + + c->proxy_protocol_port = (in_port_t) n; + + ngx_log_debug2(NGX_LOG_DEBUG_CORE, c->log, 0, + "PROXY protocol address: %V %i", &c->proxy_protocol_addr, n); skip: diff -r c90cf79d0e1d -r 28c76d9d75b7 src/http/ngx_http_variables.c --- a/src/http/ngx_http_variables.c Mon May 23 16:37:28 2016 +0300 +++ b/src/http/ngx_http_variables.c Mon May 23 18:44:21 2016 +0300 @@ -58,6 +58,8 @@ static ngx_int_t ngx_http_variable_remot ngx_http_variable_value_t *v, uintptr_t data); static ngx_int_t ngx_http_variable_proxy_protocol_addr(ngx_http_request_t *r, ngx_http_variable_value_t *v, uintptr_t data); +static ngx_int_t ngx_http_variable_proxy_protocol_port(ngx_http_request_t *r, + ngx_http_variable_value_t *v, uintptr_t data); static ngx_int_t ngx_http_variable_server_addr(ngx_http_request_t *r, ngx_http_variable_value_t *v, uintptr_t data); static ngx_int_t ngx_http_variable_server_port(ngx_http_request_t *r, @@ -194,6 +196,9 @@ static ngx_http_variable_t ngx_http_cor { ngx_string("proxy_protocol_addr"), NULL, ngx_http_variable_proxy_protocol_addr, 0, 0, 0 }, + { ngx_string("proxy_protocol_port"), NULL, + ngx_http_variable_proxy_protocol_port, 0, 0, 0 }, + { ngx_string("server_addr"), NULL, ngx_http_variable_server_addr, 0, 0, 0 }, { ngx_string("server_port"), NULL, ngx_http_variable_server_port, 0, 0, 0 }, @@ -1256,6 +1261,32 @@ ngx_http_variable_proxy_protocol_addr(ng static ngx_int_t +ngx_http_variable_proxy_protocol_port(ngx_http_request_t *r, + ngx_http_variable_value_t *v, uintptr_t data) +{ + ngx_uint_t port; + + v->len = 0; + v->valid = 1; + v->no_cacheable = 0; + v->not_found = 0; + + v->data = ngx_pnalloc(r->pool, sizeof("65535") - 1); + if (v->data == NULL) { + return NGX_ERROR; + } + + port = r->connection->proxy_protocol_port; + + if (port > 0 && port < 65536) { + v->len = ngx_sprintf(v->data, "%ui", port) - v->data; + } + + return NGX_OK; +} + + +static ngx_int_t ngx_http_variable_server_addr(ngx_http_request_t *r, ngx_http_variable_value_t *v, uintptr_t data) { From xeioex at nginx.com Mon May 23 15:45:33 2016 From: xeioex at nginx.com (Dmitry Volyntsev) Date: Mon, 23 May 2016 15:45:33 +0000 Subject: [nginx] Added the $realip_remote_port variable. Message-ID: details: http://hg.nginx.org/nginx/rev/b13d3a6f0512 branches: changeset: 6562:b13d3a6f0512 user: Dmitry Volyntsev date: Mon May 23 18:44:22 2016 +0300 description: Added the $realip_remote_port variable. diffstat: src/http/modules/ngx_http_realip_module.c | 75 +++++++++++++++++++++++++++++- 1 files changed, 71 insertions(+), 4 deletions(-) diffs (115 lines): diff -r 28c76d9d75b7 -r b13d3a6f0512 src/http/modules/ngx_http_realip_module.c --- a/src/http/modules/ngx_http_realip_module.c Mon May 23 18:44:21 2016 +0300 +++ b/src/http/modules/ngx_http_realip_module.c Mon May 23 18:44:22 2016 +0300 @@ -45,10 +45,14 @@ static char *ngx_http_realip_merge_loc_c void *parent, void *child); static ngx_int_t ngx_http_realip_add_variables(ngx_conf_t *cf); static ngx_int_t ngx_http_realip_init(ngx_conf_t *cf); +static ngx_http_realip_ctx_t *ngx_http_realip_get_module_ctx( + ngx_http_request_t *r); static ngx_int_t ngx_http_realip_remote_addr_variable(ngx_http_request_t *r, ngx_http_variable_value_t *v, uintptr_t data); +static ngx_int_t ngx_http_realip_remote_port_variable(ngx_http_request_t *r, + ngx_http_variable_value_t *v, uintptr_t data); static ngx_command_t ngx_http_realip_commands[] = { @@ -115,6 +119,9 @@ static ngx_http_variable_t ngx_http_rea { ngx_string("realip_remote_addr"), NULL, ngx_http_realip_remote_addr_variable, 0, 0, 0 }, + { ngx_string("realip_remote_port"), NULL, + ngx_http_realip_remote_port_variable, 0, 0, 0 }, + { ngx_null_string, NULL, NULL, 0, 0, 0 } }; @@ -475,11 +482,9 @@ ngx_http_realip_init(ngx_conf_t *cf) } -static ngx_int_t -ngx_http_realip_remote_addr_variable(ngx_http_request_t *r, - ngx_http_variable_value_t *v, uintptr_t data) +static ngx_http_realip_ctx_t * +ngx_http_realip_get_module_ctx(ngx_http_request_t *r) { - ngx_str_t *addr_text; ngx_pool_cleanup_t *cln; ngx_http_realip_ctx_t *ctx; @@ -500,6 +505,19 @@ ngx_http_realip_remote_addr_variable(ngx } } + return ctx; +} + + +static ngx_int_t +ngx_http_realip_remote_addr_variable(ngx_http_request_t *r, + ngx_http_variable_value_t *v, uintptr_t data) +{ + ngx_str_t *addr_text; + ngx_http_realip_ctx_t *ctx; + + ctx = ngx_http_realip_get_module_ctx(r); + addr_text = ctx ? &ctx->addr_text : &r->connection->addr_text; v->len = addr_text->len; @@ -510,3 +528,52 @@ ngx_http_realip_remote_addr_variable(ngx return NGX_OK; } + + +static ngx_int_t +ngx_http_realip_remote_port_variable(ngx_http_request_t *r, + ngx_http_variable_value_t *v, uintptr_t data) +{ + ngx_uint_t port; + struct sockaddr *sa; + ngx_http_realip_ctx_t *ctx; + + ctx = ngx_http_realip_get_module_ctx(r); + + sa = ctx ? ctx->sockaddr : r->connection->sockaddr; + + v->len = 0; + v->valid = 1; + v->no_cacheable = 0; + v->not_found = 0; + + v->data = ngx_pnalloc(r->pool, sizeof("65535") - 1); + if (v->data == NULL) { + return NGX_ERROR; + } + + switch (sa->sa_family) { + +#if (NGX_HAVE_INET6) + case AF_INET6: + port = ntohs(((struct sockaddr_in6 *) sa)->sin6_port); + break; +#endif + +#if (NGX_HAVE_UNIX_DOMAIN) + case AF_UNIX: + port = 0; + break; +#endif + + default: /* AF_INET */ + port = ntohs(((struct sockaddr_in *) sa)->sin_port); + break; + } + + if (port > 0 && port < 65536) { + v->len = ngx_sprintf(v->data, "%ui", port) - v->data; + } + + return NGX_OK; +} From xeioex at nginx.com Mon May 23 15:45:36 2016 From: xeioex at nginx.com (Dmitry Volyntsev) Date: Mon, 23 May 2016 15:45:36 +0000 Subject: [nginx] Realip: take client port from PROXY protocol header. Message-ID: details: http://hg.nginx.org/nginx/rev/26feae43987f branches: changeset: 6563:26feae43987f user: Dmitry Volyntsev date: Mon May 23 18:44:22 2016 +0300 description: Realip: take client port from PROXY protocol header. Previously, when the client address was changed to the one from the PROXY protocol header, the client port ($remote_port) was reset to zero. Now the client port is also changed to the one from the PROXY protocol header. diffstat: src/http/modules/ngx_http_realip_module.c | 22 ++++++++++++++++++++++ 1 files changed, 22 insertions(+), 0 deletions(-) diffs (39 lines): diff -r b13d3a6f0512 -r 26feae43987f src/http/modules/ngx_http_realip_module.c --- a/src/http/modules/ngx_http_realip_module.c Mon May 23 18:44:22 2016 +0300 +++ b/src/http/modules/ngx_http_realip_module.c Mon May 23 18:44:22 2016 +0300 @@ -138,6 +138,10 @@ ngx_http_realip_handler(ngx_http_request ngx_list_part_t *part; ngx_table_elt_t *header; ngx_connection_t *c; + struct sockaddr_in *sin; +#if (NGX_HAVE_INET6) + struct sockaddr_in6 *sin6; +#endif ngx_http_realip_ctx_t *ctx; ngx_http_realip_loc_conf_t *rlcf; @@ -237,6 +241,24 @@ found: rlcf->recursive) != NGX_DECLINED) { + if (rlcf->type == NGX_HTTP_REALIP_PROXY) { + + switch (addr.sockaddr->sa_family) { + +#if (NGX_HAVE_INET6) + case AF_INET6: + sin6 = (struct sockaddr_in6 *) addr.sockaddr; + sin6->sin6_port = htons(c->proxy_protocol_port); + break; +#endif + + default: /* AF_INET */ + sin = (struct sockaddr_in *) addr.sockaddr; + sin->sin_port = htons(c->proxy_protocol_port); + break; + } + } + return ngx_http_realip_set_addr(r, &addr); } From xeioex at nginx.com Mon May 23 15:45:39 2016 From: xeioex at nginx.com (Dmitry Volyntsev) Date: Mon, 23 May 2016 15:45:39 +0000 Subject: [nginx] Realip: port support in X-Real-IP and X-Forwarded-For. Message-ID: details: http://hg.nginx.org/nginx/rev/19db5a6bc34e branches: changeset: 6564:19db5a6bc34e user: Dmitry Volyntsev date: Mon May 23 18:44:23 2016 +0300 description: Realip: port support in X-Real-IP and X-Forwarded-For. Now, the module extracts optional port which may accompany an IP address. This custom extension is introduced, among other things, in order to facilitate logging of original client ports. Addresses with ports are expected to be in the RFC 3986 format, that is, with IPv6 addresses in square brackets. E.g., "X-Real-IP: [2001:0db8::1]:12345" sets client port ($remote_port) to 12345. diffstat: src/core/ngx_inet.c | 79 +++++++++++++++++++++++++++++++++++++++++ src/core/ngx_inet.h | 2 + src/http/ngx_http_core_module.c | 4 +- 3 files changed, 84 insertions(+), 1 deletions(-) diffs (115 lines): diff -r 26feae43987f -r 19db5a6bc34e src/core/ngx_inet.c --- a/src/core/ngx_inet.c Mon May 23 18:44:22 2016 +0300 +++ b/src/core/ngx_inet.c Mon May 23 18:44:23 2016 +0300 @@ -526,6 +526,85 @@ ngx_parse_addr(ngx_pool_t *pool, ngx_add ngx_int_t +ngx_parse_addr_port(ngx_pool_t *pool, ngx_addr_t *addr, u_char *text, + size_t len) +{ + u_char *p, *last; + size_t plen; + ngx_int_t rc, port; + struct sockaddr_in *sin; +#if (NGX_HAVE_INET6) + struct sockaddr_in6 *sin6; +#endif + + rc = ngx_parse_addr(pool, addr, text, len); + + if (rc != NGX_DECLINED) { + return rc; + } + + last = text + len; + +#if (NGX_HAVE_INET6) + if (len && text[0] == '[') { + + p = ngx_strlchr(text, last, ']'); + + if (p == NULL || p == last - 1 || *++p != ':') { + return NGX_DECLINED; + } + + text++; + len -= 2; + + } else +#endif + + { + p = ngx_strlchr(text, last, ':'); + + if (p == NULL) { + return NGX_DECLINED; + } + } + + p++; + plen = last - p; + + port = ngx_atoi(p, plen); + + if (port < 1 || port > 65535) { + return NGX_DECLINED; + } + + len -= plen + 1; + + rc = ngx_parse_addr(pool, addr, text, len); + + if (rc != NGX_OK) { + return rc; + } + + switch (addr->sockaddr->sa_family) { + +#if (NGX_HAVE_INET6) + case AF_INET6: + sin6 = (struct sockaddr_in6 *) addr->sockaddr; + sin6->sin6_port = htons(port); + break; +#endif + + default: /* AF_INET */ + sin = (struct sockaddr_in *) addr->sockaddr; + sin->sin_port = htons(port); + break; + } + + return NGX_OK; +} + + +ngx_int_t ngx_parse_url(ngx_pool_t *pool, ngx_url_t *u) { u_char *p; diff -r 26feae43987f -r 19db5a6bc34e src/core/ngx_inet.h --- a/src/core/ngx_inet.h Mon May 23 18:44:22 2016 +0300 +++ b/src/core/ngx_inet.h Mon May 23 18:44:23 2016 +0300 @@ -115,6 +115,8 @@ size_t ngx_inet_ntop(int family, void *a ngx_int_t ngx_ptocidr(ngx_str_t *text, ngx_cidr_t *cidr); ngx_int_t ngx_parse_addr(ngx_pool_t *pool, ngx_addr_t *addr, u_char *text, size_t len); +ngx_int_t ngx_parse_addr_port(ngx_pool_t *pool, ngx_addr_t *addr, + u_char *text, size_t len); ngx_int_t ngx_parse_url(ngx_pool_t *pool, ngx_url_t *u); ngx_int_t ngx_inet_resolve_host(ngx_pool_t *pool, ngx_url_t *u); ngx_int_t ngx_cmp_sockaddr(struct sockaddr *sa1, socklen_t slen1, diff -r 26feae43987f -r 19db5a6bc34e src/http/ngx_http_core_module.c --- a/src/http/ngx_http_core_module.c Mon May 23 18:44:22 2016 +0300 +++ b/src/http/ngx_http_core_module.c Mon May 23 18:44:23 2016 +0300 @@ -2910,7 +2910,9 @@ ngx_http_get_forwarded_addr_internal(ngx } } - if (ngx_parse_addr(r->pool, &paddr, p, xfflen - (p - xff)) != NGX_OK) { + if (ngx_parse_addr_port(r->pool, &paddr, p, xfflen - (p - xff)) + != NGX_OK) + { return NGX_DECLINED; } From ru at nginx.com Mon May 23 16:29:31 2016 From: ru at nginx.com (Ruslan Ermilov) Date: Mon, 23 May 2016 16:29:31 +0000 Subject: [nginx] Realip: detect duplicate real_ip_header directive. Message-ID: details: http://hg.nginx.org/nginx/rev/3af0e65a461a branches: changeset: 6565:3af0e65a461a user: Ruslan Ermilov date: Mon May 23 19:17:24 2016 +0300 description: Realip: detect duplicate real_ip_header directive. diffstat: src/http/modules/ngx_http_realip_module.c | 4 ++++ 1 files changed, 4 insertions(+), 0 deletions(-) diffs (14 lines): diff -r 19db5a6bc34e -r 3af0e65a461a src/http/modules/ngx_http_realip_module.c --- a/src/http/modules/ngx_http_realip_module.c Mon May 23 18:44:23 2016 +0300 +++ b/src/http/modules/ngx_http_realip_module.c Mon May 23 19:17:24 2016 +0300 @@ -387,6 +387,10 @@ ngx_http_realip(ngx_conf_t *cf, ngx_comm ngx_str_t *value; + if (rlcf->type != NGX_CONF_UNSET_UINT) { + return "is duplicate"; + } + value = cf->args->elts; if (ngx_strcmp(value[1].data, "X-Real-IP") == 0) { From vbart at nginx.com Tue May 24 14:39:27 2016 From: vbart at nginx.com (Valentin Bartenev) Date: Tue, 24 May 2016 14:39:27 +0000 Subject: [nginx] HTTP/2: implemented preread buffer for request body (closes #959). Message-ID: details: http://hg.nginx.org/nginx/rev/ce94f07d5082 branches: changeset: 6566:ce94f07d5082 user: Valentin Bartenev date: Tue May 24 17:37:52 2016 +0300 description: HTTP/2: implemented preread buffer for request body (closes #959). Previously, the stream's window was kept zero in order to prevent a client from sending the request body before it was requested (see 887cca40ba6a for details). Until such initial window was acknowledged all requests with data were rejected (see 0aa07850922f for details). That approach revealed a number of problems: 1. Some clients (notably MS IE/Edge, Safari, iOS applications) show an error or even crash if a stream is rejected; 2. This requires at least one RTT for every request with body before the client receives window update and able to send data. To overcome these problems the new directive "http2_body_preread_size" is introduced. It sets the initial window and configures a special per stream preread buffer that is used to save all incoming data before the body is requested and processed. If the directive's value is lower than the default initial window (65535), as previously, all streams with data will be rejected until the new window is acknowledged. Otherwise, no special processing is used and all requests with data are welcome right from the connection start. The default value is chosen to be 64k, which is bigger than the default initial window. Setting it to zero is fully complaint to the previous behavior. diffstat: src/http/v2/ngx_http_v2.c | 168 +++++++++++++++++++++++++++----------- src/http/v2/ngx_http_v2.h | 5 + src/http/v2/ngx_http_v2_module.c | 31 +++++++ src/http/v2/ngx_http_v2_module.h | 1 + 4 files changed, 154 insertions(+), 51 deletions(-) diffs (400 lines): diff -r 3af0e65a461a -r ce94f07d5082 src/http/v2/ngx_http_v2.c --- a/src/http/v2/ngx_http_v2.c Mon May 23 19:17:24 2016 +0300 +++ b/src/http/v2/ngx_http_v2.c Tue May 24 17:37:52 2016 +0300 @@ -48,11 +48,6 @@ #define NGX_HTTP_V2_DEFAULT_FRAME_SIZE (1 << 14) -#define NGX_HTTP_V2_MAX_WINDOW ((1U << 31) - 1) -#define NGX_HTTP_V2_DEFAULT_WINDOW 65535 - -#define NGX_HTTP_V2_INITIAL_WINDOW 0 - #define NGX_HTTP_V2_ROOT (void *) -1 @@ -879,8 +874,6 @@ ngx_http_v2_state_data(ngx_http_v2_conne return ngx_http_v2_state_skip_padded(h2c, pos, end); } - stream->in_closed = h2c->state.flags & NGX_HTTP_V2_END_STREAM_FLAG; - h2c->state.stream = stream; return ngx_http_v2_state_read_data(h2c, pos, end); @@ -891,10 +884,12 @@ static u_char * ngx_http_v2_state_read_data(ngx_http_v2_connection_t *h2c, u_char *pos, u_char *end) { - size_t size; - ngx_int_t rc; - ngx_uint_t last; - ngx_http_v2_stream_t *stream; + size_t size; + ngx_buf_t *buf; + ngx_int_t rc; + ngx_http_request_t *r; + ngx_http_v2_stream_t *stream; + ngx_http_v2_srv_conf_t *h2scf; stream = h2c->state.stream; @@ -913,17 +908,42 @@ ngx_http_v2_state_read_data(ngx_http_v2_ if (size >= h2c->state.length) { size = h2c->state.length; - last = stream->in_closed; - - } else { - last = 0; - } - - rc = ngx_http_v2_process_request_body(stream->request, pos, size, last); - - if (rc != NGX_OK) { - stream->skip_data = 1; - ngx_http_finalize_request(stream->request, rc); + stream->in_closed = h2c->state.flags & NGX_HTTP_V2_END_STREAM_FLAG; + } + + r = stream->request; + + if (r->request_body) { + rc = ngx_http_v2_process_request_body(r, pos, size, stream->in_closed); + + if (rc != NGX_OK) { + stream->skip_data = 1; + ngx_http_finalize_request(r, rc); + } + + } else if (size) { + buf = stream->preread; + + if (buf == NULL) { + h2scf = ngx_http_get_module_srv_conf(r, ngx_http_v2_module); + + buf = ngx_create_temp_buf(r->pool, h2scf->preread_size); + if (buf == NULL) { + return ngx_http_v2_connection_error(h2c, + NGX_HTTP_V2_INTERNAL_ERROR); + } + + stream->preread = buf; + } + + if (size > (size_t) (buf->end - buf->last)) { + ngx_log_error(NGX_LOG_ALERT, h2c->connection->log, 0, + "http2 preread buffer overflow"); + return ngx_http_v2_connection_error(h2c, + NGX_HTTP_V2_INTERNAL_ERROR); + } + + buf->last = ngx_cpymem(buf->last, pos, size); } pos += size; @@ -1058,7 +1078,9 @@ ngx_http_v2_state_headers(ngx_http_v2_co goto rst_stream; } - if (!h2c->settings_ack && !(h2c->state.flags & NGX_HTTP_V2_END_STREAM_FLAG)) + if (!h2c->settings_ack + && !(h2c->state.flags & NGX_HTTP_V2_END_STREAM_FLAG) + && h2scf->preread_size < NGX_HTTP_V2_DEFAULT_WINDOW) { ngx_log_error(NGX_LOG_INFO, h2c->connection->log, 0, "client sent stream with data " @@ -2434,8 +2456,7 @@ ngx_http_v2_send_settings(ngx_http_v2_co buf->last = ngx_http_v2_write_uint16(buf->last, NGX_HTTP_V2_INIT_WINDOW_SIZE_SETTING); - buf->last = ngx_http_v2_write_uint32(buf->last, - NGX_HTTP_V2_INITIAL_WINDOW); + buf->last = ngx_http_v2_write_uint32(buf->last, h2scf->preread_size); buf->last = ngx_http_v2_write_uint16(buf->last, NGX_HTTP_V2_MAX_FRAME_SIZE_SETTING); @@ -2643,6 +2664,7 @@ ngx_http_v2_create_stream(ngx_http_v2_co ngx_http_log_ctx_t *ctx; ngx_http_request_t *r; ngx_http_v2_stream_t *stream; + ngx_http_v2_srv_conf_t *h2scf; ngx_http_core_srv_conf_t *cscf; fc = h2c->free_fake_connections; @@ -2756,8 +2778,10 @@ ngx_http_v2_create_stream(ngx_http_v2_co stream->request = r; stream->connection = h2c; + h2scf = ngx_http_get_module_srv_conf(r, ngx_http_v2_module); + stream->send_window = h2c->init_window; - stream->recv_window = NGX_HTTP_V2_INITIAL_WINDOW; + stream->recv_window = h2scf->preread_size; h2c->processing++; @@ -3411,7 +3435,11 @@ ngx_http_v2_read_request_body(ngx_http_r ngx_http_client_body_handler_pt post_handler) { off_t len; + size_t size; + ngx_buf_t *buf; + ngx_int_t rc; ngx_http_v2_stream_t *stream; + ngx_http_v2_srv_conf_t *h2scf; ngx_http_request_body_t *rb; ngx_http_core_loc_conf_t *clcf; ngx_http_v2_connection_t *h2c; @@ -3444,24 +3472,34 @@ ngx_http_v2_read_request_body(ngx_http_r r->request_body = rb; + h2scf = ngx_http_get_module_srv_conf(r, ngx_http_v2_module); clcf = ngx_http_get_module_loc_conf(r, ngx_http_core_module); len = r->headers_in.content_length_n; if (r->request_body_no_buffering && !stream->in_closed) { - r->request_body_in_file_only = 0; if (len < 0 || len > (off_t) clcf->client_body_buffer_size) { len = clcf->client_body_buffer_size; } + /* + * We need a room to store data up to the stream's initial window size, + * at least until this window will be exhausted. + */ + + if (len < (off_t) h2scf->preread_size) { + len = h2scf->preread_size; + } + if (len > NGX_HTTP_V2_MAX_WINDOW) { len = NGX_HTTP_V2_MAX_WINDOW; } - } - - if (len >= 0 && len <= (off_t) clcf->client_body_buffer_size - && !r->request_body_in_file_only) + + rb->buf = ngx_create_temp_buf(r->pool, (size_t) len); + + } else if (len >= 0 && len <= (off_t) clcf->client_body_buffer_size + && !r->request_body_in_file_only) { rb->buf = ngx_create_temp_buf(r->pool, (size_t) len); @@ -3478,22 +3516,44 @@ ngx_http_v2_read_request_body(ngx_http_r return NGX_HTTP_INTERNAL_SERVER_ERROR; } + buf = stream->preread; + if (stream->in_closed) { r->request_body_no_buffering = 0; + + if (buf) { + rc = ngx_http_v2_process_request_body(r, buf->pos, + buf->last - buf->pos, 1); + ngx_pfree(r->pool, buf->start); + return rc; + } + return ngx_http_v2_process_request_body(r, NULL, 0, 1); } - if (len) { - if (r->request_body_no_buffering) { - stream->recv_window = (size_t) len; - - } else { - stream->no_flow_control = 1; - stream->recv_window = NGX_HTTP_V2_MAX_WINDOW; + if (buf) { + rc = ngx_http_v2_process_request_body(r, buf->pos, + buf->last - buf->pos, 0); + + ngx_pfree(r->pool, buf->start); + + if (rc != NGX_OK) { + stream->skip_data = 1; + return rc; } - - if (ngx_http_v2_send_window_update(stream->connection, stream->node->id, - stream->recv_window) + } + + if (r->request_body_no_buffering) { + size = len - h2scf->preread_size; + + } else { + stream->no_flow_control = 1; + size = NGX_HTTP_V2_MAX_WINDOW - stream->recv_window; + } + + if (size) { + if (ngx_http_v2_send_window_update(stream->connection, + stream->node->id, size) == NGX_ERROR) { stream->skip_data = 1; @@ -3508,9 +3568,13 @@ ngx_http_v2_read_request_body(ngx_http_r return NGX_HTTP_INTERNAL_SERVER_ERROR; } } - } - - ngx_add_timer(r->connection->read, clcf->client_body_timeout); + + stream->recv_window += size; + } + + if (!buf) { + ngx_add_timer(r->connection->read, clcf->client_body_timeout); + } r->read_event_handler = ngx_http_v2_read_client_request_body_handler; r->write_event_handler = ngx_http_request_empty_handler; @@ -3529,13 +3593,8 @@ ngx_http_v2_process_request_body(ngx_htt ngx_http_request_body_t *rb; ngx_http_core_loc_conf_t *clcf; + fc = r->connection; rb = r->request_body; - - if (rb == NULL) { - return NGX_OK; - } - - fc = r->connection; buf = rb->buf; if (size) { @@ -3789,7 +3848,14 @@ ngx_http_v2_read_unbuffered_request_body window -= h2c->state.length; } - if (window == stream->recv_window) { + if (window <= stream->recv_window) { + if (window < stream->recv_window) { + ngx_log_error(NGX_LOG_ALERT, r->connection->log, 0, + "http2 negative window update"); + stream->skip_data = 1; + return NGX_HTTP_INTERNAL_SERVER_ERROR; + } + return NGX_AGAIN; } diff -r 3af0e65a461a -r ce94f07d5082 src/http/v2/ngx_http_v2.h --- a/src/http/v2/ngx_http_v2.h Mon May 23 19:17:24 2016 +0300 +++ b/src/http/v2/ngx_http_v2.h Tue May 24 17:37:52 2016 +0300 @@ -46,6 +46,9 @@ #define NGX_HTTP_V2_PADDED_FLAG 0x08 #define NGX_HTTP_V2_PRIORITY_FLAG 0x20 +#define NGX_HTTP_V2_MAX_WINDOW ((1U << 31) - 1) +#define NGX_HTTP_V2_DEFAULT_WINDOW 65535 + typedef struct ngx_http_v2_connection_s ngx_http_v2_connection_t; typedef struct ngx_http_v2_node_s ngx_http_v2_node_t; @@ -174,6 +177,8 @@ struct ngx_http_v2_stream_s { ssize_t send_window; size_t recv_window; + ngx_buf_t *preread; + ngx_http_v2_out_frame_t *free_frames; ngx_chain_t *free_frame_headers; ngx_chain_t *free_bufs; diff -r 3af0e65a461a -r ce94f07d5082 src/http/v2/ngx_http_v2_module.c --- a/src/http/v2/ngx_http_v2_module.c Mon May 23 19:17:24 2016 +0300 +++ b/src/http/v2/ngx_http_v2_module.c Tue May 24 17:37:52 2016 +0300 @@ -30,6 +30,7 @@ static char *ngx_http_v2_merge_loc_conf( static char *ngx_http_v2_recv_buffer_size(ngx_conf_t *cf, void *post, void *data); static char *ngx_http_v2_pool_size(ngx_conf_t *cf, void *post, void *data); +static char *ngx_http_v2_preread_size(ngx_conf_t *cf, void *post, void *data); static char *ngx_http_v2_streams_index_mask(ngx_conf_t *cf, void *post, void *data); static char *ngx_http_v2_chunk_size(ngx_conf_t *cf, void *post, void *data); @@ -41,6 +42,8 @@ static ngx_conf_post_t ngx_http_v2_recv { ngx_http_v2_recv_buffer_size }; static ngx_conf_post_t ngx_http_v2_pool_size_post = { ngx_http_v2_pool_size }; +static ngx_conf_post_t ngx_http_v2_preread_size_post = + { ngx_http_v2_preread_size }; static ngx_conf_post_t ngx_http_v2_streams_index_mask_post = { ngx_http_v2_streams_index_mask }; static ngx_conf_post_t ngx_http_v2_chunk_size_post = @@ -84,6 +87,13 @@ static ngx_command_t ngx_http_v2_comman offsetof(ngx_http_v2_srv_conf_t, max_header_size), NULL }, + { ngx_string("http2_body_preread_size"), + NGX_HTTP_MAIN_CONF|NGX_HTTP_SRV_CONF|NGX_CONF_TAKE1, + ngx_conf_set_size_slot, + NGX_HTTP_SRV_CONF_OFFSET, + offsetof(ngx_http_v2_srv_conf_t, preread_size), + &ngx_http_v2_preread_size_post }, + { ngx_string("http2_streams_index_size"), NGX_HTTP_MAIN_CONF|NGX_HTTP_SRV_CONF|NGX_CONF_TAKE1, ngx_conf_set_num_slot, @@ -316,6 +326,8 @@ ngx_http_v2_create_srv_conf(ngx_conf_t * h2scf->max_field_size = NGX_CONF_UNSET_SIZE; h2scf->max_header_size = NGX_CONF_UNSET_SIZE; + h2scf->preread_size = NGX_CONF_UNSET_SIZE; + h2scf->streams_index_mask = NGX_CONF_UNSET_UINT; h2scf->recv_timeout = NGX_CONF_UNSET_MSEC; @@ -341,6 +353,8 @@ ngx_http_v2_merge_srv_conf(ngx_conf_t *c ngx_conf_merge_size_value(conf->max_header_size, prev->max_header_size, 16384); + ngx_conf_merge_size_value(conf->preread_size, prev->preread_size, 65536); + ngx_conf_merge_uint_value(conf->streams_index_mask, prev->streams_index_mask, 32 - 1); @@ -420,6 +434,23 @@ ngx_http_v2_pool_size(ngx_conf_t *cf, vo static char * +ngx_http_v2_preread_size(ngx_conf_t *cf, void *post, void *data) +{ + size_t *sp = data; + + if (*sp > NGX_HTTP_V2_MAX_WINDOW) { + ngx_conf_log_error(NGX_LOG_EMERG, cf, 0, + "the maximum body preread buffer size is %uz", + NGX_HTTP_V2_MAX_WINDOW); + + return NGX_CONF_ERROR; + } + + return NGX_CONF_OK; +} + + +static char * ngx_http_v2_streams_index_mask(ngx_conf_t *cf, void *post, void *data) { ngx_uint_t *np = data; diff -r 3af0e65a461a -r ce94f07d5082 src/http/v2/ngx_http_v2_module.h --- a/src/http/v2/ngx_http_v2_module.h Mon May 23 19:17:24 2016 +0300 +++ b/src/http/v2/ngx_http_v2_module.h Tue May 24 17:37:52 2016 +0300 @@ -25,6 +25,7 @@ typedef struct { ngx_uint_t concurrent_streams; size_t max_field_size; size_t max_header_size; + size_t preread_size; ngx_uint_t streams_index_mask; ngx_msec_t recv_timeout; ngx_msec_t idle_timeout; From mdounin at mdounin.ru Tue May 24 14:47:56 2016 From: mdounin at mdounin.ru (Maxim Dounin) Date: Tue, 24 May 2016 14:47:56 +0000 Subject: [nginx] Fixed build on MSVC. Message-ID: details: http://hg.nginx.org/nginx/rev/5d8f16859ced branches: changeset: 6567:5d8f16859ced user: Maxim Dounin date: Tue May 24 17:43:58 2016 +0300 description: Fixed build on MSVC. diffstat: src/core/ngx_inet.c | 4 ++-- 1 files changed, 2 insertions(+), 2 deletions(-) diffs (19 lines): diff --git a/src/core/ngx_inet.c b/src/core/ngx_inet.c --- a/src/core/ngx_inet.c +++ b/src/core/ngx_inet.c @@ -590,13 +590,13 @@ ngx_parse_addr_port(ngx_pool_t *pool, ng #if (NGX_HAVE_INET6) case AF_INET6: sin6 = (struct sockaddr_in6 *) addr->sockaddr; - sin6->sin6_port = htons(port); + sin6->sin6_port = htons((in_port_t) port); break; #endif default: /* AF_INET */ sin = (struct sockaddr_in *) addr->sockaddr; - sin->sin_port = htons(port); + sin->sin_port = htons((in_port_t) port); break; } From mdounin at mdounin.ru Tue May 24 14:47:59 2016 From: mdounin at mdounin.ru (Maxim Dounin) Date: Tue, 24 May 2016 14:47:59 +0000 Subject: [nginx] Updated OpenSSL used for win32 builds. Message-ID: details: http://hg.nginx.org/nginx/rev/df264686e7de branches: changeset: 6568:df264686e7de user: Maxim Dounin date: Tue May 24 17:44:01 2016 +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 @@ -5,7 +5,7 @@ NGINX = nginx-$(VER) TEMP = tmp OBJS = objs.msvc8 -OPENSSL = openssl-1.0.2g +OPENSSL = openssl-1.0.2h ZLIB = zlib-1.2.8 PCRE = pcre-8.38 From mdounin at mdounin.ru Tue May 24 16:07:51 2016 From: mdounin at mdounin.ru (Maxim Dounin) Date: Tue, 24 May 2016 16:07:51 +0000 Subject: [nginx] nginx-1.11.0-RELEASE Message-ID: details: http://hg.nginx.org/nginx/rev/271ee30c6791 branches: changeset: 6569:271ee30c6791 user: Maxim Dounin date: Tue May 24 18:54:41 2016 +0300 description: nginx-1.11.0-RELEASE diffstat: docs/xml/nginx/changes.xml | 156 +++++++++++++++++++++++++++++++++++++++++++++ 1 files changed, 156 insertions(+), 0 deletions(-) diffs (166 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,162 @@ + + + + +???????? transparent ???????? proxy_bind, fastcgi_bind, +memcached_bind, scgi_bind ? uwsgi_bind. + + +the "transparent" parameter of the "proxy_bind", "fastcgi_bind", +"memcached_bind", "scgi_bind", and "uwsgi_bind" directives. + + + + + +?????????? $request_id. + + +the $request_id variable. + + + + + +????????? map ???????????? ?????????? ?????????? ?????????? +? ???????? ?????????????? ????????. + + +the "map" directive supports combinations of multiple variables +as resulting values. + + + + + +?????? ??? ????????????? ?????? epoll +nginx ?????????, ???????????? ?? ???? ??????? EPOLLRDHUP, +? ?????????????? ???????????? ????????? ??????????. + + +now nginx checks if EPOLLRDHUP events are supported by kernel, +and optimizes connection handling accordingly +if the "epoll" method is used. + + + + + +????????? ssl_certificate ? ssl_certificate_key +?????? ????? ????????? ????????? ??? +??? ???????? ???????????? ?????? ????? (????????, RSA ? ECDSA). + + +the "ssl_certificate" and "ssl_certificate_key" directives +can be specified multiple times +to load certificates of different types (for example, RSA and ECDSA). + + + + + +??? ????????????? OpenSSL 1.0.2 ? ????? +? ??????? ????????? ssl_ecdh_curve ?????? ????? ?????? ?????? ??????; +?? ????????? ???????????? ?????????? ? OpenSSL ?????? ??????. + + +the "ssl_ecdh_curve" directive now allows specifying a list of curves +when using OpenSSL 1.0.2 or newer; +by default a list built into OpenSSL is used. + + + + + +??? ????????????? DHE-?????? ?????? ???? ???? ???????? ???? ?????????? +? ??????? ????????? ssl_dhparam. + + +to use DHE ciphers it is now required to specify parameters +using the "ssl_dhparam" directive. + + + + + +?????????? $proxy_protocol_port. + + +the $proxy_protocol_port variable. + + + + + +?????????? $realip_remote_port ? ?????? ngx_http_realip_module. + + +the $realip_remote_port variable in the ngx_http_realip_module. + + + + + +?????? ngx_http_realip_module ?????? ????????? ????????????? +?? ?????? ?????, ?? ? ???? ???????. + + +the ngx_http_realip_module is now able to set the client port +in addition to the address. + + + + + +??? ??????? ????????? ??????????? ??????, +???????????? ?? ?????????????? ? ???????? SSL handshake, +?????? ???????????? ????? "421 Misdirected Request"; +??? ???????? ????????????? ? ?????????? HTTP/2-????????? +? ?????? ????????????? ?????????? ????????????. + + +the "421 Misdirected Request" response now used +when rejecting requests to a virtual server +different from one negotiated during an SSL handshake; +this improves interoperability with some HTTP/2 clients +when using client certificates. + + + + + +HTTP/2-??????? ?????? ????? ????? ????????? ???? ???????; +????????? http2_body_preread_size ????????? ??????? ?????? ??????, ??????? +????? ?????????????? ?? ????, ??? nginx ?????? ?????? ????. + + +HTTP/2 clients can now start sending request body immediately; +the "http2_body_preread_size" directive controls size of the buffer used +before nginx will start reading client request body. + + + + + +??? ????????????? ????????? proxy_cache_bypass +?? ??????????? ?????????????? ????????? ??????. + + +cached error responses were not updated +when using the "proxy_cache_bypass" directive. + + + + + + From mdounin at mdounin.ru Tue May 24 16:07:54 2016 From: mdounin at mdounin.ru (Maxim Dounin) Date: Tue, 24 May 2016 16:07:54 +0000 Subject: [nginx] release-1.11.0 tag Message-ID: details: http://hg.nginx.org/nginx/rev/0ace370ba117 branches: changeset: 6570:0ace370ba117 user: Maxim Dounin date: Tue May 24 18:54:42 2016 +0300 description: release-1.11.0 tag diffstat: .hgtags | 1 + 1 files changed, 1 insertions(+), 0 deletions(-) diffs (8 lines): diff --git a/.hgtags b/.hgtags --- a/.hgtags +++ b/.hgtags @@ -398,3 +398,4 @@ ead3907d74f90a14d1646f1b2b56ba01d3d11702 5936b7ed929237f1a73b467f662611cdc0309e51 release-1.9.13 4106db71cbcb9c8274700199ac17e520902c6c0f release-1.9.14 13070ecfda67397985f0e986eb9c42ecb46d05b5 release-1.9.15 +271ee30c6791847980cd139d31807541f5e569bf release-1.11.0 From vbart at nginx.com Tue May 24 18:55:13 2016 From: vbart at nginx.com (Valentin Bartenev) Date: Tue, 24 May 2016 18:55:13 +0000 Subject: [nginx] Version bump. Message-ID: details: http://hg.nginx.org/nginx/rev/c3d73d75b83f branches: changeset: 6571:c3d73d75b83f user: Valentin Bartenev date: Tue May 24 21:54:32 2016 +0300 description: Version bump. diffstat: src/core/nginx.h | 4 ++-- 1 files changed, 2 insertions(+), 2 deletions(-) diffs (14 lines): diff -r 0ace370ba117 -r c3d73d75b83f src/core/nginx.h --- a/src/core/nginx.h Tue May 24 18:54:42 2016 +0300 +++ b/src/core/nginx.h Tue May 24 21:54:32 2016 +0300 @@ -9,8 +9,8 @@ #define _NGINX_H_INCLUDED_ -#define nginx_version 1011000 -#define NGINX_VERSION "1.11.0" +#define nginx_version 1011001 +#define NGINX_VERSION "1.11.1" #define NGINX_VER "nginx/" NGINX_VERSION #ifdef NGX_BUILD From vbart at nginx.com Tue May 24 18:55:16 2016 From: vbart at nginx.com (Valentin Bartenev) Date: Tue, 24 May 2016 18:55:16 +0000 Subject: [nginx] HTTP/2: unbreak build on MSVC. Message-ID: details: http://hg.nginx.org/nginx/rev/bc6fd7afeed6 branches: changeset: 6572:bc6fd7afeed6 user: Valentin Bartenev date: Tue May 24 21:54:32 2016 +0300 description: HTTP/2: unbreak build on MSVC. diffstat: src/http/v2/ngx_http_v2.c | 2 +- 1 files changed, 1 insertions(+), 1 deletions(-) diffs (12 lines): diff -r c3d73d75b83f -r bc6fd7afeed6 src/http/v2/ngx_http_v2.c --- a/src/http/v2/ngx_http_v2.c Tue May 24 21:54:32 2016 +0300 +++ b/src/http/v2/ngx_http_v2.c Tue May 24 21:54:32 2016 +0300 @@ -3544,7 +3544,7 @@ ngx_http_v2_read_request_body(ngx_http_r } if (r->request_body_no_buffering) { - size = len - h2scf->preread_size; + size = (size_t) len - h2scf->preread_size; } else { stream->no_flow_control = 1; From michael.talyansky at gmail.com Wed May 25 02:26:05 2016 From: michael.talyansky at gmail.com (Michael Talyansky) Date: Tue, 24 May 2016 19:26:05 -0700 Subject: Suspending request Message-ID: <6F3E1EEC-180D-4A3F-9AA6-B102E45B709F@gmail.com> Hi, I am trying to design a non-proxying module that would do the following: In ACCESS phase, signal to nginx event loop that this request needs to be suspended, while the module communicates with another service running on the same machine. This service, after some delay, will return a verdict that will determine whether suspended request should be resumed and proceed normally to the next phase, or terminated with some return code and body. I understand that returning NGX_DONE from a phase handler is a recommended way, and that this handler will get called again after some trigger. As stated in nginxguts blog: ?Now the list of events is determined by the list of events that trigger invocation of ngx_http_core_run_phases. So far I know only 3 of and you have already mentioned them. In the future there might be more (e.g. an event that signals that other worker has finished fetching some resource) and nothing stops you from implementing your own?. So, how do I go about implementing my own event that will trigger re-calling of the phase handler? Are there examples of modules that do similar things? Thanks! -------------- next part -------------- An HTML attachment was scrubbed... URL: From r3s1stanc3 at riseup.net Wed May 25 15:53:50 2016 From: r3s1stanc3 at riseup.net (R3s1stanc3) Date: Wed, 25 May 2016 17:53:50 +0200 Subject: VM for Windows builds Message-ID: <5745CA8E.6000306@riseup.net> Hi Since I tried for 8 straight hours to build nginx under Windows 7 today, I wanted to ask if anyone has a VM where I can build a 64bit Windows binary of nginx, he wants to share with me ;) greetings From anton at endocode.com Thu May 26 08:38:38 2016 From: anton at endocode.com (Khramov Anton) Date: Thu, 26 May 2016 10:38:38 +0200 Subject: [PATCH] Log: Added "json" parameter which escapes backslashes in logs Message-ID: <2e8a8398f0e2e928bdc4.1464251918@kay-x240> # HG changeset patch # User Khramov Anton # Date 1464194463 -7200 # Wed May 25 18:41:03 2016 +0200 # Node ID 2e8a8398f0e2e928bdc4088e5999b1ebf481fd7c # Parent bc6fd7afeed6f7433c60634d9b0867ea3241b217 Log: Added "json" parameter which escapes backslashes in logs This patch makes JSON log format not being broken when nginx escapes special characters, i.e. "/?var=\x22hello, world\x22" log entry with json parameter will look like: "/?var=\\x22hello, world\\x22", diff -r bc6fd7afeed6 -r 2e8a8398f0e2 src/http/modules/ngx_http_log_module.c --- a/src/http/modules/ngx_http_log_module.c Tue May 24 21:54:32 2016 +0300 +++ b/src/http/modules/ngx_http_log_module.c Wed May 25 18:41:03 2016 +0200 @@ -20,13 +20,14 @@ ngx_http_log_op_t *op); typedef size_t (*ngx_http_log_op_getlen_pt) (ngx_http_request_t *r, - uintptr_t data); + uintptr_t data, ngx_uint_t json); struct ngx_http_log_op_s { size_t len; ngx_http_log_op_getlen_pt getlen; ngx_http_log_op_run_pt run; + ngx_uint_t json; uintptr_t data; }; @@ -69,6 +70,7 @@ ngx_syslog_peer_t *syslog_peer; ngx_http_log_fmt_t *format; ngx_http_complex_value_t *filter; + ngx_uint_t json; } ngx_http_log_t; @@ -128,10 +130,10 @@ static ngx_int_t ngx_http_log_variable_compile(ngx_conf_t *cf, ngx_http_log_op_t *op, ngx_str_t *value); static size_t ngx_http_log_variable_getlen(ngx_http_request_t *r, - uintptr_t data); + uintptr_t data, ngx_uint_t json); static u_char *ngx_http_log_variable(ngx_http_request_t *r, u_char *buf, ngx_http_log_op_t *op); -static uintptr_t ngx_http_log_escape(u_char *dst, u_char *src, size_t size); +static uintptr_t ngx_http_log_escape(u_char *dst, u_char *src, size_t size, ngx_uint_t json); static void *ngx_http_log_create_main_conf(ngx_conf_t *cf); @@ -288,8 +290,9 @@ len = 0; op = log[l].format->ops->elts; for (i = 0; i < log[l].format->ops->nelts; i++) { + op[i].json = log[l].json; if (op[i].len == 0) { - len += op[i].getlen(r, op[i].data); + len += op[i].getlen(r, op[i].data, log[l].json); } else { len += op[i].len; @@ -928,7 +931,7 @@ static size_t -ngx_http_log_variable_getlen(ngx_http_request_t *r, uintptr_t data) +ngx_http_log_variable_getlen(ngx_http_request_t *r, uintptr_t data, ngx_uint_t json) { uintptr_t len; ngx_http_variable_value_t *value; @@ -939,10 +942,14 @@ return 1; } - len = ngx_http_log_escape(NULL, value->data, value->len); + len = ngx_http_log_escape(NULL, value->data, value->len, json); value->escape = len ? 1 : 0; + if (json) { + return value->len + len * 4; + } + return value->len + len * 3; } @@ -963,13 +970,13 @@ return ngx_cpymem(buf, value->data, value->len); } else { - return (u_char *) ngx_http_log_escape(buf, value->data, value->len); + return (u_char *) ngx_http_log_escape(buf, value->data, value->len, op->json); } } static uintptr_t -ngx_http_log_escape(u_char *dst, u_char *src, size_t size) +ngx_http_log_escape(u_char *dst, u_char *src, size_t size, ngx_uint_t json) { ngx_uint_t n; static u_char hex[] = "0123456789ABCDEF"; @@ -1012,6 +1019,9 @@ while (size) { if (escape[*src >> 5] & (1 << (*src & 0x1f))) { + if (json) { + *dst++ = '\\'; + } *dst++ = '\\'; *dst++ = 'x'; *dst++ = hex[*src >> 4]; @@ -1129,6 +1139,8 @@ return NGX_CONF_ERROR; } + log->json = 0; + lmcf = ngx_http_conf_get_module_main_conf(cf, ngx_http_log_module); fmt = lmcf->formats.elts; @@ -1147,6 +1159,7 @@ ssize_t size; ngx_int_t gzip; + ngx_int_t json; ngx_uint_t i, n; ngx_msec_t flush; ngx_str_t *value, name, s; @@ -1270,6 +1283,7 @@ size = 0; flush = 0; gzip = 0; + json = 0; for (i = 3; i < cf->args->nelts; i++) { @@ -1359,6 +1373,12 @@ continue; } + if (ngx_strncmp(value[i].data, "json", 4) == 0) + { + json = 1; + continue; + } + ngx_conf_log_error(NGX_LOG_EMERG, cf, 0, "invalid parameter \"%V\"", &value[i]); return NGX_CONF_ERROR; @@ -1371,6 +1391,10 @@ return NGX_CONF_ERROR; } + if (json) { + log->json = 1; + } + if (size) { if (log->script) { From mdounin at mdounin.ru Thu May 26 16:47:08 2016 From: mdounin at mdounin.ru (Maxim Dounin) Date: Thu, 26 May 2016 19:47:08 +0300 Subject: [PATCH] Log: Added "json" parameter which escapes backslashes in logs In-Reply-To: <2e8a8398f0e2e928bdc4.1464251918@kay-x240> References: <2e8a8398f0e2e928bdc4.1464251918@kay-x240> Message-ID: <20160526164707.GL36620@mdounin.ru> Hello! On Thu, May 26, 2016 at 10:38:38AM +0200, Khramov Anton wrote: > # HG changeset patch > # User Khramov Anton > # Date 1464194463 -7200 > # Wed May 25 18:41:03 2016 +0200 > # Node ID 2e8a8398f0e2e928bdc4088e5999b1ebf481fd7c > # Parent bc6fd7afeed6f7433c60634d9b0867ea3241b217 > Log: Added "json" parameter which escapes backslashes in logs > > This patch makes JSON log format not being broken when nginx > escapes special characters, i.e. "/?var=\x22hello, world\x22" > log entry with json parameter will look like: > "/?var=\\x22hello, world\\x22", Such approach doesn't look correct for me. If you want to write valid JSON using the access log module, you may want to do exactly this: i.e., use proper JSON-style escaping (\uXXXX) and so on. On the other hand, I'm not sure it is at all possible, as JSON format assumes character encoding is known, and this is not the case with nginx as variables logged may contain arbitrary binary data. Alternatively, you may consider using appropriate module which is able to log JSON instead of constructing it using log_format. There is at least one 3rd party module available which implements logging into JSON. -- Maxim Dounin http://nginx.org/ From vbart at nginx.com Fri May 27 14:05:04 2016 From: vbart at nginx.com (Valentin V. Bartenev) Date: Fri, 27 May 2016 17:05:04 +0300 Subject: [nginx] HTTP/2: rewritten handling of request body. In-Reply-To: <4230052.v1InuH4Yg1@vbart-workstation> References: <4230052.v1InuH4Yg1@vbart-workstation> Message-ID: <69734724.k4tR3G0840@vbart-workstation> On Thursday 05 May 2016 16:41:34 Valentin V. Bartenev wrote: > On Wednesday 04 May 2016 18:52:24 Alexey Ivanov wrote: > > There is a small issue with setting `SETTINGS_INITIAL_WINDOW_SIZE` to 0: now when client tries to POST data it needs to wait for an additional RTT(between `send HEADERS` and `recv WINDOW_UPDATE`) to start sending data. > > > [..] > > Yes, while it's not optimal from the latency point of view, such > approach simplified implementation a lot. So it's a fair price, > that was paid at the current stage of HTTP/2 implementation. > > Introducing some kind of preread buffer will the next step. > [..] Done in nginx 1.11.0: http://hg.nginx.org/nginx/rev/ce94f07d5082 wbr, Valentin V. Bartenev From wesley_pereira at apple.com Fri May 27 14:35:30 2016 From: wesley_pereira at apple.com (Wesley Pereira) Date: Fri, 27 May 2016 07:35:30 -0700 Subject: Adding support for HTTP trailing headers in chunked requests Message-ID: <8820FEEB-6085-42E3-A367-A2320DA6336D@apple.com> Are there any plans to support HTTP trailing headers in chunked requests as per https://tools.ietf.org/html/rfc2616#section-3.6.1? If not, we would be interested in sending a patch for adding support. It looks like we would modify ngx_http_parse_chunked and refactor ngx_http_parse_header_line so we can reuse it for parsing trailing headers. And then have a directive to whitelist which trailing headers to allow. When the request is proxied upstream, if it?s fully buffered we could add the trailing header as a request header. If it?s unbuffered, then just proxy them as trailing headers. And we would only include the whitelisted headers. Does this sound like a reasonable approach? What are the chances of accepting such a patch. Thanks, Wesley From mdounin at mdounin.ru Fri May 27 15:37:28 2016 From: mdounin at mdounin.ru (Maxim Dounin) Date: Fri, 27 May 2016 18:37:28 +0300 Subject: Adding support for HTTP trailing headers in chunked requests In-Reply-To: <8820FEEB-6085-42E3-A367-A2320DA6336D@apple.com> References: <8820FEEB-6085-42E3-A367-A2320DA6336D@apple.com> Message-ID: <20160527153728.GW36620@mdounin.ru> Hello! On Fri, May 27, 2016 at 07:35:30AM -0700, Wesley Pereira wrote: > Are there any plans to support HTTP trailing headers in chunked > requests as per > https://tools.ietf.org/html/rfc2616#section-3.6.1? No, there are no plans. > If not, we would be interested in sending a patch for adding > support. It looks like we would modify ngx_http_parse_chunked > and refactor ngx_http_parse_header_line so we can reuse it for > parsing trailing headers. And then have a directive to whitelist > which trailing headers to allow. > When the request is proxied upstream, if it?s fully buffered we > could add the trailing header as a request header. If it?s > unbuffered, then just proxy them as trailing headers. And we > would only include the whitelisted headers. > > Does this sound like a reasonable approach? What are the chances > of accepting such a patch. It's not clear how do you expect it to be used. As far as I know, trailers are not used in the real world applications. And, obviously, any attempt to use/support trailers should be well tought from security point of view. The whole idea of trailers looks like a security nightmare. -- Maxim Dounin http://nginx.org/ From giovani.rinaldi at azion.com Fri May 27 17:11:06 2016 From: giovani.rinaldi at azion.com (Giovani Rinaldi) Date: Fri, 27 May 2016 14:11:06 -0300 Subject: [PATCH] Script: fix log level when matching regular expressions Message-ID: # HG changeset patch # User Giovani Rinaldi # Date 1464122415 0 # Node ID a6209fc7fc0941be30850050025cfe830805b1a8 # Parent bc6fd7afeed6f7433c60634d9b0867ea3241b217 Script: fix log level when matching regular expressions Log should be written to log directive that accepts debug level. diff -r bc6fd7afeed6 -r a6209fc7fc09 src/http/ngx_http_script.c --- a/src/http/ngx_http_script.c Tue May 24 21:54:32 2016 +0300 +++ b/src/http/ngx_http_script.c Tue May 24 20:40:15 2016 +0000 @@ -933,7 +933,7 @@ if (rc == NGX_DECLINED) { if (e->log || (r->connection->log->log_level & NGX_LOG_DEBUG_HTTP)) { - ngx_log_error(NGX_LOG_NOTICE, r->connection->log, 0, + ngx_log_debug2(NGX_LOG_DEBUG_HTTP, r->connection->log, 0, "\"%V\" does not match \"%V\"", &code->name, &e->line); } @@ -967,7 +967,7 @@ } if (e->log || (r->connection->log->log_level & NGX_LOG_DEBUG_HTTP)) { - ngx_log_error(NGX_LOG_NOTICE, r->connection->log, 0, + ngx_log_debug2(NGX_LOG_DEBUG_HTTP, r->connection->log, 0, "\"%V\" matches \"%V\"", &code->name, &e->line); } -------------- next part -------------- An HTML attachment was scrubbed... URL: From richard at fussenegger.info Fri May 27 17:16:05 2016 From: richard at fussenegger.info (Richard Fussenegger) Date: Fri, 27 May 2016 19:16:05 +0200 Subject: [PATCH] Script: fix log level when matching regular expressions In-Reply-To: References: Message-ID: <21093967-1e7d-bc0f-85bc-a5d229ea0a66@fussenegger.info> Does this change result in the rewrite log only being available in debug builds? This is actually a very bad thing. I already have the problem that some people have a problem with nginx because the try_files log entries are only retrievable with debug builds. Regards On 5/27/2016 7:11 PM, Giovani Rinaldi wrote: > # HG changeset patch > # User Giovani Rinaldi > > # Date 1464122415 0 > # Node ID a6209fc7fc0941be30850050025cfe830805b1a8 > # Parent bc6fd7afeed6f7433c60634d9b0867ea3241b217 > Script: fix log level when matching regular expressions > > Log should be written to log directive that accepts debug level. > > diff -r bc6fd7afeed6 -r a6209fc7fc09 src/http/ngx_http_script.c > --- a/src/http/ngx_http_script.c Tue May 24 21:54:32 2016 +0300 > +++ b/src/http/ngx_http_script.c Tue May 24 20:40:15 2016 +0000 > @@ -933,7 +933,7 @@ > > if (rc == NGX_DECLINED) { > if (e->log || (r->connection->log->log_level & > NGX_LOG_DEBUG_HTTP)) { > - ngx_log_error(NGX_LOG_NOTICE, r->connection->log, 0, > + ngx_log_debug2(NGX_LOG_DEBUG_HTTP, r->connection->log, 0, > "\"%V\" does not match \"%V\"", > &code->name, &e->line); > } > @@ -967,7 +967,7 @@ > } > > if (e->log || (r->connection->log->log_level & NGX_LOG_DEBUG_HTTP)) { > - ngx_log_error(NGX_LOG_NOTICE, r->connection->log, 0, > + ngx_log_debug2(NGX_LOG_DEBUG_HTTP, r->connection->log, 0, > "\"%V\" matches \"%V\"", &code->name, &e->line); > } > > > > _______________________________________________ > 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 Fri May 27 18:33:59 2016 From: mdounin at mdounin.ru (Maxim Dounin) Date: Fri, 27 May 2016 21:33:59 +0300 Subject: [PATCH] Script: fix log level when matching regular expressions In-Reply-To: References: Message-ID: <20160527183359.GX36620@mdounin.ru> Hello! On Fri, May 27, 2016 at 02:11:06PM -0300, Giovani Rinaldi wrote: > # HG changeset patch > # User Giovani Rinaldi > # Date 1464122415 0 > # Node ID a6209fc7fc0941be30850050025cfe830805b1a8 > # Parent bc6fd7afeed6f7433c60634d9b0867ea3241b217 > Script: fix log level when matching regular expressions > > Log should be written to log directive that accepts debug level. > > diff -r bc6fd7afeed6 -r a6209fc7fc09 src/http/ngx_http_script.c > --- a/src/http/ngx_http_script.c Tue May 24 21:54:32 2016 +0300 > +++ b/src/http/ngx_http_script.c Tue May 24 20:40:15 2016 +0000 > @@ -933,7 +933,7 @@ > > if (rc == NGX_DECLINED) { > if (e->log || (r->connection->log->log_level & > NGX_LOG_DEBUG_HTTP)) { > - ngx_log_error(NGX_LOG_NOTICE, r->connection->log, 0, > + ngx_log_debug2(NGX_LOG_DEBUG_HTTP, r->connection->log, 0, > "\"%V\" does not match \"%V\"", > &code->name, &e->line); > } > @@ -967,7 +967,7 @@ > } > > if (e->log || (r->connection->log->log_level & NGX_LOG_DEBUG_HTTP)) { > - ngx_log_error(NGX_LOG_NOTICE, r->connection->log, 0, > + ngx_log_debug2(NGX_LOG_DEBUG_HTTP, r->connection->log, 0, > "\"%V\" matches \"%V\"", &code->name, &e->line); > } The patch is wrong, it will break the rewrite_log directive, see http://nginx.org/r/rewrite_log. (And no, further attempts to fix this are not needed, thanks.) -- Maxim Dounin http://nginx.org/ From piotrsikora at google.com Fri May 27 20:29:55 2016 From: piotrsikora at google.com (Piotr Sikora) Date: Fri, 27 May 2016 13:29:55 -0700 Subject: Adding support for HTTP trailing headers in chunked requests In-Reply-To: <8820FEEB-6085-42E3-A367-A2320DA6336D@apple.com> References: <8820FEEB-6085-42E3-A367-A2320DA6336D@apple.com> Message-ID: Hey Wesley, > Are there any plans to support HTTP trailing headers in chunked requests as per https://tools.ietf.org/html/rfc2616#section-3.6.1? Coincidentally, I've started looking into adding support for HTTP trailers yesterday. Also, you're referencing obsolete RFC, RFC7230 is the one you want. > If not, we would be interested in sending a patch for adding support. It looks like we would modify ngx_http_parse_chunked and refactor ngx_http_parse_header_line so we can reuse it for parsing trailing headers. And then have a directive to whitelist which trailing headers to allow. It seems that you're only considering sending HTTP/1.1 requests with trailers, not responses, is that correct? Out of curiosity, what's the use case? > When the request is proxied upstream, if it?s fully buffered we could add the trailing header as a request header. If it?s unbuffered, then just proxy them as trailing headers. Sounds reasonable, except that implementing such behavior means that for the same client request with trailers, depending on the buffering setting, upstream could receive two very different request from NGINX, which is quite confusing... and considering that recipient is allowed to ignore trailers, it means that depending on the buffering setting, other intermediate proxies and/or runtimes, headers received by the recipient could be different. Also, what about the case in which request arrives with "Connection: TE"? Would you enforce buffering or drop the trailers? > And we would only include the whitelisted headers. There is no whitelist for regular headers, why do you want to limit headers sent in trailers? Especially if you want to convert them into regular headers with buffering enabled. Best regards, Piotr Sikora From alexandernst at gmail.com Sat May 28 10:32:31 2016 From: alexandernst at gmail.com (Alexander Nestorov (alexandernst)) Date: Sat, 28 May 2016 10:32:31 +0000 Subject: Image filter crop coordinates In-Reply-To: References: Message-ID: *bump* El s?b., 21 may. 2016 a las 12:11, Alexander Nestorov (alexandernst) (< alexandernst at gmail.com>) escribi?: > I'm assigned with a task at my work that would require me to implement > crop coordinates/starting points. Are you willing to accept patches for > such functionality or is this outside of the scope of what the images > filter should be able to do? > > If you were to accept such patches, how should I implement such > functionality? As a separate configuration directive (for example, > "image_filter crop_coords x y;") or built in in the crop directive ("image_filter > crop width height x y;")? > > Regards > -------------- next part -------------- An HTML attachment was scrubbed... URL: From mdounin at mdounin.ru Mon May 30 15:01:15 2016 From: mdounin at mdounin.ru (Maxim Dounin) Date: Mon, 30 May 2016 18:01:15 +0300 Subject: Image filter crop coordinates In-Reply-To: References: Message-ID: <20160530150115.GD36620@mdounin.ru> Hello! On Sat, May 28, 2016 at 10:32:31AM +0000, Alexander Nestorov (alexandernst) wrote: > *bump* > > El s?b., 21 may. 2016 a las 12:11, Alexander Nestorov (alexandernst) (< > alexandernst at gmail.com>) escribi?: > > > I'm assigned with a task at my work that would require me to implement > > crop coordinates/starting points. Are you willing to accept patches for > > such functionality or is this outside of the scope of what the images > > filter should be able to do? > > > > If you were to accept such patches, how should I implement such > > functionality? As a separate configuration directive (for example, > > "image_filter crop_coords x y;") or built in in the crop directive ("image_filter > > crop width height x y;")? You may want to take a look at previous attempts to do something similar. In particular, see the following treads: http://mailman.nginx.org/pipermail/nginx-devel/2012-November/002930.html http://mailman.nginx.org/pipermail/nginx-devel/2012-December/003050.html http://mailman.nginx.org/pipermail/nginx-devel/2012-April/002156.html -- Maxim Dounin http://nginx.org/ From mdounin at mdounin.ru Mon May 30 15:10:02 2016 From: mdounin at mdounin.ru (Maxim Dounin) Date: Mon, 30 May 2016 15:10:02 +0000 Subject: [nginx] Trailing spaces removed. Message-ID: details: http://hg.nginx.org/nginx/rev/2d5d35409eba branches: changeset: 6573:2d5d35409eba user: Maxim Dounin date: Mon May 30 18:09:41 2016 +0300 description: Trailing spaces removed. diffstat: docs/xml/nginx/changes.xml | 4 ++-- 1 files changed, 2 insertions(+), 2 deletions(-) diffs (21 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 @@ -126,7 +126,7 @@ in addition to the address. ? ?????? ????????????? ?????????? ????????????. -the "421 Misdirected Request" response now used +the "421 Misdirected Request" response now used when rejecting requests to a virtual server different from one negotiated during an SSL handshake; this improves interoperability with some HTTP/2 clients @@ -149,7 +149,7 @@ before nginx will start reading client r -??? ????????????? ????????? proxy_cache_bypass +??? ????????????? ????????? proxy_cache_bypass ?? ??????????? ?????????????? ????????? ??????. From mdounin at mdounin.ru Tue May 31 16:27:41 2016 From: mdounin at mdounin.ru (Maxim Dounin) Date: Tue, 31 May 2016 16:27:41 +0000 Subject: [nginx] Core: skip special buffers on writing (ticket #981). Message-ID: details: http://hg.nginx.org/nginx/rev/7eb19447b2de branches: changeset: 6574:7eb19447b2de user: Maxim Dounin date: Tue May 31 05:13:30 2016 +0300 description: Core: skip special buffers on writing (ticket #981). A special last buffer with cl->buf->pos set to NULL can be present in a chain when writing request body if chunked encoding was used. This resulted in a NULL pointer dereference if it happened to be the only buffer left after a do...while loop iteration in ngx_write_chain_to_file(). The problem originally appeared in nginx 1.3.9 with chunked encoding support. Additionally, rev. 3832b608dc8d (nginx 1.9.13) changed the minimum number of buffers to trigger this from IOV_MAX (typically 1024) to NGX_IOVS_PREALLOCATE (typically 64). Fix is to skip such buffers in ngx_chain_to_iovec(), much like it is done in other places. diffstat: src/os/unix/ngx_files.c | 5 +++++ 1 files changed, 5 insertions(+), 0 deletions(-) diffs (15 lines): diff --git a/src/os/unix/ngx_files.c b/src/os/unix/ngx_files.c --- a/src/os/unix/ngx_files.c +++ b/src/os/unix/ngx_files.c @@ -356,6 +356,11 @@ ngx_chain_to_iovec(ngx_iovec_t *vec, ngx n = 0; for ( /* void */ ; cl; cl = cl->next) { + + if (ngx_buf_special(cl->buf)) { + continue; + } + size = cl->buf->last - cl->buf->pos; if (prev == cl->buf->pos) { From mdounin at mdounin.ru Tue May 31 16:27:44 2016 From: mdounin at mdounin.ru (Maxim Dounin) Date: Tue, 31 May 2016 16:27:44 +0000 Subject: [nginx] nginx-1.11.1-RELEASE Message-ID: details: http://hg.nginx.org/nginx/rev/cb783d9cc197 branches: changeset: 6575:cb783d9cc197 user: Maxim Dounin date: Tue May 31 16:43:49 2016 +0300 description: nginx-1.11.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 @@ + + + + +??? ?????? ???? ?????????? ?????????? ??????? ?? ????????? ???? +? ??????? ???????? ??? ??????????? segmentation fault +(CVE-2016-4450); +?????? ????????? ? 1.3.9. + + +a segmentation fault might occur in a worker process +while writing a specially crafted request body to a temporary file +(CVE-2016-4450); +the bug had appeared in 1.3.9. + + + + + + From mdounin at mdounin.ru Tue May 31 16:27:47 2016 From: mdounin at mdounin.ru (Maxim Dounin) Date: Tue, 31 May 2016 16:27:47 +0000 Subject: [nginx] release-1.11.1 tag Message-ID: details: http://hg.nginx.org/nginx/rev/ffab73f90763 branches: changeset: 6576:ffab73f90763 user: Maxim Dounin date: Tue May 31 16:43:49 2016 +0300 description: release-1.11.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 @@ -399,3 +399,4 @@ 5936b7ed929237f1a73b467f662611cdc0309e51 4106db71cbcb9c8274700199ac17e520902c6c0f release-1.9.14 13070ecfda67397985f0e986eb9c42ecb46d05b5 release-1.9.15 271ee30c6791847980cd139d31807541f5e569bf release-1.11.0 +cb783d9cc19761e14e1285d91c38f4b84d0b8756 release-1.11.1 From mdounin at mdounin.ru Tue May 31 16:27:49 2016 From: mdounin at mdounin.ru (Maxim Dounin) Date: Tue, 31 May 2016 16:27:49 +0000 Subject: [nginx] Version bump. Message-ID: details: http://hg.nginx.org/nginx/rev/fd003480a665 branches: stable-1.10 changeset: 6577:fd003480a665 user: Maxim Dounin date: Tue May 31 02:21:38 2016 +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 1010000 -#define NGINX_VERSION "1.10.0" +#define nginx_version 1010001 +#define NGINX_VERSION "1.10.1" #define NGINX_VER "nginx/" NGINX_VERSION #ifdef NGX_BUILD From mdounin at mdounin.ru Tue May 31 16:27:51 2016 From: mdounin at mdounin.ru (Maxim Dounin) Date: Tue, 31 May 2016 16:27:51 +0000 Subject: [nginx] Updated OpenSSL used for win32 builds. Message-ID: details: http://hg.nginx.org/nginx/rev/9809d3833cc0 branches: stable-1.10 changeset: 6578:9809d3833cc0 user: Maxim Dounin date: Tue May 24 17:44:01 2016 +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 @@ -5,7 +5,7 @@ NGINX = nginx-$(VER) TEMP = tmp OBJS = objs.msvc8 -OPENSSL = openssl-1.0.2g +OPENSSL = openssl-1.0.2h ZLIB = zlib-1.2.8 PCRE = pcre-8.38 From mdounin at mdounin.ru Tue May 31 16:27:54 2016 From: mdounin at mdounin.ru (Maxim Dounin) Date: Tue, 31 May 2016 16:27:54 +0000 Subject: [nginx] Core: skip special buffers on writing (ticket #981). Message-ID: details: http://hg.nginx.org/nginx/rev/0ac0575e955d branches: stable-1.10 changeset: 6579:0ac0575e955d user: Maxim Dounin date: Tue May 31 05:13:30 2016 +0300 description: Core: skip special buffers on writing (ticket #981). A special last buffer with cl->buf->pos set to NULL can be present in a chain when writing request body if chunked encoding was used. This resulted in a NULL pointer dereference if it happened to be the only buffer left after a do...while loop iteration in ngx_write_chain_to_file(). The problem originally appeared in nginx 1.3.9 with chunked encoding support. Additionally, rev. 3832b608dc8d (nginx 1.9.13) changed the minimum number of buffers to trigger this from IOV_MAX (typically 1024) to NGX_IOVS_PREALLOCATE (typically 64). Fix is to skip such buffers in ngx_chain_to_iovec(), much like it is done in other places. diffstat: src/os/unix/ngx_files.c | 5 +++++ 1 files changed, 5 insertions(+), 0 deletions(-) diffs (15 lines): diff --git a/src/os/unix/ngx_files.c b/src/os/unix/ngx_files.c --- a/src/os/unix/ngx_files.c +++ b/src/os/unix/ngx_files.c @@ -356,6 +356,11 @@ ngx_chain_to_iovec(ngx_iovec_t *vec, ngx n = 0; for ( /* void */ ; cl; cl = cl->next) { + + if (ngx_buf_special(cl->buf)) { + continue; + } + size = cl->buf->last - cl->buf->pos; if (prev == cl->buf->pos) { From mdounin at mdounin.ru Tue May 31 16:27:56 2016 From: mdounin at mdounin.ru (Maxim Dounin) Date: Tue, 31 May 2016 16:27:56 +0000 Subject: [nginx] nginx-1.10.1-RELEASE Message-ID: details: http://hg.nginx.org/nginx/rev/7fcde9122088 branches: stable-1.10 changeset: 6580:7fcde9122088 user: Maxim Dounin date: Tue May 31 16:47:01 2016 +0300 description: nginx-1.10.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 @@ + + + + +??? ?????? ???? ?????????? ?????????? ??????? ?? ????????? ???? +? ??????? ???????? ??? ??????????? segmentation fault +(CVE-2016-4450); +?????? ????????? ? 1.3.9. + + +a segmentation fault might occur in a worker process +while writing a specially crafted request body to a temporary file +(CVE-2016-4450); +the bug had appeared in 1.3.9. + + + + + + From mdounin at mdounin.ru Tue May 31 16:27:59 2016 From: mdounin at mdounin.ru (Maxim Dounin) Date: Tue, 31 May 2016 16:27:59 +0000 Subject: [nginx] release-1.10.1 tag Message-ID: details: http://hg.nginx.org/nginx/rev/79a20c61e23a branches: stable-1.10 changeset: 6581:79a20c61e23a user: Maxim Dounin date: Tue May 31 16:47:01 2016 +0300 description: release-1.10.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 @@ -399,3 +399,4 @@ 5936b7ed929237f1a73b467f662611cdc0309e51 4106db71cbcb9c8274700199ac17e520902c6c0f release-1.9.14 13070ecfda67397985f0e986eb9c42ecb46d05b5 release-1.9.15 d4b7edd7fa81cbf554ee3dcfe9de53ad6d1dbc69 release-1.10.0 +7fcde9122088094471a97030161e347aa940f8ed release-1.10.1