From: Amos Jeffries Date: Sat, 3 Oct 2015 05:26:00 +0000 (-0700) Subject: Shuffle CA verification config to libsecurity X-Git-Tag: SQUID_4_0_1~11^2~2 X-Git-Url: http://git.ipfire.org/gitweb.cgi?a=commitdiff_plain;h=86a84cc04d96f5a6582e7b8f9dbf50708f3e7d66;p=thirdparty%2Fsquid.git Shuffle CA verification config to libsecurity --- diff --git a/src/cache_cf.cc b/src/cache_cf.cc index 1dc49886cf..ff4473e652 100644 --- a/src/cache_cf.cc +++ b/src/cache_cf.cc @@ -3578,6 +3578,8 @@ parse_port_option(AnyP::PortCfgPointer &s, char *token) 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); @@ -3659,6 +3661,13 @@ parsePortCfg(AnyP::PortCfgPointer *head, const char *optionName) 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 diff --git a/src/cf.data.pre b/src/cf.data.pre index 672550ce88..df0cf87a31 100644 --- a/src/cf.data.pre +++ b/src/cf.data.pre @@ -1965,12 +1965,13 @@ DOC_START 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 @@ -2149,12 +2150,13 @@ DOC_START 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 @@ -2647,11 +2649,12 @@ DOC_START 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. @@ -3384,11 +3387,12 @@ DOC_START 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. @@ -8541,14 +8545,16 @@ DOC_START 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. diff --git a/src/security/Context.h b/src/security/Context.h index 84a59da25e..a3f28351f5 100644 --- a/src/security/Context.h +++ b/src/security/Context.h @@ -27,7 +27,7 @@ namespace Security { 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 diff --git a/src/security/PeerOptions.cc b/src/security/PeerOptions.cc index 2d2218bac0..a249090484 100644 --- a/src/security/PeerOptions.cc +++ b/src/security/PeerOptions.cc @@ -26,7 +26,6 @@ Security::PeerOptions::PeerOptions(const Security::PeerOptions &p) : certFile(p.certFile), privateKeyFile(p.privateKeyFile), sslOptions(p.sslOptions), - caFile(p.caFile), caDir(p.caDir), crlFile(p.crlFile), sslCipher(p.sslCipher), @@ -34,6 +33,7 @@ Security::PeerOptions::PeerOptions(const Security::PeerOptions &p) : sslDomain(p.sslDomain), parsedOptions(p.parsedOptions), parsedFlags(p.parsedFlags), + caFiles(p.caFiles), parsedCrl(p.parsedCrl), sslVersion(p.sslVersion), encryptTransport(p.encryptTransport) @@ -75,9 +75,12 @@ Security::PeerOptions::parse(const char *token) } 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(); @@ -117,8 +120,9 @@ Security::PeerOptions::dumpCfg(Packable *p, const char *pfx) const 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)); @@ -191,17 +195,20 @@ Security::PeerOptions::updateTlsVersionLimits() 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; } @@ -475,6 +482,40 @@ Security::PeerOptions::loadCrlFile() #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) { diff --git a/src/security/PeerOptions.h b/src/security/PeerOptions.h index db51c62c3a..5e78cc7292 100644 --- a/src/security/PeerOptions.h +++ b/src/security/PeerOptions.h @@ -37,6 +37,9 @@ public: /// 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 &); @@ -52,7 +55,6 @@ public: 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 @@ -65,6 +67,7 @@ public: long parsedOptions; ///< parsed value of sslOptions long parsedFlags; ///< parsed value of sslFlags + std::list caFiles; ///< paths of files containing trusted Certificate Authority Security::CertRevokeList parsedCrl; ///< CRL to use when verifying the remote end certificate private: diff --git a/src/ssl/support.cc b/src/ssl/support.cc index 2709294bda..23c992d1e4 100644 --- a/src/ssl/support.cc +++ b/src/ssl/support.cc @@ -576,19 +576,7 @@ configureSslContext(SSL_CTX *sslContext, AnyP::PortCfg &port) } } - 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(); @@ -712,7 +700,7 @@ ssl_next_proto_cb(SSL *s, unsigned char **out, unsigned char *outlen, const unsi #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(); @@ -782,19 +770,6 @@ sslCreateClientContext(const char *certfile, const char *keyfile, const char *ci 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 diff --git a/src/ssl/support.h b/src/ssl/support.h index e62a7b947f..75cb39ee24 100644 --- a/src/ssl/support.h +++ b/src/ssl/support.h @@ -90,7 +90,7 @@ typedef CbDataList CertErrors; 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); diff --git a/src/tests/stub_libsecurity.cc b/src/tests/stub_libsecurity.cc index c13b5e33ce..5fc2562e08 100644 --- a/src/tests/stub_libsecurity.cc +++ b/src/tests/stub_libsecurity.cc @@ -21,6 +21,7 @@ Security::PeerOptions Security::ProxyOutgoingConfig; 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) diff --git a/src/tests/stub_libsslsquid.cc b/src/tests/stub_libsslsquid.cc index 3c8fb35353..401cb7afc0 100644 --- a/src/tests/stub_libsslsquid.cc +++ b/src/tests/stub_libsslsquid.cc @@ -57,7 +57,7 @@ bool CertError::operator == (const CertError &ce) const STUB_RETVAL(false) 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