On Tue, 29 Mar 2005, Tracey, Michael wrote:
I've got a site that is required in our business flow that I can not change:
HTTP/1.1 200 OK Server: Microsoft-IIS/5.0 Date: Tue, 29 Mar 2005 19:15:38 GMT Content-type: image/jpeg Content-length: 38233 Cache-Control: no-cache Pragma: no-cache Expires: 0 Content-Length: 39145
Squid chokes on the two Content-Length headers:
2005/03/29 14:18:20| ctx: enter level 0: 'http://url/' 2005/03/29 14:18:20| WARNING: found two conflicting content-length headers 2005/03/29 14:18:20| ctx: exit level 0
Any way that I can get squid allow access to content with two Content-Length headers?
Have been pondering about this problem for a while and came up with the attached patch as a possible solution. This patch cleans up the "bad" content-length headers when relaxed_header_parser is enabled (on/warn setting, default is on).
I have also considered making yet another access lists for this but in the end decided not to (both more complex to implement and hard to configure right).
The effects of the patch has not yet been fully evaluated to make sure it doesn't open opportunities for launching the response splitting or request hiding families of attacks on Squid but from an quick evaluation it looks safe.
Regards Henrik
Index: src/HttpHeader.c =================================================================== RCS file: /cvsroot/squid/squid/src/HttpHeader.c,v retrieving revision 1.74.2.28 diff -u -p -r1.74.2.28 HttpHeader.c --- src/HttpHeader.c 6 May 2005 21:32:09 -0000 1.74.2.28 +++ src/HttpHeader.c 18 May 2005 15:47:10 -0000 @@ -475,9 +475,25 @@ httpHeaderParse(HttpHeader * hdr, const } if (e->id == HDR_CONTENT_LENGTH && (e2 = httpHeaderFindEntry(hdr, e->id)) != NULL) { if (strCmp(e->value, strBuf(e2->value)) != 0) { - debug(55, 1) ("WARNING: found two conflicting content-length headers in {%s}\n", getStringPrefix(header_start, header_end)); - httpHeaderEntryDestroy(e); - return httpHeaderReset(hdr); + squid_off_t l1, l2; + debug(55, Config.onoff.relaxed_header_parser <= 0 ? 1 : 2) ("WARNING: found two conflicting content-length headers in {%s}\n", getStringPrefix(header_start, header_end)); + if (!Config.onoff.relaxed_header_parser) { + httpHeaderEntryDestroy(e); + return httpHeaderReset(hdr); + } + if (!httpHeaderParseSize(strBuf(e->value), &l1)) { + debug(55, 1)("WARNING: Unparseable content-length '%s'\n", strBuf(e->value)); + httpHeaderEntryDestroy(e); + continue; + } else if (!httpHeaderParseSize(strBuf(e2->value), &l2)) { + debug(55, 1)("WARNING: Unparseable content-length '%s'\n", strBuf(e2->value)); + httpHeaderDelById(hdr, e2->id); + } else if (l1 > l2) { + httpHeaderDelById(hdr, e2->id); + } else { + httpHeaderEntryDestroy(e); + continue; + } } else { debug(55, Config.onoff.relaxed_header_parser <= 0 ? 1 : 2) ("NOTICE: found double content-length header\n");