mirror of git://gcc.gnu.org/git/gcc.git
				
				
				
			
		
			
				
	
	
		
			695 lines
		
	
	
		
			24 KiB
		
	
	
	
		
			Java
		
	
	
	
			
		
		
	
	
			695 lines
		
	
	
		
			24 KiB
		
	
	
	
		
			Java
		
	
	
	
/* 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;
 | 
						|
  }
 | 
						|
}
 |