import squid-4.15-1.module+el8.5.0+11469+24c223d9

This commit is contained in:
CentOS Sources 2021-10-06 05:02:46 -04:00 committed by Stepan Oksanichenko
parent 8d8cb7fe83
commit dbefd1bb72
14 changed files with 125 additions and 824 deletions

2
.gitignore vendored
View File

@ -1 +1 @@
SOURCES/squid-4.11.tar.xz
SOURCES/squid-4.15.tar.xz

View File

@ -1 +1 @@
053277bf5497163ffc9261b9807abda5959bb6fc SOURCES/squid-4.11.tar.xz
60bda34ba39657e2d870c8c1d2acece8a69c3075 SOURCES/squid-4.15.tar.xz

View File

@ -1,295 +0,0 @@
commit 93f5fda134a2a010b84ffedbe833d670e63ba4be
Author: Christos Tsantilas <christos@chtsanti.net>
Date: 2020-05-15 04:54:54 +0000
Fix sending of unknown validation errors to cert. validator (#633)
Squid may be compiled with an OpenSSL release introducing X509
validation errors that Squid does not have the names for. Send their
integer codes.
Also sync Squid certificate verification errors with OpenSSL v1.1.1g.
This is a Measurement Factory project.
diff --git a/src/format/Format.cc b/src/format/Format.cc
index 8c5574b..4b4ad42 100644
--- a/src/format/Format.cc
+++ b/src/format/Format.cc
@@ -322,15 +322,6 @@ log_quoted_string(const char *str, char *out)
*p = '\0';
}
-#if USE_OPENSSL
-static char *
-sslErrorName(Security::ErrorCode err, char *buf, size_t size)
-{
- snprintf(buf, size, "SSL_ERR=%d", err);
- return buf;
-}
-#endif
-
/// XXX: Misnamed. TODO: Split <h (and this function) to distinguish received
/// headers from sent headers rather than failing to distinguish requests from responses.
/// \retval HttpReply sent to the HTTP client (access.log and default context).
@@ -959,9 +950,7 @@ Format::Format::assemble(MemBuf &mb, const AccessLogEntry::Pointer &al, int logS
case LFT_SQUID_ERROR_DETAIL:
#if USE_OPENSSL
if (al->request && al->request->errType == ERR_SECURE_CONNECT_FAIL) {
- out = Ssl::GetErrorName(al->request->errDetail);
- if (!out)
- out = sslErrorName(al->request->errDetail, tmp, sizeof(tmp));
+ out = Ssl::GetErrorName(al->request->errDetail, true);
} else
#endif
if (al->request && al->request->errDetail != ERR_DETAIL_NONE) {
@@ -1263,10 +1252,7 @@ Format::Format::assemble(MemBuf &mb, const AccessLogEntry::Pointer &al, int logS
for (const Security::CertErrors *sslError = srvBump->sslErrors(); sslError; sslError = sslError->next) {
if (!sb.isEmpty())
sb.append(separator);
- if (const char *errorName = Ssl::GetErrorName(sslError->element.code))
- sb.append(errorName);
- else
- sb.append(sslErrorName(sslError->element.code, tmp, sizeof(tmp)));
+ sb.append(Ssl::GetErrorName(sslError->element.code, true));
if (sslError->element.depth >= 0)
sb.appendf("@depth=%d", sslError->element.depth);
}
diff --git a/src/ssl/ErrorDetail.cc b/src/ssl/ErrorDetail.cc
index ddd61fd..00eb0e2 100644
--- a/src/ssl/ErrorDetail.cc
+++ b/src/ssl/ErrorDetail.cc
@@ -233,6 +233,9 @@ static SslErrorEntry TheSslErrorArray[] = {
"X509_V_ERR_SUBTREE_MINMAX"
},
#endif
+ { X509_V_ERR_APPLICATION_VERIFICATION, //50
+ "X509_V_ERR_APPLICATION_VERIFICATION"
+ },
#if defined(X509_V_ERR_UNSUPPORTED_CONSTRAINT_TYPE)
{
X509_V_ERR_UNSUPPORTED_CONSTRAINT_TYPE, //51
@@ -257,9 +260,132 @@ static SslErrorEntry TheSslErrorArray[] = {
"X509_V_ERR_CRL_PATH_VALIDATION_ERROR"
},
#endif
- { X509_V_ERR_APPLICATION_VERIFICATION,
- "X509_V_ERR_APPLICATION_VERIFICATION"
+#if defined(X509_V_ERR_PATH_LOOP)
+ {
+ X509_V_ERR_PATH_LOOP, //55
+ "X509_V_ERR_PATH_LOOP"
+ },
+#endif
+#if defined(X509_V_ERR_SUITE_B_INVALID_VERSION)
+ {
+ X509_V_ERR_SUITE_B_INVALID_VERSION, //56
+ "X509_V_ERR_SUITE_B_INVALID_VERSION"
+ },
+#endif
+#if defined(X509_V_ERR_SUITE_B_INVALID_ALGORITHM)
+ {
+ X509_V_ERR_SUITE_B_INVALID_ALGORITHM, //57
+ "X509_V_ERR_SUITE_B_INVALID_ALGORITHM"
+ },
+#endif
+#if defined(X509_V_ERR_SUITE_B_INVALID_CURVE)
+ {
+ X509_V_ERR_SUITE_B_INVALID_CURVE, //58
+ "X509_V_ERR_SUITE_B_INVALID_CURVE"
+ },
+#endif
+#if defined(X509_V_ERR_SUITE_B_INVALID_SIGNATURE_ALGORITHM)
+ {
+ X509_V_ERR_SUITE_B_INVALID_SIGNATURE_ALGORITHM, //59
+ "X509_V_ERR_SUITE_B_INVALID_SIGNATURE_ALGORITHM"
+ },
+#endif
+#if defined(X509_V_ERR_SUITE_B_LOS_NOT_ALLOWED)
+ {
+ X509_V_ERR_SUITE_B_LOS_NOT_ALLOWED, //60
+ "X509_V_ERR_SUITE_B_LOS_NOT_ALLOWED"
+ },
+#endif
+#if defined(X509_V_ERR_SUITE_B_CANNOT_SIGN_P_384_WITH_P_256)
+ {
+ X509_V_ERR_SUITE_B_CANNOT_SIGN_P_384_WITH_P_256, //61
+ "X509_V_ERR_SUITE_B_CANNOT_SIGN_P_384_WITH_P_256"
+ },
+#endif
+#if defined(X509_V_ERR_HOSTNAME_MISMATCH)
+ {
+ X509_V_ERR_HOSTNAME_MISMATCH, //62
+ "X509_V_ERR_HOSTNAME_MISMATCH"
+ },
+#endif
+#if defined(X509_V_ERR_EMAIL_MISMATCH)
+ {
+ X509_V_ERR_EMAIL_MISMATCH, //63
+ "X509_V_ERR_EMAIL_MISMATCH"
+ },
+#endif
+#if defined(X509_V_ERR_IP_ADDRESS_MISMATCH)
+ {
+ X509_V_ERR_IP_ADDRESS_MISMATCH, //64
+ "X509_V_ERR_IP_ADDRESS_MISMATCH"
+ },
+#endif
+#if defined(X509_V_ERR_DANE_NO_MATCH)
+ {
+ X509_V_ERR_DANE_NO_MATCH, //65
+ "X509_V_ERR_DANE_NO_MATCH"
},
+#endif
+#if defined(X509_V_ERR_EE_KEY_TOO_SMALL)
+ {
+ X509_V_ERR_EE_KEY_TOO_SMALL, //66
+ "X509_V_ERR_EE_KEY_TOO_SMALL"
+ },
+#endif
+#if defined(X509_V_ERR_CA_KEY_TOO_SMALL)
+ {
+ X509_V_ERR_CA_KEY_TOO_SMALL, //67
+ "X509_V_ERR_CA_KEY_TOO_SMALL"
+ },
+#endif
+#if defined(X509_V_ERR_CA_MD_TOO_WEAK)
+ {
+ X509_V_ERR_CA_MD_TOO_WEAK, //68
+ "X509_V_ERR_CA_MD_TOO_WEAK"
+ },
+#endif
+#if defined(X509_V_ERR_INVALID_CALL)
+ {
+ X509_V_ERR_INVALID_CALL, //69
+ "X509_V_ERR_INVALID_CALL"
+ },
+#endif
+#if defined(X509_V_ERR_STORE_LOOKUP)
+ {
+ X509_V_ERR_STORE_LOOKUP, //70
+ "X509_V_ERR_STORE_LOOKUP"
+ },
+#endif
+#if defined(X509_V_ERR_NO_VALID_SCTS)
+ {
+ X509_V_ERR_NO_VALID_SCTS, //71
+ "X509_V_ERR_NO_VALID_SCTS"
+ },
+#endif
+#if defined(X509_V_ERR_PROXY_SUBJECT_NAME_VIOLATION)
+ {
+ X509_V_ERR_PROXY_SUBJECT_NAME_VIOLATION, //72
+ "X509_V_ERR_PROXY_SUBJECT_NAME_VIOLATION"
+ },
+#endif
+#if defined(X509_V_ERR_OCSP_VERIFY_NEEDED)
+ {
+ X509_V_ERR_OCSP_VERIFY_NEEDED, //73
+ "X509_V_ERR_OCSP_VERIFY_NEEDED"
+ },
+#endif
+#if defined(X509_V_ERR_OCSP_VERIFY_FAILED)
+ {
+ X509_V_ERR_OCSP_VERIFY_FAILED, //74
+ "X509_V_ERR_OCSP_VERIFY_FAILED"
+ },
+#endif
+#if defined(X509_V_ERR_OCSP_CERT_UNKNOWN)
+ {
+ X509_V_ERR_OCSP_CERT_UNKNOWN, //75
+ "X509_V_ERR_OCSP_CERT_UNKNOWN"
+ },
+#endif
{ SSL_ERROR_NONE, "SSL_ERROR_NONE"},
{SSL_ERROR_NONE, NULL}
};
@@ -286,6 +412,27 @@ static const char *OptionalSslErrors[] = {
"X509_V_ERR_UNSUPPORTED_CONSTRAINT_SYNTAX",
"X509_V_ERR_UNSUPPORTED_NAME_SYNTAX",
"X509_V_ERR_CRL_PATH_VALIDATION_ERROR",
+ "X509_V_ERR_PATH_LOOP",
+ "X509_V_ERR_SUITE_B_INVALID_VERSION",
+ "X509_V_ERR_SUITE_B_INVALID_ALGORITHM",
+ "X509_V_ERR_SUITE_B_INVALID_CURVE",
+ "X509_V_ERR_SUITE_B_INVALID_SIGNATURE_ALGORITHM",
+ "X509_V_ERR_SUITE_B_LOS_NOT_ALLOWED",
+ "X509_V_ERR_SUITE_B_CANNOT_SIGN_P_384_WITH_P_256",
+ "X509_V_ERR_HOSTNAME_MISMATCH",
+ "X509_V_ERR_EMAIL_MISMATCH",
+ "X509_V_ERR_IP_ADDRESS_MISMATCH",
+ "X509_V_ERR_DANE_NO_MATCH",
+ "X509_V_ERR_EE_KEY_TOO_SMALL",
+ "X509_V_ERR_CA_KEY_TOO_SMALL",
+ "X509_V_ERR_CA_MD_TOO_WEAK",
+ "X509_V_ERR_INVALID_CALL",
+ "X509_V_ERR_STORE_LOOKUP",
+ "X509_V_ERR_NO_VALID_SCTS",
+ "X509_V_ERR_PROXY_SUBJECT_NAME_VIOLATION",
+ "X509_V_ERR_OCSP_VERIFY_NEEDED",
+ "X509_V_ERR_OCSP_VERIFY_FAILED",
+ "X509_V_ERR_OCSP_CERT_UNKNOWN",
NULL
};
@@ -390,7 +537,7 @@ Ssl::ParseErrorString(const char *name, Security::Errors &errors)
return false; // not reached
}
-const char *Ssl::GetErrorName(Security::ErrorCode value)
+const char *Ssl::GetErrorName(Security::ErrorCode value, const bool prefixRawCode)
{
if (TheSslErrors.empty())
loadSslErrorMap();
@@ -399,7 +546,9 @@ const char *Ssl::GetErrorName(Security::ErrorCode value)
if (it != TheSslErrors.end())
return it->second->name;
- return NULL;
+ static char tmpBuffer[128];
+ snprintf(tmpBuffer, sizeof(tmpBuffer), "%s%d", prefixRawCode ? "SSL_ERR=" : "", (int)value);
+ return tmpBuffer;
}
bool
@@ -529,21 +678,14 @@ const char *Ssl::ErrorDetail::notafter() const
*/
const char *Ssl::ErrorDetail::err_code() const
{
- static char tmpBuffer[64];
// We can use the GetErrorName but using the detailEntry is faster,
// so try it first.
- const char *err = detailEntry.name.termedBuf();
+ if (const char *err = detailEntry.name.termedBuf())
+ return err;
// error details not loaded yet or not defined in error_details.txt,
// try the GetErrorName...
- if (!err)
- err = GetErrorName(error_no);
-
- if (!err) {
- snprintf(tmpBuffer, 64, "%d", (int)error_no);
- err = tmpBuffer;
- }
- return err;
+ return GetErrorName(error_no);
}
/**
diff --git a/src/ssl/ErrorDetail.h b/src/ssl/ErrorDetail.h
index 48dc405..0eec0a9 100644
--- a/src/ssl/ErrorDetail.h
+++ b/src/ssl/ErrorDetail.h
@@ -26,8 +26,9 @@ bool ParseErrorString(const char *name, Security::Errors &);
/// The Security::ErrorCode code of the error described by "name".
Security::ErrorCode GetErrorCode(const char *name);
-/// The string representation of the TLS error "value"
-const char *GetErrorName(Security::ErrorCode value);
+/// \return string representation of a known TLS error (or a raw error code)
+/// \param prefixRawCode whether to prefix raw codes with "SSL_ERR="
+const char *GetErrorName(Security::ErrorCode value, const bool prefixRawCode = false);
/// A short description of the TLS error "value"
const char *GetErrorDescr(Security::ErrorCode value);

View File

@ -1,105 +0,0 @@
commit ea12a34d338b962707d5078d6d1fc7c6eb119a22
Author: Alex Rousskov <rousskov@measurement-factory.com>
Date: 2020-05-13 14:05:00 +0000
Validate Content-Length value prefix (#629)
The new code detects all invalid Content-Length prefixes but the old
code was already rejecting most invalid prefixes using strtoll(). The
newly covered (and now rejected) invalid characters are
* explicit "+" sign;
* explicit "-" sign in "-0" values;
* isspace(3) characters that are not (relaxed) OWS characters.
In most deployment environments, the last set is probably empty because
the relaxed OWS set has all the POSIX/C isspace(3) characters but the
new line, and the new line is unlikely to sneak in past other checks.
Thank you, Amit Klein <amit.klein@safebreach.com>, for elevating the
importance of this 2016 TODO (added in commit a1b9ec2).
diff --git a/CONTRIBUTORS b/CONTRIBUTORS
index 36957f2..c10a221 100644
--- a/CONTRIBUTORS
+++ b/CONTRIBUTORS
@@ -25,6 +25,7 @@ Thank you!
Alex Wu <alex_wu2012@hotmail.com>
Alin Nastac <mrness@gentoo.org>
Alter <alter@alter.org.ua>
+ Amit Klein <amit.klein@safebreach.com>
Amos Jeffries
Amos Jeffries <amosjeffries@squid-cache.org>
Amos Jeffries <squid3@treenet.co.nz>
diff --git a/src/http/ContentLengthInterpreter.cc b/src/http/ContentLengthInterpreter.cc
index 3fdf7de..a3741eb 100644
--- a/src/http/ContentLengthInterpreter.cc
+++ b/src/http/ContentLengthInterpreter.cc
@@ -28,6 +28,24 @@ Http::ContentLengthInterpreter::ContentLengthInterpreter(const int aDebugLevel):
{
}
+/// checks whether all characters before the Content-Length number are allowed
+/// \returns the start of the digit sequence (or nil on errors)
+const char *
+Http::ContentLengthInterpreter::findDigits(const char *prefix, const char * const valueEnd) const
+{
+ // skip leading OWS in RFC 7230's `OWS field-value OWS`
+ const CharacterSet &whitespace = Http::One::Parser::WhitespaceCharacters();
+ while (prefix < valueEnd) {
+ const auto ch = *prefix;
+ if (CharacterSet::DIGIT[ch])
+ return prefix; // common case: a pre-trimmed field value
+ if (!whitespace[ch])
+ return nullptr; // (trimmed) length does not start with a digit
+ ++prefix;
+ }
+ return nullptr; // empty or whitespace-only value
+}
+
/// checks whether all characters after the Content-Length are allowed
bool
Http::ContentLengthInterpreter::goodSuffix(const char *suffix, const char * const end) const
@@ -52,10 +70,19 @@ Http::ContentLengthInterpreter::checkValue(const char *rawValue, const int value
{
Must(!sawBad);
+ const auto valueEnd = rawValue + valueSize;
+
+ const auto digits = findDigits(rawValue, valueEnd);
+ if (!digits) {
+ debugs(55, debugLevel, "WARNING: Leading garbage or empty value in" << Raw("Content-Length", rawValue, valueSize));
+ sawBad = true;
+ return false;
+ }
+
int64_t latestValue = -1;
char *suffix = nullptr;
- // TODO: Handle malformed values with leading signs (e.g., "-0" or "+1").
- if (!httpHeaderParseOffset(rawValue, &latestValue, &suffix)) {
+
+ if (!httpHeaderParseOffset(digits, &latestValue, &suffix)) {
debugs(55, DBG_IMPORTANT, "WARNING: Malformed" << Raw("Content-Length", rawValue, valueSize));
sawBad = true;
return false;
@@ -68,7 +95,7 @@ Http::ContentLengthInterpreter::checkValue(const char *rawValue, const int value
}
// check for garbage after the number
- if (!goodSuffix(suffix, rawValue + valueSize)) {
+ if (!goodSuffix(suffix, valueEnd)) {
debugs(55, debugLevel, "WARNING: Trailing garbage in" << Raw("Content-Length", rawValue, valueSize));
sawBad = true;
return false;
diff --git a/src/http/ContentLengthInterpreter.h b/src/http/ContentLengthInterpreter.h
index ce36e22..f22de91 100644
--- a/src/http/ContentLengthInterpreter.h
+++ b/src/http/ContentLengthInterpreter.h
@@ -46,6 +46,7 @@ public:
bool sawGood;
protected:
+ const char *findDigits(const char *prefix, const char *valueEnd) const;
bool goodSuffix(const char *suffix, const char * const end) const;
bool checkValue(const char *start, const int size);
bool checkList(const String &list);

View File

@ -1,44 +0,0 @@
diff --git a/src/HttpHeader.cc b/src/HttpHeader.cc
index 67543a4..19efc6d 100644
--- a/src/HttpHeader.cc
+++ b/src/HttpHeader.cc
@@ -445,18 +445,6 @@ HttpHeader::parse(const char *header_start, size_t hdrLen)
return 0;
}
- if (e->id == Http::HdrType::OTHER && stringHasWhitespace(e->name.termedBuf())) {
- debugs(55, warnOnError, "WARNING: found whitespace in HTTP header name {" <<
- getStringPrefix(field_start, field_end-field_start) << "}");
-
- if (!Config.onoff.relaxed_header_parser) {
- delete e;
- PROF_stop(HttpHeaderParse);
- clean();
- return 0;
- }
- }
-
addEntry(e);
}
@@ -1451,6 +1439,20 @@ HttpHeaderEntry::parse(const char *field_start, const char *field_end, const htt
}
}
+ /* RFC 7230 section 3.2:
+ *
+ * header-field = field-name ":" OWS field-value OWS
+ * field-name = token
+ * token = 1*TCHAR
+ */
+ for (const char *pos = field_start; pos < (field_start+name_len); ++pos) {
+ if (!CharacterSet::TCHAR[*pos]) {
+ debugs(55, 2, "found header with invalid characters in " <<
+ Raw("field-name", field_start, min(name_len,100)) << "...");
+ return nullptr;
+ }
+ }
+
/* now we know we can parse it */
debugs(55, 9, "parsing HttpHeaderEntry: near '" << getStringPrefix(field_start, field_end-field_start) << "'");

View File

@ -1,139 +0,0 @@
diff --git a/src/HttpHeader.cc b/src/HttpHeader.cc
index dc6e0ff..67543a4 100644
--- a/src/HttpHeader.cc
+++ b/src/HttpHeader.cc
@@ -174,6 +174,7 @@ HttpHeader::operator =(const HttpHeader &other)
update(&other); // will update the mask as well
len = other.len;
conflictingContentLength_ = other.conflictingContentLength_;
+ teUnsupported_ = other.teUnsupported_;
}
return *this;
}
@@ -222,6 +223,7 @@ HttpHeader::clean()
httpHeaderMaskInit(&mask, 0);
len = 0;
conflictingContentLength_ = false;
+ teUnsupported_ = false;
PROF_stop(HttpHeaderClean);
}
@@ -464,11 +466,23 @@ HttpHeader::parse(const char *header_start, size_t hdrLen)
Raw("header", header_start, hdrLen));
}
- if (chunked()) {
+ String rawTe;
+ if (getByIdIfPresent(Http::HdrType::TRANSFER_ENCODING, &rawTe)) {
// RFC 2616 section 4.4: ignore Content-Length with Transfer-Encoding
// RFC 7230 section 3.3.3 #3: Transfer-Encoding overwrites Content-Length
delById(Http::HdrType::CONTENT_LENGTH);
// and clen state becomes irrelevant
+
+ if (rawTe == "chunked") {
+ ; // leave header present for chunked() method
+ } else if (rawTe == "identity") { // deprecated. no coding
+ delById(Http::HdrType::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(Http::HdrType::CONTENT_LENGTH);
diff --git a/src/HttpHeader.h b/src/HttpHeader.h
index e3553a4..64f294a 100644
--- a/src/HttpHeader.h
+++ b/src/HttpHeader.h
@@ -140,7 +140,13 @@ public:
int hasListMember(Http::HdrType 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(Http::HdrType::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 */
@@ -158,6 +164,9 @@ protected:
private:
HttpHeaderEntry *findLastEntry(Http::HdrType 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);
@@ -167,13 +176,6 @@ SBuf httpHeaderQuoteString(const char *raw);
void httpHeaderCalcMask(HttpHeaderMask * mask, Http::HdrType http_hdr_type_enums[], size_t count);
-inline bool
-HttpHeader::chunked() const
-{
- return has(Http::HdrType::TRANSFER_ENCODING) &&
- hasListMember(Http::HdrType::TRANSFER_ENCODING, "chunked", ',');
-}
-
void httpHeaderInitModule(void);
#endif /* SQUID_HTTPHEADER_H */
diff --git a/src/client_side.cc b/src/client_side.cc
index 5f5a79e..000a00b 100644
--- a/src/client_side.cc
+++ b/src/client_side.cc
@@ -1600,9 +1600,7 @@ void
clientProcessRequest(ConnStateData *conn, const Http1::RequestParserPointer &hp, Http::Stream *context)
{
ClientHttpRequest *http = context->http;
- bool chunked = false;
bool mustReplyToOptions = false;
- bool unsupportedTe = false;
bool expectBody = false;
// We already have the request parsed and checked, so we
@@ -1659,13 +1657,7 @@ clientProcessRequest(ConnStateData *conn, const Http1::RequestParserPointer &hp,
request->http_ver.minor = http_ver.minor;
}
- if (request->header.chunked()) {
- chunked = true;
- } else if (request->header.has(Http::HdrType::TRANSFER_ENCODING)) {
- const String te = request->header.getList(Http::HdrType::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 = (request->method == Http::METHOD_OPTIONS) &&
(request->header.getInt64(Http::HdrType::MAX_FORWARDS) == 0);
@@ -1682,6 +1674,7 @@ clientProcessRequest(ConnStateData *conn, const Http1::RequestParserPointer &hp,
return;
}
+ const auto chunked = request->header.chunked();
if (!chunked && !clientIsContentLengthValid(request.getRaw())) {
clientStreamNode *node = context->getClientReplyContext();
clientReplyContext *repContext = dynamic_cast<clientReplyContext *>(node->data.getRaw());
diff --git a/src/http.cc b/src/http.cc
index 9654c4a..6f4d3b2 100644
--- a/src/http.cc
+++ b/src/http.cc
@@ -1292,6 +1292,9 @@ HttpStateData::continueAfterParsingHeader()
} 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
}

View File

@ -1,34 +0,0 @@
commit b789e719affbb0a6ff9c22095f6ca8db6a5f4926
Author: Eduard Bagdasaryan <eduard.bagdasaryan@measurement-factory.com>
Date: 2020-07-27 15:28:31 +0000
Fix livelocking in peerDigestHandleReply (#698)
peerDigestHandleReply() was missing a premature EOF check. The existing
peerDigestFetchedEnough() cannot detect EOF because it does not have
access to receivedData.length used to indicate the EOF condition. We did
not adjust peerDigestFetchedEnough() because it is abused to check both
post-I/O state and the state after each digest processing step. The
latter invocations lack access to receivedData.length and should not
really bother with EOF anyway.
diff --git a/src/peer_digest.cc b/src/peer_digest.cc
index d48340f97..265f16183 100644
--- a/src/peer_digest.cc
+++ b/src/peer_digest.cc
@@ -483,6 +483,15 @@ peerDigestHandleReply(void *data, StoreIOBuffer receivedData)
} while (cbdataReferenceValid(fetch) && prevstate != fetch->state && fetch->bufofs > 0);
+ // Check for EOF here, thus giving the parser one extra run. We could avoid this overhead by
+ // checking at the beginning of this function. However, in this case, we would have to require
+ // that the parser does not regard EOF as a special condition (it is true now but may change
+ // in the future).
+ if (!receivedData.length) { // EOF
+ peerDigestFetchAbort(fetch, fetch->buf, "premature end of digest reply");
+ return;
+ }
+
/* Update the copy offset */
fetch->offset += receivedData.length;

View File

@ -1,27 +0,0 @@
diff --git a/tools/cachemgr.cc b/tools/cachemgr.cc
index 36d8e38..50bb9b6 100644
--- a/tools/cachemgr.cc
+++ b/tools/cachemgr.cc
@@ -1092,14 +1092,20 @@ make_pub_auth(cachemgr_request * req)
if (!req->passwd || !strlen(req->passwd))
return;
+ auto *rfc1738_username = xstrdup(rfc1738_escape(safe_str(req->user_name)));
+ auto *rfc1738_passwd = xstrdup(rfc1738_escape(req->passwd));
+
/* host | time | user | passwd */
const int bufLen = snprintf(buf, sizeof(buf), "%s|%d|%s|%s",
req->hostname,
(int) now,
- rfc1738_escape(safe_str(req->user_name)),
- rfc1738_escape(req->passwd));
+ rfc1738_username,
+ rfc1738_passwd);
debug("cmgr: pre-encoded for pub: %s\n", buf);
+ safe_free(rfc1738_username);
+ safe_free(rfc1738_passwd);
+
const int encodedLen = base64_encode_len(bufLen);
req->pub_auth = (char *) xmalloc(encodedLen);
struct base64_encode_ctx ctx;

View File

@ -14,131 +14,129 @@ Move client_ip_max_connections test later in the TCP accept process to ensure ds
1 file changed, 39 insertions(+), 43 deletions(-)
diff --git a/src/comm/TcpAcceptor.cc b/src/comm/TcpAcceptor.cc
index cae92a7b1e..2109913008 100644
index d4b576d..936aa30 100644
--- a/src/comm/TcpAcceptor.cc
+++ b/src/comm/TcpAcceptor.cc
@@ -282,16 +282,7 @@ Comm::TcpAcceptor::acceptOne()
@@ -282,7 +282,16 @@ Comm::TcpAcceptor::acceptOne()
ConnectionPointer newConnDetails = new Connection();
const Comm::Flag flag = oldAccept(newConnDetails);
- /* Check for errors */
- if (!newConnDetails->isOpen()) {
-
- if (flag == Comm::NOMESSAGE) {
- /* register interest again */
- debugs(5, 5, HERE << "try later: " << conn << " handler Subscription: " << theCallSub);
- SetSelect(conn->fd, COMM_SELECT_READ, doAccept, this, 0);
- return;
- }
-
+ if (flag == Comm::COMM_ERROR) {
- if (flag == Comm::COMM_ERROR) {
+ /* Check for errors */
+ if (!newConnDetails->isOpen()) {
+
+ if (flag == Comm::NOMESSAGE) {
+ /* register interest again */
+ debugs(5, 5, HERE << "try later: " << conn << " handler Subscription: " << theCallSub);
+ SetSelect(conn->fd, COMM_SELECT_READ, doAccept, this, 0);
+ return;
+ }
+
// A non-recoverable error; notify the caller */
debugs(5, 5, HERE << "non-recoverable error:" << status() << " handler Subscription: " << theCallSub);
if (intendedForUserConnections())
@@ -301,12 +292,16 @@ Comm::TcpAcceptor::acceptOne()
@@ -292,16 +301,12 @@ Comm::TcpAcceptor::acceptOne()
return;
}
- newConnDetails->nfmark = Ip::Qos::getNfmarkFromConnection(newConnDetails, Ip::Qos::dirAccepted);
+ if (flag == Comm::NOMESSAGE) {
+ /* register interest again */
+ debugs(5, 5, "try later: " << conn << " handler Subscription: " << theCallSub);
+ } else {
+ debugs(5, 5, "Listener: " << conn <<
+ " accepted new connection " << newConnDetails <<
+ " handler Subscription: " << theCallSub);
+ notify(flag, newConnDetails);
+ }
- debugs(5, 5, HERE << "Listener: " << conn <<
- if (flag == Comm::NOMESSAGE) {
- /* register interest again */
- debugs(5, 5, "try later: " << conn << " handler Subscription: " << theCallSub);
- } else {
- debugs(5, 5, "Listener: " << conn <<
- " accepted new connection " << newConnDetails <<
- " handler Subscription: " << theCallSub);
- notify(flag, newConnDetails);
- }
+ newConnDetails->nfmark = Ip::Qos::getNfmarkFromConnection(newConnDetails, Ip::Qos::dirAccepted);
+ debugs(5, 5, HERE << "Listener: " << conn <<
+ " accepted new connection " << newConnDetails <<
+ " handler Subscription: " << theCallSub);
+ notify(flag, newConnDetails);
SetSelect(conn->fd, COMM_SELECT_READ, doAccept, this, 0);
}
@@ -346,8 +341,8 @@ Comm::TcpAcceptor::notify(const Comm::Flag flag, const Comm::ConnectionPointer &
@@ -341,8 +346,8 @@ Comm::TcpAcceptor::notify(const Comm::Flag flag, const Comm::ConnectionPointer &
*
* \retval Comm::OK success. details parameter filled.
* \retval Comm::NOMESSAGE attempted accept() but nothing useful came in.
- * \retval Comm::COMM_ERROR an outright failure occurred.
* Or this client has too many connections already.
+ * \retval Comm::COMM_ERROR an outright failure occurred.
- * Or this client has too many connections already.
* \retval Comm::COMM_ERROR an outright failure occurred.
+ * Or this client has too many connections already.
*/
Comm::Flag
Comm::TcpAcceptor::oldAccept(Comm::ConnectionPointer &details)
@@ -382,15 +377,6 @@ Comm::TcpAcceptor::oldAccept(Comm::ConnectionPointer &details)
details->fd = sock;
@@ -383,6 +388,15 @@ Comm::TcpAcceptor::oldAccept(Comm::ConnectionPointer &details)
details->remote = *gai;
- if ( Config.client_ip_max_connections >= 0) {
- if (clientdbEstablished(details->remote, 0) > Config.client_ip_max_connections) {
- debugs(50, DBG_IMPORTANT, "WARNING: " << details->remote << " attempting more than " << Config.client_ip_max_connections << " connections.");
- Ip::Address::FreeAddr(gai);
- PROF_stop(comm_accept);
- return Comm::COMM_ERROR;
- }
- }
-
// lookup the local-end details of this new connection
Ip::Address::InitAddr(gai);
details->local.setEmpty();
@@ -404,6 +390,34 @@ Comm::TcpAcceptor::oldAccept(Comm::ConnectionPointer &details)
details->local = *gai;
Ip::Address::FreeAddr(gai);
+ // Perform NAT or TPROXY operations to retrieve the real client/dest IP addresses
+ if (conn->flags&(COMM_TRANSPARENT|COMM_INTERCEPTION) && !Ip::Interceptor.Lookup(details, conn)) {
+ debugs(50, DBG_IMPORTANT, "ERROR: NAT/TPROXY lookup failed to locate original IPs on " << details);
+ // Failed.
+ PROF_stop(comm_accept);
+ return Comm::COMM_ERROR;
+ }
+
+#if USE_SQUID_EUI
+ if (Eui::TheConfig.euiLookup) {
+ if (details->remote.isIPv4()) {
+ details->remoteEui48.lookup(details->remote);
+ } else if (details->remote.isIPv6()) {
+ details->remoteEui64.lookup(details->remote);
+ }
+ }
+#endif
+
+ details->nfmark = Ip::Qos::getNfmarkFromConnection(details, Ip::Qos::dirAccepted);
+
+ if ( Config.client_ip_max_connections >= 0) {
+ if (clientdbEstablished(details->remote, 0) > Config.client_ip_max_connections) {
+ debugs(50, DBG_IMPORTANT, "WARNING: " << details->remote << " attempting more than " << Config.client_ip_max_connections << " connections.");
+ Ip::Address::FreeAddr(gai);
+ PROF_stop(comm_accept);
+ return Comm::NOMESSAGE;
+ return Comm::COMM_ERROR;
+ }
+ }
+
/* fdstat update */
// XXX : these are not all HTTP requests. use a note about type and ip:port details->
// so we end up with a uniform "(HTTP|FTP-data|HTTPS|...) remote-ip:remote-port"
@@ -425,24 +439,6 @@ Comm::TcpAcceptor::oldAccept(Comm::ConnectionPointer &details)
/* IFF the socket is (tproxy) transparent, pass the flag down to allow spoofing */
F->flags.transparent = fd_table[conn->fd].flags.transparent; // XXX: can we remove this line yet?
// lookup the local-end details of this new connection
Ip::Address::InitAddr(gai);
details->local.setEmpty();
@@ -396,6 +410,23 @@ Comm::TcpAcceptor::oldAccept(Comm::ConnectionPointer &details)
details->local = *gai;
Ip::Address::FreeAddr(gai);
- // Perform NAT or TPROXY operations to retrieve the real client/dest IP addresses
- if (conn->flags&(COMM_TRANSPARENT|COMM_INTERCEPTION) && !Ip::Interceptor.Lookup(details, conn)) {
- debugs(50, DBG_IMPORTANT, "ERROR: NAT/TPROXY lookup failed to locate original IPs on " << details);
- // Failed.
+ /* fdstat update */
+ fdd_table[sock].close_file = NULL;
+ fdd_table[sock].close_line = 0;
+
+ fde *F = &fd_table[sock];
+ details->remote.toStr(F->ipaddr,MAX_IPSTRLEN);
+ F->remote_port = details->remote.port();
+ F->local_addr = details->local;
+ F->sock_family = details->local.isIPv6()?AF_INET6:AF_INET;
+
+ // set socket flags
+ commSetCloseOnExec(sock);
+ commSetNonBlocking(sock);
+
+ /* IFF the socket is (tproxy) transparent, pass the flag down to allow spoofing */
+ F->flags.transparent = fd_table[conn->fd].flags.transparent; // XXX: can we remove this line yet?
+
// Perform NAT or TPROXY operations to retrieve the real client/dest IP addresses
if (conn->flags&(COMM_TRANSPARENT|COMM_INTERCEPTION) && !Ip::Interceptor.Lookup(details, conn)) {
debugs(50, DBG_IMPORTANT, "ERROR: NAT/TPROXY lookup failed to locate original IPs on " << details);
@@ -414,33 +445,6 @@ Comm::TcpAcceptor::oldAccept(Comm::ConnectionPointer &details)
}
#endif
- details->nfmark = Ip::Qos::getNfmarkFromConnection(details, Ip::Qos::dirAccepted);
-
- if (Config.client_ip_max_connections >= 0) {
- if (clientdbEstablished(details->remote, 0) > Config.client_ip_max_connections) {
- debugs(50, DBG_IMPORTANT, "WARNING: " << details->remote << " attempting more than " << Config.client_ip_max_connections << " connections.");
- PROF_stop(comm_accept);
- return Comm::COMM_ERROR;
- return Comm::NOMESSAGE;
- }
- }
-
-#if USE_SQUID_EUI
- if (Eui::TheConfig.euiLookup) {
- if (details->remote.isIPv4()) {
- details->remoteEui48.lookup(details->remote);
- } else if (details->remote.isIPv6()) {
- details->remoteEui64.lookup(details->remote);
- }
- }
-#endif
- /* fdstat update */
- fdd_table[sock].close_file = NULL;
- fdd_table[sock].close_line = 0;
-
- fde *F = &fd_table[sock];
- details->remote.toStr(F->ipaddr,MAX_IPSTRLEN);
- F->remote_port = details->remote.port();
- F->local_addr = details->local;
- F->sock_family = details->local.isIPv6()?AF_INET6:AF_INET;
-
- // set socket flags
- commSetCloseOnExec(sock);
- commSetNonBlocking(sock);
-
- /* IFF the socket is (tproxy) transparent, pass the flag down to allow spoofing */
- F->flags.transparent = fd_table[conn->fd].flags.transparent; // XXX: can we remove this line yet?
-
PROF_stop(comm_accept);
return Comm::OK;

View File

@ -6,5 +6,5 @@ index 90ac6a4..8dbed90 100755
-#!/usr/local/bin/perl -Tw
+#!/usr/bin/perl -Tw
#
# * Copyright (C) 1996-2020 The Squid Software Foundation and contributors
# * Copyright (C) 1996-2021 The Squid Software Foundation and contributors
# *

View File

@ -1,39 +0,0 @@
diff --git a/configure b/configure
index 17b2ebf..9530f6b 100755
--- a/configure
+++ b/configure
@@ -33915,6 +33915,7 @@ done
fi
if test "x$SYSTEMD_LIBS" != "x" ; then
CXXFLAGS="$SYSTEMD_CFLAGS $CXXFLAGS"
+ LDFLAGS="$SYSTEMD_LIBS $LDFLAGS"
$as_echo "#define USE_SYSTEMD 1" >>confdefs.h
diff --git a/src/Debug.h b/src/Debug.h
index 6eecd01..ddd9e38 100644
--- a/src/Debug.h
+++ b/src/Debug.h
@@ -99,6 +99,10 @@ public:
/// configures the active debugging context to write syslog ALERT
static void ForceAlert();
+
+ /// prefixes each grouped debugs() line after the first one in the group
+ static std::ostream& Extra(std::ostream &os) { return os << "\n "; }
+
private:
static Context *Current; ///< deepest active context; nil outside debugs()
};
diff --git a/configure.ac b/configure.ac
index d3c5da8..806302c 100644
--- a/configure.ac
+++ b/configure.ac
@@ -2162,6 +2162,7 @@ if test "x$with_systemd" != "xno" -a "x$squid_host_os" = "xlinux"; then
fi
if test "x$SYSTEMD_LIBS" != "x" ; then
CXXFLAGS="$SYSTEMD_CFLAGS $CXXFLAGS"
+ LDFLAGS="$SYSTEMD_LIBS $LDFLAGS"
AC_DEFINE(USE_SYSTEMD,1,[systemd support is available])
else
with_systemd=no

View File

@ -1,25 +0,0 @@
File: squid-4.11.tar.xz
Date: Sun Apr 19 12:56:37 UTC 2020
Size: 2447700
MD5 : 10f34e852153a9996aa4614670e2bda1
SHA1: 053277bf5497163ffc9261b9807abda5959bb6fc
Key : CD6DBF8EF3B17D3E <squid3@treenet.co.nz>
B068 84ED B779 C89B 044E 64E3 CD6D BF8E F3B1 7D3E
keyring = http://www.squid-cache.org/pgp.asc
keyserver = pool.sks-keyservers.net
-----BEGIN PGP SIGNATURE-----
iQIzBAABCgAdFiEEsGiE7bd5yJsETmTjzW2/jvOxfT4FAl6cSpEACgkQzW2/jvOx
fT6YbA/6A+IbIbNBJUW45oj23Io9Tw/CzAcTeLHR+McKwV77qMbR+L+kQ+fUdM5F
rHAmd8bVVlyHc4WanVfWItEmzBzHA/ifTNvVpefSGGEbDb80RF66k7ACiZUokg1b
kkPwc/SjDhe2wvketIaBiVVd7pylrlCdVvazcF8gE9MWDOIlJND5mnHXidXvwkbJ
T2//8JZVEmcmN9pdFGNAUVckFm+AnwWXcRM1SQPYDGSVUtjVlqido8snLTA1mZwl
rIpjppujMV54OOWlj+Gqa3MZkpNzIaMCAfphzUFlsQY+/sRUYAOv1wmxw2WclxlK
WlWM+fw8OsYNDMwkOScKZZWceoAkq6UsUHzCAdJIdLqV/R6mZ9nfuZ6BHIr0+2dP
bDf9MU4KXbwEuXiRD/KPziUxxOZwSPivbm3wy9DqTTZfO9V+Iq6FVHX+ahxJ0XbM
JWRYA3GW+DRLjorfsWxU5r4UJsrnBfhItPUAfGPjPjEGZ/pn8r9G6MGenNGPLMKy
wP1rMlOhrZPwerzokzAvKx8G0WWkfN+IPv2JK3rDot6RiJIOuvnZZd4RIuVNTGbh
liO7M24JlWX3WD2wHBzxQag46+plb3VvrrVChwIQnZ2Qzpf50w0Bife/wtNBGpK0
k/Xi/nocO796YS8GZBnmhS1lEGEwp/YpJBFWmIjTWMUMEOcswVA=
=PKl0
-----END PGP SIGNATURE-----

View File

@ -0,0 +1,25 @@
File: squid-4.15.tar.xz
Date: Mon 10 May 2021 10:50:22 UTC
Size: 2454176
MD5 : a593de9dc888dfeca4f1f7db2cd7d3b9
SHA1: 60bda34ba39657e2d870c8c1d2acece8a69c3075
Key : CD6DBF8EF3B17D3E <squid3@treenet.co.nz>
B068 84ED B779 C89B 044E 64E3 CD6D BF8E F3B1 7D3E
keyring = http://www.squid-cache.org/pgp.asc
keyserver = pool.sks-keyservers.net
-----BEGIN PGP SIGNATURE-----
iQIzBAABCgAdFiEEsGiE7bd5yJsETmTjzW2/jvOxfT4FAmCZD/UACgkQzW2/jvOx
fT6zZg/+N8JMIYpmVJ7jm4lF0Ub2kEHGTOrc+tnlA3LGnlMQuTm61+BYk58g0SKW
96NbJ0cycW215Q34L+Y0tWuxEbIU01vIc3AA7rQd0LKy+fQU0OtBuhk5Vf4bKilW
uHEVIQZs9HmY6bqC+kgtCf49tVZvR8FZYNuilg/68+i/pQdwaDDmVb+j2oF7w+y2
dgkTFWtM5NTL6bqUVC0E7lLFPjzMefKfxkkpWFdV/VrAhU25jN24kpnjcfotQhdW
LDFy5okduz3ljso9pBYJfLeMXM1FZPpceC91zj32x3tcUyrD3yIoXob58rEKvfe4
RDXN4SuClsNe4UQ4oNoGIES9XtaYlOzPR1PlbqPUrdp1cDnhgLJ+1fkAixlMqCml
wuI1VIKSEY+nvRzQzFHnXJK9otV8QwMF76AHaytO9y+X6JuZmu/CcV1pq61qY9qv
t1/8z99wWSxpu17zthZgq64J225GF/hkBedaFlYoS5k5YUMDLPlRSCC0yPmb8JBF
Cns5i/aq2PmOx2ZhQ2RQIF416J3HK8Galw8ytFOjnEcn4ux9yzKNjL38p4+PJJA0
7GCMAqYYNjok3LSkGbiR7cPgbHnkqRfYbPFLMj4FtruoFlZ9L5MIU3oFvqA3ZR6l
Az6LaKLsAYPUmukAOPUSIrqpKXZHc7hdBWkT+7RYA4qaoU+9oIo=
=1Re1
-----END PGP SIGNATURE-----

View File

@ -1,8 +1,8 @@
%define __perl_requires %{SOURCE98}
Name: squid
Version: 4.11
Release: 4%{?dist}
Version: 4.15
Release: 1%{?dist}
Summary: The Squid proxy caching server
Epoch: 7
# See CREDITS for breakdown of non GPLv2+ code
@ -33,24 +33,9 @@ Patch204: squid-4.11-include-guards.patch
Patch205: squid-4.11-large-acl.patch
# https://bugzilla.redhat.com/show_bug.cgi?id=980511
Patch206: squid-4.11-active-ftp.patch
# https://github.com/squid-cache/squid/commit/c26cd1cb6a60ff196ef13c00e82576d3bfeb2e30
Patch207: squid-4.11-systemd.patch
Patch208: squid-4.11-convert-ipv4.patch
# https://bugzilla.redhat.com/show_bug.cgi?id=1890606
Patch209: squid-4.11-cache-mgr-auth-strdup.patch
# Security fixes
# https://bugzilla.redhat.com/show_bug.cgi?id=1852554
Patch500: squid-4.11-CVE-2020-14058.patch
# https://bugzilla.redhat.com/show_bug.cgi?id=1852550
Patch501: squid-4.11-CVE-2020-15049.patch
# https://bugzilla.redhat.com/show_bug.cgi?id=1871705
Patch502: squid-4.11-CVE-2020-24606.patch
# https://bugzilla.redhat.com/show_bug.cgi?id=1871702
Patch503: squid-4.11-CVE-2020-15811.patch
# https://bugzilla.redhat.com/show_bug.cgi?id=1871700
Patch504: squid-4.11-CVE-2020-15810.patch
Requires: bash >= 2.0
Requires(pre): shadow-utils
@ -109,16 +94,9 @@ lookup program (dnsserver), a program for retrieving FTP data
%patch204 -p1 -b .include-guards
%patch205 -p1 -b .large_acl
%patch206 -p1 -b .active-ftp
%patch207 -p1 -b .systemd
%patch208 -p1 -R -b .convert-ipv4
%patch209 -p1 -b .cachemgr-strdup
%patch208 -p1 -b .convert-ipv4
# Security patches
%patch500 -p1 -b .cve-2020-14058
%patch501 -p1 -b .cve-2020-15049
%patch502 -p1 -b .cve-2020-24606
%patch503 -p1 -b .CVE-2020-15811
%patch504 -p1 -b .CVE-2020-15810
# https://bugzilla.redhat.com/show_bug.cgi?id=1679526
# Patch in the vendor documentation and used different location for documentation
@ -335,6 +313,14 @@ fi
%changelog
* Fri Jun 18 2021 Luboš Uhliarik <luhliari@redhat.com> - 7:4.15-1
- new version 4.15
- Resolves: #1964384 - squid:4 rebase to 4.15
* Wed Mar 31 2021 Lubos Uhliarik <luhliari@redhat.com> - 7:4.11-5
- Resolves: #1944261 - CVE-2020-25097 squid:4/squid: improper input validation
may allow a trusted client to perform HTTP Request Smuggling
* Mon Oct 26 2020 Lubos Uhliarik <luhliari@redhat.com> - 7:4.11-4
- Resolves: #1890606 - Fix for CVE 2019-13345 breaks authentication in
cachemgr.cgi