]> git.ipfire.org Git - thirdparty/squid.git/commitdiff
Fixed chunked request forwarding in ICAP REQMOD presence.
authorAlex Rousskov <rousskov@measurement-factory.com>
Wed, 6 Apr 2011 16:25:36 +0000 (10:25 -0600)
committerAlex Rousskov <rousskov@measurement-factory.com>
Wed, 6 Apr 2011 16:25:36 +0000 (10:25 -0600)
ICAP prohibits forwarding of hop-by-hop headers in HTTP headers. If the virgin
request has a "Transfer-Encoding: chunked" header, the ICAP server will not
receive it. Thus, when the ICAP server responds with a 200 OK and what it
thinks is a copy of the HTTP request, the adapted request will be missing the
Transfer-Encoding header.

One the server side, Squid used to test whether the request had a
Transfer-Encoding header to determine whether request chunking is needed when
talking to the next HTTP hop. That test would fail in ICAP REQMOD presence.

This change implements a more direct/robust check: if we do not know the
request content length, we chunk the request.

We also no longer forward the Content-Length header if we are chunking. It
should not really be there in most cases, but an explicit check is safer and
may also prevent request smuggling attacks via Connection: Content-Length
tricks.

src/http.cc

index d001e2531326e08c816e14b4b72c1c4762cc2023..2d0e94fa1220a6fc2cca2efa7023043a65295ca4 100644 (file)
@@ -1966,6 +1966,13 @@ copyOneHeaderFromClientsideRequestToUpstreamRequest(const HttpHeaderEntry *e, co
     case HDR_PROXY_CONNECTION: // SHOULD ignore. But doing so breaks things.
         break;
 
+    case HDR_CONTENT_LENGTH:
+        // pass through unless we chunk; also, keeping this away from default
+        // prevents request smuggling via Connection: Content-Length tricks
+        if (!flags.chunked_request)
+            hdr_out->addEntry(e->clone());
+        break;
+
     case HDR_X_FORWARDED_FOR:
 
     case HDR_CACHE_CONTROL:
@@ -2088,8 +2095,8 @@ HttpStateData::sendRequest()
                                     Dialer, this, HttpStateData::sentRequestBody);
 
         Must(!flags.chunked_request);
-        // Preserve original chunked encoding unless we learned the length.
-        if (orig_request->header.chunked() && orig_request->content_length < 0)
+        // use chunked encoding if we do not know the length
+        if (orig_request->content_length < 0)
             flags.chunked_request = 1;
     } else {
         assert(!requestBodySource);