/*
 * Copyright (c) 1999, 2013, 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.ssl;

import java.net.Socket;

import java.io.*;
import java.util.*;
import java.security.*;
import java.security.cert.*;
import java.security.cert.Certificate;

import javax.net.ssl.*;

import sun.security.provider.certpath.AlgorithmChecker;
import sun.security.action.GetPropertyAction;

public abstract class SSLContextImpl extends SSLContextSpi {

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

    private final EphemeralKeyManager ephemeralKeyManager;
    private final SSLSessionContextImpl clientCache;
    private final SSLSessionContextImpl serverCache;

    private boolean isInitialized;

    private X509ExtendedKeyManager keyManager;
    private X509TrustManager trustManager;
    private SecureRandom secureRandom;

    // supported and default protocols
    private ProtocolList defaultServerProtocolList;
    private ProtocolList defaultClientProtocolList;
    private ProtocolList supportedProtocolList;

    // supported and default cipher suites
    private CipherSuiteList defaultServerCipherSuiteList;
    private CipherSuiteList defaultClientCipherSuiteList;
    private CipherSuiteList supportedCipherSuiteList;

    SSLContextImpl() {
        ephemeralKeyManager = new EphemeralKeyManager();
        clientCache = new SSLSessionContextImpl();
        serverCache = new SSLSessionContextImpl();
    }

    @Override
    protected void engineInit(KeyManager[] km, TrustManager[] tm,
                                SecureRandom sr) throws KeyManagementException {
        isInitialized = false;
        keyManager = chooseKeyManager(km);

        if (tm == null) {
            try {
                TrustManagerFactory tmf = TrustManagerFactory.getInstance(
                        TrustManagerFactory.getDefaultAlgorithm());
                tmf.init((KeyStore)null);
                tm = tmf.getTrustManagers();
            } catch (Exception e) {
                // eat
            }
        }
        trustManager = chooseTrustManager(tm);

        if (sr == null) {
            secureRandom = JsseJce.getSecureRandom();
        } else {
            if (SunJSSE.isFIPS() &&
                        (sr.getProvider() != SunJSSE.cryptoProvider)) {
                throw new KeyManagementException
                    ("FIPS mode: SecureRandom must be from provider "
                    + SunJSSE.cryptoProvider.getName());
            }
            secureRandom = sr;
        }

        /*
         * The initial delay of seeding the random number generator
         * could be long enough to cause the initial handshake on our
         * first connection to timeout and fail. Make sure it is
         * primed and ready by getting some initial output from it.
         */
        if (debug != null && Debug.isOn("sslctx")) {
            System.out.println("trigger seeding of SecureRandom");
        }
        secureRandom.nextInt();
        if (debug != null && Debug.isOn("sslctx")) {
            System.out.println("done seeding SecureRandom");
        }
        isInitialized = true;
    }

    private X509TrustManager chooseTrustManager(TrustManager[] tm)
            throws KeyManagementException {
        // We only use the first instance of X509TrustManager passed to us.
        for (int i = 0; tm != null && i < tm.length; i++) {
            if (tm[i] instanceof X509TrustManager) {
                if (SunJSSE.isFIPS() &&
                        !(tm[i] instanceof X509TrustManagerImpl)) {
                    throw new KeyManagementException
                        ("FIPS mode: only SunJSSE TrustManagers may be used");
                }

                if (tm[i] instanceof X509ExtendedTrustManager) {
                    return (X509TrustManager)tm[i];
                } else {
                    return new AbstractTrustManagerWrapper(
                                        (X509TrustManager)tm[i]);
                }
            }
        }

        // nothing found, return a dummy X509TrustManager.
        return DummyX509TrustManager.INSTANCE;
    }

    private X509ExtendedKeyManager chooseKeyManager(KeyManager[] kms)
            throws KeyManagementException {
        for (int i = 0; kms != null && i < kms.length; i++) {
            KeyManager km = kms[i];
            if (!(km instanceof X509KeyManager)) {
                continue;
            }
            if (SunJSSE.isFIPS()) {
                // In FIPS mode, require that one of SunJSSE's own keymanagers
                // is used. Otherwise, we cannot be sure that only keys from
                // the FIPS token are used.
                if ((km instanceof X509KeyManagerImpl)
                            || (km instanceof SunX509KeyManagerImpl)) {
                    return (X509ExtendedKeyManager)km;
                } else {
                    // throw exception, we don't want to silently use the
                    // dummy keymanager without telling the user.
                    throw new KeyManagementException
                        ("FIPS mode: only SunJSSE KeyManagers may be used");
                }
            }
            if (km instanceof X509ExtendedKeyManager) {
                return (X509ExtendedKeyManager)km;
            }
            if (debug != null && Debug.isOn("sslctx")) {
                System.out.println(
                    "X509KeyManager passed to " +
                    "SSLContext.init():  need an " +
                    "X509ExtendedKeyManager for SSLEngine use");
            }
            return new AbstractKeyManagerWrapper((X509KeyManager)km);
        }

        // nothing found, return a dummy X509ExtendedKeyManager
        return DummyX509KeyManager.INSTANCE;
    }

    @Override
    protected SSLSocketFactory engineGetSocketFactory() {
        if (!isInitialized) {
            throw new IllegalStateException(
                "SSLContextImpl is not initialized");
        }
       return new SSLSocketFactoryImpl(this);
    }

    @Override
    protected SSLServerSocketFactory engineGetServerSocketFactory() {
        if (!isInitialized) {
            throw new IllegalStateException("SSLContext is not initialized");
        }
        return new SSLServerSocketFactoryImpl(this);
    }

    @Override
    protected SSLEngine engineCreateSSLEngine() {
        if (!isInitialized) {
            throw new IllegalStateException(
                "SSLContextImpl is not initialized");
        }
        return new SSLEngineImpl(this);
    }

    @Override
    protected SSLEngine engineCreateSSLEngine(String host, int port) {
        if (!isInitialized) {
            throw new IllegalStateException(
                "SSLContextImpl is not initialized");
        }
        return new SSLEngineImpl(this, host, port);
    }

    @Override
    protected SSLSessionContext engineGetClientSessionContext() {
        return clientCache;
    }

    @Override
    protected SSLSessionContext engineGetServerSessionContext() {
        return serverCache;
    }

    SecureRandom getSecureRandom() {
        return secureRandom;
    }

    X509ExtendedKeyManager getX509KeyManager() {
        return keyManager;
    }

    X509TrustManager getX509TrustManager() {
        return trustManager;
    }

    EphemeralKeyManager getEphemeralKeyManager() {
        return ephemeralKeyManager;
    }

    abstract SSLParameters getDefaultServerSSLParams();
    abstract SSLParameters getDefaultClientSSLParams();
    abstract SSLParameters getSupportedSSLParams();

    // Get supported ProtocolList.
    ProtocolList getSuportedProtocolList() {
        if (supportedProtocolList == null) {
            supportedProtocolList =
                new ProtocolList(getSupportedSSLParams().getProtocols());
        }

        return supportedProtocolList;
    }

    // Get default ProtocolList.
    ProtocolList getDefaultProtocolList(boolean roleIsServer) {
        if (roleIsServer) {
            if (defaultServerProtocolList == null) {
                defaultServerProtocolList = new ProtocolList(
                        getDefaultServerSSLParams().getProtocols());
            }

            return defaultServerProtocolList;
        } else {
            if (defaultClientProtocolList == null) {
                defaultClientProtocolList = new ProtocolList(
                        getDefaultClientSSLParams().getProtocols());
            }

            return defaultClientProtocolList;
        }
    }

    // Get supported CipherSuiteList.
    CipherSuiteList getSupportedCipherSuiteList() {
        // The maintenance of cipher suites needs to be synchronized.
        synchronized (this) {
            // Clear cache of available ciphersuites.
            clearAvailableCache();

            if (supportedCipherSuiteList == null) {
                supportedCipherSuiteList = getApplicableCipherSuiteList(
                        getSuportedProtocolList(), false);
            }

            return supportedCipherSuiteList;
        }
    }

    // Get default CipherSuiteList.
    CipherSuiteList getDefaultCipherSuiteList(boolean roleIsServer) {
        // The maintenance of cipher suites needs to be synchronized.
        synchronized (this) {
            // Clear cache of available ciphersuites.
            clearAvailableCache();

            if (roleIsServer) {
                if (defaultServerCipherSuiteList == null) {
                    defaultServerCipherSuiteList = getApplicableCipherSuiteList(
                        getDefaultProtocolList(true), true);
                }

                return defaultServerCipherSuiteList;
            } else {
                if (defaultClientCipherSuiteList == null) {
                    defaultClientCipherSuiteList = getApplicableCipherSuiteList(
                        getDefaultProtocolList(false), true);
                }

                return defaultClientCipherSuiteList;
            }
        }
    }

    /**
     * Return whether a protocol list is the original default enabled
     * protocols.  See: SSLSocket/SSLEngine.setEnabledProtocols()
     */
    boolean isDefaultProtocolList(ProtocolList protocols) {
        return (protocols == defaultServerProtocolList) ||
               (protocols == defaultClientProtocolList);
    }


    /*
     * Return the list of all available CipherSuites with a priority of
     * minPriority or above.
     */
    private CipherSuiteList getApplicableCipherSuiteList(
            ProtocolList protocols, boolean onlyEnabled) {

        int minPriority = CipherSuite.SUPPORTED_SUITES_PRIORITY;
        if (onlyEnabled) {
            minPriority = CipherSuite.DEFAULT_SUITES_PRIORITY;
        }

        Collection<CipherSuite> allowedCipherSuites =
                                    CipherSuite.allowedCipherSuites();

        TreeSet<CipherSuite> suites = new TreeSet<>();
        if (!(protocols.collection().isEmpty()) &&
                protocols.min.v != ProtocolVersion.NONE.v) {
            for (CipherSuite suite : allowedCipherSuites) {
                if (!suite.allowed || suite.priority < minPriority) {
                    continue;
                }

                if (suite.isAvailable() &&
                        suite.obsoleted > protocols.min.v &&
                        suite.supported <= protocols.max.v) {
                    if (SSLAlgorithmConstraints.DEFAULT.permits(
                            EnumSet.of(CryptoPrimitive.KEY_AGREEMENT),
                            suite.name, null)) {
                        suites.add(suite);
                    }
                } else if (debug != null &&
                        Debug.isOn("sslctx") && Debug.isOn("verbose")) {
                    if (suite.obsoleted <= protocols.min.v) {
                        System.out.println(
                            "Ignoring obsoleted cipher suite: " + suite);
                    } else if (suite.supported > protocols.max.v) {
                        System.out.println(
                            "Ignoring unsupported cipher suite: " + suite);
                    } else {
                        System.out.println(
                            "Ignoring unavailable cipher suite: " + suite);
                    }
                }
            }
        }

        return new CipherSuiteList(suites);
    }

    /**
     * Clear cache of available ciphersuites. If we support all ciphers
     * internally, there is no need to clear the cache and calling this
     * method has no effect.
     *
     * Note that every call to clearAvailableCache() and the maintenance of
     * cipher suites need to be synchronized with this instance.
     */
    private void clearAvailableCache() {
        if (CipherSuite.DYNAMIC_AVAILABILITY) {
            supportedCipherSuiteList = null;
            defaultServerCipherSuiteList = null;
            defaultClientCipherSuiteList = null;
            CipherSuite.BulkCipher.clearAvailableCache();
            JsseJce.clearEcAvailable();
        }
    }

    /*
     * The SSLContext implementation for TLS/SSL algorithm
     *
     * SSL/TLS protocols specify the forward compatibility and version
     * roll-back attack protections, however, a number of SSL/TLS server
     * vendors did not implement these aspects properly, and some current
     * SSL/TLS servers may refuse to talk to a TLS 1.1 or later client.
     *
     * Considering above interoperability issues, SunJSSE will not set
     * TLS 1.1 and TLS 1.2 as the enabled protocols for client by default.
     *
     * For SSL/TLS servers, there is no such interoperability issues as
     * SSL/TLS clients. In SunJSSE, TLS 1.1 or later version will be the
     * enabled protocols for server by default.
     *
     * We may change the behavior when popular TLS/SSL vendors support TLS
     * forward compatibility properly.
     *
     * SSLv2Hello is no longer necessary.  This interoperability option was
     * put in place in the late 90's when SSLv3/TLS1.0 were relatively new
     * and there were a fair number of SSLv2-only servers deployed.  Because
     * of the security issues in SSLv2, it is rarely (if ever) used, as
     * deployments should now be using SSLv3 and TLSv1.
     *
     * Considering the issues of SSLv2Hello, we should not enable SSLv2Hello
     * by default. Applications still can use it by enabling SSLv2Hello with
     * the series of setEnabledProtocols APIs.
     */

    /*
     * The base abstract SSLContext implementation.
     *
     * This abstract class encapsulates supported and the default server
     * SSL parameters.
     *
     * @see SSLContext
     */
    private abstract static class AbstractSSLContext extends SSLContextImpl {
        // parameters
        private static final SSLParameters defaultServerSSLParams;
        private static final SSLParameters supportedSSLParams;

        static {
            // supported SSL parameters
            supportedSSLParams = new SSLParameters();

            // candidates for available protocols
            ProtocolVersion[] candidates;

            if (SunJSSE.isFIPS()) {
                supportedSSLParams.setProtocols(new String[] {
                    ProtocolVersion.TLS10.name,
                    ProtocolVersion.TLS11.name,
                    ProtocolVersion.TLS12.name
                });

                candidates = new ProtocolVersion[] {
                    ProtocolVersion.TLS10,
                    ProtocolVersion.TLS11,
                    ProtocolVersion.TLS12
                };
            } else {
                supportedSSLParams.setProtocols(new String[] {
                    ProtocolVersion.SSL20Hello.name,
                    ProtocolVersion.SSL30.name,
                    ProtocolVersion.TLS10.name,
                    ProtocolVersion.TLS11.name,
                    ProtocolVersion.TLS12.name
                });

                candidates = new ProtocolVersion[] {
                    ProtocolVersion.SSL20Hello,
                    ProtocolVersion.SSL30,
                    ProtocolVersion.TLS10,
                    ProtocolVersion.TLS11,
                    ProtocolVersion.TLS12
                };
            }

            defaultServerSSLParams = new SSLParameters();
            defaultServerSSLParams.setProtocols(
                getAvailableProtocols(candidates).toArray(new String[0]));
        }

        @Override
        SSLParameters getDefaultServerSSLParams() {
            return defaultServerSSLParams;
        }

        @Override
        SSLParameters getSupportedSSLParams() {
            return supportedSSLParams;
        }

        static List<String> getAvailableProtocols(
                ProtocolVersion[] protocolCandidates) {

            List<String> availableProtocols = Collections.<String>emptyList();
            if (protocolCandidates !=  null && protocolCandidates.length != 0) {
                availableProtocols = new ArrayList<>(protocolCandidates.length);
                for (ProtocolVersion p : protocolCandidates) {
                    if (ProtocolVersion.availableProtocols.contains(p)) {
                        availableProtocols.add(p.name);
                    }
                }
            }

            return availableProtocols;
        }
    }

    /*
     * The SSLContext implementation for SSLv3 and TLS10 algorithm
     *
     * @see SSLContext
     */
    public static final class TLS10Context extends AbstractSSLContext {
        private static final SSLParameters defaultClientSSLParams;

        static {
            // candidates for available protocols
            ProtocolVersion[] candidates;
            if (SunJSSE.isFIPS()) {
                candidates = new ProtocolVersion[] {
                    ProtocolVersion.TLS10
                };
            } else {
                candidates = new ProtocolVersion[] {
                    ProtocolVersion.SSL30,
                    ProtocolVersion.TLS10
                };
            }

            defaultClientSSLParams = new SSLParameters();
            defaultClientSSLParams.setProtocols(
                getAvailableProtocols(candidates).toArray(new String[0]));
        }

        @Override
        SSLParameters getDefaultClientSSLParams() {
            return defaultClientSSLParams;
        }
    }

    /*
     * The SSLContext implementation for TLS11 algorithm
     *
     * @see SSLContext
     */
    public static final class TLS11Context extends AbstractSSLContext {
        private static final SSLParameters defaultClientSSLParams;

        static {
            // candidates for available protocols
            ProtocolVersion[] candidates;
            if (SunJSSE.isFIPS()) {
                candidates = new ProtocolVersion[] {
                    ProtocolVersion.TLS10,
                    ProtocolVersion.TLS11
                };
            } else {
                candidates = new ProtocolVersion[] {
                    ProtocolVersion.SSL30,
                    ProtocolVersion.TLS10,
                    ProtocolVersion.TLS11
                };
            }

            defaultClientSSLParams = new SSLParameters();
            defaultClientSSLParams.setProtocols(
                getAvailableProtocols(candidates).toArray(new String[0]));
        }

        @Override
        SSLParameters getDefaultClientSSLParams() {
            return defaultClientSSLParams;
        }
    }

    /*
     * The SSLContext implementation for TLS12 algorithm
     *
     * @see SSLContext
     */
    public static final class TLS12Context extends AbstractSSLContext {
        private static final SSLParameters defaultClientSSLParams;

        static {
            // candidates for available protocols
            ProtocolVersion[] candidates;
            if (SunJSSE.isFIPS()) {
                candidates = new ProtocolVersion[] {
                    ProtocolVersion.TLS10,
                    ProtocolVersion.TLS11,
                    ProtocolVersion.TLS12
                };
            } else {
                candidates = new ProtocolVersion[] {
                    ProtocolVersion.SSL30,
                    ProtocolVersion.TLS10,
                    ProtocolVersion.TLS11,
                    ProtocolVersion.TLS12
                };
            }

            defaultClientSSLParams = new SSLParameters();
            defaultClientSSLParams.setProtocols(
                getAvailableProtocols(candidates).toArray(new String[0]));
        }

        @Override
        SSLParameters getDefaultClientSSLParams() {
            return defaultClientSSLParams;
        }
    }

    /*
     * The SSLContext implementation for customized TLS protocols
     *
     * @see SSLContext
     */
    private static class CustomizedSSLContext extends AbstractSSLContext {
        private static final String PROPERTY_NAME = "jdk.tls.client.protocols";
        private static final SSLParameters defaultClientSSLParams;
        private static IllegalArgumentException reservedException = null;

        // Don't want a java.lang.LinkageError for illegal system property.
        //
        // Please don't throw exception in this static block.  Otherwise,
        // java.lang.LinkageError may be thrown during the instantiation of
        // the provider service. Instead, let's handle the initialization
        // exception in constructor.
        static {
            // candidates for available protocols
            ProtocolVersion[] candidates;

            String property = AccessController.doPrivileged(
                    new GetPropertyAction(PROPERTY_NAME));
            if (property == null || property.length() == 0) {
                // the default enabled client TLS protocols
                if (SunJSSE.isFIPS()) {
                    candidates = new ProtocolVersion[] {
                        ProtocolVersion.TLS10,
                        ProtocolVersion.TLS11,
                        ProtocolVersion.TLS12
                    };
                } else {
                    candidates = new ProtocolVersion[] {
                        ProtocolVersion.SSL30,
                        ProtocolVersion.TLS10,
                        ProtocolVersion.TLS11,
                        ProtocolVersion.TLS12
                    };
                }
            } else {
                // remove double quote marks from beginning/end of the property
                if (property.length() > 1 && property.charAt(0) == '"' &&
                        property.charAt(property.length() - 1) == '"') {
                    property = property.substring(1, property.length() - 1);
                }

                String[] protocols = null;
                if (property != null && property.length() != 0) {
                    protocols = property.split(",");
                } else {
                    reservedException = new IllegalArgumentException(
                        "No protocol specified in " +
                        PROPERTY_NAME + " system property");
                    protocols = new String[0];
                }

                candidates = new ProtocolVersion[protocols.length];
                for (int i = 0; i < protocols.length; i++) {
                    protocols[i] = protocols[i].trim();
                    // Is it a supported protocol name?
                    try {
                        candidates[i] = ProtocolVersion.valueOf(protocols[i]);
                    } catch (IllegalArgumentException iae) {
                        reservedException = new IllegalArgumentException(
                            PROPERTY_NAME + ": " + protocols[i] +
                            " is not a standard SSL/TLS protocol name", iae);
                        break;
                    }
                }

                if ((reservedException == null) && SunJSSE.isFIPS()) {
                    for (ProtocolVersion protocolVersion : candidates) {
                        if (ProtocolVersion.SSL20Hello.v == protocolVersion.v ||
                                ProtocolVersion.SSL30.v == protocolVersion.v) {
                            reservedException = new IllegalArgumentException(
                                    PROPERTY_NAME + ": " + protocolVersion +
                                    " is not FIPS compliant");
                        }
                    }
                }
            }

            defaultClientSSLParams = new SSLParameters();
            if (reservedException == null) {
                defaultClientSSLParams.setProtocols(
                    getAvailableProtocols(candidates).toArray(new String[0]));
            }
        }

        protected CustomizedSSLContext() {
            if (reservedException != null) {
                throw reservedException;
            }
        }

        @Override
        SSLParameters getDefaultClientSSLParams() {
            return defaultClientSSLParams;
        }
    }

    /*
     * The SSLContext implementation for default "TLS" algorithm
     *
     * @see SSLContext
     */
    public static final class TLSContext extends CustomizedSSLContext {
        // use the default constructor and methods
    }

    /*
     * The SSLContext implementation for default "Default" algorithm
     *
     * @see SSLContext
     */
    public static final class DefaultSSLContext extends CustomizedSSLContext {
        private static final String NONE = "NONE";
        private static final String P11KEYSTORE = "PKCS11";

        private static volatile SSLContextImpl defaultImpl;

        private static TrustManager[] defaultTrustManagers;
        private static KeyManager[] defaultKeyManagers;

        public DefaultSSLContext() throws Exception {
            try {
                super.engineInit(getDefaultKeyManager(),
                        getDefaultTrustManager(), null);
            } catch (Exception e) {
                if (debug != null && Debug.isOn("defaultctx")) {
                    System.out.println("default context init failed: " + e);
                }
                throw e;
            }

            if (defaultImpl == null) {
                defaultImpl = this;
            }
        }

        @Override
        protected void engineInit(KeyManager[] km, TrustManager[] tm,
            SecureRandom sr) throws KeyManagementException {
            throw new KeyManagementException
                ("Default SSLContext is initialized automatically");
        }

        static synchronized SSLContextImpl getDefaultImpl() throws Exception {
            if (defaultImpl == null) {
                new DefaultSSLContext();
            }
            return defaultImpl;
        }

        private static synchronized TrustManager[] getDefaultTrustManager()
                throws Exception {
            if (defaultTrustManagers != null) {
                return defaultTrustManagers;
            }

            KeyStore ks =
                TrustManagerFactoryImpl.getCacertsKeyStore("defaultctx");

            TrustManagerFactory tmf = TrustManagerFactory.getInstance(
                TrustManagerFactory.getDefaultAlgorithm());
            tmf.init(ks);
            defaultTrustManagers = tmf.getTrustManagers();
            return defaultTrustManagers;
        }

        private static synchronized KeyManager[] getDefaultKeyManager()
                throws Exception {
            if (defaultKeyManagers != null) {
                return defaultKeyManagers;
            }

            final Map<String,String> props = new HashMap<>();
            AccessController.doPrivileged(
                        new PrivilegedExceptionAction<Object>() {
                @Override
                public Object run() throws Exception {
                    props.put("keyStore",  System.getProperty(
                                "javax.net.ssl.keyStore", ""));
                    props.put("keyStoreType", System.getProperty(
                                "javax.net.ssl.keyStoreType",
                                KeyStore.getDefaultType()));
                    props.put("keyStoreProvider", System.getProperty(
                                "javax.net.ssl.keyStoreProvider", ""));
                    props.put("keyStorePasswd", System.getProperty(
                                "javax.net.ssl.keyStorePassword", ""));
                    return null;
                }
            });

            final String defaultKeyStore = props.get("keyStore");
            String defaultKeyStoreType = props.get("keyStoreType");
            String defaultKeyStoreProvider = props.get("keyStoreProvider");
            if (debug != null && Debug.isOn("defaultctx")) {
                System.out.println("keyStore is : " + defaultKeyStore);
                System.out.println("keyStore type is : " +
                                        defaultKeyStoreType);
                System.out.println("keyStore provider is : " +
                                        defaultKeyStoreProvider);
            }

            if (P11KEYSTORE.equals(defaultKeyStoreType) &&
                    !NONE.equals(defaultKeyStore)) {
                throw new IllegalArgumentException("if keyStoreType is "
                    + P11KEYSTORE + ", then keyStore must be " + NONE);
            }

            FileInputStream fs = null;
            KeyStore ks = null;
            char[] passwd = null;
            try {
                if (defaultKeyStore.length() != 0 &&
                        !NONE.equals(defaultKeyStore)) {
                    fs = AccessController.doPrivileged(
                            new PrivilegedExceptionAction<FileInputStream>() {
                        @Override
                        public FileInputStream run() throws Exception {
                            return new FileInputStream(defaultKeyStore);
                        }
                    });
                }

                String defaultKeyStorePassword = props.get("keyStorePasswd");
                if (defaultKeyStorePassword.length() != 0) {
                    passwd = defaultKeyStorePassword.toCharArray();
                }

                /**
                 * Try to initialize key store.
                 */
                if ((defaultKeyStoreType.length()) != 0) {
                    if (debug != null && Debug.isOn("defaultctx")) {
                        System.out.println("init keystore");
                    }
                    if (defaultKeyStoreProvider.length() == 0) {
                        ks = KeyStore.getInstance(defaultKeyStoreType);
                    } else {
                        ks = KeyStore.getInstance(defaultKeyStoreType,
                                            defaultKeyStoreProvider);
                    }

                    // if defaultKeyStore is NONE, fs will be null
                    ks.load(fs, passwd);
                }
            } finally {
                if (fs != null) {
                    fs.close();
                    fs = null;
                }
            }

            /*
             * Try to initialize key manager.
             */
            if (debug != null && Debug.isOn("defaultctx")) {
                System.out.println("init keymanager of type " +
                    KeyManagerFactory.getDefaultAlgorithm());
            }
            KeyManagerFactory kmf = KeyManagerFactory.getInstance(
                KeyManagerFactory.getDefaultAlgorithm());

            if (P11KEYSTORE.equals(defaultKeyStoreType)) {
                kmf.init(ks, null); // do not pass key passwd if using token
            } else {
                kmf.init(ks, passwd);
            }

            defaultKeyManagers = kmf.getKeyManagers();
            return defaultKeyManagers;
        }
    }

}


