You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@zookeeper.apache.org by an...@apache.org on 2026/09/02 20:02:15 UTC

(zookeeper) 01/03: Quorum TLS in FIPS mode accepts hostname-mismatched peer certificates

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

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

commit ead4f69bb1a55bd484db88b2eed7b8752331a841
Author: Andor Molnar <an...@cloudera.com>
AuthorDate: Tue Jun 23 15:33:21 2026 -0500

    Quorum TLS in FIPS mode accepts hostname-mismatched peer certificates
---
 .../zookeeper/common/SSLContextAndOptions.java     | 32 ++++++++++++++++++----
 .../zookeeper/server/quorum/QuorumSSLTest.java     | 14 ++++++----
 2 files changed, 36 insertions(+), 10 deletions(-)

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 c712f6acb..627cc17b3 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
@@ -47,7 +47,7 @@ public class SSLContextAndOptions {
     private final X509Util.ClientAuth clientAuth;
     private final SSLContext sslContext;
     private final int handshakeDetectionTimeoutMillis;
-
+    private final ZKConfig zkConfig;
 
     /**
      * Note: constructor is intentionally package-private, only the X509Util class should be creating instances of this
@@ -59,10 +59,11 @@ public class SSLContextAndOptions {
     SSLContextAndOptions(final X509Util x509Util, final ZKConfig config, final SSLContext sslContext) {
         this.x509Util = requireNonNull(x509Util);
         this.sslContext = requireNonNull(sslContext);
-        this.enabledProtocols = getEnabledProtocols(requireNonNull(config), sslContext);
-        this.cipherSuites = getCipherSuites(config);
-        this.clientAuth = getClientAuth(config);
-        this.handshakeDetectionTimeoutMillis = getHandshakeDetectionTimeoutMillis(config);
+        this.zkConfig = requireNonNull(config);
+        this.enabledProtocols = getEnabledProtocols(zkConfig, sslContext);
+        this.cipherSuites = getCipherSuites(zkConfig);
+        this.clientAuth = getClientAuth(zkConfig);
+        this.handshakeDetectionTimeoutMillis = getHandshakeDetectionTimeoutMillis(zkConfig);
     }
 
     public SSLContext getSSLContext() {
@@ -144,6 +145,27 @@ private void configureSslParameters(SSLParameters sslParameters, boolean isClien
                 break;
             }
         }
+
+        // In FIPS-mode we deal with hostname verification here,
+        // while in non-FIPS mode verification is handled by ZKTrustManager.
+        if (X509Util.getFipsMode(zkConfig)) {
+            String clientOrServer = isClientSocket ? "Server" : "Client";
+            if (isClientSocket) {
+                if (x509Util.isServerHostnameVerificationEnabled(zkConfig)) {
+                    sslParameters.setEndpointIdentificationAlgorithm("HTTPS");
+                    if (LOG.isDebugEnabled()) {
+                        LOG.debug("{} hostname verification: enabled HTTPS style endpoint identification algorithm", clientOrServer);
+                    }
+                }
+            } else {
+                if (x509Util.isClientHostnameVerificationEnabled(zkConfig)) {
+                    sslParameters.setEndpointIdentificationAlgorithm("HTTPS");
+                    if (LOG.isDebugEnabled()) {
+                        LOG.debug("{} hostname verification: enabled HTTPS style endpoint identification algorithm", clientOrServer);
+                    }
+                }
+            }
+        }
     }
 
     private String[] getEnabledProtocols(final ZKConfig config, final SSLContext sslContext) {
diff --git a/zookeeper-server/src/test/java/org/apache/zookeeper/server/quorum/QuorumSSLTest.java b/zookeeper-server/src/test/java/org/apache/zookeeper/server/quorum/QuorumSSLTest.java
index 167133424..23ce60728 100644
--- a/zookeeper-server/src/test/java/org/apache/zookeeper/server/quorum/QuorumSSLTest.java
+++ b/zookeeper-server/src/test/java/org/apache/zookeeper/server/quorum/QuorumSSLTest.java
@@ -621,7 +621,7 @@ private void stopAppendConfigRestartAll(Map<Integer, MainThread> members, String
         }
     }
 
-    @TestNoFipsOnly
+    @TestBothFipsModes
     @Timeout(value = 5, unit = TimeUnit.MINUTES)
     public void testHostnameVerificationWithInvalidHostname(boolean fipsEnabled) throws Exception {
         System.setProperty(quorumX509Util.getFipsModeProperty(), Boolean.toString(fipsEnabled));
@@ -639,7 +639,7 @@ public void testHostnameVerificationWithInvalidHostname(boolean fipsEnabled) thr
         testHostnameVerification(badhostnameKeystorePath, false);
     }
 
-    @TestNoFipsOnly
+    @TestBothFipsModes
     @Timeout(value = 5, unit = TimeUnit.MINUTES)
     public void testHostnameVerificationWithInvalidIPAddress(boolean fipsEnabled) throws Exception {
         System.setProperty(quorumX509Util.getFipsModeProperty(), Boolean.toString(fipsEnabled));
@@ -657,7 +657,7 @@ public void testHostnameVerificationWithInvalidIPAddress(boolean fipsEnabled) th
         testHostnameVerification(badhostnameKeystorePath, false);
     }
 
-    @TestNoFipsOnly
+    @TestBothFipsModes
     @Timeout(value = 5, unit = TimeUnit.MINUTES)
     public void testHostnameVerificationWithInvalidIpAddressAndInvalidHostname(boolean fipsEnabled) throws Exception {
         System.setProperty(quorumX509Util.getFipsModeProperty(), Boolean.toString(fipsEnabled));
@@ -676,7 +676,7 @@ public void testHostnameVerificationWithInvalidIpAddressAndInvalidHostname(boole
         testHostnameVerification(badhostnameKeystorePath, false);
     }
 
-    @TestNoFipsOnly
+    @TestBothFipsModes
     @Timeout(value = 5, unit = TimeUnit.MINUTES)
     public void testHostnameVerificationForInvalidMultiAddressServerConfig(boolean fipsEnabled) throws Exception {
         System.setProperty(quorumX509Util.getFipsModeProperty(), Boolean.toString(fipsEnabled));
@@ -698,6 +698,10 @@ public void testHostnameVerificationForInvalidMultiAddressServerConfig(boolean f
         testHostnameVerification(badhostnameKeystorePath, false);
     }
 
+    /**
+     * This test is NoFips only, because it needs reverse Dns lookup for client hostname verification,
+     * which is not supported in Fips mode.
+     */
     @TestNoFipsOnly
     @Timeout(value = 5, unit = TimeUnit.MINUTES)
     public void testHostnameVerificationWithInvalidIpAddressAndValidHostname(boolean fipsEnabled) throws Exception {
@@ -719,7 +723,7 @@ public void testHostnameVerificationWithInvalidIpAddressAndValidHostname(boolean
         testHostnameVerification(badhostnameKeystorePath, true);
     }
 
-    @TestNoFipsOnly
+    @TestBothFipsModes
     @Timeout(value = 5, unit = TimeUnit.MINUTES)
     public void testHostnameVerificationWithValidIpAddressAndInvalidHostname(boolean fipsEnabled) throws Exception {
         System.setProperty(quorumX509Util.getFipsModeProperty(), Boolean.toString(fipsEnabled));