You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@directory.apache.org by co...@apache.org on 2015/05/01 12:23:56 UTC

directory-kerby git commit: Adding a GSS UDP interop test

Repository: directory-kerby
Updated Branches:
  refs/heads/master 14a1e2556 -> 933280e54


Adding a GSS UDP interop test


Project: http://git-wip-us.apache.org/repos/asf/directory-kerby/repo
Commit: http://git-wip-us.apache.org/repos/asf/directory-kerby/commit/933280e5
Tree: http://git-wip-us.apache.org/repos/asf/directory-kerby/tree/933280e5
Diff: http://git-wip-us.apache.org/repos/asf/directory-kerby/diff/933280e5

Branch: refs/heads/master
Commit: 933280e5476eacc6e7c4d5d761ab3a48f9d35628
Parents: 14a1e25
Author: Colm O hEigeartaigh <co...@apache.org>
Authored: Fri May 1 11:23:34 2015 +0100
Committer: Colm O hEigeartaigh <co...@apache.org>
Committed: Fri May 1 11:23:34 2015 +0100

----------------------------------------------------------------------
 .../kerby/kerberos/kdc/GSSInteropTestBase.java  | 225 +++++++++++++++++++
 .../kerby/kerberos/kdc/GSSTCPInteropTest.java   |  69 ++++++
 .../kerby/kerberos/kdc/GSSUDPInteropTest.java   |  69 ++++++
 .../org/apache/kerby/kerberos/kdc/KdcTest.java  |  62 +++++
 kerby-kdc-test/src/test/resources/kerberos.jaas |   8 +
 kerby-kdc-test/src/test/resources/krb5-udp.conf |   7 +
 kerby-kdc-test/src/test/resources/krb5.conf     |   8 +
 .../server/impl/AbstractInternalKdcServer.java  |   2 +-
 8 files changed, 449 insertions(+), 1 deletion(-)
----------------------------------------------------------------------


