Compare commits

..

No commits in common. 'c9' and 'i8c-beta-stream-4' have entirely different histories.

3
.gitignore vendored

@ -1,2 +1 @@
SOURCES/pgp.asc SOURCES/squid-4.15.tar.xz
SOURCES/squid-5.5.tar.xz

@ -1,2 +1 @@
8e3de63f3bef0c9c4edbcfe000c567119f687143 SOURCES/pgp.asc 60bda34ba39657e2d870c8c1d2acece8a69c3075 SOURCES/squid-4.15.tar.xz
42302bd9b8feff851a41420334cb8eaeab2806ab SOURCES/squid-5.5.tar.xz

@ -5,17 +5,12 @@ fi
SQUID_CONF=${SQUID_CONF:-"/etc/squid/squid.conf"} SQUID_CONF=${SQUID_CONF:-"/etc/squid/squid.conf"}
CACHE_SWAP=`awk '/^[[:blank:]]*cache_dir/ { print $3 }' "$SQUID_CONF"` CACHE_SWAP=`sed -e 's/#.*//g' $SQUID_CONF | \
grep cache_dir | awk '{ print $3 }'`
init_cache_dirs=0
for adir in $CACHE_SWAP; do for adir in $CACHE_SWAP; do
if [ ! -d $adir/00 ]; then if [ ! -d $adir/00 ]; then
echo -n "init_cache_dir $adir... " echo -n "init_cache_dir $adir... "
init_cache_dirs=1 squid -N -z -F -f $SQUID_CONF >> /var/log/squid/squid.out 2>&1
fi fi
done done
if [ $init_cache_dirs -ne 0 ]; then
echo ""
squid --foreground -z -f "$SQUID_CONF" >> /var/log/squid/squid.out 2>&1
fi

@ -1,95 +0,0 @@
------------------------------------------------------------
revno: 14311
revision-id: squid3@treenet.co.nz-20150924130537-lqwzd1z99a3l9gt4
parent: squid3@treenet.co.nz-20150924032241-6cx3g6hwz9xfoybr
------------------------------------------------------------
revno: 14311
revision-id: squid3@treenet.co.nz-20150924130537-lqwzd1z99a3l9gt4
parent: squid3@treenet.co.nz-20150924032241-6cx3g6hwz9xfoybr
fixes bug: http://bugs.squid-cache.org/show_bug.cgi?id=4323
author: Francesco Chemolli <kinkie@squid-cache.org>
committer: Amos Jeffries <squid3@treenet.co.nz>
branch nick: trunk
timestamp: Thu 2015-09-24 06:05:37 -0700
message:
Bug 4323: Netfilter broken cross-includes with Linux 4.2
------------------------------------------------------------
# Bazaar merge directive format 2 (Bazaar 0.90)
# revision_id: squid3@treenet.co.nz-20150924130537-lqwzd1z99a3l9gt4
# target_branch: http://bzr.squid-cache.org/bzr/squid3/trunk/
# testament_sha1: c67cfca81040f3845d7c4caf2f40518511f14d0b
# timestamp: 2015-09-24 13:06:33 +0000
# source_branch: http://bzr.squid-cache.org/bzr/squid3/trunk
# base_revision_id: squid3@treenet.co.nz-20150924032241-\
# 6cx3g6hwz9xfoybr
#
# Begin patch
=== modified file 'compat/os/linux.h'
--- compat/os/linux.h 2015-01-13 07:25:36 +0000
+++ compat/os/linux.h 2015-09-24 13:05:37 +0000
@@ -30,6 +30,21 @@
#endif
/*
+ * Netfilter header madness. (see Bug 4323)
+ *
+ * Netfilter have a history of defining their own versions of network protocol
+ * primitives without sufficient protection against the POSIX defines which are
+ * aways present in Linux.
+ *
+ * netinet/in.h must be included before any other sys header in order to properly
+ * activate include guards in <linux/libc-compat.h> the kernel maintainers added
+ * to workaround it.
+ */
+#if HAVE_NETINET_IN_H
+#include <netinet/in.h>
+#endif
+
+/*
* sys/capability.h is only needed in Linux apparently.
*
* HACK: LIBCAP_BROKEN Ugly glue to get around linux header madness colliding with glibc
fixes bug: http://bugs.squid-cache.org/show_bug.cgi?id=4323
author: Francesco Chemolli <kinkie@squid-cache.org>
committer: Amos Jeffries <squid3@treenet.co.nz>
branch nick: trunk
timestamp: Thu 2015-09-24 06:05:37 -0700
message:
Bug 4323: Netfilter broken cross-includes with Linux 4.2
------------------------------------------------------------
# Bazaar merge directive format 2 (Bazaar 0.90)
# revision_id: squid3@treenet.co.nz-20150924130537-lqwzd1z99a3l9gt4
# target_branch: http://bzr.squid-cache.org/bzr/squid3/trunk/
# testament_sha1: c67cfca81040f3845d7c4caf2f40518511f14d0b
# timestamp: 2015-09-24 13:06:33 +0000
# source_branch: http://bzr.squid-cache.org/bzr/squid3/trunk
# base_revision_id: squid3@treenet.co.nz-20150924032241-\
# 6cx3g6hwz9xfoybr
#
# Begin patch
=== modified file 'compat/os/linux.h'
--- compat/os/linux.h 2015-01-13 07:25:36 +0000
+++ compat/os/linux.h 2015-09-24 13:05:37 +0000
@@ -30,6 +30,21 @@
#endif
/*
+ * Netfilter header madness. (see Bug 4323)
+ *
+ * Netfilter have a history of defining their own versions of network protocol
+ * primitives without sufficient protection against the POSIX defines which are
+ * aways present in Linux.
+ *
+ * netinet/in.h must be included before any other sys header in order to properly
+ * activate include guards in <linux/libc-compat.h> the kernel maintainers added
+ * to workaround it.
+ */
+#if HAVE_NETINET_IN_H
+#include <netinet/in.h>
+#endif
+
+/*
* sys/capability.h is only needed in Linux apparently.
*
* HACK: LIBCAP_BROKEN Ugly glue to get around linux header madness colliding with glibc

@ -1,8 +1,8 @@
diff --git a/src/clients/FtpClient.cc b/src/clients/FtpClient.cc diff --git a/src/clients/FtpClient.cc b/src/clients/FtpClient.cc
index 747ed35..f2b7126 100644 index b665bcf..d287e55 100644
--- a/src/clients/FtpClient.cc --- a/src/clients/FtpClient.cc
+++ b/src/clients/FtpClient.cc +++ b/src/clients/FtpClient.cc
@@ -795,7 +795,8 @@ Ftp::Client::connectDataChannel() @@ -778,7 +778,8 @@ Ftp::Client::connectDataChannel()
bool bool
Ftp::Client::openListenSocket() Ftp::Client::openListenSocket()
{ {
@ -13,10 +13,10 @@ index 747ed35..f2b7126 100644
/// creates a data channel Comm close callback /// creates a data channel Comm close callback
diff --git a/src/clients/FtpClient.h b/src/clients/FtpClient.h diff --git a/src/clients/FtpClient.h b/src/clients/FtpClient.h
index eb5ea1b..e92c007 100644 index a76a5a0..218d696 100644
--- a/src/clients/FtpClient.h --- a/src/clients/FtpClient.h
+++ b/src/clients/FtpClient.h +++ b/src/clients/FtpClient.h
@@ -137,7 +137,7 @@ public: @@ -118,7 +118,7 @@ public:
bool sendPort(); bool sendPort();
bool sendPassive(); bool sendPassive();
void connectDataChannel(); void connectDataChannel();
@ -26,10 +26,10 @@ index eb5ea1b..e92c007 100644
CtrlChannel ctrl; ///< FTP control channel state CtrlChannel ctrl; ///< FTP control channel state
diff --git a/src/clients/FtpGateway.cc b/src/clients/FtpGateway.cc diff --git a/src/clients/FtpGateway.cc b/src/clients/FtpGateway.cc
index 05db817..2989cd2 100644 index 411bce9..31d3e36 100644
--- a/src/clients/FtpGateway.cc --- a/src/clients/FtpGateway.cc
+++ b/src/clients/FtpGateway.cc +++ b/src/clients/FtpGateway.cc
@@ -86,6 +86,13 @@ struct GatewayFlags { @@ -87,6 +87,13 @@ struct GatewayFlags {
class Gateway; class Gateway;
typedef void (StateMethod)(Ftp::Gateway *); typedef void (StateMethod)(Ftp::Gateway *);
@ -43,7 +43,7 @@ index 05db817..2989cd2 100644
/// FTP Gateway: An FTP client that takes an HTTP request with an ftp:// URI, /// FTP Gateway: An FTP client that takes an HTTP request with an ftp:// URI,
/// converts it into one or more FTP commands, and then /// converts it into one or more FTP commands, and then
/// converts one or more FTP responses into the final HTTP response. /// converts one or more FTP responses into the final HTTP response.
@@ -136,7 +143,11 @@ public: @@ -137,7 +144,11 @@ public:
/// create a data channel acceptor and start listening. /// create a data channel acceptor and start listening.
void listenForDataChannel(const Comm::ConnectionPointer &conn); void listenForDataChannel(const Comm::ConnectionPointer &conn);
@ -56,7 +56,7 @@ index 05db817..2989cd2 100644
int checkAuth(const HttpHeader * req_hdr); int checkAuth(const HttpHeader * req_hdr);
void checkUrlpath(); void checkUrlpath();
void buildTitleUrl(); void buildTitleUrl();
@@ -1786,6 +1797,7 @@ ftpOpenListenSocket(Ftp::Gateway * ftpState, int fallback) @@ -1787,6 +1798,7 @@ ftpOpenListenSocket(Ftp::Gateway * ftpState, int fallback)
} }
ftpState->listenForDataChannel(temp); ftpState->listenForDataChannel(temp);
@ -64,7 +64,7 @@ index 05db817..2989cd2 100644
} }
static void static void
@@ -1821,13 +1833,19 @@ ftpSendPORT(Ftp::Gateway * ftpState) @@ -1822,13 +1834,19 @@ ftpSendPORT(Ftp::Gateway * ftpState)
// pull out the internal IP address bytes to send in PORT command... // pull out the internal IP address bytes to send in PORT command...
// source them from the listen_conn->local // source them from the listen_conn->local
@ -86,7 +86,7 @@ index 05db817..2989cd2 100644
ftpState->writeCommand(cbuf); ftpState->writeCommand(cbuf);
ftpState->state = Ftp::Client::SENT_PORT; ftpState->state = Ftp::Client::SENT_PORT;
@@ -1880,14 +1898,27 @@ ftpSendEPRT(Ftp::Gateway * ftpState) @@ -1881,14 +1899,27 @@ ftpSendEPRT(Ftp::Gateway * ftpState)
return; return;
} }
@ -116,7 +116,7 @@ index 05db817..2989cd2 100644
ftpState->writeCommand(cbuf); ftpState->writeCommand(cbuf);
ftpState->state = Ftp::Client::SENT_EPRT; ftpState->state = Ftp::Client::SENT_EPRT;
@@ -1906,7 +1937,7 @@ ftpReadEPRT(Ftp::Gateway * ftpState) @@ -1907,7 +1938,7 @@ ftpReadEPRT(Ftp::Gateway * ftpState)
ftpSendPORT(ftpState); ftpSendPORT(ftpState);
return; return;
} }

@ -1,7 +1,8 @@
diff -up squid-4.0.11/src/cf.data.pre.config squid-4.0.11/src/cf.data.pre diff --git a/src/cf.data.pre b/src/cf.data.pre
--- squid-4.0.11/src/cf.data.pre.config 2016-06-09 22:32:57.000000000 +0200 index 26ef576..30d5509 100644
+++ squid-4.0.11/src/cf.data.pre 2016-07-11 21:08:35.090976840 +0200 --- a/src/cf.data.pre
@@ -4658,7 +4658,7 @@ DOC_END +++ b/src/cf.data.pre
@@ -5006,7 +5006,7 @@ DOC_END
NAME: logfile_rotate NAME: logfile_rotate
TYPE: int TYPE: int
@ -10,7 +11,7 @@ diff -up squid-4.0.11/src/cf.data.pre.config squid-4.0.11/src/cf.data.pre
LOC: Config.Log.rotateNumber LOC: Config.Log.rotateNumber
DOC_START DOC_START
Specifies the default number of logfile rotations to make when you Specifies the default number of logfile rotations to make when you
@@ -6444,11 +6444,11 @@ COMMENT_END @@ -6857,11 +6857,11 @@ COMMENT_END
NAME: cache_mgr NAME: cache_mgr
TYPE: string TYPE: string

@ -0,0 +1,143 @@
From 771908d313ee9c255adfb5e4fdba4d6797c18409 Mon Sep 17 00:00:00 2001
From: Amos Jeffries <yadij@users.noreply.github.com>
Date: Thu, 7 Mar 2019 13:50:38 +0000
Subject: [PATCH] Bug 4928: Cannot convert non-IPv4 to IPv4 (#379)
... when reaching client_ip_max_connections
The client_ip_max_connections limit is checked before the TCP dst-IP is located for the newly received TCP connection. This leaves Squid unable to fetch the NFMARK or similar
details later on (they do not exist for [::]).
Move client_ip_max_connections test later in the TCP accept process to ensure dst-IP is known when the error is produced.
---
src/comm/TcpAcceptor.cc | 82 ++++++++++++++++++++---------------------
1 file changed, 39 insertions(+), 43 deletions(-)
diff --git a/src/comm/TcpAcceptor.cc b/src/comm/TcpAcceptor.cc
index d4b576d..936aa30 100644
--- a/src/comm/TcpAcceptor.cc
+++ b/src/comm/TcpAcceptor.cc
@@ -282,7 +282,16 @@ Comm::TcpAcceptor::acceptOne()
ConnectionPointer newConnDetails = new Connection();
const Comm::Flag flag = oldAccept(newConnDetails);
- 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())
@@ -292,16 +301,12 @@ Comm::TcpAcceptor::acceptOne()
return;
}
- 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);
}
@@ -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.
- * 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)
@@ -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();
@@ -396,6 +410,23 @@ Comm::TcpAcceptor::oldAccept(Comm::ConnectionPointer &details)
details->local = *gai;
Ip::Address::FreeAddr(gai);
+ /* 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::NOMESSAGE;
- }
- }
-
- /* 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;
}

@ -0,0 +1,41 @@
diff --git a/compat/os/linux.h b/compat/os/linux.h
index 0ff05c6..d51389b 100644
--- a/compat/os/linux.h
+++ b/compat/os/linux.h
@@ -44,6 +44,36 @@
#include <netinet/in.h>
#endif
+/*
+ * Netfilter header madness. (see Bug 4323)
+ *
+ * Netfilter have a history of defining their own versions of network protocol
+ * primitives without sufficient protection against the POSIX defines which are
+ * aways present in Linux.
+ *
+ * netinet/in.h must be included before any other sys header in order to properly
+ * activate include guards in <linux/libc-compat.h> the kernel maintainers added
+ * to workaround it.
+ */
+#if HAVE_NETINET_IN_H
+#include <netinet/in.h>
+#endif
+
+/*
+ * Netfilter header madness. (see Bug 4323)
+ *
+ * Netfilter have a history of defining their own versions of network protocol
+ * primitives without sufficient protection against the POSIX defines which are
+ * aways present in Linux.
+ *
+ * netinet/in.h must be included before any other sys header in order to properly
+ * activate include guards in <linux/libc-compat.h> the kernel maintainers added
+ * to workaround it.
+ */
+#if HAVE_NETINET_IN_H
+#include <netinet/in.h>
+#endif
+
/*
* sys/capability.h is only needed in Linux apparently.
*

@ -0,0 +1,178 @@
diff --git a/src/acl/RegexData.cc b/src/acl/RegexData.cc
index 01a4c12..b5c1679 100644
--- a/src/acl/RegexData.cc
+++ b/src/acl/RegexData.cc
@@ -22,6 +22,7 @@
#include "ConfigParser.h"
#include "Debug.h"
#include "sbuf/List.h"
+#include "sbuf/Algorithms.h"
ACLRegexData::~ACLRegexData()
{
@@ -129,6 +130,18 @@ compileRE(std::list<RegexPattern> &curlist, const char * RE, int flags)
return true;
}
+static bool
+compileRE(std::list<RegexPattern> &curlist, const SBufList &RE, int flags)
+{
+ if (RE.empty())
+ return curlist.empty(); // XXX: old code did this. It looks wrong.
+ SBuf regexp;
+ static const SBuf openparen("("), closeparen(")"), separator(")|(");
+ JoinContainerIntoSBuf(regexp, RE.begin(), RE.end(), separator, openparen,
+ closeparen);
+ return compileRE(curlist, regexp.c_str(), flags);
+}
+
/** Compose and compile one large RE from a set of (small) REs.
* The ultimate goal is to have only one RE per ACL so that match() is
* called only once per ACL.
@@ -137,16 +150,11 @@ static int
compileOptimisedREs(std::list<RegexPattern> &curlist, const SBufList &sl)
{
std::list<RegexPattern> newlist;
- int numREs = 0;
+ SBufList accumulatedRE;
+ int numREs = 0, reSize = 0;
int flags = REG_EXTENDED | REG_NOSUB;
- int largeREindex = 0;
- char largeRE[BUFSIZ];
- *largeRE = 0;
for (const SBuf & configurationLineWord : sl) {
- int RElen;
- RElen = configurationLineWord.length();
-
static const SBuf minus_i("-i");
static const SBuf plus_i("+i");
if (configurationLineWord == minus_i) {
@@ -155,10 +163,11 @@ compileOptimisedREs(std::list<RegexPattern> &curlist, const SBufList &sl)
debugs(28, 2, "optimisation of -i ... -i" );
} else {
debugs(28, 2, "-i" );
- if (!compileRE(newlist, largeRE, flags))
+ if (!compileRE(newlist, accumulatedRE, flags))
return 0;
flags |= REG_ICASE;
- largeRE[largeREindex=0] = '\0';
+ accumulatedRE.clear();
+ reSize = 0;
}
} else if (configurationLineWord == plus_i) {
if ((flags & REG_ICASE) == 0) {
@@ -166,37 +175,34 @@ compileOptimisedREs(std::list<RegexPattern> &curlist, const SBufList &sl)
debugs(28, 2, "optimisation of +i ... +i");
} else {
debugs(28, 2, "+i");
- if (!compileRE(newlist, largeRE, flags))
+ if (!compileRE(newlist, accumulatedRE, flags))
return 0;
flags &= ~REG_ICASE;
- largeRE[largeREindex=0] = '\0';
+ accumulatedRE.clear();
+ reSize = 0;
}
- } else if (RElen + largeREindex + 3 < BUFSIZ-1) {
+ } else if (reSize < 1024) {
debugs(28, 2, "adding RE '" << configurationLineWord << "'");
- if (largeREindex > 0) {
- largeRE[largeREindex] = '|';
- ++largeREindex;
- }
- largeRE[largeREindex] = '(';
- ++largeREindex;
- configurationLineWord.copy(largeRE+largeREindex, BUFSIZ-largeREindex);
- largeREindex += configurationLineWord.length();
- largeRE[largeREindex] = ')';
- ++largeREindex;
- largeRE[largeREindex] = '\0';
+ accumulatedRE.push_back(configurationLineWord);
++numREs;
+ reSize += configurationLineWord.length();
} else {
debugs(28, 2, "buffer full, generating new optimised RE..." );
- if (!compileRE(newlist, largeRE, flags))
+ accumulatedRE.push_back(configurationLineWord);
+ if (!compileRE(newlist, accumulatedRE, flags))
return 0;
- largeRE[largeREindex=0] = '\0';
+ accumulatedRE.clear();
+ reSize = 0;
continue; /* do the loop again to add the RE to largeRE */
}
}
- if (!compileRE(newlist, largeRE, flags))
+ if (!compileRE(newlist, accumulatedRE, flags))
return 0;
+ accumulatedRE.clear();
+ reSize = 0;
+
/* all was successful, so put the new list at the tail */
curlist.splice(curlist.end(), newlist);
diff --git a/src/sbuf/Algorithms.h b/src/sbuf/Algorithms.h
index 21ee889..338e9c0 100644
--- a/src/sbuf/Algorithms.h
+++ b/src/sbuf/Algorithms.h
@@ -81,6 +81,57 @@ SBufContainerJoin(const Container &items, const SBuf& separator)
return rv;
}
+/** Join container of SBufs and append to supplied target
+ *
+ * append to the target SBuf all elements in the [begin,end) range from
+ * an iterable container, prefixed by prefix, separated by separator and
+ * followed by suffix. Prefix and suffix are added also in case of empty
+ * iterable
+ *
+ * \return the modified dest
+ */
+template <class ContainerIterator>
+SBuf&
+JoinContainerIntoSBuf(SBuf &dest, const ContainerIterator &begin,
+ const ContainerIterator &end, const SBuf& separator,
+ const SBuf& prefix = SBuf(), const SBuf& suffix = SBuf())
+{
+ if (begin == end) {
+ dest.append(prefix).append(suffix);
+ return dest;
+ }
+
+ // optimization: pre-calculate needed storage
+ const SBuf::size_type totalContainerSize =
+ std::accumulate(begin, end, 0, SBufAddLength(separator)) +
+ dest.length() + prefix.length() + suffix.length();
+ SBufReservationRequirements req;
+ req.minSpace = totalContainerSize;
+ dest.reserve(req);
+
+ auto i = begin;
+ dest.append(prefix);
+ dest.append(*i);
+ ++i;
+ for (; i != end; ++i)
+ dest.append(separator).append(*i);
+ dest.append(suffix);
+ return dest;
+}
+
+
+/// convenience wrapper of JoinContainerIntoSBuf with no caller-supplied SBuf
+template <class ContainerIterator>
+SBuf
+JoinContainerToSBuf(const ContainerIterator &begin,
+ const ContainerIterator &end, const SBuf& separator,
+ const SBuf& prefix = SBuf(), const SBuf& suffix = SBuf())
+{
+ SBuf rv;
+ return JoinContainerIntoSBuf(rv, begin, end, separator, prefix, suffix);
+}
+
+
namespace std {
/// default hash functor to support std::unordered_map<SBuf,*>
template <>

@ -1,7 +1,8 @@
diff -up squid-3.1.0.9/QUICKSTART.location squid-3.1.0.9/QUICKSTART diff --git a/QUICKSTART b/QUICKSTART
--- squid-3.1.0.9/QUICKSTART.location 2009-06-26 12:35:27.000000000 +0200 index e5299b4..a243437 100644
+++ squid-3.1.0.9/QUICKSTART 2009-07-17 14:03:10.000000000 +0200 --- a/QUICKSTART
@@ -10,10 +10,9 @@ After you retrieved, compiled and instal +++ b/QUICKSTART
@@ -10,10 +10,9 @@ After you retrieved, compiled and installed the Squid software (see
INSTALL in the same directory), you have to configure the squid.conf INSTALL in the same directory), you have to configure the squid.conf
file. This is the list of the values you *need* to change, because no file. This is the list of the values you *need* to change, because no
sensible defaults could be defined. Do not touch the other variables sensible defaults could be defined. Do not touch the other variables
@ -14,7 +15,7 @@ diff -up squid-3.1.0.9/QUICKSTART.location squid-3.1.0.9/QUICKSTART
============================================================================== ==============================================================================
@@ -82,12 +81,12 @@ After editing squid.conf to your liking, @@ -80,12 +79,12 @@ After editing squid.conf to your liking, run Squid from the command
line TWICE: line TWICE:
To create any disk cache_dir configured: To create any disk cache_dir configured:

