need to build wolfSSL library with --enable-alpn for ALPN
even if already building wolfSSL library with --enable-openssall
(sigh)
ALPN is required by the HTTP/2 specification
crippled functionality if wolfssl library not built --enable-opensslall
* SNI not handled since SNI callbacks are disabled in wolfSSL library
unless the wolfSSL library is built with --enable-openssall
This means that there is only one certificate per listening socket --
no certificate selection based on server name indication (SNI)
and is additionally a violation of the HTTP/2 specification,
which requires SNI.
slightly reduced functionality if wolfssl not built --enable-opensslall
* disable client certificate verification (error out if in lighttpd.conf)
* omit SSL_CIPHER_USEKEYSIZE, SSL_CIPHER_ALGKEYSIZE env vars
(thx avij)
must update the cached copy of global scope config after cycling log.
Although (accesslog_st *) is modified in-place, the log_access_fd member
of (accesslog_st *) is copied into the cache and must be updated after
cycling logs in the global scope.
basic algorithms fail if NSS library has not been init'd (WTH)
lighttpd defers initialization of rand and crypto until first use
to attempt to avoid long, blocking init at startup while waiting
for sufficient system entropy to become available
use http_chunk_append_file_ref() and http_chunk_append_file_ref_range()
reduce resource usage (number of fds open) by reference counting open
fds to files served, and sharing the fd among FILE_CHUNKs in responses
minimize pause during graceful restart for server.max-worker = 0 case
The previous generation continues to accept new connections until the
restarted parent signals that the restarted server is ready to accept
new connections, and so the previous server should gracefully shutdown.
This does not apply in the case of multiple workers.
When there are multiple workers, they receive SIGINT to gracefully shut
down and stop accepting new connections. While the listen sockets are
kept open (and not closed and reopened), there is a small pause while
the parent process restarts before it begins accepting new connections
from the listen backlog.
Note: there is a window during restart during which lighttpd may exit
if it receives certain signals before it sets up signal handlers.
future: might block signals (sigprocmask()) during restart, but if that
is done, then care must be taken to unblock signals in restarted server
as soon as signal handlers are set up and before any other children are
created, e.g. by modules, or else signals must be explicitly unblocked
in children. Also, during command line and config file processing,
signals would be blocked, too, which might not be ideal.
use NSS crypto if no other crypto avail, but NSS crypto is available
"NSS crypto support" is not included in tests/LightyTest.pm:has_crypto()
due to NSS libraries (freebl3) lacking public export for HMAC funcs
wolfSSL_CTX_set_mode() differs from openssl SSL_CTX_set_mode().
wolfSSL_CTX_set_mode() takes a single flag at a time and has
sparse flag support (small number of recognized flags)
return values for sys-crypto-md.h interfaces
While some library implementations do not fail and have no return value,
others might fail on memory allocation or on failure to communicate with
an external or dedicated engine or device, e.g. which might store a
private key.
future: lighttpd callers of sys-crypto-md.h do not currently expect
or check for errors from these digest functions, but should
consider doing so.
provide implementations for conventional digest interfaces
but use the newer openssl digest interfaces under the hood
<rant>
It is baffling that the openssl library -- with *thousands* of public
interfaces -- does not provide these, and suggests that openssl
developers do not frequently write apps which utilize these interfaces.
</rant>
avoid potential double-copy due to not enough space for final '\0'
in http_chunk_append_read_fd_range() if read size is exactly multiple
of 8k and sending chunked response
simple interface to cache open file by extending struct stat_cache_entry
future: should probably create fd cache separate from stat_cache,
perhaps along w/ http-specific fields like etag and content_type
walk chunkqueue up to first FILE_CHUNK (if present)
This may incur memory load misses for pointer chasing, but effectively
preloads part of the chunkqueue, something which used to be a side
effect of a previous (less efficient) version of chunkqueue_length()
which walked the entire chunkqueue (on each and every call). The loads
here make a measurable difference in performance in underlying call to
con->network_write()
(replace existing check which suffered from ToC-ToU race condition)
enhances logic from 2015 commit 593599f1 and avoids repeated fstat()
checks when sending large files
For mmap(), lighttpd catches SIGBUS if file is (externally) truncated
and lighttpd attempts to access bytes in a read-only mapping more than
a memory page boundary following the end of the file.
For sendfile(), lighttpd returns an error if sendfile() reports no error
and that no bytes have been sent after lighttpd attempts to send a
non-zero number of bytes.
server.feature-flags += ("server.graceful-shutdown-timeout" => 10)
After receiving SIGINT or SIGUSR1, lighttpd will gracefully shutdown,
waiting for existing connections to complete. In the case of SIGUSR1,
this wait occurs before restarting lighttpd. The default timeout is
none (unlimited).
When "server.graceful-shutdown-timeout" option is set, it defines the
number of seconds that lighttpd will wait for existing connections to
complete before shutting down the connection.
Sites which expect large uploads or downloads, or those with very slow
clients, might want to set a much longer timeout, e.g 60 seconds
For more immediate graceful restarts, while still allowing existing
connections time to complete, sites should additionally consider
whether or not
server.feature-flags += ("server.graceful-restart-bg" => "enable")
is appropriate and compatible with their lighttpd.conf settings
graceful and (nearly) immediate lighttpd restart option
For *some* configurations, it *may* be safe to background the current
lighttpd server (or workers) to continue processing active requests
and, in parallel, to start up a new lighttpd server with a new
configuration. For other configurations, doing so might not be safe!
Therefore, this option must be explicitly configured to enable:
server.feature-flags += ("server.graceful-restart-bg" => "enable")
server.systemd-socket-activation = "enable"
Along with enabling server.feature-flags "server.graceful-restart-bg",
enabling server.systemd-socket-activation allows transfer of open
listening sockets to the new lighttpd server instance, and occurs
without closing the listening sockets and without destroying the
kernel listen backlog queue on the socket.
Safe configurations may include lighttpd.conf which connect to
standalone backend daemons, e.g. proxying to other servers,
including PHP-FPM backends.
Unsafe configurations include lighttpd.conf which use "bin-path" option
in *.server configs, instructing lighttpd to execute the backends.
Using the graceful-and-immediate-restart option is likely *unsafe* if
the backend daemon expects only one instance of itself to run at a time.
Current implementation of graceful and immediate restart option keeps
the backgrounded lighttpd in the same process group, so that subsequent
SIGINT or SIGTERM will shut down both the new and the backgrounded
servers. (An alternative option (commented out in the code) is to
background and detach from the new lighttpd process.) Regardless,
existing subprocesses, such as CGI, remain in original process group.
As a result, the new lighttpd server may receive SIGCHLD for unknown
processes inherited from the old server, which the new lighttpd server
will reap and discard. The original lighttpd server, now a child, will
be unable to detect exit or reap and report status on those pre-existing
subprocesses.
Graceful restart is triggered in lighttpd by sending lighttpd SIGUSR1.
If lighttpd is configured with workers, then SIGINT (not SIGUSR1) is
sent to the process group, including other processes started by
lighttpd, e.g. CGI. To work well with graceful restart, CGI scripts and
other processes should trap SIGINT (and SIGUSR1 for good measure).
Long-running scripts may want to checkpoint and close, e.g. a CGI script
implementing a long-running websocket connection.
(experimental)
add option to run lua scripts in lighttpd response start hook
allows for response header manipulation
new params provide read-only access:
lighty.env["response.http-status"]
lighty.env["response.body-length"]
lighty.env["response.body"]
allows for content manipulation if the response body is complete
The HTTP response status can be accessed in lua via
lighty.env["response.http-status"] and should be checked, as
appropriate, prior to body manipulation. The value is non-zero
in response start hook (magnet.attract-response-start-to), but is
likely to be 0 in scripts run from other lighttpd hooks earlier in
request processing,
e.g. magnet.attract-raw-url-to or magnet.attract-physical-path-to
Caller should check lighty.env["response.body-length"]
is a smaller and sane amount to read into memory and copy
a second time into lua data structures. The value is lua nil
if the response body is not yet complete (or if it is >= 2GB-1)
Loading the response body (and all mod_magnet lua scripts) are
executed serially (blocking) in lighttpd, so its use is highly
discouraged on large files. The body can be accessed in lua via
lighty.env["response.body"] if the response body is complete.
(recommended config option: server.stream-response-body = 0 (default)
if mod_magnet scripts must process the response body)
Modifying HTTP response status and response body has not changed
and is achieved by setting lua script return value and modifying
the lighty.content lua table.
(note: mod_magnet, mod_setenv, mod_deflate, mod_expire have their
response start hooks run in the order listed in server.modules)
relay 1xx from backend over HTTP/1.1, e.g. 103 Early Hints
(if client is connected using HTTP/1.1)
enabled by default unless disabled in lighttpd.conf with:
server.feature-flags += ( "server.h1-discard-backend-1xx" = "enable" )
Warning: backends which send 103 Early Hints should check User-Agent
before doing so since naive clients might not handle unexpected 1xx.
Some clients may take the 1xx response as the final response, expecting
only one response. Some clients might not properly handle 100 Continue
if the client did not send Expect: 100-continue with the request.
https://tools.ietf.org/html/rfc8297#section-3 Security Considerations
x-ref:
An HTTP Status Code for Indicating Hints (103 Early Hints)
https://tools.ietf.org/html/rfc8297
relay 1xx from backend over HTTP/2, e.g. 103 Early Hints
(if client is connected using HTTP/2)
enabled by default unless disabled in lighttpd.conf with:
server.feature-flags += ( "server.h2-discard-backend-1xx" = "enable" )
Warning: backends which send 103 Early Hints should check User-Agent
before doing so since naive clients might not handle unexpected 1xx.
Some clients may take the 1xx response as the final response, expecting
only one response. Some clients might not properly handle 100 Continue
if the client did not send Expect: 100-continue with the request.
https://tools.ietf.org/html/rfc8297#section-3 Security Considerations
x-ref:
An HTTP Status Code for Indicating Hints (103 Early Hints)
https://tools.ietf.org/html/rfc8297
support multiple 1xx intermediate responses from backends
Currently, all 1xx responses from backends are discarded.
In the future, these 1xx responses may be forwarded to the client
(when lighttpd also configured server.stream-response-body = 1 or = 2)
(optional addition to (data_string *), used by http_header.[ch])
extend (data_string *) instead of creating another data_* TYPE_*
(new data type would probably have (data_string *) as base class)
(might revisit choice in the future)
HTTP_HEADER_UNSPECIFIED has been removed. It was used in select
locations as an optimization to avoid looking up enum header_header_e
before checking the array, but the ordering in the array now relies
on having the id. Having the id allows for a quick check if a common
header is present or not in the htags bitmask, before checking the
array, and allows for integer comparison in the log(n) search of the
array, instead of strncasecmp().
With HTTP_HEADER_UNSPECIFIED removed, add optimization to set bit
in htags for HTTP_HEADER_OTHER when an "other" header is added,
but do not clear the bit, as there might be addtl "other" headers
header field-names are required to be lowercase for HTTP/2
so specialize http_header_hkey_get() as http_header_hkey_get_lc()
for simpler comparison
lowercase field-names in http_headers[], as it does not matter for
buffer_eq_icase_ssn(), which is used with http_headers[] for HTTP/1.x
separate http_header_e index from r->{rqst,resp}_htags bitmask
(allows http_header_e remain 32-bit and to be used in array indexes
while also allowing r->{rqst,resp}_htags to grow to 64-bits wide
in the future, without requiring invasive changes)
allow h2.c layer to modify r->state in addition to r->h2state
Do not retire/release r on error if trailers (as opposed to headers)
(stream r was just allocated in the same scope for headers,
so ok to release)
log stream id with debug.log-state-handling in
connection_state_machine_loop()
(id will be 0 for HTTP/2 connection, but not for streams on connection)
(id will be 0 for HTTP/1.x requests)
(thx avij)
clients should send a single Cookie header with multiple cookie values
separated with ';'.
https://tools.ietf.org/html/rfc6265#section-4.2.1
However, HTTP/2 loosens this requirement for Cookie.
https://tools.ietf.org/html/rfc7540#section-8.1.2
Section 8.1.2.5 Compressing the Cookie Header Field
and some HTTP/2 clients (Chrome, Firefox) send multiple
'cookie:' headers in a HEADERS frame.
only XXH32() is used by ls-hpack, so disable XXH64() and XXH3()
to reduce code size. (This maybe be changed in the future if
XXH64() or XXH3() are utilitized for their performance)
(bug on master branch; never released)
(thx avij)
update doc that dir-listing.hide-dotfiles = "enable" by default
since lighttpd 1.4.40 https://redmine.lighttpd.net/issues/1081
(bug on master branch; never released)
(thx avij)
fix crash on master if blank line precedes HTTP/1.1 keep-alive request
header parsing code previously made assumptions that request was
HTTP/1.0 or HTTP/1.1, where a request-line was required, and which
would error out elsewhere if request-line was missing. The parsing
code also previously looked for "\r\n\r\n" to end headers.
The header offset parsing code was modified and invalidated the above
assumptions, now looking only for blank line "\r\n", but the calling
code had not properly been updated. (until this patch)
define LSHPACK_DEC_HTTP1X_OUTPUT 0
lighttpd does not require HTTP/1.1 output compat from HPACK decoder
("field-name: value\r\n")
define NDEBUG (in ls-hpack/lshpack.c)
lighttpd spends upwards of 20% total lighttpd CPU time in HPACK
encode/decode in h2load test on static file over cleartext (not TLS)
Defining NDEBUG eliminates some asserts() and results in a small
but measurable reduction in CPU usage
defer optimization to read small files into memory until after
response_start hooks have a chance to run, e.g. until after
mod_deflate chooses whether or not to serve file from compressed
cache, if deflate.cache-dir is configured
fork connection_get_state() for use by mod_status, which
might in the future choose to display different labels.
move and rename connection_get_short_state() into mod_status,
as the func is used only by mod_status
(connection_get_state() is currently used elsewhere only for debugging
in connections.c)
Empty field-name is already ignored when generating response headers,
but this is an explicit skip of empty field-name sent from backends,
including field-names that look like HTTP/2 pseudo-headers, as those
begin with ':'.
Location response header is permitted to use relative-path in
RFC 7231 Section 7.1.2. Location
Prefer relative path in redirection for the benefit of reverse proxies
and CDNs. Doing so also avoids potentially disclosing internal schemes
and server names which client might not be able to directly reach.
To restore prior behavior of sending a fully-qualified absolute URI:
server.feature-flags += ("absolute-dir-redirect" => "enable")
x-ref:
https://bz.apache.org/bugzilla/show_bug.cgi?id=63357
http_request_parse_header() specialized for HTTP/2 request headers
to be parsed as each field-name and value is HPACK-decoded; send headers
directly from HPACK decoder, rather than double-buffering in chunkqueue
http_request_headers_process_h2() for post-processing
LiteSpeed ls-hpack v2.2.1
XXX: might be better to include this as a git submodule
but minor code changes were made here for portability:
- C99 flexible array members defined as a[] instead of a[0])
- pedantic compiler warnings (excess ';' and missing declarations)
- deletion of large tables from ls-hpack/huff-tables.h (code size)
(subsequently incrementally updated using git rebase)
huge props and many thank yous to writers of testing tools used while
developing HTTP/2 support in lighttpd:
h2spec - conformance testing tool for HTTP/2 implementation
https://github.com/summerwind/h2spec
h2load - HTTP/2 benchmarking tool
https://nghttp2.org/documentation/h2load-howto.html
curl - command line tool and library for transferring data with URLs
https://curl.haxx.se/
move code from connections-glue.c back into connections.c
move code from connections-glue.c to http-header-glue.c
rename connection_response_reset()
to http_response_reset()
rename connection_handle_read_post_error()
to http_response_reqbody_read_error()
r->con->reqbody_read() replaces connection_handle_read_post_state()
future: might provide different callbacks for request body with
Content-Length versus request body sent via Transfer-Encoding: chunked
Note: rrdtool counts do not include HTTP/2 protocol overhead.
Continue to count mod_rrdtool per request rather than per connection
so that data is updated after each request, rather than aggregated
to the end of a potentially long-lived connection with many keep-alives.
reset connection counters per connection, not per request
adjust mod_accesslog and mod_rrdtool usage
continue to count mod_rrdtool per request rather than per connection
so that data is updated after each request, rather than aggregated
to the end of a potentially long-lived connection with many keep-alives.
Even though request headers are per-request, update the proto on the
connection level for trusted (proxy) clients. Note: the proxy must use
each connection only for a single connection from a single client
(typically true in practice), and not for multiple clients.
proto was previously saved on connection level for mod_extforward with
HAProxy PROXY protocol, but did not occur with X-Forwarded-Proto or the
Forwarded request header with proto=...
Before this change, modules which returned HANDLER_COMEBACK could lose
HTTPS=on if the resulting request was for a backend such as mod_fastcgi.
This was reported in mod_rewrite, but could also affect mod_magnet if
MAGNET_RESTART_REQUEST, or mod_cgi with cgi.local-redir = "enable"
x-ref:
"FastCGI behavior different when using rewrite?"
https://redmine.lighttpd.net/boards/2/topics/9293
gamin should be used instead of fam; fam is no longer maintained
This patch makes it safe to build lighttpd with gamin, but run on
systems with the (deprecated) fam installed, which can happen due
to historical package dependency declarations on some platforms
(Debian, Ubuntu).
gamin and fam are not 100% binary compatible.
(Among other things, fam does not provide FAMNoExists())
x-ref:
"llibgamin vs libfam conflict solving"
https://salsa.debian.org/debian/lighttpd/-/merge_requests/18
"libgamin0: libfam shlib dependency wrongly set to libfam0"
https://bugs.debian.org/cgi-bin/bugreport.cgi?bug=510368
"undefined symbol: FAMNoExists"
https://bugs.launchpad.net/bugs/1453463
fix fallback if linkat() fails
check at startup if /proc/self/fd is present on systems with O_TMPFILE
(containers might not mount /proc)
x-ref:
"mod_webdav - PUT files with < 64kb Content-Length reults in zero length file"
https://redmine.lighttpd.net/boards/2/topics/9273