diff --git a/squid-4.15-0001-CVE-2023-46846.patch b/squid-4.15-0001-CVE-2023-46846.patch deleted file mode 100644 index e574fda5c17749ebea8e2ebc7d49bb23ab37a5d7..0000000000000000000000000000000000000000 --- a/squid-4.15-0001-CVE-2023-46846.patch +++ /dev/null @@ -1,180 +0,0 @@ -From 7c551aee52b3b1ba5f7d63baf1647294b4642dae Mon Sep 17 00:00:00 2001 -From: Eduard Bagdasaryan -Date: Mon, 18 Mar 2019 17:48:21 +0000 -Subject: [PATCH] Fix incremental parsing of chunked quoted extensions (#310) - -Before this change, incremental parsing of quoted chunked extensions -was broken for two reasons: - -* Http::One::Parser::skipLineTerminator() unexpectedly threw after - partially received quoted chunk extension value. - -* When Http::One::Tokenizer was unable to parse a quoted extension, - it incorrectly restored the input buffer to the beginning of the - extension value (instead of the extension itself), thus making - further incremental parsing iterations impossible. - -IMO, the reason for this problem was that Http::One::Tokenizer::qdText() -could not distinguish two cases (returning false in both): - -* the end of the quoted string not yet reached - -* an input error, e.g., wrong/unexpected character - -A possible approach could be to improve Http::One::Tokenizer, making it -aware about "needs more data" state. However, to be acceptable, -these improvements should be done in the base Parser::Tokenizer -class instead. These changes seem to be non-trivial and could be -done separately and later. - -Another approach, used here, is to simplify the complex and error-prone -chunked extensions parsing algorithm, fixing incremental parsing bugs -and still parse incrementally in almost all cases. The performance -regression could be expected only in relatively rare cases of partially -received or malformed extensions. - -Also: -* fixed parsing of partial use-original-body extension values -* do not treat an invalid use-original-body as an unknown extension -* optimization: parse use-original-body extension only in ICAP context - (i.e., where it is expected) -* improvement: added a new API to TeChunkedParser to specify known - chunked extensions list ---- - src/parser/Makefile.am | 1 + - src/parser/Tokenizer.cc | 40 ++++++++++++++++++++++++++++++++++++++++ - src/parser/Tokenizer.h | 13 +++++++++++++ - src/parser/forward.h | 22 ++++++++++++++++++++++ - 4 files changed, 76 insertions(+) - create mode 100644 src/parser/forward.h - -diff --git a/src/parser/Makefile.am b/src/parser/Makefile.am -index af2b759..0daa5a8 100644 ---- a/src/parser/Makefile.am -+++ b/src/parser/Makefile.am -@@ -13,6 +13,7 @@ noinst_LTLIBRARIES = libparser.la - libparser_la_SOURCES = \ - BinaryTokenizer.h \ - BinaryTokenizer.cc \ -+ forward.h \ - Tokenizer.h \ - Tokenizer.cc - -diff --git a/src/parser/Tokenizer.cc b/src/parser/Tokenizer.cc -index 7e73e04..68f4aec 100644 ---- a/src/parser/Tokenizer.cc -+++ b/src/parser/Tokenizer.cc -@@ -10,7 +10,9 @@ - - #include "squid.h" - #include "Debug.h" -+#include "parser/forward.h" - #include "parser/Tokenizer.h" -+#include "sbuf/Stream.h" - - #include - #if HAVE_CTYPE_H -@@ -96,6 +98,23 @@ Parser::Tokenizer::prefix(SBuf &returnedToken, const CharacterSet &tokenChars, c - return true; - } - -+SBuf -+Parser::Tokenizer::prefix(const char *description, const CharacterSet &tokenChars, const SBuf::size_type limit) -+{ -+ if (atEnd()) -+ throw InsufficientInput(); -+ -+ SBuf result; -+ -+ if (!prefix(result, tokenChars, limit)) -+ throw TexcHere(ToSBuf("cannot parse ", description)); -+ -+ if (atEnd()) -+ throw InsufficientInput(); -+ -+ return result; -+} -+ - bool - Parser::Tokenizer::suffix(SBuf &returnedToken, const CharacterSet &tokenChars, const SBuf::size_type limit) - { -@@ -283,3 +302,24 @@ Parser::Tokenizer::int64(int64_t & result, int base, bool allowSign, const SBuf: - return success(s - range.rawContent()); - } - -+int64_t -+Parser::Tokenizer::udec64(const char *description, const SBuf::size_type limit) -+{ -+ if (atEnd()) -+ throw InsufficientInput(); -+ -+ int64_t result = 0; -+ -+ // Since we only support unsigned decimals, a parsing failure with a -+ // non-empty input always implies invalid/malformed input (or a buggy -+ // limit=0 caller). TODO: Support signed and non-decimal integers by -+ // refactoring int64() to detect insufficient input. -+ if (!int64(result, 10, false, limit)) -+ throw TexcHere(ToSBuf("cannot parse ", description)); -+ -+ if (atEnd()) -+ throw InsufficientInput(); // more digits may be coming -+ -+ return result; -+} -+ -diff --git a/src/parser/Tokenizer.h b/src/parser/Tokenizer.h -index 54414be..03a8388 100644 ---- a/src/parser/Tokenizer.h -+++ b/src/parser/Tokenizer.h -@@ -143,6 +143,19 @@ public: - */ - bool int64(int64_t &result, int base = 0, bool allowSign = true, SBuf::size_type limit = SBuf::npos); - -+ /* -+ * The methods below mimic their counterparts documented above, but they -+ * throw on errors, including InsufficientInput. The field description -+ * parameter is used for error reporting and debugging. -+ */ -+ -+ /// prefix() wrapper but throws InsufficientInput if input contains -+ /// nothing but the prefix (i.e. if the prefix is not "terminated") -+ SBuf prefix(const char *description, const CharacterSet &tokenChars, SBuf::size_type limit = SBuf::npos); -+ -+ /// int64() wrapper but limited to unsigned decimal integers (for now) -+ int64_t udec64(const char *description, SBuf::size_type limit = SBuf::npos); -+ - protected: - SBuf consume(const SBuf::size_type n); - SBuf::size_type success(const SBuf::size_type n); -diff --git a/src/parser/forward.h b/src/parser/forward.h -new file mode 100644 -index 0000000..5a95b7a ---- /dev/null -+++ b/src/parser/forward.h -@@ -0,0 +1,22 @@ -+/* -+ * Copyright (C) 1996-2019 The Squid Software Foundation and contributors -+ * -+ * Squid software is distributed under GPLv2+ license and includes -+ * contributions from numerous individuals and organizations. -+ * Please see the COPYING and CONTRIBUTORS files for details. -+ */ -+ -+#ifndef SQUID_PARSER_FORWARD_H -+#define SQUID_PARSER_FORWARD_H -+ -+namespace Parser { -+class Tokenizer; -+class BinaryTokenizer; -+ -+// TODO: Move this declaration (to parser/Elements.h) if we need more like it. -+/// thrown by modern "incremental" parsers when they need more data -+class InsufficientInput {}; -+} // namespace Parser -+ -+#endif /* SQUID_PARSER_FORWARD_H */ -+ --- -2.31.1 - diff --git a/squid-4.15-0003-CVE-2023-46846.patch b/squid-4.15-0003-CVE-2023-46846.patch deleted file mode 100644 index 493b346dbb43170bbf3d66bd61fb2ac83822a0a3..0000000000000000000000000000000000000000 --- a/squid-4.15-0003-CVE-2023-46846.patch +++ /dev/null @@ -1,180 +0,0 @@ -From 05f6af2f4c85cc99323cfff6149c3d74af661b6d Mon Sep 17 00:00:00 2001 -From: Amos Jeffries -Date: Fri, 13 Oct 2023 08:44:16 +0000 -Subject: [PATCH] RFC 9112: Improve HTTP chunked encoding compliance (#1498) - -Conflict:NA -Reference:http://www.squid-cache.org/Versions/v5/SQUID-2023_1.patch ---- - src/http/one/Parser.cc | 8 +------- - src/http/one/Parser.h | 4 +--- - src/http/one/TeChunkedParser.cc | 23 ++++++++++++++++++----- - src/parser/Tokenizer.cc | 12 ++++++++++++ - src/parser/Tokenizer.h | 7 +++++++ - 5 files changed, 39 insertions(+), 15 deletions(-) - -diff --git a/src/http/one/Parser.cc b/src/http/one/Parser.cc -index c78ddd7f0..291ae39f0 100644 ---- a/src/http/one/Parser.cc -+++ b/src/http/one/Parser.cc -@@ -65,16 +65,10 @@ Http::One::Parser::DelimiterCharacters() - void - Http::One::Parser::skipLineTerminator(Tokenizer &tok) const - { -- if (tok.skip(Http1::CrLf())) -- return; -- - if (Config.onoff.relaxed_header_parser && tok.skipOne(CharacterSet::LF)) - return; - -- if (tok.atEnd() || (tok.remaining().length() == 1 && tok.remaining().at(0) == '\r')) -- throw InsufficientInput(); -- -- throw TexcHere("garbage instead of CRLF line terminator"); -+ tok.skipRequired("line-terminating CRLF", Http1::CrLf()); - } - - /// all characters except the LF line terminator -diff --git a/src/http/one/Parser.h b/src/http/one/Parser.h -index f83c01a9a..aab895583 100644 ---- a/src/http/one/Parser.h -+++ b/src/http/one/Parser.h -@@ -124,9 +124,7 @@ protected: - * detect and skip the CRLF or (if tolerant) LF line terminator - * consume from the tokenizer. - * -- * \throws exception on bad or InsuffientInput. -- * \retval true only if line terminator found. -- * \retval false incomplete or missing line terminator, need more data. -+ * \throws exception on bad or InsufficientInput - */ - void skipLineTerminator(Tokenizer &) const; - -diff --git a/src/http/one/TeChunkedParser.cc b/src/http/one/TeChunkedParser.cc -index 1434100b6..8bdb65abb 100644 ---- a/src/http/one/TeChunkedParser.cc -+++ b/src/http/one/TeChunkedParser.cc -@@ -91,6 +91,11 @@ Http::One::TeChunkedParser::parseChunkSize(Tokenizer &tok) - { - Must(theChunkSize <= 0); // Should(), really - -+ static const SBuf bannedHexPrefixLower("0x"); -+ static const SBuf bannedHexPrefixUpper("0X"); -+ if (tok.skip(bannedHexPrefixLower) || tok.skip(bannedHexPrefixUpper)) -+ throw TextException("chunk starts with 0x", Here()); -+ - int64_t size = -1; - if (tok.int64(size, 16, false) && !tok.atEnd()) { - if (size < 0) -@@ -121,7 +126,7 @@ Http::One::TeChunkedParser::parseChunkMetadataSuffix(Tokenizer &tok) - // bad or insufficient input, like in the code below. TODO: Expand up. - try { - parseChunkExtensions(tok); // a possibly empty chunk-ext list -- skipLineTerminator(tok); -+ tok.skipRequired("CRLF after [chunk-ext]", Http1::CrLf()); - buf_ = tok.remaining(); - parsingStage_ = theChunkSize ? Http1::HTTP_PARSE_CHUNK : Http1::HTTP_PARSE_MIME; - return true; -@@ -132,12 +137,14 @@ Http::One::TeChunkedParser::parseChunkMetadataSuffix(Tokenizer &tok) - // other exceptions bubble up to kill message parsing - } - --/// Parses the chunk-ext list (RFC 7230 section 4.1.1 and its Errata #4667): -+/// Parses the chunk-ext list (RFC 9112 section 7.1.1: - /// chunk-ext = *( BWS ";" BWS chunk-ext-name [ BWS "=" BWS chunk-ext-val ] ) - void --Http::One::TeChunkedParser::parseChunkExtensions(Tokenizer &tok) -+Http::One::TeChunkedParser::parseChunkExtensions(Tokenizer &callerTok) - { - do { -+ auto tok = callerTok; -+ - ParseBws(tok); // Bug 4492: IBM_HTTP_Server sends SP after chunk-size - - if (!tok.skip(';')) -@@ -145,6 +152,7 @@ Http::One::TeChunkedParser::parseChunkExtensions(Tokenizer &tok) - - parseOneChunkExtension(tok); - buf_ = tok.remaining(); // got one extension -+ callerTok = tok; - } while (true); - } - -@@ -158,11 +166,14 @@ Http::One::ChunkExtensionValueParser::Ignore(Tokenizer &tok, const SBuf &extName - /// Parses a single chunk-ext list element: - /// chunk-ext = *( BWS ";" BWS chunk-ext-name [ BWS "=" BWS chunk-ext-val ] ) - void --Http::One::TeChunkedParser::parseOneChunkExtension(Tokenizer &tok) -+Http::One::TeChunkedParser::parseOneChunkExtension(Tokenizer &callerTok) - { -+ auto tok = callerTok; -+ - ParseBws(tok); // Bug 4492: ICAP servers send SP before chunk-ext-name - - const auto extName = tok.prefix("chunk-ext-name", CharacterSet::TCHAR); -+ callerTok = tok; // in case we determine that this is a valueless chunk-ext - - ParseBws(tok); - -@@ -176,6 +187,8 @@ Http::One::TeChunkedParser::parseOneChunkExtension(Tokenizer &tok) - customExtensionValueParser->parse(tok, extName); - else - ChunkExtensionValueParser::Ignore(tok, extName); -+ -+ callerTok = tok; - } - - bool -@@ -209,7 +222,7 @@ Http::One::TeChunkedParser::parseChunkEnd(Tokenizer &tok) - Must(theLeftBodySize == 0); // Should(), really - - try { -- skipLineTerminator(tok); -+ tok.skipRequired("chunk CRLF", Http1::CrLf()); - buf_ = tok.remaining(); // parse checkpoint - theChunkSize = 0; // done with the current chunk - parsingStage_ = Http1::HTTP_PARSE_CHUNK_SZ; -diff --git a/src/parser/Tokenizer.cc b/src/parser/Tokenizer.cc -index edaffd8d3..15df793b8 100644 ---- a/src/parser/Tokenizer.cc -+++ b/src/parser/Tokenizer.cc -@@ -147,6 +147,18 @@ Parser::Tokenizer::skipAll(const CharacterSet &tokenChars) - return success(prefixLen); - } - -+void -+Parser::Tokenizer::skipRequired(const char *description, const SBuf &tokenToSkip) -+{ -+ if (skip(tokenToSkip) || tokenToSkip.isEmpty()) -+ return; -+ -+ if (tokenToSkip.startsWith(buf_)) -+ throw InsufficientInput(); -+ -+ throw TextException(ToSBuf("cannot skip ", description), Here()); -+} -+ - bool - Parser::Tokenizer::skipOne(const CharacterSet &chars) - { -diff --git a/src/parser/Tokenizer.h b/src/parser/Tokenizer.h -index 7bae1ccbb..3cfa7dd6c 100644 ---- a/src/parser/Tokenizer.h -+++ b/src/parser/Tokenizer.h -@@ -115,6 +115,13 @@ public: - */ - SBuf::size_type skipAll(const CharacterSet &discardables); - -+ /** skips a given character sequence (string); -+ * does nothing if the sequence is empty -+ * -+ * \throws exception on mismatching prefix or InsufficientInput -+ */ -+ void skipRequired(const char *description, const SBuf &tokenToSkip); -+ - /** Removes a single trailing character from the set. - * - * \return whether a character was removed --- -2.25.1 - diff --git a/squid-4.15-0002-CVE-2023-46846.patch b/squid-4.15-CVE-2023-46846.patch similarity index 75% rename from squid-4.15-0002-CVE-2023-46846.patch rename to squid-4.15-CVE-2023-46846.patch index d2cbb3390789729586fb9f2f6ec2756ee7990e54..57387038863f8ae6f226b1b1c57f98b7a930e028 100644 --- a/squid-4.15-0002-CVE-2023-46846.patch +++ b/squid-4.15-CVE-2023-46846.patch @@ -1,67 +1,5 @@ -From 417da4006cf5c97d44e74431b816fc58fec9e270 Mon Sep 17 00:00:00 2001 -From: Eduard Bagdasaryan -Date: Mon, 18 Mar 2019 17:48:21 +0000 -Subject: [PATCH] Fix incremental parsing of chunked quoted extensions (#310) - -Before this change, incremental parsing of quoted chunked extensions -was broken for two reasons: - -* Http::One::Parser::skipLineTerminator() unexpectedly threw after - partially received quoted chunk extension value. - -* When Http::One::Tokenizer was unable to parse a quoted extension, - it incorrectly restored the input buffer to the beginning of the - extension value (instead of the extension itself), thus making - further incremental parsing iterations impossible. - -IMO, the reason for this problem was that Http::One::Tokenizer::qdText() -could not distinguish two cases (returning false in both): - -* the end of the quoted string not yet reached - -* an input error, e.g., wrong/unexpected character - -A possible approach could be to improve Http::One::Tokenizer, making it -aware about "needs more data" state. However, to be acceptable, -these improvements should be done in the base Parser::Tokenizer -class instead. These changes seem to be non-trivial and could be -done separately and later. - -Another approach, used here, is to simplify the complex and error-prone -chunked extensions parsing algorithm, fixing incremental parsing bugs -and still parse incrementally in almost all cases. The performance -regression could be expected only in relatively rare cases of partially -received or malformed extensions. - -Also: -* fixed parsing of partial use-original-body extension values -* do not treat an invalid use-original-body as an unknown extension -* optimization: parse use-original-body extension only in ICAP context - (i.e., where it is expected) -* improvement: added a new API to TeChunkedParser to specify known - chunked extensions list - -Conflict:Context adaptation and remove some file modifications -Reference:https://github.com/squid-cache/squid/commit/417da4006cf5c97d44e74431b816fc58fec9e270 ---- - src/adaptation/icap/ModXact.cc | 23 +++++- - src/adaptation/icap/ModXact.h | 20 +++++ - src/http/one/Parser.cc | 35 ++++---- - src/http/one/Parser.h | 10 ++- - src/http/one/RequestParser.cc | 16 ++-- - src/http/one/RequestParser.h | 8 +- - src/http/one/ResponseParser.cc | 17 ++-- - src/http/one/ResponseParser.h | 2 +- - src/http/one/TeChunkedParser.cc | 138 ++++++++++++++++++-------------- - src/http/one/TeChunkedParser.h | 41 ++++++++-- - src/http/one/Tokenizer.cc | 108 ++++++++++++------------- - src/http/one/Tokenizer.h | 89 ++++++++------------ - src/http/one/forward.h | 3 + - src/parser/BinaryTokenizer.h | 3 +- - 14 files changed, 291 insertions(+), 222 deletions(-) - diff --git a/src/adaptation/icap/ModXact.cc b/src/adaptation/icap/ModXact.cc -index 634f06d..4d55e7a 100644 +index 2db0a68..370f077 100644 --- a/src/adaptation/icap/ModXact.cc +++ b/src/adaptation/icap/ModXact.cc @@ -25,12 +25,13 @@ @@ -92,24 +30,23 @@ index 634f06d..4d55e7a 100644 state.parsing = State::psBody; replyHttpBodySize = 0; bodyParser = new Http1::TeChunkedParser; -+ bodyParser->parseExtensionValuesWith(&extensionParser); ++ bodyParser->parseExtensionValuesWith(&extensionParser); makeAdaptedBodyPipe("adapted response from the ICAP server"); Must(state.sending == State::sendingAdapted); } else { -@@ -1142,9 +1146,9 @@ void Adaptation::Icap::ModXact::parseBody() +@@ -1142,9 +1146,8 @@ void Adaptation::Icap::ModXact::parseBody() } if (parsed) { - if (state.readyForUob && bodyParser->useOriginBody >= 0) { - prepPartialBodyEchoing( - static_cast(bodyParser->useOriginBody)); -+ if (state.readyForUob && extensionParser.sawUseOriginalBody()) -+ { ++ if (state.readyForUob && extensionParser.sawUseOriginalBody()) { + prepPartialBodyEchoing(extensionParser.useOriginalBody()); stopParsing(); return; } -@@ -2014,3 +2018,14 @@ void Adaptation::Icap::ModXactLauncher::updateHistory(bool doStart) +@@ -2014,3 +2017,14 @@ void Adaptation::Icap::ModXactLauncher::updateHistory(bool doStart) } } @@ -125,7 +62,7 @@ index 634f06d..4d55e7a 100644 +} + diff --git a/src/adaptation/icap/ModXact.h b/src/adaptation/icap/ModXact.h -index e0c5c52..a4ac0fb 100644 +index f7afa69..fb4dec0 100644 --- a/src/adaptation/icap/ModXact.h +++ b/src/adaptation/icap/ModXact.h @@ -15,6 +15,7 @@ @@ -170,7 +107,7 @@ index e0c5c52..a4ac0fb 100644 { diff --git a/src/http/one/Parser.cc b/src/http/one/Parser.cc -index c51ebe0..f3444d7 100644 +index 0c86733..affe0b1 100644 --- a/src/http/one/Parser.cc +++ b/src/http/one/Parser.cc @@ -7,10 +7,11 @@ @@ -276,7 +213,7 @@ index c51ebe0..f3444d7 100644 } diff --git a/src/http/one/Parser.h b/src/http/one/Parser.h -index 046a96f..04d97f1 100644 +index 58a5cae..40e281b 100644 --- a/src/http/one/Parser.h +++ b/src/http/one/Parser.h @@ -12,6 +12,7 @@ @@ -321,7 +258,7 @@ index 046a96f..04d97f1 100644 /// the right debugs() level for logging HTTP violation messages int ErrorLevel(); diff --git a/src/http/one/RequestParser.cc b/src/http/one/RequestParser.cc -index 0fe67ca..3133357 100644 +index a325f7d..0f13c92 100644 --- a/src/http/one/RequestParser.cc +++ b/src/http/one/RequestParser.cc @@ -9,8 +9,8 @@ @@ -395,7 +332,7 @@ index 0fe67ca..3133357 100644 if (!parseMethodField(tok)) return -1; diff --git a/src/http/one/RequestParser.h b/src/http/one/RequestParser.h -index 2ff0a63..17dd768 100644 +index 7086548..26697cd 100644 --- a/src/http/one/RequestParser.h +++ b/src/http/one/RequestParser.h @@ -54,11 +54,11 @@ private: @@ -415,7 +352,7 @@ index 2ff0a63..17dd768 100644 bool http0() const {return !msgProtocol_.major;} static const CharacterSet &RequestTargetCharacters(); diff --git a/src/http/one/ResponseParser.cc b/src/http/one/ResponseParser.cc -index a548134..d9f3888 100644 +index 24af849..65baf09 100644 --- a/src/http/one/ResponseParser.cc +++ b/src/http/one/ResponseParser.cc @@ -9,8 +9,8 @@ @@ -446,7 +383,7 @@ index a548134..d9f3888 100644 - buf_ = tok.remaining(); // resume checkpoint - return 1; - } -+ skipLineTerminator(tok); ++ skipLineTerminator(tok); + buf_ = tok.remaining(); // resume checkpoint + debugs(74, DBG_DATA, Raw("leftovers", buf_.rawContent(), buf_.length())); + return 1; @@ -467,7 +404,7 @@ index a548134..d9f3888 100644 const CharacterSet &WspDelim = DelimiterCharacters(); diff --git a/src/http/one/ResponseParser.h b/src/http/one/ResponseParser.h -index 55e68dd..db20a62 100644 +index 15db4a0..cf13b4d 100644 --- a/src/http/one/ResponseParser.h +++ b/src/http/one/ResponseParser.h @@ -43,7 +43,7 @@ public: @@ -480,7 +417,7 @@ index 55e68dd..db20a62 100644 /// magic prefix for identifying ICY response messages static const SBuf IcyMagic; diff --git a/src/http/one/TeChunkedParser.cc b/src/http/one/TeChunkedParser.cc -index 3d26c6f..bf3d315 100644 +index 754086e..6d2f8ea 100644 --- a/src/http/one/TeChunkedParser.cc +++ b/src/http/one/TeChunkedParser.cc @@ -13,10 +13,13 @@ @@ -524,7 +461,7 @@ index 3d26c6f..bf3d315 100644 do { - if (parsingStage_ == Http1::HTTP_PARSE_CHUNK_EXT && !parseChunkExtension(tok, theChunkSize)) -+ if (parsingStage_ == Http1::HTTP_PARSE_CHUNK_EXT && !parseChunkMetadataSuffix(tok)) ++ if (parsingStage_ == Http1::HTTP_PARSE_CHUNK_EXT && !parseChunkMetadataSuffix(tok)) return false; if (parsingStage_ == Http1::HTTP_PARSE_CHUNK && !parseChunkBody(tok)) @@ -610,7 +547,8 @@ index 3d26c6f..bf3d315 100644 } + // other exceptions bubble up to kill message parsing +} -+ + +- return false; +/// Parses the chunk-ext list (RFC 7230 section 4.1.1 and its Errata #4667): +/// chunk-ext = *( BWS ";" BWS chunk-ext-name [ BWS "=" BWS chunk-ext-val ] ) +void @@ -626,8 +564,7 @@ index 3d26c6f..bf3d315 100644 + buf_ = tok.remaining(); // got one extension + } while (true); +} - -- return false; ++ +void +Http::One::ChunkExtensionValueParser::Ignore(Tokenizer &tok, const SBuf &extName) +{ @@ -664,7 +601,7 @@ index 3d26c6f..bf3d315 100644 { if (theLeftBodySize > 0) { buf_ = tok.remaining(); // sync buffers before buf_ use -@@ -188,17 +204,21 @@ Http::One::TeChunkedParser::parseChunkBody(Http1::Tokenizer &tok) +@@ -188,17 +204,20 @@ Http::One::TeChunkedParser::parseChunkBody(Http1::Tokenizer &tok) } bool @@ -681,7 +618,7 @@ index 3d26c6f..bf3d315 100644 parsingStage_ = Http1::HTTP_PARSE_CHUNK_SZ; return true; } - +- - return false; + catch (const InsufficientInput &) { + return false; @@ -690,7 +627,7 @@ index 3d26c6f..bf3d315 100644 } diff --git a/src/http/one/TeChunkedParser.h b/src/http/one/TeChunkedParser.h -index 517dcd0..09f908c 100644 +index 1b0319e..2ca8988 100644 --- a/src/http/one/TeChunkedParser.h +++ b/src/http/one/TeChunkedParser.h @@ -18,6 +18,26 @@ namespace Http @@ -768,7 +705,7 @@ index 517dcd0..09f908c 100644 } // namespace One diff --git a/src/http/one/Tokenizer.cc b/src/http/one/Tokenizer.cc -index 371ed46..b790542 100644 +index 804b8e1..3a6bef3 100644 --- a/src/http/one/Tokenizer.cc +++ b/src/http/one/Tokenizer.cc @@ -8,35 +8,18 @@ @@ -850,35 +787,33 @@ index 371ed46..b790542 100644 - return false; - } - returnedToken.append(escaped); -+ if (!tok.prefix(escaped, qPairChars, 1)) ++ if (!tok.prefix(escaped, qPairChars, 1)) + throw TexcHere("invalid escaped character in quoted-pair"); + + parsedToken.append(escaped); continue; -+ } ++ } - } else if (skip('"')) { - break; // done -- ++ if (tok.skip('"')) ++ return parsedToken; // may be empty + - } else if (atEnd()) { - // need more data - returnedToken.clear(); - restoreLastCheckpoint(); - return false; - } -- ++ if (tok.atEnd()) ++ break; + - // else, we have an error - debugs(24, 8, "invalid bytes for set " << tokenChars.name); - returnedToken.clear(); - restoreLastCheckpoint(); - return false; -+ if (tok.skip('"')) -+ return parsedToken; // may be empty -+ -+ if (tok.atEnd()) -+ break; -+ -+ throw TexcHere(ToSBuf("invalid bytes for set ", tokenChars.name)); ++ throw TexcHere(ToSBuf("invalid bytes for set ", tokenChars.name)); } - // found the whole string @@ -907,7 +842,7 @@ index 371ed46..b790542 100644 } diff --git a/src/http/one/Tokenizer.h b/src/http/one/Tokenizer.h -index a29ce5c..cbd7b1c 100644 +index 658875f..2d40574 100644 --- a/src/http/one/Tokenizer.h +++ b/src/http/one/Tokenizer.h @@ -9,68 +9,47 @@ @@ -1014,7 +949,7 @@ index a29ce5c..cbd7b1c 100644 } // namespace One } // namespace Http diff --git a/src/http/one/forward.h b/src/http/one/forward.h -index ab8c7a5..c9216ab 100644 +index c90dc34..2b4ad28 100644 --- a/src/http/one/forward.h +++ b/src/http/one/forward.h @@ -10,6 +10,7 @@ @@ -1035,7 +970,7 @@ index ab8c7a5..c9216ab 100644 } // namespace Http diff --git a/src/parser/BinaryTokenizer.h b/src/parser/BinaryTokenizer.h -index 29ac815..462b83b 100644 +index acebd4d..24042d4 100644 --- a/src/parser/BinaryTokenizer.h +++ b/src/parser/BinaryTokenizer.h @@ -9,6 +9,7 @@ @@ -1055,6 +990,292 @@ index 29ac815..462b83b 100644 typedef uint64_t size_type; // enough for the largest supported offset BinaryTokenizer(); --- -2.33.0 - +diff --git a/src/parser/Makefile.am b/src/parser/Makefile.am +index af2b759..0daa5a8 100644 +--- a/src/parser/Makefile.am ++++ b/src/parser/Makefile.am +@@ -13,6 +13,7 @@ noinst_LTLIBRARIES = libparser.la + libparser_la_SOURCES = \ + BinaryTokenizer.h \ + BinaryTokenizer.cc \ ++ forward.h \ + Tokenizer.h \ + Tokenizer.cc + +diff --git a/src/parser/Tokenizer.cc b/src/parser/Tokenizer.cc +index 7e73e04..68f4aec 100644 +--- a/src/parser/Tokenizer.cc ++++ b/src/parser/Tokenizer.cc +@@ -10,7 +10,9 @@ + + #include "squid.h" + #include "Debug.h" ++#include "parser/forward.h" + #include "parser/Tokenizer.h" ++#include "sbuf/Stream.h" + + #include + #if HAVE_CTYPE_H +@@ -96,6 +98,23 @@ Parser::Tokenizer::prefix(SBuf &returnedToken, const CharacterSet &tokenChars, c + return true; + } + ++SBuf ++Parser::Tokenizer::prefix(const char *description, const CharacterSet &tokenChars, const SBuf::size_type limit) ++{ ++ if (atEnd()) ++ throw InsufficientInput(); ++ ++ SBuf result; ++ ++ if (!prefix(result, tokenChars, limit)) ++ throw TexcHere(ToSBuf("cannot parse ", description)); ++ ++ if (atEnd()) ++ throw InsufficientInput(); ++ ++ return result; ++} ++ + bool + Parser::Tokenizer::suffix(SBuf &returnedToken, const CharacterSet &tokenChars, const SBuf::size_type limit) + { +@@ -283,3 +302,24 @@ Parser::Tokenizer::int64(int64_t & result, int base, bool allowSign, const SBuf: + return success(s - range.rawContent()); + } + ++int64_t ++Parser::Tokenizer::udec64(const char *description, const SBuf::size_type limit) ++{ ++ if (atEnd()) ++ throw InsufficientInput(); ++ ++ int64_t result = 0; ++ ++ // Since we only support unsigned decimals, a parsing failure with a ++ // non-empty input always implies invalid/malformed input (or a buggy ++ // limit=0 caller). TODO: Support signed and non-decimal integers by ++ // refactoring int64() to detect insufficient input. ++ if (!int64(result, 10, false, limit)) ++ throw TexcHere(ToSBuf("cannot parse ", description)); ++ ++ if (atEnd()) ++ throw InsufficientInput(); // more digits may be coming ++ ++ return result; ++} ++ +diff --git a/src/parser/Tokenizer.h b/src/parser/Tokenizer.h +index 54414be..03a8388 100644 +--- a/src/parser/Tokenizer.h ++++ b/src/parser/Tokenizer.h +@@ -143,6 +143,19 @@ public: + */ + bool int64(int64_t &result, int base = 0, bool allowSign = true, SBuf::size_type limit = SBuf::npos); + ++ /* ++ * The methods below mimic their counterparts documented above, but they ++ * throw on errors, including InsufficientInput. The field description ++ * parameter is used for error reporting and debugging. ++ */ ++ ++ /// prefix() wrapper but throws InsufficientInput if input contains ++ /// nothing but the prefix (i.e. if the prefix is not "terminated") ++ SBuf prefix(const char *description, const CharacterSet &tokenChars, SBuf::size_type limit = SBuf::npos); ++ ++ /// int64() wrapper but limited to unsigned decimal integers (for now) ++ int64_t udec64(const char *description, SBuf::size_type limit = SBuf::npos); ++ + protected: + SBuf consume(const SBuf::size_type n); + SBuf::size_type success(const SBuf::size_type n); +diff --git a/src/parser/forward.h b/src/parser/forward.h +new file mode 100644 +index 0000000..5a95b7a +--- /dev/null ++++ b/src/parser/forward.h +@@ -0,0 +1,22 @@ ++/* ++ * Copyright (C) 1996-2019 The Squid Software Foundation and contributors ++ * ++ * Squid software is distributed under GPLv2+ license and includes ++ * contributions from numerous individuals and organizations. ++ * Please see the COPYING and CONTRIBUTORS files for details. ++ */ ++ ++#ifndef SQUID_PARSER_FORWARD_H ++#define SQUID_PARSER_FORWARD_H ++ ++namespace Parser { ++class Tokenizer; ++class BinaryTokenizer; ++ ++// TODO: Move this declaration (to parser/Elements.h) if we need more like it. ++/// thrown by modern "incremental" parsers when they need more data ++class InsufficientInput {}; ++} // namespace Parser ++ ++#endif /* SQUID_PARSER_FORWARD_H */ ++ +diff --git a/src/http/one/Parser.cc b/src/http/one/Parser.cc +index affe0b1..05591fe 100644 +--- a/src/http/one/Parser.cc ++++ b/src/http/one/Parser.cc +@@ -65,16 +65,10 @@ Http::One::Parser::DelimiterCharacters() + void + Http::One::Parser::skipLineTerminator(Tokenizer &tok) const + { +- if (tok.skip(Http1::CrLf())) +- return; +- + if (Config.onoff.relaxed_header_parser && tok.skipOne(CharacterSet::LF)) + return; + +- if (tok.atEnd() || (tok.remaining().length() == 1 && tok.remaining().at(0) == '\r')) +- throw InsufficientInput(); +- +- throw TexcHere("garbage instead of CRLF line terminator"); ++ tok.skipRequired("line-terminating CRLF", Http1::CrLf()); + } + + /// all characters except the LF line terminator +diff --git a/src/http/one/Parser.h b/src/http/one/Parser.h +index 40e281b..9a2a4ad 100644 +--- a/src/http/one/Parser.h ++++ b/src/http/one/Parser.h +@@ -120,9 +120,7 @@ protected: + * detect and skip the CRLF or (if tolerant) LF line terminator + * consume from the tokenizer. + * +- * \throws exception on bad or InsuffientInput. +- * \retval true only if line terminator found. +- * \retval false incomplete or missing line terminator, need more data. ++ * \throws exception on bad or InsufficientInput + */ + void skipLineTerminator(Tokenizer &) const; + +diff --git a/src/http/one/TeChunkedParser.cc b/src/http/one/TeChunkedParser.cc +index 6d2f8ea..3bff6c7 100644 +--- a/src/http/one/TeChunkedParser.cc ++++ b/src/http/one/TeChunkedParser.cc +@@ -91,6 +91,11 @@ Http::One::TeChunkedParser::parseChunkSize(Tokenizer &tok) + { + Must(theChunkSize <= 0); // Should(), really + ++ static const SBuf bannedHexPrefixLower("0x"); ++ static const SBuf bannedHexPrefixUpper("0X"); ++ if (tok.skip(bannedHexPrefixLower) || tok.skip(bannedHexPrefixUpper)) ++ throw TextException("chunk starts with 0x", Here()); ++ + int64_t size = -1; + if (tok.int64(size, 16, false) && !tok.atEnd()) { + if (size < 0) +@@ -121,7 +126,7 @@ Http::One::TeChunkedParser::parseChunkMetadataSuffix(Tokenizer &tok) + // bad or insufficient input, like in the code below. TODO: Expand up. + try { + parseChunkExtensions(tok); // a possibly empty chunk-ext list +- skipLineTerminator(tok); ++ tok.skipRequired("CRLF after [chunk-ext]", Http1::CrLf()); + buf_ = tok.remaining(); + parsingStage_ = theChunkSize ? Http1::HTTP_PARSE_CHUNK : Http1::HTTP_PARSE_MIME; + return true; +@@ -132,12 +137,14 @@ Http::One::TeChunkedParser::parseChunkMetadataSuffix(Tokenizer &tok) + // other exceptions bubble up to kill message parsing + } + +-/// Parses the chunk-ext list (RFC 7230 section 4.1.1 and its Errata #4667): ++/// Parses the chunk-ext list (RFC 9112 section 7.1.1: + /// chunk-ext = *( BWS ";" BWS chunk-ext-name [ BWS "=" BWS chunk-ext-val ] ) + void +-Http::One::TeChunkedParser::parseChunkExtensions(Tokenizer &tok) ++Http::One::TeChunkedParser::parseChunkExtensions(Tokenizer &callerTok) + { + do { ++ auto tok = callerTok; ++ + ParseBws(tok); // Bug 4492: IBM_HTTP_Server sends SP after chunk-size + + if (!tok.skip(';')) +@@ -145,6 +152,7 @@ Http::One::TeChunkedParser::parseChunkExtensions(Tokenizer &tok) + + parseOneChunkExtension(tok); + buf_ = tok.remaining(); // got one extension ++ callerTok = tok; + } while (true); + } + +@@ -158,11 +166,14 @@ Http::One::ChunkExtensionValueParser::Ignore(Tokenizer &tok, const SBuf &extName + /// Parses a single chunk-ext list element: + /// chunk-ext = *( BWS ";" BWS chunk-ext-name [ BWS "=" BWS chunk-ext-val ] ) + void +-Http::One::TeChunkedParser::parseOneChunkExtension(Tokenizer &tok) ++Http::One::TeChunkedParser::parseOneChunkExtension(Tokenizer &callerTok) + { ++ auto tok = callerTok; ++ + ParseBws(tok); // Bug 4492: ICAP servers send SP before chunk-ext-name + + const auto extName = tok.prefix("chunk-ext-name", CharacterSet::TCHAR); ++ callerTok = tok; // in case we determine that this is a valueless chunk-ext + + ParseBws(tok); + +@@ -176,6 +187,8 @@ Http::One::TeChunkedParser::parseOneChunkExtension(Tokenizer &tok) + customExtensionValueParser->parse(tok, extName); + else + ChunkExtensionValueParser::Ignore(tok, extName); ++ ++ callerTok = tok; + } + + bool +@@ -209,7 +222,7 @@ Http::One::TeChunkedParser::parseChunkEnd(Tokenizer &tok) + Must(theLeftBodySize == 0); // Should(), really + + try { +- skipLineTerminator(tok); ++ tok.skipRequired("chunk CRLF", Http1::CrLf()); + buf_ = tok.remaining(); // parse checkpoint + theChunkSize = 0; // done with the current chunk + parsingStage_ = Http1::HTTP_PARSE_CHUNK_SZ; +diff --git a/src/parser/Tokenizer.cc b/src/parser/Tokenizer.cc +index 68f4aec..8516869 100644 +--- a/src/parser/Tokenizer.cc ++++ b/src/parser/Tokenizer.cc +@@ -147,6 +147,18 @@ Parser::Tokenizer::skipAll(const CharacterSet &tokenChars) + return success(prefixLen); + } + ++void ++Parser::Tokenizer::skipRequired(const char *description, const SBuf &tokenToSkip) ++{ ++ if (skip(tokenToSkip) || tokenToSkip.isEmpty()) ++ return; ++ ++ if (tokenToSkip.startsWith(buf_)) ++ throw InsufficientInput(); ++ ++ throw TextException(ToSBuf("cannot skip ", description), Here()); ++} ++ + bool + Parser::Tokenizer::skipOne(const CharacterSet &chars) + { +diff --git a/src/parser/Tokenizer.h b/src/parser/Tokenizer.h +index 03a8388..78ab9e7 100644 +--- a/src/parser/Tokenizer.h ++++ b/src/parser/Tokenizer.h +@@ -115,6 +115,13 @@ public: + */ + SBuf::size_type skipAll(const CharacterSet &discardables); + ++ /** skips a given character sequence (string); ++ * does nothing if the sequence is empty ++ * ++ * \throws exception on mismatching prefix or InsufficientInput ++ */ ++ void skipRequired(const char *description, const SBuf &tokenToSkip); ++ + /** Removes a single trailing character from the set. + * + * \return whether a character was removed diff --git a/squid-4.15-CVE-2023-46847.patch b/squid-4.15-CVE-2023-46847.patch index 0d2e06153410bf5196566375fea1657bc1181e22..c2685170f07b193cc319a16eaa1233b8ed2ba73a 100644 --- a/squid-4.15-CVE-2023-46847.patch +++ b/squid-4.15-CVE-2023-46847.patch @@ -1,24 +1,3 @@ -From 2208acd78dbca40f382bd929cdedf1c3a3c40982 Mon Sep 17 00:00:00 2001 -From: squidadm -Date: Wed, 18 Oct 2023 04:50:56 +1300 -Subject: [PATCH] Fix stack buffer overflow when parsing Digest Authorization - (#1517) - -The bug was discovered and detailed by Joshua Rogers at -https://megamansec.github.io/Squid-Security-Audit/digest-overflow.html -where it was filed as "Stack Buffer Overflow in Digest Authentication". - ---------- - -Co-authored-by: Alex Bason -Co-authored-by: Amos Jeffries - -Conflict:NA -Reference:http://www.squid-cache.org/Versions/v5/SQUID-2023_3.patch ---- - src/auth/digest/Config.cc | 10 +++++++--- - 1 file changed, 7 insertions(+), 3 deletions(-) - diff --git a/src/auth/digest/Config.cc b/src/auth/digest/Config.cc index 6a9736f..0a883fa 100644 --- a/src/auth/digest/Config.cc @@ -42,6 +21,3 @@ index 6a9736f..0a883fa 100644 break; case DIGEST_CNONCE: --- -2.31.1 - diff --git a/squid-4.15-halfclosed.patch b/squid-4.15-halfclosed.patch new file mode 100644 index 0000000000000000000000000000000000000000..6a9fc59d95a9992e2aa687dfea57ae66b4747cfb --- /dev/null +++ b/squid-4.15-halfclosed.patch @@ -0,0 +1,163 @@ +diff --git a/src/client_side.cc b/src/client_side.cc +index f57f3f7..ab393e4 100644 +--- a/src/client_side.cc ++++ b/src/client_side.cc +@@ -906,7 +906,7 @@ ConnStateData::kick() + * We are done with the response, and we are either still receiving request + * body (early response!) or have already stopped receiving anything. + * +- * If we are still receiving, then clientParseRequest() below will fail. ++ * If we are still receiving, then parseRequests() below will fail. + * (XXX: but then we will call readNextRequest() which may succeed and + * execute a smuggled request as we are not done with the current request). + * +@@ -926,28 +926,12 @@ ConnStateData::kick() + * Attempt to parse a request from the request buffer. + * If we've been fed a pipelined request it may already + * be in our read buffer. +- * +- \par +- * This needs to fall through - if we're unlucky and parse the _last_ request +- * from our read buffer we may never re-register for another client read. + */ + +- if (clientParseRequests()) { +- debugs(33, 3, clientConnection << ": parsed next request from buffer"); +- } ++ parseRequests(); + +- /** \par +- * Either we need to kick-start another read or, if we have +- * a half-closed connection, kill it after the last request. +- * This saves waiting for half-closed connections to finished being +- * half-closed _AND_ then, sometimes, spending "Timeout" time in +- * the keepalive "Waiting for next request" state. +- */ +- if (commIsHalfClosed(clientConnection->fd) && pipeline.empty()) { +- debugs(33, 3, "half-closed client with no pending requests, closing"); +- clientConnection->close(); ++ if (!isOpen()) + return; +- } + + /** \par + * At this point we either have a parsed request (which we've +@@ -2058,16 +2042,11 @@ ConnStateData::receivedFirstByte() + commSetConnTimeout(clientConnection, Config.Timeout.request, timeoutCall); + } + +-/** +- * Attempt to parse one or more requests from the input buffer. +- * Returns true after completing parsing of at least one request [header]. That +- * includes cases where parsing ended with an error (e.g., a huge request). +- */ +-bool +-ConnStateData::clientParseRequests() ++/// Attempt to parse one or more requests from the input buffer. ++/// May close the connection. ++void ++ConnStateData::parseRequests() + { +- bool parsed_req = false; +- + debugs(33, 5, HERE << clientConnection << ": attempting to parse"); + + // Loop while we have read bytes that are not needed for producing the body +@@ -2116,8 +2095,6 @@ ConnStateData::clientParseRequests() + + processParsedRequest(context); + +- parsed_req = true; // XXX: do we really need to parse everything right NOW ? +- + if (context->mayUseConnection()) { + debugs(33, 3, HERE << "Not parsing new requests, as this request may need the connection"); + break; +@@ -2130,8 +2107,19 @@ ConnStateData::clientParseRequests() + } + } + +- /* XXX where to 'finish' the parsing pass? */ +- return parsed_req; ++ debugs(33, 7, "buffered leftovers: " << inBuf.length()); ++ ++ if (isOpen() && commIsHalfClosed(clientConnection->fd)) { ++ if (pipeline.empty()) { ++ // we processed what we could parse, and no more data is coming ++ debugs(33, 5, "closing half-closed without parsed requests: " << clientConnection); ++ clientConnection->close(); ++ } else { ++ // we parsed what we could, and no more data is coming ++ debugs(33, 5, "monitoring half-closed while processing parsed requests: " << clientConnection); ++ flags.readMore = false; // may already be false ++ } ++ } + } + + void +@@ -2148,23 +2136,7 @@ ConnStateData::afterClientRead() + if (pipeline.empty()) + fd_note(clientConnection->fd, "Reading next request"); + +- if (!clientParseRequests()) { +- if (!isOpen()) +- return; +- /* +- * If the client here is half closed and we failed +- * to parse a request, close the connection. +- * The above check with connFinishedWithConn() only +- * succeeds _if_ the buffer is empty which it won't +- * be if we have an incomplete request. +- * XXX: This duplicates ConnStateData::kick +- */ +- if (pipeline.empty() && commIsHalfClosed(clientConnection->fd)) { +- debugs(33, 5, clientConnection << ": half-closed connection, no completed request parsed, connection closing."); +- clientConnection->close(); +- return; +- } +- } ++ parseRequests(); + + if (!isOpen()) + return; +@@ -3945,7 +3917,7 @@ ConnStateData::notePinnedConnectionBecameIdle(PinnedIdleContext pic) + startPinnedConnectionMonitoring(); + + if (pipeline.empty()) +- kick(); // in case clientParseRequests() was blocked by a busy pic.connection ++ kick(); // in case parseRequests() was blocked by a busy pic.connection + } + + /// Forward future client requests using the given server connection. +diff --git a/src/client_side.h b/src/client_side.h +index 9fe8463..dfb4d8e 100644 +--- a/src/client_side.h ++++ b/src/client_side.h +@@ -85,7 +85,6 @@ public: + virtual void doneWithControlMsg(); + + /// Traffic parsing +- bool clientParseRequests(); + void readNextRequest(); + + /// try to make progress on a transaction or read more I/O +@@ -373,6 +372,7 @@ private: + virtual bool connFinishedWithConn(int size); + virtual void checkLogging(); + ++ void parseRequests(); + void clientAfterReadingRequests(); + bool concurrentRequestQueueFilled() const; + +diff --git a/src/tests/stub_client_side.cc b/src/tests/stub_client_side.cc +index d7efb0f..655ed83 100644 +--- a/src/tests/stub_client_side.cc ++++ b/src/tests/stub_client_side.cc +@@ -14,7 +14,7 @@ + #include "tests/STUB.h" + + #include "client_side.h" +-bool ConnStateData::clientParseRequests() STUB_RETVAL(false) ++void ConnStateData::parseRequests() STUB + void ConnStateData::readNextRequest() STUB + bool ConnStateData::isOpen() const STUB_RETVAL(false) + void ConnStateData::kick() STUB diff --git a/squid.spec b/squid.spec index a6c2ff99f22312b6bc3b32219cffefcfb0d12962..757f49f2b4f8c43e7d1a5b1a3877fe9a2dbb28fd 100644 --- a/squid.spec +++ b/squid.spec @@ -2,7 +2,7 @@ Name: squid Version: 4.15 -Release: 6%{?dist}.1 +Release: 7%{?dist}.1 Summary: The Squid proxy caching server Epoch: 7 # See CREDITS for breakdown of non GPLv2+ code @@ -38,6 +38,8 @@ Patch206: squid-4.11-active-ftp.patch Patch208: squid-4.11-convert-ipv4.patch # https://bugzilla.redhat.com/show_bug.cgi?id=2006121 Patch209: squid-4.15-ftp-filename-extraction.patch +# https://bugzilla.redhat.com/show_bug.cgi?id=2076717 +Patch210: squid-4.15-halfclosed.patch # Security fixes # https://bugzilla.redhat.com/show_bug.cgi?id=1941506 @@ -46,13 +48,11 @@ Patch300: squid-4.15-CVE-2021-28116.patch Patch301: squid-4.15-CVE-2021-46784.patch # https://bugzilla.redhat.com/show_bug.cgi?id=2129771 Patch302: squid-4.15-CVE-2022-41318.patch -# Fix CVE-2023-46846 -Patch303: squid-4.15-0001-CVE-2023-46846.patch -Patch304: squid-4.15-0002-CVE-2023-46846.patch -Patch305: squid-4.15-0003-CVE-2023-46846.patch -# Fix CVE-2023-46847 -Patch306: squid-4.15-CVE-2023-46847.patch - +# https://bugzilla.redhat.com/show_bug.cgi?id=2245910 +# +backported: https://github.com/squid-cache/squid/commit/417da4006cf5c97d44e74431b816fc58fec9e270 +Patch303: squid-4.15-CVE-2023-46846.patch +# https://bugzilla.redhat.com/show_bug.cgi?id=2245916 +Patch304: squid-4.15-CVE-2023-46847.patch Requires: bash >= 2.0 Requires(pre): shadow-utils @@ -114,15 +114,14 @@ lookup program (dnsserver), a program for retrieving FTP data %patch206 -p1 -b .active-ftp %patch208 -p1 -b .convert-ipv4 %patch209 -p1 -b .ftp-fn-extraction +%patch210 -p1 -b .halfclosed # Security patches %patch300 -p1 -b .CVE-2021-28116 %patch301 -p1 -b .CVE-2021-46784 %patch302 -p1 -b .CVE-2022-41318 %patch303 -p1 -b .CVE-2023-46846 -%patch304 -p1 -b .CVE-2023-46846 -%patch305 -p1 -b .CVE-2023-46846 -%patch306 -p1 -b .CVE-2023-46847 +%patch304 -p1 -b .CVE-2023-46847 # https://bugzilla.redhat.com/show_bug.cgi?id=1679526 # Patch in the vendor documentation and used different location for documentation @@ -339,10 +338,19 @@ fi %changelog -* Wed Nov 8 2023 Bo Liu - 4.15-6.1 -- Fix CVE-2023-46846 +* Tue Dec 12 2023 Bo Liu - 4.15-7.1 +- Fix CVE-2023-46846 - Fix CVE-2023-46847 +* Mon Oct 30 2023 Luboš Uhliarik - 7:4.15-7.1 +- Resolves: RHEL-14801 - squid: squid: Denial of Service in HTTP Digest + Authentication +- Resolves: RHEL-14776 - squid: squid: Request/Response smuggling in HTTP/1.1 + and ICAP + +* Wed Aug 16 2023 Luboš Uhliarik - 7:4.15-7 +- Resolves: #2076717 - Crash with half_closed_client on + * Thu Dec 08 2022 Tomas Korbar - 4.15-6 - Resolves: #2072988 - [RFE] Add the "IP_BIND_ADDRESS_NO_PORT" flag to sockets created for outgoing connections in the squid source code.