final class AbstractTrustManagerWrapper extends X509ExtendedTrustManager
            implements X509TrustManager {

    // the delegated trust manager
    private final X509TrustManager tm;

    AbstractTrustManagerWrapper(X509TrustManager tm) {
        this.tm = tm;
    }

    @Override
    public void checkClientTrusted(X509Certificate[] chain, String authType)
        throws CertificateException {
        tm.checkClientTrusted(chain, authType);
    }

    @Override
    public void checkServerTrusted(X509Certificate[] chain, String authType)
        throws CertificateException {
        tm.checkServerTrusted(chain, authType);
    }

    @Override
    public X509Certificate[] getAcceptedIssuers() {
        return tm.getAcceptedIssuers();
    }

    @Override
    public void checkClientTrusted(X509Certificate[] chain, String authType,
                Socket socket) throws CertificateException {
        tm.checkClientTrusted(chain, authType);
        checkAdditionalTrust(chain, authType, socket, true);
    }

    @Override
    public void checkServerTrusted(X509Certificate[] chain, String authType,
            Socket socket) throws CertificateException {
        tm.checkServerTrusted(chain, authType);
        checkAdditionalTrust(chain, authType, socket, false);
    }

    @Override
    public void checkClientTrusted(X509Certificate[] chain, String authType,
            SSLEngine engine) throws CertificateException {
        tm.checkClientTrusted(chain, authType);
        checkAdditionalTrust(chain, authType, engine, true);
    }

    @Override
    public void checkServerTrusted(X509Certificate[] chain, String authType,
            SSLEngine engine) throws CertificateException {
        tm.checkServerTrusted(chain, authType);
        checkAdditionalTrust(chain, authType, engine, false);
    }

    private void checkAdditionalTrust(X509Certificate[] chain, String authType,
                Socket socket, boolean isClient) throws CertificateException {
        if (socket != null && socket.isConnected() &&
                                    socket instanceof SSLSocket) {

            SSLSocket sslSocket = (SSLSocket)socket;
            SSLSession session = sslSocket.getHandshakeSession();
            if (session == null) {
                throw new CertificateException("No handshake session");
            }

            // check endpoint identity
            String identityAlg = sslSocket.getSSLParameters().
                                        getEndpointIdentificationAlgorithm();
            if (identityAlg != null && identityAlg.length() != 0) {
                String hostname = session.getPeerHost();
                X509TrustManagerImpl.checkIdentity(
                                    hostname, chain[0], identityAlg);
            }

            // try the best to check the algorithm constraints
            ProtocolVersion protocolVersion =
                ProtocolVersion.valueOf(session.getProtocol());
            AlgorithmConstraints constraints = null;
            if (protocolVersion.v >= ProtocolVersion.TLS12.v) {
                if (session instanceof ExtendedSSLSession) {
                    ExtendedSSLSession extSession =
                                    (ExtendedSSLSession)session;
                    String[] peerSupportedSignAlgs =
                            extSession.getLocalSupportedSignatureAlgorithms();

                    constraints = new SSLAlgorithmConstraints(
                                    sslSocket, peerSupportedSignAlgs, true);
                } else {
                    constraints =
                            new SSLAlgorithmConstraints(sslSocket, true);
                }
            } else {
                constraints = new SSLAlgorithmConstraints(sslSocket, true);
            }

            checkAlgorithmConstraints(chain, constraints);
        }
    }

    private void checkAdditionalTrust(X509Certificate[] chain, String authType,
            SSLEngine engine, boolean isClient) throws CertificateException {
        if (engine != null) {
            SSLSession session = engine.getHandshakeSession();
            if (session == null) {
                throw new CertificateException("No handshake session");
            }

            // check endpoint identity
            String identityAlg = engine.getSSLParameters().
                                        getEndpointIdentificationAlgorithm();
            if (identityAlg != null && identityAlg.length() != 0) {
                String hostname = session.getPeerHost();
                X509TrustManagerImpl.checkIdentity(
                                    hostname, chain[0], identityAlg);
            }

            // try the best to check the algorithm constraints
            ProtocolVersion protocolVersion =
                ProtocolVersion.valueOf(session.getProtocol());
            AlgorithmConstraints constraints = null;
            if (protocolVersion.v >= ProtocolVersion.TLS12.v) {
                if (session instanceof ExtendedSSLSession) {
                    ExtendedSSLSession extSession =
                                    (ExtendedSSLSession)session;
                    String[] peerSupportedSignAlgs =
                            extSession.getLocalSupportedSignatureAlgorithms();

                    constraints = new SSLAlgorithmConstraints(
                                    engine, peerSupportedSignAlgs, true);
                } else {
                    constraints =
                            new SSLAlgorithmConstraints(engine, true);
                }
            } else {
                constraints = new SSLAlgorithmConstraints(engine, true);
            }

            checkAlgorithmConstraints(chain, constraints);
        }
    }

    private void checkAlgorithmConstraints(X509Certificate[] chain,
            AlgorithmConstraints constraints) throws CertificateException {

        try {
            // Does the certificate chain end with a trusted certificate?
            int checkedLength = chain.length - 1;

            Collection<X509Certificate> trustedCerts = new HashSet<>();
            X509Certificate[] certs = tm.getAcceptedIssuers();
            if ((certs != null) && (certs.length > 0)){
                Collections.addAll(trustedCerts, certs);
            }

            if (trustedCerts.contains(chain[checkedLength])) {
                    checkedLength--;
            }

            // A forward checker, need to check from trust to target
            if (checkedLength >= 0) {
                AlgorithmChecker checker = new AlgorithmChecker(constraints);
                checker.init(false);
                for (int i = checkedLength; i >= 0; i--) {
                    Certificate cert = chain[i];
                    // We don't care about the unresolved critical extensions.
                    checker.check(cert, Collections.<String>emptySet());
                }
            }
        } catch (CertPathValidatorException cpve) {
            throw new CertificateException(
                "Certificates does not conform to algorithm constraints");
        }
    }
}

