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); } } }