/* PKIXCertPathValidatorImpl.java -- PKIX certificate path validator.
   Copyright (C) 2004, 2005, 2006  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 = Logger.getLogger(PKIXCertPathValidatorImpl.class.getName());

  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;
  }
}
