/* * Copyright (c) 2000, 2011, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it * under the terms of the GNU General Public License version 2 only, as * published by the Free Software Foundation. Oracle designates this * particular file as subject to the "Classpath" exception as provided * by Oracle in the LICENSE file that accompanied this code. * * This code is distributed in the hope that it will be useful, but WITHOUT * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License * version 2 for more details (a copy is included in the LICENSE file that * accompanied this code). * * You should have received a copy of the GNU General Public License version * 2 along with this work; if not, write to the Free Software Foundation, * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. * * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA * or visit www.oracle.com if you need additional information or have any * questions. */ package sun.security.provider.certpath; import java.io.IOException;import java.util.*; import java.security.GeneralSecurityException;import java.security.InvalidKeyException;import java.security.cert.Certificate;import java.security.cert.CertificateException;import java.security.cert.CertPathValidatorException;import java.security.cert.PKIXReason;import java.security.cert.CertStore;import java.security.cert.CertStoreException;import java.security.cert.PKIXBuilderParameters;import java.security.cert.PKIXCertPathChecker;import java.security.cert.TrustAnchor;import java.security.cert.X509Certificate;import java.security.cert.X509CertSelector;import javax.security.auth.x500.X500Principal; import sun.security.util.Debug;import sun.security.util.DerOutputStream;import sun.security.x509.AccessDescription;import sun.security.x509.AuthorityInfoAccessExtension;import sun.security.x509.PKIXExtensions;import sun.security.x509.PolicyMappingsExtension;import sun.security.x509.X500Name;import sun.security.x509.X509CertImpl;import sun.security.x509.X509CRLImpl;import sun.security.x509.AuthorityKeyIdentifierExtension;import sun.security.x509.KeyIdentifier;import sun.security.x509.SubjectKeyIdentifierExtension;import sun.security.x509.SerialNumber;import sun.security.x509.GeneralNames;import sun.security.x509.GeneralName;import sun.security.x509.GeneralNameInterface;import java.math.BigInteger; /** * This class represents a forward builder, which is able to retrieve * matching certificates from CertStores and verify a particular certificate * against a ForwardState. * * @since 1.4 * @author Yassir Elley * @author Sean Mullan */class ForwardBuilder extends Builder { private static final Debug debug = Debug.getInstance("certpath"); private final Set<X509Certificate> trustedCerts; private final Set<X500Principal> trustedSubjectDNs; private final Set<TrustAnchor> trustAnchors; private X509CertSelector eeSelector; private AdaptableX509CertSelector caSelector; private X509CertSelector caTargetSelector; TrustAnchor trustAnchor; private Comparator<X509Certificate> comparator; private boolean searchAllCertStores = true; private boolean onlyEECert = false; /** * Initialize the builder with the input parameters. * * @param params the parameter set used to build a certification path */ ForwardBuilder(PKIXBuilderParameters buildParams, X500Principal targetSubjectDN, boolean searchAllCertStores, boolean onlyEECert) { super(buildParams, targetSubjectDN); // populate sets of trusted certificates and subject DNs trustAnchors = buildParams.getTrustAnchors(); trustedCerts = new HashSet<X509Certificate>(trustAnchors.size()); trustedSubjectDNs = new HashSet<X500Principal>(trustAnchors.size()); for (TrustAnchor anchor : trustAnchors) { X509Certificate trustedCert = anchor.getTrustedCert(); if (trustedCert != null) { trustedCerts.add(trustedCert); trustedSubjectDNs.add(trustedCert.getSubjectX500Principal()); } else { trustedSubjectDNs.add(anchor.getCA()); } } comparator = new PKIXCertComparator(trustedSubjectDNs); this.searchAllCertStores = searchAllCertStores; this.onlyEECert = onlyEECert; } /** * Retrieves all certs from the specified CertStores that satisfy the * requirements specified in the parameters and the current * PKIX state (name constraints, policy constraints, etc). * * @param currentState the current state. * Must be an instance of <code>ForwardState</code> * @param certStores list of CertStores */ Collection<X509Certificate> getMatchingCerts (State currentState, List<CertStore> certStores) throws CertStoreException, CertificateException, IOException { if (debug != null) { debug.println("ForwardBuilder.getMatchingCerts()..."); } ForwardState currState = (ForwardState) currentState; /* * We store certs in a Set because we don't want duplicates. * As each cert is added, it is sorted based on the PKIXCertComparator * algorithm. */ Set<X509Certificate> certs = new TreeSet<X509Certificate>(comparator); /* * Only look for EE certs if search has just started. */ if (currState.isInitial()) { getMatchingEECerts(currState, certStores, certs); } getMatchingCACerts(currState, certStores, certs); return certs; } /* * Retrieves all end-entity certificates which satisfy constraints * and requirements specified in the parameters and PKIX state. */ private void getMatchingEECerts(ForwardState currentState, List<CertStore> certStores, Collection<X509Certificate> eeCerts) throws IOException { if (debug != null) { debug.println("ForwardBuilder.getMatchingEECerts()..."); } /* * Compose a certificate matching rule to filter out * certs which don't satisfy constraints * * First, retrieve clone of current target cert constraints, * and then add more selection criteria based on current validation * state. Since selector never changes, cache local copy & reuse. */ if (eeSelector == null) { eeSelector = (X509CertSelector) targetCertConstraints.clone(); /* * Match on certificate validity date */ eeSelector.setCertificateValid(date); /* * Policy processing optimizations */ if (buildParams.isExplicitPolicyRequired()) { eeSelector.setPolicy(getMatchingPolicies()); } /* * Require EE certs */ eeSelector.setBasicConstraints(-2); } /* Retrieve matching EE certs from CertStores */ addMatchingCerts(eeSelector, certStores, eeCerts, searchAllCertStores); } /** * Retrieves all CA certificates which satisfy constraints * and requirements specified in the parameters and PKIX state. */ private void getMatchingCACerts(ForwardState currentState, List<CertStore> certStores, Collection<X509Certificate> caCerts) throws IOException { if (debug != null) { debug.println("ForwardBuilder.getMatchingCACerts()..."); } int initialSize = caCerts.size(); /* * Compose a CertSelector to filter out * certs which do not satisfy requirements. */ X509CertSelector sel = null; if (currentState.isInitial()) { if (targetCertConstraints.getBasicConstraints() == -2) { // no need to continue: this means we never can match a CA cert return; } /* This means a CA is the target, so match on same stuff as * getMatchingEECerts */ if (debug != null) { debug.println("ForwardBuilder.getMatchingCACerts(): ca is target"); } if (caTargetSelector == null) { caTargetSelector = (X509CertSelector) targetCertConstraints.clone(); /* * Since we don't check the validity period of trusted * certificates, please don't set the certificate valid * criterion unless the trusted certificate matching is * completed. */ /* * Policy processing optimizations */ if (buildParams.isExplicitPolicyRequired()) caTargetSelector.setPolicy(getMatchingPolicies()); } sel = caTargetSelector; } else { if (caSelector == null) { caSelector = new AdaptableX509CertSelector(); /* * Since we don't check the validity period of trusted * certificates, please don't set the certificate valid * criterion unless the trusted certificate matching is * completed. */ /* * Policy processing optimizations */ if (buildParams.isExplicitPolicyRequired()) caSelector.setPolicy(getMatchingPolicies()); } /* * Match on subject (issuer of previous cert) */ caSelector.setSubject(currentState.issuerDN); /* * Match on subjectNamesTraversed (both DNs and AltNames) * (checks that current cert's name constraints permit it * to certify all the DNs and AltNames that have been traversed) */ CertPathHelper.setPathToNames (caSelector, currentState.subjectNamesTraversed); /* * Facilitate certification path construction with authority * key identifier and subject key identifier. */ AuthorityKeyIdentifierExtension akidext = currentState.cert.getAuthorityKeyIdentifierExtension(); caSelector.parseAuthorityKeyIdentifierExtension(akidext); /* * check the validity period */ caSelector.setValidityPeriod(currentState.cert.getNotBefore(), currentState.cert.getNotAfter()); sel = caSelector; } /* * For compatibility, conservatively, we don't check the path * length constraint of trusted anchors. Please don't set the * basic constraints criterion unless the trusted certificate * matching is completed. */ sel.setBasicConstraints(-1); for (X509Certificate trustedCert : trustedCerts) { if (sel.match(trustedCert)) { if (debug != null) { debug.println("ForwardBuilder.getMatchingCACerts: " + "found matching trust anchor"); } if (caCerts.add(trustedCert) && !searchAllCertStores) { return; } } } /* * The trusted certificate matching is completed. We need to match * on certificate validity date. */ sel.setCertificateValid(date); /* * Require CA certs with a pathLenConstraint that allows * at least as many CA certs that have already been traversed */ sel.setBasicConstraints(currentState.traversedCACerts); /* * If we have already traversed as many CA certs as the maxPathLength * will allow us to, then we don't bother looking through these * certificate pairs. If maxPathLength has a value of -1, this * means it is unconstrained, so we always look through the * certificate pairs. */ if (currentState.isInitial() || (buildParams.getMaxPathLength() == -1) || (buildParams.getMaxPathLength() > currentState.traversedCACerts)) { if (addMatchingCerts(sel, certStores, caCerts, searchAllCertStores) && !searchAllCertStores) { return; } } if (!currentState.isInitial() && Builder.USE_AIA) { // check for AuthorityInformationAccess extension AuthorityInfoAccessExtension aiaExt = currentState.cert.getAuthorityInfoAccessExtension(); if (aiaExt != null) { getCerts(aiaExt, caCerts); } } if (debug != null) { int numCerts = caCerts.size() - initialSize; debug.println("ForwardBuilder.getMatchingCACerts: found " + numCerts + " CA certs"); } } /** * Download Certificates from the given AIA and add them to the * specified Collection. */ private boolean getCerts(AuthorityInfoAccessExtension aiaExt, Collection<X509Certificate> certs) { if (Builder.USE_AIA == false) { return false; } List<AccessDescription> adList = aiaExt.getAccessDescriptions(); if (adList == null || adList.isEmpty()) { return false; } boolean add = false; for (AccessDescription ad : adList) { CertStore cs = URICertStore.getInstance(ad); try { if (certs.addAll((Collection<X509Certificate>) cs.getCertificates(caSelector))) { add = true; if (!searchAllCertStores) { return true; } } } catch (CertStoreException cse) { if (debug != null) { debug.println("exception getting certs from CertStore:"); cse.printStackTrace(); } continue; } } return add; } /** * This inner class compares 2 PKIX certificates according to which * should be tried first when building a path from the target. * The preference order is as follows: * * Given trusted certificate(s): * Subject:ou=D,ou=C,o=B,c=A * * Preference order for current cert: * * 1) Issuer matches a trusted subject * Issuer: ou=D,ou=C,o=B,c=A * * 2) Issuer is a descendant of a trusted subject (in order of * number of links to the trusted subject) * a) Issuer: ou=E,ou=D,ou=C,o=B,c=A [links=1] * b) Issuer: ou=F,ou=E,ou=D,ou=C,ou=B,c=A [links=2] * * 3) Issuer is an ancestor of a trusted subject (in order of number of * links to the trusted subject) * a) Issuer: ou=C,o=B,c=A [links=1] * b) Issuer: o=B,c=A [links=2] * * 4) Issuer is in the same namespace as a trusted subject (in order of * number of links to the trusted subject) * a) Issuer: ou=G,ou=C,o=B,c=A [links=2] * b) Issuer: ou=H,o=B,c=A [links=3] * * 5) Issuer is an ancestor of certificate subject (in order of number * of links to the certificate subject) * a) Issuer: ou=K,o=J,c=A * Subject: ou=L,ou=K,o=J,c=A * b) Issuer: o=J,c=A * Subject: ou=L,ou=K,0=J,c=A * * 6) Any other certificates */ static class PKIXCertComparator implements Comparator<X509Certificate> { final static String METHOD_NME = "PKIXCertComparator.compare()"; private final Set<X500Principal> trustedSubjectDNs; PKIXCertComparator(Set<X500Principal> trustedSubjectDNs) { this.trustedSubjectDNs = trustedSubjectDNs; } /** * @param oCert1 First X509Certificate to be compared * @param oCert2 Second X509Certificate to be compared * @return -1 if oCert1 is preferable to oCert2, or * if oCert1 and oCert2 are equally preferable (in this * case it doesn't matter which is preferable, but we don't * return 0 because the comparator would behave strangely * when used in a SortedSet). * 1 if oCert2 is preferable to oCert1 * 0 if oCert1.equals(oCert2). We only return 0 if the * certs are equal so that this comparator behaves * correctly when used in a SortedSet. * @throws ClassCastException if either argument is not of type * X509Certificate */ public int compare(X509Certificate oCert1, X509Certificate oCert2) { // if certs are the same, return 0 if (oCert1.equals(oCert2)) return 0; X500Principal cIssuer1 = oCert1.getIssuerX500Principal(); X500Principal cIssuer2 = oCert2.getIssuerX500Principal(); X500Name cIssuer1Name = X500Name.asX500Name(cIssuer1); X500Name cIssuer2Name = X500Name.asX500Name(cIssuer2); if (debug != null) { debug.println(METHOD_NME + " o1 Issuer: " + cIssuer1); debug.println(METHOD_NME + " o2 Issuer: " + cIssuer2); } /* If one cert's issuer matches a trusted subject, then it is * preferable. */ if (debug != null) { debug.println(METHOD_NME + " MATCH TRUSTED SUBJECT TEST..."); } boolean m1 = trustedSubjectDNs.contains(cIssuer1); boolean m2 = trustedSubjectDNs.contains(cIssuer2); if (debug != null) { debug.println(METHOD_NME + " m1: " + m1); debug.println(METHOD_NME + " m2: " + m2); } if (m1 && m2) { return -1; } else if (m1) { return -1; } else if (m2) { return 1; } /* If one cert's issuer is a naming descendant of a trusted subject, * then it is preferable, in order of increasing naming distance. */ if (debug != null) { debug.println(METHOD_NME + " NAMING DESCENDANT TEST..."); }Lines 1–500 of 930. Load more
/* * Copyright (c) 2000, 2011, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it * under the terms of the GNU General Public License version 2 only, as * published by the Free Software Foundation. Oracle designates this * particular file as subject to the "Classpath" exception as provided * by Oracle in the LICENSE file that accompanied this code. * * This code is distributed in the hope that it will be useful, but WITHOUT * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License * version 2 for more details (a copy is included in the LICENSE file that * accompanied this code). * * You should have received a copy of the GNU General Public License version * 2 along with this work; if not, write to the Free Software Foundation, * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. * * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA * or visit www.oracle.com if you need additional information or have any * questions. */ package sun.security.provider.certpath; import java.io.IOException; import java.util.*; import java.security.GeneralSecurityException; import java.security.InvalidKeyException; import java.security.cert.Certificate; import java.security.cert.CertificateException; import java.security.cert.CertPathValidatorException; import java.security.cert.PKIXReason; import java.security.cert.CertStore; import java.security.cert.CertStoreException; import java.security.cert.PKIXBuilderParameters; import java.security.cert.PKIXCertPathChecker; import java.security.cert.TrustAnchor; import java.security.cert.X509Certificate; import java.security.cert.X509CertSelector; import javax.security.auth.x500.X500Principal; import sun.security.util.Debug; import sun.security.util.DerOutputStream; import sun.security.x509.AccessDescription; import sun.security.x509.AuthorityInfoAccessExtension; import sun.security.x509.PKIXExtensions; import sun.security.x509.PolicyMappingsExtension; import sun.security.x509.X500Name; import sun.security.x509.X509CertImpl; import sun.security.x509.X509CRLImpl; import sun.security.x509.AuthorityKeyIdentifierExtension; import sun.security.x509.KeyIdentifier; import sun.security.x509.SubjectKeyIdentifierExtension; import sun.security.x509.SerialNumber; import sun.security.x509.GeneralNames; import sun.security.x509.GeneralName; import sun.security.x509.GeneralNameInterface; import java.math.BigInteger; /** * This class represents a forward builder, which is able to retrieve * matching certificates from CertStores and verify a particular certificate * against a ForwardState. * * @since 1.4 * @author Yassir Elley * @author Sean Mullan */ class ForwardBuilder extends Builder { private static final Debug debug = Debug.getInstance("certpath"); private final Set<X509Certificate> trustedCerts; private final Set<X500Principal> trustedSubjectDNs; private final Set<TrustAnchor> trustAnchors; private X509CertSelector eeSelector; private AdaptableX509CertSelector caSelector; private X509CertSelector caTargetSelector; TrustAnchor trustAnchor; private Comparator<X509Certificate> comparator; private boolean searchAllCertStores = true; private boolean onlyEECert = false; /** * Initialize the builder with the input parameters. * * @param params the parameter set used to build a certification path */ ForwardBuilder(PKIXBuilderParameters buildParams, X500Principal targetSubjectDN, boolean searchAllCertStores, boolean onlyEECert) { super(buildParams, targetSubjectDN); // populate sets of trusted certificates and subject DNs trustAnchors = buildParams.getTrustAnchors(); trustedCerts = new HashSet<X509Certificate>(trustAnchors.size()); trustedSubjectDNs = new HashSet<X500Principal>(trustAnchors.size()); for (TrustAnchor anchor : trustAnchors) { X509Certificate trustedCert = anchor.getTrustedCert(); if (trustedCert != null) { trustedCerts.add(trustedCert); trustedSubjectDNs.add(trustedCert.getSubjectX500Principal()); } else { trustedSubjectDNs.add(anchor.getCA()); } } comparator = new PKIXCertComparator(trustedSubjectDNs); this.searchAllCertStores = searchAllCertStores; this.onlyEECert = onlyEECert; } /** * Retrieves all certs from the specified CertStores that satisfy the * requirements specified in the parameters and the current * PKIX state (name constraints, policy constraints, etc). * * @param currentState the current state. * Must be an instance of <code>ForwardState</code> * @param certStores list of CertStores */ Collection<X509Certificate> getMatchingCerts (State currentState, List<CertStore> certStores) throws CertStoreException, CertificateException, IOException { if (debug != null) { debug.println("ForwardBuilder.getMatchingCerts()..."); } ForwardState currState = (ForwardState) currentState; /* * We store certs in a Set because we don't want duplicates. * As each cert is added, it is sorted based on the PKIXCertComparator * algorithm. */ Set<X509Certificate> certs = new TreeSet<X509Certificate>(comparator); /* * Only look for EE certs if search has just started. */ if (currState.isInitial()) { getMatchingEECerts(currState, certStores, certs); } getMatchingCACerts(currState, certStores, certs); return certs; } /* * Retrieves all end-entity certificates which satisfy constraints * and requirements specified in the parameters and PKIX state. */ private void getMatchingEECerts(ForwardState currentState, List<CertStore> certStores, Collection<X509Certificate> eeCerts) throws IOException { if (debug != null) { debug.println("ForwardBuilder.getMatchingEECerts()..."); } /* * Compose a certificate matching rule to filter out * certs which don't satisfy constraints * * First, retrieve clone of current target cert constraints, * and then add more selection criteria based on current validation * state. Since selector never changes, cache local copy & reuse. */ if (eeSelector == null) { eeSelector = (X509CertSelector) targetCertConstraints.clone(); /* * Match on certificate validity date */ eeSelector.setCertificateValid(date); /* * Policy processing optimizations */ if (buildParams.isExplicitPolicyRequired()) { eeSelector.setPolicy(getMatchingPolicies()); } /* * Require EE certs */ eeSelector.setBasicConstraints(-2); } /* Retrieve matching EE certs from CertStores */ addMatchingCerts(eeSelector, certStores, eeCerts, searchAllCertStores); } /** * Retrieves all CA certificates which satisfy constraints * and requirements specified in the parameters and PKIX state. */ private void getMatchingCACerts(ForwardState currentState, List<CertStore> certStores, Collection<X509Certificate> caCerts) throws IOException { if (debug != null) { debug.println("ForwardBuilder.getMatchingCACerts()..."); } int initialSize = caCerts.size(); /* * Compose a CertSelector to filter out * certs which do not satisfy requirements. */ X509CertSelector sel = null; if (currentState.isInitial()) { if (targetCertConstraints.getBasicConstraints() == -2) { // no need to continue: this means we never can match a CA cert return; } /* This means a CA is the target, so match on same stuff as * getMatchingEECerts */ if (debug != null) { debug.println("ForwardBuilder.getMatchingCACerts(): ca is target"); } if (caTargetSelector == null) { caTargetSelector = (X509CertSelector) targetCertConstraints.clone(); /* * Since we don't check the validity period of trusted * certificates, please don't set the certificate valid * criterion unless the trusted certificate matching is * completed. */ /* * Policy processing optimizations */ if (buildParams.isExplicitPolicyRequired()) caTargetSelector.setPolicy(getMatchingPolicies()); } sel = caTargetSelector; } else { if (caSelector == null) { caSelector = new AdaptableX509CertSelector(); /* * Since we don't check the validity period of trusted * certificates, please don't set the certificate valid * criterion unless the trusted certificate matching is * completed. */ /* * Policy processing optimizations */ if (buildParams.isExplicitPolicyRequired()) caSelector.setPolicy(getMatchingPolicies()); } /* * Match on subject (issuer of previous cert) */ caSelector.setSubject(currentState.issuerDN); /* * Match on subjectNamesTraversed (both DNs and AltNames) * (checks that current cert's name constraints permit it * to certify all the DNs and AltNames that have been traversed) */ CertPathHelper.setPathToNames (caSelector, currentState.subjectNamesTraversed); /* * Facilitate certification path construction with authority * key identifier and subject key identifier. */ AuthorityKeyIdentifierExtension akidext = currentState.cert.getAuthorityKeyIdentifierExtension(); caSelector.parseAuthorityKeyIdentifierExtension(akidext); /* * check the validity period */ caSelector.setValidityPeriod(currentState.cert.getNotBefore(), currentState.cert.getNotAfter()); sel = caSelector; } /* * For compatibility, conservatively, we don't check the path * length constraint of trusted anchors. Please don't set the * basic constraints criterion unless the trusted certificate * matching is completed. */ sel.setBasicConstraints(-1); for (X509Certificate trustedCert : trustedCerts) { if (sel.match(trustedCert)) { if (debug != null) { debug.println("ForwardBuilder.getMatchingCACerts: " + "found matching trust anchor"); } if (caCerts.add(trustedCert) && !searchAllCertStores) { return; } } } /* * The trusted certificate matching is completed. We need to match * on certificate validity date. */ sel.setCertificateValid(date); /* * Require CA certs with a pathLenConstraint that allows * at least as many CA certs that have already been traversed */ sel.setBasicConstraints(currentState.traversedCACerts); /* * If we have already traversed as many CA certs as the maxPathLength * will allow us to, then we don't bother looking through these * certificate pairs. If maxPathLength has a value of -1, this * means it is unconstrained, so we always look through the * certificate pairs. */ if (currentState.isInitial() || (buildParams.getMaxPathLength() == -1) || (buildParams.getMaxPathLength() > currentState.traversedCACerts)) { if (addMatchingCerts(sel, certStores, caCerts, searchAllCertStores) && !searchAllCertStores) { return; } } if (!currentState.isInitial() && Builder.USE_AIA) { // check for AuthorityInformationAccess extension AuthorityInfoAccessExtension aiaExt = currentState.cert.getAuthorityInfoAccessExtension(); if (aiaExt != null) { getCerts(aiaExt, caCerts); } } if (debug != null) { int numCerts = caCerts.size() - initialSize; debug.println("ForwardBuilder.getMatchingCACerts: found " + numCerts + " CA certs"); } } /** * Download Certificates from the given AIA and add them to the * specified Collection. */ private boolean getCerts(AuthorityInfoAccessExtension aiaExt, Collection<X509Certificate> certs) { if (Builder.USE_AIA == false) { return false; } List<AccessDescription> adList = aiaExt.getAccessDescriptions(); if (adList == null || adList.isEmpty()) { return false; } boolean add = false; for (AccessDescription ad : adList) { CertStore cs = URICertStore.getInstance(ad); try { if (certs.addAll((Collection<X509Certificate>) cs.getCertificates(caSelector))) { add = true; if (!searchAllCertStores) { return true; } } } catch (CertStoreException cse) { if (debug != null) { debug.println("exception getting certs from CertStore:"); cse.printStackTrace(); } continue; } } return add; } /** * This inner class compares 2 PKIX certificates according to which * should be tried first when building a path from the target. * The preference order is as follows: * * Given trusted certificate(s): * Subject:ou=D,ou=C,o=B,c=A * * Preference order for current cert: * * 1) Issuer matches a trusted subject * Issuer: ou=D,ou=C,o=B,c=A * * 2) Issuer is a descendant of a trusted subject (in order of * number of links to the trusted subject) * a) Issuer: ou=E,ou=D,ou=C,o=B,c=A [links=1] * b) Issuer: ou=F,ou=E,ou=D,ou=C,ou=B,c=A [links=2] * * 3) Issuer is an ancestor of a trusted subject (in order of number of * links to the trusted subject) * a) Issuer: ou=C,o=B,c=A [links=1] * b) Issuer: o=B,c=A [links=2] * * 4) Issuer is in the same namespace as a trusted subject (in order of * number of links to the trusted subject) * a) Issuer: ou=G,ou=C,o=B,c=A [links=2] * b) Issuer: ou=H,o=B,c=A [links=3] * * 5) Issuer is an ancestor of certificate subject (in order of number * of links to the certificate subject) * a) Issuer: ou=K,o=J,c=A * Subject: ou=L,ou=K,o=J,c=A * b) Issuer: o=J,c=A * Subject: ou=L,ou=K,0=J,c=A * * 6) Any other certificates */ static class PKIXCertComparator implements Comparator<X509Certificate> { final static String METHOD_NME = "PKIXCertComparator.compare()"; private final Set<X500Principal> trustedSubjectDNs; PKIXCertComparator(Set<X500Principal> trustedSubjectDNs) { this.trustedSubjectDNs = trustedSubjectDNs; } /** * @param oCert1 First X509Certificate to be compared * @param oCert2 Second X509Certificate to be compared * @return -1 if oCert1 is preferable to oCert2, or * if oCert1 and oCert2 are equally preferable (in this * case it doesn't matter which is preferable, but we don't * return 0 because the comparator would behave strangely * when used in a SortedSet). * 1 if oCert2 is preferable to oCert1 * 0 if oCert1.equals(oCert2). We only return 0 if the * certs are equal so that this comparator behaves * correctly when used in a SortedSet. * @throws ClassCastException if either argument is not of type * X509Certificate */ public int compare(X509Certificate oCert1, X509Certificate oCert2) { // if certs are the same, return 0 if (oCert1.equals(oCert2)) return 0; X500Principal cIssuer1 = oCert1.getIssuerX500Principal(); X500Principal cIssuer2 = oCert2.getIssuerX500Principal(); X500Name cIssuer1Name = X500Name.asX500Name(cIssuer1); X500Name cIssuer2Name = X500Name.asX500Name(cIssuer2); if (debug != null) { debug.println(METHOD_NME + " o1 Issuer: " + cIssuer1); debug.println(METHOD_NME + " o2 Issuer: " + cIssuer2); } /* If one cert's issuer matches a trusted subject, then it is * preferable. */ if (debug != null) { debug.println(METHOD_NME + " MATCH TRUSTED SUBJECT TEST..."); } boolean m1 = trustedSubjectDNs.contains(cIssuer1); boolean m2 = trustedSubjectDNs.contains(cIssuer2); if (debug != null) { debug.println(METHOD_NME + " m1: " + m1); debug.println(METHOD_NME + " m2: " + m2); } if (m1 && m2) { return -1; } else if (m1) { return -1; } else if (m2) { return 1; } /* If one cert's issuer is a naming descendant of a trusted subject, * then it is preferable, in order of increasing naming distance. */ if (debug != null) { debug.println(METHOD_NME + " NAMING DESCENDANT TEST..."); }