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:
wtc%google.com
2012-07-27 21:41:52 +00:00
parent 1361f732a7
commit 14dcfdbf7a
3 changed files with 90 additions and 18 deletions

View File

@@ -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;
}

View File

@@ -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 */

View File

@@ -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 */