http://git-wip-us.apache.org/repos/asf/directory-kerby/blob/933280e5/kerby-kdc-test/src/test/java/org/apache/kerby/kerberos/kdc/GSSInteropTestBase.java
----------------------------------------------------------------------
diff --git a/kerby-kdc-test/src/test/java/org/apache/kerby/kerberos/kdc/GSSInteropTestBase.java b/kerby-kdc-test/src/test/java/org/apache/kerby/kerberos/kdc/GSSInteropTestBase.java
new file mode 100644
index 0000000..da5369c
--- /dev/null
+++ b/kerby-kdc-test/src/test/java/org/apache/kerby/kerberos/kdc/GSSInteropTestBase.java
@@ -0,0 +1,225 @@
+/**
+ *  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.kerby.kerberos.kdc;
+
+import java.io.IOException;
+import java.security.Principal;
+import java.security.PrivilegedExceptionAction;
+import java.util.Set;
+
+import javax.security.auth.Subject;
+import javax.security.auth.callback.Callback;
+import javax.security.auth.callback.CallbackHandler;
+import javax.security.auth.callback.PasswordCallback;
+import javax.security.auth.callback.UnsupportedCallbackException;
+import javax.security.auth.kerberos.KerberosTicket;
+import javax.security.auth.login.LoginContext;
+
+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.junit.Assert;
+import org.junit.Test;
+import org.apache.kerby.kerberos.kdc.impl.NettyKdcServerImpl;
+import org.apache.kerby.kerberos.kerb.server.KdcConfigKey;
+import org.apache.kerby.kerberos.kerb.server.TestKdcServer;
+
+/**
+ * This is an interop test using the Java GSS APIs against the Kerby KDC
+ */
+public abstract class GSSInteropTestBase extends KdcTest {
+    
+    @Override
+    protected void setUpKdcServer() throws Exception {
+        kdcServer = new TestKdcServer();
+        prepareKdcServer();
+        
+        kdcServer.setInnerKdcImpl(new NettyKdcServerImpl());
+        kdcServer.init();
+        
+        // Must disable pre-auth
+        kdcServer.getSetting().getKdcConfig().setBoolean(KdcConfigKey.PREAUTH_REQUIRED, false);
+        
+        kdcRealm = kdcServer.getKdcRealm();
+        clientPrincipal = "drankye@" + kdcRealm;
+        serverPrincipal = "test-service/localhost@" + kdcRealm;
+    }
+    
+    @Override
+    protected void createPrincipals() {
+        kdcServer.createTgsPrincipal();
+        kdcServer.createPrincipal(serverPrincipal, TEST_PASSWORD);
+        kdcServer.createPrincipal(clientPrincipal, TEST_PASSWORD);
+    }
+    
+    @Test
+    public void testKdc() throws Exception {
+        kdcServer.start();
+        
+        LoginContext loginContext = new LoginContext("drankye", new KerberosCallbackHandler());
+        loginContext.login();
+        
+        Subject clientSubject = loginContext.getSubject();
+        Set<Principal> clientPrincipals = clientSubject.getPrincipals();
+        Assert.assertFalse(clientPrincipals.isEmpty());
+
+        // Get the TGT
+        Set<KerberosTicket> privateCredentials = 
+            clientSubject.getPrivateCredentials(KerberosTicket.class);
+        Assert.assertFalse(privateCredentials.isEmpty());
+        KerberosTicket tgt = privateCredentials.iterator().next();
+        Assert.assertNotNull(tgt);
+
+        // Get the service ticket
+        KerberosClientExceptionAction action =
+            new KerberosClientExceptionAction(clientPrincipals.iterator().next(), 
+                                              "test-service/localhost@TEST.COM");
+        
+        byte[] kerberosToken = (byte[]) Subject.doAs(clientSubject, action);
+        Assert.assertNotNull(kerberosToken);
+        
+        loginContext.logout();
+        
+        validateServiceTicket(kerberosToken);
+        
+        kdcServer.stop();
+    }
+    
+    private void validateServiceTicket(byte[] ticket) throws Exception {
+        // Get the TGT for the service
+        LoginContext loginContext = new LoginContext("test-service", new KerberosCallbackHandler());
+        loginContext.login();
+        
+        Subject serviceSubject = loginContext.getSubject();
+        Set<Principal> servicePrincipals = serviceSubject.getPrincipals();
+        Assert.assertFalse(servicePrincipals.isEmpty());
+
+        // Handle the service ticket
+        KerberosServiceExceptionAction serviceAction = 
+            new KerberosServiceExceptionAction(ticket, "test-service@TEST.COM");
+        
+        Subject.doAs(serviceSubject, serviceAction);
+    }
+    
+    private static class KerberosCallbackHandler implements CallbackHandler {
+
+        public void handle(Callback[] callbacks) throws IOException,
+                UnsupportedCallbackException {
+            for (int i = 0; i < callbacks.length; i++) {
+                if (callbacks[i] instanceof PasswordCallback) {
+                    PasswordCallback pc = (PasswordCallback) callbacks[i];
+                    if (pc.getPrompt().contains("drankye")) {
+                        pc.setPassword(TEST_PASSWORD.toCharArray());
+                        break;
+                    } else if (pc.getPrompt().contains("test-service")) {
+                        pc.setPassword(TEST_PASSWORD.toCharArray());
+                        break;
+                    }
+                }
+            }
+        }
+    }
+    
+    /**
+     * This class represents a PrivilegedExceptionAction implementation to obtain a service ticket from a Kerberos
+     * Key Distribution Center.
+     */
+    private static class KerberosClientExceptionAction implements PrivilegedExceptionAction<byte[]> {
+
+        private static final String JGSS_KERBEROS_TICKET_OID = "1.2.840.113554.1.2.2";
+        
+        private Principal clientPrincipal;
+        private String serviceName;
+
+        public KerberosClientExceptionAction(Principal clientPrincipal, String serviceName) { 
+            this.clientPrincipal = clientPrincipal;
+            this.serviceName = serviceName;
+        }
+        
+        public byte[] run() throws GSSException {
+            GSSManager gssManager = GSSManager.getInstance();
+
+            GSSName gssService = gssManager.createName(serviceName, GSSName.NT_USER_NAME);
+            Oid oid = new Oid(JGSS_KERBEROS_TICKET_OID);
+            GSSName gssClient = gssManager.createName(clientPrincipal.getName(), GSSName.NT_USER_NAME);
+            GSSCredential credentials = 
+                gssManager.createCredential(
+                    gssClient, GSSCredential.DEFAULT_LIFETIME, oid, GSSCredential.INITIATE_ONLY
+                );
+
+            GSSContext secContext =
+                gssManager.createContext(
+                    gssService, oid, credentials, GSSContext.DEFAULT_LIFETIME
+                );
+
+            secContext.requestMutualAuth(false);
+            secContext.requestCredDeleg(false);
+
+            try {
+                byte[] token = new byte[0];
+                byte[] returnedToken = secContext.initSecContext(token, 0, token.length);
+
+                return returnedToken;
+            } finally {
+                secContext.dispose();
+            }
+        }
+    }
+    
+    private static class KerberosServiceExceptionAction implements PrivilegedExceptionAction<byte[]> {
+
+        private static final String JGSS_KERBEROS_TICKET_OID = "1.2.840.113554.1.2.2";
+
+        private byte[] ticket;
+        private String serviceName;
+
+        public KerberosServiceExceptionAction(byte[] ticket, String serviceName) {
+            this.ticket = ticket;
+            this.serviceName = serviceName;
+        }
+
+        public byte[] run() throws GSSException {
+
+            GSSManager gssManager = GSSManager.getInstance();
+
+            GSSContext secContext = null;
+            GSSName gssService = gssManager.createName(serviceName, GSSName.NT_HOSTBASED_SERVICE);
+              
+            Oid oid = new Oid(JGSS_KERBEROS_TICKET_OID);
+            GSSCredential credentials = 
+                gssManager.createCredential(
+                    gssService, GSSCredential.DEFAULT_LIFETIME, oid, GSSCredential.ACCEPT_ONLY
+                );
+            secContext = gssManager.createContext(credentials);
+
+            try {
+                return secContext.acceptSecContext(ticket, 0, ticket.length);
+            } finally {
+                if (null != secContext) {
+                    secContext.dispose();    
+                }
+            }               
+        }
+
+    }
+}
\ No newline at end of file

