Sign Up
Log In
Log In
or
Sign Up
Places
All Projects
Status Monitor
Collapse sidebar
SUSE:SLE-12-SP4:GA
squid
SQUID-2020_8.patch
Overview
Repositories
Revisions
Requests
Users
Attributes
Meta
File SQUID-2020_8.patch of Package squid
from: commit fd68382860633aca92065e6c343cfd1b12b126e7 Author: Amos Jeffries <yadij@users.noreply.github.com> Date: Sun Aug 16 02:21:22 2020 +0000 Improve Transfer-Encoding handling (#702) Reject messages containing Transfer-Encoding header with coding other than chunked or identity. Squid does not support other codings. For simplicity and security sake, also reject messages where Transfer-Encoding contains unnecessary complex values that are technically equivalent to "chunked" or "identity" (e.g., ",,chunked" or "identity, chunked"). RFC 7230 formally deprecated and removed identity coding, but it is still used by some agents. Index: squid-3.5.21/src/HttpHeader.cc =================================================================== --- squid-3.5.21.orig/src/HttpHeader.cc +++ squid-3.5.21/src/HttpHeader.cc @@ -469,6 +469,7 @@ HttpHeader::operator =(const HttpHeader update(&other, NULL); // will update the mask as well len = other.len; conflictingContentLength_ = other.conflictingContentLength_; + teUnsupported_ = other.teUnsupported_; } return *this; } @@ -518,6 +519,7 @@ HttpHeader::clean() httpHeaderMaskInit(&mask, 0); len = 0; conflictingContentLength_ = false; + teUnsupported_ = false; PROF_stop(HttpHeaderClean); } @@ -723,11 +725,22 @@ HttpHeader::parse(const char *header_sta Raw("header", header_start, header_end - header_start)); } - if (chunked()) { + if (has(HDR_TRANSFER_ENCODING)) { + const String rawTe = getStrOrList(HDR_TRANSFER_ENCODING); // RFC 2616 section 4.4: ignore Content-Length with Transfer-Encoding delById(HDR_CONTENT_LENGTH); // RFC 7230 section 3.3.3 #4: ignore Content-Length conflicts with Transfer-Encoding conflictingContentLength_ = false; + + if (rawTe == "chunked") { + ; // leave header present for chunked() method + } else if (rawTe == "identity") { // deprecated. no coding + delById(HDR_TRANSFER_ENCODING); + } else { + // This also rejects multiple encodings until we support them properly. + debugs(55, warnOnError, "WARNING: unsupported Transfer-Encoding used by client: " << rawTe); + teUnsupported_ = true; + } } else if (clen.sawBad) { // ensure our callers do not accidentally see bad Content-Length values delById(HDR_CONTENT_LENGTH); Index: squid-3.5.21/src/HttpHeader.h =================================================================== --- squid-3.5.21.orig/src/HttpHeader.h +++ squid-3.5.21/src/HttpHeader.h @@ -267,7 +267,13 @@ public: int hasListMember(http_hdr_type id, const char *member, const char separator) const; int hasByNameListMember(const char *name, const char *member, const char separator) const; void removeHopByHopEntries(); - inline bool chunked() const; ///< whether message uses chunked Transfer-Encoding + + /// whether the message uses chunked Transfer-Encoding + /// optimized implementation relies on us rejecting/removing other codings + bool chunked() const { return has(HDR_TRANSFER_ENCODING); } + + /// whether message used an unsupported and/or invalid Transfer-Encoding + bool unsupportedTe() const { return teUnsupported_; } /* protected, do not use these, use interface functions instead */ std::vector<HttpHeaderEntry *> entries; /**< parsed fields in raw format */ @@ -282,6 +288,9 @@ protected: private: HttpHeaderEntry *findLastEntry(http_hdr_type id) const; bool conflictingContentLength_; ///< found different Content-Length fields + /// unsupported encoding, unnecessary syntax characters, and/or + /// invalid field-value found in Transfer-Encoding header + bool teUnsupported_ = false; }; int httpHeaderParseQuotedString(const char *start, const int len, String *val); @@ -293,13 +302,6 @@ int httpHeaderHasByNameListMember(const void httpHeaderUpdate(HttpHeader * old, const HttpHeader * fresh, const HttpHeaderMask * denied_mask); void httpHeaderCalcMask(HttpHeaderMask * mask, http_hdr_type http_hdr_type_enums[], size_t count); -inline bool -HttpHeader::chunked() const -{ - return has(HDR_TRANSFER_ENCODING) && - hasListMember(HDR_TRANSFER_ENCODING, "chunked", ','); -} - void httpHeaderInitModule(void); void httpHeaderCleanModule(void); Index: squid-3.5.21/src/client_side.cc =================================================================== --- squid-3.5.21.orig/src/client_side.cc +++ squid-3.5.21/src/client_side.cc @@ -2581,9 +2581,7 @@ clientProcessRequest(ConnStateData *conn ClientHttpRequest *http = context->http; HttpRequest::Pointer request; bool notedUseOfBuffer = false; - bool chunked = false; bool mustReplyToOptions = false; - bool unsupportedTe = false; bool expectBody = false; // temporary hack to avoid splitting this huge function with sensitive code @@ -2767,13 +2765,7 @@ clientProcessRequest(ConnStateData *conn // TODO: this effectively obsoletes a lot of conn->FOO copying. That needs cleaning up later. request->clientConnectionManager = conn; - if (request->header.chunked()) { - chunked = true; - } else if (request->header.has(HDR_TRANSFER_ENCODING)) { - const String te = request->header.getList(HDR_TRANSFER_ENCODING); - // HTTP/1.1 requires chunking to be the last encoding if there is one - unsupportedTe = te.size() && te != "identity"; - } // else implied identity coding + const auto unsupportedTe = request->header.unsupportedTe(); mustReplyToOptions = (method == Http::METHOD_OPTIONS) && (request->header.getInt64(HDR_MAX_FORWARDS) == 0); @@ -2791,6 +2783,7 @@ clientProcessRequest(ConnStateData *conn return; } + const auto chunked = request->header.chunked(); if (!chunked && !clientIsContentLengthValid(request.getRaw())) { clientStreamNode *node = context->getClientReplyContext(); clientReplyContext *repContext = dynamic_cast<clientReplyContext *>(node->data.getRaw()); Index: squid-3.5.21/src/http.cc =================================================================== --- squid-3.5.21.orig/src/http.cc +++ squid-3.5.21/src/http.cc @@ -1265,6 +1265,9 @@ HttpStateData::continueAfterParsingHeade } else if (vrep->header.conflictingContentLength()) { fwd->dontRetry(true); error = ERR_INVALID_RESP; + } else if (vrep->header.unsupportedTe()) { + fwd->dontRetry(true); + error = ERR_INVALID_RESP; } else { return true; // done parsing, got reply, and no error }
Locations
Projects
Search
Status Monitor
Help
OpenBuildService.org
Documentation
API Documentation
Code of Conduct
Contact
Support
@OBShq
Terms
openSUSE Build Service is sponsored by
The Open Build Service is an
openSUSE project
.
Sign Up
Log In
Places
Places
All Projects
Status Monitor