From: Rafał Miłecki Date: Thu, 29 Jun 2017 07:24:37 +0000 (+0200) Subject: lighttpd: backport more mod_cgi fixes queued for 1.4.46 X-Git-Url: http://git.openwrt.org/?a=commitdiff_plain;h=1359e072be2e4b368d7b1b793f487905e74903ae;p=feed%2Fpackages.git lighttpd: backport more mod_cgi fixes queued for 1.4.46 The most important change is local redirects being disabled by default. There is an option called cgi.local-redir that allows enabling this optimization manually back if needed. Local redirects were initially introduced in 1.4.40 but caused many problems for *some* web services. One of problems is breaking Post/Redirect/Get design pattern. With redirects handled on server side there is no browser redirection making it "lose" the POST data. Another possible issue are HTML forms with action="". With CGI local redirects browser may be sending form data to the wrong URL (the one that was supposed to redirect the browser). Signed-off-by: Rafał Miłecki --- diff --git a/net/lighttpd/Makefile b/net/lighttpd/Makefile index 4e6d79fcdd..20f0d5725f 100644 --- a/net/lighttpd/Makefile +++ b/net/lighttpd/Makefile @@ -9,7 +9,7 @@ include $(TOPDIR)/rules.mk PKG_NAME:=lighttpd PKG_VERSION:=1.4.45 -PKG_RELEASE:=5 +PKG_RELEASE:=6 PKG_SOURCE:=$(PKG_NAME)-$(PKG_VERSION).tar.xz PKG_SOURCE_URL:=https://download.lighttpd.net/lighttpd/releases-1.4.x diff --git a/net/lighttpd/patches/0001-mod_cgi-RFC3875-CGI-local-redir-strict-adherence-210.patch b/net/lighttpd/patches/0001-mod_cgi-RFC3875-CGI-local-redir-strict-adherence-210.patch new file mode 100644 index 0000000000..9b797aca38 --- /dev/null +++ b/net/lighttpd/patches/0001-mod_cgi-RFC3875-CGI-local-redir-strict-adherence-210.patch @@ -0,0 +1,62 @@ +From dde50f1939e22926d17342b5d812e9a3034e7e98 Mon Sep 17 00:00:00 2001 +From: Glenn Strauss +Date: Wed, 25 Jan 2017 11:22:39 -0500 +Subject: [PATCH] [mod_cgi] RFC3875 CGI local-redir strict adherence (#2108) + +RFC3875 CGI local-redir stricter adherence + +do not apply local-redir if any response headers besides "Location" +do not apply local-redir if any response body has been received +(though it might not have been received yet, and we do not wait to find + out, if lighttpd is configured to stream response body back to client) + +x-ref: + RFC3875 CGI 1.1 specification section 6.2.2 Local Redirect Response + http://www.ietf.org/rfc/rfc3875 + "CGI local redirect not implemented correctly" + https://redmine.lighttpd.net/issues/2108 +--- + src/mod_cgi.c | 25 ++++++++++++++++++++++++- + 1 file changed, 24 insertions(+), 1 deletion(-) + +--- a/src/mod_cgi.c ++++ b/src/mod_cgi.c +@@ -527,6 +527,27 @@ static int cgi_demux_response(server *sr + /* parse the response header */ + cgi_response_parse(srv, con, p, hctx->response_header); + ++ /* [RFC3875] 6.2.2 Local Redirect Response ++ * ++ * The CGI script can return a URI path and query-string ++ * ('local-pathquery') for a local resource in a Location header field. ++ * This indicates to the server that it should reprocess the request ++ * using the path specified. ++ * ++ * local-redir-response = local-Location NL ++ * ++ * The script MUST NOT return any other header fields or a message-body, ++ * and the server MUST generate the response that it would have produced ++ * in response to a request containing the URL ++ * ++ * scheme "://" server-name ":" server-port local-pathquery ++ * ++ * (Might not have begun to receive body yet, but do skip local-redir ++ * if we already have started receiving a response body (blen > 0)) ++ * (Also, while not required by the RFC, do not send local-redir back ++ * to same URL, since CGI should have handled it internally if it ++ * really wanted to do that internally) ++ */ + if (con->http_status >= 300 && con->http_status < 400) { + /*(con->parsed_response & HTTP_LOCATION)*/ + size_t ulen = buffer_string_length(con->uri.path); +@@ -535,7 +556,9 @@ static int cgi_demux_response(server *sr + && ds->value->ptr[0] == '/' + && (0 != strncmp(ds->value->ptr, con->uri.path->ptr, ulen) + || (ds->value->ptr[ulen] != '\0' && ds->value->ptr[ulen] != '/' && ds->value->ptr[ulen] != '?')) +- && NULL == array_get_element(con->response.headers, "Set-Cookie")) { ++ && 0 == blen ++ && !(con->parsed_response & HTTP_STATUS) /* no "Status" or NPH response line */ ++ && 1 == con->response.headers->used) { + if (++con->loops_per_request > 5) { + log_error_write(srv, __FILE__, __LINE__, "sb", "too many internal loops while processing request:", con->request.orig_uri); + con->http_status = 500; /* Internal Server Error */ diff --git a/net/lighttpd/patches/0001-mod_cgi-fix-CGI-local-redir-w-url.rewrite-once-fixes.patch b/net/lighttpd/patches/0001-mod_cgi-fix-CGI-local-redir-w-url.rewrite-once-fixes.patch deleted file mode 100644 index a6bbcbe430..0000000000 --- a/net/lighttpd/patches/0001-mod_cgi-fix-CGI-local-redir-w-url.rewrite-once-fixes.patch +++ /dev/null @@ -1,32 +0,0 @@ -From: Glenn Strauss -Subject: [PATCH] [mod_cgi] fix CGI local-redir w/ url.rewrite-once (fixes - #2793) - -x-ref: - "1.4.40 regression: broken redirect (using Location) between url.rewrite-once URLs" - https://redmine.lighttpd.net/issues/2793 ---- - src/mod_cgi.c | 5 ++--- - 1 file changed, 2 insertions(+), 3 deletions(-) - ---- a/src/mod_cgi.c -+++ b/src/mod_cgi.c -@@ -560,8 +560,7 @@ static int cgi_demux_response(server *sr - } - - connection_response_reset(srv, con); /*(includes con->http_status = 0)*/ -- -- con->mode = DIRECT; -+ plugins_call_connection_reset(srv, con); - return FDEVENT_HANDLED_COMEBACK; - } - } -@@ -780,7 +779,7 @@ static int cgi_recv_response(server *srv - /* if we get a IN|HUP and have read everything don't exec the close twice */ - return HANDLER_FINISHED; - case FDEVENT_HANDLED_COMEBACK: -- cgi_connection_close(srv, hctx); -+ /*cgi_connection_close(srv, hctx);*//*(already cleaned up and hctx is now invalid)*/ - return HANDLER_COMEBACK; - case FDEVENT_HANDLED_ERROR: - log_error_write(srv, __FILE__, __LINE__, "s", "demuxer failed: "); diff --git a/net/lighttpd/patches/0002-mod_cgi-fix-CGI-local-redir-w-url.rewrite-once-fixes.patch b/net/lighttpd/patches/0002-mod_cgi-fix-CGI-local-redir-w-url.rewrite-once-fixes.patch new file mode 100644 index 0000000000..e8e1cefad4 --- /dev/null +++ b/net/lighttpd/patches/0002-mod_cgi-fix-CGI-local-redir-w-url.rewrite-once-fixes.patch @@ -0,0 +1,34 @@ +From ab85841b142c62c47f69fc45c0b54f080d54ddc9 Mon Sep 17 00:00:00 2001 +From: Glenn Strauss +Date: Mon, 20 Feb 2017 14:47:13 -0500 +Subject: [PATCH] [mod_cgi] fix CGI local-redir w/ url.rewrite-once (fixes + #2793) + +x-ref: + "1.4.40 regression: broken redirect (using Location) between url.rewrite-once URLs" + https://redmine.lighttpd.net/issues/2793 +--- + src/mod_cgi.c | 5 ++--- + 1 file changed, 2 insertions(+), 3 deletions(-) + +--- a/src/mod_cgi.c ++++ b/src/mod_cgi.c +@@ -583,8 +583,7 @@ static int cgi_demux_response(server *sr + } + + connection_response_reset(srv, con); /*(includes con->http_status = 0)*/ +- +- con->mode = DIRECT; ++ plugins_call_connection_reset(srv, con); + return FDEVENT_HANDLED_COMEBACK; + } + } +@@ -803,7 +802,7 @@ static int cgi_recv_response(server *srv + /* if we get a IN|HUP and have read everything don't exec the close twice */ + return HANDLER_FINISHED; + case FDEVENT_HANDLED_COMEBACK: +- cgi_connection_close(srv, hctx); ++ /*cgi_connection_close(srv, hctx);*//*(already cleaned up and hctx is now invalid)*/ + return HANDLER_COMEBACK; + case FDEVENT_HANDLED_ERROR: + log_error_write(srv, __FILE__, __LINE__, "s", "demuxer failed: "); diff --git a/net/lighttpd/patches/0003-mod_cgi-status-200-OK-if-no-hdrs-deprecated-2786.patch b/net/lighttpd/patches/0003-mod_cgi-status-200-OK-if-no-hdrs-deprecated-2786.patch new file mode 100644 index 0000000000..7e7d9eef4c --- /dev/null +++ b/net/lighttpd/patches/0003-mod_cgi-status-200-OK-if-no-hdrs-deprecated-2786.patch @@ -0,0 +1,46 @@ +From 51ff7ac504f7001dc54807f9b2a72de891ab9ee5 Mon Sep 17 00:00:00 2001 +From: Glenn Strauss +Date: Wed, 22 Feb 2017 11:58:21 -0500 +Subject: [PATCH] [mod_cgi] status 200 OK if no hdrs (deprecated) (#2786) + +set status 200 OK if CGI does not return CGI headers + +Note: +This mode in lighttpd is deprecated and may be removed in the next major +release of lighttpd. CGI scripts should return a proper CGI header in +the response, even if that header is empty and followed by a blank line, +before return response body. + +Without a proper CGI response header, the first line(s) of the response +might be incorrectly construed as being CGI response headers, especially +if they contain ':', and response may be corrupted. That is why this +mode is deprecated (and not supported in numerous other web servers). + +The minimal valid CGI response header is "\n", which lighttpd will treat +as equivalent to "Status: 200\n\n" + +x-ref: + "error 500 (mod_cgi.c.601) cgi died" + https://redmine.lighttpd.net/issues/2786 +--- + src/mod_cgi.c | 2 ++ + 1 file changed, 2 insertions(+) + +--- a/src/mod_cgi.c ++++ b/src/mod_cgi.c +@@ -502,6 +502,7 @@ static int cgi_demux_response(server *sr + if (0 != http_chunk_append_buffer(srv, con, hctx->response_header)) { + return FDEVENT_HANDLED_ERROR; + } ++ if (0 == con->http_status) con->http_status = 200; /* OK */ + } else { + const char *bstart; + size_t blen; +@@ -846,6 +847,7 @@ static handler_t cgi_handle_fdevent(serv + cgi_connection_close(srv, hctx); + return HANDLER_ERROR; + } ++ if (0 == con->http_status) con->http_status = 200; /* OK */ + } else { + # if 0 + log_error_write(srv, __FILE__, __LINE__, "sddd", "got HUP from cgi", con->fd, hctx->fd, revents); diff --git a/net/lighttpd/patches/0004-mod_cgi-cgi.local-redir-enable-disable-2108-2793.patch b/net/lighttpd/patches/0004-mod_cgi-cgi.local-redir-enable-disable-2108-2793.patch new file mode 100644 index 0000000000..327b080d7d --- /dev/null +++ b/net/lighttpd/patches/0004-mod_cgi-cgi.local-redir-enable-disable-2108-2793.patch @@ -0,0 +1,105 @@ +From 57ab20ace504fdb6e0944ef6fa6e0ce35adc4446 Mon Sep 17 00:00:00 2001 +From: Glenn Strauss +Date: Sun, 26 Feb 2017 17:49:47 -0500 +Subject: [PATCH] [mod_cgi] cgi.local-redir = [enable|disable] (#2108, #2793) + +new directive cgi.local-redir = [enable|disable] + +*disable* RFC3875 6.2.2 local-redir by default. +(behavior change from when local-redir support added in lighttpd 1.4.40) + +The reason for this behavior change is that CGI local-redir support +(RFC3875 6.2.2) is an optimization. Absence of support may result in +additional latency in servicing a request due the additional round-trip +to the client, but that was the prior behavior (before lighttpd 1.4.40) +and is the behavior of web servers which do not support CGI local-redir. + +However, enabling CGI local-redir by default may result in broken links +in the case where a user config (unaware of CGI local-redir behavior) +returns HTML pages containing *relative* paths (not root-relative paths) +which are relative to the location of the local-redir target document, +and the local-redir target document is located at a different URL-path +from the original CGI request. + +x-ref: + RFC3875 CGI 1.1 specification section 6.2.2 Local Redirect Response + http://www.ietf.org/rfc/rfc3875 + "CGI local redirect not implemented correctly" + https://redmine.lighttpd.net/issues/2108 + "1.4.40 regression: broken redirect (using Location) between url.rewrite-once URLs" + https://redmine.lighttpd.net/issues/2793 +--- + src/mod_cgi.c | 9 ++++++++- + tests/lighttpd.conf | 1 + + 2 files changed, 9 insertions(+), 1 deletion(-) + +--- a/src/mod_cgi.c ++++ b/src/mod_cgi.c +@@ -66,6 +66,7 @@ typedef struct { + typedef struct { + array *cgi; + unsigned short execute_x_only; ++ unsigned short local_redir; + unsigned short xsendfile_allow; + array *xsendfile_docroot; + } plugin_config; +@@ -172,6 +173,7 @@ SETDEFAULTS_FUNC(mod_fastcgi_set_default + { "cgi.execute-x-only", NULL, T_CONFIG_BOOLEAN, T_CONFIG_SCOPE_CONNECTION }, /* 1 */ + { "cgi.x-sendfile", NULL, T_CONFIG_BOOLEAN, T_CONFIG_SCOPE_CONNECTION }, /* 2 */ + { "cgi.x-sendfile-docroot", NULL, T_CONFIG_ARRAY, T_CONFIG_SCOPE_CONNECTION }, /* 3 */ ++ { "cgi.local-redir", NULL, T_CONFIG_BOOLEAN, T_CONFIG_SCOPE_CONNECTION }, /* 4 */ + { NULL, NULL, T_CONFIG_UNSET, T_CONFIG_SCOPE_UNSET} + }; + +@@ -189,6 +191,7 @@ SETDEFAULTS_FUNC(mod_fastcgi_set_default + + s->cgi = array_init(); + s->execute_x_only = 0; ++ s->local_redir = 0; + s->xsendfile_allow= 0; + s->xsendfile_docroot = array_init(); + +@@ -196,6 +199,7 @@ SETDEFAULTS_FUNC(mod_fastcgi_set_default + cv[1].destination = &(s->execute_x_only); + cv[2].destination = &(s->xsendfile_allow); + cv[3].destination = s->xsendfile_docroot; ++ cv[4].destination = &(s->local_redir); + + p->config_storage[i] = s; + +@@ -549,7 +553,7 @@ static int cgi_demux_response(server *sr + * to same URL, since CGI should have handled it internally if it + * really wanted to do that internally) + */ +- if (con->http_status >= 300 && con->http_status < 400) { ++ if (hctx->conf.local_redir && con->http_status >= 300 && con->http_status < 400) { + /*(con->parsed_response & HTTP_LOCATION)*/ + size_t ulen = buffer_string_length(con->uri.path); + data_string *ds; +@@ -1321,6 +1325,7 @@ static int mod_cgi_patch_connection(serv + + PATCH(cgi); + PATCH(execute_x_only); ++ PATCH(local_redir); + PATCH(xsendfile_allow); + PATCH(xsendfile_docroot); + +@@ -1340,6 +1345,8 @@ static int mod_cgi_patch_connection(serv + PATCH(cgi); + } else if (buffer_is_equal_string(du->key, CONST_STR_LEN("cgi.execute-x-only"))) { + PATCH(execute_x_only); ++ } else if (buffer_is_equal_string(du->key, CONST_STR_LEN("cgi.local-redir"))) { ++ PATCH(local_redir); + } else if (buffer_is_equal_string(du->key, CONST_STR_LEN("cgi.x-sendfile"))) { + PATCH(xsendfile_allow); + } else if (buffer_is_equal_string(du->key, CONST_STR_LEN("cgi.x-sendfile-docroot"))) { +--- a/tests/lighttpd.conf ++++ b/tests/lighttpd.conf +@@ -110,6 +110,7 @@ fastcgi.server = ( + ) ), + ) + ++cgi.local-redir = "enable" + cgi.assign = ( + ".pl" => env.PERL, + ".cgi" => env.PERL,