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