zookeeper-commits mailing list archives

Site index · List index
Message view « Date » · « Thread »
Top « Date » · « Thread »
From an...@apache.org
Subject [2/3] zookeeper git commit: ZOOKEEPER-236: SSL Support for Atomic Broadcast protocol (master)
Date Tue, 16 Oct 2018 14:22:13 GMT
http://git-wip-us.apache.org/repos/asf/zookeeper/blob/7b679bc9/zookeeper-common/src/test/java/org/apache/zookeeper/test/SSLAuthTest.java
----------------------------------------------------------------------
diff --git a/zookeeper-common/src/test/java/org/apache/zookeeper/test/SSLAuthTest.java b/zookeeper-common/src/test/java/org/apache/zookeeper/test/SSLAuthTest.java
index 337c8f7..8fd35bc 100644
--- a/zookeeper-common/src/test/java/org/apache/zookeeper/test/SSLAuthTest.java
+++ b/zookeeper-common/src/test/java/org/apache/zookeeper/test/SSLAuthTest.java
@@ -23,7 +23,8 @@ import java.util.concurrent.TimeUnit;
 import org.apache.zookeeper.PortAssignment;
 import org.apache.zookeeper.TestableZooKeeper;
 import org.apache.zookeeper.client.ZKClientConfig;
-import org.apache.zookeeper.common.ZKConfig;
+import org.apache.zookeeper.common.ClientX509Util;
+import org.apache.zookeeper.common.X509Util;
 import org.apache.zookeeper.server.ServerCnxnFactory;
 import org.junit.After;
 import org.junit.Assert;
