]> git.ipfire.org Git - thirdparty/squid.git/commitdiff
Use Security::PeerOptions in AnyP::PortCfg for basic TLS config
authorAmos Jeffries <squid3@treenet.co.nz>
Fri, 27 Mar 2015 14:12:17 +0000 (07:12 -0700)
committerAmos Jeffries <squid3@treenet.co.nz>
Fri, 27 Mar 2015 14:12:17 +0000 (07:12 -0700)
src/anyp/PortCfg.cc
src/anyp/PortCfg.h
src/cache_cf.cc
src/security/PeerOptions.cc
src/security/PeerOptions.h
src/ssl/support.cc

index 1c69394cce3d2609b24a2bcd896ed81591294f7d..a4facffdedcf6722e43db011ce4813bac10b7aa5 100644 (file)
@@ -44,15 +44,8 @@ AnyP::PortCfg::PortCfg() :
     disable_pmtu_discovery(0),
     listenConn()
 #if USE_OPENSSL
-    ,cert(NULL),
-    key(NULL),
-    version(0),
-    cipher(NULL),
-    options(NULL),
+    ,
     clientca(NULL),
-    cafile(NULL),
-    capath(NULL),
-    crlfile(NULL),
     dhfile(NULL),
     sslContextSessionId(NULL),
     generateHostCertificates(false),
@@ -66,9 +59,7 @@ AnyP::PortCfg::PortCfg() :
     clientVerifyCrls(),
     clientCA(),
     dhParams(),
