From: Christos Tsantilas Date: Tue, 7 Oct 2014 14:11:12 +0000 (+0300) Subject: sslproxy_cert_sign_hash configuration option X-Git-Tag: SQUID_3_5_0_1~14 X-Git-Url: http://git.ipfire.org/?a=commitdiff_plain;h=3c26b00aa3a2d8b515af363d289113d5f4726049;p=thirdparty%2Fsquid.git sslproxy_cert_sign_hash configuration option Browser vendors will get rid of SSL certificates that use SHA-1 to generate the hash that is then signed by the CA. For example, Google Chrome will start to show an "insecure" sign for certificates that are valid after 1.1.2016 and will generate a warning page for certificates that are valid after 1.1.2017 [1], [2],[4]. Microsoft will block certificates with SHA-1 after 1.1.2017 [3]. This patch: 1) Add a new configuration option to select the signing hash for generated certificates: sslproxy_cert_sign_hash. 2) If sslproxy_cert_sign_hash is not set, then use the sha256 hash. [1] https://groups.google.com/a/chromium.org/forum/#!msg/blink-dev/2-R4XziFc7A/YO0ZSrX_X4wJ [2] https://code.google.com/p/chromium/issues/detail?id=401365 [3] http://blogs.technet.com/b/pki/archive/2013/11/12/sha1-deprecation-policy.aspx [4] http://googleonlinesecurity.blogspot.ch/2014/09/gradually-sunsetting-sha-1.html This is a Measurement Factory project --- diff --git a/src/SquidConfig.h b/src/SquidConfig.h index f69c336cc4..47dda24563 100644 --- a/src/SquidConfig.h +++ b/src/SquidConfig.h @@ -476,6 +476,7 @@ public: char *ssl_engine; int session_ttl; size_t sessionCacheSize; + char *certSignHash; } SSL; #endif diff --git a/src/cf.data.pre b/src/cf.data.pre index d19d6f5070..c6c8a484f5 100644 --- a/src/cf.data.pre +++ b/src/cf.data.pre @@ -2505,6 +2505,24 @@ DOC_START Sets the cache size to use for ssl session DOC_END +NAME: sslproxy_cert_sign_hash +IFDEF: USE_OPENSSL +DEFAULT: none +LOC: Config.SSL.certSignHash +TYPE: string +DOC_START + Sets the hashing algorithm to use when signing generated certificates. + Valid algorithm names depend on the OpenSSL library used. The following + names are usually available: sha1, sha256, sha512, and md5. Please see + your OpenSSL library manual for the available hashes. By default, Squids + that support this option use sha256 hashes. + + Squid does not forcefully purge cached certificates that were generated + with an algorithm other than the currently configured one. They remain + in the cache, subject to the regular cache eviction policy, and become + useful if the algorithm changes again. +DOC_END + NAME: ssl_bump IFDEF: USE_OPENSSL TYPE: sslproxy_ssl_bump diff --git a/src/client_side.cc b/src/client_side.cc index 4af2cc9bac..fbac89f885 100644 --- a/src/client_side.cc +++ b/src/client_side.cc @@ -4055,6 +4055,8 @@ void ConnStateData::buildSslCertGenerationParams(Ssl::CertificateProperties &cer certProperties.signWithPkey.resetAndLock(port->signPkey.get()); } signAlgorithm = certProperties.signAlgorithm; + + certProperties.signHash = Ssl::DefaultSignHash; } void diff --git a/src/ssl/crtd_message.cc b/src/ssl/crtd_message.cc index dc36ac5a3a..25b983c967 100644 --- a/src/ssl/crtd_message.cc +++ b/src/ssl/crtd_message.cc @@ -206,12 +206,21 @@ bool Ssl::CrtdMessage::parseRequest(Ssl::CertificateProperties &certProperties, i = map.find(Ssl::CrtdMessage::param_Sign); if (i != map.end()) { if ((certProperties.signAlgorithm = Ssl::certSignAlgorithmId(i->second.c_str())) == Ssl::algSignEnd) { - error = "Wrong signing algoritm: " + i->second; + error = "Wrong signing algoritm: "; + error += i->second; return false; } } else certProperties.signAlgorithm = Ssl::algSignTrusted; + i = map.find(Ssl::CrtdMessage::param_SignHash); + const char *signHashName = i != map.end() ? i->second.c_str() : SQUID_SSL_SIGN_HASH_IF_NONE; + if (!(certProperties.signHash = EVP_get_digestbyname(signHashName))) { + error = "Wrong signing hash: "; + error += signHashName; + return false; + } + if (!Ssl::readCertAndPrivateKeyFromMemory(certProperties.signWithX509, certProperties.signWithPkey, certs_part.c_str())) { error = "Broken signing certificate!"; return false; @@ -239,6 +248,8 @@ void Ssl::CrtdMessage::composeRequest(Ssl::CertificateProperties const &certProp body += "\n" + Ssl::CrtdMessage::param_SetValidBefore + "=on"; if (certProperties.signAlgorithm != Ssl::algSignEnd) body += "\n" + Ssl::CrtdMessage::param_Sign + "=" + certSignAlgorithm(certProperties.signAlgorithm); + if (certProperties.signHash) + body += "\n" + Ssl::CrtdMessage::param_SignHash + "=" + EVP_MD_name(certProperties.signHash); std::string certsPart; if (!Ssl::writeCertAndPrivateKeyToMemory(certProperties.signWithX509, certProperties.signWithPkey, certsPart)) @@ -256,3 +267,4 @@ const std::string Ssl::CrtdMessage::param_SetValidAfter(Ssl::CertAdaptAlgorithmS const std::string Ssl::CrtdMessage::param_SetValidBefore(Ssl::CertAdaptAlgorithmStr[algSetValidBefore]); const std::string Ssl::CrtdMessage::param_SetCommonName(Ssl::CertAdaptAlgorithmStr[algSetCommonName]); const std::string Ssl::CrtdMessage::param_Sign("Sign"); +const std::string Ssl::CrtdMessage::param_SignHash("SignHash"); diff --git a/src/ssl/crtd_message.h b/src/ssl/crtd_message.h index cdc1818c3c..d730d88e44 100644 --- a/src/ssl/crtd_message.h +++ b/src/ssl/crtd_message.h @@ -84,6 +84,8 @@ public: static const std::string param_SetCommonName; /// Parameter name for passing signing algorithm static const std::string param_Sign; + /// The signing hash to use + static const std::string param_SignHash; protected: enum ParseState { BEFORE_CODE, diff --git a/src/ssl/gadgets.cc b/src/ssl/gadgets.cc index 04d9f06f83..58337ddf02 100644 --- a/src/ssl/gadgets.cc +++ b/src/ssl/gadgets.cc @@ -221,7 +221,8 @@ Ssl::CertificateProperties::CertificateProperties(): setValidAfter(false), setValidBefore(false), setCommonName(false), - signAlgorithm(Ssl::algSignEnd) + signAlgorithm(Ssl::algSignEnd), + signHash(NULL) {} std::string & Ssl::CertificateProperties::dbKey() const @@ -255,6 +256,11 @@ std::string & Ssl::CertificateProperties::dbKey() const certKey.append(certSignAlgorithm(signAlgorithm)); } + if (signHash != NULL) { + certKey.append("+SignHash=", 10); + certKey.append(EVP_MD_name(signHash)); + } + return certKey; } @@ -434,11 +440,13 @@ static bool generateFakeSslCertificate(Ssl::X509_Pointer & certToStore, Ssl::EVP if (!ret) return false; + const EVP_MD *hash = properties.signHash ? properties.signHash : EVP_get_digestbyname(SQUID_SSL_SIGN_HASH_IF_NONE); + assert(hash); /*Now sign the request */ if (properties.signAlgorithm != Ssl::algSignSelf && properties.signWithPkey.get()) - ret = X509_sign(cert.get(), properties.signWithPkey.get(), EVP_sha1()); + ret = X509_sign(cert.get(), properties.signWithPkey.get(), hash); else //else sign with self key (self signed request) - ret = X509_sign(cert.get(), pkey.get(), EVP_sha1()); + ret = X509_sign(cert.get(), pkey.get(), hash); if (!ret) return false; diff --git a/src/ssl/gadgets.h b/src/ssl/gadgets.h index 928758e607..75a0c47044 100644 --- a/src/ssl/gadgets.h +++ b/src/ssl/gadgets.h @@ -34,6 +34,10 @@ typedef const SSL_METHOD * ContextMethod; typedef SSL_METHOD * ContextMethod; #endif +#if !defined(SQUID_SSL_SIGN_HASH_IF_NONE) +#define SQUID_SSL_SIGN_HASH_IF_NONE "sha256" +#endif + /** \ingroup SslCrtdSslAPI * Add SSL locking (a.k.a. reference counting) to TidyPointer @@ -234,6 +238,7 @@ public: bool setCommonName; ///< Replace the CN field of the mimicing subject with the given std::string commonName; ///< A CN to use for the generated certificate CertSignAlgorithm signAlgorithm; ///< The signing algorithm to use + const EVP_MD *signHash; ///< The signing hash to use /// Returns certificate database primary key. New fake certificates /// purge old fake certificates with the same key. std::string & dbKey() const; diff --git a/src/ssl/ssl_crtd.cc b/src/ssl/ssl_crtd.cc index 846e2a02bc..1e56b684ba 100644 --- a/src/ssl/ssl_crtd.cc +++ b/src/ssl/ssl_crtd.cc @@ -295,6 +295,9 @@ int main(int argc, char *argv[]) { Ssl::CertificateDb::check(db_path, max_db_size); } + // Initialize SSL subsystem + SSL_load_error_strings(); + SSLeay_add_ssl_algorithms(); // proccess request. for (;;) { char request[HELPER_INPUT_BUFFER]; diff --git a/src/ssl/support.cc b/src/ssl/support.cc index 0a498bfaa2..b6a4f38618 100644 --- a/src/ssl/support.cc +++ b/src/ssl/support.cc @@ -36,6 +36,8 @@ static void setSessionCallbacks(SSL_CTX *ctx); Ipc::MemMap *SslSessionCache = NULL; const char *SslSessionCacheName = "ssl_session_cache"; +const EVP_MD *Ssl::DefaultSignHash = NULL; + const char *Ssl::BumpModeStr[] = { "none", "client-first", @@ -718,6 +720,11 @@ ssl_initialize(void) fatalf("Your OpenSSL has no SSL engine support\n"); #endif + const char *defName = Config.SSL.certSignHash ? Config.SSL.certSignHash : SQUID_SSL_SIGN_HASH_IF_NONE; + Ssl::DefaultSignHash = EVP_get_digestbyname(defName); + if (!Ssl::DefaultSignHash) + fatalf("Sign hash '%s' is not supported\n", defName); + ssl_ex_index_server = SSL_get_ex_new_index(0, (void *) "server", NULL, NULL, NULL); ssl_ctx_ex_index_dont_verify_domain = SSL_CTX_get_ex_new_index(0, (void *) "dont_verify_domain", NULL, NULL, NULL); ssl_ex_index_cert_error_check = SSL_get_ex_new_index(0, (void *) "cert_error_check", NULL, &ssl_dupAclChecklist, &ssl_freeAclChecklist); diff --git a/src/ssl/support.h b/src/ssl/support.h index 8a55eb9740..1d99e1f4ef 100644 --- a/src/ssl/support.h +++ b/src/ssl/support.h @@ -132,6 +132,8 @@ GETX509ATTRIBUTE GetX509CAAttribute; /// \ingroup ServerProtocolSSLAPI GETX509ATTRIBUTE GetX509Fingerprint; +extern const EVP_MD *DefaultSignHash; + /** \ingroup ServerProtocolSSLAPI * Supported ssl-bump modes