Author: camille
Date: Wed Sep 11 20:42:24 2013
New Revision: 1522028

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

Modified:
    zookeeper/branches/branch-3.4/CHANGES.txt
    
zookeeper/branches/branch-3.4/src/java/main/org/apache/zookeeper/client/ZooKeeperSaslClient.java
    
zookeeper/branches/branch-3.4/src/java/main/org/apache/zookeeper/server/ZooKeeperSaslServer.java

Modified: zookeeper/branches/branch-3.4/CHANGES.txt
URL: 
http://svn.apache.org/viewvc/zookeeper/branches/branch-3.4/CHANGES.txt?rev=1522028&r1=1522027&r2=1522028&view=diff
==============================================================================
--- zookeeper/branches/branch-3.4/CHANGES.txt (original)
+++ zookeeper/branches/branch-3.4/CHANGES.txt Wed Sep 11 20:42:24 2013
@@ -91,7 +91,8 @@ BUGFIXES:
   ZOOKEEPER-1670: zookeeper should set a default value for SERVER_JVMFLAGS and 
CLIENT_JVMFLAGS so that memory usage is controlled (Arpit Gupta via fpj)
 
   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-1564. Allow JUnit test build with IBM Java

Modified: 
zookeeper/branches/branch-3.4/src/java/main/org/apache/zookeeper/client/ZooKeeperSaslClient.java
URL: 
http://svn.apache.org/viewvc/zookeeper/branches/branch-3.4/src/java/main/org/apache/zookeeper/client/ZooKeeperSaslClient.java?rev=1522028&r1=1522027&r2=1522028&view=diff
==============================================================================
--- 
zookeeper/branches/branch-3.4/src/java/main/org/apache/zookeeper/client/ZooKeeperSaslClient.java
 (original)
+++ 
zookeeper/branches/branch-3.4/src/java/main/org/apache/zookeeper/client/ZooKeeperSaslClient.java
 Wed Sep 11 20:42:24 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/branches/branch-3.4/src/java/main/org/apache/zookeeper/server/ZooKeeperSaslServer.java
URL: 
http://svn.apache.org/viewvc/zookeeper/branches/branch-3.4/src/java/main/org/apache/zookeeper/server/ZooKeeperSaslServer.java?rev=1522028&r1=1522027&r2=1522028&view=diff
==============================================================================
--- 
zookeeper/branches/branch-3.4/src/java/main/org/apache/zookeeper/server/ZooKeeperSaslServer.java
 (original)
+++ 
zookeeper/branches/branch-3.4/src/java/main/org/apache/zookeeper/server/ZooKeeperSaslServer.java
 Wed Sep 11 20:42:24 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);
                     }
                 }
             }


Reply via email to