Fixed (and renamed) Ssl::ReadX509Certificate() API (#1048)
This pointer-returning non-throwing function was used to load an unknown
number of certificates from a file. A nil result normally indicated the
end of the certificate sequence but also a certificate loading failure.
The caller could not distinguish the two nil-result outcomes without
OpenSSL error stack analysis, which is difficult to do correctly, and
which none of the callers bothered to do, resulting in some certificate
configuration errors silently ignored by Squid.
The adjusted API uses exceptions to report errors. A nil result is still
used to report the end of the certificate sequence. To help callers that
must have at least one certificate, one function is now dedicated to
loading required certificate(s) while a companion function is added to
load optional ones.
Avoid exponential growth in the number of changed functions by wrapping
callers inside the not-ready-to-throw code chains (that cannot be easily
converted) with try/catch-return-false blocks.
Also removed the need for Ssl::readCertFromMemory() by adding
Ssl::ReadOnlyBioTiedTo(). Functions reading things (from various input
sources) should be kept separately from functions creating input sources
(for various reading functions). Otherwise, we will end up creating a
lot more functions (at least readers*creators) with virtually no gain in
performance or convenience. OpenSSL BIO API exists specifically to
separate I/O mechanisms from I/O users. Use it to our advantage.
We now also clear old/stale OpenSSL error stack before performing the
certificate loading operation that may trigger one or more errors.
Also forget stale errno when forgetting OpenSSL errors. This reset
avoids misleading error reports based on stale errno values.
Also detail certificate loading errors, now that they are not ignored.
ReportSysError was added to avoid SysErrorDetail::NewIfAny() memory
allocations when reporting basic system call errors. Perhaps there is a
way to reuse SysErrorDetail here via (enhanced) Optional, but the
resulting complexity and the current SBuf-based reporting overheads do
not justify the reuse of "if errno then strerror(errno)" logic. We may
revisit this when Optional supports non-trivial classes.
Also moved most SysErrorDetail implementation details to the newly added
.cc file (to reduce user exposure), replacing strerror() with xstrerr().
ForgetErrors guts were moved from Security to Ssl because we cannot link
helpers with src/security (yet). We may have to refactor Security to
make such reuse possible in the future.