-    contextMethod(),
-    sslContextFlags(0),
-    sslOptions(0)
+    contextMethod()
 #endif
 {
     memset(&tcp_keepalive, 0, sizeof(tcp_keepalive));
@@ -85,14 +76,7 @@ AnyP::PortCfg::~PortCfg()
     safe_free(defaultsite);
 
 #if USE_OPENSSL
-    safe_free(cert);
-    safe_free(key);
-    safe_free(cipher);
-    safe_free(options);
     safe_free(clientca);
-    safe_free(cafile);
-    safe_free(capath);
-    safe_free(crlfile);
     safe_free(dhfile);
     safe_free(sslContextSessionId);
 #endif
@@ -117,29 +101,13 @@ AnyP::PortCfg::clone() const
     b->ftp_track_dirs = ftp_track_dirs;
     b->disable_pmtu_discovery = disable_pmtu_discovery;
     b->tcp_keepalive = tcp_keepalive;
+    b->secure = secure;
 
 #if USE_OPENSSL
-    if (cert)
-        b->cert = xstrdup(cert);
-    if (key)
-        b->key = xstrdup(key);
-    b->version = version;
-    if (cipher)
-        b->cipher = xstrdup(cipher);
-    if (options)
-        b->options = xstrdup(options);
     if (clientca)
         b->clientca = xstrdup(clientca);
-    if (cafile)
-        b->cafile = xstrdup(cafile);
-    if (capath)
-        b->capath = xstrdup(capath);
-    if (crlfile)
-        b->crlfile = xstrdup(crlfile);
     if (dhfile)
         b->dhfile = xstrdup(dhfile);
-    b->sslflags = sslflags;
-    b->sslContextFlags = sslContextFlags;
     if (sslContextSessionId)
         b->sslContextSessionId = xstrdup(sslContextSessionId);
 
@@ -158,8 +126,8 @@ AnyP::PortCfg::clone() const
 void
 AnyP::PortCfg::configureSslServerContext()
 {
-    if (cert)
-        Ssl::readCertChainAndPrivateKeyFromFiles(signingCert, signPkey, certsToChain, cert, key);
+    if (!secure.certFile.isEmpty())
+        Ssl::readCertChainAndPrivateKeyFromFiles(signingCert, signPkey, certsToChain, secure.certFile.c_str(), secure.privateKeyFile.c_str());
 
     if (!signingCert) {
         char buf[128];
@@ -177,8 +145,8 @@ AnyP::PortCfg::configureSslServerContext()
         fatalf("Unable to generate signing SSL certificate for untrusted sites for %s_port %s", AnyP::ProtocolType_str[transport.protocol], s.toUrl(buf, sizeof(buf)));
     }
 
-    if (crlfile)
-        clientVerifyCrls.reset(Ssl::loadCrl(crlfile, sslContextFlags));
+    if (!secure.crlFile.isEmpty())
+        clientVerifyCrls.reset(Ssl::loadCrl(secure.crlFile.c_str(), secure.parsedFlags));
 
     if (clientca) {
         clientCA.reset(SSL_load_client_CA_file(clientca));
@@ -187,16 +155,13 @@ AnyP::PortCfg::configureSslServerContext()
         }
     }
 
-    contextMethod = Ssl::contextMethod(version);
+    contextMethod = Ssl::contextMethod(secure.sslVersion);
     if (!contextMethod)
         fatalf("Unable to compute context method to use");
 
     if (dhfile)
         dhParams.reset(Ssl::readDHParams(dhfile));
 
-    sslContextFlags = Security::ParseFlags(sslflags);
-    sslOptions = Security::ParseOptions(options);
-
     staticSslContext.reset(sslCreateServerContext(*this));
 
     if (!staticSslContext) {
index ccaede26f7a480a59358382b03c92eb74bb836c2..a2b3def9505bc45283777b293149dfc7cfca10a5 100644 (file)
@@ -14,6 +14,7 @@
 #include "anyp/TrafficMode.h"
 #include "comm/Connection.h"
 #include "SBuf.h"
+#include "security/PeerOptions.h"
 
 #if USE_OPENSSL
 #include "ssl/gadgets.h"
@@ -68,18 +69,12 @@ public:
      */
     Comm::ConnectionPointer listenConn;
 
+    /// TLS configuration options for this listening port
+    Security::PeerOptions secure;
+
 #if USE_OPENSSL
-    char *cert;
-    char *key;
-    int version;
-    char *cipher;
-    char *options;
     char *clientca;
-    char *cafile;
-    char *capath;
-    char *crlfile;
     char *dhfile;
-    SBuf sslflags;
     char *sslContextSessionId; ///< "session id context" for staticSslContext
     bool generateHostCertificates; ///< dynamically make host cert for sslBump
     size_t dynamicCertMemCacheSize; ///< max size of generated certificates memory cache
@@ -95,8 +90,6 @@ public:
     Ssl::X509_NAME_STACK_Pointer clientCA; ///< CA certificates to use when verifying client certificates
     Ssl::DH_Pointer dhParams; ///< DH parameters for temporary/ephemeral DH key exchanges
     Ssl::ContextMethod contextMethod; ///< The context method (SSL_METHOD) to use when creating certificates
-    long sslContextFlags; ///< flags modifying the use of SSL
-    long sslOptions; ///< SSL engine options
 #endif
 };
 
index 69652d2bc176d431a6a05b95cff59ab32cc8850e..485fb5f1b0d2be5069e0030e81f2974c3c2e7c73 100644 (file)
@@ -3569,44 +3569,37 @@ parse_port_option(AnyP::PortCfgPointer &s, char *token)
         }
 #if USE_OPENSSL
     } else if (strcmp(token, "sslBump") == 0) {
-        debugs(3, DBG_CRITICAL, "WARNING: '" << token << "' is deprecated " <<
+        debugs(3, DBG_PARSE_NOTE(1), "WARNING: '" << token << "' is deprecated " <<
                "in " << cfg_directive << ". Use 'ssl-bump' instead.");
         s->flags.tunnelSslBumping = true;
     } else if (strcmp(token, "ssl-bump") == 0) {
         s->flags.tunnelSslBumping = true;
     } else if (strncmp(token, "cert=", 5) == 0) {
-        safe_free(s->cert);
-        s->cert = xstrdup(token + 5);
+        s->secure.parse(token);
     } else if (strncmp(token, "key=", 4) == 0) {
-        safe_free(s->key);
-        s->key = xstrdup(token + 4);
+        s->secure.parse(token);
     } else if (strncmp(token, "version=", 8) == 0) {
-        s->version = xatoi(token + 8);
-        if (s->version < 1 || s->version > 4)
+        s->secure.parse(token);
+        if (s->secure.sslVersion < 1 || s->secure.sslVersion > 4)
             self_destruct();
     } else if (strncmp(token, "options=", 8) == 0) {
-        safe_free(s->options);
-        s->options = xstrdup(token + 8);
+        s->secure.parse(token);
     } else if (strncmp(token, "cipher=", 7) == 0) {
-        safe_free(s->cipher);
-        s->cipher = xstrdup(token + 7);
+        s->secure.parse(token);
     } else if (strncmp(token, "clientca=", 9) == 0) {
         safe_free(s->clientca);
         s->clientca = xstrdup(token + 9);
     } else if (strncmp(token, "cafile=", 7) == 0) {
-        safe_free(s->cafile);
-        s->cafile = xstrdup(token + 7);
+        s->secure.parse(token);
     } else if (strncmp(token, "capath=", 7) == 0) {
-        safe_free(s->capath);
-        s->capath = xstrdup(token + 7);
+        s->secure.parse(token);
     } else if (strncmp(token, "crlfile=", 8) == 0) {
-        safe_free(s->crlfile);
-        s->crlfile = xstrdup(token + 8);
+        s->secure.parse(token);
     } else if (strncmp(token, "dhparams=", 9) == 0) {
         safe_free(s->dhfile);
         s->dhfile = xstrdup(token + 9);
     } else if (strncmp(token, "sslflags=", 9) == 0) {
-        s->sslflags = SBuf(token + 9);
+        s->secure.parse(token+3);
     } else if (strncmp(token, "sslcontext=", 11) == 0) {
         safe_free(s->sslContextSessionId);
         s->sslContextSessionId = xstrdup(token + 11);
@@ -3619,6 +3612,8 @@ parse_port_option(AnyP::PortCfgPointer &s, char *token)
     } else if (strncmp(token, "dynamic_cert_mem_cache_size=", 28) == 0) {
         parseBytesOptionValue(&s->dynamicCertMemCacheSize, B_BYTES_STR, token + 28);
 #endif
+    } else if (strncmp(token, "tls-", 4) == 0) {
+        s->secure.parse(token+4);
     } else if (strcmp(token, "ftp-track-dirs") == 0) {
         s->ftp_track_dirs = true;
     } else {
@@ -3799,37 +3794,36 @@ dump_generic_port(StoreEntry * e, const char *n, const AnyP::PortCfgPointer &s)
 #if USE_OPENSSL
     if (s->flags.tunnelSslBumping)
         storeAppendPrintf(e, " ssl-bump");
+#endif
 
-    if (s->cert)
-        storeAppendPrintf(e, " cert=%s", s->cert);
+    if (!s->secure.certFile.isEmpty())
+        storeAppendPrintf(e, " tls-cert=" SQUIDSBUFPH, SQUIDSBUFPRINT(s->secure.certFile));
 
-    if (s->key)
-        storeAppendPrintf(e, " key=%s", s->key);
+    if (!s->secure.privateKeyFile.isEmpty() && s->secure.privateKeyFile != s->secure.certFile)
+        storeAppendPrintf(e, " tls-key=" SQUIDSBUFPH, SQUIDSBUFPRINT(s->secure.privateKeyFile));
 
-    if (s->version)
-        storeAppendPrintf(e, " version=%d", s->version);
+    if (s->secure.sslVersion)
+        storeAppendPrintf(e, " tls-version=%d", s->secure.sslVersion);
 
-    if (s->options)
-        storeAppendPrintf(e, " options=%s", s->options);
+    if (!s->secure.sslOptions.isEmpty())
+        storeAppendPrintf(e, " tls-options=" SQUIDSBUFPH, SQUIDSBUFPRINT(s->secure.sslOptions));
 
-    if (s->cipher)
-        storeAppendPrintf(e, " cipher=%s", s->cipher);
+    if (!s->secure.sslCipher.isEmpty())
+        storeAppendPrintf(e, " tls-cipher=" SQUIDSBUFPH, SQUIDSBUFPRINT(s->secure.sslCipher));
 
-    if (s->cafile)
-        storeAppendPrintf(e, " cafile=%s", s->cafile);
+    if (!s->secure.caFile.isEmpty())
+        storeAppendPrintf(e, " tls-cafile=" SQUIDSBUFPH, SQUIDSBUFPRINT(s->secure.caFile));
 
-    if (s->capath)
-        storeAppendPrintf(e, " capath=%s", s->capath);
+    if (!s->secure.caDir.isEmpty())
+        storeAppendPrintf(e, " tls-capath=" SQUIDSBUFPH, SQUIDSBUFPRINT(s->secure.caDir));
 
-    if (s->crlfile)
-        storeAppendPrintf(e, " crlfile=%s", s->crlfile);
+    if (!s->secure.crlFile.isEmpty())
+        storeAppendPrintf(e, " tls-crlfile=" SQUIDSBUFPH, SQUIDSBUFPRINT(s->secure.crlFile));
 
+#if USE_OPENSSL
     if (s->dhfile)
         storeAppendPrintf(e, " dhparams=%s", s->dhfile);
 
-    if (!s->sslflags.isEmpty())
-        storeAppendPrintf(e, " sslflags=" SQUIDSBUFPH, SQUIDSBUFPRINT(s->sslflags));
-
     if (s->sslContextSessionId)
         storeAppendPrintf(e, " sslcontext=%s", s->sslContextSessionId);
 
@@ -3839,6 +3833,9 @@ dump_generic_port(StoreEntry * e, const char *n, const AnyP::PortCfgPointer &s)
     if (s->dynamicCertMemCacheSize != std::numeric_limits<size_t>::max())
         storeAppendPrintf(e, "dynamic_cert_mem_cache_size=%lu%s\n", (unsigned long)s->dynamicCertMemCacheSize, B_BYTES_STR);
 #endif
+
+    if (!s->secure.sslFlags.isEmpty())
+        storeAppendPrintf(e, " tls-flags=" SQUIDSBUFPH, SQUIDSBUFPRINT(s->secure.sslFlags));
 }
 
 static void
index 7e9fba6d3c8c355d56475bb52530dfbf5344f587..9aa8706fb0f931b88b4da286087e4bb35acdd0b4 100644 (file)
 
 Security::PeerOptions Security::ProxyOutgoingConfig;
 
+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),
+    sslFlags(p.sslFlags),
+    sslDomain(p.sslDomain),
+    parsedOptions(p.parsedOptions),
+    parsedFlags(p.parsedFlags),
+    sslVersion(p.sslVersion),
+    encryptTransport(p.encryptTransport)
+{
+}
+
 void
 Security::PeerOptions::parse(const char *token)
 {
@@ -30,7 +47,7 @@ Security::PeerOptions::parse(const char *token)
     } else if (strncmp(token, "key=", 4) == 0) {
         privateKeyFile = SBuf(token + 4);
         if (certFile.isEmpty()) {
-            debugs(0, DBG_PARSE_NOTE(1), "WARNING: cert= option needs to be set before key= is used.");
+            debugs(3, DBG_PARSE_NOTE(1), "WARNING: cert= option needs to be set before key= is used.");
             certFile = privateKeyFile;
         }
     } else if (strncmp(token, "version=", 8) == 0) {
@@ -53,12 +70,14 @@ Security::PeerOptions::parse(const char *token)
         crlFile = SBuf(token + 8);
     } else if (strncmp(token, "flags=", 6) == 0) {
         if (parsedFlags != 0) {
-            debugs(0, DBG_PARSE_NOTE(1), "WARNING: Overwriting flags=" << sslFlags << " with " << SBuf(token + 6));
+            debugs(3, DBG_PARSE_NOTE(1), "WARNING: Overwriting flags=" << sslFlags << " with " << SBuf(token + 6));
         }
         sslFlags = SBuf(token + 6);
         parsedFlags = Security::ParseFlags(sslFlags);
     } else if (strncmp(token, "domain=", 7) == 0) {
         sslDomain = SBuf(token + 7);
+    } else {
+        debugs(3, DBG_CRITICAL, "ERROR: Unknown TLS option '" << token << "'");
     }
 }
 
