------------------------------------------------------------ revno: 13631 revision-id: chtsanti@users.sourceforge.net-20141007141112-5ndx2qz2be36afta parent: squid3@treenet.co.nz-20141006193803-6739k48w4hr12899 committer: Christos Tsantilas branch nick: trunk timestamp: Tue 2014-10-07 17:11:12 +0300 message: 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 ------------------------------------------------------------ # Bazaar merge directive format 2 (Bazaar 0.90) # revision_id: chtsanti@users.sourceforge.net-20141007141112-\ # 5ndx2qz2be36afta # target_branch: http://bzr.squid-cache.org/bzr/squid3/trunk/ # testament_sha1: 5768ff4b52e7124e0f8f798a3e1b4018171613b7 # timestamp: 2014-10-07 14:51:03 +0000 # source_branch: http://bzr.squid-cache.org/bzr/squid3/trunk # base_revision_id: squid3@treenet.co.nz-20141006193803-\ # 6739k48w4hr12899 # # Begin patch === modified file 'src/SquidConfig.h' --- src/SquidConfig.h 2014-09-25 06:50:32 +0000 +++ src/SquidConfig.h 2014-10-07 14:11:12 +0000 @@ -476,6 +476,7 @@ char *ssl_engine; int session_ttl; size_t sessionCacheSize; + char *certSignHash; } SSL; #endif === modified file 'src/cf.data.pre' --- src/cf.data.pre 2014-09-22 19:06:19 +0000 +++ src/cf.data.pre 2014-10-07 14:11:12 +0000 @@ -2505,6 +2505,24 @@ 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 === modified file 'src/client_side.cc' --- src/client_side.cc 2014-10-01 12:31:58 +0000 +++ src/client_side.cc 2014-10-07 14:11:12 +0000 @@ -4055,6 +4055,8 @@ certProperties.signWithPkey.resetAndLock(port->signPkey.get()); } signAlgorithm = certProperties.signAlgorithm; + + certProperties.signHash = Ssl::DefaultSignHash; } void === modified file 'src/ssl/crtd_message.cc' --- src/ssl/crtd_message.cc 2014-09-13 13:59:43 +0000 +++ src/ssl/crtd_message.cc 2014-10-07 14:11:12 +0000 @@ -206,12 +206,21 @@ 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 @@ 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_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"); === modified file 'src/ssl/crtd_message.h' --- src/ssl/crtd_message.h 2014-09-13 13:59:43 +0000 +++ src/ssl/crtd_message.h 2014-10-07 14:11:12 +0000 @@ -84,6 +84,8 @@ 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, === modified file 'src/ssl/gadgets.cc' --- src/ssl/gadgets.cc 2014-09-13 13:59:43 +0000 +++ src/ssl/gadgets.cc 2014-10-07 14:11:12 +0000 @@ -221,7 +221,8 @@ setValidAfter(false), setValidBefore(false), setCommonName(false), - signAlgorithm(Ssl::algSignEnd) + signAlgorithm(Ssl::algSignEnd), + signHash(NULL) {} std::string & Ssl::CertificateProperties::dbKey() const @@ -255,6 +256,11 @@ certKey.append(certSignAlgorithm(signAlgorithm)); } + if (signHash != NULL) { + certKey.append("+SignHash=", 10); + certKey.append(EVP_MD_name(signHash)); + } + return certKey; } @@ -434,11 +440,13 @@ 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; === modified file 'src/ssl/gadgets.h' --- src/ssl/gadgets.h 2014-09-13 13:59:43 +0000 +++ src/ssl/gadgets.h 2014-10-07 14:11:12 +0000 @@ -34,6 +34,10 @@ 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 @@ 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; === modified file 'src/ssl/ssl_crtd.cc' --- src/ssl/ssl_crtd.cc 2014-09-13 13:59:43 +0000 +++ src/ssl/ssl_crtd.cc 2014-10-07 14:11:12 +0000 @@ -295,6 +295,9 @@ { 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]; === modified file 'src/ssl/support.cc' --- src/ssl/support.cc 2014-09-13 13:59:43 +0000 +++ src/ssl/support.cc 2014-10-07 14:11:12 +0000 @@ -36,6 +36,8 @@ 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 @@ 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); === modified file 'src/ssl/support.h' --- src/ssl/support.h 2014-09-13 13:59:43 +0000 +++ src/ssl/support.h 2014-10-07 14:11:12 +0000 @@ -132,6 +132,8 @@ /// \ingroup ServerProtocolSSLAPI GETX509ATTRIBUTE GetX509Fingerprint; +extern const EVP_MD *DefaultSignHash; + /** \ingroup ServerProtocolSSLAPI * Supported ssl-bump modes