@ -1,10 +1,10 @@
diff --git a/contrib/url-normalizer.pl b/contrib/url-normalizer.pl diff --git a/contrib/url-normalizer.pl b/contrib/url-normalizer.pl
index 4cb0480..4b89910 100755 index 90ac6a4..8dbed90 100755
--- a/contrib/url-normalizer.pl --- a/contrib/url-normalizer.pl
+++ b/contrib/url-normalizer.pl +++ b/contrib/url-normalizer.pl
@@ -1,4 +1,4 @@ @@ -1,4 +1,4 @@
-#!/usr/local/bin/perl -Tw -#!/usr/local/bin/perl -Tw
+#!/usr/bin/perl -Tw +#!/usr/bin/perl -Tw
# #
# * Copyright (C) 1996-2022 The Squid Software Foundation and contributors # * Copyright (C) 1996-2021 The Squid Software Foundation and contributors
# * # *

@ -0,0 +1,424 @@
commit b003a0da7865caa25b5d1e70c79329b32409b02a (HEAD -> refs/heads/v4, refs/remotes/origin/v4)
Author: Amos Jeffries <yadij@users.noreply.github.com>
Date: 2021-09-24 21:53:11 +0000
WCCP: Validate packets better (#899)
Update WCCP to support exception based error handling for
parsing and processing we are moving Squid to for protocol
handling.
Update the main WCCPv2 parsing checks to throw meaningful
exceptions when detected.
diff --git a/src/wccp2.cc b/src/wccp2.cc
index ee592449c..6ef469e91 100644
--- a/src/wccp2.cc
+++ b/src/wccp2.cc
@@ -1108,6 +1108,59 @@ wccp2ConnectionClose(void)
* Functions for handling the requests.
*/
+/// Checks that the given area section ends inside the given (whole) area.
+/// \param error the message to throw when the section does not fit
+static void
+CheckSectionLength(const void *sectionStart, const size_t sectionLength, const void *wholeStart, const size_t wholeSize, const char *error)
+{
+ assert(sectionStart);
+ assert(wholeStart);
+
+ const auto wholeEnd = static_cast<const char*>(wholeStart) + wholeSize;
+ assert(sectionStart >= wholeStart && "we never go backwards");
+ assert(sectionStart <= wholeEnd && "we never go beyond our whole (but zero-sized fields are OK)");
+ static_assert(sizeof(wccp2_i_see_you_t) <= PTRDIFF_MAX, "paranoid: no UB when subtracting in-whole pointers");
+ // subtraction safe due to the three assertions above
+ const auto remainderDiff = wholeEnd - static_cast<const char*>(sectionStart);
+
+ // casting safe due to the assertions above (and size_t definition)
+ assert(remainderDiff >= 0);
+ const auto remainderSize = static_cast<size_t>(remainderDiff);
+
+ if (sectionLength <= remainderSize)
+ return;
+
+ throw TextException(error, Here());
+}
+
+/// Checks that the area contains at least dataLength bytes after the header.
+/// The size of the field header itself is not included in dataLength.
+/// \returns the total field size -- the field header and field data combined
+template<class FieldHeader>
+static size_t
+CheckFieldDataLength(const FieldHeader *header, const size_t dataLength, const void *areaStart, const size_t areaSize, const char *error)
+{
+ assert(header);
+ const auto dataStart = reinterpret_cast<const char*>(header) + sizeof(header);
+ CheckSectionLength(dataStart, dataLength, areaStart, areaSize, error);
+ return sizeof(header) + dataLength; // no overflow after CheckSectionLength()
+}
+
+/// Positions the given field at a given start within a given packet area.
+/// The Field type determines the correct field size (used for bounds checking).
+/// \param field the field pointer the function should set
+/// \param areaStart the start of a packet (sub)structure containing the field
+/// \param areaSize the size of the packet (sub)structure starting at areaStart
+/// \param fieldStart the start of a field within the given area
+/// \param error the message to throw when the field does not fit the area
+template<class Field>
+static void
+SetField(Field *&field, const void *fieldStart, const void *areaStart, const size_t areaSize, const char *error)
+{
+ CheckSectionLength(fieldStart, sizeof(Field), areaStart, areaSize, error);
+ field = static_cast<Field*>(const_cast<void*>(fieldStart));
+}
+
/*
* Accept the UDP packet
*/
@@ -1124,8 +1177,6 @@ wccp2HandleUdp(int sock, void *)
/* These structs form the parts of the packet */
- struct wccp2_item_header_t *header = NULL;
-
struct wccp2_security_none_t *security_info = NULL;
struct wccp2_service_info_t *service_info = NULL;
@@ -1141,14 +1192,13 @@ wccp2HandleUdp(int sock, void *)
struct wccp2_cache_identity_info_t *cache_identity = NULL;
struct wccp2_capability_info_header_t *router_capability_header = NULL;
+ char *router_capability_data_start = nullptr;
struct wccp2_capability_element_t *router_capability_element;
struct sockaddr_in from;
struct in_addr cache_address;
- int len, found;
- short int data_length, offset;
uint32_t tmp;
char *ptr;
int num_caches;
@@ -1161,20 +1211,18 @@ wccp2HandleUdp(int sock, void *)
Ip::Address from_tmp;
from_tmp.setIPv4();
- len = comm_udp_recvfrom(sock,
- &wccp2_i_see_you,
- WCCP_RESPONSE_SIZE,
- 0,
- from_tmp);
+ const auto lenOrError = comm_udp_recvfrom(sock, &wccp2_i_see_you, WCCP_RESPONSE_SIZE, 0, from_tmp);
- if (len < 0)
+ if (lenOrError < 0)
return;
+ const auto len = static_cast<size_t>(lenOrError);
- if (ntohs(wccp2_i_see_you.version) != WCCP2_VERSION)
- return;
-
- if (ntohl(wccp2_i_see_you.type) != WCCP2_I_SEE_YOU)
- return;
+ try {
+ // TODO: Remove wccp2_i_see_you.data and use a buffer to read messages.
+ const auto message_header_size = sizeof(wccp2_i_see_you) - sizeof(wccp2_i_see_you.data);
+ Must2(len >= message_header_size, "incomplete WCCP message header");
+ Must2(ntohs(wccp2_i_see_you.version) == WCCP2_VERSION, "WCCP version unsupported");
+ Must2(ntohl(wccp2_i_see_you.type) == WCCP2_I_SEE_YOU, "WCCP packet type unsupported");
/* FIXME INET6 : drop conversion boundary */
from_tmp.getSockAddr(from);
@@ -1182,73 +1230,60 @@ wccp2HandleUdp(int sock, void *)
debugs(80, 3, "Incoming WCCPv2 I_SEE_YOU length " << ntohs(wccp2_i_see_you.length) << ".");
/* Record the total data length */
- data_length = ntohs(wccp2_i_see_you.length);
+ const auto data_length = ntohs(wccp2_i_see_you.length);
+ Must2(data_length <= len - message_header_size,
+ "malformed packet claiming it's bigger than received data");
- offset = 0;
-
- if (data_length > len) {
- debugs(80, DBG_IMPORTANT, "ERROR: Malformed WCCPv2 packet claiming it's bigger than received data");
- return;
- }
+ size_t offset = 0;
/* Go through the data structure */
- while (data_length > offset) {
+ while (offset + sizeof(struct wccp2_item_header_t) <= data_length) {
char *data = wccp2_i_see_you.data;
- header = (struct wccp2_item_header_t *) &data[offset];
+ const auto itemHeader = reinterpret_cast<const wccp2_item_header_t*>(&data[offset]);
+ const auto itemSize = CheckFieldDataLength(itemHeader, ntohs(itemHeader->length),
+ data, data_length, "truncated record");
+ // XXX: Check "The specified length must be a multiple of 4 octets"
+ // requirement to avoid unaligned memory reads after the first item.
- switch (ntohs(header->type)) {
+ switch (ntohs(itemHeader->type)) {
case WCCP2_SECURITY_INFO:
-
- if (security_info != NULL) {
- debugs(80, DBG_IMPORTANT, "Duplicate security definition");
- return;
- }
-
- security_info = (struct wccp2_security_none_t *) &wccp2_i_see_you.data[offset];
+ Must2(!security_info, "duplicate security definition");
+ SetField(security_info, itemHeader, itemHeader, itemSize,
+ "security definition truncated");
break;
case WCCP2_SERVICE_INFO:
-
- if (service_info != NULL) {
- debugs(80, DBG_IMPORTANT, "Duplicate service_info definition");
- return;
- }
-
- service_info = (struct wccp2_service_info_t *) &wccp2_i_see_you.data[offset];
+ Must2(!service_info, "duplicate service_info definition");
+ SetField(service_info, itemHeader, itemHeader, itemSize,
+ "service_info definition truncated");
break;
case WCCP2_ROUTER_ID_INFO:
-
- if (router_identity_info != NULL) {
- debugs(80, DBG_IMPORTANT, "Duplicate router_identity_info definition");
- return;
- }
-
- router_identity_info = (struct router_identity_info_t *) &wccp2_i_see_you.data[offset];
+ Must2(!router_identity_info, "duplicate router_identity_info definition");
+ SetField(router_identity_info, itemHeader, itemHeader, itemSize,
+ "router_identity_info definition truncated");
break;
case WCCP2_RTR_VIEW_INFO:
-
- if (router_view_header != NULL) {
- debugs(80, DBG_IMPORTANT, "Duplicate router_view definition");
- return;
- }
-
- router_view_header = (struct router_view_t *) &wccp2_i_see_you.data[offset];
+ Must2(!router_view_header, "duplicate router_view definition");
+ SetField(router_view_header, itemHeader, itemHeader, itemSize,
+ "router_view definition truncated");
break;
- case WCCP2_CAPABILITY_INFO:
-
- if (router_capability_header != NULL) {
- debugs(80, DBG_IMPORTANT, "Duplicate router_capability definition");
- return;
- }
+ case WCCP2_CAPABILITY_INFO: {
+ Must2(!router_capability_header, "duplicate router_capability definition");
+ SetField(router_capability_header, itemHeader, itemHeader, itemSize,
+ "router_capability definition truncated");
- router_capability_header = (struct wccp2_capability_info_header_t *) &wccp2_i_see_you.data[offset];
+ CheckFieldDataLength(router_capability_header, ntohs(router_capability_header->capability_info_length),
+ itemHeader, itemSize, "capability info truncated");
+ router_capability_data_start = reinterpret_cast<char*>(router_capability_header) +
+ sizeof(*router_capability_header);
break;
+ }
/* Nothing to do for the types below */
@@ -1257,22 +1292,17 @@ wccp2HandleUdp(int sock, void *)
break;
default:
- debugs(80, DBG_IMPORTANT, "Unknown record type in WCCPv2 Packet (" << ntohs(header->type) << ").");
+ debugs(80, DBG_IMPORTANT, "Unknown record type in WCCPv2 Packet (" << ntohs(itemHeader->type) << ").");
}
- offset += sizeof(struct wccp2_item_header_t);
- offset += ntohs(header->length);
-
- if (offset > data_length) {
- debugs(80, DBG_IMPORTANT, "Error: WCCPv2 packet tried to tell us there is data beyond the end of the packet");
- return;
- }
+ offset += itemSize;
+ assert(offset <= data_length && "CheckFieldDataLength(itemHeader...) established that");
}
- if ((security_info == NULL) || (service_info == NULL) || (router_identity_info == NULL) || (router_view_header == NULL)) {
- debugs(80, DBG_IMPORTANT, "Incomplete WCCPv2 Packet");
- return;
- }
+ Must2(security_info, "packet missing security definition");
+ Must2(service_info, "packet missing service_info definition");
+ Must2(router_identity_info, "packet missing router_identity_info definition");
+ Must2(router_view_header, "packet missing router_view definition");
debugs(80, 5, "Complete packet received");
@@ -1308,10 +1338,7 @@ wccp2HandleUdp(int sock, void *)
break;
}
- if (router_list_ptr->next == NULL) {
- debugs(80, DBG_IMPORTANT, "WCCPv2 Packet received from unknown router");
- return;
- }
+ Must2(router_list_ptr->next, "packet received from unknown router");
/* Set the router id */
router_list_ptr->info->router_address = router_identity_info->router_id_element.router_address;
@@ -1331,11 +1358,20 @@ wccp2HandleUdp(int sock, void *)
}
} else {
- char *end = ((char *) router_capability_header) + sizeof(*router_capability_header) + ntohs(router_capability_header->capability_info_length) - sizeof(struct wccp2_capability_info_header_t);
-
- router_capability_element = (struct wccp2_capability_element_t *) (((char *) router_capability_header) + sizeof(*router_capability_header));
-
- while ((char *) router_capability_element <= end) {
+ const auto router_capability_data_length = ntohs(router_capability_header->capability_info_length);
+ assert(router_capability_data_start);
+ const auto router_capability_data_end = router_capability_data_start +
+ router_capability_data_length;
+ for (auto router_capability_data_current = router_capability_data_start;
+ router_capability_data_current < router_capability_data_end;) {
+
+ SetField(router_capability_element, router_capability_data_current,
+ router_capability_data_start, router_capability_data_length,
+ "capability element header truncated");
+ const auto elementSize = CheckFieldDataLength(
+ router_capability_element, ntohs(router_capability_element->capability_length),
+ router_capability_data_start, router_capability_data_length,
+ "capability element truncated");
switch (ntohs(router_capability_element->capability_type)) {
@@ -1377,7 +1413,7 @@ wccp2HandleUdp(int sock, void *)
debugs(80, DBG_IMPORTANT, "Unknown capability type in WCCPv2 Packet (" << ntohs(router_capability_element->capability_type) << ").");
}
- router_capability_element = (struct wccp2_capability_element_t *) (((char *) router_capability_element) + sizeof(struct wccp2_item_header_t) + ntohs(router_capability_element->capability_length));
+ router_capability_data_current += elementSize;
}
}
@@ -1396,23 +1432,34 @@ wccp2HandleUdp(int sock, void *)
num_caches = 0;
/* Check to see if we're the master cache and update the cache list */
- found = 0;
+ bool found = false;
service_list_ptr->lowest_ip = 1;
cache_list_ptr = &router_list_ptr->cache_list_head;
/* to find the list of caches, we start at the end of the router view header */
ptr = (char *) (router_view_header) + sizeof(struct router_view_t);
+ const auto router_view_size = sizeof(struct router_view_t) +
+ ntohs(router_view_header->header.length);
/* Then we read the number of routers */
- memcpy(&tmp, ptr, sizeof(tmp));
+ const uint32_t *routerCountRaw = nullptr;
+ SetField(routerCountRaw, ptr, router_view_header, router_view_size,
+ "malformed packet (truncated router view info w/o number of routers)");
/* skip the number plus all the ip's */
-
- ptr += sizeof(tmp) + (ntohl(tmp) * sizeof(struct in_addr));
+ ptr += sizeof(*routerCountRaw);
+ const auto ipCount = ntohl(*routerCountRaw);
+ const auto ipsSize = ipCount * sizeof(struct in_addr); // we check for unsigned overflow below
+ Must2(ipsSize / sizeof(struct in_addr) != ipCount, "huge IP address count");
+ CheckSectionLength(ptr, ipsSize, router_view_header, router_view_size, "invalid IP address count");
+ ptr += ipsSize;
/* Then read the number of caches */
- memcpy(&tmp, ptr, sizeof(tmp));
+ const uint32_t *cacheCountRaw = nullptr;
+ SetField(cacheCountRaw, ptr, router_view_header, router_view_size,
+ "malformed packet (truncated router view info w/o cache count)");
+ memcpy(&tmp, cacheCountRaw, sizeof(tmp)); // TODO: Replace tmp with cacheCount
ptr += sizeof(tmp);
if (ntohl(tmp) != 0) {
@@ -1426,7 +1473,8 @@ wccp2HandleUdp(int sock, void *)
case WCCP2_ASSIGNMENT_METHOD_HASH:
- cache_identity = (struct wccp2_cache_identity_info_t *) ptr;
+ SetField(cache_identity, ptr, router_view_header, router_view_size,
+ "malformed packet (truncated router view info cache w/o assignment hash)");
ptr += sizeof(struct wccp2_cache_identity_info_t);
@@ -1437,13 +1485,15 @@ wccp2HandleUdp(int sock, void *)
case WCCP2_ASSIGNMENT_METHOD_MASK:
- cache_mask_info = (struct cache_mask_info_t *) ptr;
+ SetField(cache_mask_info, ptr, router_view_header, router_view_size,
+ "malformed packet (truncated router view info cache w/o assignment mask)");
/* The mask assignment has an undocumented variable length entry here */
if (ntohl(cache_mask_info->num1) == 3) {
- cache_mask_identity = (struct wccp2_cache_mask_identity_info_t *) ptr;
+ SetField(cache_mask_identity, ptr, router_view_header, router_view_size,
+ "malformed packet (truncated router view info cache w/o assignment mask identity)");
ptr += sizeof(struct wccp2_cache_mask_identity_info_t);
@@ -1474,10 +1524,7 @@ wccp2HandleUdp(int sock, void *)
debugs (80, 5, "checking cache list: (" << std::hex << cache_address.s_addr << ":" << router_list_ptr->local_ip.s_addr << ")");
/* Check to see if it's the master, or us */
-
- if (cache_address.s_addr == router_list_ptr->local_ip.s_addr) {
- found = 1;
- }
+ found = found || (cache_address.s_addr == router_list_ptr->local_ip.s_addr);
if (cache_address.s_addr < router_list_ptr->local_ip.s_addr) {
service_list_ptr->lowest_ip = 0;
@@ -1494,7 +1541,7 @@ wccp2HandleUdp(int sock, void *)
cache_list_ptr->next = NULL;
service_list_ptr->lowest_ip = 1;
- found = 1;
+ found = true;
num_caches = 1;
}
@@ -1502,7 +1549,7 @@ wccp2HandleUdp(int sock, void *)
router_list_ptr->num_caches = htonl(num_caches);
- if ((found == 1) && (service_list_ptr->lowest_ip == 1)) {
+ if (found && (service_list_ptr->lowest_ip == 1)) {
if (ntohl(router_view_header->change_number) != router_list_ptr->member_change) {
debugs(80, 4, "Change detected - queueing up new assignment");
router_list_ptr->member_change = ntohl(router_view_header->change_number);
@@ -1515,6 +1562,10 @@ wccp2HandleUdp(int sock, void *)
eventDelete(wccp2AssignBuckets, NULL);
debugs(80, 5, "I am not the lowest ip cache - not assigning buckets");
}
+
+ } catch (...) {
+ debugs(80, DBG_IMPORTANT, "ERROR: Ignoring WCCPv2 message: " << CurrentException);
+ }
}
static void

@ -1,8 +1,17 @@
From 780c4ea1b4c9d2fb41f6962aa6ed73ae57f74b2b Mon Sep 17 00:00:00 2001
From: Joshua Rogers <MegaManSec@users.noreply.github.com>
Date: Mon, 18 Apr 2022 13:42:36 +0000
Subject: [PATCH] Improve handling of Gopher responses (#1022)
---
src/gopher.cc | 45 ++++++++++++++++++++-------------------------
1 file changed, 20 insertions(+), 25 deletions(-)
diff --git a/src/gopher.cc b/src/gopher.cc diff --git a/src/gopher.cc b/src/gopher.cc
index 576a3f7..2645b6b 100644 index 169b0e18299..6187da18bcd 100644
--- a/src/gopher.cc --- a/src/gopher.cc
+++ b/src/gopher.cc +++ b/src/gopher.cc
@@ -364,7 +364,6 @@ gopherToHTML(GopherStateData * gopherState, char *inbuf, int len) @@ -371,7 +371,6 @@ gopherToHTML(GopherStateData * gopherState, char *inbuf, int len)
char *lpos = NULL; char *lpos = NULL;
char *tline = NULL; char *tline = NULL;
LOCAL_ARRAY(char, line, TEMP_BUF_SIZE); LOCAL_ARRAY(char, line, TEMP_BUF_SIZE);
@ -10,7 +19,7 @@ index 576a3f7..2645b6b 100644
char *name = NULL; char *name = NULL;
char *selector = NULL; char *selector = NULL;
char *host = NULL; char *host = NULL;
@@ -374,7 +373,6 @@ gopherToHTML(GopherStateData * gopherState, char *inbuf, int len) @@ -381,7 +380,6 @@ gopherToHTML(GopherStateData * gopherState, char *inbuf, int len)
char gtype; char gtype;
StoreEntry *entry = NULL; StoreEntry *entry = NULL;
@ -18,7 +27,7 @@ index 576a3f7..2645b6b 100644
memset(line, '\0', TEMP_BUF_SIZE); memset(line, '\0', TEMP_BUF_SIZE);
entry = gopherState->entry; entry = gopherState->entry;
@@ -409,7 +407,7 @@ gopherToHTML(GopherStateData * gopherState, char *inbuf, int len) @@ -416,7 +414,7 @@ gopherToHTML(GopherStateData * gopherState, char *inbuf, int len)
return; return;
} }
@ -27,7 +36,7 @@ index 576a3f7..2645b6b 100644
if (!gopherState->HTML_header_added) { if (!gopherState->HTML_header_added) {
if (gopherState->conversion == GopherStateData::HTML_CSO_RESULT) if (gopherState->conversion == GopherStateData::HTML_CSO_RESULT)
@@ -577,34 +575,34 @@ gopherToHTML(GopherStateData * gopherState, char *inbuf, int len) @@ -583,34 +581,34 @@ gopherToHTML(GopherStateData * gopherState, char *inbuf, int len)
break; break;
} }
@ -76,7 +85,7 @@ index 576a3f7..2645b6b 100644
} else { } else {
memset(line, '\0', TEMP_BUF_SIZE); memset(line, '\0', TEMP_BUF_SIZE);
continue; continue;
@@ -637,13 +635,12 @@ gopherToHTML(GopherStateData * gopherState, char *inbuf, int len) @@ -643,13 +641,12 @@ gopherToHTML(GopherStateData * gopherState, char *inbuf, int len)
break; break;
if (gopherState->cso_recno != recno) { if (gopherState->cso_recno != recno) {
@ -92,7 +101,7 @@ index 576a3f7..2645b6b 100644
break; break;
} else { } else {
int code; int code;
@@ -671,8 +668,7 @@ gopherToHTML(GopherStateData * gopherState, char *inbuf, int len) @@ -677,8 +674,7 @@ gopherToHTML(GopherStateData * gopherState, char *inbuf, int len)
case 502: { /* Too Many Matches */ case 502: { /* Too Many Matches */
/* Print the message the server returns */ /* Print the message the server returns */
@ -102,7 +111,7 @@ index 576a3f7..2645b6b 100644
break; break;
} }
@@ -688,13 +684,12 @@ gopherToHTML(GopherStateData * gopherState, char *inbuf, int len) @@ -694,13 +690,12 @@ gopherToHTML(GopherStateData * gopherState, char *inbuf, int len)
} /* while loop */ } /* while loop */

File diff suppressed because it is too large Load Diff

@ -1,26 +1,8 @@
From 052cf082b0faaef4eaaa4e94119d7a1437aac4a3 Mon Sep 17 00:00:00 2001
From: squidadm <squidadm@users.noreply.github.com>
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 <nonsleepr@gmail.com>
Co-authored-by: Amos Jeffries <yadij@users.noreply.github.com>
---
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 diff --git a/src/auth/digest/Config.cc b/src/auth/digest/Config.cc
index d42831a55..be9f3c433 100644 index 6a9736f..0a883fa 100644
--- a/src/auth/digest/Config.cc --- a/src/auth/digest/Config.cc
+++ b/src/auth/digest/Config.cc +++ b/src/auth/digest/Config.cc
@@ -844,11 +844,15 @@ Auth::Digest::Config::decode(char const *proxy_auth, const HttpRequest *request, @@ -847,11 +847,15 @@ Auth::Digest::Config::decode(char const *proxy_auth, const char *aRequestRealm)
break; break;
case DIGEST_NC: case DIGEST_NC:
@ -39,5 +21,3 @@ index d42831a55..be9f3c433 100644
break; break;
case DIGEST_CNONCE: case DIGEST_CNONCE:
--
2.25.1

@ -1,8 +1,8 @@
diff --git a/src/ClientRequestContext.h b/src/ClientRequestContext.h diff --git a/src/ClientRequestContext.h b/src/ClientRequestContext.h
index 55a7a43..94a8700 100644 index fe2edf6..47aa935 100644
--- a/src/ClientRequestContext.h --- a/src/ClientRequestContext.h
+++ b/src/ClientRequestContext.h +++ b/src/ClientRequestContext.h
@@ -80,6 +80,10 @@ public: @@ -81,6 +81,10 @@ public:
#endif #endif
ErrorState *error; ///< saved error page for centralized/delayed processing ErrorState *error; ///< saved error page for centralized/delayed processing
bool readNextRequest; ///< whether Squid should read after error handling bool readNextRequest; ///< whether Squid should read after error handling
@ -14,10 +14,10 @@ index 55a7a43..94a8700 100644
#endif /* SQUID_CLIENTREQUESTCONTEXT_H */ #endif /* SQUID_CLIENTREQUESTCONTEXT_H */
diff --git a/src/client_side_request.cc b/src/client_side_request.cc diff --git a/src/client_side_request.cc b/src/client_side_request.cc
index f44849e..c7c09d4 100644 index 1c6ff62..b758f6f 100644
--- a/src/client_side_request.cc --- a/src/client_side_request.cc
+++ b/src/client_side_request.cc +++ b/src/client_side_request.cc
@@ -80,6 +80,11 @@ @@ -78,6 +78,11 @@
static const char *const crlf = "\r\n"; static const char *const crlf = "\r\n";
#if FOLLOW_X_FORWARDED_FOR #if FOLLOW_X_FORWARDED_FOR
@ -26,10 +26,10 @@ index f44849e..c7c09d4 100644
+#define SQUID_X_FORWARDED_FOR_HOP_MAX 64 +#define SQUID_X_FORWARDED_FOR_HOP_MAX 64
+#endif +#endif
+ +
static void clientFollowXForwardedForCheck(Acl::Answer answer, void *data); static void clientFollowXForwardedForCheck(allow_t answer, void *data);
#endif /* FOLLOW_X_FORWARDED_FOR */ #endif /* FOLLOW_X_FORWARDED_FOR */
@@ -485,8 +490,16 @@ clientFollowXForwardedForCheck(Acl::Answer answer, void *data) @@ -485,8 +490,16 @@ clientFollowXForwardedForCheck(allow_t answer, void *data)
/* override the default src_addr tested if we have to go deeper than one level into XFF */ /* override the default src_addr tested if we have to go deeper than one level into XFF */
Filled(calloutContext->acl_checklist)->src_addr = request->indirect_client_addr; Filled(calloutContext->acl_checklist)->src_addr = request->indirect_client_addr;
} }

@ -0,0 +1,32 @@
diff --git a/src/clients/FtpGateway.cc b/src/clients/FtpGateway.cc
index da9867f..e992638 100644
--- a/src/clients/FtpGateway.cc
+++ b/src/clients/FtpGateway.cc
@@ -1084,16 +1084,17 @@ Ftp::Gateway::checkAuth(const HttpHeader * req_hdr)
void
Ftp::Gateway::checkUrlpath()
{
- static SBuf str_type_eq("type=");
- auto t = request->url.path().rfind(';');
-
- if (t != SBuf::npos) {
- auto filenameEnd = t-1;
- if (request->url.path().substr(++t).cmp(str_type_eq, str_type_eq.length()) == 0) {
- t += str_type_eq.length();
- typecode = (char)xtoupper(request->url.path()[t]);
- request->url.path(request->url.path().substr(0,filenameEnd));
- }
+ // If typecode was specified, extract it and leave just the filename in
+ // url.path. Tolerate trailing garbage or missing typecode value. Roughly:
+ // [filename] ;type=[typecode char] [trailing garbage]
+ static const SBuf middle(";type=");
+ const auto typeSpecStart = request->url.path().find(middle);
+ if (typeSpecStart != SBuf::npos) {
+ const auto fullPath = request->url.path();
+ const auto typecodePos = typeSpecStart + middle.length();
+ typecode = (typecodePos < fullPath.length()) ?
+ static_cast<char>(xtoupper(fullPath[typecodePos])) : '\0';
+ request->url.path(fullPath.substr(0, typeSpecStart));
}
int l = request->url.path().length();

@ -1,8 +1,8 @@
diff --git a/src/client_side.cc b/src/client_side.cc diff --git a/src/client_side.cc b/src/client_side.cc
index 4eb6976..63f1b66 100644 index f57f3f7..ab393e4 100644
--- a/src/client_side.cc --- a/src/client_side.cc
+++ b/src/client_side.cc +++ b/src/client_side.cc
@@ -957,7 +957,7 @@ ConnStateData::kick() @@ -906,7 +906,7 @@ ConnStateData::kick()
* We are done with the response, and we are either still receiving request * We are done with the response, and we are either still receiving request
* body (early response!) or have already stopped receiving anything. * body (early response!) or have already stopped receiving anything.
* *
@ -11,7 +11,7 @@ index 4eb6976..63f1b66 100644
* (XXX: but then we will call readNextRequest() which may succeed and * (XXX: but then we will call readNextRequest() which may succeed and
* execute a smuggled request as we are not done with the current request). * execute a smuggled request as we are not done with the current request).
* *
@@ -977,28 +977,12 @@ ConnStateData::kick() @@ -926,28 +926,12 @@ ConnStateData::kick()
* Attempt to parse a request from the request buffer. * Attempt to parse a request from the request buffer.
* If we've been fed a pipelined request it may already * If we've been fed a pipelined request it may already
* be in our read buffer. * be in our read buffer.
@ -42,8 +42,8 @@ index 4eb6976..63f1b66 100644
/** \par /** \par
* At this point we either have a parsed request (which we've * At this point we either have a parsed request (which we've
@@ -1935,16 +1919,11 @@ ConnStateData::receivedFirstByte() @@ -2058,16 +2042,11 @@ ConnStateData::receivedFirstByte()
resetReadTimeout(Config.Timeout.request); commSetConnTimeout(clientConnection, Config.Timeout.request, timeoutCall);
} }
-/** -/**
@ -63,7 +63,7 @@ index 4eb6976..63f1b66 100644
debugs(33, 5, HERE << clientConnection << ": attempting to parse"); debugs(33, 5, HERE << clientConnection << ": attempting to parse");
// Loop while we have read bytes that are not needed for producing the body // Loop while we have read bytes that are not needed for producing the body
@@ -1989,8 +1968,6 @@ ConnStateData::clientParseRequests() @@ -2116,8 +2095,6 @@ ConnStateData::clientParseRequests()
processParsedRequest(context); processParsedRequest(context);
@ -72,7 +72,7 @@ index 4eb6976..63f1b66 100644
if (context->mayUseConnection()) { if (context->mayUseConnection()) {
debugs(33, 3, HERE << "Not parsing new requests, as this request may need the connection"); debugs(33, 3, HERE << "Not parsing new requests, as this request may need the connection");
break; break;
@@ -2003,8 +1980,19 @@ ConnStateData::clientParseRequests() @@ -2130,8 +2107,19 @@ ConnStateData::clientParseRequests()
} }
} }
@ -94,16 +94,21 @@ index 4eb6976..63f1b66 100644
} }
void void
@@ -2021,18 +2009,7 @@ ConnStateData::afterClientRead() @@ -2148,23 +2136,7 @@ ConnStateData::afterClientRead()
if (pipeline.empty()) if (pipeline.empty())
fd_note(clientConnection->fd, "Reading next request"); fd_note(clientConnection->fd, "Reading next request");
- if (!clientParseRequests()) { - if (!clientParseRequests()) {
- if (!isOpen()) - if (!isOpen())
- return; - return;
- // We may get here if the client half-closed after sending a partial - /*
- // request. See doClientRead() and shouldCloseOnEof(). - * If the client here is half closed and we failed
- // XXX: This partially duplicates ConnStateData::kick(). - * 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)) { - if (pipeline.empty() && commIsHalfClosed(clientConnection->fd)) {
- debugs(33, 5, clientConnection << ": half-closed connection, no completed request parsed, connection closing."); - debugs(33, 5, clientConnection << ": half-closed connection, no completed request parsed, connection closing.");
- clientConnection->close(); - clientConnection->close();
@ -114,7 +119,7 @@ index 4eb6976..63f1b66 100644
if (!isOpen()) if (!isOpen())
return; return;
@@ -3789,7 +3766,7 @@ ConnStateData::notePinnedConnectionBecameIdle(PinnedIdleContext pic) @@ -3945,7 +3917,7 @@ ConnStateData::notePinnedConnectionBecameIdle(PinnedIdleContext pic)
startPinnedConnectionMonitoring(); startPinnedConnectionMonitoring();
if (pipeline.empty()) if (pipeline.empty())
@ -124,10 +129,10 @@ index 4eb6976..63f1b66 100644
/// Forward future client requests using the given server connection. /// Forward future client requests using the given server connection.
diff --git a/src/client_side.h b/src/client_side.h diff --git a/src/client_side.h b/src/client_side.h
index 2793673..7c8d86b 100644 index 9fe8463..dfb4d8e 100644
--- a/src/client_side.h --- a/src/client_side.h
+++ b/src/client_side.h +++ b/src/client_side.h
@@ -93,7 +93,6 @@ public: @@ -85,7 +85,6 @@ public:
virtual void doneWithControlMsg(); virtual void doneWithControlMsg();
/// Traffic parsing /// Traffic parsing
@ -135,16 +140,16 @@ index 2793673..7c8d86b 100644
void readNextRequest(); void readNextRequest();
/// try to make progress on a transaction or read more I/O /// try to make progress on a transaction or read more I/O
@@ -422,6 +421,7 @@ private: @@ -373,6 +372,7 @@ private:
virtual bool connFinishedWithConn(int size);
void checkLogging(); virtual void checkLogging();
+ void parseRequests(); + void parseRequests();
void clientAfterReadingRequests(); void clientAfterReadingRequests();
bool concurrentRequestQueueFilled() const; bool concurrentRequestQueueFilled() const;
diff --git a/src/tests/stub_client_side.cc b/src/tests/stub_client_side.cc diff --git a/src/tests/stub_client_side.cc b/src/tests/stub_client_side.cc
index acf61c4..b1d82bf 100644 index d7efb0f..655ed83 100644
--- a/src/tests/stub_client_side.cc --- a/src/tests/stub_client_side.cc
+++ b/src/tests/stub_client_side.cc +++ b/src/tests/stub_client_side.cc
@@ -14,7 +14,7 @@ @@ -14,7 +14,7 @@

@ -1,14 +1,14 @@
commit c54122584d175cf1d292b239a5b70f2d1aa77c3a commit c08948c8b831a2ba73c676b48aa11ba1b58cc542
Author: Tomas Korbar <tkorbar@redhat.com> Author: Tomas Korbar <tkorbar@redhat.com>
Date: Mon Dec 5 15:03:07 2022 +0100 Date: Thu Dec 8 11:03:08 2022 +0100
Backport adding IP_BIND_ADDRESS_NO_PORT flag to outgoing connections Backport adding IP_BIND_ADDRESS_NO_PORT flag to outgoing connections
diff --git a/src/comm.cc b/src/comm.cc diff --git a/src/comm.cc b/src/comm.cc
index b4818f3..b18d175 100644 index 0d5f34d..6811b54 100644
--- a/src/comm.cc --- a/src/comm.cc
+++ b/src/comm.cc +++ b/src/comm.cc
@@ -59,6 +59,7 @@ @@ -58,6 +58,7 @@
*/ */
static IOCB commHalfClosedReader; static IOCB commHalfClosedReader;
@ -16,7 +16,7 @@ index b4818f3..b18d175 100644
static void comm_init_opened(const Comm::ConnectionPointer &conn, const char *note, struct addrinfo *AI); static void comm_init_opened(const Comm::ConnectionPointer &conn, const char *note, struct addrinfo *AI);
static int comm_apply_flags(int new_socket, Ip::Address &addr, int flags, struct addrinfo *AI); static int comm_apply_flags(int new_socket, Ip::Address &addr, int flags, struct addrinfo *AI);
@@ -76,6 +77,7 @@ static EVH commHalfClosedCheck; @@ -75,6 +76,7 @@ static EVH commHalfClosedCheck;
static void commPlanHalfClosedCheck(); static void commPlanHalfClosedCheck();
static Comm::Flag commBind(int s, struct addrinfo &); static Comm::Flag commBind(int s, struct addrinfo &);
@ -24,7 +24,7 @@ index b4818f3..b18d175 100644
static void commSetReuseAddr(int); static void commSetReuseAddr(int);
static void commSetNoLinger(int); static void commSetNoLinger(int);
#ifdef TCP_NODELAY #ifdef TCP_NODELAY
@@ -202,6 +204,22 @@ comm_local_port(int fd) @@ -201,6 +203,22 @@ comm_local_port(int fd)
return F->local_addr.port(); return F->local_addr.port();
} }
@ -47,18 +47,18 @@ index b4818f3..b18d175 100644
static Comm::Flag static Comm::Flag
commBind(int s, struct addrinfo &inaddr) commBind(int s, struct addrinfo &inaddr)
{ {
@@ -228,6 +246,10 @@ comm_open(int sock_type, @@ -227,6 +245,10 @@ comm_open(int sock_type,
int flags, int flags,
const char *note) const char *note)
{ {
+ // assume zero-port callers do not need to know the assigned port right away + // assume zero-port callers do not need to know the assigned port right away
+ if (sock_type == SOCK_STREAM && addr.port() == 0 && ((flags & COMM_DOBIND) || !addr.isAnyAddr())) + if (sock_type == SOCK_STREAM && addr.port() == 0 && ((flags & COMM_DOBIND) || !addr.isAnyAddr()))
+ flags |= COMM_DOBIND_PORT_LATER; + flags |= COMM_DOBIND_PORT_LATER;
+ +
return comm_openex(sock_type, proto, addr, flags, note); return comm_openex(sock_type, proto, addr, flags, note);
} }
@@ -329,7 +351,7 @@ comm_set_transparent(int fd) @@ -328,7 +350,7 @@ comm_set_transparent(int fd)
* Create a socket. Default is blocking, stream (TCP) socket. IO_TYPE * Create a socket. Default is blocking, stream (TCP) socket. IO_TYPE
* is OR of flags specified in defines.h:COMM_* * is OR of flags specified in defines.h:COMM_*
*/ */
@ -67,10 +67,10 @@ index b4818f3..b18d175 100644
comm_openex(int sock_type, comm_openex(int sock_type,
int proto, int proto,
Ip::Address &addr, Ip::Address &addr,
@@ -488,6 +510,9 @@ comm_apply_flags(int new_socket, @@ -476,6 +498,9 @@ comm_apply_flags(int new_socket,
} if ( addr.isNoAddr() )
} debugs(5,0,"CRITICAL: Squid is attempting to bind() port " << addr << "!!");
#endif
+ if ((flags & COMM_DOBIND_PORT_LATER)) + if ((flags & COMM_DOBIND_PORT_LATER))
+ commSetBindAddressNoPort(new_socket); + commSetBindAddressNoPort(new_socket);
+ +
@ -78,7 +78,7 @@ index b4818f3..b18d175 100644
comm_close(new_socket); comm_close(new_socket);
return -1; return -1;
diff --git a/src/comm.h b/src/comm.h diff --git a/src/comm.h b/src/comm.h
index 5a1a7c2..a9f33db 100644 index c963e1c..9ff201d 100644
--- a/src/comm.h --- a/src/comm.h
+++ b/src/comm.h +++ b/src/comm.h
@@ -43,7 +43,6 @@ void comm_import_opened(const Comm::ConnectionPointer &, const char *note, struc @@ -43,7 +43,6 @@ void comm_import_opened(const Comm::ConnectionPointer &, const char *note, struc
@ -98,10 +98,10 @@ index 5a1a7c2..a9f33db 100644
int comm_udp_sendto(int sock, const Ip::Address &to, const void *buf, int buflen); int comm_udp_sendto(int sock, const Ip::Address &to, const void *buf, int buflen);
diff --git a/src/comm/ConnOpener.cc b/src/comm/ConnOpener.cc diff --git a/src/comm/ConnOpener.cc b/src/comm/ConnOpener.cc
index 19c1237..79fa2ed 100644 index 25a30e4..2082214 100644
--- a/src/comm/ConnOpener.cc --- a/src/comm/ConnOpener.cc
+++ b/src/comm/ConnOpener.cc +++ b/src/comm/ConnOpener.cc
@@ -285,7 +285,7 @@ Comm::ConnOpener::createFd() @@ -263,7 +263,7 @@ Comm::ConnOpener::createFd()
if (callback_ == NULL || callback_->canceled()) if (callback_ == NULL || callback_->canceled())
return false; return false;
@ -111,20 +111,20 @@ index 19c1237..79fa2ed 100644
sendAnswer(Comm::ERR_CONNECT, 0, "Comm::ConnOpener::createFd"); sendAnswer(Comm::ERR_CONNECT, 0, "Comm::ConnOpener::createFd");
return false; return false;
diff --git a/src/comm/Connection.h b/src/comm/Connection.h diff --git a/src/comm/Connection.h b/src/comm/Connection.h
index 40c2249..2641f4e 100644 index 4f2f23a..1e32c22 100644
--- a/src/comm/Connection.h --- a/src/comm/Connection.h
+++ b/src/comm/Connection.h +++ b/src/comm/Connection.h
@@ -52,6 +52,8 @@ namespace Comm @@ -47,6 +47,8 @@ namespace Comm
#define COMM_REUSEPORT 0x40 //< needs SO_REUSEPORT #define COMM_DOBIND 0x08 // requires a bind()
/// not registered with Comm and not owned by any connection-closing code #define COMM_TRANSPARENT 0x10 // arrived via TPROXY
#define COMM_ORPHANED 0x40 #define COMM_INTERCEPTION 0x20 // arrived via NAT
+/// Internal Comm optimization: Keep the source port unassigned until connect(2) +/// Internal Comm optimization: Keep the source port unassigned until connect(2)
+#define COMM_DOBIND_PORT_LATER 0x100 +#define COMM_DOBIND_PORT_LATER 0x100
/** /**
* Store data about the physical and logical attributes of a connection. * Store data about the physical and logical attributes of a connection.
diff --git a/src/ipc.cc b/src/ipc.cc diff --git a/src/ipc.cc b/src/ipc.cc
index 45cab52..42e11e6 100644 index e1d48fc..e92a27f 100644
--- a/src/ipc.cc --- a/src/ipc.cc
+++ b/src/ipc.cc +++ b/src/ipc.cc
@@ -95,12 +95,12 @@ ipcCreate(int type, const char *prog, const char *const args[], const char *name @@ -95,12 +95,12 @@ ipcCreate(int type, const char *prog, const char *const args[], const char *name
@ -143,10 +143,10 @@ index 45cab52..42e11e6 100644
local_addr, local_addr,
0, /* blocking */ 0, /* blocking */
diff --git a/src/tests/stub_comm.cc b/src/tests/stub_comm.cc diff --git a/src/tests/stub_comm.cc b/src/tests/stub_comm.cc
index a1d33d6..bf4bea6 100644 index 58f85e4..5381ab2 100644
--- a/src/tests/stub_comm.cc --- a/src/tests/stub_comm.cc
+++ b/src/tests/stub_comm.cc +++ b/src/tests/stub_comm.cc
@@ -48,7 +48,6 @@ int comm_open_uds(int sock_type, int proto, struct sockaddr_un* addr, int flags) @@ -46,7 +46,6 @@ int comm_open_uds(int sock_type, int proto, struct sockaddr_un* addr, int flags)
void comm_import_opened(const Comm::ConnectionPointer &, const char *note, struct addrinfo *AI) STUB void comm_import_opened(const Comm::ConnectionPointer &, const char *note, struct addrinfo *AI) STUB
int comm_open_listener(int sock_type, int proto, Ip::Address &addr, int flags, const char *note) STUB_RETVAL(-1) int comm_open_listener(int sock_type, int proto, Ip::Address &addr, int flags, const char *note) STUB_RETVAL(-1)
void comm_open_listener(int sock_type, int proto, Comm::ConnectionPointer &conn, const char *note) STUB void comm_open_listener(int sock_type, int proto, Comm::ConnectionPointer &conn, const char *note) STUB

@ -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-----

@ -1,68 +0,0 @@
From fc01451000eaa5592cd5afbd6aee14e53f7dd2c3 Mon Sep 17 00:00:00 2001
From: Amos Jeffries <amosjeffries@squid-cache.org>
Date: Sun, 18 Oct 2020 20:23:10 +1300
Subject: [PATCH] Update translations integration
* Add credits for es-mx translation moderator
* Use es-mx for default of all Spanish (Central America) texts
* Update translation related .am files
---
doc/manuals/language.am | 2 +-
errors/TRANSLATORS | 1 +
errors/aliases | 3 ++-
errors/language.am | 3 ++-
errors/template.am | 2 +-
5 files changed, 7 insertions(+), 4 deletions(-)
diff --git a/doc/manuals/language.am b/doc/manuals/language.am
index 7670c88380c..f03c4cf71b4 100644
--- a/doc/manuals/language.am
+++ b/doc/manuals/language.am
@@ -18,4 +18,4 @@ TRANSLATE_LANGUAGES = \
oc.lang \
pt.lang \
ro.lang \
- ru.lang
+ ru.lang
diff --git a/errors/aliases b/errors/aliases
index 36f17f4b80f..cf0116f297d 100644
--- a/errors/aliases
+++ b/errors/aliases
@@ -14,7 +14,8 @@ da da-dk
de de-at de-ch de-de de-li de-lu
el el-gr
en en-au en-bz en-ca en-cn en-gb en-ie en-in en-jm en-nz en-ph en-sg en-tt en-uk en-us en-za en-zw
-es es-ar es-bo es-cl es-co es-cr es-do es-ec es-es es-gt es-hn es-mx es-ni es-pa es-pe es-pr es-py es-sv es-us es-uy es-ve es-xl
+es es-ar es-bo es-cl es-cu es-co es-do es-ec es-es es-pe es-pr es-py es-us es-uy es-ve es-xl spq
+es-mx es-bz es-cr es-gt es-hn es-ni es-pa es-sv
et et-ee
fa fa-fa fa-ir
fi fi-fi
diff --git a/errors/language.am b/errors/language.am
index 12b1b2b3b43..029e8c1eb2f 100644
--- a/errors/language.am
+++ b/errors/language.am
@@ -17,6 +17,7 @@ TRANSLATE_LANGUAGES = \
de.lang \
el.lang \
en.lang \
+ es-mx.lang \
es.lang \
et.lang \
fa.lang \
@@ -51,4 +52,4 @@ TRANSLATE_LANGUAGES = \
uz.lang \
vi.lang \
zh-hans.lang \
- zh-hant.lang
+ zh-hant.lang
diff --git a/errors/template.am b/errors/template.am
index 6c12781e6f4..715c65aa22b 100644
--- a/errors/template.am
+++ b/errors/template.am
@@ -48,4 +48,4 @@ ERROR_TEMPLATES = \
templates/ERR_UNSUP_REQ \
templates/ERR_URN_RESOLVE \
templates/ERR_WRITE_ERROR \
- templates/ERR_ZERO_SIZE_OBJECT
+ templates/ERR_ZERO_SIZE_OBJECT

@ -1,185 +0,0 @@
diff --git a/src/ssl/support.cc b/src/ssl/support.cc
index 3ad135d..73912ce 100644
--- a/src/ssl/support.cc
+++ b/src/ssl/support.cc
@@ -557,7 +557,11 @@ Ssl::VerifyCallbackParameters::At(Security::Connection &sconn)
}
// "dup" function for SSL_get_ex_new_index("cert_err_check")
-#if SQUID_USE_CONST_CRYPTO_EX_DATA_DUP
+#if OPENSSL_VERSION_MAJOR >= 3
+static int
+ssl_dupAclChecklist(CRYPTO_EX_DATA *, const CRYPTO_EX_DATA *, void **,
+ int, long, void *)
+#elif SQUID_USE_CONST_CRYPTO_EX_DATA_DUP
static int
ssl_dupAclChecklist(CRYPTO_EX_DATA *, const CRYPTO_EX_DATA *, void *,
int, long, void *)
diff --git a/src/security/PeerOptions.cc b/src/security/PeerOptions.cc
index cf1d4ba..4346ba5 100644
--- a/src/security/PeerOptions.cc
+++ b/src/security/PeerOptions.cc
@@ -297,130 +297,130 @@ static struct ssl_option {
} ssl_options[] = {
-#if SSL_OP_NETSCAPE_REUSE_CIPHER_CHANGE_BUG
+#ifdef SSL_OP_NETSCAPE_REUSE_CIPHER_CHANGE_BUG
{
"NETSCAPE_REUSE_CIPHER_CHANGE_BUG", SSL_OP_NETSCAPE_REUSE_CIPHER_CHANGE_BUG
},
#endif
-#if SSL_OP_SSLREF2_REUSE_CERT_TYPE_BUG
+#ifdef SSL_OP_SSLREF2_REUSE_CERT_TYPE_BUG
{
"SSLREF2_REUSE_CERT_TYPE_BUG", SSL_OP_SSLREF2_REUSE_CERT_TYPE_BUG
},
#endif
-#if SSL_OP_MICROSOFT_BIG_SSLV3_BUFFER
+#ifdef SSL_OP_MICROSOFT_BIG_SSLV3_BUFFER
{
"MICROSOFT_BIG_SSLV3_BUFFER", SSL_OP_MICROSOFT_BIG_SSLV3_BUFFER
},
#endif
-#if SSL_OP_SSLEAY_080_CLIENT_DH_BUG
+#ifdef SSL_OP_SSLEAY_080_CLIENT_DH_BUG
{
"SSLEAY_080_CLIENT_DH_BUG", SSL_OP_SSLEAY_080_CLIENT_DH_BUG
},
#endif
-#if SSL_OP_TLS_D5_BUG
+#ifdef SSL_OP_TLS_D5_BUG
{
"TLS_D5_BUG", SSL_OP_TLS_D5_BUG
},
#endif
-#if SSL_OP_TLS_BLOCK_PADDING_BUG
+#ifdef SSL_OP_TLS_BLOCK_PADDING_BUG
{
"TLS_BLOCK_PADDING_BUG", SSL_OP_TLS_BLOCK_PADDING_BUG
},
#endif
-#if SSL_OP_TLS_ROLLBACK_BUG
+#ifdef SSL_OP_TLS_ROLLBACK_BUG
{
"TLS_ROLLBACK_BUG", SSL_OP_TLS_ROLLBACK_BUG
},
#endif
-#if SSL_OP_ALL
+#ifdef SSL_OP_ALL
{
"ALL", (long)SSL_OP_ALL
},
#endif
-#if SSL_OP_SINGLE_DH_USE
+#ifdef SSL_OP_SINGLE_DH_USE
{
"SINGLE_DH_USE", SSL_OP_SINGLE_DH_USE
},
#endif
-#if SSL_OP_EPHEMERAL_RSA
+#ifdef SSL_OP_EPHEMERAL_RSA
{
"EPHEMERAL_RSA", SSL_OP_EPHEMERAL_RSA
},
#endif
-#if SSL_OP_PKCS1_CHECK_1
+#ifdef SSL_OP_PKCS1_CHECK_1
{
"PKCS1_CHECK_1", SSL_OP_PKCS1_CHECK_1
},
#endif
-#if SSL_OP_PKCS1_CHECK_2
+#ifdef SSL_OP_PKCS1_CHECK_2
{
"PKCS1_CHECK_2", SSL_OP_PKCS1_CHECK_2
},
#endif
-#if SSL_OP_NETSCAPE_CA_DN_BUG
+#ifdef SSL_OP_NETSCAPE_CA_DN_BUG
{
"NETSCAPE_CA_DN_BUG", SSL_OP_NETSCAPE_CA_DN_BUG
},
#endif
-#if SSL_OP_NON_EXPORT_FIRST
+#ifdef SSL_OP_NON_EXPORT_FIRST
{
"NON_EXPORT_FIRST", SSL_OP_NON_EXPORT_FIRST
},
#endif
-#if SSL_OP_CIPHER_SERVER_PREFERENCE
+#ifdef SSL_OP_CIPHER_SERVER_PREFERENCE
{
"CIPHER_SERVER_PREFERENCE", SSL_OP_CIPHER_SERVER_PREFERENCE
},
#endif
-#if SSL_OP_NETSCAPE_DEMO_CIPHER_CHANGE_BUG
+#ifdef SSL_OP_NETSCAPE_DEMO_CIPHER_CHANGE_BUG
{
"NETSCAPE_DEMO_CIPHER_CHANGE_BUG", SSL_OP_NETSCAPE_DEMO_CIPHER_CHANGE_BUG
},
#endif
-#if SSL_OP_NO_SSLv3
+#ifdef SSL_OP_NO_SSLv3
{
"NO_SSLv3", SSL_OP_NO_SSLv3
},
#endif
-#if SSL_OP_NO_TLSv1
+#ifdef SSL_OP_NO_TLSv1
{
"NO_TLSv1", SSL_OP_NO_TLSv1
},
#else
{ "NO_TLSv1", 0 },
#endif
-#if SSL_OP_NO_TLSv1_1
+#ifdef SSL_OP_NO_TLSv1_1
{
"NO_TLSv1_1", SSL_OP_NO_TLSv1_1
},
#else
{ "NO_TLSv1_1", 0 },
#endif
-#if SSL_OP_NO_TLSv1_2
+#ifdef SSL_OP_NO_TLSv1_2
{
"NO_TLSv1_2", SSL_OP_NO_TLSv1_2
},
#else
{ "NO_TLSv1_2", 0 },
#endif
-#if SSL_OP_NO_TLSv1_3
+#ifdef SSL_OP_NO_TLSv1_3
{
"NO_TLSv1_3", SSL_OP_NO_TLSv1_3
},
#else
{ "NO_TLSv1_3", 0 },
#endif
-#if SSL_OP_NO_COMPRESSION
+#ifdef SSL_OP_NO_COMPRESSION
{
"No_Compression", SSL_OP_NO_COMPRESSION
},
#endif
-#if SSL_OP_NO_TICKET
+#ifdef SSL_OP_NO_TICKET
{
"NO_TICKET", SSL_OP_NO_TICKET
},
#endif
-#if SSL_OP_SINGLE_ECDH_USE
+#ifdef SSL_OP_SINGLE_ECDH_USE
{
"SINGLE_ECDH_USE", SSL_OP_SINGLE_ECDH_USE
},
@@ -512,7 +512,7 @@ Security::PeerOptions::parseOptions()
}
-#if SSL_OP_NO_SSLv2
+#ifdef SSL_OP_NO_SSLv2
// compliance with RFC 6176: Prohibiting Secure Sockets Layer (SSL) Version 2.0
op = op | SSL_OP_NO_SSLv2;
#endif

@ -1,24 +0,0 @@
diff --git a/src/tests/testStoreHashIndex.cc b/src/tests/testStoreHashIndex.cc
index 0564380..fcd60b9 100644
--- a/src/tests/testStoreHashIndex.cc
+++ b/src/tests/testStoreHashIndex.cc
@@ -102,6 +102,8 @@ void commonInit()
if (inited)
return;
+ inited = true;
+
Mem::Init();
Config.Store.avgObjectSize = 1024;
@@ -109,6 +111,10 @@ void commonInit()
Config.Store.objectsPerBucket = 20;
Config.Store.maxObjectSize = 2048;
+
+ Config.memShared.defaultTo(false);
+
+ Config.store_dir_select_algorithm = xstrdup("round-robin");
}
/* TODO make this a cbdata class */

@ -1,178 +0,0 @@
From 05f6af2f4c85cc99323cfff6149c3d74af661b6d Mon Sep 17 00:00:00 2001
From: Amos Jeffries <yadij@users.noreply.github.com>
Date: Fri, 13 Oct 2023 08:44:16 +0000
Subject: [PATCH] RFC 9112: Improve HTTP chunked encoding compliance (#1498)
---
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

@ -1,46 +0,0 @@
From c67bf049871a49e9871efe50b230a7f37b7039f6 Mon Sep 17 00:00:00 2001
From: Alex Rousskov <rousskov@measurement-factory.com>
Date: Thu, 25 May 2023 02:10:28 +0000
Subject: [PATCH] Fix userinfo percent-encoding (#1367)
%X expects an unsigned int, and that is what we were giving it. However,
to get to the correct unsigned int value from a (signed) char, one has
to cast to an unsigned char (or equivalent) first.
Broken since inception in commit 7b75100.
Also adjusted similar (commented out) ext_edirectory_userip_acl code.
---
src/acl/external/eDirectory_userip/ext_edirectory_userip_acl.cc | 2 +-
src/anyp/Uri.cc | 2 +-
2 files changed, 2 insertions(+), 2 deletions(-)
diff --git a/src/acl/external/eDirectory_userip/ext_edirectory_userip_acl.cc b/src/acl/external/eDirectory_userip/ext_edirectory_userip_acl.cc
index dbc20ae54..9028d1562 100644
--- a/src/acl/external/eDirectory_userip/ext_edirectory_userip_acl.cc
+++ b/src/acl/external/eDirectory_userip/ext_edirectory_userip_acl.cc
@@ -1612,7 +1612,7 @@ MainSafe(int argc, char **argv)
/* BINARY DEBUGGING *
local_printfx("while() -> bufa[%" PRIuSIZE "]: %s", k, bufa);
for (i = 0; i < k; ++i)
- local_printfx("%02X", bufa[i]);
+ local_printfx("%02X", static_cast<unsigned int>(static_cast<unsigned char>(bufa[i])));
local_printfx("\n");
* BINARY DEBUGGING */
/* Check for CRLF */
diff --git a/src/anyp/Uri.cc b/src/anyp/Uri.cc
index a6a5d5d9e..3d19188e9 100644
--- a/src/anyp/Uri.cc
+++ b/src/anyp/Uri.cc
@@ -70,7 +70,7 @@ AnyP::Uri::Encode(const SBuf &buf, const CharacterSet &ignore)
while (!tk.atEnd()) {
// TODO: Add Tokenizer::parseOne(void).
const auto ch = tk.remaining()[0];
- output.appendf("%%%02X", static_cast<unsigned int>(ch)); // TODO: Optimize using a table
+ output.appendf("%%%02X", static_cast<unsigned int>(static_cast<unsigned char>(ch))); // TODO: Optimize using a table
(void)tk.skip(ch);
if (tk.prefix(goodSection, ignore))
--
2.25.1

@ -1,30 +0,0 @@
commit 8fcff9c09824b18628f010d26a04247f6a6cbcb8
Author: Alex Rousskov <rousskov@measurement-factory.com>
Date: Sun Nov 12 09:33:20 2023 +0000
Do not update StoreEntry expiration after errorAppendEntry() (#1580)
errorAppendEntry() is responsible for setting entry expiration times,
which it does by calling StoreEntry::storeErrorResponse() that calls
StoreEntry::negativeCache().
This change was triggered by a vulnerability report by Joshua Rogers at
https://megamansec.github.io/Squid-Security-Audit/cache-uaf.html where
it was filed as "Use-After-Free in Cache Manager Errors". The reported
"use after free" vulnerability was unknowingly addressed by 2022 commit
1fa761a that removed excessively long "reentrant" store_client calls
responsible for the disappearance of the properly locked StoreEntry in
this (and probably other) contexts.
diff --git a/src/cache_manager.cc b/src/cache_manager.cc
index 61c7f65be..65bf22dd0 100644
--- a/src/cache_manager.cc
+++ b/src/cache_manager.cc
@@ -326,7 +326,6 @@ CacheManager::start(const Comm::ConnectionPointer &client, HttpRequest *request,
err->url = xstrdup(entry->url());
err->detailError(new ExceptionErrorDetail(Here().id()));
errorAppendEntry(entry, err);
- entry->expires = squid_curtime;
return;
}

@ -1,192 +0,0 @@
diff --git a/src/http.cc b/src/http.cc
index 98e3969..8b55bf3 100644
--- a/src/http.cc
+++ b/src/http.cc
@@ -54,6 +54,7 @@
#include "rfc1738.h"
#include "SquidConfig.h"
#include "SquidTime.h"
+#include "SquidMath.h"
#include "StatCounters.h"
#include "Store.h"
#include "StrList.h"
@@ -1235,18 +1236,26 @@ HttpStateData::readReply(const CommIoCbParams &io)
* Plus, it breaks our lame *HalfClosed() detection
*/
- Must(maybeMakeSpaceAvailable(true));
- CommIoCbParams rd(this); // will be expanded with ReadNow results
- rd.conn = io.conn;
- rd.size = entry->bytesWanted(Range<size_t>(0, inBuf.spaceSize()));
+ const auto moreDataPermission = canBufferMoreReplyBytes();
+ if (!moreDataPermission) {
+ abortTransaction("ready to read required data, but the read buffer is full and cannot be drained");
+ return;
+ }
+
+ const auto readSizeMax = maybeMakeSpaceAvailable(moreDataPermission.value());
+ // TODO: Move this logic inside maybeMakeSpaceAvailable():
+ const auto readSizeWanted = readSizeMax ? entry->bytesWanted(Range<size_t>(0, readSizeMax)) : 0;
- if (rd.size <= 0) {
+ if (readSizeWanted <= 0) {
assert(entry->mem_obj);
AsyncCall::Pointer nilCall;
entry->mem_obj->delayRead(DeferredRead(readDelayed, this, CommRead(io.conn, NULL, 0, nilCall)));
return;
}
+ CommIoCbParams rd(this); // will be expanded with ReadNow results
+ rd.conn = io.conn;
+ rd.size = readSizeWanted;
switch (Comm::ReadNow(rd, inBuf)) {
case Comm::INPROGRESS:
if (inBuf.isEmpty())
@@ -1617,8 +1626,10 @@ HttpStateData::maybeReadVirginBody()
if (!Comm::IsConnOpen(serverConnection) || fd_table[serverConnection->fd].closing())
return;
- if (!maybeMakeSpaceAvailable(false))
+ if (!canBufferMoreReplyBytes()) {
+ abortTransaction("more response bytes required, but the read buffer is full and cannot be drained");
return;
+ }
// XXX: get rid of the do_next_read flag
// check for the proper reasons preventing read(2)
@@ -1636,40 +1647,78 @@ HttpStateData::maybeReadVirginBody()
Comm::Read(serverConnection, call);
}
-bool
-HttpStateData::maybeMakeSpaceAvailable(bool doGrow)
+/// Desired inBuf capacity based on various capacity preferences/limits:
+/// * a smaller buffer may not hold enough for look-ahead header/body parsers;
+/// * a smaller buffer may result in inefficient tiny network reads;
+/// * a bigger buffer may waste memory;
+/// * a bigger buffer may exceed SBuf storage capabilities (SBuf::maxSize);
+size_t
+HttpStateData::calcReadBufferCapacityLimit() const
{
- // how much we are allowed to buffer
- const int limitBuffer = (flags.headers_parsed ? Config.readAheadGap : Config.maxReplyHeaderSize);
-
- if (limitBuffer < 0 || inBuf.length() >= (SBuf::size_type)limitBuffer) {
- // when buffer is at or over limit already
- debugs(11, 7, "will not read up to " << limitBuffer << ". buffer has (" << inBuf.length() << "/" << inBuf.spaceSize() << ") from " << serverConnection);
- debugs(11, DBG_DATA, "buffer has {" << inBuf << "}");
- // Process next response from buffer
- processReply();
- return false;
+ if (!flags.headers_parsed)
+ return Config.maxReplyHeaderSize;
+
+ // XXX: Our inBuf is not used to maintain the read-ahead gap, and using
+ // Config.readAheadGap like this creates huge read buffers for large
+ // read_ahead_gap values. TODO: Switch to using tcp_recv_bufsize as the
+ // primary read buffer capacity factor.
+ //
+ // TODO: Cannot reuse throwing NaturalCast() here. Consider removing
+ // .value() dereference in NaturalCast() or add/use NaturalCastOrMax().
+ const auto configurationPreferences = NaturalSum<size_t>(Config.readAheadGap).value_or(SBuf::maxSize);
+
+ // TODO: Honor TeChunkedParser look-ahead and trailer parsing requirements
+ // (when explicit configurationPreferences are set too low).
+
+ return std::min<size_t>(configurationPreferences, SBuf::maxSize);
+}
+
+/// The maximum number of virgin reply bytes we may buffer before we violate
+/// the currently configured response buffering limits.
+/// \retval std::nullopt means that no more virgin response bytes can be read
+/// \retval 0 means that more virgin response bytes may be read later
+/// \retval >0 is the number of bytes that can be read now (subject to other constraints)
+std::optional<size_t>
+HttpStateData::canBufferMoreReplyBytes() const
+{
+#if USE_ADAPTATION
+ // If we do not check this now, we may say the final "no" prematurely below
+ // because inBuf.length() will decrease as adaptation drains buffered bytes.
+ if (responseBodyBuffer) {
+ debugs(11, 3, "yes, but waiting for adaptation to drain read buffer");
+ return 0; // yes, we may be able to buffer more (but later)
+ }
+#endif
+
+ const auto maxCapacity = calcReadBufferCapacityLimit();
+ if (inBuf.length() >= maxCapacity) {
+ debugs(11, 3, "no, due to a full buffer: " << inBuf.length() << '/' << inBuf.spaceSize() << "; limit: " << maxCapacity);
+ return std::nullopt; // no, configuration prohibits buffering more
}
+ const auto maxReadSize = maxCapacity - inBuf.length(); // positive
+ debugs(11, 7, "yes, may read up to " << maxReadSize << " into " << inBuf.length() << '/' << inBuf.spaceSize());
+ return maxReadSize; // yes, can read up to this many bytes (subject to other constraints)
+}
+
+/// prepare read buffer for reading
+/// \return the maximum number of bytes the caller should attempt to read
+/// \retval 0 means that the caller should delay reading
+size_t
+HttpStateData::maybeMakeSpaceAvailable(const size_t maxReadSize)
+{
// how much we want to read
- const size_t read_size = calcBufferSpaceToReserve(inBuf.spaceSize(), (limitBuffer - inBuf.length()));
+ const size_t read_size = calcBufferSpaceToReserve(inBuf.spaceSize(), maxReadSize);
- if (!read_size) {
+ if (read_size < 2) {
debugs(11, 7, "will not read up to " << read_size << " into buffer (" << inBuf.length() << "/" << inBuf.spaceSize() << ") from " << serverConnection);
- return false;
+ return 0;
}
- // just report whether we could grow or not, do not actually do it
- if (doGrow)
- return (read_size >= 2);
-
// we may need to grow the buffer
inBuf.reserveSpace(read_size);
- debugs(11, 8, (!flags.do_next_read ? "will not" : "may") <<
- " read up to " << read_size << " bytes info buf(" << inBuf.length() << "/" << inBuf.spaceSize() <<
- ") from " << serverConnection);
-
- return (inBuf.spaceSize() >= 2); // only read if there is 1+ bytes of space available
+ debugs(11, 7, "may read up to " << read_size << " bytes info buffer (" << inBuf.length() << "/" << inBuf.spaceSize() << ") from " << serverConnection);
+ return read_size;
}
/// called after writing the very last request byte (body, last-chunk, etc)
diff --git a/src/http.h b/src/http.h
index e70cd7e..f7ed40d 100644
--- a/src/http.h
+++ b/src/http.h
@@ -15,6 +15,8 @@
#include "http/StateFlags.h"
#include "sbuf/SBuf.h"
+#include <optional>
+
class FwdState;
class HttpHeader;
class String;
@@ -112,16 +114,9 @@ private:
void abortTransaction(const char *reason) { abortAll(reason); } // abnormal termination
- /**
- * determine if read buffer can have space made available
- * for a read.
- *
- * \param grow whether to actually expand the buffer
- *
- * \return whether the buffer can be grown to provide space
- * regardless of whether the grow actually happened.
- */
- bool maybeMakeSpaceAvailable(bool grow);
+ size_t calcReadBufferCapacityLimit() const;
+ std::optional<size_t> canBufferMoreReplyBytes() const;
+ size_t maybeMakeSpaceAvailable(size_t maxReadSize);
// consuming request body
virtual void handleMoreRequestBodyAvailable();

@ -1,105 +0,0 @@
diff --git a/src/SquidString.h b/src/SquidString.h
index e36cd27..ea613ad 100644
--- a/src/SquidString.h
+++ b/src/SquidString.h
@@ -140,7 +140,16 @@ private:
size_type len_ = 0; /* current length */
- static const size_type SizeMax_ = 65535; ///< 64K limit protects some fixed-size buffers
+ /// An earlier 64KB limit was meant to protect some fixed-size buffers, but
+ /// (a) we do not know where those buffers are (or whether they still exist)
+ /// (b) too many String users unknowingly exceeded that limit and asserted.
+ /// We are now using a larger limit to reduce the number of (b) cases,
+ /// especially cases where "compact" lists of items grow 50% in size when we
+ /// convert them to canonical form. The new limit is selected to withstand
+ /// concatenation and ~50% expansion of two HTTP headers limited by default
+ /// request_header_max_size and reply_header_max_size settings.
+ static const size_type SizeMax_ = 3*64*1024 - 1;
+
/// returns true after increasing the first argument by extra if the sum does not exceed SizeMax_
static bool SafeAdd(size_type &base, size_type extra) { if (extra <= SizeMax_ && base <= SizeMax_ - extra) { base += extra; return true; } return false; }
diff --git a/src/cache_cf.cc b/src/cache_cf.cc
index cb746dc..c4ade96 100644
--- a/src/cache_cf.cc
+++ b/src/cache_cf.cc
@@ -950,6 +950,18 @@ configDoConfigure(void)
(uint32_t)Config.maxRequestBufferSize, (uint32_t)Config.maxRequestHeaderSize);
}
+ // Warn about the dangers of exceeding String limits when manipulating HTTP
+ // headers. Technically, we do not concatenate _requests_, so we could relax
+ // their check, but we keep the two checks the same for simplicity sake.
+ const auto safeRawHeaderValueSizeMax = (String::SizeMaxXXX()+1)/3;
+ // TODO: static_assert(safeRawHeaderValueSizeMax >= 64*1024); // no WARNINGs for default settings
+ if (Config.maxRequestHeaderSize > safeRawHeaderValueSizeMax)
+ debugs(3, DBG_CRITICAL, "WARNING: Increasing request_header_max_size beyond " << safeRawHeaderValueSizeMax <<
+ " bytes makes Squid more vulnerable to denial-of-service attacks; configured value: " << Config.maxRequestHeaderSize << " bytes");
+ if (Config.maxReplyHeaderSize > safeRawHeaderValueSizeMax)
+ debugs(3, DBG_CRITICAL, "WARNING: Increasing reply_header_max_size beyond " << safeRawHeaderValueSizeMax <<
+ " bytes makes Squid more vulnerable to denial-of-service attacks; configured value: " << Config.maxReplyHeaderSize << " bytes");
+
/*
* Disable client side request pipelining if client_persistent_connections OFF.
* Waste of resources queueing any pipelined requests when the first will close the connection.
diff --git a/src/cf.data.pre b/src/cf.data.pre
index 67a66b0..61a66f1 100644
--- a/src/cf.data.pre
+++ b/src/cf.data.pre
@@ -6489,11 +6489,14 @@ TYPE: b_size_t
DEFAULT: 64 KB
LOC: Config.maxRequestHeaderSize
DOC_START
- This specifies the maximum size for HTTP headers in a request.
- Request headers are usually relatively small (about 512 bytes).
- Placing a limit on the request header size will catch certain
- bugs (for example with persistent connections) and possibly
- buffer-overflow or denial-of-service attacks.
+ This directives limits the header size of a received HTTP request
+ (including request-line). Increasing this limit beyond its 64 KB default
+ exposes certain old Squid code to various denial-of-service attacks. This
+ limit also applies to received FTP commands.
+
+ This limit has no direct affect on Squid memory consumption.
+
+ Squid does not check this limit when sending requests.
DOC_END
NAME: reply_header_max_size
@@ -6502,11 +6505,14 @@ TYPE: b_size_t
DEFAULT: 64 KB
LOC: Config.maxReplyHeaderSize
DOC_START
- This specifies the maximum size for HTTP headers in a reply.
- Reply headers are usually relatively small (about 512 bytes).
- Placing a limit on the reply header size will catch certain
- bugs (for example with persistent connections) and possibly
- buffer-overflow or denial-of-service attacks.
+ This directives limits the header size of a received HTTP response
+ (including status-line). Increasing this limit beyond its 64 KB default
+ exposes certain old Squid code to various denial-of-service attacks. This
+ limit also applies to FTP command responses.
+
+ Squid also checks this limit when loading hit responses from disk cache.
+
+ Squid does not check this limit when sending responses.
DOC_END
NAME: request_body_max_size
diff --git a/src/http.cc b/src/http.cc
index 7c9ae70..98e3969 100644
--- a/src/http.cc
+++ b/src/http.cc
@@ -1926,8 +1926,9 @@ HttpStateData::httpBuildRequestHeader(HttpRequest * request,
String strFwd = hdr_in->getList(Http::HdrType::X_FORWARDED_FOR);
- // if we cannot double strFwd size, then it grew past 50% of the limit
- if (!strFwd.canGrowBy(strFwd.size())) {
+ // Detect unreasonably long header values. And paranoidly check String
+ // limits: a String ought to accommodate two reasonable-length values.
+ if (strFwd.size() > 32*1024 || !strFwd.canGrowBy(strFwd.size())) {
// There is probably a forwarding loop with Via detection disabled.
// If we do nothing, String will assert on overflow soon.
// TODO: Terminate all transactions with huge XFF?

@ -1,13 +0,0 @@
diff --git a/lib/libTrie/TrieNode.cc b/lib/libTrie/TrieNode.cc
index b379856..5d87279 100644
--- a/lib/libTrie/TrieNode.cc
+++ b/lib/libTrie/TrieNode.cc
@@ -32,7 +32,7 @@ TrieNode::add(char const *aString, size_t theLength, void *privatedata, TrieChar
/* We trust that privatedata and existant keys have already been checked */
if (theLength) {
- int index = transform ? (*transform)(*aString): *aString;
+ const unsigned char index = transform ? (*transform)(*aString): *aString;
if (!internal[index])
internal[index] = new TrieNode;

@ -1,367 +0,0 @@
From 8d0ee420a4d91ac7fd97316338f1e28b4b060cbf Mon Sep 17 00:00:00 2001
From: =?UTF-8?q?Lubo=C5=A1=20Uhliarik?= <luhliari@redhat.com>
Date: Thu, 10 Oct 2024 19:26:27 +0200
Subject: [PATCH 1/6] Ignore whitespace chars after chunk-size
Previously (before #1498 change), squid was accepting TE-chunked replies
with whitespaces after chunk-size and missing chunk-ext data. After
It turned out that replies with such whitespace chars are pretty
common and other webservers which can act as forward proxies (e.g.
nginx, httpd...) are accepting them.
This change will allow to proxy chunked responses from origin server,
which had whitespaces inbetween chunk-size and CRLF.
---
src/http/one/TeChunkedParser.cc | 1 +
1 file changed, 1 insertion(+)
diff --git a/src/http/one/TeChunkedParser.cc b/src/http/one/TeChunkedParser.cc
index 9cce10fdc91..04753395e16 100644
--- a/src/http/one/TeChunkedParser.cc
+++ b/src/http/one/TeChunkedParser.cc
@@ -125,6 +125,7 @@ Http::One::TeChunkedParser::parseChunkMetadataSuffix(Tokenizer &tok)
// Code becomes much simpler when incremental parsing functions throw on
// bad or insufficient input, like in the code below. TODO: Expand up.
try {
+ tok.skipAll(CharacterSet::WSP); // Some servers send SP/TAB after chunk-size
parseChunkExtensions(tok); // a possibly empty chunk-ext list
tok.skipRequired("CRLF after [chunk-ext]", Http1::CrLf());
buf_ = tok.remaining();
From 9c8d35f899035fa06021ab3fe6919f892c2f0c6b Mon Sep 17 00:00:00 2001
From: =?UTF-8?q?Lubo=C5=A1=20Uhliarik?= <luhliari@redhat.com>
Date: Fri, 11 Oct 2024 02:06:31 +0200
Subject: [PATCH 2/6] Added new argument to Http::One::ParseBws()
Depending on new wsp_only argument in ParseBws() it will be decided
which set of whitespaces characters will be parsed. If wsp_only is set
to true, only SP and HTAB chars will be parsed.
Also optimized number of ParseBws calls.
---
src/http/one/Parser.cc | 4 ++--
src/http/one/Parser.h | 3 ++-
src/http/one/TeChunkedParser.cc | 13 +++++++++----
src/http/one/TeChunkedParser.h | 2 +-
4 files changed, 14 insertions(+), 8 deletions(-)
diff --git a/src/http/one/Parser.cc b/src/http/one/Parser.cc
index b1908316a0b..01d7e3bc0e8 100644
--- a/src/http/one/Parser.cc
+++ b/src/http/one/Parser.cc
@@ -273,9 +273,9 @@ Http::One::ErrorLevel()
// BWS = *( SP / HTAB ) ; WhitespaceCharacters() may relax this RFC 7230 rule
void
-Http::One::ParseBws(Parser::Tokenizer &tok)
+Http::One::ParseBws(Parser::Tokenizer &tok, const bool wsp_only)
{
- const auto count = tok.skipAll(Parser::WhitespaceCharacters());
+ const auto count = tok.skipAll(wsp_only ? CharacterSet::WSP : Parser::WhitespaceCharacters());
if (tok.atEnd())
throw InsufficientInput(); // even if count is positive
diff --git a/src/http/one/Parser.h b/src/http/one/Parser.h
index d9a0ac8c273..08200371cd6 100644
--- a/src/http/one/Parser.h
+++ b/src/http/one/Parser.h
@@ -163,8 +163,9 @@ class Parser : public RefCountable
};
/// skips and, if needed, warns about RFC 7230 BWS ("bad" whitespace)
+/// \param wsp_only force skipping of whitespaces only, don't consider skipping relaxed delimeter chars
/// \throws InsufficientInput when the end of BWS cannot be confirmed
-void ParseBws(Parser::Tokenizer &);
+void ParseBws(Parser::Tokenizer &, const bool wsp_only = false);
/// the right debugs() level for logging HTTP violation messages
int ErrorLevel();
diff --git a/src/http/one/TeChunkedParser.cc b/src/http/one/TeChunkedParser.cc
index 04753395e16..41e1e5ddaea 100644
--- a/src/http/one/TeChunkedParser.cc
+++ b/src/http/one/TeChunkedParser.cc
@@ -125,8 +125,11 @@ Http::One::TeChunkedParser::parseChunkMetadataSuffix(Tokenizer &tok)
// Code becomes much simpler when incremental parsing functions throw on
// bad or insufficient input, like in the code below. TODO: Expand up.
try {
- tok.skipAll(CharacterSet::WSP); // Some servers send SP/TAB after chunk-size
- parseChunkExtensions(tok); // a possibly empty chunk-ext list
+ // A possibly empty chunk-ext list. If no chunk-ext has been found,
+ // try to skip trailing BWS, because some servers send "chunk-size BWS CRLF".
+ if (!parseChunkExtensions(tok))
+ ParseBws(tok, true);
+
tok.skipRequired("CRLF after [chunk-ext]", Http1::CrLf());
buf_ = tok.remaining();
parsingStage_ = theChunkSize ? Http1::HTTP_PARSE_CHUNK : Http1::HTTP_PARSE_MIME;
@@ -140,20 +143,22 @@ Http::One::TeChunkedParser::parseChunkMetadataSuffix(Tokenizer &tok)
/// Parses the chunk-ext list (RFC 9112 section 7.1.1:
/// chunk-ext = *( BWS ";" BWS chunk-ext-name [ BWS "=" BWS chunk-ext-val ] )
-void
+bool
Http::One::TeChunkedParser::parseChunkExtensions(Tokenizer &callerTok)
{
+ bool foundChunkExt = false;
do {
auto tok = callerTok;
ParseBws(tok); // Bug 4492: IBM_HTTP_Server sends SP after chunk-size
if (!tok.skip(';'))
- return; // reached the end of extensions (if any)
+ return foundChunkExt; // reached the end of extensions (if any)
parseOneChunkExtension(tok);
buf_ = tok.remaining(); // got one extension
callerTok = tok;
+ foundChunkExt = true;
} while (true);
}
diff --git a/src/http/one/TeChunkedParser.h b/src/http/one/TeChunkedParser.h
index 02eacd1bb89..8c5d4bb4cba 100644
--- a/src/http/one/TeChunkedParser.h
+++ b/src/http/one/TeChunkedParser.h
@@ -71,7 +71,7 @@ class TeChunkedParser : public Http1::Parser
private:
bool parseChunkSize(Tokenizer &tok);
bool parseChunkMetadataSuffix(Tokenizer &);
- void parseChunkExtensions(Tokenizer &);
+ bool parseChunkExtensions(Tokenizer &);
void parseOneChunkExtension(Tokenizer &);
bool parseChunkBody(Tokenizer &tok);
bool parseChunkEnd(Tokenizer &tok);
From 81e67f97f9c386bdd0bb4a5e182395c46adb70ad Mon Sep 17 00:00:00 2001
From: =?UTF-8?q?Lubo=C5=A1=20Uhliarik?= <luhliari@redhat.com>
Date: Fri, 11 Oct 2024 02:44:33 +0200
Subject: [PATCH 3/6] Fix typo in Parser.h
---
src/http/one/Parser.h | 2 +-
1 file changed, 1 insertion(+), 1 deletion(-)
diff --git a/src/http/one/Parser.h b/src/http/one/Parser.h
index 08200371cd6..3ef4c5f7752 100644
--- a/src/http/one/Parser.h
+++ b/src/http/one/Parser.h
@@ -163,7 +163,7 @@ class Parser : public RefCountable
};
/// skips and, if needed, warns about RFC 7230 BWS ("bad" whitespace)
-/// \param wsp_only force skipping of whitespaces only, don't consider skipping relaxed delimeter chars
+/// \param wsp_only force skipping of whitespaces only, don't consider skipping relaxed delimiter chars
/// \throws InsufficientInput when the end of BWS cannot be confirmed
void ParseBws(Parser::Tokenizer &, const bool wsp_only = false);
From a0d4fe1794e605f8299a5c118c758a807453f016 Mon Sep 17 00:00:00 2001
From: Alex Rousskov <rousskov@measurement-factory.com>
Date: Thu, 10 Oct 2024 22:39:42 -0400
Subject: [PATCH 4/6] Bug 5449 is a regression of Bug 4492!
Both bugs deal with "chunk-size SP+ CRLF" use cases. Bug 4492 had _two_
spaces after chunk-size, which answers one of the PR review questions:
Should we skip just one space? No, we should not.
The lines moved around in many commits, but I believe this regression
was introduced in commit 951013d0 because that commit stopped consuming
partially parsed chunk-ext sequences. That consumption was wrong, but it
had a positive side effect -- fixing Bug 4492...
---
src/http/one/TeChunkedParser.cc | 10 +++++-----
1 file changed, 5 insertions(+), 5 deletions(-)
diff --git a/src/http/one/TeChunkedParser.cc b/src/http/one/TeChunkedParser.cc
index 41e1e5ddaea..aa4a840fdcf 100644
--- a/src/http/one/TeChunkedParser.cc
+++ b/src/http/one/TeChunkedParser.cc
@@ -125,10 +125,10 @@ Http::One::TeChunkedParser::parseChunkMetadataSuffix(Tokenizer &tok)
// Code becomes much simpler when incremental parsing functions throw on
// bad or insufficient input, like in the code below. TODO: Expand up.
try {
- // A possibly empty chunk-ext list. If no chunk-ext has been found,
- // try to skip trailing BWS, because some servers send "chunk-size BWS CRLF".
- if (!parseChunkExtensions(tok))
- ParseBws(tok, true);
+ // Bug 4492: IBM_HTTP_Server sends SP after chunk-size
+ ParseBws(tok, true);
+
+ parseChunkExtensions(tok);
tok.skipRequired("CRLF after [chunk-ext]", Http1::CrLf());
buf_ = tok.remaining();
@@ -150,7 +150,7 @@ Http::One::TeChunkedParser::parseChunkExtensions(Tokenizer &callerTok)
do {
auto tok = callerTok;
- ParseBws(tok); // Bug 4492: IBM_HTTP_Server sends SP after chunk-size
+ ParseBws(tok);
if (!tok.skip(';'))
return foundChunkExt; // reached the end of extensions (if any)
From f837f5ff61301a17008f16ce1fb793c2abf19786 Mon Sep 17 00:00:00 2001
From: Alex Rousskov <rousskov@measurement-factory.com>
Date: Thu, 10 Oct 2024 23:06:42 -0400
Subject: [PATCH 5/6] fixup: Fewer conditionals/ifs and more explicit spelling
... to draw code reader attention when something unusual is going on.
---
src/http/one/Parser.cc | 22 ++++++++++++++++++----
src/http/one/Parser.h | 10 ++++++++--
src/http/one/TeChunkedParser.cc | 14 ++++++--------
src/http/one/TeChunkedParser.h | 2 +-
4 files changed, 33 insertions(+), 15 deletions(-)
diff --git a/src/http/one/Parser.cc b/src/http/one/Parser.cc
index 01d7e3bc0e8..d3937e5e96b 100644
--- a/src/http/one/Parser.cc
+++ b/src/http/one/Parser.cc
@@ -271,11 +271,12 @@ Http::One::ErrorLevel()
return Config.onoff.relaxed_header_parser < 0 ? DBG_IMPORTANT : 5;
}
-// BWS = *( SP / HTAB ) ; WhitespaceCharacters() may relax this RFC 7230 rule
-void
-Http::One::ParseBws(Parser::Tokenizer &tok, const bool wsp_only)
+/// common part of ParseBws() and ParseStrctBws()
+namespace Http::One {
+static void
+ParseBws_(Parser::Tokenizer &tok, const CharacterSet &bwsChars)
{
- const auto count = tok.skipAll(wsp_only ? CharacterSet::WSP : Parser::WhitespaceCharacters());
+ const auto count = tok.skipAll(bwsChars);
if (tok.atEnd())
throw InsufficientInput(); // even if count is positive
@@ -290,4 +291,17 @@ Http::One::ParseBws(Parser::Tokenizer &tok, const bool wsp_only)
// success: no more BWS characters expected
}
+} // namespace Http::One
+
+void
+Http::One::ParseBws(Parser::Tokenizer &tok)
+{
+ ParseBws_(tok, CharacterSet::WSP);
+}
+
+void
+Http::One::ParseStrictBws(Parser::Tokenizer &tok)
+{
+ ParseBws_(tok, Parser::WhitespaceCharacters());
+}
diff --git a/src/http/one/Parser.h b/src/http/one/Parser.h
index 3ef4c5f7752..49e399de546 100644
--- a/src/http/one/Parser.h
+++ b/src/http/one/Parser.h
@@ -163,9 +163,15 @@ class Parser : public RefCountable
};
/// skips and, if needed, warns about RFC 7230 BWS ("bad" whitespace)
-/// \param wsp_only force skipping of whitespaces only, don't consider skipping relaxed delimiter chars
/// \throws InsufficientInput when the end of BWS cannot be confirmed
-void ParseBws(Parser::Tokenizer &, const bool wsp_only = false);
+/// \sa WhitespaceCharacters() for the definition of BWS characters
+/// \sa ParseStrictBws() that avoids WhitespaceCharacters() uncertainties
+void ParseBws(Parser::Tokenizer &);
+
+/// Like ParseBws() but only skips CharacterSet::WSP characters. This variation
+/// must be used if the next element may start with CR or any other character
+/// from RelaxedDelimiterCharacters().
+void ParseStrictBws(Parser::Tokenizer &);
/// the right debugs() level for logging HTTP violation messages
int ErrorLevel();
diff --git a/src/http/one/TeChunkedParser.cc b/src/http/one/TeChunkedParser.cc
index aa4a840fdcf..859471b8c77 100644
--- a/src/http/one/TeChunkedParser.cc
+++ b/src/http/one/TeChunkedParser.cc
@@ -125,11 +125,11 @@ Http::One::TeChunkedParser::parseChunkMetadataSuffix(Tokenizer &tok)
// Code becomes much simpler when incremental parsing functions throw on
// bad or insufficient input, like in the code below. TODO: Expand up.
try {
- // Bug 4492: IBM_HTTP_Server sends SP after chunk-size
- ParseBws(tok, true);
-
- parseChunkExtensions(tok);
+ // Bug 4492: IBM_HTTP_Server sends SP after chunk-size.
+ // No ParseBws() here because it may consume CR required further below.
+ ParseStrictBws(tok);
+ parseChunkExtensions(tok); // a possibly empty chunk-ext list
tok.skipRequired("CRLF after [chunk-ext]", Http1::CrLf());
buf_ = tok.remaining();
parsingStage_ = theChunkSize ? Http1::HTTP_PARSE_CHUNK : Http1::HTTP_PARSE_MIME;
@@ -143,22 +143,20 @@ Http::One::TeChunkedParser::parseChunkMetadataSuffix(Tokenizer &tok)
/// Parses the chunk-ext list (RFC 9112 section 7.1.1:
/// chunk-ext = *( BWS ";" BWS chunk-ext-name [ BWS "=" BWS chunk-ext-val ] )
-bool
+void
Http::One::TeChunkedParser::parseChunkExtensions(Tokenizer &callerTok)
{
- bool foundChunkExt = false;
do {
auto tok = callerTok;
ParseBws(tok);
if (!tok.skip(';'))
- return foundChunkExt; // reached the end of extensions (if any)
+ return; // reached the end of extensions (if any)
parseOneChunkExtension(tok);
buf_ = tok.remaining(); // got one extension
callerTok = tok;
- foundChunkExt = true;
} while (true);
}
diff --git a/src/http/one/TeChunkedParser.h b/src/http/one/TeChunkedParser.h
index 8c5d4bb4cba..02eacd1bb89 100644
--- a/src/http/one/TeChunkedParser.h
+++ b/src/http/one/TeChunkedParser.h
@@ -71,7 +71,7 @@ class TeChunkedParser : public Http1::Parser
private:
bool parseChunkSize(Tokenizer &tok);
bool parseChunkMetadataSuffix(Tokenizer &);
- bool parseChunkExtensions(Tokenizer &);
+ void parseChunkExtensions(Tokenizer &);
void parseOneChunkExtension(Tokenizer &);
bool parseChunkBody(Tokenizer &tok);
bool parseChunkEnd(Tokenizer &tok);
From f79936a234e722adb2dd08f31cf6019d81ee712c Mon Sep 17 00:00:00 2001
From: Alex Rousskov <rousskov@measurement-factory.com>
Date: Thu, 10 Oct 2024 23:31:08 -0400
Subject: [PATCH 6/6] fixup: Deadly typo
---
src/http/one/Parser.cc | 4 ++--
1 file changed, 2 insertions(+), 2 deletions(-)
diff --git a/src/http/one/Parser.cc b/src/http/one/Parser.cc
index d3937e5e96b..7403a9163a2 100644
--- a/src/http/one/Parser.cc
+++ b/src/http/one/Parser.cc
@@ -296,12 +296,12 @@ ParseBws_(Parser::Tokenizer &tok, const CharacterSet &bwsChars)
void
Http::One::ParseBws(Parser::Tokenizer &tok)
{
- ParseBws_(tok, CharacterSet::WSP);
+ ParseBws_(tok, Parser::WhitespaceCharacters());
}
void
Http::One::ParseStrictBws(Parser::Tokenizer &tok)
{
- ParseBws_(tok, Parser::WhitespaceCharacters());
+ ParseBws_(tok, CharacterSet::WSP);
}

@ -1,113 +0,0 @@
From a0a9e6dc69d0c7b9ba237702b4c5020abc7ad1f8 Mon Sep 17 00:00:00 2001
From: Alex Rousskov <rousskov@measurement-factory.com>
Date: Sat, 4 Nov 2023 00:30:42 +0000
Subject: [PATCH] Bug 5154: Do not open IPv6 sockets when IPv6 is disabled
(#1567)
... but allow basic IPv6 manipulations like getSockAddr().
Address.cc:663 getAddrInfo() assertion failed: false
Squids receives IPv6 addresses from traffic, configuration, or
hard-coded constants even when ./configured with --disable-ipv6 or when
IPv6 support was automatically disabled at startup after failing IPv6
tests. To handle IPv6 correctly, such Squids must support basic IPv6
operations like recognizing an IPv6 address in a request-target or
reporting an unsolicited IPv6 DNS record. At least for now, such Squids
must also correctly parse configuration-related IPv6 addresses.
All those activities rely on various low-level operations like filling
addrinfo structure with IP address information. Since 2012 commit
c5fbbc7, Ip::Address::getAddrInfo() was failing for IPv6 addresses when
Ip::EnableIpv6 was falsy. That change correctly recognized[^1] the need
for such Squids to handle IPv6, but to support basic operations, we need
to reject IPv6 addresses at a higher level and without asserting.
That high-level rejection work is ongoing, but initial attempts have
exposed difficult problems that will take time to address. For now, we
just avoid the assertion while protecting IPv6-disabled Squid from
listening on or opening connections to IPv6 addresses. Since Squid
already expects (and usually correctly handles) socket opening failures,
disabling those operations is better than failing in low-level IP
manipulation code.
The overall IPv6 posture of IPv6-disabled Squids that lack http_access
or other rules to deny IPv6 requests will change: This fix exposes more
of IPv6-disabled Squid code to IPv6 addresses. It is possible that such
exposure will make some IPv6 resources inside Squid (e.g., a previously
cached HTTP response) accessible to external requests. Squids will not
open or accept IPv6 connections but may forward requests with raw IPv6
targets to IPv4 cache_peers. Whether these and similar behavior changes
are going to be permanent is open for debate, but even if they are
temporary, they are arguably better than the corresponding assertions.
These changes do not effect IPv6-enabled Squids.
The assertion in IPv6-disabled Squid was reported by Joshua Rogers at
https://megamansec.github.io/Squid-Security-Audit/ipv6-assert.html where
it was filed as "Assertion on IPv6 Host Requests with --disable-ipv6".
[^1]: https://bugs.squid-cache.org/show_bug.cgi?id=3593#c1
---
src/comm.cc | 6 ++++++
src/ip/Address.cc | 2 +-
src/ip/Intercept.cc | 8 ++++++++
3 files changed, 15 insertions(+), 1 deletion(-)
diff --git a/src/comm.cc b/src/comm.cc
index 4659955b011..271ba04d4da 100644
--- a/src/comm.cc
+++ b/src/comm.cc
@@ -344,6 +344,12 @@ comm_openex(int sock_type,
/* Create socket for accepting new connections. */
++ statCounter.syscalls.sock.sockets;
+ if (!Ip::EnableIpv6 && addr.isIPv6()) {
+ debugs(50, 2, "refusing to open an IPv6 socket when IPv6 support is disabled: " << addr);
+ errno = ENOTSUP;
+ return -1;
+ }
+
/* Setup the socket addrinfo details for use */
addr.getAddrInfo(AI);
AI->ai_socktype = sock_type;
diff --git a/src/ip/Address.cc b/src/ip/Address.cc
index b6f810bfc25..ae6db37da5e 100644
--- a/src/ip/Address.cc
+++ b/src/ip/Address.cc
@@ -623,7 +623,7 @@ Ip::Address::getAddrInfo(struct addrinfo *&dst, int force) const
&& dst->ai_protocol == 0)
dst->ai_protocol = IPPROTO_UDP;
- if (force == AF_INET6 || (force == AF_UNSPEC && Ip::EnableIpv6 && isIPv6()) ) {
+ if (force == AF_INET6 || (force == AF_UNSPEC && isIPv6()) ) {
dst->ai_addr = (struct sockaddr*)new sockaddr_in6;
memset(dst->ai_addr,0,sizeof(struct sockaddr_in6));
diff --git a/src/ip/Intercept.cc b/src/ip/Intercept.cc
index 1a5e2d15af1..a8522efaac0 100644
--- a/src/ip/Intercept.cc
+++ b/src/ip/Intercept.cc
@@ -15,6 +15,7 @@
#include "comm/Connection.h"
#include "fde.h"
#include "ip/Intercept.h"
+#include "ip/tools.h"
#include "src/tools.h"
#include <cerrno>
@@ -430,6 +431,13 @@ Ip::Intercept::ProbeForTproxy(Ip::Address &test)
debugs(3, 3, "Detect TPROXY support on port " << test);
+ if (!Ip::EnableIpv6 && test.isIPv6() && !test.setIPv4()) {
+ debugs(3, DBG_CRITICAL, "Cannot use TPROXY for " << test << " because IPv6 support is disabled");
+ if (doneSuid)
+ leave_suid();
+ return false;
+ }
+
int tos = 1;
int tmp_sock = -1;

@ -1,117 +0,0 @@
From 4d6dd3ddba5e850a42c86d8233735165a371c31c Mon Sep 17 00:00:00 2001
From: Alex Rousskov <rousskov@measurement-factory.com>
Date: Sun, 1 Sep 2024 00:39:34 +0000
Subject: [PATCH] Bug 5405: Large uploads fill request buffer and die (#1887)
maybeMakeSpaceAvailable: request buffer full
ReadNow: ... size 0, retval 0, errno 0
terminateAll: 1/1 after ERR_CLIENT_GONE/WITH_CLIENT
%Ss=TCP_MISS_ABORTED
This bug is triggered by a combination of the following two conditions:
* HTTP client upload fills Squid request buffer faster than it is
drained by an origin server, cache_peer, or REQMOD service. The buffer
accumulates 576 KB (default 512 KB client_request_buffer_max_size + 64
KB internal "pipe" buffer).
* The affected server or service consumes a few bytes after the critical
accumulation is reached. In other words, the bug cannot be triggered
if nothing is consumed after the first condition above is met.
Comm::ReadNow() must not be called with a full buffer: Related
FD_READ_METHOD() code cannot distinguish "received EOF" from "had no
buffer space" outcomes. Server::readSomeData() tried to prevent such
calls, but the corresponding check had two problems:
* The check had an unsigned integer underflow bug[^1] that made it
ineffective when inBuf length exceeded Config.maxRequestBufferSize.
That length could exceed the limit due to reconfiguration and when
inBuf space size first grew outside of maybeMakeSpaceAvailable()
protections (e.g., during an inBuf.c_str() call) and then got filled
with newly read data. That growth started happening after 2020 commit
1dfbca06 optimized SBuf::cow() to merge leading and trailing space.
Prior to that commit, Bug 5405 could probably only affect Squid
reconfigurations that lower client_request_buffer_max_size.
* The check was separated from the ReadNow() call it was meant to
protect. While ConnStateData was waiting for the socket to become
ready for reading, various asynchronous events could alter inBuf or
Config.maxRequestBufferSize.
This change fixes both problems.
This change also fixes Squid Bug 5214.
[^1]: That underflow bug was probably introduced in 2015 commit 4d1376d7
while trying to emulate the original "do not read less than two bytes"
ConnStateData::In::maybeMakeSpaceAvailable() condition. That condition
itself looks like a leftover from manual zero-terminated input buffer
days that ended with 2014 commit e7287625. It is now removed.
---
diff --git a/src/servers/Server.cc b/src/servers/Server.cc
index 70fd10b..dd20619 100644
--- a/src/servers/Server.cc
+++ b/src/servers/Server.cc
@@ -83,16 +83,25 @@ Server::maybeMakeSpaceAvailable()
debugs(33, 4, "request buffer full: client_request_buffer_max_size=" << Config.maxRequestBufferSize);
}
+bool
+Server::mayBufferMoreRequestBytes() const
+{
+ // TODO: Account for bodyPipe buffering as well.
+ if (inBuf.length() >= Config.maxRequestBufferSize) {
+ debugs(33, 4, "no: " << inBuf.length() << '-' << Config.maxRequestBufferSize << '=' << (inBuf.length() - Config.maxRequestBufferSize));
+ return false;
+ }
+ debugs(33, 7, "yes: " << Config.maxRequestBufferSize << '-' << inBuf.length() << '=' << (Config.maxRequestBufferSize - inBuf.length()));
+ return true;
+}
+
void
Server::readSomeData()
{
if (reading())
return;
- debugs(33, 4, clientConnection << ": reading request...");
-
- // we can only read if there is more than 1 byte of space free
- if (Config.maxRequestBufferSize - inBuf.length() < 2)
+ if (!mayBufferMoreRequestBytes())
return;
typedef CommCbMemFunT<Server, CommIoCbParams> Dialer;
@@ -123,7 +132,16 @@ Server::doClientRead(const CommIoCbParams &io)
* Plus, it breaks our lame *HalfClosed() detection
*/
+ // mayBufferMoreRequestBytes() was true during readSomeData(), but variables
+ // like Config.maxRequestBufferSize may have changed since that check
+ if (!mayBufferMoreRequestBytes()) {
+ // XXX: If we avoid Comm::ReadNow(), we should not Comm::Read() again
+ // when the wait is over; resume these doClientRead() checks instead.
+ return; // wait for noteMoreBodySpaceAvailable() or a similar inBuf draining event
+ }
maybeMakeSpaceAvailable();
+ Assure(inBuf.spaceSize());
+
CommIoCbParams rd(this); // will be expanded with ReadNow results
rd.conn = io.conn;
switch (Comm::ReadNow(rd, inBuf)) {
diff --git a/src/servers/Server.h b/src/servers/Server.h
index ef105f5..6e549b3 100644
--- a/src/servers/Server.h
+++ b/src/servers/Server.h
@@ -119,6 +119,9 @@ protected:
/// abort any pending transactions and prevent new ones (by closing)
virtual void terminateAll(const Error &, const LogTagsErrors &) = 0;
+ /// whether client_request_buffer_max_size allows inBuf.length() increase
+ bool mayBufferMoreRequestBytes() const;
+
void doClientRead(const CommIoCbParams &io);
void clientWriteDone(const CommIoCbParams &io);

@ -1,25 +0,0 @@
File: squid-5.5.tar.xz
Date: Wed 13 Apr 2022 08:45:42 UTC
Size: 2565732
MD5 : 83ccc2d86ca0966e3555a3b78f5afd14
SHA1: 42302bd9b8feff851a41420334cb8eaeab2806ab
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/jvOxfT4FAmJWjb4ACgkQzW2/jvOx
fT7t0A/9GjAdINfSP4gQyUr+Uvakz9O6fA9Jo3F30VafYimrSGm+VdGWntTsrOaP
VcsCdG3/Dvrhnqtu9+hwfKKQ61lmmUC7KVycx3whEUepQbZu5kd05csD7nwQ+AFe
7eJr0IwbRI4XdUhNW4AB52i/+hpHs/YSrSokumx5NVhwAUvT81TToUNzUjfKuXyy
U+w6GQ9kJbVW1UgFYZGZdJwCmD5Z7fNdUllKZhLj4I5GZ+5Zz5+lJP3ZBC6qavde
34hbpHbt+/lqz337eNoxwlyPNKPDiGIUEY9T4cdzA0BiLggTmlukDFErlYuHgCMX
BmQ9elJtdRaCD2YD+U1H9J+2wqt9O01gdyFU1V3RnNLZphgWur9X808rujuE46+Q
sxyV6SjeBh6Xs/I7wA9utX0pbVD+nLvna6Be49M1yAghBwTjiYN9fGC3ufj4St3k
PCvkTkBUOop3m4aBCRtUVO6w4Y/YmF71qAHIiSLe1i6xoztEDTVI0CA+vfrwwu2G
rFP5wuKsaYfBjkhQw4Jv6X30vnnOVqlxITGXcOnPXrHoD5KuYXv/Xsobqf8XsFdl
3qyXUe8lSI5idCg+Ajj9m0IqGWA50iFBs28Ca7GDacl9KApGn4O7kPLQY+7nN5cz
Nv3k8lYPh4KvRI1b2hcuoe3K63rEzty0e2vqG9zqxkpxOt20E/U=
=9xr/
-----END PGP SIGNATURE-----

@ -2,7 +2,6 @@
weekly weekly
rotate 5 rotate 5
compress compress
delaycompress
notifempty notifempty
missingok missingok
nocreate nocreate
@ -11,5 +10,7 @@
# Asks squid to reopen its logs. (logfile_rotate 0 is set in squid.conf) # Asks squid to reopen its logs. (logfile_rotate 0 is set in squid.conf)
# errors redirected to make it silent if squid is not running # errors redirected to make it silent if squid is not running
/usr/sbin/squid -k rotate 2>/dev/null /usr/sbin/squid -k rotate 2>/dev/null
# Wait a little to allow Squid to catch up before the logs is compressed
sleep 1
endscript endscript
} }

@ -2,6 +2,6 @@
case "$2" in case "$2" in
up|down|vpn-up|vpn-down) up|down|vpn-up|vpn-down)
/usr/bin/systemctl -q reload squid.service || : /bin/systemctl -q reload squid.service || :
;; ;;
esac esac

@ -1,5 +1,9 @@
# default squid options # default squid options
SQUID_OPTS="" SQUID_OPTS=""
# Time to wait for Squid to shut down when asked. Should not be necessary
# most of the time.
SQUID_SHUTDOWN_TIMEOUT=100
# default squid conf file # default squid conf file
SQUID_CONF="/etc/squid/squid.conf" SQUID_CONF="/etc/squid/squid.conf"

@ -1,2 +0,0 @@
g squid 23 -
u squid 23 "Squid proxy user" /var/spool/squid /sbin/nologin

@ -1,98 +1,78 @@
%define __perl_requires %{SOURCE98} %define __perl_requires %{SOURCE98}
Name: squid Name: squid
Version: 5.5 Version: 4.15
Release: 14%{?dist}.3 Release: 9%{?dist}
Summary: The Squid proxy caching server Summary: The Squid proxy caching server
Epoch: 7 Epoch: 7
# See CREDITS for breakdown of non GPLv2+ code # See CREDITS for breakdown of non GPLv2+ code
License: GPLv2+ and (LGPLv2+ and MIT and BSD and Public Domain) License: GPLv2+ and (LGPLv2+ and MIT and BSD and Public Domain)
URL: http://www.squid-cache.org URL: http://www.squid-cache.org
Source0: http://www.squid-cache.org/Versions/v4/squid-%{version}.tar.xz
Source0: http://www.squid-cache.org/Versions/v5/squid-%{version}.tar.xz Source1: http://www.squid-cache.org/Versions/v4/squid-%{version}.tar.xz.asc
Source1: http://www.squid-cache.org/Versions/v5/squid-%{version}.tar.xz.asc Source2: squid.logrotate
Source2: http://www.squid-cache.org/pgp.asc Source3: squid.sysconfig
Source3: squid.logrotate Source4: squid.pam
Source4: squid.sysconfig Source5: squid.nm
Source5: squid.pam Source6: squid.service
Source6: squid.nm Source7: cache_swap.sh
Source7: squid.service
Source8: cache_swap.sh
Source9: squid.sysusers
Source98: perl-requires-squid.sh Source98: perl-requires-squid.sh
# Upstream patches # Upstream patches
# Backported patches # Backported patches
# https://bugzilla.redhat.com/show_bug.cgi?id=2151188 Patch101: squid-4.15-ip-bind-address-no-port.patch
Patch101: squid-5.5-ip-bind-address-no-port.patch # https://bugzilla.redhat.com/show_bug.cgi?id=2072988
# Local patches # Local patches
# Applying upstream patches first makes it less likely that local patches # Applying upstream patches first makes it less likely that local patches
# will break upstream ones. # will break upstream ones.
Patch201: squid-4.0.11-config.patch Patch201: squid-4.11-config.patch
Patch202: squid-3.1.0.9-location.patch Patch202: squid-4.11-location.patch
Patch203: squid-3.0.STABLE1-perlpath.patch Patch203: squid-4.11-perlpath.patch
Patch204: squid-3.5.9-include-guards.patch Patch204: squid-4.11-include-guards.patch
# revert this upstream patch - https://bugzilla.redhat.com/show_bug.cgi?id=1936422 Patch205: squid-4.11-large-acl.patch
# workaround for #1934919 # https://bugzilla.redhat.com/show_bug.cgi?id=980511
Patch205: squid-5.0.5-symlink-lang-err.patch Patch206: squid-4.11-active-ftp.patch
# https://bugzilla.redhat.com/show_bug.cgi?id=1953505 Patch208: squid-4.11-convert-ipv4.patch
Patch206: squid-5.0.6-openssl3.patch # https://bugzilla.redhat.com/show_bug.cgi?id=2006121
# https://bugzilla.redhat.com/show_bug.cgi?id=1969322 Patch209: squid-4.15-ftp-filename-extraction.patch
Patch207: squid-5.0.6-active-ftp.patch # https://bugzilla.redhat.com/show_bug.cgi?id=2076717
# https://bugzilla.redhat.com/show_bug.cgi?id=1988122 Patch210: squid-4.15-halfclosed.patch
Patch208: squid-5.1-test-store-cppsuite.patch
# https://bugzilla.redhat.com/show_bug.cgi?id=2231827 # Security fixes
Patch209: squid-5.5-halfclosed.patch # https://bugzilla.redhat.com/show_bug.cgi?id=1941506
# https://issues.redhat.com/browse/RHEL-30352 Patch300: squid-4.15-CVE-2021-28116.patch
Patch210: squid-5.5-ipv6-crash.patch
# https://issues.redhat.com/browse/RHEL-12356
Patch211: squid-5.5-large-upload-buffer-dies.patch
# Security patches
# https://bugzilla.redhat.com/show_bug.cgi?id=2100721 # https://bugzilla.redhat.com/show_bug.cgi?id=2100721
Patch501: squid-5.5-CVE-2021-46784.patch Patch301: squid-4.15-CVE-2021-46784.patch
# https://bugzilla.redhat.com/show_bug.cgi?id=2129771 # https://bugzilla.redhat.com/show_bug.cgi?id=2129771
Patch502: squid-5.5-CVE-2022-41318.patch Patch302: squid-4.15-CVE-2022-41318.patch
# https://bugzilla.redhat.com/show_bug.cgi?id=2245910 # https://bugzilla.redhat.com/show_bug.cgi?id=2245910
Patch503: squid-5.5-CVE-2023-46846.patch # +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 # https://bugzilla.redhat.com/show_bug.cgi?id=2245916
Patch504: squid-5.5-CVE-2023-46847.patch Patch304: squid-4.15-CVE-2023-46847.patch
# https://bugzilla.redhat.com/show_bug.cgi?id=2245919 # https://issues.redhat.com/browse/RHEL-14792
Patch505: squid-5.5-CVE-2023-46848.patch Patch305: squid-4.15-CVE-2023-5824.patch
# https://issues.redhat.com/browse/RHEL-14802
Patch506: squid-5.5-CVE-2023-5824.patch
# https://bugzilla.redhat.com/show_bug.cgi?id=2248521 # https://bugzilla.redhat.com/show_bug.cgi?id=2248521
Patch507: squid-5.5-CVE-2023-46728.patch Patch306: squid-4.15-CVE-2023-46728.patch
# https://bugzilla.redhat.com/show_bug.cgi?id=2247567 # https://bugzilla.redhat.com/show_bug.cgi?id=2247567
Patch508: squid-5.5-CVE-2023-46724.patch Patch307: squid-4.15-CVE-2023-46724.patch
# https://bugzilla.redhat.com/show_bug.cgi?id=2252926 # https://bugzilla.redhat.com/show_bug.cgi?id=2252926
Patch509: squid-5.5-CVE-2023-49285.patch Patch308: squid-4.15-CVE-2023-49285.patch
# https://bugzilla.redhat.com/show_bug.cgi?id=2252923 # https://bugzilla.redhat.com/show_bug.cgi?id=2252923
Patch510: squid-5.5-CVE-2023-49286.patch Patch309: squid-4.15-CVE-2023-49286.patch
# https://bugzilla.redhat.com/show_bug.cgi?id=2254663 # https://bugzilla.redhat.com/show_bug.cgi?id=2254663
Patch511: squid-5.5-CVE-2023-50269.patch Patch310: squid-4.15-CVE-2023-50269.patch
# https://bugzilla.redhat.com/show_bug.cgi?id=2264309
Patch512: squid-5.5-CVE-2024-25617.patch
# https://bugzilla.redhat.com/show_bug.cgi?id=2268366
Patch513: squid-5.5-CVE-2024-25111.patch
# https://bugzilla.redhat.com/show_bug.cgi?id=2294353
Patch514: squid-5.5-CVE-2024-37894.patch
# https://bugzilla.redhat.com/show_bug.cgi?id=2260051
Patch515: squid-5.5-CVE-2024-23638.patch
# Regression caused by squid-5.5-CVE-2023-46846.patch
# Upstream PR: https://github.com/squid-cache/squid/pull/1914
Patch516: squid-5.5-ignore-wsp-after-chunk-size.patch
# cache_swap.sh
Requires: bash gawk
# for httpd conf file - cachemgr script alias
Requires: httpd-filesystem
Requires: bash >= 2.0
Requires(pre): shadow-utils
Requires(post): systemd
Requires(preun): systemd
Requires(postun): systemd
# squid_ldap_auth and other LDAP helpers require OpenLDAP # squid_ldap_auth and other LDAP helpers require OpenLDAP
BuildRequires: make
BuildRequires: openldap-devel BuildRequires: openldap-devel
# squid_pam_auth requires PAM development libs # squid_pam_auth requires PAM development libs
BuildRequires: pam-devel BuildRequires: pam-devel
@ -100,8 +80,10 @@ BuildRequires: pam-devel
BuildRequires: openssl-devel BuildRequires: openssl-devel
# squid_kerb_aut requires Kerberos development libs # squid_kerb_aut requires Kerberos development libs
BuildRequires: krb5-devel BuildRequires: krb5-devel
# time_quota requires TrivialDB # time_quota requires DB
BuildRequires: libtdb-devel BuildRequires: libdb-devel
# ESI support requires Expat & libxml2
BuildRequires: expat-devel libxml2-devel
# TPROXY requires libcap, and also increases security somewhat # TPROXY requires libcap, and also increases security somewhat
BuildRequires: libcap-devel BuildRequires: libcap-devel
# eCAP support # eCAP support
@ -112,20 +94,10 @@ BuildRequires: libtool libtool-ltdl-devel
BuildRequires: perl-generators BuildRequires: perl-generators
# For test suite # For test suite
BuildRequires: pkgconfig(cppunit) BuildRequires: pkgconfig(cppunit)
# For verifying downloded src tarball BuildRequires: autoconf
BuildRequires: gnupg2
# for _tmpfilesdir and _unitdir macro
# see https://docs.fedoraproject.org/en-US/packaging-guidelines/Systemd/#_packaging
BuildRequires: systemd-rpm-macros
# systemd notify # systemd notify
BuildRequires: systemd-devel BuildRequires: systemd-devel
%{?systemd_requires}
%{?sysusers_requires_compat}
# Old NetworkManager expects the dispatcher scripts in a different place
Conflicts: NetworkManager < 1.20
%description %description
Squid is a high-performance proxy caching server for Web clients, Squid is a high-performance proxy caching server for Web clients,
supporting FTP, gopher, and HTTP data objects. Unlike traditional supporting FTP, gopher, and HTTP data objects. Unlike traditional
@ -139,7 +111,6 @@ lookup program (dnsserver), a program for retrieving FTP data
(ftpget), and some management and client tools. (ftpget), and some management and client tools.
%prep %prep
%{gpgverify} --keyring='%{SOURCE2}' --signature='%{SOURCE1}' --data='%{SOURCE0}'
%setup -q %setup -q
# Upstream patches # Upstream patches
@ -151,31 +122,25 @@ lookup program (dnsserver), a program for retrieving FTP data
%patch201 -p1 -b .config %patch201 -p1 -b .config
%patch202 -p1 -b .location %patch202 -p1 -b .location
%patch203 -p1 -b .perlpath %patch203 -p1 -b .perlpath
%patch204 -p0 -b .include-guards %patch204 -p1 -b .include-guards
%patch205 -p1 -R -b .symlink-lang-err %patch205 -p1 -b .large_acl
%patch206 -p1 -b .openssl3 %patch206 -p1 -b .active-ftp
%patch207 -p1 -b .active-ftp %patch208 -p1 -b .convert-ipv4
%patch208 -p1 -b .test-store-cpp %patch209 -p1 -b .ftp-fn-extraction
%patch209 -p1 -b .halfclosed %patch210 -p1 -b .halfclosed
%patch210 -p1 -b .ipv6-crash
%patch211 -p1 -b .large-upload-buffer-dies # Security patches
%patch300 -p1 -b .CVE-2021-28116
%patch501 -p1 -b .CVE-2021-46784 %patch301 -p1 -b .CVE-2021-46784
%patch502 -p1 -b .CVE-2022-41318 %patch302 -p1 -b .CVE-2022-41318
%patch503 -p1 -b .CVE-2023-46846 %patch303 -p1 -b .CVE-2023-46846
%patch504 -p1 -b .CVE-2023-46847 %patch304 -p1 -b .CVE-2023-46847
%patch505 -p1 -b .CVE-2023-46848 %patch305 -p1 -b .CVE-2023-5824
%patch506 -p1 -b .CVE-2023-5824 %patch306 -p1 -b .CVE-2023-46728
%patch507 -p1 -b .CVE-2023-46728 %patch307 -p1 -b .CVE-2023-46724
%patch508 -p1 -b .CVE-2023-46724 %patch308 -p1 -b .CVE-2023-49285
%patch509 -p1 -b .CVE-2023-49285 %patch309 -p1 -b .CVE-2023-49286
%patch510 -p1 -b .CVE-2023-49286 %patch310 -p1 -b .CVE-2023-50269
%patch511 -p1 -b .CVE-2023-50269
%patch512 -p1 -b .CVE-2024-25617
%patch513 -p1 -b .CVE-2024-25111
%patch514 -p1 -b .CVE-2024-37894
%patch515 -p1 -b .CVE-2024-23638
%patch516 -p1 -b .ignore-wsp-chunk-sz
# https://bugzilla.redhat.com/show_bug.cgi?id=1679526 # https://bugzilla.redhat.com/show_bug.cgi?id=1679526
@ -183,6 +148,8 @@ lookup program (dnsserver), a program for retrieving FTP data
sed -i 's|@SYSCONFDIR@/squid.conf.documented|%{_pkgdocdir}/squid.conf.documented|' src/squid.8.in sed -i 's|@SYSCONFDIR@/squid.conf.documented|%{_pkgdocdir}/squid.conf.documented|' src/squid.8.in
%build %build
# cppunit-config patch changes configure.ac
autoconf
# NIS helper has been removed because of the following bug # NIS helper has been removed because of the following bug
# https://bugzilla.redhat.com/show_bug.cgi?id=1531540 # https://bugzilla.redhat.com/show_bug.cgi?id=1531540
@ -191,7 +158,7 @@ sed -i 's|@SYSCONFDIR@/squid.conf.documented|%{_pkgdocdir}/squid.conf.documented
--datadir=%{_datadir}/squid \ --datadir=%{_datadir}/squid \
--sysconfdir=%{_sysconfdir}/squid \ --sysconfdir=%{_sysconfdir}/squid \
--with-logdir='%{_localstatedir}/log/squid' \ --with-logdir='%{_localstatedir}/log/squid' \
--with-pidfile='/run/squid.pid' \ --with-pidfile='%{_localstatedir}/run/squid.pid' \
--disable-dependency-tracking \ --disable-dependency-tracking \
--enable-eui \ --enable-eui \
--enable-follow-x-forwarded-for \ --enable-follow-x-forwarded-for \
@ -219,7 +186,7 @@ sed -i 's|@SYSCONFDIR@/squid.conf.documented|%{_pkgdocdir}/squid.conf.documented
--enable-storeio="aufs,diskd,ufs,rock" \ --enable-storeio="aufs,diskd,ufs,rock" \
--enable-diskio \ --enable-diskio \
--enable-wccpv2 \ --enable-wccpv2 \
--disable-esi \ --enable-esi \
--enable-ecap \ --enable-ecap \
--with-aio \ --with-aio \
--with-default-user="squid" \ --with-default-user="squid" \
@ -228,14 +195,8 @@ sed -i 's|@SYSCONFDIR@/squid.conf.documented|%{_pkgdocdir}/squid.conf.documented
--with-pthreads \ --with-pthreads \
--disable-arch-native \ --disable-arch-native \
--disable-security-cert-validators \ --disable-security-cert-validators \
--disable-strict-error-checking \
--with-swapdir=%{_localstatedir}/spool/squid --with-swapdir=%{_localstatedir}/spool/squid
# workaround to build squid v5
mkdir -p src/icmp/tests
mkdir -p tools/squidclient/tests
mkdir -p tools/tests
%make_build %make_build
%check %check
@ -263,20 +224,22 @@ mkdir -p $RPM_BUILD_ROOT%{_sysconfdir}/logrotate.d
mkdir -p $RPM_BUILD_ROOT%{_sysconfdir}/sysconfig mkdir -p $RPM_BUILD_ROOT%{_sysconfdir}/sysconfig
mkdir -p $RPM_BUILD_ROOT%{_sysconfdir}/pam.d mkdir -p $RPM_BUILD_ROOT%{_sysconfdir}/pam.d
mkdir -p $RPM_BUILD_ROOT%{_sysconfdir}/httpd/conf.d/ mkdir -p $RPM_BUILD_ROOT%{_sysconfdir}/httpd/conf.d/
mkdir -p $RPM_BUILD_ROOT%{_prefix}/lib/NetworkManager/dispatcher.d mkdir -p $RPM_BUILD_ROOT%{_sysconfdir}/NetworkManager/dispatcher.d
mkdir -p $RPM_BUILD_ROOT%{_unitdir} mkdir -p $RPM_BUILD_ROOT%{_unitdir}
mkdir -p $RPM_BUILD_ROOT%{_libexecdir}/squid mkdir -p $RPM_BUILD_ROOT%{_libexecdir}/squid
install -m 644 %{SOURCE3} $RPM_BUILD_ROOT%{_sysconfdir}/logrotate.d/squid install -m 644 %{SOURCE2} $RPM_BUILD_ROOT%{_sysconfdir}/logrotate.d/squid
install -m 644 %{SOURCE4} $RPM_BUILD_ROOT%{_sysconfdir}/sysconfig/squid install -m 644 %{SOURCE3} $RPM_BUILD_ROOT%{_sysconfdir}/sysconfig/squid
install -m 644 %{SOURCE5} $RPM_BUILD_ROOT%{_sysconfdir}/pam.d/squid install -m 644 %{SOURCE4} $RPM_BUILD_ROOT%{_sysconfdir}/pam.d/squid
install -m 644 %{SOURCE7} $RPM_BUILD_ROOT%{_unitdir} install -m 644 %{SOURCE6} $RPM_BUILD_ROOT%{_unitdir}
install -m 755 %{SOURCE8} $RPM_BUILD_ROOT%{_libexecdir}/squid install -m 755 %{SOURCE7} $RPM_BUILD_ROOT%{_libexecdir}/squid
install -m 644 $RPM_BUILD_ROOT/squid.httpd.tmp $RPM_BUILD_ROOT%{_sysconfdir}/httpd/conf.d/squid.conf install -m 644 $RPM_BUILD_ROOT/squid.httpd.tmp $RPM_BUILD_ROOT%{_sysconfdir}/httpd/conf.d/squid.conf
install -m 755 %{SOURCE6} $RPM_BUILD_ROOT%{_prefix}/lib/NetworkManager/dispatcher.d/20-squid install -m 644 %{SOURCE5} $RPM_BUILD_ROOT%{_sysconfdir}/NetworkManager/dispatcher.d/20-squid
mkdir -p $RPM_BUILD_ROOT%{_localstatedir}/log/squid mkdir -p $RPM_BUILD_ROOT%{_localstatedir}/log/squid
mkdir -p $RPM_BUILD_ROOT%{_localstatedir}/spool/squid mkdir -p $RPM_BUILD_ROOT%{_localstatedir}/spool/squid
mkdir -p $RPM_BUILD_ROOT/run/squid mkdir -p $RPM_BUILD_ROOT%{_localstatedir}/run/squid
chmod 644 contrib/url-normalizer.pl contrib/user-agents.pl chmod 644 contrib/url-normalizer.pl contrib/user-agents.pl
iconv -f ISO88591 -t UTF8 ChangeLog -o ChangeLog.tmp
mv -f ChangeLog.tmp ChangeLog
# install /usr/lib/tmpfiles.d/squid.conf # install /usr/lib/tmpfiles.d/squid.conf
mkdir -p ${RPM_BUILD_ROOT}%{_tmpfilesdir} mkdir -p ${RPM_BUILD_ROOT}%{_tmpfilesdir}
@ -294,12 +257,11 @@ mv $RPM_BUILD_ROOT/usr/share/squid/mib.txt $RPM_BUILD_ROOT/usr/share/snmp/mibs/S
rm -f $RPM_BUILD_ROOT%{_sysconfdir}/squid/squid.conf.documented rm -f $RPM_BUILD_ROOT%{_sysconfdir}/squid/squid.conf.documented
# remove unpackaged files from the buildroot # remove unpackaged files from the buildroot
rm -f $RPM_BUILD_ROOT%{_bindir}/{RunAccel,RunCache}
rm -f $RPM_BUILD_ROOT/squid.httpd.tmp rm -f $RPM_BUILD_ROOT/squid.httpd.tmp
# sysusers.d
install -p -D -m 0644 %{SOURCE9} %{buildroot}%{_sysusersdir}/squid.conf
%files %files
%defattr(-,root,root,-)
%license COPYING %license COPYING
%doc CONTRIBUTORS README ChangeLog QUICKSTART src/squid.conf.documented %doc CONTRIBUTORS README ChangeLog QUICKSTART src/squid.conf.documented
%doc contrib/url-normalizer.pl contrib/user-agents.pl %doc contrib/url-normalizer.pl contrib/user-agents.pl
@ -311,7 +273,7 @@ install -p -D -m 0644 %{SOURCE9} %{buildroot}%{_sysusersdir}/squid.conf
%attr(755,root,root) %dir %{_libdir}/squid %attr(755,root,root) %dir %{_libdir}/squid
%attr(770,squid,root) %dir %{_localstatedir}/log/squid %attr(770,squid,root) %dir %{_localstatedir}/log/squid
%attr(750,squid,squid) %dir %{_localstatedir}/spool/squid %attr(750,squid,squid) %dir %{_localstatedir}/spool/squid
%attr(755,squid,squid) %dir /run/squid %attr(755,squid,squid) %dir %{_localstatedir}/run/squid
%config(noreplace) %attr(644,root,root) %{_sysconfdir}/httpd/conf.d/squid.conf %config(noreplace) %attr(644,root,root) %{_sysconfdir}/httpd/conf.d/squid.conf
%config(noreplace) %attr(640,root,squid) %{_sysconfdir}/squid/squid.conf %config(noreplace) %attr(640,root,squid) %{_sysconfdir}/squid/squid.conf
@ -329,7 +291,7 @@ install -p -D -m 0644 %{SOURCE9} %{buildroot}%{_sysusersdir}/squid.conf
%dir %{_datadir}/squid %dir %{_datadir}/squid
%attr(-,root,root) %{_datadir}/squid/errors %attr(-,root,root) %{_datadir}/squid/errors
%{_prefix}/lib/NetworkManager %attr(755,root,root) %{_sysconfdir}/NetworkManager/dispatcher.d/20-squid
%{_datadir}/squid/icons %{_datadir}/squid/icons
%{_sbindir}/squid %{_sbindir}/squid
%{_bindir}/squidclient %{_bindir}/squidclient
@ -339,10 +301,15 @@ install -p -D -m 0644 %{SOURCE9} %{buildroot}%{_sysusersdir}/squid.conf
%{_libdir}/squid/* %{_libdir}/squid/*
%{_datadir}/snmp/mibs/SQUID-MIB.txt %{_datadir}/snmp/mibs/SQUID-MIB.txt
%{_tmpfilesdir}/squid.conf %{_tmpfilesdir}/squid.conf
%{_sysusersdir}/squid.conf
%pre %pre
%sysusers_create_compat %{SOURCE9} if ! getent group squid >/dev/null 2>&1; then
/usr/sbin/groupadd -g 23 squid
fi
if ! getent passwd squid >/dev/null 2>&1 ; then
/usr/sbin/useradd -g 23 -u 23 -d /var/spool/squid -r -s /sbin/nologin squid >/dev/null 2>&1 || exit 1
fi
for i in /var/log/squid /var/spool/squid ; do for i in /var/log/squid /var/spool/squid ; do
if [ -d $i ] ; then if [ -d $i ] ; then
@ -355,18 +322,6 @@ done
exit 0 exit 0
%pretrans -p <lua> %pretrans -p <lua>
-- temporarilly commented until https://bugzilla.redhat.com/show_bug.cgi?id=1936422 is resolved
--
-- previously /usr/share/squid/errors/es-mx was symlink, now it is directory since squid v5
-- see https://docs.fedoraproject.org/en-US/packaging-guidelines/Directory_Replacement/
-- Define the path to the symlink being replaced below.
--
-- path = "/usr/share/squid/errors/es-mx"
-- st = posix.stat(path)
-- if st and st.type == "link" then
-- os.remove(path)
-- end
-- Due to a bug #447156 -- Due to a bug #447156
paths = {"/usr/share/squid/errors/zh-cn", "/usr/share/squid/errors/zh-tw"} paths = {"/usr/share/squid/errors/zh-cn", "/usr/share/squid/errors/zh-tw"}
for key,path in ipairs(paths) for key,path in ipairs(paths)
@ -403,252 +358,166 @@ fi
%changelog %changelog
* Thu Nov 07 2024 Luboš Uhliarik <luhliari@redhat.com> - 7:5.5-14.3 * Wed Apr 03 2024 MSVSphere Packaging Team <packager@msvsphere-os.ru> - 7:4.15-9
- Disable ESI support - Rebuilt for MSVSphere 8.10 beta
- Resolves: RHEL-65076 - CVE-2024-45802 squid: Denial of Service processing ESI
response content * Fri Feb 02 2024 Luboš Uhliarik <luhliari@redhat.com> - 7:4.15-9
- Resolves: RHEL-19552 - squid:4/squid: denial of service in HTTP request
* Wed Oct 23 2024 Luboš Uhliarik <luhliari@redhat.com> - 7:5.5-14.2
- Resolves: RHEL-64425 TCP_MISS_ABORTED/100 erros when uploading
* Mon Oct 14 2024 Luboš Uhliarik <luhliari@redhat.com> - 7:5.5-14.1
- Resolves: RHEL-62332 - (Regression) Transfer-encoding:chunked data is not sent
to the client in its complementary
* Mon Jul 01 2024 Luboš Uhliarik <luhliari@redhat.com> - 7:5.5-14
- Resolves: RHEL-45057 - squid: Out-of-bounds write error may lead to Denial of
Service (CVE-2024-37894)
- Resolves: RHEL-22594 - squid: vulnerable to a Denial of Service attack against
Cache Manager error responses (CVE-2024-23638)
* Thu May 09 2024 Luboš Uhliarik <luhliari@redhat.com> - 7:5.5-13
- Resolves: RHEL-30352 - squid v5 crashes with SIGABRT when ipv6 is disabled
at kernel level but it is asked to connect to an ipv6 address by a client
* Tue Mar 19 2024 Luboš Uhliarik <luhliari@redhat.com> - 7:5.5-12
- Resolves: RHEL-28530 - squid: Denial of Service in HTTP Chunked
Decoding (CVE-2024-25111)
- Resolves: RHEL-26092 - squid: denial of service in HTTP header
parser (CVE-2024-25617)
* Fri Feb 02 2024 Luboš Uhliarik <luhliari@redhat.com> - 7:5.5-10
- Resolves: RHEL-19556 - squid: denial of service in HTTP request
parsing (CVE-2023-50269) parsing (CVE-2023-50269)
* Thu Feb 01 2024 Luboš Uhliarik <luhliari@redhat.com> - 7:5.5-9 * Fri Feb 02 2024 Luboš Uhliarik <luhliari@redhat.com> - 7:4.15-8
- Resolves: RHEL-18354 - squid: Buffer over-read in the HTTP Message processing - Resolves: RHEL-18351 - squid:4/squid: Buffer over-read in the HTTP Message
feature (CVE-2023-49285) processing feature (CVE-2023-49285)
- Resolves: RHEL-18345 - squid: Incorrect Check of Function Return Value In - Resolves: RHEL-18342 - squid:4/squid: Incorrect Check of Function Return
Helper Process management (CVE-2023-49286) Value In Helper Process management (CVE-2023-49286)
- Resolves: RHEL-18146 - squid crashes in assertion when a parent peer exists - Resolves: RHEL-18230 - squid:4/squid: Denial of Service in SSL Certificate
- Resolves: RHEL-18231 - squid: Denial of Service in SSL Certificate validation validation (CVE-2023-46724)
(CVE-2023-46724) - Resolves: RHEL-15911 - squid:4/squid: NULL pointer dereference in the gopher
- Resolves: RHEL-15912 - squid: NULL pointer dereference in the gopher protocol protocol code (CVE-2023-46728)
code (CVE-2023-46728) - Resolves: RHEL-18251 - squid crashes in assertion when a parent peer exists
- Resolves: RHEL-14794 - squid: squid multiple issues in HTTP response caching
* Tue Dec 05 2023 Tomas Korbar <tkorbar@redhat.com> - 7:5.5-8 (CVE-2023-5824)
- Resolves: RHEL-14802 - squid: multiple issues in HTTP response caching - Resolves: RHEL-14803 - squid: squid: Denial of Service in HTTP Digest
Authentication (CVE-2023-46847)
* Sun Nov 12 2023 Luboš Uhliarik <luhliari@redhat.com> - 7:5.5-7 - Resolves: RHEL-14777 - squid: squid: Request/Response smuggling in HTTP/1.1
- Resolves: RHEL-14820 - squid: squid: denial of Servicein FTP and ICAP (CVE-2023-46846)
- Resolves: RHEL-14809 - squid: squid: Denial of Service in HTTP Digest
Authentication * Wed Aug 16 2023 Luboš Uhliarik <luhliari@redhat.com> - 7:4.15-7
- Resolves: RHEL-14781 - squid: squid: Request/Response smuggling in HTTP/1.1 - Resolves: #2076717 - Crash with half_closed_client on
and ICAP
* Thu Dec 08 2022 Tomas Korbar <tkorbar@redhat.com> - 4.15-6
* Wed Aug 16 2023 Luboš Uhliarik <luhliari@redhat.com> - 7:5.5-6 - Resolves: #2072988 - [RFE] Add the "IP_BIND_ADDRESS_NO_PORT"
- Resolves: #2231827 - Crash with half_closed_client on
* Tue Dec 06 2022 Tomas Korbar <tkorbar@redhat.com> - 7:5.5-5
- Resolves: #2151188 - [RFE] Add the "IP_BIND_ADDRESS_NO_PORT"
flag to sockets created for outgoing connections in the squid source code. flag to sockets created for outgoing connections in the squid source code.
* Mon Nov 07 2022 Luboš Uhliarik <luhliari@redhat.com> - 7:5.5-4 * Wed Sep 28 2022 Luboš Uhliarik <luhliari@redhat.com> - 7:4.15-5
- Resolves: #2095468 - [RFE] squid use systemd-sysusers - Resolves: #2130260 - CVE-2022-41318 squid:4/squid: buffer-over-read in SSPI and SMB
* Mon Nov 07 2022 Luboš Uhliarik <luhliari@redhat.com> - 7:5.5-3
- Resolves: #2130253 - CVE-2022-41318 squid: buffer-over-read in SSPI and SMB
authentication authentication
* Mon Jul 11 2022 Luboš Uhliarik <luhliari@redhat.com> - 7:5.5-2 * Tue Jun 28 2022 Luboš Uhliarik <luhliari@redhat.com> - 7:4.15-4
- Resolves: #2100785 - CVE-2021-46784 squid: DoS when processing gopher server - Resolves: #2100783 - CVE-2021-46784 squid:4/squid: DoS when processing gopher
responses server responses
* Tue May 31 2022 Luboš Uhliarik <luhliari@redhat.com> - 7:5.5-1
- new version 5.5
- Resolves: #2075727 - The memory usage of the squid process keeps increasing
* Thu Oct 07 2021 Luboš Uhliarik <luhliari@redhat.com> - 7:5.2-1
- new version 5.2
- Resolves: #1934560 - squid: out-of-bounds read in WCCP protocol
- Resolves: #2011637 - Rebase squid to 5.2
* Wed Sep 15 2021 Luboš Uhliarik <luhliari@redhat.com> - 7:5.1-3
- Resolves: #1988122 - Enable LTO build of squid for RHEL 9
* Tue Aug 10 2021 Mohan Boddu <mboddu@redhat.com> - 7:5.1-2
- Rebuilt for IMA sigs, glibc 2.34, aarch64 flags
Related: rhbz#1991688
* Thu Aug 05 2021 Luboš Uhliarik <luhliari@redhat.com> - 7:5.1-1
- new version 5.1
- Resolves: #1990517 - Rebase squid to 5.1
- Resolves: #1985231 - squid: FTBFS because of OpenSSL 3.0 preprocessor macro
changes
* Wed Jun 16 2021 Mohan Boddu <mboddu@redhat.com> - 7:5.0.6-4
- Rebuilt for RHEL 9 BETA for openssl 3.0
Related: rhbz#1971065
* Tue Jun 08 2021 Luboš Uhliarik <luhliari@redhat.com> - 7:5.0.6-3
- Resolves: #1969322 - squid doesn't work with active ftp
* Mon May 17 2021 Lubos Uhliarik <luhliari@redhat.com> - 7:5.0.6-2 * Wed Feb 09 2022 Luboš Uhliarik <luhliari@redhat.com> - 7:4.15-3
- Resolves: #1953505 - squid: Port to OpenSSL 3.0 - Resolves: #1941506 - CVE-2021-28116 squid:4/squid: out-of-bounds read in WCCP
protocol data may lead to information disclosure
* Mon May 17 2021 Lubos Uhliarik <luhliari@redhat.com> - 7:5.0.6-1 * Tue Jan 25 2022 Luboš Uhliarik <luhliari@redhat.com> - 7:4.15-2
- new version 5.0.6 - Resolves: #2006121 - SQUID shortens FTP Link wrong that contains a semi-colon
- Resolves: #1961253 - Rebase squid to 5.0.6 and as a result is not able to download zip file.CODE 404 TO CLIENT)
* Fri Apr 23 2021 Lubos Uhliarik <luhliari@redhat.com> - 7:5.0.5-2 * Fri Jun 18 2021 Luboš Uhliarik <luhliari@redhat.com> - 7:4.15-1
- new version 5.0.5 - new version 4.15
- Resolves: #1952896 - Rebase squid to >= 5.0.5 - Resolves: #1964384 - squid:4 rebase to 4.15
- Resolves: #1940412 - Remove libdb dependency from squid
* Fri Apr 16 2021 Mohan Boddu <mboddu@redhat.com> - 7:4.14-2 * Wed Mar 31 2021 Lubos Uhliarik <luhliari@redhat.com> - 7:4.11-5
- Rebuilt for RHEL 9 BETA on Apr 15th 2021. Related: rhbz#1947937 - Resolves: #1944261 - CVE-2020-25097 squid:4/squid: improper input validation
may allow a trusted client to perform HTTP Request Smuggling
* Wed Mar 31 2021 Lubos Uhliarik <luhliari@redhat.com> - 7:4.14-1 * Mon Oct 26 2020 Lubos Uhliarik <luhliari@redhat.com> - 7:4.11-4
- new version 4.14 - Resolves: #1890606 - Fix for CVE 2019-13345 breaks authentication in
- Resolves: #1939927 - CVE-2020-25097 squid: improper input validation may allow cachemgr.cgi
a trusted client to perform HTTP Request Smuggling
* Wed Jan 27 2021 Fedora Release Engineering <releng@fedoraproject.org> - 7:4.13-3 * Wed Aug 26 2020 Lubos Uhliarik <luhliari@redhat.com> - 7:4.11-3
- Rebuilt for https://fedoraproject.org/wiki/Fedora_34_Mass_Rebuild - Resolves: #1871705 - CVE-2020-24606 squid: Improper Input Validation could
result in a DoS
- Resolves: #1871702 - CVE-2020-15811 squid: HTTP Request Splitting could result
in cache poisoning
- Resolves: #1871700 - CVE-2020-15810 squid: HTTP Request Smuggling could result
in cache poisoning
* Sat Oct 17 2020 Jeff Law <law@redhat.com> - 7:4.13-2 * Thu Jul 02 2020 Lubos Uhliarik <luhliari@redhat.com> - 7:4.11-2
- Fix missing #includes for gcc-11 - Resolves: #1853130 - CVE-2020-15049 squid:4/squid: request smuggling and
poisoning attack against the HTTP cache
* Tue Aug 25 2020 Lubos Uhliarik <luhliari@redhat.com> - 7:4.13-1 - Resolves: #1853136 - CVE-2020-14058 squid:4/squid: DoS in TLS handshake
- new version 4.13
* Fri Aug 07 2020 Jeff law <law@redhat.com> - 7:4.12-4
- Disable LTO
* Sat Aug 01 2020 Fedora Release Engineering <releng@fedoraproject.org> - 7:4.12-3
- Second attempt - Rebuilt for
https://fedoraproject.org/wiki/Fedora_33_Mass_Rebuild
* Wed Jul 29 2020 Fedora Release Engineering <releng@fedoraproject.org> - 7:4.12-2
- Rebuilt for https://fedoraproject.org/wiki/Fedora_33_Mass_Rebuild
* Mon Jun 15 2020 Lubos Uhliarik <luhliari@redhat.com> - 7:4.12-1
- new version 4.12
* Thu May 07 2020 Lubos Uhliarik <luhliari@redhat.com> - 7:4.11-1 * Thu May 07 2020 Lubos Uhliarik <luhliari@redhat.com> - 7:4.11-1
- new version 4.11 - new version 4.11
- libsystemd integration - libsystemd integration
- Resolves: #1827564 - CVE-2020-11945 squid: improper access restriction upon - Resolves: #1829467 - squid:4 rebase
- Resolves: #1828378 - CVE-2019-12521 squid:4/squid: off-by-one error in
addStackElement allows for a heap buffer overflow and a crash
- Resolves: #1828377 - CVE-2019-12520 squid:4/squid: improper input validation
in request allows for proxy manipulation
- Resolves: #1828375 - CVE-2019-12524 squid:4/squid: improper access restriction
in url_regex may lead to security bypass
- Resolves: #1820664 - CVE-2019-18860 squid: mishandles HTML in the host
parameter to cachemgr.cgi which could result in squid behaving in unsecure way
- Resolves: #1802514 - CVE-2020-8449 squid:4/squid: Improper input validation
issues in HTTP Request processing
- Resolves: #1802513 - CVE-2020-8450 squid:4/squid: Buffer overflow in a Squid
acting as reverse-proxy
- Resolves: #1802512 - CVE-2019-12528 squid:4/squid: Information Disclosure
issue in FTP Gateway
- Resolves: #1771288 - CVE-2019-18678 squid:4/squid: HTTP Request Splitting
issue in HTTP message processing
- Resolves: #1771283 - CVE-2019-18679 squid:4/squid: Information Disclosure
issue in HTTP Digest Authentication
- Resolves: #1771280 - CVE-2019-18677 squid:4/squid: Cross-Site Request Forgery
issue in HTTP Request processing
- Resolves: #1771275 - CVE-2019-12523 squid:4/squid: Improper input validation
in URI processor
- Resolves: #1771272 - CVE-2019-18676 squid:4/squid: Buffer overflow in URI
processor
- Resolves: #1771264 - CVE-2019-12526 squid:4/squid: Heap overflow issue in URN
processing
- Resolves: #1738581 - CVE-2019-12529 squid: OOB read in Proxy-Authorization
header causes DoS
* Tue Apr 28 2020 Lubos Uhliarik <luhliari@redhat.com> - 7:4.4-9
- Resolves: #1738583 - CVE-2019-12525 squid:4/squid: parsing of header
Proxy-Authentication leads to memory corruption
- Resolves: #1828369 - CVE-2020-11945 squid: improper access restriction upon
Digest Authentication nonce replay could lead to remote code execution Digest Authentication nonce replay could lead to remote code execution
- Resolves: #1828370 - CVE-2019-12519 squid: improper check for new member in
ESIExpression::Evaluate allows for stack buffer overflow
* Thu Mar 26 2020 Lubos Uhliarik <luhliari@redhat.com> - 7:4.10-4 * Fri Aug 23 2019 Lubos Uhliarik <luhliari@redhat.com> - 7:4.4-8
- Resolves: #1817208 - More cache_swap.sh optimizations - Resolves: # 1738485 - CVE-2019-12527 squid:4/squid: heap-based buffer overflow
in HttpHeader::getAuth
* Wed Mar 25 2020 Lubos Uhliarik <luhliari@redhat.com> - 7:4.10-3
- Resolves: #1786485 - squid.service: use ${SQUID_CONF} rather than $SQUID_CONF
- Resolves: #1798535 - CVE-2019-12528 squid: Information Disclosure issue in
FTP Gateway
- Resolves: #1798554 - CVE-2020-8450 squid: Buffer overflow in a Squid acting
as reverse-proxy
- Resolves: #1798541 - CVE-2020-8449 squid: Improper input validation issues
in HTTP Request processing
* Tue Jan 28 2020 Lubos Uhliarik <luhliari@redhat.com> - 7:4.10-1
- new version 4.10
* Tue Dec 17 2019 Lubos Uhliarik <luhliari@redhat.com> - 7:4.9-3
- Resolves: #1784383 - Add BuildRequires: systemd-rpm-macros
- Resolves: #1783757 - Build with ./configure --with-pidfile=/run/squid.pid
- Resolves: #1783768 - Optimize cache_swap.sh cache_dir search
* Mon Nov 11 2019 Lubos Uhliarik <luhliari@redhat.com> - 7:4.9-2
- new version 4.9
- verify src taball signature by default in prep section
* Tue Oct 08 2019 Lubos Uhliarik <luhliari@redhat.com> - 7:4.8-6
- Resolves: #1741342 - Do not call autoconf at build time
* Tue Oct 08 2019 Lubos Uhliarik <luhliari@redhat.com> - 7:4.8-5
- Resolves: #1716950 - Drop "sleep 1" from logrotate fragment
* Thu Aug 22 2019 Lubomir Rintel <lkundrak@v3.sk> - 7:4.8-4 * Wed Jul 31 2019 Lubos Uhliarik <luhliari@redhat.com> - 7:4.4-7
- Move the NetworkManager dispatcher script out of /etc - Resolves: #1729436 - CVE-2019-13345 squid: XSS via user_name or auth parameter
in cachemgr.cgi
* Mon Aug 05 2019 Lubos Uhliarik <luhliari@redhat.com> - 7:4.8-3 * Fri Jun 21 2019 Lubos Uhliarik <luhliari@redhat.com> - 7:4.4-6
- Resolves: #1737030 - depend on httpd-filesystem - Resolves: #1679526 - Missing detailed configuration file
- Resolves: #1703117 - RHEL 7 to 8 fails with squid installed because dirs
changed to symlinks
- Resolves: #1691741 - Squid cache_peer DNS lookup failed when not all lower
case
- Resolves: #1683527 - "Reloading" message on a fresh reboot after enabling
squid
* Sat Jul 27 2019 Fedora Release Engineering <releng@fedoraproject.org> - 7:4.8-2 * Tue Dec 11 2018 Lubos Uhliarik <luhliari@redhat.com> - 7:4.4-4
- Rebuilt for https://fedoraproject.org/wiki/Fedora_31_Mass_Rebuild - Resolves: #1612524 - Man page scan results for squid
* Wed Jul 10 2019 Lubos Uhliarik <luhliari@redhat.com> - 7:4.8-1 * Tue Dec 11 2018 Lubos Uhliarik <luhliari@redhat.com> - 7:4.4-3
- new version 4.8 - Resolves: #1642384 - squid doesn't work with active ftp
- Resolves: #1727745 - squid: CVe-2019-13345 squid: XSS via user_name or auth
parameter in cachemgr.cgi
* Tue Jul 02 2019 Lubos Uhliarik <luhliari@redhat.com> - 7:4.7-6 * Tue Dec 11 2018 Lubos Uhliarik <luhliari@redhat.com> - 7:4.4-2
- fix filepath to squid.conf.documented in squid's manpage - Resolves: #1657847 - Unable to start Squid in Selinux Enforcing mode
- fix path to systemctl in nm script
* Wed May 22 2019 Lubos Uhliarik <luhliari@redhat.com> - 7:4.7-5
- Related: #1709299 - Use upstream squid.service
* Fri May 17 2019 Luboš Uhliarik <luhliari@redhat.com> - 7:4.7-1
- new version 4.7
* Fri May 17 2019 Luboš Uhliarik <luhliari@redhat.com> - 7:4.6-3
- Resolves: #1709299 - Use upstream squid.service
* Mon Apr 29 2019 Lubos Uhliarik <luhliari@redhat.com> - 7:4.6-2
- Resolves: #1599074 - squid: 3 coredumps every day
* Wed Apr 24 2019 Lubos Uhliarik <luhliari@redhat.com> - 7:4.6-1
- new version 4.6
- disabled strict checking due to gcc warnings
* Sun Feb 03 2019 Fedora Release Engineering <releng@fedoraproject.org> - 7:4.4-3
- Rebuilt for https://fedoraproject.org/wiki/Fedora_30_Mass_Rebuild
* Mon Jan 14 2019 Björn Esser <besser82@fedoraproject.org> - 7:4.4-2
- Rebuilt for libcrypt.so.2 (#1666033)
* Mon Dec 10 2018 Lubos Uhliarik <luhliari@redhat.com> - 7:4.4-1 * Mon Dec 10 2018 Lubos Uhliarik <luhliari@redhat.com> - 7:4.4-1
- new version 4.4 - Resolves: #1656871 - squid rebase to 4.4
- Resolves: #1645148 - CVE-2018-19131 squid: Cross-Site Scripting when
* Sun Oct 14 2018 Peter Robinson <pbrobinson@fedoraproject.org> 7:4.2-3 generating HTTPS response messages about TLS errors
- Drop obsolete legacy sys-v remanents - Resolves: #1645156 - CVE-2018-19132 squid: Memory leak in SNMP query
rejection code
* Mon Aug 20 2018 Luboš Uhliarik <luhliari@redhat.com> - 7:4.2-2
- Resolves: #1618790 - SELinux 'dac_override' denial for cache_swap.sh
* Mon Aug 06 2018 Luboš Uhliarik <luhliari@redhat.com> - 7:4.2-1 * Mon Aug 06 2018 Lubos Uhliarik <luhliari@redhat.com> - 7:4.2-1
- new version 4.2 - new version 4.2
- enable back strict error checking - enable back strict error checking
* Wed Aug 01 2018 Luboš Uhliarik <luhliari@redhat.com> - 7:4.1-1 * Wed Aug 01 2018 Luboš Uhliarik <luhliari@redhat.com> - 7:4.1-1
- new version 4.1 - new version 4.1
* Sat Jul 14 2018 Fedora Release Engineering <releng@fedoraproject.org> - 7:4.0.25-2 * Mon Jun 04 2018 Luboš Uhliarik <luhliari@redhat.com> - 7:4.0.23-5
- Rebuilt for https://fedoraproject.org/wiki/Fedora_29_Mass_Rebuild - Resolves: #1585617 - Build against libdb only instead of libdb4
- disabled strict checking for now (squid can not be built with GCC8)
* Thu Jun 28 2018 Luboš Uhliarik <luhliari@redhat.com> - 7:4.0.25-1
- new version 4.0.25
* Mon Jun 04 2018 Luboš Uhliarik <luhliari@redhat.com> - 7:4.0.24-2
- removed obsolete BuildRequires (libdb4-devel)
* Thu Mar 08 2018 Luboš Uhliarik <luhliari@redhat.com> - 7:4.0.24-1 * Mon Apr 16 2018 Luboš Uhliarik <luhliari@redhat.com> - 7:4.0.23-4
- new version 4.0.24 - Resolves: #1566055 - module squid cannot be installed due to missing
- disabled strict checking (removed -Werror) perl(Crypt::OpenSSL::X509)
* Fri Feb 09 2018 Fedora Release Engineering <releng@fedoraproject.org> - 7:4.0.23-3 * Fri Feb 09 2018 Fedora Release Engineering <releng@fedoraproject.org> - 7:4.0.23-3
- Rebuilt for https://fedoraproject.org/wiki/Fedora_28_Mass_Rebuild - Rebuilt for https://fedoraproject.org/wiki/Fedora_28_Mass_Rebuild

Loading…
Cancel
Save