This is an automated email from the ASF dual-hosted git repository.

kezhuw pushed a commit to branch master
in repository https://gitbox.apache.org/repos/asf/zookeeper.git


The following commit(s) were added to refs/heads/master by this push:
     new 2aaeff840 ZOOKEEPER-4912: Remove default TLS cipher overrides
2aaeff840 is described below

commit 2aaeff840e8e5b61a30530b261b8c05c181d078f
Author: Istvan Toth <[email protected]>
AuthorDate: Sun May 11 04:16:38 2025 +0200

    ZOOKEEPER-4912: Remove default TLS cipher overrides
    
    Reviewers: cnauroth, anmolnar, kezhuw
    Author: stoty
    Closes #2239 from stoty/ZOOKEEPER-4912
---
 .../src/main/resources/markdown/zookeeperAdmin.md  | 16 +++++-
 .../apache/zookeeper/common/ClientX509Util.java    | 17 +++---
 .../zookeeper/common/SSLContextAndOptions.java     |  2 +-
 .../java/org/apache/zookeeper/common/X509Util.java | 60 +-------------------
 .../org/apache/zookeeper/common/X509UtilTest.java  | 66 ----------------------
 5 files changed, 28 insertions(+), 133 deletions(-)

diff --git a/zookeeper-docs/src/main/resources/markdown/zookeeperAdmin.md 
b/zookeeper-docs/src/main/resources/markdown/zookeeperAdmin.md
index 70ce27b72..a4fccf1f9 100644
--- a/zookeeper-docs/src/main/resources/markdown/zookeeperAdmin.md
+++ b/zookeeper-docs/src/main/resources/markdown/zookeeperAdmin.md
@@ -43,6 +43,7 @@ limitations under the License.
         * [Advanced Configuration](#sc_advancedConfiguration)
         * [Cluster Options](#sc_clusterOptions)
         * [Encryption, Authentication, Authorization Options](#sc_authOptions)
+            * [TLS Cipher Suites](#sc_tls_cipher_suites)
         * [Experimental Options/Features](#Experimental+Options%2FFeatures)
         * [Unsafe Options](#Unsafe+Options)
         * [Disabling data directory 
autocreation](#Disabling+data+directory+autocreation)
@@ -1738,7 +1739,7 @@ and [SASL authentication for 
ZooKeeper](https://cwiki.apache.org/confluence/disp
     (Java system properties: **zookeeper.ssl.ciphersuites** and 
**zookeeper.ssl.quorum.ciphersuites**)
     **New in 3.5.5:**
     Specifies the enabled cipher suites to be used in client and quorum TLS 
negotiation.
-    Default: Enabled cipher suites depend on the Java runtime version being 
used.
+    Default: JDK defaults since 3.10.0, and hard coded cipher suites for 3.9 
and earlier versions. See [TLS Cipher Suites](#sc_tls_cipher_suites).
 
 * *ssl.context.supplier.class* and *ssl.quorum.context.supplier.class* :
     (Java system properties: **zookeeper.ssl.context.supplier.class** and 
**zookeeper.ssl.quorum.context.supplier.class**)
@@ -1877,6 +1878,19 @@ and [SASL authentication for 
ZooKeeper](https://cwiki.apache.org/confluence/disp
     
     Default: **true** (3.9.0+), **false** (3.8.x)
 
+<a name="sc_tls_cipher_suites"></a>
+
+##### TLS Cipher Suites
+
+From 3.5.5 to 3.9 a hard coded default cipher list was used, with the ordering
+dependent on whether it is run Java 8 or a later version.
+
+The list on Java 8 includes TLSv1.2 CBC, GCM and TLSv1.3 ciphers in ordering: 
*TLS_ECDHE_ECDSA_WITH_AES_128_CBC_SHA256, 
TLS_ECDHE_RSA_WITH_AES_128_CBC_SHA256, TLS_ECDHE_ECDSA_WITH_AES_128_CBC_SHA, 
TLS_ECDHE_RSA_WITH_AES_128_CBC_SHA, TLS_ECDHE_ECDSA_WITH_AES_256_CBC_SHA384, 
TLS_ECDHE_RSA_WITH_AES_256_CBC_SHA384, TLS_ECDHE_ECDSA_WITH_AES_256_CBC_SHA, 
TLS_ECDHE_RSA_WITH_AES_256_CBC_SHA, TLS_ECDHE_ECDSA_WITH_AES_128_GCM_SHA256, 
TLS_ECDHE_RSA_WITH_AES_128_GCM_SHA256, TLS_ECDHE_ECDSA_WITH_AES_ [...]
+
+The list on Java 9+ includes TLSv1.2 GCM, CBC and TLSv1.3 ciphers in ordering: 
*TLS_ECDHE_ECDSA_WITH_AES_128_GCM_SHA256, 
TLS_ECDHE_RSA_WITH_AES_128_GCM_SHA256, TLS_ECDHE_ECDSA_WITH_AES_256_GCM_SHA384, 
TLS_ECDHE_RSA_WITH_AES_256_GCM_SHA384, TLS_ECDHE_ECDSA_WITH_AES_128_CBC_SHA256, 
TLS_ECDHE_RSA_WITH_AES_128_CBC_SHA256, TLS_ECDHE_ECDSA_WITH_AES_128_CBC_SHA, 
TLS_ECDHE_RSA_WITH_AES_128_CBC_SHA, TLS_ECDHE_ECDSA_WITH_AES_256_CBC_SHA384, 
TLS_ECDHE_RSA_WITH_AES_256_CBC_SHA384, TLS_ECDHE_ECDSA_WI [...]
+
+Since 3.10 there is no hardcoded list, and the JDK defaults are used.
+
 <a name="Experimental+Options%2FFeatures"></a>
 
 #### Experimental Options/Features
diff --git 
a/zookeeper-server/src/main/java/org/apache/zookeeper/common/ClientX509Util.java
 
b/zookeeper-server/src/main/java/org/apache/zookeeper/common/ClientX509Util.java
index 7bb453903..9aa03ae49 100644
--- 
a/zookeeper-server/src/main/java/org/apache/zookeeper/common/ClientX509Util.java
+++ 
b/zookeeper-server/src/main/java/org/apache/zookeeper/common/ClientX509Util.java
@@ -80,7 +80,10 @@ public SslContext createNettySslContextForClient(ZKConfig 
config)
         }
 
         
sslContextBuilder.enableOcsp(config.getBoolean(getSslOcspEnabledProperty()));
-        sslContextBuilder.protocols(getEnabledProtocols(config));
+        String[] enabledProtocols = getEnabledProtocols(config);
+        if (enabledProtocols != null) {
+            sslContextBuilder.protocols(enabledProtocols);
+        }
         Iterable<String> enabledCiphers = getCipherSuites(config);
         if (enabledCiphers != null) {
             sslContextBuilder.ciphers(enabledCiphers);
@@ -121,7 +124,10 @@ public SslContext createNettySslContextForServer(ZKConfig 
config, KeyManager key
         }
 
         
sslContextBuilder.enableOcsp(config.getBoolean(getSslOcspEnabledProperty()));
-        sslContextBuilder.protocols(getEnabledProtocols(config));
+        String[] enabledProtocols = getEnabledProtocols(config);
+        if (enabledProtocols != null) {
+            sslContextBuilder.protocols(enabledProtocols);
+        }
         
sslContextBuilder.clientAuth(getClientAuth(config).toNettyClientAuth());
         Iterable<String> enabledCiphers = getCipherSuites(config);
         if (enabledCiphers != null) {
@@ -155,7 +161,7 @@ protected void initEngine(SSLEngine sslEngine) {
     private String[] getEnabledProtocols(final ZKConfig config) {
         String enabledProtocolsInput = 
config.getProperty(getSslEnabledProtocolsProperty());
         if (enabledProtocolsInput == null) {
-            return new String[]{ config.getProperty(getSslProtocolProperty(), 
DEFAULT_PROTOCOL) };
+            return null;
         }
         return enabledProtocolsInput.split(",");
     }
@@ -167,10 +173,7 @@ private X509Util.ClientAuth getClientAuth(final ZKConfig 
config) {
     private Iterable<String> getCipherSuites(final ZKConfig config) {
         String cipherSuitesInput = 
config.getProperty(getSslCipherSuitesProperty());
         if (cipherSuitesInput == null) {
-            if (getSslProvider(config) != SslProvider.JDK) {
-                return null;
-            }
-            return Arrays.asList(X509Util.getDefaultCipherSuites());
+            return null;
         } else {
             return Arrays.asList(cipherSuitesInput.split(","));
         }
diff --git 
a/zookeeper-server/src/main/java/org/apache/zookeeper/common/SSLContextAndOptions.java
 
b/zookeeper-server/src/main/java/org/apache/zookeeper/common/SSLContextAndOptions.java
index 3a2542552..c712f6acb 100644
--- 
a/zookeeper-server/src/main/java/org/apache/zookeeper/common/SSLContextAndOptions.java
+++ 
b/zookeeper-server/src/main/java/org/apache/zookeeper/common/SSLContextAndOptions.java
@@ -160,7 +160,7 @@ private String[] getEnabledProtocols(final ZKConfig config, 
final SSLContext ssl
     private String[] getCipherSuites(final ZKConfig config) {
         String cipherSuitesInput = 
config.getProperty(x509Util.getSslCipherSuitesProperty());
         if (cipherSuitesInput == null) {
-            return X509Util.getDefaultCipherSuites();
+            return null;
         } else {
             return cipherSuitesInput.split(",");
         }
diff --git 
a/zookeeper-server/src/main/java/org/apache/zookeeper/common/X509Util.java 
b/zookeeper-server/src/main/java/org/apache/zookeeper/common/X509Util.java
index 17818207e..153a826ba 100644
--- a/zookeeper-server/src/main/java/org/apache/zookeeper/common/X509Util.java
+++ b/zookeeper-server/src/main/java/org/apache/zookeeper/common/X509Util.java
@@ -36,16 +36,13 @@
 import java.util.ArrayList;
 import java.util.Arrays;
 import java.util.List;
-import java.util.Objects;
 import java.util.concurrent.atomic.AtomicReference;
 import java.util.function.Supplier;
-import java.util.stream.Collectors;
 import javax.net.ssl.CertPathTrustManagerParameters;
 import javax.net.ssl.KeyManager;
 import javax.net.ssl.KeyManagerFactory;
 import javax.net.ssl.SSLContext;
 import javax.net.ssl.SSLServerSocket;
-import javax.net.ssl.SSLServerSocketFactory;
 import javax.net.ssl.SSLSocket;
 import javax.net.ssl.TrustManager;
 import javax.net.ssl.TrustManagerFactory;
@@ -62,11 +59,6 @@
 
 /**
  * Utility code for X509 handling
- *
- * Default cipher suites:
- *
- *   Performance testing done by Facebook engineers shows that on Intel x86_64 
machines, Java9 performs better with
- *   GCM and Java8 performs better with CBC, so these seem like reasonable 
defaults.
  */
 public abstract class X509Util implements Closeable, AutoCloseable {
 
@@ -102,6 +94,8 @@ private static String defaultTlsProtocol() {
         List<String> supported = new ArrayList<>();
         try {
             supported = 
Arrays.asList(SSLContext.getDefault().getSupportedSSLParameters().getProtocols());
+            // We cannot use the default protocols directly, because the 
SSLContext factory methods
+            // only accept a single protocol
             if (supported.contains(TLS_1_3)) {
                 defaultProtocol = TLS_1_3;
             }
@@ -112,36 +106,6 @@ private static String defaultTlsProtocol() {
         return defaultProtocol;
     }
 
-    // ChaCha20 was introduced in OpenJDK 11.0.15 and it is not supported by 
JDK8.
-    private static String[] getTLSv13Ciphers() {
-        return new String[]{"TLS_AES_256_GCM_SHA384", 
"TLS_AES_128_GCM_SHA256", "TLS_CHACHA20_POLY1305_SHA256"};
-    }
-
-    private static String[] getGCMCiphers() {
-        return new String[]{"TLS_ECDHE_ECDSA_WITH_AES_128_GCM_SHA256", 
"TLS_ECDHE_RSA_WITH_AES_128_GCM_SHA256", 
"TLS_ECDHE_ECDSA_WITH_AES_256_GCM_SHA384", 
"TLS_ECDHE_RSA_WITH_AES_256_GCM_SHA384"};
-    }
-
-    private static String[] getCBCCiphers() {
-        return new String[]{"TLS_ECDHE_ECDSA_WITH_AES_128_CBC_SHA256", 
"TLS_ECDHE_RSA_WITH_AES_128_CBC_SHA256", 
"TLS_ECDHE_ECDSA_WITH_AES_128_CBC_SHA", "TLS_ECDHE_RSA_WITH_AES_128_CBC_SHA", 
"TLS_ECDHE_ECDSA_WITH_AES_256_CBC_SHA384", 
"TLS_ECDHE_RSA_WITH_AES_256_CBC_SHA384", 
"TLS_ECDHE_ECDSA_WITH_AES_256_CBC_SHA", "TLS_ECDHE_RSA_WITH_AES_256_CBC_SHA"};
-    }
-
-    /**
-     * Returns a filtered set of ciphers, where ciphers not supported by the 
JDK are removed.
-     */
-    private static String[] getSupportedCiphers(String[]... cipherLists) {
-        List<String> supported = Arrays.asList(
-            ((SSLServerSocketFactory) 
SSLServerSocketFactory.getDefault()).getSupportedCipherSuites());
-
-        return 
Arrays.stream(cipherLists).flatMap(Arrays::stream).filter(supported::contains).collect(Collectors.toList()).toArray(new
 String[0]);
-    }
-
-    // On Java 8, prefer CBC ciphers since AES-NI support is lacking and GCM 
is slower than CBC.
-    private static final String[] DEFAULT_CIPHERS_JAVA8 = 
getSupportedCiphers(getCBCCiphers(), getGCMCiphers(), getTLSv13Ciphers());
-    // On Java 9 and later, prefer GCM ciphers due to improved AES-NI support.
-    // Note that this performance assumption might not hold true for 
architectures other than x86_64.
-    // TLSv1.3 ciphers can be added at the end of the list without impacting 
the priority of TLSv1.3 vs TLSv1.2.
-    private static final String[] DEFAULT_CIPHERS_JAVA9 = 
getSupportedCiphers(getGCMCiphers(), getCBCCiphers(), getTLSv13Ciphers());
-
     public static final int DEFAULT_HANDSHAKE_DETECTION_TIMEOUT_MILLIS = 5000;
 
     /**
@@ -636,26 +600,6 @@ public SSLServerSocket createSSLServerSocket(int port) 
throws X509Exception, IOE
         return getDefaultSSLContextAndOptions().createSSLServerSocket(port);
     }
 
-    static String[] getDefaultCipherSuites() {
-        return 
getDefaultCipherSuitesForJavaVersion(System.getProperty("java.specification.version"));
-    }
-
-    static String[] getDefaultCipherSuitesForJavaVersion(String javaVersion) {
-        Objects.requireNonNull(javaVersion);
-        if (javaVersion.matches("\\d+")) {
-            // Must be Java 9 or later
-            LOG.debug("Using Java9+ optimized cipher suites for Java version 
{}", javaVersion);
-            return DEFAULT_CIPHERS_JAVA9;
-        } else if (javaVersion.startsWith("1.")) {
-            // Must be Java 1.8 or earlier
-            LOG.debug("Using Java8 optimized cipher suites for Java version 
{}", javaVersion);
-            return DEFAULT_CIPHERS_JAVA8;
-        } else {
-            LOG.debug("Could not parse java version {}, using Java8 optimized 
cipher suites", javaVersion);
-            return DEFAULT_CIPHERS_JAVA8;
-        }
-    }
-
     private FileChangeWatcher newFileChangeWatcher(String fileLocation) throws 
IOException {
         if (fileLocation == null || fileLocation.isEmpty()) {
             return null;
diff --git 
a/zookeeper-server/src/test/java/org/apache/zookeeper/common/X509UtilTest.java 
b/zookeeper-server/src/test/java/org/apache/zookeeper/common/X509UtilTest.java
index 1218a00de..e4f19d77f 100644
--- 
a/zookeeper-server/src/test/java/org/apache/zookeeper/common/X509UtilTest.java
+++ 
b/zookeeper-server/src/test/java/org/apache/zookeeper/common/X509UtilTest.java
@@ -829,72 +829,6 @@ public void handshakeCompleted(HandshakeCompletedEvent 
handshakeCompletedEvent)
         });
     }
 
-    @ParameterizedTest
-    @MethodSource("data")
-    public void testGetDefaultCipherSuitesJava8(
-            X509KeyType caKeyType, X509KeyType certKeyType, String 
keyPassword, Integer paramIndex)
-            throws Exception {
-        init(caKeyType, certKeyType, keyPassword, paramIndex);
-        String[] cipherSuites = 
X509Util.getDefaultCipherSuitesForJavaVersion("1.8");
-        // Java 8 default should have the CBC suites first
-        assertTrue(cipherSuites[0].contains("CBC"));
-    }
-
-    @ParameterizedTest
-    @MethodSource("data")
-    public void testGetDefaultCipherSuitesJava9(
-            X509KeyType caKeyType, X509KeyType certKeyType, String 
keyPassword, Integer paramIndex)
-            throws Exception {
-        init(caKeyType, certKeyType, keyPassword, paramIndex);
-        String[] cipherSuites = 
X509Util.getDefaultCipherSuitesForJavaVersion("9");
-        // Java 9+ default should have the GCM suites first
-        assertTrue(cipherSuites[0].contains("GCM"));
-    }
-
-    @ParameterizedTest
-    @MethodSource("data")
-    public void testGetDefaultCipherSuitesJava10(
-            X509KeyType caKeyType, X509KeyType certKeyType, String 
keyPassword, Integer paramIndex)
-            throws Exception {
-        init(caKeyType, certKeyType, keyPassword, paramIndex);
-        String[] cipherSuites = 
X509Util.getDefaultCipherSuitesForJavaVersion("10");
-        // Java 9+ default should have the GCM suites first
-        assertTrue(cipherSuites[0].contains("GCM"));
-    }
-
-    @ParameterizedTest
-    @MethodSource("data")
-    public void testGetDefaultCipherSuitesJava11(
-            X509KeyType caKeyType, X509KeyType certKeyType, String 
keyPassword, Integer paramIndex)
-            throws Exception {
-        init(caKeyType, certKeyType, keyPassword, paramIndex);
-        String[] cipherSuites = 
X509Util.getDefaultCipherSuitesForJavaVersion("11");
-        // Java 9+ default should have the GCM suites first
-        assertTrue(cipherSuites[0].contains("GCM"));
-    }
-
-    @ParameterizedTest
-    @MethodSource("data")
-    public void testGetDefaultCipherSuitesUnknownVersion(
-            X509KeyType caKeyType, X509KeyType certKeyType, String 
keyPassword, Integer paramIndex)
-            throws Exception {
-        init(caKeyType, certKeyType, keyPassword, paramIndex);
-        String[] cipherSuites = 
X509Util.getDefaultCipherSuitesForJavaVersion("notaversion");
-        // If version can't be parsed, use the more conservative Java 8 default
-        assertTrue(cipherSuites[0].contains("CBC"));
-    }
-
-    @ParameterizedTest
-    @MethodSource("data")
-    public void testGetDefaultCipherSuitesNullVersion(
-            X509KeyType caKeyType, X509KeyType certKeyType, String 
keyPassword, Integer paramIndex)
-            throws Exception {
-        init(caKeyType, certKeyType, keyPassword, paramIndex);
-        assertThrows(NullPointerException.class, () -> {
-            X509Util.getDefaultCipherSuitesForJavaVersion(null);
-        });
-    }
-
     // Warning: this will reset the x509Util
     private void setCustomCipherSuites() {
         System.setProperty(x509Util.getCipherSuitesProperty(), 
customCipherSuites[0] + "," + customCipherSuites[1]);

Reply via email to