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