Skip to content

Commit 972e71c

Browse files
authored
ZOOKEEPER-5043: Disable fallback to DIGEST-MD5 in SaslServer when FIPS mode is set
Reviewers: anmolnar, meszibalu Author: PDavid Closes #2381 from PDavid/ZOOKEEPER-5043-disable-DIGEST-MD5
1 parent 8184fd1 commit 972e71c

5 files changed

Lines changed: 97 additions & 4 deletions

File tree

zookeeper-client/zookeeper-client-c/tests/zkServer.sh

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -113,7 +113,8 @@ read_only=
113113
PROPERTIES=($EXTRA_JVM_ARGS "-Dzookeeper.extendedTypesEnabled=true" "-Dznode.container.checkIntervalMs=100")
114114
if [[ $1 == "startRequireSASLAuth" ]]; then
115115
PROPERTIES=("-Dzookeeper.sessionRequireClientSASLAuth=true" "${PROPERTIES[@]}"
116-
"-Dzookeeper.authProvider.1=org.apache.zookeeper.server.auth.SASLAuthenticationProvider")
116+
"-Dzookeeper.authProvider.1=org.apache.zookeeper.server.auth.SASLAuthenticationProvider"
117+
"-Dzookeeper.fips-mode=false")
117118
if [[ -n $2 ]]; then
118119
PROPERTIES=("${PROPERTIES[@]}" "-Djava.security.auth.login.config=$2")
119120
fi

zookeeper-server/src/main/java/org/apache/zookeeper/server/ZooKeeperSaslServer.java