index e50184f0b4be26881bfc0f0d58a23e6705a911c3..15510c9088528991221cd3adefdd9713be85e69e 100644 (file)
@@ -21,6 +21,7 @@ class PeerOptions
 {
 public:
     PeerOptions() : parsedOptions(0), sslVersion(0), encryptTransport(false) {}
+    PeerOptions(const PeerOptions &);
 
     /// parse a TLS squid.conf option
     void parse(const char *);
index 2223620830f3a81829f1879a4ba0336989de59af..300dc8b14c803565b8f149e5da815435e90c2648 100644 (file)
@@ -542,12 +542,12 @@ static bool
 configureSslContext(SSL_CTX *sslContext, AnyP::PortCfg &port)
 {
     int ssl_error;
-    SSL_CTX_set_options(sslContext, port.sslOptions);
+    SSL_CTX_set_options(sslContext, port.secure.parsedOptions);
 
     if (port.sslContextSessionId)
         SSL_CTX_set_session_id_context(sslContext, (const unsigned char *)port.sslContextSessionId, strlen(port.sslContextSessionId));
 
-    if (port.sslContextFlags & SSL_FLAG_NO_SESSION_REUSE) {
+    if (port.secure.parsedFlags & SSL_FLAG_NO_SESSION_REUSE) {
         SSL_CTX_set_session_cache_mode(sslContext, SSL_SESS_CACHE_OFF);
     }
 
@@ -557,12 +557,12 @@ configureSslContext(SSL_CTX *sslContext, AnyP::PortCfg &port)
         SSL_CTX_set_quiet_shutdown(sslContext, 1);
     }
 
-    if (port.cipher) {
-        debugs(83, 5, "Using chiper suite " << port.cipher << ".");
+    if (!port.secure.sslCipher.isEmpty()) {
+        debugs(83, 5, "Using chiper suite " << port.secure.sslCipher << ".");
 
-        if (!SSL_CTX_set_cipher_list(sslContext, port.cipher)) {
+        if (!SSL_CTX_set_cipher_list(sslContext, port.secure.sslCipher.c_str())) {
             ssl_error = ERR_get_error();
-            debugs(83, DBG_CRITICAL, "ERROR: Failed to set SSL cipher suite '" << port.cipher << "': " << ERR_error_string(ssl_error, NULL));
+            debugs(83, DBG_CRITICAL, "ERROR: Failed to set SSL cipher suite '" << port.secure.sslCipher << "': " << ERR_error_string(ssl_error, NULL));
             return false;
         }
     }
@@ -572,13 +572,13 @@ configureSslContext(SSL_CTX *sslContext, AnyP::PortCfg &port)
 
     debugs(83, 9, "Setting CA certificate locations.");
 
-    const char *cafile = port.cafile ? port.cafile : port.clientca;
-    if ((cafile || port.capath) && !SSL_CTX_load_verify_locations(sslContext, cafile, port.capath)) {
+    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.sslContextFlags & SSL_FLAG_NO_DEFAULT_CA) &&
+    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));
@@ -588,7 +588,7 @@ configureSslContext(SSL_CTX *sslContext, AnyP::PortCfg &port)
         ERR_clear_error();
         SSL_CTX_set_client_CA_list(sslContext, port.clientCA.get());
 
-        if (port.sslContextFlags & SSL_FLAG_DELAYED_AUTH) {
+        if (port.secure.parsedFlags & SSL_FLAG_DELAYED_AUTH) {
             debugs(83, 9, "Not requesting client certificates until acl processing requires one");
             SSL_CTX_set_verify(sslContext, SSL_VERIFY_NONE, NULL);
         } else {
@@ -606,9 +606,9 @@ configureSslContext(SSL_CTX *sslContext, AnyP::PortCfg &port)
         }
 
 #if X509_V_FLAG_CRL_CHECK
-        if (port.sslContextFlags & SSL_FLAG_VERIFY_CRL_ALL)
+        if (port.secure.parsedFlags & SSL_FLAG_VERIFY_CRL_ALL)
             X509_STORE_set_flags(SSL_CTX_get_cert_store(sslContext), X509_V_FLAG_CRL_CHECK|X509_V_FLAG_CRL_CHECK_ALL);
-        else if (port.sslContextFlags & SSL_FLAG_VERIFY_CRL)
+        else if (port.secure.parsedFlags & SSL_FLAG_VERIFY_CRL)
             X509_STORE_set_flags(SSL_CTX_get_cert_store(sslContext), X509_V_FLAG_CRL_CHECK);
 #endif
 
@@ -621,7 +621,7 @@ configureSslContext(SSL_CTX *sslContext, AnyP::PortCfg &port)
         SSL_CTX_set_tmp_dh(sslContext, port.dhParams.get());
     }
 
-    if (port.sslContextFlags & SSL_FLAG_DONT_VERIFY_DOMAIN)
+    if (port.secure.parsedFlags & SSL_FLAG_DONT_VERIFY_DOMAIN)
         SSL_CTX_set_ex_data(sslContext, ssl_ctx_ex_index_dont_verify_domain, (void *) -1);
 
     setSessionCallbacks(sslContext);
@@ -632,22 +632,10 @@ configureSslContext(SSL_CTX *sslContext, AnyP::PortCfg &port)
 SSL_CTX *
 sslCreateServerContext(AnyP::PortCfg &port)
 {
-    int ssl_error;
-    SSL_CTX *sslContext;
-    const char *keyfile, *certfile;
-    certfile = port.cert;
-    keyfile = port.key;
-
     ssl_initialize();
+    SSL_CTX *sslContext = SSL_CTX_new(port.contextMethod);
 
-    if (!keyfile)
-        keyfile = certfile;
-
-    if (!certfile)
-        certfile = keyfile;
-
-    sslContext = SSL_CTX_new(port.contextMethod);
-
+    int ssl_error;
     if (sslContext == NULL) {
         ssl_error = ERR_get_error();
         debugs(83, DBG_CRITICAL, "ERROR: Failed to allocate SSL context: " << ERR_error_string(ssl_error, NULL));
@@ -656,14 +644,14 @@ sslCreateServerContext(AnyP::PortCfg &port)
 
     if (!SSL_CTX_use_certificate(sslContext, port.signingCert.get())) {
         ssl_error = ERR_get_error();
-        debugs(83, DBG_CRITICAL, "ERROR: Failed to acquire SSL certificate '" << certfile << "': " << ERR_error_string(ssl_error, NULL));
+        debugs(83, DBG_CRITICAL, "ERROR: Failed to acquire SSL certificate '" << port.secure.certFile << "': " << ERR_error_string(ssl_error, NULL));
         SSL_CTX_free(sslContext);
         return NULL;
     }
 
     if (!SSL_CTX_use_PrivateKey(sslContext, port.signPkey.get())) {
         ssl_error = ERR_get_error();
-        debugs(83, DBG_CRITICAL, "ERROR: Failed to acquire SSL private key '" << keyfile << "': " << ERR_error_string(ssl_error, NULL));
+        debugs(83, DBG_CRITICAL, "ERROR: Failed to acquire SSL private key '" << port.secure.privateKeyFile << "': " << ERR_error_string(ssl_error, NULL));
         SSL_CTX_free(sslContext);
         return NULL;
     }