From bfd1455b8d9099932f8d222caf9218875082b7e4 Mon Sep 17 00:00:00 2001 From: CentOS Sources Date: May 06 2020 12:53:16 +0000 Subject: import squid-4.4-8.module+el8.2.0+6449+6ba3df3e.1 --- diff --git a/SOURCES/squid-4.4.0-CVE-2019-12519.patch b/SOURCES/squid-4.4.0-CVE-2019-12519.patch new file mode 100644 index 0000000..d0f7c27 --- /dev/null +++ b/SOURCES/squid-4.4.0-CVE-2019-12519.patch @@ -0,0 +1,296 @@ +commit fdd4123629320aa1ee4c3481bb392437c90d188d +Author: Amos Jeffries +Date: 2019-05-20 11:23:13 +0000 + + ESI: convert parse exceptions into 500 status response (#411) + + Produce a valid HTTP 500 status reply and continue operations when + ESI parser throws an exception. This will prevent incomplete ESI + responses reaching clients on server errors. Such responses might + have been cacheable and thus corrupted, albeit corrupted consistently + and at source by the reverse-proxy delivering them. + + ESI: throw on large stack recursions (#408) + + This reduces the impact on concurrent clients to only those + accessing the malformed resource. + + Depending on what type of recursion is being performed the + resource may appear to the client with missing segments, or + not at all. + +diff --git a/src/esi/Context.h b/src/esi/Context.h +index f3281a1..1b08cfb 100644 +--- a/src/esi/Context.h ++++ b/src/esi/Context.h +@@ -12,6 +12,7 @@ + #include "clientStream.h" + #include "err_type.h" + #include "esi/Element.h" ++#include "esi/Esi.h" + #include "esi/Parser.h" + #include "http/forward.h" + #include "http/StatusCode.h" +@@ -113,7 +114,7 @@ public: + { + + public: +- ESIElement::Pointer stack[10]; /* a stack of esi elements that are open */ ++ ESIElement::Pointer stack[ESI_STACK_DEPTH_LIMIT]; /* a stack of esi elements that are open */ + int stackdepth; /* self explanatory */ + ESIParser::Pointer theParser; + ESIElement::Pointer top(); +diff --git a/src/esi/Esi.cc b/src/esi/Esi.cc +index cc662c4..e41d593 100644 +--- a/src/esi/Esi.cc ++++ b/src/esi/Esi.cc +@@ -29,6 +29,7 @@ + #include "esi/Expression.h" + #include "esi/Segment.h" + #include "esi/VarState.h" ++#include "FadingCounter.h" + #include "fatal.h" + #include "http/Stream.h" + #include "HttpHdrSc.h" +@@ -930,13 +931,18 @@ void + ESIContext::addStackElement (ESIElement::Pointer element) + { + /* Put on the stack to allow skipping of 'invalid' markup */ +- assert (parserState.stackdepth <11); ++ ++ // throw an error if the stack location would be invalid ++ if (parserState.stackdepth >= ESI_STACK_DEPTH_LIMIT) ++ throw Esi::Error("ESI Too many nested elements"); ++ if (parserState.stackdepth < 0) ++ throw Esi::Error("ESI elements stack error, probable error in ESI template"); ++ + assert (!failed()); + debugs(86, 5, "ESIContext::addStackElement: About to add ESI Node " << element.getRaw()); + + if (!parserState.top()->addElement(element)) { +- debugs(86, DBG_IMPORTANT, "ESIContext::addStackElement: failed to add esi node, probable error in ESI template"); +- flags.error = 1; ++ throw Esi::Error("ESIContext::addStackElement failed, probable error in ESI template"); + } else { + /* added ok, push onto the stack */ + parserState.stack[parserState.stackdepth] = element; +@@ -1188,13 +1194,10 @@ ESIContext::addLiteral (const char *s, int len) + assert (len); + debugs(86, 5, "literal length is " << len); + /* give a literal to the current element */ +- assert (parserState.stackdepth <11); + ESIElement::Pointer element (new esiLiteral (this, s, len)); + +- if (!parserState.top()->addElement(element)) { +- debugs(86, DBG_IMPORTANT, "ESIContext::addLiteral: failed to add esi node, probable error in ESI template"); +- flags.error = 1; +- } ++ if (!parserState.top()->addElement(element)) ++ throw Esi::Error("ESIContext::addLiteral failed, probable error in ESI template"); + } + + void +@@ -1256,8 +1259,24 @@ ESIContext::parse() + + PROF_start(esiParsing); + +- while (buffered.getRaw() && !flags.error) +- parseOneBuffer(); ++ try { ++ while (buffered.getRaw() && !flags.error) ++ parseOneBuffer(); ++ ++ } catch (Esi::ErrorDetail &errMsg) { // FIXME: non-const for c_str() ++ // level-2: these are protocol/syntax errors from upstream ++ debugs(86, 2, "WARNING: ESI syntax error: " << errMsg); ++ setError(); ++ setErrorMessage(errMsg.c_str()); ++ ++ } catch (...) { ++ // DBG_IMPORTANT because these are local issues the admin needs to fix ++ static FadingCounter logEntries; // TODO: set horizon less than infinity ++ if (logEntries.count(1) < 100) ++ debugs(86, DBG_IMPORTANT, "ERROR: ESI parser: " << CurrentException); ++ setError(); ++ setErrorMessage("ESI parser error"); ++ } + + PROF_stop(esiParsing); + +diff --git a/src/esi/Esi.h b/src/esi/Esi.h +index 180b2c4..6fd5aac 100644 +--- a/src/esi/Esi.h ++++ b/src/esi/Esi.h +@@ -10,6 +10,11 @@ + #define SQUID_ESI_H + + #include "clientStream.h" ++#include "sbuf/SBuf.h" ++ ++#if !defined(ESI_STACK_DEPTH_LIMIT) ++#define ESI_STACK_DEPTH_LIMIT 20 ++#endif + + /* ESI.c */ + extern CSR esiStreamRead; +@@ -18,5 +23,14 @@ extern CSD esiStreamDetach; + extern CSS esiStreamStatus; + int esiEnableProcessing (HttpReply *); + ++namespace Esi ++{ ++ ++typedef SBuf ErrorDetail; ++/// prepare an Esi::ErrorDetail for throw on ESI parser internal errors ++inline Esi::ErrorDetail Error(const char *msg) { return ErrorDetail(msg); } ++ ++} // namespace Esi ++ + #endif /* SQUID_ESI_H */ + +diff --git a/src/esi/Expression.cc b/src/esi/Expression.cc +index 2b5b762..8519b03 100644 +--- a/src/esi/Expression.cc ++++ b/src/esi/Expression.cc +@@ -10,6 +10,7 @@ + + #include "squid.h" + #include "Debug.h" ++#include "esi/Esi.h" + #include "esi/Expression.h" + #include "profiler/Profiler.h" + +@@ -97,6 +98,17 @@ stackpop(stackmember * s, int *depth) + cleanmember(&s[*depth]); + } + ++static void ++stackpush(stackmember *stack, stackmember &item, int *depth) ++{ ++ if (*depth < 0) ++ throw Esi::Error("ESIExpression stack has negative size"); ++ if (*depth >= ESI_STACK_DEPTH_LIMIT) ++ throw Esi::Error("ESIExpression stack is full, cannot push"); ++ ++ stack[(*depth)++] = item; ++} ++ + static evaluate evalnegate; + static evaluate evalliteral; + static evaluate evalor; +@@ -208,6 +220,11 @@ evalnegate(stackmember * stack, int *depth, int whereAmI, stackmember * candidat + /* invalid stack */ + return 1; + ++ if (whereAmI < 0) ++ throw Esi::Error("negate expression location too small"); ++ if (*depth >= ESI_STACK_DEPTH_LIMIT) ++ throw Esi::Error("negate expression too complex"); ++ + if (stack[whereAmI + 1].valuetype != ESI_EXPR_EXPR) + /* invalid operand */ + return 1; +@@ -280,7 +297,7 @@ evalor(stackmember * stack, int *depth, int whereAmI, stackmember * candidate) + + srv.precedence = 1; + +- stack[(*depth)++] = srv; ++ stackpush(stack, srv, depth); + + /* we're out of way, try adding now */ + if (!addmember(stack, depth, candidate)) +@@ -327,7 +344,7 @@ evaland(stackmember * stack, int *depth, int whereAmI, stackmember * candidate) + + srv.precedence = 1; + +- stack[(*depth)++] = srv; ++ stackpush(stack, srv, depth); + + /* we're out of way, try adding now */ + if (!addmember(stack, depth, candidate)) +@@ -373,7 +390,7 @@ evallesseq(stackmember * stack, int *depth, int whereAmI, stackmember * candidat + + srv.precedence = 1; + +- stack[(*depth)++] = srv; ++ stackpush(stack, srv, depth); + + /* we're out of way, try adding now */ + if (!addmember(stack, depth, candidate)) +@@ -421,7 +438,7 @@ evallessthan(stackmember * stack, int *depth, int whereAmI, stackmember * candid + + srv.precedence = 1; + +- stack[(*depth)++] = srv; ++ stackpush(stack, srv, depth); + + /* we're out of way, try adding now */ + if (!addmember(stack, depth, candidate)) +@@ -469,7 +486,7 @@ evalmoreeq(stackmember * stack, int *depth, int whereAmI, stackmember * candidat + + srv.precedence = 1; + +- stack[(*depth)++] = srv; ++ stackpush(stack, srv, depth); + + /* we're out of way, try adding now */ + if (!addmember(stack, depth, candidate)) +@@ -517,7 +534,7 @@ evalmorethan(stackmember * stack, int *depth, int whereAmI, stackmember * candid + + srv.precedence = 1; + +- stack[(*depth)++] = srv; ++ stackpush(stack, srv, depth); + + /* we're out of way, try adding now */ + if (!addmember(stack, depth, candidate)) +@@ -566,7 +583,7 @@ evalequals(stackmember * stack, int *depth, int whereAmI, + + srv.precedence = 1; + +- stack[(*depth)++] = srv; ++ stackpush(stack, srv, depth); + + /* we're out of way, try adding now */ + if (!addmember(stack, depth, candidate)) +@@ -613,7 +630,7 @@ evalnotequals(stackmember * stack, int *depth, int whereAmI, stackmember * candi + + srv.precedence = 1; + +- stack[(*depth)++] = srv; ++ stackpush(stack, srv, depth); + + /* we're out of way, try adding now */ + if (!addmember(stack, depth, candidate)) +@@ -953,6 +970,9 @@ addmember(stackmember * stack, int *stackdepth, stackmember * candidate) + /* !(!(a==b))) is why thats safe */ + /* strictly less than until we unwind */ + ++ if (*stackdepth >= ESI_STACK_DEPTH_LIMIT) ++ throw Esi::Error("ESI expression too complex to add member"); ++ + if (candidate->precedence < stack[*stackdepth - 1].precedence || + candidate->precedence < stack[*stackdepth - 2].precedence) { + /* must be an operator */ +@@ -968,10 +988,10 @@ addmember(stackmember * stack, int *stackdepth, stackmember * candidate) + return 0; + } + } else { +- stack[(*stackdepth)++] = *candidate; ++ stackpush(stack, *candidate, stackdepth); + } + } else if (candidate->valuetype != ESI_EXPR_INVALID) +- stack[(*stackdepth)++] = *candidate; ++ stackpush(stack, *candidate, stackdepth); + + return 1; + } +@@ -979,7 +999,7 @@ addmember(stackmember * stack, int *stackdepth, stackmember * candidate) + int + ESIExpression::Evaluate(char const *s) + { +- stackmember stack[20]; ++ stackmember stack[ESI_STACK_DEPTH_LIMIT]; + int stackdepth = 0; + char const *end; + PROF_start(esiExpressionEval); diff --git a/SOURCES/squid-4.4.0-CVE-2019-12525.patch b/SOURCES/squid-4.4.0-CVE-2019-12525.patch new file mode 100644 index 0000000..ee093f1 --- /dev/null +++ b/SOURCES/squid-4.4.0-CVE-2019-12525.patch @@ -0,0 +1,30 @@ +commit 409956536647b3a05ee1e367424a24ae6b8f13fd +Author: Amos Jeffries +Date: 2019-06-08 21:09:23 +0000 + + Fix Digest auth parameter parsing (#415) + + Only remove quoting if the domain=, uri= or qop= parameter + value is surrounded by double-quotes. + +diff --git a/src/auth/digest/Config.cc b/src/auth/digest/Config.cc +index a8a07cd..b547bf8 100644 +--- a/src/auth/digest/Config.cc ++++ b/src/auth/digest/Config.cc +@@ -787,14 +787,14 @@ Auth::Digest::Config::decode(char const *proxy_auth, const char *aRequestRealm) + if (keyName == SBuf("domain",6) || keyName == SBuf("uri",3)) { + // domain is Special. Not a quoted-string, must not be de-quoted. But is wrapped in '"' + // BUG 3077: uri= can also be sent to us in a mangled (invalid!) form like domain +- if (*p == '"' && *(p + vlen -1) == '"') { ++ if (vlen > 1 && *p == '"' && *(p + vlen -1) == '"') { + value.limitInit(p+1, vlen-2); + } + } else if (keyName == SBuf("qop",3)) { + // qop is more special. + // On request this must not be quoted-string de-quoted. But is several values wrapped in '"' + // On response this is a single un-quoted token. +- if (*p == '"' && *(p + vlen -1) == '"') { ++ if (vlen > 1 && *p == '"' && *(p + vlen -1) == '"') { + value.limitInit(p+1, vlen-2); + } else { + value.limitInit(p, vlen); diff --git a/SOURCES/squid-4.4.0-CVE-2020-11945.patch b/SOURCES/squid-4.4.0-CVE-2020-11945.patch new file mode 100644 index 0000000..8c48f26 --- /dev/null +++ b/SOURCES/squid-4.4.0-CVE-2020-11945.patch @@ -0,0 +1,50 @@ +diff --git a/src/auth/digest/Config.cc b/src/auth/digest/Config.cc +index 45e46c0..433335a 100644 +--- a/src/auth/digest/Config.cc ++++ b/src/auth/digest/Config.cc +@@ -94,9 +94,6 @@ static void authenticateDigestNonceDelete(digest_nonce_h * nonce); + static void authenticateDigestNonceSetup(void); + static void authDigestNonceEncode(digest_nonce_h * nonce); + static void authDigestNonceLink(digest_nonce_h * nonce); +-#if NOT_USED +-static int authDigestNonceLinks(digest_nonce_h * nonce); +-#endif + static void authDigestNonceUserUnlink(digest_nonce_h * nonce); + + static void +@@ -287,21 +284,10 @@ authDigestNonceLink(digest_nonce_h * nonce) + { + assert(nonce != NULL); + ++nonce->references; ++ assert(nonce->references != 0); // no overflows + debugs(29, 9, "nonce '" << nonce << "' now at '" << nonce->references << "'."); + } + +-#if NOT_USED +-static int +-authDigestNonceLinks(digest_nonce_h * nonce) +-{ +- if (!nonce) +- return -1; +- +- return nonce->references; +-} +- +-#endif +- + void + authDigestNonceUnlink(digest_nonce_h * nonce) + { +diff --git a/src/auth/digest/Config.h b/src/auth/digest/Config.h +index b79ff30..2840865 100644 +--- a/src/auth/digest/Config.h ++++ b/src/auth/digest/Config.h +@@ -44,7 +44,7 @@ struct _digest_nonce_h : public hash_link { + /* number of uses we've seen of this nonce */ + unsigned long nc; + /* reference count */ +- short references; ++ uint64_t references; + /* the auth_user this nonce has been tied to */ + Auth::Digest::User *user; + /* has this nonce been invalidated ? */ diff --git a/SPECS/squid.spec b/SPECS/squid.spec index 81f9470..7c507cf 100644 --- a/SPECS/squid.spec +++ b/SPECS/squid.spec @@ -2,7 +2,7 @@ Name: squid Version: 4.4 -Release: 8%{?dist} +Release: 8%{?dist}.1 Summary: The Squid proxy caching server Epoch: 7 # See CREDITS for breakdown of non GPLv2+ code @@ -43,6 +43,12 @@ Patch208: squid-4.4.0-lower-cachepeer.patch Patch500: squid-4.4.0-CVE-2019-13345.patch # https://bugzilla.redhat.com/show_bug.cgi?id=1738485 Patch501: squid-4.4.0-CVE-2019-12527.patch +# https://bugzilla.redhat.com/show_bug.cgi?id=1828368 +Patch502: squid-4.4.0-CVE-2019-12519.patch +# https://bugzilla.redhat.com/show_bug.cgi?id=1828367 +Patch503: squid-4.4.0-CVE-2020-11945.patch +# https://bugzilla.redhat.com/show_bug.cgi?id=1829402 +Patch504: squid-4.4.0-CVE-2019-12525.patch Requires: bash >= 2.0 Requires(pre): shadow-utils @@ -104,6 +110,9 @@ lookup program (dnsserver), a program for retrieving FTP data %patch500 -p1 -b .CVE-2019-13345 %patch501 -p1 -b .CVE-2019-12527 +%patch502 -p1 -b .CVE-2019-12519 +%patch503 -p1 -b .CVE-2020-11945 +%patch504 -p1 -b .CVE-2019-12525 # https://bugzilla.redhat.com/show_bug.cgi?id=1679526 # Patch in the vendor documentation and used different location for documentation @@ -320,6 +329,14 @@ fi %changelog +* Wed Apr 29 2020 Lubos Uhliarik - 7:4.4-8.1 +- Resolves: #1828368 - CVE-2019-12519 squid: improper check for new member in + ESIExpression::Evaluate allows for stack buffer overflow +- Resolves: #1828367 - CVE-2020-11945 squid: improper access restriction upon + Digest Authentication nonce replay could lead to remote code execution +- Resolves: #1829402 - CVE-2019-12525 squid:4/squid: parsing of header + Proxy-Authentication leads to memory corruption + * Fri Aug 23 2019 Lubos Uhliarik - 7:4.4-8 - Resolves: # 1738485 - CVE-2019-12527 squid:4/squid: heap-based buffer overflow in HttpHeader::getAuth