packages/net/lighttpd/patches/0001-mod_cgi-RFC3875-CGI-local-redir-strict-adherence-210.patch
Rafał Miłecki 1359e072be 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 <rafal@milecki.pl>
2017-06-29 09:41:30 +02:00

62 lines
3 KiB
Diff

From dde50f1939e22926d17342b5d812e9a3034e7e98 Mon Sep 17 00:00:00 2001
From: Glenn Strauss <gstrauss@gluelogic.com>
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 */