client: reject requests with multiple content-lengths and/or TEs
authorJo-Philipp Wich <[email protected]>
Sat, 5 Apr 2025 23:35:10 +0000 (01:35 +0200)
committerJo-Philipp Wich <[email protected]>
Sat, 5 Apr 2025 23:36:37 +0000 (01:36 +0200)
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 <[email protected]>
client.c

index a987867c14304ee0d0ceaac2956086c908b6bb12..1d302d7b2ba7b8ce878a4445e6ab3a2bec859333 100644 (file)
--- 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;