From kyprizel at gmail.com Tue Oct 1 13:37:34 2013 From: kyprizel at gmail.com (kyprizel) Date: Tue, 1 Oct 2013 17:37:34 +0400 Subject: Distributed SSL session cache In-Reply-To: <20130930180014.GM56438@mdounin.ru> References: <20130916133727.GF57081@mdounin.ru> <20130930145041.GF56438@mdounin.ru> <20130930153136.GI56438@mdounin.ru> <20130930180014.GM56438@mdounin.ru> Message-ID: Ok, I don't insist - I just need the functionality. What should I do to get my patch accepted? :) 1. Store key as bin 2. Separate files On Mon, Sep 30, 2013 at 10:00 PM, Maxim Dounin wrote: > Hello! > > On Mon, Sep 30, 2013 at 08:15:34PM +0400, kyprizel wrote: > > > $ openssl rand -base64 48 | awk '{print "-----BEGIN SESSION TICKET > > KEY-----"; print; print "-----END SESSION TICKET KEY-----"}' >> > > ticket.key.new && cat ticket.key | awk 'sa==1{n++;sa=1}/-----BEGIN > SESSION > > TICKET KEY-----/{sa=1;X=2}{if(n<3*X){print;}}' >> ticket.key.new && mv > > ticket.key.new ticket.key > > > > store not more than X=2 old keys + new one, you can add it to cron file. > > > > I know it's weird to use awk, but I only try to illustrate that it's not > a > > big problem to rotate keys with my schema ;) > > While it's not a big problem, it's certainly not something > trivial. > > > But you can' rotate keys with > > oneliner if you use "one key per file schema" - there'll be too big > > probability of mistake during nginx config parsing. > > Huh? Even trivial > > $ mv key.new key.old && openssl rand 48 > key.new > > would be fine as in a worst case a new configuration will just > fail to load. And > > $ cp key.new key.old.tmp && mv key.old.tmp key.old \ > && openssl rand 48 > key.new.tmp && mv key.new.tmp key.new > > is atomic. > > -- > Maxim Dounin > http://nginx.org/en/donation.html > > _______________________________________________ > nginx-devel mailing list > nginx-devel at nginx.org > http://mailman.nginx.org/mailman/listinfo/nginx-devel > -------------- next part -------------- An HTML attachment was scrubbed... URL: From mdounin at mdounin.ru Tue Oct 1 13:48:53 2013 From: mdounin at mdounin.ru (Maxim Dounin) Date: Tue, 01 Oct 2013 13:48:53 +0000 Subject: [nginx] nginx-1.5.6-RELEASE Message-ID: details: http://hg.nginx.org/nginx/rev/70c5cd3a61cb branches: changeset: 5406:70c5cd3a61cb user: Maxim Dounin date: Tue Oct 01 17:44:51 2013 +0400 description: nginx-1.5.6-RELEASE diffstat: docs/xml/nginx/changes.xml | 98 ++++++++++++++++++++++++++++++++++++++++++++++ 1 files changed, 98 insertions(+), 0 deletions(-) diffs (108 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,104 @@ + + + + +????????? fastcgi_buffering. + + +the "fastcgi_buffering" directive. + + + + + +????????? proxy_ssl_protocols ? proxy_ssl_ciphers.
+??????? Piotr Sikora. +
+ +the "proxy_ssl_protocols" and "proxy_ssl_ciphers" directives.
+Thanks to Piotr Sikora. +
+
+ + + +??????????? SSL handshake ??? ????????????? ??????? ??????? ????????????. + + +optimization of SSL handshakes when using long certificate chains. + + + + + +???????? ??????-?????? ???????????? SMTP pipelining. + + +the mail proxy supports SMTP pipelining. + + + + + +? ?????? ngx_http_auth_basic_module +??? ????????????? ?????? ?????????? ??????? "$apr1$".
+??????? Markus Linnala. +
+ +in the ngx_http_auth_basic_module +when using "$apr1$" password encryption method.
+Thanks to Markus Linnala. +
+
+ + + +?? MacOSX, Cygwin ? nginx/Windows +??? ????????? ??????? ??? ?????????????? ???????? location, +???? ??? ??????? location'?? ?????????????? ??????? ?????? ?????????. + + +in MacOSX, Cygwin, and nginx/Windows +incorrect location might be used to process a request +if locations were given using characters in different cases. + + + + + +?????????????? ??????????????? ? ??????????? ???????????? ????? +??? ?????????????? location'?? ????? ?? ????????. + + +automatic redirect with appended trailing slash +for proxied locations might not work. + + + + + +? ???????? ??????-???????. + + +in the mail proxy server. + + + + + +? ?????? ngx_http_spdy_module. + + +in the ngx_http_spdy_module. + + + +
+ + From mdounin at mdounin.ru Tue Oct 1 13:48:54 2013 From: mdounin at mdounin.ru (Maxim Dounin) Date: Tue, 01 Oct 2013 13:48:54 +0000 Subject: [nginx] release-1.5.6 tag Message-ID: details: http://hg.nginx.org/nginx/rev/15056a29841a branches: changeset: 5407:15056a29841a user: Maxim Dounin date: Tue Oct 01 17:44:51 2013 +0400 description: release-1.5.6 tag diffstat: .hgtags | 1 + 1 files changed, 1 insertions(+), 0 deletions(-) diffs (8 lines): diff --git a/.hgtags b/.hgtags --- a/.hgtags +++ b/.hgtags @@ -361,3 +361,4 @@ 5bdca4812974011731e5719a6c398b54f14a6d61 644a079526295aca11c52c46cb81e3754e6ad4ad release-1.5.3 376a5e7694004048a9d073e4feb81bb54ee3ba91 release-1.5.4 60e0409b9ec7ee194c6d8102f0656598cc4a6cfe release-1.5.5 +70c5cd3a61cb476c2afb3a61826e59c7cda0b7a7 release-1.5.6 From pluknet at nginx.com Wed Oct 2 07:53:11 2013 From: pluknet at nginx.com (Sergey Kandaurov) Date: Wed, 02 Oct 2013 07:53:11 +0000 Subject: [nginx] Version bump. Message-ID: details: http://hg.nginx.org/nginx/rev/d7a2729623d3 branches: changeset: 5408:d7a2729623d3 user: Sergey Kandaurov date: Wed Oct 02 11:50:56 2013 +0400 description: Version bump. diffstat: src/core/nginx.h | 4 ++-- 1 files changed, 2 insertions(+), 2 deletions(-) diffs (14 lines): diff -r 15056a29841a -r d7a2729623d3 src/core/nginx.h --- a/src/core/nginx.h Tue Oct 01 17:44:51 2013 +0400 +++ b/src/core/nginx.h Wed Oct 02 11:50:56 2013 +0400 @@ -9,8 +9,8 @@ #define _NGINX_H_INCLUDED_ -#define nginx_version 1005006 -#define NGINX_VERSION "1.5.6" +#define nginx_version 1005007 +#define NGINX_VERSION "1.5.7" #define NGINX_VER "nginx/" NGINX_VERSION #define NGINX_VAR "NGINX" From pluknet at nginx.com Wed Oct 2 07:53:12 2013 From: pluknet at nginx.com (Sergey Kandaurov) Date: Wed, 02 Oct 2013 07:53:12 +0000 Subject: [nginx] Unused macro and variable removed. Message-ID: details: http://hg.nginx.org/nginx/rev/11599a3d0c7c branches: changeset: 5409:11599a3d0c7c user: Sergey Kandaurov date: Wed Oct 02 11:51:04 2013 +0400 description: Unused macro and variable removed. The macro NGX_HTTP_DAV_COPY_BLOCK is not used since 8101d9101ed8 (0.8.9). The variable ngx_accept_mutex_lock_file was never used. diffstat: src/event/ngx_event.c | 1 - src/http/modules/ngx_http_dav_module.c | 2 -- 2 files changed, 0 insertions(+), 3 deletions(-) diffs (23 lines): diff -r d7a2729623d3 -r 11599a3d0c7c src/event/ngx_event.c --- a/src/event/ngx_event.c Wed Oct 02 11:50:56 2013 +0400 +++ b/src/event/ngx_event.c Wed Oct 02 11:51:04 2013 +0400 @@ -56,7 +56,6 @@ ngx_uint_t ngx_accept_events; ngx_uint_t ngx_accept_mutex_held; ngx_msec_t ngx_accept_mutex_delay; ngx_int_t ngx_accept_disabled; -ngx_file_t ngx_accept_mutex_lock_file; #if (NGX_STAT_STUB) diff -r d7a2729623d3 -r 11599a3d0c7c src/http/modules/ngx_http_dav_module.c --- a/src/http/modules/ngx_http_dav_module.c Wed Oct 02 11:50:56 2013 +0400 +++ b/src/http/modules/ngx_http_dav_module.c Wed Oct 02 11:51:04 2013 +0400 @@ -10,8 +10,6 @@ #include -#define NGX_HTTP_DAV_COPY_BLOCK 65536 - #define NGX_HTTP_DAV_OFF 2 From piotr at cloudflare.com Wed Oct 2 08:47:10 2013 From: piotr at cloudflare.com (Piotr Sikora) Date: Wed, 2 Oct 2013 01:47:10 -0700 Subject: [PATCH] SSL: added support for TLS Session Tickets (RFC5077). In-Reply-To: <20130930142655.GD56438@mdounin.ru> References: <20130930142655.GD56438@mdounin.ru> Message-ID: Hello Maxim, > As previously noted, the patch description is wrong. It also > make sense to add some description of the directive added. Yeah, will do. > This makes the directive unavailable without any meaningfull > diagnostics if nginx was build with old OpenSSL, which isn't very > user-friendly. I'll fix that, it makes sense to be a bit more user-friendly :) > But actually I doubt we at all need an explicit mark for default > key. Just using first one for encryption would probably be good > enough. I tend to think that being overly explicit isn't always a bad thing. In this particular case, users would need to know that the first key on the list is "active/default" while the rest of them is just old keys, which is an implementation detail and might not be obvious to everybody. > I also think it would be better to don't rely on an explicitly > written name, which will make automatic key rotation a pain - as > one will have to update both name in a configuration file and a > file with keys. E.g. Apache uses a binary file with 48 bytes of > random data, which is much easier to generate and rotate if > needed. The reason why I went with the key name in nginx.conf is because it allows users to use a naming scheme for the keys (ex. YYYYMMDDHH, if you rotate keys hourly, etc.) instead of random and meaningless names. Having said that, I don't mind pushing key name back to the file. > Not sure if this code should be here. Other file operations are > handled in the ngx_event_openssl.c, and doing the same for session > tickets might be a good idea as well. Especially if you'll > consider adding relevant directives to the mail module. Sure, sounds reasonable. I'll send updated patch in a few days. Best regards, Piotr Sikora From mdounin at mdounin.ru Wed Oct 2 10:38:33 2013 From: mdounin at mdounin.ru (Maxim Dounin) Date: Wed, 2 Oct 2013 14:38:33 +0400 Subject: Distributed SSL session cache In-Reply-To: References: <20130930145041.GF56438@mdounin.ru> <20130930153136.GI56438@mdounin.ru> <20130930180014.GM56438@mdounin.ru> Message-ID: <20131002103833.GU62063@mdounin.ru> Hello! On Tue, Oct 01, 2013 at 05:37:34PM +0400, kyprizel wrote: > Ok, I don't insist - I just need the functionality. What should I do to get > my patch accepted? :) Piotr's patch is already under review, and I don't think that duplicating efforts make sense. You may want to join the review process instead. -- Maxim Dounin http://nginx.org/en/donation.html From mdounin at mdounin.ru Wed Oct 2 11:08:38 2013 From: mdounin at mdounin.ru (Maxim Dounin) Date: Wed, 02 Oct 2013 11:08:38 +0000 Subject: [nginx] Upstream: fixed "down" and "backup" parsing. Message-ID: details: http://hg.nginx.org/nginx/rev/16b68c724438 branches: changeset: 5410:16b68c724438 user: Maxim Dounin date: Wed Oct 02 15:07:15 2013 +0400 description: Upstream: fixed "down" and "backup" parsing. Previously arguments starting with "down" or "backup" were considered valid, e.g. "server ... downFOO;". diffstat: src/http/ngx_http_upstream.c | 4 ++-- 1 files changed, 2 insertions(+), 2 deletions(-) diffs (21 lines): diff --git a/src/http/ngx_http_upstream.c b/src/http/ngx_http_upstream.c --- a/src/http/ngx_http_upstream.c +++ b/src/http/ngx_http_upstream.c @@ -4701,7 +4701,7 @@ ngx_http_upstream_server(ngx_conf_t *cf, continue; } - if (ngx_strncmp(value[i].data, "backup", 6) == 0) { + if (ngx_strcmp(value[i].data, "backup") == 0) { if (!(uscf->flags & NGX_HTTP_UPSTREAM_BACKUP)) { goto invalid; @@ -4712,7 +4712,7 @@ ngx_http_upstream_server(ngx_conf_t *cf, continue; } - if (ngx_strncmp(value[i].data, "down", 4) == 0) { + if (ngx_strcmp(value[i].data, "down") == 0) { if (!(uscf->flags & NGX_HTTP_UPSTREAM_DOWN)) { goto invalid; From mdounin at mdounin.ru Wed Oct 2 11:08:39 2013 From: mdounin at mdounin.ru (Maxim Dounin) Date: Wed, 02 Oct 2013 11:08:39 +0000 Subject: [nginx] Limit req: fixed "nodelay" parsing. Message-ID: details: http://hg.nginx.org/nginx/rev/5483d9e77b32 branches: changeset: 5411:5483d9e77b32 user: Maxim Dounin date: Wed Oct 02 15:07:17 2013 +0400 description: Limit req: fixed "nodelay" parsing. Previously arguments starting with "nodelay" were considered valid, e.g. "limit_req ... nodelayFOO;". diffstat: src/http/modules/ngx_http_limit_req_module.c | 2 +- 1 files changed, 1 insertions(+), 1 deletions(-) diffs (12 lines): diff --git a/src/http/modules/ngx_http_limit_req_module.c b/src/http/modules/ngx_http_limit_req_module.c --- a/src/http/modules/ngx_http_limit_req_module.c +++ b/src/http/modules/ngx_http_limit_req_module.c @@ -912,7 +912,7 @@ ngx_http_limit_req(ngx_conf_t *cf, ngx_c continue; } - if (ngx_strncmp(value[i].data, "nodelay", 7) == 0) { + if (ngx_strcmp(value[i].data, "nodelay") == 0) { nodelay = 1; continue; } From a.marinov at ucdn.com Wed Oct 2 12:03:18 2013 From: a.marinov at ucdn.com (Anatoli Marinov) Date: Wed, 2 Oct 2013 15:03:18 +0300 Subject: nginx usptream 302 redirect Message-ID: Hello, Is there an easy way to configure nginx upstream to follow 302 instead of send them to the browser? Thanks -------------- next part -------------- An HTML attachment was scrubbed... URL: From mdounin at mdounin.ru Wed Oct 2 12:12:25 2013 From: mdounin at mdounin.ru (Maxim Dounin) Date: Wed, 2 Oct 2013 16:12:25 +0400 Subject: nginx usptream 302 redirect In-Reply-To: References: Message-ID: <20131002121225.GZ62063@mdounin.ru> Hello! On Wed, Oct 02, 2013 at 03:03:18PM +0300, Anatoli Marinov wrote: > Hello, > Is there an easy way to configure nginx upstream to follow 302 instead of > send them to the browser? The question seems to be off-topic on the nginx-devel@ list. The answer is yes, but you'll need to configure it carefully yourself using the proxy_intercept_errors and error_page 302. -- Maxim Dounin http://nginx.org/en/donation.html From kyprizel at gmail.com Wed Oct 2 15:19:21 2013 From: kyprizel at gmail.com (kyprizel) Date: Wed, 2 Oct 2013 19:19:21 +0400 Subject: [PATCH] SSL: added support for TLS Session Tickets (RFC5077). In-Reply-To: References: <20130930142655.GD56438@mdounin.ru> Message-ID: If we have multiple keyfiles - I like the idea of marking some key as default. On Wed, Oct 2, 2013 at 12:47 PM, Piotr Sikora wrote: > Hello Maxim, > > > As previously noted, the patch description is wrong. It also > > make sense to add some description of the directive added. > > Yeah, will do. > > > This makes the directive unavailable without any meaningfull > > diagnostics if nginx was build with old OpenSSL, which isn't very > > user-friendly. > > I'll fix that, it makes sense to be a bit more user-friendly :) > > > But actually I doubt we at all need an explicit mark for default > > key. Just using first one for encryption would probably be good > > enough. > > I tend to think that being overly explicit isn't always a bad thing. > In this particular case, users would need to know that the first key > on the list is "active/default" while the rest of them is just old > keys, which is an implementation detail and might not be obvious to > everybody. > > > I also think it would be better to don't rely on an explicitly > > written name, which will make automatic key rotation a pain - as > > one will have to update both name in a configuration file and a > > file with keys. E.g. Apache uses a binary file with 48 bytes of > > random data, which is much easier to generate and rotate if > > needed. > > The reason why I went with the key name in nginx.conf is because it > allows users to use a naming scheme for the keys (ex. YYYYMMDDHH, if > you rotate keys hourly, etc.) instead of random and meaningless names. > > Having said that, I don't mind pushing key name back to the file. > > > Not sure if this code should be here. Other file operations are > > handled in the ngx_event_openssl.c, and doing the same for session > > tickets might be a good idea as well. Especially if you'll > > consider adding relevant directives to the mail module. > > Sure, sounds reasonable. > > I'll send updated patch in a few days. > > Best regards, > Piotr Sikora > > _______________________________________________ > 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 lcolina at cenditel.gob.ve Thu Oct 3 15:10:09 2013 From: lcolina at cenditel.gob.ve (lcolina at cenditel.gob.ve) Date: Thu, 03 Oct 2013 10:40:09 -0430 Subject: [PATCH 0 of 1] Dav: Changes in the destination header in MOVE and DELETE methods for files and/or folders Message-ID: Dear nginx developers, The dav module of nginx was tested with client Nautilus 3.4.2 to implement a shared file system in operations office. While testing the ngx_http_dav_module, found some conflicts that are described below: 1. In operations with MOVE method for files and/or directories: It was found a conflict with the destination header, because Nautilus client sends the URI with the user name, but the user name in the destination header is not supported by nginx, resulting in the following error. acesses_log: - - 192.168.12.229 - lcolina [27/Sep/2013:09:37:19 -0430] MOVE /data/imagenes/imagen2 HTTP/1.1 "400" 166 "-" "gvfs/1.12.3" "-" error_log: 2013/09/27 09:37:19 [debug] 18900#0: *145 http process request header line 2013/09/27 09:37:19 [debug] 18900#0: *145 http header: "Host: webdav.org.ve" 2013/09/27 09:37:19 [debug] 18900#0: *145 http header: "Destination: https://lcolina at webdav.org.ve/data/imagenes/imagen" 2013/09/27 09:37:19 [debug] 18900#0: *145 http header: "Overwrite: F" 2013/09/27 09:37:19 [error] 18900#0: *145 "Destination" URI "https://lcolina at webdav.org.ve/data/imagenes/imagen" is handled by different repository than the source URI while sending to client, client: 192.168.12.229, server: webdav.org.ve, request: "MOVE /data/imagenes/imagen2 HTTP/1.1", host: "webdav.org.ve" I think this should be changed because according to the standard is optional URI that contains the user information. So nginx should be able to handle the URI with the user name or not. ?The user information, if present, is followed by a commercial at-sign ("@") that delimits it from the host.? This conflict is solved in line @@ -579,6 +578,16 @@ the patch below. 2. In operations with MOVE method for directories: It was found a conflict when rename a folder from Nautilus client, the source path contains no final slash, resulting a bad request error because nginx requires source path with final slash. acesses_log: - - 192.168.12.229 - lcolina [27/Sep/2013:11:08:34 -0430] MOVE /data/repositorio HTTP/1.1 "400" 166 "-" "gvfs/1.12.3" "-" error_log: 2013/09/27 11:08:34 [debug] 27733#0: *146 http copy from: "/srv/data/repositorio" 2013/09/27 11:08:34 [debug] 27733#0: *146 http copy to: "/srv/data/repositorio1" 2013/09/27 11:08:34 [error] 27733#0: *146 "/data/repositorio" is collection while sending to client, client: 192.168.12.229, server: webdav.org.ve, request: "MOVE /data/repositorio HTTP/1.1", host: "webdav.org.ve" 2013/09/27 11:08:34 [debug] 27733#0: *146 http finalize request: 400, "/data/repositorio?" a:1, c:1 2013/09/27 11:08:34 [debug] 27733#0: *146 http special response: 400, "/data/repositorio?" 2013/09/27 11:08:34 [debug] 27733#0: *146 http set discard body 2013/09/27 11:08:34 [debug] 27733#0: *146 xslt filter header 2013/09/27 11:08:34 [debug] 27733#0: *146 HTTP/1.1 400 Bad Request I think this should be changed because according to the standard not mandatory if the directory path contains final slash. So nginx should be able to handle the source path with final slash or not. This conflict is solved in line @@ -736,10 +745,9 @@ the patch below. 3. In operations with DELETE method for directories: It was found a conflict when delete a folder from Nautilus client, the directory path to eliminate contains no final slash, causing a conflict because nginx requires source path with final slash, similar to the case number 2. acesses_log: - - 192.168.12.229 - lcolina [28/Sep/2013:04:03:29 -0430] DELETE /data/imagenes/Carpeta%20sin%20t%C3%ADtulo HTTP/1.1 "409" 160 "-" "gvfs/1.12.3" "-" error_log: 2013/09/28 04:03:29 [debug] 13397#0: *211 http delete filename: "/srv/data/imagenes/Carpeta sin t?tulo" 2013/09/28 04:03:29 [error] 13397#0: *211 DELETE "/srv/data/imagenes/Carpeta sin t?tulo" failed (21: Is a directory) while sending to client, client: 192.168.12.229, server: web dav.org.ve, request: "DELETE /data/imagenes/Carpeta%20sin%20t%C3%ADtulo HTTP/1.1", host: "webdav.org.ve" 2013/09/28 04:03:29 [debug] 13397#0: *211 http finalize request: 409, "/data/imagenes/Carpeta sin t?tulo?" a:1, c:1 2013/09/28 04:03:29 [debug] 13397#0: *211 http special response: 409, "/data/imagenes/Carpeta sin t?tulo?" 2013/09/28 04:03:29 [debug] 13397#0: *211 http set discard body 2013/09/28 04:03:29 [debug] 13397#0: *211 xslt filter header 2013/09/28 04:03:29 [debug] 13397#0: *211 HTTP/1.1 409 Conflict So I think nginx should be able to handle the directory path to eliminate with final slash or not. This conflict is solved in line @@ -338,10 +338,9 @@ the patch below. Best regards, Laura Colina Centro Nacional de Desarrollo e Investigaci?n en Tecnolog?as Libres (CENDITEL) Ministerio del Poder Popular para Ciencia, Tecnolog?a e Innovaci?n Rep?blica Bolivariana de Venezuela From lcolina at cenditel.gob.ve Thu Oct 3 15:10:10 2013 From: lcolina at cenditel.gob.ve (lcolina at cenditel.gob.ve) Date: Thu, 03 Oct 2013 10:40:10 -0430 Subject: [PATCH 1 of 1] Changes in the destination header in MOVE and DELETE methods for files and/or folders In-Reply-To: References: Message-ID: # HG changeset patch # User Laura Colina # Date 1378836243 16200 # Node ID c6e3ea382a3ab5f98350c5810c3ebc080ae0f0ae # Parent 72e31d88defadc94a17ce208c487aac98632e8f2 Changes in the destination header in MOVE and DELETE methods for files and/or folders diff -r 72e31d88defa -r c6e3ea382a3a src/http/modules/ngx_http_dav_module.c --- a/src/http/modules/ngx_http_dav_module.c Mon Sep 23 19:37:13 2013 +0400 +++ b/src/http/modules/ngx_http_dav_module.c Tue Sep 10 13:34:03 2013 -0430 @@ -338,10 +338,9 @@ if (ngx_is_dir(&fi)) { - if (r->uri.data[r->uri.len - 1] != '/') { - ngx_log_error(NGX_LOG_ERR, r->connection->log, NGX_EISDIR, - "DELETE \"%s\" failed", path.data); - return NGX_HTTP_CONFLICT; + if (path.data[path.len - 1] == '/') { + path.len--; + path.data[path.len] = '\0'; } depth = ngx_http_dav_depth(r, NGX_HTTP_DAV_INFINITY_DEPTH); @@ -352,7 +351,7 @@ return NGX_HTTP_BAD_REQUEST; } - path.len -= 2; /* omit "/\0" */ + path.len -= 1; /* omit "\0" */ dir = 1; @@ -579,6 +578,16 @@ host = dest->value.data + sizeof("http://") - 1; } + for (p = host; *p!='\0'; p++) { + if (*p == '/') { + break; + } + else if (*p == '@') { + host = p + 1; + break; + } + } + if (ngx_strncmp(host, r->headers_in.server.data, len) != 0) { ngx_log_error(NGX_LOG_ERR, r->connection->log, 0, "\"Destination\" URI \"%V\" is handled by " @@ -736,10 +745,9 @@ if (ngx_is_dir(&fi)) { - if (r->uri.data[r->uri.len - 1] != '/') { - ngx_log_error(NGX_LOG_ERR, r->connection->log, 0, - "\"%V\" is collection", &r->uri); - return NGX_HTTP_BAD_REQUEST; + if (path.data[path.len - 1] == '/') { + path.len--; + path.data[path.len] = '\0'; } if (overwrite) { @@ -756,7 +764,7 @@ if (ngx_is_dir(&fi)) { - path.len -= 2; /* omit "/\0" */ + path.len -= 1; /* omit "\0" */ if (r->method == NGX_HTTP_MOVE) { if (ngx_rename_file(path.data, copy.path.data) != NGX_FILE_ERROR) { From mdounin at mdounin.ru Thu Oct 3 15:17:24 2013 From: mdounin at mdounin.ru (Maxim Dounin) Date: Thu, 3 Oct 2013 19:17:24 +0400 Subject: [PATCH] SSL: added support for TLS Session Tickets (RFC5077). In-Reply-To: References: <20130930142655.GD56438@mdounin.ru> Message-ID: <20131003151724.GI62063@mdounin.ru> Hello! On Wed, Oct 02, 2013 at 01:47:10AM -0700, Piotr Sikora wrote: [...] > > But actually I doubt we at all need an explicit mark for default > > key. Just using first one for encryption would probably be good > > enough. > > I tend to think that being overly explicit isn't always a bad thing. > In this particular case, users would need to know that the first key > on the list is "active/default" while the rest of them is just old > keys, which is an implementation detail and might not be obvious to > everybody. While being explicit is a good thing, this will require (lots of) custom code in a configuration parsing and subsequent handling. On the other hand, ngx_conf_set_str_array_slot() should be enough otherwise. I don't think the explicitness here deserves custom code it requires. YMMV. -- Maxim Dounin http://nginx.org/en/donation.html From mdounin at mdounin.ru Thu Oct 3 16:08:30 2013 From: mdounin at mdounin.ru (Maxim Dounin) Date: Thu, 3 Oct 2013 20:08:30 +0400 Subject: [PATCH 0 of 1] Dav: Changes in the destination header in MOVE and DELETE methods for files and/or folders In-Reply-To: References: Message-ID: <20131003160829.GK62063@mdounin.ru> Hello! On Thu, Oct 03, 2013 at 10:40:09AM -0430, lcolina at cenditel.gob.ve wrote: > Dear nginx developers, > > The dav module of nginx was tested with client Nautilus 3.4.2 to > implement a shared file system in operations office. > > While testing the ngx_http_dav_module, found some conflicts that > are described below: > > 1. In operations with MOVE method for files and/or directories: > It was found a conflict with the destination header, because > Nautilus client sends the URI with the user name, but the user > name in the destination header is not supported by nginx, > resulting in the following error. > > acesses_log: > - - 192.168.12.229 - lcolina [27/Sep/2013:09:37:19 -0430] MOVE /data/imagenes/imagen2 HTTP/1.1 "400" 166 "-" "gvfs/1.12.3" "-" > > error_log: > 2013/09/27 09:37:19 [debug] 18900#0: *145 http process request header line > 2013/09/27 09:37:19 [debug] 18900#0: *145 http header: "Host: webdav.org.ve" > 2013/09/27 09:37:19 [debug] 18900#0: *145 http header: "Destination: https://lcolina at webdav.org.ve/data/imagenes/imagen" > 2013/09/27 09:37:19 [debug] 18900#0: *145 http header: "Overwrite: F" > 2013/09/27 09:37:19 [error] 18900#0: *145 "Destination" URI "https://lcolina at webdav.org.ve/data/imagenes/imagen" is handled by different repository than the source URI while sending to client, client: 192.168.12.229, server: webdav.org.ve, request: "MOVE /data/imagenes/imagen2 HTTP/1.1", host: "webdav.org.ve" > > I think this should be changed because according to the standard > is optional URI that contains the user information. So nginx > should be able to handle the URI with the user name or not. ?The > user information, if present, is followed by a commercial > at-sign ("@") that delimits it from the host.? There is no "userinfo" in a http scheme URLs syntax as per RFC2616. Quote from http://tools.ietf.org/html/rfc2616#section-3.2: The "http" scheme is used to locate network resources via the HTTP protocol. This section defines the scheme-specific syntax and semantics for http URLs. http_URL = "http:" "//" host [ ":" port ] [ abs_path [ "?" query ]] Upcoming work of httpbis explicitly prohibts use of userinfo in http messages, see http://tools.ietf.org/html/draft-ietf-httpbis-p1-messaging-24#section-2.7.1: The URI generic syntax for authority also includes a deprecated userinfo subcomponent ([RFC3986], Section 3.2.1) for including user authentication information in the URI. Some implementations make use of the userinfo component for internal configuration of authentication information, such as within command invocation options, configuration files, or bookmark lists, even though such usage might expose a user identifier or password. A sender MUST NOT generate the userinfo subcomponent (and its "@" delimiter) when an "http" URI reference is generated within a message as a request target or header field value. Before making use of an "http" URI reference received from an untrusted source, a recipient ought to parse for userinfo and treat its presence as an error; it is likely being used to obscure the authority for the sake of phishing attacks. There is no userinfo support in nginx, and it's intentional. And, as the above links show, this seems to agree with standards. > 2. In operations with MOVE method for directories: It was found > a conflict when rename a folder from Nautilus client, the > source path contains no final slash, resulting a bad request > error because nginx requires source path with final slash. > > acesses_log: > - - 192.168.12.229 - lcolina [27/Sep/2013:11:08:34 -0430] MOVE /data/repositorio HTTP/1.1 "400" 166 "-" "gvfs/1.12.3" "-" > > error_log: > 2013/09/27 11:08:34 [debug] 27733#0: *146 http copy from: "/srv/data/repositorio" > 2013/09/27 11:08:34 [debug] 27733#0: *146 http copy to: "/srv/data/repositorio1" > 2013/09/27 11:08:34 [error] 27733#0: *146 "/data/repositorio" is collection while sending to client, client: 192.168.12.229, server: webdav.org.ve, request: "MOVE /data/repositorio HTTP/1.1", host: "webdav.org.ve" > 2013/09/27 11:08:34 [debug] 27733#0: *146 http finalize request: 400, "/data/repositorio?" a:1, c:1 > 2013/09/27 11:08:34 [debug] 27733#0: *146 http special response: 400, "/data/repositorio?" > 2013/09/27 11:08:34 [debug] 27733#0: *146 http set discard body > 2013/09/27 11:08:34 [debug] 27733#0: *146 xslt filter header > 2013/09/27 11:08:34 [debug] 27733#0: *146 HTTP/1.1 400 Bad Request > > I think this should be changed because according to the standard > not mandatory if the directory path contains final slash. So > nginx should be able to handle the source path with final slash > or not. > This conflict is solved in line @@ -736,10 +745,9 @@ the patch below. The collection identifier is with trailing slash, as in conformance with RFC 4918, http://tools.ietf.org/html/rfc4918#section-8.3: Identifiers for collections SHOULD end in a '/' character. Suggested patch seems to try to implement the MAY clause from http://tools.ietf.org/html/rfc4918#section-5.2: There is a standing convention that when a collection is referred to by its name without a trailing slash, the server MAY handle the request as if the trailing slash were present. In this case, it SHOULD return a Content-Location header in the response, pointing to the URL ending with the "/". For example, if a client invokes a method on http://example.com/blah (no trailing slash), the server may respond as if the operation were invoked on http://example.com/blah/ (trailing slash), and should return a Content-Location header with the value http://example.com/blah/. Wherever a server produces a URL referring to a collection, the server SHOULD include the trailing slash. In general, clients SHOULD use the trailing slash form of collection names. If clients do not use the trailing slash form the client needs to be prepared to see a redirect response. Clients will find the DAV:resourcetype property more reliable than the URL to find out if a resource is a collection. But it clearly lacks Content-Location. And it may be much better idea to change the client to follow SHOULD clauses instead (or find out a reason why it doesn't in your case). We may consider returning redirects in such cases with trailing slash added, much like it currently happens on GET requests. But I tend to think that it would be better to preserve 400. > 3. In operations with DELETE method for directories: It was > found a conflict when delete a folder from Nautilus client, the > directory path to eliminate contains no final slash, causing a > conflict because nginx requires source path with final slash, > similar to the case number 2. See above. -- Maxim Dounin http://nginx.org/en/donation.html From rob.stradling at comodo.com Fri Oct 4 12:25:25 2013 From: rob.stradling at comodo.com (Rob Stradling) Date: Fri, 04 Oct 2013 13:25:25 +0100 Subject: OCSP stapling limitations (was Re: [PATCH 0 of 4] OCSP stapling) In-Reply-To: References: Message-ID: <524EB3B5.5060203@comodo.com> On 05/09/12 12:14, Maxim Dounin wrote: > Hello! > > Here are patches for OCSP stapling support. Testing and > review appreciated. > Known limitations: > > - Unless externally set OCSP response is used (via the "ssl_stapling_file" > directive), stapled response won't be sent in a first connection. This > is due to the fact that OCSP responders are currently queried by nginx > once it receives connection with certificate_status extension in ClientHello, > and due to limitations in OpenSSL API (certificate status callback is > blocking). Hi Maxim. This limitation is turning out to be a problem, for several reasons: 1. In some situations, the limitation appears to be amplified - there are more "first connections" than you might expect. Netcraft reported [1] that: "Fewer than 50% of the CloudFlare IP addresses responded with an OCSP response stapled on the first non-discarded connection attempt. Even after 20 requests, the response rate is not consistent, some IP addresses still fail to staple an OCSP response on each and every SSL connection. This inconsistent behaviour may be down to a number of separate machines responding to the same IP address either in different locations, or behind a load balancer." 2. The CA/Browser Forum are defining a "must staple" certificate extension [2], which we anticipate that browsers (e.g. [3]) will recognize and enforce, by aborting the TLS handshake if a stapled OCSP response was not sent. 3. Google are planning [4] to require the use of Certificate Transparency (CT) [5], and this plan expects OCSP Stapling to work reliably. What work needs to be done to enable Nginx to send a stapled OCSP response every time (without having to use the "ssl_stapling_file" directive)? Could you work around the fact that the OpenSSL certificate status callback is blocking? Or would you absolutely require a non-blocking alternative to be available? (Ben Laurie, who is on both the OpenSSL and CT teams, told me recently: "If there's changes needed to OpenSSL, it'd be helpful to know sooner rather than later.") Thanks. [1] http://news.netcraft.com/archives/2013/07/19/microsoft-achieves-world-domination-in-ocsp-stapling.html [2] http://tools.ietf.org/html/draft-hallambaker-muststaple-00 [3] https://bugzilla.mozilla.org/show_bug.cgi?id=901698 [4] http://www.ietf.org/mail-archive/web/tls/current/msg10083.html [5] http://tools.ietf.org/html/rfc6962 -- Rob Stradling Senior Research & Development Scientist COMODO - Creating Trust Online From a.marinov at ucdn.com Fri Oct 4 13:20:04 2013 From: a.marinov at ucdn.com (Anatoli Marinov) Date: Fri, 4 Oct 2013 16:20:04 +0300 Subject: nginx usptream 302 redirect In-Reply-To: <20131002121225.GZ62063@mdounin.ru> References: <20131002121225.GZ62063@mdounin.ru> Message-ID: Where I can ask for a help with this configuration? I cannot manage to configure it. My config is as follow: http { proxy_intercept_errors on; proxy_cache_path /home/toli/nginx/run/cache keys_zone=zone_c1:256m inactive=5d max_size=30g; upstream up_servers { server 127.0.1.1:8081; } server { listen 127.0.0.1:8080; location / { proxy_cache zone_c1; proxy_pass http://127.0.1.1:8081; proxy_temp_path tmp ; error_page 301 302 307 @redir; } location @redir { proxy_cache zone_c1; proxy_pass $upstream_http_location; proxy_temp_path tmp ; } } } But I receive 500 internal server error and in the logs I have: invalid URL prefix in "" I think the variable $upstream_http_location is empty. Should I use different variable? Thanks in advance! On Wed, Oct 2, 2013 at 3:12 PM, Maxim Dounin wrote: > Hello! > > On Wed, Oct 02, 2013 at 03:03:18PM +0300, Anatoli Marinov wrote: > > > Hello, > > Is there an easy way to configure nginx upstream to follow 302 instead of > > send them to the browser? > > The question seems to be off-topic on the nginx-devel@ list. > > The answer is yes, but you'll need to configure it carefully > yourself using the proxy_intercept_errors and error_page 302. > > -- > Maxim Dounin > http://nginx.org/en/donation.html > > _______________________________________________ > 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 Oct 4 14:11:23 2013 From: mdounin at mdounin.ru (Maxim Dounin) Date: Fri, 4 Oct 2013 18:11:23 +0400 Subject: nginx usptream 302 redirect In-Reply-To: References: <20131002121225.GZ62063@mdounin.ru> Message-ID: <20131004141123.GO62063@mdounin.ru> Hello! On Fri, Oct 04, 2013 at 04:20:04PM +0300, Anatoli Marinov wrote: > Where I can ask for a help with this configuration? > > I cannot manage to configure it. The nginx@ list is intended for user questions, see http://nginx.org/en/support.html. [...] > But I receive 500 internal server error and in the logs I have: > invalid URL prefix in "" > I think the variable $upstream_http_location is empty. Should I use > different variable? You should save a value of the $upstream_http_location variable before upstream data will be reinitialized, e.g. via "set $foo $upstream_http_location". -- Maxim Dounin http://nginx.org/en/donation.html From a.marinov at ucdn.com Fri Oct 4 14:51:32 2013 From: a.marinov at ucdn.com (Anatoli Marinov) Date: Fri, 4 Oct 2013 17:51:32 +0300 Subject: nginx usptream 302 redirect In-Reply-To: <20131004141123.GO62063@mdounin.ru> References: <20131002121225.GZ62063@mdounin.ru> <20131004141123.GO62063@mdounin.ru> Message-ID: I sent an email to nginx@ also. With your approach also don't work. I mean "set $foo $upstream_http_location". I use this in the first location block and in the second I used $foo instead of $upstream_http_location but it is also empty and I get 500 again. So the config now is: http { proxy_intercept_errors on; proxy_cache_path /home/toli/nginx/run/cache keys_zone=zone_c1:256m inactive=5d max_size=30g; upstream up_servers { server 127.0.1.1:8081; } server { listen 127.0.0.1:8080; set $foo "sasdfsdfsdf"; location / { proxy_cache zone_c1; proxy_pass http://127.0.1.1:8081; proxy_temp_path tmp ; set $foo $upstream_http_location; error_page 301 302 307 @redir; } location @redir { proxy_cache zone_c1; proxy_pass $foo; proxy_temp_path tmp ; } } } The issue appears again - 500 internal server error. On Fri, Oct 4, 2013 at 5:11 PM, Maxim Dounin wrote: > Hello! > > On Fri, Oct 04, 2013 at 04:20:04PM +0300, Anatoli Marinov wrote: > > > Where I can ask for a help with this configuration? > > > > I cannot manage to configure it. > > The nginx@ list is intended for user questions, see > http://nginx.org/en/support.html. > > [...] > > > But I receive 500 internal server error and in the logs I have: > > invalid URL prefix in "" > > I think the variable $upstream_http_location is empty. Should I use > > different variable? > > You should save a value of the $upstream_http_location variable > before upstream data will be reinitialized, e.g. via "set $foo > $upstream_http_location". > > -- > Maxim Dounin > http://nginx.org/en/donation.html > > _______________________________________________ > 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 Oct 4 15:15:40 2013 From: mdounin at mdounin.ru (Maxim Dounin) Date: Fri, 4 Oct 2013 19:15:40 +0400 Subject: nginx usptream 302 redirect In-Reply-To: References: <20131002121225.GZ62063@mdounin.ru> <20131004141123.GO62063@mdounin.ru> Message-ID: <20131004151540.GR62063@mdounin.ru> Hello! On Fri, Oct 04, 2013 at 05:51:32PM +0300, Anatoli Marinov wrote: > I sent an email to nginx@ also. Let the discussion continue there. As already said, it's offtopic in nginx-devel@ list. [...] -- Maxim Dounin http://nginx.org/en/donation.html From a.marinov at ucdn.com Fri Oct 4 15:35:33 2013 From: a.marinov at ucdn.com (Anatoli Marinov) Date: Fri, 4 Oct 2013 18:35:33 +0300 Subject: nginx usptream 302 redirect In-Reply-To: <20131004151540.GR62063@mdounin.ru> References: <20131002121225.GZ62063@mdounin.ru> <20131004141123.GO62063@mdounin.ru> <20131004151540.GR62063@mdounin.ru> Message-ID: Sure, Thank you ! On Fri, Oct 4, 2013 at 6:15 PM, Maxim Dounin wrote: > Hello! > > On Fri, Oct 04, 2013 at 05:51:32PM +0300, Anatoli Marinov wrote: > > > I sent an email to nginx@ also. > > Let the discussion continue there. As already said, it's offtopic > in nginx-devel@ list. > > [...] > > -- > Maxim Dounin > http://nginx.org/en/donation.html > > _______________________________________________ > 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 Sun Oct 6 09:37:08 2013 From: mdounin at mdounin.ru (Maxim Dounin) Date: Sun, 6 Oct 2013 13:37:08 +0400 Subject: Help with shared memory usage In-Reply-To: References: <20130701113629.GO20717@mdounin.ru> <20130729171109.GA2130@mdounin.ru> <20130730100931.GD2130@mdounin.ru> Message-ID: <20131006093708.GY62063@mdounin.ru> Hello! On Wed, Jul 31, 2013 at 12:28:02AM -0300, Wandenberg Peixoto wrote: > Hello! > > Thanks for your help. I hope that the patch be OK now. > I don't know if the function and variable names are on nginx pattern. > Feel free to change the patch. > If you have any other point before accept it, will be a pleasure to fix it. Sorry for long delay. As promised, I've looked into this. Apart from multiple style problems, I see at least one case of possible use of uninitialized memory. See below for comments. > > --- src/core/ngx_slab.c 2013-05-06 07:27:10.000000000 -0300 > +++ src/core/ngx_slab.c 2013-07-31 00:21:08.043034442 -0300 > @@ -615,6 +615,26 @@ fail: > > > static ngx_slab_page_t * > +ngx_slab_merge_with_neighbour(ngx_slab_pool_t *pool, ngx_slab_page_t *page) A side note: there are multiple issues with style in this patch. In no particular order: 1. There is no reason to return ngx_slab_page_t * here. Just ngx_int_t should be enough (or, even void would be good enough, see below). 2. It is recommended do place function implementation below it's use (and add a prototype). This allows to read the code linearly, top-down. > +{ > + ngx_slab_page_t *neighbour = &page[page->slab]; Here "neighbour" may point outside of the allocated page structures if we are freeing the last page in the pool. > + if (((ngx_slab_page_t *) neighbour->prev != NULL) && (neighbour->next > != NULL) && ((neighbour->prev & NGX_SLAB_PAGE_MASK) == NGX_SLAB_PAGE)) { In no particular order: 1. Style problems - more than 80 chars, extra parens. 2. There is probably no need to check both prev and next. 3. See below about casting neighbour->prev to (ngx_slab_page_t *). > + page->slab += neighbour->slab; > + > + ((ngx_slab_page_t *) neighbour->prev)->next = neighbour->next; > + neighbour->next->prev = neighbour->prev; Casting neighbour->prev to (ngx_slab_page_t *) without removing last NGX_SLAB_PAGE_MASK bits isn't really a good idea. It works here as NGX_SLAB_PAGE == 0, but may fail in other cases. It would be much better to use a snippet already used in other places: prev = (ngx_slab_page_t *) (p->prev & ~NGX_SLAB_PAGE_MASK); prev->next = p->next; p->next->prev = p->prev; > + neighbour->slab = NGX_SLAB_PAGE_FREE; > + neighbour->prev = (uintptr_t) &pool->free; > + neighbour->next = &pool->free; Unused page structures used to be zeroed. Any reason for prev/next pointing to pool->free? It looks like something like p->slab = NGX_SLAB_PAGE_FREE; p->next = NULL; p->prev = NGX_SLAB_PAGE; would be reasonable here. > + > + return page; > + } > + return NULL; > +} See above, there is no need to return page as it's unused. Something like return NGX_OK / return NGX_DECLINED would be better here - if we are going to check if any pages were actually merged. Additionally, an empty line should be before last return. > + > + > +static ngx_slab_page_t * > ngx_slab_alloc_pages(ngx_slab_pool_t *pool, ngx_uint_t pages) > { > ngx_slab_page_t *page, *p; > @@ -657,6 +677,19 @@ ngx_slab_alloc_pages(ngx_slab_pool_t *po > } > } > > + ngx_flag_t retry = 0; > + for (page = pool->free.next; page != &pool->free;) { > + if (ngx_slab_merge_with_neighbour(pool, page)) { > + retry = 1; > + } else { > + page = page->next; > + } > + } > + > + if (retry) { > + return ngx_slab_alloc_pages(pool, pages); > + } > + Apart from multiple style issues here, I think we should choose one aproach: either loop over free pages and merge them here, or maintain all free pages merged in ngx_slab_free_pages() (that is, merge in both directions there). > ngx_slab_error(pool, NGX_LOG_CRIT, "ngx_slab_alloc() failed: no > memory"); > > return NULL; > @@ -687,6 +720,8 @@ ngx_slab_free_pages(ngx_slab_pool_t *poo > page->next->prev = (uintptr_t) page; > > pool->free.next = page; > + > + ngx_slab_merge_with_neighbour(pool, page); > } See above. Overral it looks much better than previous patch, but still needs more work. -- Maxim Dounin http://nginx.org/en/donation.html From mdounin at mdounin.ru Sun Oct 6 10:14:10 2013 From: mdounin at mdounin.ru (Maxim Dounin) Date: Sun, 6 Oct 2013 14:14:10 +0400 Subject: OCSP stapling limitations (was Re: [PATCH 0 of 4] OCSP stapling) In-Reply-To: <524EB3B5.5060203@comodo.com> References: <524EB3B5.5060203@comodo.com> Message-ID: <20131006101410.GZ62063@mdounin.ru> Hello! On Fri, Oct 04, 2013 at 01:25:25PM +0100, Rob Stradling wrote: > On 05/09/12 12:14, Maxim Dounin wrote: > >Hello! > > > >Here are patches for OCSP stapling support. Testing and > >review appreciated. > > >Known limitations: > > > >- Unless externally set OCSP response is used (via the "ssl_stapling_file" > > directive), stapled response won't be sent in a first connection. This > > is due to the fact that OCSP responders are currently queried by nginx > > once it receives connection with certificate_status extension in ClientHello, > > and due to limitations in OpenSSL API (certificate status callback is > > blocking). > > Hi Maxim. This limitation is turning out to be a problem, for > several reasons: > > 1. In some situations, the limitation appears to be amplified - > there are more "first connections" than you might expect. Netcraft > reported [1] that: > "Fewer than 50% of the CloudFlare IP addresses responded with an > OCSP response stapled on the first non-discarded connection attempt. > Even after 20 requests, the response rate is not consistent, some IP > addresses still fail to staple an OCSP response on each and every > SSL connection. This inconsistent behaviour may be down to a number > of separate machines responding to the same IP address either in > different locations, or behind a load balancer." It's believed to be related to a number of hosts CloudFlare uses for each https domain and the fact that domains checked by Netcraft are mostly unused. Piotr Sikora may be able to provide more info. I don't think this is a problem for ordinary uses of OCSP stapling, as for unused domains optimization provided by OCSP stapling doesn't really matter. If it turns out to be a real problem - an obvious way to improve things is to provide a cache for OCSP responses shared between worker processes. > 2. The CA/Browser Forum are defining a "must staple" certificate > extension [2], which we anticipate that browsers (e.g. [3]) will > recognize and enforce, by aborting the TLS handshake if a stapled > OCSP response was not sent. I believe it was said more than once that this changes OCSP stapling quite significantly. As of now it's an optimization technology, while with "must staple" it will become a required part of a certificate. There is no surprise such change requires quite a different coding aproach. BTW, the draft in question was already expired. > 3. Google are planning [4] to require the use of Certificate > Transparency (CT) [5], and this plan expects OCSP Stapling to work > reliably. It looks like there is more than one way to include signed certificate timestamp, and OCSP stapling is just one of them. And I'm not sure it's a good way - the X509v3 certificate extension should be better, as long as it's a required part of a certificate. > What work needs to be done to enable Nginx to send a stapled OCSP > response every time (without having to use the "ssl_stapling_file" > directive)? I tend to think that ssl_stapling_file is a good way to provide an OCSP response if it's required for some reason. > Could you work around the fact that the OpenSSL certificate status > callback is blocking? Or would you absolutely require a > non-blocking alternative to be available? > (Ben Laurie, who is on both the OpenSSL and CT teams, told me > recently: "If there's changes needed to OpenSSL, it'd be helpful to > know sooner > rather than later.") I don't think changing OpenSSL to support non-blocking callbacks is feasible. While it's something we would like to have (just couple of weeks ago we've discussed here that non-blocking callbacks are required to support external session store), it looks like too major change for OpenSSL. It will also take several years to be actually usable. -- Maxim Dounin http://nginx.org/en/donation.html From ashuven63 at gmail.com Sun Oct 6 15:50:32 2013 From: ashuven63 at gmail.com (Ashwini Venkatesh) Date: Sun, 6 Oct 2013 21:20:32 +0530 Subject: Nginx spdy server push implementation help Message-ID: My team is working on extending the present SPDY module by enabling server push. Till now we have understood the clear requirements and seen the implementation of the same in apache and used nodejs to see live SPDY sessions which support server push. We have also understood to an extent the essentials of Nginx and it's working. Now we are in a stage where we would like some guidance. Questions like should server push be a separate module since the handling of the request changes (if some content has to be pushed then open new streams), if not, should it be made a separate filter are posed. If anyone could guide us or provide some pointers it would be of a great help. Thank you. -- Regards, Ashwini Venkatesh -------------- next part -------------- An HTML attachment was scrubbed... URL: From rob.stradling at comodo.com Mon Oct 7 10:29:00 2013 From: rob.stradling at comodo.com (Rob Stradling) Date: Mon, 07 Oct 2013 11:29:00 +0100 Subject: OCSP stapling limitations (was Re: [PATCH 0 of 4] OCSP stapling) In-Reply-To: <20131006101410.GZ62063@mdounin.ru> References: <524EB3B5.5060203@comodo.com> <20131006101410.GZ62063@mdounin.ru> Message-ID: <52528CEC.7060104@comodo.com> On 06/10/13 11:14, Maxim Dounin wrote: >> 2. The CA/Browser Forum are defining a "must staple" certificate >> extension [2], which we anticipate that browsers (e.g. [3]) will >> recognize and enforce, by aborting the TLS handshake if a stapled >> OCSP response was not sent. > > I believe it was said more than once that this changes OCSP > stapling quite significantly. As of now it's an optimization > technology, Yes, but it's an optimization technology that seems to work reliably in httpd and IIS. ;-) > while with "must staple" it will become a required part of a > certificate. There is no surprise such change requires quite a > different coding aproach. > > BTW, the draft in question was already expired. So it has. I've notified the author. Thanks. >> 3. Google are planning [4] to require the use of Certificate >> Transparency (CT) [5], and this plan expects OCSP Stapling to work >> reliably. > > It looks like there is more than one way to include signed > certificate timestamp, and OCSP stapling is just one of them. And > I'm not sure it's a good way - the X509v3 certificate extension > should be better, as long as it's a required part of a > certificate. Both approaches have advantages and disadvantages. Google plan to require multiple Signed Certificate Timestamps (SCTs) when the X509v3 certificate extension approach is used (= certificate size bloat), but only 1 SCT when the OCSP Stapling approach is used. >> What work needs to be done to enable Nginx to send a stapled OCSP >> response every time (without having to use the "ssl_stapling_file" >> directive)? > > I tend to think that ssl_stapling_file is a good way to provide an > OCSP response if it's required for some reason. It works, but doesn't it require the user to regularly download a newer OCSP Response for each certificate, update the contents of their stapling file(s), and reload Nginx? IMHO, this needs to be fully automated, just as it is in httpd and IIS. Are you saying that there's zero chance of this ever happening? >> Could you work around the fact that the OpenSSL certificate status >> callback is blocking? Or would you absolutely require a >> non-blocking alternative to be available? >> (Ben Laurie, who is on both the OpenSSL and CT teams, told me >> recently: "If there's changes needed to OpenSSL, it'd be helpful to >> know sooner rather than later.") > > I don't think changing OpenSSL to support non-blocking callbacks > is feasible. While it's something we would like to have (just couple > of weeks ago we've discussed here that non-blocking callbacks are > required to support external session store), it looks like too > major change for OpenSSL. It will also take several years to be > actually usable. I'll discuss this further with Ben. Thanks. -- Rob Stradling Senior Research & Development Scientist COMODO - Creating Trust Online From mdounin at mdounin.ru Mon Oct 7 12:37:28 2013 From: mdounin at mdounin.ru (Maxim Dounin) Date: Mon, 7 Oct 2013 16:37:28 +0400 Subject: OCSP stapling limitations (was Re: [PATCH 0 of 4] OCSP stapling) In-Reply-To: <52528CEC.7060104@comodo.com> References: <524EB3B5.5060203@comodo.com> <20131006101410.GZ62063@mdounin.ru> <52528CEC.7060104@comodo.com> Message-ID: <20131007123728.GC76294@mdounin.ru> Hello! On Mon, Oct 07, 2013 at 11:29:00AM +0100, Rob Stradling wrote: > On 06/10/13 11:14, Maxim Dounin wrote: > > >>2. The CA/Browser Forum are defining a "must staple" certificate > >>extension [2], which we anticipate that browsers (e.g. [3]) will > >>recognize and enforce, by aborting the TLS handshake if a stapled > >>OCSP response was not sent. > > > >I believe it was said more than once that this changes OCSP > >stapling quite significantly. As of now it's an optimization > >technology, > > Yes, but it's an optimization technology that seems to work reliably > in httpd and IIS. ;-) The "seems" is a key word here, it seems. :) [...] > >>What work needs to be done to enable Nginx to send a stapled OCSP > >>response every time (without having to use the "ssl_stapling_file" > >>directive)? > > > >I tend to think that ssl_stapling_file is a good way to provide an > >OCSP response if it's required for some reason. > > It works, but doesn't it require the user to regularly download a > newer OCSP Response for each certificate, update the contents of > their stapling file(s), and reload Nginx? > IMHO, this needs to be fully automated, just as it is in httpd and IIS. > > Are you saying that there's zero chance of this ever happening? Automatic download doesn't make OCSP responses magically available in all cases. But if an OCSP response is required for a server to work - a server should refuse to start if it's missing and can't be downloaded. And this is not something httpd and/or IIS do now, AFAIK. On the other hand, ssl_stapling_file allows this to be done if needed. If it is actually needed. [...] -- Maxim Dounin http://nginx.org/en/donation.html From mdounin at mdounin.ru Tue Oct 8 12:12:29 2013 From: mdounin at mdounin.ru (Maxim Dounin) Date: Tue, 08 Oct 2013 12:12:29 +0000 Subject: [nginx] Version bump. Message-ID: details: http://hg.nginx.org/nginx/rev/f842bd852d1d branches: stable-1.4 changeset: 5412:f842bd852d1d user: Maxim Dounin date: Mon Oct 07 20:30:03 2013 +0400 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 1004002 -#define NGINX_VERSION "1.4.2" +#define nginx_version 1004003 +#define NGINX_VERSION "1.4.3" #define NGINX_VER "nginx/" NGINX_VERSION #define NGINX_VAR "NGINX" From mdounin at mdounin.ru Tue Oct 8 12:12:30 2013 From: mdounin at mdounin.ru (Maxim Dounin) Date: Tue, 08 Oct 2013 12:12:30 +0000 Subject: [nginx] SPDY: fixed segfault with "client_body_in_file_only" ena... Message-ID: details: http://hg.nginx.org/nginx/rev/bd91997a1117 branches: stable-1.4 changeset: 5413:bd91997a1117 user: Valentin Bartenev date: Wed Jul 24 22:24:25 2013 +0400 description: SPDY: fixed segfault with "client_body_in_file_only" enabled. It is possible to send FLAG_FIN in additional empty data frame, even if it is known from the content-length header that request body is empty. And Firefox actually behaves like this (see ticket #357). To simplify code we sacrificed our microoptimization that did not work right due to missing check in the ngx_http_spdy_state_data() function for rb->buf set to NULL. diffstat: src/http/ngx_http_spdy.c | 11 ++--------- 1 files changed, 2 insertions(+), 9 deletions(-) diffs (30 lines): diff --git a/src/http/ngx_http_spdy.c b/src/http/ngx_http_spdy.c --- a/src/http/ngx_http_spdy.c +++ b/src/http/ngx_http_spdy.c @@ -2529,13 +2529,6 @@ ngx_http_spdy_init_request_body(ngx_http return NGX_ERROR; } - if (rb->rest == 0) { - buf->in_file = 1; - buf->file = &tf->file; - } else { - rb->buf = buf; - } - } else { if (rb->rest == 0) { @@ -2546,10 +2539,10 @@ ngx_http_spdy_init_request_body(ngx_http if (buf == NULL) { return NGX_ERROR; } - - rb->buf = buf; } + rb->buf = buf; + rb->bufs = ngx_alloc_chain_link(r->pool); if (rb->bufs == NULL) { return NGX_ERROR; From mdounin at mdounin.ru Tue Oct 8 12:12:32 2013 From: mdounin at mdounin.ru (Maxim Dounin) Date: Tue, 08 Oct 2013 12:12:32 +0000 Subject: [nginx] Autoindex: return NGX_ERROR on error if headers were sent. Message-ID: details: http://hg.nginx.org/nginx/rev/5fa350899fe0 branches: stable-1.4 changeset: 5414:5fa350899fe0 user: Sergey Kandaurov date: Tue Jul 30 11:43:21 2013 +0400 description: Autoindex: return NGX_ERROR on error if headers were sent. This prevents ngx_http_finalize_request() from issuing ngx_http_special_response_handler() on a freed context. diffstat: src/http/modules/ngx_http_autoindex_module.c | 4 ++-- 1 files changed, 2 insertions(+), 2 deletions(-) diffs (21 lines): diff --git a/src/http/modules/ngx_http_autoindex_module.c b/src/http/modules/ngx_http_autoindex_module.c --- a/src/http/modules/ngx_http_autoindex_module.c +++ b/src/http/modules/ngx_http_autoindex_module.c @@ -388,7 +388,7 @@ ngx_http_autoindex_handler(ngx_http_requ b = ngx_create_temp_buf(r->pool, len); if (b == NULL) { - return NGX_HTTP_INTERNAL_SERVER_ERROR; + return NGX_ERROR; } if (entries.nelts > 1) { @@ -649,7 +649,7 @@ ngx_http_autoindex_error(ngx_http_reques ngx_close_dir_n " \"%V\" failed", name); } - return NGX_HTTP_INTERNAL_SERVER_ERROR; + return r->header_sent ? NGX_ERROR : NGX_HTTP_INTERNAL_SERVER_ERROR; } From mdounin at mdounin.ru Tue Oct 8 12:12:33 2013 From: mdounin at mdounin.ru (Maxim Dounin) Date: Tue, 08 Oct 2013 12:12:33 +0000 Subject: [nginx] Autoindex: improved ngx_de_info() error handling. Message-ID: details: http://hg.nginx.org/nginx/rev/f7e8e6bd5379 branches: stable-1.4 changeset: 5415:f7e8e6bd5379 user: Sergey Kandaurov date: Tue Jul 30 11:43:21 2013 +0400 description: Autoindex: improved ngx_de_info() error handling. This allows to build a directory listing whenever a loop exists in symbolic link resolution of the path argument. diffstat: src/http/modules/ngx_http_autoindex_module.c | 2 +- src/os/unix/ngx_errno.h | 2 +- src/os/win32/ngx_errno.h | 1 + 3 files changed, 3 insertions(+), 2 deletions(-) diffs (38 lines): diff --git a/src/http/modules/ngx_http_autoindex_module.c b/src/http/modules/ngx_http_autoindex_module.c --- a/src/http/modules/ngx_http_autoindex_module.c +++ b/src/http/modules/ngx_http_autoindex_module.c @@ -304,7 +304,7 @@ ngx_http_autoindex_handler(ngx_http_requ if (ngx_de_info(filename, &dir) == NGX_FILE_ERROR) { err = ngx_errno; - if (err != NGX_ENOENT) { + if (err != NGX_ENOENT && err != NGX_ELOOP) { ngx_log_error(NGX_LOG_CRIT, r->connection->log, err, ngx_de_info_n " \"%s\" failed", filename); diff --git a/src/os/unix/ngx_errno.h b/src/os/unix/ngx_errno.h --- a/src/os/unix/ngx_errno.h +++ b/src/os/unix/ngx_errno.h @@ -49,10 +49,10 @@ typedef int ngx_err_t; #define NGX_ECANCELED ECANCELED #define NGX_EILSEQ EILSEQ #define NGX_ENOMOREFILES 0 +#define NGX_ELOOP ELOOP #if (NGX_HAVE_OPENAT) #define NGX_EMLINK EMLINK -#define NGX_ELOOP ELOOP #endif #if (__hpux__) diff --git a/src/os/win32/ngx_errno.h b/src/os/win32/ngx_errno.h --- a/src/os/win32/ngx_errno.h +++ b/src/os/win32/ngx_errno.h @@ -51,6 +51,7 @@ typedef DWORD ngx_e #define NGX_EHOSTUNREACH WSAEHOSTUNREACH #define NGX_ENOMOREFILES ERROR_NO_MORE_FILES #define NGX_EILSEQ ERROR_NO_UNICODE_TRANSLATION +#define NGX_ELOOP 0 #define NGX_EALREADY WSAEALREADY #define NGX_EINVAL WSAEINVAL From mdounin at mdounin.ru Tue Oct 8 12:12:34 2013 From: mdounin at mdounin.ru (Maxim Dounin) Date: Tue, 08 Oct 2013 12:12:34 +0000 Subject: [nginx] Fixed try_files with empty argument (ticket #390). Message-ID: details: http://hg.nginx.org/nginx/rev/ddf740b9fdf6 branches: stable-1.4 changeset: 5416:ddf740b9fdf6 user: Maxim Dounin date: Fri Aug 23 22:18:39 2013 +0400 description: Fixed try_files with empty argument (ticket #390). diffstat: src/http/ngx_http_core_module.c | 4 +++- 1 files changed, 3 insertions(+), 1 deletions(-) diffs (14 lines): diff --git a/src/http/ngx_http_core_module.c b/src/http/ngx_http_core_module.c --- a/src/http/ngx_http_core_module.c +++ b/src/http/ngx_http_core_module.c @@ -4758,7 +4758,9 @@ ngx_http_core_try_files(ngx_conf_t *cf, tf[i].name = value[i + 1]; - if (tf[i].name.data[tf[i].name.len - 1] == '/') { + if (tf[i].name.len > 0 + && tf[i].name.data[tf[i].name.len - 1] == '/') + { tf[i].test_dir = 1; tf[i].name.len--; tf[i].name.data[tf[i].name.len] = '\0'; From mdounin at mdounin.ru Tue Oct 8 12:12:36 2013 From: mdounin at mdounin.ru (Maxim Dounin) Date: Tue, 08 Oct 2013 12:12:36 +0000 Subject: [nginx] Win32: $request_time fixed. Message-ID: details: http://hg.nginx.org/nginx/rev/3169a9b2250d branches: stable-1.4 changeset: 5417:3169a9b2250d user: Maxim Dounin date: Wed Sep 04 20:48:30 2013 +0400 description: Win32: $request_time fixed. On win32, time_t is 64 bits wide by default, and passing an ngx_msec_int_t argument for %T format specifier doesn't work. This doesn't manifest itself on other platforms as time_t and ngx_msec_int_t are usually of the same size. diffstat: src/http/modules/ngx_http_log_module.c | 2 +- src/http/ngx_http_variables.c | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diffs (24 lines): diff --git a/src/http/modules/ngx_http_log_module.c b/src/http/modules/ngx_http_log_module.c --- a/src/http/modules/ngx_http_log_module.c +++ b/src/http/modules/ngx_http_log_module.c @@ -780,7 +780,7 @@ ngx_http_log_request_time(ngx_http_reque ((tp->sec - r->start_sec) * 1000 + (tp->msec - r->start_msec)); ms = ngx_max(ms, 0); - return ngx_sprintf(buf, "%T.%03M", ms / 1000, ms % 1000); + return ngx_sprintf(buf, "%T.%03M", (time_t) ms / 1000, ms % 1000); } diff --git a/src/http/ngx_http_variables.c b/src/http/ngx_http_variables.c --- a/src/http/ngx_http_variables.c +++ b/src/http/ngx_http_variables.c @@ -1988,7 +1988,7 @@ ngx_http_variable_request_time(ngx_http_ ((tp->sec - r->start_sec) * 1000 + (tp->msec - r->start_msec)); ms = ngx_max(ms, 0); - v->len = ngx_sprintf(p, "%T.%03M", ms / 1000, ms % 1000) - p; + v->len = ngx_sprintf(p, "%T.%03M", (time_t) ms / 1000, ms % 1000) - p; v->valid = 1; v->no_cacheable = 0; v->not_found = 0; From mdounin at mdounin.ru Tue Oct 8 12:12:37 2013 From: mdounin at mdounin.ru (Maxim Dounin) Date: Tue, 08 Oct 2013 12:12:37 +0000 Subject: [nginx] Core: fix misallocation at ngx_crypt_apr1 (ticket #412). Message-ID: details: http://hg.nginx.org/nginx/rev/6961d52ebc49 branches: stable-1.4 changeset: 5418:6961d52ebc49 user: Markus Linnala date: Fri Sep 20 17:57:21 2013 +0300 description: Core: fix misallocation at ngx_crypt_apr1 (ticket #412). Found by using auth_basic.t from mdounin nginx-tests under valgrind. ==10470== Invalid write of size 1 ==10470== at 0x43603D: ngx_crypt_to64 (ngx_crypt.c:168) ==10470== by 0x43648E: ngx_crypt (ngx_crypt.c:153) ==10470== by 0x489D8B: ngx_http_auth_basic_crypt_handler (ngx_http_auth_basic_module.c:297) ==10470== by 0x48A24A: ngx_http_auth_basic_handler (ngx_http_auth_basic_module.c:240) ==10470== by 0x44EAB9: ngx_http_core_access_phase (ngx_http_core_module.c:1121) ==10470== by 0x44A822: ngx_http_core_run_phases (ngx_http_core_module.c:895) ==10470== by 0x44A932: ngx_http_handler (ngx_http_core_module.c:878) ==10470== by 0x455EEF: ngx_http_process_request (ngx_http_request.c:1852) ==10470== by 0x456527: ngx_http_process_request_headers (ngx_http_request.c:1283) ==10470== by 0x456A91: ngx_http_process_request_line (ngx_http_request.c:964) ==10470== by 0x457097: ngx_http_wait_request_handler (ngx_http_request.c:486) ==10470== by 0x4411EE: ngx_epoll_process_events (ngx_epoll_module.c:691) ==10470== Address 0x5866fab is 0 bytes after a block of size 27 alloc'd ==10470== at 0x4A074CD: malloc (vg_replace_malloc.c:236) ==10470== by 0x43B251: ngx_alloc (ngx_alloc.c:22) ==10470== by 0x421B0D: ngx_malloc (ngx_palloc.c:119) ==10470== by 0x421B65: ngx_pnalloc (ngx_palloc.c:147) ==10470== by 0x436368: ngx_crypt (ngx_crypt.c:140) ==10470== by 0x489D8B: ngx_http_auth_basic_crypt_handler (ngx_http_auth_basic_module.c:297) ==10470== by 0x48A24A: ngx_http_auth_basic_handler (ngx_http_auth_basic_module.c:240) ==10470== by 0x44EAB9: ngx_http_core_access_phase (ngx_http_core_module.c:1121) ==10470== by 0x44A822: ngx_http_core_run_phases (ngx_http_core_module.c:895) ==10470== by 0x44A932: ngx_http_handler (ngx_http_core_module.c:878) ==10470== by 0x455EEF: ngx_http_process_request (ngx_http_request.c:1852) ==10470== by 0x456527: ngx_http_process_request_headers (ngx_http_request.c:1283) ==10470== diffstat: src/core/ngx_crypt.c | 2 +- 1 files changed, 1 insertions(+), 1 deletions(-) diffs (12 lines): diff --git a/src/core/ngx_crypt.c b/src/core/ngx_crypt.c --- a/src/core/ngx_crypt.c +++ b/src/core/ngx_crypt.c @@ -137,7 +137,7 @@ ngx_crypt_apr1(ngx_pool_t *pool, u_char /* output */ - *encrypted = ngx_pnalloc(pool, sizeof("$apr1$") - 1 + saltlen + 16 + 1); + *encrypted = ngx_pnalloc(pool, sizeof("$apr1$") - 1 + saltlen + 1 + 22 + 1); if (*encrypted == NULL) { return NGX_ERROR; } From mdounin at mdounin.ru Tue Oct 8 12:12:38 2013 From: mdounin at mdounin.ru (Maxim Dounin) Date: Tue, 08 Oct 2013 12:12:38 +0000 Subject: [nginx] Mail: fixed overrun of allocated memory (ticket #411). Message-ID: details: http://hg.nginx.org/nginx/rev/66db21c0ac55 branches: stable-1.4 changeset: 5419:66db21c0ac55 user: Maxim Dounin date: Mon Sep 30 22:10:08 2013 +0400 description: Mail: fixed overrun of allocated memory (ticket #411). Reported by Markus Linnala. diffstat: src/mail/ngx_mail_smtp_module.c | 1 - 1 files changed, 0 insertions(+), 1 deletions(-) diffs (11 lines): diff --git a/src/mail/ngx_mail_smtp_module.c b/src/mail/ngx_mail_smtp_module.c --- a/src/mail/ngx_mail_smtp_module.c +++ b/src/mail/ngx_mail_smtp_module.c @@ -277,7 +277,6 @@ ngx_mail_smtp_merge_srv_conf(ngx_conf_t p = ngx_cpymem(p, conf->capability.data, conf->capability.len); p = ngx_cpymem(p, "250 STARTTLS" CRLF, sizeof("250 STARTTLS" CRLF) - 1); - *p++ = CR; *p = LF; p = conf->starttls_capability.data + (last - conf->capability.data) + 3; From mdounin at mdounin.ru Tue Oct 8 12:12:39 2013 From: mdounin at mdounin.ru (Maxim Dounin) Date: Tue, 08 Oct 2013 12:12:39 +0000 Subject: [nginx] Mail: fixed segfault with ssl/starttls at mail{} level a... Message-ID: details: http://hg.nginx.org/nginx/rev/3ff1e663fa08 branches: stable-1.4 changeset: 5420:3ff1e663fa08 user: Maxim Dounin date: Mon Sep 30 22:10:13 2013 +0400 description: Mail: fixed segfault with ssl/starttls at mail{} level and no cert. A configuration like "mail { starttls on; server {}}" triggered NULL pointer dereference in ngx_mail_ssl_merge_conf() as conf->file was not set. diffstat: src/mail/ngx_mail_ssl_module.c | 5 +++++ 1 files changed, 5 insertions(+), 0 deletions(-) diffs (15 lines): 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 @@ -235,6 +235,11 @@ ngx_mail_ssl_merge_conf(ngx_conf_t *cf, mode = ""; } + if (conf->file == NULL) { + conf->file = prev->file; + conf->line = prev->line; + } + if (*mode) { if (conf->certificate.len == 0) { From mdounin at mdounin.ru Tue Oct 8 13:21:27 2013 From: mdounin at mdounin.ru (Maxim Dounin) Date: Tue, 08 Oct 2013 13:21:27 +0000 Subject: [nginx] nginx-1.4.3-RELEASE Message-ID: details: http://hg.nginx.org/nginx/rev/69ffaca77955 branches: stable-1.4 changeset: 5421:69ffaca77955 user: Maxim Dounin date: Tue Oct 08 16:07:13 2013 +0400 description: nginx-1.4.3-RELEASE diffstat: docs/xml/nginx/changes.xml | 69 ++++++++++++++++++++++++++++++++++++++++++++++ 1 files changed, 69 insertions(+), 0 deletions(-) diffs (79 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,75 @@ + + + + +? ??????? ???????? ??? ????????? segmentation fault, +???? ????????????? ?????? ngx_http_spdy_module +? ????????? client_body_in_file_only. + + +a segmentation fault might occur in a worker process +if the ngx_http_spdy_module was used +with the "client_body_in_file_only" directive. + + + + + +?? ?????? ??? ?? ????? ???????????????? ??? ????????? segmentation fault, +???? ?????????????? ????????? try_files ? ?????? ??????????. + + +a segmentation fault might occur on start or during reconfiguration +if the "try_files" directive was used with an empty parameter. + + + + + +?????????? $request_time ?? ???????? ? nginx/Windows. + + +the $request_time variable did not work in nginx/Windows. + + + + + +? ?????? ngx_http_auth_basic_module +??? ????????????? ?????? ?????????? ??????? "$apr1$".
+??????? Markus Linnala. +
+ +in the ngx_http_auth_basic_module +when using "$apr1$" password encryption method.
+Thanks to Markus Linnala. +
+
+ + + +? ?????? ngx_http_autoindex_module. + + +in the ngx_http_autoindex_module. + + + + + +? ???????? ??????-???????. + + +in the mail proxy server. + + + +
+ + From mdounin at mdounin.ru Tue Oct 8 13:21:29 2013 From: mdounin at mdounin.ru (Maxim Dounin) Date: Tue, 08 Oct 2013 13:21:29 +0000 Subject: [nginx] release-1.4.3 tag Message-ID: details: http://hg.nginx.org/nginx/rev/89405deca1ad branches: stable-1.4 changeset: 5422:89405deca1ad user: Maxim Dounin date: Tue Oct 08 16:07:14 2013 +0400 description: release-1.4.3 tag diffstat: .hgtags | 1 + 1 files changed, 1 insertions(+), 0 deletions(-) diffs (8 lines): diff --git a/.hgtags b/.hgtags --- a/.hgtags +++ b/.hgtags @@ -357,3 +357,4 @@ 23159600bdea695db8f9d2890aaf73424303e49c 7809529022b83157067e7d1e2fb65d57db5f4d99 release-1.4.0 0702de638a4c51123d7b97801d393e8e25eb48de release-1.4.1 50f065641b4c52ced41fae1ce216c73aaf112306 release-1.4.2 +69ffaca7795531e19f3827940cc28dca0b50d0b8 release-1.4.3 From dmitry.petroff at gmail.com Wed Oct 9 14:54:08 2013 From: dmitry.petroff at gmail.com (Dmitry Petrov) Date: Wed, 9 Oct 2013 18:54:08 +0400 Subject: Incorrect handling of "%2b" in rewrite directive Message-ID: Hi. To perform rewrite, nginx does ngx_unescape_uri and then ngx_escape_uri to pass request to backend. There is a problem with this functions: they both can't handler "+" propertly: ngx_escape_uri does not escape ?+? character So when there is ?%2b? sequence in rewrite command, it will be passed to backend as ?+? where it SHOULD be interpreted as space character. I've attached a small patch that solved a problem for me. For testing I used location /foo { rewrite (.*) $1 break; proxy_pass http://localhost:1234; } + while true; do nc -l -p 1234; done ? to watch what is really send to backend by nginx. -- Regards, Dmitry -------------- next part -------------- An HTML attachment was scrubbed... URL: -------------- next part -------------- A non-text attachment was scrubbed... Name: uri-escape.patch Type: application/octet-stream Size: 880 bytes Desc: not available URL: From mdounin at mdounin.ru Wed Oct 9 16:02:37 2013 From: mdounin at mdounin.ru (Maxim Dounin) Date: Wed, 9 Oct 2013 20:02:37 +0400 Subject: Incorrect handling of "%2b" in rewrite directive In-Reply-To: References: Message-ID: <20131009160237.GZ76294@mdounin.ru> Hello! On Wed, Oct 09, 2013 at 06:54:08PM +0400, Dmitry Petrov wrote: > Hi. > > To perform rewrite, nginx does ngx_unescape_uri and then ngx_escape_uri to > pass request to backend. There is a problem with this functions: they both > can't handler "+" propertly: ngx_escape_uri does not escape ?+? character > > So when there is ?%2b? sequence in rewrite command, it will be passed to > backend as ?+? where it SHOULD be interpreted as space character. > I've attached a small patch that solved a problem for me. > > For testing I used > location /foo { > rewrite (.*) $1 break; > proxy_pass http://localhost:1234; > } > + while true; do nc -l -p 1234; done ? to watch what is really send to > backend by nginx. The "+" character has a special meaning only in query components. It is allowed and has no special meaning in paths. That is, URLs "http://example.com/foo+bar" and "http://example.com/foo%bbar" are equivalent. -- Maxim Dounin http://nginx.org/en/donation.html From aviram at adallom.com Wed Oct 9 16:32:52 2013 From: aviram at adallom.com (Aviram Cohen) Date: Wed, 9 Oct 2013 19:32:52 +0300 Subject: [PATCH] Proxy remote server SSL certificate verification In-Reply-To: <20130903132139.GK65634@mdounin.ru> References: <20130820140912.GF19334@mdounin.ru> <20130821143033.GP19334@mdounin.ru> <20130828004143.GE2748@mdounin.ru> <20130902120959.GB65634@mdounin.ru> <20130903132139.GK65634@mdounin.ru> Message-ID: Hello!, I've made the necessary fixes. A few comments about those: - Name validation - Unlike Apache, in this patch, the configuration must contain the name to verify. In most cases, this should be set to the $host variable (and this is the default value). I've encountered certificates that validate names differently (some of Microsoft's certificates), and this is useful for such cases. - Many certificates use wildcards in the names on which they sign (i.e. "*.google.com"). Though wildcards can appear anywhere according to the standard, I've added support only for a wildcard in the beginning of the name. This is the normal case, and it is easier to implement. This is is how Apache implements the wildcard name validation as well. Note also that the function X509_check_host will be introduced in future versions of OpenSSL that will provide the entire feature. - CRL verification - I've added CRL validation, but note that OpenSSL doesn't download CRL files from the servers, so the CRL file that is used should contain the revocation lists of all the proxied hosts. This also means that it is out of Nginx's scope to update this file. Apache does the same thing. - The patch was made for v1.4.1. The patch itself is in the end of this mail, and also in: https://gist.github.com/aviramc/6903821 Best regards, Aviram # HG changeset patch # User Aviram Cohen # Date 1381334949 -7200 # Branch stable-1.4 # Node ID 9a6e20bf72f8cf4d17653e4fdfcbac48c4de03aa # Parent 0702de638a4c51123d7b97801d393e8e25eb48de Added remote end SSL certificate verification in the proxy module. This patch adds the following directives to the proxy module: - proxy_ssl_verify - whether or not to verify the remote end's certificate. Default is off. - proxy_ssl_verify_name - the remote end's name to verify. Default is $host, can be set to "" in order to avoid name verification. - proxy_ssl_verify_depth - how deep the ssl verification should be done. Default is 1. - proxy_ssl_trusted_certificate - the path of the certificate file that is used for verification. This must be provided when proxy_ssl_verify is on. - proxy_ssl_crl - the path a file that contains the CRLs of the hosts to which we proxy. Default is empty, and CRL verification is not done. diff -r 0702de638a4c -r 9a6e20bf72f8 src/event/ngx_event_openssl.c --- a/src/event/ngx_event_openssl.c Mon May 06 14:20:27 2013 +0400 +++ b/src/event/ngx_event_openssl.c Wed Oct 09 18:09:09 2013 +0200 @@ -42,6 +42,11 @@ static char *ngx_openssl_engine(ngx_conf_t *cf, ngx_command_t *cmd, void *conf); static void ngx_openssl_exit(ngx_cycle_t *cycle); +static int ngx_openssl_host_wildcard_match(ASN1_STRING *match_pattern, + ngx_str_t *hostname); +static int ngx_openssl_host_exact_match(ASN1_STRING *match_pattern, + ngx_str_t *hostname); + static ngx_command_t ngx_openssl_commands[] = { @@ -2562,3 +2567,163 @@ EVP_cleanup(); ENGINE_cleanup(); } + + +static int +ngx_openssl_host_wildcard_match(ASN1_STRING *match_pattern, + ngx_str_t *hostname) +{ + int host_top_domain_length; + u_char *host_top_domain; + u_char *wildcard_pattern; + + /* sanity check */ + if (!match_pattern + || match_pattern->length <= 0 + || !hostname + || !hostname->len) + { + return 0; + } + + /* trivial case */ + if (ngx_strncasecmp((u_char *) match_pattern->data, + hostname->data, + hostname->len) + == 0) + { + return 1; + } + + /* simple wildcard matching - only in the beginning of the string. */ + if (match_pattern->length > 2 + && match_pattern->data[0] == '*' + && match_pattern->data[1] == '.') + { + + wildcard_pattern = (u_char *) (match_pattern->data + 1); + + host_top_domain = ngx_strlchr(hostname->data, + hostname->data + hostname->len, + '.'); + + /* + * If the pattern begings with "*." and the hostname consists of + * a top level domain, compare the pattern to the top level domain. + */ + if (host_top_domain != NULL) { + host_top_domain_length = + hostname->len - (int) (host_top_domain - hostname->data); + + if (host_top_domain_length == match_pattern->length - 1 + && ngx_strncasecmp(wildcard_pattern, + host_top_domain, + match_pattern->length - 1) + == 0) + { + return 1; + } + } + } + + return 0; +} + + +static int +ngx_openssl_host_exact_match(ASN1_STRING *match_pattern, + ngx_str_t *hostname) +{ + /* sanity check */ + if (!match_pattern + || match_pattern->length <= 0 + || !hostname + || !hostname->len + || match_pattern->length != (int) hostname->len) + { + return 0; + } + + if (ngx_strncmp((u_char *) match_pattern->data, + hostname->data, + hostname->len) + == 0) + { + return 1; + } + + return 0; +} + + +int +ngx_openssl_verify_name(X509 *cert, ngx_str_t *expected_name) +{ + GENERAL_NAMES *gens = NULL; + GENERAL_NAME *gen; + X509_NAME *name = NULL; + ASN1_STRING *cstr = NULL; + X509_NAME_ENTRY *ne; + int i; + int rc = 0; + + /* based on OpenSSL's do_x509_check */ + + gens = X509_get_ext_d2i(cert, NID_subject_alt_name, NULL, NULL); + + if (gens) { + + rc = 0; + + for (i = 0; i < sk_GENERAL_NAME_num(gens); i++) { + + gen = sk_GENERAL_NAME_value(gens, i); + + /* we only check for either name or IP */ + switch (gen->type) { + + case GEN_DNS: + cstr = gen->d.dNSName; + rc = ngx_openssl_host_wildcard_match(cstr, + expected_name); + break; + + case GEN_IPADD: + cstr = gen->d.iPAddress; + rc = ngx_openssl_host_exact_match(cstr, + expected_name); + break; + + default: + cstr = NULL; + rc = 0; + } + + if (rc) { + break; + } + + } + + GENERAL_NAMES_free(gens); + + if (rc) { + return 1; + } + } + + name = X509_get_subject_name(cert); + i = X509_NAME_get_index_by_NID(name, NID_commonName, -1); + while (i >= 0) { + ne = X509_NAME_get_entry(name, i); + cstr = X509_NAME_ENTRY_get_data(ne); + + if (ngx_openssl_host_exact_match(cstr, expected_name)) { + return 1; + } + + i = X509_NAME_get_index_by_NID(name, NID_commonName, i); + } + + return 0; +} diff -r 0702de638a4c -r 9a6e20bf72f8 src/event/ngx_event_openssl.h --- a/src/event/ngx_event_openssl.h Mon May 06 14:20:27 2013 +0400 +++ b/src/event/ngx_event_openssl.h Wed Oct 09 18:09:09 2013 +0200 @@ -167,6 +167,8 @@ char *fmt, ...); void ngx_ssl_cleanup_ctx(void *data); +int +ngx_openssl_verify_name(X509 *cert, ngx_str_t *expected_name); extern int ngx_ssl_connection_index; extern int ngx_ssl_server_conf_index; diff -r 0702de638a4c -r 9a6e20bf72f8 src/http/modules/ngx_http_proxy_module.c --- a/src/http/modules/ngx_http_proxy_module.c Mon May 06 14:20:27 2013 +0400 +++ b/src/http/modules/ngx_http_proxy_module.c Wed Oct 09 18:09:09 2013 +0200 @@ -74,6 +74,15 @@ ngx_uint_t http_version; +#if (NGX_HTTP_SSL) + ngx_uint_t ssl_verify_depth; + ngx_str_t ssl_trusted_certificate; + ngx_str_t ssl_crl; + ngx_str_t ssl_verify_name_source; + ngx_array_t *ssl_verify_name_lengths; + ngx_array_t *ssl_verify_name_values; +#endif + ngx_uint_t headers_hash_max_size; ngx_uint_t headers_hash_bucket_size; } ngx_http_proxy_loc_conf_t; @@ -510,6 +519,41 @@ NGX_HTTP_LOC_CONF_OFFSET, offsetof(ngx_http_proxy_loc_conf_t, upstream.ssl_session_reuse), NULL }, + + { ngx_string("proxy_ssl_verify"), + NGX_HTTP_MAIN_CONF|NGX_HTTP_SRV_CONF|NGX_HTTP_LOC_CONF|NGX_CONF_TAKE1, + ngx_conf_set_flag_slot, + NGX_HTTP_LOC_CONF_OFFSET, + offsetof(ngx_http_proxy_loc_conf_t, upstream.ssl_verify), + NULL }, + + { ngx_string("proxy_ssl_verify_name"), + NGX_HTTP_MAIN_CONF|NGX_HTTP_SRV_CONF|NGX_HTTP_LOC_CONF|NGX_CONF_TAKE1, + ngx_conf_set_str_slot, + NGX_HTTP_LOC_CONF_OFFSET, + offsetof(ngx_http_proxy_loc_conf_t, ssl_verify_name_source), + NULL }, + + { ngx_string("proxy_ssl_verify_depth"), + NGX_HTTP_MAIN_CONF|NGX_HTTP_SRV_CONF|NGX_HTTP_LOC_CONF|NGX_CONF_TAKE1, + ngx_conf_set_num_slot, + NGX_HTTP_LOC_CONF_OFFSET, + offsetof(ngx_http_proxy_loc_conf_t, ssl_verify_depth), + NULL }, + + { ngx_string("proxy_ssl_trusted_certificate"), + NGX_HTTP_MAIN_CONF|NGX_HTTP_SRV_CONF|NGX_HTTP_LOC_CONF|NGX_CONF_TAKE1, + ngx_conf_set_str_slot, + NGX_HTTP_LOC_CONF_OFFSET, + offsetof(ngx_http_proxy_loc_conf_t, ssl_trusted_certificate), + NULL }, + + { ngx_string("proxy_ssl_crl"), + NGX_HTTP_MAIN_CONF|NGX_HTTP_SRV_CONF|NGX_HTTP_LOC_CONF|NGX_CONF_TAKE1, + ngx_conf_set_str_slot, + NGX_HTTP_LOC_CONF_OFFSET, + offsetof(ngx_http_proxy_loc_conf_t, ssl_crl), + NULL }, #endif @@ -633,6 +677,7 @@ ngx_http_upstream_t *u; ngx_http_proxy_ctx_t *ctx; ngx_http_proxy_loc_conf_t *plcf; + ngx_str_t host; if (ngx_http_upstream_create(r) != NGX_OK) { return NGX_HTTP_INTERNAL_SERVER_ERROR; @@ -662,6 +707,24 @@ } } +#if (NGX_HTTP_SSL) + + if (plcf->ssl_verify_name_lengths == NULL) { + u->ssl_verify_name.data = plcf->ssl_verify_name_source.data; + u->ssl_verify_name.len = plcf->ssl_verify_name_source.len; + } else { + if (ngx_http_script_run(r, &host, plcf->ssl_verify_name_lengths->elts, + 0, plcf->ssl_verify_name_values->elts) + == NULL) + { + return NGX_HTTP_INTERNAL_SERVER_ERROR; + } + u->ssl_verify_name.data = host.data; + u->ssl_verify_name.len = host.len; + } + +#endif + u->output.tag = (ngx_buf_tag_t) &ngx_http_proxy_module; u->conf = &plcf->upstream; @@ -2382,6 +2445,11 @@ * conf->body_set = NULL; * conf->body_source = { 0, NULL }; * conf->redirects = NULL; + * conf->ssl_trusted_certificate = { 0, NULL }; + * conf->ssl_crl = { 0, NULL }; + * conf->ssl_verify_name_source = { 0, NULL }; + * conf->ssl_verify_name_lengths = NULL; + * conf->ssl_verify_name_values = NULL; */ conf->upstream.store = NGX_CONF_UNSET; @@ -2419,8 +2487,11 @@ conf->upstream.pass_headers = NGX_CONF_UNSET_PTR; conf->upstream.intercept_errors = NGX_CONF_UNSET; + #if (NGX_HTTP_SSL) conf->upstream.ssl_session_reuse = NGX_CONF_UNSET; + conf->upstream.ssl_verify = NGX_CONF_UNSET; + conf->ssl_verify_depth = NGX_CONF_UNSET_UINT; #endif /* "proxy_cyclic_temp_file" is disabled */ @@ -2455,6 +2526,7 @@ ngx_http_core_loc_conf_t *clcf; ngx_http_proxy_rewrite_t *pr; ngx_http_script_compile_t sc; + ngx_int_t n; if (conf->upstream.store != 0) { ngx_conf_merge_value(conf->upstream.store, @@ -2695,8 +2767,62 @@ prev->upstream.intercept_errors, 0); #if (NGX_HTTP_SSL) + ngx_conf_merge_value(conf->upstream.ssl_session_reuse, prev->upstream.ssl_session_reuse, 1); + ngx_conf_merge_value(conf->upstream.ssl_verify, + prev->upstream.ssl_verify, 0); + ngx_conf_merge_str_value(conf->ssl_verify_name_source, + prev->ssl_verify_name_source, "$host"); + ngx_conf_merge_uint_value(conf->ssl_verify_depth, + prev->ssl_verify_depth, 1); + ngx_conf_merge_str_value(conf->ssl_trusted_certificate, + prev->ssl_trusted_certificate, ""); + ngx_conf_merge_str_value(conf->ssl_crl, + prev->ssl_crl, ""); + + if (conf->upstream.ssl && conf->upstream.ssl_verify) { + if (conf->ssl_trusted_certificate.len == 0) { + ngx_conf_log_error(NGX_LOG_EMERG, cf, 0, + "no \"proxy_ssl_trusted_certificate\" is " + " defined for the \"proxy_ssl_verify\" " + "directive"); + + return NGX_CONF_ERROR; + } + + if (ngx_ssl_trusted_certificate(cf, conf->upstream.ssl, + &conf->ssl_trusted_certificate, + conf->ssl_verify_depth) + != NGX_OK) + { + return NGX_CONF_ERROR; + } + + if (ngx_ssl_crl(cf, conf->upstream.ssl, &conf->ssl_crl) != NGX_OK) { + return NGX_CONF_ERROR; + } + + n = ngx_http_script_variables_count(&conf->ssl_verify_name_source); + + if (n) { + ngx_memzero(&sc, sizeof(ngx_http_script_compile_t)); + + sc.cf = cf; + sc.source = &conf->ssl_verify_name_source; + sc.variables = n; + sc.lengths = &conf->ssl_verify_name_lengths; + sc.values = &conf->ssl_verify_name_values; + sc.complete_lengths = 1; + sc.complete_values = 1; + + if (ngx_http_script_compile(&sc) != NGX_OK) { + return NGX_CONF_ERROR; + } + + } + } + #endif ngx_conf_merge_value(conf->redirect, prev->redirect, 1); diff -r 0702de638a4c -r 9a6e20bf72f8 src/http/ngx_http_upstream.c --- a/src/http/ngx_http_upstream.c Mon May 06 14:20:27 2013 +0400 +++ b/src/http/ngx_http_upstream.c Wed Oct 09 18:09:09 2013 +0200 @@ -1319,12 +1319,43 @@ { ngx_http_request_t *r; ngx_http_upstream_t *u; - + X509 *cert; + long rc; + r = c->data; u = r->upstream; if (c->ssl->handshaked) { - + if (u->conf->ssl_verify) { + rc = SSL_get_verify_result(c->ssl->connection); + if (rc != X509_V_OK) { + ngx_log_error(NGX_LOG_ERR, c->log, 0, + "upstream SSL certificate verify error: (%l:%s)", + rc, X509_verify_cert_error_string(rc)); + goto fail; + } + + cert = SSL_get_peer_certificate(c->ssl->connection); + + if (cert == NULL) { + ngx_log_error(NGX_LOG_ERR, c->log, 0, + "upstream sent no SSL certificate"); + goto fail; + } + + if (u->ssl_verify_name.len + && ngx_openssl_verify_name(cert, &u->ssl_verify_name) + == 0) + { + X509_free(cert); + ngx_log_error(NGX_LOG_ERR, c->log, 0, + "upstream SSL certificate name validation error"); + goto fail; + } + + X509_free(cert); + } + if (u->conf->ssl_session_reuse) { u->peer.save_session(&u->peer, u->peer.data); } @@ -1332,13 +1363,22 @@ c->write->handler = ngx_http_upstream_handler; c->read->handler = ngx_http_upstream_handler; + c = r->connection; + ngx_http_upstream_send_request(r, u); + ngx_http_run_posted_requests(c); + return; } +fail: + + c = r->connection; + ngx_http_upstream_next(r, u, NGX_HTTP_UPSTREAM_FT_ERROR); + ngx_http_run_posted_requests(c); } #endif diff -r 0702de638a4c -r 9a6e20bf72f8 src/http/ngx_http_upstream.h --- a/src/http/ngx_http_upstream.h Mon May 06 14:20:27 2013 +0400 +++ b/src/http/ngx_http_upstream.h Wed Oct 09 18:09:09 2013 +0200 @@ -191,6 +191,7 @@ #if (NGX_HTTP_SSL) ngx_ssl_t *ssl; ngx_flag_t ssl_session_reuse; + ngx_flag_t ssl_verify; #endif ngx_str_t module; @@ -297,6 +298,10 @@ ngx_int_t (*input_filter)(void *data, ssize_t bytes); void *input_filter_ctx; +#if (NGX_HTTP_SSL) + ngx_str_t ssl_verify_name; +#endif + #if (NGX_HTTP_CACHE) ngx_int_t (*create_key)(ngx_http_request_t *r); #endif On Tue, Sep 3, 2013 at 4:21 PM, Maxim Dounin wrote: > Hello! > > On Tue, Sep 03, 2013 at 03:32:58PM +0300, Aviram Cohen wrote: > >> Thanks for the comments. The new version with all the fixes is >> attached (and also pasted in this mail). > > See below for comments. > > [...] > >> @@ -2382,6 +2408,7 @@ ngx_http_proxy_create_loc_conf(ngx_conf_ >> * conf->body_set = NULL; >> * conf->body_source = { 0, NULL }; >> * conf->redirects = NULL; >> + * conf->ssl_trusted_certificate = NULL; >> */ >> >> conf->upstream.store = NGX_CONF_UNSET; > > Nitpicking: ssl_trusted_certificate is ngx_str_t, so it's set > to { 0, NULL } (much like body_source above). > > [...] > >> + if (conf->upstream.ssl && conf->upstream.ssl_verify) { >> + if (conf->ssl_trusted_certificate.len == 0) { >> + ngx_conf_log_error(NGX_LOG_EMERG, cf, 0, >> + "no \"proxy_ssl_trusted_certificate\" is " >> + " defined for the \"proxy_ssl_verify\" " >> + "directive"); >> + >> + return NGX_CONF_ERROR; >> + } >> + } >> + >> + if (conf->upstream.ssl >> + && ngx_ssl_trusted_certificate(cf, conf->upstream.ssl, >> + &conf->ssl_trusted_certificate, >> + conf->ssl_verify_depth) >> + != NGX_OK) >> + { >> + return NGX_CONF_ERROR; >> + } > > Nitpicking: if (conf->upstream.ssl) seems to be common condition, > and probably conf->upstream.ssl_verify too. Merging the two under > something like > > if (conf->upstream.ssl && conf->upstream.ssl_verify) { > > if (conf->ssl_trusted_certificate.len == 0) { > ... > } > > if (ngx_ssl_trusted_certificate(...) > != NGX_OK) > { > ... > } > } > > should be better. > > [...] > >> @@ -1319,12 +1319,30 @@ ngx_http_upstream_ssl_handshake(ngx_conn >> { >> ngx_http_request_t *r; >> ngx_http_upstream_t *u; >> - >> + X509 *cert; >> + >> r = c->data; >> u = r->upstream; >> >> if (c->ssl->handshaked) { >> - >> + if (u->conf->ssl_verify) { >> + if (SSL_get_verify_result(c->ssl->connection) != X509_V_OK) { >> + ngx_log_error(NGX_LOG_ERR, c->log, 0, >> + "upstream ssl certificate validation failed"); > > This seems to lack detailsed error reporting. Logging at least > error returned and X509_verify_cert_error_string() as it's done in > ngx_http_process_request() is really good idea. > >> + goto fail; >> + } >> + >> + cert = SSL_get_peer_certificate(c->ssl->connection); >> + >> + if (cert == NULL) { >> + ngx_log_error(NGX_LOG_INFO, c->log, 0, >> + "upstream sent no required SSL certificate"); > > The "required" is probably not needed. And NGX_LOG_INFO logging > level looks very wrong - while it's used by > ngx_http_process_request(), it's used in a situation which may be > easily triggered by broken/malicious clients, so the "info" level > is appropiate. No certificate from an upstream server deserves at > least "error" level (which is already used in your patch by > previous error message). > >> + goto fail; >> + } >> + >> + X509_free(cert); >> + } >> + >> if (u->conf->ssl_session_reuse) { >> u->peer.save_session(&u->peer, u->peer.data); >> } > > One more relatively major point: certificate checking seems to > lack any peer name validation. Without it, any certificate issued > by a trusted certificate authority can be used, making it > impossible to use certificate verification to prevent MITM if you > don't control trusted CAs. > > I tend to think it's required for initial proxy certificate > verification. Though probably there should be a directive to > switch the off, like in Apache, see > http://httpd.apache.org/docs/2.4/mod/mod_ssl.html#sslproxycheckpeername. > > Additionally, it might be good idea to introduce an ssl_crl > counterpart for proxy. > >> @@ -1332,13 +1350,21 @@ ngx_http_upstream_ssl_handshake(ngx_conn >> c->write->handler = ngx_http_upstream_handler; >> c->read->handler = ngx_http_upstream_handler; >> >> + c = r->connection; >> + >> ngx_http_upstream_send_request(r, u); >> >> + ngx_http_run_posted_requests(c); >> + >> return; >> } >> >> +fail: >> + c = r->connection; >> + >> ngx_http_upstream_next(r, u, NGX_HTTP_UPSTREAM_FT_ERROR); >> >> + ngx_http_run_posted_requests(c); >> } > > Nitpicking: I think there should be empty line after "fail:". > > BTW, you may want to build patches against mercurial repo, it > already has the posted requests code here. See > > http://nginx.org/en/docs/contributing_changes.html > > for basic tips. > > [...] > > -- > Maxim Dounin > http://nginx.org/en/donation.html > > _______________________________________________ > nginx-devel mailing list > nginx-devel at nginx.org > http://mailman.nginx.org/mailman/listinfo/nginx-devel -- Aviram Cohen, R&D Adallom, 1 Ha'Barzel st., Tel-Aviv, Israel Mobile: +972 (54) 5833508 aviram at adallom.com, www.adallom.com From piotr at cloudflare.com Wed Oct 9 21:21:08 2013 From: piotr at cloudflare.com (Piotr Sikora) Date: Wed, 9 Oct 2013 14:21:08 -0700 Subject: [PATCH] SSL: respect session timeout in configs without session cache. Message-ID: # HG changeset patch # User Piotr Sikora # Date 1381353349 25200 # Wed Oct 09 14:15:49 2013 -0700 # Node ID 6d1d1c6d346839d3ccdca92cee32bc9887c19841 # Parent 5483d9e77b3287b00b1104a07688bda37bc7351e SSL: respect session timeout in configs without session cache. Previously, session timeout value was used only when session cache was configured, which meant that in configurations without it, Session Tickets would always get 5 minutes timeout hint, regardless of the configured session timeout. Signed-off-by: Piotr Sikora diff -r 5483d9e77b32 -r 6d1d1c6d3468 src/event/ngx_event_openssl.c --- a/src/event/ngx_event_openssl.c Wed Oct 02 15:07:17 2013 +0400 +++ b/src/event/ngx_event_openssl.c Wed Oct 09 14:15:49 2013 -0700 @@ -1700,7 +1700,7 @@ ngx_ssl_error(ngx_uint_t level, ngx_log_ ngx_int_t ngx_ssl_session_cache(ngx_ssl_t *ssl, ngx_str_t *sess_ctx, - ssize_t builtin_session_cache, ngx_shm_zone_t *shm_zone, time_t timeout) + ssize_t builtin_session_cache, ngx_shm_zone_t *shm_zone) { long cache_mode; @@ -1749,8 +1749,6 @@ ngx_ssl_session_cache(ngx_ssl_t *ssl, ng } } - SSL_CTX_set_timeout(ssl->ctx, (long) timeout); - if (shm_zone) { SSL_CTX_sess_set_new_cb(ssl->ctx, ngx_ssl_new_session); SSL_CTX_sess_set_get_cb(ssl->ctx, ngx_ssl_get_cached_session); diff -r 5483d9e77b32 -r 6d1d1c6d3468 src/event/ngx_event_openssl.h --- a/src/event/ngx_event_openssl.h Wed Oct 02 15:07:17 2013 +0400 +++ b/src/event/ngx_event_openssl.h Wed Oct 09 14:15:49 2013 -0700 @@ -115,7 +115,7 @@ RSA *ngx_ssl_rsa512_key_callback(ngx_ssl ngx_int_t ngx_ssl_dhparam(ngx_conf_t *cf, ngx_ssl_t *ssl, ngx_str_t *file); ngx_int_t ngx_ssl_ecdh_curve(ngx_conf_t *cf, ngx_ssl_t *ssl, ngx_str_t *name); ngx_int_t ngx_ssl_session_cache(ngx_ssl_t *ssl, ngx_str_t *sess_ctx, - ssize_t builtin_session_cache, ngx_shm_zone_t *shm_zone, time_t timeout); + ssize_t builtin_session_cache, ngx_shm_zone_t *shm_zone); ngx_int_t ngx_ssl_session_cache_init(ngx_shm_zone_t *shm_zone, void *data); ngx_int_t ngx_ssl_create_connection(ngx_ssl_t *ssl, ngx_connection_t *c, ngx_uint_t flags); diff -r 5483d9e77b32 -r 6d1d1c6d3468 src/http/modules/ngx_http_ssl_module.c --- a/src/http/modules/ngx_http_ssl_module.c Wed Oct 02 15:07:17 2013 +0400 +++ b/src/http/modules/ngx_http_ssl_module.c Wed Oct 09 14:15:49 2013 -0700 @@ -615,9 +615,10 @@ ngx_http_ssl_merge_srv_conf(ngx_conf_t * conf->shm_zone = prev->shm_zone; } + SSL_CTX_set_timeout(conf->ssl.ctx, (long) conf->session_timeout); + if (ngx_ssl_session_cache(&conf->ssl, &ngx_http_ssl_sess_id_ctx, - conf->builtin_session_cache, - conf->shm_zone, conf->session_timeout) + conf->builtin_session_cache, conf->shm_zone) != NGX_OK) { return NGX_CONF_ERROR; diff -r 5483d9e77b32 -r 6d1d1c6d3468 src/mail/ngx_mail_ssl_module.c --- a/src/mail/ngx_mail_ssl_module.c Wed Oct 02 15:07:17 2013 +0400 +++ b/src/mail/ngx_mail_ssl_module.c Wed Oct 09 14:15:49 2013 -0700 @@ -323,9 +323,10 @@ ngx_mail_ssl_merge_conf(ngx_conf_t *cf, conf->shm_zone = prev->shm_zone; } + SSL_CTX_set_timeout(conf->ssl.ctx, (long) conf->session_timeout); + if (ngx_ssl_session_cache(&conf->ssl, &ngx_mail_ssl_sess_id_ctx, - conf->builtin_session_cache, - conf->shm_zone, conf->session_timeout) + conf->builtin_session_cache, conf->shm_zone) != NGX_OK) { return NGX_CONF_ERROR; From ddiaz at cenditel.gob.ve Wed Oct 9 22:55:22 2013 From: ddiaz at cenditel.gob.ve (=?UTF-8?B?RGhpb25lbCBEw63CrWF6?=) Date: Wed, 09 Oct 2013 18:25:22 -0430 Subject: [PATCH 0 of 1] Dav: Changes in the destination header in MOVE and DELETE methods for files and/or folders In-Reply-To: <20131003160829.GK62063@mdounin.ru> References: <20131003160829.GK62063@mdounin.ru> Message-ID: <5255DEDA.6020506@cenditel.gob.ve> Hello, Thanks for taking the time to revise the patch our team is proposing. We know it concerns to some small details in a module that perhaps is not frequently used, and therefore appreciate the attention received. Some comments follow. El 03/10/13 11:38, Maxim Dounin escribi?: > Hello! > > On Thu, Oct 03, 2013 at 10:40:09AM -0430, lcolina at cenditel.gob.ve wrote: > >> Dear nginx developers, >> >> The dav module of nginx was tested with client Nautilus 3.4.2 to >> implement a shared file system in operations office. >> >> While testing the ngx_http_dav_module, found some conflicts that >> are described below: >> >> 1. In operations with MOVE method for files and/or directories: >> It was found a conflict with the destination header, because >> Nautilus client sends the URI with the user name, but the user >> name in the destination header is not supported by nginx, >> resulting in the following error. [...] > > There is no "userinfo" in a http scheme URLs syntax as per > RFC2616. Quote from > http://tools.ietf.org/html/rfc2616#section-3.2: > > The "http" scheme is used to locate network resources via the HTTP > protocol. This section defines the scheme-specific syntax and > semantics for http URLs. > > http_URL = "http:" "//" host [ ":" port ] [ abs_path [ "?" query ]] > > Upcoming work of httpbis explicitly prohibts use of userinfo in > http messages, see > http://tools.ietf.org/html/draft-ietf-httpbis-p1-messaging-24#section-2.7.1: > > The URI generic syntax for authority also includes a deprecated > userinfo subcomponent ([RFC3986], Section 3.2.1) for including user > authentication information in the URI. Some implementations make use > of the userinfo component for internal configuration of > authentication information, such as within command invocation > options, configuration files, or bookmark lists, even though such > usage might expose a user identifier or password. A sender MUST NOT > generate the userinfo subcomponent (and its "@" delimiter) when an > "http" URI reference is generated within a message as a request > target or header field value. Before making use of an "http" URI > reference received from an untrusted source, a recipient ought to > parse for userinfo and treat its presence as an error; it is likely > being used to obscure the authority for the sake of phishing attacks. > > There is no userinfo support in nginx, and it's intentional. And, > as the above links show, this seems to agree with standards. > We thought that the syntax described in http://tools.ietf.org/html/rfc3986#section-3 was directly appliable, the provision of http://tools.ietf.org/html/rfc3986#section-1.1.1 that reads: "(...) the URI syntax is a federated and extensible naming system wherein each scheme's specification may further restrict the syntax and semantics of identifiers using that scheme." and the details of http scheme URL syntax were overlooked. Sorry for the confusion. Therefore it follows that the client (Nautilus 3.4.2, via gvfs 1.12.3) fails to comply the standard and a bug report could be in order. To workaround this client failure, a rewrite of Destination header at configuration level may be the appropiate approach. As those client software is widely deployed, it could be considered the inclusion of some remarks about this bug in WebDAV module documentation. >> 2. In operations with MOVE method for directories: It was found >> a conflict when rename a folder from Nautilus client, the >> source path contains no final slash, resulting a bad request >> error because nginx requires source path with final slash. [...] > > The collection identifier is with trailing slash, as in > conformance with RFC 4918, http://tools.ietf.org/html/rfc4918#section-8.3: > > Identifiers for collections SHOULD end in a '/' character. > > Suggested patch seems to try to implement the MAY clause from > http://tools.ietf.org/html/rfc4918#section-5.2: > > There is a standing convention that when a collection is referred to > by its name without a trailing slash, the server MAY handle the > request as if the trailing slash were present. In this case, it > SHOULD return a Content-Location header in the response, pointing to > the URL ending with the "/". For example, if a client invokes a > method on http://example.com/blah (no trailing slash), the server may > respond as if the operation were invoked on http://example.com/blah/ > (trailing slash), and should return a Content-Location header with > the value http://example.com/blah/. Wherever a server produces a URL > referring to a collection, the server SHOULD include the trailing > slash. In general, clients SHOULD use the trailing slash form of > collection names. If clients do not use the trailing slash form the > client needs to be prepared to see a redirect response. Clients will > find the DAV:resourcetype property more reliable than the URL to find > out if a resource is a collection. > > But it clearly lacks Content-Location. And it may be much better > idea to change the client to follow SHOULD clauses instead (or > find out a reason why it doesn't in your case). > > We may consider returning redirects in such cases with trailing > slash added, much like it currently happens on GET requests. But > I tend to think that it would be better to preserve 400. > >> 3. In operations with DELETE method for directories: It was >> found a conflict when delete a folder from Nautilus client, the >> directory path to eliminate contains no final slash, causing a >> conflict because nginx requires source path with final slash, >> similar to the case number 2. > > See above. > A brief revision of gvfs dav backend source code available in: https://git.gnome.org/browse/gvfs/tree/daemon/gvfsbackenddav.c shows that, if not present, a trailing slash is added in function g_vfs_backend_dav_uri_for_path for operations where is known that the target is a directory (make_directory and propfind with depth>0). In other cases pathnames provided by outer software layers are not changed. Browsing through gvfsjobmove.c and gvfsjob.c, part of those upper layers, and a brief revision of https://wiki.gnome.org/gvfs/doc and https://developer.gnome.org/gio/stable/ch01.html shows that this client software seems to use POSIX semantics for the pathnames everywhere. In those semantics rename operations doesn't need to know if the target file is a regular one, a directory or some other kind of file and that information is therefore not sent to inner software layers. As in POSIX pathnames trailing slashes are optional and directories are considered a type of file in that standard, in gvfs the DAV backend has apparently been delegated the task of finding out if a trailing slash should be added to a pathname when building the associated URI. In the DAV backend, in order to find out if a pathname is associated with a file or a directory, a PROPFIND request could be sent or the MOVE request could be sent with the pathname unchanged and a provision be made to handle an eventual redirect response. The second approach is being used in gvfs, perhaps because it reduces the number of requests in the case of regular files. That could be the reason for which gvfs doesn't follow in all cases the RFC 4918 SHOULD clause on collection URIs. RFC4918 doesn't seem to have an imperative clause establishing the appropriate server behavior when it chooses not to handle a request in which a collection is referred without a trailing slash in the URI as if that slash were present. However, from the quoted 5.2 section may be inferred that after sending such a request, the client software should expect either a regular response with a Content-Location header or a redirect response. An error response is not mentioned and, when considering if that is the appliable default behaviour, at least one should examine what would be the erroneous behaviour that response would be complaining to the clients. The only fault I can see would be the asumption that either a regular or a redirect response will be received if a URI sent in a request without trailing slash happened to be associated to a collection resource. If the standard provision were that a collection URI MUST have a trailing slash the story would be different, but that is not the case. Based on the rationale just discussed, I think that the appropriate behaviour when dealing with a request where a collection URI is sent without trailing slash would be either a regular response, with a Content-Location header, or a redirect response. As the first option involves a simplification of client-server interaction, I think it is a reasonable approach and therefore would like to propose a patch that implements it by means of adding the Content-Location header missing in the proposal discussed in this thread. As a side note, I don't get the rationale behind the requirement of a trailing slash in collection URIs. It is neither necessary for identification purposes nor it is recommended as a way to establish if a resource is a collection. It rather seems to be something like a remnant from an ancient age, where Hungarian notation, 8.3 filenames and other species flourished. I have found convenient a somewhat detailed rationale to properly illustrate the point, thanks for reading it all the way to here. Best regards, -- Dhionel D?az Centro Nacional de Desarrollo e Investigaci?n en Tecnolog?as Libres Ministerio del Poder Popular para Ciencia, Tecnolog?a e Innovaci?n -------------- next part -------------- A non-text attachment was scrubbed... Name: signature.asc Type: application/pgp-signature Size: 897 bytes Desc: OpenPGP digital signature URL: From mdounin at mdounin.ru Thu Oct 10 12:48:58 2013 From: mdounin at mdounin.ru (Maxim Dounin) Date: Thu, 10 Oct 2013 16:48:58 +0400 Subject: [PATCH] SSL: respect session timeout in configs without session cache. In-Reply-To: References: Message-ID: <20131010124858.GC76294@mdounin.ru> Hello! On Wed, Oct 09, 2013 at 02:21:08PM -0700, Piotr Sikora wrote: > # HG changeset patch > # User Piotr Sikora > # Date 1381353349 25200 > # Wed Oct 09 14:15:49 2013 -0700 > # Node ID 6d1d1c6d346839d3ccdca92cee32bc9887c19841 > # Parent 5483d9e77b3287b00b1104a07688bda37bc7351e > SSL: respect session timeout in configs without session cache. > > Previously, session timeout value was used only when session cache > was configured, which meant that in configurations without it, > Session Tickets would always get 5 minutes timeout hint, regardless > of the configured session timeout. > > Signed-off-by: Piotr Sikora > > diff -r 5483d9e77b32 -r 6d1d1c6d3468 src/event/ngx_event_openssl.c > --- a/src/event/ngx_event_openssl.c Wed Oct 02 15:07:17 2013 +0400 > +++ b/src/event/ngx_event_openssl.c Wed Oct 09 14:15:49 2013 -0700 > @@ -1700,7 +1700,7 @@ ngx_ssl_error(ngx_uint_t level, ngx_log_ > > ngx_int_t > ngx_ssl_session_cache(ngx_ssl_t *ssl, ngx_str_t *sess_ctx, > - ssize_t builtin_session_cache, ngx_shm_zone_t *shm_zone, time_t timeout) > + ssize_t builtin_session_cache, ngx_shm_zone_t *shm_zone) > { > long cache_mode; > > @@ -1749,8 +1749,6 @@ ngx_ssl_session_cache(ngx_ssl_t *ssl, ng > } > } > > - SSL_CTX_set_timeout(ssl->ctx, (long) timeout); > - > if (shm_zone) { > SSL_CTX_sess_set_new_cb(ssl->ctx, ngx_ssl_new_session); > SSL_CTX_sess_set_get_cb(ssl->ctx, ngx_ssl_get_cached_session); [...] I don't see a real reason for the API change, and direct use of SSL_CTX_set_timeout() in http/mail ssl modules. What about this instead: 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 @@ -1704,6 +1704,8 @@ ngx_ssl_session_cache(ngx_ssl_t *ssl, { long cache_mode; + SSL_CTX_set_timeout(ssl->ctx, (long) timeout); + if (builtin_session_cache == NGX_SSL_NO_SCACHE) { SSL_CTX_set_session_cache_mode(ssl->ctx, SSL_SESS_CACHE_OFF); return NGX_OK; @@ -1749,8 +1751,6 @@ ngx_ssl_session_cache(ngx_ssl_t *ssl, } } - SSL_CTX_set_timeout(ssl->ctx, (long) timeout); - if (shm_zone) { SSL_CTX_sess_set_new_cb(ssl->ctx, ngx_ssl_new_session); SSL_CTX_sess_set_get_cb(ssl->ctx, ngx_ssl_get_cached_session); ? -- Maxim Dounin http://nginx.org/en/donation.html From agentzh at gmail.com Thu Oct 10 19:46:03 2013 From: agentzh at gmail.com (Yichun Zhang (agentzh)) Date: Thu, 10 Oct 2013 12:46:03 -0700 Subject: Disallowing multiple http {} blocks in nginx.conf? Message-ID: Hello guys! Some Nginx users use multiple http {} blocks in their nginx.conf, which causing issues because following http {} blocks override previous http modules' main_conf leading inconsistencies in calls like ngx_http_conf_get_module_main_conf and ngx_http_cycle_get_module_main_conf in global handler contexts like "post configuration" handlers. Do you think it is a good idea to simply disallow multiple http {} blocks in nginx.conf? Best regards, -agentzh -------------- next part -------------- An HTML attachment was scrubbed... URL: From piotr at cloudflare.com Thu Oct 10 20:17:14 2013 From: piotr at cloudflare.com (Piotr Sikora) Date: Thu, 10 Oct 2013 13:17:14 -0700 Subject: [PATCH] SSL: respect session timeout in configs without session cache. In-Reply-To: <20131010124858.GC76294@mdounin.ru> References: <20131010124858.GC76294@mdounin.ru> Message-ID: Hey Maxim, > I don't see a real reason for the API change, and direct use of > SSL_CTX_set_timeout() in http/mail ssl modules. What about this > instead: While your patch fixes the issue, I personally don't like the fact that session timeout is being set within code block responsible for session cache logic because it simply doesn't belong there. Having said that, feel free to commit whichever patch you find more appropriate. Best regards, Piotr Sikora From mdounin at mdounin.ru Thu Oct 10 20:21:26 2013 From: mdounin at mdounin.ru (Maxim Dounin) Date: Fri, 11 Oct 2013 00:21:26 +0400 Subject: Disallowing multiple http {} blocks in nginx.conf? In-Reply-To: References: Message-ID: <20131010202126.GH76294@mdounin.ru> Hello! On Thu, Oct 10, 2013 at 12:46:03PM -0700, Yichun Zhang (agentzh) wrote: > Hello guys! > > Some Nginx users use multiple http {} blocks in their nginx.conf, which > causing issues because following http {} blocks override previous http > modules' main_conf leading inconsistencies in calls > like ngx_http_conf_get_module_main_conf > and ngx_http_cycle_get_module_main_conf in global handler contexts like > "post configuration" handlers. > > Do you think it is a good idea to simply disallow multiple http {} blocks > in nginx.conf? I don't thinks that it's a good idea to disallow configurations with multiple http{} blocks. While this wasn't claimed to be supported, it allows fun things like running multiple configuration isolated, and e.g. makes merging configs from multiple servers much easier. AFAIR, as of now only one of standard modules has problems with this - embeeded perl, and it has appropriate "caveat emptor" clause in it's documentation. -- Maxim Dounin http://nginx.org/en/donation.html From agentzh at gmail.com Thu Oct 10 21:39:45 2013 From: agentzh at gmail.com (Yichun Zhang (agentzh)) Date: Thu, 10 Oct 2013 14:39:45 -0700 Subject: Disallowing multiple http {} blocks in nginx.conf? In-Reply-To: <20131010202126.GH76294@mdounin.ru> References: <20131010202126.GH76294@mdounin.ru> Message-ID: Hello! On Thu, Oct 10, 2013 at 1:21 PM, Maxim Dounin wrote: > > I don't thinks that it's a good idea to disallow configurations > with multiple http{} blocks. While this wasn't claimed to be > supported, it allows fun things like running multiple > configuration isolated, and e.g. makes merging configs from > multiple servers much easier. > Is this going to get officially supported? I totally understand the "fun part" of this usage. It's just that it's hard to get everything exactly right, especially with 3rd-party modules enabled. And a "fun configuration" that is not guaranteed to always work is no longer fun at all :) > AFAIR, as of now only one of standard modules has problems with > this - embeeded perl, and it has appropriate "caveat emptor" > clause in it's documentation. > Are you suggesting 3rd-party modules should always put a similar caveat in their documentation too? That's kinda sad and can lead to more confusions in the future because not every user reads the whole documentation carefully enough. I hope we can have a better solution here. Regards, -agentzh From mdounin at mdounin.ru Thu Oct 10 22:30:14 2013 From: mdounin at mdounin.ru (Maxim Dounin) Date: Fri, 11 Oct 2013 02:30:14 +0400 Subject: Disallowing multiple http {} blocks in nginx.conf? In-Reply-To: References: <20131010202126.GH76294@mdounin.ru> Message-ID: <20131010223014.GI76294@mdounin.ru> Hello! On Thu, Oct 10, 2013 at 02:39:45PM -0700, Yichun Zhang (agentzh) wrote: > Hello! > > On Thu, Oct 10, 2013 at 1:21 PM, Maxim Dounin wrote: > > > > I don't thinks that it's a good idea to disallow configurations > > with multiple http{} blocks. While this wasn't claimed to be > > supported, it allows fun things like running multiple > > configuration isolated, and e.g. makes merging configs from > > multiple servers much easier. > > > > Is this going to get officially supported? May be. At least it's not something should be officially disallowed, I think. [...] > > AFAIR, as of now only one of standard modules has problems with > > this - embeeded perl, and it has appropriate "caveat emptor" > > clause in it's documentation. > > > > Are you suggesting 3rd-party modules should always put a similar > caveat in their documentation too? That's kinda sad and can lead to > more confusions in the future because not every user reads the whole > documentation carefully enough. I hope we can have a better solution > here. No, I just said that all non-experimental official modules can cope with multiple http{} blocks, and this is another reason to not disallow multiple http{} blocks, but find a better solution instead. -- Maxim Dounin http://nginx.org/en/donation.html From mdounin at mdounin.ru Thu Oct 10 22:51:11 2013 From: mdounin at mdounin.ru (Maxim Dounin) Date: Fri, 11 Oct 2013 02:51:11 +0400 Subject: [PATCH] SSL: respect session timeout in configs without session cache. In-Reply-To: References: <20131010124858.GC76294@mdounin.ru> Message-ID: <20131010225111.GJ76294@mdounin.ru> Hello! On Thu, Oct 10, 2013 at 01:17:14PM -0700, Piotr Sikora wrote: > Hey Maxim, > > > I don't see a real reason for the API change, and direct use of > > SSL_CTX_set_timeout() in http/mail ssl modules. What about this > > instead: > > While your patch fixes the issue, I personally don't like the fact > that session timeout is being set within code block responsible for > session cache logic because it simply doesn't belong there. Huh? The SSL_CTX_set_timeout is a function which is documented to "manipulate timeout values for session caching" [1], and it looks quite reasonable for me to be set in a block responsible for session cache logic. I would rather think about TLS Session Tickets as a specific way to cache sessions. [1] http://www.openssl.org/docs/ssl/SSL_CTX_set_timeout.html -- Maxim Dounin http://nginx.org/en/donation.html From piotr at cloudflare.com Thu Oct 10 23:22:13 2013 From: piotr at cloudflare.com (Piotr Sikora) Date: Thu, 10 Oct 2013 16:22:13 -0700 Subject: [PATCH] SSL: added support for TLS Session Tickets (RFC5077). In-Reply-To: <20131003151724.GI62063@mdounin.ru> References: <20130930142655.GD56438@mdounin.ru> <20131003151724.GI62063@mdounin.ru> Message-ID: # HG changeset patch # User Piotr Sikora # Date 1381446441 25200 # Thu Oct 10 16:07:21 2013 -0700 # Node ID 7132c555e445419008520563da63d3b122772b97 # Parent 5483d9e77b3287b00b1104a07688bda37bc7351e SSL: added ability to set keys used for Session Tickets (RFC5077). In order to support key rollover, ssl_session_ticket_key can be defined multiple times. The first key will be used to issue and resume Session Tickets, while the rest will be used only to resume them. ssl_session_ticket_key session_ticket_current.key; ssl_session_ticket_key session_ticket_curr-1h.key; ssl_session_ticket_key session_ticket_curr-2h.key; Please note that nginx supports Session Tickets even without explicit configuration of the keys and this feature should be only used in setups where SSL traffic is distributed across multiple nginx servers. Signed-off-by: Piotr Sikora diff -r 5483d9e77b32 -r 7132c555e445 src/event/ngx_event_openssl.c --- a/src/event/ngx_event_openssl.c Wed Oct 02 15:07:17 2013 +0400 +++ b/src/event/ngx_event_openssl.c Thu Oct 10 16:07:21 2013 -0700 @@ -38,6 +38,18 @@ static void ngx_ssl_expire_sessions(ngx_ static void ngx_ssl_session_rbtree_insert_value(ngx_rbtree_node_t *temp, ngx_rbtree_node_t *node, ngx_rbtree_node_t *sentinel); +#ifdef SSL_CTRL_SET_TLSEXT_TICKET_KEY_CB +static int ngx_ssl_session_ticket_key_callback(ngx_ssl_conn_t *ssl_conn, + unsigned char *name, unsigned char *iv, EVP_CIPHER_CTX *ectx, + HMAC_CTX *hctx, int enc); + +#ifdef OPENSSL_NO_SHA256 +#define ngx_ssl_session_ticket_md EVP_sha1 +#else +#define ngx_ssl_session_ticket_md EVP_sha256 +#endif +#endif + static void *ngx_openssl_create_conf(ngx_cycle_t *cycle); static char *ngx_openssl_engine(ngx_conf_t *cf, ngx_command_t *cmd, void *conf); static void ngx_openssl_exit(ngx_cycle_t *cycle); @@ -84,6 +96,9 @@ int ngx_ssl_server_conf_index; int ngx_ssl_session_cache_index; int ngx_ssl_certificate_index; int ngx_ssl_stapling_index; +#ifdef SSL_CTRL_SET_TLSEXT_TICKET_KEY_CB +int ngx_ssl_session_ticket_keys_index; +#endif ngx_int_t @@ -155,6 +170,18 @@ ngx_ssl_init(ngx_log_t *log) return NGX_ERROR; } +#ifdef SSL_CTRL_SET_TLSEXT_TICKET_KEY_CB + + ngx_ssl_session_ticket_keys_index = SSL_CTX_get_ex_new_index(0, NULL, NULL, + NULL, NULL); + if (ngx_ssl_session_ticket_keys_index == -1) { + ngx_ssl_error(NGX_LOG_ALERT, log, 0, + "SSL_CTX_get_ex_new_index() failed"); + return NGX_ERROR; + } + +#endif + return NGX_OK; } @@ -2240,6 +2267,219 @@ ngx_ssl_session_rbtree_insert_value(ngx_ } +#ifdef SSL_CTRL_SET_TLSEXT_TICKET_KEY_CB + +ngx_int_t +ngx_ssl_session_ticket_keys(ngx_conf_t *cf, ngx_ssl_t *ssl, ngx_array_t *paths) +{ + u_char buf[48]; + ssize_t n; + ngx_str_t *path; + ngx_file_t file; + ngx_uint_t i; + ngx_array_t *keys; + ngx_file_info_t fi; + ngx_ssl_session_ticket_key_t *key; + + if (paths == NULL) { + return NGX_OK; + } + + keys = ngx_array_create(cf->pool, paths->nelts, + sizeof(ngx_ssl_session_ticket_key_t)); + if (keys == NULL) { + return NGX_ERROR; + } + + path = paths->elts; + for (i = 0; i < paths->nelts; i++) { + + if (ngx_conf_full_name(cf->cycle, &path[i], 1) != NGX_OK) { + return NGX_ERROR; + } + + ngx_memzero(&file, sizeof(ngx_file_t)); + file.name = path[i]; + file.log = cf->log; + + file.fd = ngx_open_file(file.name.data, NGX_FILE_RDONLY, 0, 0); + if (file.fd == NGX_INVALID_FILE) { + ngx_conf_log_error(NGX_LOG_EMERG, cf, ngx_errno, + ngx_open_file_n " \"%V\" failed", &file.name); + return NGX_ERROR; + } + + if (ngx_fd_info(file.fd, &fi) == NGX_FILE_ERROR) { + ngx_conf_log_error(NGX_LOG_CRIT, cf, ngx_errno, + ngx_fd_info_n " \"%V\" failed", &file.name); + goto failed; + } + + if (ngx_file_size(&fi) != 48) { + ngx_conf_log_error(NGX_LOG_EMERG, cf, 0, + "\"%V\" must be 48 bytes", &file.name); + goto failed; + } + + n = ngx_read_file(&file, buf, 48, 0); + + if (n == NGX_ERROR) { + ngx_conf_log_error(NGX_LOG_CRIT, cf, ngx_errno, + ngx_read_file_n " \"%V\" failed", &file.name); + goto failed; + } + + if (n != 48) { + ngx_conf_log_error(NGX_LOG_CRIT, cf, 0, + ngx_read_file_n " \"%V\" returned only %z bytes " + "instead of 48", &file.name, n); + goto failed; + } + + key = ngx_array_push(keys); + if (key == NULL) { + goto failed; + } + + ngx_memcpy(key->name, buf, 16); + ngx_memcpy(key->aes_key, buf + 16, 16); + ngx_memcpy(key->hmac_key, buf + 32, 16); + + if (ngx_close_file(file.fd) == NGX_FILE_ERROR) { + ngx_log_error(NGX_LOG_ALERT, cf->log, ngx_errno, + ngx_close_file_n " \"%V\" failed", &file.name); + } + } + + if (SSL_CTX_set_ex_data(ssl->ctx, ngx_ssl_session_ticket_keys_index, keys) + == 0) + { + ngx_ssl_error(NGX_LOG_EMERG, ssl->log, 0, + "SSL_CTX_set_ex_data() failed"); + return NGX_ERROR; + } + + if (SSL_CTX_set_tlsext_ticket_key_cb(ssl->ctx, + ngx_ssl_session_ticket_key_callback) + == 0) + { + ngx_log_error(NGX_LOG_WARN, cf->log, 0, + "nginx was built with Session Tickets support, however, " + "now it is linked dynamically to an OpenSSL library " + "which has no tlsext support, therefore Session Tickets " + "are not available"); + } + + return NGX_OK; + +failed: + + if (ngx_close_file(file.fd) == NGX_FILE_ERROR) { + ngx_log_error(NGX_LOG_ALERT, cf->log, ngx_errno, + ngx_close_file_n " \"%V\" failed", &file.name); + } + + return NGX_ERROR; +} + + +static int +ngx_ssl_session_ticket_key_callback(ngx_ssl_conn_t *ssl_conn, + unsigned char *name, unsigned char *iv, EVP_CIPHER_CTX *ectx, + HMAC_CTX *hctx, int enc) +{ + u_char buf[32]; + SSL_CTX *ssl_ctx; + ngx_uint_t i; + ngx_array_t *keys; + ngx_ssl_session_ticket_key_t *key; +#if (NGX_DEBUG) + ngx_connection_t *c; +#endif + + ssl_ctx = SSL_get_SSL_CTX(ssl_conn); + + keys = SSL_CTX_get_ex_data(ssl_ctx, ngx_ssl_session_ticket_keys_index); + if (keys == NULL) { + return -1; + } + + key = keys->elts; + +#if (NGX_DEBUG) + c = ngx_ssl_get_connection(ssl_conn); +#endif + + if (enc == 1) { + /* encrypt session ticket */ + +#if (NGX_DEBUG) + ngx_hex_dump(buf, key[0].name, 16); + + ngx_log_debug3(NGX_LOG_DEBUG_HTTP, c->log, 0, + "ssl session ticket encrypt, key: \"%*s\" (%s session)", + 32, buf, + SSL_session_reused(ssl_conn) ? "reused" : "new"); +#endif + + RAND_pseudo_bytes(iv, 16); + EVP_EncryptInit_ex(ectx, EVP_aes_128_cbc(), NULL, key[0].aes_key, iv); + HMAC_Init_ex(hctx, key[0].hmac_key, 16, ngx_ssl_session_ticket_md(), + NULL); + memcpy(name, key[0].name, 16); + + return 0; + + } else { + /* decrypt session ticket */ + + for (i = 0; i < keys->nelts; i++) { + if (ngx_strncmp(name, key[i].name, 16) == 0) { + break; + } + } + + if (i == keys->nelts) { + ngx_hex_dump(buf, name, 16); + + ngx_log_debug2(NGX_LOG_DEBUG_HTTP, c->log, 0, + "ssl session ticket decrypt, key: \"%*s\" " + "not found", 32, buf); + return 0; + } + +#if (NGX_DEBUG) + ngx_hex_dump(buf, key[i].name, 16); + + ngx_log_debug3(NGX_LOG_DEBUG_HTTP, c->log, 0, + "ssl session ticket decrypt, key: \"%*s\"%s", + 32, buf, (i == 0) ? " (default)" : ""); +#endif + + HMAC_Init_ex(hctx, key[i].hmac_key, 16, ngx_ssl_session_ticket_md(), + NULL); + EVP_DecryptInit_ex(ectx, EVP_aes_128_cbc(), NULL, key[i].aes_key, iv); + + return (i == 0) ? 1 : 2 /* renew */; + } +} + +#else + +ngx_int_t +ngx_ssl_session_ticket_keys(ngx_conf_t *cf, ngx_ssl_t *ssl, ngx_array_t *paths) +{ + if (paths) { + ngx_log_error(NGX_LOG_WARN, ssl->log, 0, + "\"ssl_session_ticket_keys\" ignored, not supported"); + } + + return NGX_OK; +} + +#endif + + void ngx_ssl_cleanup_ctx(void *data) { diff -r 5483d9e77b32 -r 7132c555e445 src/event/ngx_event_openssl.h --- a/src/event/ngx_event_openssl.h Wed Oct 02 15:07:17 2013 +0400 +++ b/src/event/ngx_event_openssl.h Thu Oct 10 16:07:21 2013 -0700 @@ -83,6 +83,16 @@ typedef struct { } ngx_ssl_session_cache_t; +#ifdef SSL_CTRL_SET_TLSEXT_TICKET_KEY_CB + +typedef struct { + u_char name[16]; + u_char aes_key[16]; + u_char hmac_key[16]; +} ngx_ssl_session_ticket_key_t; + +#endif + #define NGX_SSL_SSLv2 0x0002 #define NGX_SSL_SSLv3 0x0004 @@ -116,6 +126,8 @@ ngx_int_t ngx_ssl_dhparam(ngx_conf_t *cf ngx_int_t ngx_ssl_ecdh_curve(ngx_conf_t *cf, ngx_ssl_t *ssl, ngx_str_t *name); ngx_int_t ngx_ssl_session_cache(ngx_ssl_t *ssl, ngx_str_t *sess_ctx, ssize_t builtin_session_cache, ngx_shm_zone_t *shm_zone, time_t timeout); +ngx_int_t ngx_ssl_session_ticket_keys(ngx_conf_t *cf, ngx_ssl_t *ssl, + ngx_array_t *paths); ngx_int_t ngx_ssl_session_cache_init(ngx_shm_zone_t *shm_zone, void *data); ngx_int_t ngx_ssl_create_connection(ngx_ssl_t *ssl, ngx_connection_t *c, ngx_uint_t flags); @@ -175,6 +187,9 @@ extern int ngx_ssl_server_conf_index; extern int ngx_ssl_session_cache_index; extern int ngx_ssl_certificate_index; extern int ngx_ssl_stapling_index; +#ifdef SSL_CTRL_SET_TLSEXT_TICKET_KEY_CB +extern int ngx_ssl_session_ticket_keys_index; +#endif #endif /* _NGX_EVENT_OPENSSL_H_INCLUDED_ */ diff -r 5483d9e77b32 -r 7132c555e445 src/http/modules/ngx_http_ssl_module.c --- a/src/http/modules/ngx_http_ssl_module.c Wed Oct 02 15:07:17 2013 +0400 +++ b/src/http/modules/ngx_http_ssl_module.c Thu Oct 10 16:07:21 2013 -0700 @@ -153,6 +153,13 @@ static ngx_command_t ngx_http_ssl_comma 0, NULL }, + { ngx_string("ssl_session_ticket_key"), + NGX_HTTP_MAIN_CONF|NGX_HTTP_SRV_CONF|NGX_CONF_TAKE1, + ngx_conf_set_str_array_slot, + NGX_HTTP_SRV_CONF_OFFSET, + offsetof(ngx_http_ssl_srv_conf_t, session_ticket_keys), + NULL }, + { ngx_string("ssl_session_timeout"), NGX_HTTP_MAIN_CONF|NGX_HTTP_SRV_CONF|NGX_CONF_TAKE1, ngx_conf_set_sec_slot, @@ -421,6 +428,7 @@ ngx_http_ssl_create_srv_conf(ngx_conf_t sscf->verify_depth = NGX_CONF_UNSET_UINT; sscf->builtin_session_cache = NGX_CONF_UNSET; sscf->session_timeout = NGX_CONF_UNSET; + sscf->session_ticket_keys = NGX_CONF_UNSET_PTR; sscf->stapling = NGX_CONF_UNSET; sscf->stapling_verify = NGX_CONF_UNSET; @@ -623,6 +631,15 @@ ngx_http_ssl_merge_srv_conf(ngx_conf_t * return NGX_CONF_ERROR; } + ngx_conf_merge_ptr_value(conf->session_ticket_keys, + prev->session_ticket_keys, NULL); + + if (ngx_ssl_session_ticket_keys(cf, &conf->ssl, conf->session_ticket_keys) + != NGX_OK) + { + return NGX_CONF_ERROR; + } + if (conf->stapling) { if (ngx_ssl_stapling(cf, &conf->ssl, &conf->stapling_file, diff -r 5483d9e77b32 -r 7132c555e445 src/http/modules/ngx_http_ssl_module.h --- a/src/http/modules/ngx_http_ssl_module.h Wed Oct 02 15:07:17 2013 +0400 +++ b/src/http/modules/ngx_http_ssl_module.h Thu Oct 10 16:07:21 2013 -0700 @@ -42,6 +42,8 @@ typedef struct { ngx_shm_zone_t *shm_zone; + ngx_array_t *session_ticket_keys; + ngx_flag_t stapling; ngx_flag_t stapling_verify; ngx_str_t stapling_file; diff -r 5483d9e77b32 -r 7132c555e445 src/mail/ngx_mail_ssl_module.c --- a/src/mail/ngx_mail_ssl_module.c Wed Oct 02 15:07:17 2013 +0400 +++ b/src/mail/ngx_mail_ssl_module.c Thu Oct 10 16:07:21 2013 -0700 @@ -116,6 +116,13 @@ static ngx_command_t ngx_mail_ssl_comma 0, NULL }, + { ngx_string("ssl_session_ticket_key"), + NGX_MAIL_MAIN_CONF|NGX_MAIL_SRV_CONF|NGX_CONF_TAKE1, + ngx_conf_set_str_array_slot, + NGX_MAIL_SRV_CONF_OFFSET, + offsetof(ngx_mail_ssl_conf_t, session_ticket_keys), + NULL }, + { ngx_string("ssl_session_timeout"), NGX_MAIL_MAIN_CONF|NGX_MAIL_SRV_CONF|NGX_CONF_TAKE1, ngx_conf_set_sec_slot, @@ -184,6 +191,7 @@ ngx_mail_ssl_create_conf(ngx_conf_t *cf) scf->prefer_server_ciphers = NGX_CONF_UNSET; scf->builtin_session_cache = NGX_CONF_UNSET; scf->session_timeout = NGX_CONF_UNSET; + scf->session_ticket_keys = NGX_CONF_UNSET_PTR; return scf; } @@ -331,6 +339,15 @@ ngx_mail_ssl_merge_conf(ngx_conf_t *cf, return NGX_CONF_ERROR; } + ngx_conf_merge_ptr_value(conf->session_ticket_keys, + prev->session_ticket_keys, NULL); + + if (ngx_ssl_session_ticket_keys(cf, &conf->ssl, conf->session_ticket_keys) + != NGX_OK) + { + return NGX_CONF_ERROR; + } + return NGX_CONF_OK; } diff -r 5483d9e77b32 -r 7132c555e445 src/mail/ngx_mail_ssl_module.h --- a/src/mail/ngx_mail_ssl_module.h Wed Oct 02 15:07:17 2013 +0400 +++ b/src/mail/ngx_mail_ssl_module.h Thu Oct 10 16:07:21 2013 -0700 @@ -41,6 +41,8 @@ typedef struct { ngx_shm_zone_t *shm_zone; + ngx_array_t *session_ticket_keys; + u_char *file; ngx_uint_t line; } ngx_mail_ssl_conf_t; From piotr at cloudflare.com Thu Oct 10 23:33:34 2013 From: piotr at cloudflare.com (Piotr Sikora) Date: Thu, 10 Oct 2013 16:33:34 -0700 Subject: [PATCH] SSL: added support for TLS Session Tickets (RFC5077). In-Reply-To: References: <20130930142655.GD56438@mdounin.ru> <20131003151724.GI62063@mdounin.ru> Message-ID: Oops, one line was 81 chars long... Fixed patch below. # HG changeset patch # User Piotr Sikora # Date 1381447913 25200 # Thu Oct 10 16:31:53 2013 -0700 # Node ID 4617733b2d7130313241253ef22958790d6fc902 # Parent 5483d9e77b3287b00b1104a07688bda37bc7351e SSL: added ability to set keys used for Session Tickets (RFC5077). In order to support key rollover, ssl_session_ticket_key can be defined multiple times. The first key will be used to issue and resume Session Tickets, while the rest will be used only to resume them. ssl_session_ticket_key session_ticket_current.key; ssl_session_ticket_key session_ticket_curr-1h.key; ssl_session_ticket_key session_ticket_curr-2h.key; Please note that nginx supports Session Tickets even without explicit configuration of the keys and this feature should be only used in setups where SSL traffic is distributed across multiple nginx servers. Signed-off-by: Piotr Sikora diff -r 5483d9e77b32 -r 4617733b2d71 src/event/ngx_event_openssl.c --- a/src/event/ngx_event_openssl.c Wed Oct 02 15:07:17 2013 +0400 +++ b/src/event/ngx_event_openssl.c Thu Oct 10 16:31:53 2013 -0700 @@ -38,6 +38,18 @@ static void ngx_ssl_expire_sessions(ngx_ static void ngx_ssl_session_rbtree_insert_value(ngx_rbtree_node_t *temp, ngx_rbtree_node_t *node, ngx_rbtree_node_t *sentinel); +#ifdef SSL_CTRL_SET_TLSEXT_TICKET_KEY_CB +static int ngx_ssl_session_ticket_key_callback(ngx_ssl_conn_t *ssl_conn, + unsigned char *name, unsigned char *iv, EVP_CIPHER_CTX *ectx, + HMAC_CTX *hctx, int enc); + +#ifdef OPENSSL_NO_SHA256 +#define ngx_ssl_session_ticket_md EVP_sha1 +#else +#define ngx_ssl_session_ticket_md EVP_sha256 +#endif +#endif + static void *ngx_openssl_create_conf(ngx_cycle_t *cycle); static char *ngx_openssl_engine(ngx_conf_t *cf, ngx_command_t *cmd, void *conf); static void ngx_openssl_exit(ngx_cycle_t *cycle); @@ -84,6 +96,9 @@ int ngx_ssl_server_conf_index; int ngx_ssl_session_cache_index; int ngx_ssl_certificate_index; int ngx_ssl_stapling_index; +#ifdef SSL_CTRL_SET_TLSEXT_TICKET_KEY_CB +int ngx_ssl_session_ticket_keys_index; +#endif ngx_int_t @@ -155,6 +170,18 @@ ngx_ssl_init(ngx_log_t *log) return NGX_ERROR; } +#ifdef SSL_CTRL_SET_TLSEXT_TICKET_KEY_CB + + ngx_ssl_session_ticket_keys_index = SSL_CTX_get_ex_new_index(0, NULL, NULL, + NULL, NULL); + if (ngx_ssl_session_ticket_keys_index == -1) { + ngx_ssl_error(NGX_LOG_ALERT, log, 0, + "SSL_CTX_get_ex_new_index() failed"); + return NGX_ERROR; + } + +#endif + return NGX_OK; } @@ -2240,6 +2267,219 @@ ngx_ssl_session_rbtree_insert_value(ngx_ } +#ifdef SSL_CTRL_SET_TLSEXT_TICKET_KEY_CB + +ngx_int_t +ngx_ssl_session_ticket_keys(ngx_conf_t *cf, ngx_ssl_t *ssl, ngx_array_t *paths) +{ + u_char buf[48]; + ssize_t n; + ngx_str_t *path; + ngx_file_t file; + ngx_uint_t i; + ngx_array_t *keys; + ngx_file_info_t fi; + ngx_ssl_session_ticket_key_t *key; + + if (paths == NULL) { + return NGX_OK; + } + + keys = ngx_array_create(cf->pool, paths->nelts, + sizeof(ngx_ssl_session_ticket_key_t)); + if (keys == NULL) { + return NGX_ERROR; + } + + path = paths->elts; + for (i = 0; i < paths->nelts; i++) { + + if (ngx_conf_full_name(cf->cycle, &path[i], 1) != NGX_OK) { + return NGX_ERROR; + } + + ngx_memzero(&file, sizeof(ngx_file_t)); + file.name = path[i]; + file.log = cf->log; + + file.fd = ngx_open_file(file.name.data, NGX_FILE_RDONLY, 0, 0); + if (file.fd == NGX_INVALID_FILE) { + ngx_conf_log_error(NGX_LOG_EMERG, cf, ngx_errno, + ngx_open_file_n " \"%V\" failed", &file.name); + return NGX_ERROR; + } + + if (ngx_fd_info(file.fd, &fi) == NGX_FILE_ERROR) { + ngx_conf_log_error(NGX_LOG_CRIT, cf, ngx_errno, + ngx_fd_info_n " \"%V\" failed", &file.name); + goto failed; + } + + if (ngx_file_size(&fi) != 48) { + ngx_conf_log_error(NGX_LOG_EMERG, cf, 0, + "\"%V\" must be 48 bytes", &file.name); + goto failed; + } + + n = ngx_read_file(&file, buf, 48, 0); + + if (n == NGX_ERROR) { + ngx_conf_log_error(NGX_LOG_CRIT, cf, ngx_errno, + ngx_read_file_n " \"%V\" failed", &file.name); + goto failed; + } + + if (n != 48) { + ngx_conf_log_error(NGX_LOG_CRIT, cf, 0, + ngx_read_file_n " \"%V\" returned only " + "%z bytes instead of 48", &file.name, n); + goto failed; + } + + key = ngx_array_push(keys); + if (key == NULL) { + goto failed; + } + + ngx_memcpy(key->name, buf, 16); + ngx_memcpy(key->aes_key, buf + 16, 16); + ngx_memcpy(key->hmac_key, buf + 32, 16); + + if (ngx_close_file(file.fd) == NGX_FILE_ERROR) { + ngx_log_error(NGX_LOG_ALERT, cf->log, ngx_errno, + ngx_close_file_n " \"%V\" failed", &file.name); + } + } + + if (SSL_CTX_set_ex_data(ssl->ctx, ngx_ssl_session_ticket_keys_index, keys) + == 0) + { + ngx_ssl_error(NGX_LOG_EMERG, ssl->log, 0, + "SSL_CTX_set_ex_data() failed"); + return NGX_ERROR; + } + + if (SSL_CTX_set_tlsext_ticket_key_cb(ssl->ctx, + ngx_ssl_session_ticket_key_callback) + == 0) + { + ngx_log_error(NGX_LOG_WARN, cf->log, 0, + "nginx was built with Session Tickets support, however, " + "now it is linked dynamically to an OpenSSL library " + "which has no tlsext support, therefore Session Tickets " + "are not available"); + } + + return NGX_OK; + +failed: + + if (ngx_close_file(file.fd) == NGX_FILE_ERROR) { + ngx_log_error(NGX_LOG_ALERT, cf->log, ngx_errno, + ngx_close_file_n " \"%V\" failed", &file.name); + } + + return NGX_ERROR; +} + + +static int +ngx_ssl_session_ticket_key_callback(ngx_ssl_conn_t *ssl_conn, + unsigned char *name, unsigned char *iv, EVP_CIPHER_CTX *ectx, + HMAC_CTX *hctx, int enc) +{ + u_char buf[32]; + SSL_CTX *ssl_ctx; + ngx_uint_t i; + ngx_array_t *keys; + ngx_ssl_session_ticket_key_t *key; +#if (NGX_DEBUG) + ngx_connection_t *c; +#endif + + ssl_ctx = SSL_get_SSL_CTX(ssl_conn); + + keys = SSL_CTX_get_ex_data(ssl_ctx, ngx_ssl_session_ticket_keys_index); + if (keys == NULL) { + return -1; + } + + key = keys->elts; + +#if (NGX_DEBUG) + c = ngx_ssl_get_connection(ssl_conn); +#endif + + if (enc == 1) { + /* encrypt session ticket */ + +#if (NGX_DEBUG) + ngx_hex_dump(buf, key[0].name, 16); + + ngx_log_debug3(NGX_LOG_DEBUG_HTTP, c->log, 0, + "ssl session ticket encrypt, key: \"%*s\" (%s session)", + 32, buf, + SSL_session_reused(ssl_conn) ? "reused" : "new"); +#endif + + RAND_pseudo_bytes(iv, 16); + EVP_EncryptInit_ex(ectx, EVP_aes_128_cbc(), NULL, key[0].aes_key, iv); + HMAC_Init_ex(hctx, key[0].hmac_key, 16, ngx_ssl_session_ticket_md(), + NULL); + memcpy(name, key[0].name, 16); + + return 0; + + } else { + /* decrypt session ticket */ + + for (i = 0; i < keys->nelts; i++) { + if (ngx_strncmp(name, key[i].name, 16) == 0) { + break; + } + } + + if (i == keys->nelts) { + ngx_hex_dump(buf, name, 16); + + ngx_log_debug2(NGX_LOG_DEBUG_HTTP, c->log, 0, + "ssl session ticket decrypt, key: \"%*s\" " + "not found", 32, buf); + return 0; + } + +#if (NGX_DEBUG) + ngx_hex_dump(buf, key[i].name, 16); + + ngx_log_debug3(NGX_LOG_DEBUG_HTTP, c->log, 0, + "ssl session ticket decrypt, key: \"%*s\"%s", + 32, buf, (i == 0) ? " (default)" : ""); +#endif + + HMAC_Init_ex(hctx, key[i].hmac_key, 16, ngx_ssl_session_ticket_md(), + NULL); + EVP_DecryptInit_ex(ectx, EVP_aes_128_cbc(), NULL, key[i].aes_key, iv); + + return (i == 0) ? 1 : 2 /* renew */; + } +} + +#else + +ngx_int_t +ngx_ssl_session_ticket_keys(ngx_conf_t *cf, ngx_ssl_t *ssl, ngx_array_t *paths) +{ + if (paths) { + ngx_log_error(NGX_LOG_WARN, ssl->log, 0, + "\"ssl_session_ticket_keys\" ignored, not supported"); + } + + return NGX_OK; +} + +#endif + + void ngx_ssl_cleanup_ctx(void *data) { diff -r 5483d9e77b32 -r 4617733b2d71 src/event/ngx_event_openssl.h --- a/src/event/ngx_event_openssl.h Wed Oct 02 15:07:17 2013 +0400 +++ b/src/event/ngx_event_openssl.h Thu Oct 10 16:31:53 2013 -0700 @@ -83,6 +83,16 @@ typedef struct { } ngx_ssl_session_cache_t; +#ifdef SSL_CTRL_SET_TLSEXT_TICKET_KEY_CB + +typedef struct { + u_char name[16]; + u_char aes_key[16]; + u_char hmac_key[16]; +} ngx_ssl_session_ticket_key_t; + +#endif + #define NGX_SSL_SSLv2 0x0002 #define NGX_SSL_SSLv3 0x0004 @@ -116,6 +126,8 @@ ngx_int_t ngx_ssl_dhparam(ngx_conf_t *cf ngx_int_t ngx_ssl_ecdh_curve(ngx_conf_t *cf, ngx_ssl_t *ssl, ngx_str_t *name); ngx_int_t ngx_ssl_session_cache(ngx_ssl_t *ssl, ngx_str_t *sess_ctx, ssize_t builtin_session_cache, ngx_shm_zone_t *shm_zone, time_t timeout); +ngx_int_t ngx_ssl_session_ticket_keys(ngx_conf_t *cf, ngx_ssl_t *ssl, + ngx_array_t *paths); ngx_int_t ngx_ssl_session_cache_init(ngx_shm_zone_t *shm_zone, void *data); ngx_int_t ngx_ssl_create_connection(ngx_ssl_t *ssl, ngx_connection_t *c, ngx_uint_t flags); @@ -175,6 +187,9 @@ extern int ngx_ssl_server_conf_index; extern int ngx_ssl_session_cache_index; extern int ngx_ssl_certificate_index; extern int ngx_ssl_stapling_index; +#ifdef SSL_CTRL_SET_TLSEXT_TICKET_KEY_CB +extern int ngx_ssl_session_ticket_keys_index; +#endif #endif /* _NGX_EVENT_OPENSSL_H_INCLUDED_ */ diff -r 5483d9e77b32 -r 4617733b2d71 src/http/modules/ngx_http_ssl_module.c --- a/src/http/modules/ngx_http_ssl_module.c Wed Oct 02 15:07:17 2013 +0400 +++ b/src/http/modules/ngx_http_ssl_module.c Thu Oct 10 16:31:53 2013 -0700 @@ -153,6 +153,13 @@ static ngx_command_t ngx_http_ssl_comma 0, NULL }, + { ngx_string("ssl_session_ticket_key"), + NGX_HTTP_MAIN_CONF|NGX_HTTP_SRV_CONF|NGX_CONF_TAKE1, + ngx_conf_set_str_array_slot, + NGX_HTTP_SRV_CONF_OFFSET, + offsetof(ngx_http_ssl_srv_conf_t, session_ticket_keys), + NULL }, + { ngx_string("ssl_session_timeout"), NGX_HTTP_MAIN_CONF|NGX_HTTP_SRV_CONF|NGX_CONF_TAKE1, ngx_conf_set_sec_slot, @@ -421,6 +428,7 @@ ngx_http_ssl_create_srv_conf(ngx_conf_t sscf->verify_depth = NGX_CONF_UNSET_UINT; sscf->builtin_session_cache = NGX_CONF_UNSET; sscf->session_timeout = NGX_CONF_UNSET; + sscf->session_ticket_keys = NGX_CONF_UNSET_PTR; sscf->stapling = NGX_CONF_UNSET; sscf->stapling_verify = NGX_CONF_UNSET; @@ -623,6 +631,15 @@ ngx_http_ssl_merge_srv_conf(ngx_conf_t * return NGX_CONF_ERROR; } + ngx_conf_merge_ptr_value(conf->session_ticket_keys, + prev->session_ticket_keys, NULL); + + if (ngx_ssl_session_ticket_keys(cf, &conf->ssl, conf->session_ticket_keys) + != NGX_OK) + { + return NGX_CONF_ERROR; + } + if (conf->stapling) { if (ngx_ssl_stapling(cf, &conf->ssl, &conf->stapling_file, diff -r 5483d9e77b32 -r 4617733b2d71 src/http/modules/ngx_http_ssl_module.h --- a/src/http/modules/ngx_http_ssl_module.h Wed Oct 02 15:07:17 2013 +0400 +++ b/src/http/modules/ngx_http_ssl_module.h Thu Oct 10 16:31:53 2013 -0700 @@ -42,6 +42,8 @@ typedef struct { ngx_shm_zone_t *shm_zone; + ngx_array_t *session_ticket_keys; + ngx_flag_t stapling; ngx_flag_t stapling_verify; ngx_str_t stapling_file; diff -r 5483d9e77b32 -r 4617733b2d71 src/mail/ngx_mail_ssl_module.c --- a/src/mail/ngx_mail_ssl_module.c Wed Oct 02 15:07:17 2013 +0400 +++ b/src/mail/ngx_mail_ssl_module.c Thu Oct 10 16:31:53 2013 -0700 @@ -116,6 +116,13 @@ static ngx_command_t ngx_mail_ssl_comma 0, NULL }, + { ngx_string("ssl_session_ticket_key"), + NGX_MAIL_MAIN_CONF|NGX_MAIL_SRV_CONF|NGX_CONF_TAKE1, + ngx_conf_set_str_array_slot, + NGX_MAIL_SRV_CONF_OFFSET, + offsetof(ngx_mail_ssl_conf_t, session_ticket_keys), + NULL }, + { ngx_string("ssl_session_timeout"), NGX_MAIL_MAIN_CONF|NGX_MAIL_SRV_CONF|NGX_CONF_TAKE1, ngx_conf_set_sec_slot, @@ -184,6 +191,7 @@ ngx_mail_ssl_create_conf(ngx_conf_t *cf) scf->prefer_server_ciphers = NGX_CONF_UNSET; scf->builtin_session_cache = NGX_CONF_UNSET; scf->session_timeout = NGX_CONF_UNSET; + scf->session_ticket_keys = NGX_CONF_UNSET_PTR; return scf; } @@ -331,6 +339,15 @@ ngx_mail_ssl_merge_conf(ngx_conf_t *cf, return NGX_CONF_ERROR; } + ngx_conf_merge_ptr_value(conf->session_ticket_keys, + prev->session_ticket_keys, NULL); + + if (ngx_ssl_session_ticket_keys(cf, &conf->ssl, conf->session_ticket_keys) + != NGX_OK) + { + return NGX_CONF_ERROR; + } + return NGX_CONF_OK; } diff -r 5483d9e77b32 -r 4617733b2d71 src/mail/ngx_mail_ssl_module.h --- a/src/mail/ngx_mail_ssl_module.h Wed Oct 02 15:07:17 2013 +0400 +++ b/src/mail/ngx_mail_ssl_module.h Thu Oct 10 16:31:53 2013 -0700 @@ -41,6 +41,8 @@ typedef struct { ngx_shm_zone_t *shm_zone; + ngx_array_t *session_ticket_keys; + u_char *file; ngx_uint_t line; } ngx_mail_ssl_conf_t; From piotr at cloudflare.com Thu Oct 10 23:49:15 2013 From: piotr at cloudflare.com (Piotr Sikora) Date: Thu, 10 Oct 2013 16:49:15 -0700 Subject: [PATCH] SSL: respect session timeout in configs without session cache. In-Reply-To: <20131010225111.GJ76294@mdounin.ru> References: <20131010124858.GC76294@mdounin.ru> <20131010225111.GJ76294@mdounin.ru> Message-ID: Hey Maxim, > Huh? > > The SSL_CTX_set_timeout is a function which is documented to > "manipulate timeout values for session caching" [1], and it looks > quite reasonable for me to be set in a block responsible for > session cache logic. > > I would rather think about TLS Session Tickets as a specific way > to cache sessions. Session cache (server-side) and Session Tickets (client-side) are two different approaches to do the session resumption. Session timeout (at least in OpenSSL) applies to both of them, but existing nginx code (and your patch) calls SSL_CTX_set_timeout() within session cache (server-side) code block, even though session timeout is used in setups without session cache (server-side). But if you disagree with my logic, then feel free to commit your patch, you're the gatekeeper so I'm fine with that. > [1] http://www.openssl.org/docs/ssl/SSL_CTX_set_timeout.html OpenSSL documentation is terrible and a lot of time outdated, I wouldn't be surprised if this was written before Session Tickets support was added. Best regards, Piotr Sikora From mdounin at mdounin.ru Fri Oct 11 00:33:58 2013 From: mdounin at mdounin.ru (Maxim Dounin) Date: Fri, 11 Oct 2013 04:33:58 +0400 Subject: [PATCH] Proxy remote server SSL certificate verification In-Reply-To: References: <20130821143033.GP19334@mdounin.ru> <20130828004143.GE2748@mdounin.ru> <20130902120959.GB65634@mdounin.ru> <20130903132139.GK65634@mdounin.ru> Message-ID: <20131011003358.GL76294@mdounin.ru> Hello! On Wed, Oct 09, 2013 at 07:32:52PM +0300, Aviram Cohen wrote: > Hello!, > > I've made the necessary fixes. A few comments about those: > - Name validation > - Unlike Apache, in this patch, the configuration must contain the name > to verify. In most cases, this should be set to the $host variable (and > this is the default value). I've encountered certificates that validate > names differently (some of Microsoft's certificates), and this is useful > for such cases. Use of $host is certainly wrong. By default nginx uses $proxy_host as a name of the upstream server, and having different default for the verification is bad idea. > - Many certificates use wildcards in the names on which they sign (i.e. > "*.google.com"). Though wildcards can appear anywhere according to the > standard, I've added support only for a wildcard in the beginning of the > name. This is the normal case, and it is easier to implement. This is > is how Apache implements the wildcard name validation as well. Note also > that the function X509_check_host will be introduced in future versions > of OpenSSL that will provide the entire feature. It may be a good idea to actually use X509_check_host() if it's available. And may be even refuse to do a validation if it's not, instead of reimplementing the wheel. > - CRL verification - I've added CRL validation, but note that OpenSSL doesn't > download CRL files from the servers, so the CRL file that is used should > contain the revocation lists of all the proxied hosts. This also > means that it > is out of Nginx's scope to update this file. Apache does the same thing. This is in line with how ssl_crl works, everything else probably doesn't matter. > - The patch was made for v1.4.1. This is a bit strange - there is no chance the patch will be committed over 1.4.1, and there are conflicting changes in recent versions. [...] > # HG changeset patch > # User Aviram Cohen > # Date 1381334949 -7200 > # Branch stable-1.4 > # Node ID 9a6e20bf72f8cf4d17653e4fdfcbac48c4de03aa > # Parent 0702de638a4c51123d7b97801d393e8e25eb48de > Added remote end SSL certificate verification in the proxy module. > > This patch adds the following directives to the proxy module: > - proxy_ssl_verify - whether or not to verify the remote end's > certificate. Default is off. > - proxy_ssl_verify_name - the remote end's name to verify. Default is > $host, can be set to "" in order to avoid name verification. Not sure if "" to avoid name verification is a good value. > - proxy_ssl_verify_depth - how deep the ssl verification should be > done. Default is 1. > - proxy_ssl_trusted_certificate - the path of the certificate file > that is used for verification. This must be provided when > proxy_ssl_verify is on. > - proxy_ssl_crl - the path a file that contains the CRLs of the hosts > to which we proxy. Default is empty, and CRL verification is not done. Given the number of changes, it probably should be more than one patch. > > diff -r 0702de638a4c -r 9a6e20bf72f8 src/event/ngx_event_openssl.c > --- a/src/event/ngx_event_openssl.c Mon May 06 14:20:27 2013 +0400 > +++ b/src/event/ngx_event_openssl.c Wed Oct 09 18:09:09 2013 +0200 > @@ -42,6 +42,11 @@ > static char *ngx_openssl_engine(ngx_conf_t *cf, ngx_command_t *cmd, > void *conf); > static void ngx_openssl_exit(ngx_cycle_t *cycle); > > +static int ngx_openssl_host_wildcard_match(ASN1_STRING *match_pattern, > + ngx_str_t *hostname); > +static int ngx_openssl_host_exact_match(ASN1_STRING *match_pattern, > + ngx_str_t *hostname); > + > > static ngx_command_t ngx_openssl_commands[] = { > > @@ -2562,3 +2567,163 @@ Please add [diff] showfunc=1 to your ~/.hgrc. > EVP_cleanup(); > ENGINE_cleanup(); > } > + > + > +static int > +ngx_openssl_host_wildcard_match(ASN1_STRING *match_pattern, > + ngx_str_t *hostname) > +{ Nipicking: functions seems to be badly placed. Configuration parsing and init/exit handlers are intentionally at the end. They are also badly named, as they aren't OpenSSL-specific, and should be ngx_ssl_* instead. > + int host_top_domain_length; > + u_char *host_top_domain; > + u_char *wildcard_pattern; > + > + /* sanity check */ > + if (!match_pattern > + || match_pattern->length <= 0 > + || !hostname > + || !hostname->len) > + { > + return 0; > + } > + > + /* trivial case */ > + if (ngx_strncasecmp((u_char *) match_pattern->data, > + hostname->data, > + hostname->len) > + == 0) > + { > + return 1; > + } > + > + /* simple wildcard matching - only in the beginning of the string. */ > + if (match_pattern->length > 2 > + && match_pattern->data[0] == '*' > + && match_pattern->data[1] == '.') > + { > + > + wildcard_pattern = (u_char *) (match_pattern->data + 1); > + > + host_top_domain = ngx_strlchr(hostname->data, > + hostname->data + hostname->len, > + '.'); > + Long variable names used seems to result in hardly readable code. [...] > +int > +ngx_openssl_verify_name(X509 *cert, ngx_str_t *expected_name) > +{ > + GENERAL_NAMES *gens = NULL; > + GENERAL_NAME *gen; > + X509_NAME *name = NULL; > + ASN1_STRING *cstr = NULL; > + X509_NAME_ENTRY *ne; > + int i; > + int rc = 0; See elsewhere about variables sorting. And please don't use local variables initialization mixed with declaration. Well, initialization seems to be unneeded here at all. > + > + /* based on OpenSSL's do_x509_check */ > + > + gens = X509_get_ext_d2i(cert, NID_subject_alt_name, NULL, NULL); > + > + if (gens) { > + > + rc = 0; > + > + for (i = 0; i < sk_GENERAL_NAME_num(gens); i++) { > + > + gen = sk_GENERAL_NAME_value(gens, i); > + > + /* we only check for either name or IP */ > + switch (gen->type) { > + > + case GEN_DNS: > + cstr = gen->d.dNSName; > + rc = ngx_openssl_host_wildcard_match(cstr, > + expected_name); > + break; > + > + case GEN_IPADD: > + cstr = gen->d.iPAddress; > + rc = ngx_openssl_host_exact_match(cstr, > + expected_name); Why IP address matching? It doesn't looks like something present in other implementations, nor something used in real certificates. It also doesn't looks like something correctly implemented, as d.iPAddress is expected to contain a binary address. [...] > --- a/src/http/modules/ngx_http_proxy_module.c Mon May 06 14:20:27 2013 +0400 > +++ b/src/http/modules/ngx_http_proxy_module.c Wed Oct 09 18:09:09 2013 +0200 > @@ -74,6 +74,15 @@ > > ngx_uint_t http_version; > > +#if (NGX_HTTP_SSL) > + ngx_uint_t ssl_verify_depth; > + ngx_str_t ssl_trusted_certificate; > + ngx_str_t ssl_crl; > + ngx_str_t ssl_verify_name_source; > + ngx_array_t *ssl_verify_name_lengths; > + ngx_array_t *ssl_verify_name_values; Using a complex value should be simplier. [...] > + n = ngx_http_script_variables_count(&conf->ssl_verify_name_source); > + > + if (n) { > + ngx_memzero(&sc, sizeof(ngx_http_script_compile_t)); > + > + sc.cf = cf; > + sc.source = &conf->ssl_verify_name_source; > + sc.variables = n; > + sc.lengths = &conf->ssl_verify_name_lengths; > + sc.values = &conf->ssl_verify_name_values; > + sc.complete_lengths = 1; > + sc.complete_values = 1; > + > + if (ngx_http_script_compile(&sc) != NGX_OK) { > + return NGX_CONF_ERROR; > + } > + Doing a compilation on every merge isn't a good idea. > + } > + } > + > #endif > > ngx_conf_merge_value(conf->redirect, prev->redirect, 1); > diff -r 0702de638a4c -r 9a6e20bf72f8 src/http/ngx_http_upstream.c > --- a/src/http/ngx_http_upstream.c Mon May 06 14:20:27 2013 +0400 > +++ b/src/http/ngx_http_upstream.c Wed Oct 09 18:09:09 2013 +0200 > @@ -1319,12 +1319,43 @@ > { > ngx_http_request_t *r; > ngx_http_upstream_t *u; > - > + X509 *cert; > + long rc; > + Style nitpicking: 1. Empty lines with "-" and "+" suggests there is something wrong with newlines. 2. Variables order is wrong, shortest types first. > r = c->data; > u = r->upstream; > > if (c->ssl->handshaked) { > - > + if (u->conf->ssl_verify) { > + rc = SSL_get_verify_result(c->ssl->connection); > + if (rc != X509_V_OK) { Style nitpicking: I would suggest to preserve empty line after "if (c->ssl->handshaked)", and add one between SSL_get_verify_result() and "if (rc != X509_V_OK)". > + ngx_log_error(NGX_LOG_ERR, c->log, 0, > + "upstream SSL certificate verify error: (%l:%s)", > + rc, X509_verify_cert_error_string(rc)); > + goto fail; > + } > + > + cert = SSL_get_peer_certificate(c->ssl->connection); > + > + if (cert == NULL) { > + ngx_log_error(NGX_LOG_ERR, c->log, 0, > + "upstream sent no SSL certificate"); > + goto fail; > + } > + > + if (u->ssl_verify_name.len > + && ngx_openssl_verify_name(cert, &u->ssl_verify_name) > + == 0) Style nitpicking: "==" should be aligned with a function which return value it checks, if (u->ssl_verify_name.len && ngx_openssl_verify_name(cert, &u->ssl_verify_name) == 0) { And the ngx_openssl_verify_name() interface probably needs to be changed to be more like other interfaces in nginx - i.e., return NGX_OK on success. With already suggested rename, and a 80 chars limit which isn't actually reached even with long name, this gives us something like this: if (u->ssl_verify_name.len && ngx_ssl_verify_name(cert, &u->ssl_verify_name) != NGX_OK) { [...] -- Maxim Dounin http://nginx.org/en/donation.html From mdounin at mdounin.ru Fri Oct 11 14:26:47 2013 From: mdounin at mdounin.ru (Maxim Dounin) Date: Fri, 11 Oct 2013 18:26:47 +0400 Subject: [PATCH] SSL: added support for TLS Session Tickets (RFC5077). In-Reply-To: References: <20130930142655.GD56438@mdounin.ru> <20131003151724.GI62063@mdounin.ru> Message-ID: <20131011142647.GQ76294@mdounin.ru> Hello! On Thu, Oct 10, 2013 at 04:33:34PM -0700, Piotr Sikora wrote: > Oops, one line was 81 chars long... Fixed patch below. > > # HG changeset patch > # User Piotr Sikora > # Date 1381447913 25200 > # Thu Oct 10 16:31:53 2013 -0700 > # Node ID 4617733b2d7130313241253ef22958790d6fc902 > # Parent 5483d9e77b3287b00b1104a07688bda37bc7351e > SSL: added ability to set keys used for Session Tickets (RFC5077). > > In order to support key rollover, ssl_session_ticket_key can be defined > multiple times. The first key will be used to issue and resume Session > Tickets, while the rest will be used only to resume them. > > ssl_session_ticket_key session_ticket_current.key; > ssl_session_ticket_key session_ticket_curr-1h.key; > ssl_session_ticket_key session_ticket_curr-2h.key; > > Please note that nginx supports Session Tickets even without explicit > configuration of the keys and this feature should be only used in setups > where SSL traffic is distributed across multiple nginx servers. Looks almost good, see some minor nits below. [...] > --- a/src/event/ngx_event_openssl.c Wed Oct 02 15:07:17 2013 +0400 > +++ b/src/event/ngx_event_openssl.c Thu Oct 10 16:31:53 2013 -0700 > @@ -38,6 +38,18 @@ static void ngx_ssl_expire_sessions(ngx_ > static void ngx_ssl_session_rbtree_insert_value(ngx_rbtree_node_t *temp, > ngx_rbtree_node_t *node, ngx_rbtree_node_t *sentinel); > > +#ifdef SSL_CTRL_SET_TLSEXT_TICKET_KEY_CB > +static int ngx_ssl_session_ticket_key_callback(ngx_ssl_conn_t *ssl_conn, > + unsigned char *name, unsigned char *iv, EVP_CIPHER_CTX *ectx, > + HMAC_CTX *hctx, int enc); > + > +#ifdef OPENSSL_NO_SHA256 > +#define ngx_ssl_session_ticket_md EVP_sha1 > +#else > +#define ngx_ssl_session_ticket_md EVP_sha256 > +#endif > +#endif > + Wouldn't it better to move ngx_ssl_session_ticket_md defines to ngx_ssl_session_ticket_key_callback() implementation? [...] > @@ -84,6 +96,9 @@ int ngx_ssl_server_conf_index; > int ngx_ssl_session_cache_index; > int ngx_ssl_certificate_index; > int ngx_ssl_stapling_index; > +#ifdef SSL_CTRL_SET_TLSEXT_TICKET_KEY_CB > +int ngx_ssl_session_ticket_keys_index; > +#endif > > > ngx_int_t > @@ -155,6 +170,18 @@ ngx_ssl_init(ngx_log_t *log) > return NGX_ERROR; > } > > +#ifdef SSL_CTRL_SET_TLSEXT_TICKET_KEY_CB > + > + ngx_ssl_session_ticket_keys_index = SSL_CTX_get_ex_new_index(0, NULL, NULL, > + NULL, NULL); > + if (ngx_ssl_session_ticket_keys_index == -1) { > + ngx_ssl_error(NGX_LOG_ALERT, log, 0, > + "SSL_CTX_get_ex_new_index() failed"); > + return NGX_ERROR; > + } > + > +#endif > + Do we really need these #ifdef's? I don't think saving several bytes in ancient OpenSSL versions worth it (and the ngx_ssl_stapling_index doesn't have #ifdef's). [...] > +ngx_int_t > +ngx_ssl_session_ticket_keys(ngx_conf_t *cf, ngx_ssl_t *ssl, ngx_array_t *paths) > +{ > + u_char buf[48]; > + ssize_t n; > + ngx_str_t *path; > + ngx_file_t file; > + ngx_uint_t i; > + ngx_array_t *keys; > + ngx_file_info_t fi; > + ngx_ssl_session_ticket_key_t *key; Wouldn't ngx_ssl_ticket_key_t be better? Up to you, but "ngx_ssl_session_ticket_key_t" looks a bit too long. [...] > + if (enc == 1) { > + /* encrypt session ticket */ > + > +#if (NGX_DEBUG) > + ngx_hex_dump(buf, key[0].name, 16); > + > + ngx_log_debug3(NGX_LOG_DEBUG_HTTP, c->log, 0, > + "ssl session ticket encrypt, key: \"%*s\" (%s session)", > + 32, buf, > + SSL_session_reused(ssl_conn) ? "reused" : "new"); > +#endif What about something like this: ngx_log_debug3(NGX_LOG_DEBUG_HTTP, c->log, 0, "ssl session ticket encrypt, key: \"%*s\" (%s session)", ngx_hex_dump(buf, key[0].name, 16) - buf, buf, SSL_session_reused(ssl_conn) ? "reused" : "new"); ? (Well, actually I'm not sure we need key name logged, but it probably doesn't matter much.) > + > + RAND_pseudo_bytes(iv, 16); > + EVP_EncryptInit_ex(ectx, EVP_aes_128_cbc(), NULL, key[0].aes_key, iv); > + HMAC_Init_ex(hctx, key[0].hmac_key, 16, ngx_ssl_session_ticket_md(), > + NULL); Just in case, using a shorter name "ngx_ssl_ticket_md()" would save us from wrapping here and in decrypt case. > + memcpy(name, key[0].name, 16); > + > + return 0; > + > + } else { > + /* decrypt session ticket */ > + > + for (i = 0; i < keys->nelts; i++) { > + if (ngx_strncmp(name, key[i].name, 16) == 0) { Shouldn't it be ngx_memcmp(), as it checks binary data now? > + break; > + } > + } > + > + if (i == keys->nelts) { Adding "goto found" instead of "break" would allow to avoid this additional check. Up to you though. > + ngx_hex_dump(buf, name, 16); > + > + ngx_log_debug2(NGX_LOG_DEBUG_HTTP, c->log, 0, > + "ssl session ticket decrypt, key: \"%*s\" " > + "not found", 32, buf); > + return 0; > + } > + > +#if (NGX_DEBUG) > + ngx_hex_dump(buf, key[i].name, 16); > + > + ngx_log_debug3(NGX_LOG_DEBUG_HTTP, c->log, 0, > + "ssl session ticket decrypt, key: \"%*s\"%s", > + 32, buf, (i == 0) ? " (default)" : ""); > +#endif > + > + HMAC_Init_ex(hctx, key[i].hmac_key, 16, ngx_ssl_session_ticket_md(), > + NULL); > + EVP_DecryptInit_ex(ectx, EVP_aes_128_cbc(), NULL, key[i].aes_key, iv); > + > + return (i == 0) ? 1 : 2 /* renew */; [...] -- Maxim Dounin http://nginx.org/en/donation.html From piotr at cloudflare.com Fri Oct 11 23:22:07 2013 From: piotr at cloudflare.com (Piotr Sikora) Date: Fri, 11 Oct 2013 16:22:07 -0700 Subject: [PATCH] SSL: added support for TLS Session Tickets (RFC5077). In-Reply-To: <20131011142647.GQ76294@mdounin.ru> References: <20130930142655.GD56438@mdounin.ru> <20131003151724.GI62063@mdounin.ru> <20131011142647.GQ76294@mdounin.ru> Message-ID: Hey Maxim, > Wouldn't it better to move ngx_ssl_session_ticket_md defines > to ngx_ssl_session_ticket_key_callback() implementation? You mean inside the function or just above it? I moved them just above it. > Do we really need these #ifdef's? I don't think saving several > bytes in ancient OpenSSL versions worth it (and the > ngx_ssl_stapling_index doesn't have #ifdef's). Probably not, removed. While there, I moved the definitions and initialization right after ngx_ssl_session_cache_index, so that the two session resumption indexes are together, hopefully that's alright. > Wouldn't ngx_ssl_ticket_key_t be better? Up to you, but > "ngx_ssl_session_ticket_key_t" looks a bit too long. It's a bit too long, yes, but I prefer to keep everything with the same prefix, so either rename everything to "ngx_ssl_ticket_" (which I don't like that much) or keep long names. > What about something like this: > > ngx_log_debug3(NGX_LOG_DEBUG_HTTP, c->log, 0, > "ssl session ticket encrypt, key: \"%*s\" (%s session)", > ngx_hex_dump(buf, key[0].name, 16) - buf, buf, > SSL_session_reused(ssl_conn) ? "reused" : "new"); > > ? > > (Well, actually I'm not sure we need key name logged, but it > probably doesn't matter much.) That's much better, thanks. It's used only for the debugging, so I think it's fine to print it. > Just in case, using a shorter name "ngx_ssl_ticket_md()" would > save us from wrapping here and in decrypt case. I know, I had something shorter here originally, but I've decided to rename it, so that it would have the same prefix... But if you really want to get rid of the wrap, maybe we could use "ngx_ssl_md()" here? What do you think? > Shouldn't it be ngx_memcmp(), as it checks binary data now? Good catch, thanks! That was leftover from my previous implementation. > Adding "goto found" instead of "break" would allow to avoid this > additional check. Up to you though. Personally, I prefer the explicit "end-of-the-loop" check, but I don't mind either way. Changed to "goto found". Updated patch attached, with slightly changed commit message (better file names in the example). Please note, that it doesn't have any session timeout logic, so it should be committed after the timeout patch :) Best regards, Piotr Sikora # HG changeset patch # User Piotr Sikora # Date 1381532724 25200 # Fri Oct 11 16:05:24 2013 -0700 # Node ID 296805806a43f4b222c4cf34dd6489b37394e315 # Parent 5483d9e77b3287b00b1104a07688bda37bc7351e SSL: added ability to set keys used for Session Tickets (RFC5077). In order to support key rollover, ssl_session_ticket_key can be defined multiple times. The first key will be used to issue and resume Session Tickets, while the rest will be used only to resume them. ssl_session_ticket_key session_tickets/current.key; ssl_session_ticket_key session_tickets/prev-1h.key; ssl_session_ticket_key session_tickets/prev-2h.key; Please note that nginx supports Session Tickets even without explicit configuration of the keys and this feature should be only used in setups where SSL traffic is distributed across multiple nginx servers. Signed-off-by: Piotr Sikora diff -r 5483d9e77b32 -r 296805806a43 src/event/ngx_event_openssl.c --- a/src/event/ngx_event_openssl.c Wed Oct 02 15:07:17 2013 +0400 +++ b/src/event/ngx_event_openssl.c Fri Oct 11 16:05:24 2013 -0700 @@ -38,6 +38,12 @@ static void ngx_ssl_expire_sessions(ngx_ static void ngx_ssl_session_rbtree_insert_value(ngx_rbtree_node_t *temp, ngx_rbtree_node_t *node, ngx_rbtree_node_t *sentinel); +#ifdef SSL_CTRL_SET_TLSEXT_TICKET_KEY_CB +static int ngx_ssl_session_ticket_key_callback(ngx_ssl_conn_t *ssl_conn, + unsigned char *name, unsigned char *iv, EVP_CIPHER_CTX *ectx, + HMAC_CTX *hctx, int enc); +#endif + static void *ngx_openssl_create_conf(ngx_cycle_t *cycle); static char *ngx_openssl_engine(ngx_conf_t *cf, ngx_command_t *cmd, void *conf); static void ngx_openssl_exit(ngx_cycle_t *cycle); @@ -82,6 +88,7 @@ ngx_module_t ngx_openssl_module = { int ngx_ssl_connection_index; 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_stapling_index; @@ -139,6 +146,14 @@ ngx_ssl_init(ngx_log_t *log) return NGX_ERROR; } + ngx_ssl_session_ticket_keys_index = SSL_CTX_get_ex_new_index(0, NULL, NULL, + NULL, NULL); + if (ngx_ssl_session_ticket_keys_index == -1) { + ngx_ssl_error(NGX_LOG_ALERT, log, 0, + "SSL_CTX_get_ex_new_index() failed"); + return NGX_ERROR; + } + ngx_ssl_certificate_index = SSL_CTX_get_ex_new_index(0, NULL, NULL, NULL, NULL); if (ngx_ssl_certificate_index == -1) { @@ -2240,6 +2255,218 @@ ngx_ssl_session_rbtree_insert_value(ngx_ } +#ifdef SSL_CTRL_SET_TLSEXT_TICKET_KEY_CB + +ngx_int_t +ngx_ssl_session_ticket_keys(ngx_conf_t *cf, ngx_ssl_t *ssl, ngx_array_t *paths) +{ + u_char buf[48]; + ssize_t n; + ngx_str_t *path; + ngx_file_t file; + ngx_uint_t i; + ngx_array_t *keys; + ngx_file_info_t fi; + ngx_ssl_session_ticket_key_t *key; + + if (paths == NULL) { + return NGX_OK; + } + + keys = ngx_array_create(cf->pool, paths->nelts, + sizeof(ngx_ssl_session_ticket_key_t)); + if (keys == NULL) { + return NGX_ERROR; + } + + path = paths->elts; + for (i = 0; i < paths->nelts; i++) { + + if (ngx_conf_full_name(cf->cycle, &path[i], 1) != NGX_OK) { + return NGX_ERROR; + } + + ngx_memzero(&file, sizeof(ngx_file_t)); + file.name = path[i]; + file.log = cf->log; + + file.fd = ngx_open_file(file.name.data, NGX_FILE_RDONLY, 0, 0); + if (file.fd == NGX_INVALID_FILE) { + ngx_conf_log_error(NGX_LOG_EMERG, cf, ngx_errno, + ngx_open_file_n " \"%V\" failed", &file.name); + return NGX_ERROR; + } + + if (ngx_fd_info(file.fd, &fi) == NGX_FILE_ERROR) { + ngx_conf_log_error(NGX_LOG_CRIT, cf, ngx_errno, + ngx_fd_info_n " \"%V\" failed", &file.name); + goto failed; + } + + if (ngx_file_size(&fi) != 48) { + ngx_conf_log_error(NGX_LOG_EMERG, cf, 0, + "\"%V\" must be 48 bytes", &file.name); + goto failed; + } + + n = ngx_read_file(&file, buf, 48, 0); + + if (n == NGX_ERROR) { + ngx_conf_log_error(NGX_LOG_CRIT, cf, ngx_errno, + ngx_read_file_n " \"%V\" failed", &file.name); + goto failed; + } + + if (n != 48) { + ngx_conf_log_error(NGX_LOG_CRIT, cf, 0, + ngx_read_file_n " \"%V\" returned only " + "%z bytes instead of 48", &file.name, n); + goto failed; + } + + key = ngx_array_push(keys); + if (key == NULL) { + goto failed; + } + + ngx_memcpy(key->name, buf, 16); + ngx_memcpy(key->aes_key, buf + 16, 16); + ngx_memcpy(key->hmac_key, buf + 32, 16); + + if (ngx_close_file(file.fd) == NGX_FILE_ERROR) { + ngx_log_error(NGX_LOG_ALERT, cf->log, ngx_errno, + ngx_close_file_n " \"%V\" failed", &file.name); + } + } + + if (SSL_CTX_set_ex_data(ssl->ctx, ngx_ssl_session_ticket_keys_index, keys) + == 0) + { + ngx_ssl_error(NGX_LOG_EMERG, ssl->log, 0, + "SSL_CTX_set_ex_data() failed"); + return NGX_ERROR; + } + + if (SSL_CTX_set_tlsext_ticket_key_cb(ssl->ctx, + ngx_ssl_session_ticket_key_callback) + == 0) + { + ngx_log_error(NGX_LOG_WARN, cf->log, 0, + "nginx was built with Session Tickets support, however, " + "now it is linked dynamically to an OpenSSL library " + "which has no tlsext support, therefore Session Tickets " + "are not available"); + } + + return NGX_OK; + +failed: + + if (ngx_close_file(file.fd) == NGX_FILE_ERROR) { + ngx_log_error(NGX_LOG_ALERT, cf->log, ngx_errno, + ngx_close_file_n " \"%V\" failed", &file.name); + } + + return NGX_ERROR; +} + + +#ifdef OPENSSL_NO_SHA256 +#define ngx_ssl_session_ticket_md EVP_sha1 +#else +#define ngx_ssl_session_ticket_md EVP_sha256 +#endif + + +static int +ngx_ssl_session_ticket_key_callback(ngx_ssl_conn_t *ssl_conn, + unsigned char *name, unsigned char *iv, EVP_CIPHER_CTX *ectx, + HMAC_CTX *hctx, int enc) +{ + SSL_CTX *ssl_ctx; + ngx_uint_t i; + ngx_array_t *keys; + ngx_ssl_session_ticket_key_t *key; +#if (NGX_DEBUG) + u_char buf[32]; + ngx_connection_t *c; +#endif + + ssl_ctx = SSL_get_SSL_CTX(ssl_conn); + + keys = SSL_CTX_get_ex_data(ssl_ctx, ngx_ssl_session_ticket_keys_index); + if (keys == NULL) { + return -1; + } + + key = keys->elts; + +#if (NGX_DEBUG) + c = ngx_ssl_get_connection(ssl_conn); +#endif + + if (enc == 1) { + /* encrypt session ticket */ + + ngx_log_debug3(NGX_LOG_DEBUG_HTTP, c->log, 0, + "ssl session ticket encrypt, key: \"%*s\" (%s session)", + ngx_hex_dump(buf, key[0].name, 16) - buf, buf, + SSL_session_reused(ssl_conn) ? "reused" : "new"); + + RAND_pseudo_bytes(iv, 16); + EVP_EncryptInit_ex(ectx, EVP_aes_128_cbc(), NULL, key[0].aes_key, iv); + HMAC_Init_ex(hctx, key[0].hmac_key, 16, ngx_ssl_session_ticket_md(), + NULL); + memcpy(name, key[0].name, 16); + + return 0; + + } else { + /* decrypt session ticket */ + + for (i = 0; i < keys->nelts; i++) { + if (ngx_memcmp(name, key[i].name, 16) == 0) { + goto found; + } + } + + ngx_log_debug2(NGX_LOG_DEBUG_HTTP, c->log, 0, + "ssl session ticket decrypt, key: \"%*s\" not found", + ngx_hex_dump(buf, name, 16) - buf, buf); + + return 0; + +found: + + ngx_log_debug3(NGX_LOG_DEBUG_HTTP, c->log, 0, + "ssl session ticket decrypt, key: \"%*s\"%s", + ngx_hex_dump(buf, key[i].name, 16) - buf, buf, + (i == 0) ? " (default)" : ""); + + HMAC_Init_ex(hctx, key[i].hmac_key, 16, ngx_ssl_session_ticket_md(), + NULL); + EVP_DecryptInit_ex(ectx, EVP_aes_128_cbc(), NULL, key[i].aes_key, iv); + + return (i == 0) ? 1 : 2 /* renew */; + } +} + +#else + +ngx_int_t +ngx_ssl_session_ticket_keys(ngx_conf_t *cf, ngx_ssl_t *ssl, ngx_array_t *paths) +{ + if (paths) { + ngx_log_error(NGX_LOG_WARN, ssl->log, 0, + "\"ssl_session_ticket_keys\" ignored, not supported"); + } + + return NGX_OK; +} + +#endif + + void ngx_ssl_cleanup_ctx(void *data) { diff -r 5483d9e77b32 -r 296805806a43 src/event/ngx_event_openssl.h --- a/src/event/ngx_event_openssl.h Wed Oct 02 15:07:17 2013 +0400 +++ b/src/event/ngx_event_openssl.h Fri Oct 11 16:05:24 2013 -0700 @@ -83,6 +83,16 @@ typedef struct { } ngx_ssl_session_cache_t; +#ifdef SSL_CTRL_SET_TLSEXT_TICKET_KEY_CB + +typedef struct { + u_char name[16]; + u_char aes_key[16]; + u_char hmac_key[16]; +} ngx_ssl_session_ticket_key_t; + +#endif + #define NGX_SSL_SSLv2 0x0002 #define NGX_SSL_SSLv3 0x0004 @@ -116,6 +126,8 @@ ngx_int_t ngx_ssl_dhparam(ngx_conf_t *cf ngx_int_t ngx_ssl_ecdh_curve(ngx_conf_t *cf, ngx_ssl_t *ssl, ngx_str_t *name); ngx_int_t ngx_ssl_session_cache(ngx_ssl_t *ssl, ngx_str_t *sess_ctx, ssize_t builtin_session_cache, ngx_shm_zone_t *shm_zone, time_t timeout); +ngx_int_t ngx_ssl_session_ticket_keys(ngx_conf_t *cf, ngx_ssl_t *ssl, + ngx_array_t *paths); ngx_int_t ngx_ssl_session_cache_init(ngx_shm_zone_t *shm_zone, void *data); ngx_int_t ngx_ssl_create_connection(ngx_ssl_t *ssl, ngx_connection_t *c, ngx_uint_t flags); @@ -173,6 +185,7 @@ void ngx_ssl_cleanup_ctx(void *data); extern int ngx_ssl_connection_index; 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_stapling_index; diff -r 5483d9e77b32 -r 296805806a43 src/http/modules/ngx_http_ssl_module.c --- a/src/http/modules/ngx_http_ssl_module.c Wed Oct 02 15:07:17 2013 +0400 +++ b/src/http/modules/ngx_http_ssl_module.c Fri Oct 11 16:05:24 2013 -0700 @@ -153,6 +153,13 @@ static ngx_command_t ngx_http_ssl_comma 0, NULL }, + { ngx_string("ssl_session_ticket_key"), + NGX_HTTP_MAIN_CONF|NGX_HTTP_SRV_CONF|NGX_CONF_TAKE1, + ngx_conf_set_str_array_slot, + NGX_HTTP_SRV_CONF_OFFSET, + offsetof(ngx_http_ssl_srv_conf_t, session_ticket_keys), + NULL }, + { ngx_string("ssl_session_timeout"), NGX_HTTP_MAIN_CONF|NGX_HTTP_SRV_CONF|NGX_CONF_TAKE1, ngx_conf_set_sec_slot, @@ -421,6 +428,7 @@ ngx_http_ssl_create_srv_conf(ngx_conf_t sscf->verify_depth = NGX_CONF_UNSET_UINT; sscf->builtin_session_cache = NGX_CONF_UNSET; sscf->session_timeout = NGX_CONF_UNSET; + sscf->session_ticket_keys = NGX_CONF_UNSET_PTR; sscf->stapling = NGX_CONF_UNSET; sscf->stapling_verify = NGX_CONF_UNSET; @@ -623,6 +631,15 @@ ngx_http_ssl_merge_srv_conf(ngx_conf_t * return NGX_CONF_ERROR; } + ngx_conf_merge_ptr_value(conf->session_ticket_keys, + prev->session_ticket_keys, NULL); + + if (ngx_ssl_session_ticket_keys(cf, &conf->ssl, conf->session_ticket_keys) + != NGX_OK) + { + return NGX_CONF_ERROR; + } + if (conf->stapling) { if (ngx_ssl_stapling(cf, &conf->ssl, &conf->stapling_file, diff -r 5483d9e77b32 -r 296805806a43 src/http/modules/ngx_http_ssl_module.h --- a/src/http/modules/ngx_http_ssl_module.h Wed Oct 02 15:07:17 2013 +0400 +++ b/src/http/modules/ngx_http_ssl_module.h Fri Oct 11 16:05:24 2013 -0700 @@ -42,6 +42,8 @@ typedef struct { ngx_shm_zone_t *shm_zone; + ngx_array_t *session_ticket_keys; + ngx_flag_t stapling; ngx_flag_t stapling_verify; ngx_str_t stapling_file; diff -r 5483d9e77b32 -r 296805806a43 src/mail/ngx_mail_ssl_module.c --- a/src/mail/ngx_mail_ssl_module.c Wed Oct 02 15:07:17 2013 +0400 +++ b/src/mail/ngx_mail_ssl_module.c Fri Oct 11 16:05:24 2013 -0700 @@ -116,6 +116,13 @@ static ngx_command_t ngx_mail_ssl_comma 0, NULL }, + { ngx_string("ssl_session_ticket_key"), + NGX_MAIL_MAIN_CONF|NGX_MAIL_SRV_CONF|NGX_CONF_TAKE1, + ngx_conf_set_str_array_slot, + NGX_MAIL_SRV_CONF_OFFSET, + offsetof(ngx_mail_ssl_conf_t, session_ticket_keys), + NULL }, + { ngx_string("ssl_session_timeout"), NGX_MAIL_MAIN_CONF|NGX_MAIL_SRV_CONF|NGX_CONF_TAKE1, ngx_conf_set_sec_slot, @@ -184,6 +191,7 @@ ngx_mail_ssl_create_conf(ngx_conf_t *cf) scf->prefer_server_ciphers = NGX_CONF_UNSET; scf->builtin_session_cache = NGX_CONF_UNSET; scf->session_timeout = NGX_CONF_UNSET; + scf->session_ticket_keys = NGX_CONF_UNSET_PTR; return scf; } @@ -331,6 +339,15 @@ ngx_mail_ssl_merge_conf(ngx_conf_t *cf, return NGX_CONF_ERROR; } + ngx_conf_merge_ptr_value(conf->session_ticket_keys, + prev->session_ticket_keys, NULL); + + if (ngx_ssl_session_ticket_keys(cf, &conf->ssl, conf->session_ticket_keys) + != NGX_OK) + { + return NGX_CONF_ERROR; + } + return NGX_CONF_OK; } diff -r 5483d9e77b32 -r 296805806a43 src/mail/ngx_mail_ssl_module.h --- a/src/mail/ngx_mail_ssl_module.h Wed Oct 02 15:07:17 2013 +0400 +++ b/src/mail/ngx_mail_ssl_module.h Fri Oct 11 16:05:24 2013 -0700 @@ -41,6 +41,8 @@ typedef struct { ngx_shm_zone_t *shm_zone; + ngx_array_t *session_ticket_keys; + u_char *file; ngx_uint_t line; } ngx_mail_ssl_conf_t; From mdounin at mdounin.ru Mon Oct 14 13:29:25 2013 From: mdounin at mdounin.ru (Maxim Dounin) Date: Mon, 14 Oct 2013 13:29:25 +0000 Subject: [nginx] SSL: fixed build with OpenSSL 0.9.7. Message-ID: details: http://hg.nginx.org/nginx/rev/5b5a486bd40e branches: changeset: 5423:5b5a486bd40e user: Maxim Dounin date: Mon Oct 14 13:44:09 2013 +0400 description: SSL: fixed build with OpenSSL 0.9.7. SSL_get_rbio() and SSL_get_wbio() functions used to get non-const pointer in OpenSSL 0.9.7, hence an explicit cast added to drop const qualifier. diffstat: src/event/ngx_event_openssl.c | 4 ++-- 1 files changed, 2 insertions(+), 2 deletions(-) diffs (14 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 @@ -548,8 +548,8 @@ ngx_ssl_info_callback(const ngx_ssl_conn * added to wbio, and set buffer size. */ - rbio = SSL_get_rbio(ssl_conn); - wbio = SSL_get_wbio(ssl_conn); + rbio = SSL_get_rbio((ngx_ssl_conn_t *) ssl_conn); + wbio = SSL_get_wbio((ngx_ssl_conn_t *) ssl_conn); if (rbio != wbio) { (void) BIO_set_write_buffer_size(wbio, NGX_SSL_BUFSIZE); From mdounin at mdounin.ru Mon Oct 14 13:29:26 2013 From: mdounin at mdounin.ru (Maxim Dounin) Date: Mon, 14 Oct 2013 13:29:26 +0000 Subject: [nginx] SSL: SSL_CTX_set_timeout() now always called. Message-ID: details: http://hg.nginx.org/nginx/rev/767aa37f12de branches: changeset: 5424:767aa37f12de user: Maxim Dounin date: Mon Oct 14 13:59:35 2013 +0400 description: SSL: SSL_CTX_set_timeout() now always called. The timeout set is used by OpenSSL as a hint for clients in TLS Session Tickets. Previous code resulted in a default timeout (5m) used for TLS Sessions Tickets if there was no session cache configured. Prodded by Piotr Sikora. diffstat: src/event/ngx_event_openssl.c | 4 ++-- 1 files changed, 2 insertions(+), 2 deletions(-) diffs (21 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 @@ -1704,6 +1704,8 @@ ngx_ssl_session_cache(ngx_ssl_t *ssl, ng { long cache_mode; + SSL_CTX_set_timeout(ssl->ctx, (long) timeout); + if (builtin_session_cache == NGX_SSL_NO_SCACHE) { SSL_CTX_set_session_cache_mode(ssl->ctx, SSL_SESS_CACHE_OFF); return NGX_OK; @@ -1749,8 +1751,6 @@ ngx_ssl_session_cache(ngx_ssl_t *ssl, ng } } - SSL_CTX_set_timeout(ssl->ctx, (long) timeout); - if (shm_zone) { SSL_CTX_sess_set_new_cb(ssl->ctx, ngx_ssl_new_session); SSL_CTX_sess_set_get_cb(ssl->ctx, ngx_ssl_get_cached_session); From mdounin at mdounin.ru Mon Oct 14 13:29:28 2013 From: mdounin at mdounin.ru (Maxim Dounin) Date: Mon, 14 Oct 2013 13:29:28 +0000 Subject: [nginx] SSL: added ability to set keys used for Session Tickets ... Message-ID: details: http://hg.nginx.org/nginx/rev/1356a3b96924 branches: changeset: 5425:1356a3b96924 user: Piotr Sikora date: Fri Oct 11 16:05:24 2013 -0700 description: SSL: added ability to set keys used for Session Tickets (RFC5077). In order to support key rollover, ssl_session_ticket_key can be defined multiple times. The first key will be used to issue and resume Session Tickets, while the rest will be used only to resume them. ssl_session_ticket_key session_tickets/current.key; ssl_session_ticket_key session_tickets/prev-1h.key; ssl_session_ticket_key session_tickets/prev-2h.key; Please note that nginx supports Session Tickets even without explicit configuration of the keys and this feature should be only used in setups where SSL traffic is distributed across multiple nginx servers. Signed-off-by: Piotr Sikora diffstat: src/event/ngx_event_openssl.c | 227 +++++++++++++++++++++++++++++++++ src/event/ngx_event_openssl.h | 13 + src/http/modules/ngx_http_ssl_module.c | 17 ++ src/http/modules/ngx_http_ssl_module.h | 2 + src/mail/ngx_mail_ssl_module.c | 17 ++ src/mail/ngx_mail_ssl_module.h | 2 + 6 files changed, 278 insertions(+), 0 deletions(-) diffs (truncated from 401 to 300 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 @@ -38,6 +38,12 @@ static void ngx_ssl_expire_sessions(ngx_ static void ngx_ssl_session_rbtree_insert_value(ngx_rbtree_node_t *temp, ngx_rbtree_node_t *node, ngx_rbtree_node_t *sentinel); +#ifdef SSL_CTRL_SET_TLSEXT_TICKET_KEY_CB +static int ngx_ssl_session_ticket_key_callback(ngx_ssl_conn_t *ssl_conn, + unsigned char *name, unsigned char *iv, EVP_CIPHER_CTX *ectx, + HMAC_CTX *hctx, int enc); +#endif + static void *ngx_openssl_create_conf(ngx_cycle_t *cycle); static char *ngx_openssl_engine(ngx_conf_t *cf, ngx_command_t *cmd, void *conf); static void ngx_openssl_exit(ngx_cycle_t *cycle); @@ -82,6 +88,7 @@ ngx_module_t ngx_openssl_module = { int ngx_ssl_connection_index; 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_stapling_index; @@ -139,6 +146,14 @@ ngx_ssl_init(ngx_log_t *log) return NGX_ERROR; } + ngx_ssl_session_ticket_keys_index = SSL_CTX_get_ex_new_index(0, NULL, NULL, + NULL, NULL); + if (ngx_ssl_session_ticket_keys_index == -1) { + ngx_ssl_error(NGX_LOG_ALERT, log, 0, + "SSL_CTX_get_ex_new_index() failed"); + return NGX_ERROR; + } + ngx_ssl_certificate_index = SSL_CTX_get_ex_new_index(0, NULL, NULL, NULL, NULL); if (ngx_ssl_certificate_index == -1) { @@ -2240,6 +2255,218 @@ ngx_ssl_session_rbtree_insert_value(ngx_ } +#ifdef SSL_CTRL_SET_TLSEXT_TICKET_KEY_CB + +ngx_int_t +ngx_ssl_session_ticket_keys(ngx_conf_t *cf, ngx_ssl_t *ssl, ngx_array_t *paths) +{ + u_char buf[48]; + ssize_t n; + ngx_str_t *path; + ngx_file_t file; + ngx_uint_t i; + ngx_array_t *keys; + ngx_file_info_t fi; + ngx_ssl_session_ticket_key_t *key; + + if (paths == NULL) { + return NGX_OK; + } + + keys = ngx_array_create(cf->pool, paths->nelts, + sizeof(ngx_ssl_session_ticket_key_t)); + if (keys == NULL) { + return NGX_ERROR; + } + + path = paths->elts; + for (i = 0; i < paths->nelts; i++) { + + if (ngx_conf_full_name(cf->cycle, &path[i], 1) != NGX_OK) { + return NGX_ERROR; + } + + ngx_memzero(&file, sizeof(ngx_file_t)); + file.name = path[i]; + file.log = cf->log; + + file.fd = ngx_open_file(file.name.data, NGX_FILE_RDONLY, 0, 0); + if (file.fd == NGX_INVALID_FILE) { + ngx_conf_log_error(NGX_LOG_EMERG, cf, ngx_errno, + ngx_open_file_n " \"%V\" failed", &file.name); + return NGX_ERROR; + } + + if (ngx_fd_info(file.fd, &fi) == NGX_FILE_ERROR) { + ngx_conf_log_error(NGX_LOG_CRIT, cf, ngx_errno, + ngx_fd_info_n " \"%V\" failed", &file.name); + goto failed; + } + + if (ngx_file_size(&fi) != 48) { + ngx_conf_log_error(NGX_LOG_EMERG, cf, 0, + "\"%V\" must be 48 bytes", &file.name); + goto failed; + } + + n = ngx_read_file(&file, buf, 48, 0); + + if (n == NGX_ERROR) { + ngx_conf_log_error(NGX_LOG_CRIT, cf, ngx_errno, + ngx_read_file_n " \"%V\" failed", &file.name); + goto failed; + } + + if (n != 48) { + ngx_conf_log_error(NGX_LOG_CRIT, cf, 0, + ngx_read_file_n " \"%V\" returned only " + "%z bytes instead of 48", &file.name, n); + goto failed; + } + + key = ngx_array_push(keys); + if (key == NULL) { + goto failed; + } + + ngx_memcpy(key->name, buf, 16); + ngx_memcpy(key->aes_key, buf + 16, 16); + ngx_memcpy(key->hmac_key, buf + 32, 16); + + if (ngx_close_file(file.fd) == NGX_FILE_ERROR) { + ngx_log_error(NGX_LOG_ALERT, cf->log, ngx_errno, + ngx_close_file_n " \"%V\" failed", &file.name); + } + } + + if (SSL_CTX_set_ex_data(ssl->ctx, ngx_ssl_session_ticket_keys_index, keys) + == 0) + { + ngx_ssl_error(NGX_LOG_EMERG, ssl->log, 0, + "SSL_CTX_set_ex_data() failed"); + return NGX_ERROR; + } + + if (SSL_CTX_set_tlsext_ticket_key_cb(ssl->ctx, + ngx_ssl_session_ticket_key_callback) + == 0) + { + ngx_log_error(NGX_LOG_WARN, cf->log, 0, + "nginx was built with Session Tickets support, however, " + "now it is linked dynamically to an OpenSSL library " + "which has no tlsext support, therefore Session Tickets " + "are not available"); + } + + return NGX_OK; + +failed: + + if (ngx_close_file(file.fd) == NGX_FILE_ERROR) { + ngx_log_error(NGX_LOG_ALERT, cf->log, ngx_errno, + ngx_close_file_n " \"%V\" failed", &file.name); + } + + return NGX_ERROR; +} + + +#ifdef OPENSSL_NO_SHA256 +#define ngx_ssl_session_ticket_md EVP_sha1 +#else +#define ngx_ssl_session_ticket_md EVP_sha256 +#endif + + +static int +ngx_ssl_session_ticket_key_callback(ngx_ssl_conn_t *ssl_conn, + unsigned char *name, unsigned char *iv, EVP_CIPHER_CTX *ectx, + HMAC_CTX *hctx, int enc) +{ + SSL_CTX *ssl_ctx; + ngx_uint_t i; + ngx_array_t *keys; + ngx_ssl_session_ticket_key_t *key; +#if (NGX_DEBUG) + u_char buf[32]; + ngx_connection_t *c; +#endif + + ssl_ctx = SSL_get_SSL_CTX(ssl_conn); + + keys = SSL_CTX_get_ex_data(ssl_ctx, ngx_ssl_session_ticket_keys_index); + if (keys == NULL) { + return -1; + } + + key = keys->elts; + +#if (NGX_DEBUG) + c = ngx_ssl_get_connection(ssl_conn); +#endif + + if (enc == 1) { + /* encrypt session ticket */ + + ngx_log_debug3(NGX_LOG_DEBUG_HTTP, c->log, 0, + "ssl session ticket encrypt, key: \"%*s\" (%s session)", + ngx_hex_dump(buf, key[0].name, 16) - buf, buf, + SSL_session_reused(ssl_conn) ? "reused" : "new"); + + RAND_pseudo_bytes(iv, 16); + EVP_EncryptInit_ex(ectx, EVP_aes_128_cbc(), NULL, key[0].aes_key, iv); + HMAC_Init_ex(hctx, key[0].hmac_key, 16, + ngx_ssl_session_ticket_md(), NULL); + memcpy(name, key[0].name, 16); + + return 0; + + } else { + /* decrypt session ticket */ + + for (i = 0; i < keys->nelts; i++) { + if (ngx_memcmp(name, key[i].name, 16) == 0) { + goto found; + } + } + + ngx_log_debug2(NGX_LOG_DEBUG_HTTP, c->log, 0, + "ssl session ticket decrypt, key: \"%*s\" not found", + ngx_hex_dump(buf, name, 16) - buf, buf); + + return 0; + + found: + + ngx_log_debug3(NGX_LOG_DEBUG_HTTP, c->log, 0, + "ssl session ticket decrypt, key: \"%*s\"%s", + ngx_hex_dump(buf, key[i].name, 16) - buf, buf, + (i == 0) ? " (default)" : ""); + + HMAC_Init_ex(hctx, key[i].hmac_key, 16, + ngx_ssl_session_ticket_md(), NULL); + EVP_DecryptInit_ex(ectx, EVP_aes_128_cbc(), NULL, key[i].aes_key, iv); + + return (i == 0) ? 1 : 2 /* renew */; + } +} + +#else + +ngx_int_t +ngx_ssl_session_ticket_keys(ngx_conf_t *cf, ngx_ssl_t *ssl, ngx_array_t *paths) +{ + if (paths) { + ngx_log_error(NGX_LOG_WARN, ssl->log, 0, + "\"ssl_session_ticket_keys\" ignored, not supported"); + } + + return NGX_OK; +} + +#endif + + void ngx_ssl_cleanup_ctx(void *data) { 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 @@ -83,6 +83,16 @@ typedef struct { } ngx_ssl_session_cache_t; +#ifdef SSL_CTRL_SET_TLSEXT_TICKET_KEY_CB + +typedef struct { + u_char name[16]; + u_char aes_key[16]; + u_char hmac_key[16]; +} ngx_ssl_session_ticket_key_t; + +#endif + #define NGX_SSL_SSLv2 0x0002 #define NGX_SSL_SSLv3 0x0004 @@ -116,6 +126,8 @@ ngx_int_t ngx_ssl_dhparam(ngx_conf_t *cf ngx_int_t ngx_ssl_ecdh_curve(ngx_conf_t *cf, ngx_ssl_t *ssl, ngx_str_t *name); ngx_int_t ngx_ssl_session_cache(ngx_ssl_t *ssl, ngx_str_t *sess_ctx, ssize_t builtin_session_cache, ngx_shm_zone_t *shm_zone, time_t timeout); +ngx_int_t ngx_ssl_session_ticket_keys(ngx_conf_t *cf, ngx_ssl_t *ssl, + ngx_array_t *paths); ngx_int_t ngx_ssl_session_cache_init(ngx_shm_zone_t *shm_zone, void *data); ngx_int_t ngx_ssl_create_connection(ngx_ssl_t *ssl, ngx_connection_t *c, ngx_uint_t flags); @@ -173,6 +185,7 @@ void ngx_ssl_cleanup_ctx(void *data); extern int ngx_ssl_connection_index; 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_stapling_index; 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 @@ -153,6 +153,13 @@ static ngx_command_t ngx_http_ssl_comma 0, From mdounin at mdounin.ru Mon Oct 14 13:29:52 2013 From: mdounin at mdounin.ru (Maxim Dounin) Date: Mon, 14 Oct 2013 17:29:52 +0400 Subject: [PATCH] SSL: added support for TLS Session Tickets (RFC5077). In-Reply-To: References: <20130930142655.GD56438@mdounin.ru> <20131003151724.GI62063@mdounin.ru> <20131011142647.GQ76294@mdounin.ru> Message-ID: <20131014132952.GD2144@mdounin.ru> Hello! On Fri, Oct 11, 2013 at 04:22:07PM -0700, Piotr Sikora wrote: > Hey Maxim, > > > Wouldn't it better to move ngx_ssl_session_ticket_md defines > > to ngx_ssl_session_ticket_key_callback() implementation? > > You mean inside the function or just above it? I moved them just above it. I'm fine with either variant. > > Do we really need these #ifdef's? I don't think saving several > > bytes in ancient OpenSSL versions worth it (and the > > ngx_ssl_stapling_index doesn't have #ifdef's). > > Probably not, removed. > > While there, I moved the definitions and initialization right after > ngx_ssl_session_cache_index, so that the two session resumption > indexes are together, hopefully that's alright. Looks good. > > Wouldn't ngx_ssl_ticket_key_t be better? Up to you, but > > "ngx_ssl_session_ticket_key_t" looks a bit too long. > > It's a bit too long, yes, but I prefer to keep everything with the > same prefix, so either rename everything to "ngx_ssl_ticket_" (which I > don't like that much) or keep long names. I think it would be fine to name functions ngx_ssl_session_ticket_keys() and ngx_ssl_session_ticket_key_callback(), but use shorter names for the rest of the identifiers. Especially keeping in mind OpenSSL calls relevant call SSL_CTX_set_tlsext_ticket_key_cb() anyway. But I don't insist, up to you. > > What about something like this: > > > > ngx_log_debug3(NGX_LOG_DEBUG_HTTP, c->log, 0, > > "ssl session ticket encrypt, key: \"%*s\" (%s session)", > > ngx_hex_dump(buf, key[0].name, 16) - buf, buf, > > SSL_session_reused(ssl_conn) ? "reused" : "new"); > > > > ? > > > > (Well, actually I'm not sure we need key name logged, but it > > probably doesn't matter much.) > > That's much better, thanks. > > It's used only for the debugging, so I think it's fine to print it. Sometimes too much debugging is bad, too. But let's keep it as is for now. > > Just in case, using a shorter name "ngx_ssl_ticket_md()" would > > save us from wrapping here and in decrypt case. > > I know, I had something shorter here originally, but I've decided to > rename it, so that it would have the same prefix... But if you really > want to get rid of the wrap, maybe we could use "ngx_ssl_md()" here? > What do you think? The "ngx_ssl_md()" looks wrong for me, as it's a message digest used for session tickets, not something global for our ssl implementation. > > Shouldn't it be ngx_memcmp(), as it checks binary data now? > > Good catch, thanks! That was leftover from my previous implementation. > > > Adding "goto found" instead of "break" would allow to avoid this > > additional check. Up to you though. > > Personally, I prefer the explicit "end-of-the-loop" check, but I don't > mind either way. Changed to "goto found". Minor nit: labels should be indented to match blocks, not unindented. E.g., if (foo) { if (bar) { goto found; } found: ... } > Updated patch attached, with slightly changed commit message (better > file names in the example). > > Please note, that it doesn't have any session timeout logic, so it > should be committed after the timeout patch :) Sure. > # HG changeset patch > # User Piotr Sikora > # Date 1381532724 25200 > # Fri Oct 11 16:05:24 2013 -0700 > # Node ID 296805806a43f4b222c4cf34dd6489b37394e315 > # Parent 5483d9e77b3287b00b1104a07688bda37bc7351e > SSL: added ability to set keys used for Session Tickets (RFC5077). > > In order to support key rollover, ssl_session_ticket_key can be defined > multiple times. The first key will be used to issue and resume Session > Tickets, while the rest will be used only to resume them. > > ssl_session_ticket_key session_tickets/current.key; > ssl_session_ticket_key session_tickets/prev-1h.key; > ssl_session_ticket_key session_tickets/prev-2h.key; > > Please note that nginx supports Session Tickets even without explicit > configuration of the keys and this feature should be only used in setups > where SSL traffic is distributed across multiple nginx servers. > > Signed-off-by: Piotr Sikora [...] Committed with the followin minor tweaks: --- a/src/event/ngx_event_openssl.c +++ b/src/event/ngx_event_openssl.c @@ -2415,8 +2415,8 @@ ngx_ssl_session_ticket_key_callback(ngx_ RAND_pseudo_bytes(iv, 16); EVP_EncryptInit_ex(ectx, EVP_aes_128_cbc(), NULL, key[0].aes_key, iv); - HMAC_Init_ex(hctx, key[0].hmac_key, 16, ngx_ssl_session_ticket_md(), - NULL); + HMAC_Init_ex(hctx, key[0].hmac_key, 16, + ngx_ssl_session_ticket_md(), NULL); memcpy(name, key[0].name, 16); return 0; @@ -2436,15 +2436,15 @@ ngx_ssl_session_ticket_key_callback(ngx_ return 0; -found: + found: ngx_log_debug3(NGX_LOG_DEBUG_HTTP, c->log, 0, "ssl session ticket decrypt, key: \"%*s\"%s", ngx_hex_dump(buf, key[i].name, 16) - buf, buf, (i == 0) ? " (default)" : ""); - HMAC_Init_ex(hctx, key[i].hmac_key, 16, ngx_ssl_session_ticket_md(), - NULL); + HMAC_Init_ex(hctx, key[i].hmac_key, 16, + ngx_ssl_session_ticket_md(), NULL); EVP_DecryptInit_ex(ectx, EVP_aes_128_cbc(), NULL, key[i].aes_key, iv); return (i == 0) ? 1 : 2 /* renew */; Thanks! -- Maxim Dounin http://nginx.org/en/donation.html From aviram at adallom.com Wed Oct 16 12:28:09 2013 From: aviram at adallom.com (Aviram Cohen) Date: Wed, 16 Oct 2013 15:28:09 +0300 Subject: [PATCH] Proxy remote server SSL certificate verification In-Reply-To: <20131011003358.GL76294@mdounin.ru> References: <20130821143033.GP19334@mdounin.ru> <20130828004143.GE2748@mdounin.ru> <20130902120959.GB65634@mdounin.ru> <20130903132139.GK65634@mdounin.ru> <20131011003358.GL76294@mdounin.ru> Message-ID: Hello! I've fixed the comments and made a new version (for a newer Nginx version). I haven't removed the name verification however. OpenSSL's X509_check_host will be available in v 1.1.0, and it doesn't seem to be available soon, and name verification is significant when verifying SSL certificates. The new version is here https://gist.github.com/aviramc/7006607 and here: # HG changeset patch # User Aviram Cohen # Date 1381924204 -7200 # Node ID eb4a27153a24e4477d9074bd51ba56ce58be4177 # Parent 70c5cd3a61cb476c2afb3a61826e59c7cda0b7a7 Added remote end SSL certificate verification in the proxy module. This patch adds the following directives to the proxy module: - proxy_ssl_verify - whether or not to verify the remote end's certificate. Default is off. - proxy_ssl_verify_name - the remote end's name to verify. If no value is given, name verification is turned off. - proxy_ssl_verify_depth - how deep the ssl verification should be done. Default is 1. - proxy_ssl_trusted_certificate - the path of the certificate file that is used for verification. This must be provided when proxy_ssl_verify is on. - proxy_ssl_crl - the path a file that contains the CRLs of the hosts to which we proxy. Default is empty, and CRL verification is not done. diff -r 70c5cd3a61cb -r eb4a27153a24 src/event/ngx_event_openssl.c --- a/src/event/ngx_event_openssl.c Tue Oct 01 17:44:51 2013 +0400 +++ b/src/event/ngx_event_openssl.c Wed Oct 16 13:50:04 2013 +0200 @@ -38,6 +38,11 @@ static void ngx_ssl_expire_sessions(ngx_ static void ngx_ssl_session_rbtree_insert_value(ngx_rbtree_node_t *temp, ngx_rbtree_node_t *node, ngx_rbtree_node_t *sentinel); +static int ngx_ssl_host_wildcard_match(ASN1_STRING *pattern, + ngx_str_t *hostname); +static int ngx_ssl_host_exact_match(ASN1_STRING *pattern, + ngx_str_t *hostname); + static void *ngx_openssl_create_conf(ngx_cycle_t *cycle); static char *ngx_openssl_engine(ngx_conf_t *cf, ngx_command_t *cmd, void *conf); static void ngx_openssl_exit(ngx_cycle_t *cycle); @@ -2541,6 +2546,159 @@ ngx_ssl_get_client_verify(ngx_connection } +static int +ngx_ssl_host_wildcard_match(ASN1_STRING *pattern, + ngx_str_t *hostname) +{ + int n; + u_char *p; + u_char *wp; + + /* sanity check */ + if (!pattern + || pattern->length <= 0 + || !hostname + || !hostname->len) + { + return 0; + } + + /* trivial case */ + if (ngx_strncasecmp((u_char *) pattern->data, + hostname->data, + hostname->len) + == 0) + { + return 1; + } + + /* simple wildcard matching - only in the beginning of the string. */ + if (pattern->length > 2 + && pattern->data[0] == '*' + && pattern->data[1] == '.') + { + + wp = (u_char *) (pattern->data + 1); + + p = ngx_strlchr(hostname->data, + hostname->data + hostname->len, + '.'); + + /* + * If the pattern begings with "*." and the hostname consists of + * a top level domain, compare the pattern to the top level domain. + */ + if (p != NULL) { + n = hostname->len - (int) (p - hostname->data); + + if (n == pattern->length - 1 + && ngx_strncasecmp(wp, + p, + pattern->length - 1) + == 0) + { + return 1; + } + } + } + + return 0; +} + + +static int +ngx_ssl_host_exact_match(ASN1_STRING *pattern, + ngx_str_t *hostname) +{ + /* sanity check */ + if (!pattern + || pattern->length <= 0 + || !hostname + || !hostname->len + || pattern->length != (int) hostname->len) + { + return 0; + } + + if (ngx_strncmp((u_char *) pattern->data, + hostname->data, + hostname->len) + == 0) + { + return 1; + } + + return 0; +} + + +ngx_int_t +ngx_ssl_verify_name(X509 *cert, ngx_str_t *name) +{ + X509_NAME_ENTRY *ne; + GENERAL_NAMES *gens; + GENERAL_NAME *gen; + ASN1_STRING *cstr; + X509_NAME *sn; + int rc; + int i; + + /* based on OpenSSL's do_x509_check */ + + gens = X509_get_ext_d2i(cert, NID_subject_alt_name, NULL, NULL); + + if (gens) { + + rc = 0; + + for (i = 0; i < sk_GENERAL_NAME_num(gens); i++) { + + gen = sk_GENERAL_NAME_value(gens, i); + + /* we only check for name */ + switch (gen->type) { + + case GEN_DNS: + cstr = gen->d.dNSName; + rc = ngx_ssl_host_wildcard_match(cstr, + name); + break; + + default: + cstr = NULL; + rc = 0; + } + + if (rc) { + break; + } + + } + + GENERAL_NAMES_free(gens); + + if (rc) { + return NGX_OK; + } + } + + sn = X509_get_subject_name(cert); + i = X509_NAME_get_index_by_NID(sn, NID_commonName, -1); + while (i >= 0) { + ne = X509_NAME_get_entry(sn, i); + cstr = X509_NAME_ENTRY_get_data(ne); + + if (ngx_ssl_host_exact_match(cstr, name)) { + return NGX_OK; + } + + i = X509_NAME_get_index_by_NID(sn, NID_commonName, i); + } + + return NGX_ERROR; +} + + static void * ngx_openssl_create_conf(ngx_cycle_t *cycle) { diff -r 70c5cd3a61cb -r eb4a27153a24 src/event/ngx_event_openssl.h --- a/src/event/ngx_event_openssl.h Tue Oct 01 17:44:51 2013 +0400 +++ b/src/event/ngx_event_openssl.h Wed Oct 16 13:50:04 2013 +0200 @@ -158,6 +158,7 @@ ngx_int_t ngx_ssl_get_client_verify(ngx_ ngx_int_t ngx_ssl_handshake(ngx_connection_t *c); +ngx_int_t ngx_ssl_verify_name(X509 *cert, ngx_str_t *name); ssize_t ngx_ssl_recv(ngx_connection_t *c, u_char *buf, size_t size); ssize_t ngx_ssl_write(ngx_connection_t *c, u_char *data, size_t size); ssize_t ngx_ssl_recv_chain(ngx_connection_t *c, ngx_chain_t *cl); diff -r 70c5cd3a61cb -r eb4a27153a24 src/http/modules/ngx_http_proxy_module.c --- a/src/http/modules/ngx_http_proxy_module.c Tue Oct 01 17:44:51 2013 +0400 +++ b/src/http/modules/ngx_http_proxy_module.c Wed Oct 16 13:50:04 2013 +0200 @@ -81,6 +81,10 @@ typedef struct { ngx_uint_t ssl; ngx_uint_t ssl_protocols; ngx_str_t ssl_ciphers; + ngx_uint_t ssl_verify_depth; + ngx_str_t ssl_trusted_certificate; + ngx_str_t ssl_crl; + ngx_http_complex_value_t ssl_verify_name; #endif } ngx_http_proxy_loc_conf_t; @@ -168,6 +172,8 @@ static ngx_int_t ngx_http_proxy_rewrite_ #if (NGX_HTTP_SSL) static ngx_int_t ngx_http_proxy_set_ssl(ngx_conf_t *cf, ngx_http_proxy_loc_conf_t *plcf); +static char * ngx_http_proxy_verify_name(ngx_conf_t *cf, ngx_command_t *cmd, + void *conf); #endif static void ngx_http_proxy_set_vars(ngx_url_t *u, ngx_http_proxy_vars_t *v); @@ -546,6 +552,41 @@ static ngx_command_t ngx_http_proxy_com offsetof(ngx_http_proxy_loc_conf_t, ssl_ciphers), NULL }, + { ngx_string("proxy_ssl_verify"), + NGX_HTTP_MAIN_CONF|NGX_HTTP_SRV_CONF|NGX_HTTP_LOC_CONF|NGX_CONF_TAKE1, + ngx_conf_set_flag_slot, + NGX_HTTP_LOC_CONF_OFFSET, + offsetof(ngx_http_proxy_loc_conf_t, upstream.ssl_verify), + NULL }, + + { ngx_string("proxy_ssl_verify_name"), + NGX_HTTP_MAIN_CONF|NGX_HTTP_SRV_CONF|NGX_HTTP_LOC_CONF|NGX_CONF_TAKE1, + ngx_http_proxy_verify_name, + NGX_HTTP_LOC_CONF_OFFSET, + 0, + NULL }, + + { ngx_string("proxy_ssl_verify_depth"), + NGX_HTTP_MAIN_CONF|NGX_HTTP_SRV_CONF|NGX_HTTP_LOC_CONF|NGX_CONF_TAKE1, + ngx_conf_set_num_slot, + NGX_HTTP_LOC_CONF_OFFSET, + offsetof(ngx_http_proxy_loc_conf_t, ssl_verify_depth), + NULL }, + + { ngx_string("proxy_ssl_trusted_certificate"), + NGX_HTTP_MAIN_CONF|NGX_HTTP_SRV_CONF|NGX_HTTP_LOC_CONF|NGX_CONF_TAKE1, + ngx_conf_set_str_slot, + NGX_HTTP_LOC_CONF_OFFSET, + offsetof(ngx_http_proxy_loc_conf_t, ssl_trusted_certificate), + NULL }, + + { ngx_string("proxy_ssl_crl"), + NGX_HTTP_MAIN_CONF|NGX_HTTP_SRV_CONF|NGX_HTTP_LOC_CONF|NGX_CONF_TAKE1, + ngx_conf_set_str_slot, + NGX_HTTP_LOC_CONF_OFFSET, + offsetof(ngx_http_proxy_loc_conf_t, ssl_crl), + NULL }, + #endif ngx_null_command @@ -698,6 +739,20 @@ ngx_http_proxy_handler(ngx_http_request_ } } +#if (NGX_HTTP_SSL) + + if (plcf->ssl + && plcf->ssl_verify_name.value.data + && ngx_http_complex_value(r, + &plcf->ssl_verify_name, + &u->ssl_verify_name) + != NGX_OK) + { + return NGX_ERROR; + } + +#endif + u->output.tag = (ngx_buf_tag_t) &ngx_http_proxy_module; u->conf = &plcf->upstream; @@ -2460,8 +2515,11 @@ ngx_http_proxy_create_loc_conf(ngx_conf_ conf->upstream.pass_headers = NGX_CONF_UNSET_PTR; conf->upstream.intercept_errors = NGX_CONF_UNSET; + #if (NGX_HTTP_SSL) conf->upstream.ssl_session_reuse = NGX_CONF_UNSET; + conf->upstream.ssl_verify = NGX_CONF_UNSET; + conf->ssl_verify_depth = NGX_CONF_UNSET_UINT; #endif /* "proxy_cyclic_temp_file" is disabled */ @@ -2740,10 +2798,45 @@ ngx_http_proxy_merge_loc_conf(ngx_conf_t ngx_conf_merge_str_value(conf->ssl_ciphers, prev->ssl_ciphers, "DEFAULT"); + ngx_conf_merge_value(conf->upstream.ssl_verify, + prev->upstream.ssl_verify, 0); + ngx_conf_merge_uint_value(conf->ssl_verify_depth, + prev->ssl_verify_depth, 1); + ngx_conf_merge_str_value(conf->ssl_trusted_certificate, + prev->ssl_trusted_certificate, ""); + ngx_conf_merge_str_value(conf->ssl_crl, + prev->ssl_crl, ""); if (conf->ssl && ngx_http_proxy_set_ssl(cf, conf) != NGX_OK) { return NGX_CONF_ERROR; } + + if (conf->ssl_verify_name.value.data == NULL) { + conf->ssl_verify_name = prev->ssl_verify_name; + } + + if (conf->ssl && conf->upstream.ssl && conf->upstream.ssl_verify) { + if (conf->ssl_trusted_certificate.len == 0) { + ngx_conf_log_error(NGX_LOG_EMERG, cf, 0, + "no \"proxy_ssl_trusted_certificate\" is " + " defined for the \"proxy_ssl_verify\" " + "directive"); + + return NGX_CONF_ERROR; + } + + if (ngx_ssl_trusted_certificate(cf, conf->upstream.ssl, + &conf->ssl_trusted_certificate, + conf->ssl_verify_depth) + != NGX_OK) + { + return NGX_CONF_ERROR; + } + + if (ngx_ssl_crl(cf, conf->upstream.ssl, &conf->ssl_crl) != NGX_OK) { + return NGX_CONF_ERROR; + } + } #endif ngx_conf_merge_value(conf->redirect, prev->redirect, 1); @@ -3811,6 +3904,35 @@ ngx_http_proxy_set_ssl(ngx_conf_t *cf, n return NGX_OK; } + +char * +ngx_http_proxy_verify_name(ngx_conf_t *cf, ngx_command_t *cmd, + void *conf) +{ + ngx_http_proxy_loc_conf_t *plcf = conf; + + ngx_str_t *value; + ngx_http_compile_complex_value_t ccv; + + value = cf->args->elts; + + if (plcf->ssl_verify_name.value.data) { + return "is duplicate"; + } + + ngx_memzero(&ccv, sizeof(ngx_http_compile_complex_value_t)); + + ccv.cf = cf; + ccv.value = &value[1]; + ccv.complex_value = &plcf->ssl_verify_name; + + if (ngx_http_compile_complex_value(&ccv) != NGX_OK) { + return NGX_CONF_ERROR; + } + + return NGX_CONF_OK; +} + #endif diff -r 70c5cd3a61cb -r eb4a27153a24 src/http/ngx_http_upstream.c --- a/src/http/ngx_http_upstream.c Tue Oct 01 17:44:51 2013 +0400 +++ b/src/http/ngx_http_upstream.c Wed Oct 16 13:50:04 2013 +0200 @@ -1372,6 +1372,8 @@ ngx_http_upstream_ssl_init_connection(ng static void ngx_http_upstream_ssl_handshake(ngx_connection_t *c) { + X509 *cert; + long rc; ngx_http_request_t *r; ngx_http_upstream_t *u; @@ -1379,7 +1381,37 @@ ngx_http_upstream_ssl_handshake(ngx_conn u = r->upstream; if (c->ssl->handshaked) { - + if (u->conf->ssl_verify) { + + rc = SSL_get_verify_result(c->ssl->connection); + + if (rc != X509_V_OK) { + ngx_log_error(NGX_LOG_ERR, c->log, 0, + "upstream SSL certificate verify error: (%l:%s)", + rc, X509_verify_cert_error_string(rc)); + goto fail; + } + + cert = SSL_get_peer_certificate(c->ssl->connection); + + if (cert == NULL) { + ngx_log_error(NGX_LOG_ERR, c->log, 0, + "upstream sent no SSL certificate"); + goto fail; + } + + if (u->ssl_verify_name.data + && ngx_ssl_verify_name(cert, &u->ssl_verify_name) != NGX_OK) + { + X509_free(cert); + ngx_log_error(NGX_LOG_ERR, c->log, 0, + "upstream SSL certificate name validation error"); + goto fail; + } + + X509_free(cert); + } + if (u->conf->ssl_session_reuse) { u->peer.save_session(&u->peer, u->peer.data); } @@ -1395,6 +1427,8 @@ ngx_http_upstream_ssl_handshake(ngx_conn return; } +fail: + c = r->connection; ngx_http_upstream_next(r, u, NGX_HTTP_UPSTREAM_FT_ERROR); diff -r 70c5cd3a61cb -r eb4a27153a24 src/http/ngx_http_upstream.h --- a/src/http/ngx_http_upstream.h Tue Oct 01 17:44:51 2013 +0400 +++ b/src/http/ngx_http_upstream.h Wed Oct 16 13:50:04 2013 +0200 @@ -193,6 +193,7 @@ typedef struct { #if (NGX_HTTP_SSL) ngx_ssl_t *ssl; ngx_flag_t ssl_session_reuse; + ngx_flag_t ssl_verify; #endif ngx_str_t module; @@ -299,6 +300,10 @@ struct ngx_http_upstream_s { ngx_int_t (*input_filter)(void *data, ssize_t bytes); void *input_filter_ctx; +#if (NGX_HTTP_SSL) + ngx_str_t ssl_verify_name; +#endif + #if (NGX_HTTP_CACHE) ngx_int_t (*create_key)(ngx_http_request_t *r); #endif On Fri, Oct 11, 2013 at 3:33 AM, Maxim Dounin wrote: > Hello! > > On Wed, Oct 09, 2013 at 07:32:52PM +0300, Aviram Cohen wrote: > >> Hello!, >> >> I've made the necessary fixes. A few comments about those: >> - Name validation >> - Unlike Apache, in this patch, the configuration must contain the name >> to verify. In most cases, this should be set to the $host variable (and >> this is the default value). I've encountered certificates that validate >> names differently (some of Microsoft's certificates), and this is useful >> for such cases. > > Use of $host is certainly wrong. By default nginx uses > $proxy_host as a name of the upstream server, and having different > default for the verification is bad idea. > >> - Many certificates use wildcards in the names on which they sign (i.e. >> "*.google.com"). Though wildcards can appear anywhere according to the >> standard, I've added support only for a wildcard in the beginning of the >> name. This is the normal case, and it is easier to implement. This is >> is how Apache implements the wildcard name validation as well. Note also >> that the function X509_check_host will be introduced in future versions >> of OpenSSL that will provide the entire feature. > > It may be a good idea to actually use X509_check_host() if it's > available. And may be even refuse to do a validation if it's not, > instead of reimplementing the wheel. > >> - CRL verification - I've added CRL validation, but note that OpenSSL doesn't >> download CRL files from the servers, so the CRL file that is used should >> contain the revocation lists of all the proxied hosts. This also >> means that it >> is out of Nginx's scope to update this file. Apache does the same thing. > > This is in line with how ssl_crl works, everything else probably > doesn't matter. > >> - The patch was made for v1.4.1. > > This is a bit strange - there is no chance the patch will be > committed over 1.4.1, and there are conflicting changes in recent > versions. > > [...] > >> # HG changeset patch >> # User Aviram Cohen >> # Date 1381334949 -7200 >> # Branch stable-1.4 >> # Node ID 9a6e20bf72f8cf4d17653e4fdfcbac48c4de03aa >> # Parent 0702de638a4c51123d7b97801d393e8e25eb48de >> Added remote end SSL certificate verification in the proxy module. >> >> This patch adds the following directives to the proxy module: >> - proxy_ssl_verify - whether or not to verify the remote end's >> certificate. Default is off. >> - proxy_ssl_verify_name - the remote end's name to verify. Default is >> $host, can be set to "" in order to avoid name verification. > > Not sure if "" to avoid name verification is a good value. > >> - proxy_ssl_verify_depth - how deep the ssl verification should be >> done. Default is 1. >> - proxy_ssl_trusted_certificate - the path of the certificate file >> that is used for verification. This must be provided when >> proxy_ssl_verify is on. >> - proxy_ssl_crl - the path a file that contains the CRLs of the hosts >> to which we proxy. Default is empty, and CRL verification is not done. > > Given the number of changes, it probably should be more than one > patch. > >> >> diff -r 0702de638a4c -r 9a6e20bf72f8 src/event/ngx_event_openssl.c >> --- a/src/event/ngx_event_openssl.c Mon May 06 14:20:27 2013 +0400 >> +++ b/src/event/ngx_event_openssl.c Wed Oct 09 18:09:09 2013 +0200 >> @@ -42,6 +42,11 @@ >> static char *ngx_openssl_engine(ngx_conf_t *cf, ngx_command_t *cmd, >> void *conf); >> static void ngx_openssl_exit(ngx_cycle_t *cycle); >> >> +static int ngx_openssl_host_wildcard_match(ASN1_STRING *match_pattern, >> + ngx_str_t *hostname); >> +static int ngx_openssl_host_exact_match(ASN1_STRING *match_pattern, >> + ngx_str_t *hostname); >> + >> >> static ngx_command_t ngx_openssl_commands[] = { >> >> @@ -2562,3 +2567,163 @@ > > Please add > > [diff] > showfunc=1 > > to your ~/.hgrc. > >> EVP_cleanup(); >> ENGINE_cleanup(); >> } >> + >> + >> +static int >> +ngx_openssl_host_wildcard_match(ASN1_STRING *match_pattern, >> + ngx_str_t *hostname) >> +{ > > Nipicking: functions seems to be badly placed. Configuration > parsing and init/exit handlers are intentionally at the end. > > They are also badly named, as they aren't OpenSSL-specific, and > should be ngx_ssl_* instead. > >> + int host_top_domain_length; >> + u_char *host_top_domain; >> + u_char *wildcard_pattern; >> + >> + /* sanity check */ >> + if (!match_pattern >> + || match_pattern->length <= 0 >> + || !hostname >> + || !hostname->len) >> + { >> + return 0; >> + } >> + >> + /* trivial case */ >> + if (ngx_strncasecmp((u_char *) match_pattern->data, >> + hostname->data, >> + hostname->len) >> + == 0) >> + { >> + return 1; >> + } >> + >> + /* simple wildcard matching - only in the beginning of the string. */ >> + if (match_pattern->length > 2 >> + && match_pattern->data[0] == '*' >> + && match_pattern->data[1] == '.') >> + { >> + >> + wildcard_pattern = (u_char *) (match_pattern->data + 1); >> + >> + host_top_domain = ngx_strlchr(hostname->data, >> + hostname->data + hostname->len, >> + '.'); >> + > > Long variable names used seems to result in hardly readable code. > > [...] > >> +int >> +ngx_openssl_verify_name(X509 *cert, ngx_str_t *expected_name) >> +{ >> + GENERAL_NAMES *gens = NULL; >> + GENERAL_NAME *gen; >> + X509_NAME *name = NULL; >> + ASN1_STRING *cstr = NULL; >> + X509_NAME_ENTRY *ne; >> + int i; >> + int rc = 0; > > See elsewhere about variables sorting. And please don't use > local variables initialization mixed with declaration. Well, > initialization seems to be unneeded here at all. > >> + >> + /* based on OpenSSL's do_x509_check */ >> + >> + gens = X509_get_ext_d2i(cert, NID_subject_alt_name, NULL, NULL); >> + >> + if (gens) { >> + >> + rc = 0; >> + >> + for (i = 0; i < sk_GENERAL_NAME_num(gens); i++) { >> + >> + gen = sk_GENERAL_NAME_value(gens, i); >> + >> + /* we only check for either name or IP */ >> + switch (gen->type) { >> + >> + case GEN_DNS: >> + cstr = gen->d.dNSName; >> + rc = ngx_openssl_host_wildcard_match(cstr, >> + expected_name); >> + break; >> + >> + case GEN_IPADD: >> + cstr = gen->d.iPAddress; >> + rc = ngx_openssl_host_exact_match(cstr, >> + expected_name); > > Why IP address matching? It doesn't looks like something present > in other implementations, nor something used in real certificates. > > It also doesn't looks like something correctly implemented, as > d.iPAddress is expected to contain a binary address. > > [...] > >> --- a/src/http/modules/ngx_http_proxy_module.c Mon May 06 14:20:27 2013 +0400 >> +++ b/src/http/modules/ngx_http_proxy_module.c Wed Oct 09 18:09:09 2013 +0200 >> @@ -74,6 +74,15 @@ >> >> ngx_uint_t http_version; >> >> +#if (NGX_HTTP_SSL) >> + ngx_uint_t ssl_verify_depth; >> + ngx_str_t ssl_trusted_certificate; >> + ngx_str_t ssl_crl; >> + ngx_str_t ssl_verify_name_source; >> + ngx_array_t *ssl_verify_name_lengths; >> + ngx_array_t *ssl_verify_name_values; > > Using a complex value should be simplier. > > [...] > >> + n = ngx_http_script_variables_count(&conf->ssl_verify_name_source); >> + >> + if (n) { >> + ngx_memzero(&sc, sizeof(ngx_http_script_compile_t)); >> + >> + sc.cf = cf; >> + sc.source = &conf->ssl_verify_name_source; >> + sc.variables = n; >> + sc.lengths = &conf->ssl_verify_name_lengths; >> + sc.values = &conf->ssl_verify_name_values; >> + sc.complete_lengths = 1; >> + sc.complete_values = 1; >> + >> + if (ngx_http_script_compile(&sc) != NGX_OK) { >> + return NGX_CONF_ERROR; >> + } >> + > > Doing a compilation on every merge isn't a good idea. > >> + } >> + } >> + >> #endif >> >> ngx_conf_merge_value(conf->redirect, prev->redirect, 1); >> diff -r 0702de638a4c -r 9a6e20bf72f8 src/http/ngx_http_upstream.c >> --- a/src/http/ngx_http_upstream.c Mon May 06 14:20:27 2013 +0400 >> +++ b/src/http/ngx_http_upstream.c Wed Oct 09 18:09:09 2013 +0200 >> @@ -1319,12 +1319,43 @@ >> { >> ngx_http_request_t *r; >> ngx_http_upstream_t *u; >> - >> + X509 *cert; >> + long rc; >> + > > Style nitpicking: > > 1. Empty lines with "-" and "+" suggests there is something wrong > with newlines. > > 2. Variables order is wrong, shortest types first. > >> r = c->data; >> u = r->upstream; >> >> if (c->ssl->handshaked) { >> - >> + if (u->conf->ssl_verify) { >> + rc = SSL_get_verify_result(c->ssl->connection); >> + if (rc != X509_V_OK) { > > Style nitpicking: I would suggest to preserve empty line after "if > (c->ssl->handshaked)", and add one between SSL_get_verify_result() > and "if (rc != X509_V_OK)". > >> + ngx_log_error(NGX_LOG_ERR, c->log, 0, >> + "upstream SSL certificate verify error: (%l:%s)", >> + rc, X509_verify_cert_error_string(rc)); >> + goto fail; >> + } >> + >> + cert = SSL_get_peer_certificate(c->ssl->connection); >> + >> + if (cert == NULL) { >> + ngx_log_error(NGX_LOG_ERR, c->log, 0, >> + "upstream sent no SSL certificate"); >> + goto fail; >> + } >> + >> + if (u->ssl_verify_name.len >> + && ngx_openssl_verify_name(cert, &u->ssl_verify_name) >> + == 0) > > Style nitpicking: "==" should be aligned with a function which > return value it checks, > > if (u->ssl_verify_name.len > && ngx_openssl_verify_name(cert, &u->ssl_verify_name) > == 0) > { > > And the ngx_openssl_verify_name() interface probably needs to be > changed to be more like other interfaces in nginx - i.e., return > NGX_OK on success. With already suggested rename, and a 80 chars > limit which isn't actually reached even with long name, this gives us > something like this: > > if (u->ssl_verify_name.len > && ngx_ssl_verify_name(cert, &u->ssl_verify_name) != NGX_OK) > { > > [...] > > -- > Maxim Dounin > http://nginx.org/en/donation.html > > _______________________________________________ > nginx-devel mailing list > nginx-devel at nginx.org > http://mailman.nginx.org/mailman/listinfo/nginx-devel -- Aviram Cohen, R&D Adallom, 1 Ha'Barzel st., Tel-Aviv, Israel Mobile: +972 (54) 5833508 aviram at adallom.com, www.adallom.com From rob.stradling at comodo.com Thu Oct 17 14:09:42 2013 From: rob.stradling at comodo.com (Rob Stradling) Date: Thu, 17 Oct 2013 15:09:42 +0100 Subject: [PATCH] RSA+DSA+ECC bundles In-Reply-To: <006701ce048e$d1b9e090$752da1b0$@slo-tech.com> References: <006701ce048e$d1b9e090$752da1b0$@slo-tech.com> Message-ID: <525FEFA6.9040004@comodo.com> On 06/02/13 17:24, Primoz Bratanic wrote: > Hi, > > Apache supports specifying multiple certificates (different types) for same > host in line with OpenSSL support (RSA, DSA, ECC). This allows using ECC key > exchange methods with clients that support it and it's backwards compatible. > I wonder how much work would it be to add support for this to nginx. Is it > just allowing specifying 2-3 certificates (and checking they have different > key type) + adding support for returning proper key chain or are the any > other obvious roadblocks (that are not obvious to me). Here's a first stab at a patch. I hope this is a useful starting point for getting this feature added to Nginx. To specify an RSA cert plus an ECC cert, use... ssl_certificate my_rsa.crt my_ecc.crt; ssl_certificate_key my_rsa.key my_ecc.key; ssl_prefer_server_ciphers on; Also, configure ssl_ciphers to prefer at least 1 ECDSA cipher and permit at least 1 RSA cipher. I think DSA certs should work too, but I've not tested this. Issues I'm aware of with this patch: - It doesn't check that each of the certs has a different key type (but perhaps it should). If you specify multiple certs with the same algorithm, all but the last one will be ignored. - The certs and keys need to be specified in the correct order. If you specify "my_rsa.crt my_ecc.crt" and "my_ecc.key my_rsa.key", Nginx will start but it won't be able to complete any SSL handshakes. This could be improved. - It doesn't add the new feature to mail_ssl_module. Perhaps it should. - The changes I made to ngx_conf_set_str_array_slot() work for me, but do they break anything? - An RSA cert and an ECC cert might well be issued by different CAs. On Apache httpd, you have to use SSLCACertificatePath to persuade OpenSSL to send different Intermediate certs for each one. Nginx doesn't currently have an equivalent directive, and Maxim has previously said it's unlikely to be added [1]. I haven't researched this properly yet, but I think it might be possible to do "certificate path" in memory (i.e. without syscalls and disk access on each certificate check) using the OpenSSL X509_LOOKUP API. - I expect Maxim will have other comments. :-) [1] http://forum.nginx.org/read.php?2,229129,229151 -- Rob Stradling Senior Research & Development Scientist COMODO - Creating Trust Online -------------- next part -------------- A non-text attachment was scrubbed... Name: nginx_multiple_certs.patch Type: text/x-patch Size: 11873 bytes Desc: not available URL: From mdounin at mdounin.ru Thu Oct 17 15:18:00 2013 From: mdounin at mdounin.ru (Maxim Dounin) Date: Thu, 17 Oct 2013 19:18:00 +0400 Subject: [PATCH] RSA+DSA+ECC bundles In-Reply-To: <525FEFA6.9040004@comodo.com> References: <006701ce048e$d1b9e090$752da1b0$@slo-tech.com> <525FEFA6.9040004@comodo.com> Message-ID: <20131017151800.GI2144@mdounin.ru> Hello! On Thu, Oct 17, 2013 at 03:09:42PM +0100, Rob Stradling wrote: > On 06/02/13 17:24, Primoz Bratanic wrote: > >Hi, > > > >Apache supports specifying multiple certificates (different types) for same > >host in line with OpenSSL support (RSA, DSA, ECC). This allows using ECC key > >exchange methods with clients that support it and it's backwards compatible. > >I wonder how much work would it be to add support for this to nginx. Is it > >just allowing specifying 2-3 certificates (and checking they have different > >key type) + adding support for returning proper key chain or are the any > >other obvious roadblocks (that are not obvious to me). > > Here's a first stab at a patch. I hope this is a useful starting > point for getting this feature added to Nginx. > > To specify an RSA cert plus an ECC cert, use... > ssl_certificate my_rsa.crt my_ecc.crt; > ssl_certificate_key my_rsa.key my_ecc.key; > ssl_prefer_server_ciphers on; > Also, configure ssl_ciphers to prefer at least 1 ECDSA cipher and > permit at least 1 RSA cipher. > > I think DSA certs should work too, but I've not tested this. > > > Issues I'm aware of with this patch: > > - It doesn't check that each of the certs has a different key type > (but perhaps it should). If you specify multiple certs with the > same algorithm, all but the last one will be ignored. Bad, but we could live with it if there will be no better way to do things. > - The certs and keys need to be specified in the correct order. > If you specify "my_rsa.crt my_ecc.crt" and "my_ecc.key my_rsa.key", > Nginx will start but it won't be able to complete any SSL > handshakes. This could be improved. This is certainly not something acceptable. There should be a better way to specify certs and keys. > - It doesn't add the new feature to mail_ssl_module. Perhaps it should. This could wait. > - The changes I made to ngx_conf_set_str_array_slot() work for me, > but do they break anything? It doesn't look like changes we want. The ngx_conf_set_str_array_slot() function is intended to handle arrays like this: example_array_directive value1; example_array_directive value2; I would rather see ssl_certificates to be used this way, something like: ssl_certificate rsa.crt; ssl_certificate_key rsa.key; ssl_certificate ecc.crt; ssl_certificate_key ecc.key; > - An RSA cert and an ECC cert might well be issued by different > CAs. On Apache httpd, you have to use SSLCACertificatePath to > persuade OpenSSL to send different Intermediate certs for each one. > Nginx doesn't currently have an equivalent directive, and Maxim has > previously said it's unlikely to be added [1]. > I haven't researched this properly yet, but I think it might be > possible to do "certificate path" in memory (i.e. without syscalls > and disk access on each certificate check) using the OpenSSL > X509_LOOKUP API. AFAIR, OpenSSL only able to store one certificate chain per SSL_CTX, which is the root cause of the problem. > - I expect Maxim will have other comments. :-) One thing which instantly comes in mind is SSL Stapling related issues. -- Maxim Dounin http://nginx.org/en/donation.html From witekfl at gazeta.pl Thu Oct 17 17:27:40 2013 From: witekfl at gazeta.pl ( Witold Filipczyk) Date: Thu, 17 Oct 2013 19:27:40 +0200 Subject: The dollar sign in the sub_filter Message-ID: I tried to add a jquery sample code in the sub_filter. (nginx-1.4.3), but I cannot. sub_filter $(document) References: <006701ce048e$d1b9e090$752da1b0$@slo-tech.com> <525FEFA6.9040004@comodo.com> <20131017151800.GI2144@mdounin.ru> Message-ID: Hey, > I would rather see ssl_certificates to be used this way, something > like: > > ssl_certificate rsa.crt; > ssl_certificate_key rsa.key; > > ssl_certificate ecc.crt; > ssl_certificate_key ecc.key; Yeah, I'm in favor of that syntax as well. > AFAIR, OpenSSL only able to store one certificate chain per > SSL_CTX, which is the root cause of the problem. That's solved in OpenSSL-1.0.2 (unreleased). For now, the one thing we could do is to let OpenSSL build certificate chains from the trusted certificates store... In order to do that, all we need to do is to load only the first certificate in the file (i.e. don't load intermediate certificates) in case there are multiple certificates defined. This way, OpenSSL will try to build the certificate chain automatically (unfortunately, it will do that on the fly for each connection, so it's a noticeable overhead). Optimized version of that could compare intermediates from all the files and only do that in case they differ. Best regards, Piotr Sikora From ashuven63 at gmail.com Fri Oct 18 06:50:58 2013 From: ashuven63 at gmail.com (Ashwini Venkatesh) Date: Fri, 18 Oct 2013 12:20:58 +0530 Subject: SPDY server push` Message-ID: Hello, I am working on implementing server push for SPDY. Can anyone guide on how to create a server initiated stream ? -- Regards, Ashwini Venkatesh -------------- next part -------------- An HTML attachment was scrubbed... URL: From francis at daoine.org Fri Oct 18 08:17:20 2013 From: francis at daoine.org (Francis Daly) Date: Fri, 18 Oct 2013 09:17:20 +0100 Subject: The dollar sign in the sub_filter In-Reply-To: References: Message-ID: <20131018081720.GJ19345@craic.sysops.org> > From: " Witold Filipczyk" > Message-ID: > I tried to add a jquery sample code in the sub_filter. (nginx-1.4.3), but > I cannot. > > sub_filter src="text/javascript">$(document) > With \$ also fails. > Is it a bug? http://forum.nginx.org/read.php?2,218536,218559 Unless there's a more recent note with a different workaround. f -- Francis Daly francis at daoine.org From mdounin at mdounin.ru Fri Oct 18 14:16:03 2013 From: mdounin at mdounin.ru (Maxim Dounin) Date: Fri, 18 Oct 2013 14:16:03 +0000 Subject: [nginx] Style. Message-ID: details: http://hg.nginx.org/nginx/rev/4bfa982dbf0e branches: changeset: 5426:4bfa982dbf0e user: Maxim Dounin date: Fri Oct 18 18:13:35 2013 +0400 description: Style. diffstat: src/http/ngx_http_script.c | 2 +- 1 files changed, 1 insertions(+), 1 deletions(-) diffs (12 lines): diff --git a/src/http/ngx_http_script.c b/src/http/ngx_http_script.c --- a/src/http/ngx_http_script.c +++ b/src/http/ngx_http_script.c @@ -1394,7 +1394,7 @@ ngx_http_script_if_code(ngx_http_script_ e->sp--; - if (e->sp->len && (e->sp->len !=1 || e->sp->data[0] != '0')) { + if (e->sp->len && (e->sp->len != 1 || e->sp->data[0] != '0')) { if (code->loc_conf) { e->request->loc_conf = code->loc_conf; ngx_http_update_location_config(e->request); From mdounin at mdounin.ru Fri Oct 18 14:16:04 2013 From: mdounin at mdounin.ru (Maxim Dounin) Date: Fri, 18 Oct 2013 14:16:04 +0000 Subject: [nginx] Headers filter: empty Cache-Control is no longer added. Message-ID: details: http://hg.nginx.org/nginx/rev/7ed23dcfea3d branches: changeset: 5427:7ed23dcfea3d user: Maxim Dounin date: Fri Oct 18 18:13:44 2013 +0400 description: Headers filter: empty Cache-Control is no longer added. Much like with other headers, "add_header Cache-Control $value;" no longer results in anything added to response headers if $value evaluates to an empty string. diffstat: src/http/modules/ngx_http_headers_filter_module.c | 4 ++++ 1 files changed, 4 insertions(+), 0 deletions(-) diffs (14 lines): diff --git a/src/http/modules/ngx_http_headers_filter_module.c b/src/http/modules/ngx_http_headers_filter_module.c --- a/src/http/modules/ngx_http_headers_filter_module.c +++ b/src/http/modules/ngx_http_headers_filter_module.c @@ -339,6 +339,10 @@ ngx_http_add_cache_control(ngx_http_requ { ngx_table_elt_t *cc, **ccp; + if (value->len == 0) { + return NGX_OK; + } + ccp = r->headers_out.cache_control.elts; if (ccp == NULL) { From mdounin at mdounin.ru Fri Oct 18 14:16:05 2013 From: mdounin at mdounin.ru (Maxim Dounin) Date: Fri, 18 Oct 2013 14:16:05 +0000 Subject: [nginx] Fixed "satisfy any" if 403 is returned after 401 (ticket... Message-ID: details: http://hg.nginx.org/nginx/rev/fcecb9c6a057 branches: changeset: 5428:fcecb9c6a057 user: Maxim Dounin date: Fri Oct 18 18:13:49 2013 +0400 description: Fixed "satisfy any" if 403 is returned after 401 (ticket #285). The 403 (Forbidden) should not overwrite 401 (Unauthorized) as the latter should be returned with the WWW-Authenticate header to request authentication by a client. The problem could be triggered with 3rd party modules and the "deny" directive, or with auth_basic and auth_request which returns 403 (in 1.5.4+). Patch by Jan Marc Hoffmann. diffstat: src/http/ngx_http_core_module.c | 4 +++- 1 files changed, 3 insertions(+), 1 deletions(-) diffs (14 lines): diff --git a/src/http/ngx_http_core_module.c b/src/http/ngx_http_core_module.c --- a/src/http/ngx_http_core_module.c +++ b/src/http/ngx_http_core_module.c @@ -1144,7 +1144,9 @@ ngx_http_core_access_phase(ngx_http_requ } if (rc == NGX_HTTP_FORBIDDEN || rc == NGX_HTTP_UNAUTHORIZED) { - r->access_code = rc; + if (r->access_code != NGX_HTTP_UNAUTHORIZED) { + r->access_code = rc; + } r->phase_handler++; return NGX_AGAIN; From shield1182 at gmail.com Fri Oct 18 18:01:14 2013 From: shield1182 at gmail.com (Agent Coulson) Date: Fri, 18 Oct 2013 18:01:14 +0000 Subject: SSL_read error on multiple simultaneous upstream SSL downloads Message-ID: I am able to reproduce the following error when I have nginx configured with an upstream https connection. I have tweaked various settings all to no avail (proxy_buffer_size, proxy_buffers, proxy_ssl_session_reuse). 2013/10/18 17:17:31 [debug] 15644#0: *39 SSL_read: -1, SSL_pending: 16384 2013/10/18 17:17:31 [debug] 15644#0: *39 SSL_get_error: 1 2013/10/18 17:17:31 [error] 15644#0: *39 SSL_read() failed (SSL: error:1408F119:SSL routines:SSL3_GET_RECORD:decryption failed or bad record mac) while sending to client, client: 127.0.0.1, server: -, request: "GET /test-1 HTTP/1.1", upstream: "https://x.x.x.x:443/test-1", host: "localhost:1182" I've applied the following patch to log the SSL_pending bytes after an SSL_read. --- dist/nginx-1.4.3/src/event/ngx_event_openssl.c 2013-10-08 12:07:14.000000000 +0000 +++ new/nginx-1.4.3/src/event/ngx_event_openssl.c 2013-10-18 17:37:15.059940303 +0000 @@ -952,7 +952,9 @@ ngx_ssl_recv(ngx_connection_t *c, u_char n = SSL_read(c->ssl->connection, buf, size); - ngx_log_debug1(NGX_LOG_DEBUG_EVENT, c->log, 0, "SSL_read: %d", n); + ngx_log_debug2(NGX_LOG_DEBUG_EVENT, c->log, 0, + "SSL_read: %d, SSL_pending: %d", + n, SSL_pending(c->ssl->connection)); if (n > 0) { bytes += n; I've seen a bug report on this too (http://trac.nginx.org/nginx/ticket/215), so thought i would send this here to see if anyone else is actively working on the issue. Here are my configure settings: ./configure --prefix=/var/nginx --with-debug --with-http_ssl_module --without-http_auth_basic_module --without-http_autoindex_module --without-http_browser_module --without-http-cache --without-http_charset_module --without-http_empty_gif_module --without-http_fastcgi_module --without-http_geo_module --without-http_gzip_module --without-http_limit_conn_module --without-http_map_module --without-http_memcached_module --without-http_referer_module --without-http_rewrite_module --without-http_scgi_module --without-http_split_clients_module --without-http_ssi_module --without-http_upstream_ip_hash_module --without-http_userid_module --without-http_uwsgi_module --without-mail_imap_module --without-mail_pop3_module --without-mail_smtp_module Here is my configuration: ### Begin nginx.conf ### worker_processes 1; error_log logs/error.log debug; pid logs/nginx.pid; events { worker_connections 1024; } http { include mime.types; default_type application/octet-stream; access_log logs/access.log; keepalive_timeout 60; upstream http { server upstream.srv:443; keepalive 512; } server { listen 1182 default_server; server_name -; ssl_protocols SSLv3 TLSv1; ssl_ciphers RC4:HIGH:!aNULL:!MD5; ssl_prefer_server_ciphers on; location / { proxy_pass https://http; proxy_redirect off; proxy_read_timeout 10s; proxy_connect_timeout 6s; proxy_buffering off; proxy_buffer_size 64k; proxy_buffers 6 16k; proxy_busy_buffers_size 80k; proxy_pass_header Server; proxy_pass_header Date; proxy_pass_header X-Pad; proxy_set_header Connection "Keep-Alive"; proxy_set_header Host "upstream.srv"; } } } ### End nginx.conf ### -------------- next part -------------- An HTML attachment was scrubbed... URL: From mdounin at mdounin.ru Fri Oct 18 19:06:05 2013 From: mdounin at mdounin.ru (Maxim Dounin) Date: Fri, 18 Oct 2013 23:06:05 +0400 Subject: SSL_read error on multiple simultaneous upstream SSL downloads In-Reply-To: References: Message-ID: <20131018190605.GP2144@mdounin.ru> Hello! On Fri, Oct 18, 2013 at 06:01:14PM +0000, Agent Coulson wrote: > I am able to reproduce the following error when I have nginx configured > with an upstream https connection. I have tweaked various settings all to > no avail (proxy_buffer_size, proxy_buffers, proxy_ssl_session_reuse). > > 2013/10/18 17:17:31 [debug] 15644#0: *39 SSL_read: -1, SSL_pending: 16384 > 2013/10/18 17:17:31 [debug] 15644#0: *39 SSL_get_error: 1 > 2013/10/18 17:17:31 [error] 15644#0: *39 SSL_read() failed (SSL: > error:1408F119:SSL routines:SSL3_GET_RECORD:decryption failed or bad record > mac) while sending to client, client: 127.0.0.1, server: -, request: "GET > /test-1 HTTP/1.1", upstream: "https://x.x.x.x:443/test-1", host: > "localhost:1182" I tend to think it's highly unlikely it's a problem in nginx. Most likely, it's a problem either in OpenSSL library used on nginx side, or in SSL implementation used on a backend. First thing I would recommend to test is to make sure you are able to reporoduce the problem: 1. Using nginx statically compiled with a known version of the OpenSSL library (--with-openssl=..., with sources from openssl.org). 2. Using the same nginx as a backend. [...] > I've seen a bug report on this too (http://trac.nginx.org/nginx/ticket/215), > so thought i would send this here to see if anyone else is actively working > on the issue. As of now, no one provided enough steps to reproduce the problem. And, see above, most likely the problem is not in nginx. -- Maxim Dounin http://nginx.org/en/donation.html From shield1182 at gmail.com Fri Oct 18 19:59:40 2013 From: shield1182 at gmail.com (Agent Coulson) Date: Fri, 18 Oct 2013 19:59:40 +0000 Subject: SSL_read error on multiple simultaneous upstream SSL downloads In-Reply-To: <20131018190605.GP2144@mdounin.ru> References: <20131018190605.GP2144@mdounin.ru> Message-ID: Yes, I am able to reproduce this talking to the same nginx as an upstream, here is my new config. To reproduce, create a file in the root which is several Mb, i used 20Mb, and issus multiple simultaneous curl's to the object, i found rate-limiting my curl is the best way to repro. This suggests there is some problem when we have to buffer. I'm skeptical that this is an openssl issue as I have used multiple different openssl versions and still run into this. However for completeness, I've reprod with openssl sources from openssl.org (openssl-1.0.1e) as you suggested. Updated conf: ### Begin ngxin.conf ### worker_processes 1; error_log logs/error.log debug; pid logs/nginx.pid; events { worker_connections 1024; } http { include mime.types; default_type application/octet-stream; access_log logs/access.log; keepalive_timeout 60; upstream http { server 127.0.0.1:1183; keepalive 512; } server { listen 1182 default_server; server_name -; ssl_protocols SSLv3 TLSv1; ssl_ciphers RC4:HIGH:!aNULL:!MD5; ssl_prefer_server_ciphers on; location / { proxy_pass https://http; proxy_redirect off; proxy_read_timeout 10s; proxy_connect_timeout 6s; proxy_buffering off; proxy_buffer_size 64k; proxy_buffers 6 16k; proxy_busy_buffers_size 80k; proxy_pass_header Server; proxy_pass_header Date; proxy_pass_header X-Pad; proxy_set_header Connection "Keep-Alive"; proxy_set_header Host "upstream.srv"; } } server { listen 1183 ssl; server_name upstream.srv; ssl_certificate /var/nginx/conf/upstream.srv.pem; ssl_certificate_key /var/nginx/conf/upstream.srv.key; ssl_protocols SSLv3 TLSv1; ssl_ciphers RC4:HIGH:!aNULL:!MD5; ssl_prefer_server_ciphers on; location / { root /var/nginx/html; } } } ### End ngxin.conf ### configure flags for nginx 1.4.3: ./configure --prefix=/var/nginx --with-debug --with-http_ssl_module --without-http_auth_basic_module --without-http_autoindex_module --without-http_browser_module --without-http-cache --without-http_charset_module --without-http_empty_gif_module --without-http_fastcgi_module --without-http_geo_module --without-http_gzip_module --without-http_limit_conn_module --without-http_map_module --without-http_memcached_module --without-http_referer_module --without-http_rewrite_module --without-http_scgi_module --without-http_split_clients_module --without-http_ssi_module --without-http_upstream_ip_hash_module --without-http_userid_module --without-http_uwsgi_module --without-mail_imap_module --without-mail_pop3_module --without-mail_smtp_module --with-openssl=/tmp/openssl-1.0.1e I start nginx and then issue 3 simultaneous curl's from the local box, rate-limited. This should be sufficient for anyone else to repro the issue. curl --limit-rate 800k -v -o /dev/null http://localhost:1182/20m.txt& curl --limit-rate 800k -v -o /dev/null http://localhost:1182/20m.txt& curl --limit-rate 800k -v -o /dev/null http://localhost:1182/20m.txt& At least one will fail with bytes remaining, and you will see the error in the error.log. 2013/10/18 19:56:50 [error] 14667#0: *4 SSL_read() failed (SSL: error:1408F119:SSL routines:SSL3_GET_RECORD:decryption failed or bad record mac) while sending to client, client: 127.0.0.1, server: -, request: "GET /20m.bin HTTP/1.1", upstream: "https://127.0.0.1:1183/20m.bin", host: "localhost:1182" thanks for your attention. On Fri, Oct 18, 2013 at 7:06 PM, Maxim Dounin wrote: > Hello! > > On Fri, Oct 18, 2013 at 06:01:14PM +0000, Agent Coulson wrote: > > > I am able to reproduce the following error when I have nginx configured > > with an upstream https connection. I have tweaked various settings all > to > > no avail (proxy_buffer_size, proxy_buffers, proxy_ssl_session_reuse). > > > > 2013/10/18 17:17:31 [debug] 15644#0: *39 SSL_read: -1, SSL_pending: 16384 > > 2013/10/18 17:17:31 [debug] 15644#0: *39 SSL_get_error: 1 > > 2013/10/18 17:17:31 [error] 15644#0: *39 SSL_read() failed (SSL: > > error:1408F119:SSL routines:SSL3_GET_RECORD:decryption failed or bad > record > > mac) while sending to client, client: 127.0.0.1, server: -, request: "GET > > /test-1 HTTP/1.1", upstream: "https://x.x.x.x:443/test-1", host: > > "localhost:1182" > > I tend to think it's highly unlikely it's a problem in nginx. > Most likely, it's a problem either in OpenSSL library used on > nginx side, or in SSL implementation used on a backend. > > First thing I would recommend to test is to make sure you are able > to reporoduce the problem: > > 1. Using nginx statically compiled with a known version of the > OpenSSL library (--with-openssl=..., with sources from > openssl.org). > > 2. Using the same nginx as a backend. > > [...] > > > I've seen a bug report on this too ( > http://trac.nginx.org/nginx/ticket/215), > > so thought i would send this here to see if anyone else is actively > working > > on the issue. > > As of now, no one provided enough steps to reproduce the problem. > And, see above, most likely the problem is not in nginx. > > -- > Maxim Dounin > http://nginx.org/en/donation.html > > _______________________________________________ > 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 rob.stradling at comodo.com Fri Oct 18 22:51:01 2013 From: rob.stradling at comodo.com (Rob Stradling) Date: Fri, 18 Oct 2013 23:51:01 +0100 Subject: [PATCH] RSA+DSA+ECC bundles In-Reply-To: <20131017151800.GI2144@mdounin.ru> References: <006701ce048e$d1b9e090$752da1b0$@slo-tech.com> <525FEFA6.9040004@comodo.com> <20131017151800.GI2144@mdounin.ru> Message-ID: <5261BB55.4060505@comodo.com> On 17/10/13 16:18, Maxim Dounin wrote: >> Issues I'm aware of with this patch: >> >> - It doesn't check that each of the certs has a different key type >> (but perhaps it should). If you specify multiple certs with the >> same algorithm, all but the last one will be ignored. > > Bad, but we could live with it if there will be no better way to > do things. We could call EVP_PKEY_type() for each private key, and throw an error if there's >1 key of any particular type (EVP_PKEY_RSA, EVP_PKEY_DSA, EVP_PKEY_EC). But I think I'd prefer to "live with it". Future OpenSSL versions might add new key types, or might make it possible for a server to offer multiple certs of the same type (e.g. 2 ECC certs with different curves). It would be nice if Nginx could support such enhancements automatically. >> - The certs and keys need to be specified in the correct order. >> If you specify "my_rsa.crt my_ecc.crt" and "my_ecc.key my_rsa.key", >> Nginx will start but it won't be able to complete any SSL >> handshakes. This could be improved. > > This is certainly not something acceptable. There should be a > better way to specify certs and keys. Patch v2 (attached) checks that each cert and key are correctly paired. If they're incorrectly paired, Nginx will throw an error and refuse to start. >> - It doesn't add the new feature to mail_ssl_module. Perhaps it should. > > This could wait. Implemented in patch v2. Untested, but the changes are virtually identical to the http_ssl_module changes. >> - The changes I made to ngx_conf_set_str_array_slot() work for me, >> but do they break anything? > > It doesn't look like changes we want. The > ngx_conf_set_str_array_slot() function is intended to handle > arrays like this: > > example_array_directive value1; > example_array_directive value2; Thanks for that tip. :-) > I would rather see ssl_certificates to be used this way, something > like: > > ssl_certificate rsa.crt; > ssl_certificate_key rsa.key; > > ssl_certificate ecc.crt; > ssl_certificate_key ecc.key; I agree. Fixed in patch v2. >> - An RSA cert and an ECC cert might well be issued by different >> CAs. On Apache httpd, you have to use SSLCACertificatePath to >> persuade OpenSSL to send different Intermediate certs for each one. >> Nginx doesn't currently have an equivalent directive, and Maxim has >> previously said it's unlikely to be added [1]. >> I haven't researched this properly yet, but I think it might be >> possible to do "certificate path" in memory (i.e. without syscalls >> and disk access on each certificate check) using the OpenSSL >> X509_LOOKUP API. > > AFAIR, OpenSSL only able to store one certificate chain per > SSL_CTX, which is the root cause of the problem. I think you're right. I've not tried to address this yet. >> - I expect Maxim will have other comments. :-) > > One thing which instantly comes in mind is SSL Stapling related > issues. Ah yes. The Nginx stapling code seems to assume one cert and therefore one OCSP Response. So, I think it needs updating to handle multiple certs and OCSP Responses and to call SSL_get_certificate(SSL*) to get the cert that the server has selected to send to the client. I've not tried to address this yet. -- Rob Stradling Senior Research & Development Scientist COMODO - Creating Trust Online -------------- next part -------------- A non-text attachment was scrubbed... Name: nginx_multiple_certs_V2.patch Type: text/x-patch Size: 18772 bytes Desc: not available URL: From rob.stradling at comodo.com Fri Oct 18 23:06:57 2013 From: rob.stradling at comodo.com (Rob Stradling) Date: Sat, 19 Oct 2013 00:06:57 +0100 Subject: [PATCH] RSA+DSA+ECC bundles In-Reply-To: References: <006701ce048e$d1b9e090$752da1b0$@slo-tech.com> <525FEFA6.9040004@comodo.com> <20131017151800.GI2144@mdounin.ru> Message-ID: <5261BF11.7010708@comodo.com> On 17/10/13 23:00, Piotr Sikora wrote: > Hey, > >> I would rather see ssl_certificates to be used this way, something >> like: >> >> ssl_certificate rsa.crt; >> ssl_certificate_key rsa.key; >> >> ssl_certificate ecc.crt; >> ssl_certificate_key ecc.key; > > Yeah, I'm in favor of that syntax as well. > >> AFAIR, OpenSSL only able to store one certificate chain per >> SSL_CTX, which is the root cause of the problem. > > That's solved in OpenSSL-1.0.2 (unreleased). Thanks Piotr. I tried building Nginx with my v2 patch against OpenSSL_1_0_2, but I didn't see any change in behaviour. i.e. With an RSA cert and an ECC cert issued by different CAs, Nginx sends the intermediate certs from both chains in both cases. Nginx uses SSL_CTX_add_extra_chain_cert(), and I think that might be the problem. That function's 1_0_2 man page says "Different chains for different certificates (for example if both RSA and DSA certificates are specified by the same server) or different SSL structures with the same parent SSL_CTX cannot be specified using this function. For more flexibility functions such as SSL_add1_chain_cert() should be used instead." I'll investigate more next week. > For now, the one thing we could do is to let OpenSSL build certificate > chains from the trusted certificates store... In order to do that, all > we need to do is to load only the first certificate in the file (i.e. > don't load intermediate certificates) in case there are multiple > certificates defined. This way, OpenSSL will try to build the > certificate chain automatically (unfortunately, it will do that on the > fly for each connection, so it's a noticeable overhead). Yes, but (assuming "...from the trusted certificates store" would do syscalls and disk access for every connection) hasn't Maxim already said that that overhead would be unacceptable? > Optimized version of that could compare intermediates from all the > files and only do that in case they differ. -- Rob Stradling Senior Research & Development Scientist COMODO - Creating Trust Online From mdounin at mdounin.ru Sat Oct 19 10:14:24 2013 From: mdounin at mdounin.ru (Maxim Dounin) Date: Sat, 19 Oct 2013 14:14:24 +0400 Subject: [PATCH] RSA+DSA+ECC bundles In-Reply-To: <5261BF11.7010708@comodo.com> References: <006701ce048e$d1b9e090$752da1b0$@slo-tech.com> <525FEFA6.9040004@comodo.com> <20131017151800.GI2144@mdounin.ru> <5261BF11.7010708@comodo.com> Message-ID: <20131019101424.GS2144@mdounin.ru> Hello! On Sat, Oct 19, 2013 at 12:06:57AM +0100, Rob Stradling wrote: > On 17/10/13 23:00, Piotr Sikora wrote: > >Hey, > > > >>I would rather see ssl_certificates to be used this way, something > >>like: > >> > >> ssl_certificate rsa.crt; > >> ssl_certificate_key rsa.key; > >> > >> ssl_certificate ecc.crt; > >> ssl_certificate_key ecc.key; > > > >Yeah, I'm in favor of that syntax as well. > > > >>AFAIR, OpenSSL only able to store one certificate chain per > >>SSL_CTX, which is the root cause of the problem. > > > >That's solved in OpenSSL-1.0.2 (unreleased). > > Thanks Piotr. I tried building Nginx with my v2 patch against > OpenSSL_1_0_2, but I didn't see any change in behaviour. i.e. With > an RSA cert and an ECC cert issued by different CAs, Nginx sends the > intermediate certs from both chains in both cases. > > Nginx uses SSL_CTX_add_extra_chain_cert(), and I think that might be > the problem. That function's 1_0_2 man page says "Different chains > for different certificates (for example if both RSA and DSA > certificates are specified by the same server) or different SSL > structures with the same parent SSL_CTX cannot be specified using > this function. For more flexibility functions such as > SSL_add1_chain_cert() should be used instead." > > I'll investigate more next week. The SSL_add1_chain_cert() function documentation says: : These functions were first added to OpenSSL 1.0.2. That is, they aren't yet available. > >For now, the one thing we could do is to let OpenSSL build certificate > >chains from the trusted certificates store... In order to do that, all > >we need to do is to load only the first certificate in the file (i.e. > >don't load intermediate certificates) in case there are multiple > >certificates defined. This way, OpenSSL will try to build the > >certificate chain automatically (unfortunately, it will do that on the > >fly for each connection, so it's a noticeable overhead). > > Yes, but (assuming "...from the trusted certificates store" would do > syscalls and disk access for every connection) hasn't Maxim already > said that that overhead would be unacceptable? This would be bad for sure, but the message you've referenced says about CApath vs. CAfile. We have the ssl_trusted_certificate directive which loads certs to the trusted certificates store. -- Maxim Dounin http://nginx.org/en/donation.html From mdounin at mdounin.ru Sat Oct 19 12:58:47 2013 From: mdounin at mdounin.ru (Maxim Dounin) Date: Sat, 19 Oct 2013 16:58:47 +0400 Subject: SSL_read error on multiple simultaneous upstream SSL downloads In-Reply-To: References: <20131018190605.GP2144@mdounin.ru> Message-ID: <20131019125847.GT2144@mdounin.ru> Hello! On Fri, Oct 18, 2013 at 07:59:40PM +0000, Agent Coulson wrote: > Yes, I am able to reproduce this talking to the same nginx as an upstream, > here is my new config. To reproduce, create a file in the root which is > several Mb, i used 20Mb, and issus multiple simultaneous curl's to the > object, i found rate-limiting my curl is the best way to repro. This > suggests there is some problem when we have to buffer. I'm skeptical that > this is an openssl issue as I have used multiple different openssl versions > and still run into this. However for completeness, I've reprod with > openssl sources from openssl.org (openssl-1.0.1e) as you suggested. [...] Ok, I was able to reproduce this. Looks like a regression in OpenSSL 1.0.0+. I'm able to reporduce the problem with OpenSSL 1.0.0 and more recent versions, including recent git snapshot, but everything is fine with OpenSSL 0.9.8y and previous versions. Bisection on OpenSSL 1.0.0 branch may be a helpful to trace the exact cause. -- Maxim Dounin http://nginx.org/en/donation.html From wangxiaochen0 at gmail.com Mon Oct 21 11:15:48 2013 From: wangxiaochen0 at gmail.com (Xiaochen Wang) Date: Mon, 21 Oct 2013 19:15:48 +0800 Subject: [PATCH] round robin: optimize loop in ngx_http_upstream_init_round_robin() Message-ID: <20131021111546.GA67080@gmail.com> # HG changeset patch # User Xiaochen Wang # Date 1382350832 -28800 # Node ID b61b9d7d665fffd49fb6711db4d018a6aeb26222 # Parent fcecb9c6a0573f2edd48ff87cef69bd7e7523729 round robin: optimize loop in ngx_http_upstream_init_round_robin() It is a trivial patch to move continue statement from inner loop to outer loop. diff -r fcecb9c6a057 -r b61b9d7d665f src/http/ngx_http_upstream_round_robin.c --- a/src/http/ngx_http_upstream_round_robin.c Fri Oct 18 18:13:49 2013 +0400 +++ b/src/http/ngx_http_upstream_round_robin.c Mon Oct 21 18:20:32 2013 +0800 @@ -71,11 +71,11 @@ n = 0; for (i = 0; i < us->servers->nelts; i++) { + if (server[i].backup) { + continue; + } + for (j = 0; j < server[i].naddrs; j++) { - if (server[i].backup) { - continue; - } - peers->peer[n].sockaddr = server[i].addrs[j].sockaddr; peers->peer[n].socklen = server[i].addrs[j].socklen; peers->peer[n].name = server[i].addrs[j].name; @@ -125,11 +125,11 @@ n = 0; for (i = 0; i < us->servers->nelts; i++) { + if (!server[i].backup) { + continue; + } + for (j = 0; j < server[i].naddrs; j++) { - if (!server[i].backup) { - continue; - } - backup->peer[n].sockaddr = server[i].addrs[j].sockaddr; backup->peer[n].socklen = server[i].addrs[j].socklen; backup->peer[n].name = server[i].addrs[j].name; From mdounin at mdounin.ru Mon Oct 21 14:38:18 2013 From: mdounin at mdounin.ru (Maxim Dounin) Date: Mon, 21 Oct 2013 14:38:18 +0000 Subject: [nginx] Upstream: optimize loops in ngx_http_upstream_init_round... Message-ID: details: http://hg.nginx.org/nginx/rev/e6a1623f87bc branches: changeset: 5429:e6a1623f87bc user: Xiaochen Wang date: Mon Oct 21 18:20:32 2013 +0800 description: Upstream: optimize loops in ngx_http_upstream_init_round_robin(). diffstat: src/http/ngx_http_upstream_round_robin.c | 16 ++++++++-------- 1 files changed, 8 insertions(+), 8 deletions(-) diffs (35 lines): diff --git a/src/http/ngx_http_upstream_round_robin.c b/src/http/ngx_http_upstream_round_robin.c --- a/src/http/ngx_http_upstream_round_robin.c +++ b/src/http/ngx_http_upstream_round_robin.c @@ -71,11 +71,11 @@ ngx_http_upstream_init_round_robin(ngx_c n = 0; for (i = 0; i < us->servers->nelts; i++) { + if (server[i].backup) { + continue; + } + for (j = 0; j < server[i].naddrs; j++) { - if (server[i].backup) { - continue; - } - peers->peer[n].sockaddr = server[i].addrs[j].sockaddr; peers->peer[n].socklen = server[i].addrs[j].socklen; peers->peer[n].name = server[i].addrs[j].name; @@ -125,11 +125,11 @@ ngx_http_upstream_init_round_robin(ngx_c n = 0; for (i = 0; i < us->servers->nelts; i++) { + if (!server[i].backup) { + continue; + } + for (j = 0; j < server[i].naddrs; j++) { - if (!server[i].backup) { - continue; - } - backup->peer[n].sockaddr = server[i].addrs[j].sockaddr; backup->peer[n].socklen = server[i].addrs[j].socklen; backup->peer[n].name = server[i].addrs[j].name; From mdounin at mdounin.ru Mon Oct 21 14:39:02 2013 From: mdounin at mdounin.ru (Maxim Dounin) Date: Mon, 21 Oct 2013 18:39:02 +0400 Subject: [PATCH] round robin: optimize loop in ngx_http_upstream_init_round_robin() In-Reply-To: <20131021111546.GA67080@gmail.com> References: <20131021111546.GA67080@gmail.com> Message-ID: <20131021143902.GG7074@mdounin.ru> Hello! On Mon, Oct 21, 2013 at 07:15:48PM +0800, Xiaochen Wang wrote: > # HG changeset patch > # User Xiaochen Wang > # Date 1382350832 -28800 > # Node ID b61b9d7d665fffd49fb6711db4d018a6aeb26222 > # Parent fcecb9c6a0573f2edd48ff87cef69bd7e7523729 > round robin: optimize loop in ngx_http_upstream_init_round_robin() > > It is a trivial patch to move continue statement from inner loop to outer loop. [...] Committed with minor changes to description, thanks. -- Maxim Dounin http://nginx.org/en/donation.html From shield1182 at gmail.com Mon Oct 21 17:50:31 2013 From: shield1182 at gmail.com (Agent Coulson) Date: Mon, 21 Oct 2013 17:50:31 +0000 Subject: SSL_read error on multiple simultaneous upstream SSL downloads In-Reply-To: <20131019125847.GT2144@mdounin.ru> References: <20131018190605.GP2144@mdounin.ru> <20131019125847.GT2144@mdounin.ru> Message-ID: Hi! thanks for that input, I have done some debugging and examined the SSL context when this state arrises. Two SSL* structs (from different connections) point to the same packet data. Disabling the read_ahead flag mitigates this. I've attached a patch, after applying I was unable to repro using openssl-1.0.1e. I'll submit a report to the upstream openssl project. thanks! On Sat, Oct 19, 2013 at 12:58 PM, Maxim Dounin wrote: > Hello! > > On Fri, Oct 18, 2013 at 07:59:40PM +0000, Agent Coulson wrote: > > > Yes, I am able to reproduce this talking to the same nginx as an > upstream, > > here is my new config. To reproduce, create a file in the root which is > > several Mb, i used 20Mb, and issus multiple simultaneous curl's to the > > object, i found rate-limiting my curl is the best way to repro. This > > suggests there is some problem when we have to buffer. I'm skeptical > that > > this is an openssl issue as I have used multiple different openssl > versions > > and still run into this. However for completeness, I've reprod with > > openssl sources from openssl.org (openssl-1.0.1e) as you suggested. > > [...] > > Ok, I was able to reproduce this. > > Looks like a regression in OpenSSL 1.0.0+. I'm able to reporduce > the problem with OpenSSL 1.0.0 and more recent versions, including > recent git snapshot, but everything is fine with OpenSSL 0.9.8y > and previous versions. > > Bisection on OpenSSL 1.0.0 branch may be a helpful to trace the > exact cause. > > -- > Maxim Dounin > http://nginx.org/en/donation.html > > _______________________________________________ > 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: -------------- next part -------------- A non-text attachment was scrubbed... Name: patch.patch Type: application/octet-stream Size: 978 bytes Desc: not available URL: From piotr at cloudflare.com Mon Oct 21 18:57:34 2013 From: piotr at cloudflare.com (Piotr Sikora) Date: Mon, 21 Oct 2013 11:57:34 -0700 Subject: SSL_read error on multiple simultaneous upstream SSL downloads In-Reply-To: <20131019125847.GT2144@mdounin.ru> References: <20131018190605.GP2144@mdounin.ru> <20131019125847.GT2144@mdounin.ru> Message-ID: Hey, > Looks like a regression in OpenSSL 1.0.0+. I'm able to reporduce > the problem with OpenSSL 1.0.0 and more recent versions, including > recent git snapshot, but everything is fine with OpenSSL 0.9.8y > and previous versions. > > Bisection on OpenSSL 1.0.0 branch may be a helpful to trace the > exact cause. I've looked a bit into this over the weekend and it seems that it's being triggered by use of both: reading ahead and releasing buffers (introduced in OpenSSL-1.0.0, hence the regression) on the client side with upstream buffering off (I wasn't able to reproduce it with upstream buffering on, but that might be just because it's harder to trigger, as OpenSSL code path is effectively the same in both cases). I don't think that we're affected on the server side (which would actually suggest nginx bug), so the work-around for the issue (at least for the time being) is to stop releasing buffers when nginx acts as a client. I'm a bit tempted to do it only for the case with buffering turned off, but from looking at the code I can't tell why it would make a difference. Patch attached. Best regards, Piotr Sikora # HG changeset patch # User Piotr Sikora # Date 1382381412 25200 # Mon Oct 21 11:50:12 2013 -0700 # Node ID 353b7360da138542933e01686f359ed72e7930d1 # Parent e6a1623f87bc96d5ec62b6d77356aa47dbc60756 SSL: release OpenSSL buffers only when acting as a server. Signed-off-by: Piotr Sikora diff -r e6a1623f87bc -r 353b7360da13 src/event/ngx_event_openssl.c --- a/src/event/ngx_event_openssl.c Mon Oct 21 18:20:32 2013 +0800 +++ b/src/event/ngx_event_openssl.c Mon Oct 21 11:50:12 2013 -0700 @@ -237,10 +237,6 @@ ngx_ssl_create(ngx_ssl_t *ssl, ngx_uint_ SSL_CTX_set_options(ssl->ctx, SSL_OP_NO_COMPRESSION); #endif -#ifdef SSL_MODE_RELEASE_BUFFERS - SSL_CTX_set_mode(ssl->ctx, SSL_MODE_RELEASE_BUFFERS); -#endif - SSL_CTX_set_read_ahead(ssl->ctx, 1); SSL_CTX_set_info_callback(ssl->ctx, ngx_ssl_info_callback); diff -r e6a1623f87bc -r 353b7360da13 src/http/modules/ngx_http_ssl_module.c --- a/src/http/modules/ngx_http_ssl_module.c Mon Oct 21 18:20:32 2013 +0800 +++ b/src/http/modules/ngx_http_ssl_module.c Mon Oct 21 11:50:12 2013 -0700 @@ -528,6 +528,10 @@ ngx_http_ssl_merge_srv_conf(ngx_conf_t * return NGX_CONF_ERROR; } +#ifdef SSL_MODE_RELEASE_BUFFERS + SSL_CTX_set_mode(conf->ssl.ctx, SSL_MODE_RELEASE_BUFFERS); +#endif + #ifdef SSL_CTRL_SET_TLSEXT_HOSTNAME if (SSL_CTX_set_tlsext_servername_callback(conf->ssl.ctx, diff -r e6a1623f87bc -r 353b7360da13 src/mail/ngx_mail_ssl_module.c --- a/src/mail/ngx_mail_ssl_module.c Mon Oct 21 18:20:32 2013 +0800 +++ b/src/mail/ngx_mail_ssl_module.c Mon Oct 21 11:50:12 2013 -0700 @@ -285,6 +285,10 @@ ngx_mail_ssl_merge_conf(ngx_conf_t *cf, return NGX_CONF_ERROR; } +#ifdef SSL_MODE_RELEASE_BUFFERS + SSL_CTX_set_mode(conf->ssl.ctx, SSL_MODE_RELEASE_BUFFERS); +#endif + cln = ngx_pool_cleanup_add(cf->pool, 0); if (cln == NULL) { return NGX_CONF_ERROR; From mdounin at mdounin.ru Mon Oct 21 19:49:37 2013 From: mdounin at mdounin.ru (Maxim Dounin) Date: Mon, 21 Oct 2013 23:49:37 +0400 Subject: SSL_read error on multiple simultaneous upstream SSL downloads In-Reply-To: References: <20131018190605.GP2144@mdounin.ru> <20131019125847.GT2144@mdounin.ru> Message-ID: <20131021194937.GM7074@mdounin.ru> Hello! On Mon, Oct 21, 2013 at 05:50:31PM +0000, Agent Coulson wrote: > Hi! > > thanks for that input, I have done some debugging and examined the SSL > context when this state arrises. Two SSL* structs (from different > connections) point to the same packet data. Disabling the read_ahead flag > mitigates this. > > I've attached a patch, after applying I was unable to repro using > openssl-1.0.1e. > > I'll submit a report to the upstream openssl project. Disabling the read_ahead as a workaround looks wrong for me. While it probably reduces a chance for a problem to appear, it's likely still there. Have you tried looking into the OpenSSL code to find out what causes the actual problem? I think it's likely SSL_MODE_RELEASE_BUFFERS related (and I indeed can't reproduce the error without SSL_MODE_RELEASE_BUFFERS set), but I don't see any obvious problems in the code. -- Maxim Dounin http://nginx.org/en/donation.html From mdounin at mdounin.ru Mon Oct 21 20:00:36 2013 From: mdounin at mdounin.ru (Maxim Dounin) Date: Tue, 22 Oct 2013 00:00:36 +0400 Subject: SSL_read error on multiple simultaneous upstream SSL downloads In-Reply-To: References: <20131018190605.GP2144@mdounin.ru> <20131019125847.GT2144@mdounin.ru> Message-ID: <20131021200036.GN7074@mdounin.ru> Hello! On Mon, Oct 21, 2013 at 11:57:34AM -0700, Piotr Sikora wrote: > Hey, > > > Looks like a regression in OpenSSL 1.0.0+. I'm able to reporduce > > the problem with OpenSSL 1.0.0 and more recent versions, including > > recent git snapshot, but everything is fine with OpenSSL 0.9.8y > > and previous versions. > > > > Bisection on OpenSSL 1.0.0 branch may be a helpful to trace the > > exact cause. > > I've looked a bit into this over the weekend and it seems that it's > being triggered by use of both: reading ahead and releasing buffers > (introduced in OpenSSL-1.0.0, hence the regression) on the client side > with upstream buffering off (I wasn't able to reproduce it with > upstream buffering on, but that might be just because it's harder to > trigger, as OpenSSL code path is effectively the same in both cases). > > I don't think that we're affected on the server side (which would > actually suggest nginx bug), so the work-around for the issue (at > least for the time being) is to stop releasing buffers when nginx acts > as a client. I'm a bit tempted to do it only for the case with > buffering turned off, but from looking at the code I can't tell why it > would make a difference. While I tend to think that the problem is indeed related to SSL_MODE_RELEASE_BUFFERS I don't see any reasons why the server side shouldn't be affected. Could you please point out why you think so? In any case I don't think we should commit any workarounds before the problem is at least understood. Trivial mitigation for the errors observed so far would be to switch proxy_buffering back to on, as by default, and/or use larger buffers. -- Maxim Dounin http://nginx.org/en/donation.html From rob.stradling at comodo.com Mon Oct 21 21:40:43 2013 From: rob.stradling at comodo.com (Rob Stradling) Date: Mon, 21 Oct 2013 22:40:43 +0100 Subject: [PATCH] RSA+DSA+ECC bundles In-Reply-To: <20131019101424.GS2144@mdounin.ru> References: <006701ce048e$d1b9e090$752da1b0$@slo-tech.com> <525FEFA6.9040004@comodo.com> <20131017151800.GI2144@mdounin.ru> <5261BF11.7010708@comodo.com> <20131019101424.GS2144@mdounin.ru> Message-ID: <52659F5B.1050708@comodo.com> On 19/10/13 11:14, Maxim Dounin wrote: >> I'll investigate more next week. > > The SSL_add1_chain_cert() function documentation says: > > : These functions were first added to OpenSSL 1.0.2. > > That is, they aren't yet available. True. FWIW, changing "SSL_CTX_add_extra_chain_cert" to "SSL_CTX_add1_chain_cert" in ngx_event_openssl.c and compiling against OpenSSL_1_0_2 does give the desired behaviour though. >>> For now, the one thing we could do is to let OpenSSL build certificate >>> chains from the trusted certificates store... In order to do that, all >>> we need to do is to load only the first certificate in the file (i.e. >>> don't load intermediate certificates) in case there are multiple >>> certificates defined. This way, OpenSSL will try to build the >>> certificate chain automatically (unfortunately, it will do that on the >>> fly for each connection, so it's a noticeable overhead). >> >> Yes, but (assuming "...from the trusted certificates store" would do >> syscalls and disk access for every connection) hasn't Maxim already >> said that that overhead would be unacceptable? > > This would be bad for sure, but the message you've referenced says > about CApath vs. CAfile. We have the ssl_trusted_certificate > directive which loads certs to the trusted certificates store. Ah, I see. It's just "CApath" that you want to avoid, and ssl_trusted_certificate is basically the same thing as "CAfile". To keep things simple for users, I think it would be best for Nginx to keep expecting to find the intermediate CA certs at the end of the ssl_certificate file (rather than require users to put them in the ssl_trusted_certificate file under certain circumstances). But I agree with using the "trusted certificates store" under the hood. The following approach seems to work: #if OPENSSL_VERSION_NUMBER >= 0x10002000L // OpenSSL 1.0.2 lets us do this properly Call SSL_CTX_add1_chain_cert(ssl->ctx, x509) #else If (number of ssl_certificate directives > 1) // Put this intermediate in the "trusted certificates store" Call X509_STORE_add_cert(ssl->ctx->cert_store, x509) Else // This is what Nginx does currently Call SSL_CTX_add_extra_chain_cert(ssl->ctx, x509) End If #endif (A side effect is that I'm seeing "OCSP_basic_verify:signer certificate not found" from the stapling code in both cases where I don't call SSL_CTX_add_extra_chain_cert() - another thing to look into!) -- Rob Stradling Senior Research & Development Scientist COMODO - Creating Trust Online From shield1182 at gmail.com Mon Oct 21 20:00:32 2013 From: shield1182 at gmail.com (Agent Coulson) Date: Mon, 21 Oct 2013 20:00:32 +0000 Subject: SSL_read error on multiple simultaneous upstream SSL downloads In-Reply-To: <20131021194937.GM7074@mdounin.ru> References: <20131018190605.GP2144@mdounin.ru> <20131019125847.GT2144@mdounin.ru> <20131021194937.GM7074@mdounin.ru> Message-ID: I think i would go with Piotr's suggestion, I had only started to dig into the code, so hadn't got as far as he did (I took the weekend off)! thanks again On Mon, Oct 21, 2013 at 7:49 PM, Maxim Dounin wrote: > Hello! > > On Mon, Oct 21, 2013 at 05:50:31PM +0000, Agent Coulson wrote: > > > Hi! > > > > thanks for that input, I have done some debugging and examined the SSL > > context when this state arrises. Two SSL* structs (from different > > connections) point to the same packet data. Disabling the read_ahead > flag > > mitigates this. > > > > I've attached a patch, after applying I was unable to repro using > > openssl-1.0.1e. > > > > I'll submit a report to the upstream openssl project. > > Disabling the read_ahead as a workaround looks wrong for me. > While it probably reduces a chance for a problem to appear, it's > likely still there. > > Have you tried looking into the OpenSSL code to find out what > causes the actual problem? > > I think it's likely SSL_MODE_RELEASE_BUFFERS related (and I indeed > can't reproduce the error without SSL_MODE_RELEASE_BUFFERS set), > but I don't see any obvious problems in the code. > > -- > Maxim Dounin > http://nginx.org/en/donation.html > > _______________________________________________ > nginx-devel mailing list > nginx-devel at nginx.org > http://mailman.nginx.org/mailman/listinfo/nginx-devel > -------------- next part -------------- An HTML attachment was scrubbed... URL: From mdounin at mdounin.ru Tue Oct 22 12:09:39 2013 From: mdounin at mdounin.ru (Maxim Dounin) Date: Tue, 22 Oct 2013 16:09:39 +0400 Subject: [PATCH] RSA+DSA+ECC bundles In-Reply-To: <52659F5B.1050708@comodo.com> References: <006701ce048e$d1b9e090$752da1b0$@slo-tech.com> <525FEFA6.9040004@comodo.com> <20131017151800.GI2144@mdounin.ru> <5261BF11.7010708@comodo.com> <20131019101424.GS2144@mdounin.ru> <52659F5B.1050708@comodo.com> Message-ID: <20131022120939.GU7074@mdounin.ru> Hello! On Mon, Oct 21, 2013 at 10:40:43PM +0100, Rob Stradling wrote: > On 19/10/13 11:14, Maxim Dounin wrote: > > >>I'll investigate more next week. > > > >The SSL_add1_chain_cert() function documentation says: > > > >: These functions were first added to OpenSSL 1.0.2. > > > >That is, they aren't yet available. > > True. FWIW, changing "SSL_CTX_add_extra_chain_cert" to > "SSL_CTX_add1_chain_cert" in ngx_event_openssl.c and compiling > against OpenSSL_1_0_2 does give the desired behaviour though. > > >>>For now, the one thing we could do is to let OpenSSL build certificate > >>>chains from the trusted certificates store... In order to do that, all > >>>we need to do is to load only the first certificate in the file (i.e. > >>>don't load intermediate certificates) in case there are multiple > >>>certificates defined. This way, OpenSSL will try to build the > >>>certificate chain automatically (unfortunately, it will do that on the > >>>fly for each connection, so it's a noticeable overhead). > >> > >>Yes, but (assuming "...from the trusted certificates store" would do > >>syscalls and disk access for every connection) hasn't Maxim already > >>said that that overhead would be unacceptable? > > > >This would be bad for sure, but the message you've referenced says > >about CApath vs. CAfile. We have the ssl_trusted_certificate > >directive which loads certs to the trusted certificates store. > > Ah, I see. It's just "CApath" that you want to avoid, and > ssl_trusted_certificate is basically the same thing as "CAfile". > > To keep things simple for users, I think it would be best for Nginx > to keep expecting to find the intermediate CA certs at the end of > the ssl_certificate file (rather than require users to put them in > the ssl_trusted_certificate file under certain circumstances). But > I agree with using the "trusted certificates store" under the hood. > The following approach seems to work: > > #if OPENSSL_VERSION_NUMBER >= 0x10002000L > // OpenSSL 1.0.2 lets us do this properly > Call SSL_CTX_add1_chain_cert(ssl->ctx, x509) > #else > If (number of ssl_certificate directives > 1) > // Put this intermediate in the "trusted certificates store" > Call X509_STORE_add_cert(ssl->ctx->cert_store, x509) > Else > // This is what Nginx does currently > Call SSL_CTX_add_extra_chain_cert(ssl->ctx, x509) > End If > #endif An unwanted side effect would be that this will allow client certificate authentication to use certs from a server's certificate chain. Probably not something we want to happen. > (A side effect is that I'm seeing "OCSP_basic_verify:signer > certificate not found" from the stapling code in both cases where I > don't call SSL_CTX_add_extra_chain_cert() - another thing to look > into!) OCSP Stapling code uses certificate chain as available via SSL_CTX_get_extra_chain_certs() to look for issuer cert, see ngx_ssl_stapling_issuer(). Though certs from a trusted store should be used too. -- Maxim Dounin http://nginx.org/en/donation.html From rob.stradling at comodo.com Tue Oct 22 13:31:01 2013 From: rob.stradling at comodo.com (Rob Stradling) Date: Tue, 22 Oct 2013 14:31:01 +0100 Subject: [PATCH] RSA+DSA+ECC bundles In-Reply-To: <20131022120939.GU7074@mdounin.ru> References: <006701ce048e$d1b9e090$752da1b0$@slo-tech.com> <525FEFA6.9040004@comodo.com> <20131017151800.GI2144@mdounin.ru> <5261BF11.7010708@comodo.com> <20131019101424.GS2144@mdounin.ru> <52659F5B.1050708@comodo.com> <20131022120939.GU7074@mdounin.ru> Message-ID: <52667E15.1010301@comodo.com> On 22/10/13 13:09, Maxim Dounin wrote: > Hello! > > On Mon, Oct 21, 2013 at 10:40:43PM +0100, Rob Stradling wrote: >> The following approach seems to work: >> >> #if OPENSSL_VERSION_NUMBER >= 0x10002000L >> // OpenSSL 1.0.2 lets us do this properly >> Call SSL_CTX_add1_chain_cert(ssl->ctx, x509) >> #else >> If (number of ssl_certificate directives > 1) >> // Put this intermediate in the "trusted certificates store" >> Call X509_STORE_add_cert(ssl->ctx->cert_store, x509) >> Else >> // This is what Nginx does currently >> Call SSL_CTX_add_extra_chain_cert(ssl->ctx, x509) >> End If >> #endif > > An unwanted side effect would be that this will allow client > certificate authentication to use certs from a server's > certificate chain. Probably not something we want to happen. Yes, that's a potentially unwanted side effect. But unfortunately, AFAICT, putting the intermediates into the "trusted certificates store" is the only way to implement this feature with OpenSSL <1.0.2. Could you live with this side effect if the user had to explicitly enable it? Like this... #if OPENSSL_VERSION_NUMBER >= 0x10002000L // OpenSSL 1.0.2 lets us do this properly Call SSL_CTX_add1_chain_cert(ssl->ctx, x509) #else If (number of ssl_certificate directives > 1) // Do nothing here. // The user is expected to put the required intermediates // into the ssl_trusted_certificate file. In doing so, they'll // also be trusting those intermediates for verifying client // certs - if that's unacceptable to them, then they'll have to // stick to just 1 ssl_certificate directive or else upgrade to // OpenSSL 1.0.2. Else // This is what Nginx does currently Call SSL_CTX_add_extra_chain_cert(ssl->ctx, x509) End If #endif >> (A side effect is that I'm seeing "OCSP_basic_verify:signer >> certificate not found" from the stapling code in both cases where I >> don't call SSL_CTX_add_extra_chain_cert() - another thing to look >> into!) > > OCSP Stapling code uses certificate chain as available via > SSL_CTX_get_extra_chain_certs() to look for issuer cert, see > ngx_ssl_stapling_issuer(). Yep, I'd found that. > Though certs from a trusted store should be used too. ngx_event_openssl_stapling.c provides OCSP_basic_verify() with 3 places to look for certs: inside the OCSP Response, the extra_chain_certs and the "trusted certificate store". OCSP_basic_verify() calls ocsp_find_signer() to locate the certificate that signed the OCSP Response, but this function only looks in the first 2 of those 3 places. (There's a comment "/* Maybe lookup from store if by subject name */", but no associated code). This is a problem for OCSP Responses that are signed directly by the CA certificate (rather than by a delegated OCSP Response Signing Certificate). It currently works because that CA certificate is almost certainly present in extra_chain_certs. But, to support RSA+DSA+ECC certs signed by different intermediates, we already established that we can't use extra_chain_certs. To workaround this, I think the only option would be to pass to OCSP_basic_verify() a different STACK_OF(X509) that includes all of the extra_chain_certs plus whatever other CA certificates that Nginx can lay its hands on! -- Rob Stradling Senior Research & Development Scientist COMODO - Creating Trust Online From manlio.perillo at gmail.com Tue Oct 22 14:32:27 2013 From: manlio.perillo at gmail.com (Manlio Perillo) Date: Tue, 22 Oct 2013 16:32:27 +0200 Subject: use of C reserved identifiers Message-ID: <52668C7B.20201@gmail.com> As per ISO C, identifiers that begin with an underscore and an uppercase letter are always reserved for any use; however in Nginx source code such identifiers are used as macros to guard against multiple file inclusion. This is not a real issue, but since it is easy to fix I have reported it. Regards Manlio Perillo From igor at sysoev.ru Tue Oct 22 14:36:14 2013 From: igor at sysoev.ru (Igor Sysoev) Date: Tue, 22 Oct 2013 18:36:14 +0400 Subject: use of C reserved identifiers In-Reply-To: <52668C7B.20201@gmail.com> References: <52668C7B.20201@gmail.com> Message-ID: On Oct 22, 2013, at 18:32 , Manlio Perillo wrote: > As per ISO C, identifiers that begin with an underscore and an uppercase letter are always reserved for any use; however in Nginx source code such identifiers are used as macros to guard against multiple file inclusion. > > This is not a real issue, but since it is easy to fix I have reported it. I do not believe that C reserved words will ever start with _NGX_... -- Igor Sysoev http://nginx.com From manlio.perillo at gmail.com Tue Oct 22 15:06:21 2013 From: manlio.perillo at gmail.com (Manlio Perillo) Date: Tue, 22 Oct 2013 17:06:21 +0200 Subject: use of C reserved identifiers In-Reply-To: References: <52668C7B.20201@gmail.com> Message-ID: <5266946D.6080201@gmail.com> On 22/10/2013 16:36, Igor Sysoev wrote: > On Oct 22, 2013, at 18:32 , Manlio Perillo wrote: > >> As per ISO C, identifiers that begin with an underscore and an uppercase letter are always reserved for any use; however in Nginx source code such identifiers are used as macros to guard against multiple file inclusion. >> >> This is not a real issue, but since it is easy to fix I have reported it. > > I do not believe that C reserved words will ever start with _NGX_... > > Of course, that's the reason why I wrote this is not a real issue. However, according to ISO C, doing so is still undefined behaviour; pratically this is not a problem, unless you want to get some sort of source code certification (?). Regards Manlio From B22173 at freescale.com Tue Oct 22 17:07:40 2013 From: B22173 at freescale.com (Myla John-B22173) Date: Tue, 22 Oct 2013 17:07:40 +0000 Subject: accept_mutex In-Reply-To: References: <20130902144927.GD65634@mdounin.ru> Message-ID: Hello, I am trying to understand the use of "accept_mutex". Is it required for latest Linux versions? Can you please share some info on the need for this directive? Regards, John -------------- next part -------------- An HTML attachment was scrubbed... URL: From mdounin at mdounin.ru Tue Oct 22 22:05:05 2013 From: mdounin at mdounin.ru (Maxim Dounin) Date: Wed, 23 Oct 2013 02:05:05 +0400 Subject: accept_mutex In-Reply-To: References: <20130902144927.GD65634@mdounin.ru> Message-ID: <20131022220504.GX7074@mdounin.ru> Hello! On Tue, Oct 22, 2013 at 05:07:40PM +0000, Myla John-B22173 wrote: > Hello, > > I am trying to understand the use of "accept_mutex". Is it > required for latest Linux versions? > > Can you please share some info on the need for this directive? Please do not post off-topic questions. This is developers list. For user-level questions, nginx@ list is more appropriate. See http://nginx.org/en/support.html for details. Please also do not hijack unrelated threads. Please also note that the directive you are asking about is documented, see http://nginx.org/r/accept_mutex. It might make sense to read the documentation before asking in mailing lists. Thank you for cooperation. -- Maxim Dounin http://nginx.org/en/donation.html From vshebordaev at mail.ru Tue Oct 22 23:36:19 2013 From: vshebordaev at mail.ru (Vladimir Shebordaev) Date: Wed, 23 Oct 2013 03:36:19 +0400 Subject: use of C reserved identifiers In-Reply-To: <5266946D.6080201@gmail.com> References: <52668C7B.20201@gmail.com> <5266946D.6080201@gmail.com> Message-ID: <52670BF3.20604@mail.ru> OMG, d? you mean ISO or ANSI are to certify nginx source code for the C language standards compliance? I guess, it is the clause 7.1.3 of the recent ANSI/ISO C language standard that makes you so worry. The clause states that using the identifiers reserved for the C standard library usage results in undefined behavior. Well, the behavior that is said to be undefined by the C language standard, must be pretty well defined by a particular compiler and a C standard library implementation. That is, when you are building nginx for a particular operating system, the behavior is rather implementation-defined, since you are bound to certain compiler and the C standard library implementation. In this case, when you redefine a macro that is already defined, e.g. by the system header file, the most probably, you will be strictly warned against doing so, or you even end up with a broken build. I mean, there is basically no harm in the undefined behavior. Unless you know what you are doing. As far as I can see, neither Igor nor other nginx developers do pretend to duplicate any C standard library functionality. Instead, they provide the API to the server core for module developers. The API header files should be considered as a part of the module's translation environment, while the server core is to be a significant part of its execution environment, pretty much like the C standard library for the server core itself. Hope it helps. Regards, Vladimir On 22.10.2013 19:06, Manlio Perillo wrote: > On 22/10/2013 16:36, Igor Sysoev wrote: >> On Oct 22, 2013, at 18:32 , Manlio Perillo wrote: >> >>> As per ISO C, identifiers that begin with an underscore and an >>> uppercase letter are always reserved for any use; however in >>> Nginx source code such identifiers are used as macros to guard >>> against multiple file inclusion. >>> >>> This is not a real issue, but since it is easy to fix I have >>> reported it. >> >> I do not believe that C reserved words will ever start with >> _NGX_... >> >> > > Of course, that's the reason why I wrote this is not a real issue. > > However, according to ISO C, doing so is still undefined behaviour; > pratically this is not a problem, unless you want to get some > sort of source code certification (?). > > > Regards Manlio > From mdounin at mdounin.ru Wed Oct 23 00:25:25 2013 From: mdounin at mdounin.ru (Maxim Dounin) Date: Wed, 23 Oct 2013 04:25:25 +0400 Subject: [PATCH] RSA+DSA+ECC bundles In-Reply-To: <52667E15.1010301@comodo.com> References: <006701ce048e$d1b9e090$752da1b0$@slo-tech.com> <525FEFA6.9040004@comodo.com> <20131017151800.GI2144@mdounin.ru> <5261BF11.7010708@comodo.com> <20131019101424.GS2144@mdounin.ru> <52659F5B.1050708@comodo.com> <20131022120939.GU7074@mdounin.ru> <52667E15.1010301@comodo.com> Message-ID: <20131023002525.GZ7074@mdounin.ru> Hello! On Tue, Oct 22, 2013 at 02:31:01PM +0100, Rob Stradling wrote: > On 22/10/13 13:09, Maxim Dounin wrote: > >Hello! > > > >On Mon, Oct 21, 2013 at 10:40:43PM +0100, Rob Stradling wrote: > > >>The following approach seems to work: > >> > >>#if OPENSSL_VERSION_NUMBER >= 0x10002000L > >> // OpenSSL 1.0.2 lets us do this properly > >> Call SSL_CTX_add1_chain_cert(ssl->ctx, x509) > >>#else > >> If (number of ssl_certificate directives > 1) > >> // Put this intermediate in the "trusted certificates store" > >> Call X509_STORE_add_cert(ssl->ctx->cert_store, x509) > >> Else > >> // This is what Nginx does currently > >> Call SSL_CTX_add_extra_chain_cert(ssl->ctx, x509) > >> End If > >>#endif > > > >An unwanted side effect would be that this will allow client > >certificate authentication to use certs from a server's > >certificate chain. Probably not something we want to happen. > > Yes, that's a potentially unwanted side effect. But unfortunately, > AFAICT, putting the intermediates into the "trusted certificates > store" is the only way to implement this feature with OpenSSL > <1.0.2. > > Could you live with this side effect if the user had to explicitly > enable it? Like this... I think this should be left up to a user. That is, if user want us to work this way, he can use the ssl_trusted_certificate directive to supply needed certs. [...] > >>(A side effect is that I'm seeing "OCSP_basic_verify:signer > >>certificate not found" from the stapling code in both cases where I > >>don't call SSL_CTX_add_extra_chain_cert() - another thing to look > >>into!) > > > >OCSP Stapling code uses certificate chain as available via > >SSL_CTX_get_extra_chain_certs() to look for issuer cert, see > >ngx_ssl_stapling_issuer(). > > Yep, I'd found that. > > >Though certs from a trusted store should be used too. > > ngx_event_openssl_stapling.c provides OCSP_basic_verify() with 3 > places to look for certs: inside the OCSP Response, the > extra_chain_certs and the "trusted certificate store". > > OCSP_basic_verify() calls ocsp_find_signer() to locate the > certificate that signed the OCSP Response, but this function only > looks in the first 2 of those 3 places. (There's a comment "/* > Maybe lookup from store if by subject name */", but no associated > code). Err, sorry, I've somehow misread you mail and tought you are talking about "issuer certificate not found" errors. The OCSP_basic_verify() indeed will likely require additional fixes and/or workarounds. > This is a problem for OCSP Responses that are signed directly by the > CA certificate (rather than by a delegated OCSP Response Signing > Certificate). It currently works because that CA certificate is > almost certainly present in extra_chain_certs. But, to support > RSA+DSA+ECC certs signed by different intermediates, we already > established that we can't use extra_chain_certs. > > To workaround this, I think the only option would be to pass to > OCSP_basic_verify() a different STACK_OF(X509) that includes all of > the extra_chain_certs plus whatever other CA certificates that Nginx > can lay its hands on! Given the number of problems, it might be easier to assume the chains must be the same. How it looks from a CA point of view? -- Maxim Dounin http://nginx.org/en/donation.html From wmark+nginx at hurrikane.de Wed Oct 23 17:07:12 2013 From: wmark+nginx at hurrikane.de (W-Mark Kubacki) Date: Wed, 23 Oct 2013 19:07:12 +0200 Subject: [PATCH] RSA+DSA+ECC bundles In-Reply-To: <20131023002525.GZ7074@mdounin.ru> References: <006701ce048e$d1b9e090$752da1b0$@slo-tech.com> <525FEFA6.9040004@comodo.com> <20131017151800.GI2144@mdounin.ru> <5261BF11.7010708@comodo.com> <20131019101424.GS2144@mdounin.ru> <52659F5B.1050708@comodo.com> <20131022120939.GU7074@mdounin.ru> <52667E15.1010301@comodo.com> <20131023002525.GZ7074@mdounin.ru> Message-ID: Hi, As someone about to purchase two certificates please allow me to weight in an outside perspective: On 2013-10-22 12:09 UTC Maxim Dounin wrote: > > An unwanted side effect would be that this will allow client > certificate authentication to use certs from a server's > certificate chain. Probably not something we want to happen. On 2013-10-22 13:31 UTC Rob Stradling replied: > > Yes, that's a potentially unwanted side effect. But unfortunately, > AFAICT, putting the intermediates into the "trusted certificates > store" is the only way to implement this feature with OpenSSL > <1.0.2. Just drop the backwards-compatibility and require OpenSSL 1.0.2 or later for that feature, just like a particular version of OpenSSL is needed for TLS-SNI. On 2013-10-23 00:25 UTC Maxim Dounin wrote: > > Given the number of problems, it might be easier to assume the > [certificate-]chains must be the same. [?] ? When you are about to get two certificates, most likely RSA+ECC, you go for a ECC-only and a RSA-only chain: The former because clients support ECC anyway, all the way up to the CA. If not, then the latter ?classic? RSA-chain would be used. ? Additionally, it enables you to purchase from more than one CA ? which is good if a visitor with a recent browser doesn't want to trust a CA anymore. I would disable OCSP for now in such cases and implement it later. -- Mark From rob.stradling at comodo.com Wed Oct 23 15:51:46 2013 From: rob.stradling at comodo.com (Rob Stradling) Date: Wed, 23 Oct 2013 16:51:46 +0100 Subject: [PATCH] RSA+DSA+ECC bundles In-Reply-To: <20131023002525.GZ7074@mdounin.ru> References: <006701ce048e$d1b9e090$752da1b0$@slo-tech.com> <525FEFA6.9040004@comodo.com> <20131017151800.GI2144@mdounin.ru> <5261BF11.7010708@comodo.com> <20131019101424.GS2144@mdounin.ru> <52659F5B.1050708@comodo.com> <20131022120939.GU7074@mdounin.ru> <52667E15.1010301@comodo.com> <20131023002525.GZ7074@mdounin.ru> Message-ID: <5267F092.5060909@comodo.com> On 23/10/13 01:25, Maxim Dounin wrote: > On Tue, Oct 22, 2013 at 02:31:01PM +0100, Rob Stradling wrote: >> Yes, that's a potentially unwanted side effect. But unfortunately, >> AFAICT, putting the intermediates into the "trusted certificates >> store" is the only way to implement this feature with OpenSSL >> <1.0.2. >> >> Could you live with this side effect if the user had to explicitly >> enable it? Like this... > I think this should be left up to a user. That is, if user want > us to work this way, he can use the ssl_trusted_certificate directive > to supply needed certs. OK. When multiple certs are configured, OpenSSL <1.0.2 is being used, and there are 1 or more Intermediate certs in the ssl_certificate files that will therefore be ignored, I think it would be helpful to log a warning (to inform the user that those certs have been ignored and would need to be moved to the ssl_trusted_certificate file). >> OCSP_basic_verify() calls ocsp_find_signer() to locate the >> certificate that signed the OCSP Response, but this function only >> looks in the first 2 of those 3 places. (There's a comment "/* >> Maybe lookup from store if by subject name */", but no associated >> code). > > Err, sorry, I've somehow misread you mail and tought you are > talking about "issuer certificate not found" errors. The > OCSP_basic_verify() indeed will likely require additional fixes > and/or workarounds. Yep. I've made a start on attempting to change the stapling code to support multiple certs. (Hopefully I'll be able to complete this!) >> This is a problem for OCSP Responses that are signed directly by the >> CA certificate (rather than by a delegated OCSP Response Signing >> Certificate). It currently works because that CA certificate is >> almost certainly present in extra_chain_certs. But, to support >> RSA+DSA+ECC certs signed by different intermediates, we already >> established that we can't use extra_chain_certs. >> >> To workaround this, I think the only option would be to pass to >> OCSP_basic_verify() a different STACK_OF(X509) that includes all of >> the extra_chain_certs plus whatever other CA certificates that Nginx >> can lay its hands on! > > Given the number of problems, it might be easier to assume the > chains must be the same. I'm not ready to give up yet. :-) > How it looks from a CA point of view? We plan to issue RSA certs from an RSA CA, and ECC certs from an ECC CA. AIUI, TLS <=1.1 requires ECC certs to be issued by an ECC CA, and RSA certs to be issued by an RSA CA - see RFC4492 section 2. Only TLS 1.2 allows ECC certs to be issued by an RSA CA (and vice versa). -- Rob Stradling Senior Research & Development Scientist COMODO - Creating Trust Online From rob.stradling at comodo.com Wed Oct 23 19:13:11 2013 From: rob.stradling at comodo.com (Rob Stradling) Date: Wed, 23 Oct 2013 20:13:11 +0100 Subject: [PATCH] RSA+DSA+ECC bundles In-Reply-To: References: <006701ce048e$d1b9e090$752da1b0$@slo-tech.com> <525FEFA6.9040004@comodo.com> <20131017151800.GI2144@mdounin.ru> <5261BF11.7010708@comodo.com> <20131019101424.GS2144@mdounin.ru> <52659F5B.1050708@comodo.com> <20131022120939.GU7074@mdounin.ru> <52667E15.1010301@comodo.com> <20131023002525.GZ7074@mdounin.ru> Message-ID: <52681FC7.7040208@comodo.com> On 23/10/13 18:07, W-Mark Kubacki wrote: > Hi, > > As someone about to purchase two certificates please allow me to > weight in an outside perspective: Thanks! > On 2013-10-22 12:09 UTC Maxim Dounin wrote: >> >> An unwanted side effect would be that this will allow client >> certificate authentication to use certs from a server's >> certificate chain. Probably not something we want to happen. > > On 2013-10-22 13:31 UTC Rob Stradling replied: >> >> Yes, that's a potentially unwanted side effect. But unfortunately, >> AFAICT, putting the intermediates into the "trusted certificates >> store" is the only way to implement this feature with OpenSSL >> <1.0.2. > > Just drop the backwards-compatibility and require OpenSSL 1.0.2 or > later for that feature, just like a particular version of OpenSSL is > needed for TLS-SNI. Apache httpd can do RSA+DSA+ECC with OpenSSL 1.0.0, and OCSP Stapling works correctly (in recent OpenSSL versions anyway - see [1] ;-) ). Why wouldn't Nginx want to offer the same compatibility? CAs are already starting to sell ECC certs. OpenSSL 1.0.2 isn't even released yet, so most sites will be stuck on <1.0.2 for quite some time. Most sites don't use TLS client authentication, so they wouldn't be affected by the "unwanted side effect" anyway. > On 2013-10-23 00:25 UTC Maxim Dounin wrote: >> >> Given the number of problems, it might be easier to assume the >> [certificate-]chains must be the same. [?] > > ? When you are about to get two certificates, most likely RSA+ECC, you > go for a ECC-only and a RSA-only chain: The former because clients > support ECC anyway, all the way up to the CA. If not, then the latter > ?classic? RSA-chain would be used. > ? Additionally, it enables you to purchase from more than one CA ? > which is good if a visitor with a recent browser doesn't want to trust > a CA anymore. I agree. > I would disable OCSP for now in such cases and implement it later. Why's that? [1] http://git.openssl.org/gitweb/?p=openssl.git;a=patch;h=bb65e3f22bc743f2427b6ed4144d654ec7ddaeef -- Rob Stradling Senior Research & Development Scientist COMODO - Creating Trust Online From piotr at cloudflare.com Wed Oct 23 21:26:41 2013 From: piotr at cloudflare.com (Piotr Sikora) Date: Wed, 23 Oct 2013 14:26:41 -0700 Subject: SSL_read error on multiple simultaneous upstream SSL downloads In-Reply-To: <20131021200036.GN7074@mdounin.ru> References: <20131018190605.GP2144@mdounin.ru> <20131019125847.GT2144@mdounin.ru> <20131021200036.GN7074@mdounin.ru> Message-ID: Hey Maxim, > While I tend to think that the problem is indeed related to > SSL_MODE_RELEASE_BUFFERS I don't see any reasons why the server > side shouldn't be affected. Could you please point out why you > think so? Well, I don't see this from the code, so it's just a hunch, but: - I wasn't able to reproduce it on the server side with big uploads, - I wasn't able to reproduce it on the client side with buffering on, - I was able to consistently reproduce it on the client side with buffering off, - I did a fast scan on some of our production logs and I see those errors only for content that would be transferred with proxy buffering off, - I think that we would see much more complains if this was happening on the server side or on the client side with default settings (buffering on). I know this isn't very scientific, but those are the facts. Note: I didn't play around with WebSockets... They are effectively unbuffered, so they might be triggering this issue on the server side. > In any case I don't think we should commit any workarounds before > the problem is at least understood. Agreed. I should be more clear that my patch was more of a temporary work-around that a proper solution. > Trivial mitigation for the > errors observed so far would be to switch proxy_buffering back to > on, as by default, and/or use larger buffers. Surprisingly, at least on OSX, larger buffers are part of the problem. Small buffers (4k/8k) work fine, but the moment I increase the buffer size (16k+) the error is triggered right away. Best regards, Piotr Sikora From mdounin at mdounin.ru Wed Oct 23 21:46:06 2013 From: mdounin at mdounin.ru (Maxim Dounin) Date: Thu, 24 Oct 2013 01:46:06 +0400 Subject: SSL_read error on multiple simultaneous upstream SSL downloads In-Reply-To: References: <20131018190605.GP2144@mdounin.ru> <20131019125847.GT2144@mdounin.ru> <20131021200036.GN7074@mdounin.ru> Message-ID: <20131023214606.GJ7074@mdounin.ru> Hello! On Wed, Oct 23, 2013 at 02:26:41PM -0700, Piotr Sikora wrote: > Hey Maxim, > > > While I tend to think that the problem is indeed related to > > SSL_MODE_RELEASE_BUFFERS I don't see any reasons why the server > > side shouldn't be affected. Could you please point out why you > > think so? > > Well, I don't see this from the code, so it's just a hunch, but: > - I wasn't able to reproduce it on the server side with big uploads, > - I wasn't able to reproduce it on the client side with buffering on, > - I was able to consistently reproduce it on the client side with buffering off, > - I did a fast scan on some of our production logs and I see those > errors only for content that would be transferred with proxy buffering > off, > - I think that we would see much more complains if this was happening > on the server side or on the client side with default settings > (buffering on). > > I know this isn't very scientific, but those are the facts. > > Note: I didn't play around with WebSockets... They are effectively > unbuffered, so they might be triggering this issue on the server side. As far as I understand, the problem happens if for some reason nginx isn't able to read all the data OpenSSL read from a socket, i.e. if some data are left in the OpenSSL read buffers. (And of course it only happens if OpenSSL uses the same buffers for multiple connections.) This is not something impossible on the server side - but likely much less common than with proxy_buffering set to off. It can happen e.g. with pipelined requests, or if a request with a body is delayed with limit_req. -- Maxim Dounin http://nginx.org/en/donation.html From piotr at cloudflare.com Wed Oct 23 21:48:38 2013 From: piotr at cloudflare.com (Piotr Sikora) Date: Wed, 23 Oct 2013 14:48:38 -0700 Subject: [PATCH] RSA+DSA+ECC bundles In-Reply-To: References: <006701ce048e$d1b9e090$752da1b0$@slo-tech.com> <525FEFA6.9040004@comodo.com> <20131017151800.GI2144@mdounin.ru> <5261BF11.7010708@comodo.com> <20131019101424.GS2144@mdounin.ru> <52659F5B.1050708@comodo.com> <20131022120939.GU7074@mdounin.ru> <52667E15.1010301@comodo.com> <20131023002525.GZ7074@mdounin.ru> Message-ID: Hey, > Just drop the backwards-compatibility and require OpenSSL 1.0.2 or > later for that feature, just like a particular version of OpenSSL is > needed for TLS-SNI. I kind of agree with that. While OpenSSL-1.0.2 is still unreleased, it seems that all options for existing releases are a bit hacky, to say at least... The trusted certificate store sounds like the only way to do it right now, but it effectively makes SSL client verification useless and creates a security issue. What do you think, Maxim? Best regards, Piotr Sikora From piotr at cloudflare.com Wed Oct 23 21:55:04 2013 From: piotr at cloudflare.com (Piotr Sikora) Date: Wed, 23 Oct 2013 14:55:04 -0700 Subject: [PATCH] RSA+DSA+ECC bundles In-Reply-To: <52659F5B.1050708@comodo.com> References: <006701ce048e$d1b9e090$752da1b0$@slo-tech.com> <525FEFA6.9040004@comodo.com> <20131017151800.GI2144@mdounin.ru> <5261BF11.7010708@comodo.com> <20131019101424.GS2144@mdounin.ru> <52659F5B.1050708@comodo.com> Message-ID: Hey Rob, > #if OPENSSL_VERSION_NUMBER >= 0x10002000L > // OpenSSL 1.0.2 lets us do this properly > Call SSL_CTX_add1_chain_cert(ssl->ctx, x509) > #else > If (number of ssl_certificate directives > 1) > // Put this intermediate in the "trusted certificates store" > Call X509_STORE_add_cert(ssl->ctx->cert_store, x509) > Else > // This is what Nginx does currently > Call SSL_CTX_add_extra_chain_cert(ssl->ctx, x509) > End If > #endif For the consistency sake, you should be using SSL_CTX_add0_chain_cert(), since it doesn't increase OpenSSL's internal reference count, same as SSL_CTX_add_extra_chain_cert()... If you want use SSL_CTX_add1_chain_cert() then you should free x509 afterwards. Best regards, Piotr Sikora From mdounin at mdounin.ru Thu Oct 24 00:26:53 2013 From: mdounin at mdounin.ru (Maxim Dounin) Date: Thu, 24 Oct 2013 04:26:53 +0400 Subject: [PATCH] RSA+DSA+ECC bundles In-Reply-To: References: <20131017151800.GI2144@mdounin.ru> <5261BF11.7010708@comodo.com> <20131019101424.GS2144@mdounin.ru> <52659F5B.1050708@comodo.com> <20131022120939.GU7074@mdounin.ru> <52667E15.1010301@comodo.com> <20131023002525.GZ7074@mdounin.ru> Message-ID: <20131024002653.GK7074@mdounin.ru> Hello! On Wed, Oct 23, 2013 at 02:48:38PM -0700, Piotr Sikora wrote: > Hey, > > > Just drop the backwards-compatibility and require OpenSSL 1.0.2 or > > later for that feature, just like a particular version of OpenSSL is > > needed for TLS-SNI. > > I kind of agree with that. > > While OpenSSL-1.0.2 is still unreleased, it seems that all options for > existing releases are a bit hacky, to say at least... The trusted > certificate store sounds like the only way to do it right now, but it > effectively makes SSL client verification useless and creates a > security issue. > > What do you think, Maxim? I strongly disagree with automatic adding certificates from a certificate chain to a trusted store, it's just not an option. Otherwise, I don't think that use of a trusted certificate store is a major problem. The same problem is already here if one want to use OCSP Stapling and verify signatures (and one probably want to, given the fact that an incorrect OCSP Staple can be easily used to DoS a server if a client follows RFC6066, and e.g. Firefox folks seems to try to do so and fail a connection on an incorrect OCSP Staple, see http://trac.nginx.org/nginx/ticket/425). And the same happens if a complex PKI is used, and only some users should be allowed to login. In a long term I think that our client verification code should be complemented by some access control functionality (as of now, one can use rewrite module for checks, and some do use them anyway, but it's not very convenient). As for multiple certs per se, I don't think it should be limited to recent OpenSSL versions only. As far as I can tell, current versions of OpenSSL will work just fine (well, mostly) as long as both ECDSA and RSA certs use the same certificate chain. I believe at least some CAs issue ECDSA certs this way, and this should work. Limiting support for multiple certs with separate certificate chains to only recent OpenSSL versions seems reasonable for me, but if Rob wants to try to make it work with older versions - I don't really object. If it won't be too hacky it might worth supporting. -- Maxim Dounin http://nginx.org/en/donation.html From rob.stradling at comodo.com Thu Oct 24 12:08:27 2013 From: rob.stradling at comodo.com (Rob Stradling) Date: Thu, 24 Oct 2013 13:08:27 +0100 Subject: [PATCH] RSA+DSA+ECC bundles In-Reply-To: References: <006701ce048e$d1b9e090$752da1b0$@slo-tech.com> <525FEFA6.9040004@comodo.com> <20131017151800.GI2144@mdounin.ru> <5261BF11.7010708@comodo.com> <20131019101424.GS2144@mdounin.ru> <52659F5B.1050708@comodo.com> Message-ID: <52690DBB.8090307@comodo.com> On 23/10/13 22:55, Piotr Sikora wrote: > Hey Rob, > >> #if OPENSSL_VERSION_NUMBER >= 0x10002000L >> // OpenSSL 1.0.2 lets us do this properly >> Call SSL_CTX_add1_chain_cert(ssl->ctx, x509) >> #else >> If (number of ssl_certificate directives > 1) >> // Put this intermediate in the "trusted certificates store" >> Call X509_STORE_add_cert(ssl->ctx->cert_store, x509) >> Else >> // This is what Nginx does currently >> Call SSL_CTX_add_extra_chain_cert(ssl->ctx, x509) >> End If >> #endif > > For the consistency sake, you should be using > SSL_CTX_add0_chain_cert(), since it doesn't increase OpenSSL's > internal reference count, same as SSL_CTX_add_extra_chain_cert()... If > you want use SSL_CTX_add1_chain_cert() then you should free x509 > afterwards. Good point. Thanks Piotr! -- Rob Stradling Senior Research & Development Scientist COMODO - Creating Trust Online From deymon at inbox.ru Thu Oct 24 15:01:29 2013 From: deymon at inbox.ru (=?UTF-8?B?RGV5bW9u?=) Date: Thu, 24 Oct 2013 19:01:29 +0400 Subject: Modules developing Message-ID: <1382626889.825586379@f146.i.mail.ru> Good day, all nginx?s developers. There are task module development for nginx. Upon receipt of the request, permitting it, we forward the request to the backend (e.g. ?other web-server) using the modified module (ngx_http_proxy_module). Upon receipt the response from the server, we need to modify the response (buffers chunks) and send it to frontend (e.g. browser). We have tried to connect to the stream via: - ?? u->pipe->input_filter; - ?? r->upstream->pipe->input_filter. But but did not get the desired result. How to solve this problem? How to we need to connect to the processing chain: as a module-handler, filter-module? ? We look forward to any help. Thanks in advance. ? ? Best regards, Edelkin Dmitry, the developer (Department of Applied Systems, ext. tel. 1624) Russian Federation, Republic of Tatarstan, Kazan city, group of companies ?CENTER? telephone number: +7 (843) 533 88 00 e-mail: edelkin at cg.ru skype: edelkin.dmitr y -------------- next part -------------- An HTML attachment was scrubbed... URL: From mdounin at mdounin.ru Thu Oct 24 16:33:17 2013 From: mdounin at mdounin.ru (Maxim Dounin) Date: Thu, 24 Oct 2013 20:33:17 +0400 Subject: Modules developing In-Reply-To: <1382626889.825586379@f146.i.mail.ru> References: <1382626889.825586379@f146.i.mail.ru> Message-ID: <20131024163317.GO7074@mdounin.ru> Hello! On Thu, Oct 24, 2013 at 07:01:29PM +0400, Deymon wrote: > > Good day, > all nginx?s developers. > There are > task module development for nginx. > Upon > receipt of the request, permitting it, we forward the request to the backend > (e.g. ?other web-server) using the modified module > (ngx_http_proxy_module). Upon receipt the response from the server, we need to > modify the response (buffers chunks) and send it to frontend (e.g. browser). We > have tried to connect to the stream via: > - ?? u->pipe->input_filter; > - ?? r->upstream->pipe->input_filter. > But but did > not get the desired result. > How to > solve this problem? How to we need to connect to the processing chain: as a > module-handler, filter-module? The input_filter callback is intended to parse protocol data (e.g., FastCGI records). For general response modifications consider writing a filter module. Some general hints can be found in Evan Miller's guide, see here: http://www.evanmiller.org/nginx-modules-guide.html -- Maxim Dounin http://nginx.org/en/donation.html From piotr at cloudflare.com Thu Oct 24 21:22:02 2013 From: piotr at cloudflare.com (Piotr Sikora) Date: Thu, 24 Oct 2013 14:22:02 -0700 Subject: [PATCH] Core: stop trying to get TCP_DEFER_ACCEPT from unix sockets. Message-ID: # HG changeset patch # User Piotr Sikora # Date 1382649516 25200 # Thu Oct 24 14:18:36 2013 -0700 # Node ID c677648001a2efc383e97229251a5f1df8407122 # Parent e6a1623f87bc96d5ec62b6d77356aa47dbc60756 Core: stop trying to get TCP_DEFER_ACCEPT from unix sockets. Signed-off-by: Piotr Sikora diff -r e6a1623f87bc -r c677648001a2 src/core/ngx_connection.c --- a/src/core/ngx_connection.c Mon Oct 21 18:20:32 2013 +0800 +++ b/src/core/ngx_connection.c Thu Oct 24 14:18:36 2013 -0700 @@ -242,6 +242,10 @@ ngx_set_inherited_sockets(ngx_cycle_t *c #if (NGX_HAVE_DEFERRED_ACCEPT && defined TCP_DEFER_ACCEPT) + if (ls[i].sockaddr->sa_family == AF_UNIX) { + continue; + } + timeout = 0; olen = sizeof(int); From piotr at cloudflare.com Thu Oct 24 21:22:05 2013 From: piotr at cloudflare.com (Piotr Sikora) Date: Thu, 24 Oct 2013 14:22:05 -0700 Subject: [PATCH] Core: apply missed options to sockets added during binary upgrade. Message-ID: # HG changeset patch # User Piotr Sikora # Date 1382649517 25200 # Thu Oct 24 14:18:37 2013 -0700 # Node ID d8ee8ef5dcde554bf1d89d61912e6e6f3c5573f2 # Parent e6a1623f87bc96d5ec62b6d77356aa47dbc60756 Core: apply missed options to sockets added during binary upgrade. The accept_filter and deferred options were not applied to sockets that were added to configuration during binary upgrade cycle. Signed-off-by: Piotr Sikora diff -r e6a1623f87bc -r d8ee8ef5dcde src/core/ngx_cycle.c --- a/src/core/ngx_cycle.c Mon Oct 21 18:20:32 2013 +0800 +++ b/src/core/ngx_cycle.c Thu Oct 24 14:18:37 2013 -0700 @@ -545,6 +545,16 @@ ngx_init_cycle(ngx_cycle_t *old_cycle) if (nls[n].fd == (ngx_socket_t) -1) { nls[n].open = 1; +#if (NGX_HAVE_DEFERRED_ACCEPT && defined SO_ACCEPTFILTER) + if (nls[n].accept_filter) { + nls[n].add_deferred = 1; + } +#endif +#if (NGX_HAVE_DEFERRED_ACCEPT && defined TCP_DEFER_ACCEPT) + if (nls[n].deferred_accept) { + nls[n].add_deferred = 1; + } +#endif } } From ashuven63 at gmail.com Fri Oct 25 01:24:43 2013 From: ashuven63 at gmail.com (Ashwini Venkatesh) Date: Fri, 25 Oct 2013 06:54:43 +0530 Subject: Nginx body filter Message-ID: Hello! I wanted to know how is the chain of execution of body filters. In my case the header filter of the same filter is executed but not the body filter. Does it depend on the execution of previous body filters? -- Regards, Ashwini Venkatesh -------------- next part -------------- An HTML attachment was scrubbed... URL: From mdounin at mdounin.ru Fri Oct 25 17:01:57 2013 From: mdounin at mdounin.ru (Maxim Dounin) Date: Fri, 25 Oct 2013 21:01:57 +0400 Subject: Nginx body filter In-Reply-To: References: Message-ID: <20131025170157.GK7074@mdounin.ru> Hello! On Fri, Oct 25, 2013 at 06:54:43AM +0530, Ashwini Venkatesh wrote: > Hello! > I wanted to know how is the chain of execution of body filters. > In my case the header filter of the same filter is executed but not the > body filter. Does it depend on the execution of previous body filters? Each body filter calls next filter in chain (till writer filter, which is special and writes data to a socket). Most likely reason for "my filter isn't called" problems is registering a filter in a wrong place. Make sure you do something like HTTP_AUX_FILTER_MODULES="$HTTP_AUX_FILTER_MODULES \ ngx_http_test_filter_module" in your module "config" file. Adding a filter to the HTTP_MODULES list won't do anything good. -- Maxim Dounin http://nginx.org/en/donation.html From mdounin at mdounin.ru Fri Oct 25 18:16:28 2013 From: mdounin at mdounin.ru (Maxim Dounin) Date: Fri, 25 Oct 2013 22:16:28 +0400 Subject: [PATCH] Core: stop trying to get TCP_DEFER_ACCEPT from unix sockets. In-Reply-To: References: Message-ID: <20131025181628.GM7074@mdounin.ru> Hello! On Thu, Oct 24, 2013 at 02:22:02PM -0700, Piotr Sikora wrote: > # HG changeset patch > # User Piotr Sikora > # Date 1382649516 25200 > # Thu Oct 24 14:18:36 2013 -0700 > # Node ID c677648001a2efc383e97229251a5f1df8407122 > # Parent e6a1623f87bc96d5ec62b6d77356aa47dbc60756 > Core: stop trying to get TCP_DEFER_ACCEPT from unix sockets. > > Signed-off-by: Piotr Sikora > > diff -r e6a1623f87bc -r c677648001a2 src/core/ngx_connection.c > --- a/src/core/ngx_connection.c Mon Oct 21 18:20:32 2013 +0800 > +++ b/src/core/ngx_connection.c Thu Oct 24 14:18:36 2013 -0700 > @@ -242,6 +242,10 @@ ngx_set_inherited_sockets(ngx_cycle_t *c > > #if (NGX_HAVE_DEFERRED_ACCEPT && defined TCP_DEFER_ACCEPT) > > + if (ls[i].sockaddr->sa_family == AF_UNIX) { > + continue; > + } > + > timeout = 0; > olen = sizeof(int); Any specific reason to? It doesn't seems to fail / produce any problems, and may even start working eventually. -- Maxim Dounin http://nginx.org/en/donation.html From aaron.peschel at gmail.com Fri Oct 25 21:06:44 2013 From: aaron.peschel at gmail.com (Aaron Peschel) Date: Fri, 25 Oct 2013 14:06:44 -0700 Subject: Add Support for Weak ETags Message-ID: This is a response to rev 4746 which removed ETags. 4746 removes the ETag field from the header in all instances where content is modified by the web server prior to being sent to the requesting client. This is far more stringent than required by the HTTP spec. The HTTP spec requires that strict ETags be dependent on the variant that is returned by the server. While removing all ETags from these variants *technically* meets the spec, it is a bit extreme. This commit modifies the ngx_http_clear_etag macro to check if the ETag is marked as a weak ETag. IFF that case, the ETag is retained, and not dropped. Longer term, a better solution would be to completely remove ngx_http_clear_strict_etag and replace it with functions to generate a strict ETag for a variant prior to sending a response to the client, provided that there is not a weak ETag field already included. -------------- next part -------------- A non-text attachment was scrubbed... Name: patch.diff Type: application/octet-stream Size: 5845 bytes Desc: not available URL: From piotr at cloudflare.com Fri Oct 25 21:54:18 2013 From: piotr at cloudflare.com (Piotr Sikora) Date: Fri, 25 Oct 2013 14:54:18 -0700 Subject: Add Support for Weak ETags In-Reply-To: References: Message-ID: Hi Aaron, I disagree with your patch... While retaining weak ETags in case of gzip/gunzip modules is correct, other modules are modifying the content and weak ETags should be removed from responses processed by them. Best regards, Piotr Sikora From piotr at cloudflare.com Fri Oct 25 22:57:24 2013 From: piotr at cloudflare.com (Piotr Sikora) Date: Fri, 25 Oct 2013 15:57:24 -0700 Subject: [PATCH] Core: stop trying to get TCP_DEFER_ACCEPT from unix sockets. In-Reply-To: <20131025181628.GM7074@mdounin.ru> References: <20131025181628.GM7074@mdounin.ru> Message-ID: Hey Maxim, > Any specific reason to? It doesn't seems to fail / produce any > problems, and may even start working eventually. On the contrary, the call used to succeed (tested with Linux 3.2), but recently started failing (tested with Linux 3.9), which results in errors produced during binary upgrade: [notice] 1#0: getsockopt(TCP_DEFER_ACCEPT) for unix:/tmp/test.sock failed, ignored (95: Operation not supported) Also, because it's getsockopt() on IPPROTO_TCP level, I doubt that it will ever start working with unix sockets. Best regards, Piotr Sikora From agentzh at gmail.com Sat Oct 26 00:16:24 2013 From: agentzh at gmail.com (Yichun Zhang (agentzh)) Date: Fri, 25 Oct 2013 17:16:24 -0700 Subject: [PATCH] ngx_gzip might hang the request for slow downstreams Message-ID: Hello! I've noticed a request hang due to an issue in ngx_http_gzip_filter_module's output body filter. Basically when the downstream connection is slow to write to, a write event can trigger a call of ngx_http_output_filter(r, NULL) but ngx_gzip's body filter does not pass the NULL chain link to its downstream filters when its ctx->out == NULL, leading to the downstream connection not flushed at all and a hang. This issue exists in both nginx 1.4.3 and 1.5.6. The following patch fixes the test case on my side. Comments welcome! Thanks! -agentzh --- nginx-1.4.3/src/http/modules/ngx_http_gzip_filter_module.c 2013-10-08 05:07:14.000000000 -0700 +++ nginx-1.4.3-patched/src/http/modules/ngx_http_gzip_filter_module.c 2013-10-25 17:00:00.712697908 -0700 @@ -433,7 +433,15 @@ ngx_http_gzip_body_filter(ngx_http_reque if (ctx->out == NULL) { ngx_http_gzip_filter_free_copy_buf(r, ctx); - return ctx->busy ? NGX_AGAIN : NGX_OK; + if (ctx->busy) { + if (in == NULL) { + return ngx_http_next_body_filter(r, NULL); + } + + return NGX_AGAIN; + } + + return NGX_OK; } if (!ctx->gzheader) { -------------- next part -------------- A non-text attachment was scrubbed... Name: nginx-1.4.3-gzip_flush_bug.patch Type: text/x-patch Size: 686 bytes Desc: not available URL: From mdounin at mdounin.ru Sat Oct 26 01:48:15 2013 From: mdounin at mdounin.ru (Maxim Dounin) Date: Sat, 26 Oct 2013 05:48:15 +0400 Subject: [PATCH] ngx_gzip might hang the request for slow downstreams In-Reply-To: References: Message-ID: <20131026014815.GN7074@mdounin.ru> Hello! On Fri, Oct 25, 2013 at 05:16:24PM -0700, Yichun Zhang (agentzh) wrote: > Hello! > > I've noticed a request hang due to an issue in > ngx_http_gzip_filter_module's output body filter. Basically when the > downstream connection is slow to write to, a write event can trigger a > call of ngx_http_output_filter(r, NULL) but ngx_gzip's body filter > does not pass the NULL chain link to its downstream filters when its > ctx->out == NULL, leading to the downstream connection not flushed at > all and a hang. > > This issue exists in both nginx 1.4.3 and 1.5.6. > > The following patch fixes the test case on my side. Comments welcome! > > Thanks! > -agentzh > > --- nginx-1.4.3/src/http/modules/ngx_http_gzip_filter_module.c > 2013-10-08 05:07:14.000000000 -0700 > +++ nginx-1.4.3-patched/src/http/modules/ngx_http_gzip_filter_module.c > 2013-10-25 17:00:00.712697908 -0700 > @@ -433,7 +433,15 @@ ngx_http_gzip_body_filter(ngx_http_reque > if (ctx->out == NULL) { > ngx_http_gzip_filter_free_copy_buf(r, ctx); > > - return ctx->busy ? NGX_AGAIN : NGX_OK; > + if (ctx->busy) { > + if (in == NULL) { > + return ngx_http_next_body_filter(r, NULL); > + } > + > + return NGX_AGAIN; > + } > + > + return NGX_OK; > } > > if (!ctx->gzheader) { If a write event is going to trigger ngx_http_output_filter(r, NULL), it means that the request was already finalized, and in non-error case there should be last buffer already seen by gzip filter, and hence either ctx->done set, or ctx->nomem case triggered. Could you please elaborate how do you see the problem? In 1.5.6 this probably can be triggered with incomplete upstream response, which intentionally results in no last buffer send, but with such responses nothing is guaranteed anyway. And I don't think there are any legitimate ways to trigger it in 1.4.3. -- Maxim Dounin http://nginx.org/en/donation.html From mdounin at mdounin.ru Sat Oct 26 03:31:10 2013 From: mdounin at mdounin.ru (Maxim Dounin) Date: Sat, 26 Oct 2013 07:31:10 +0400 Subject: [PATCH] Core: stop trying to get TCP_DEFER_ACCEPT from unix sockets. In-Reply-To: References: <20131025181628.GM7074@mdounin.ru> Message-ID: <20131026033110.GO7074@mdounin.ru> Hello! On Fri, Oct 25, 2013 at 03:57:24PM -0700, Piotr Sikora wrote: > Hey Maxim, > > > Any specific reason to? It doesn't seems to fail / produce any > > problems, and may even start working eventually. > > On the contrary, the call used to succeed (tested with Linux 3.2), > but recently started failing (tested with Linux 3.9), which results > in errors produced during binary upgrade: > > [notice] 1#0: getsockopt(TCP_DEFER_ACCEPT) for unix:/tmp/test.sock > failed, ignored (95: Operation not supported) Ok, fair enough. Wouldn't something like this be better then (untested)? # HG changeset patch # User Maxim Dounin # Date 1382758089 -14400 # Sat Oct 26 07:28:09 2013 +0400 # Node ID b4a2dbe4527b274d3b87b8cdab8e1637c379a05a # Parent e6a1623f87bc96d5ec62b6d77356aa47dbc60756 Core: handling of getsockopt(TCP_DEFER_ACCEPT) failures. Recent Linux versions started to return EOPNOTSUPP to getsockopt() calls on unix sockets, resulting in log pollution on binary upgrade. Silently ignore such errors. diff --git a/src/core/ngx_connection.c b/src/core/ngx_connection.c --- a/src/core/ngx_connection.c +++ b/src/core/ngx_connection.c @@ -93,8 +93,10 @@ ngx_set_inherited_sockets(ngx_cycle_t *c ngx_uint_t i; ngx_listening_t *ls; socklen_t olen; +#if (NGX_HAVE_DEFERRED_ACCEPT) + ngx_err_t err; +#endif #if (NGX_HAVE_DEFERRED_ACCEPT && defined SO_ACCEPTFILTER) - ngx_err_t err; struct accept_filter_arg af; #endif #if (NGX_HAVE_DEFERRED_ACCEPT && defined TCP_DEFER_ACCEPT) @@ -248,7 +250,13 @@ ngx_set_inherited_sockets(ngx_cycle_t *c if (getsockopt(ls[i].fd, IPPROTO_TCP, TCP_DEFER_ACCEPT, &timeout, &olen) == -1) { - ngx_log_error(NGX_LOG_NOTICE, cycle->log, ngx_errno, + err = ngx_errno; + + if (err == NGX_EOPNOTSUPP) { + continue; + } + + ngx_log_error(NGX_LOG_NOTICE, cycle->log, err, "getsockopt(TCP_DEFER_ACCEPT) for %V failed, ignored", &ls[i].addr_text); continue; diff --git a/src/os/unix/ngx_errno.h b/src/os/unix/ngx_errno.h --- a/src/os/unix/ngx_errno.h +++ b/src/os/unix/ngx_errno.h @@ -51,6 +51,7 @@ typedef int ngx_err_t; #define NGX_ENOMOREFILES 0 #define NGX_ELOOP ELOOP #define NGX_EBADF EBADF +#define NGX_EOPNOTSUPP EOPNOTSUPP #if (NGX_HAVE_OPENAT) #define NGX_EMLINK EMLINK -- Maxim Dounin http://nginx.org/en/donation.html From agentzh at gmail.com Sat Oct 26 05:55:08 2013 From: agentzh at gmail.com (Yichun Zhang (agentzh)) Date: Fri, 25 Oct 2013 22:55:08 -0700 Subject: [PATCH] ngx_gzip might hang the request for slow downstreams In-Reply-To: <20131026014815.GN7074@mdounin.ru> References: <20131026014815.GN7074@mdounin.ru> Message-ID: Hello! On Fri, Oct 25, 2013 at 6:48 PM, Maxim Dounin wrote: > > Could you please elaborate how do you see the problem? In 1.5.6 > this probably can be triggered with incomplete upstream response, > which intentionally results in no last buffer send, but with such > responses nothing is guaranteed anyway. And I don't think there > are any legitimate ways to trigger it in 1.4.3. > This is triggered by my own (3rd-party) module, ngx_lua. This module provides a ngx.flush(true) API function that flushes out all pending output data and *wait* (nonblockingly) until all outputs are *indeed* flushed out (into the system socket send buffer): https://github.com/chaoslawful/lua-nginx-module#ngxflush Best regards, -agentzh From agentzh at gmail.com Sat Oct 26 05:59:44 2013 From: agentzh at gmail.com (Yichun Zhang (agentzh)) Date: Fri, 25 Oct 2013 22:59:44 -0700 Subject: [PATCH] ngx_gzip might hang the request for slow downstreams In-Reply-To: References: <20131026014815.GN7074@mdounin.ru> Message-ID: Hello! On Fri, Oct 25, 2013 at 10:55 PM, Yichun Zhang (agentzh) wrote: > > This is triggered by my own (3rd-party) module, ngx_lua. This module > provides a ngx.flush(true) API function that flushes out all pending > output data and *wait* (nonblockingly) until all outputs are *indeed* > flushed out (into the system socket send buffer): > > https://github.com/chaoslawful/lua-nginx-module#ngxflush > Sorry, I pressed the mail send button too fast. Below are some more details: Under the hood, it sends out a special buf with ->flush set and then checks the return value of the output filter chain. If it is NGX_AGAIN, then wait for the next write event. Upon a new write event, call ngx_http_output_filter(r, NULL) to flush out the output and check r->connection->buffered to see if there's still any pending data. Is this the right way to do this? If not, do you have any suggestions? Thanks! -agentzh From mdounin at mdounin.ru Sat Oct 26 21:40:13 2013 From: mdounin at mdounin.ru (Maxim Dounin) Date: Sun, 27 Oct 2013 01:40:13 +0400 Subject: [PATCH] ngx_gzip might hang the request for slow downstreams In-Reply-To: References: <20131026014815.GN7074@mdounin.ru> Message-ID: <20131026214013.GP7074@mdounin.ru> Hello! On Fri, Oct 25, 2013 at 10:59:44PM -0700, Yichun Zhang (agentzh) wrote: > Hello! > > On Fri, Oct 25, 2013 at 10:55 PM, Yichun Zhang (agentzh) wrote: > > > > This is triggered by my own (3rd-party) module, ngx_lua. This module > > provides a ngx.flush(true) API function that flushes out all pending > > output data and *wait* (nonblockingly) until all outputs are *indeed* > > flushed out (into the system socket send buffer): > > > > https://github.com/chaoslawful/lua-nginx-module#ngxflush > > > > Sorry, I pressed the mail send button too fast. Below are some more details: > > Under the hood, it sends out a special buf with ->flush set and then > checks the return value of the output filter chain. If it is > NGX_AGAIN, then wait for the next write event. Upon a new write event, > call ngx_http_output_filter(r, NULL) to flush out the output and check > r->connection->buffered to see if there's still any pending data. > > Is this the right way to do this? If not, do you have any suggestions? Well, it would be good to adjust gzip (and other filters) to make this actually work. And I think something similar may be triggered using non-buffered proxy, too. Part of a response might be left in buffers till new data from an upstream is received (despite the fact that a client is again able to recieve the data, and non-buffered proxy tries to flush everything as fast as possible). I don't think the patch you suggested is correct though. At least it lacks update chains call. It may also make sense to look at the "if (ctx->nomem)" codepath, which is very similar and probably may be adjusted to handle this case as well. -- Maxim Dounin http://nginx.org/en/donation.html From agentzh at gmail.com Sat Oct 26 22:38:35 2013 From: agentzh at gmail.com (Yichun Zhang (agentzh)) Date: Sat, 26 Oct 2013 15:38:35 -0700 Subject: [PATCH] Request hang when cache_lock is used in subrequests Message-ID: Hello! Akos Gyimesi reported a request hang (downstream connections stuck in the CLOSE_WAIT state forever) regarding use of proxy_cache_lock in subrequests. The issue is that when proxy_cache_lock_timeout is reached, ngx_http_file_cache_lock_wait_handler calls r->connection->write->handler() directly, but r->connection->write->handler is (usually) just ngx_http_request_handler, which simply picks up r->connection->data, which is *not* necessarily the current (sub)request, so the current subrequest may never be continued nor finalized, leading to an infinite request hang. The following patch fixes this issue for me. Comments welcome! Thanks! -agentzh --- nginx-1.4.3/src/http/ngx_http_file_cache.c 2013-10-08 05:07:14.000000000 -0700 +++ nginx-1.4.3-patched/src/http/ngx_http_file_cache.c 2013-10-26 14:47:56.184041728 -0700 @@ -432,6 +432,7 @@ ngx_http_file_cache_lock_wait_handler(ng ngx_uint_t wait; ngx_msec_t timer; ngx_http_cache_t *c; + ngx_connection_t *conn; ngx_http_request_t *r; ngx_http_file_cache_t *cache; @@ -471,7 +472,10 @@ wakeup: c->waiting = 0; r->main->blocked--; - r->connection->write->handler(r->connection->write); + + conn = r->connection; + r->write_event_handler(r); + ngx_http_run_posted_requests(conn); } -------------- next part -------------- A non-text attachment was scrubbed... Name: nginx-1.4.3-cache_lock_hang_in_subreq.patch Type: text/x-patch Size: 705 bytes Desc: not available URL: From agentzh at gmail.com Sun Oct 27 00:16:38 2013 From: agentzh at gmail.com (Yichun Zhang (agentzh)) Date: Sat, 26 Oct 2013 17:16:38 -0700 Subject: [PATCH] ngx_gzip might hang the request for slow downstreams In-Reply-To: <20131026214013.GP7074@mdounin.ru> References: <20131026014815.GN7074@mdounin.ru> <20131026214013.GP7074@mdounin.ru> Message-ID: Hello! On Sat, Oct 26, 2013 at 2:40 PM, Maxim Dounin wrote: > > Well, it would be good to adjust gzip (and other filters) to make > this actually work. And I think something similar may be > triggered using non-buffered proxy, too. Part of a response might > be left in buffers till new data from an upstream is received > (despite the fact that a client is again able to recieve the data, > and non-buffered proxy tries to flush everything as fast as > possible). > Yeah, I was thinking along this line too ;) > I don't think the patch you suggested is correct though. At least > it lacks update chains call. It may also make sense to look at > the "if (ctx->nomem)" codepath, which is very similar and probably > may be adjusted to handle this case as well. > Thank you for the suggestions! How about the following patch? Regards, -agentzh --- nginx-1.4.3/src/http/modules/ngx_http_gzip_filter_module.c 2013-10-08 05:07:14.000000000 -0700 +++ nginx-1.4.3-patched/src/http/modules/ngx_http_gzip_filter_module.c 2013-10-26 17:14:22.132109569 -0700 @@ -370,11 +370,12 @@ ngx_http_gzip_body_filter(ngx_http_reque } } - if (ctx->nomem) { + if (ctx->nomem || in == NULL) { /* flush busy buffers */ - if (ngx_http_next_body_filter(r, NULL) == NGX_ERROR) { + rc = ngx_http_next_body_filter(r, NULL); + if (rc == NGX_ERROR) { goto failed; } @@ -383,6 +384,10 @@ ngx_http_gzip_body_filter(ngx_http_reque ngx_chain_update_chains(r->pool, &ctx->free, &ctx->busy, &cl, (ngx_buf_tag_t) &ngx_http_gzip_filter_module); ctx->nomem = 0; + + if (in == NULL) { + return rc; + } } for ( ;; ) { -------------- next part -------------- A non-text attachment was scrubbed... Name: nginx-1.4.3-gzip_flush_bug.patch Type: text/x-patch Size: 901 bytes Desc: not available URL: From mdounin at mdounin.ru Sun Oct 27 11:14:08 2013 From: mdounin at mdounin.ru (Maxim Dounin) Date: Sun, 27 Oct 2013 15:14:08 +0400 Subject: [PATCH] ngx_gzip might hang the request for slow downstreams In-Reply-To: References: <20131026014815.GN7074@mdounin.ru> <20131026214013.GP7074@mdounin.ru> Message-ID: <20131027111408.GQ7074@mdounin.ru> Hello! On Sat, Oct 26, 2013 at 05:16:38PM -0700, Yichun Zhang (agentzh) wrote: > Hello! > > On Sat, Oct 26, 2013 at 2:40 PM, Maxim Dounin wrote: > > > > Well, it would be good to adjust gzip (and other filters) to make > > this actually work. And I think something similar may be > > triggered using non-buffered proxy, too. Part of a response might > > be left in buffers till new data from an upstream is received > > (despite the fact that a client is again able to recieve the data, > > and non-buffered proxy tries to flush everything as fast as > > possible). > > > > Yeah, I was thinking along this line too ;) > > > I don't think the patch you suggested is correct though. At least > > it lacks update chains call. It may also make sense to look at > > the "if (ctx->nomem)" codepath, which is very similar and probably > > may be adjusted to handle this case as well. > > > > Thank you for the suggestions! How about the following patch? > > Regards, > -agentzh > > --- nginx-1.4.3/src/http/modules/ngx_http_gzip_filter_module.c > 2013-10-08 05:07:14.000000000 -0700 > +++ nginx-1.4.3-patched/src/http/modules/ngx_http_gzip_filter_module.c > 2013-10-26 17:14:22.132109569 -0700 > @@ -370,11 +370,12 @@ ngx_http_gzip_body_filter(ngx_http_reque > } > } > > - if (ctx->nomem) { > + if (ctx->nomem || in == NULL) { > > /* flush busy buffers */ > > - if (ngx_http_next_body_filter(r, NULL) == NGX_ERROR) { > + rc = ngx_http_next_body_filter(r, NULL); > + if (rc == NGX_ERROR) { > goto failed; > } Just a side note: this change is unrelated. > > @@ -383,6 +384,10 @@ ngx_http_gzip_body_filter(ngx_http_reque > ngx_chain_update_chains(r->pool, &ctx->free, &ctx->busy, &cl, > (ngx_buf_tag_t) &ngx_http_gzip_filter_module); > ctx->nomem = 0; > + > + if (in == NULL) { > + return rc; > + } > } > > for ( ;; ) { If there are pending data in ctx->in, they won't be handled. -- Maxim Dounin http://nginx.org/en/donation.html From mdounin at mdounin.ru Sun Oct 27 14:06:36 2013 From: mdounin at mdounin.ru (Maxim Dounin) Date: Sun, 27 Oct 2013 18:06:36 +0400 Subject: [PATCH] ngx_gzip might hang the request for slow downstreams In-Reply-To: <20131027111408.GQ7074@mdounin.ru> References: <20131026014815.GN7074@mdounin.ru> <20131026214013.GP7074@mdounin.ru> <20131027111408.GQ7074@mdounin.ru> Message-ID: <20131027140636.GR7074@mdounin.ru> Hello! On Sun, Oct 27, 2013 at 03:14:08PM +0400, Maxim Dounin wrote: [...] > > - if (ctx->nomem) { > > + if (ctx->nomem || in == NULL) { > > > > /* flush busy buffers */ > > > > - if (ngx_http_next_body_filter(r, NULL) == NGX_ERROR) { > > + rc = ngx_http_next_body_filter(r, NULL); > > + if (rc == NGX_ERROR) { > > goto failed; > > } > > Just a side note: this change is unrelated. Err, missed the use of "rc" in "return" below, disregrad this comment. [...] -- Maxim Dounin http://nginx.org/en/donation.html From agentzh at gmail.com Sun Oct 27 22:03:03 2013 From: agentzh at gmail.com (Yichun Zhang (agentzh)) Date: Sun, 27 Oct 2013 15:03:03 -0700 Subject: [PATCH] ngx_gzip might hang the request for slow downstreams In-Reply-To: <20131027111408.GQ7074@mdounin.ru> References: <20131026014815.GN7074@mdounin.ru> <20131026214013.GP7074@mdounin.ru> <20131027111408.GQ7074@mdounin.ru> Message-ID: Hello! On Sun, Oct 27, 2013 at 4:14 AM, Maxim Dounin wrote: >> ctx->nomem = 0; >> + >> + if (in == NULL) { >> + return rc; >> + } >> } >> >> for ( ;; ) { > > If there are pending data in ctx->in, they won't be handled. > Thank you for the catch! Updated my patch accordingly: --- nginx-1.4.3/src/http/modules/ngx_http_gzip_filter_module.c 2013-10-08 05:07:14.000000000 -0700 +++ nginx-1.4.3-patched/src/http/modules/ngx_http_gzip_filter_module.c 2013-10-27 14:53:49.723406912 -0700 @@ -370,7 +370,7 @@ ngx_http_gzip_body_filter(ngx_http_reque } } - if (ctx->nomem) { + if (ctx->nomem || in == NULL) { /* flush busy buffers */ -------------- next part -------------- A non-text attachment was scrubbed... Name: nginx-1.4.3-gzip_flush_bug.patch Type: text/x-patch Size: 385 bytes Desc: not available URL: From agentzh at gmail.com Sun Oct 27 22:46:05 2013 From: agentzh at gmail.com (Yichun Zhang (agentzh)) Date: Sun, 27 Oct 2013 15:46:05 -0700 Subject: [PATCH] Make $proxy_host and $proxy_port accessible in dynamic languages Message-ID: Hello! Recently a user of our ngx_lua module reported that he could not access $proxy_host and $proxy_port in Lua because these two variables set the flag NGX_HTTP_VAR_NOHASH: https://github.com/chaoslawful/lua-nginx-module/issues/301 The patch below removes this flag from these two variables to make them accessible in dynamic languages like Perl and Lua. Comments welcome! Thanks! -agentzh --- nginx-1.4.3/src/http/modules/ngx_http_proxy_module.c 2013-10-08 05:07:14.000000000 -0700 +++ nginx-1.4.3-patched/src/http/modules/ngx_http_proxy_module.c 2013-10-27 15:29:41.619378592 -0700 @@ -602,10 +602,10 @@ static ngx_keyval_t ngx_http_proxy_cach static ngx_http_variable_t ngx_http_proxy_vars[] = { { ngx_string("proxy_host"), NULL, ngx_http_proxy_host_variable, 0, - NGX_HTTP_VAR_CHANGEABLE|NGX_HTTP_VAR_NOCACHEABLE|NGX_HTTP_VAR_NOHASH, 0 }, + NGX_HTTP_VAR_CHANGEABLE|NGX_HTTP_VAR_NOCACHEABLE, 0 }, { ngx_string("proxy_port"), NULL, ngx_http_proxy_port_variable, 0, - NGX_HTTP_VAR_CHANGEABLE|NGX_HTTP_VAR_NOCACHEABLE|NGX_HTTP_VAR_NOHASH, 0 }, + NGX_HTTP_VAR_CHANGEABLE|NGX_HTTP_VAR_NOCACHEABLE, 0 }, { ngx_string("proxy_add_x_forwarded_for"), NULL, ngx_http_proxy_add_x_forwarded_for_variable, 0, NGX_HTTP_VAR_NOHASH, 0 }, -------------- next part -------------- A non-text attachment was scrubbed... Name: nginx-1.4.3-proxy_host_port_vars.patch Type: text/x-patch Size: 885 bytes Desc: not available URL: From guido.accardo at usmediaconsulting.com Mon Oct 28 13:51:42 2013 From: guido.accardo at usmediaconsulting.com (Guido Accardo) Date: Mon, 28 Oct 2013 11:51:42 -0200 Subject: Limit_req_status code less than 400 Message-ID: Hi everyone, I'm configuring nginx's module HttpLimitReqModule to limit requests at 2K r/s. I realize that this module only can return codes between 400 and 599 and as in my team we are developing Real Time Bedding we need to response http 204 No Content to those requests that exceeds our limit. Since this seems impossible to do by configuring nginx in a different way I'm planning to modify the code. Could you give me an idea in which parts of the code should I look at in order to modify them? Thank you in advance. Guido.- -------------- next part -------------- An HTML attachment was scrubbed... URL: From aviram at adallom.com Mon Oct 28 16:53:21 2013 From: aviram at adallom.com (Aviram Cohen) Date: Mon, 28 Oct 2013 18:53:21 +0200 Subject: [BUG] Gunzip module may cause requests to hang Message-ID: Hello! I have encountered the following possible bug in Nginx - When using the proxy_pass directive along with 'gunzip on;' in the same location, if replies from the remote server are empty but contain the header 'Content-Encoding: gzip', the request hangs (the worker process doesn't get stuck and can still serve other requests). This was reproduced in v1.4.3. If anyone can verify the problem and suggest a patch to solve the issue, that would be great. Regards, Aviram -- Aviram Cohen, R&D Adallom, 1 Ha'Barzel st., Tel-Aviv, Israel Mobile: +972 (54) 5833508 aviram at adallom.com, www.adallom.com -------------- next part -------------- An HTML attachment was scrubbed... URL: From mdounin at mdounin.ru Mon Oct 28 18:17:57 2013 From: mdounin at mdounin.ru (Maxim Dounin) Date: Mon, 28 Oct 2013 22:17:57 +0400 Subject: Limit_req_status code less than 400 In-Reply-To: References: Message-ID: <20131028181757.GU7074@mdounin.ru> Hello! On Mon, Oct 28, 2013 at 11:51:42AM -0200, Guido Accardo wrote: > Hi everyone, > > I'm configuring nginx's module HttpLimitReqModule to limit requests at 2K > r/s. I realize that this module only can return codes between 400 and 599 > and as in my team we are developing Real Time Bedding we need to response > http 204 No Content to those requests that exceeds our limit. Since this > seems impossible to do by configuring nginx in a different way I'm planning > to modify the code. Could you give me an idea in which parts of the code > should I look at in order to modify them? There is no need to modify the code, just use error_page directive. error_page 503 = /empty; location = /empty { return 204; } -- Maxim Dounin http://nginx.org/en/donation.html From mdounin at mdounin.ru Mon Oct 28 20:21:53 2013 From: mdounin at mdounin.ru (Maxim Dounin) Date: Tue, 29 Oct 2013 00:21:53 +0400 Subject: [BUG] Gunzip module may cause requests to hang In-Reply-To: References: Message-ID: <20131028202153.GV7074@mdounin.ru> Hello! On Mon, Oct 28, 2013 at 06:53:21PM +0200, Aviram Cohen wrote: > Hello! > > I have encountered the following possible bug in Nginx - > When using the proxy_pass directive along with 'gunzip on;' in the same > location, if replies from the remote server are empty but contain the > header 'Content-Encoding: gzip', the request hangs (the worker process > doesn't get stuck and can still serve other requests). > > This was reproduced in v1.4.3. > > If anyone can verify the problem and suggest a patch to solve the issue, > that would be great. Something like this should be appropriate: --- a/src/http/modules/ngx_http_gunzip_filter_module.c +++ b/src/http/modules/ngx_http_gunzip_filter_module.c @@ -500,9 +500,13 @@ ngx_http_gunzip_filter_inflate(ngx_http_ return NGX_OK; } - if (rc == Z_STREAM_END && ctx->flush == Z_FINISH - && ctx->zstream.avail_in == 0) - { + if (ctx->flush == Z_FINISH && ctx->zstream.avail_in == 0) { + + if (rc != Z_STREAM_END) { + ngx_log_error(NGX_LOG_ERR, r->connection->log, 0, + "inflate() returned %d on response end", rc); + return NGX_ERROR; + } if (ngx_http_gunzip_filter_inflate_end(r, ctx) != NGX_OK) { return NGX_ERROR; It will close a connection on such a malformed backend response and will log appropriate error. -- Maxim Dounin http://nginx.org/en/donation.html From mdounin at mdounin.ru Mon Oct 28 20:41:08 2013 From: mdounin at mdounin.ru (Maxim Dounin) Date: Tue, 29 Oct 2013 00:41:08 +0400 Subject: [PATCH] Make $proxy_host and $proxy_port accessible in dynamic languages In-Reply-To: References: Message-ID: <20131028204108.GX7074@mdounin.ru> Hello! On Sun, Oct 27, 2013 at 03:46:05PM -0700, Yichun Zhang (agentzh) wrote: > Hello! > > Recently a user of our ngx_lua module reported that he could not > access $proxy_host and $proxy_port in Lua because these two variables > set the flag NGX_HTTP_VAR_NOHASH: > > https://github.com/chaoslawful/lua-nginx-module/issues/301 > > The patch below removes this flag from these two variables to make > them accessible in dynamic languages like Perl and Lua. Comments > welcome! What's the intended use? Note that variables are marked as NOHASH if they are not expected to be usable in dynamic cases like embedded perl/ssi. This allows to reduce variables hash size and to speed up things. Just removing the flag without real need looks silly. -- Maxim Dounin http://nginx.org/en/donation.html From mdounin at mdounin.ru Mon Oct 28 21:02:31 2013 From: mdounin at mdounin.ru (Maxim Dounin) Date: Tue, 29 Oct 2013 01:02:31 +0400 Subject: [PATCH] ngx_gzip might hang the request for slow downstreams In-Reply-To: References: <20131026014815.GN7074@mdounin.ru> <20131026214013.GP7074@mdounin.ru> <20131027111408.GQ7074@mdounin.ru> Message-ID: <20131028210231.GZ7074@mdounin.ru> Hello! On Sun, Oct 27, 2013 at 03:03:03PM -0700, Yichun Zhang (agentzh) wrote: > Hello! > > On Sun, Oct 27, 2013 at 4:14 AM, Maxim Dounin wrote: > >> ctx->nomem = 0; > >> + > >> + if (in == NULL) { > >> + return rc; > >> + } > >> } > >> > >> for ( ;; ) { > > > > If there are pending data in ctx->in, they won't be handled. > > > > Thank you for the catch! Updated my patch accordingly: > > --- nginx-1.4.3/src/http/modules/ngx_http_gzip_filter_module.c > 2013-10-08 05:07:14.000000000 -0700 > +++ nginx-1.4.3-patched/src/http/modules/ngx_http_gzip_filter_module.c > 2013-10-27 14:53:49.723406912 -0700 > @@ -370,7 +370,7 @@ ngx_http_gzip_body_filter(ngx_http_reque > } > } > > - if (ctx->nomem) { > + if (ctx->nomem || in == NULL) { > > /* flush busy buffers */ Is the same problem exists in the gunzip filter, which has very similar code? Is a similar patch needed there? And, BTW, do you care to provide a Mercurial changeset, as suggested by nginx.org/en/docs/contributing_changes.html? It's not something required, but will make sure your name will be kept in history as a proper person to blame. :) -- Maxim Dounin http://nginx.org/en/donation.html From piotr at cloudflare.com Mon Oct 28 21:16:48 2013 From: piotr at cloudflare.com (Piotr Sikora) Date: Mon, 28 Oct 2013 14:16:48 -0700 Subject: [PATCH] Core: stop trying to get TCP_DEFER_ACCEPT from unix sockets. In-Reply-To: <20131026033110.GO7074@mdounin.ru> References: <20131025181628.GM7074@mdounin.ru> <20131026033110.GO7074@mdounin.ru> Message-ID: Hey Maxim, > Ok, fair enough. Wouldn't something like this be better then > (untested)? It would, originally I had pretty much the same patch, but for some reason I thought you'd like the one I send better. Tested and works fine. > --- a/src/os/unix/ngx_errno.h > +++ b/src/os/unix/ngx_errno.h > @@ -51,6 +51,7 @@ typedef int ngx_err_t; > #define NGX_ENOMOREFILES 0 > #define NGX_ELOOP ELOOP > #define NGX_EBADF EBADF > +#define NGX_EOPNOTSUPP EOPNOTSUPP Just a nitpick, but I believe that NGX_EOPNOTSUPP should be added between NGX_EINPROGRESS & NGX_EADDRINUSE, to keep the order the same as in system's errno.h. Best regards, Piotr Sikora From agentzh at gmail.com Mon Oct 28 21:44:45 2013 From: agentzh at gmail.com (Yichun Zhang (agentzh)) Date: Mon, 28 Oct 2013 14:44:45 -0700 Subject: [PATCH] Make $proxy_host and $proxy_port accessible in dynamic languages In-Reply-To: <20131028204108.GX7074@mdounin.ru> References: <20131028204108.GX7074@mdounin.ru> Message-ID: Hello! On Mon, Oct 28, 2013 at 1:41 PM, Maxim Dounin wrote: > > What's the intended use? I cannot really speak for my user. But one use case that I can think of is for (nonblocking) access logging in Lua, for example, as in https://github.com/cloudflare/lua-resty-logger-socket where we can log $proxy_host and $proxy_port to a nonblocking socket in Lua :) Best regards, -agentzh From agentzh at gmail.com Mon Oct 28 22:37:44 2013 From: agentzh at gmail.com (Yichun Zhang (agentzh)) Date: Mon, 28 Oct 2013 15:37:44 -0700 Subject: [PATCH] ngx_gzip might hang the request for slow downstreams In-Reply-To: <20131028210231.GZ7074@mdounin.ru> References: <20131026014815.GN7074@mdounin.ru> <20131026214013.GP7074@mdounin.ru> <20131027111408.GQ7074@mdounin.ru> <20131028210231.GZ7074@mdounin.ru> Message-ID: Hello! On Mon, Oct 28, 2013 at 2:02 PM, Maxim Dounin wrote: >> >> - if (ctx->nomem) { >> + if (ctx->nomem || in == NULL) { >> >> /* flush busy buffers */ > > Is the same problem exists in the gunzip filter, which has very > similar code? Yes. I've reproduced the request hang in the gunzip filter module as well, with the following minimal test case: https://github.com/chaoslawful/lua-nginx-module/commit/594f55b > Is a similar patch needed there? > Yes. I can confirm that a similar patch fixes the hang on my side. > And, BTW, do you care to provide a Mercurial changeset, as > suggested by nginx.org/en/docs/contributing_changes.html? It's > not something required, but will make sure your name will be kept > in history as a proper person to blame. :) > Here we go: # HG changeset patch # User Yichun Zhang # Date 1382997696 25200 # Branch gzip-flush # Node ID 8985d6cc9a4334e954909c130e6204c6fc673d7e # Parent e6a1623f87bc96d5ec62b6d77356aa47dbc60756 Flush pending data when incoming chain is NULL in gzip and gunzip modules diff -r e6a1623f87bc -r 8985d6cc9a43 src/http/modules/ngx_http_gunzip_filter_module.c --- a/src/http/modules/ngx_http_gunzip_filter_module.c Mon Oct 21 18:20:32 2013 +0800 +++ b/src/http/modules/ngx_http_gunzip_filter_module.c Mon Oct 28 15:01:36 2013 -0700 @@ -199,7 +199,7 @@ } } - if (ctx->nomem) { + if (ctx->nomem || in == NULL) { /* flush busy buffers */ diff -r e6a1623f87bc -r 8985d6cc9a43 src/http/modules/ngx_http_gzip_filter_module.c --- a/src/http/modules/ngx_http_gzip_filter_module.c Mon Oct 21 18:20:32 2013 +0800 +++ b/src/http/modules/ngx_http_gzip_filter_module.c Mon Oct 28 15:01:36 2013 -0700 @@ -372,7 +372,7 @@ r->connection->buffered |= NGX_HTTP_GZIP_BUFFERED; } - if (ctx->nomem) { + if (ctx->nomem || in == NULL) { /* flush busy buffers */ -------------- next part -------------- A non-text attachment was scrubbed... Name: gzip_gunzip_flush_bug.patch Type: text/x-patch Size: 1117 bytes Desc: not available URL: From toshic.toshic at gmail.com Tue Oct 29 12:06:35 2013 From: toshic.toshic at gmail.com (ToSHiC) Date: Tue, 29 Oct 2013 16:06:35 +0400 Subject: IPv6 support in resolver In-Reply-To: <51E3F300.3070509@nginx.com> References: <20130617153021.GH72282@mdounin.ru> <51E3F300.3070509@nginx.com> Message-ID: Hello, Yesterday you had a talk on Highload++ and said about lack of IPv6 resolver support. Do you have any news about my patch? Regards, Anton Kortunov. On Mon, Jul 15, 2013 at 5:02 PM, Maxim Konovalov wrote: > Hi Anton, > > First of all, thanks for the patches! > > Just want to let you know that we have a ticket in our internal > system assigned your patches to the developer for review but it'll > take some time due to other tasks and complexity of the patch series. > > On 7/10/13 9:17 PM, ToSHiC wrote: > > Hello, > > > > I've split this big patch into several small patches, taking into > > account your comments. I'll send each part in separate email. Here > > is the first one. > > > > commit 597d09e7ae9247c5466b18aa2ef3f5892e61b708 > > Author: Anton Kortunov > > > > Date: Wed Jul 10 13:14:52 2013 +0400 > > > > Added new structure ngx_ipaddr_t > > > > This structure contains family field > > and the union of ipv4/ipv6 structures in_addr_t and in6_addr. > > > > diff --git a/src/core/ngx_inet.h b/src/core/ngx_inet.h > > index 6a5a368..077ed34 100644 > > --- a/src/core/ngx_inet.h > > +++ b/src/core/ngx_inet.h > > @@ -68,6 +68,16 @@ typedef struct { > > > > > > typedef struct { > > + ngx_uint_t family; > > + union { > > + in_addr_t v4; > > +#if (NGX_HAVE_INET6) > > + struct in6_addr v6; > > +#endif > > + } u; > > +} ngx_ipaddr_t; > > + > > +typedef struct { > > struct sockaddr *sockaddr; > > socklen_t socklen; > > ngx_str_t name; > > > > > > > > On Mon, Jun 17, 2013 at 7:30 PM, Maxim Dounin > > wrote: > > > > Hello! > > > > On Fri, Jun 14, 2013 at 09:44:46PM +0400, ToSHiC wrote: > > > > > Hello, > > > > > > We needed this feature in our company, I found that it is in > > milestones of > > > version 1.5 but doesn't exist yet. So I've implemented it > > based in 1.3 code > > > and merged in current 1.5 code. When I wrote this code I > > mostly cared about > > > minimum intrusion into other parts of nginx. > > > > > > IPv6 fallback logic is not a straightforward implementation of > > suggested by > > > RFC. RFC states that IPv6 resolving have priority over IPv4, > > and it's not > > > very good for Internet we have currently. With this patch you > > can specify > > > priority, and in upstream and mail modules I've set IPv4 as > > preferred > > > address family. > > > > > > Patch is pretty big and I hope it'll not break mailing list or > > mail clients. > > > > You may want to try to split the patch into smaller patches to > > simplify review. See also some hints here: > > > > http://nginx.org/en/docs/contributing_changes.html > > > > Some quick comments below. > > > > [...] > > > > > - addr = ntohl(ctx->addr); > > > +failed: > > > + > > > + //addr = ntohl(ctx->addr); > > > + inet_ntop(ctx->addr.family, &ctx->addr.u, text, > > > NGX_SOCKADDR_STRLEN); > > > > > > ngx_log_error(NGX_LOG_ALERT, r->log, 0, > > > - "could not cancel %ud.%ud.%ud.%ud > > resolving", > > > - (addr >> 24) & 0xff, (addr >> 16) & 0xff, > > > - (addr >> 8) & 0xff, addr & 0xff); > > > + "could not cancel %s resolving", text); > > > > 1. Don't use inet_ntop(), there is ngx_sock_ntop() instead. > > > > 2. Don't use C++ style ("//") comments. > > > > 3. If some data is only needed for debug logging, keep relevant > > calculations under #if (NGX_DEBUG). > > > > [...] > > > > > @@ -334,6 +362,7 @@ > > > ngx_http_upstream_create_round_robin_peer(ngx_http_request_t *r, > > > peers->peer[i].current_weight = 0; > > > peers->peer[i].max_fails = 1; > > > peers->peer[i].fail_timeout = 10; > > > + > > > } > > > } > > > > > > > Please avoid unrelated changes. > > > > [...] > > > > -- > > Maxim Dounin > > http://nginx.org/en/donation.html > > > > _______________________________________________ > > 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 > > > > > -- > Maxim Konovalov > +7 (910) 4293178 > http://nginx.com/services.html > -------------- next part -------------- An HTML attachment was scrubbed... URL: From maxim at nginx.com Tue Oct 29 12:54:54 2013 From: maxim at nginx.com (Maxim Konovalov) Date: Tue, 29 Oct 2013 16:54:54 +0400 Subject: IPv6 support in resolver In-Reply-To: References: <20130617153021.GH72282@mdounin.ru> <51E3F300.3070509@nginx.com> Message-ID: <526FB01E.5040706@nginx.com> Hi Anton, we are planning to work on IPv6 resolver support in November. This feature is already in 1.5 trunk roadmap. On 10/29/13 4:06 PM, ToSHiC wrote: > Hello, > > Yesterday you had a talk on Highload++ and said about lack of IPv6 > resolver support. Do you have any news about my patch? > > Regards, > Anton Kortunov. > > > On Mon, Jul 15, 2013 at 5:02 PM, Maxim Konovalov > wrote: > > Hi Anton, > > First of all, thanks for the patches! > > Just want to let you know that we have a ticket in our internal > system assigned your patches to the developer for review but it'll > take some time due to other tasks and complexity of the patch > series. > > On 7/10/13 9:17 PM, ToSHiC wrote: > > Hello, > > > > I've split this big patch into several small patches, taking into > > account your comments. I'll send each part in separate email. Here > > is the first one. > > > > commit 597d09e7ae9247c5466b18aa2ef3f5892e61b708 > > Author: Anton Kortunov > > >> > > Date: Wed Jul 10 13:14:52 2013 +0400 > > > > Added new structure ngx_ipaddr_t > > > > This structure contains family field > > and the union of ipv4/ipv6 structures in_addr_t and in6_addr. > > > > diff --git a/src/core/ngx_inet.h b/src/core/ngx_inet.h > > index 6a5a368..077ed34 100644 > > --- a/src/core/ngx_inet.h > > +++ b/src/core/ngx_inet.h > > @@ -68,6 +68,16 @@ typedef struct { > > > > > > typedef struct { > > + ngx_uint_t family; > > + union { > > + in_addr_t v4; > > +#if (NGX_HAVE_INET6) > > + struct in6_addr v6; > > +#endif > > + } u; > > +} ngx_ipaddr_t; > > + > > +typedef struct { > > struct sockaddr *sockaddr; > > socklen_t socklen; > > ngx_str_t name; > > > > > > > > On Mon, Jun 17, 2013 at 7:30 PM, Maxim Dounin > > > >> wrote: > > > > Hello! > > > > On Fri, Jun 14, 2013 at 09:44:46PM +0400, ToSHiC wrote: > > > > > Hello, > > > > > > We needed this feature in our company, I found that it is in > > milestones of > > > version 1.5 but doesn't exist yet. So I've implemented it > > based in 1.3 code > > > and merged in current 1.5 code. When I wrote this code I > > mostly cared about > > > minimum intrusion into other parts of nginx. > > > > > > IPv6 fallback logic is not a straightforward > implementation of > > suggested by > > > RFC. RFC states that IPv6 resolving have priority over IPv4, > > and it's not > > > very good for Internet we have currently. With this > patch you > > can specify > > > priority, and in upstream and mail modules I've set IPv4 as > > preferred > > > address family. > > > > > > Patch is pretty big and I hope it'll not break mailing > list or > > mail clients. > > > > You may want to try to split the patch into smaller patches to > > simplify review. See also some hints here: > > > > http://nginx.org/en/docs/contributing_changes.html > > > > Some quick comments below. > > > > [...] > > > > > - addr = ntohl(ctx->addr); > > > +failed: > > > + > > > + //addr = ntohl(ctx->addr); > > > + inet_ntop(ctx->addr.family, &ctx->addr.u, text, > > > NGX_SOCKADDR_STRLEN); > > > > > > ngx_log_error(NGX_LOG_ALERT, r->log, 0, > > > - "could not cancel %ud.%ud.%ud.%ud > > resolving", > > > - (addr >> 24) & 0xff, (addr >> 16) > & 0xff, > > > - (addr >> 8) & 0xff, addr & 0xff); > > > + "could not cancel %s resolving", > text); > > > > 1. Don't use inet_ntop(), there is ngx_sock_ntop() instead. > > > > 2. Don't use C++ style ("//") comments. > > > > 3. If some data is only needed for debug logging, keep > relevant > > calculations under #if (NGX_DEBUG). > > > > [...] > > > > > @@ -334,6 +362,7 @@ > > > > ngx_http_upstream_create_round_robin_peer(ngx_http_request_t *r, > > > peers->peer[i].current_weight = 0; > > > peers->peer[i].max_fails = 1; > > > peers->peer[i].fail_timeout = 10; > > > + > > > } > > > } > > > > > > > Please avoid unrelated changes. > > > > [...] > > > > -- > > Maxim Dounin > > http://nginx.org/en/donation.html > > > > _______________________________________________ > > 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 > > > > > -- > Maxim Konovalov > +7 (910) 4293178 > http://nginx.com/services.html > > -- Maxim Konovalov http://nginx.com From rob.stradling at comodo.com Tue Oct 29 21:44:46 2013 From: rob.stradling at comodo.com (Rob Stradling) Date: Tue, 29 Oct 2013 21:44:46 +0000 Subject: Optimizing TLS Record Size & Buffering Latency Message-ID: <52702C4E.4050004@comodo.com> http://www.igvita.com/2013/10/24/optimizing-tls-record-size-and-buffering-latency/ "The larger the TLS record size, the higher the likelihood that we may incur an additional roundtrip due to a TCP retransmission or "overflow" of the congestion window. That said, the fix is also relatively simple: send smaller records. In fact, to eliminate this problem entirely, configure your TLS record size to fit into a single TCP segment. ... The bad news is that many TLS servers do not provide an easy way to configure TLS record size and instead use the default maximum of 16 KB. ... Nginx hardcodes 16KB size in ngx_event_openssl, which you can change and recompile from source." Would it be worth lowering this default value? and/or How about adding a config directive that allows users to change it without having to edit the source code? -- Rob Stradling Senior Research & Development Scientist COMODO - Creating Trust Online From piotr at cloudflare.com Tue Oct 29 21:48:05 2013 From: piotr at cloudflare.com (Piotr Sikora) Date: Tue, 29 Oct 2013 14:48:05 -0700 Subject: Optimizing TLS Record Size & Buffering Latency In-Reply-To: <52702C4E.4050004@comodo.com> References: <52702C4E.4050004@comodo.com> Message-ID: Hey Rob, > How about adding a config directive that allows users to change it without > having to edit the source code? Funny you mention that, I just started working on making this a configure option. It's been on my TODO list forever, but Ilya's article brought it to my attention again :) Best regards, Piotr Sikora From aaron.peschel at gmail.com Tue Oct 29 22:04:15 2013 From: aaron.peschel at gmail.com (Aaron Peschel) Date: Tue, 29 Oct 2013 15:04:15 -0700 Subject: Add Support for Weak ETags In-Reply-To: References: Message-ID: On Fri, Oct 25, 2013 at 2:54 PM, Piotr Sikora wrote: > Hi Aaron, > I disagree with your patch... While retaining weak ETags in case of > gzip/gunzip modules is correct, other modules are modifying the > content and weak ETags should be removed from responses processed by > them. > > Best regards, > Piotr Sikora > > _______________________________________________ > nginx-devel mailing list > nginx-devel at nginx.org > http://mailman.nginx.org/mailman/listinfo/nginx-devel What are your thoughts on the correct way to proceed from here? Should there be two macros, ngx_http_clear_strict_etag and ngx_http_clear_etag and then have the gunzip and gzip only clear the strict etag? EG #define ngx_http_clear_etag(r) \ \ if (r->headers_out.etag) { \ r->headers_out.etag->hash = 0; \ r->headers_out.etag = NULL; \ } #define ngx_http_clear_strict_etag(r) \ \ if (r->headers_out.etag) { \ if (! ngx_strncmp(r->headers_out.etag->value.data, "W/", 2)) { \ r->headers_out.etag->hash = 0; \ r->headers_out.etag = NULL; \ } \ } The gzip module is the module I am most interested in providing weak ETag support for. Please let me know what the suggested path is here, and I will put in the work for it. Thank you, -Aaron From alex at zeitgeist.se Tue Oct 29 23:32:19 2013 From: alex at zeitgeist.se (Alex) Date: Wed, 30 Oct 2013 00:32:19 +0100 Subject: Optimizing TLS Record Size & Buffering Latency In-Reply-To: References: <52702C4E.4050004@comodo.com> Message-ID: > Funny you mention that, I just started working on making this a > configure option. That's great news, Piotr! In the blog entry Ilya states that Google servers make TLS records fit into single network segment (so that means something like a NGX_SSL_BUFSIZE of 1460 minus overhead, timestamps disabled). In the TLS chapter in his book, however, he stated that Google uses SSL buffers of "about 5 KB", so that's more like one TLS record sent through 3-4 TCP segments). I guess it will require some testing. From mdounin at mdounin.ru Wed Oct 30 13:56:10 2013 From: mdounin at mdounin.ru (Maxim Dounin) Date: Wed, 30 Oct 2013 17:56:10 +0400 Subject: IPv6 support in resolver In-Reply-To: References: <20130617153021.GH72282@mdounin.ru> <51E3F300.3070509@nginx.com> Message-ID: <20131030135610.GH84761@mdounin.ru> Hello! On Tue, Oct 29, 2013 at 04:06:35PM +0400, ToSHiC wrote: > Hello, > > Yesterday you had a talk on Highload++ and said about lack of IPv6 resolver > support. Do you have any news about my patch? Just in case, it was me who had a talk, there are lots of Maxim's here. ;) Ruslan Ermilov, who is mostly responsible for IPv6 improvements in the code, looked into your patch and he isn't happy with many parts of it. As Maxim Konovalov already replied, more work on this is expected to happen soon. -- Maxim Dounin http://nginx.org/en/donation.html From mdounin at mdounin.ru Wed Oct 30 14:17:50 2013 From: mdounin at mdounin.ru (Maxim Dounin) Date: Wed, 30 Oct 2013 18:17:50 +0400 Subject: [PATCH] Make $proxy_host and $proxy_port accessible in dynamic languages In-Reply-To: References: <20131028204108.GX7074@mdounin.ru> Message-ID: <20131030141749.GI84761@mdounin.ru> Hello! On Mon, Oct 28, 2013 at 02:44:45PM -0700, Yichun Zhang (agentzh) wrote: > Hello! > > On Mon, Oct 28, 2013 at 1:41 PM, Maxim Dounin wrote: > > > > What's the intended use? > > I cannot really speak for my user. But one use case that I can think > of is for (nonblocking) access logging in Lua, for example, as in > > https://github.com/cloudflare/lua-resty-logger-socket > > where we can log $proxy_host and $proxy_port to a nonblocking socket in Lua :) For logging, there is $upstream_addr variable, which is actually contatains some additional information, while $proxy_host is just a result of parsing the proxy_pass directive arguments. The $proxy_host/$proxy_port variables are mostly for use in proxy_set_header Host, much like $proxy_add_x_forwarded_for. Note well, that if there is a need to access these variables from dynamic languages for some reason, it can be easily done by adding a map{} into a configuration. I tend to say "no", at least unless a better use case provided. -- Maxim Dounin http://nginx.org/en/donation.html From mdounin at mdounin.ru Thu Oct 31 00:01:06 2013 From: mdounin at mdounin.ru (Maxim Dounin) Date: Thu, 31 Oct 2013 00:01:06 +0000 Subject: [nginx] Core: apply missed options to sockets added during binar... Message-ID: details: http://hg.nginx.org/nginx/rev/d8ee8ef5dcde branches: changeset: 5430:d8ee8ef5dcde user: Piotr Sikora date: Thu Oct 24 14:18:37 2013 -0700 description: Core: apply missed options to sockets added during binary upgrade. The accept_filter and deferred options were not applied to sockets that were added to configuration during binary upgrade cycle. Signed-off-by: Piotr Sikora diffstat: src/core/ngx_cycle.c | 10 ++++++++++ 1 files changed, 10 insertions(+), 0 deletions(-) diffs (20 lines): diff --git a/src/core/ngx_cycle.c b/src/core/ngx_cycle.c --- a/src/core/ngx_cycle.c +++ b/src/core/ngx_cycle.c @@ -545,6 +545,16 @@ ngx_init_cycle(ngx_cycle_t *old_cycle) if (nls[n].fd == (ngx_socket_t) -1) { nls[n].open = 1; +#if (NGX_HAVE_DEFERRED_ACCEPT && defined SO_ACCEPTFILTER) + if (nls[n].accept_filter) { + nls[n].add_deferred = 1; + } +#endif +#if (NGX_HAVE_DEFERRED_ACCEPT && defined TCP_DEFER_ACCEPT) + if (nls[n].deferred_accept) { + nls[n].add_deferred = 1; + } +#endif } } From mdounin at mdounin.ru Thu Oct 31 00:01:07 2013 From: mdounin at mdounin.ru (Maxim Dounin) Date: Thu, 31 Oct 2013 00:01:07 +0000 Subject: [nginx] Core: handling of getsockopt(TCP_DEFER_ACCEPT) failures. Message-ID: details: http://hg.nginx.org/nginx/rev/91bd62a9627e branches: changeset: 5431:91bd62a9627e user: Maxim Dounin date: Thu Oct 31 04:00:37 2013 +0400 description: Core: handling of getsockopt(TCP_DEFER_ACCEPT) failures. Recent Linux versions started to return EOPNOTSUPP to getsockopt() calls on unix sockets, resulting in log pollution on binary upgrade. Such errors are silently ignored now. diffstat: src/core/ngx_connection.c | 12 ++++++++++-- src/os/unix/ngx_errno.h | 1 + src/os/win32/ngx_errno.h | 1 + 3 files changed, 12 insertions(+), 2 deletions(-) diffs (52 lines): diff --git a/src/core/ngx_connection.c b/src/core/ngx_connection.c --- a/src/core/ngx_connection.c +++ b/src/core/ngx_connection.c @@ -93,8 +93,10 @@ ngx_set_inherited_sockets(ngx_cycle_t *c ngx_uint_t i; ngx_listening_t *ls; socklen_t olen; +#if (NGX_HAVE_DEFERRED_ACCEPT) + ngx_err_t err; +#endif #if (NGX_HAVE_DEFERRED_ACCEPT && defined SO_ACCEPTFILTER) - ngx_err_t err; struct accept_filter_arg af; #endif #if (NGX_HAVE_DEFERRED_ACCEPT && defined TCP_DEFER_ACCEPT) @@ -248,7 +250,13 @@ ngx_set_inherited_sockets(ngx_cycle_t *c if (getsockopt(ls[i].fd, IPPROTO_TCP, TCP_DEFER_ACCEPT, &timeout, &olen) == -1) { - ngx_log_error(NGX_LOG_NOTICE, cycle->log, ngx_errno, + err = ngx_errno; + + if (err == NGX_EOPNOTSUPP) { + continue; + } + + ngx_log_error(NGX_LOG_NOTICE, cycle->log, err, "getsockopt(TCP_DEFER_ACCEPT) for %V failed, ignored", &ls[i].addr_text); continue; diff --git a/src/os/unix/ngx_errno.h b/src/os/unix/ngx_errno.h --- a/src/os/unix/ngx_errno.h +++ b/src/os/unix/ngx_errno.h @@ -34,6 +34,7 @@ typedef int ngx_err_t; #define NGX_ENOSPC ENOSPC #define NGX_EPIPE EPIPE #define NGX_EINPROGRESS EINPROGRESS +#define NGX_EOPNOTSUPP EOPNOTSUPP #define NGX_EADDRINUSE EADDRINUSE #define NGX_ECONNABORTED ECONNABORTED #define NGX_ECONNRESET ECONNRESET diff --git a/src/os/win32/ngx_errno.h b/src/os/win32/ngx_errno.h --- a/src/os/win32/ngx_errno.h +++ b/src/os/win32/ngx_errno.h @@ -38,6 +38,7 @@ typedef DWORD ngx_e #define NGX_EPIPE EPIPE #define NGX_EAGAIN WSAEWOULDBLOCK #define NGX_EINPROGRESS WSAEINPROGRESS +#define NGX_EOPNOTSUPP WSAEOPNOTSUPP #define NGX_EADDRINUSE WSAEADDRINUSE #define NGX_ECONNABORTED WSAECONNABORTED #define NGX_ECONNRESET WSAECONNRESET From mdounin at mdounin.ru Thu Oct 31 00:04:48 2013 From: mdounin at mdounin.ru (Maxim Dounin) Date: Thu, 31 Oct 2013 04:04:48 +0400 Subject: [PATCH] Core: stop trying to get TCP_DEFER_ACCEPT from unix sockets. In-Reply-To: References: <20131025181628.GM7074@mdounin.ru> <20131026033110.GO7074@mdounin.ru> Message-ID: <20131031000448.GJ84761@mdounin.ru> Hello! On Mon, Oct 28, 2013 at 02:16:48PM -0700, Piotr Sikora wrote: > Hey Maxim, > > > Ok, fair enough. Wouldn't something like this be better then > > (untested)? > > It would, originally I had pretty much the same patch, but for some > reason I thought you'd like the one I send better. > > Tested and works fine. > > > --- a/src/os/unix/ngx_errno.h > > +++ b/src/os/unix/ngx_errno.h > > @@ -51,6 +51,7 @@ typedef int ngx_err_t; > > #define NGX_ENOMOREFILES 0 > > #define NGX_ELOOP ELOOP > > #define NGX_EBADF EBADF > > +#define NGX_EOPNOTSUPP EOPNOTSUPP > > Just a nitpick, but I believe that NGX_EOPNOTSUPP should be added > between NGX_EINPROGRESS & NGX_EADDRINUSE, to keep the order the same > as in system's errno.h. Sure, fixed (and added win32 define for completeness). Committed, thanks. -- Maxim Dounin http://nginx.org/en/donation.html From mdounin at mdounin.ru Thu Oct 31 00:05:10 2013 From: mdounin at mdounin.ru (Maxim Dounin) Date: Thu, 31 Oct 2013 04:05:10 +0400 Subject: [PATCH] Core: apply missed options to sockets added during binary upgrade. In-Reply-To: References: Message-ID: <20131031000510.GK84761@mdounin.ru> Hello! On Thu, Oct 24, 2013 at 02:22:05PM -0700, Piotr Sikora wrote: > # HG changeset patch > # User Piotr Sikora > # Date 1382649517 25200 > # Thu Oct 24 14:18:37 2013 -0700 > # Node ID d8ee8ef5dcde554bf1d89d61912e6e6f3c5573f2 > # Parent e6a1623f87bc96d5ec62b6d77356aa47dbc60756 > Core: apply missed options to sockets added during binary upgrade. > > The accept_filter and deferred options were not applied to sockets > that were added to configuration during binary upgrade cycle. > > Signed-off-by: Piotr Sikora > > diff -r e6a1623f87bc -r d8ee8ef5dcde src/core/ngx_cycle.c > --- a/src/core/ngx_cycle.c Mon Oct 21 18:20:32 2013 +0800 > +++ b/src/core/ngx_cycle.c Thu Oct 24 14:18:37 2013 -0700 > @@ -545,6 +545,16 @@ ngx_init_cycle(ngx_cycle_t *old_cycle) > > if (nls[n].fd == (ngx_socket_t) -1) { > nls[n].open = 1; > +#if (NGX_HAVE_DEFERRED_ACCEPT && defined SO_ACCEPTFILTER) > + if (nls[n].accept_filter) { > + nls[n].add_deferred = 1; > + } > +#endif > +#if (NGX_HAVE_DEFERRED_ACCEPT && defined TCP_DEFER_ACCEPT) > + if (nls[n].deferred_accept) { > + nls[n].add_deferred = 1; > + } > +#endif > } > } Committed, thanks. -- Maxim Dounin http://nginx.org/en/donation.html From mdounin at mdounin.ru Thu Oct 31 00:06:07 2013 From: mdounin at mdounin.ru (Maxim Dounin) Date: Thu, 31 Oct 2013 04:06:07 +0400 Subject: [PATCH] ngx_gzip might hang the request for slow downstreams In-Reply-To: References: <20131026014815.GN7074@mdounin.ru> <20131026214013.GP7074@mdounin.ru> <20131027111408.GQ7074@mdounin.ru> <20131028210231.GZ7074@mdounin.ru> Message-ID: <20131031000607.GL84761@mdounin.ru> Hello! On Mon, Oct 28, 2013 at 03:37:44PM -0700, Yichun Zhang (agentzh) wrote: > Hello! > > On Mon, Oct 28, 2013 at 2:02 PM, Maxim Dounin wrote: > >> > >> - if (ctx->nomem) { > >> + if (ctx->nomem || in == NULL) { > >> > >> /* flush busy buffers */ > > > > Is the same problem exists in the gunzip filter, which has very > > similar code? > > Yes. I've reproduced the request hang in the gunzip filter module as > well, with the following minimal test case: > > https://github.com/chaoslawful/lua-nginx-module/commit/594f55b > > > Is a similar patch needed there? > > > > Yes. I can confirm that a similar patch fixes the hang on my side. > > > And, BTW, do you care to provide a Mercurial changeset, as > > suggested by nginx.org/en/docs/contributing_changes.html? It's > > not something required, but will make sure your name will be kept > > in history as a proper person to blame. :) > > > > Here we go: > > # HG changeset patch > # User Yichun Zhang > # Date 1382997696 25200 > # Branch gzip-flush > # Node ID 8985d6cc9a4334e954909c130e6204c6fc673d7e > # Parent e6a1623f87bc96d5ec62b6d77356aa47dbc60756 > Flush pending data when incoming chain is NULL in gzip and gunzip modules Committed with minor commit log changes, thanks. -- Maxim Dounin http://nginx.org/en/donation.html From mdounin at mdounin.ru Thu Oct 31 00:06:32 2013 From: mdounin at mdounin.ru (Maxim Dounin) Date: Thu, 31 Oct 2013 00:06:32 +0000 Subject: [nginx] Gzip, gunzip: flush pending data when incoming chain is ... Message-ID: details: http://hg.nginx.org/nginx/rev/c52a761a2029 branches: changeset: 5432:c52a761a2029 user: Yichun Zhang date: Mon Oct 28 15:01:36 2013 -0700 description: Gzip, gunzip: flush pending data when incoming chain is NULL. diffstat: src/http/modules/ngx_http_gunzip_filter_module.c | 2 +- src/http/modules/ngx_http_gzip_filter_module.c | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diffs (24 lines): diff --git a/src/http/modules/ngx_http_gunzip_filter_module.c b/src/http/modules/ngx_http_gunzip_filter_module.c --- a/src/http/modules/ngx_http_gunzip_filter_module.c +++ b/src/http/modules/ngx_http_gunzip_filter_module.c @@ -199,7 +199,7 @@ ngx_http_gunzip_body_filter(ngx_http_req } } - if (ctx->nomem) { + if (ctx->nomem || in == NULL) { /* flush busy buffers */ diff --git a/src/http/modules/ngx_http_gzip_filter_module.c b/src/http/modules/ngx_http_gzip_filter_module.c --- a/src/http/modules/ngx_http_gzip_filter_module.c +++ b/src/http/modules/ngx_http_gzip_filter_module.c @@ -372,7 +372,7 @@ ngx_http_gzip_body_filter(ngx_http_reque r->connection->buffered |= NGX_HTTP_GZIP_BUFFERED; } - if (ctx->nomem) { + if (ctx->nomem || in == NULL) { /* flush busy buffers */ From mdounin at mdounin.ru Thu Oct 31 00:06:34 2013 From: mdounin at mdounin.ru (Maxim Dounin) Date: Thu, 31 Oct 2013 00:06:34 +0000 Subject: [nginx] Auth basic: "info" logging level on no user/password. Message-ID: details: http://hg.nginx.org/nginx/rev/c37f34bda5ea branches: changeset: 5433:c37f34bda5ea user: Maxim Dounin date: Thu Oct 31 04:02:21 2013 +0400 description: Auth basic: "info" logging level on no user/password. This isn't an exceptional condition and normally happens on first request from a client. diffstat: src/http/modules/ngx_http_auth_basic_module.c | 2 +- 1 files changed, 1 insertions(+), 1 deletions(-) diffs (12 lines): diff --git a/src/http/modules/ngx_http_auth_basic_module.c b/src/http/modules/ngx_http_auth_basic_module.c --- a/src/http/modules/ngx_http_auth_basic_module.c +++ b/src/http/modules/ngx_http_auth_basic_module.c @@ -137,7 +137,7 @@ ngx_http_auth_basic_handler(ngx_http_req if (rc == NGX_DECLINED) { - ngx_log_error(NGX_LOG_ERR, r->connection->log, 0, + ngx_log_error(NGX_LOG_INFO, r->connection->log, 0, "no user/password was provided for basic authentication"); return ngx_http_auth_basic_set_realm(r, &realm); From mdounin at mdounin.ru Thu Oct 31 00:06:35 2013 From: mdounin at mdounin.ru (Maxim Dounin) Date: Thu, 31 Oct 2013 00:06:35 +0000 Subject: [nginx] Removed extra allocation for $sent_http_last_modified. Message-ID: details: http://hg.nginx.org/nginx/rev/c21e341c51cb branches: changeset: 5434:c21e341c51cb user: Maxim Dounin date: Thu Oct 31 04:02:59 2013 +0400 description: Removed extra allocation for $sent_http_last_modified. There is no need to allocate memory for "Last-Modified: " string, the variable only contains date itself. diffstat: src/http/ngx_http_variables.c | 3 +-- 1 files changed, 1 insertions(+), 2 deletions(-) diffs (13 lines): diff --git a/src/http/ngx_http_variables.c b/src/http/ngx_http_variables.c --- a/src/http/ngx_http_variables.c +++ b/src/http/ngx_http_variables.c @@ -1744,8 +1744,7 @@ ngx_http_variable_sent_last_modified(ngx } if (r->headers_out.last_modified_time >= 0) { - p = ngx_pnalloc(r->pool, - sizeof("Last-Modified: Mon, 28 Sep 1970 06:00:00 GMT") - 1); + p = ngx_pnalloc(r->pool, sizeof("Mon, 28 Sep 1970 06:00:00 GMT") - 1); if (p == NULL) { return NGX_ERROR; } From mdounin at mdounin.ru Thu Oct 31 00:18:59 2013 From: mdounin at mdounin.ru (Maxim Dounin) Date: Thu, 31 Oct 2013 00:18:59 +0000 Subject: [nginx] Gunzip: "error" logging level on inflate() errors. Message-ID: details: http://hg.nginx.org/nginx/rev/2bb2571d6e34 branches: changeset: 5435:2bb2571d6e34 user: Maxim Dounin date: Thu Oct 31 04:12:53 2013 +0400 description: Gunzip: "error" logging level on inflate() errors. Errors can easily happen due to broken upstream responses, there is no need to log them at "alert" level. diffstat: src/http/modules/ngx_http_gunzip_filter_module.c | 2 +- 1 files changed, 1 insertions(+), 1 deletions(-) diffs (12 lines): diff --git a/src/http/modules/ngx_http_gunzip_filter_module.c b/src/http/modules/ngx_http_gunzip_filter_module.c --- a/src/http/modules/ngx_http_gunzip_filter_module.c +++ b/src/http/modules/ngx_http_gunzip_filter_module.c @@ -422,7 +422,7 @@ ngx_http_gunzip_filter_inflate(ngx_http_ rc = inflate(&ctx->zstream, ctx->flush); if (rc != Z_OK && rc != Z_STREAM_END && rc != Z_BUF_ERROR) { - ngx_log_error(NGX_LOG_ALERT, r->connection->log, 0, + ngx_log_error(NGX_LOG_ERR, r->connection->log, 0, "inflate() failed: %d, %d", ctx->flush, rc); return NGX_ERROR; } From mdounin at mdounin.ru Thu Oct 31 00:19:00 2013 From: mdounin at mdounin.ru (Maxim Dounin) Date: Thu, 31 Oct 2013 00:19:00 +0000 Subject: [nginx] Gunzip: proper error handling on gunzipping an empty res... Message-ID: details: http://hg.nginx.org/nginx/rev/6aa75f4982ce branches: changeset: 5436:6aa75f4982ce user: Maxim Dounin date: Thu Oct 31 04:16:20 2013 +0400 description: Gunzip: proper error handling on gunzipping an empty response. With previous code, an empty (malformed) response resulted in a request finalized without sending anything to a client. diffstat: src/http/modules/ngx_http_gunzip_filter_module.c | 10 +++++++--- 1 files changed, 7 insertions(+), 3 deletions(-) diffs (20 lines): diff --git a/src/http/modules/ngx_http_gunzip_filter_module.c b/src/http/modules/ngx_http_gunzip_filter_module.c --- a/src/http/modules/ngx_http_gunzip_filter_module.c +++ b/src/http/modules/ngx_http_gunzip_filter_module.c @@ -500,9 +500,13 @@ ngx_http_gunzip_filter_inflate(ngx_http_ return NGX_OK; } - if (rc == Z_STREAM_END && ctx->flush == Z_FINISH - && ctx->zstream.avail_in == 0) - { + if (ctx->flush == Z_FINISH && ctx->zstream.avail_in == 0) { + + if (rc != Z_STREAM_END) { + ngx_log_error(NGX_LOG_ERR, r->connection->log, 0, + "inflate() returned %d on response end", rc); + return NGX_ERROR; + } if (ngx_http_gunzip_filter_inflate_end(r, ctx) != NGX_OK) { return NGX_ERROR; From raimon at 3scale.net Thu Oct 31 10:10:19 2013 From: raimon at 3scale.net (Raimon Grau) Date: Thu, 31 Oct 2013 11:10:19 +0100 Subject: [PATCH] Allow returning 407 status Message-ID: Hi, Nginx forbids returning 407 (Proxy Authorization Required). If we allow it, we can play with headers and make it a regular http proxy. With some nginx external modules like ngx-lua, we could even debug mobile apps, or http traffic Regards, Rai PS: It's my first email/patch here. I'm sorry if there's any convention I'm not following. I tried my best :) -- Raimon Grau 3scale Networks -------------- next part -------------- A non-text attachment was scrubbed... Name: allow-407.patch Type: text/x-patch Size: 849 bytes Desc: not available URL: From ru at nginx.com Thu Oct 31 11:12:30 2013 From: ru at nginx.com (Ruslan Ermilov) Date: Thu, 31 Oct 2013 15:12:30 +0400 Subject: [PATCH] Allow returning 407 status In-Reply-To: References: Message-ID: <20131031111230.GB90747@lo0.su> On Thu, Oct 31, 2013 at 11:10:19AM +0100, Raimon Grau wrote: > Hi, > > Nginx forbids returning 407 (Proxy Authorization Required). If we > allow it, we can play with headers and make it a regular http proxy. What do you mean by "forbids"? What's wrong with "return 407"? > With some nginx external modules like ngx-lua, we could even debug > mobile apps, or http traffic From raimon at 3scale.net Thu Oct 31 14:27:07 2013 From: raimon at 3scale.net (Raimon Grau) Date: Thu, 31 Oct 2013 15:27:07 +0100 Subject: [PATCH] Allow returning 407 status In-Reply-To: <20131031111230.GB90747@lo0.su> References: <20131031111230.GB90747@lo0.su> Message-ID: On Thu, Oct 31, 2013 at 12:12 PM, Ruslan Ermilov wrote: > What do you mean by "forbids"? What's wrong with "return 407"? In 1.4.3, using the default nginx.conf, just adding "location /hola { return 407;} " doesn't answer correctly: https://gist.github.com/kidd/7250643 The same with return 201 worked fine. BUT, I have just tried 1.5.6, and it works there. In fact, the file where the patch applied changed quite a bit, so even the patch wouldn't be appliable for 1.5.6 Regards -- Raimon Grau 3scale Networks From raimon at 3scale.net Thu Oct 31 14:38:21 2013 From: raimon at 3scale.net (Raimon Grau) Date: Thu, 31 Oct 2013 15:38:21 +0100 Subject: [PATCH] Allow returning 407 status In-Reply-To: References: <20131031111230.GB90747@lo0.su> Message-ID: On Thu, Oct 31, 2013 at 3:27 PM, Raimon Grau wrote: > BUT, I have just tried 1.5.6, and it works there. In fact, the file > where the patch applied changed quite a bit, so even the patch > wouldn't be appliable for 1.5.6 Sorry, The file didn't chage that much but it seems to work anyway. https://gist.github.com/kidd/7250889 From ru at nginx.com Thu Oct 31 20:11:59 2013 From: ru at nginx.com (Ruslan Ermilov) Date: Fri, 1 Nov 2013 00:11:59 +0400 Subject: [PATCH] Allow returning 407 status In-Reply-To: References: <20131031111230.GB90747@lo0.su> Message-ID: <20131031201159.GE89295@lo0.su> On Thu, Oct 31, 2013 at 03:38:21PM +0100, Raimon Grau wrote: > On Thu, Oct 31, 2013 at 3:27 PM, Raimon Grau wrote: > > BUT, I have just tried 1.5.6, and it works there. In fact, the file > > where the patch applied changed quite a bit, so even the patch > > wouldn't be appliable for 1.5.6 > > Sorry, The file didn't chage that much but it seems to work anyway. > https://gist.github.com/kidd/7250889 http://mailman.nginx.org/pipermail/nginx-devel/2013-April/003609.html http://trac.nginx.org/nginx/changeset/5364/nginx From rob.stradling at comodo.com Thu Oct 31 20:58:31 2013 From: rob.stradling at comodo.com (Rob Stradling) Date: Thu, 31 Oct 2013 20:58:31 +0000 Subject: [PATCH] RSA+DSA+ECC bundles In-Reply-To: <20131024002653.GK7074@mdounin.ru> References: <20131017151800.GI2144@mdounin.ru> <5261BF11.7010708@comodo.com> <20131019101424.GS2144@mdounin.ru> <52659F5B.1050708@comodo.com> <20131022120939.GU7074@mdounin.ru> <52667E15.1010301@comodo.com> <20131023002525.GZ7074@mdounin.ru> <20131024002653.GK7074@mdounin.ru> Message-ID: <5272C477.6060901@comodo.com> On 24/10/13 01:26, Maxim Dounin wrote: > As for multiple certs per se, I don't think it should be limited > to recent OpenSSL versions only. As far as I can tell, current > versions of OpenSSL will work just fine (well, mostly) as long as > both ECDSA and RSA certs use the same certificate chain. I > believe at least some CAs issue ECDSA certs this way, and this > should work. > > Limiting support for multiple certs with separate certificate > chains to only recent OpenSSL versions seems reasonable for me, > but if Rob wants to try to make it work with older versions - I > don't really object. If it won't be too hacky it might worth > supporting. Updated patch attached. This implements multiple certs and makes OCSP Stapling work correctly with them. It works with all of the active OpenSSL branches (including 0_9_8). I'm afraid it's a much larger patch than I anticipated it would be when I started working on it! Maxim, does this patch look commit-able? -- Rob Stradling Senior Research & Development Scientist COMODO - Creating Trust Online -------------- next part -------------- A non-text attachment was scrubbed... Name: nginx_multiple_certs_and_stapling.patch Type: text/x-patch Size: 56104 bytes Desc: not available URL: From rob.stradling at comodo.com Thu Oct 31 21:58:01 2013 From: rob.stradling at comodo.com (Rob Stradling) Date: Thu, 31 Oct 2013 21:58:01 +0000 Subject: [PATCH] RSA+DSA+ECC bundles In-Reply-To: <5272C477.6060901@comodo.com> References: <20131017151800.GI2144@mdounin.ru> <5261BF11.7010708@comodo.com> <20131019101424.GS2144@mdounin.ru> <52659F5B.1050708@comodo.com> <20131022120939.GU7074@mdounin.ru> <52667E15.1010301@comodo.com> <20131023002525.GZ7074@mdounin.ru> <20131024002653.GK7074@mdounin.ru> <5272C477.6060901@comodo.com> Message-ID: <5272D269.20203@comodo.com> On 31/10/13 20:58, Rob Stradling wrote: > On 24/10/13 01:26, Maxim Dounin wrote: > >> As for multiple certs per se, I don't think it should be limited >> to recent OpenSSL versions only. As far as I can tell, current >> versions of OpenSSL will work just fine (well, mostly) as long as >> both ECDSA and RSA certs use the same certificate chain. I >> believe at least some CAs issue ECDSA certs this way, and this >> should work. >> >> Limiting support for multiple certs with separate certificate >> chains to only recent OpenSSL versions seems reasonable for me, >> but if Rob wants to try to make it work with older versions - I >> don't really object. If it won't be too hacky it might worth >> supporting. > > Updated patch attached. This implements multiple certs and makes OCSP > Stapling work correctly with them. It works with all of the active > OpenSSL branches (including 0_9_8). That patch caused problems with ssl_stapling_file. Fixed in the attached V2 patch. > I'm afraid it's a much larger patch than I anticipated it would be when > I started working on it! > > Maxim, does this patch look commit-able? -- Rob Stradling Senior Research & Development Scientist COMODO - Creating Trust Online -------------- next part -------------- A non-text attachment was scrubbed... Name: nginx_multiple_certs_and_stapling_V2.patch Type: text/x-patch Size: 56213 bytes Desc: not available URL: