summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorHauke Mehrtens2026-06-13 00:40:15 +0000
committerHauke Mehrtens2026-06-15 23:30:15 +0000
commitae015e099986ceace44975cb69629841a2d58d37 (patch)
treec02f54e973bc643ce9dc6c02ccc6dff483d249e3
parent1b624f8f814ed568608d756512892416e0431d77 (diff)
downloaduhttpd-ae015e099986ceace44975cb69629841a2d58d37.tar.gz
client: reject unhandled Transfer-Encoding values
client_parse_header() lowercases header names but compared the Transfer-Encoding value with a case-sensitive strcmp(val, "chunked"). RFC 9112 6.1 requires transfer-coding tokens to be matched case-insensitively, so a request with "Transfer-Encoding: Chunked" was accepted but chunked framing was never enabled. The declared body was then left unread and, on a keep-alive connection, parsed as the next HTTP request (request smuggling). Match "chunked" with strcasecmp and reject any other transfer-coding we do not implement with 501, instead of silently ignoring it and losing track of the message framing. Link: https://github.com/openwrt/uhttpd/security/advisories/GHSA-mcfg-c4r7-pjpf Reported-by: @dyingc Assisted-by: Claude:claude-opus-4-8 Signed-off-by: Hauke Mehrtens <hauke@hauke-m.de>
-rw-r--r--client.c10
1 files changed, 9 insertions, 1 deletions
diff --git a/client.c b/client.c
index 48231cf..caec7f8 100644
--- a/client.c
+++ b/client.c
@@ -403,8 +403,16 @@ static void client_parse_header(struct client *cl, char *data)
}
r->content_length = (int)length;
} else if (!strcmp(data, "transfer-encoding")) {
- if (!strcmp(val, "chunked"))
+ /* RFC 9112 6.1: transfer-coding tokens are case-insensitive.
+ * Reject any coding we do not implement instead of silently
+ * ignoring it, otherwise the body framing would be unknown and
+ * the unread body could be parsed as the next request. */
+ if (!strcasecmp(val, "chunked")) {
r->transfer_chunked = true;
+ } else {
+ uh_header_error(cl, 501, "Not Implemented");
+ return;
+ }
} else if (!strcmp(data, "connection")) {
if (!strcasecmp(val, "close"))
r->connection_close = true;