@@ -31,17 +32,20 @@ import org.junit.Before;
 import org.junit.Test;
 
 public class SSLAuthTest extends ClientBase {
+    
+    private ClientX509Util clientX509Util = new ClientX509Util();
+    
     @Before
     public void setUp() throws Exception {
         String testDataPath = System.getProperty("test.data.dir", "build/test/data");
         System.setProperty(ServerCnxnFactory.ZOOKEEPER_SERVER_CNXN_FACTORY, "org.apache.zookeeper.server.NettyServerCnxnFactory");
         System.setProperty(ZKClientConfig.ZOOKEEPER_CLIENT_CNXN_SOCKET, "org.apache.zookeeper.ClientCnxnSocketNetty");
         System.setProperty(ZKClientConfig.SECURE_CLIENT, "true");
-        System.setProperty(ZKConfig.SSL_AUTHPROVIDER, "x509");
-        System.setProperty(ZKConfig.SSL_KEYSTORE_LOCATION, testDataPath + "/ssl/testKeyStore.jks");
-        System.setProperty(ZKConfig.SSL_KEYSTORE_PASSWD, "testpass");
-        System.setProperty(ZKConfig.SSL_TRUSTSTORE_LOCATION, testDataPath + "/ssl/testTrustStore.jks");
-        System.setProperty(ZKConfig.SSL_TRUSTSTORE_PASSWD, "testpass");
+        System.setProperty(clientX509Util.getSslAuthProviderProperty(), "x509");
+        System.setProperty(clientX509Util.getSslKeystoreLocationProperty(), testDataPath + "/ssl/testKeyStore.jks");
+        System.setProperty(clientX509Util.getSslKeystorePasswdProperty(), "testpass");
+        System.setProperty(clientX509Util.getSslTruststoreLocationProperty(), testDataPath + "/ssl/testTrustStore.jks");
+        System.setProperty(clientX509Util.getSslTruststorePasswdProperty(), "testpass");
         System.setProperty("javax.net.debug", "ssl");
         System.setProperty("zookeeper.authProvider.x509", "org.apache.zookeeper.server.auth.X509AuthenticationProvider");
 
@@ -60,11 +64,11 @@ public class SSLAuthTest extends ClientBase {
         System.clearProperty(ServerCnxnFactory.ZOOKEEPER_SERVER_CNXN_FACTORY);
         System.clearProperty(ZKClientConfig.ZOOKEEPER_CLIENT_CNXN_SOCKET);
         System.clearProperty(ZKClientConfig.SECURE_CLIENT);
-        System.clearProperty(ZKConfig.SSL_AUTHPROVIDER);
-        System.clearProperty(ZKConfig.SSL_KEYSTORE_LOCATION);
-        System.clearProperty(ZKConfig.SSL_KEYSTORE_PASSWD);
-        System.clearProperty(ZKConfig.SSL_TRUSTSTORE_LOCATION);
-        System.clearProperty(ZKConfig.SSL_TRUSTSTORE_PASSWD);
+        System.clearProperty(clientX509Util.getSslAuthProviderProperty());
+        System.clearProperty(clientX509Util.getSslKeystoreLocationProperty());
+        System.clearProperty(clientX509Util.getSslKeystorePasswdProperty());
+        System.clearProperty(clientX509Util.getSslTruststoreLocationProperty());
+        System.clearProperty(clientX509Util.getSslTruststorePasswdProperty());
         System.clearProperty("javax.net.debug");
         System.clearProperty("zookeeper.authProvider.x509");
     }
@@ -74,8 +78,8 @@ public class SSLAuthTest extends ClientBase {
         String testDataPath = System.getProperty("test.data.dir", "build/test/data");
 
         // Replace trusted keys with a valid key that is not trusted by the server
-        System.setProperty(ZKConfig.SSL_KEYSTORE_LOCATION, testDataPath + "/ssl/testUntrustedKeyStore.jks");
-        System.setProperty(ZKConfig.SSL_KEYSTORE_PASSWD, "testpass");
+        System.setProperty(clientX509Util.getSslKeystoreLocationProperty(), testDataPath + "/ssl/testUntrustedKeyStore.jks");
+        System.setProperty(clientX509Util.getSslKeystorePasswdProperty(), "testpass");
 
         CountdownWatcher watcher = new CountdownWatcher();
 
@@ -87,11 +91,11 @@ public class SSLAuthTest extends ClientBase {
 
     @Test
     public void testMisconfiguration() throws Exception {
-        System.clearProperty(ZKConfig.SSL_AUTHPROVIDER);
-        System.clearProperty(ZKConfig.SSL_KEYSTORE_LOCATION);
-        System.clearProperty(ZKConfig.SSL_KEYSTORE_PASSWD);
-        System.clearProperty(ZKConfig.SSL_TRUSTSTORE_LOCATION);
-        System.clearProperty(ZKConfig.SSL_TRUSTSTORE_PASSWD);
+        System.clearProperty(clientX509Util.getSslAuthProviderProperty());
+        System.clearProperty(clientX509Util.getSslKeystoreLocationProperty());
+        System.clearProperty(clientX509Util.getSslKeystorePasswdProperty());
+        System.clearProperty(clientX509Util.getSslTruststoreLocationProperty());
+        System.clearProperty(clientX509Util.getSslTruststorePasswdProperty());
 
         CountdownWatcher watcher = new CountdownWatcher();
         new TestableZooKeeper(hostPort, CONNECTION_TIMEOUT, watcher);

http://git-wip-us.apache.org/repos/asf/zookeeper/blob/7b679bc9/zookeeper-common/src/test/java/org/apache/zookeeper/test/SSLTest.java
----------------------------------------------------------------------
diff --git a/zookeeper-common/src/test/java/org/apache/zookeeper/test/SSLTest.java b/zookeeper-common/src/test/java/org/apache/zookeeper/test/SSLTest.java
deleted file mode 100644
index 16911b7..0000000
--- a/zookeeper-common/src/test/java/org/apache/zookeeper/test/SSLTest.java
+++ /dev/null
@@ -1,130 +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.test;
-
-
-import org.apache.zookeeper.CreateMode;
-import org.apache.zookeeper.PortAssignment;
-import org.apache.zookeeper.ZooDefs;
-import org.apache.zookeeper.ZooKeeper;
-import org.apache.zookeeper.client.ZKClientConfig;
-import org.apache.zookeeper.common.ZKConfig;
-import org.apache.zookeeper.server.ServerCnxnFactory;
-import org.apache.zookeeper.server.quorum.QuorumPeerTestBase;
-import org.junit.After;
-import org.junit.Assert;
-import org.junit.Before;
-import org.junit.Test;
-
-public class SSLTest extends QuorumPeerTestBase {
-
-    @Before
-    public void setup() {
-        String testDataPath = System.getProperty("test.data.dir", "build/test/data");
-        System.setProperty(ServerCnxnFactory.ZOOKEEPER_SERVER_CNXN_FACTORY, "org.apache.zookeeper.server.NettyServerCnxnFactory");
-        System.setProperty(ZKClientConfig.ZOOKEEPER_CLIENT_CNXN_SOCKET, "org.apache.zookeeper.ClientCnxnSocketNetty");
-        System.setProperty(ZKClientConfig.SECURE_CLIENT, "true");
-        System.setProperty(ZKConfig.SSL_KEYSTORE_LOCATION, testDataPath + "/ssl/testKeyStore.jks");
-        System.setProperty(ZKConfig.SSL_KEYSTORE_PASSWD, "testpass");
-        System.setProperty(ZKConfig.SSL_TRUSTSTORE_LOCATION, testDataPath + "/ssl/testTrustStore.jks");
-        System.setProperty(ZKConfig.SSL_TRUSTSTORE_PASSWD, "testpass");
-    }
-
-    @After
-    public void teardown() throws Exception {
-        System.clearProperty(ServerCnxnFactory.ZOOKEEPER_SERVER_CNXN_FACTORY);
-        System.clearProperty(ZKClientConfig.ZOOKEEPER_CLIENT_CNXN_SOCKET);
-        System.clearProperty(ZKClientConfig.SECURE_CLIENT);
-        System.clearProperty(ZKConfig.SSL_KEYSTORE_LOCATION);
-        System.clearProperty(ZKConfig.SSL_KEYSTORE_PASSWD);
-        System.clearProperty(ZKConfig.SSL_TRUSTSTORE_LOCATION);
-        System.clearProperty(ZKConfig.SSL_TRUSTSTORE_PASSWD);
-    }
-
-    /**
-     * This test checks that SSL works in cluster setup of ZK servers, which includes:
-     * 1. setting "secureClientPort" in "zoo.cfg" file.
-     * 2. setting jvm flags for serverCnxn, keystore, truststore.
-     * Finally, a zookeeper client should be able to connect to the secure port and
-     * communicate with server via secure connection.
-     * <p/>
-     * Note that in this test a ZK server has two ports -- clientPort and secureClientPort.
-     */
-    @Test
-    public void testSecureQuorumServer() throws Exception {
-        final int SERVER_COUNT = 3;
-        final int clientPorts[] = new int[SERVER_COUNT];
-        final Integer secureClientPorts[] = new Integer[SERVER_COUNT];
-        StringBuilder sb = new StringBuilder();
-        for (int i = 0; i < SERVER_COUNT; i++) {
-            clientPorts[i] = PortAssignment.unique();
-            secureClientPorts[i] = PortAssignment.unique();
-            String server = String.format("server.%d=localhost:%d:%d:participant;localhost:%d",
-                    i, PortAssignment.unique(), PortAssignment.unique(), clientPorts[i]);
-            sb.append(server + "\n");
-        }
-        String quorumCfg = sb.toString();
-
-
-        MainThread[] mt = new MainThread[SERVER_COUNT];
-        for (int i = 0; i < SERVER_COUNT; i++) {
-            mt[i] = new MainThread(i, quorumCfg, secureClientPorts[i], true);
-            mt[i].start();
-        }
-
-        // Servers have been set up. Now go test if secure connection is successful.
-        for (int i = 0; i < SERVER_COUNT; i++) {
-            Assert.assertTrue("waiting for server " + i + " being up",
-                    ClientBase.waitForServerUp("127.0.0.1:" + clientPorts[i], TIMEOUT));
-
-            ZooKeeper zk = ClientBase.createZKClient("127.0.0.1:" + secureClientPorts[i], TIMEOUT);
-            // Do a simple operation to make sure the connection is fine.
-            zk.create("/test", "".getBytes(), ZooDefs.Ids.OPEN_ACL_UNSAFE, CreateMode.PERSISTENT);
-            zk.delete("/test", -1);
-            zk.close();
-        }
-
-        for (int i = 0; i < mt.length; i++) {
-            mt[i].shutdown();
-        }
-    }
-
-
-    /**
-     * Developers might use standalone mode (which is the default for one server).
-     * This test checks SSL works in standalone mode of ZK server.
-     * <p/>
-     * Note that in this test the Zk server has only secureClientPort
-     */
-    @Test
-    public void testSecureStandaloneServer() throws Exception {
-        Integer secureClientPort = PortAssignment.unique();
-        MainThread mt = new MainThread(MainThread.UNSET_MYID, "", secureClientPort, false);
-        mt.start();
-
-        ZooKeeper zk = ClientBase.createZKClient("127.0.0.1:" + secureClientPort, TIMEOUT);
-        zk.create("/test", "".getBytes(), ZooDefs.Ids.OPEN_ACL_UNSAFE, CreateMode.PERSISTENT);
-        zk.delete("/test", -1);
-        zk.close();
-        mt.shutdown();
-    }
-}

http://git-wip-us.apache.org/repos/asf/zookeeper/blob/7b679bc9/zookeeper-common/src/test/java/org/apache/zookeeper/test/SSLTest.java.orig
----------------------------------------------------------------------
diff --git a/zookeeper-common/src/test/java/org/apache/zookeeper/test/SSLTest.java.orig b/zookeeper-common/src/test/java/org/apache/zookeeper/test/SSLTest.java.orig
new file mode 100644
index 0000000..16911b7
--- /dev/null
+++ b/zookeeper-common/src/test/java/org/apache/zookeeper/test/SSLTest.java.orig
@@ -0,0 +1,130 @@
+/**
+ * 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.test;
+
+
+import org.apache.zookeeper.CreateMode;
+import org.apache.zookeeper.PortAssignment;
+import org.apache.zookeeper.ZooDefs;
+import org.apache.zookeeper.ZooKeeper;
+import org.apache.zookeeper.client.ZKClientConfig;
+import org.apache.zookeeper.common.ZKConfig;
+import org.apache.zookeeper.server.ServerCnxnFactory;
+import org.apache.zookeeper.server.quorum.QuorumPeerTestBase;
+import org.junit.After;
+import org.junit.Assert;
+import org.junit.Before;
+import org.junit.Test;
+
+public class SSLTest extends QuorumPeerTestBase {
+
+    @Before
+    public void setup() {
+        String testDataPath = System.getProperty("test.data.dir", "build/test/data");
+        System.setProperty(ServerCnxnFactory.ZOOKEEPER_SERVER_CNXN_FACTORY, "org.apache.zookeeper.server.NettyServerCnxnFactory");
+        System.setProperty(ZKClientConfig.ZOOKEEPER_CLIENT_CNXN_SOCKET, "org.apache.zookeeper.ClientCnxnSocketNetty");
+        System.setProperty(ZKClientConfig.SECURE_CLIENT, "true");
+        System.setProperty(ZKConfig.SSL_KEYSTORE_LOCATION, testDataPath + "/ssl/testKeyStore.jks");
+        System.setProperty(ZKConfig.SSL_KEYSTORE_PASSWD, "testpass");
+        System.setProperty(ZKConfig.SSL_TRUSTSTORE_LOCATION, testDataPath + "/ssl/testTrustStore.jks");
+        System.setProperty(ZKConfig.SSL_TRUSTSTORE_PASSWD, "testpass");
+    }
+
+    @After
+    public void teardown() throws Exception {
+        System.clearProperty(ServerCnxnFactory.ZOOKEEPER_SERVER_CNXN_FACTORY);
+        System.clearProperty(ZKClientConfig.ZOOKEEPER_CLIENT_CNXN_SOCKET);
+        System.clearProperty(ZKClientConfig.SECURE_CLIENT);
+        System.clearProperty(ZKConfig.SSL_KEYSTORE_LOCATION);
+        System.clearProperty(ZKConfig.SSL_KEYSTORE_PASSWD);
+        System.clearProperty(ZKConfig.SSL_TRUSTSTORE_LOCATION);
+        System.clearProperty(ZKConfig.SSL_TRUSTSTORE_PASSWD);
+    }
+
+    /**
+     * This test checks that SSL works in cluster setup of ZK servers, which includes:
+     * 1. setting "secureClientPort" in "zoo.cfg" file.
+     * 2. setting jvm flags for serverCnxn, keystore, truststore.
+     * Finally, a zookeeper client should be able to connect to the secure port and
+     * communicate with server via secure connection.
+     * <p/>
+     * Note that in this test a ZK server has two ports -- clientPort and secureClientPort.
+     */
+    @Test
+    public void testSecureQuorumServer() throws Exception {
+        final int SERVER_COUNT = 3;
+        final int clientPorts[] = new int[SERVER_COUNT];
+        final Integer secureClientPorts[] = new Integer[SERVER_COUNT];
+        StringBuilder sb = new StringBuilder();
+        for (int i = 0; i < SERVER_COUNT; i++) {
+            clientPorts[i] = PortAssignment.unique();
+            secureClientPorts[i] = PortAssignment.unique();
+            String server = String.format("server.%d=localhost:%d:%d:participant;localhost:%d",
+                    i, PortAssignment.unique(), PortAssignment.unique(), clientPorts[i]);
+            sb.append(server + "\n");
+        }
+        String quorumCfg = sb.toString();
+
+
+        MainThread[] mt = new MainThread[SERVER_COUNT];
+        for (int i = 0; i < SERVER_COUNT; i++) {
+            mt[i] = new MainThread(i, quorumCfg, secureClientPorts[i], true);
+            mt[i].start();
+        }
+
+        // Servers have been set up. Now go test if secure connection is successful.
+        for (int i = 0; i < SERVER_COUNT; i++) {
+            Assert.assertTrue("waiting for server " + i + " being up",
+                    ClientBase.waitForServerUp("127.0.0.1:" + clientPorts[i], TIMEOUT));
+
+            ZooKeeper zk = ClientBase.createZKClient("127.0.0.1:" + secureClientPorts[i], TIMEOUT);
+            // Do a simple operation to make sure the connection is fine.
+            zk.create("/test", "".getBytes(), ZooDefs.Ids.OPEN_ACL_UNSAFE, CreateMode.PERSISTENT);
+            zk.delete("/test", -1);
+            zk.close();
+        }
+
+        for (int i = 0; i < mt.length; i++) {
+            mt[i].shutdown();
+        }
+    }
+
+
+    /**
+     * Developers might use standalone mode (which is the default for one server).
+     * This test checks SSL works in standalone mode of ZK server.
+     * <p/>
+     * Note that in this test the Zk server has only secureClientPort
+     */
+    @Test
+    public void testSecureStandaloneServer() throws Exception {
+        Integer secureClientPort = PortAssignment.unique();
+        MainThread mt = new MainThread(MainThread.UNSET_MYID, "", secureClientPort, false);
+        mt.start();
+
+        ZooKeeper zk = ClientBase.createZKClient("127.0.0.1:" + secureClientPort, TIMEOUT);
+        zk.create("/test", "".getBytes(), ZooDefs.Ids.OPEN_ACL_UNSAFE, CreateMode.PERSISTENT);
+        zk.delete("/test", -1);
+        zk.close();
+        mt.shutdown();
+    }
+}

http://git-wip-us.apache.org/repos/asf/zookeeper/blob/7b679bc9/zookeeper-server/src/main/java/org/apache/zookeeper/server/NettyServerCnxnFactory.java
----------------------------------------------------------------------
diff --git a/zookeeper-server/src/main/java/org/apache/zookeeper/server/NettyServerCnxnFactory.java b/zookeeper-server/src/main/java/org/apache/zookeeper/server/NettyServerCnxnFactory.java
index 3e7c380..547d291 100644
--- a/zookeeper-server/src/main/java/org/apache/zookeeper/server/NettyServerCnxnFactory.java
+++ b/zookeeper-server/src/main/java/org/apache/zookeeper/server/NettyServerCnxnFactory.java
@@ -18,31 +18,10 @@
 
 package org.apache.zookeeper.server;
 
-import static org.jboss.netty.buffer.ChannelBuffers.dynamicBuffer;
-
-import java.io.IOException;
-import java.net.InetAddress;
-import java.net.InetSocketAddress;
-import java.security.KeyManagementException;
-import java.security.NoSuchAlgorithmException;
-import java.util.HashMap;
-import java.util.HashSet;
-import java.util.Map;
-import java.util.Set;
-import java.util.concurrent.Executors;
-
-import javax.net.ssl.SSLContext;
-import javax.net.ssl.SSLEngine;
-import javax.net.ssl.SSLPeerUnverifiedException;
-import javax.net.ssl.SSLSession;
-import javax.net.ssl.X509KeyManager;
-import javax.net.ssl.X509TrustManager;
-
 import org.apache.zookeeper.KeeperException;
-import org.apache.zookeeper.common.ZKConfig;
+import org.apache.zookeeper.common.ClientX509Util;
 import org.apache.zookeeper.common.X509Exception;
 import org.apache.zookeeper.common.X509Exception.SSLContextException;
-import org.apache.zookeeper.common.X509Util;
 import org.apache.zookeeper.server.auth.ProviderRegistry;
 import org.apache.zookeeper.server.auth.X509AuthenticationProvider;
 import org.jboss.netty.bootstrap.ServerBootstrap;
@@ -68,6 +47,25 @@ import org.jboss.netty.handler.ssl.SslHandler;
 import org.slf4j.Logger;
 import org.slf4j.LoggerFactory;
 
+import javax.net.ssl.SSLContext;
+import javax.net.ssl.SSLEngine;
+import javax.net.ssl.SSLPeerUnverifiedException;
+import javax.net.ssl.SSLSession;
+import javax.net.ssl.X509KeyManager;
+import javax.net.ssl.X509TrustManager;
+import java.io.IOException;
+import java.net.InetAddress;
+import java.net.InetSocketAddress;
+import java.security.KeyManagementException;
+import java.security.NoSuchAlgorithmException;
+import java.util.HashMap;
+import java.util.HashSet;
+import java.util.Map;
+import java.util.Set;
+import java.util.concurrent.Executors;
+
+import static org.jboss.netty.buffer.ChannelBuffers.dynamicBuffer;
+
 public class NettyServerCnxnFactory extends ServerCnxnFactory {
     private static final Logger LOG = LoggerFactory.getLogger(NettyServerCnxnFactory.class);
 
@@ -78,6 +76,7 @@ public class NettyServerCnxnFactory extends ServerCnxnFactory {
         new HashMap<InetAddress, Set<NettyServerCnxn>>( );
     InetSocketAddress localAddress;
     int maxClientCnxns = 60;
+    ClientX509Util x509Util;
 
     /**
      * This is an inner class since we need to extend SimpleChannelHandler, but
@@ -302,7 +301,7 @@ public class NettyServerCnxnFactory extends ServerCnxnFactory {
                     cnxn.setClientCertificateChain(session.getPeerCertificates());
 
                     String authProviderProp
-                            = System.getProperty(ZKConfig.SSL_AUTHPROVIDER, "x509");
+                            = System.getProperty(x509Util.getSslAuthProviderProperty(), "x509");
 
                     X509AuthenticationProvider authProvider =
                             (X509AuthenticationProvider)
@@ -358,20 +357,20 @@ public class NettyServerCnxnFactory extends ServerCnxnFactory {
                 return p;
             }
         });
+        x509Util = new ClientX509Util();
     }
 
     private synchronized void initSSL(ChannelPipeline p)
             throws X509Exception, KeyManagementException, NoSuchAlgorithmException {
-        String authProviderProp = System.getProperty(ZKConfig.SSL_AUTHPROVIDER);
+        String authProviderProp = System.getProperty(x509Util.getSslAuthProviderProperty());
         SSLContext sslContext;
         if (authProviderProp == null) {
-            sslContext = X509Util.createSSLContext();
+            sslContext = x509Util.getDefaultSSLContext();
         } else {
             sslContext = SSLContext.getInstance("TLSv1");
             X509AuthenticationProvider authProvider =
                     (X509AuthenticationProvider)ProviderRegistry.getProvider(
-                            System.getProperty(ZKConfig.SSL_AUTHPROVIDER,
-                                    "x509"));
+                            System.getProperty(x509Util.getSslAuthProviderProperty(), "x509"));
 
             if (authProvider == null)
             {

http://git-wip-us.apache.org/repos/asf/zookeeper/blob/7b679bc9/zookeeper-server/src/main/java/org/apache/zookeeper/server/auth/X509AuthenticationProvider.java
----------------------------------------------------------------------
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 93bc8fc..8a699ce 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
@@ -26,6 +26,7 @@ import javax.net.ssl.X509TrustManager;
 import javax.security.auth.x500.X500Principal;
 
 import org.apache.zookeeper.KeeperException;
+import org.apache.zookeeper.common.ClientX509Util;
 import org.apache.zookeeper.common.ZKConfig;
 import org.apache.zookeeper.common.X509Exception;
 import org.apache.zookeeper.common.X509Exception.KeyManagerException;
@@ -66,47 +67,50 @@ public class X509AuthenticationProvider implements AuthenticationProvider {
      * <br/><code>zookeeper.ssl.trustStore.password</code>
      */
     public X509AuthenticationProvider() throws X509Exception {
-        String keyStoreLocationProp = System.getProperty(
-                ZKConfig.SSL_KEYSTORE_LOCATION);
-        String keyStorePasswordProp = System.getProperty(
-                ZKConfig.SSL_KEYSTORE_PASSWD);
+        ZKConfig config = new ZKConfig();
+        X509Util x509Util = new ClientX509Util();
+
+        String keyStoreLocation = config.getProperty(x509Util.getSslKeystoreLocationProperty());
+        String keyStorePassword = config.getProperty(x509Util.getSslKeystorePasswdProperty());
+
+        boolean crlEnabled = Boolean.parseBoolean(System.getProperty(x509Util.getSslCrlEnabledProperty()));
+        boolean ocspEnabled = Boolean.parseBoolean(System.getProperty(x509Util.getSslOcspEnabledProperty()));
+        boolean hostnameVerificationEnabled = Boolean.parseBoolean(System.getProperty(x509Util.getSslHostnameVerificationEnabledProperty()));
 
         X509KeyManager km = null;
         X509TrustManager tm = null;
-        if (keyStoreLocationProp == null && keyStorePasswordProp == null) {
+        if (keyStoreLocation == null && keyStorePassword == null) {
             LOG.warn("keystore not specified for client connection");
         } else {
-            if (keyStoreLocationProp == null) {
+            if (keyStoreLocation == null) {
                 throw new X509Exception("keystore location not specified for client connection");
             }
-            if (keyStorePasswordProp == null) {
+            if (keyStorePassword == null) {
                 throw new X509Exception("keystore password not specified for client connection");
             }
             try {
-                km = X509Util.createKeyManager(
-                        keyStoreLocationProp, keyStorePasswordProp);
+                km = X509Util.createKeyManager(keyStoreLocation, keyStorePassword);
             } catch (KeyManagerException e) {
                 LOG.error("Failed to create key manager", e);
             }
         }
         
-        String trustStoreLocationProp = System.getProperty(
-                ZKConfig.SSL_TRUSTSTORE_LOCATION);
-        String trustStorePasswordProp = System.getProperty(
-                ZKConfig.SSL_TRUSTSTORE_PASSWD);
+        String trustStoreLocation = config.getProperty(x509Util.getSslTruststoreLocationProperty());
+        String trustStorePassword = config.getProperty(x509Util.getSslTruststorePasswdProperty());
 
-        if (trustStoreLocationProp == null && trustStorePasswordProp == null) {
+        if (trustStoreLocation == null && trustStorePassword == null) {
             LOG.warn("Truststore not specified for client connection");
         } else {
-            if (trustStoreLocationProp == null) {
+            if (trustStoreLocation == null) {
                 throw new X509Exception("Truststore location not specified for client connection");
             }
-            if (trustStorePasswordProp == null) {
+            if (trustStorePassword == null) {
                 throw new X509Exception("Truststore password not specified for client connection");
             }
             try {
                 tm = X509Util.createTrustManager(
-                        trustStoreLocationProp, trustStorePasswordProp);
+                        trustStoreLocation, trustStorePassword, crlEnabled, ocspEnabled,
+                        hostnameVerificationEnabled, false);
             } catch (TrustManagerException e) {
                 LOG.error("Failed to create trust manager", e);
             }

http://git-wip-us.apache.org/repos/asf/zookeeper/blob/7b679bc9/zookeeper-server/src/main/java/org/apache/zookeeper/server/quorum/Leader.java
----------------------------------------------------------------------
diff --git a/zookeeper-server/src/main/java/org/apache/zookeeper/server/quorum/Leader.java b/zookeeper-server/src/main/java/org/apache/zookeeper/server/quorum/Leader.java
index 62dec30..9270548 100644
--- a/zookeeper-server/src/main/java/org/apache/zookeeper/server/quorum/Leader.java
+++ b/zookeeper-server/src/main/java/org/apache/zookeeper/server/quorum/Leader.java
@@ -42,7 +42,9 @@ import java.util.concurrent.ConcurrentMap;
 import javax.security.sasl.SaslException;
 
 import org.apache.zookeeper.ZooDefs.OpCode;
+import org.apache.zookeeper.common.QuorumX509Util;
 import org.apache.zookeeper.common.Time;
+import org.apache.zookeeper.common.X509Exception;
 import org.apache.zookeeper.server.FinalRequestProcessor;
 import org.apache.zookeeper.server.Request;
 import org.apache.zookeeper.server.RequestProcessor;
@@ -232,19 +234,36 @@ public class Leader {
 
     private final ServerSocket ss;
 
-    Leader(QuorumPeer self,LeaderZooKeeperServer zk) throws IOException {
+    Leader(QuorumPeer self,LeaderZooKeeperServer zk) throws IOException, X509Exception {
         this.self = self;
         this.proposalStats = new BufferStats();
         try {
-            if (self.getQuorumListenOnAllIPs()) {
-                ss = new ServerSocket(self.getQuorumAddress().getPort());
+            if (self.shouldUsePortUnification()) {
+                if (self.getQuorumListenOnAllIPs()) {
+                    ss = new UnifiedServerSocket(new QuorumX509Util(), self.getQuorumAddress().getPort());
+                } else {
+                    ss = new UnifiedServerSocket(new QuorumX509Util());
+                }
+            } else if (self.isSslQuorum()) {
+                if (self.getQuorumListenOnAllIPs()) {
+                    ss = new QuorumX509Util().createSSLServerSocket(self.getQuorumAddress().getPort());
+                } else {
+                    ss = new QuorumX509Util().createSSLServerSocket();
+                }
             } else {
-                ss = new ServerSocket();
+                if (self.getQuorumListenOnAllIPs()) {
+                    ss = new ServerSocket(self.getQuorumAddress().getPort());
+                } else {
+                    ss = new ServerSocket();
+                }
             }
             ss.setReuseAddress(true);
             if (!self.getQuorumListenOnAllIPs()) {
                 ss.bind(self.getQuorumAddress());
             }
+        } catch (X509Exception e) {
+            LOG.error("Failed to setup ssl server socket", e);
+            throw e;
         } catch (BindException e) {
             if (self.getQuorumListenOnAllIPs()) {
                 LOG.error("Couldn't bind to port " + self.getQuorumAddress().getPort(), e);
@@ -382,6 +401,7 @@ public class Leader {
                 while (!stop) {
                     try{
                         Socket s = ss.accept();
+
                         // start with the initLimit, once the ack is processed
                         // in LearnerHandler switch to the syncLimit
                         s.setSoTimeout(self.tickTime * self.initLimit);

http://git-wip-us.apache.org/repos/asf/zookeeper/blob/7b679bc9/zookeeper-server/src/main/java/org/apache/zookeeper/server/quorum/Learner.java
----------------------------------------------------------------------
diff --git a/zookeeper-server/src/main/java/org/apache/zookeeper/server/quorum/Learner.java b/zookeeper-server/src/main/java/org/apache/zookeeper/server/quorum/Learner.java
index 72be55f..c740d53 100644
--- a/zookeeper-server/src/main/java/org/apache/zookeeper/server/quorum/Learner.java
+++ b/zookeeper-server/src/main/java/org/apache/zookeeper/server/quorum/Learner.java
@@ -38,6 +38,9 @@ import org.apache.jute.BinaryOutputArchive;
 import org.apache.jute.InputArchive;
 import org.apache.jute.OutputArchive;
 import org.apache.jute.Record;
+import org.apache.zookeeper.common.QuorumX509Util;
+import org.apache.zookeeper.common.X509Exception;
+import org.apache.zookeeper.common.X509Util;
 import org.apache.zookeeper.server.ExitCode;
 import org.slf4j.Logger;
 import org.slf4j.LoggerFactory;
@@ -52,6 +55,8 @@ import org.apache.zookeeper.server.util.ZxidUtils;
 import org.apache.zookeeper.txn.SetDataTxn;
 import org.apache.zookeeper.txn.TxnHeader;
 
+import javax.net.ssl.SSLSocket;
+
 /**
  * This class is the superclass of two of the three main actors in a ZK
  * ensemble: Followers and Observers. Both Followers and Observers share 
@@ -68,6 +73,8 @@ public class Learner {
     protected BufferedOutputStream bufferedOutput;
     
     protected Socket sock;
+
+    protected X509Util x509Util;
     
     /**
      * Socket getter
@@ -241,9 +248,8 @@ public class Learner {
      * @throws InterruptedException
      */
     protected void connectToLeader(InetSocketAddress addr, String hostname)
-    throws IOException, ConnectException, InterruptedException {
-        sock = new Socket();        
-        sock.setSoTimeout(self.tickTime * self.initLimit);
+            throws IOException, InterruptedException, X509Exception {
+        this.sock = createSocket();
 
         int initLimitTime = self.tickTime * self.initLimit;
         int remainingInitLimitTime = initLimitTime;
@@ -259,6 +265,9 @@ public class Learner {
                 }
 
                 sockConnect(sock, addr, Math.min(self.tickTime * self.syncLimit, remainingInitLimitTime));
+                if (self.isSslQuorum())  {
+                    ((SSLSocket) sock).startHandshake();
+                }
                 sock.setTcpNoDelay(nodelay);
                 break;
             } catch (IOException e) {
@@ -278,8 +287,7 @@ public class Learner {
                     LOG.warn("Unexpected exception, tries=" + tries +
                             ", remaining init limit=" + remainingInitLimitTime +
                             ", connecting to " + addr,e);
-                    sock = new Socket();
-                    sock.setSoTimeout(self.tickTime * self.initLimit);
+                    this.sock = createSocket();
                 }
             }
             Thread.sleep(1000);
@@ -291,8 +299,22 @@ public class Learner {
                 sock.getInputStream()));
         bufferedOutput = new BufferedOutputStream(sock.getOutputStream());
         leaderOs = BinaryOutputArchive.getArchive(bufferedOutput);
-    }   
-    
+    }
+
+    private Socket createSocket() throws X509Exception, IOException {
+        Socket sock;
+        if (self.isSslQuorum()) {
+            if (x509Util == null) {
+                x509Util = new QuorumX509Util();
+            }
+            sock = x509Util.createSSLSocket();
+        } else {
+            sock = new Socket();
+        }
+        sock.setSoTimeout(self.tickTime * self.initLimit);
+        return sock;
+    }
+
     /**
      * Once connected to the leader, perform the handshake protocol to
      * establish a following / observing connection. 

http://git-wip-us.apache.org/repos/asf/zookeeper/blob/7b679bc9/zookeeper-server/src/main/java/org/apache/zookeeper/server/quorum/PrependableSocket.java
----------------------------------------------------------------------
diff --git a/zookeeper-server/src/main/java/org/apache/zookeeper/server/quorum/PrependableSocket.java b/zookeeper-server/src/main/java/org/apache/zookeeper/server/quorum/PrependableSocket.java
new file mode 100644
index 0000000..a86608f
--- /dev/null
+++ b/zookeeper-server/src/main/java/org/apache/zookeeper/server/quorum/PrependableSocket.java
@@ -0,0 +1,49 @@
+/**
+ * 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.server.quorum;
+
+import java.io.ByteArrayInputStream;
+import java.io.IOException;
+import java.io.InputStream;
+import java.io.SequenceInputStream;
+import java.net.Socket;
+import java.net.SocketImpl;
+
+public class PrependableSocket extends Socket {
+
+  private SequenceInputStream sequenceInputStream;
+
+  public PrependableSocket(SocketImpl base) throws IOException {
+    super(base);
+  }
+
+  @Override
+  public InputStream getInputStream() throws IOException {
+    if (sequenceInputStream == null) {
+      return super.getInputStream();
+    }
+
+    return sequenceInputStream;
+  }
+
+  public void prependToInputStream(byte[] bytes) throws IOException {
+    sequenceInputStream = new SequenceInputStream(new ByteArrayInputStream(bytes), getInputStream());
+  }
+
+}
\ No newline at end of file

http://git-wip-us.apache.org/repos/asf/zookeeper/blob/7b679bc9/zookeeper-server/src/main/java/org/apache/zookeeper/server/quorum/QuorumBean.java
----------------------------------------------------------------------
diff --git a/zookeeper-server/src/main/java/org/apache/zookeeper/server/quorum/QuorumBean.java b/zookeeper-server/src/main/java/org/apache/zookeeper/server/quorum/QuorumBean.java
index 0c0f112..9b0717c 100644
--- a/zookeeper-server/src/main/java/org/apache/zookeeper/server/quorum/QuorumBean.java
+++ b/zookeeper-server/src/main/java/org/apache/zookeeper/server/quorum/QuorumBean.java
@@ -29,16 +29,29 @@ public class QuorumBean implements QuorumMXBean, ZKMBeanInfo {
         this.peer = peer;
         name = "ReplicatedServer_id" + peer.getId();
     }
-    
+
+    @Override
     public String getName() {
         return name;
     }
-    
+
+    @Override
     public boolean isHidden() {
         return false;
     }
-    
+
+    @Override
     public int getQuorumSize() {
         return peer.getQuorumSize();
     }
+
+    @Override
+    public boolean isSslQuorum() {
+        return peer.isSslQuorum();
+    }
+
+    @Override
+    public boolean isPortUnification() {
+        return peer.shouldUsePortUnification();
+    }
 }

http://git-wip-us.apache.org/repos/asf/zookeeper/blob/7b679bc9/zookeeper-server/src/main/java/org/apache/zookeeper/server/quorum/QuorumCnxManager.java
----------------------------------------------------------------------
diff --git a/zookeeper-server/src/main/java/org/apache/zookeeper/server/quorum/QuorumCnxManager.java b/zookeeper-server/src/main/java/org/apache/zookeeper/server/quorum/QuorumCnxManager.java
index 9a2f103..8b91023 100644
--- a/zookeeper-server/src/main/java/org/apache/zookeeper/server/quorum/QuorumCnxManager.java
+++ b/zookeeper-server/src/main/java/org/apache/zookeeper/server/quorum/QuorumCnxManager.java
@@ -47,6 +47,9 @@ import java.util.NoSuchElementException;
 import java.util.concurrent.atomic.AtomicInteger;
 import java.util.concurrent.atomic.AtomicLong;
 
+import org.apache.zookeeper.common.QuorumX509Util;
+import org.apache.zookeeper.common.X509Exception;
+import org.apache.zookeeper.common.X509Util;
 import org.apache.zookeeper.server.ExitCode;
 import org.apache.zookeeper.server.quorum.QuorumPeerConfig.ConfigException;
 import org.apache.zookeeper.server.util.ConfigUtils;
@@ -57,6 +60,7 @@ import org.apache.zookeeper.server.quorum.flexible.QuorumVerifier;
 import org.slf4j.Logger;
 import org.slf4j.LoggerFactory;
 
+import javax.net.ssl.SSLSocket;
 import static org.apache.zookeeper.common.NetUtils.formatInetAddr;
 
 /**
@@ -172,6 +176,8 @@ public class QuorumCnxManager {
     private final boolean tcpKeepAlive = Boolean.getBoolean("zookeeper.tcpKeepAlive");
 
 
+    private X509Util x509Util;
+
     static public class Message {
         Message(ByteBuffer buffer, long sid) {
             this.buffer = buffer;
@@ -285,6 +291,8 @@ public class QuorumCnxManager {
         // Starts listener thread that waits for connection requests
         listener = new Listener();
         listener.setName("QuorumPeerListener");
+
+        x509Util = new QuorumX509Util();
     }
 
     private void initializeAuth(final long mySid,
@@ -548,14 +556,13 @@ public class QuorumCnxManager {
                 LOG.info("Setting arbitrary identifier to observer: " + sid);
             }
         } catch (IOException e) {
+            LOG.warn("Exception reading or writing challenge: {}", e);
             closeSocket(sock);
-            LOG.warn("Exception reading or writing challenge: {}", e.toString());
             return;
         }
 
         // do authenticating learner
         authServer.authenticate(sock, din);
-
         //If wins the challenge, then close the new connection.
         if (sid < self.getId()) {
             /*
@@ -646,11 +653,19 @@ public class QuorumCnxManager {
 
         Socket sock = null;
         try {
-             LOG.debug("Opening channel to server " + sid);
-             sock = new Socket();
-             setSockOpts(sock);
-             sock.connect(electionAddr, cnxTO);
-             LOG.debug("Connected to server " + sid);
+            LOG.debug("Opening channel to server " + sid);
+            if (self.isSslQuorum()) {
+                SSLSocket sslSock = x509Util.createSSLSocket();
+                setSockOpts(sslSock);
+                sslSock.connect(electionAddr, cnxTO);
+                sslSock.startHandshake();
+                sock = sslSock;
+            } else {
+                sock = new Socket();
+                setSockOpts(sock);
+                sock.connect(electionAddr, cnxTO);
+            }
+            LOG.debug("Connected to server " + sid);
             // Sends connection request asynchronously if the quorum
             // sasl authentication is enabled. This is required because
             // sasl server authentication process may take few seconds to
@@ -660,24 +675,28 @@ public class QuorumCnxManager {
             } else {
                 initiateConnection(sock, sid);
             }
-             return true;
-         } catch (UnresolvedAddressException e) {
-             // Sun doesn't include the address that causes this
-             // exception to be thrown, also UAE cannot be wrapped cleanly
-             // so we log the exception in order to capture this critical
-             // detail.
-             LOG.warn("Cannot open channel to " + sid
-                     + " at election address " + electionAddr, e);
-             closeSocket(sock);
-             throw e;
-         } catch (IOException e) {
-             LOG.warn("Cannot open channel to " + sid
-                     + " at election address " + electionAddr,
-                     e);
-             closeSocket(sock);
-             return false;
-         }
-
+            return true;
+        } catch (UnresolvedAddressException e) {
+            // Sun doesn't include the address that causes this
+            // exception to be thrown, also UAE cannot be wrapped cleanly
+            // so we log the exception in order to capture this critical
+            // detail.
+            LOG.warn("Cannot open channel to " + sid
+                    + " at election address " + electionAddr, e);
+            closeSocket(sock);
+            throw e;
+        } catch (X509Exception e) {
+            LOG.warn("Cannot open secure channel to " + sid
+                    + " at election address " + electionAddr, e);
+            closeSocket(sock);
+            return false;
+        } catch (IOException e) {
+            LOG.warn("Cannot open channel to " + sid
+                            + " at election address " + electionAddr,
+                    e);
+            closeSocket(sock);
+            return false;
+        }
     }
 
     /**
@@ -853,11 +872,19 @@ public class QuorumCnxManager {
             int numRetries = 0;
             InetSocketAddress addr;
             Socket client = null;
-            IOException exitException = null;
+            Exception exitException = null;
             while((!shutdown) && (numRetries < 3)){
                 try {
-                    ss = new ServerSocket();
+                    if (self.shouldUsePortUnification()) {
+                        ss = new UnifiedServerSocket(x509Util);
+                    } else if (self.isSslQuorum()) {
+                        ss = x509Util.createSSLServerSocket();
+                    } else {
+                        ss = new ServerSocket();
+                    }
+
                     ss.setReuseAddress(true);
+
                     if (self.getQuorumListenOnAllIPs()) {
                         int port = self.getElectionAddress().getPort();
                         addr = new InetSocketAddress(port);
@@ -893,7 +920,7 @@ public class QuorumCnxManager {
                                      + "see ZOOKEEPER-2836");
                         }
                     }
-                } catch (IOException e) {
+                } catch (IOException|X509Exception e) {
                     if (shutdown) {
                         break;
                     }

http://git-wip-us.apache.org/repos/asf/zookeeper/blob/7b679bc9/zookeeper-server/src/main/java/org/apache/zookeeper/server/quorum/QuorumMXBean.java
----------------------------------------------------------------------
diff --git a/zookeeper-server/src/main/java/org/apache/zookeeper/server/quorum/QuorumMXBean.java b/zookeeper-server/src/main/java/org/apache/zookeeper/server/quorum/QuorumMXBean.java
index 2edce68..d0215c8 100644
--- a/zookeeper-server/src/main/java/org/apache/zookeeper/server/quorum/QuorumMXBean.java
+++ b/zookeeper-server/src/main/java/org/apache/zookeeper/server/quorum/QuorumMXBean.java
@@ -31,4 +31,14 @@ public interface QuorumMXBean {
      * @return configured number of peers in the quorum
      */
     public int getQuorumSize();
+
+    /**
+     * @return SSL communication between quorum members required
+     */
+    public boolean isSslQuorum();
+
+    /**
+     * @return SSL communication between quorum members enabled
+     */
+    public boolean isPortUnification();
 }

http://git-wip-us.apache.org/repos/asf/zookeeper/blob/7b679bc9/zookeeper-server/src/main/java/org/apache/zookeeper/server/quorum/QuorumPeer.java
----------------------------------------------------------------------
diff --git a/zookeeper-server/src/main/java/org/apache/zookeeper/server/quorum/QuorumPeer.java b/zookeeper-server/src/main/java/org/apache/zookeeper/server/quorum/QuorumPeer.java
index cbf643e..136a538 100644
--- a/zookeeper-server/src/main/java/org/apache/zookeeper/server/quorum/QuorumPeer.java
+++ b/zookeeper-server/src/main/java/org/apache/zookeeper/server/quorum/QuorumPeer.java
@@ -48,6 +48,7 @@ import org.apache.zookeeper.KeeperException.BadArgumentsException;
 import org.apache.zookeeper.common.AtomicFileWritingIdiom;
 import org.apache.zookeeper.common.AtomicFileWritingIdiom.WriterStatement;
 import org.apache.zookeeper.common.Time;
+import org.apache.zookeeper.common.X509Exception;
 import org.apache.zookeeper.jmx.MBeanRegistry;
 import org.apache.zookeeper.jmx.ZKMBeanInfo;
 import org.apache.zookeeper.server.ServerCnxnFactory;
@@ -240,7 +241,7 @@ public class QuorumPeer extends ZooKeeperThread implements QuorumStats.Provider
                 throw new ConfigException("Address unresolved: " + serverParts[0] + ":" + serverParts[1]);
             }
             try {
-                electionAddr = new InetSocketAddress(serverParts[0], 
+                electionAddr = new InetSocketAddress(serverParts[0],
                         Integer.parseInt(serverParts[2]));
             } catch (NumberFormatException e) {
                 throw new ConfigException("Address unresolved: " + serverParts[0] + ":" + serverParts[2]);
@@ -467,6 +468,17 @@ public class QuorumPeer extends ZooKeeperThread implements QuorumStats.Provider
         this.myid = id;
     }
 
+    private boolean sslQuorum;
+    private boolean shouldUsePortUnification;
+
+    public boolean isSslQuorum() {
+        return sslQuorum;
+    }
+
+    public boolean shouldUsePortUnification() {
+        return shouldUsePortUnification;
+    }
+
     /**
      * This is who I think the leader currently is.
      */
@@ -1009,7 +1021,7 @@ public class QuorumPeer extends ZooKeeperThread implements QuorumStats.Provider
         return new Follower(this, new FollowerZooKeeperServer(logFactory, this, this.zkDb));
     }
 
-    protected Leader makeLeader(FileTxnSnapLog logFactory) throws IOException {
+    protected Leader makeLeader(FileTxnSnapLog logFactory) throws IOException, X509Exception {
         return new Leader(this, new LeaderZooKeeperServer(logFactory, this, this.zkDb));
     }
 
@@ -1691,6 +1703,14 @@ public class QuorumPeer extends ZooKeeperThread implements QuorumStats.Provider
         this.rootMetricsContext = rootMetricsContext;
     }
 
+    public void setSslQuorum(boolean sslQuorum) {
+        this.sslQuorum = sslQuorum;
+    }
+
+    public void setUsePortUnification(boolean shouldUsePortUnification) {
+        this.shouldUsePortUnification = shouldUsePortUnification;
+    }
+
     private void startServerCnxnFactory() {
         if (cnxnFactory != null) {
             cnxnFactory.start();

http://git-wip-us.apache.org/repos/asf/zookeeper/blob/7b679bc9/zookeeper-server/src/main/java/org/apache/zookeeper/server/quorum/QuorumPeerConfig.java
----------------------------------------------------------------------
diff --git a/zookeeper-server/src/main/java/org/apache/zookeeper/server/quorum/QuorumPeerConfig.java b/zookeeper-server/src/main/java/org/apache/zookeeper/server/quorum/QuorumPeerConfig.java
index f4e8a5f..45463b1 100644
--- a/zookeeper-server/src/main/java/org/apache/zookeeper/server/quorum/QuorumPeerConfig.java
+++ b/zookeeper-server/src/main/java/org/apache/zookeeper/server/quorum/QuorumPeerConfig.java
@@ -37,8 +37,8 @@ import java.util.Properties;
 import java.util.Map.Entry;
 
 import org.apache.yetus.audience.InterfaceAudience;
+import org.apache.zookeeper.common.ClientX509Util;
 import org.apache.zookeeper.common.StringUtils;
-import org.apache.zookeeper.common.ZKConfig;
 import org.slf4j.Logger;
 import org.slf4j.LoggerFactory;
 import org.slf4j.MDC;
@@ -69,6 +69,8 @@ public class QuorumPeerConfig {
 
     protected InetSocketAddress clientPortAddress;
     protected InetSocketAddress secureClientPortAddress;
+    protected boolean sslQuorum = false;
+    protected boolean shouldUsePortUnification = false;
     protected File dataDir;
     protected File dataLogDir;
     protected String dynamicConfigFileStr = null;
@@ -311,6 +313,11 @@ public class QuorumPeerConfig {
                 } else {
                     throw new ConfigException("Invalid option " + value + " for reconfigEnabled flag. Choose 'true' or 'false.'");
                 }
+            } else if (key.equals("sslQuorum")){
+                sslQuorum = Boolean.parseBoolean(value);
+// TODO: UnifiedServerSocket is currently buggy, will be fixed when @ivmaykov's PRs are merged. Disable port unification until then.
+//            } else if (key.equals("portUnification")){
+//                shouldUsePortUnification = Boolean.parseBoolean(value);
             } else if ((key.startsWith("server.") || key.startsWith("group") || key.startsWith("weight")) && zkProp.containsKey("dynamicConfigFile")) {
                 throw new ConfigException("parameter: " + key + " must be in a separate dynamic config file");
             } else if (key.equals(QuorumAuth.QUORUM_SASL_AUTH_ENABLED)) {
@@ -445,14 +452,15 @@ public class QuorumPeerConfig {
      *             provider is not configured.
      */
     private void configureSSLAuth() throws ConfigException {
-        String sslAuthProp = "zookeeper.authProvider." + System.getProperty(ZKConfig.SSL_AUTHPROVIDER, "x509");
+        ClientX509Util clientX509Util = new ClientX509Util();
+        String sslAuthProp = "zookeeper.authProvider." + System.getProperty(clientX509Util.getSslAuthProviderProperty(), "x509");
         if (System.getProperty(sslAuthProp) == null) {
             if ("zookeeper.authProvider.x509".equals(sslAuthProp)) {
                 System.setProperty("zookeeper.authProvider.x509",
                         "org.apache.zookeeper.server.auth.X509AuthenticationProvider");
             } else {
                 throw new ConfigException("No auth provider configured for the SSL authentication scheme '"
-                        + System.getProperty(ZKConfig.SSL_AUTHPROVIDER) + "'.");
+                        + System.getProperty(clientX509Util.getSslAuthProviderProperty()) + "'.");
             }
         }
     }
@@ -759,6 +767,13 @@ public class QuorumPeerConfig {
     public boolean isLocalSessionsUpgradingEnabled() {
         return localSessionsUpgradingEnabled;
     }
+    public boolean isSslQuorum() {
+        return sslQuorum;
+    }
+
+    public boolean shouldUsePortUnification() {
+        return shouldUsePortUnification;
+    }
 
     public int getInitLimit() { return initLimit; }
     public int getSyncLimit() { return syncLimit; }

http://git-wip-us.apache.org/repos/asf/zookeeper/blob/7b679bc9/zookeeper-server/src/main/java/org/apache/zookeeper/server/quorum/QuorumPeerMain.java
----------------------------------------------------------------------
diff --git a/zookeeper-server/src/main/java/org/apache/zookeeper/server/quorum/QuorumPeerMain.java b/zookeeper-server/src/main/java/org/apache/zookeeper/server/quorum/QuorumPeerMain.java
index 11b5c0b..d2a02b2 100644
--- a/zookeeper-server/src/main/java/org/apache/zookeeper/server/quorum/QuorumPeerMain.java
+++ b/zookeeper-server/src/main/java/org/apache/zookeeper/server/quorum/QuorumPeerMain.java
@@ -197,6 +197,8 @@ public class QuorumPeerMain {
           quorumPeer.initConfigInZKDatabase();
           quorumPeer.setCnxnFactory(cnxnFactory);
           quorumPeer.setSecureCnxnFactory(secureCnxnFactory);
+          quorumPeer.setSslQuorum(config.isSslQuorum());
+          quorumPeer.setUsePortUnification(config.shouldUsePortUnification());
           quorumPeer.setLearnerType(config.getPeerType());
           quorumPeer.setSyncEnabled(config.getSyncEnabled());
           quorumPeer.setQuorumListenOnAllIPs(config.getQuorumListenOnAllIPs());

http://git-wip-us.apache.org/repos/asf/zookeeper/blob/7b679bc9/zookeeper-server/src/main/java/org/apache/zookeeper/server/quorum/UnifiedServerSocket.java
----------------------------------------------------------------------
diff --git a/zookeeper-server/src/main/java/org/apache/zookeeper/server/quorum/UnifiedServerSocket.java b/zookeeper-server/src/main/java/org/apache/zookeeper/server/quorum/UnifiedServerSocket.java
new file mode 100644
index 0000000..4802ecf
--- /dev/null
+++ b/zookeeper-server/src/main/java/org/apache/zookeeper/server/quorum/UnifiedServerSocket.java
@@ -0,0 +1,79 @@
+/**
+ * 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.server.quorum;
+
+import org.apache.zookeeper.common.X509Exception;
+import org.apache.zookeeper.common.X509Util;
+import org.jboss.netty.buffer.ChannelBuffers;
+import org.jboss.netty.handler.ssl.SslHandler;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+
+import javax.net.ssl.SSLSocket;
+import java.io.IOException;
+import java.net.ServerSocket;
+import java.net.Socket;
+import java.net.SocketException;
+
+public class UnifiedServerSocket extends ServerSocket {
+    private static final Logger LOG = LoggerFactory.getLogger(UnifiedServerSocket.class);
+
+    private X509Util x509Util;
+
+    public UnifiedServerSocket(X509Util x509Util) throws IOException {
+        super();
+        this.x509Util = x509Util;
+    }
+
+    public UnifiedServerSocket(X509Util x509Util, int port) throws IOException {
+        super(port);
+        this.x509Util = x509Util;
+    }
+
+    @Override
+    public Socket accept() throws IOException {
+        if (isClosed()) {
+            throw new SocketException("Socket is closed");
+        }
+        if (!isBound()) {
+            throw new SocketException("Socket is not bound yet");
+        }
+        final PrependableSocket prependableSocket = new PrependableSocket(null);
+        implAccept(prependableSocket);
+
+        byte[] litmus = new byte[5];
+        int bytesRead = prependableSocket.getInputStream().read(litmus, 0, 5);
+        prependableSocket.prependToInputStream(litmus);
+
+        if (bytesRead == 5 && SslHandler.isEncrypted(ChannelBuffers.wrappedBuffer(litmus))) {
+            LOG.info(getInetAddress() + " attempting to connect over ssl");
+            SSLSocket sslSocket;
+            try {
+                sslSocket = x509Util.createSSLSocket(prependableSocket);
+            } catch (X509Exception e) {
+                throw new IOException("failed to create SSL context", e);
+            }
+            sslSocket.setUseClientMode(false);
+            return sslSocket;
+        } else {
+            LOG.info(getInetAddress() + " attempting to connect without ssl");
+            return prependableSocket;
+        }
+    }
+}
\ No newline at end of file

http://git-wip-us.apache.org/repos/asf/zookeeper/blob/7b679bc9/zookeeper-server/src/test/java/org/apache/zookeeper/server/quorum/LeaderBeanTest.java
----------------------------------------------------------------------
diff --git a/zookeeper-server/src/test/java/org/apache/zookeeper/server/quorum/LeaderBeanTest.java b/zookeeper-server/src/test/java/org/apache/zookeeper/server/quorum/LeaderBeanTest.java
index b017551..9087483 100644
--- a/zookeeper-server/src/test/java/org/apache/zookeeper/server/quorum/LeaderBeanTest.java
+++ b/zookeeper-server/src/test/java/org/apache/zookeeper/server/quorum/LeaderBeanTest.java
@@ -20,6 +20,7 @@ package org.apache.zookeeper.server.quorum;
 
 import org.apache.jute.OutputArchive;
 import org.apache.jute.Record;
+import org.apache.zookeeper.common.X509Exception;
 import org.apache.zookeeper.server.Request;
 import org.apache.zookeeper.server.ZKDatabase;
 import org.apache.zookeeper.server.persistence.FileTxnSnapLog;
@@ -53,7 +54,7 @@ public class LeaderBeanTest {
     private QuorumPeer qp;
 
     @Before
-    public void setUp() throws IOException {
+    public void setUp() throws IOException, X509Exception {
         qp = new QuorumPeer();
         QuorumVerifier quorumVerifierMock = mock(QuorumVerifier.class);
         qp.setQuorumVerifier(quorumVerifierMock, false);

http://git-wip-us.apache.org/repos/asf/zookeeper/blob/7b679bc9/zookeeper-server/src/test/java/org/apache/zookeeper/server/quorum/QuorumBeanTest.java
----------------------------------------------------------------------
diff --git a/zookeeper-server/src/test/java/org/apache/zookeeper/server/quorum/QuorumBeanTest.java b/zookeeper-server/src/test/java/org/apache/zookeeper/server/quorum/QuorumBeanTest.java
new file mode 100644
index 0000000..650dc82
--- /dev/null
+++ b/zookeeper-server/src/test/java/org/apache/zookeeper/server/quorum/QuorumBeanTest.java
@@ -0,0 +1,75 @@
+/**
+ * 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.server.quorum;
+
+import org.junit.Test;
+
+import static org.hamcrest.CoreMatchers.equalTo;
+import static org.hamcrest.MatcherAssert.assertThat;
+import static org.mockito.Mockito.mock;
+import static org.mockito.Mockito.when;
+
+public class QuorumBeanTest {
+    @Test
+    public void testGetNameProperty() {
+        QuorumPeer qpMock = mock(QuorumPeer.class);
+        when(qpMock.getId()).thenReturn(1L);
+        QuorumBean qb = new QuorumBean(qpMock);
+
+        assertThat("getName property should return Bean name in the right format", qb.getName(), equalTo("ReplicatedServer_id1"));
+    }
+
+    @Test
+    public void testIsHiddenProperty() {
+        QuorumPeer qpMock = mock(QuorumPeer.class);
+        QuorumBean qb = new QuorumBean(qpMock);
+        assertThat("isHidden should return false", qb.isHidden(), equalTo(false));
+    }
+
+    @Test
+    public void testGetQuorumSizeProperty() {
+        QuorumPeer qpMock = mock(QuorumPeer.class);
+        QuorumBean qb = new QuorumBean(qpMock);
+
+        when(qpMock.getQuorumSize()).thenReturn(5);
+        assertThat("getQuorumSize property should return value of peet.getQuorumSize()", qb.getQuorumSize(), equalTo(5));
+    }
+
+    @Test
+    public void testSslQuorumProperty() {
+        QuorumPeer qpMock = mock(QuorumPeer.class);
+        QuorumBean qb = new QuorumBean(qpMock);
+
+        when(qpMock.isSslQuorum()).thenReturn(true);
+        assertThat("isSslQuorum property should return value of peer.isSslQuorum()", qb.isSslQuorum(), equalTo(true));
+        when(qpMock.isSslQuorum()).thenReturn(false);
+        assertThat("isSslQuorum property should return value of peer.isSslQuorum()", qb.isSslQuorum(), equalTo(false));
+    }
+
+    @Test
+    public void testPortUnificationProperty() {
+        QuorumPeer qpMock = mock(QuorumPeer.class);
+        QuorumBean qb = new QuorumBean(qpMock);
+
+        when(qpMock.shouldUsePortUnification()).thenReturn(true);
+        assertThat("isPortUnification property should return value of peer.shouldUsePortUnification()", qb.isPortUnification(), equalTo(true));
+        when(qpMock.shouldUsePortUnification()).thenReturn(false);
+        assertThat("isPortUnification property should return value of peer.shouldUsePortUnification()", qb.isPortUnification(), equalTo(false));
+    }
+}

http://git-wip-us.apache.org/repos/asf/zookeeper/blob/7b679bc9/zookeeper-server/src/test/java/org/apache/zookeeper/server/quorum/QuorumPeerConfigTest.java
----------------------------------------------------------------------
diff --git a/zookeeper-server/src/test/java/org/apache/zookeeper/server/quorum/QuorumPeerConfigTest.java b/zookeeper-server/src/test/java/org/apache/zookeeper/server/quorum/QuorumPeerConfigTest.java
index 524fcee..f4a8b4b 100644
--- a/zookeeper-server/src/test/java/org/apache/zookeeper/server/quorum/QuorumPeerConfigTest.java
+++ b/zookeeper-server/src/test/java/org/apache/zookeeper/server/quorum/QuorumPeerConfigTest.java
@@ -27,7 +27,7 @@ import java.io.IOException;
 import java.net.InetSocketAddress;
 import java.util.Properties;
 
-import org.apache.zookeeper.common.ZKConfig;
+import org.apache.zookeeper.common.ClientX509Util;
 import org.apache.zookeeper.server.quorum.QuorumPeerConfig.ConfigException;
 import org.apache.zookeeper.server.quorum.QuorumPeer.QuorumServer;
 import org.junit.Test;
@@ -93,7 +93,7 @@ public class QuorumPeerConfigTest {
     @Test
     public void testCustomSSLAuth()
             throws IOException{
-        System.setProperty(ZKConfig.SSL_AUTHPROVIDER, "y509");
+        System.setProperty(new ClientX509Util().getSslAuthProviderProperty(), "y509");
         QuorumPeerConfig quorumPeerConfig = new QuorumPeerConfig();
         try {
             Properties zkProp = getDefaultZKProperties();

http://git-wip-us.apache.org/repos/asf/zookeeper/blob/7b679bc9/zookeeper-server/src/test/java/org/apache/zookeeper/server/quorum/QuorumPeerMainTest.java
----------------------------------------------------------------------
diff --git a/zookeeper-server/src/test/java/org/apache/zookeeper/server/quorum/QuorumPeerMainTest.java b/zookeeper-server/src/test/java/org/apache/zookeeper/server/quorum/QuorumPeerMainTest.java
index 2591f8d..947e7a5 100644
--- a/zookeeper-server/src/test/java/org/apache/zookeeper/server/quorum/QuorumPeerMainTest.java
+++ b/zookeeper-server/src/test/java/org/apache/zookeeper/server/quorum/QuorumPeerMainTest.java
@@ -55,6 +55,7 @@ import org.apache.zookeeper.ZooKeeper;
 import org.apache.zookeeper.ZooDefs.Ids;
 import org.apache.zookeeper.ZooKeeper.States;
 import org.apache.zookeeper.common.Time;
+import org.apache.zookeeper.common.X509Exception;
 import org.apache.zookeeper.data.Stat;
 import org.apache.zookeeper.metrics.BaseTestMetricsProvider;
 import org.apache.zookeeper.metrics.impl.NullMetricsProvider;
@@ -1801,7 +1802,7 @@ public class QuorumPeerMainTest extends QuorumPeerTestBase {
         }
 
         @Override
-        protected Leader makeLeader(FileTxnSnapLog logFactory) throws IOException {
+        protected Leader makeLeader(FileTxnSnapLog logFactory) throws IOException, X509Exception {
             return new Leader(this, new LeaderZooKeeperServer(logFactory,
                     this, this.getZkDb())) {
                 @Override


Mime
View raw message