Bug 5211: support.cc:355: "!filledCheck->sslErrors" assertion (#1044)
One master transaction may encounter several certificate
validation-related errors because Squid may need to validate several
server certificates for one connection and may even need to open several
server connections. Since 2012 commit
4fb72cb, ssl_verify_cb()
incorrectly assumed that no past errors were possible. The callback
started to assert when recent code changes (commit
e227da8?) improved
delivery of past errors to ACL checks.
While fixing this bug, we discovered that ServerBump::serverSession
ignored new TLS connection when Squid connected to another destination
after a failed TLS handshake. That stale value was then used to extract
stale information about past TLS errors. In some cases, that would
prevent Squid from hitting the now-fixed assertion. In other cases, it
could result in wrong sslproxy_cert_sign and sslproxy_cert_adapt
decisions. Now also fixed; see Ssl::ServerBump::attachServerSession().
A nil PeerConnector::check->sslErrors value may get stale because
PeerConnector::check is filled just once: sslError will remain nil
during the second validation pass (after PeerConnector fetches missing
intermediate certificates and revalidates), despite validation errors
discovered during the first pass. Today, ssl_verify_cb() does not really
use FilledChecklist::sslErrors preset by its PeerConnector, so a stale
value currently has no effect. Fixing this waiting-to-happen problem is
not trivial (we tried). A proper fix deserves a dedicated PR. Added XXX.
While working on these changes, we discovered that Squid implements two
mutually exclusive ssl_error (FilledChecklist::sslErrors) definitions:
* In sslproxy_cert_error context, ssl_error matches the last or current
error being examined by the sslproxy_cert_error code.
* In sslproxy_cert_sign and sslproxy_cert_adapt context, ssl_error
matches any previously observed validation error.
This change updates Squid documentation to reflect the above findings.
Unfortunately, it is not feasible to remove this unwanted directive
"sensitivity" without deprecating/replacing sslproxy_cert_error and
ssl_error: Selecting any one of the two ssl_error definitions above may
seriously (and silently) break existing configurations:
# If all-errors semantics is adopted for sslproxy_cert_error, then
# this configuration will start allowing certificates with _any_
# error as long as that certificate also has a minorError:
acl minorError ssl_error ...
sslproxy_cert_error allow minorError
# If last-error semantics is adopted for sslproxy_cert_sign, then
# this configuration will stop properly signing certificates that
# mimic self-signed real certificates if the very last error during
# that real certificate validation was _not_ certSelfSigned:
sslproxy_cert_sign signSelf ssl::certSelfSigned