// Dummy X509TrustManager implementation, rejects all peer certificates.
// Used if the application did not specify a proper X509TrustManager.
final class DummyX509TrustManager extends X509ExtendedTrustManager
            implements X509TrustManager {

    static final X509TrustManager INSTANCE = new DummyX509TrustManager();

    private DummyX509TrustManager() {
        // empty
    }

    /*
     * Given the partial or complete certificate chain
     * provided by the peer, build a certificate path
     * to a trusted root and return if it can be
     * validated and is trusted for client SSL authentication.
     * If not, it throws an exception.
     */
    @Override
    public void checkClientTrusted(X509Certificate[] chain, String authType)
        throws CertificateException {
        throw new CertificateException(
            "No X509TrustManager implementation avaiable");
    }

    /*
     * Given the partial or complete certificate chain
     * provided by the peer, build a certificate path
     * to a trusted root and return if it can be
     * validated and is trusted for server SSL authentication.
     * If not, it throws an exception.
     */
    @Override
    public void checkServerTrusted(X509Certificate[] chain, String authType)
        throws CertificateException {
        throw new CertificateException(
            "No X509TrustManager implementation available");
    }

    /*
     * Return an array of issuer certificates which are trusted
     * for authenticating peers.
     */
    @Override
    public X509Certificate[] getAcceptedIssuers() {
        return new X509Certificate[0];
    }

    @Override
    public void checkClientTrusted(X509Certificate[] chain, String authType,
                Socket socket) throws CertificateException {
        throw new CertificateException(
            "No X509TrustManager implementation available");
    }

    @Override
    public void checkServerTrusted(X509Certificate[] chain, String authType,
            Socket socket) throws CertificateException {
        throw new CertificateException(
            "No X509TrustManager implementation available");
    }

    @Override
    public void checkClientTrusted(X509Certificate[] chain, String authType,
            SSLEngine engine) throws CertificateException {
        throw new CertificateException(
            "No X509TrustManager implementation available");
    }

    @Override
    public void checkServerTrusted(X509Certificate[] chain, String authType,
            SSLEngine engine) throws CertificateException {
        throw new CertificateException(
            "No X509TrustManager implementation available");
    }
}

