/*
 * Copyright (c) 2012, Oracle and/or its affiliates. All rights reserved.
 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
 *
 * This code is free software; you can redistribute it and/or modify it
 * under the terms of the GNU General Public License version 2 only, as
 * published by the Free Software Foundation.  Oracle designates this
 * particular file as subject to the "Classpath" exception as provided
 * by Oracle in the LICENSE file that accompanied this code.
 *
 * This code is distributed in the hope that it will be useful, but WITHOUT
 * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
 * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
 * version 2 for more details (a copy is included in the LICENSE file that
 * accompanied this code).
 *
 * You should have received a copy of the GNU General Public License version
 * 2 along with this work; if not, write to the Free Software Foundation,
 * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
 *
 * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
 * or visit www.oracle.com if you need additional information or have any
 * questions.
 */
package sun.security.provider.certpath;

import java.security.InvalidAlgorithmParameterException;
import java.security.KeyStore;
import java.security.PublicKey;
import java.security.cert.*;
import java.security.interfaces.DSAPublicKey;
import java.util.*;
import javax.security.auth.x500.X500Principal;

import sun.security.util.Debug;

/**
 * Common utility methods and classes used by the PKIX CertPathValidator and
 * CertPathBuilder implementation.
 */
class PKIX {

    private static final Debug debug = Debug.getInstance("certpath");

    private PKIX() { }

    static boolean isDSAPublicKeyWithoutParams(PublicKey publicKey) {
        return (publicKey instanceof DSAPublicKey &&
               ((DSAPublicKey)publicKey).getParams() == null);
    }

    static ValidatorParams checkParams(CertPath cp, CertPathParameters params)
        throws InvalidAlgorithmParameterException
    {
        if (!(params instanceof PKIXParameters)) {
            throw new InvalidAlgorithmParameterException("inappropriate "
                + "params, must be an instance of PKIXParameters");
        }
        return new ValidatorParams(cp, (PKIXParameters)params);
    }

    static BuilderParams checkBuilderParams(CertPathParameters params)
        throws InvalidAlgorithmParameterException
    {
        if (!(params instanceof PKIXBuilderParameters)) {
            throw new InvalidAlgorithmParameterException("inappropriate "
                + "params, must be an instance of PKIXBuilderParameters");
        }
        return new BuilderParams((PKIXBuilderParameters)params);
    }

    /**
     * PKIXParameters that are shared by the PKIX CertPathValidator
     * implementation. Provides additional functionality and avoids
     * unnecessary cloning.
     */
    static class ValidatorParams {
        private final PKIXParameters params;
        private CertPath certPath;
        private List<PKIXCertPathChecker> checkers;
        private List<CertStore> stores;
        private boolean gotDate;
        private Date date;
        private Set<String> policies;
        private boolean gotConstraints;
        private CertSelector constraints;
        private Set<TrustAnchor> anchors;
        private List<X509Certificate> certs;

        ValidatorParams(CertPath cp, PKIXParameters params)
            throws InvalidAlgorithmParameterException
        {
            this(params);
            if (!cp.getType().equals("X.509") && !cp.getType().equals("X509")) {
                throw new InvalidAlgorithmParameterException("inappropriate "
                    + "CertPath type specified, must be X.509 or X509");
            }
            this.certPath = cp;
        }

        ValidatorParams(PKIXParameters params)
            throws InvalidAlgorithmParameterException
        {
            this.anchors = params.getTrustAnchors();
            // Make sure that none of the trust anchors include name constraints
            // (not supported).
            for (TrustAnchor anchor : this.anchors) {
                if (anchor.getNameConstraints() != null) {
                    throw new InvalidAlgorithmParameterException
                        ("name constraints in trust anchor not supported");
                }
            }
            this.params = params;
        }

        CertPath certPath() {
            return certPath;
        }
        // called by CertPathBuilder after path has been built
        void setCertPath(CertPath cp) {
            this.certPath = cp;
        }
        List<X509Certificate> certificates() {
            if (certs == null) {
                if (certPath == null) {
                    certs = Collections.emptyList();
                } else {
                    // Reverse the ordering for validation so that the target
                    // cert is the last certificate
                    @SuppressWarnings("unchecked")
                    List<X509Certificate> xc = new ArrayList<>
                        ((List<X509Certificate>)certPath.getCertificates());
                    Collections.reverse(xc);
                    certs = xc;
                }
            }
            return certs;
        }
        List<PKIXCertPathChecker> certPathCheckers() {
            if (checkers == null)
                checkers = params.getCertPathCheckers();
            return checkers;
        }
        List<CertStore> certStores() {
            if (stores == null)
                stores = params.getCertStores();
            return stores;
        }
        Date date() {
            if (!gotDate) {
                date = params.getDate();
                if (date == null)
                    date = new Date();
                gotDate = true;
            }
            return date;
        }
        Set<String> initialPolicies() {
            if (policies == null)
                policies = params.getInitialPolicies();
            return policies;
        }
        CertSelector targetCertConstraints() {
            if (!gotConstraints) {
                constraints = params.getTargetCertConstraints();
                gotConstraints = true;
            }
            return constraints;
        }
        Set<TrustAnchor> trustAnchors() {
            return anchors;
        }
        boolean revocationEnabled() {
            return params.isRevocationEnabled();
        }
        boolean policyMappingInhibited() {
            return params.isPolicyMappingInhibited();
        }
        boolean explicitPolicyRequired() {
            return params.isExplicitPolicyRequired();
        }
        boolean policyQualifiersRejected() {
            return params.getPolicyQualifiersRejected();
        }
        String sigProvider() { return params.getSigProvider(); }
        boolean anyPolicyInhibited() { return params.isAnyPolicyInhibited(); }

