1145 lines · 41.1 KB · Java
RawDownload
/* * Copyright (c) 1999, 2011, 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; 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();    }     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 == false) {                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;    }     protected SSLSocketFactory engineGetSocketFactory() {        if (!isInitialized) {            throw new IllegalStateException(                "SSLContextImpl is not initialized");        }       return new SSLSocketFactoryImpl(this);    }     protected SSLServerSocketFactory engineGetServerSocketFactory() {        if (!isInitialized) {            throw new IllegalStateException("SSLContext is not initialized");        }        return new SSLServerSocketFactoryImpl(this);    }     protected SSLEngine engineCreateSSLEngine() {        if (!isInitialized) {            throw new IllegalStateException(                "SSLContextImpl is not initialized");        }        return new SSLEngineImpl(this);    }     protected SSLEngine engineCreateSSLEngine(String host, int port) {        if (!isInitialized) {            throw new IllegalStateException(                "SSLContextImpl is not initialized");        }        return new SSLEngineImpl(this, host, port);    }     protected SSLSessionContext engineGetClientSessionContext() {        return clientCache;    }     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 suported ProtoclList.    ProtocolList getSuportedProtocolList() {        if (supportedProtocolList == null) {            supportedProtocolList =                new ProtocolList(getSupportedSSLParams().getProtocols());        }         return supportedProtocolList;    }     // Get default ProtoclList.    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 suported CipherSuiteList.    CipherSuiteList getSuportedCipherSuiteList() {        // Clear cache of available ciphersuites.        clearAvailableCache();         if (supportedCipherSuiteList == null) {            supportedCipherSuiteList =                getApplicableCipherSuiteList(getSuportedProtocolList(), false);        }         return supportedCipherSuiteList;    }     // Get default CipherSuiteList.    CipherSuiteList getDefaultCipherSuiteList(boolean roleIsServer) {        // 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();         ArrayList<CipherSuite> suites = new ArrayList<>();        if (!(protocols.collection().isEmpty()) &&                protocols.min.v != ProtocolVersion.NONE.v) {            for (CipherSuite suite : allowedCipherSuites) {                if (suite.allowed == false || 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.     */    synchronized 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 conservative SSLContext implementation for TLS, SSL, SSLv3 and     * TLS10 algorithm.     *     * This is a super class of DefaultSSLContext and TLS10Context.     *     * @see SSLContext     */    private static class ConservativeSSLContext extends SSLContextImpl {        // parameters        private static SSLParameters defaultServerSSLParams;        private static SSLParameters defaultClientSSLParams;        private static SSLParameters supportedSSLParams;         static {            if (SunJSSE.isFIPS()) {                supportedSSLParams = new SSLParameters();                supportedSSLParams.setProtocols(new String[] {                    ProtocolVersion.TLS10.name,                    ProtocolVersion.TLS11.name,                    ProtocolVersion.TLS12.name                });                 defaultServerSSLParams = supportedSSLParams;                 defaultClientSSLParams = new SSLParameters();                defaultClientSSLParams.setProtocols(new String[] {                    ProtocolVersion.TLS10.name                });             } else {                supportedSSLParams = new SSLParameters();                supportedSSLParams.setProtocols(new String[] {                    ProtocolVersion.SSL20Hello.name,                    ProtocolVersion.SSL30.name,                    ProtocolVersion.TLS10.name,                    ProtocolVersion.TLS11.name,                    ProtocolVersion.TLS12.name                });                 defaultServerSSLParams = supportedSSLParams;                 defaultClientSSLParams = new SSLParameters();                defaultClientSSLParams.setProtocols(new String[] {                    ProtocolVersion.SSL30.name,                    ProtocolVersion.TLS10.name                });            }        }         SSLParameters getDefaultServerSSLParams() {            return defaultServerSSLParams;        }         SSLParameters getDefaultClientSSLParams() {            return defaultClientSSLParams;        }         SSLParameters getSupportedSSLParams() {            return supportedSSLParams;        }    }     /*     * The SSLContext implementation for default algorithm     *     * @see SSLContext     */    public static final class DefaultSSLContext extends ConservativeSSLContext {        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;            }        }         protected void engineInit(KeyManager[] km, TrustManager[] tm,

Lines 1–500 of 1145.