/*
 * A wrapper class to turn a X509KeyManager into an X509ExtendedKeyManager
 */
final class AbstractKeyManagerWrapper extends X509ExtendedKeyManager {

    private final X509KeyManager km;

    AbstractKeyManagerWrapper(X509KeyManager km) {
        this.km = km;
    }

    @Override
    public String[] getClientAliases(String keyType, Principal[] issuers) {
        return km.getClientAliases(keyType, issuers);
    }

    @Override
    public String chooseClientAlias(String[] keyType, Principal[] issuers,
            Socket socket) {
        return km.chooseClientAlias(keyType, issuers, socket);
    }

    @Override
    public String[] getServerAliases(String keyType, Principal[] issuers) {
        return km.getServerAliases(keyType, issuers);
    }

    @Override
    public String chooseServerAlias(String keyType, Principal[] issuers,
            Socket socket) {
        return km.chooseServerAlias(keyType, issuers, socket);
    }

    @Override
    public X509Certificate[] getCertificateChain(String alias) {
        return km.getCertificateChain(alias);
    }

    @Override
    public PrivateKey getPrivateKey(String alias) {
        return km.getPrivateKey(alias);
    }

    // Inherit chooseEngineClientAlias() and chooseEngineServerAlias() from
    // X509ExtendedKeymanager. It defines them to return null;
}


