You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@zookeeper.apache.org by ca...@apache.org on 2013/09/11 22:44:15 UTC

svn commit: r1522029 - in /zookeeper/trunk: CHANGES.txt src/java/main/org/apache/zookeeper/client/ZooKeeperSaslClient.java src/java/main/org/apache/zookeeper/server/ZooKeeperSaslServer.java

Author: camille
Date: Wed Sep 11 20:44:15 2013
New Revision: 1522029

URL: http://svn.apache.org/r1522029
Log:
 ZOOKEEPER-1664. Kerberos auth doesn't work with native platform GSS integration. (Boaz Kelmer via camille) 
  

Modified:
    zookeeper/trunk/CHANGES.txt
    zookeeper/trunk/src/java/main/org/apache/zookeeper/client/ZooKeeperSaslClient.java
    zookeeper/trunk/src/java/main/org/apache/zookeeper/server/ZooKeeperSaslServer.java

Modified: zookeeper/trunk/CHANGES.txt
URL: http://svn.apache.org/viewvc/zookeeper/trunk/CHANGES.txt?rev=1522029&r1=1522028&r2=1522029&view=diff
==============================================================================
--- zookeeper/trunk/CHANGES.txt (original)
+++ zookeeper/trunk/CHANGES.txt Wed Sep 11 20:44:15 2013
@@ -374,6 +374,8 @@ BUGFIXES:
 
   ZOOKEEPER-1448. Node+Quota creation in transaction log can crash leader startup (Botond Hejj via fpj)
   
+  ZOOKEEPER-1664. Kerberos auth doesn't work with native platform GSS integration. (Boaz Kelmer via camille) 
+  
 IMPROVEMENTS:
 
   ZOOKEEPER-1170. Fix compiler (eclipse) warnings: unused imports,

Modified: zookeeper/trunk/src/java/main/org/apache/zookeeper/client/ZooKeeperSaslClient.java
URL: http://svn.apache.org/viewvc/zookeeper/trunk/src/java/main/org/apache/zookeeper/client/ZooKeeperSaslClient.java?rev=1522029&r1=1522028&r2=1522029&view=diff
==============================================================================
--- zookeeper/trunk/src/java/main/org/apache/zookeeper/client/ZooKeeperSaslClient.java (original)
+++ zookeeper/trunk/src/java/main/org/apache/zookeeper/client/ZooKeeperSaslClient.java Wed Sep 11 20:44:15 2013
@@ -18,23 +18,11 @@
 
 package org.apache.zookeeper.client;
 
-import org.apache.zookeeper.AsyncCallback;
-import org.apache.zookeeper.ClientCnxn;
-import org.apache.zookeeper.Login;
-import org.apache.zookeeper.Watcher.Event.KeeperState;
-import org.apache.zookeeper.ZooDefs;
-import org.apache.zookeeper.Environment;
-import org.apache.zookeeper.data.Stat;
-import org.apache.zookeeper.proto.GetSASLRequest;
-import org.apache.zookeeper.proto.SetSASLResponse;
-import org.apache.zookeeper.server.auth.KerberosName;
-import org.slf4j.Logger;
-import org.slf4j.LoggerFactory;
-
 import java.io.IOException;
 import java.security.Principal;
 import java.security.PrivilegedActionException;
 import java.security.PrivilegedExceptionAction;
+
 import javax.security.auth.Subject;
 import javax.security.auth.callback.Callback;
 import javax.security.auth.callback.CallbackHandler;
@@ -50,6 +38,24 @@ import javax.security.sasl.Sasl;
 import javax.security.sasl.SaslClient;
 import javax.security.sasl.SaslException;
 
