]> git.ipfire.org Git - thirdparty/squid.git/commitdiff
sslproxy_cert_sign_hash configuration option
authorChristos Tsantilas <chtsanti@users.sourceforge.net>
Tue, 7 Oct 2014 14:11:12 +0000 (17:11 +0300)
committerChristos Tsantilas <chtsanti@users.sourceforge.net>
Tue, 7 Oct 2014 14:11:12 +0000 (17:11 +0300)
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

src/SquidConfig.h
src/cf.data.pre
src/client_side.cc
src/ssl/crtd_message.cc
src/ssl/crtd_message.h
src/ssl/gadgets.cc
src/ssl/gadgets.h
src/ssl/ssl_crtd.cc
src/ssl/support.cc
src/ssl/support.h

index f69c336cc49fb4baa51379896417f5cc70248476..47dda24563cbe234ad5eec03e15505a4c856a8d5 100644 (file)
@@ -476,6 +476,7 @@ public:
         char *ssl_engine;
         int session_ttl;
         size_t sessionCacheSize;
+        char *certSignHash;
     } SSL;
 #endif
 
index d19d6f50702005822a8ed464ba97a6f97f06c3a9..c6c8a484f508a8ed0d136e598113cee2226b1398 100644 (file)
@@ -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
index 4af2cc9baca2a404012383f821a398fef933e4b3..fbac89f885c343a7dc2c2c6aa0126c04bf58894b 100644 (file)
@@ -4055,6 +4055,8 @@ void ConnStateData::buildSslCertGenerationParams(Ssl::CertificateProperties &cer
             certProperties.signWithPkey.resetAndLock(port->signPkey.get());
     }
     signAlgorithm = certProperties.signAlgorithm;
+
+    certProperties.signHash = Ssl::DefaultSignHash;
 }
 
 void
index dc36ac5a3ae315f8f49fc6cfaf6e0eeeaf677e5c..25b983c9678f3d2ecbe536b4803ff4ccb6b8f751 100644 (file)
@@ -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");
index cdc1818c3ce8edf462a6c59eb33d85686c96857e..d730d88e442ceae32118d35d6ef76de4621816a4 100644 (file)
@@ -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,
index 04d9f06f8306019835dc124ec0e979779be13159..58337ddf02b7e8304cc91150fe7291ca49ac72f0 100644 (file)
@@ -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;
index 928758e607d976f8861a856fe264ed2c9a660316..75a0c470440906ab9513dd7a487f0f1cb04b7c35 100644 (file)
@@ -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;
index 846e2a02bc627fae80cc970a8fcd894fb0a36da6..1e56b684ba25f2200aad3fc6b2b518276a77e9c1 100644 (file)
@@ -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];
index 0a498bfaa2454e2338a8e4b034aecb9b15455e7d..b6a4f38618cac17cd95603b0b8c80ff5b0813ecb 100644 (file)
@@ -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);
index 8a55eb9740ca4859ef59d5dc16e8e0190eacf832..1d99e1f4effb15140b23e178678e95f2b16272e5 100644 (file)
@@ -132,6 +132,8 @@ GETX509ATTRIBUTE GetX509CAAttribute;
 /// \ingroup ServerProtocolSSLAPI
 GETX509ATTRIBUTE GetX509Fingerprint;
 
+extern const EVP_MD *DefaultSignHash;
+
 /**
   \ingroup ServerProtocolSSLAPI
  * Supported ssl-bump modes