From cbc59eaef1b28eeee2e78ff6575f49b3212889a5 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?D=C3=A1vid=20Paksy?= Date: Wed, 10 Jun 2026 15:28:55 +0200 Subject: [PATCH] ZOOKEEPER-5053: Fix ZooKeeper 3.8 client cannot connect because of no common TLS protocol When there is no TLS protocol configured on client side, use SSLContext.getProtocol("TLS") instead of SSLContext.getProtocol("TLSv1.2") so that client can support multiple TLS protocol versions. --- .../org/apache/zookeeper/common/X509Util.java | 18 ++++++++++++------ .../server/NettyServerCnxnFactory.java | 2 +- .../apache/zookeeper/common/X509UtilTest.java | 2 +- 3 files changed, 14 insertions(+), 8 deletions(-) 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 2f8ec88a72a..f30499a33c0 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 @@ -83,7 +83,8 @@ public abstract class X509Util implements Closeable, AutoCloseable { } } - public static final String DEFAULT_PROTOCOL = "TLSv1.2"; + public static final String DEFAULT_PROTOCOL_SERVER = "TLSv1.2"; + public static final String DEFAULT_PROTOCOL_CLIENT = "TLS"; 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"}; } @@ -288,7 +289,7 @@ public SSLContext getDefaultSSLContext() throws X509Exception.SSLContextExceptio } public SSLContext createSSLContext(ZKConfig config) throws SSLContextException { - return createSSLContextAndOptions(config).getSSLContext(); + return createSSLContextAndOptions(config, true).getSSLContext(); } public SSLContextAndOptions getDefaultSSLContextAndOptions() throws X509Exception.SSLContextException { @@ -341,8 +342,12 @@ public int getSslHandshakeTimeoutMillis() { } } - @SuppressWarnings("unchecked") public SSLContextAndOptions createSSLContextAndOptions(ZKConfig config) throws SSLContextException { + return createSSLContextAndOptions(config, false); + } + + @SuppressWarnings("unchecked") + public SSLContextAndOptions createSSLContextAndOptions(ZKConfig config, boolean isClient) throws SSLContextException { final String supplierContextClassName = config.getProperty(sslContextSupplierClassProperty); if (supplierContextClassName != null) { LOG.debug("Loading SSLContext supplier from property '{}'", sslContextSupplierClassProperty); @@ -364,11 +369,11 @@ public SSLContextAndOptions createSSLContextAndOptions(ZKConfig config) throws S + "'", e); } } else { - return createSSLContextAndOptionsFromConfig(config); + return createSSLContextAndOptionsFromConfig(config, isClient); } } - public SSLContextAndOptions createSSLContextAndOptionsFromConfig(ZKConfig config) throws SSLContextException { + public SSLContextAndOptions createSSLContextAndOptionsFromConfig(ZKConfig config, boolean isClient) throws SSLContextException { KeyManager[] keyManagers = null; TrustManager[] trustManagers = null; @@ -421,7 +426,8 @@ public SSLContextAndOptions createSSLContextAndOptionsFromConfig(ZKConfig config } } - String protocol = config.getProperty(sslProtocolProperty, DEFAULT_PROTOCOL); + String defaultProtocol = isClient ? DEFAULT_PROTOCOL_CLIENT : DEFAULT_PROTOCOL_SERVER; + String protocol = config.getProperty(sslProtocolProperty, defaultProtocol); try { SSLContext sslContext = SSLContext.getInstance(protocol); sslContext.init(keyManagers, trustManagers, null); diff --git a/zookeeper-server/src/main/java/org/apache/zookeeper/server/NettyServerCnxnFactory.java b/zookeeper-server/src/main/java/org/apache/zookeeper/server/NettyServerCnxnFactory.java index 914a18d92dd..06b74f0d5f0 100644 --- a/zookeeper-server/src/main/java/org/apache/zookeeper/server/NettyServerCnxnFactory.java +++ b/zookeeper-server/src/main/java/org/apache/zookeeper/server/NettyServerCnxnFactory.java @@ -580,7 +580,7 @@ private synchronized void initSSL(ChannelPipeline p, boolean supportPlaintext) t SSLContextAndOptions sslContextAndOptions = x509Util.getDefaultSSLContextAndOptions(); nettySslContext = sslContextAndOptions.createNettyJdkSslContext(sslContextAndOptions.getSSLContext()); } else { - SSLContext sslContext = SSLContext.getInstance(ClientX509Util.DEFAULT_PROTOCOL); + SSLContext sslContext = SSLContext.getInstance(ClientX509Util.DEFAULT_PROTOCOL_SERVER); X509AuthenticationProvider authProvider = (X509AuthenticationProvider) ProviderRegistry.getProvider( System.getProperty(x509Util.getSslAuthProviderProperty(), "x509")); 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 a4ac4754373..03a01558984 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 @@ -101,7 +101,7 @@ public void testCreateSSLContextWithoutCustomProtocol( throws Exception { init(caKeyType, certKeyType, keyPassword, paramIndex); SSLContext sslContext = x509Util.getDefaultSSLContext(); - assertEquals(X509Util.DEFAULT_PROTOCOL, sslContext.getProtocol()); + assertEquals(X509Util.DEFAULT_PROTOCOL_SERVER, sslContext.getProtocol()); } @ParameterizedTest