Bug 479508, bug 482153, bug 764393: add the isTrustedForUsage method to the
nssDecodedCert structure. Change nssCertificateArray_FindBestCertificate to take trust into consideration, always choosing a trusted cert over an untrusted cert when presented with that choice. Based on a patch by Nelson Bolyard. r=rob.stradling,rrelyea. Modified Files: pki3hack.c pkibase.c pkitm.h git-svn-id: svn://10.0.0.236/trunk@264085 18797224-902f-48f8-a5cc-f745e15eee43
This commit is contained in:
@@ -3,7 +3,7 @@
|
||||
* file, You can obtain one at http://mozilla.org/MPL/2.0/. */
|
||||
|
||||
#ifdef DEBUG
|
||||
static const char CVS_ID[] = "@(#) $RCSfile: pki3hack.c,v $ $Revision: 1.108 $ $Date: 2012-05-17 21:39:40 $";
|
||||
static const char CVS_ID[] = "@(#) $RCSfile: pki3hack.c,v $ $Revision: 1.109 $ $Date: 2012-07-27 21:41:52 $";
|
||||
#endif /* DEBUG */
|
||||
|
||||
/*
|
||||
@@ -412,6 +412,50 @@ nss3certificate_matchUsage(nssDecodedCert *dc, const NSSUsage *usage)
|
||||
return match;
|
||||
}
|
||||
|
||||
static PRBool
|
||||
nss3certificate_isTrustedForUsage(nssDecodedCert *dc, const NSSUsage *usage)
|
||||
{
|
||||
CERTCertificate *cc;
|
||||
PRBool ca;
|
||||
SECStatus secrv;
|
||||
unsigned int requiredFlags;
|
||||
unsigned int trustFlags;
|
||||
SECTrustType trustType;
|
||||
CERTCertTrust trust;
|
||||
|
||||
/* This is for NSS 3.3 functions that do not specify a usage */
|
||||
if (usage->anyUsage) {
|
||||
return PR_FALSE; /* XXX is this right? */
|
||||
}
|
||||
cc = (CERTCertificate *)dc->data;
|
||||
ca = usage->nss3lookingForCA;
|
||||
if (!ca) {
|
||||
PRBool trusted;
|
||||
unsigned int failedFlags;
|
||||
secrv = cert_CheckLeafTrust(cc, usage->nss3usage,
|
||||
&failedFlags, &trusted);
|
||||
return secrv == SECSuccess && trusted;
|
||||
}
|
||||
secrv = CERT_TrustFlagsForCACertUsage(usage->nss3usage, &requiredFlags,
|
||||
&trustType);
|
||||
if (secrv != SECSuccess) {
|
||||
return PR_FALSE;
|
||||
}
|
||||
secrv = CERT_GetCertTrust(cc, &trust);
|
||||
if (secrv != SECSuccess) {
|
||||
return PR_FALSE;
|
||||
}
|
||||
if (trustType == trustTypeNone) {
|
||||
/* normally trustTypeNone usages accept any of the given trust bits
|
||||
* being on as acceptable. */
|
||||
trustFlags = trust.sslFlags | trust.emailFlags |
|
||||
trust.objectSigningFlags;
|
||||
} else {
|
||||
trustFlags = SEC_GET_TRUST_FLAGS(&trust, trustType);
|
||||
}
|
||||
return (trustFlags & requiredFlags) == requiredFlags;
|
||||
}
|
||||
|
||||
static NSSASCII7 *
|
||||
nss3certificate_getEmailAddress(nssDecodedCert *dc)
|
||||
{
|
||||
@@ -462,6 +506,7 @@ nssDecodedPKIXCertificate_Create (
|
||||
rvDC->isValidAtTime = nss3certificate_isValidAtTime;
|
||||
rvDC->isNewerThan = nss3certificate_isNewerThan;
|
||||
rvDC->matchUsage = nss3certificate_matchUsage;
|
||||
rvDC->isTrustedForUsage = nss3certificate_isTrustedForUsage;
|
||||
rvDC->getEmailAddress = nss3certificate_getEmailAddress;
|
||||
rvDC->getDERSerialNumber = nss3certificate_getDERSerialNumber;
|
||||
} else {
|
||||
@@ -489,7 +534,9 @@ create_decoded_pkix_cert_from_nss3cert (
|
||||
rvDC->isValidAtTime = nss3certificate_isValidAtTime;
|
||||
rvDC->isNewerThan = nss3certificate_isNewerThan;
|
||||
rvDC->matchUsage = nss3certificate_matchUsage;
|
||||
rvDC->isTrustedForUsage = nss3certificate_isTrustedForUsage;
|
||||
rvDC->getEmailAddress = nss3certificate_getEmailAddress;
|
||||
rvDC->getDERSerialNumber = nss3certificate_getDERSerialNumber;
|
||||
}
|
||||
return rvDC;
|
||||
}
|
||||
|
||||
@@ -3,7 +3,7 @@
|
||||
* file, You can obtain one at http://mozilla.org/MPL/2.0/. */
|
||||
|
||||
#ifdef DEBUG
|
||||
static const char CVS_ID[] = "@(#) $RCSfile: pkibase.c,v $ $Revision: 1.35 $ $Date: 2012-05-17 21:39:40 $";
|
||||
static const char CVS_ID[] = "@(#) $RCSfile: pkibase.c,v $ $Revision: 1.36 $ $Date: 2012-07-27 21:41:52 $";
|
||||
#endif /* DEBUG */
|
||||
|
||||
#ifndef DEV_H
|
||||
@@ -434,9 +434,12 @@ nssCertificateArray_FindBestCertificate (
|
||||
)
|
||||
{
|
||||
NSSCertificate *bestCert = NULL;
|
||||
nssDecodedCert *bestdc = NULL;
|
||||
NSSTime *time, sTime;
|
||||
PRBool haveUsageMatch = PR_FALSE;
|
||||
PRBool bestCertMatches = PR_FALSE;
|
||||
PRBool thisCertMatches;
|
||||
PRBool bestCertIsValidAtTime = PR_FALSE;
|
||||
PRBool bestCertIsTrusted = PR_FALSE;
|
||||
|
||||
if (timeOpt) {
|
||||
time = timeOpt;
|
||||
@@ -448,7 +451,7 @@ nssCertificateArray_FindBestCertificate (
|
||||
return (NSSCertificate *)NULL;
|
||||
}
|
||||
for (; *certs; certs++) {
|
||||
nssDecodedCert *dc, *bestdc;
|
||||
nssDecodedCert *dc;
|
||||
NSSCertificate *c = *certs;
|
||||
dc = nssCertificate_GetDecoding(c);
|
||||
if (!dc) continue;
|
||||
@@ -458,34 +461,31 @@ nssCertificateArray_FindBestCertificate (
|
||||
* the usage matched
|
||||
*/
|
||||
bestCert = nssCertificate_AddRef(c);
|
||||
haveUsageMatch = thisCertMatches;
|
||||
bestCertMatches = thisCertMatches;
|
||||
bestdc = dc;
|
||||
continue;
|
||||
} else {
|
||||
if (haveUsageMatch && !thisCertMatches) {
|
||||
if (bestCertMatches && !thisCertMatches) {
|
||||
/* if already have a cert for this usage, and if this cert
|
||||
* doesn't have the correct usage, continue
|
||||
*/
|
||||
continue;
|
||||
} else if (!haveUsageMatch && thisCertMatches) {
|
||||
} else if (!bestCertMatches && thisCertMatches) {
|
||||
/* this one does match usage, replace the other */
|
||||
nssCertificate_Destroy(bestCert);
|
||||
bestCert = nssCertificate_AddRef(c);
|
||||
haveUsageMatch = PR_TRUE;
|
||||
bestCertMatches = thisCertMatches;
|
||||
bestdc = dc;
|
||||
continue;
|
||||
}
|
||||
/* this cert match as well as any cert we've found so far,
|
||||
* defer to time/policies
|
||||
* */
|
||||
}
|
||||
bestdc = nssCertificate_GetDecoding(bestCert);
|
||||
if (!bestdc) {
|
||||
nssCertificate_Destroy(bestCert);
|
||||
bestCert = nssCertificate_AddRef(c);
|
||||
continue;
|
||||
}
|
||||
/* time */
|
||||
if (bestdc->isValidAtTime(bestdc, time)) {
|
||||
if (bestCertIsValidAtTime || bestdc->isValidAtTime(bestdc, time)) {
|
||||
/* The current best cert is valid at time */
|
||||
bestCertIsValidAtTime = PR_TRUE;
|
||||
if (!dc->isValidAtTime(dc, time)) {
|
||||
/* If the new cert isn't valid at time, it's not better */
|
||||
continue;
|
||||
@@ -496,14 +496,36 @@ nssCertificateArray_FindBestCertificate (
|
||||
/* If the new cert is valid at time, it's better */
|
||||
nssCertificate_Destroy(bestCert);
|
||||
bestCert = nssCertificate_AddRef(c);
|
||||
bestdc = dc;
|
||||
bestCertIsValidAtTime = PR_TRUE;
|
||||
continue;
|
||||
}
|
||||
}
|
||||
/* either they are both valid at time, or neither valid;
|
||||
* take the newer one
|
||||
/* Either they are both valid at time, or neither valid.
|
||||
* If only one is trusted for this usage, take it.
|
||||
*/
|
||||
if (bestCertIsTrusted || bestdc->isTrustedForUsage(bestdc, usage)) {
|
||||
bestCertIsTrusted = PR_TRUE;
|
||||
if (!dc->isTrustedForUsage(dc, usage)) {
|
||||
continue;
|
||||
}
|
||||
} else {
|
||||
/* The current best cert is not trusted */
|
||||
if (dc->isTrustedForUsage(dc, usage)) {
|
||||
/* If the new cert is trusted, it's better */
|
||||
nssCertificate_Destroy(bestCert);
|
||||
bestCert = nssCertificate_AddRef(c);
|
||||
bestdc = dc;
|
||||
bestCertIsTrusted = PR_TRUE;
|
||||
continue;
|
||||
}
|
||||
}
|
||||
/* Otherwise, take the newer one. */
|
||||
if (!bestdc->isNewerThan(bestdc, dc)) {
|
||||
nssCertificate_Destroy(bestCert);
|
||||
bestCert = nssCertificate_AddRef(c);
|
||||
bestdc = dc;
|
||||
continue;
|
||||
}
|
||||
/* policies */
|
||||
/* XXX later -- defer to policies */
|
||||
|
||||
@@ -6,7 +6,7 @@
|
||||
#define PKITM_H
|
||||
|
||||
#ifdef DEBUG
|
||||
static const char PKITM_CVS_ID[] = "@(#) $RCSfile: pkitm.h,v $ $Revision: 1.16 $ $Date: 2012-04-25 14:50:07 $";
|
||||
static const char PKITM_CVS_ID[] = "@(#) $RCSfile: pkitm.h,v $ $Revision: 1.17 $ $Date: 2012-07-27 21:41:52 $";
|
||||
#endif /* DEBUG */
|
||||
|
||||
/*
|
||||
@@ -58,6 +58,9 @@ struct nssDecodedCertStr {
|
||||
PRBool (*isNewerThan)(nssDecodedCert *dc, nssDecodedCert *cmpdc);
|
||||
/* does the usage for this cert match the requested usage? */
|
||||
PRBool (*matchUsage)(nssDecodedCert *dc, const NSSUsage *usage);
|
||||
/* is this cert trusted for the requested usage? */
|
||||
PRBool (*isTrustedForUsage)(nssDecodedCert *dc,
|
||||
const NSSUsage *usage);
|
||||
/* extract the email address */
|
||||
NSSASCII7 *(*getEmailAddress)(nssDecodedCert *dc);
|
||||
/* extract the DER-encoded serial number */
|
||||
|
||||
Reference in New Issue
Block a user