From: Christos Tsantilas Date: Tue, 5 Apr 2016 09:43:47 +0000 (+0300) Subject: author: Nathan Hoad X-Git-Tag: SQUID_4_0_9~24 X-Git-Url: http://git.ipfire.org/?a=commitdiff_plain;h=d8f0ceabcf49d92c1d5104067fc27caa6a7f9b62;p=thirdparty%2Fsquid.git author: Nathan Hoad Add chained certificates and signing certificate to peek-then-bumped connections. The scenario this patch addresses is when Squid is configured with an intermediate signing CA certificate, and clients have the root CA installed on their machines. What happens is that the generated certificates come down with an unknown issuer (the intermediate signing certificate), with no intermediates, so they are rejected. By adding the configured certificate chain as old client-first mode did, the intermediate and root certificates come down as well, resulting in the issuer being identified and the connection being established "securely". This work is submitted on behalf of Bloomberg L.P. --- diff --git a/src/client_side.cc b/src/client_side.cc index 165ae8607f..03dcfd53a4 100644 --- a/src/client_side.cc +++ b/src/client_side.cc @@ -2867,6 +2867,9 @@ ConnStateData::sslCrtdHandleReply(const Helper::Reply &reply) bool ret = Ssl::configureSSLUsingPkeyAndCertFromMemory(ssl, reply_message.getBody().c_str(), *port); if (!ret) debugs(33, 5, "Failed to set certificates to ssl object for PeekAndSplice mode"); + + SSL_CTX *sslContext = SSL_get_SSL_CTX(ssl); + Ssl::configureUnconfiguredSslContext(sslContext, signAlgorithm, *port); } else { auto ctx = Ssl::generateSslContextUsingPkeyAndCertFromMemory(reply_message.getBody().c_str(), *port); getSslContextDone(ctx, true); @@ -3026,6 +3029,9 @@ ConnStateData::getSslContextStart() auto ssl = fd_table[clientConnection->fd].ssl.get(); if (!Ssl::configureSSL(ssl, certProperties, *port)) debugs(33, 5, "Failed to set certificates to ssl object for PeekAndSplice mode"); + + SSL_CTX *sslContext = SSL_get_SSL_CTX(ssl); + Ssl::configureUnconfiguredSslContext(sslContext, certProperties.signAlgorithm, *port); } else { auto dynCtx = Ssl::generateSslContext(certProperties, *port); getSslContextDone(dynCtx, true); @@ -3041,17 +3047,10 @@ ConnStateData::getSslContextDone(Security::ContextPtr sslContext, bool isNew) // Try to add generated ssl context to storage. if (port->generateHostCertificates && isNew) { - if (signAlgorithm == Ssl::algSignTrusted) { - // Add signing certificate to the certificates chain - X509 *cert = port->signingCert.get(); - if (SSL_CTX_add_extra_chain_cert(sslContext, cert)) { - // increase the certificate lock - CRYPTO_add(&(cert->references),1,CRYPTO_LOCK_X509); - } else { - const int ssl_error = ERR_get_error(); - debugs(33, DBG_IMPORTANT, "WARNING: can not add signing certificate to SSL context chain: " << ERR_error_string(ssl_error, NULL)); - } - Ssl::addChainToSslContext(sslContext, port->certsToChain.get()); + if (sslContext && (signAlgorithm == Ssl::algSignTrusted)) { + Ssl::chainCertificatesToSSLContext(sslContext, *port); + } else if (signAlgorithm == Ssl::algSignTrusted) { + debugs(33, DBG_IMPORTANT, "WARNING: can not add signing certificate to SSL context chain because SSL context chain is invalid!"); } //else it is self-signed or untrusted do not attrach any certificate diff --git a/src/ssl/support.cc b/src/ssl/support.cc index 611c412d33..1205bd41b3 100644 --- a/src/ssl/support.cc +++ b/src/ssl/support.cc @@ -969,6 +969,30 @@ Ssl::generateSslContext(CertificateProperties const &properties, AnyP::PortCfg & return createSSLContext(cert, pkey, port); } +void +Ssl::chainCertificatesToSSLContext(SSL_CTX *sslContext, AnyP::PortCfg &port) +{ + assert(sslContext != NULL); + // Add signing certificate to the certificates chain + X509 *signingCert = port.signingCert.get(); + if (SSL_CTX_add_extra_chain_cert(sslContext, signingCert)) { + // increase the certificate lock + CRYPTO_add(&(signingCert->references),1,CRYPTO_LOCK_X509); + } else { + const int ssl_error = ERR_get_error(); + debugs(33, DBG_IMPORTANT, "WARNING: can not add signing certificate to SSL context chain: " << ERR_error_string(ssl_error, NULL)); + } + Ssl::addChainToSslContext(sslContext, port.certsToChain.get()); +} + +void +Ssl::configureUnconfiguredSslContext(SSL_CTX *sslContext, Ssl::CertSignAlgorithm signAlgorithm,AnyP::PortCfg &port) +{ + if (sslContext && signAlgorithm == Ssl::algSignTrusted) { + Ssl::chainCertificatesToSSLContext(sslContext, port); + } +} + bool Ssl::configureSSL(SSL *ssl, CertificateProperties const &properties, AnyP::PortCfg &port) { diff --git a/src/ssl/support.h b/src/ssl/support.h index b54828693f..16b4b2fb54 100644 --- a/src/ssl/support.h +++ b/src/ssl/support.h @@ -239,6 +239,18 @@ Security::ContextPtr generateSslContextUsingPkeyAndCertFromMemory(const char * d */ Security::ContextPtr createSSLContext(Security::CertPointer & x509, Ssl::EVP_PKEY_Pointer & pkey, AnyP::PortCfg &port); +/** + \ingroup ServerProtocolSSLAPI + * Chain signing certificate and chained certificates to an SSL Context + */ +void chainCertificatesToSSLContext(SSL_CTX *sslContext, AnyP::PortCfg &port); + +/** + \ingroup ServerProtocolSSLAPI + * Configure a previously unconfigured SSL context object. + */ +void configureUnconfiguredSslContext(SSL_CTX *sslContext, Ssl::CertSignAlgorithm signAlgorithm,AnyP::PortCfg &port); + /** \ingroup ServerProtocolSSLAPI * Generates a certificate and a private key using provided properies and set it