From: rousskov <> Date: Sat, 9 Feb 2008 01:27:59 +0000 (+0000) Subject: Bug 2038: check reply_body_max_size before ICAP X-Git-Tag: BASIC_TPROXY4~134 X-Git-Url: http://git.ipfire.org/cgi-bin/gitweb.cgi?a=commitdiff_plain;h=0667cbfb5a0b749a6d0f670f99b69e7bd0d64290;p=thirdparty%2Fsquid.git Bug 2038: check reply_body_max_size before ICAP Moved maxReplyBodySize-related code from ClientHttpRequest to HttpReply because server-side needs it too to check limits before ICAP sucks all the data in. Calculating limit requires knowing HttpRequest because it affects expected content length. Since I did not find a single place where any HttpReply would be guaranteed to be given the request to calculate the limit, we now supply the request whenever a limit check is performed. The limit calculation result is cached and the calculation should not be repeated. --- diff --git a/src/HttpReply.cc b/src/HttpReply.cc index e5ae153bec..ee6718ad62 100644 --- a/src/HttpReply.cc +++ b/src/HttpReply.cc @@ -1,6 +1,6 @@ /* - * $Id: HttpReply.cc,v 1.99 2008/02/03 10:00:29 amosjeffries Exp $ + * $Id: HttpReply.cc,v 1.100 2008/02/08 18:27:59 rousskov Exp $ * * DEBUG: section 58 HTTP Reply (Response) * AUTHOR: Alex Rousskov @@ -40,6 +40,7 @@ #include "HttpHdrContRange.h" #include "HttpHdrSc.h" #include "ACLChecklist.h" +#include "HttpRequest.h" #include "MemBuf.h" /* local constants */ @@ -77,7 +78,9 @@ httpReplyInitModule(void) httpHeaderCalcMask(&Denied304HeadersMask, Denied304HeadersArr, countof(Denied304HeadersArr)); } -HttpReply::HttpReply() : HttpMsg(hoReply), date (0), last_modified (0), expires (0), surrogate_control (NULL), content_range (NULL), keep_alive (0), protoPrefix("HTTP/") +HttpReply::HttpReply() : HttpMsg(hoReply), date (0), last_modified (0), + expires (0), surrogate_control (NULL), content_range (NULL), keep_alive (0), + protoPrefix("HTTP/"), bodySizeMax(-2) { init(); } @@ -122,6 +125,7 @@ HttpReply::clean() hdrCacheClean(); header.clean(); httpStatusLineClean(&sline); + bodySizeMax = -2; // hack: make calculatedBodySizeMax() false } void @@ -496,3 +500,54 @@ HttpReply::expectingBody(const HttpRequestMethod& req_method, int64_t& theSize) return expectBody; } + +bool +HttpReply::receivedBodyTooLarge(HttpRequest& request, int64_t receivedSize) +{ + calcMaxBodySize(request); + debugs(58, 3, HERE << receivedSize << " >? " << bodySizeMax); + return bodySizeMax >= 0 && receivedSize > bodySizeMax; +} + +bool +HttpReply::expectedBodyTooLarge(HttpRequest& request) +{ + calcMaxBodySize(request); + debugs(58, 7, HERE << "bodySizeMax=" << bodySizeMax); + + if (bodySizeMax < 0) // no body size limit + return false; + + int64_t expectedSize = -1; + if (!expectingBody(request.method, expectedSize)) + return false; + + debugs(58, 6, HERE << expectedSize << " >? " << bodySizeMax); + + if (expectedSize < 0) // expecting body of an unknown length + return false; + + return expectedSize > bodySizeMax; +} + +void +HttpReply::calcMaxBodySize(HttpRequest& request) +{ + // hack: -2 is used as "we have not calculated max body size yet" state + if (bodySizeMax != -2) // already tried + return; + bodySizeMax = -1; + + ACLChecklist ch; + ch.src_addr = request.client_addr; + ch.my_addr = request.my_addr; + ch.reply = HTTPMSGLOCK(this); // XXX: this lock makes method non-const + ch.request = HTTPMSGLOCK(&request); + for (acl_size_t *l = Config.ReplyBodySize; l; l = l -> next) { + if (ch.matchAclListFast(l->aclList)) { + debugs(58, 4, HERE << "bodySizeMax=" << bodySizeMax); + bodySizeMax = l->size; // may be -1 + break; + } + } +} diff --git a/src/HttpReply.h b/src/HttpReply.h index 6230d05d01..8afd07d316 100644 --- a/src/HttpReply.h +++ b/src/HttpReply.h @@ -1,6 +1,6 @@ /* - * $Id: HttpReply.h,v 1.22 2008/01/20 08:54:28 amosjeffries Exp $ + * $Id: HttpReply.h,v 1.23 2008/02/08 18:27:59 rousskov Exp $ * * * SQUID Web Proxy Cache http://www.squid-cache.org/ @@ -118,6 +118,14 @@ public: int64_t bodySize(const HttpRequestMethod&) const; + /// Checks whether received body exceeds known maximum size. + /// Requires a prior call to calcMaxBodySize(). + bool receivedBodyTooLarge(HttpRequest&, int64_t receivedBodySize); + + /// Checks whether expected body exceeds known maximum size. + /// Requires a prior call to calcMaxBodySize(). + bool expectedBodyTooLarge(HttpRequest& request); + int validatorsMatch (HttpReply const *other) const; void packHeadersInto(Packer * p) const; @@ -139,6 +147,12 @@ private: /* header manipulation */ time_t hdrExpirationTime(); + // Calculates and stores maximum body size if needed. Used by + // receivedBodyTooLarge() and expectedBodyTooLarge(). + void calcMaxBodySize(HttpRequest& request); + + mutable int64_t bodySizeMax; // cached result of calcMaxBodySize + protected: virtual void packFirstLineInto(Packer * p, bool) const; diff --git a/src/client_side_request.cc b/src/client_side_request.cc index cf9b3656fb..83bdb0e659 100644 --- a/src/client_side_request.cc +++ b/src/client_side_request.cc @@ -1,6 +1,6 @@ /* - * $Id: client_side_request.cc,v 1.102 2008/02/03 10:00:30 amosjeffries Exp $ + * $Id: client_side_request.cc,v 1.103 2008/02/08 18:27:59 rousskov Exp $ * * DEBUG: section 85 Client-side Request Routines * AUTHOR: Robert Collins (Originally Duane Wessels in client_side.c) @@ -926,30 +926,6 @@ ClientHttpRequest::gotEnough() const return true; } -void -ClientHttpRequest::maxReplyBodySize(int64_t clen) -{ - maxReplyBodySize_ = clen; -} - -int64_t -ClientHttpRequest::maxReplyBodySize() const -{ - return maxReplyBodySize_; -} - -bool -ClientHttpRequest::isReplyBodyTooLarge(int64_t clen) const -{ - if (0 == maxReplyBodySize()) - return 0; /* disabled */ - - if (clen < 0) - return 0; /* unknown */ - - return clen > maxReplyBodySize(); -} - void ClientHttpRequest::storeEntry(StoreEntry *newEntry) { diff --git a/src/client_side_request.h b/src/client_side_request.h index 5234b0a7d0..17eb4bf68b 100644 --- a/src/client_side_request.h +++ b/src/client_side_request.h @@ -1,6 +1,6 @@ /* - * $Id: client_side_request.h,v 1.34 2008/01/20 08:54:28 amosjeffries Exp $ + * $Id: client_side_request.h,v 1.35 2008/02/08 18:27:59 rousskov Exp $ * * * SQUID Web Proxy Cache http://www.squid-cache.org/ @@ -144,10 +144,6 @@ unsigned int purging: dlink_list client_stream; int mRangeCLen(); - int64_t maxReplyBodySize() const; - void maxReplyBodySize(int64_t size); - bool isReplyBodyTooLarge(int64_t len) const; - ClientRequestContext *calloutContext; void doCallouts();