        // in rare cases we need access to the original params, for example
        // in order to clone CertPathCheckers before building a new chain
        PKIXParameters getPKIXParameters() {
            return params;
        }
    }

    static class BuilderParams extends ValidatorParams {
        private PKIXBuilderParameters params;
        private boolean buildForward = true;
        private List<CertStore> stores;
        private X500Principal targetSubject;

        BuilderParams(PKIXBuilderParameters params)
            throws InvalidAlgorithmParameterException
        {
            super(params);
            checkParams(params);
        }
        private void checkParams(PKIXBuilderParameters params)
            throws InvalidAlgorithmParameterException
        {
            CertSelector sel = targetCertConstraints();
            if (!(sel instanceof X509CertSelector)) {
                throw new InvalidAlgorithmParameterException("the "
                    + "targetCertConstraints parameter must be an "
                    + "X509CertSelector");
            }
            if (params instanceof SunCertPathBuilderParameters) {
                buildForward =
                    ((SunCertPathBuilderParameters)params).getBuildForward();
            }
            this.params = params;
            this.targetSubject = getTargetSubject(
                certStores(), (X509CertSelector)targetCertConstraints());
        }
        @Override List<CertStore> certStores() {
            if (stores == null) {
                // reorder CertStores so that local CertStores are tried first
                stores = new ArrayList<>(params.getCertStores());
                Collections.sort(stores, new CertStoreComparator());
            }
            return stores;
        }
        int maxPathLength() { return params.getMaxPathLength(); }
        boolean buildForward() { return buildForward; }
        PKIXBuilderParameters params() { return params; }
        X500Principal targetSubject() { return targetSubject; }

        /**
         * Returns the target subject DN from the first X509Certificate that
         * is fetched that matches the specified X509CertSelector.
         */
        private static X500Principal getTargetSubject(List<CertStore> stores,
                                                      X509CertSelector sel)
            throws InvalidAlgorithmParameterException
        {
            X500Principal subject = sel.getSubject();
            if (subject != null) {
                return subject;
            }
            X509Certificate cert = sel.getCertificate();
            if (cert != null) {
                subject = cert.getSubjectX500Principal();
            }
            if (subject != null) {
                return subject;
            }
            for (CertStore store : stores) {
                try {
                    Collection<? extends Certificate> certs =
                        (Collection<? extends Certificate>)
                            store.getCertificates(sel);
                    if (!certs.isEmpty()) {
                        X509Certificate xc =
                            (X509Certificate)certs.iterator().next();
                        return xc.getSubjectX500Principal();
                    }
                } catch (CertStoreException e) {
                    // ignore but log it
                    if (debug != null) {
                        debug.println("BuilderParams.getTargetSubjectDN: " +
                            "non-fatal exception retrieving certs: " + e);
                        e.printStackTrace();
                    }
                }
            }
            throw new InvalidAlgorithmParameterException
                ("Could not determine unique target subject");
        }
    }

    /**
     * A CertStoreException with additional information about the type of
     * CertStore that generated the exception.
     */
    static class CertStoreTypeException extends CertStoreException {
        private static final long serialVersionUID = 7463352639238322556L;

        private final String type;

        CertStoreTypeException(String type, CertStoreException cse) {
            super(cse.getMessage(), cse.getCause());
            this.type = type;
        }
        String getType() {
            return type;
        }
    }

    /**
     * Comparator that orders CertStores so that local CertStores come before
     * remote CertStores.
     */
    private static class CertStoreComparator implements Comparator<CertStore> {
        @Override
        public int compare(CertStore store1, CertStore store2) {
            if (store1.getType().equals("Collection") ||
                store1.getCertStoreParameters() instanceof
                CollectionCertStoreParameters) {
                return -1;
            } else {
                return 1;
            }
        }
    }
}
