From: Christos Tsantilas Date: Thu, 16 Feb 2012 20:00:16 +0000 (+0200) Subject: stable certificates part1 X-Git-Tag: BumpSslServerFirst.take05~22 X-Git-Url: http://git.ipfire.org/?a=commitdiff_plain;h=955881706f096d8c4f149aab85f761e7cd79f95c;p=thirdparty%2Fsquid.git stable certificates part1 Changes to make fake certificates "stable" and "unique". This patch modify bump-server-first branch to: - use configured trusted CA private key for generating all fake certificates, including trusted, untrusted, and self-signed fake certificates. - use untrusted CA certificate which be deterministically derived from the trusted CA certificate to both reduce configuration effort (compared to a configuration option) and to generate identical untrusted CA certificates given identical Squid configurations. --- diff --git a/src/ProtoPort.h b/src/ProtoPort.h index d80fa00891..c83fa9f95b 100644 --- a/src/ProtoPort.h +++ b/src/ProtoPort.h @@ -73,6 +73,8 @@ struct http_port_list { Ssl::X509_Pointer signingCert; ///< x509 certificate for signing generated certificates Ssl::EVP_PKEY_Pointer signPkey; ///< private key for sighing generated certificates Ssl::X509_STACK_Pointer certsToChain; ///< x509 certificates to send with the generated cert + Ssl::X509_Pointer untrustedSigningCert; ///< x509 certificate for signing untrusted generated certificates + Ssl::EVP_PKEY_Pointer untrustedSignPkey; ///< private key for signing untrusted generated certificates #endif CBDATA_CLASS2(http_port_list); diff --git a/src/cache_cf.cc b/src/cache_cf.cc index 1d610b042c..ea38819c28 100644 --- a/src/cache_cf.cc +++ b/src/cache_cf.cc @@ -922,6 +922,12 @@ configDoConfigure(void) s->sslContextSessionId)); Ssl::readCertChainAndPrivateKeyFromFiles(s->signingCert, s->signPkey, s->certsToChain, s->cert, s->key); + + if (!s->signPkey) + debugs(3, DBG_IMPORTANT, "No SSL private key configured for http_port " << s->http.s); + + Ssl::generateUntrustedCert(s->untrustedSigningCert, s->untrustedSignPkey, + s->signingCert, s->signPkey); } } @@ -938,8 +944,14 @@ configDoConfigure(void) s->cafile, s->capath, s->crlfile, s->dhfile, s->sslContextSessionId)); - if (s->cert && s->sslBump) + if (s->cert && s->sslBump) { Ssl::readCertChainAndPrivateKeyFromFiles(s->signingCert, s->signPkey, s->certsToChain, s->cert, s->key); + if (!s->signPkey) + debugs(3, DBG_IMPORTANT, "No SSL private key configured for https_port " << s->http.s); + + Ssl::generateUntrustedCert(s->untrustedSigningCert, s->untrustedSignPkey, + s->signingCert, s->signPkey); + } } } diff --git a/src/client_side.cc b/src/client_side.cc index b50330fac1..20837434ce 100644 --- a/src/client_side.cc +++ b/src/client_side.cc @@ -3710,9 +3710,8 @@ void ConnStateData::buildSslCertGenerationParams(Ssl::CertificateProperties &cer assert(certProperties.signAlgorithm != Ssl::algSignEnd); if (certProperties.signAlgorithm == Ssl::algSignUntrusted) { - assert(Ssl::SquidCaCert.get() && Ssl::SquidCaCertKey.get()); - certProperties.signWithX509.resetAndLock(Ssl::SquidCaCert.get()); - certProperties.signWithPkey.resetAndLock(Ssl::SquidCaCertKey.get()); + certProperties.signWithX509.resetAndLock(port->untrustedSigningCert.get()); + certProperties.signWithPkey.resetAndLock(port->untrustedSignPkey.get()); } else { if (port->signingCert.get()) diff --git a/src/ssl/gadgets.cc b/src/ssl/gadgets.cc index 62895d2914..7be9cb0702 100644 --- a/src/ssl/gadgets.cc +++ b/src/ssl/gadgets.cc @@ -292,7 +292,12 @@ static bool buildCertificate(Ssl::X509_Pointer & cert, Ssl::CertificatePropertie bool Ssl::generateSslCertificate(Ssl::X509_Pointer & certToStore, Ssl::EVP_PKEY_Pointer & pkeyToStore, Ssl::CertificateProperties const &properties) { Ssl::EVP_PKEY_Pointer pkey; - pkey.reset(createSslPrivateKey()); + // Use signing certificates private key as generated certificate private key + if (properties.signWithPkey.get()) + pkey.resetAndLock(properties.signWithPkey.get()); + else // if not exist generate one + pkey.reset(createSslPrivateKey()); + if (!pkey) return false; diff --git a/src/ssl/support.cc b/src/ssl/support.cc index d28cb37309..32f78038ae 100644 --- a/src/ssl/support.cc +++ b/src/ssl/support.cc @@ -46,9 +46,6 @@ #include "ssl/support.h" #include "ssl/gadgets.h" -Ssl::X509_Pointer Ssl::SquidCaCert; -Ssl::EVP_PKEY_Pointer Ssl::SquidCaCertKey; - /** \defgroup ServerProtocolSSLInternal Server-Side SSL Internals \ingroup ServerProtocolSSLAPI @@ -652,13 +649,6 @@ ssl_initialize(void) } - // Generate the self-signed Ssl::SquidCaCert, using the "SquidLocalCa" as CN - Ssl::CertificateProperties certProperties; - certProperties.commonName = "Squid CA for Untrusted Certificates"; - certProperties.signAlgorithm = Ssl::algSignSelf; - bool ret = Ssl::generateSslCertificate(Ssl::SquidCaCert, Ssl::SquidCaCertKey, certProperties); - assert(ret); - 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); @@ -1391,21 +1381,57 @@ void Ssl::readCertChainAndPrivateKeyFromFiles(X509_Pointer & cert, EVP_PKEY_Poin } } -const char *Ssl::CommonHostName(X509 *x509) +static const char *getSubjectEntry(X509 *x509, int nid) { - static char name[256] = ""; // stores common name (CN) + static char name[1024] = ""; // stores common name (CN) if (!x509) return NULL; - // TODO: What if CN is a UTF8String? See X509_NAME_get_index_by_NID(3ssl). + // TODO: What if the entry is a UTF8String? See X509_NAME_get_index_by_NID(3ssl). const int nameLen = X509_NAME_get_text_by_NID( X509_get_subject_name(x509), - NID_commonName, name, sizeof(name)); + nid, name, sizeof(name)); if (nameLen > 0) return name; return NULL; } + +const char *Ssl::CommonHostName(X509 *x509) +{ + return getSubjectEntry(x509, NID_commonName); +} + +static const char *getOrganization(X509 *x509) +{ + return getSubjectEntry(x509, NID_organizationName); +} + +bool Ssl::generateUntrustedCert(X509_Pointer &untrustedCert, EVP_PKEY_Pointer &untrustedPkey, X509_Pointer const &cert, EVP_PKEY_Pointer const & pkey) +{ + // Generate the self-signed certificate, using a hard-coded subject prefix + Ssl::CertificateProperties certProperties; + if (const char *cn = CommonHostName(cert.get())) { + certProperties.commonName = "Not trusted by \""; + certProperties.commonName += cn; + certProperties.commonName += "\""; + } + else if (const char *org = getOrganization(cert.get())) { + certProperties.commonName = "Not trusted by \""; + certProperties.commonName += org; + certProperties.commonName += "\""; + } + else + certProperties.commonName = "Not trusted"; + certProperties.setCommonName = true; + // O, OU, and other CA subject fields will be mimicked + // Expiration date and other common properties will be mimicked + certProperties.signAlgorithm = Ssl::algSignSelf; + certProperties.signWithPkey.resetAndLock(pkey.get()); + certProperties.mimicCert.resetAndLock(cert.get()); + return Ssl::generateSslCertificate(untrustedCert, untrustedPkey, certProperties); +} + #endif /* USE_SSL */ diff --git a/src/ssl/support.h b/src/ssl/support.h index a4f571e140..5584a74bdc 100644 --- a/src/ssl/support.h +++ b/src/ssl/support.h @@ -109,19 +109,11 @@ const char *sslGetUserCertificateChainPEM(SSL *ssl); namespace Ssl { - -/** - \ingroup ServerProtocolSSLAPI - * A temporary self-signed certificate generated on squid start up, to be - * used to sign the generated untrusted certificates. -*/ -extern X509_Pointer SquidCaCert; - /** \ingroup ServerProtocolSSLAPI - * The key of the SquidCaCert certificate. + * Generate a certificate to be used as untrusted signing certificate, based on a trusted CA */ -extern EVP_PKEY_Pointer SquidCaCertKey; +bool generateUntrustedCert(X509_Pointer & untrustedCert, EVP_PKEY_Pointer & untrustedPkey, X509_Pointer const & cert, EVP_PKEY_Pointer const & pkey); /** \ingroup ServerProtocolSSLAPI