提交 2954e595 编写于 作者: J juh

8007967: Infinite loop can happen in...

8007967: Infinite loop can happen in sun.security.provider.certpath.SunCertPathBuilder.depthFirstSearchForward()
Reviewed-by: mullan
上级 5cd4f8fa
...@@ -75,6 +75,25 @@ public class DistributionPointFetcher { ...@@ -75,6 +75,25 @@ public class DistributionPointFetcher {
Set<TrustAnchor> trustAnchors, Set<TrustAnchor> trustAnchors,
Date validity) Date validity)
throws CertStoreException throws CertStoreException
{
return getCRLs(selector, signFlag, prevKey, null, provider, certStores,
reasonsMask, trustAnchors, validity);
}
/**
* Return the X509CRLs matching this selector. The selector must be
* an X509CRLSelector with certificateChecking set.
*/
public static Collection<X509CRL> getCRLs(X509CRLSelector selector,
boolean signFlag,
PublicKey prevKey,
X509Certificate prevCert,
String provider,
List<CertStore> certStores,
boolean[] reasonsMask,
Set<TrustAnchor> trustAnchors,
Date validity)
throws CertStoreException
{ {
X509Certificate cert = selector.getCertificateChecking(); X509Certificate cert = selector.getCertificateChecking();
if (cert == null) { if (cert == null) {
...@@ -101,7 +120,7 @@ public class DistributionPointFetcher { ...@@ -101,7 +120,7 @@ public class DistributionPointFetcher {
t.hasNext() && !Arrays.equals(reasonsMask, ALL_REASONS); ) { t.hasNext() && !Arrays.equals(reasonsMask, ALL_REASONS); ) {
DistributionPoint point = t.next(); DistributionPoint point = t.next();
Collection<X509CRL> crls = getCRLs(selector, certImpl, Collection<X509CRL> crls = getCRLs(selector, certImpl,
point, reasonsMask, signFlag, prevKey, provider, point, reasonsMask, signFlag, prevKey, prevCert, provider,
certStores, trustAnchors, validity); certStores, trustAnchors, validity);
results.addAll(crls); results.addAll(crls);
} }
...@@ -125,9 +144,10 @@ public class DistributionPointFetcher { ...@@ -125,9 +144,10 @@ public class DistributionPointFetcher {
*/ */
private static Collection<X509CRL> getCRLs(X509CRLSelector selector, private static Collection<X509CRL> getCRLs(X509CRLSelector selector,
X509CertImpl certImpl, DistributionPoint point, boolean[] reasonsMask, X509CertImpl certImpl, DistributionPoint point, boolean[] reasonsMask,
boolean signFlag, PublicKey prevKey, String provider, boolean signFlag, PublicKey prevKey, X509Certificate prevCert,
List<CertStore> certStores, Set<TrustAnchor> trustAnchors, String provider, List<CertStore> certStores,
Date validity) throws CertStoreException { Set<TrustAnchor> trustAnchors, Date validity)
throws CertStoreException {
// check for full name // check for full name
GeneralNames fullName = point.getFullName(); GeneralNames fullName = point.getFullName();
...@@ -188,8 +208,8 @@ public class DistributionPointFetcher { ...@@ -188,8 +208,8 @@ public class DistributionPointFetcher {
// we check the issuer in verifyCRLs method // we check the issuer in verifyCRLs method
selector.setIssuerNames(null); selector.setIssuerNames(null);
if (selector.match(crl) && verifyCRL(certImpl, point, crl, if (selector.match(crl) && verifyCRL(certImpl, point, crl,
reasonsMask, signFlag, prevKey, provider, trustAnchors, reasonsMask, signFlag, prevKey, prevCert, provider,
certStores, validity)) { trustAnchors, certStores, validity)) {
crls.add(crl); crls.add(crl);
} }
} catch (IOException | CRLException e) { } catch (IOException | CRLException e) {
...@@ -284,6 +304,8 @@ public class DistributionPointFetcher { ...@@ -284,6 +304,8 @@ public class DistributionPointFetcher {
* @param reasonsMask the interim reasons mask * @param reasonsMask the interim reasons mask
* @param signFlag true if prevKey can be used to verify the CRL * @param signFlag true if prevKey can be used to verify the CRL
* @param prevKey the public key that verifies the certificate's signature * @param prevKey the public key that verifies the certificate's signature
* @param prevCert the certificate whose public key verifies
* {@code certImpl}'s signature
* @param provider the Signature provider to use * @param provider the Signature provider to use
* @param trustAnchors a {@code Set} of {@code TrustAnchor}s * @param trustAnchors a {@code Set} of {@code TrustAnchor}s
* @param certStores a {@code List} of {@code CertStore}s to be used in * @param certStores a {@code List} of {@code CertStore}s to be used in
...@@ -294,7 +316,7 @@ public class DistributionPointFetcher { ...@@ -294,7 +316,7 @@ public class DistributionPointFetcher {
*/ */
static boolean verifyCRL(X509CertImpl certImpl, DistributionPoint point, static boolean verifyCRL(X509CertImpl certImpl, DistributionPoint point,
X509CRL crl, boolean[] reasonsMask, boolean signFlag, X509CRL crl, boolean[] reasonsMask, boolean signFlag,
PublicKey prevKey, String provider, PublicKey prevKey, X509Certificate prevCert, String provider,
Set<TrustAnchor> trustAnchors, List<CertStore> certStores, Set<TrustAnchor> trustAnchors, List<CertStore> certStores,
Date validity) throws CRLException, IOException { Date validity) throws CRLException, IOException {
...@@ -591,18 +613,26 @@ public class DistributionPointFetcher { ...@@ -591,18 +613,26 @@ public class DistributionPointFetcher {
// the subject criterion will be set by builder automatically. // the subject criterion will be set by builder automatically.
} }
// by far, we have validated the previous certificate, we can // By now, we have validated the previous certificate, so we can
// trust it during validating the CRL issuer. // trust it during the validation of the CRL issuer.
// Except the performance improvement, another benefit is to break // In addition to the performance improvement, another benefit is to
// the dead loop while looking for the issuer back and forth // break the dead loop while looking for the issuer back and forth
// between the delegated self-issued certificate and its issuer. // between the delegated self-issued certificate and its issuer.
Set<TrustAnchor> newTrustAnchors = new HashSet<>(trustAnchors); Set<TrustAnchor> newTrustAnchors = new HashSet<>(trustAnchors);
if (prevKey != null) { if (prevKey != null) {
// Add the previous certificate as a trust anchor. // Add the previous certificate as a trust anchor.
X500Principal principal = certImpl.getIssuerX500Principal(); // If prevCert is not null, we want to construct a TrustAnchor
TrustAnchor temporary = // using the cert object because when the certpath for the CRL
new TrustAnchor(principal, prevKey, null); // is built later, the CertSelector will make comparisons with
// the TrustAnchor's trustedCert member rather than its pubKey.
TrustAnchor temporary;
if (prevCert != null) {
temporary = new TrustAnchor(prevCert, null);
} else {
X500Principal principal = certImpl.getIssuerX500Principal();
temporary = new TrustAnchor(principal, prevKey, null);
}
newTrustAnchors.add(temporary); newTrustAnchors.add(temporary);
} }
......
/* /*
* Copyright (c) 2000, 2012, Oracle and/or its affiliates. All rights reserved. * Copyright (c) 2000, 2013, Oracle and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
* *
* This code is free software; you can redistribute it and/or modify it * This code is free software; you can redistribute it and/or modify it
...@@ -47,9 +47,7 @@ import sun.security.util.Debug; ...@@ -47,9 +47,7 @@ import sun.security.util.Debug;
import sun.security.x509.AccessDescription; import sun.security.x509.AccessDescription;
import sun.security.x509.AuthorityInfoAccessExtension; import sun.security.x509.AuthorityInfoAccessExtension;
import static sun.security.x509.PKIXExtensions.*; import static sun.security.x509.PKIXExtensions.*;
import sun.security.x509.PolicyMappingsExtension;
import sun.security.x509.X500Name; import sun.security.x509.X500Name;
import sun.security.x509.X509CertImpl;
import sun.security.x509.AuthorityKeyIdentifierExtension; import sun.security.x509.AuthorityKeyIdentifierExtension;
/** /**
...@@ -672,32 +670,16 @@ class ForwardBuilder extends Builder { ...@@ -672,32 +670,16 @@ class ForwardBuilder extends Builder {
currState.untrustedChecker.check(cert, Collections.<String>emptySet()); currState.untrustedChecker.check(cert, Collections.<String>emptySet());
/* /*
* check for looping - abort a loop if * check for looping - abort a loop if we encounter the same
* ((we encounter the same certificate twice) AND * certificate twice
* ((policyMappingInhibited = true) OR (no policy mapping
* extensions can be found between the occurrences of the same
* certificate)))
*/ */
if (certPathList != null) { if (certPathList != null) {
boolean policyMappingFound = false;
for (X509Certificate cpListCert : certPathList) { for (X509Certificate cpListCert : certPathList) {
X509CertImpl cpListCertImpl = X509CertImpl.toImpl(cpListCert);
PolicyMappingsExtension policyMappingsExt
= cpListCertImpl.getPolicyMappingsExtension();
if (policyMappingsExt != null) {
policyMappingFound = true;
}
if (debug != null) {
debug.println("policyMappingFound = " + policyMappingFound);
}
if (cert.equals(cpListCert)) { if (cert.equals(cpListCert)) {
if ((buildParams.policyMappingInhibited()) || if (debug != null) {
(!policyMappingFound)) { debug.println("loop detected!!");
if (debug != null) {
debug.println("loop detected!!");
}
throw new CertPathValidatorException("loop detected");
} }
throw new CertPathValidatorException("loop detected");
} }
} }
} }
......
...@@ -456,12 +456,13 @@ class RevocationChecker extends PKIXRevocationChecker { ...@@ -456,12 +456,13 @@ class RevocationChecker extends PKIXRevocationChecker {
PublicKey pubKey, boolean signFlag) PublicKey pubKey, boolean signFlag)
throws CertPathValidatorException throws CertPathValidatorException
{ {
checkCRLs(cert, pubKey, signFlag, true, checkCRLs(cert, pubKey, null, signFlag, true,
stackedCerts, params.trustAnchors()); stackedCerts, params.trustAnchors());
} }
private void checkCRLs(X509Certificate cert, PublicKey prevKey, private void checkCRLs(X509Certificate cert, PublicKey prevKey,
boolean signFlag, boolean allowSeparateKey, X509Certificate prevCert, boolean signFlag,
boolean allowSeparateKey,
Set<X509Certificate> stackedCerts, Set<X509Certificate> stackedCerts,
Set<TrustAnchor> anchors) Set<TrustAnchor> anchors)
throws CertPathValidatorException throws CertPathValidatorException
...@@ -543,7 +544,7 @@ class RevocationChecker extends PKIXRevocationChecker { ...@@ -543,7 +544,7 @@ class RevocationChecker extends PKIXRevocationChecker {
try { try {
if (crlDP) { if (crlDP) {
approvedCRLs.addAll(DistributionPointFetcher.getCRLs( approvedCRLs.addAll(DistributionPointFetcher.getCRLs(
sel, signFlag, prevKey, sel, signFlag, prevKey, prevCert,
params.sigProvider(), certStores, params.sigProvider(), certStores,
reasonsMask, anchors, null)); reasonsMask, anchors, null));
} }
...@@ -825,7 +826,7 @@ class RevocationChecker extends PKIXRevocationChecker { ...@@ -825,7 +826,7 @@ class RevocationChecker extends PKIXRevocationChecker {
for (X509CRL crl : crls) { for (X509CRL crl : crls) {
if (DistributionPointFetcher.verifyCRL( if (DistributionPointFetcher.verifyCRL(
certImpl, point, crl, reasonsMask, signFlag, certImpl, point, crl, reasonsMask, signFlag,
prevKey, params.sigProvider(), anchors, prevKey, null, params.sigProvider(), anchors,
certStores, params.date())) certStores, params.date()))
{ {
results.add(crl); results.add(crl);
...@@ -1043,7 +1044,7 @@ class RevocationChecker extends PKIXRevocationChecker { ...@@ -1043,7 +1044,7 @@ class RevocationChecker extends PKIXRevocationChecker {
+ " index " + i + " checking " + " index " + i + " checking "
+ cert); + cert);
} }
checkCRLs(cert, prevKey2, signFlag, true, checkCRLs(cert, prevKey2, null, signFlag, true,
stackedCerts, newAnchors); stackedCerts, newAnchors);
signFlag = certCanSignCrl(cert); signFlag = certCanSignCrl(cert);
prevKey2 = cert.getPublicKey(); prevKey2 = cert.getPublicKey();
...@@ -1058,13 +1059,14 @@ class RevocationChecker extends PKIXRevocationChecker { ...@@ -1058,13 +1059,14 @@ class RevocationChecker extends PKIXRevocationChecker {
debug.println("RevocationChecker.buildToNewKey()" + debug.println("RevocationChecker.buildToNewKey()" +
" got key " + cpbr.getPublicKey()); " got key " + cpbr.getPublicKey());
} }
// Now check revocation on the current cert using that key. // Now check revocation on the current cert using that key and
// the corresponding certificate.
// If it doesn't check out, try to find a different key. // If it doesn't check out, try to find a different key.
// And if we can't find a key, then return false. // And if we can't find a key, then return false.
PublicKey newKey = cpbr.getPublicKey(); PublicKey newKey = cpbr.getPublicKey();
try { try {
checkCRLs(currCert, newKey, true, false, null, checkCRLs(currCert, newKey, (X509Certificate) cpList.get(0),
params.trustAnchors()); true, false, null, params.trustAnchors());
// If that passed, the cert is OK! // If that passed, the cert is OK!
return; return;
} catch (CertPathValidatorException cpve) { } catch (CertPathValidatorException cpve) {
......
...@@ -30,6 +30,7 @@ import java.security.GeneralSecurityException; ...@@ -30,6 +30,7 @@ import java.security.GeneralSecurityException;
import java.security.InvalidAlgorithmParameterException; import java.security.InvalidAlgorithmParameterException;
import java.security.PublicKey; import java.security.PublicKey;
import java.security.cert.*; import java.security.cert.*;
import java.security.cert.CertPathValidatorException.BasicReason;
import java.security.cert.PKIXReason; import java.security.cert.PKIXReason;
import java.util.ArrayList; import java.util.ArrayList;
import java.util.Collection; import java.util.Collection;
...@@ -49,7 +50,7 @@ import sun.security.util.Debug; ...@@ -49,7 +50,7 @@ import sun.security.util.Debug;
* This class is able to build certification paths in either the forward * This class is able to build certification paths in either the forward
* or reverse directions. * or reverse directions.
* *
* <p> If successful, it returns a certification path which has succesfully * <p> If successful, it returns a certification path which has successfully
* satisfied all the constraints and requirements specified in the * satisfied all the constraints and requirements specified in the
* PKIXBuilderParameters object and has been validated according to the PKIX * PKIXBuilderParameters object and has been validated according to the PKIX
* path validation algorithm defined in RFC 3280. * path validation algorithm defined in RFC 3280.
...@@ -510,6 +511,12 @@ public final class SunCertPathBuilder extends CertPathBuilderSpi { ...@@ -510,6 +511,12 @@ public final class SunCertPathBuilder extends CertPathBuilderSpi {
debug.println debug.println
("SunCertPathBuilder.depthFirstSearchForward(): " + ("SunCertPathBuilder.depthFirstSearchForward(): " +
"final verification failed: " + cpve); "final verification failed: " + cpve);
// If the target cert itself is revoked, we
// cannot trust it. We can bail out here.
if (buildParams.targetCertConstraints().match(currCert)
&& cpve.getReason() == BasicReason.REVOKED) {
throw cpve;
}
vertex.setThrowable(cpve); vertex.setThrowable(cpve);
continue vertices; continue vertices;
} }
......
Markdown is supported
0% .
You are about to add 0 people to the discussion. Proceed with caution.
先完成此消息的编辑!
想要评论请 注册