提交 c6a9b973 编写于 作者: C coffeys

8162362: Introduce system property to control enabled ciphersuites

Reviewed-by: xuelei
上级 5c94d589
......@@ -53,6 +53,11 @@ public abstract class SSLContextImpl extends SSLContextSpi {
private X509TrustManager trustManager;
private SecureRandom secureRandom;
private final static Collection<CipherSuite> clientCustomizedCipherSuites =
getCustomizedCipherSuites("jdk.tls.client.cipherSuites");
private final static Collection<CipherSuite> serverCustomizedCipherSuites =
getCustomizedCipherSuites("jdk.tls.server.cipherSuites");
SSLContextImpl() {
ephemeralKeyManager = new EphemeralKeyManager();
clientCache = new SSLSessionContextImpl();
......@@ -279,19 +284,50 @@ public abstract class SSLContextImpl extends SSLContextSpi {
}
/*
* Return the list of all available CipherSuites with a priority of
* minPriority or above.
* Return the list of all available CipherSuites that are supported
* using currently installed providers.
*/
private static CipherSuiteList getApplicableCipherSuiteList(
ProtocolList protocols, boolean onlyEnabled) {
private static CipherSuiteList getApplicableSupportedCipherSuiteList(
ProtocolList protocols) {
return getApplicableCipherSuiteList(
CipherSuite.allowedCipherSuites(),
protocols, CipherSuite.SUPPORTED_SUITES_PRIORITY);
}
int minPriority = CipherSuite.SUPPORTED_SUITES_PRIORITY;
if (onlyEnabled) {
minPriority = CipherSuite.DEFAULT_SUITES_PRIORITY;
/*
* Return the list of all available CipherSuites that are default enabled
* in client or server side.
*/
private static CipherSuiteList getApplicableEnabledCipherSuiteList(
ProtocolList protocols, boolean isClient) {
if (isClient) {
if (!clientCustomizedCipherSuites.isEmpty()) {
return getApplicableCipherSuiteList(
clientCustomizedCipherSuites,
protocols, CipherSuite.SUPPORTED_SUITES_PRIORITY);
}
} else {
if (!serverCustomizedCipherSuites.isEmpty()) {
return getApplicableCipherSuiteList(
serverCustomizedCipherSuites,
protocols, CipherSuite.SUPPORTED_SUITES_PRIORITY);
}
}
Collection<CipherSuite> allowedCipherSuites =
CipherSuite.allowedCipherSuites();
return getApplicableCipherSuiteList(
CipherSuite.allowedCipherSuites(),
protocols, CipherSuite.DEFAULT_SUITES_PRIORITY);
}
/*
* Return the list of available CipherSuites which are applicable to
* the specified protocols.
*/
private static CipherSuiteList getApplicableCipherSuiteList(
Collection<CipherSuite> allowedCipherSuites,
ProtocolList protocols, int minPriority) {
TreeSet<CipherSuite> suites = new TreeSet<>();
if (!(protocols.collection().isEmpty()) &&
......@@ -328,6 +364,67 @@ public abstract class SSLContextImpl extends SSLContextSpi {
return new CipherSuiteList(suites);
}
/*
* Get the customized cipher suites specified by the given system property.
*/
private static Collection<CipherSuite> getCustomizedCipherSuites(
String propertyName) {
String property = AccessController.doPrivileged(
new GetPropertyAction(propertyName));
if (debug != null && Debug.isOn("sslctx")) {
System.out.println(
"System property " + propertyName + " is set to '" +
property + "'");
}
if (property != null && property.length() != 0) {
// 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);
}
}
if (property != null && property.length() != 0) {
String[] cipherSuiteNames = property.split(",");
Collection<CipherSuite> cipherSuites =
new ArrayList<>(cipherSuiteNames.length);
for (int i = 0; i < cipherSuiteNames.length; i++) {
cipherSuiteNames[i] = cipherSuiteNames[i].trim();
if (cipherSuiteNames[i].isEmpty()) {
continue;
}
CipherSuite suite;
try {
suite = CipherSuite.valueOf(cipherSuiteNames[i]);
} catch (IllegalArgumentException iae) {
if (debug != null && Debug.isOn("sslctx")) {
System.out.println(
"Unknown or unsupported cipher suite name: " +
cipherSuiteNames[i]);
}
continue;
}
if (suite.isAvailable()) {
cipherSuites.add(suite);
} else {
if (debug != null && Debug.isOn("sslctx")) {
System.out.println(
"The current installed providers do not " +
"support cipher suite: " + cipherSuiteNames[i]);
}
}
}
return cipherSuites;
}
return Collections.emptyList();
}
private static String[] getAvailableProtocols(
ProtocolVersion[] protocolCandidates) {
......@@ -422,10 +519,10 @@ public abstract class SSLContextImpl extends SSLContextSpi {
}));
}
supportedCipherSuiteList = getApplicableCipherSuiteList(
supportedProtocolList, false); // all supported
serverDefaultCipherSuiteList = getApplicableCipherSuiteList(
serverDefaultProtocolList, true); // enabled only
supportedCipherSuiteList = getApplicableSupportedCipherSuiteList(
supportedProtocolList);
serverDefaultCipherSuiteList = getApplicableEnabledCipherSuiteList(
serverDefaultProtocolList, false);
}
@Override
......@@ -482,8 +579,8 @@ public abstract class SSLContextImpl extends SSLContextSpi {
}));
}
clientDefaultCipherSuiteList = getApplicableCipherSuiteList(
clientDefaultProtocolList, true); // enabled only
clientDefaultCipherSuiteList = getApplicableEnabledCipherSuiteList(
clientDefaultProtocolList, true);
}
@Override
......@@ -522,8 +619,9 @@ public abstract class SSLContextImpl extends SSLContextSpi {
}));
}
clientDefaultCipherSuiteList = getApplicableCipherSuiteList(
clientDefaultProtocolList, true); // enabled only
clientDefaultCipherSuiteList = getApplicableEnabledCipherSuiteList(
clientDefaultProtocolList, true);
}
@Override
......@@ -564,8 +662,8 @@ public abstract class SSLContextImpl extends SSLContextSpi {
}));
}
clientDefaultCipherSuiteList = getApplicableCipherSuiteList(
clientDefaultProtocolList, true); // enabled only
clientDefaultCipherSuiteList = getApplicableEnabledCipherSuiteList(
clientDefaultProtocolList, true);
}
@Override
......@@ -696,8 +794,9 @@ public abstract class SSLContextImpl extends SSLContextSpi {
clientDefaultProtocolList = new ProtocolList(
getAvailableProtocols(candidates));
clientDefaultCipherSuiteList = getApplicableCipherSuiteList(
clientDefaultProtocolList, true); // enabled only
clientDefaultCipherSuiteList =
getApplicableEnabledCipherSuiteList(
clientDefaultProtocolList, true);
} else {
clientDefaultProtocolList = null; // unlikely to be used
clientDefaultCipherSuiteList = null; // unlikely to be used
......
......@@ -1946,13 +1946,21 @@ final public class SSLEngineImpl extends SSLEngine {
case cs_START:
/*
* If we need to change the engine mode and the enabled
* protocols haven't specifically been set by the user,
* change them to the corresponding default ones.
* If we need to change the socket mode and the enabled
* protocols and cipher suites haven't specifically been
* set by the user, change them to the corresponding
* default ones.
*/
if (roleIsServer != (!flag) &&
sslContext.isDefaultProtocolList(enabledProtocols)) {
enabledProtocols = sslContext.getDefaultProtocolList(!flag);
if (roleIsServer != (!flag)) {
if (sslContext.isDefaultProtocolList(enabledProtocols)) {
enabledProtocols =
sslContext.getDefaultProtocolList(!flag);
}
if (sslContext.isDefaultCipherSuiteList(enabledCipherSuites)) {
enabledCipherSuites =
sslContext.getDefaultCipherSuiteList(!flag);
}
}
roleIsServer = !flag;
......
......@@ -2417,13 +2417,22 @@ final public class SSLSocketImpl extends BaseSSLSocketImpl {
case cs_START:
/*
* If we need to change the socket mode and the enabled
* protocols haven't specifically been set by the user,
* change them to the corresponding default ones.
* protocols and cipher suites haven't specifically been
* set by the user, change them to the corresponding
* default ones.
*/
if (roleIsServer != (!flag) &&
sslContext.isDefaultProtocolList(enabledProtocols)) {
enabledProtocols = sslContext.getDefaultProtocolList(!flag);
if (roleIsServer != (!flag)) {
if (sslContext.isDefaultProtocolList(enabledProtocols)) {
enabledProtocols =
sslContext.getDefaultProtocolList(!flag);
}
if (sslContext.isDefaultCipherSuiteList(enabledCipherSuites)) {
enabledCipherSuites =
sslContext.getDefaultCipherSuiteList(!flag);
}
}
roleIsServer = !flag;
break;
......
/*
* Copyright (c) 2016, 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.
*
* 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.
*/
// SunJSSE does not support dynamic system properties, no way to re-use
// system properties in samevm/agentvm mode.
/*
* @test
* @bug 8162362
* @summary Cannot enable previously default enabled cipher suites
* @run main/othervm
* CustomizedCipherSuites Default true
* TLS_RSA_WITH_AES_128_CBC_SHA
* SSL_RSA_WITH_DES_CBC_SHA
* @run main/othervm
* -Djdk.tls.client.cipherSuites="unknown"
* CustomizedCipherSuites Default true
* TLS_RSA_WITH_AES_128_CBC_SHA
* SSL_RSA_WITH_DES_CBC_SHA
* @run main/othervm
* -Djdk.tls.client.cipherSuites=""
* CustomizedCipherSuites Default true
* TLS_RSA_WITH_AES_128_CBC_SHA
* SSL_RSA_WITH_DES_CBC_SHA
* @run main/othervm
* -Djdk.tls.client.cipherSuites="SSL_RSA_WITH_DES_CBC_SHA"
* CustomizedCipherSuites Default true
* SSL_RSA_WITH_DES_CBC_SHA
* TLS_RSA_WITH_AES_128_CBC_SHA
* @run main/othervm
* -Djdk.tls.server.cipherSuites="SSL_RSA_WITH_DES_CBC_SHA"
* CustomizedCipherSuites Default false
* SSL_RSA_WITH_DES_CBC_SHA
* TLS_RSA_WITH_AES_128_CBC_SHA
* @run main/othervm
* -Djdk.tls.client.cipherSuites="TLS_RSA_WITH_AES_128_CBC_SHA,unknown,SSL_RSA_WITH_DES_CBC_SHA"
* CustomizedCipherSuites Default true
* SSL_RSA_WITH_DES_CBC_SHA
* ""
* @run main/othervm
* -Djdk.tls.server.cipherSuites="TLS_RSA_WITH_AES_128_CBC_SHA,unknown,SSL_RSA_WITH_DES_CBC_SHA"
* CustomizedCipherSuites Default false
* TLS_RSA_WITH_AES_128_CBC_SHA
* ""
* @run main/othervm
* -Djdk.tls.server.cipherSuites="SSL_RSA_WITH_DES_CBC_SHA"
* CustomizedCipherSuites Default true
* TLS_RSA_WITH_AES_128_CBC_SHA
* SSL_RSA_WITH_DES_CBC_SHA
* @run main/othervm
* -Djdk.tls.client.cipherSuites="SSL_RSA_WITH_DES_CBC_SHA"
* CustomizedCipherSuites Default false
* TLS_RSA_WITH_AES_128_CBC_SHA
* SSL_RSA_WITH_DES_CBC_SHA
*/
import javax.net.ssl.*;
/**
* Test the customized default cipher suites.
*
* This test is based on the behavior that SSL_RSA_WITH_DES_CBC_SHA is
* disabled by default, and TLS_RSA_WITH_AES_128_CBC_SHA is enabled by
* default in JDK. If the behavior is changed in the future, please
* update the test cases above accordingly.
*/
public class CustomizedCipherSuites {
private static String contextProtocol;
private static boolean isClientMode;
private static String enabledCipherSuite;
private static String disabledCipherSuite;
public static void main(String[] args) throws Exception {
contextProtocol = trimQuotes(args[0]);
isClientMode = Boolean.parseBoolean(args[1]);
enabledCipherSuite = trimQuotes(args[2]);
disabledCipherSuite = trimQuotes(args[3]);
//
// Create instance of SSLContext with the specified protocol.
//
SSLContext context = SSLContext.getInstance(contextProtocol);
// Default SSLContext is initialized automatically.
if (!contextProtocol.equals("Default")) {
// Use default TK, KM and random.
context.init((KeyManager[])null, (TrustManager[])null, null);
}
// SSLContext default parameters is client mode in JDK.
if (isClientMode) {
//
// Check default parameters of the specified SSLContext protocol
//
SSLParameters parameters = context.getDefaultSSLParameters();
System.out.println("Checking SSLContext default parameters ...");
checkEnabledCiphers(parameters.getCipherSuites());
}
//
// Check supported parameters of the specified SSLContext protocol
//
SSLParameters parameters = context.getSupportedSSLParameters();
System.out.println("Checking SSLContext suppport parameters ...");
checkSupportedCiphers(parameters.getCipherSuites());
//
// Check the default cipher suites of SSLEngine.
//
SSLEngine engine = context.createSSLEngine();
engine.setUseClientMode(isClientMode);
System.out.println("Checking SSLEngine default cipher suites ...");
checkEnabledCiphers(engine.getEnabledCipherSuites());
//
// Check the supported cipher suites of SSLEngine.
//
System.out.println("Checking SSLEngine supported cipher suites ...");
checkSupportedCiphers(engine.getSupportedCipherSuites());
if (isClientMode) {
SSLSocketFactory factory = context.getSocketFactory();
// Use an unconnected socket.
try (SSLSocket socket = (SSLSocket)factory.createSocket()) {
//
// Check the default cipher suites of SSLSocket.
//
System.out.println(
"Checking SSLSocket default cipher suites ...");
checkEnabledCiphers(socket.getEnabledCipherSuites());
//
// Check the supported cipher suites of SSLSocket.
//
System.out.println(
"Checking SSLSocket supported cipher suites ...");
checkSupportedCiphers(socket.getSupportedCipherSuites());
}
} else {
SSLServerSocketFactory factory = context.getServerSocketFactory();
// Use an unbound server socket.
try (SSLServerSocket socket =
(SSLServerSocket)factory.createServerSocket()) {
//
// Check the default cipher suites of SSLServerSocket.
//
System.out.println(
"Checking SSLServerSocket default cipher suites ...");
checkEnabledCiphers(socket.getEnabledCipherSuites());
//
// Check the supported cipher suites of SSLServerSocket.
//
System.out.println(
"Checking SSLServerSocket supported cipher suites ...");
checkSupportedCiphers(socket.getSupportedCipherSuites());
}
}
System.out.println("\t... Success");
}
private static void checkEnabledCiphers(
String[] ciphers) throws Exception {
if (ciphers.length == 0) {
throw new Exception("No default cipher suites");
}
boolean isMatch = false;
if (enabledCipherSuite.isEmpty()) {
// Don't check if not specify the expected cipher suite.
isMatch = true;
}
boolean isBroken = false;
for (String cipher : ciphers) {
System.out.println("\tdefault cipher suite " + cipher);
if (!enabledCipherSuite.isEmpty() &&
cipher.equals(enabledCipherSuite)) {
isMatch = true;
}
if (!disabledCipherSuite.isEmpty() &&
cipher.equals(disabledCipherSuite)) {
isBroken = true;
}
}
if (!isMatch) {
throw new Exception(
"Cipher suite " + enabledCipherSuite + " should be enabled");
}
if (isBroken) {
throw new Exception(
"Cipher suite " + disabledCipherSuite + " should be disabled");
}
}
private static void checkSupportedCiphers(
String[] ciphers) throws Exception {
if (ciphers.length == 0) {
throw new Exception("No supported cipher suites");
}
boolean hasEnabledCipherSuite = enabledCipherSuite.isEmpty();
boolean hasDisabledCipherSuite = disabledCipherSuite.isEmpty();
for (String cipher : ciphers) {
System.out.println("\tsupported cipher suite " + cipher);
if (!enabledCipherSuite.isEmpty() &&
cipher.equals(enabledCipherSuite)) {
hasEnabledCipherSuite = true;
}
if (!disabledCipherSuite.isEmpty() &&
cipher.equals(disabledCipherSuite)) {
hasDisabledCipherSuite = true;
}
}
if (!hasEnabledCipherSuite) {
throw new Exception(
"Cipher suite " + enabledCipherSuite + " should be supported");
}
if (!hasDisabledCipherSuite) {
throw new Exception(
"Cipher suite " + disabledCipherSuite + " should be supported");
}
}
private static String trimQuotes(String candidate) {
if (candidate != null && candidate.length() != 0) {
// Remove double quote marks from beginning/end of the string.
if (candidate.length() > 1 && candidate.charAt(0) == '"' &&
candidate.charAt(candidate.length() - 1) == '"') {
return candidate.substring(1, candidate.length() - 1);
}
}
return candidate;
}
}
Markdown is supported
0% .
You are about to add 0 people to the discussion. Proceed with caution.
先完成此消息的编辑!
想要评论请 注册