]> git.ipfire.org Git - thirdparty/squid.git/commitdiff
Shuffle CA verification config to libsecurity
authorAmos Jeffries <squid3@treenet.co.nz>
Sat, 3 Oct 2015 05:26:00 +0000 (22:26 -0700)
committerAmos Jeffries <squid3@treenet.co.nz>
Sat, 3 Oct 2015 05:26:00 +0000 (22:26 -0700)
src/cache_cf.cc
src/cf.data.pre
src/security/Context.h
src/security/PeerOptions.cc
src/security/PeerOptions.h
src/ssl/support.cc
src/ssl/support.h
src/tests/stub_libsecurity.cc
src/tests/stub_libsslsquid.cc

index 1dc49886cf83b80af61d865fb1c48e82e76074b0..ff4473e6524834c0c502f31584dbe0cd99e08555 100644 (file)
@@ -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
index 672550ce8894122a003e5b9e68de8c7019d08fc9..df0cf87a31515e4a044a19759e7ba802970a956e 100644 (file)
@@ -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.
index 84a59da25e51686b9564395bc9f7a1c81d12c1f5..a3f28351f5025ea49d19be2f15183c7eb6e76045 100644 (file)
@@ -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
index 2d2218bac092d3d1a965d4a1b8e64f6caeb13381..a2490904849f612145c733b93e23617ad44fe873 100644 (file)
@@ -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)
 {
index db51c62c3aabfcc7e138875ededbd518cb517b4c..5e78cc7292162a3285a086429a220d5108f2a039 100644 (file)
@@ -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<SBuf> caFiles;  ///< paths of files containing trusted Certificate Authority
     Security::CertRevokeList parsedCrl; ///< CRL to use when verifying the remote end certificate
 
 private:
index 2709294bdadbbd32c92bad419b6808982734a0e8..23c992d1e4bd804208ff80bb080ee2fc9febef0c 100644 (file)
@@ -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
index e62a7b947faf25a76441ed99d10a571264e6f91c..75cb39ee246c07aa399ffcd29b354c63d64e4e80 100644 (file)
@@ -90,7 +90,7 @@ typedef CbDataList<Ssl::CertError> 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);
index c13b5e33ce5e9e8db0df70bbc53092e470a981bd..5fc2562e080587d521fbe3b839c2b52c2c318023 100644 (file)
@@ -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)
index 3c8fb35353dd3cbb21f81de0c394875256640e1b..401cb7afc033fd85660a100b671ff55b3159e1fa 100644 (file)
@@ -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