Repository: cassandra
Updated Branches:
  refs/heads/trunk 298416a74 -> ac1bb7586


Extend IAuthenticator to accept peer SSL certificates

patch by Dinesh Joshi; reviewed by jasobrown for CASSANDRA-14652


Project: http://git-wip-us.apache.org/repos/asf/cassandra/repo
Commit: http://git-wip-us.apache.org/repos/asf/cassandra/commit/ac1bb758
Tree: http://git-wip-us.apache.org/repos/asf/cassandra/tree/ac1bb758
Diff: http://git-wip-us.apache.org/repos/asf/cassandra/diff/ac1bb758

Branch: refs/heads/trunk
Commit: ac1bb75867a9a878a86d9b659234f78772627287
Parents: 298416a
Author: Dinesh A. Joshi <dinesh.jo...@apple.com>
Authored: Thu Aug 16 15:01:20 2018 -0700
Committer: Jason Brown <jasedbr...@gmail.com>
Committed: Fri Aug 17 06:43:45 2018 -0700

----------------------------------------------------------------------
 CHANGES.txt                                     |  1 +
 .../apache/cassandra/auth/IAuthenticator.java   | 18 +++++++++++
 .../cassandra/transport/ServerConnection.java   | 33 +++++++++++++++++++-
 3 files changed, 51 insertions(+), 1 deletion(-)
----------------------------------------------------------------------


http://git-wip-us.apache.org/repos/asf/cassandra/blob/ac1bb758/CHANGES.txt
----------------------------------------------------------------------
diff --git a/CHANGES.txt b/CHANGES.txt
index 0e671b0..d906879 100644
--- a/CHANGES.txt
+++ b/CHANGES.txt
@@ -1,4 +1,5 @@
 4.0
+ * Extend IAuthenticator to accept peer SSL certificates (CASSANDRA-14652)
  * Incomplete handling of exceptions when decoding incoming messages 
(CASSANDRA-14574)
  * Add diagnostic events for user audit logging (CASSANDRA-13668)
  * Allow retrieving diagnostic events via JMX (CASSANDRA-14435)

http://git-wip-us.apache.org/repos/asf/cassandra/blob/ac1bb758/src/java/org/apache/cassandra/auth/IAuthenticator.java
----------------------------------------------------------------------
diff --git a/src/java/org/apache/cassandra/auth/IAuthenticator.java 
b/src/java/org/apache/cassandra/auth/IAuthenticator.java
index 9eb50a7..212e774 100644
--- a/src/java/org/apache/cassandra/auth/IAuthenticator.java
+++ b/src/java/org/apache/cassandra/auth/IAuthenticator.java
@@ -21,6 +21,8 @@ import java.net.InetAddress;
 import java.util.Map;
 import java.util.Set;
 
+import javax.security.cert.X509Certificate;
+
 import org.apache.cassandra.exceptions.AuthenticationException;
 import org.apache.cassandra.exceptions.ConfigurationException;
 
@@ -65,6 +67,22 @@ public interface IAuthenticator
     SaslNegotiator newSaslNegotiator(InetAddress clientAddress);
 
     /**
+     * Provide a SASL handler to perform authentication for an single 
connection. SASL
+     * is a stateful protocol, so a new instance must be used for each 
authentication
+     * attempt. This method accepts certificates as well. Authentication 
strategies can
+     * override this method to gain access to client's certificate chain, if 
present.
+     * @param clientAddress the IP address of the client whom we wish to 
authenticate, or null
+     *                      if an internal client (one not connected over the 
remote transport).
+     * @param certificates the peer's X509 Certificate chain, if present.
+     * @return org.apache.cassandra.auth.IAuthenticator.SaslNegotiator 
implementation
+     * (see {@link 
org.apache.cassandra.auth.PasswordAuthenticator.PlainTextSaslAuthenticator})
+     */
+    default SaslNegotiator newSaslNegotiator(InetAddress clientAddress, 
X509Certificate[] certificates)
+    {
+        return newSaslNegotiator(clientAddress);
+    }
+
+    /**
      * A legacy method that is still used by JMX authentication.
      *
      * You should implement this for having JMX authentication through your

http://git-wip-us.apache.org/repos/asf/cassandra/blob/ac1bb758/src/java/org/apache/cassandra/transport/ServerConnection.java
----------------------------------------------------------------------
diff --git a/src/java/org/apache/cassandra/transport/ServerConnection.java 
b/src/java/org/apache/cassandra/transport/ServerConnection.java
index d78b7c0..00e334c 100644
--- a/src/java/org/apache/cassandra/transport/ServerConnection.java
+++ b/src/java/org/apache/cassandra/transport/ServerConnection.java
@@ -20,8 +20,15 @@ package org.apache.cassandra.transport;
 import java.util.concurrent.ConcurrentHashMap;
 import java.util.concurrent.ConcurrentMap;
 
+import javax.net.ssl.SSLPeerUnverifiedException;
+import javax.security.cert.X509Certificate;
+
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+
 import io.netty.channel.Channel;
 import com.codahale.metrics.Counter;
+import io.netty.handler.ssl.SslHandler;
 import org.apache.cassandra.auth.IAuthenticator;
 import org.apache.cassandra.config.DatabaseDescriptor;
 import org.apache.cassandra.service.ClientState;
@@ -29,6 +36,7 @@ import org.apache.cassandra.service.QueryState;
 
 public class ServerConnection extends Connection
 {
+    private static Logger logger = 
LoggerFactory.getLogger(ServerConnection.class);
 
     private volatile IAuthenticator.SaslNegotiator saslNegotiator;
     private final ClientState clientState;
@@ -124,7 +132,30 @@ public class ServerConnection extends Connection
     public IAuthenticator.SaslNegotiator getSaslNegotiator(QueryState 
queryState)
     {
         if (saslNegotiator == null)
-            saslNegotiator = 
DatabaseDescriptor.getAuthenticator().newSaslNegotiator(queryState.getClientAddress());
+            saslNegotiator = DatabaseDescriptor.getAuthenticator()
+                                               
.newSaslNegotiator(queryState.getClientAddress(), certificates());
         return saslNegotiator;
     }
+
+    private X509Certificate[] certificates()
+    {
+        SslHandler sslHandler = (SslHandler) channel().pipeline()
+                                                      .get("ssl");
+        X509Certificate[] certificates = null;
+
+        if (sslHandler != null)
+        {
+            try
+            {
+                certificates = sslHandler.engine()
+                                         .getSession()
+                                         .getPeerCertificateChain();
+            }
+            catch (SSLPeerUnverifiedException e)
+            {
+                logger.error("Failed to get peer certificates for peer {}", 
channel().remoteAddress(), e);
+            }
+        }
+        return certificates;
+    }
 }


---------------------------------------------------------------------
To unsubscribe, e-mail: commits-unsubscr...@cassandra.apache.org
For additional commands, e-mail: commits-h...@cassandra.apache.org

Reply via email to