From: Amos Jeffries Date: Fri, 27 Mar 2015 14:12:17 +0000 (-0700) Subject: Use Security::PeerOptions in AnyP::PortCfg for basic TLS config X-Git-Tag: merge-candidate-3-v1~38^2~21^2~13 X-Git-Url: http://git.ipfire.org/?a=commitdiff_plain;h=9a622f3eb79658cde733cdecf2aa6419a64fcf86;p=thirdparty%2Fsquid.git Use Security::PeerOptions in AnyP::PortCfg for basic TLS config --- diff --git a/src/anyp/PortCfg.cc b/src/anyp/PortCfg.cc index 1c69394cce..a4facffded 100644 --- a/src/anyp/PortCfg.cc +++ b/src/anyp/PortCfg.cc @@ -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) { diff --git a/src/anyp/PortCfg.h b/src/anyp/PortCfg.h index ccaede26f7..a2b3def950 100644 --- a/src/anyp/PortCfg.h +++ b/src/anyp/PortCfg.h @@ -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 }; diff --git a/src/cache_cf.cc b/src/cache_cf.cc index 69652d2bc1..485fb5f1b0 100644 --- a/src/cache_cf.cc +++ b/src/cache_cf.cc @@ -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::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 diff --git a/src/security/PeerOptions.cc b/src/security/PeerOptions.cc index 7e9fba6d3c..9aa8706fb0 100644 --- a/src/security/PeerOptions.cc +++ b/src/security/PeerOptions.cc @@ -20,6 +20,23 @@ 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 << "'"); } } diff --git a/src/security/PeerOptions.h b/src/security/PeerOptions.h index e50184f0b4..15510c9088 100644 --- a/src/security/PeerOptions.h +++ b/src/security/PeerOptions.h @@ -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 *); diff --git a/src/ssl/support.cc b/src/ssl/support.cc index 2223620830..300dc8b14c 100644 --- a/src/ssl/support.cc +++ b/src/ssl/support.cc @@ -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; }