+import org.apache.zookeeper.AsyncCallback;
+import org.apache.zookeeper.ClientCnxn;
+import org.apache.zookeeper.Environment;
+import org.apache.zookeeper.Login;
+import org.apache.zookeeper.Watcher.Event.KeeperState;
+import org.apache.zookeeper.ZooDefs;
+import org.apache.zookeeper.data.Stat;
+import org.apache.zookeeper.proto.GetSASLRequest;
+import org.apache.zookeeper.proto.SetSASLResponse;
+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.Oid;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+
 /**
  * This class manages SASL authentication for the client. It
  * allows ClientCnxn to authenticate using SASL with a Zookeeper server.
@@ -213,6 +219,33 @@ public class ZooKeeperSaslClient {
                 return saslClient;
             }
             else { // GSSAPI.
+            	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);
+            			if (LOG.isDebugEnabled()) {
+            				LOG.debug("Added private credential to subject: " + cred);
+            			}
+            		} catch (GSSException ex) {
+            			LOG.warn("Cannot add private credential to subject; " +
+            					"authentication at the server may fail", ex);
+            		}
+            	}
                 final Object[] principals = subject.getPrincipals().toArray();
                 // determine client principal from subject.
                 final Principal clientPrincipal = (Principal)principals[0];
@@ -237,7 +270,7 @@ public class ZooKeeperSaslClient {
                     return saslClient;
                 }
                 catch (Exception e) {
-                    LOG.error("Error creating SASL client:" + e);
+                	LOG.error("Exception while trying to create SASL client", e);
                     e.printStackTrace();
                     return null;
                 }

Modified: zookeeper/trunk/src/java/main/org/apache/zookeeper/server/ZooKeeperSaslServer.java
URL: http://svn.apache.org/viewvc/zookeeper/trunk/src/java/main/org/apache/zookeeper/server/ZooKeeperSaslServer.java?rev=1522029&r1=1522028&r2=1522029&view=diff
==============================================================================
--- zookeeper/trunk/src/java/main/org/apache/zookeeper/server/ZooKeeperSaslServer.java (original)
+++ zookeeper/trunk/src/java/main/org/apache/zookeeper/server/ZooKeeperSaslServer.java Wed Sep 11 20:44:15 2013
@@ -21,13 +21,21 @@ package org.apache.zookeeper.server;
 import java.security.Principal;
 import java.security.PrivilegedActionException;
 import java.security.PrivilegedExceptionAction;
-import org.slf4j.Logger;
-import org.slf4j.LoggerFactory;
+
 import javax.security.auth.Subject;
 import javax.security.sasl.Sasl;
 import javax.security.sasl.SaslException;
 import javax.security.sasl.SaslServer;
+
 import org.apache.zookeeper.Login;
+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;
+import org.slf4j.LoggerFactory;
 
 public class ZooKeeperSaslServer {
     public static final String LOGIN_CONTEXT_NAME_KEY = "zookeeper.sasl.serverconfig";
@@ -68,9 +76,40 @@ public class ZooKeeperSaslServer {
                         final String mech = "GSSAPI";   // TODO: should depend on zoo.cfg specified mechs, but if subject is non-null, it can be assumed to be GSSAPI.
 
                         LOG.debug("serviceHostname is '"+ serviceHostname + "'");
-                        LOG.debug("servicePrincipalName is "+ servicePrincipalName + "'");
-                        LOG.debug("SASL mechanism(mech) is "+ mech +"'");
+                        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);
+                        		if (LOG.isDebugEnabled()) {
+                        			LOG.debug("Added private credential to subject: " + cred);
+                        		}
+                        	} 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() {
@@ -94,8 +133,8 @@ public class ZooKeeperSaslServer {
                             e.printStackTrace();
                         }
                     }
-                    catch (Exception e) {
-                        LOG.error("server principal name/hostname determination error: " + e);
+                    catch (IndexOutOfBoundsException e) {
+                        LOG.error("server principal name/hostname determination error: ", e);
                     }
                 }
                 else {
@@ -106,7 +145,7 @@ public class ZooKeeperSaslServer {
                         return saslServer;
                     }
                     catch (SaslException e) {
-                        LOG.error("Zookeeper Quorum member failed to create a SaslServer to interact with a client during session initiation: " + e);
+                        LOG.error("Zookeeper Quorum member failed to create a SaslServer to interact with a client during session initiation", e);
                     }
                 }
             }