alvinalexander.com | career | drupal | java | mac | mysql | perl | scala | uml | unix  

Java example source code file (SSLContextImpl.java)

This example Java source code file (SSLContextImpl.java) is included in the alvinalexander.com "Java Source Code Warehouse" project. The intent of this project is to help you "Learn Java by Example" TM.

Learn more about this Java project at its project page.

Java - Java tags/keywords

certificateexception, keymanagementexception, net, network, override, principal, protocollist, security, socket, ssl, sslalgorithmconstraints, sslcontextimpl, sslengine, sslparameters, string, util, x509extendedkeymanager, x509trustmanager

The SSLContextImpl.java Java example source code

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

    // The default algrithm constraints
    private AlgorithmConstraints defaultAlgorithmConstraints =
                                 new SSLAlgorithmConstraints(null);

    // 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 (defaultAlgorithmConstraints.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 final static SSLParameters defaultServerSSLParams;
        private final static SSLParameters supportedSSLParams;

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

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

                defaultServerSSLParams = supportedSSLParams;
            }
        }

        @Override
        SSLParameters getDefaultServerSSLParams() {
            return defaultServerSSLParams;
        }

        @Override
        SSLParameters getSupportedSSLParams() {
            return supportedSSLParams;
        }
    }

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

        static {
            defaultClientSSLParams = new SSLParameters();
            if (SunJSSE.isFIPS()) {
                defaultClientSSLParams.setProtocols(new String[] {
                    ProtocolVersion.TLS10.name
                });

            } else {
                defaultClientSSLParams.setProtocols(new String[] {
                    ProtocolVersion.SSL30.name,
                    ProtocolVersion.TLS10.name
                });
            }
        }

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

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

        static {
            defaultClientSSLParams = new SSLParameters();
            if (SunJSSE.isFIPS()) {
                defaultClientSSLParams.setProtocols(new String[] {
                    ProtocolVersion.TLS10.name,
                    ProtocolVersion.TLS11.name
                });

            } else {
                defaultClientSSLParams.setProtocols(new String[] {
                    ProtocolVersion.SSL30.name,
                    ProtocolVersion.TLS10.name,
                    ProtocolVersion.TLS11.name
                });
            }
        }

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

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

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

            } else {
                defaultClientSSLParams.setProtocols(new String[] {
                    ProtocolVersion.SSL30.name,
                    ProtocolVersion.TLS10.name,
                    ProtocolVersion.TLS11.name,
                    ProtocolVersion.TLS12.name
                });
            }
        }

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

    /*
     * The SSLContext implementation for customized TLS protocols
     *
     * @see SSLContext
     */
    private static class CustomizedSSLContext extends AbstractSSLContext {
        private final static String PROPERTY_NAME = "jdk.tls.client.protocols";
        private final static 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 {
            String property = AccessController.doPrivileged(
                    new GetPropertyAction(PROPERTY_NAME));
            defaultClientSSLParams = new SSLParameters();
            if (property == null || property.length() == 0) {
                // the default enabled client TLS protocols
                if (SunJSSE.isFIPS()) {
                    defaultClientSSLParams.setProtocols(new String[] {
                        ProtocolVersion.TLS10.name,
                        ProtocolVersion.TLS11.name,
                        ProtocolVersion.TLS12.name
                    });

                } else {
                    defaultClientSSLParams.setProtocols(new String[] {
                        ProtocolVersion.SSL30.name,
                        ProtocolVersion.TLS10.name,
                        ProtocolVersion.TLS11.name,
                        ProtocolVersion.TLS12.name
                    });
                }
            } else {
                // remove double quote marks from beginning/end of the property
                if (property.charAt(0) == '"' &&
                        property.charAt(property.length() - 1) == '"') {
                    property = property.substring(1, property.length() - 1);
                }

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

                if ((reservedException == null) && SunJSSE.isFIPS()) {
                    for (String protocol : protocols) {
                        if (ProtocolVersion.SSL20Hello.name.equals(protocol) ||
                                ProtocolVersion.SSL30.name.equals(protocol)) {
                            reservedException = new IllegalArgumentException(
                                    PROPERTY_NAME + ": " + protocol +
                                    " is not FIPS compliant");
                        }
                    }
                }

                if (reservedException == null) {
                    defaultClientSSLParams.setProtocols(protocols);
               }
            }
        }

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

Other Java examples (source code examples)

Here is a short list of links related to this Java SSLContextImpl.java source code file:

... this post is sponsored by my books ...

#1 New Release!

FP Best Seller

 

new blog posts

 

Copyright 1998-2024 Alvin Alexander, alvinalexander.com
All Rights Reserved.

A percentage of advertising revenue from
pages under the /java/jwarehouse URI on this website is
paid back to open source projects.