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 9aa03ae491a..1c2b0e49ea5 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 @@ -79,7 +79,9 @@ public SslContext createNettySslContextForClient(ZKConfig config) sslContextBuilder.trustManager(tm); } - sslContextBuilder.enableOcsp(config.getBoolean(getSslOcspEnabledProperty())); + if (!config.getTriState(getSslOcspEnabledProperty()).isSystem()) { + sslContextBuilder.enableOcsp(config.getBoolean(getSslOcspEnabledProperty())); + } String[] enabledProtocols = getEnabledProtocols(config); if (enabledProtocols != null) { sslContextBuilder.protocols(enabledProtocols); @@ -123,7 +125,9 @@ public SslContext createNettySslContextForServer(ZKConfig config, KeyManager key sslContextBuilder.trustManager(trustManager); } - sslContextBuilder.enableOcsp(config.getBoolean(getSslOcspEnabledProperty())); + if (!config.getTriState(getSslOcspEnabledProperty()).isSystem()) { + sslContextBuilder.enableOcsp(config.getBoolean(getSslOcspEnabledProperty())); + } String[] enabledProtocols = getEnabledProtocols(config); if (enabledProtocols != null) { sslContextBuilder.protocols(enabledProtocols); @@ -189,8 +193,8 @@ private TrustManager getTrustManager(ZKConfig config) throws X509Exception.Trust getSslTruststorePasswdPathProperty()); String trustStoreType = config.getProperty(getSslTruststoreTypeProperty()); - boolean sslCrlEnabled = config.getBoolean(getSslCrlEnabledProperty()); - boolean sslOcspEnabled = config.getBoolean(getSslOcspEnabledProperty()); + TriState sslCrlEnabled = config.getTriState(getSslCrlEnabledProperty()); + TriState sslOcspEnabled = config.getTriState(getSslOcspEnabledProperty()); boolean sslServerHostnameVerificationEnabled = isServerHostnameVerificationEnabled(config); boolean sslClientHostnameVerificationEnabled = isClientHostnameVerificationEnabled(config); diff --git a/zookeeper-server/src/main/java/org/apache/zookeeper/common/TriState.java b/zookeeper-server/src/main/java/org/apache/zookeeper/common/TriState.java new file mode 100644 index 00000000000..52d6359f358 --- /dev/null +++ b/zookeeper-server/src/main/java/org/apache/zookeeper/common/TriState.java @@ -0,0 +1,40 @@ +package org.apache.zookeeper.common; + +/** + * Represent True / False / System (unset/default) values. + * + */ +public enum TriState { + True, + False, + System; + + /** + * @param value the string representation + * @return TriState.true if value equals "true" ignoring case, TriState.System + * if value equals "system", Tristate.False otherwise + */ + public static TriState parse(String value) { + if (value == null) { + return TriState.False; + } else if (value.equalsIgnoreCase("true")) { + return TriState.True; + } else if (value.equalsIgnoreCase("system")) { + return TriState.System; + } else { + return TriState.False; + } + } + + public boolean isTrue() { + return this == TriState.True; + } + + public boolean isFalse() { + return this == TriState.False; + } + + public boolean isSystem() { + return this == TriState.System; + } +} 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 153a826ba4f..60000a19cfc 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 @@ -392,8 +392,8 @@ public SSLContextAndOptions createSSLContextAndOptionsFromConfig(ZKConfig config String trustStorePasswordProp = getPasswordFromConfigPropertyOrFile(config, sslTruststorePasswdProperty, sslTruststorePasswdPathProperty); String trustStoreTypeProp = config.getProperty(sslTruststoreTypeProperty); - boolean sslCrlEnabled = config.getBoolean(this.sslCrlEnabledProperty); - boolean sslOcspEnabled = config.getBoolean(this.sslOcspEnabledProperty); + TriState sslCrlEnabled = config.getTriState(this.sslCrlEnabledProperty); + TriState sslOcspEnabled = config.getTriState(this.sslOcspEnabledProperty); boolean sslServerHostnameVerificationEnabled = isServerHostnameVerificationEnabled(config); boolean sslClientHostnameVerificationEnabled = isClientHostnameVerificationEnabled(config); boolean fipsMode = getFipsMode(config); @@ -537,8 +537,8 @@ public static X509TrustManager createTrustManager( String trustStoreLocation, String trustStorePassword, String trustStoreTypeProp, - boolean crlEnabled, - boolean ocspEnabled, + TriState crlEnabled, + TriState ocspEnabled, final boolean serverHostnameVerificationEnabled, final boolean clientHostnameVerificationEnabled, final boolean fipsMode) throws TrustManagerException { @@ -548,17 +548,19 @@ public static X509TrustManager createTrustManager( try { KeyStore ts = loadTrustStore(trustStoreLocation, trustStorePassword, trustStoreTypeProp); PKIXBuilderParameters pbParams = new PKIXBuilderParameters(ts, new X509CertSelector()); - if (crlEnabled || ocspEnabled) { - pbParams.setRevocationEnabled(true); - System.setProperty("com.sun.net.ssl.checkRevocation", "true"); - System.setProperty("com.sun.security.enableCRLDP", "true"); - if (ocspEnabled) { - Security.setProperty("ocsp.enable", "true"); - } - } else { - pbParams.setRevocationEnabled(false); + // Leave CRL/OCSP JVM global properties alone both are set to "system" (represented as null) + if (!crlEnabled.isSystem() || !ocspEnabled.isSystem()) { + if (crlEnabled.isTrue() || ocspEnabled.isTrue()) { + pbParams.setRevocationEnabled(true); + System.setProperty("com.sun.net.ssl.checkRevocation", "true"); + System.setProperty("com.sun.security.enableCRLDP", "true"); + if (ocspEnabled.isTrue()) { + Security.setProperty("ocsp.enable", "true"); + } + } else { + pbParams.setRevocationEnabled(false); + } } - // Revocation checking is only supported with the PKIX algorithm TrustManagerFactory tmf = TrustManagerFactory.getInstance("PKIX"); tmf.init(new CertPathTrustManagerParameters(pbParams)); diff --git a/zookeeper-server/src/main/java/org/apache/zookeeper/common/ZKConfig.java b/zookeeper-server/src/main/java/org/apache/zookeeper/common/ZKConfig.java index 846a5632e06..06e7d05b7f7 100644 --- a/zookeeper-server/src/main/java/org/apache/zookeeper/common/ZKConfig.java +++ b/zookeeper-server/src/main/java/org/apache/zookeeper/common/ZKConfig.java @@ -233,6 +233,18 @@ private void parseProperties(Properties cfg) { } } + /** + * Returns {@code Boolean.True} if and only if the property named by the argument + * exists and is case insensitive equal to the string {@code "true"}. + * Returns {@code nuln} if and only if the property named by the argument + * exists and is case insensitive equal to the string {@code "system"}. + * Returns {@code Boolean.False} otherwise. + */ + public TriState getTriState(String key) { + String propertyValue = getProperty(key); + return TriState.parse(propertyValue); + } + /** * Returns {@code true} if and only if the property named by the argument * exists and is equal to the string {@code "true"}. diff --git a/zookeeper-server/src/main/java/org/apache/zookeeper/server/auth/X509AuthenticationProvider.java b/zookeeper-server/src/main/java/org/apache/zookeeper/server/auth/X509AuthenticationProvider.java index 4ea925320f6..af952abaa4f 100644 --- a/zookeeper-server/src/main/java/org/apache/zookeeper/server/auth/X509AuthenticationProvider.java +++ b/zookeeper-server/src/main/java/org/apache/zookeeper/server/auth/X509AuthenticationProvider.java @@ -32,6 +32,7 @@ import javax.servlet.http.HttpServletRequest; import org.apache.zookeeper.KeeperException; import org.apache.zookeeper.common.ClientX509Util; +import org.apache.zookeeper.common.TriState; import org.apache.zookeeper.common.X509Exception; import org.apache.zookeeper.common.X509Exception.KeyManagerException; import org.apache.zookeeper.common.X509Exception.TrustManagerException; @@ -85,8 +86,8 @@ public X509AuthenticationProvider() throws X509Exception { x509Util.getSslKeystorePasswdPathProperty()); String keyStoreTypeProp = config.getProperty(x509Util.getSslKeystoreTypeProperty()); - boolean crlEnabled = Boolean.parseBoolean(config.getProperty(x509Util.getSslCrlEnabledProperty())); - boolean ocspEnabled = Boolean.parseBoolean(config.getProperty(x509Util.getSslOcspEnabledProperty())); + TriState crlEnabled = config.getTriState(x509Util.getSslOcspEnabledProperty()); + TriState ocspEnabled = config.getTriState(x509Util.getSslOcspEnabledProperty()); boolean hostnameVerificationEnabled = Boolean.parseBoolean(config.getProperty(x509Util.getSslHostnameVerificationEnabledProperty())); X509KeyManager km = 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 e4f19d77fd1..2ae89600f2b 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 @@ -266,6 +266,42 @@ public void testOCSPEnabled( assertTrue(Boolean.valueOf(Security.getProperty("ocsp.enable"))); } + @ParameterizedTest + @MethodSource("data") + @Timeout(value = 5) + public void testOCSPCRLTransparentFalse( + X509KeyType caKeyType, X509KeyType certKeyType, String keyPassword, Integer paramIndex) + throws Exception { + System.setProperty("com.sun.net.ssl.checkRevocation", Boolean.FALSE.toString()); + System.setProperty("com.sun.security.enableCRLDP", Boolean.FALSE.toString()); + Security.setProperty("ocsp.enable", Boolean.FALSE.toString()); + init(caKeyType, certKeyType, keyPassword, paramIndex); + System.setProperty(x509Util.getSslOcspEnabledProperty(), "system"); + System.setProperty(x509Util.getSslCrlEnabledProperty(), "system"); + x509Util.getDefaultSSLContext(); + assertFalse(Boolean.valueOf(System.getProperty("com.sun.net.ssl.checkRevocation"))); + assertFalse(Boolean.valueOf(System.getProperty("com.sun.security.enableCRLDP"))); + assertFalse(Boolean.valueOf(Security.getProperty("ocsp.enable"))); + } + + @ParameterizedTest + @MethodSource("data") + @Timeout(value = 5) + public void testOCSPCRLTransparentTrue( + X509KeyType caKeyType, X509KeyType certKeyType, String keyPassword, Integer paramIndex) + throws Exception { + System.setProperty("com.sun.net.ssl.checkRevocation", Boolean.TRUE.toString()); + System.setProperty("com.sun.security.enableCRLDP", Boolean.TRUE.toString()); + Security.setProperty("ocsp.enable", Boolean.TRUE.toString()); + init(caKeyType, certKeyType, keyPassword, paramIndex); + System.setProperty(x509Util.getSslOcspEnabledProperty(), "system"); + System.setProperty(x509Util.getSslCrlEnabledProperty(), "system"); + x509Util.getDefaultSSLContext(); + assertTrue(Boolean.valueOf(System.getProperty("com.sun.net.ssl.checkRevocation"))); + assertTrue(Boolean.valueOf(System.getProperty("com.sun.security.enableCRLDP"))); + assertTrue(Boolean.valueOf(Security.getProperty("ocsp.enable"))); + } + @ParameterizedTest @MethodSource("data") @Timeout(value = 5) @@ -373,8 +409,8 @@ public void testLoadPEMTrustStore( X509TrustManager tm = X509Util.createTrustManager( x509TestContext.getTrustStoreFile(KeyStoreFileType.PEM).getAbsolutePath(), x509TestContext.getTrustStorePassword(), KeyStoreFileType.PEM.getPropertyValue(), - false, - false, + TriState.False, + TriState.False, true, true, false); @@ -394,8 +430,8 @@ public void testLoadPEMTrustStoreNullPassword( x509TestContext.getTrustStoreFile(KeyStoreFileType.PEM).getAbsolutePath(), null, KeyStoreFileType.PEM.getPropertyValue(), - false, - false, + TriState.False, + TriState.False, true, true, false); @@ -413,8 +449,8 @@ public void testLoadPEMTrustStoreAutodetectStoreFileType( x509TestContext.getTrustStoreFile(KeyStoreFileType.PEM).getAbsolutePath(), x509TestContext.getTrustStorePassword(), null, // null StoreFileType means 'autodetect from file extension' - false, - false, + TriState.False, + TriState.False, true, true, false); @@ -488,8 +524,8 @@ public void testLoadJKSTrustStore( x509TestContext.getTrustStoreFile(KeyStoreFileType.JKS).getAbsolutePath(), x509TestContext.getTrustStorePassword(), KeyStoreFileType.JKS.getPropertyValue(), - true, - true, + TriState.True, + TriState.True, true, true, false); @@ -509,8 +545,8 @@ public void testLoadJKSTrustStoreNullPassword( x509TestContext.getTrustStoreFile(KeyStoreFileType.JKS).getAbsolutePath(), null, KeyStoreFileType.JKS.getPropertyValue(), - false, - false, + TriState.False, + TriState.False, true, true, false); @@ -527,8 +563,8 @@ public void testLoadJKSTrustStoreAutodetectStoreFileType( x509TestContext.getTrustStoreFile(KeyStoreFileType.JKS).getAbsolutePath(), x509TestContext.getTrustStorePassword(), null, // null StoreFileType means 'autodetect from file extension' - true, - true, + TriState.True, + TriState.True, true, true, false); @@ -546,8 +582,8 @@ public void testLoadJKSTrustStoreWithWrongPassword( x509TestContext.getTrustStoreFile(KeyStoreFileType.JKS).getAbsolutePath(), "wrong password", KeyStoreFileType.JKS.getPropertyValue(), - true, - true, + TriState.True, + TriState.True, true, true, false); @@ -621,8 +657,8 @@ public void testLoadPKCS12TrustStore( X509TrustManager tm = X509Util.createTrustManager( x509TestContext.getTrustStoreFile(KeyStoreFileType.PKCS12).getAbsolutePath(), x509TestContext.getTrustStorePassword(), KeyStoreFileType.PKCS12.getPropertyValue(), - true, - true, + TriState.True, + TriState.True, true, true, false); @@ -642,8 +678,8 @@ public void testLoadPKCS12TrustStoreNullPassword( x509TestContext.getTrustStoreFile(KeyStoreFileType.PKCS12).getAbsolutePath(), null, KeyStoreFileType.PKCS12.getPropertyValue(), - false, - false, + TriState.False, + TriState.False, true, true, false); @@ -660,8 +696,8 @@ public void testLoadPKCS12TrustStoreAutodetectStoreFileType( x509TestContext.getTrustStoreFile(KeyStoreFileType.PKCS12).getAbsolutePath(), x509TestContext.getTrustStorePassword(), null, // null StoreFileType means 'autodetect from file extension' - true, - true, + TriState.True, + TriState.True, true, true, false); @@ -679,8 +715,8 @@ public void testLoadPKCS12TrustStoreWithWrongPassword( x509TestContext.getTrustStoreFile(KeyStoreFileType.PKCS12).getAbsolutePath(), "wrong password", KeyStoreFileType.PKCS12.getPropertyValue(), - true, - true, + TriState.True, + TriState.True, true, true, false);