| /* PKIXCertPathValidatorImpl.java -- PKIX certificate path validator. | |
| Copyright (C) 2004, 2005, 2006, 2010 Free Software Foundation, Inc. | |
| This file is part of GNU Classpath. | |
| GNU Classpath is free software; you can redistribute it and/or modify | |
| it under the terms of the GNU General Public License as published by | |
| the Free Software Foundation; either version 2, or (at your option) | |
| any later version. | |
| GNU Classpath 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 for more details. | |
| You should have received a copy of the GNU General Public License | |
| along with GNU Classpath; see the file COPYING. If not, write to the | |
| Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA | |
| 02110-1301 USA. | |
| Linking this library statically or dynamically with other modules is | |
| making a combined work based on this library. Thus, the terms and | |
| conditions of the GNU General Public License cover the whole | |
| combination. | |
| As a special exception, the copyright holders of this library give you | |
| permission to link this library with independent modules to produce an | |
| executable, regardless of the license terms of these independent | |
| modules, and to copy and distribute the resulting executable under | |
| terms of your choice, provided that you also meet, for each linked | |
| independent module, the terms and conditions of the license of that | |
| module. An independent module is a module which is not derived from | |
| or based on this library. If you modify this library, you may extend | |
| this exception to your version of the library, but you are not | |
| obligated to do so. If you do not wish to do so, delete this | |
| exception statement from your version. */ | |
| package gnu.java.security.provider; | |
| import gnu.java.security.Configuration; | |
| import gnu.java.security.OID; | |
| import gnu.java.security.Registry; | |
| import gnu.java.security.key.dss.DSSPublicKey; | |
| import gnu.java.security.x509.GnuPKIExtension; | |
| import gnu.java.security.x509.PolicyNodeImpl; | |
| import gnu.java.security.x509.X509CRLSelectorImpl; | |
| import gnu.java.security.x509.X509CertSelectorImpl; | |
| import gnu.java.security.x509.ext.BasicConstraints; | |
| import gnu.java.security.x509.ext.CertificatePolicies; | |
| import gnu.java.security.x509.ext.Extension; | |
| import gnu.java.security.x509.ext.KeyUsage; | |
| import gnu.java.security.x509.ext.PolicyConstraint; | |
| import java.io.IOException; | |
| import java.security.InvalidAlgorithmParameterException; | |
| import java.security.InvalidKeyException; | |
| import java.security.PublicKey; | |
| import java.security.cert.CRL; | |
| import java.security.cert.CertPath; | |
| import java.security.cert.CertPathParameters; | |
| import java.security.cert.CertPathValidatorException; | |
| import java.security.cert.CertPathValidatorResult; | |
| import java.security.cert.CertPathValidatorSpi; | |
| import java.security.cert.CertStore; | |
| import java.security.cert.CertStoreException; | |
| import java.security.cert.CertificateException; | |
| import java.security.cert.PKIXCertPathChecker; | |
| import java.security.cert.PKIXCertPathValidatorResult; | |
| import java.security.cert.PKIXParameters; | |
| import java.security.cert.TrustAnchor; | |
| import java.security.cert.X509CRL; | |
| import java.security.cert.X509Certificate; | |
| import java.security.interfaces.DSAParams; | |
| import java.security.interfaces.DSAPublicKey; | |
| import java.util.Arrays; | |
| import java.util.Collection; | |
| import java.util.Collections; | |
| import java.util.Date; | |
| import java.util.HashSet; | |
| import java.util.Iterator; | |
| import java.util.LinkedList; | |
| import java.util.List; | |
| import java.util.Set; | |
| import java.util.logging.Logger; | |
| /** | |
| * An implementation of the Public Key Infrastructure's X.509 certificate path | |
| * validation algorithm. | |
| * <p> | |
| * See <a href="http://www.ietf.org/rfc/rfc3280.txt">RFC 3280: Internet X.509 | |
| * Public Key Infrastructure Certificate and Certificate Revocation List (CRL) | |
| * Profile</a>. | |
| * | |
| * @author Casey Marshall (rsdio@metastatic.org) | |
| */ | |
| public class PKIXCertPathValidatorImpl | |
| extends CertPathValidatorSpi | |
| { | |
| private static final Logger log = Configuration.DEBUG ? | |
| Logger.getLogger(PKIXCertPathValidatorImpl.class.getName()) : null; | |
| public static final String ANY_POLICY = "2.5.29.32.0"; | |
| public PKIXCertPathValidatorImpl() | |
| { | |
| super(); | |
| } | |
| public CertPathValidatorResult engineValidate(CertPath path, | |
| CertPathParameters params) | |
| throws CertPathValidatorException, InvalidAlgorithmParameterException | |
| { | |
| if (! (params instanceof PKIXParameters)) | |
| throw new InvalidAlgorithmParameterException("not a PKIXParameters object"); | |
| // First check if the certificate path is valid. | |
| // | |
| // This means that: | |
| // | |
| // (a) for all x in {1, ..., n-1}, the subject of certificate x is | |
| // the issuer of certificate x+1; | |
| // | |
| // (b) for all x in {1, ..., n}, the certificate was valid at the | |
| // time in question. | |
| // | |
| // Because this is the X.509 algorithm, we also check if all | |
| // cerificates are of type X509Certificate. | |
| PolicyNodeImpl rootNode = new PolicyNodeImpl(); | |
| Set initPolicies = ((PKIXParameters) params).getInitialPolicies(); | |
| rootNode.setValidPolicy(ANY_POLICY); | |
| rootNode.setCritical(false); | |
| rootNode.setDepth(0); | |
| if (initPolicies != null) | |
| rootNode.addAllExpectedPolicies(initPolicies); | |
| else | |
| rootNode.addExpectedPolicy(ANY_POLICY); | |
| List checks = ((PKIXParameters) params).getCertPathCheckers(); | |
| List l = path.getCertificates(); | |
| if (l == null || l.size() == 0) | |
| throw new CertPathValidatorException(); | |
| X509Certificate[] p = null; | |
| try | |
| { | |
| p = (X509Certificate[]) l.toArray(new X509Certificate[l.size()]); | |
| } | |
| catch (ClassCastException cce) | |
| { | |
| throw new CertPathValidatorException("invalid certificate path"); | |
| } | |
| String sigProvider = ((PKIXParameters) params).getSigProvider(); | |
| PublicKey prevKey = null; | |
| Date now = ((PKIXParameters) params).getDate(); | |
| if (now == null) | |
| now = new Date(); | |
| LinkedList policyConstraints = new LinkedList(); | |
| for (int i = p.length - 1; i >= 0; i--) | |
| { | |
| try | |
| { | |
| p[i].checkValidity(now); | |
| } | |
| catch (CertificateException ce) | |
| { | |
| throw new CertPathValidatorException(ce.toString()); | |
| } | |
| Set uce = getCritExts(p[i]); | |
| for (Iterator check = checks.iterator(); check.hasNext();) | |
| { | |
| try | |
| { | |
| ((PKIXCertPathChecker) check.next()).check(p[i], uce); | |
| } | |
| catch (Exception x) | |
| { | |
| } | |
| } | |
| PolicyConstraint constr = null; | |
| if (p[i] instanceof GnuPKIExtension) | |
| { | |
| Extension pcx = ((GnuPKIExtension) p[i]).getExtension(PolicyConstraint.ID); | |
| if (pcx != null) | |
| constr = (PolicyConstraint) pcx.getValue(); | |
| } | |
| else | |
| { | |
| byte[] pcx = p[i].getExtensionValue(PolicyConstraint.ID.toString()); | |
| if (pcx != null) | |
| { | |
| try | |
| { | |
| constr = new PolicyConstraint(pcx); | |
| } | |
| catch (Exception x) | |
| { | |
| } | |
| } | |
| } | |
| if (constr != null && constr.getRequireExplicitPolicy() >= 0) | |
| policyConstraints.add(new int[] { p.length - i, | |
| constr.getRequireExplicitPolicy() }); | |
| updatePolicyTree(p[i], rootNode, p.length - i, (PKIXParameters) params, | |
| checkExplicitPolicy(p.length - i, policyConstraints)); | |
| // The rest of the tests involve this cert's relationship with the | |
| // next in the path. If this cert is the end entity, we can stop. | |
| if (i == 0) | |
| break; | |
| basicSanity(p, i); | |
| PublicKey pubKey = null; | |
| try | |
| { | |
| pubKey = p[i].getPublicKey(); | |
| if (pubKey instanceof DSAPublicKey) | |
| { | |
| DSAParams dsa = ((DSAPublicKey) pubKey).getParams(); | |
| // If the DSA public key is missing its parameters, use those | |
| // from the previous cert's key. | |
| if (dsa == null || dsa.getP() == null || dsa.getG() == null | |
| || dsa.getQ() == null) | |
| { | |
| if (prevKey == null) | |
| throw new InvalidKeyException("DSA keys not chainable"); | |
| if (! (prevKey instanceof DSAPublicKey)) | |
| throw new InvalidKeyException("DSA keys not chainable"); | |
| dsa = ((DSAPublicKey) prevKey).getParams(); | |
| pubKey = new DSSPublicKey(Registry.X509_ENCODING_ID, | |
| dsa.getP(), dsa.getQ(), | |
| dsa.getG(), | |
| ((DSAPublicKey) pubKey).getY()); | |
| } | |
| } | |
| if (sigProvider == null) | |
| p[i - 1].verify(pubKey); | |
| else | |
| p[i - 1].verify(pubKey, sigProvider); | |
| prevKey = pubKey; | |
| } | |
| catch (Exception e) | |
| { | |
| throw new CertPathValidatorException(e.toString()); | |
| } | |
| if (! p[i].getSubjectDN().equals(p[i - 1].getIssuerDN())) | |
| throw new CertPathValidatorException("issuer DN mismatch"); | |
| boolean[] issuerUid = p[i - 1].getIssuerUniqueID(); | |
| boolean[] subjectUid = p[i].getSubjectUniqueID(); | |
| if (issuerUid != null && subjectUid != null) | |
| if (! Arrays.equals(issuerUid, subjectUid)) | |
| throw new CertPathValidatorException("UID mismatch"); | |
| // Check the certificate against the revocation lists. | |
| if (((PKIXParameters) params).isRevocationEnabled()) | |
| { | |
| X509CRLSelectorImpl selector = new X509CRLSelectorImpl(); | |
| try | |
| { | |
| selector.addIssuerName(p[i].getSubjectDN()); | |
| } | |
| catch (IOException ioe) | |
| { | |
| throw new CertPathValidatorException("error selecting CRLs"); | |
| } | |
| List certStores = ((PKIXParameters) params).getCertStores(); | |
| List crls = new LinkedList(); | |
| for (Iterator it = certStores.iterator(); it.hasNext();) | |
| { | |
| CertStore cs = (CertStore) it.next(); | |
| try | |
| { | |
| Collection c = cs.getCRLs(selector); | |
| crls.addAll(c); | |
| } | |
| catch (CertStoreException cse) | |
| { | |
| } | |
| } | |
| if (crls.isEmpty()) | |
| throw new CertPathValidatorException("no CRLs for issuer"); | |
| boolean certOk = false; | |
| for (Iterator it = crls.iterator(); it.hasNext();) | |
| { | |
| CRL crl = (CRL) it.next(); | |
| if (! (crl instanceof X509CRL)) | |
| continue; | |
| X509CRL xcrl = (X509CRL) crl; | |
| if (! checkCRL(xcrl, p, now, p[i], pubKey, certStores)) | |
| continue; | |
| if (xcrl.isRevoked(p[i - 1])) | |
| throw new CertPathValidatorException("certificate is revoked"); | |
| else | |
| certOk = true; | |
| } | |
| if (! certOk) | |
| throw new CertPathValidatorException( | |
| "certificate's validity could not be determined"); | |
| } | |
| } | |
| rootNode.setReadOnly(); | |
| // Now ensure that the first certificate in the chain was issued | |
| // by a trust anchor. | |
| Exception cause = null; | |
| Set anchors = ((PKIXParameters) params).getTrustAnchors(); | |
| for (Iterator i = anchors.iterator(); i.hasNext();) | |
| { | |
| TrustAnchor anchor = (TrustAnchor) i.next(); | |
| X509Certificate anchorCert = null; | |
| PublicKey anchorKey = null; | |
| if (anchor.getTrustedCert() != null) | |
| { | |
| anchorCert = anchor.getTrustedCert(); | |
| anchorKey = anchorCert.getPublicKey(); | |
| } | |
| else | |
| anchorKey = anchor.getCAPublicKey(); | |
| if (anchorKey == null) | |
| continue; | |
| try | |
| { | |
| if (anchorCert != null) | |
| anchorCert.checkValidity(now); | |
| p[p.length - 1].verify(anchorKey); | |
| if (anchorCert != null && anchorCert.getBasicConstraints() >= 0 | |
| && anchorCert.getBasicConstraints() < p.length) | |
| continue; | |
| if (((PKIXParameters) params).isRevocationEnabled()) | |
| { | |
| X509CRLSelectorImpl selector = new X509CRLSelectorImpl(); | |
| if (anchorCert != null) | |
| try | |
| { | |
| selector.addIssuerName(anchorCert.getSubjectDN()); | |
| } | |
| catch (IOException ioe) | |
| { | |
| } | |
| else | |
| selector.addIssuerName(anchor.getCAName()); | |
| List certStores = ((PKIXParameters) params).getCertStores(); | |
| List crls = new LinkedList(); | |
| for (Iterator it = certStores.iterator(); it.hasNext();) | |
| { | |
| CertStore cs = (CertStore) it.next(); | |
| try | |
| { | |
| Collection c = cs.getCRLs(selector); | |
| crls.addAll(c); | |
| } | |
| catch (CertStoreException cse) | |
| { | |
| } | |
| } | |
| if (crls.isEmpty()) | |
| continue; | |
| for (Iterator it = crls.iterator(); it.hasNext();) | |
| { | |
| CRL crl = (CRL) it.next(); | |
| if (! (crl instanceof X509CRL)) | |
| continue; | |
| X509CRL xcrl = (X509CRL) crl; | |
| try | |
| { | |
| xcrl.verify(anchorKey); | |
| } | |
| catch (Exception x) | |
| { | |
| continue; | |
| } | |
| Date nextUpdate = xcrl.getNextUpdate(); | |
| if (nextUpdate != null && nextUpdate.compareTo(now) < 0) | |
| continue; | |
| if (xcrl.isRevoked(p[p.length - 1])) | |
| throw new CertPathValidatorException("certificate is revoked"); | |
| } | |
| } | |
| // The chain is valid; return the result. | |
| return new PKIXCertPathValidatorResult(anchor, rootNode, | |
| p[0].getPublicKey()); | |
| } | |
| catch (Exception ignored) | |
| { | |
| cause = ignored; | |
| continue; | |
| } | |
| } | |
| // The path is not valid. | |
| CertPathValidatorException cpve = | |
| new CertPathValidatorException("path validation failed"); | |
| if (cause != null) | |
| cpve.initCause(cause); | |
| throw cpve; | |
| } | |
| /** | |
| * Check if a given CRL is acceptable for checking the revocation status of | |
| * certificates in the path being checked. | |
| * <p> | |
| * The CRL is accepted iff: | |
| * <ol> | |
| * <li>The <i>nextUpdate</i> field (if present) is in the future.</li> | |
| * <li>The CRL does not contain any unsupported critical extensions.</li> | |
| * <li>The CRL is signed by one of the certificates in the path, or,</li> | |
| * <li>The CRL is signed by the given public key and was issued by the public | |
| * key's subject, or,</li> | |
| * <li>The CRL is signed by a certificate in the given cert stores, and that | |
| * cert is signed by one of the certificates in the path.</li> | |
| * </ol> | |
| * | |
| * @param crl The CRL being checked. | |
| * @param path The path this CRL is being checked against. | |
| * @param now The value to use as 'now'. | |
| * @param pubKeyCert The certificate authenticating the public key. | |
| * @param pubKey The public key to check. | |
| * @return True if the CRL is acceptable. | |
| */ | |
| private static boolean checkCRL(X509CRL crl, X509Certificate[] path, | |
| Date now, X509Certificate pubKeyCert, | |
| PublicKey pubKey, List certStores) | |
| { | |
| Date nextUpdate = crl.getNextUpdate(); | |
| if (nextUpdate != null && nextUpdate.compareTo(now) < 0) | |
| return false; | |
| if (crl.hasUnsupportedCriticalExtension()) | |
| return false; | |
| for (int i = 0; i < path.length; i++) | |
| { | |
| if (! path[i].getSubjectDN().equals(crl.getIssuerDN())) | |
| continue; | |
| boolean[] keyUsage = path[i].getKeyUsage(); | |
| if (keyUsage != null) | |
| { | |
| if (! keyUsage[KeyUsage.CRL_SIGN]) | |
| continue; | |
| } | |
| try | |
| { | |
| crl.verify(path[i].getPublicKey()); | |
| return true; | |
| } | |
| catch (Exception x) | |
| { | |
| } | |
| } | |
| if (crl.getIssuerDN().equals(pubKeyCert.getSubjectDN())) | |
| { | |
| try | |
| { | |
| boolean[] keyUsage = pubKeyCert.getKeyUsage(); | |
| if (keyUsage != null) | |
| { | |
| if (! keyUsage[KeyUsage.CRL_SIGN]) | |
| throw new Exception(); | |
| } | |
| crl.verify(pubKey); | |
| return true; | |
| } | |
| catch (Exception x) | |
| { | |
| } | |
| } | |
| try | |
| { | |
| X509CertSelectorImpl select = new X509CertSelectorImpl(); | |
| select.addSubjectName(crl.getIssuerDN()); | |
| List certs = new LinkedList(); | |
| for (Iterator it = certStores.iterator(); it.hasNext();) | |
| { | |
| CertStore cs = (CertStore) it.next(); | |
| try | |
| { | |
| certs.addAll(cs.getCertificates(select)); | |
| } | |
| catch (CertStoreException cse) | |
| { | |
| } | |
| } | |
| for (Iterator it = certs.iterator(); it.hasNext();) | |
| { | |
| X509Certificate c = (X509Certificate) it.next(); | |
| for (int i = 0; i < path.length; i++) | |
| { | |
| if (! c.getIssuerDN().equals(path[i].getSubjectDN())) | |
| continue; | |
| boolean[] keyUsage = c.getKeyUsage(); | |
| if (keyUsage != null) | |
| { | |
| if (! keyUsage[KeyUsage.CRL_SIGN]) | |
| continue; | |
| } | |
| try | |
| { | |
| c.verify(path[i].getPublicKey()); | |
| crl.verify(c.getPublicKey()); | |
| return true; | |
| } | |
| catch (Exception x) | |
| { | |
| } | |
| } | |
| if (c.getIssuerDN().equals(pubKeyCert.getSubjectDN())) | |
| { | |
| c.verify(pubKey); | |
| crl.verify(c.getPublicKey()); | |
| } | |
| } | |
| } | |
| catch (Exception x) | |
| { | |
| } | |
| return false; | |
| } | |
| private static Set getCritExts(X509Certificate cert) | |
| { | |
| HashSet s = new HashSet(); | |
| if (cert instanceof GnuPKIExtension) | |
| { | |
| Collection exts = ((GnuPKIExtension) cert).getExtensions(); | |
| for (Iterator it = exts.iterator(); it.hasNext();) | |
| { | |
| Extension ext = (Extension) it.next(); | |
| if (ext.isCritical() && ! ext.isSupported()) | |
| s.add(ext.getOid().toString()); | |
| } | |
| } | |
| else | |
| s.addAll(cert.getCriticalExtensionOIDs()); | |
| return s; | |
| } | |
| /** | |
| * Perform a basic sanity check on the CA certificate at <code>index</code>. | |
| */ | |
| private static void basicSanity(X509Certificate[] path, int index) | |
| throws CertPathValidatorException | |
| { | |
| X509Certificate cert = path[index]; | |
| int pathLen = 0; | |
| for (int i = index - 1; i > 0; i--) | |
| { | |
| if (! path[i].getIssuerDN().equals(path[i].getSubjectDN())) | |
| pathLen++; | |
| } | |
| Extension e = null; | |
| if (cert instanceof GnuPKIExtension) | |
| { | |
| e = ((GnuPKIExtension) cert).getExtension(BasicConstraints.ID); | |
| } | |
| else | |
| { | |
| try | |
| { | |
| e = new Extension(cert.getExtensionValue(BasicConstraints.ID.toString())); | |
| } | |
| catch (Exception x) | |
| { | |
| } | |
| } | |
| if (e == null) | |
| throw new CertPathValidatorException("no basicConstraints"); | |
| BasicConstraints bc = (BasicConstraints) e.getValue(); | |
| if (! bc.isCA()) | |
| throw new CertPathValidatorException( | |
| "certificate cannot be used to verify signatures"); | |
| if (bc.getPathLengthConstraint() >= 0 | |
| && bc.getPathLengthConstraint() < pathLen) | |
| throw new CertPathValidatorException("path is too long"); | |
| boolean[] keyUsage = cert.getKeyUsage(); | |
| if (keyUsage != null) | |
| { | |
| if (! keyUsage[KeyUsage.KEY_CERT_SIGN]) | |
| throw new CertPathValidatorException( | |
| "certificate cannot be used to sign certificates"); | |
| } | |
| } | |
| private static void updatePolicyTree(X509Certificate cert, | |
| PolicyNodeImpl root, int depth, | |
| PKIXParameters params, | |
| boolean explicitPolicy) | |
| throws CertPathValidatorException | |
| { | |
| if (Configuration.DEBUG) | |
| log.fine("updatePolicyTree depth == " + depth); | |
| Set nodes = new HashSet(); | |
| LinkedList stack = new LinkedList(); | |
| Iterator current = null; | |
| stack.addLast(Collections.singleton(root).iterator()); | |
| do | |
| { | |
| current = (Iterator) stack.removeLast(); | |
| while (current.hasNext()) | |
| { | |
| PolicyNodeImpl p = (PolicyNodeImpl) current.next(); | |
| if (Configuration.DEBUG) | |
| log.fine("visiting node == " + p); | |
| if (p.getDepth() == depth - 1) | |
| { | |
| if (Configuration.DEBUG) | |
| log.fine("added node"); | |
| nodes.add(p); | |
| } | |
| else | |
| { | |
| if (Configuration.DEBUG) | |
| log.fine("skipped node"); | |
| stack.addLast(current); | |
| current = p.getChildren(); | |
| } | |
| } | |
| } | |
| while (! stack.isEmpty()); | |
| Extension e = null; | |
| CertificatePolicies policies = null; | |
| List qualifierInfos = null; | |
| if (cert instanceof GnuPKIExtension) | |
| { | |
| e = ((GnuPKIExtension) cert).getExtension(CertificatePolicies.ID); | |
| if (e != null) | |
| policies = (CertificatePolicies) e.getValue(); | |
| } | |
| List cp = null; | |
| if (policies != null) | |
| cp = policies.getPolicies(); | |
| else | |
| cp = Collections.EMPTY_LIST; | |
| boolean match = false; | |
| if (Configuration.DEBUG) | |
| { | |
| log.fine("nodes are == " + nodes); | |
| log.fine("cert policies are == " + cp); | |
| } | |
| for (Iterator it = nodes.iterator(); it.hasNext();) | |
| { | |
| PolicyNodeImpl parent = (PolicyNodeImpl) it.next(); | |
| if (Configuration.DEBUG) | |
| log.fine("adding policies to " + parent); | |
| for (Iterator it2 = cp.iterator(); it2.hasNext();) | |
| { | |
| OID policy = (OID) it2.next(); | |
| if (Configuration.DEBUG) | |
| log.fine("trying to add policy == " + policy); | |
| if (policy.toString().equals(ANY_POLICY) | |
| && params.isAnyPolicyInhibited()) | |
| continue; | |
| PolicyNodeImpl child = new PolicyNodeImpl(); | |
| child.setValidPolicy(policy.toString()); | |
| child.addExpectedPolicy(policy.toString()); | |
| if (parent.getExpectedPolicies().contains(policy.toString())) | |
| { | |
| parent.addChild(child); | |
| match = true; | |
| } | |
| else if (parent.getExpectedPolicies().contains(ANY_POLICY)) | |
| { | |
| parent.addChild(child); | |
| match = true; | |
| } | |
| else if (ANY_POLICY.equals(policy.toString())) | |
| { | |
| parent.addChild(child); | |
| match = true; | |
| } | |
| if (match && policies != null) | |
| { | |
| List qualifiers = policies.getPolicyQualifierInfos(policy); | |
| if (qualifiers != null) | |
| child.addAllPolicyQualifiers(qualifiers); | |
| } | |
| } | |
| } | |
| if (! match && (params.isExplicitPolicyRequired() || explicitPolicy)) | |
| throw new CertPathValidatorException("policy tree building failed"); | |
| } | |
| private boolean checkExplicitPolicy(int depth, List explicitPolicies) | |
| { | |
| if (Configuration.DEBUG) | |
| log.fine("checkExplicitPolicy depth=" + depth); | |
| for (Iterator it = explicitPolicies.iterator(); it.hasNext();) | |
| { | |
| int[] i = (int[]) it.next(); | |
| int caDepth = i[0]; | |
| int limit = i[1]; | |
| if (Configuration.DEBUG) | |
| log.fine(" caDepth=" + caDepth + " limit=" + limit); | |
| if (depth - caDepth >= limit) | |
| return true; | |
| } | |
| return false; | |
| } | |
| } |