http://git-wip-us.apache.org/repos/asf/directory-kerby/blob/933280e5/kerby-kdc-test/src/test/java/org/apache/kerby/kerberos/kdc/GSSTCPInteropTest.java
----------------------------------------------------------------------
diff --git a/kerby-kdc-test/src/test/java/org/apache/kerby/kerberos/kdc/GSSTCPInteropTest.java b/kerby-kdc-test/src/test/java/org/apache/kerby/kerberos/kdc/GSSTCPInteropTest.java
new file mode 100644
index 0000000..bc99ea9
--- /dev/null
+++ b/kerby-kdc-test/src/test/java/org/apache/kerby/kerberos/kdc/GSSTCPInteropTest.java
@@ -0,0 +1,69 @@
+/**
+ *  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.kerby.kerberos.kdc;
+
+import java.io.File;
+import java.io.FileInputStream;
+import java.io.FileOutputStream;
+
+import org.apache.commons.io.IOUtils;
+import org.junit.Before;
+
+/**
+ * This is an interop test using the Java GSS APIs against the Kerby KDC (using TCP)
+ */
+public class GSSTCPInteropTest extends GSSInteropTestBase {
+    
+    @Before
+    @Override
+    public void setUp() throws Exception {
+        super.setUp();
+        
+        String basedir = System.getProperty("basedir");
+        if (basedir == null) {
+            basedir = new File(".").getCanonicalPath();
+        }
+        
+        // System.setProperty("sun.security.krb5.debug", "true");
+        System.setProperty("java.security.auth.login.config", 
+                           basedir + "/src/test/resources/kerberos.jaas");
+        
+        // Read in krb5.conf and substitute in the correct port
+        File f = new File(basedir + "/src/test/resources/krb5.conf");
+
+        FileInputStream inputStream = new FileInputStream(f);
+        String content = IOUtils.toString(inputStream, "UTF-8");
+        inputStream.close();
+        content = content.replaceAll("port", "" + tcpPort);
+
+        File f2 = new File(basedir + "/target/test-classes/krb5.conf");
+        FileOutputStream outputStream = new FileOutputStream(f2);
+        IOUtils.write(content, outputStream, "UTF-8");
+        outputStream.close();
+
+        System.setProperty("java.security.krb5.conf", f2.getPath());
+    }
+
+    @Override
+    protected boolean allowUdp() {
+        return false;
+    }
+
+}
\ No newline at end of file