Lines changed: 9 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -22,6 +22,7 @@
2222
import javax.security.sasl.SaslException;
2323
import javax.security.sasl.SaslServer;
2424
import org.apache.zookeeper.Login;
25+
import org.apache.zookeeper.common.ZKConfig;
2526
import org.apache.zookeeper.util.SecurityUtils;
2627
import org.slf4j.Logger;
2728
import org.slf4j.LoggerFactory;
@@ -32,20 +33,26 @@ public class ZooKeeperSaslServer {
3233
public static final String DEFAULT_LOGIN_CONTEXT_NAME = "Server";
3334

3435
private static final Logger LOG = LoggerFactory.getLogger(ZooKeeperSaslServer.class);
35-
private SaslServer saslServer;
36+
private final SaslServer saslServer;
37+
private final ZKConfig config;
3638

3739
ZooKeeperSaslServer(final Login login) {
40+
config = new ZKConfig();
3841
saslServer = createSaslServer(login);
3942
}
4043

4144
private SaslServer createSaslServer(final Login login) {
4245
synchronized (login) {
4346
Subject subject = login.getSubject();
44-
return SecurityUtils.createSaslServer(subject, "zookeeper", "zk-sasl-md5", login.newCallbackHandler(), LOG);
47+
return SecurityUtils.createSaslServer(config, subject, "zookeeper", "zk-sasl-md5", login.newCallbackHandler(), LOG);
4548
}
4649
}
4750

4851
public byte[] evaluateResponse(byte[] response) throws SaslException {
52+
if (saslServer == null) {
53+
LOG.error("SaslServer failed to initialize (FIPS mode may have blocked DIGEST-MD5). Cannot authenticate client.");
54+
throw new SaslException("SaslServer is null, cannot evaluate client SASL response.");
55+
}
4956
return saslServer.evaluateResponse(response);
5057
}
5158

zookeeper-server/src/main/java/org/apache/zookeeper/server/quorum/auth/SaslQuorumAuthServer.java

Lines changed: 7 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -47,6 +47,7 @@ public class SaslQuorumAuthServer implements QuorumAuthServer {
4747
private static final int MAX_RETRIES = 5;
4848
private final Login serverLogin;
4949
private final boolean quorumRequireSasl;
50+
private final ZKConfig zkConfig;
5051

5152
public SaslQuorumAuthServer(boolean quorumRequireSasl, String loginContext, Set<String> authzHosts) throws SaslException {
5253
this.quorumRequireSasl = quorumRequireSasl;
@@ -60,7 +61,8 @@ public SaslQuorumAuthServer(boolean quorumRequireSasl, String loginContext, Set<
6061
Supplier<CallbackHandler> callbackSupplier = () -> {
6162
return new SaslQuorumServerCallbackHandler(entries, authzHosts);
6263
};
63-
serverLogin = new Login(loginContext, callbackSupplier, new ZKConfig());
64+
zkConfig = new ZKConfig();
65+
serverLogin = new Login(loginContext, callbackSupplier, zkConfig);
6466
serverLogin.startThreadIfNeeded();
6567
} catch (Throwable e) {
6668
throw new SaslException("Failed to initialize authentication mechanism using SASL", e);
@@ -86,11 +88,15 @@ public void authenticate(Socket sock, DataInputStream din) throws SaslException
8688
dout = new DataOutputStream(sock.getOutputStream());
8789
byte[] challenge = null;
8890
ss = SecurityUtils.createSaslServer(
91+
zkConfig,
8992
serverLogin.getSubject(),
9093
QuorumAuth.QUORUM_SERVER_PROTOCOL_NAME,
9194
QuorumAuth.QUORUM_SERVER_SASL_DIGEST,
9295
serverLogin.newCallbackHandler(),
9396
LOG);
97+
if (ss == null) {
98+
throw new SaslException("Failed to create SaslServer (FIPS mode may be blocking DIGEST-MD5)");
99+
}
94100
while (!ss.isComplete()) {
95101
challenge = ss.evaluateResponse(token);
96102
if (!ss.isComplete()) {

zookeeper-server/src/main/java/org/apache/zookeeper/util/SecurityUtils.java

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -153,6 +153,7 @@ public SaslClient run() throws SaslException {
153153
/**
154154
* Create an instance of a SaslServer. It will return null if there is an exception.
155155
*
156+
* @param config to check whether FIPS mode is enabled.
156157
* @param subject subject
157158
* @param protocol protocol
158159
* @param serverName server name
@@ -161,6 +162,7 @@ public SaslClient run() throws SaslException {
161162
* @return sasl server object
162163
*/
163164
public static SaslServer createSaslServer(
165+
final ZKConfig config,
164166
final Subject subject,
165167
final String protocol,
166168
final String serverName,
@@ -251,6 +253,11 @@ public SaslServer run() {
251253
// JAAS non-GSSAPI authentication: assuming and supporting only
252254
// DIGEST-MD5 mechanism for now.
253255
// TODO: use 'authMech=' value in zoo.cfg.
256+
// FIPS-mode: don't try DIGEST-MD5, just return error
257+
if (X509Util.getFipsMode(config)) {
258+
LOG.warn("SaslServer will not use DIGEST-MD5 as SASL mechanism, because FIPS mode is enabled.");
259+
return null;
260+
}
254261
try {
255262
SaslServer saslServer = Sasl.createSaslServer("DIGEST-MD5", protocol, serverName, null, callbackHandler);
256263
return saslServer;
Lines changed: 72 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,72 @@
1+
/*
2+
* Licensed to the Apache Software Foundation (ASF) under one
3+
* or more contributor license agreements. See the NOTICE file
4+
* distributed with this work for additional information
5+
* regarding copyright ownership. The ASF licenses this file
6+
* to you under the Apache License, Version 2.0 (the
7+
* "License"); you may not use this file except in compliance
8+
* with the License. You may obtain a copy of the License at
9+
*
10+
* http://www.apache.org/licenses/LICENSE-2.0
11+
*
12+
* Unless required by applicable law or agreed to in writing, software
13+
* distributed under the License is distributed on an "AS IS" BASIS,
14+
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
15+
* See the License for the specific language governing permissions and
16+
* limitations under the License.
17+
*/
18+
19+
package org.apache.zookeeper.test;
20+
21+
import static org.junit.jupiter.api.Assertions.assertEquals;
22+
import static org.junit.jupiter.api.Assertions.fail;
23+
import org.apache.zookeeper.CreateMode;
24+
import org.apache.zookeeper.KeeperException;
25+
import org.apache.zookeeper.ZooDefs.Ids;
26+
import org.apache.zookeeper.ZooKeeper;
27+
import org.apache.zookeeper.common.X509Util;
28+
import org.junit.jupiter.api.AfterAll;
29+
import org.junit.jupiter.api.BeforeAll;
30+
import org.junit.jupiter.api.Test;
31+
32+
/**
33+
* Tests that DIGEST-MD5 SASL authentication is rejected when FIPS mode is enabled.
34+
* Does NOT extend SaslAuthDigestTestBase because that base class disables FIPS mode.
35+
*/
36+
public class SaslAuthFailFipsModeTest extends ClientBase {
37+
38+
@BeforeAll
39+
public static void setUpBeforeClass() {
40+
System.setProperty(X509Util.FIPS_MODE_PROPERTY, "true");
41+
System.setProperty(SaslTestUtil.requireSASLAuthProperty, "true");
42+
System.setProperty(SaslTestUtil.authProviderProperty, SaslTestUtil.authProvider);
43+
System.setProperty(SaslTestUtil.jaasConfig, SaslTestUtil.createJAASConfigFile("jaas_fips.conf", "test"));
44+
}
45+
46+
@AfterAll
47+
public static void tearDownAfterClass() {
48+
System.clearProperty(X509Util.FIPS_MODE_PROPERTY);
49+
System.clearProperty(SaslTestUtil.requireSASLAuthProperty);
50+
System.clearProperty(SaslTestUtil.authProviderProperty);
51+
System.clearProperty(SaslTestUtil.jaasConfig);
52+
}
53+
54+
@Test
55+
public void testDigestMd5RejectedInFipsMode() throws Exception {
56+
ZooKeeper zk = null;
57+
CountdownWatcher watcher = new CountdownWatcher();
58+
try {
59+
zk = createClient(watcher);
60+
zk.create("/fips-test", null, Ids.CREATOR_ALL_ACL, CreateMode.PERSISTENT);
61+
fail("DIGEST-MD5 SASL authentication should be rejected when FIPS mode is enabled.");
62+
} catch (KeeperException e) {
63+
assertEquals(KeeperException.Code.AUTHFAILED, e.code());
64+
watcher.waitForDisconnected(SaslTestUtil.CLIENT_DISCONNECT_TIMEOUT);
65+
} finally {
66+
if (zk != null) {
67+
zk.close();
68+
}
69+
}
70+
}
71+
72+
}

0 commit comments

Comments
 (0)