diff --git a/SOURCES/squid-3.5.20-CVE-2018-1000024.patch b/SOURCES/squid-3.5.20-CVE-2018-1000024.patch new file mode 100644 index 0000000..9392219 --- /dev/null +++ b/SOURCES/squid-3.5.20-CVE-2018-1000024.patch @@ -0,0 +1,28 @@ +commit eb2db98a676321b814fc4a51c4fb7928a8bb45d9 (refs/remotes/origin/v3.5) +Author: Amos Jeffries +Date: 2018-01-19 13:54:14 +1300 + + ESI: make sure endofName never exceeds tagEnd (#130) + +diff --git a/src/esi/CustomParser.cc b/src/esi/CustomParser.cc +index d86d2d3..db634d9 100644 +--- a/src/esi/CustomParser.cc ++++ b/src/esi/CustomParser.cc +@@ -121,7 +121,7 @@ ESICustomParser::parse(char const *dataToParse, size_t const lengthOfData, bool + + char * endofName = strpbrk(const_cast(tag), w_space); + +- if (endofName > tagEnd) ++ if (!endofName || endofName > tagEnd) + endofName = const_cast(tagEnd); + + *endofName = '\0'; +@@ -214,7 +214,7 @@ ESICustomParser::parse(char const *dataToParse, size_t const lengthOfData, bool + + char * endofName = strpbrk(const_cast(tag), w_space); + +- if (endofName > tagEnd) ++ if (!endofName || endofName > tagEnd) + endofName = const_cast(tagEnd); + + *endofName = '\0'; diff --git a/SOURCES/squid-3.5.20-CVE-2018-1000027.patch b/SOURCES/squid-3.5.20-CVE-2018-1000027.patch new file mode 100644 index 0000000..9ecd8a5 --- /dev/null +++ b/SOURCES/squid-3.5.20-CVE-2018-1000027.patch @@ -0,0 +1,23 @@ +commit 8232b83d3fa47a1399f155cb829db829369fbae9 (refs/remotes/origin/v3.5) +Author: squidadm +Date: 2018-01-21 08:07:08 +1300 + + Fix indirect IP logging for transactions without a client connection (#129) (#136) + +diff --git a/src/client_side_request.cc b/src/client_side_request.cc +index be124f3..203f89d 100644 +--- a/src/client_side_request.cc ++++ b/src/client_side_request.cc +@@ -488,9 +488,9 @@ clientFollowXForwardedForCheck(allow_t answer, void *data) + * Ensure that the access log shows the indirect client + * instead of the direct client. + */ +- ConnStateData *conn = http->getConn(); +- conn->log_addr = request->indirect_client_addr; +- http->al->cache.caddr = conn->log_addr; ++ http->al->cache.caddr = request->indirect_client_addr; ++ if (ConnStateData *conn = http->getConn()) ++ conn->log_addr = request->indirect_client_addr; + } + request->x_forwarded_for_iterator.clean(); + request->flags.done_follow_x_forwarded_for = true; diff --git a/SOURCES/squid-3.5.20-CVE-2019-13345.patch b/SOURCES/squid-3.5.20-CVE-2019-13345.patch new file mode 100644 index 0000000..7142830 --- /dev/null +++ b/SOURCES/squid-3.5.20-CVE-2019-13345.patch @@ -0,0 +1,64 @@ +diff --git a/tools/cachemgr.cc b/tools/cachemgr.cc +index 1ec4e15..fb5146e 100644 +--- a/tools/cachemgr.cc ++++ b/tools/cachemgr.cc +@@ -354,7 +354,7 @@ auth_html(const char *host, int port, const char *user_name) + + printf("Manager name:\n", user_name); ++ printf("size=\"30\" VALUE=\"%s\">\n", rfc1738_escape(user_name)); + + printf("Password:hostname, + req->port, +- safe_str(req->user_name), ++ rfc1738_escape(safe_str(req->user_name)), + action, + safe_str(req->pub_auth)); + return url; +@@ -1073,8 +1073,8 @@ make_pub_auth(cachemgr_request * req) + const int bufLen = snprintf(buf, sizeof(buf), "%s|%d|%s|%s", + req->hostname, + (int) now, +- req->user_name ? req->user_name : "", +- req->passwd); ++ rfc1738_escape(safe_str(req->user_name)), ++ rfc1738_escape(req->passwd)); + debug("cmgr: pre-encoded for pub: %s\n", buf); + + const int encodedLen = base64_encode_len(bufLen); +@@ -1089,8 +1089,6 @@ decode_pub_auth(cachemgr_request * req) + char *buf; + const char *host_name; + const char *time_str; +- const char *user_name; +- const char *passwd; + + debug("cmgr: decoding pub: '%s'\n", safe_str(req->pub_auth)); + safe_free(req->passwd); +@@ -1119,17 +1117,21 @@ decode_pub_auth(cachemgr_request * req) + + debug("cmgr: decoded time: '%s' (now: %d)\n", time_str, (int) now); + ++ char *user_name; + if ((user_name = strtok(NULL, "|")) == NULL) { + xfree(buf); + return; + } ++ rfc1738_unescape(user_name); + + debug("cmgr: decoded uname: '%s'\n", user_name); + ++ char *passwd; + if ((passwd = strtok(NULL, "|")) == NULL) { + xfree(buf); + return; + } ++ rfc1738_unescape(passwd); + + debug("cmgr: decoded passwd: '%s'\n", passwd); + diff --git a/SOURCES/squid-3.5.20-cache-peer-tolower.patch b/SOURCES/squid-3.5.20-cache-peer-tolower.patch new file mode 100644 index 0000000..71b395d --- /dev/null +++ b/SOURCES/squid-3.5.20-cache-peer-tolower.patch @@ -0,0 +1,32 @@ +From d3527ec67a9ddad9c189ae360d4f6181d5413bfa Mon Sep 17 00:00:00 2001 +From: uhliarik +Date: Mon, 15 Jul 2019 03:42:39 +0000 +Subject: [PATCH] Bug 4966: Lower cache_peer hostname (#420) + +When parsing entries from /etc/hosts file, they are all lowered +(see bug 3040). If cache_peer hostname is uppercase, it will +lead to DNS resolution failure. Lowering cache_peer host fixes +this issue. + +This change may expose broken Squid configurations that +incorrectly relied on non-lowercase peer host names to +bypass Squid's "is this cache_peer different from me?" +check. Though such configurations should encounter +forwarding loop errors later anyway. +--- + src/cache_cf.cc | 1 + + 1 file changed, 1 insertion(+) + +diff --git a/src/cache_cf.cc b/src/cache_cf.cc +index 8886b68..e6b231c 100644 +--- a/src/cache_cf.cc ++++ b/src/cache_cf.cc +@@ -2075,7 +2075,7 @@ parse_peer(CachePeer ** head) + self_destruct(); + + p->host = xstrdup(token); +- ++ Tolower(p->host); + p->name = xstrdup(token); + + if ((token = ConfigParser::NextToken()) == NULL) diff --git a/SOURCES/squid-3.5.20-cache-siblings-gw.patch b/SOURCES/squid-3.5.20-cache-siblings-gw.patch new file mode 100644 index 0000000..95b0edf --- /dev/null +++ b/SOURCES/squid-3.5.20-cache-siblings-gw.patch @@ -0,0 +1,308 @@ +diff --git a/src/FwdState.cc b/src/FwdState.cc +index f16acd0..c1d8a0f 100644 +--- a/src/FwdState.cc ++++ b/src/FwdState.cc +@@ -139,7 +139,6 @@ FwdState::FwdState(const Comm::ConnectionPointer &client, StoreEntry * e, HttpRe + start_t = squid_curtime; + serverDestinations.reserve(Config.forward_max_tries); + e->lock("FwdState"); +- EBIT_SET(e->flags, ENTRY_FWD_HDR_WAIT); + } + + // Called once, right after object creation, when it is safe to set self +@@ -250,7 +249,6 @@ FwdState::completed() + } + #endif + } else { +- EBIT_CLR(entry->flags, ENTRY_FWD_HDR_WAIT); + entry->complete(); + entry->releaseRequest(); + } +@@ -495,7 +493,6 @@ FwdState::complete() + debugs(17, 3, HERE << "server FD " << serverConnection()->fd << " not re-forwarding status " << entry->getReply()->sline.status()); + else + debugs(17, 3, HERE << "server (FD closed) not re-forwarding status " << entry->getReply()->sline.status()); +- EBIT_CLR(entry->flags, ENTRY_FWD_HDR_WAIT); + entry->complete(); + + if (!Comm::IsConnOpen(serverConn)) +diff --git a/src/MemStore.cc b/src/MemStore.cc +index 86b6024..405b644 100644 +--- a/src/MemStore.cc ++++ b/src/MemStore.cc +@@ -402,7 +402,6 @@ MemStore::copyFromShmSlice(StoreEntry &e, const StoreIOBuffer &buf, bool eof) + const int result = rep->httpMsgParseStep(mb.buf, buf.length, eof); + if (result > 0) { + assert(rep->pstate == psParsed); +- EBIT_CLR(e.flags, ENTRY_FWD_HDR_WAIT); + } else if (result < 0) { + debugs(20, DBG_IMPORTANT, "Corrupted mem-cached headers: " << e); + return false; +@@ -508,15 +507,9 @@ MemStore::startCaching(StoreEntry &e) + void + MemStore::copyToShm(StoreEntry &e) + { +- // prevents remote readers from getting ENTRY_FWD_HDR_WAIT entries and +- // not knowing when the wait is over +- if (EBIT_TEST(e.flags, ENTRY_FWD_HDR_WAIT)) { +- debugs(20, 5, "postponing copying " << e << " for ENTRY_FWD_HDR_WAIT"); +- return; +- } +- + assert(map); + assert(e.mem_obj); ++ Must(!EBIT_TEST(e.flags, ENTRY_FWD_HDR_WAIT)); + + const int32_t index = e.mem_obj->memCache.index; + assert(index >= 0); +diff --git a/src/client_side_request.cc b/src/client_side_request.cc +index a824b08..5debc29 100644 +--- a/src/client_side_request.cc ++++ b/src/client_side_request.cc +@@ -1919,7 +1919,6 @@ ClientHttpRequest::handleAdaptedHeader(HttpMsg *msg) + assert(repContext); + repContext->createStoreEntry(request->method, request->flags); + +- EBIT_CLR(storeEntry()->flags, ENTRY_FWD_HDR_WAIT); + request_satisfaction_mode = true; + request_satisfaction_offset = 0; + storeEntry()->replaceHttpReply(new_rep); +diff --git a/src/clients/FtpGateway.cc b/src/clients/FtpGateway.cc +index 9c78bbb..4f8319a 100644 +--- a/src/clients/FtpGateway.cc ++++ b/src/clients/FtpGateway.cc +@@ -2309,7 +2309,6 @@ Ftp::Gateway::completedListing() + ferr.ftp.server_msg = ctrl.message; + ctrl.message = NULL; + entry->replaceHttpReply( ferr.BuildHttpReply() ); +- EBIT_CLR(entry->flags, ENTRY_FWD_HDR_WAIT); + entry->flush(); + entry->unlock("Ftp::Gateway"); + } +@@ -2588,8 +2587,6 @@ Ftp::Gateway::appendSuccessHeader() + + assert(entry->isEmpty()); + +- EBIT_CLR(entry->flags, ENTRY_FWD_HDR_WAIT); +- + entry->buffer(); /* released when done processing current data payload */ + + filename = (t = urlpath.rpos('/')) ? t + 1 : urlpath.termedBuf(); +diff --git a/src/clients/FtpRelay.cc b/src/clients/FtpRelay.cc +index ed498b4..f1d4e9e 100644 +--- a/src/clients/FtpRelay.cc ++++ b/src/clients/FtpRelay.cc +@@ -290,7 +290,6 @@ Ftp::Relay::failedErrorMessage(err_type error, int xerrno) + const Http::StatusCode httpStatus = failedHttpStatus(error); + HttpReply *const reply = createHttpReply(httpStatus); + entry->replaceHttpReply(reply); +- EBIT_CLR(entry->flags, ENTRY_FWD_HDR_WAIT); + fwd->request->detailError(error, xerrno); + } + +@@ -373,7 +372,6 @@ void + Ftp::Relay::forwardReply() + { + assert(entry->isEmpty()); +- EBIT_CLR(entry->flags, ENTRY_FWD_HDR_WAIT); + + HttpReply *const reply = createHttpReply(Http::scNoContent); + +@@ -448,7 +446,6 @@ Ftp::Relay::startDataDownload() + " (" << data.conn->local << ")"); + + HttpReply *const reply = createHttpReply(Http::scOkay, -1); +- EBIT_CLR(entry->flags, ENTRY_FWD_HDR_WAIT); + setVirginReply(reply); + adaptOrFinalizeReply(); + +diff --git a/src/enums.h b/src/enums.h +index 4d04805..50199da 100644 +--- a/src/enums.h ++++ b/src/enums.h +@@ -96,12 +96,31 @@ typedef enum { + enum { + ENTRY_SPECIAL, + ENTRY_REVALIDATE, ++ ++ /// Tiny Store writes are likely. The writes should be aggregated together ++ /// before Squid announces the new content availability to the store ++ /// clients. For example, forming a cached HTTP response header may result ++ /// in dozens of StoreEntry::write() calls, many of which adding as little ++ /// as two bytes. Sharing those small writes with the store clients ++ /// increases overhead, especially because the client code can do nothing ++ /// useful with the written content until the whole response header is ++ /// stored. Might be combined with ENTRY_FWD_HDR_WAIT. TODO: Rename to ++ /// ENTRY_DELAY_WHILE_COALESCING to emphasize the difference from and ++ /// similarity with ENTRY_FWD_HDR_WAIT. + DELAY_SENDING, + RELEASE_REQUEST, + REFRESH_REQUEST, + ENTRY_CACHABLE_RESERVED_FOR_FUTURE_USE, + ENTRY_DISPATCHED, + KEY_PRIVATE, ++ ++ /// The current entry response may change. The contents of an entry in this ++ /// state must not be shared with its store clients. For example, Squid ++ /// receives (and buffers) an HTTP/504 response but may decide to retry that ++ /// transaction to receive a successful response from another server ++ /// instead. Might be combined with DELAY_SENDING. TODO: Rename to ++ /// ENTRY_DELAY_WHILE_WOBBLING to emphasize the difference from and ++ /// similarity with DELAY_SENDING. + ENTRY_FWD_HDR_WAIT, + ENTRY_NEGCACHED, + ENTRY_VALIDATED, +diff --git a/src/gopher.cc b/src/gopher.cc +index d373e8a..6d4ab1e 100644 +--- a/src/gopher.cc ++++ b/src/gopher.cc +@@ -233,7 +233,6 @@ gopherMimeCreate(GopherStateData * gopherState) + } + + assert(entry->isEmpty()); +- EBIT_CLR(entry->flags, ENTRY_FWD_HDR_WAIT); + + HttpReply *reply = new HttpReply; + entry->buffer(); +diff --git a/src/http.cc b/src/http.cc +index 1dd1e6d..08531dc 100644 +--- a/src/http.cc ++++ b/src/http.cc +@@ -932,8 +932,8 @@ HttpStateData::haveParsedReplyHeaders() + + if (vary.isEmpty()) { + entry->makePrivate(); +- if (!fwd->reforwardableStatus(rep->sline.status())) +- EBIT_CLR(entry->flags, ENTRY_FWD_HDR_WAIT); ++ if (fwd->reforwardableStatus(rep->sline.status())) ++ EBIT_SET(entry->flags, ENTRY_FWD_HDR_WAIT); + varyFailure = true; + } else { + entry->mem_obj->vary_headers = vary; +@@ -945,8 +945,8 @@ HttpStateData::haveParsedReplyHeaders() + * If its not a reply that we will re-forward, then + * allow the client to get it. + */ +- if (!fwd->reforwardableStatus(rep->sline.status())) +- EBIT_CLR(entry->flags, ENTRY_FWD_HDR_WAIT); ++ if (fwd->reforwardableStatus(rep->sline.status())) ++ EBIT_SET(entry->flags, ENTRY_FWD_HDR_WAIT); + + switch (cacheableReply()) { + +diff --git a/src/ipc/Forwarder.cc b/src/ipc/Forwarder.cc +index bf3c428..116d6f0 100644 +--- a/src/ipc/Forwarder.cc ++++ b/src/ipc/Forwarder.cc +@@ -94,8 +94,10 @@ Ipc::Forwarder::handleRemoteAck() + { + debugs(54, 3, HERE); + request->requestId = 0; +- // Do not clear ENTRY_FWD_HDR_WAIT or do entry->complete() because +- // it will trigger our client side processing. Let job cleanup close. ++ // Do not do entry->complete() because it will trigger our client side ++ // processing when we no longer own the client-Squid connection. ++ // Let job cleanup close the client-Squid connection that Coordinator ++ // now owns. + } + + /// Ipc::Forwarder::requestTimedOut wrapper +diff --git a/src/mgr/Forwarder.cc b/src/mgr/Forwarder.cc +index 3c4e4f3..7d33a9b 100644 +--- a/src/mgr/Forwarder.cc ++++ b/src/mgr/Forwarder.cc +@@ -37,7 +37,6 @@ Mgr::Forwarder::Forwarder(const Comm::ConnectionPointer &aConn, const ActionPara + + HTTPMSGLOCK(httpRequest); + entry->lock("Mgr::Forwarder"); +- EBIT_SET(entry->flags, ENTRY_FWD_HDR_WAIT); + + closer = asyncCall(16, 5, "Mgr::Forwarder::noteCommClosed", + CommCbMemFunT(this, &Forwarder::noteCommClosed)); +@@ -122,7 +121,6 @@ Mgr::Forwarder::sendError(ErrorState *error) + Must(entry != NULL); + Must(httpRequest != NULL); + +- EBIT_CLR(entry->flags, ENTRY_FWD_HDR_WAIT); + entry->buffer(); + entry->replaceHttpReply(error->BuildHttpReply()); + entry->expires = squid_curtime; +diff --git a/src/store.cc b/src/store.cc +index cbb2676..c5ae817 100644 +--- a/src/store.cc ++++ b/src/store.cc +@@ -831,8 +831,12 @@ StoreEntry::write (StoreIOBuffer writeBuffer) + storeGetMemSpace(writeBuffer.length); + mem_obj->write(writeBuffer); + +- if (!EBIT_TEST(flags, DELAY_SENDING)) +- invokeHandlers(); ++ if (EBIT_TEST(flags, ENTRY_FWD_HDR_WAIT) && !mem_obj->readAheadPolicyCanRead()) { ++ debugs(20, 3, "allow Store clients to get entry content after buffering too much for " << *this); ++ EBIT_CLR(flags, ENTRY_FWD_HDR_WAIT); ++ } ++ ++ invokeHandlers(); + } + + /* Append incoming data from a primary server to an entry. */ +@@ -1047,6 +1051,9 @@ StoreEntry::complete() + { + debugs(20, 3, "storeComplete: '" << getMD5Text() << "'"); + ++ // To preserve forwarding retries, call FwdState::complete() instead. ++ EBIT_CLR(flags, ENTRY_FWD_HDR_WAIT); ++ + if (store_status != STORE_PENDING) { + /* + * if we're not STORE_PENDING, then probably we got aborted +@@ -1103,6 +1110,9 @@ StoreEntry::abort() + + EBIT_SET(flags, ENTRY_ABORTED); + ++ // allow the Store clients to be told about the problem ++ EBIT_CLR(flags, ENTRY_FWD_HDR_WAIT); ++ + setMemStatus(NOT_IN_MEMORY); + + store_status = STORE_OK; +@@ -1890,7 +1900,6 @@ StoreEntry::startWriting() + + rep->packHeadersInto(&p); + mem_obj->markEndOfReplyHeaders(); +- EBIT_CLR(flags, ENTRY_FWD_HDR_WAIT); + + rep->body.packInto(&p); + +diff --git a/src/store_client.cc b/src/store_client.cc +index 07a05d4..7ee1b10 100644 +--- a/src/store_client.cc ++++ b/src/store_client.cc +@@ -282,11 +282,6 @@ storeClientCopy2(StoreEntry * e, store_client * sc) + return; + } + +- if (EBIT_TEST(e->flags, ENTRY_FWD_HDR_WAIT)) { +- debugs(90, 5, "storeClientCopy2: returning because ENTRY_FWD_HDR_WAIT set"); +- return; +- } +- + if (sc->flags.store_copying) { + sc->flags.copy_event_pending = true; + debugs(90, 3, "storeClientCopy2: Queueing storeClientCopyEvent()"); +@@ -720,6 +715,15 @@ storeUnregister(store_client * sc, StoreEntry * e, void *data) + void + StoreEntry::invokeHandlers() + { ++ if (EBIT_TEST(flags, DELAY_SENDING)) { ++ debugs(90, 3, "DELAY_SENDING is on, exiting " << *this); ++ return; ++ } ++ if (EBIT_TEST(flags, ENTRY_FWD_HDR_WAIT)) { ++ debugs(90, 3, "ENTRY_FWD_HDR_WAIT is on, exiting " << *this); ++ return; ++ } ++ + /* Commit what we can to disk, if appropriate */ + swapOut(); + int i = 0; diff --git a/SOURCES/squid-3.5.20-https-packet-size.patch b/SOURCES/squid-3.5.20-https-packet-size.patch new file mode 100644 index 0000000..1222bb7 --- /dev/null +++ b/SOURCES/squid-3.5.20-https-packet-size.patch @@ -0,0 +1,154 @@ +diff --git a/src/client_side.cc b/src/client_side.cc +index 79b1b4b..01760f3 100644 +--- a/src/client_side.cc ++++ b/src/client_side.cc +@@ -4369,7 +4369,7 @@ void httpsSslBumpStep2AccessCheckDone(allow_t answer, void *data) + connState->in.buf.append(rbuf.content(), rbuf.contentSize()); + ClientSocketContext::Pointer context = connState->getCurrentContext(); + ClientHttpRequest *http = context->http; +- tunnelStart(http, &http->out.size, &http->al->http.code, http->al); ++ tunnelStart(http); + } + } + } +diff --git a/src/client_side_reply.cc b/src/client_side_reply.cc +index d17cfec..84447d1 100644 +--- a/src/client_side_reply.cc ++++ b/src/client_side_reply.cc +@@ -1114,7 +1114,7 @@ clientReplyContext::storeNotOKTransferDone() const + if (curReply->content_length < 0) + return 0; + +- int64_t expectedLength = curReply->content_length + http->out.headers_sz; ++ uint64_t expectedLength = curReply->content_length + http->out.headers_sz; + + if (http->out.size < expectedLength) + return 0; +diff --git a/src/client_side_request.cc b/src/client_side_request.cc +index 05de6da..a824b08 100644 +--- a/src/client_side_request.cc ++++ b/src/client_side_request.cc +@@ -1501,7 +1501,7 @@ ClientHttpRequest::processRequest() + } + #endif + getConn()->stopReading(); // tunnels read for themselves +- tunnelStart(this, &out.size, &al->http.code, al); ++ tunnelStart(this); + return; + } + +diff --git a/src/client_side_request.h b/src/client_side_request.h +index 442d362..51a6d75 100644 +--- a/src/client_side_request.h ++++ b/src/client_side_request.h +@@ -73,7 +73,7 @@ public: + + struct { + int64_t offset; +- int64_t size; ++ uint64_t size; + size_t headers_sz; + } out; + +@@ -180,7 +180,7 @@ int clientHttpRequestStatus(int fd, ClientHttpRequest const *http); + void clientAccessCheck(ClientHttpRequest *); + + /* ones that should be elsewhere */ +-void tunnelStart(ClientHttpRequest *, int64_t *, int *, const AccessLogEntry::Pointer &al); ++void tunnelStart(ClientHttpRequest *); + + #if _USE_INLINE_ + #include "client_side_request.cci" +diff --git a/src/tests/stub_tunnel.cc b/src/tests/stub_tunnel.cc +index 822b8c8..6a57dfb 100644 +--- a/src/tests/stub_tunnel.cc ++++ b/src/tests/stub_tunnel.cc +@@ -14,7 +14,7 @@ + #include "FwdState.h" + class ClientHttpRequest; + +-void tunnelStart(ClientHttpRequest *, int64_t *, int *, const AccessLogEntryPointer &al) STUB ++void tunnelStart(ClientHttpRequest *) STUB + + void switchToTunnel(HttpRequest *request, Comm::ConnectionPointer &clientConn, Comm::ConnectionPointer &srvConn) STUB + +diff --git a/src/tunnel.cc b/src/tunnel.cc +index 1d4bed7..d595150 100644 +--- a/src/tunnel.cc ++++ b/src/tunnel.cc +@@ -139,7 +139,7 @@ public: + int len; + char *buf; + AsyncCall::Pointer writer; ///< pending Comm::Write callback +- int64_t *size_ptr; /* pointer to size in an ConnStateData for logging */ ++ uint64_t *size_ptr; /* pointer to size in an ConnStateData for logging */ + + Comm::ConnectionPointer conn; ///< The currently connected connection. + uint8_t delayedLoops; ///< how many times a read on this connection has been postponed. +@@ -849,6 +849,11 @@ tunnelConnectedWriteDone(const Comm::ConnectionPointer &conn, char *buf, size_t + return; + } + ++ if (ClientHttpRequest *http = tunnelState->http.get()) { ++ http->out.headers_sz += size; ++ http->out.size += size; ++ } ++ + tunnelStartShoveling(tunnelState); + } + +@@ -996,7 +1001,7 @@ tunnelConnectDone(const Comm::ConnectionPointer &conn, Comm::Flag status, int xe + } + + void +-tunnelStart(ClientHttpRequest * http, int64_t * size_ptr, int *status_ptr, const AccessLogEntryPointer &al) ++tunnelStart(ClientHttpRequest * http) + { + debugs(26, 3, HERE); + /* Create state structure. */ +@@ -1022,7 +1027,7 @@ tunnelStart(ClientHttpRequest * http, int64_t * size_ptr, int *status_ptr, const + if (ch.fastCheck() == ACCESS_DENIED) { + debugs(26, 4, HERE << "MISS access forbidden."); + err = new ErrorState(ERR_FORWARDING_DENIED, Http::scForbidden, request); +- *status_ptr = Http::scForbidden; ++ http->al->http.code = Http::scForbidden; + errorSend(http->getConn()->clientConnection, err); + return; + } +@@ -1038,12 +1043,13 @@ tunnelStart(ClientHttpRequest * http, int64_t * size_ptr, int *status_ptr, const + #endif + tunnelState->url = xstrdup(url); + tunnelState->request = request; +- tunnelState->server.size_ptr = size_ptr; +- tunnelState->status_ptr = status_ptr; ++ tunnelState->server.size_ptr = &http->out.size; ++ tunnelState->client.size_ptr = &http->al->http.clientRequestSz.payloadData; ++ tunnelState->status_ptr = &http->al->http.code; + tunnelState->logTag_ptr = &http->logType; + tunnelState->client.conn = http->getConn()->clientConnection; + tunnelState->http = http; +- tunnelState->al = al; ++ tunnelState->al = http->al ; + tunnelState->started = squid_curtime; + + comm_add_close_handler(tunnelState->client.conn->fd, +@@ -1054,7 +1060,7 @@ tunnelStart(ClientHttpRequest * http, int64_t * size_ptr, int *status_ptr, const + CommTimeoutCbPtrFun(tunnelTimeout, tunnelState)); + commSetConnTimeout(tunnelState->client.conn, Config.Timeout.lifetime, timeoutCall); + +- peerSelect(&(tunnelState->serverDestinations), request, al, ++ peerSelect(&(tunnelState->serverDestinations), request, tunnelState->al, + NULL, + tunnelPeerSelectComplete, + tunnelState); +@@ -1227,6 +1233,10 @@ switchToTunnel(HttpRequest *request, Comm::ConnectionPointer &clientConn, Comm:: + if (context != NULL && context->http != NULL) { + tunnelState->logTag_ptr = &context->http->logType; + tunnelState->server.size_ptr = &context->http->out.size; ++ if (context->http->al != NULL) { ++ tunnelState->al = context->http->al; ++ tunnelState->client.size_ptr = &context->http->al->http.clientRequestSz.payloadData; ++ } + + #if USE_DELAY_POOLS + /* no point using the delayIsNoDelay stuff since tunnel is nice and simple */ diff --git a/SOURCES/squid-3.5.20-mem-usage-out-of-fd.patch b/SOURCES/squid-3.5.20-mem-usage-out-of-fd.patch new file mode 100644 index 0000000..c09f2b1 --- /dev/null +++ b/SOURCES/squid-3.5.20-mem-usage-out-of-fd.patch @@ -0,0 +1,155 @@ +diff -up squid-3.5.20/src/comm/AcceptLimiter.cc.02396660 squid-3.5.20/src/comm/AcceptLimiter.cc +--- squid-3.5.20/src/comm/AcceptLimiter.cc.02396660 2019-06-05 13:18:11.000000000 +0200 ++++ squid-3.5.20/src/comm/AcceptLimiter.cc 2019-06-05 13:21:29.000000000 +0200 +@@ -24,42 +24,33 @@ Comm::AcceptLimiter::Instance() + void + Comm::AcceptLimiter::defer(const Comm::TcpAcceptor::Pointer &afd) + { +- ++ (afd->isLimited); +- debugs(5, 5, afd->conn << " x" << afd->isLimited); ++ debugs(5, 5, afd->conn << "; already queued: " << deferred_.size()); + deferred_.push_back(afd); + } + + void + Comm::AcceptLimiter::removeDead(const Comm::TcpAcceptor::Pointer &afd) + { +- uint64_t abandonedClients = 0; +- for (unsigned int i = 0; i < deferred_.size() && afd->isLimited > 0; ++i) { +- if (deferred_[i] == afd) { +- -- deferred_[i]->isLimited; +- deferred_[i] = NULL; // fast. kick() will skip empty entries later. +- debugs(5, 5, afd->conn << " x" << afd->isLimited); +- ++abandonedClients; ++ for (auto it = deferred_.begin(); it != deferred_.end(); ++it) { ++ if (*it == afd) { ++ *it = nullptr; // fast. kick() will skip empty entries later. ++ debugs(5,4, "Abandoned client TCP SYN by closing socket: " << afd->conn); ++ return; + } + } +- debugs(5,4, "Abandoned " << abandonedClients << " client TCP SYN by closing socket: " << afd->conn); ++ debugs(5,4, "Not found " << afd->conn << " in queue, size: " << deferred_.size()); + } + + void + Comm::AcceptLimiter::kick() + { +- // TODO: this could be optimized further with an iterator to search +- // looking for first non-NULL, followed by dumping the first N +- // with only one shift()/pop_front operation +- // OR, by reimplementing as a list instead of Vector. +- + debugs(5, 5, "size=" << deferred_.size()); +- while (deferred_.size() > 0 && fdNFree() >= RESERVED_FD) { ++ while (deferred_.size() > 0 && Comm::TcpAcceptor::okToAccept()) { + /* NP: shift() is equivalent to pop_front(). Giving us a FIFO queue. */ + TcpAcceptor::Pointer temp = deferred_.front(); + deferred_.erase(deferred_.begin()); + if (temp.valid()) { + debugs(5, 5, "doing one."); +- -- temp->isLimited; + temp->acceptNext(); + break; + } +diff -up squid-3.5.20/src/comm/AcceptLimiter.h.02396660 squid-3.5.20/src/comm/AcceptLimiter.h +--- squid-3.5.20/src/comm/AcceptLimiter.h.02396660 2019-06-05 13:18:27.000000000 +0200 ++++ squid-3.5.20/src/comm/AcceptLimiter.h 2019-06-05 13:22:09.000000000 +0200 +@@ -11,7 +11,7 @@ + + #include "comm/TcpAcceptor.h" + +-#include ++#include + + namespace Comm + { +@@ -26,16 +26,6 @@ namespace Comm + * removeDead - used only by Comm layer ConnAcceptor to remove themselves when dying. + * kick - used by Comm layer when FD are closed. + */ +-/* TODO this algorithm can be optimized further: +- * +- * 1) reduce overheads by only pushing one entry per port to the list? +- * use TcpAcceptor::isLimited as a flag whether to re-list when kick()'ing +- * or to NULL an entry while scanning the list for empty spaces. +- * Side effect: TcpAcceptor->kick() becomes allowed to pull off multiple accept()'s in bunches +- * +- * 2) re-implement as a std::queue instead of std::vector +- * storing head/tail pointers for fast push/pop and avoiding the whole shift() overhead +- */ + class AcceptLimiter + { + +@@ -56,7 +46,7 @@ private: + static AcceptLimiter Instance_; + + /** FIFO queue */ +- std::vector deferred_; ++ std::deque deferred_; + }; + + }; // namepace Comm +diff -up squid-3.5.20/src/comm/TcpAcceptor.cc.02396660 squid-3.5.20/src/comm/TcpAcceptor.cc +--- squid-3.5.20/src/comm/TcpAcceptor.cc.02396660 2019-06-05 13:18:49.000000000 +0200 ++++ squid-3.5.20/src/comm/TcpAcceptor.cc 2019-06-05 13:23:49.000000000 +0200 +@@ -41,7 +41,6 @@ CBDATA_NAMESPACED_CLASS_INIT(Comm, TcpAc + Comm::TcpAcceptor::TcpAcceptor(const Comm::ConnectionPointer &newConn, const char *note, const Subscription::Pointer &aSub) : + AsyncJob("Comm::TcpAcceptor"), + errcode(0), +- isLimited(0), + theCallSub(aSub), + conn(newConn), + listenPort_() +@@ -50,7 +49,6 @@ Comm::TcpAcceptor::TcpAcceptor(const Com + Comm::TcpAcceptor::TcpAcceptor(const AnyP::PortCfgPointer &p, const char *note, const Subscription::Pointer &aSub) : + AsyncJob("Comm::TcpAcceptor"), + errcode(0), +- isLimited(0), + theCallSub(aSub), + conn(p->listenConn), + listenPort_(p) +@@ -227,7 +225,6 @@ Comm::TcpAcceptor::doAccept(int fd, void + } else { + afd->acceptNext(); + } +- SetSelect(fd, COMM_SELECT_READ, Comm::TcpAcceptor::doAccept, afd, 0); + + } catch (const std::exception &e) { + fatalf("FATAL: error while accepting new client connection: %s\n", e.what()); +@@ -286,6 +283,7 @@ Comm::TcpAcceptor::acceptOne() + " accepted new connection " << newConnDetails << + " handler Subscription: " << theCallSub); + notify(flag, newConnDetails); ++ SetSelect(conn->fd, COMM_SELECT_READ, doAccept, this, 0); + } + + void +diff -up squid-3.5.20/src/comm/TcpAcceptor.h.02396660 squid-3.5.20/src/comm/TcpAcceptor.h +--- squid-3.5.20/src/comm/TcpAcceptor.h.02396660 2019-06-05 13:18:57.000000000 +0200 ++++ squid-3.5.20/src/comm/TcpAcceptor.h 2019-06-05 13:25:05.000000000 +0200 +@@ -74,9 +74,12 @@ public: + /// errno code of the last accept() or listen() action if one occurred. + int errcode; + ++ /// Method to test if there are enough file descriptors to open a new client connection ++ /// if not the accept() will be postponed ++ static bool okToAccept(); ++ + protected: + friend class AcceptLimiter; +- int32_t isLimited; ///< whether this socket is delayed and on the AcceptLimiter queue. + + private: + Subscription::Pointer theCallSub; ///< used to generate AsyncCalls handling our events. +@@ -91,10 +94,6 @@ private: + /// listen socket closure handler + AsyncCall::Pointer closer_; + +- /// Method to test if there are enough file descriptors to open a new client connection +- /// if not the accept() will be postponed +- static bool okToAccept(); +- + /// Method callback for whenever an FD is ready to accept a client connection. + static void doAccept(int fd, void *data); + diff --git a/SPECS/squid.spec b/SPECS/squid.spec index a85b797..971fa13 100644 --- a/SPECS/squid.spec +++ b/SPECS/squid.spec @@ -4,7 +4,7 @@ Name: squid Version: 3.5.20 -Release: 12%{?dist}.1 +Release: 15%{?dist} Summary: The Squid proxy caching server Epoch: 7 # See CREDITS for breakdown of non GPLv2+ code @@ -49,8 +49,24 @@ Patch212: squid-3.5.20-man-typos.patch Patch213: squid-3.5.20-man-see-also.patch # https://bugzilla.redhat.com/show_bug.cgi?id=1620546 Patch214: squid-3.5.20-empty-cname.patch +# https://bugzilla.redhat.com/show_bug.cgi?id=1690551 +Patch215: squid-3.5.20-cache-peer-tolower.patch +# https://bugzilla.redhat.com/show_bug.cgi?id=1680022 +Patch216: squid-3.5.20-https-packet-size.patch +# https://bugzilla.redhat.com/show_bug.cgi?id=1717430 +Patch217: squid-3.5.20-mem-usage-out-of-fd.patch +# https://bugzilla.redhat.com/show_bug.cgi?id=1676420 +Patch218: squid-3.5.20-cache-siblings-gw.patch +# Security Fixes: + +# https://bugzilla.redhat.com/show_bug.cgi?id=1727744 +Patch500: squid-3.5.20-CVE-2019-13345.patch +# https://bugzilla.redhat.com/show_bug.cgi?id=1582301 +Patch501: squid-3.5.20-CVE-2018-1000024.patch +Patch502: squid-3.5.20-CVE-2018-1000027.patch + Buildroot: %{_tmppath}/%{name}-%{version}-%{release}-root-%(%{__id_u} -n) Requires: bash >= 2.0 Requires: squid-migration-script @@ -131,6 +147,15 @@ migration and script which prepares squid for downgrade operation. %patch212 -p1 -b .man-see-also %patch213 -p1 -b .man-typos %patch214 -p1 -b .empty-cname +%patch215 -p1 -b .cache-peer-tolower +%patch216 -p1 -b .https-packet-size +%patch217 -p1 -b .mem-usage-out-of-fd +%patch218 -p1 -b .cache-siblings-gw + +# security fixes +%patch500 -p1 -b .CVE-2019-13345 +%patch501 -p1 -b .CVE-2018-1000024 +%patch502 -p1 -b .CVE-2018-1000027 # https://bugzilla.redhat.com/show_bug.cgi?id=1471140 # Patch in the vendor documentation and used different location for documentation @@ -360,8 +385,19 @@ fi chgrp squid /var/cache/samba/winbindd_privileged >/dev/null 2>&1 || : %changelog -* Mon Dec 10 2018 Luboš Uhliarik - 7:3.5.20-12.1 -- Resolves: #1657638 - migration of upstream squid bug 4007 +* Thu Jul 25 2019 Lubos Uhliarik - 7:3.5.20-15 +- Resolves: #1690551 - Squid cache_peer DNS lookup failed when not all lower + case +- Resolves: #1680022 - squid can't display download/upload packet size for HTTPS + sites +- Resolves: #1717430 - Excessive memory usage when running out of descriptors +- Resolves: #1676420 - Cache siblings return wrongly cached gateway timeouts +- Resolves: #1729435 - CVE-2019-13345 squid: XSS via user_name or auth parameter + in cachemgr.cgi +- Resolves: #1582301 - CVE-2018-1000024 CVE-2018-1000027 squid: various flaws + +* Thu Dec 06 2018 Luboš Uhliarik - 7:3.5.20-13 +- Resolves: #1620546 - migration of upstream squid * Mon Oct 02 2017 Luboš Uhliarik - 7:3.5.20-12 - Resolves: #1471140 - Missing detailed configuration file