http://git-wip-us.apache.org/repos/asf/zookeeper/blob/43d71c2e/zookeeper-common/src/main/java/org/apache/zookeeper/common/X509Exception.java ---------------------------------------------------------------------- diff --git a/zookeeper-common/src/main/java/org/apache/zookeeper/common/X509Exception.java b/zookeeper-common/src/main/java/org/apache/zookeeper/common/X509Exception.java deleted file mode 100644 index 984a2ab..0000000 --- a/zookeeper-common/src/main/java/org/apache/zookeeper/common/X509Exception.java +++ /dev/null @@ -1,67 +0,0 @@ -/** - * Licensed to the Apache Software Foundation (ASF) under one - * or more contributor license agreements. See the NOTICE file - * distributed with this work for additional information - * regarding copyright ownership. The ASF licenses this file - * to you under the Apache License, Version 2.0 (the - * "License"); you may not use this file except in compliance - * with the License. You may obtain a copy of the License at - * <p/> - * http://www.apache.org/licenses/LICENSE-2.0 - * <p/> - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ -package org.apache.zookeeper.common; - -@SuppressWarnings("serial") -public class X509Exception extends Exception { - public X509Exception(String message) { - super(message); - } - - public X509Exception(Throwable cause) { - super(cause); - } - - public X509Exception(String message, Throwable cause) { - super(message, cause); - } - - public static class KeyManagerException extends X509Exception { - public KeyManagerException(String message) { - super(message); - } - - public KeyManagerException(Throwable cause) { - super(cause); - } - } - - public static class TrustManagerException extends X509Exception { - public TrustManagerException(String message) { - super(message); - } - - public TrustManagerException(Throwable cause) { - super(cause); - } - } - - public static class SSLContextException extends X509Exception { - public SSLContextException(String message) { - super(message); - } - - public SSLContextException(Throwable cause) { - super(cause); - } - - public SSLContextException(String message, Throwable cause) { - super(message, cause); - } - } -}
http://git-wip-us.apache.org/repos/asf/zookeeper/blob/43d71c2e/zookeeper-common/src/main/java/org/apache/zookeeper/common/X509Util.java ---------------------------------------------------------------------- diff --git a/zookeeper-common/src/main/java/org/apache/zookeeper/common/X509Util.java b/zookeeper-common/src/main/java/org/apache/zookeeper/common/X509Util.java deleted file mode 100644 index 2112c70..0000000 --- a/zookeeper-common/src/main/java/org/apache/zookeeper/common/X509Util.java +++ /dev/null @@ -1,363 +0,0 @@ -/** - * Licensed to the Apache Software Foundation (ASF) under one - * or more contributor license agreements. See the NOTICE file - * distributed with this work for additional information - * regarding copyright ownership. The ASF licenses this file - * to you under the Apache License, Version 2.0 (the - * "License"); you may not use this file except in compliance - * with the License. You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ -package org.apache.zookeeper.common; - - -import org.slf4j.Logger; -import org.slf4j.LoggerFactory; - -import javax.net.ssl.CertPathTrustManagerParameters; -import javax.net.ssl.KeyManager; -import javax.net.ssl.KeyManagerFactory; -import javax.net.ssl.SSLContext; -import javax.net.ssl.SSLParameters; -import javax.net.ssl.SSLServerSocket; -import javax.net.ssl.SSLSocket; -import javax.net.ssl.TrustManager; -import javax.net.ssl.TrustManagerFactory; -import javax.net.ssl.X509ExtendedTrustManager; -import javax.net.ssl.X509KeyManager; -import javax.net.ssl.X509TrustManager; -import java.io.File; -import java.io.FileInputStream; -import java.io.IOException; -import java.net.Socket; -import java.security.InvalidAlgorithmParameterException; -import java.security.KeyManagementException; -import java.security.KeyStore; -import java.security.KeyStoreException; -import java.security.NoSuchAlgorithmException; -import java.security.Security; -import java.security.UnrecoverableKeyException; -import java.security.cert.CertificateException; -import java.security.cert.PKIXBuilderParameters; -import java.security.cert.X509CertSelector; -import java.util.Arrays; -import java.util.concurrent.atomic.AtomicReference; - -import org.apache.zookeeper.common.X509Exception.KeyManagerException; -import org.apache.zookeeper.common.X509Exception.SSLContextException; -import org.apache.zookeeper.common.X509Exception.TrustManagerException; - -/** - * 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 { - private static final Logger LOG = LoggerFactory.getLogger(X509Util.class); - - static final String DEFAULT_PROTOCOL = "TLSv1.2"; - private static final String[] DEFAULT_CIPHERS_JAVA8 = { - "TLS_ECDHE_ECDSA_WITH_AES_128_CBC_SHA256", - "TLS_ECDHE_RSA_WITH_AES_128_CBC_SHA256", - "TLS_ECDHE_ECDSA_WITH_AES_128_GCM_SHA256", - "TLS_ECDHE_RSA_WITH_AES_128_GCM_SHA256" - }; - private static final String[] DEFAULT_CIPHERS_JAVA9 = { - "TLS_ECDHE_ECDSA_WITH_AES_128_GCM_SHA256", - "TLS_ECDHE_RSA_WITH_AES_128_GCM_SHA256", - "TLS_ECDHE_ECDSA_WITH_AES_128_CBC_SHA256", - "TLS_ECDHE_RSA_WITH_AES_128_CBC_SHA256" - }; - - private String sslProtocolProperty = getConfigPrefix() + "protocol"; - private String cipherSuitesProperty = getConfigPrefix() + "ciphersuites"; - private String sslKeystoreLocationProperty = getConfigPrefix() + "keyStore.location"; - private String sslKeystorePasswdProperty = getConfigPrefix() + "keyStore.password"; - private String sslTruststoreLocationProperty = getConfigPrefix() + "trustStore.location"; - private String sslTruststorePasswdProperty = getConfigPrefix() + "trustStore.password"; - private String sslHostnameVerificationEnabledProperty = getConfigPrefix() + "hostnameVerification"; - private String sslCrlEnabledProperty = getConfigPrefix() + "crl"; - private String sslOcspEnabledProperty = getConfigPrefix() + "ocsp"; - - private String[] cipherSuites; - - private AtomicReference<SSLContext> defaultSSLContext = new AtomicReference<>(null); - - public X509Util() { - String cipherSuitesInput = System.getProperty(cipherSuitesProperty); - if (cipherSuitesInput == null) { - cipherSuites = getDefaultCipherSuites(); - } else { - cipherSuites = cipherSuitesInput.split(","); - } - } - - protected abstract String getConfigPrefix(); - protected abstract boolean shouldVerifyClientHostname(); - - public String getSslProtocolProperty() { - return sslProtocolProperty; - } - - public String getCipherSuitesProperty() { - return cipherSuitesProperty; - } - - public String getSslKeystoreLocationProperty() { - return sslKeystoreLocationProperty; - } - - public String getSslKeystorePasswdProperty() { - return sslKeystorePasswdProperty; - } - - public String getSslTruststoreLocationProperty() { - return sslTruststoreLocationProperty; - } - - public String getSslTruststorePasswdProperty() { - return sslTruststorePasswdProperty; - } - - public String getSslHostnameVerificationEnabledProperty() { - return sslHostnameVerificationEnabledProperty; - } - - public String getSslCrlEnabledProperty() { - return sslCrlEnabledProperty; - } - - public String getSslOcspEnabledProperty() { - return sslOcspEnabledProperty; - } - - public SSLContext getDefaultSSLContext() throws X509Exception.SSLContextException { - SSLContext result = defaultSSLContext.get(); - if (result == null) { - result = createSSLContext(); - if (!defaultSSLContext.compareAndSet(null, result)) { - // lost the race, another thread already set the value - result = defaultSSLContext.get(); - } - } - return result; - } - - private SSLContext createSSLContext() throws SSLContextException { - /* - * Since Configuration initializes the key store and trust store related - * configuration from system property. Reading property from - * configuration will be same reading from system property - */ - ZKConfig config=new ZKConfig(); - return createSSLContext(config); - } - - public SSLContext createSSLContext(ZKConfig config) throws SSLContextException { - KeyManager[] keyManagers = null; - TrustManager[] trustManagers = null; - - String keyStoreLocationProp = config.getProperty(sslKeystoreLocationProperty); - String keyStorePasswordProp = config.getProperty(sslKeystorePasswdProperty); - - // There are legal states in some use cases for null KeyManager or TrustManager. - // But if a user wanna specify one, location and password are required. - - if (keyStoreLocationProp == null && keyStorePasswordProp == null) { - LOG.warn(getSslKeystoreLocationProperty() + " not specified"); - } else { - if (keyStoreLocationProp == null) { - throw new SSLContextException(getSslKeystoreLocationProperty() + " not specified"); - } - if (keyStorePasswordProp == null) { - throw new SSLContextException(getSslKeystorePasswdProperty() + " not specified"); - } - try { - keyManagers = new KeyManager[]{ - createKeyManager(keyStoreLocationProp, keyStorePasswordProp)}; - } catch (KeyManagerException keyManagerException) { - throw new SSLContextException("Failed to create KeyManager", keyManagerException); - } - } - - String trustStoreLocationProp = config.getProperty(sslTruststoreLocationProperty); - String trustStorePasswordProp = config.getProperty(sslTruststorePasswdProperty); - - boolean sslCrlEnabled = config.getBoolean(this.sslCrlEnabledProperty); - boolean sslOcspEnabled = config.getBoolean(this.sslOcspEnabledProperty); - boolean sslServerHostnameVerificationEnabled = - config.getBoolean(this.getSslHostnameVerificationEnabledProperty(),true); - boolean sslClientHostnameVerificationEnabled = sslServerHostnameVerificationEnabled && shouldVerifyClientHostname(); - - if (trustStoreLocationProp == null) { - LOG.warn(getSslTruststoreLocationProperty() + " not specified"); - } else { - try { - trustManagers = new TrustManager[]{ - createTrustManager(trustStoreLocationProp, trustStorePasswordProp, sslCrlEnabled, sslOcspEnabled, - sslServerHostnameVerificationEnabled, sslClientHostnameVerificationEnabled)}; - } catch (TrustManagerException trustManagerException) { - throw new SSLContextException("Failed to create TrustManager", trustManagerException); - } - } - - String protocol = System.getProperty(sslProtocolProperty, DEFAULT_PROTOCOL); - try { - SSLContext sslContext = SSLContext.getInstance(protocol); - sslContext.init(keyManagers, trustManagers, null); - return sslContext; - } catch (NoSuchAlgorithmException|KeyManagementException sslContextInitException) { - throw new SSLContextException(sslContextInitException); - } - } - - public static X509KeyManager createKeyManager(String keyStoreLocation, String keyStorePassword) - throws KeyManagerException { - FileInputStream inputStream = null; - try { - char[] keyStorePasswordChars = keyStorePassword.toCharArray(); - File keyStoreFile = new File(keyStoreLocation); - KeyStore ks = KeyStore.getInstance("JKS"); - inputStream = new FileInputStream(keyStoreFile); - ks.load(inputStream, keyStorePasswordChars); - KeyManagerFactory kmf = KeyManagerFactory.getInstance("PKIX"); - kmf.init(ks, keyStorePasswordChars); - - for (KeyManager km : kmf.getKeyManagers()) { - if (km instanceof X509KeyManager) { - return (X509KeyManager) km; - } - } - throw new KeyManagerException("Couldn't find X509KeyManager"); - - } catch (IOException|CertificateException|UnrecoverableKeyException|NoSuchAlgorithmException|KeyStoreException - keyManagerCreationException) { - throw new KeyManagerException(keyManagerCreationException); - } finally { - if (inputStream != null) { - try { - inputStream.close(); - } catch (IOException ioException) { - LOG.info("Failed to close key store input stream", ioException); - } - } - } - } - - public static X509TrustManager createTrustManager(String trustStoreLocation, String trustStorePassword, - boolean crlEnabled, boolean ocspEnabled, - final boolean serverHostnameVerificationEnabled, - final boolean clientHostnameVerificationEnabled) - throws TrustManagerException { - FileInputStream inputStream = null; - try { - File trustStoreFile = new File(trustStoreLocation); - KeyStore ts = KeyStore.getInstance("JKS"); - inputStream = new FileInputStream(trustStoreFile); - if (trustStorePassword != null) { - char[] trustStorePasswordChars = trustStorePassword.toCharArray(); - ts.load(inputStream, trustStorePasswordChars); - } else { - ts.load(inputStream, null); - } - - 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); - } - - // Revocation checking is only supported with the PKIX algorithm - TrustManagerFactory tmf = TrustManagerFactory.getInstance("PKIX"); - tmf.init(new CertPathTrustManagerParameters(pbParams)); - - for (final TrustManager tm : tmf.getTrustManagers()) { - if (tm instanceof X509ExtendedTrustManager) { - return new ZKTrustManager((X509ExtendedTrustManager) tm, - serverHostnameVerificationEnabled, clientHostnameVerificationEnabled); - } - } - throw new TrustManagerException("Couldn't find X509TrustManager"); - } catch (IOException|CertificateException|NoSuchAlgorithmException|InvalidAlgorithmParameterException|KeyStoreException - trustManagerCreationException) { - throw new TrustManagerException(trustManagerCreationException); - } finally { - if (inputStream != null) { - try { - inputStream.close(); - } catch (IOException ioException) { - LOG.info("failed to close TrustStore input stream", ioException); - } - } - } - } - - public SSLSocket createSSLSocket() throws X509Exception, IOException { - SSLSocket sslSocket = (SSLSocket) getDefaultSSLContext().getSocketFactory().createSocket(); - configureSSLSocket(sslSocket); - - return sslSocket; - } - - public SSLSocket createSSLSocket(Socket socket) throws X509Exception, IOException { - SSLSocket sslSocket = (SSLSocket) getDefaultSSLContext().getSocketFactory().createSocket(socket, null, socket.getPort(), true); - configureSSLSocket(sslSocket); - - return sslSocket; - } - - private void configureSSLSocket(SSLSocket sslSocket) { - SSLParameters sslParameters = sslSocket.getSSLParameters(); - LOG.debug("Setup cipher suites for client socket: {}", Arrays.toString(cipherSuites)); - sslParameters.setCipherSuites(cipherSuites); - sslSocket.setSSLParameters(sslParameters); - } - - public SSLServerSocket createSSLServerSocket() throws X509Exception, IOException { - SSLServerSocket sslServerSocket = (SSLServerSocket) getDefaultSSLContext().getServerSocketFactory().createServerSocket(); - configureSSLServerSocket(sslServerSocket); - - return sslServerSocket; - } - - public SSLServerSocket createSSLServerSocket(int port) throws X509Exception, IOException { - SSLServerSocket sslServerSocket = (SSLServerSocket) getDefaultSSLContext().getServerSocketFactory().createServerSocket(port); - configureSSLServerSocket(sslServerSocket); - - return sslServerSocket; - } - - private void configureSSLServerSocket(SSLServerSocket sslServerSocket) { - SSLParameters sslParameters = sslServerSocket.getSSLParameters(); - sslParameters.setNeedClientAuth(true); - LOG.debug("Setup cipher suites for server socket: {}", Arrays.toString(cipherSuites)); - sslParameters.setCipherSuites(cipherSuites); - sslServerSocket.setSSLParameters(sslParameters); - } - - private String[] getDefaultCipherSuites() { - String javaVersion = System.getProperty("java.specification.version"); - if ("9".equals(javaVersion)) { - LOG.debug("Using Java9-optimized cipher suites for Java version {}", javaVersion); - return DEFAULT_CIPHERS_JAVA9; - } - LOG.debug("Using Java8-optimized cipher suites for Java version {}", javaVersion); - return DEFAULT_CIPHERS_JAVA8; - } -} http://git-wip-us.apache.org/repos/asf/zookeeper/blob/43d71c2e/zookeeper-common/src/main/java/org/apache/zookeeper/common/ZKConfig.java ---------------------------------------------------------------------- diff --git a/zookeeper-common/src/main/java/org/apache/zookeeper/common/ZKConfig.java b/zookeeper-common/src/main/java/org/apache/zookeeper/common/ZKConfig.java deleted file mode 100644 index dc24b19..0000000 --- a/zookeeper-common/src/main/java/org/apache/zookeeper/common/ZKConfig.java +++ /dev/null @@ -1,280 +0,0 @@ -/** - * Licensed to the Apache Software Foundation (ASF) under one - * or more contributor license agreements. See the NOTICE file - * distributed with this work for additional information - * regarding copyright ownership. The ASF licenses this file - * to you under the Apache License, Version 2.0 (the - * "License"); you may not use this file except in compliance - * with the License. You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -package org.apache.zookeeper.common; - -import java.io.File; -import java.io.FileInputStream; -import java.io.IOException; -import java.util.HashMap; -import java.util.Map; -import java.util.Map.Entry; -import java.util.Properties; - -import org.apache.zookeeper.Environment; -import org.apache.zookeeper.server.quorum.QuorumPeerConfig.ConfigException; -import org.apache.zookeeper.server.util.VerifyingFileFactory; -import org.slf4j.Logger; -import org.slf4j.LoggerFactory; - -/** - * This class is a base class for the configurations of both client and server. - * It supports reading client configuration from both system properties and - * configuration file. A user can override any system property by calling - * {@link #setProperty(String, String)}. - * @since 3.5.2 - */ -public class ZKConfig { - - private static final Logger LOG = LoggerFactory.getLogger(ZKConfig.class); - - public static final String JUTE_MAXBUFFER = "jute.maxbuffer"; - - /** - * Path to a kinit binary: {@value}. Defaults to - * <code>"/usr/bin/kinit"</code> - */ - public static final String KINIT_COMMAND = "zookeeper.kinit"; - public static final String JGSS_NATIVE = "sun.security.jgss.native"; - - private final Map<String, String> properties = new HashMap<String, String>(); - - /** - * properties, which are common to both client and server, are initialized - * from system properties - */ - public ZKConfig() { - init(); - } - - /** - * @param configPath - * Configuration file path - * @throws ConfigException - * if failed to load configuration properties - */ - - public ZKConfig(String configPath) throws ConfigException { - this(new File(configPath)); - } - - /** - * - * @param configFile - * Configuration file - * @throws ConfigException - * if failed to load configuration properties - */ - public ZKConfig(File configFile) throws ConfigException { - this(); - addConfiguration(configFile); - } - - private void init() { - /** - * backward compatibility for all currently available client properties - */ - handleBackwardCompatibility(); - } - - /** - * Now onwards client code will use properties from this class but older - * clients still be setting properties through system properties. So to make - * this change backward compatible we should set old system properties in - * this configuration. - */ - protected void handleBackwardCompatibility() { - properties.put(JUTE_MAXBUFFER, System.getProperty(JUTE_MAXBUFFER)); - properties.put(KINIT_COMMAND, System.getProperty(KINIT_COMMAND)); - properties.put(JGSS_NATIVE, System.getProperty(JGSS_NATIVE)); - - ClientX509Util clientX509Util = new ClientX509Util(); - putSSLProperties(clientX509Util); - properties.put(clientX509Util.getSslAuthProviderProperty(), - System.getProperty(clientX509Util.getSslAuthProviderProperty())); - - putSSLProperties(new QuorumX509Util()); - } - - private void putSSLProperties(X509Util x509Util) { - properties.put(x509Util.getSslKeystoreLocationProperty(), - System.getProperty(x509Util.getSslKeystoreLocationProperty())); - properties.put(x509Util.getSslKeystorePasswdProperty(), - System.getProperty(x509Util.getSslKeystorePasswdProperty())); - properties.put(x509Util.getSslTruststoreLocationProperty(), - System.getProperty(x509Util.getSslTruststoreLocationProperty())); - properties.put(x509Util.getSslTruststorePasswdProperty(), - System.getProperty(x509Util.getSslTruststorePasswdProperty())); - properties.put(x509Util.getSslHostnameVerificationEnabledProperty(), - System.getProperty(x509Util.getSslHostnameVerificationEnabledProperty())); - properties.put(x509Util.getSslCrlEnabledProperty(), - System.getProperty(x509Util.getSslCrlEnabledProperty())); - properties.put(x509Util.getSslOcspEnabledProperty(), - System.getProperty(x509Util.getSslOcspEnabledProperty())); - } - - /** - * Get the property value - * - * @param key - * @return property value - */ - public String getProperty(String key) { - return properties.get(key); - } - - /** - * Get the property value, if it is null return default value - * - * @param key - * property key - * @param defaultValue - * @return property value or default value - */ - public String getProperty(String key, String defaultValue) { - String value = properties.get(key); - return (value == null) ? defaultValue : value; - } - - /** - * Return the value of "java.security.auth.login.config" system property - * - * @return value - */ - public String getJaasConfKey() { - return System.getProperty(Environment.JAAS_CONF_KEY); - } - - /** - * Maps the specified <code>key</code> to the specified <code>value</code>. - * key can not be <code>null</code>. If key is already mapped then the old - * value of the <code>key</code> is replaced by the specified - * <code>value</code>. - * - * @param key - * @param value - */ - public void setProperty(String key, String value) { - if (null == key) { - throw new IllegalArgumentException("property key is null."); - } - String oldValue = properties.put(key, value); - if (LOG.isDebugEnabled()) { - if (null != oldValue && !oldValue.equals(value)) { - LOG.debug("key {}'s value {} is replaced with new value {}", key, oldValue, value); - } - } - } - - /** - * Add a configuration resource. The properties form this configuration will - * overwrite corresponding already loaded property and system property - * - * @param configFile - * Configuration file. - */ - public void addConfiguration(File configFile) throws ConfigException { - LOG.info("Reading configuration from: {}", configFile.getAbsolutePath()); - try { - configFile = (new VerifyingFileFactory.Builder(LOG).warnForRelativePath().failForNonExistingPath().build()) - .validate(configFile); - Properties cfg = new Properties(); - FileInputStream in = new FileInputStream(configFile); - try { - cfg.load(in); - } finally { - in.close(); - } - parseProperties(cfg); - } catch (IOException | IllegalArgumentException e) { - LOG.error("Error while configuration from: {}", configFile.getAbsolutePath(), e); - throw new ConfigException("Error while processing " + configFile.getAbsolutePath(), e); - } - } - - /** - * Add a configuration resource. The properties form this configuration will - * overwrite corresponding already loaded property and system property - * - * @param configPath - * Configuration file path. - */ - public void addConfiguration(String configPath) throws ConfigException { - addConfiguration(new File(configPath)); - } - - private void parseProperties(Properties cfg) { - for (Entry<Object, Object> entry : cfg.entrySet()) { - String key = entry.getKey().toString().trim(); - String value = entry.getValue().toString().trim(); - setProperty(key, value); - } - } - - /** - * Returns {@code true} if and only if the property named by the argument - * exists and is equal to the string {@code "true"}. - */ - public boolean getBoolean(String key) { - return getBoolean(key, false); - } - - /** - * Get the value of the <code>key</code> property as a <code>boolean</code>. Returns - * {@code true} if and only if the property named by the argument exists and is equal - * to the string {@code "true"}. If the property is not set, the provided - * <code>defaultValue</code> is returned. - * - * @param key - * property key. - * @param defaultValue - * default value. - * @return return property value as an <code>boolean</code>, or - * <code>defaultValue</code> - */ - public boolean getBoolean(String key, boolean defaultValue) { - String propertyValue = getProperty(key); - if (propertyValue == null) { - return defaultValue; - } else { - return Boolean.parseBoolean(propertyValue); - } - } - - /** - * Get the value of the <code>key</code> property as an <code>int</code>. If - * property is not set, the provided <code>defaultValue</code> is returned - * - * @param key - * property key. - * @param defaultValue - * default value. - * @throws NumberFormatException - * when the value is invalid - * @return return property value as an <code>int</code>, or - * <code>defaultValue</code> - */ - public int getInt(String key, int defaultValue) { - String value = getProperty(key); - if (value != null) { - return Integer.parseInt(value.trim()); - } - return defaultValue; - } - -} http://git-wip-us.apache.org/repos/asf/zookeeper/blob/43d71c2e/zookeeper-common/src/main/java/org/apache/zookeeper/common/ZKHostnameVerifier.java ---------------------------------------------------------------------- diff --git a/zookeeper-common/src/main/java/org/apache/zookeeper/common/ZKHostnameVerifier.java b/zookeeper-common/src/main/java/org/apache/zookeeper/common/ZKHostnameVerifier.java deleted file mode 100644 index 740fef0..0000000 --- a/zookeeper-common/src/main/java/org/apache/zookeeper/common/ZKHostnameVerifier.java +++ /dev/null @@ -1,349 +0,0 @@ -/** - * Licensed to the Apache Software Foundation (ASF) under one - * or more contributor license agreements. See the NOTICE file - * distributed with this work for additional information - * regarding copyright ownership. The ASF licenses this file - * to you under the Apache License, Version 2.0 (the - * "License"); you may not use this file except in compliance - * with the License. You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -package org.apache.zookeeper.common; - -import org.slf4j.Logger; -import org.slf4j.LoggerFactory; - -import javax.naming.InvalidNameException; -import javax.naming.NamingException; -import javax.naming.directory.Attribute; -import javax.naming.directory.Attributes; -import javax.naming.ldap.LdapName; -import javax.naming.ldap.Rdn; -import javax.net.ssl.HostnameVerifier; -import javax.net.ssl.SSLException; -import javax.net.ssl.SSLPeerUnverifiedException; -import javax.net.ssl.SSLSession; -import javax.security.auth.x500.X500Principal; -import java.net.InetAddress; -import java.net.UnknownHostException; -import java.security.cert.Certificate; -import java.security.cert.CertificateParsingException; -import java.security.cert.X509Certificate; -import java.util.ArrayList; -import java.util.Collection; -import java.util.Collections; -import java.util.List; -import java.util.Locale; -import java.util.NoSuchElementException; -import java.util.Objects; -import java.util.regex.Pattern; - -/** - * Note: copied from Apache httpclient with some modifications. We want host verification, but depending - * on the httpclient jar caused unexplained performance regressions (even when the code was not used). - */ -final class ZKHostnameVerifier implements HostnameVerifier { - - /** - * Note: copied from Apache httpclient with some minor modifications. We want host verification, but depending - * on the httpclient jar caused unexplained performance regressions (even when the code was not used). - */ - private static final class SubjectName { - static final int DNS = 2; - static final int IP = 7; - - private final String value; - private final int type; - - static SubjectName IP(final String value) { - return new SubjectName(value, IP); - } - - static SubjectName DNS(final String value) { - return new SubjectName(value, DNS); - } - - SubjectName(final String value, final int type) { - if (type != DNS && type != IP) { - throw new IllegalArgumentException("Invalid type: " + type); - } - this.value = Objects.requireNonNull(value); - this.type = type; - } - - public int getType() { - return type; - } - - public String getValue() { - return value; - } - - @Override - public String toString() { - return value; - } - } - - /** - * Note: copied from Apache httpclient. We want host verification, but depending on the - * httpclient jar caused unexplained performance regressions (even when the code was not used). - */ - private static class InetAddressUtils { - private InetAddressUtils() {} - - private static final Pattern IPV4_PATTERN = Pattern.compile( - "^(25[0-5]|2[0-4]\\d|[0-1]?\\d?\\d)(\\.(25[0-5]|2[0-4]\\d|[0-1]?\\d?\\d)){3}$"); - - private static final Pattern IPV6_STD_PATTERN = Pattern.compile( - "^(?:[0-9a-fA-F]{1,4}:){7}[0-9a-fA-F]{1,4}$"); - - private static final Pattern IPV6_HEX_COMPRESSED_PATTERN = Pattern.compile( - "^((?:[0-9A-Fa-f]{1,4}(?::[0-9A-Fa-f]{1,4})*)?)::((?:[0-9A-Fa-f]{1,4}(?::[0-9A-Fa-f]{1,4})*)?)$"); - - static boolean isIPv4Address(final String input) { - return IPV4_PATTERN.matcher(input).matches(); - } - - static boolean isIPv6StdAddress(final String input) { - return IPV6_STD_PATTERN.matcher(input).matches(); - } - - static boolean isIPv6HexCompressedAddress(final String input) { - return IPV6_HEX_COMPRESSED_PATTERN.matcher(input).matches(); - } - - static boolean isIPv6Address(final String input) { - return isIPv6StdAddress(input) || isIPv6HexCompressedAddress(input); - } - } - - enum HostNameType { - - IPv4(7), IPv6(7), DNS(2); - - final int subjectType; - - HostNameType(final int subjectType) { - this.subjectType = subjectType; - } - - } - - private final Logger log = LoggerFactory.getLogger(ZKHostnameVerifier.class); - - @Override - public boolean verify(final String host, final SSLSession session) { - try { - final Certificate[] certs = session.getPeerCertificates(); - final X509Certificate x509 = (X509Certificate) certs[0]; - verify(host, x509); - return true; - } catch (final SSLException ex) { - if (log.isDebugEnabled()) { - log.debug(ex.getMessage(), ex); - } - return false; - } - } - - void verify(final String host, final X509Certificate cert) throws SSLException { - final HostNameType hostType = determineHostFormat(host); - final List<SubjectName> subjectAlts = getSubjectAltNames(cert); - if (subjectAlts != null && !subjectAlts.isEmpty()) { - switch (hostType) { - case IPv4: - matchIPAddress(host, subjectAlts); - break; - case IPv6: - matchIPv6Address(host, subjectAlts); - break; - default: - matchDNSName(host, subjectAlts); - } - } else { - // CN matching has been deprecated by rfc2818 and can be used - // as fallback only when no subjectAlts are available - final X500Principal subjectPrincipal = cert.getSubjectX500Principal(); - final String cn = extractCN(subjectPrincipal.getName(X500Principal.RFC2253)); - if (cn == null) { - throw new SSLException("Certificate subject for <" + host + "> doesn't contain " + - "a common name and does not have alternative names"); - } - matchCN(host, cn); - } - } - - private static void matchIPAddress(final String host, final List<SubjectName> subjectAlts) throws SSLException { - for (int i = 0; i < subjectAlts.size(); i++) { - final SubjectName subjectAlt = subjectAlts.get(i); - if (subjectAlt.getType() == SubjectName.IP) { - if (host.equals(subjectAlt.getValue())) { - return; - } - } - } - throw new SSLPeerUnverifiedException("Certificate for <" + host + "> doesn't match any " + - "of the subject alternative names: " + subjectAlts); - } - - private static void matchIPv6Address(final String host, final List<SubjectName> subjectAlts) throws SSLException { - final String normalisedHost = normaliseAddress(host); - for (int i = 0; i < subjectAlts.size(); i++) { - final SubjectName subjectAlt = subjectAlts.get(i); - if (subjectAlt.getType() == SubjectName.IP) { - final String normalizedSubjectAlt = normaliseAddress(subjectAlt.getValue()); - if (normalisedHost.equals(normalizedSubjectAlt)) { - return; - } - } - } - throw new SSLPeerUnverifiedException("Certificate for <" + host + "> doesn't match any " + - "of the subject alternative names: " + subjectAlts); - } - - private static void matchDNSName(final String host, final List<SubjectName> subjectAlts) throws SSLException { - final String normalizedHost = host.toLowerCase(Locale.ROOT); - for (int i = 0; i < subjectAlts.size(); i++) { - final SubjectName subjectAlt = subjectAlts.get(i); - if (subjectAlt.getType() == SubjectName.DNS) { - final String normalizedSubjectAlt = subjectAlt.getValue().toLowerCase(Locale.ROOT); - if (matchIdentityStrict(normalizedHost, normalizedSubjectAlt)) { - return; - } - } - } - throw new SSLPeerUnverifiedException("Certificate for <" + host + "> doesn't match any " + - "of the subject alternative names: " + subjectAlts); - } - - private static void matchCN(final String host, final String cn) throws SSLException { - final String normalizedHost = host.toLowerCase(Locale.ROOT); - final String normalizedCn = cn.toLowerCase(Locale.ROOT); - if (!matchIdentityStrict(normalizedHost, normalizedCn)) { - throw new SSLPeerUnverifiedException("Certificate for <" + host + "> doesn't match " + - "common name of the certificate subject: " + cn); - } - } - - private static boolean matchIdentity(final String host, final String identity, - final boolean strict) { - // RFC 2818, 3.1. Server Identity - // "...Names may contain the wildcard - // character * which is considered to match any single domain name - // component or component fragment..." - // Based on this statement presuming only singular wildcard is legal - final int asteriskIdx = identity.indexOf('*'); - if (asteriskIdx != -1) { - final String prefix = identity.substring(0, asteriskIdx); - final String suffix = identity.substring(asteriskIdx + 1); - if (!prefix.isEmpty() && !host.startsWith(prefix)) { - return false; - } - if (!suffix.isEmpty() && !host.endsWith(suffix)) { - return false; - } - // Additional sanity checks on content selected by wildcard can be done here - if (strict) { - final String remainder = host.substring( - prefix.length(), host.length() - suffix.length()); - if (remainder.contains(".")) { - return false; - } - } - return true; - } - return host.equalsIgnoreCase(identity); - } - - private static boolean matchIdentityStrict(final String host, final String identity) { - return matchIdentity(host, identity, true); - } - - private static String extractCN(final String subjectPrincipal) throws SSLException { - if (subjectPrincipal == null) { - return null; - } - try { - final LdapName subjectDN = new LdapName(subjectPrincipal); - final List<Rdn> rdns = subjectDN.getRdns(); - for (int i = rdns.size() - 1; i >= 0; i--) { - final Rdn rds = rdns.get(i); - final Attributes attributes = rds.toAttributes(); - final Attribute cn = attributes.get("cn"); - if (cn != null) { - try { - final Object value = cn.get(); - if (value != null) { - return value.toString(); - } - } catch (final NoSuchElementException ignore) { - // ignore exception - } catch (final NamingException ignore) { - // ignore exception - } - } - } - return null; - } catch (final InvalidNameException e) { - throw new SSLException(subjectPrincipal + " is not a valid X500 distinguished name"); - } - } - - private static HostNameType determineHostFormat(final String host) { - if (InetAddressUtils.isIPv4Address(host)) { - return HostNameType.IPv4; - } - String s = host; - if (s.startsWith("[") && s.endsWith("]")) { - s = host.substring(1, host.length() - 1); - } - if (InetAddressUtils.isIPv6Address(s)) { - return HostNameType.IPv6; - } - return HostNameType.DNS; - } - - private static List<SubjectName> getSubjectAltNames(final X509Certificate cert) { - try { - final Collection<List<?>> entries = cert.getSubjectAlternativeNames(); - if (entries == null) { - return Collections.emptyList(); - } - final List<SubjectName> result = new ArrayList<SubjectName>(); - for (List<?> entry: entries) { - final Integer type = entry.size() >= 2 ? (Integer) entry.get(0) : null; - if (type != null) { - final String s = (String) entry.get(1); - result.add(new SubjectName(s, type)); - } - } - return result; - } catch (final CertificateParsingException ignore) { - return Collections.emptyList(); - } - } - - /* - * Normalize IPv6 or DNS name. - */ - private static String normaliseAddress(final String hostname) { - if (hostname == null) { - return hostname; - } - try { - final InetAddress inetAddress = InetAddress.getByName(hostname); - return inetAddress.getHostAddress(); - } catch (final UnknownHostException unexpected) { // Should not happen, because we check for IPv6 address above - return hostname; - } - } -} http://git-wip-us.apache.org/repos/asf/zookeeper/blob/43d71c2e/zookeeper-common/src/main/java/org/apache/zookeeper/common/ZKTrustManager.java ---------------------------------------------------------------------- diff --git a/zookeeper-common/src/main/java/org/apache/zookeeper/common/ZKTrustManager.java b/zookeeper-common/src/main/java/org/apache/zookeeper/common/ZKTrustManager.java deleted file mode 100644 index 73006d0..0000000 --- a/zookeeper-common/src/main/java/org/apache/zookeeper/common/ZKTrustManager.java +++ /dev/null @@ -1,150 +0,0 @@ -/** - * Licensed to the Apache Software Foundation (ASF) under one - * or more contributor license agreements. See the NOTICE file - * distributed with this work for additional information - * regarding copyright ownership. The ASF licenses this file - * to you under the Apache License, Version 2.0 (the - * "License"); you may not use this file except in compliance - * with the License. You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ -package org.apache.zookeeper.common; - -import org.slf4j.Logger; -import org.slf4j.LoggerFactory; - -import javax.net.ssl.SSLEngine; -import javax.net.ssl.SSLException; -import javax.net.ssl.X509ExtendedTrustManager; -import java.net.InetAddress; -import java.net.Socket; -import java.net.UnknownHostException; -import java.security.cert.CertificateException; -import java.security.cert.X509Certificate; - -/** - * A custom TrustManager that supports hostname verification via org.apache.http.conn.ssl.DefaultHostnameVerifier. - * - * We attempt to perform verification using just the IP address first and if that fails will attempt to perform a - * reverse DNS lookup and verify using the hostname. - */ -public class ZKTrustManager extends X509ExtendedTrustManager { - - private static final Logger LOG = LoggerFactory.getLogger(ZKTrustManager.class); - - private X509ExtendedTrustManager x509ExtendedTrustManager; - private boolean serverHostnameVerificationEnabled; - private boolean clientHostnameVerificationEnabled; - - private ZKHostnameVerifier hostnameVerifier; - - /** - * Instantiate a new ZKTrustManager. - * - * @param x509ExtendedTrustManager The trustmanager to use for checkClientTrusted/checkServerTrusted logic - * @param serverHostnameVerificationEnabled If true, this TrustManager should verify hostnames of servers that this - * instance connects to. - * @param clientHostnameVerificationEnabled If true, the hostname of a client connecting to this machine will be - * verified. - */ - ZKTrustManager(X509ExtendedTrustManager x509ExtendedTrustManager, boolean serverHostnameVerificationEnabled, - boolean clientHostnameVerificationEnabled) { - this.x509ExtendedTrustManager = x509ExtendedTrustManager; - this.serverHostnameVerificationEnabled = serverHostnameVerificationEnabled; - this.clientHostnameVerificationEnabled = clientHostnameVerificationEnabled; - hostnameVerifier = new ZKHostnameVerifier(); - } - - @Override - public X509Certificate[] getAcceptedIssuers() { - return x509ExtendedTrustManager.getAcceptedIssuers(); - } - - @Override - public void checkClientTrusted(X509Certificate[] chain, String authType, Socket socket) throws CertificateException { - x509ExtendedTrustManager.checkClientTrusted(chain, authType, socket); - if (clientHostnameVerificationEnabled) { - performHostVerification(socket.getInetAddress(), chain[0]); - } - } - - @Override - public void checkServerTrusted(X509Certificate[] chain, String authType, Socket socket) throws CertificateException { - x509ExtendedTrustManager.checkServerTrusted(chain, authType, socket); - if (serverHostnameVerificationEnabled) { - performHostVerification(socket.getInetAddress(), chain[0]); - } - } - - @Override - public void checkClientTrusted(X509Certificate[] chain, String authType, SSLEngine engine) throws CertificateException { - x509ExtendedTrustManager.checkServerTrusted(chain, authType, engine); - if (clientHostnameVerificationEnabled) { - try { - performHostVerification(InetAddress.getByName(engine.getPeerHost()), chain[0]); - } catch (UnknownHostException e) { - throw new CertificateException("Failed to verify host", e); - } - } - } - - @Override - public void checkServerTrusted(X509Certificate[] chain, String authType, SSLEngine engine) - throws CertificateException { - x509ExtendedTrustManager.checkServerTrusted(chain, authType, engine); - if (serverHostnameVerificationEnabled) { - try { - performHostVerification(InetAddress.getByName(engine.getPeerHost()), chain[0]); - } catch (UnknownHostException e) { - throw new CertificateException("Failed to verify host", e); - } - } - } - - @Override - public void checkClientTrusted(X509Certificate[] chain, String authType) throws CertificateException { - x509ExtendedTrustManager.checkClientTrusted(chain, authType); - } - - @Override - public void checkServerTrusted(X509Certificate[] chain, String authType) throws CertificateException { - x509ExtendedTrustManager.checkServerTrusted(chain, authType); - } - - /** - * Compares peer's hostname with the one stored in the provided client certificate. Performs verification - * with the help of provided HostnameVerifier. - * - * @param inetAddress Peer's inet address. - * @param certificate Peer's certificate - * @throws CertificateException Thrown if the provided certificate doesn't match the peer hostname. - */ - private void performHostVerification(InetAddress inetAddress, X509Certificate certificate) - throws CertificateException { - String hostAddress = ""; - String hostName = ""; - try { - hostAddress = inetAddress.getHostAddress(); - hostnameVerifier.verify(hostAddress, certificate); - } catch (SSLException addressVerificationException) { - try { - LOG.debug("Failed to verify host address: {} attempting to verify host name with reverse dns lookup", - hostAddress, addressVerificationException); - hostName = inetAddress.getHostName(); - hostnameVerifier.verify(hostName, certificate); - } catch (SSLException hostnameVerificationException) { - LOG.error("Failed to verify host address: {}", hostAddress, addressVerificationException); - LOG.error("Failed to verify hostname: {}", hostName, hostnameVerificationException); - throw new CertificateException("Failed to verify both host address and host name", - hostnameVerificationException); - } - } - } -} http://git-wip-us.apache.org/repos/asf/zookeeper/blob/43d71c2e/zookeeper-common/src/main/java/org/apache/zookeeper/util/SecurityUtils.java ---------------------------------------------------------------------- diff --git a/zookeeper-common/src/main/java/org/apache/zookeeper/util/SecurityUtils.java b/zookeeper-common/src/main/java/org/apache/zookeeper/util/SecurityUtils.java deleted file mode 100644 index 67484e4..0000000 --- a/zookeeper-common/src/main/java/org/apache/zookeeper/util/SecurityUtils.java +++ /dev/null @@ -1,298 +0,0 @@ -/** - * Licensed to the Apache Software Foundation (ASF) under one - * or more contributor license agreements. See the NOTICE file - * distributed with this work for additional information - * regarding copyright ownership. The ASF licenses this file - * to you under the Apache License, Version 2.0 (the - * "License"); you may not use this file except in compliance - * with the License. You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -package org.apache.zookeeper.util; - -import java.security.Principal; -import java.security.PrivilegedActionException; -import java.security.PrivilegedExceptionAction; - -import javax.security.auth.Subject; -import javax.security.auth.callback.CallbackHandler; -import javax.security.sasl.Sasl; -import javax.security.sasl.SaslClient; -import javax.security.sasl.SaslException; -import javax.security.sasl.SaslServer; - -import org.apache.zookeeper.SaslClientCallbackHandler; -import org.apache.zookeeper.server.auth.KerberosName; -import org.ietf.jgss.GSSContext; -import org.ietf.jgss.GSSCredential; -import org.ietf.jgss.GSSException; -import org.ietf.jgss.GSSManager; -import org.ietf.jgss.GSSName; -import org.ietf.jgss.Oid; -import org.slf4j.Logger; - -public final class SecurityUtils { - - public static final String QUORUM_HOSTNAME_PATTERN = "_HOST"; - - /** - * Create an instance of a SaslClient. It will return null if there is an exception. - * - * @param subject subject - * @param servicePrincipal principal - * @param protocol name of the protocol for which the authentication is being performed - * @param serverName name of the server to authenticate to - * @param LOG logger - * @param entity can be either zookeeper client or quorum learner - * - * @return saslclient object - * @throws SaslException - */ - public static SaslClient createSaslClient(final Subject subject, - final String servicePrincipal, final String protocol, - final String serverName, final Logger LOG, final String entity) throws SaslException { - SaslClient saslClient; - // Use subject.getPrincipals().isEmpty() as an indication of which SASL - // mechanism to use: if empty, use DIGEST-MD5; otherwise, use GSSAPI. - if (subject.getPrincipals().isEmpty()) { - // no principals: must not be GSSAPI: use DIGEST-MD5 mechanism - // instead. - LOG.info("{} will use DIGEST-MD5 as SASL mechanism.", entity); - String[] mechs = { "DIGEST-MD5" }; - String username = (String) (subject.getPublicCredentials() - .toArray()[0]); - String password = (String) (subject.getPrivateCredentials() - .toArray()[0]); - // 'domain' parameter is hard-wired between the server and client - saslClient = Sasl.createSaslClient(mechs, username, protocol, - serverName, null, new SaslClientCallbackHandler(password, entity)); - return saslClient; - } else { // GSSAPI. - final Object[] principals = subject.getPrincipals().toArray(); - // determine client principal from subject. - final Principal clientPrincipal = (Principal) principals[0]; - boolean usingNativeJgss = Boolean - .getBoolean("sun.security.jgss.native"); - if (usingNativeJgss) { - // http://docs.oracle.com/javase/6/docs/technotes/guides/security/jgss/jgss-features.html - // """ - // In addition, when performing operations as a particular - // Subject, e.g. Subject.doAs(...) or - // Subject.doAsPrivileged(...), - // the to-be-used GSSCredential should be added to Subject's - // private credential set. Otherwise, the GSS operations will - // fail since no credential is found. - // """ - try { - GSSManager manager = GSSManager.getInstance(); - Oid krb5Mechanism = new Oid("1.2.840.113554.1.2.2"); - GSSCredential cred = manager.createCredential(null, - GSSContext.DEFAULT_LIFETIME, krb5Mechanism, - GSSCredential.INITIATE_ONLY); - subject.getPrivateCredentials().add(cred); - LOG.debug("Added private credential to {} principal name: '{}'", - entity, clientPrincipal); - } catch (GSSException ex) { - LOG.warn("Cannot add private credential to subject; " - + "authentication at the server may fail", ex); - } - } - final KerberosName clientKerberosName = new KerberosName( - clientPrincipal.getName()); - // assume that server and client are in the same realm (by default; - // unless the system property - // "zookeeper.server.realm" is set). - String serverRealm = System.getProperty("zookeeper.server.realm", - clientKerberosName.getRealm()); - KerberosName serviceKerberosName = new KerberosName( - servicePrincipal + "@" + serverRealm); - final String serviceName = serviceKerberosName.getServiceName(); - final String serviceHostname = serviceKerberosName.getHostName(); - final String clientPrincipalName = clientKerberosName.toString(); - try { - saslClient = Subject.doAs(subject, - new PrivilegedExceptionAction<SaslClient>() { - public SaslClient run() throws SaslException { - LOG.info("{} will use GSSAPI as SASL mechanism.", entity); - String[] mechs = { "GSSAPI" }; - LOG.debug("creating sasl client: {}={};service={};serviceHostname={}", - new Object[] { entity, clientPrincipalName, serviceName, serviceHostname }); - SaslClient saslClient = Sasl.createSaslClient( - mechs, clientPrincipalName, serviceName, - serviceHostname, null, - new SaslClientCallbackHandler(null, entity)); - return saslClient; - } - }); - return saslClient; - } catch (Exception e) { - LOG.error("Exception while trying to create SASL client", e); - return null; - } - } - } - - /** - * Create an instance of a SaslServer. It will return null if there is an exception. - * - * @param subject subject - * @param protocol protocol - * @param serverName server name - * @param callbackHandler login callback handler - * @param LOG logger - * @return sasl server object - */ - public static SaslServer createSaslServer(final Subject subject, - final String protocol, final String serverName, - final CallbackHandler callbackHandler, final Logger LOG) { - if (subject != null) { - // server is using a JAAS-authenticated subject: determine service - // principal name and hostname from zk server's subject. - if (subject.getPrincipals().size() > 0) { - try { - final Object[] principals = subject.getPrincipals() - .toArray(); - final Principal servicePrincipal = (Principal) principals[0]; - - // e.g. servicePrincipalNameAndHostname := - // "zookeeper/myhost.foo....@foo.com" - final String servicePrincipalNameAndHostname = servicePrincipal - .getName(); - - int indexOf = servicePrincipalNameAndHostname.indexOf("/"); - - // e.g. servicePrincipalName := "zookeeper" - final String servicePrincipalName = servicePrincipalNameAndHostname - .substring(0, indexOf); - - // e.g. serviceHostnameAndKerbDomain := - // "myhost.foo....@foo.com" - final String serviceHostnameAndKerbDomain = servicePrincipalNameAndHostname - .substring(indexOf + 1, - servicePrincipalNameAndHostname.length()); - - indexOf = serviceHostnameAndKerbDomain.indexOf("@"); - // e.g. serviceHostname := "myhost.foo.com" - final String serviceHostname = serviceHostnameAndKerbDomain - .substring(0, indexOf); - - // TODO: should depend on zoo.cfg specified mechs, but if - // subject is non-null, it can be assumed to be GSSAPI. - final String mech = "GSSAPI"; - - LOG.debug("serviceHostname is '" + serviceHostname + "'"); - LOG.debug("servicePrincipalName is '" + servicePrincipalName - + "'"); - LOG.debug("SASL mechanism(mech) is '" + mech + "'"); - - boolean usingNativeJgss = Boolean - .getBoolean("sun.security.jgss.native"); - if (usingNativeJgss) { - // http://docs.oracle.com/javase/6/docs/technotes/guides/security/jgss/jgss-features.html - // """ - // In addition, when performing operations as a - // particular - // Subject, e.g. Subject.doAs(...) or - // Subject.doAsPrivileged(...), the to-be-used - // GSSCredential should be added to Subject's - // private credential set. Otherwise, the GSS operations - // will fail since no credential is found. - // """ - try { - GSSManager manager = GSSManager.getInstance(); - Oid krb5Mechanism = new Oid("1.2.840.113554.1.2.2"); - GSSName gssName = manager.createName( - servicePrincipalName + "@" - + serviceHostname, - GSSName.NT_HOSTBASED_SERVICE); - GSSCredential cred = manager.createCredential( - gssName, GSSContext.DEFAULT_LIFETIME, - krb5Mechanism, GSSCredential.ACCEPT_ONLY); - subject.getPrivateCredentials().add(cred); - LOG.debug("Added private credential to service principal name: '{}'," - + " GSSCredential name: {}", servicePrincipalName, cred.getName()); - } catch (GSSException ex) { - LOG.warn("Cannot add private credential to subject; " - + "clients authentication may fail", ex); - } - } - try { - return Subject.doAs(subject, - new PrivilegedExceptionAction<SaslServer>() { - public SaslServer run() { - try { - SaslServer saslServer; - saslServer = Sasl.createSaslServer( - mech, servicePrincipalName, - serviceHostname, null, - callbackHandler); - return saslServer; - } catch (SaslException e) { - LOG.error("Zookeeper Server failed to create a SaslServer to interact with a client during session initiation: ", e); - return null; - } - } - }); - } catch (PrivilegedActionException e) { - // TODO: exit server at this point(?) - LOG.error("Zookeeper Quorum member experienced a PrivilegedActionException exception while creating a SaslServer using a JAAS principal context:", e); - } - } catch (IndexOutOfBoundsException e) { - LOG.error("server principal name/hostname determination error: ", e); - } - } else { - // JAAS non-GSSAPI authentication: assuming and supporting only - // DIGEST-MD5 mechanism for now. - // TODO: use 'authMech=' value in zoo.cfg. - try { - SaslServer saslServer = Sasl.createSaslServer("DIGEST-MD5", - protocol, serverName, null, callbackHandler); - return saslServer; - } catch (SaslException e) { - LOG.error("Zookeeper Quorum member failed to create a SaslServer to interact with a client during session initiation", e); - } - } - } - return null; - } - - /** - * Convert Kerberos principal name pattern to valid Kerberos principal name. - * If the principal name contains hostname pattern "_HOST" then it replaces - * with the given hostname, which should be fully-qualified domain name. - * - * @param principalConfig - * the Kerberos principal name conf value to convert - * @param hostname - * the fully-qualified domain name used for substitution - * @return converted Kerberos principal name - */ - public static String getServerPrincipal(String principalConfig, - String hostname) { - String[] components = getComponents(principalConfig); - if (components == null || components.length != 2 - || !components[1].equals(QUORUM_HOSTNAME_PATTERN)) { - return principalConfig; - } else { - return replacePattern(components, hostname); - } - } - - private static String[] getComponents(String principalConfig) { - if (principalConfig == null) - return null; - return principalConfig.split("[/]"); - } - - private static String replacePattern(String[] components, String hostname) { - return components[0] + "/" + hostname.toLowerCase(); - } -} http://git-wip-us.apache.org/repos/asf/zookeeper/blob/43d71c2e/zookeeper-common/src/main/java/org/apache/zookeeper/version/util/VerGen.java ---------------------------------------------------------------------- diff --git a/zookeeper-common/src/main/java/org/apache/zookeeper/version/util/VerGen.java b/zookeeper-common/src/main/java/org/apache/zookeeper/version/util/VerGen.java deleted file mode 100644 index 014f01d..0000000 --- a/zookeeper-common/src/main/java/org/apache/zookeeper/version/util/VerGen.java +++ /dev/null @@ -1,167 +0,0 @@ -/** - * Licensed to the Apache Software Foundation (ASF) under one - * or more contributor license agreements. See the NOTICE file - * distributed with this work for additional information - * regarding copyright ownership. The ASF licenses this file - * to you under the Apache License, Version 2.0 (the - * "License"); you may not use this file except in compliance - * with the License. You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -package org.apache.zookeeper.version.util; - -import java.io.File; -import java.io.FileWriter; -import java.io.IOException; -import java.util.regex.Matcher; -import java.util.regex.Pattern; - -public class VerGen { - private static final String PACKAGE_NAME = "org.apache.zookeeper.version"; - private static final String TYPE_NAME = "Info"; - - static void printUsage() { - System.out.print("Usage:\tjava -cp <classpath> org.apache.zookeeper." - + "version.util.VerGen maj.min.micro[-qualifier] rev buildDate"); - System.exit(1); - } - - public static void generateFile(File outputDir, Version version, String rev, String buildDate) - { - String path = PACKAGE_NAME.replaceAll("\\.", "/"); - File pkgdir = new File(outputDir, path); - if (!pkgdir.exists()) { - // create the pkg directory - boolean ret = pkgdir.mkdirs(); - if (!ret) { - System.out.println("Cannnot create directory: " + path); - System.exit(1); - } - } else if (!pkgdir.isDirectory()) { - // not a directory - System.out.println(path + " is not a directory."); - System.exit(1); - } - - try (FileWriter w = new FileWriter(new File(pkgdir, TYPE_NAME + ".java"))) { - w.write("// Do not edit!\n// File generated by org.apache.zookeeper" - + ".version.util.VerGen.\n"); - w.write("/**\n"); - w.write("* Licensed to the Apache Software Foundation (ASF) under one\n"); - w.write("* or more contributor license agreements. See the NOTICE file\n"); - w.write("* distributed with this work for additional information\n"); - w.write("* regarding copyright ownership. The ASF licenses this file\n"); - w.write("* to you under the Apache License, Version 2.0 (the\n"); - w.write("* \"License\"); you may not use this file except in compliance\n"); - w.write("* with the License. You may obtain a copy of the License at\n"); - w.write("*\n"); - w.write("* http://www.apache.org/licenses/LICENSE-2.0\n"); - w.write("*\n"); - w.write("* Unless required by applicable law or agreed to in writing, software\n"); - w.write("* distributed under the License is distributed on an \"AS IS\" BASIS,\n"); - w.write("* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n"); - w.write("* See the License for the specific language governing permissions and\n"); - w.write("* limitations under the License.\n"); - w.write("*/\n"); - w.write("\n"); - w.write("package " + PACKAGE_NAME + ";\n\n"); - w.write("public interface " + TYPE_NAME + " {\n"); - w.write(" int MAJOR=" + version.maj + ";\n"); - w.write(" int MINOR=" + version.min + ";\n"); - w.write(" int MICRO=" + version.micro + ";\n"); - w.write(" String QUALIFIER=" - + (version.qualifier == null ? null : - "\"" + version.qualifier + "\"") - + ";\n"); - if (rev.equals("-1")) { - System.out.println("Unknown REVISION number, using " + rev); - } - w.write(" int REVISION=-1; //TODO: remove as related to SVN VCS\n"); - w.write(" String REVISION_HASH=\"" + rev + "\";\n"); - w.write(" String BUILD_DATE=\"" + buildDate - + "\";\n"); - w.write("}\n"); - } catch (IOException e) { - System.out.println("Unable to generate version.Info file: " - + e.getMessage()); - System.exit(1); - } - } - - public static class Version { - public int maj; - public int min; - public int micro; - public String qualifier; - } - - public static Version parseVersionString(String input) { - Version result = new Version(); - - Pattern p = Pattern.compile("^(\\d+)\\.(\\d+)\\.(\\d+)((\\.\\d+)*)(-(.+))?$"); - Matcher m = p.matcher(input); - - if (!m.matches()) { - return null; - } - result.maj = Integer.parseInt(m.group(1)); - result.min = Integer.parseInt(m.group(2)); - result.micro = Integer.parseInt(m.group(3)); - if (m.groupCount() == 7) { - result.qualifier = m.group(7); - } else { - result.qualifier = null; - } - return result; - } - - /** - * Emits a org.apache.zookeeper.version.Info interface file with version and - * revision information constants set to the values passed in as command - * line parameters. The file is created in the current directory. <br> - * Usage: java org.apache.zookeeper.version.util.VerGen maj.min.micro[-qualifier] - * rev buildDate - * - * @param args - * <ul> - * <li>maj - major version number - * <li>min - minor version number - * <li>micro - minor minor version number - * <li>qualifier - optional qualifier (dash followed by qualifier text) - * <li>rev - current Git revision number - * <li>buildDate - date the build - * </ul> - */ - public static void main(String[] args) { - if (args.length != 3) - printUsage(); - try { - Version version = parseVersionString(args[0]); - if (version == null) { - System.err.println( - "Invalid version number format, must be \"x.y.z(-.*)?\""); - System.exit(1); - } - String rev = args[1]; - if (rev == null || rev.trim().isEmpty()) { - rev = "-1"; - } else { - rev = rev.trim(); - } - generateFile(new File("."), version, rev, args[2]); - } catch (NumberFormatException e) { - System.err.println( - "All version-related parameters must be valid integers!"); - throw e; - } - } - -} http://git-wip-us.apache.org/repos/asf/zookeeper/blob/43d71c2e/zookeeper-common/src/main/resources/lib/cobertura/README.txt ---------------------------------------------------------------------- diff --git a/zookeeper-common/src/main/resources/lib/cobertura/README.txt b/zookeeper-common/src/main/resources/lib/cobertura/README.txt deleted file mode 100644 index f5ba88f..0000000 --- a/zookeeper-common/src/main/resources/lib/cobertura/README.txt +++ /dev/null @@ -1,3 +0,0 @@ -Download the cobertura binary from the following location and unpack it into this directory. Run "cobertura-report" target from build.xml to generate coverage report. - -http://cobertura.sourceforge.net/download.html