fix streaming response when server.stream-response-body = 2
and client catches up to stream from backend
(thx horgh)
x-ref:
"mod_fastcgi can fail to read entire response from server"
https://redmine.lighttpd.net/issues/2796
More specific checks on contents of array lists. Each module using
lists now does better checking on the types of values in the list
(strings, integers, arrays/lists)
This helps prevent misconfiguration of things like cgi.assign,
fastcgi.server, and scgi.server, where source code might be
served as static files if parenthesis are misplaced.
x-ref:
https://redmine.lighttpd.net/boards/2/topics/6571
consolidate backend process accounting for consistency
x-ref:
"FreeBSD/1.4.45/SSL: requests getting stuck in handle-req state occasionally"
https://redmine.lighttpd.net/issues/2788
more consistent waitpid() handling, consolidate similar code
If ECHILD received for a given pid, do not retry waitpid() for that pid
x-ref:
"mod_fastcgi : pid {pid} 1 not found: No child processes"
https://redmine.lighttpd.net/issues/2791
When spawning backends, retry blocking connect() to backend if EINTR
received when attempting to see if backend is already running. EINTR
might be received if a HUP or USR1 signal is received while connecting
(or SIGCHLD on systems without SA_RESTART)
(expected to occur extremely rarely, but simple to handle properly)
x-ref:
"FreeBSD/1.4.45/SSL: requests getting stuck in handle-req state occasionally"
https://redmine.lighttpd.net/issues/2788
It is still not a good idea for backend to send Transfer-Encoding unless
backend is mod_proxy, and mod_proxy should not currently receive chunked
response since mod_proxy sends HTTP/1.0 request.
If mod_proxy is changed to sent HTTP/1.1 request, then lighttpd would
need to check if client is HTTP/1.0 and would need to de-chunk and
remove any other transfer-codings if not supported by next-hop.
x-ref:
"error 500 (mod_cgi.c.601) cgi died"
https://redmine.lighttpd.net/issues/2786
"Status" from CGI/1.1 environment should not be sent back to client.
Also, do not send "Status" back to client in mod_scgi
and more precisely parse for "Status" in mod_fastcgi
when available, use getaddrinfo(),inet_pton() instead of gethostbyname()
NOTE: behavior change: mod_scgi now listens to INADDR_LOOPBACK if "host"
is not specified. (Prior behavior was INADDR_ANY.) Backends
should not listen on potentially public IPs unless explicitly
configured to do so. This change matches a change to mod_fastcgi
made in 2008.
x-ref
"gethostbyname deprecated, should use getaddrinfo"
https://redmine.lighttpd.net/issues/2783
The (misnamed) connection_reset hook is always called after a request,
whether request completes or is aborted, and whether keep-alive or not,
so no needed to repeat the same function in the handle_connection_close
hook.
support Transfer-Encoding: chunked request body in conjunction with
server.stream-request-body = 0
dynamic handlers will still return 411 Length Required if
server.stream-request-body = 1 or 2 (!= 0)
since CGI-like env requires CONTENT_LENGTH be set
(and mod_proxy currently sends HTTP/1.0 requests to backends,
and Content-Length recommended for robust interaction with backend)
x-ref:
"request: support Chunked Transfer Coding for HTTP PUT"
https://redmine.lighttpd.net/issues/2156
e.g. if /usr/bin/php-cgi does not exist
A distribution package might need to be installed:
'php-cli' Fedora package; 'php7.0-cgi' or 'php5-cgi' Debian package
setting or removing FD_CLOEXEC flag does not fail
Also the use in mod_fastcgi and mod_scgi is in child after fork().
If the fd already happens to be 0 (should not happen in current code)
and removing the FD_CLOEXEC flag fails, then the backend will fail
to start.
consolidated from CGI, FastCGI, SCGI, SSI
Note: due to prior inconsistencies between the code in mod_cgi,
mod_fastcgi, mod_scgi, and mod_ssi, there are some minor behavior
changes.
CONTENT_LENGTH is now always set, even if 0
(though CONTENT_LENGTH is never set for FASTCGI_AUTHORIZER)
PATH_INFO is created only if present, not if empty.
(mod_fastcgi and mod_ssi previously set PATH_INFO="" (blank value))
PATH_TRANSLATED is now set if PATH_INFO is present
(previously missing from mod_cgi and mod_ssi)
mod_ssi now sets DOCUMENT_ROOT to con->physical.basedir, like others
(previously, mod_ssi set DOCUMENT_ROOT to con->physical.doc_root,
which matched con->physical.basedir unless mod_alias changed basedir)
mod_ssi now sets REQUEST_URI to con->request.orig_uri, like others
(previously, mod_ssi set REQUEST_URI to con->request.uri, which
matched con->request.orig_uri except after redirects, error docs)
allow authorizer and responder to be configured for same path or ext
x-ref:
"mod_fastcgi authorizers cannot protect fastcgi responders"
https://redmine.lighttpd.net/issues/321
(for persistence across multiple re-entries into routines upon
receiving fdevent)
(setting module debug flag in global scope is still recommended
since there are places where p->conf.debug is checked since
handler_ctx might not be available at all points)
import Variable-* from FastCGI authorizer response into con->environment
restart request after FastCGI authorizer if no fastcgi.server docroot
(thx Christoph Kreutzer for initial patch attempt)
x-ref:
"mod_fastcgi authorizers cannot protect fastcgi responders"
http://redmine.lighttpd.net/issues/321
x-ref:
"FastCGI Authorizer support for Variable-name variable passing"
http://redmine.lighttpd.net/issues/322
github: closes #70
mod_fastcgi, mod_scgi, and mod_proxy must enforce wait for POLLWR
after EINPROGRESS or else getsockopt(fd, SOL_SOCKET, SO_ERROR, ...)
may succeed even though socket connection is not yet established,
and subsequent writev() will fail ENOTCONN.
(thx pkubaj)
x-ref:
"1.4.40/41 writev failed: Socket is not connected (fastcgi,scgi,proxy)"
https://redmine.lighttpd.net/issues/2744
reverts part of commit:dbdab5db which swapped REQUEST_URI, REDIRECT_URI
x-ref:
"mediawiki redirect loop if REQUEST_URI not orig req in 1.4.40"
https://redmine.lighttpd.net/issues/2738
Explanation:
REQUEST_URI and REDIRECT_URI are not part of CGI standard environment.
The reason for their existence is that PATH_INFO in CGI environment may
be different from the path in the current request. The main reason for
this potential difference is that the URI path is normalized to a path
in the filesystem and tested against the filesystem to determine which
part is SCRIPT_NAME and which part is PATH_INFO. In case-insensitive
filesystems, the URI might be lowercased before testing against the
filesystem, leading to loss of case-sensitive submission in any
resulting PATH_INFO. Also, duplicated slashes "///" and directory
references "/." and "/.." are removed, including prior path component in
the case of "/..". This might be undesirable when the information after
the SCRIPT_NAME is virtual information and there target script needs the
virtual path preserved as-is. In that case, the target script can
re-parse REQUEST_URI (or REDIRECT_URI, as appropriate) to obtain the
unmodified information from the URI.
con->request.uri is equivalent to con->request.orig_uri unless the
request has been internally rewritten (e.g. by mod_rewrite, mod_magnet,
others), in which case con->request.orig_uri is the request made by the
client, and con->request.uri is the current URI being processed.
Historical REQUEST_URI (environment variable) lighttpd inconsistencies
- mod_cml set REQUEST_URI to con->request.orig_uri
- mod_cgi set REQUEST_URI to con->request.orig_uri
- mod_fastcgi set REQUEST_URI to con->request.orig_uri
- mod_scgi set REQUEST_URI to con->request.orig_uri
- mod_ssi set REQUEST_URI to current con->request.uri
- mod_magnet set MAGNET_ENV_REQUEST_URI to current con->request.uri
and MAGNET_ENV_REQUEST_ORIG_URI to con->request.orig_uri
Historical REDIRECT_URI (environment variable) previously set only in
mod_fastcgi and mod_scgi, and set to con->request.uri
Since lighttpd 1.4.40 provides REDIRECT_URI with con->request.orig_uri,
changes were made to REQUEST_URI for consistency, with the hope that
there would be little impact to existing configurations since the
request uri and original request uri are the same unless there has been
an internal redirect. It turns out that various PHP frameworks use
REQUEST_URI and require that it be the original URI requested by client.
Therefore, this change is being reverted, and lighttpd will set
REQUEST_URI to con->request.orig_uri in mod_cgi, mod_fastcgi, mod_scgi
as was done in lighttpd 1.4.39 and earlier. Similarly, REDIRECT_URI
also has the prior behavior in mod_fastcgi and mod_scgi, and added to
mod_cgi.
A future release of lighttpd might change mod_ssi to be consistent with
the other modules in setting REQUEST_URI to con->request.orig_uri and to
add REDIRECT_URI, when an internal redirect has occurred.
Strip bogus "Proxy" header before creating subprocess environment.
(mod_cgi, mod_fastcgi, mod_scgi, mod_ssi, mod_proxy)
Do not emit HTTP_PROXY to subprocess environment.
Some executables use HTTP_PROXY to configure outgoing proxy.
This is not a lighttpd security issue per se, but this change to
lighttpd adds a layer of defense to protect backend processes which
might be vulnerable due to blindly using this untrusted environment
variable. The HTTP_PROXY environment variable should not be trusted
by a program running in a CGI-like environment.
Mitigation in lighttpd <= 1.4.40 is to reject requests w/ Proxy header:
* Create "/path/to/deny-proxy.lua", read-only to lighttpd, with content:
if (lighty.request["Proxy"] == nil) then return 0 else return 403 end
* Modify lighttpd.conf to load mod_magnet and run lua code
server.modules += ( "mod_magnet" )
magnet.attract-raw-url-to = ( "/path/to/deny-proxy.lua" )
References:
https://www.kb.cert.org/vuls/id/797896
CGI web servers assign Proxy header values from client requests to
internal HTTP_PROXY environment variables
https://httpoxy.org/
httpoxy: A CGI application vulnerability
error out if duplicated unix socket path and different bin-path is
used by lighttpd to start the backend. This is an error.
Updates commits 97556d99 and b67ff2aa
x-ref:
"Should warn if two FastCGI servers point to same socket file"
https://redmine.lighttpd.net/issues/319
silently use same 'host' if unix socket path is duplicated
(instead of erroring out). Updates commit 97556d99
(It is possible for use of += in config to result in duplicated
fastcgi.server and scgi.server entries)
x-ref:
"Should warn if two FastCGI servers point to same socket file"
https://redmine.lighttpd.net/issues/319
do not expose server info server_tag is configured by admin
default con->conf.server_tag is still PACKAGE_DESC, those
admin can configure server.tag otherwise.
(these changes reduce recompilation and relinking when switching
brances in source control)
cygwin does not support ioctl on sockets, returning EOPTNOTSUPP
(would be better if cygwin used Windows ioctlsocket() instead)
Windows uses signed (socklen_t), so add some casts to quiet warnings
Windows path handling is convoluted, so disable one tests in mod_fastcgi
since trailing spaces are removed from URL for _WIN32 and __CYGWIN__ in
response.c
Set server.stream-response-body = 1 or server.stream-response-body = 2
to have lighttpd stream response body to client as it arrives from the
backend (CGI, FastCGI, SCGI, proxy).
default: buffer entire response body before sending response to client.
(This preserves existing behavior for now, but may in the future be
changed to stream response to client, which is the behavior more
commonly expected.)
x-ref:
"fastcgi, cgi, flush, php5 problem."
https://redmine.lighttpd.net/issues/949
"Random crashing on FreeBSD 6.1"
https://redmine.lighttpd.net/issues/760
"Memory usage increases when proxy+ssl+large file"
https://redmine.lighttpd.net/issues/1283
"lighttpd+fastcgi memory problem"
https://redmine.lighttpd.net/issues/1387
move code in dynamic handlers (CGI, FastCGI, SCGI, proxy)
from *_handle_fdevent() to *_recv_response() for reuse
outside the *_handle_fdevent() routine
Set server.stream-request-body = 1 or server.stream-request-body = 2
to have lighttpd connect to backend (CGI, FastCGI, SCGI, proxy)
immediately after parsing request headers, and to stream request body
as it arrives.
default: buffer entire request body before connecting to backend,
in order to avoid tying up (limited) backend resources which are often
implemented using libraries which wait for entire request body before
proceeding.
x-ref:
"Reimplement upload (POST) handling to match apache/zeus/thttpd/boa functionality"
https://redmine.lighttpd.net/issues/376
handle X-Sendfile and X-LIGHTTPD-send-file w/ http_response_xsendfile()
if host is configured ( "x-sendfile" = "enable" )
Note: X-Sendfile path is url-decoded for consistency, like X-Sendfile2
(response headers should be url-encoded to avoid tripping over
chars allowed in filesystem but which might change response
header parsing semantics)
Note: deprecated: "allow-x-send-file"; use "x-sendfile"
Note: deprecated: X-LIGHTTPD-send-file header; use X-Sendfile header
Note: deprecated: X-Sendfile2 header; use X-Sendfile header
For now, X-Sendfile2 is still handled internally by mod_fastcgi.
Since http_response_send_file() supports HTTP Range requests,
X-Sendfile2 is effectively obsolete. However, any code, e.g. PHP,
currently using X-Sendfile2 is probably manually generating 206 Partial
Content status and Range response headers. A future version of lighttpd
might *remove* X-Sendfile2. Existing code should be converted to use
X-Sendfile, which is easily done by removing all the special logic
around using X-Sendfile2, since the 206 Partial Content status and Range
response headers are handled in http_response_send_file().
x-ref:
"mod_fastcgi + X-Sendfile -> mod_staticfile"
https://redmine.lighttpd.net/issues/799
"Feature Request: New option "x-send-file-docroot""
https://redmine.lighttpd.net/issues/851
"X-Sendfile handoff to mod-static-file in 1.4.x"
https://redmine.lighttpd.net/issues/2017
"X-sendfile should be able to set content-type"
https://redmine.lighttpd.net/issues/2076
server.error-handler preserves HTTP status error code when error page
is static, and allows dynamic handlers to change HTTP status code
when error page is provided by dynamic handler. server.error-handler
intercepts all HTTP status codes >= 400 except when the content is
generated by a dynamic handler (cgi, ssi, fastcgi, scgi, proxy, lua).
The request method is unconditionally changed to GET for the request
to service the error handler, and the original request method is
later restored (for logging purposes). request body from the
original request, if present, is discarded.
server.error-handler is somewhat similar to server.error-handler-404,
but server.error-handler-404 is now deprecated, intercepts only 404
and 403 HTTP status codes, and returns 200 OK for static error pages,
a source of confusion for some admins. On the other hand, the new
server.error-handler, when set, will intercept all HTTP status error
codes >= 400. server.error-handler takes precedence over
server.error-handler-404 when both are set.
NOTE: a major difference between server.error-handler and the
now-deprecated server.error-handler-404 is that the values of the
non-standard CGI environment variables REQUEST_URI and REDIRECT_URI
have been swapped. Since REDIRECT_STATUS is the original HTTP
status code, REDIRECT_URI is now the original request, and REQUEST_URI
is the current request (e.g. the URI/URL to the error handler).
The prior behavior -- which reversed REQUEST_URI and REDIRECT_URI values
from those described above -- is preserved for server.error-handler-404.
Additionally, REDIRECT_STATUS is now available to mod_magnet, which
continues to have access to request.uri and request.orig_uri.
See further discussion at https://redmine.lighttpd.net/issues/2702
and https://redmine.lighttpd.net/issues/1828
github: closes #36