http://git-wip-us.apache.org/repos/asf/directory-kerby/blob/933280e5/kerby-kdc-test/src/test/java/org/apache/kerby/kerberos/kdc/GSSUDPInteropTest.java
----------------------------------------------------------------------
diff --git a/kerby-kdc-test/src/test/java/org/apache/kerby/kerberos/kdc/GSSUDPInteropTest.java b/kerby-kdc-test/src/test/java/org/apache/kerby/kerberos/kdc/GSSUDPInteropTest.java
new file mode 100644
index 0000000..157c706
--- /dev/null
+++ b/kerby-kdc-test/src/test/java/org/apache/kerby/kerberos/kdc/GSSUDPInteropTest.java
@@ -0,0 +1,69 @@
+/**
+ *  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.kerby.kerberos.kdc;
+
+import java.io.File;
+import java.io.FileInputStream;
+import java.io.FileOutputStream;
+
+import org.apache.commons.io.IOUtils;
+import org.junit.Before;
+
+/**
+ * This is an interop test using the Java GSS APIs against the Kerby KDC (using UDP)
+ */
+public class GSSUDPInteropTest extends GSSInteropTestBase {
+    
+    @Before
+    @Override
+    public void setUp() throws Exception {
+        super.setUp();
+        
+        String basedir = System.getProperty("basedir");
+        if (basedir == null) {
+            basedir = new File(".").getCanonicalPath();
+        }
+        
+        // System.setProperty("sun.security.krb5.debug", "true");
+        System.setProperty("java.security.auth.login.config", 
+                           basedir + "/src/test/resources/kerberos.jaas");
+        
+        // Read in krb5.conf and substitute in the correct port
+        File f = new File(basedir + "/src/test/resources/krb5-udp.conf");
+
+        FileInputStream inputStream = new FileInputStream(f);
+        String content = IOUtils.toString(inputStream, "UTF-8");
+        inputStream.close();
+        content = content.replaceAll("port", "" + udpPort);
+
+        File f2 = new File(basedir + "/target/test-classes/krb5-udp.conf");
+        FileOutputStream outputStream = new FileOutputStream(f2);
+        IOUtils.write(content, outputStream, "UTF-8");
+        outputStream.close();
+
+        System.setProperty("java.security.krb5.conf", f2.getPath());
+    }
+
+    @Override
+    protected boolean allowUdp() {
+        return true;
+    }
+
+}
\ No newline at end of file

