mirror of
https://github.com/openjdk/jdk.git
synced 2026-03-05 13:40:18 +00:00
8162362: Introduce system property to control enabled ciphersuites
Reviewed-by: coffeys, mullan
This commit is contained in:
parent
dac6760af7
commit
abe8a9eae5
@ -59,6 +59,11 @@ public abstract class SSLContextImpl extends SSLContextSpi {
|
||||
"jdk.tls.client.enableStatusRequestExtension", true);
|
||||
private final boolean serverEnableStapling = Debug.getBooleanProperty(
|
||||
"jdk.tls.server.enableStatusRequestExtension", false);
|
||||
private final static Collection<CipherSuite> clientCustomizedCipherSuites =
|
||||
getCustomizedCipherSuites("jdk.tls.client.cipherSuites");
|
||||
private final static Collection<CipherSuite> serverCustomizedCipherSuites =
|
||||
getCustomizedCipherSuites("jdk.tls.server.cipherSuites");
|
||||
|
||||
private volatile StatusResponseManager statusResponseManager;
|
||||
|
||||
SSLContextImpl() {
|
||||
@ -336,20 +341,52 @@ public abstract class SSLContextImpl extends SSLContextSpi {
|
||||
return isClient ? clientEnableStapling : serverEnableStapling;
|
||||
}
|
||||
|
||||
/*
|
||||
* Return the list of all available CipherSuites with a priority of
|
||||
* minPriority or above.
|
||||
*/
|
||||
private static CipherSuiteList getApplicableCipherSuiteList(
|
||||
ProtocolList protocols, boolean onlyEnabled) {
|
||||
|
||||
int minPriority = CipherSuite.SUPPORTED_SUITES_PRIORITY;
|
||||
if (onlyEnabled) {
|
||||
minPriority = CipherSuite.DEFAULT_SUITES_PRIORITY;
|
||||
/*
|
||||
* Return the list of all available CipherSuites that are supported
|
||||
* using currently installed providers.
|
||||
*/
|
||||
private static CipherSuiteList getApplicableSupportedCipherSuiteList(
|
||||
ProtocolList protocols) {
|
||||
|
||||
return getApplicableCipherSuiteList(
|
||||
CipherSuite.allowedCipherSuites(),
|
||||
protocols, CipherSuite.SUPPORTED_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()) &&
|
||||
@ -386,6 +423,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 = GetPropertyAction.privilegedGetProperty(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) {
|
||||
|
||||
@ -481,10 +579,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
|
||||
@ -541,8 +639,8 @@ public abstract class SSLContextImpl extends SSLContextSpi {
|
||||
}));
|
||||
}
|
||||
|
||||
clientDefaultCipherSuiteList = getApplicableCipherSuiteList(
|
||||
clientDefaultProtocolList, true); // enabled only
|
||||
clientDefaultCipherSuiteList = getApplicableEnabledCipherSuiteList(
|
||||
clientDefaultProtocolList, true);
|
||||
}
|
||||
|
||||
@Override
|
||||
@ -581,8 +679,9 @@ public abstract class SSLContextImpl extends SSLContextSpi {
|
||||
}));
|
||||
}
|
||||
|
||||
clientDefaultCipherSuiteList = getApplicableCipherSuiteList(
|
||||
clientDefaultProtocolList, true); // enabled only
|
||||
clientDefaultCipherSuiteList = getApplicableEnabledCipherSuiteList(
|
||||
clientDefaultProtocolList, true);
|
||||
|
||||
}
|
||||
|
||||
@Override
|
||||
@ -623,8 +722,8 @@ public abstract class SSLContextImpl extends SSLContextSpi {
|
||||
}));
|
||||
}
|
||||
|
||||
clientDefaultCipherSuiteList = getApplicableCipherSuiteList(
|
||||
clientDefaultProtocolList, true); // enabled only
|
||||
clientDefaultCipherSuiteList = getApplicableEnabledCipherSuiteList(
|
||||
clientDefaultProtocolList, true);
|
||||
}
|
||||
|
||||
@Override
|
||||
@ -757,8 +856,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
|
||||
@ -1032,10 +1132,10 @@ public abstract class SSLContextImpl extends SSLContextSpi {
|
||||
ProtocolVersion.DTLS12
|
||||
}));
|
||||
|
||||
supportedCipherSuiteList = getApplicableCipherSuiteList(
|
||||
supportedProtocolList, false); // all supported
|
||||
serverDefaultCipherSuiteList = getApplicableCipherSuiteList(
|
||||
serverDefaultProtocolList, true); // enabled only
|
||||
supportedCipherSuiteList = getApplicableSupportedCipherSuiteList(
|
||||
supportedProtocolList);
|
||||
serverDefaultCipherSuiteList = getApplicableEnabledCipherSuiteList(
|
||||
serverDefaultProtocolList, false);
|
||||
}
|
||||
|
||||
@Override
|
||||
@ -1090,8 +1190,8 @@ public abstract class SSLContextImpl extends SSLContextSpi {
|
||||
ProtocolVersion.DTLS10
|
||||
}));
|
||||
|
||||
clientDefaultCipherSuiteList = getApplicableCipherSuiteList(
|
||||
clientDefaultProtocolList, true); // enabled only
|
||||
clientDefaultCipherSuiteList = getApplicableEnabledCipherSuiteList(
|
||||
clientDefaultProtocolList, true);
|
||||
}
|
||||
|
||||
@Override
|
||||
@ -1122,8 +1222,8 @@ public abstract class SSLContextImpl extends SSLContextSpi {
|
||||
ProtocolVersion.DTLS12
|
||||
}));
|
||||
|
||||
clientDefaultCipherSuiteList = getApplicableCipherSuiteList(
|
||||
clientDefaultProtocolList, true); // enabled only
|
||||
clientDefaultCipherSuiteList = getApplicableEnabledCipherSuiteList(
|
||||
clientDefaultProtocolList, true);
|
||||
}
|
||||
|
||||
@Override
|
||||
@ -1187,8 +1287,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
|
||||
|
||||
@ -0,0 +1,270 @@
|
||||
/*
|
||||
* 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;
|
||||
}
|
||||
}
|
||||
Loading…
x
Reference in New Issue
Block a user