Webserver-scoped log lines now carry the same severity prefix and
process/thread ID format as FTL.log. log_web() gained (priority, flag)
arguments - log_web(priority, ...) for plain messages and
log_web_debug(flag, ...) for gated debug output - and both are emitted
to the FIFO buffer and webserver.log. Call sites across the API and the
web server were moved over, keeping process-health messages in FTL.log.
Signed-off-by: darkexplosiveqwx <101737077+darkexplosiveqwx@users.noreply.github.com>
x509: keep TLS log messages in FTL.log
The TLS problems in x509.c are process-health signals ("HTTPS is broken")
and belong in FTL.log. The earlier move to log_web()/webserver.log also
made the file inconsistent within one function: set_name() and the fchmod()
warning in write_to_file() are reached only from generate_certificate(),
whose other failure sites all stayed log_err(). --read-x509 output only
stays clean because args.c disables file logging before the call.
Revert all log sites here to _FTL_log().
Signed-off-by: darkexplosiveqwx <101737077+darkexplosiveqwx@users.noreply.github.com>
weblog: decide whether to relay before printing to stdout
_log_web() printed to stdout and then, when the web log file could not be
opened, handed the message to _FTL_log(), which prints to stdout under the
same condition. On a foreground run with an unwritable files.log.webserver
every relayed error showed up twice on the console.
Compute whether we relay (print_log set, no web log available, severity
WARNING or worse) before printing anything and let _FTL_log() own the
whole message - stdout, FIFO, FTL.log/syslog - in that case.
Signed-off-by: darkexplosiveqwx <101737077+darkexplosiveqwx@users.noreply.github.com>
The sources are now copied from https://github.com/DL6ER/civetweb (branch
`pi-hole`), which is CivetWeb master plus the fixes we have pending upstream.
That branch stays deliberately close to master - only necessary and security
fixes go on it, everything Pi-hole specific stays in `patch/civetweb/`.
This picks up two memory-safety fixes we were missing: the integer underflow in
the multipart form field length, where `next` can point before `hend` on a
malformed part and the unchecked pointer subtraction underflows `size_t`, and
the endless loop on a truncated URL-encoded body. Neither is upstream yet, so
waiting for a CivetWeb release would not have given us either. It also brings
the error status for custom error pages, which we need for the static web
interface.
`patch/civetweb.sh` now applies the stack with `git apply --3way` rather than
`patch`. This is not cosmetic: `patch` matches hunks by surrounding context and
silently applies them elsewhere when that context has drifted. Dropping our
sources in and running the old script applied three patches into the wrong place
while still reporting success, so `mg_request_info.csrf_token`, the
`mg_server_port.addr` union and the thread `setpriority()` call all vanished and
the tree no longer compiled. A three-way merge uses the blob a patch was
generated against and either merges correctly or leaves a real conflict, and it
copes with code moving around - which is the normal case after a bump. The
script also fails now instead of printing that everything applied okay.
The Kepler patch had lost the leading space on three of its context lines, which
GNU `patch` tolerates and `git apply` rejects; those are restored.
The PROXY protocol v2 patch is dropped: it is on the fork as a commit, so
carrying it here as well conflicts.
Signed-off-by: DL6ER <dl6er@dl6er.de>
Since the migration from mbedTLS to OpenSSL (#2941), OpenSSL surfaces the
TLS alert a browser sends when it rejects our self-signed certificate
(`certificate_unknown` / `unknown_ca`) on its error queue. CivetWeb dumps
that queue verbatim through `mg_cry_internal`, so `webserver.log` now fills
with `sslize error: ...` lines on every fresh connection - something
mbedTLS silently swallowed before.
Such a handshake is recoverable, i.e., the user clicks through the warning
and the connection proceeds, so it is not really an error on our side. When
the failing `sslize` runs in a server context and the reason is a received
TLS alert (reason >= `SSL_AD_REASON_OFFSET`), log it via `DEBUG_TRACE`
instead, which only prints when `debug.webserver` is enabled. Genuine SSL
errors and the client path keep crying into the log as before.
The in-tree `civetweb.c` change is mirrored in
`patch/civetweb/0001-Demote-server-side-TLS-handshake-alerts-to-debug.patch`
so it survives the next CivetWeb update.
Signed-off-by: DL6ER <dl6er@dl6er.de>
pi_hole_extra_headers is a global char[1024] buffer written by API
handlers and read/cleared by civetweb's send_additional_header(), but
civetweb runs up to 50 worker threads concurrently. When multiple
threads handle authenticated requests in parallel, one thread can
overwrite or clear another's header data, causing wrong Set-Cookie
headers to be sent to wrong clients or cookies to be dropped entirely.
Make pi_hole_extra_headers _Thread_local so each worker thread gets its
own buffer. This is safe because civetweb handles each request entirely
within a single thread.
The auth_data session array has a similar race: concurrent threads
read/modify sessions without synchronization. Add a pthread mutex
protecting all auth_data access, using AUTOLOCK/AUTOUNLOCK macros based
on __attribute__((cleanup)) for RAII-style auto-unlock — ensuring the
mutex is released on every exit path, including hidden returns inside
JSON macros that do `return 500` on allocation failure.
Change api->session from a pointer into auth_data to an embedded struct
copy so downstream API handlers read from a per-request snapshot rather
than shared state. Use JSON_COPY_STR_TO_OBJECT for auth_data strings
so the JSON tree owns its own copies after the lock is released.
Fixes: #2824
Signed-off-by: Dominik <dl6er@dl6er.de>