------------------------------------------------------------ revno: 14031 revision-id: squid3@treenet.co.nz-20160419150409-nkmjryvaa3101lwu parent: chtsanti@users.sourceforge.net-20160418152815-kvxyig2ogqv0iy11 author: Nathan Hoad committer: Amos Jeffries branch nick: 3.5 timestamp: Wed 2016-04-20 03:04:09 +1200 message: 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. ------------------------------------------------------------ # Bazaar merge directive format 2 (Bazaar 0.90) # revision_id: squid3@treenet.co.nz-20160419150409-nkmjryvaa3101lwu # target_branch: http://bzr.squid-cache.org/bzr/squid3/3.5 # testament_sha1: 3882adfd4700ed9a4c5c5457c4e3f040bc748454 # timestamp: 2016-04-19 15:50:54 +0000 # source_branch: http://bzr.squid-cache.org/bzr/squid3/3.5 # base_revision_id: chtsanti@users.sourceforge.net-20160418152815-\ # kvxyig2ogqv0iy11 # # Begin patch === modified file 'src/client_side.cc' --- src/client_side.cc 2016-04-01 06:15:31 +0000 +++ src/client_side.cc 2016-04-19 15:04:09 +0000 @@ -3997,6 +3997,9 @@ 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 { SSL_CTX *ctx = Ssl::generateSslContextUsingPkeyAndCertFromMemory(reply_message.getBody().c_str(), *port); getSslContextDone(ctx, true); @@ -4155,6 +4158,9 @@ SSL *ssl = fd_table[clientConnection->fd].ssl; 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 { SSL_CTX *dynCtx = Ssl::generateSslContext(certProperties, *port); getSslContextDone(dynCtx, true); @@ -4170,17 +4176,10 @@ // 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 === modified file 'src/ssl/support.cc' --- src/ssl/support.cc 2016-01-01 00:14:27 +0000 +++ src/ssl/support.cc 2016-04-19 15:04:09 +0000 @@ -1697,6 +1697,30 @@ 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) { === modified file 'src/ssl/support.h' --- src/ssl/support.h 2016-01-01 00:14:27 +0000 +++ src/ssl/support.h 2016-04-19 15:04:09 +0000 @@ -247,6 +247,18 @@ SSL_CTX * createSSLContext(Ssl::X509_Pointer & 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 * to SSL object.