http://git-wip-us.apache.org/repos/asf/directory-kerby/blob/933280e5/kerby-kdc-test/src/test/java/org/apache/kerby/kerberos/kdc/KdcTest.java
----------------------------------------------------------------------
diff --git a/kerby-kdc-test/src/test/java/org/apache/kerby/kerberos/kdc/KdcTest.java b/kerby-kdc-test/src/test/java/org/apache/kerby/kerberos/kdc/KdcTest.java
new file mode 100644
index 0000000..dd827b5
--- /dev/null
+++ b/kerby-kdc-test/src/test/java/org/apache/kerby/kerberos/kdc/KdcTest.java
@@ -0,0 +1,62 @@
+/**
+ *  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.kerby.kerberos.kdc;
+
+import org.apache.kerby.kerberos.kerb.server.KdcTestBase;
+import org.apache.kerby.kerberos.kerb.spec.ticket.ServiceTicket;
+import org.apache.kerby.kerberos.kerb.spec.ticket.TgtTicket;
+import org.junit.Assert;
+
+import java.io.File;
+
+import static org.assertj.core.api.Assertions.assertThat;
+
+public abstract class KdcTest extends KdcTestBase {
+
+    @Override
+    protected void createPrincipals() {
+        super.createPrincipals();
+        kdcServer.createPrincipal(clientPrincipal, TEST_PASSWORD);
+    }
+
+    protected void performKdcTest() throws Exception {
+        kdcServer.start();
+
+        File testDir = new File(System.getProperty("test.dir", "target"));
+        File testConfDir = new File(testDir, "conf");
+        krbClnt.setConfDir(testConfDir);
+        krbClnt.init();
+
+        TgtTicket tgt;
+        ServiceTicket tkt;
+
+        try {
+            tgt = krbClnt.requestTgtWithPassword(clientPrincipal, TEST_PASSWORD);
+            assertThat(tgt).isNotNull();
+
+            tkt = krbClnt.requestServiceTicketWithTgt(tgt, serverPrincipal);
+            assertThat(tkt).isNotNull();
+        } catch (Exception e) {
+            System.out.println("Exception occurred with good password");
+            e.printStackTrace();
+            Assert.fail();
+        }
+    }
+}
\ No newline at end of file

http://git-wip-us.apache.org/repos/asf/directory-kerby/blob/933280e5/kerby-kdc-test/src/test/resources/kerberos.jaas
----------------------------------------------------------------------
diff --git a/kerby-kdc-test/src/test/resources/kerberos.jaas b/kerby-kdc-test/src/test/resources/kerberos.jaas
new file mode 100644
index 0000000..9bcdd0c
--- /dev/null
+++ b/kerby-kdc-test/src/test/resources/kerberos.jaas
@@ -0,0 +1,8 @@
+
+drankye {
+    com.sun.security.auth.module.Krb5LoginModule required refreshKrb5Config=true useKeyTab=false principal="drankye";
+};
+
+test-service {
+    com.sun.security.auth.module.Krb5LoginModule required refreshKrb5Config=true useKeyTab=false storeKey=true principal="test-service/localhost";
+};

http://git-wip-us.apache.org/repos/asf/directory-kerby/blob/933280e5/kerby-kdc-test/src/test/resources/krb5-udp.conf
----------------------------------------------------------------------
diff --git a/kerby-kdc-test/src/test/resources/krb5-udp.conf b/kerby-kdc-test/src/test/resources/krb5-udp.conf
new file mode 100644
index 0000000..d8deffc
--- /dev/null
+++ b/kerby-kdc-test/src/test/resources/krb5-udp.conf
@@ -0,0 +1,7 @@
+[libdefaults]
+	default_realm = TEST.COM
+
+[realms]
+	TEST.COM = {
+		kdc = localhost:port
+	}
\ No newline at end of file

http://git-wip-us.apache.org/repos/asf/directory-kerby/blob/933280e5/kerby-kdc-test/src/test/resources/krb5.conf
----------------------------------------------------------------------
diff --git a/kerby-kdc-test/src/test/resources/krb5.conf b/kerby-kdc-test/src/test/resources/krb5.conf
new file mode 100644
index 0000000..e2fa16a
--- /dev/null
+++ b/kerby-kdc-test/src/test/resources/krb5.conf
@@ -0,0 +1,8 @@
+[libdefaults]
+	default_realm = TEST.COM
+	udp_preference_limit = 1
+
+[realms]
+	TEST.COM = {
+		kdc = localhost:port
+	}
\ No newline at end of file

http://git-wip-us.apache.org/repos/asf/directory-kerby/blob/933280e5/kerby-kerb/kerb-server/src/main/java/org/apache/kerby/kerberos/kerb/server/impl/AbstractInternalKdcServer.java
----------------------------------------------------------------------
diff --git a/kerby-kerb/kerb-server/src/main/java/org/apache/kerby/kerberos/kerb/server/impl/AbstractInternalKdcServer.java b/kerby-kerb/kerb-server/src/main/java/org/apache/kerby/kerberos/kerb/server/impl/AbstractInternalKdcServer.java
index f861cbb..c22b503 100644
--- a/kerby-kerb/kerb-server/src/main/java/org/apache/kerby/kerberos/kerb/server/impl/AbstractInternalKdcServer.java
+++ b/kerby-kerb/kerb-server/src/main/java/org/apache/kerby/kerberos/kerb/server/impl/AbstractInternalKdcServer.java
@@ -112,7 +112,7 @@ public class AbstractInternalKdcServer implements InternalKdcServer {
             backendClassName = MemoryIdentityBackend.class.getCanonicalName();
         }
 
-        Class backendClass = null;
+        Class<?> backendClass = null;
         try {
             backendClass = Class.forName(backendClassName);
         } catch (ClassNotFoundException e) {