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 <yadij@users.noreply.github.com>
+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<char *>(tag), w_space);
+ 
+-            if (endofName > tagEnd)
++            if (!endofName || endofName > tagEnd)
+                 endofName = const_cast<char *>(tagEnd);
+ 
+             *endofName = '\0';
+@@ -214,7 +214,7 @@ ESICustomParser::parse(char const *dataToParse, size_t const lengthOfData, bool
+ 
+             char * endofName = strpbrk(const_cast<char *>(tag), w_space);
+ 
+-            if (endofName > tagEnd)
++            if (!endofName || endofName > tagEnd)
+                 endofName = const_cast<char *>(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 <squidadm@users.noreply.github.com>
+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("<TR><TH ALIGN=\"left\">Manager name:</TH><TD><INPUT NAME=\"user_name\" ");
+ 
+-    printf("size=\"30\" VALUE=\"%s\"></TD></TR>\n", user_name);
++    printf("size=\"30\" VALUE=\"%s\"></TD></TR>\n", rfc1738_escape(user_name));
+ 
+     printf("<TR><TH ALIGN=\"left\">Password:</TH><TD><INPUT TYPE=\"password\" NAME=\"passwd\" ");
+ 
+@@ -418,7 +418,7 @@ menu_url(cachemgr_request * req, const char *action)
+              script_name,
+              req->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 <luhliari@redhat.com>
+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<Forwarder, CommCloseCbParams>(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 <vector>
++#include <deque>
+ 
+ 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<TcpAcceptor::Pointer> deferred_;
++    std::deque<TcpAcceptor::Pointer> 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 <luhliari@redhat.com> - 7:3.5.20-12.1
-- Resolves: #1657638 - migration of upstream squid bug 4007
+* Thu Jul 25 2019 Lubos Uhliarik <luhliari@redhat.com> - 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 <luhliari@redhat.com> - 7:3.5.20-13
+- Resolves: #1620546 - migration of upstream squid
 
 * Mon Oct 02 2017 Luboš Uhliarik <luhliari@redhat.com> - 7:3.5.20-12
 - Resolves: #1471140 - Missing detailed configuration file