// Dummy X509KeyManager implementation, never returns any certificates/keys.
// Used if the application did not specify a proper X509TrustManager.
final class DummyX509KeyManager extends X509ExtendedKeyManager {

    static final X509ExtendedKeyManager INSTANCE = new DummyX509KeyManager();

    private DummyX509KeyManager() {
        // empty
    }

    /*
     * Get the matching aliases for authenticating the client side of a secure
     * socket given the public key type and the list of
     * certificate issuer authorities recognized by the peer (if any).
     */
    @Override
    public String[] getClientAliases(String keyType, Principal[] issuers) {
        return null;
    }

    /*
     * Choose an alias to authenticate the client side of a secure
     * socket given the public key type and the list of
     * certificate issuer authorities recognized by the peer (if any).
     */
    @Override
    public String chooseClientAlias(String[] keyTypes, Principal[] issuers,
            Socket socket) {
        return null;
    }

    /*
     * Choose an alias to authenticate the client side of an
     * engine given the public key type and the list of
     * certificate issuer authorities recognized by the peer (if any).
     */
    @Override
    public String chooseEngineClientAlias(
            String[] keyTypes, Principal[] issuers, SSLEngine engine) {
        return null;
    }

    /*
     * Get the matching aliases for authenticating the server side of a secure
     * socket given the public key type and the list of
     * certificate issuer authorities recognized by the peer (if any).
     */
    @Override
    public String[] getServerAliases(String keyType, Principal[] issuers) {
        return null;
    }

    /*
     * Choose an alias to authenticate the server side of a secure
     * socket given the public key type and the list of
     * certificate issuer authorities recognized by the peer (if any).
     */
    @Override
    public String chooseServerAlias(String keyType, Principal[] issuers,
            Socket socket) {
        return null;
    }

    /*
     * Choose an alias to authenticate the server side of an engine
     * given the public key type and the list of
     * certificate issuer authorities recognized by the peer (if any).
     */
    @Override
    public String chooseEngineServerAlias(
            String keyType, Principal[] issuers, SSLEngine engine) {
        return null;
    }

    /**
     * Returns the certificate chain associated with the given alias.
     *
     * @param alias the alias name
     *
     * @return the certificate chain (ordered with the user's certificate first
     * and the root certificate authority last)
     */
    @Override
    public X509Certificate[] getCertificateChain(String alias) {
        return null;
    }

    /*
     * Returns the key associated with the given alias, using the given
     * password to recover it.
     *
     * @param alias the alias name
     *
     * @return the requested key
     */
    @Override
    public PrivateKey getPrivateKey(String alias) {
        return null;
    }
}
