Date: Tuesday, December 3, 2019 @ 14:11:58 Author: heftig Revision: 370265
add missing patch Added: nss/trunk/nss-3.47-certdb-temp-cert.patch ---------------------------------+ nss-3.47-certdb-temp-cert.patch | 230 ++++++++++++++++++++++++++++++++++++++ 1 file changed, 230 insertions(+) Added: nss-3.47-certdb-temp-cert.patch =================================================================== --- nss-3.47-certdb-temp-cert.patch (rev 0) +++ nss-3.47-certdb-temp-cert.patch 2019-12-03 14:11:58 UTC (rev 370265) @@ -0,0 +1,230 @@ +# HG changeset patch +# User Daiki Ueno <du...@redhat.com> +# Date 1574953499 -3600 +# Thu Nov 28 16:04:59 2019 +0100 +# Node ID f1f705bd0528713216e16867233825c299d3e3b2 +# Parent 10722c590949819ed4d971ad5ae213bc8b11a1bf +Bug 1593167, certdb: prefer perm certs over temp certs when trust is not available + +Summary: +When a builtin root module is loaded after some temp certs being +loaded, our certificate lookup logic preferred those temp certs over +perm certs stored on the root module. This was a problem because such +temp certs are usually not accompanied with trust information. + +This makes the certificate lookup logic capable of handling such +situations by checking if the trust information is attached to temp +certs and otherwise falling back to perm certs. + +Reviewers: rrelyea, keeler + +Reviewed By: rrelyea + +Subscribers: heftig + +Bug #: 1593167 + +Differential Revision: https://phabricator.services.mozilla.com/D54726 + +diff --git a/lib/certdb/stanpcertdb.c b/lib/certdb/stanpcertdb.c +--- a/lib/certdb/stanpcertdb.c ++++ b/lib/certdb/stanpcertdb.c +@@ -340,6 +340,91 @@ CERT_AddTempCertToPerm(CERTCertificate * + return __CERT_AddTempCertToPerm(cert, nickname, trust); + } + ++static CERTCertificate * ++find_cert_by_der_cert(CERTCertDBHandle *handle, SECItem *derCert) ++{ ++ CERTCertificate *cc; ++ NSSCryptoContext *context; ++ NSSCertificate *cert = NULL; ++ NSSCertificate *tempCert = NULL; ++ NSSCertificate *permCert = NULL; ++ NSSDER encoding; ++ nssCertificateStoreTrace lockTrace = { NULL, NULL, PR_FALSE, PR_FALSE }; ++ nssCertificateStoreTrace unlockTrace = { NULL, NULL, PR_FALSE, PR_FALSE }; ++ ++ /* We retrieve a certificate instance for derCert in this order: ++ * 1. Look up a temp cert in the crypto context. If it is found ++ * and has a trust object associated, use it. ++ * 2. Look up a perm cert in the trust domain. If it is found, ++ * use it. Otherwise, use the temp cert. ++ */ ++ NSSITEM_FROM_SECITEM(&encoding, derCert); ++ context = STAN_GetDefaultCryptoContext(); ++ ++ /* First, see if it is already a temp cert */ ++ tempCert = NSSCryptoContext_FindCertificateByEncodedCertificate(context, ++ &encoding); ++ if (tempCert) { ++ NSSTrust *trust; ++ ++ trust = nssCryptoContext_FindTrustForCertificate(context, tempCert); ++ if (trust) { ++ nssTrust_Destroy(trust); ++ cert = tempCert; ++ tempCert = NULL; ++ } ++ } ++ ++ /* Then, see if it is already a perm cert */ ++ if (!cert && handle) { ++ permCert = NSSTrustDomain_FindCertificateByEncodedCertificate(handle, ++ &encoding); ++ if (permCert) { ++ /* Delete the temp instance */ ++ if (tempCert) { ++ nssCertificateStore_Lock(context->certStore, &lockTrace); ++ nssCertificateStore_RemoveCertLOCKED(context->certStore, ++ tempCert); ++ nssCertificateStore_Unlock(context->certStore, &lockTrace, ++ &unlockTrace); ++ } ++ cert = permCert; ++ permCert = NULL; ++ } else if (tempCert) { ++ cert = tempCert; ++ tempCert = NULL; ++ } ++ } ++ ++ if (tempCert) { ++ nssCertificate_Destroy(tempCert); ++ } ++ if (permCert) { ++ nssCertificate_Destroy(permCert); ++ } ++ ++ if (!cert) { ++ return NULL; ++ } ++ ++ /* Actually, that search ends up going by issuer/serial, ++ * so it is still possible to return a cert with the same ++ * issuer/serial but a different encoding, and we're ++ * going to reject that ++ */ ++ if (!nssItem_Equal(&cert->encoding, &encoding, NULL)) { ++ nssCertificate_Destroy(cert); ++ PORT_SetError(SEC_ERROR_REUSED_ISSUER_AND_SERIAL); ++ return NULL; ++ } ++ ++ cc = STAN_GetCERTCertificateOrRelease(cert); ++ if (!cc) { ++ CERT_MapStanError(); ++ } ++ return cc; ++} ++ + CERTCertificate * + CERT_NewTempCertificate(CERTCertDBHandle *handle, SECItem *derCert, + char *nickname, PRBool isperm, PRBool copyDER) +@@ -351,32 +436,8 @@ CERT_NewTempCertificate(CERTCertDBHandle + NSSCryptoContext *gCC = STAN_GetDefaultCryptoContext(); + NSSTrustDomain *gTD = STAN_GetDefaultTrustDomain(); + if (!isperm) { +- NSSDER encoding; +- NSSITEM_FROM_SECITEM(&encoding, derCert); +- /* First, see if it is already a temp cert */ +- c = NSSCryptoContext_FindCertificateByEncodedCertificate(gCC, +- &encoding); +- if (!c && handle) { +- /* Then, see if it is already a perm cert */ +- c = NSSTrustDomain_FindCertificateByEncodedCertificate(handle, +- &encoding); +- } +- if (c) { +- /* actually, that search ends up going by issuer/serial, +- * so it is still possible to return a cert with the same +- * issuer/serial but a different encoding, and we're +- * going to reject that +- */ +- if (!nssItem_Equal(&c->encoding, &encoding, NULL)) { +- nssCertificate_Destroy(c); +- PORT_SetError(SEC_ERROR_REUSED_ISSUER_AND_SERIAL); +- cc = NULL; +- } else { +- cc = STAN_GetCERTCertificateOrRelease(c); +- if (cc == NULL) { +- CERT_MapStanError(); +- } +- } ++ cc = find_cert_by_der_cert(handle, derCert); ++ if (cc) { + return cc; + } + } +@@ -598,19 +659,7 @@ CERT_FindCertByNickname(CERTCertDBHandle + CERTCertificate * + CERT_FindCertByDERCert(CERTCertDBHandle *handle, SECItem *derCert) + { +- NSSCryptoContext *cc; +- NSSCertificate *c; +- NSSDER encoding; +- NSSITEM_FROM_SECITEM(&encoding, derCert); +- cc = STAN_GetDefaultCryptoContext(); +- c = NSSCryptoContext_FindCertificateByEncodedCertificate(cc, &encoding); +- if (!c) { +- c = NSSTrustDomain_FindCertificateByEncodedCertificate(handle, +- &encoding); +- if (!c) +- return NULL; +- } +- return STAN_GetCERTCertificateOrRelease(c); ++ return find_cert_by_der_cert(handle, derCert); + } + + static CERTCertificate * +diff --git a/lib/pki/pkistore.c b/lib/pki/pkistore.c +--- a/lib/pki/pkistore.c ++++ b/lib/pki/pkistore.c +@@ -27,6 +27,8 @@ + + #include "prbit.h" + ++#include "secerr.h" ++ + /* + * Certificate Store + * +@@ -544,6 +546,13 @@ nssCertificateStore_FindCertificateByEnc + &serial); + PORT_Free(issuer.data); + PORT_Free(serial.data); ++ ++ if (rvCert && !nssItem_Equal(&rvCert->encoding, encoding, NULL)) { ++ nssCertificate_Destroy(rvCert); ++ PORT_SetError(SEC_ERROR_REUSED_ISSUER_AND_SERIAL); ++ return NULL; ++ } ++ + return rvCert; + } + +diff --git a/lib/pki/trustdomain.c b/lib/pki/trustdomain.c +--- a/lib/pki/trustdomain.c ++++ b/lib/pki/trustdomain.c +@@ -15,6 +15,7 @@ + #include "pk11pub.h" + #include "nssrwlk.h" + #include "pk11priv.h" ++#include "secerr.h" + + #define NSSTRUSTDOMAIN_DEFAULT_CACHE_SIZE 32 + +@@ -841,6 +842,13 @@ nssTrustDomain_FindCertificateByEncodedC + &serial); + PORT_Free(issuer.data); + PORT_Free(serial.data); ++ ++ if (rvCert && !nssItem_Equal(&rvCert->encoding, ber, NULL)) { ++ nssCertificate_Destroy(rvCert); ++ PORT_SetError(SEC_ERROR_REUSED_ISSUER_AND_SERIAL); ++ return NULL; ++ } ++ + return rvCert; + } +