From: Alex Rousskov Date: Wed, 6 Apr 2011 16:25:36 +0000 (-0600) Subject: Fixed chunked request forwarding in ICAP REQMOD presence. X-Git-Tag: take06~27^2~30 X-Git-Url: http://git.ipfire.org/gitweb.cgi?a=commitdiff_plain;h=f228d6f6eaebf171858a67ea8bd625255b738ded;p=thirdparty%2Fsquid.git Fixed chunked request forwarding in ICAP REQMOD presence. 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. --- diff --git a/src/http.cc b/src/http.cc index d001e25313..2d0e94fa12 100644 --- a/src/http.cc +++ b/src/http.cc @@ -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);