/*
 * Copyright (c) 2012, 2015, 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.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 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");
            }
            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(); }
        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;
            }
        }
    }
}
