Amos Jeffries [Sun, 20 Nov 2016 09:12:00 +0000 (22:12 +1300)]
C++11: Remove GnuRegex and all -lregex related code
Squid is now exclusively using the STL std::regex API provided on all
operating systems in a portable manner.
We no longer have any need of detecting if the system is providing a
libregex, or user has configured one, or if it actually works, or how
to call it, or use the GnuRegex code as a backup when one of those
complex details goes wrong.
Amos Jeffries [Fri, 18 Nov 2016 18:08:30 +0000 (07:08 +1300)]
Fix Null pointer dereferences after rev.14913
on_unsupported_protocol with non-HTTP requests occurs without
an HTTP request object. Some ACLs will not be possible to check
but that is not a reason to crash.
The r14945 patch has a major bug:
When the Http::One::Server::writeControlMsgAndCall fails to write the control
message, schedules a Comm::Write callback using just a ScheduleCallHere command.
The callback called withtout the CommIoCbParams details and squid is crashes.
This patch fixes the ConnStateData::writeControlMsgAndCall to return false if it
fails to write the control message and allow the caller to handle the failure.
The following sequence of events triggers this assertion:
- The server sends an 1xx control message.
- http.cc schedules ConnStateData::sendControlMsg call.
- Before sendControlMsg is fired, http.cc detects an error (e.g., I/O
error or timeout) and starts writing the reply to the user.
- The ConnStateData::sendControlMsg is fired, starts writing 1xx, and
hits the "no concurrent writes" assertion.
We could only reproduce this sequence in the lab after changing Squid
code to trigger a timeout at the right moment, but the sequence looks
plausible. Other event sequences might result in the same outcome.
To avoid concurrent writes, Squid now drops the control message if
Http::One::Server detects that a reply is already being written. Also,
ConnStateData delays reply writing until a pending control message write
has been completed.
ICAP trailers are currently specified by
https://datatracker.ietf.org/doc/draft-rousskov-icap-trailers/
This implementation complies with version -01 of that draft:
- Squid unconditionally announces ICAP Trailer support via the ICAP
Allow request header field.
- Squid parses the ICAP response trailer if and only if the ICAP server
signals its presence by sending both Trailer header and Allow/trailers
in the ICAP response.
Squid logs and ignores all parsed ICAP header fields (for now).
Also refactored HttpHeader parsing methods in order to reuse them for
ICAP trailer parsing.
Also simplified and fixed headers isolating code while dealing with
empty (i.e. zero header fields) headers. Old httpMsgIsolateHeaders()
tried to re-implement header end detection/processing logic that is
actually covered by headersEnd(). Old httpMsgIsolateHeaders() could
return success for some garbage input (e.g., a buffer of several CRs)
even if no end of headers was found.
Added nil dereference checks for Ftp::Client::ctrl.conn, including:
- Ftp::Client::handlePasvReply() and handleEpsvReply() that dereference
ctrl.conn in DBG_IMPORTANT messages.
- Many functions inside FtpClient.cc and FtpGateway.cc files.
TODO: We need to find a better way to handle nil ctrl.conn. It is only
a matter of time when we forget to add another dereference check or
discover a place we missed during this change.
Also disabled forwarding of EPRT and PORT commands to origin servers.
Squid support for those commands is broken and their forwarding may
cause segfaults (bug #4004). Active FTP is still supported, of course.
Amos Jeffries [Mon, 7 Nov 2016 10:49:37 +0000 (23:49 +1300)]
Bug 4599 pt1: initial support for OpenSSL v1.1
Converts some CRYPTO_add(..., CRYPTO_LOCK_X509) calls with portability
wrapper for X509_up_ref(). Just the calls which are in code not yet using
Security::CertPointer.
Alex Rousskov [Fri, 4 Nov 2016 22:04:34 +0000 (16:04 -0600)]
Improved testAppendSBuf to actually test SBuf::append() optimization.
... rather than to test SBuf::id preservation across assignments
[currently used by that optimization].
Trunk r14911 talks about bitwise object copy but making sure that SBuf
has a working assignment operator is an issue unrelated to append() and
its optimization. Besides, it is not really the prohibited by C++
bitwise copy that we might worry about but the default member-wise
assignment that we may forget to customize.
Alex Rousskov [Fri, 4 Nov 2016 21:14:54 +0000 (15:14 -0600)]
Honor SBufReservationRequirements::minSize regardless of idealSize.
In a fully specified SBufReservationRequirements, idealSize would
naturally match or exceed minSize. However, the idealSize default value
(zero) may not. We should honor minSize regardless of idealSize, just as
the API documentation promises to do.
No runtime changes expected right now because the only existing user of
SBufReservationRequirements sets .idealSize to CLIENT_REQ_BUF_SZ (4096)
and .minSize to 1024.
The pinned_connection->stopPinnedConnectionMonitoring() call does not needed,
it is already called from inside pinned_connection->borrowPinnedConnection
called two lines before.
Support tunneling of bumped non-HTTP traffic. Other SslBump fixes.
Use case: Skype groups appear to use TLS-encrypted MSNP protocol instead
of HTTPS. This change allows Squid admins using SslBump to tunnel Skype
groups and similar non-HTTP traffic bytes via "on_unsupported_protocol
tunnel all". Previously, the combination resulted in encrypted HTTP 400
(Bad Request) messages sent to the client (that does not speak HTTP).
Also this patch:
* fixes bug 4529: !EBIT_TEST(entry->flags, ENTRY_FWD_HDR_WAIT)
assertion in FwdState.cc.
* when splicing transparent connections during SslBump step1, avoid
access-logging an extra record and log %ssl::bump_mode as the expected
"splice" not "none".
* handles an XXX comment inside clientTunnelOnError for possible memory
leak of client streams related objects
* fixes TunnelStateData logging in the case of splicing after peek.
Alex Rousskov [Thu, 3 Nov 2016 13:57:02 +0000 (02:57 +1300)]
Optimize appending to empty SBufs, a common use case.
Most appends start with an empty buffer. Some append only once. There
is no reason to allocate new memory for that first append or force the
appender to write code to optimize that first append.
Why also check that SBuf has never been configured or altered then? To
preserve pre-allocated SBufs, such as those [ab]used as I/O buffers.
Amos Jeffries [Fri, 28 Oct 2016 08:41:57 +0000 (21:41 +1300)]
Fix GCC 4.9 build after rev.14893
GCC 4.9 does not support some corner cases of C++11 syntax. In this case
when it is presented with default nulptr initialization of function
pointers it gets confused with 'pure virtual' initialization:
error: invalid pure specifier (only '= 0' is allowed) before ';' token
ssl::server_name ACL badly broken since inception (trunk r14008).
The original server_name code mishandled all SNI checks and some rare
host checks:
* The SNI-derived value was pointing to an already freed memory storage.
* Missing host-derived values were not detected (host() is never nil).
* Mismatches were re-checked with an undocumented "none" value
instead of being treated as mismatches.
Same for ssl::server_name_regex.
Also set SNI for more server-first and client-first transactions.
Amos Jeffries [Fri, 28 Oct 2016 07:56:00 +0000 (20:56 +1300)]
HTTP: initial support for Cache-Control:immutable
The 'immutable' cache control is a proposed standardization of
behaviour equivalent to the refresh_pattern 'ignore-reload' option.
Reducing latency delays from revalidation when an object is known not
to be updated until it expires.
When a server emits it on responses a recipient cache is expected to
treat the response as not requiring any revalidation until it becomes
stale. For the duration of its freshness period it may be used as-is
to respond to client requests - including reload (CC:max-age=0)
requests.
This initial code does not yet support preventing IMS conditional
requests behaviour when the 'immutable' signal is received.
Note that CC:no-cache in requests, and If-None-Match ETag based
conditionals can still make an 'immutable' response be irrelevant to
a particular client request. So server contact is not completely
prevented.
Use 'immutable' option in preference over the refresh_pattern
'ignore-reload' in order to track whether that override is still
relevant.
Amos Jeffries [Tue, 25 Oct 2016 08:03:32 +0000 (21:03 +1300)]
HTTP/1.1: make Vary:* objects cacheable
Under new clauses from RFC 7231 section 7.1.4 and HTTP response
containing header Vary:* (wifcard variant) can be cached, but
requires revalidation with server before each use.
Use the new mandatory revalidation flags to allow storing of any
wildcard Vary:* response.
Note that responses with headers like Vary:A,B,C,* are equivalent
to Vary:*. The cache key string for these objects is normalized.
Amos Jeffries [Mon, 24 Oct 2016 12:46:35 +0000 (01:46 +1300)]
Cleanup: convert AclDenyInfoList and AclNameList to MEMPROXY_CLASS
Use the C++ new/delete operators provided by MEMPROXY_CLASS and
associated as-needed pool creation instead of C Alloc/Free
functions and pre-initialized pool.
Remove now unused MEM_ACL_DENY_INFO_LIST and MEM_ACL_NAME_LIST
memory pools.
Remove apparently unused DenyInfoList global.
Fixes a memory leak on shutdown/reconfigure when
aclDestroyDenyInfoList() frees a list of AclDenyInfoList object
but not the AclNameList objects attached to them.
Fixes a memory leak when reconfigure frees a list of AclDenyInfoList
objects but not the URL/page-name strings attached to them.
Squid crashed because HttpMsg::body_pipe was used without check that it
was initialized. The message lacks body pipe when it has no body or
empty body.
Amos Jeffries [Wed, 19 Oct 2016 21:14:13 +0000 (10:14 +1300)]
Cleanup: use new/delete allocation from netdbEntry class
Use the C++ new/delete operators provided by MEMPRXY_CLASS and
associated as-needed pool creation instead of C Alloc/Free
functions and pre-initialized pool.
Use class initializers for members to demonstrate mixed default
and explicit member initialization.
Avoid segfaults when we lack the server name for certificate validator.
Squid could crash when transparently proxying a TLS client that does not
send SNI because the code composing certificate validator request
assumed that the intended server name is always available. There could
have been other use cases leading to the same kind of crash.
Fixed Squid sends an empty domain name to the certificate validator when
SSL_ex_data[ssl_ex_index_server] does not exist.
Amos Jeffries [Wed, 12 Oct 2016 09:25:08 +0000 (22:25 +1300)]
Cleanup: convert htcpSpecifier to Refcountable class
Use refcounting Pointer to manage htcpSpecifier object deletion
instead of explicit Free function calls.
Use HttpRequestPointer for members to ensure proper refcounting
for those as well. Combined with C++11 default member initialization
this permits default constructors and destructors to be used.
HTTP: MUST ignore a [revalidation] response with an older Date header.
Before this patch, Squid violated the RFC 7234 section 4 MUST
requirement: "When more than one suitable response is stored, a cache
MUST use the most recent response (as determined by the Date header
field)." This problem may be damaging in cache hierarchies where
parent caches may have different responses. Trusting the older response
may lead to excessive IMS requests, cache thrashing and other problems.
The downloadFinished() method was responsible for the job clean up, but
that asynchronous method is not called when the Downloader job quits
before the call can be fired. This early termination happens when, for
example, the job finishes while still inside the start() method (e.g., a
memory hit with no async ACLs to check). It also happens if an exception
is thrown while the job is running under async call protections.
Ensure the cleanup happens regardless of the job path to finish.
Alex Rousskov [Thu, 6 Oct 2016 22:05:50 +0000 (16:05 -0600)]
Fix known "concurrent c_str()s" violations of SBuf API.
The second c_str() call destroys the buffer still being used by the
first c_str() result, leading to many "Invalid read of size N" errors.
IMO, we must instead fix SBuf to make similar violations unlikely, but
there is currently no squid-dev consensus on whether and how to do that.
See "[RFC] Support concurrent SBuf::c_str() calls" thread on squid-dev.
Amos Jeffries [Thu, 6 Oct 2016 21:02:32 +0000 (10:02 +1300)]
Fix header name mismatching after rev.14870
When a mime header set contains two custom headers and one
name is the prefix for the other the name lookup using a
fixed length for String comparison can wrongly match the
longer header as being equal to the shorter one, since only
the identical prefix portion is compared.
To avoid this we must check that the lengths are also matching.
This also improves performance very slightly as the common
case for custom headers is to have an "X-" prefix which is
slower to compare than total length. Headers having same
length and same prefix is quite rare.
Alex Rousskov [Thu, 6 Oct 2016 00:05:38 +0000 (18:05 -0600)]
Hide OpenSSL tricks from Valgrind far-reaching initialization errors.
This change has no effect unless ./configured --with-valgrind-debug.
OpenSSL, including its Assembly code, contains many optimizations and
timing defenses that Valgrind misinterprets as uninitialized value
usage. Most of those tricks can be disabled by #defining PURIFY when
building OpenSSL, but some are not protected with PURIFY and most
OpenSSL libraries are (and should be) built without that #define.
To make matters worse, once Valgrind misdetects uninitialized memory, it
will complain about every usage of that memory. Those complaints create
a lot of noise, complicate triage, and effectively mask true bugs.
AFAICT, they cannot be suppressed by listing the source of that memory.
For example, this OpenSSL Assembly trick:
Uninitialised value was created by a stack allocation
at 0x556C2F7: aesni_cbc_encrypt (aesni-x86_64.s:2081)
Triggers many false errors like this one:
Conditional jump or move depends on uninitialised value(s)
by 0x750838: Debug::Finish()
by 0x942E68: Http::One::ResponseParser::parse(SBuf const&)
...
This change marks OpenSSL-returned decrypted bytes as initialized. This
might miss some true OpenSSL bugs, but we should focus on Squid bugs.
Alex Rousskov [Wed, 5 Oct 2016 04:24:28 +0000 (22:24 -0600)]
Fixed "Invalid read of size 1" bug in non-standard HTTP header search.
Valgrind error report:
Invalid read of size 1
at strcasecmp
by String::caseCmp(char const*) const
by HttpHeader::getByNameIfPresent(char const*, int, String&)
by HttpHeader::getByNameIfPresent(SBuf const&, String&)
by HttpHeader::getByName(SBuf const&) const
by assembleVaryKey(String&, SBuf&, HttpRequest const&)
...
The bug is probably not specific to Vary assembly and may have been
present since r14285 (gperf perfect hash refactoring).
HTTP/1.1: handle syntactically valid requests with unsupported HTTP versions
Before this change, when a syntactically valid HTTP/1 request indicated
HTTP major version 2, Squid mangled and forwarded the request as an
HTTP/1 message. Since Squid does not and cannot correctly interpret an
HTTP/1 request using HTTP/2 rules, returning an error and closing the
connection appears to be the only correct action possible.
If a version label matches the "HTTP/" 1*DIGIT "." 1*DIGIT pattern from
RFC 2616 it should not be handled as 0.9 syntax. All unacceptible
versions that begin with "HTTP/" should get a 505.
To be compliant with RFC 7230 as well:
- versions 1.2 thru 1.9 accept and handle normally. That is a SHOULD
requirement in RFC 7230 section 2.6 final paragraph.
- other single-digit versions should get the 505 error.
- versions with multiple digits should get the 505 error.
Amos Jeffries [Mon, 3 Oct 2016 04:33:08 +0000 (17:33 +1300)]
Convert DNS shutdown to use a registered runner
This patch adds a Runner to manage the DNS component state on shutdown
(and the matching reconfigure port closures). The actions taken on
reconfigure and shutdown are not changed, just their timing.
Visible differences are now that Squid logs when DNS ports are being
closed (and the reason), also that the still-open FD table report no
longer lists the DNS listening FD as being open on shutdown when
comm_exit() is called and forces all fd_table entries to close.
NP: I have not moved the Dns::Init() operations to the runner at this
stage because it needs some deeper analysis and redesign as to which
Squid processes DNS is enabled/initialized. Currently everything from
coordinator to Diskers enable the internal-DNS state.
One BUG found but not fixed:
DNS sockets being closed during reconfigure produces a race between
any already active connections (or ones received between closing DNS
sockets and server listening sockets) and the reconfigure completing
(Runner syncConfig() being run). Transactions which loose this race
will produce DNS timeouts (or whatever the caller set) as the queries
never get queued to be re-tried after the DNS sockets are re-opened.
We now seem to have had several patches successfully use members
declared with default values (C++11 feature) and/or with the
"*this = Foo();" shortcut for a reset/clear method.
So I think we can start using these to replace old C-style
initialization and clear() functions.
This patch begins by replacing the Config2 use of memset(). I for one am
constantly mistaking which of the Config objects has memset() applied to
it at the global level when reconfigure happens. Now we do not need to
care, each object handles its own clearing one way or another.