summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorJo-Philipp Wich2025-04-05 23:35:10 +0000
committerJo-Philipp Wich2025-04-05 23:36:37 +0000
commitc7294e7037a9e6f8fb4b9084d31cb8e98bd7b5f9 (patch)
tree07a7b4a58802f9240f4f447c237bd832bd9ae879
parent3d6f01b9d01a6ffa9e73705112cd51bfd98ec2fc (diff)
downloaduhttpd-c7294e7037a9e6f8fb4b9084d31cb8e98bd7b5f9.tar.gz
client: reject requests with multiple content-lengths and/or TEs
Add logic to reject requests with multiple Content-Length headers or both Content-Length and Transfer-Encoding headers. Fixes: #8 Signed-off-by: Jo-Philipp Wich <jo@mein.io>
-rw-r--r--client.c36
1 files changed, 36 insertions, 0 deletions
diff --git a/client.c b/client.c
index a987867..1d302d7 100644
--- a/client.c
+++ b/client.c
@@ -234,6 +234,39 @@ static bool client_init_cb(struct client *cl, char *buf, int len)
return true;
}
+static bool request_header_check(struct client *cl)
+{
+ size_t num_transfer_encoding = 0;
+ size_t num_content_length = 0;
+ struct blob_attr *cur;
+ int rem;
+
+ blob_for_each_attr(cur, cl->hdr.head, rem) {
+ if (!strcasecmp(blobmsg_name(cur), "Transfer-Encoding"))
+ num_transfer_encoding++;
+ else if (!strcasecmp(blobmsg_name(cur), "Content-Length"))
+ num_content_length++;
+ }
+
+ /* Section 3.3.2 of RFC 7230: messages with multiple Content-Length headers
+ containing different values MUST be rejected as invalid. Messages with
+ multiple Content-Length headers containing identical values MAY be
+ rejected as invalid */
+ if (num_content_length > 1) {
+ uh_header_error(cl, 400, "Bad Request");
+ return false;
+ }
+
+ /* Section 3.3.3 of RFC 7230: messages with both Content-Length and
+ Transfer-Encoding ought to be handled as an error */
+ if (num_content_length > 0 && num_transfer_encoding > 0) {
+ uh_header_error(cl, 400, "Bad Request");
+ return false;
+ }
+
+ return true;
+}
+
static bool rfc1918_filter_check(struct client *cl)
{
if (!conf.rfc1918_filter)
@@ -298,6 +331,9 @@ static void client_header_complete(struct client *cl)
{
struct http_request *r = &cl->request;
+ if (!request_header_check(cl))
+ return;
+
if (!rfc1918_filter_check(cl))
return;