Index: mozilla/security/nss/lib/pki/pkibase.c |
=================================================================== |
--- mozilla/security/nss/lib/pki/pkibase.c (revision 158129) |
+++ mozilla/security/nss/lib/pki/pkibase.c (working copy) |
@@ -434,9 +434,12 @@ |
) |
{ |
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 @@ |
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 @@ |
* 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 @@ |
/* 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 */ |