Reduce UDS/segment name clashes across same-service instances (#2023)
Add a PID file name hash to the names of the shared memory segments and
Unix Domain Sockets. Since all instances running on the same host are
supposed to have unique PID files, this addition significantly reduces
the probability of name clashes when running multiple Squid instances
with the same service name (i.e. the same `squid -n` parameter value
that defaults to "squid").
A clash may still happen if two different PID file names have the same
hash or if multiple instances disable PID file management with
`pid_filename none`. Clashes may also happen in environments where Squid
does not even use service name for naming shared memory segments.
Examples of UDS and shared memory segment names (while using default
service name):
Support no-digest X509 certificate keys like ML-DSA/EdDSA (#2165)
Recent OpenSSL releases (e.g., OpenSSL v3.5) support several private key
types[^1] for which supplying a message digest algorithm is prohibited
when signing a certificate. Prior to this enhancement, Squid was
rejecting https_port and http_port configurations using such key types
(with the above FATAL message) because OpenSSL X509_sign() call made
with a prohibited (for the given key type) non-nil digest algorithm was
failing.
Technically, only listening ports with generate-host-certificates (and
ssl-bump) parameters need to generate X509 certificates and, hence, call
X509_sign(). However, current Squid code generates so called "untrusted"
certificates even for ports that do not support dynamic host certificate
generation or SslBump (XXX). Thus, this enhancement is applicable to
both regular and SslBump configurations.
[^1]: Known no-message-digest key types are ML-DSA-44, ML-DSA-65,
ML-DSA-87, ED25519, and ED448, but others might exist or will be added.
This change was tested against known types, but should support others.
ML-DSA key types are used in post-quantum cryptography.
SNMP: Match Var allocation/deallocation methods (#2183)
Pdu::setVars() and Pdu::unpack() allocate variables with `new Var(...)`,
but clearVars() freed them using snmp_var_free(). That skipped the `Var`
destructor and mismatched the allocator.
We hope that all Pdu::variables are allocated via Pdu class methods
despite the presence of snmp_var_new() and snmp_var_clone() calls in
low-level snmplib code.
Fix parsing of malformed quoted squid.conf strings (#2239)
Iteration of a quoted token that ends with a backslash (escape with no
next char) kept going past the end of the token. That bug as well as
hypothetical 2KB-byte tokens (exceeding CONFIG_LINE_LIMIT) could also
result in a 1-byte NUL overrun.
HTCP: Check for too-small packed and too-large unpacked fields (#2164)
Harden HTCP parsing by checking HTCP fields
- Check packed field lengths and buffer space before reads.
- Guard CLR "reason" when sz < 2; log invalid messages.
- Support old minor==0 layout with safe prefix copy.
- Use early returns and unique_ptr for safer flows.
Previously, nmasldap_get_simple_pwd() and nmasldap_get_password()
could overrun or return non-terminated strings at length
boundaries. This change adds strict bounds checks, copies at most
len - 1, and ensures explicit NUL termination, aligning both
helpers buffer/length semantics without altering call-site
behavior.
Fix off-by-one in helper args count assertion (#2212)
The `nargs` value should now be pointing past both the
`HELPER_MAX_ARGS` and the additional terminator. i.e. outside
the valid array space. This is okay because it is an absolute
counter (1-based) not an offset (0-based) despite how it is
used to fill the array.
Fix UDP log module opening and closing code (#2214)
logfile_mod_udp_open() mistreated successful comm_connect_addr() result
as an "Unable to connect" failure (and vice versa), rendering UDP-based
logging unusable. Broken since at least 2010 commit d938215.
Also fixed logfile_mod_udp_close() closing FD 0 after "Invalid UDP
logging address" ERRORs during logfile_mod_udp_open().
ext_file_userip_acl: harden lookups and memory handling (#2198)
Stop mutating getgrnam(3) buffer; iterate gr_mem safely
Zero last node and NULL-check in dict_lookup() to prevent OOB read
Add free_dict() and free dictionary before exit
This patch NULL-terminates the NMAS Universal Password values
array (values[1] = nullptr) to match ldap_get_values() semantics
and avoid potential out-of-bounds iteration.
negotiate_kerberos_auth: Properly align NDR data (#2186)
Resolves sporadic Negotiate/Kerberos auth failures that manifested
as proxy 407 loops or helper errors when decoding PAC data, depending
on ticket layout.
Previously, the parser advanced bpos by the remainder:
(bpos += bpos %n)
instead of padding to the next multiple of n.
For example, n = 4:
bpos=5 (r=1): current: 6 (wrong), correct: 8
bpos=6 (r=2): current: 8 (accidentally right)
bpos=7 (r=3): current: 10 (wrong), correct: 8
SNMP: Improve parsing of malformed ASN.1 object identifiers (#2185)
ASN.1 object identifiers are length-delimited, not null-terminated. If
the input encoding omits a terminating byte (MSB clear), then the parser
would walk past the buffer.
Also simplified expressions related to sub-identifier parsing.
ntlm_sspi_auth: memcmp not memcpy, send newline, no uninit mem (#2218)
Previously, memcpy was incorrectly used instead of memcmp. In addition
to this, uninitalized memory could be used, and responses to Squid were
missing a newline.
On errors, the helper was reporting DsRoleGetPrimaryDomainInformation()
error info using the wrong/bogus error code and probably freeing an
uninitialized pointer.
FTP: Avoid null dereferences when handling ftp_port traffic (#2172)
`strchr` may return null if a deliminator is not found. Likewise,
if an `Http::HdrType::FTP_REASON` string is not found, nullptr would
be used in the %s formatter, leading to UB.
Norman Ziert [Tue, 5 Aug 2025 08:31:40 +0000 (08:31 +0000)]
Bug 5407: Support at least 1000 groups per Kerberos user (#2047)
Increase MAX_PAC_GROUP_SIZE to a more reasonable value,
so negotiate_kerberos_auth can report more than approximately
200 groups an authenticated user is member of back to Squid.
Checking PID to ignore stale responses became unnecessary after 2021
commit 4c21861 added Mine() calls that guarantee message freshness.
Also replaced the matching kidId check with an assertion because no IPC
messages, not even stale ones, may be sent to the kid with the wrong kid
identifier. This assertion cannot be easily generalized because most IPC
messages do not contain the kid identifier of the intended recipient.
aafbsd [Thu, 26 Jun 2025 18:57:19 +0000 (18:57 +0000)]
Bug 5497: Fix detection of duped IPs returned by getaddrinfo() (#2100)
WARNING: Ignoring <IP X> because it is already covered by <IP X>
Affects `src`, `dst`, and `localip` ACLs, especially those that use
domain names with multiple DNS A or AAAA records.
IP addresses returned by getaddrinfo(3) may not be sorted (e.g., when a
host has multiple DNS A RRs on FreeBSD). Instead of comparing the
current address with just the previous one, we now check all previously
added addresses (while processing a single getaddrinfo() call output).
This surgical fix minimizes changes without improving surrounding code.
Amos Jeffries [Sun, 22 Jun 2025 00:48:05 +0000 (00:48 +0000)]
Fix missing CONTRIBUTOR name (#2091)
Despite CONTRIBUTORS file being UTF-8 Ture's name
was dropped by our conversion script which does not
handle non-ASCII characters nicely. Re-add it manually.
Do not duplicate received Surrogate-Capability in sent requests (#2087)
When computing Surrogate-Capability header while forwarding an
accelerated request, Squid duplicated old (i.e. received) header entries
(if any). For example, this outgoing request shows an extra hop1 entry:
GET / HTTP/1.1
...
Surrogate-Capability: hop1="Surrogate/1.0"
Surrogate-Capability: hop1="Surrogate/1.0", hop2="Surrogate/1.0"
Amos Jeffries [Mon, 9 Jun 2025 04:49:04 +0000 (04:49 +0000)]
CI: Fix gperf 3.2 output filter (#2081)
gperf 3.2 now provides properly compiler and C++ version scoped
fallthrough attributes. Our filter to convert the gperf 3.1 and
older output for C++17 attribute requirements is now broken and
produces compiler errors due to listing '[[fallback]];' on two
consecutive lines.
Fix OpenSSL build with GCC v15.1.1 [-Wformat-truncation=] (#2077)
On arm64 Fedora 42:
src/ssl/crtd_message.cc:132:39: error: '%zd' directive output may be
truncated writing between 1 and 19 bytes into a region
of size 10 [-Werror=format-truncation=]
snprintf(buffer, sizeof(buffer), "%zd", body.length());
Carl Vuosalo [Wed, 28 May 2025 19:17:38 +0000 (19:17 +0000)]
Fix SNMP cacheNumObjCount -- number of cached objects (#2053)
SNMP counter cacheNumObjCount used StoreEntry::inUseCount() stats. For
Squid instances using a rock cache_dirs or a shared memory cache, the
number of StoreEntry objects in use is usually very different from the
number of cached objects because these caches do not use StoreEntry
objects as a part of their index. For all instances, inUseCount() also
includes ongoing transactions and internal tasks that are not related to
cached objects at all.
We now use the sum of the counters already reported on "on-disk objects"
and "Hot Object Cache Items" lines in "Internal Data Structures" section
of `mgr:info` cache manager report. Due to floating-point arithmetic,
these stats are approximate, but it is best to keep SNMP and cache
manager reports consistent.
This change does not fix SNMP Gauge32 overflow bug: Caches with 2^32 or
more objects continue to report wrong/smaller cacheNumObjCount values.
### On MemStore::getStats() and StoreInfoStats changes
To include the number of memory-cached objects while supporting SMP
configurations with shared memory caches, we had to change how cache
manager code aggregates StoreInfoStats::mem data collected from SMP
worker processes. Before these changes, `StoreInfoStats::operator +=()`
used a mem.shared data member to trigger special aggregation code hack,
but
* SNMP-specific code cannot benefit from that StoreInfoStats aggregation
because SNMP code exchanges simple counters rather than StoreInfoStats
objects. `StoreInfoStats::operator +=()` is never called by SNMP code.
Instead, SNMP uses Snmp::Pdu::aggregate() and friends.
* We could not accommodate SNMP by simply adding special aggregation
hacks directly to MemStore::getStats() because that would break
critical "all workers report about the same stats" expectations of the
special hack in `StoreInfoStats::operator +=()`.
To make both SNMP and cache manager use cases work, we removed the hack
from StoreInfoStats::operator +=() and hacked MemStore::getStats()
instead, making the first worker responsible for shared memory cache
stats reporting (unlike SMP rock diskers, there is no single kid process
dedicated to managing a shared memory cache). StoreInfoStats operator
now uses natural aggregation logic without hacks.
TODO: After these changes, StoreInfoStats::mem.shared becomes
essentially unused because it was only used to enable special
aggregation hack in StoreInfoStats that no longer exists. Remove?
Bug 5352: Do not get stuck in RESPMOD after pausing peer read(2) (#2065)
The transaction gets stuck if Squid, while sending virgin body bytes to
an ICAP RESPMOD service, temporary stops reading additional virgin body
bytes from cache_peer or origin server. Squid pauses reading (with
readSizeWanted becoming zero) if reading more virgin bytes is temporary
prohibited by delay pools and/or read_ahead_gap limits:
readReply: avoid delayRead() to give adaptation a chance to drain...
HttpStateData::readReply() starts waiting for ModXact to drain the
BodyPipe buffer, but that draining may not happen, either because
ModXact::virginConsume() is not called at all[^1] or because it is
"postponing consumption" when BodyPipe still has some unused space[^2].
With HttpStateData not reading more virgin bytes, Squid may not write
more virgin body bytes to the ICAP service, and the ICAP service may not
start or continue responding to the RESPMOD request. Without that ICAP
activity, ModXact does not consume, the virgin BodyPipe buffer is not
drained, HttpStateData is not reading, and no progress is possible.
HttpStateData::readReply() should start waiting for adaptation to drain
BodyPipe only when the buffer becomes completely full (instead of when
it is not empty). This change may increase virgin response body bytes
accumulation but not the buffer capacity because existing buffer
space-increasing logic in maybeMakeSpaceAvailable() remains intact.
To prevent stalling, both BodyPipe ends (i.e. HttpStateData and
Icap::ModXact) must use matching "progress is possible" conditions, but
* HttpStateData used hasContent()
* Icap::ModXact used spaceSize()
* Ftp::Client used potentialSpaceSize()
Now, all three use matching potentialSpaceSize()-based conditions.
Squid eCAP code is unaffected by this bug, because it does not postpone
BodyPipe consumption. eCAP API does not expose virgin body buffer
capacity, so an eCAP adapter that postpones consumption risks filling
the virgin body buffer and stalling. This is an eCAP API limitation.
[^1]: Zero readSizeWanted is reachable without delay pools, but only if
Squid receives an adapted response (that makes readAheadPolicyCanRead()
false by filling StoreEntry). Ideally, receiving an adapted response
should result in a virginConsume() calls (that would trigger BodyPipe
draining), but currently it may not. Reliably starting virgin data
consumption sooner is not trivial and deserves a dedicated change.
[^2]: ModXact postpones consumption to preserve virgin bytes for ICAP
retries and similar purposes. ModXact believes it is safe to postpone
because there is still space left in the buffer for HttpStateData to
continue to make progress. ModXact would normally start or resume
draining the buffer when sending more virgin bytes to the ICAP service.
Amos Jeffries [Sun, 18 May 2025 06:39:04 +0000 (06:39 +0000)]
Maintenance: Remove shared LDADD (#2058)
Most built binaries have a distinct set of dependencies and already have
their own foo_LDADD variables. Add a few variables to cover the
remaining binaries and stop setting an (incomplete) LDADD global.
Also removed unnecessary EXTRA_PROGRAMS because mem_node_test and splay
binaries are built unconditionally.
The FreeBSD project has promoted version 14.2 to stable.
Some packages we use are not compatible with version 14.1.
Upgrade the reference version we use, the action supports it
store/Disks.cc:690: error: argument 1 value 18446744073709551615
exceeds maximum object size 9223372036854775807
[-Werror=alloc-size-larger-than=]
const auto tmp = new SwapDir::Pointer[swap->n_allocated];
pconn.cc:43:53: error: argument 1 value 18446744073709551615 ...
theList_ = new Comm::ConnectionPointer[capacity_];
Andreas Weigel [Thu, 13 Mar 2025 11:30:28 +0000 (11:30 +0000)]
Fix tls-dh support for DHE parameters with OpenSSL v3+ (#1949)
# When applying tls-dh=prime256v1:dhparams.pem configuration:
WARNING: Failed to decode EC parameters 'dhparams.pem'
# When forcing the use of FFDHE with something like
# openssl s_client -tls1_2 -cipher DHE-RSA-AES256-SHA256 -connect...
ERROR: failure while accepting a TLS connection on:
SQUID_TLS_ERR_ACCEPT+TLS_LIB_ERR=A0000C1+TLS_IO_ERR=1
Squid `https_port ... tls-dh=curve:dhparams.pem` configuration is
supposed to support _both_ ECDHE and FFDHE key exchange mechanisms (and
their cipher suites), depending on client-supported cipher suites. ECDHE
mechanism should use the named curve (e.g., `prime256v1`), and FFDHE
mechanism should use key exchange parameters loaded from the named PEM
file (e.g., `ffdhe4096` named group specified in RFC 7919).
When 2022 commit 742236c added support for OpenSSL v3 APIs, new
loadDhParams() code misinterpreted curve name presence in `tls-dh` value
as an indication that the named parameters file contains ECDHE
parameters, setting OSSL_DECODER_CTX_new_for_pkey() type parameter to
"EC", and (when parameter file specified FFDHE details) triggering the
WARNING message quoted above.
Squid should not expect additional ECDHE parameters when the elliptic
curve group is already fully specified by naming it at the start of
`tls-dh` value. Squid now reverts to earlier (v4) behavior, where
the two mechanisms can coexist and can be configured separately as
described above:
Furthermore, updateContextEecdh() code in commit 742236c continued to
load parsed parameters using old SSL_CTX_set_tmp_dh() call but should
have used SSL_CTX_set0_tmp_dh_pkey() API because the type of parsed
parameters (i.e. DhePointer) have changed from DH to EVP_PKEY pointer.
This second bug affected configurations with and without an explicit
curve name in `tls-dh` value.
Also report a failure to load parsed parameters into TLS context.
CI: Do not classify "no failures" stats as test-build errors (#2001)
CppUnit tests emit a lot of "FAIL: 0" and "XFAIL: 0" lines, which are
incorrectly classified as errors by the test-builds.sh. Filter these
messages out as they are not indicative of problems.
MinGW: use nameless unions in ext_ad_group_acl (#2004)
ext_ad_group_acl was written in 2008 in C, and
it used the C variant of the Win32 API.
It was then ported to C++, but the API callers were
not updated to the C++ version of the API.
With more modern compilers, and
Squid enforcing more strict types and error handling,
it is no longer compiling.
This is part 1 of 2 of the fixes to make the helper build
again, the scope is to update Win32 API callers so they
use the C++ version of the API
Examples of fixed errors:
error: 'IADs' {aka 'struct IADs'} has no member named 'lpVtbl'
error: 'VARIANT' {aka 'struct tagVARIANT'} has no member named 'n1'
On Windows, mkdir only takes one argument.
compat/mswindows.h has an adapter, add it to
compat/mingw.h as well.
Solves error:
```
UFSSwapDir.cc:617:26: error: too many arguments
to function 'int mkdir(const char*)'
mingw/include/io.h:282:15: note: declared here
int __cdecl mkdir (const char *);
```
The AIO Windows compatibilty layer is also
necessary on mingw
Problems fixed:
```
DiskIO/AIO/async_io.h:58:18:
error: field 'aq_e_aiocb' has incomplete type 'aiocb'
DiskIO/AIO/async_io.h:58:12:
note: forward declaration of 'struct aiocb'
DiskIO/AIO/AIODiskFile.cc:
In member function
'virtual void AIODiskFile::read(ReadRequest*)':
src/DiskIO/AIO/AIODiskFile.cc:134:9:
error: 'aio_read' was not declared in this scope;
did you mean 'file_read' ?
```
ntlm_sspi_auth: Fix missing base64 symbol linkage (#2031)
Solve build error:
```
ld: ntlm_sspi_auth.o: in function `token_decode':
undefined reference to `nettle_base64_decode_init'
undefined reference to `nettle_base64_decode_update'
undefined reference to `nettle_base64_decode_final'
```
Level-2 "Tunnel Server RESPONSE:..." debugs() incorrectly assumed that
its readBuf parameter contained hdr_sz header bytes. In reality, by the
time code reached that debugs(), readBuf no longer had any header bytes
(and often had no bytes at all). Besides broken header dumps, this bug
could lead to problems that Valgrind reports as "Conditional jump or
move depends on uninitialised value" in DebugChannel::writeToStream().
This fix mimics HttpStateData::processReplyHeader() reporting code,
including its known problems. Future changes should address those
problems and reduce code duplication across at least ten functions
containing similar "decorated" level-2 message dumps.
Bug 5093: List http_port params that https_port/ftp_port lack (#1977)
To avoid documentation duplication, current https_port and ftp_port
directive descriptions reference http_port directive instead of
detailing their own supported parameters. For https_port, this solution
creates a false impression that the directive supports all http_port
options. Our ftp_port documentation is better but still leaves the
reader guessing which options are actually supported.
This change starts enumerating http_port configuration parameters that
ftp_port and https_port directives do _not_ support. Eventually, Squid
should reject configurations with unsupported listening port options.
Alex Rousskov [Tue, 31 Dec 2024 21:59:05 +0000 (21:59 +0000)]
Work around some mgr:forward accounting/reporting bugs (#1969)
In modern code, FwdReplyCodes[0][i] is usually zero because n_tries is
usually at least one at logReplyStatus() call time. This leads to
mgr:forward report showing nothing but table heading (i.e. no stats)
Also improve `try#N` heading:data match by skipping FwdReplyCodes[0]
reporting (there is still no `try#0` heading) and adding a previously
missing `try#9` heading
Alex Rousskov [Tue, 31 Dec 2024 20:40:46 +0000 (20:40 +0000)]
Clarify --enable-ecap failure on missing shared library support (#1968)
checking if libtool supports shared libraries... no
checking whether to build shared libraries... no
configure: error: eCAP support requires loadable modules.
Please do not use --disable-shared with --enable-ecap.
After 2022 commit 5a2409b7, our advice for handling the above error
became misleading in environments that do not --disable-shared
explicitly but lack shared libraries support for other reasons