safe_free(s->clientca);
s->clientca = xstrdup(token + 9);
} else if (strncmp(token, "cafile=", 7) == 0) {
+ debugs(3, DBG_PARSE_NOTE(1), "UPGRADE WARNING: '" << token << "' is deprecated " <<
+ "in " << cfg_directive << ". Use 'tls-cafile=' instead.");
s->secure.parse(token);
} else if (strncmp(token, "capath=", 7) == 0) {
s->secure.parse(token);
parse_port_option(s, token);
}
+#if USE_OPENSSL
+ // if clientca has been defined but not cafile, then use it to verify
+ // but if cafile has been defined, only use that to verify
+ if (s->clientca && !s->secure.caFiles.size())
+ s->secure.caFiles.emplace_back(SBuf(s->clientca));
+#endif
+
if (s->transport.protocol == AnyP::PROTO_HTTPS) {
s->secure.encryptTransport = true;
#if USE_OPENSSL
clientca= File containing the list of CAs to use when
requesting a client certificate.
- cafile= File containing additional CA certificates to
- use when verifying client certificates. If unset
- clientca will be used.
+ tls-cafile= PEM file containing CA certificates to use when verifying
+ client certificates. If not configured clientca will be
+ used. May be repeated to load multiple files.
capath= Directory containing additional CA certificates
and CRL lists to use when verifying client certificates.
+ Requires OpenSSL or LibreSSL.
crlfile= File of additional CRL lists to use when verifying
the client certificate, in addition to CRLs stored in
clientca= File containing the list of CAs to use when
requesting a client certificate.
- cafile= File containing additional CA certificates to
- use when verifying client certificates. If unset
- clientca will be used.
+ tls-cafile= PEM file containing CA certificates to use when verifying
+ client certificates. If not configured clientca will be
+ used. May be repeated to load multiple files.
capath= Directory containing additional CA certificates
and CRL lists to use when verifying client certificates.
+ Requires OpenSSL or LibreSSL.
crlfile= File of additional CRL lists to use when verifying
the client certificate, in addition to CRLs stored in
See the OpenSSL SSL_CTX_set_options documentation for a
more complete list.
- cafile=... A file containing additional CA certificates to use
- when verifying the peer certificate.
-
- capath=... A directory containing additional CA certificates to
+ cafile= PEM file containing CA certificates to use when verifying
+ the peer certificate. May be repeated to load multiple files.
+
+ capath= A directory containing additional CA certificates to
use when verifying the peer certificate.
+ Requires OpenSSL or LibreSSL.
crlfile=... A certificate revocation list file to use when
verifying the peer certificate.
See the OpenSSL SSL_CTX_set_options documentation for a
more complete list.
- sslcafile=... A file containing additional CA certificates to use
- when verifying the peer certificate.
+ tls-cafile= PEM file containing CA certificates to use when verifying
+ the peer certificate. May be repeated to load multiple files.
sslcapath=... A directory containing additional CA certificates to
use when verifying the peer certificate.
+ Requires OpenSSL or LibreSSL.
sslcrlfile=... A certificate revocation list file to use when
verifying the peer certificate.
more complete list. Options relevant only to SSLv2 are
not supported.
- tls-cafile=... A PEM file containing additional CA certificates to use
- when verifying the icap server certificate. Used
- to specify intermediate CA certificate(s) if not sent
- by the server. Or the full CA chain for the server
- when using the NO_DEFAULT_CA flag.
+ tls-cafile= PEM file containing CA certificates to use when verifying
+ the icap server certificate.
+ Use to specify intermediate CA certificate(s) if not sent
+ by the server. Or the full CA chain for the server when
+ using the NO_DEFAULT_CA flag.
+ May be repeated to load multiple files.
tls-capath=... A directory containing additional CA certificates to
use when verifying the icap server certificate.
+ Requires OpenSSL or LibreSSL.
tls-crlfile=... A certificate revocation list file to use when
verifying the icap server certificate.
typedef SSL_CTX* ContextPointer;
#elif USE_GNUTLS
-typedef gnutls_certificate_credentials_t* ContextPointer;
+typedef gnutls_certificate_credentials_t ContextPointer;
#else
// use void* so we can check against NULL
certFile(p.certFile),
privateKeyFile(p.privateKeyFile),
sslOptions(p.sslOptions),
- caFile(p.caFile),
caDir(p.caDir),
crlFile(p.crlFile),
sslCipher(p.sslCipher),
sslDomain(p.sslDomain),
parsedOptions(p.parsedOptions),
parsedFlags(p.parsedFlags),
+ caFiles(p.caFiles),
parsedCrl(p.parsedCrl),
sslVersion(p.sslVersion),
encryptTransport(p.encryptTransport)
} else if (strncmp(token, "cipher=", 7) == 0) {
sslCipher = SBuf(token + 7);
} else if (strncmp(token, "cafile=", 7) == 0) {
- caFile = SBuf(token + 7);
+ caFiles.emplace_back(SBuf(token + 7));
} else if (strncmp(token, "capath=", 7) == 0) {
caDir = SBuf(token + 7);
+#if !USE_OPENSSL
+ debugs(3, DBG_PARSE_NOTE(1), "WARNING: capath= option requires --with-openssl.");
+#endif
} else if (strncmp(token, "crlfile=", 8) == 0) {
crlFile = SBuf(token + 8);
loadCrlFile();
if (!sslCipher.isEmpty())
p->appendf(" %scipher=" SQUIDSBUFPH, pfx, SQUIDSBUFPRINT(sslCipher));
- if (!caFile.isEmpty())
- p->appendf(" %scafile=" SQUIDSBUFPH, pfx, SQUIDSBUFPRINT(caFile));
+ for (auto i : caFiles) {
+ p->appendf(" %scafile=" SQUIDSBUFPH, pfx, SQUIDSBUFPRINT(i));
+ }
if (!caDir.isEmpty())
p->appendf(" %scapath=" SQUIDSBUFPH, pfx, SQUIDSBUFPRINT(caDir));
Security::ContextPointer
Security::PeerOptions::createClientContext(bool setOptions)
{
- Security::ContextPointer t = NULL;
+ Security::ContextPointer t = nullptr;
updateTlsVersionLimits();
+
#if USE_OPENSSL
// XXX: temporary performance regression. c_str() data copies and prevents this being a const method
t = sslCreateClientContext(certFile.c_str(), privateKeyFile.c_str(), sslCipher.c_str(),
- (setOptions ? parsedOptions : 0), parsedFlags,
- caFile.c_str(), caDir.c_str());
+ (setOptions ? parsedOptions : 0), parsedFlags);
#endif
- updateContextCrl(t);
+ if (t) {
+ updateContextCa(t);
+ updateContextCrl(t);
+ }
return t;
}
#endif
}
+void
+Security::PeerOptions::updateContextCa(Security::ContextPointer &ctx)
+{
+ debugs(83, 8, "Setting CA certificate locations.");
+
+ for (auto i : caFiles) {
+#if USE_OPENSSL
+ if (!SSL_CTX_load_verify_locations(ctx, i.c_str(), caDir.c_str())) {
+ const int ssl_error = ERR_get_error();
+ debugs(83, DBG_IMPORTANT, "WARNING: Ignoring error setting CA certificate locations: " << ERR_error_string(ssl_error, NULL));
+ }
+#elif USE_GNUTLS
+ if (gnutls_certificate_set_x509_trust_file(ctx, i.c_str(), GNUTLS_X509_FMT_PEM) < 0) {
+ debugs(83, DBG_IMPORTANT, "WARNING: Ignoring error setting CA certificate location: " << i);
+ }
+#endif
+ }
+
+ if ((parsedFlags & SSL_FLAG_NO_DEFAULT_CA))
+ return;
+
+#if USE_OPENSSL
+ if (!SSL_CTX_set_default_verify_paths(ctx)) {
+ const int ssl_error = ERR_get_error();
+ debugs(83, DBG_IMPORTANT, "WARNING: Ignoring error setting default trusted CA : "
+ << ERR_error_string(ssl_error, NULL));
+ }
+#elif USE_GNUTLS
+ if (gnutls_certificate_set_x509_system_trust(ctx) != GNUTLS_E_SUCCESS) {
+ debugs(83, DBG_IMPORTANT, "WARNING: Ignoring error setting default trusted CA.");
+ }
+#endif
+}
+
void
Security::PeerOptions::updateContextCrl(Security::ContextPointer &ctx)
{
/// sync the context options with tls-min-version=N configuration
void updateTlsVersionLimits();
+ /// setup the CA details for the given context
+ void updateContextCa(Security::ContextPointer &);
+
/// setup the CRL details for the given context
void updateContextCrl(Security::ContextPointer &);
SBuf certFile; ///< path of file containing PEM format X509 certificate
SBuf privateKeyFile; ///< path of file containing private key in PEM format
SBuf sslOptions; ///< library-specific options string
- SBuf caFile; ///< path of file containing trusted Certificate Authority
SBuf caDir; ///< path of directory containing a set of trusted Certificate Authorities
SBuf crlFile; ///< path of file containing Certificate Revoke List
long parsedOptions; ///< parsed value of sslOptions
long parsedFlags; ///< parsed value of sslFlags
+ std::list<SBuf> caFiles; ///< paths of files containing trusted Certificate Authority
Security::CertRevokeList parsedCrl; ///< CRL to use when verifying the remote end certificate
private:
}
}
- debugs(83, 9, "Setting CA certificate locations.");
-
- const char *cafile = port.secure.caFile.isEmpty() ? port.clientca : port.secure.caFile.c_str();
- if ((cafile || !port.secure.caDir.isEmpty()) && !SSL_CTX_load_verify_locations(sslContext, cafile, port.secure.caDir.c_str())) {
- ssl_error = ERR_get_error();
- debugs(83, DBG_IMPORTANT, "WARNING: Ignoring error setting CA certificate locations: " << ERR_error_string(ssl_error, NULL));
- }
-
- if (!(port.secure.parsedFlags & SSL_FLAG_NO_DEFAULT_CA) &&
- !SSL_CTX_set_default_verify_paths(sslContext)) {
- ssl_error = ERR_get_error();
- debugs(83, DBG_IMPORTANT, "WARNING: Ignoring error setting default CA certificate location: " << ERR_error_string(ssl_error, NULL));
- }
+ port.secure.updateContextCa(sslContext);
if (port.clientCA.get()) {
ERR_clear_error();
#endif
SSL_CTX *
-sslCreateClientContext(const char *certfile, const char *keyfile, const char *cipher, long options, long fl, const char *CAfile, const char *CApath)
+sslCreateClientContext(const char *certfile, const char *keyfile, const char *cipher, long options, long fl)
{
ssl_initialize();
SSL_CTX_set_verify(sslContext, SSL_VERIFY_PEER | SSL_VERIFY_FAIL_IF_NO_PEER_CERT, ssl_verify_cb);
}
- debugs(83, 9, "Setting CA certificate locations.");
-
- if ((*CAfile || *CApath) && !SSL_CTX_load_verify_locations(sslContext, CAfile, CApath)) {
- const int ssl_error = ERR_get_error();
- debugs(83, DBG_IMPORTANT, "WARNING: Ignoring error setting CA certificate locations: " << ERR_error_string(ssl_error, NULL));
- }
-
- if (!(fl & SSL_FLAG_NO_DEFAULT_CA) &&
- !SSL_CTX_set_default_verify_paths(sslContext)) {
- const int ssl_error = ERR_get_error();
- debugs(83, DBG_IMPORTANT, "WARNING: Ignoring error setting default CA certificate location: " << ERR_error_string(ssl_error, NULL));
- }
-
#if defined(TLSEXT_TYPE_next_proto_neg)
SSL_CTX_set_next_proto_select_cb(sslContext, &ssl_next_proto_cb, NULL);
#endif
SSL_CTX *sslCreateServerContext(AnyP::PortCfg &port);
/// \ingroup ServerProtocolSSLAPI
-SSL_CTX *sslCreateClientContext(const char *certfile, const char *keyfile, const char *cipher, long options, long flags, const char *CAfile, const char *CApath);
+SSL_CTX *sslCreateClientContext(const char *certfile, const char *keyfile, const char *cipher, long options, long flags);
/// \ingroup ServerProtocolSSLAPI
int ssl_read_method(int, char *, int);
void Security::PeerOptions::parse(char const*) STUB
Security::ContextPointer Security::PeerOptions::createClientContext(bool) STUB_RETVAL(NULL)
void Security::PeerOptions::updateTlsVersionLimits() STUB
+void Security::PeerOptions::updateContextCa(Security::ContextPointer &) STUB
void Security::PeerOptions::updateContextCrl(Security::ContextPointer &) STUB
void Security::PeerOptions::dumpCfg(Packable*, char const*) const STUB
long Security::PeerOptions::parseOptions() STUB_RETVAL(0)
bool CertError::operator != (const CertError &ce) const STUB_RETVAL(false)
} // namespace Ssl
SSL_CTX *sslCreateServerContext(AnyP::PortCfg &port) STUB_RETVAL(NULL)
-SSL_CTX *sslCreateClientContext(const char *certfile, const char *keyfile, const char *cipher, long options, const char *flags, const char *CAfile, const char *CApath) STUB_RETVAL(NULL)
+SSL_CTX *sslCreateClientContext(const char *certfile, const char *keyfile, const char *cipher, long options, const char *flags) STUB_RETVAL(NULL)
int ssl_read_method(int, char *, int) STUB_RETVAL(0)
int ssl_write_method(int, const char *, int) STUB_RETVAL(0)
void ssl_shutdown_method(SSL *ssl) STUB