You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@karaf.apache.org by ja...@apache.org on 2014/04/30 16:50:46 UTC

git commit: KARAF-2957 - LDAP login module cannot handle slashes in CN

Repository: karaf
Updated Branches:
  refs/heads/karaf-2.x 4b8cc1022 -> b7e0aa921


KARAF-2957 - LDAP login module cannot handle slashes in CN


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

Branch: refs/heads/karaf-2.x
Commit: b7e0aa921db7fd3c777da4b836b27ab57da46b13
Parents: 4b8cc10
Author: Jonathan Anstey <ja...@gmail.com>
Authored: Wed Apr 30 12:20:02 2014 -0230
Committer: Jonathan Anstey <ja...@gmail.com>
Committed: Wed Apr 30 12:20:02 2014 -0230

----------------------------------------------------------------------
 jaas/modules/pom.xml                            |  12 ++
 .../jaas/modules/ldap/LDAPLoginModule.java      |  12 +-
 .../jaas/modules/ldap/LdapLoginModuleTest.java  | 186 +++++++++++++++++++
 .../ldap/LdapLoginModuleWithEscapesTest.java    |  35 ++++
 .../modules/src/test/resources/log4j.properties |  34 ++++
 .../karaf/jaas/modules/ldap/example.com.ldif    |  58 ++++++
 .../modules/ldap/example.com_with_escapes.ldif  |  58 ++++++
 .../karaf/jaas/modules/ldap/ldap.properties     |  36 ++++
 pom.xml                                         |   1 +
 9 files changed, 431 insertions(+), 1 deletion(-)
----------------------------------------------------------------------


http://git-wip-us.apache.org/repos/asf/karaf/blob/b7e0aa92/jaas/modules/pom.xml
----------------------------------------------------------------------
diff --git a/jaas/modules/pom.xml b/jaas/modules/pom.xml
index e41c2e0..376de9e 100644
--- a/jaas/modules/pom.xml
+++ b/jaas/modules/pom.xml
@@ -86,6 +86,18 @@
             <artifactId>org.apache.aries.blueprint.core</artifactId>
             <scope>provided</scope>
         </dependency>
+        <dependency>
+            <groupId>org.apache.directory.server</groupId>
+            <artifactId>apacheds-core-integ</artifactId>
+            <version>${directory-version}</version>
+            <scope>test</scope>
+        </dependency>
+        <dependency>
+            <groupId>org.apache.directory.server</groupId>
+            <artifactId>apacheds-server-integ</artifactId>
+            <version>${directory-version}</version>
+            <scope>test</scope>
+        </dependency>
     </dependencies>
 
     <build>

http://git-wip-us.apache.org/repos/asf/karaf/blob/b7e0aa92/jaas/modules/src/main/java/org/apache/karaf/jaas/modules/ldap/LDAPLoginModule.java
----------------------------------------------------------------------
diff --git a/jaas/modules/src/main/java/org/apache/karaf/jaas/modules/ldap/LDAPLoginModule.java b/jaas/modules/src/main/java/org/apache/karaf/jaas/modules/ldap/LDAPLoginModule.java
index c3b55db..0ddc83f 100644
--- a/jaas/modules/src/main/java/org/apache/karaf/jaas/modules/ldap/LDAPLoginModule.java
+++ b/jaas/modules/src/main/java/org/apache/karaf/jaas/modules/ldap/LDAPLoginModule.java
@@ -214,7 +214,17 @@ public class LDAPLoginModule extends AbstractKarafLoginModule {
             }
             logger.debug("Get the user DN.");
             SearchResult result = (SearchResult) namingEnumeration.next();
-            userDN = (String) result.getName();
+            
+            // We need to do the following because slashes are handled badly. For example, when searching 
+            // for a user with lots of special characters like cn=admin,=+<>#;\
+            // SearchResult contains 2 different results:
+            // 
+            // SearchResult.getName = cn=admin\,\=\+\<\>\#\;\\\\
+            // SearchResult.getNameInNamespace = cn=admin\,\=\+\<\>#\;\\,ou=people,dc=example,dc=com
+            //
+            // the second escapes the slashes correctly.
+            userDN = result.getNameInNamespace().replace("," + userBaseDN, "");
+            
             namingEnumeration.close();
         } catch (Exception e) {
             throw new LoginException("Can't connect to the LDAP server: " + e.getMessage());

http://git-wip-us.apache.org/repos/asf/karaf/blob/b7e0aa92/jaas/modules/src/test/java/org/apache/karaf/jaas/modules/ldap/LdapLoginModuleTest.java
----------------------------------------------------------------------
diff --git a/jaas/modules/src/test/java/org/apache/karaf/jaas/modules/ldap/LdapLoginModuleTest.java b/jaas/modules/src/test/java/org/apache/karaf/jaas/modules/ldap/LdapLoginModuleTest.java
new file mode 100644
index 0000000..40604d0
--- /dev/null
+++ b/jaas/modules/src/test/java/org/apache/karaf/jaas/modules/ldap/LdapLoginModuleTest.java
@@ -0,0 +1,186 @@
+/*
+ *
+ *  Licensed 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.
+ *  under the License.
+ */
+
+package org.apache.karaf.jaas.modules.ldap;
+
+import org.apache.directory.server.core.integ.AbstractLdapTestUnit;
+import org.apache.directory.server.core.integ.FrameworkRunner;
+import org.apache.directory.server.annotations.CreateLdapServer;
+import org.apache.directory.server.annotations.CreateTransport;
+import org.apache.directory.server.core.annotations.ApplyLdifFiles;
+import org.apache.directory.server.core.annotations.CreateDS;
+import org.apache.directory.server.core.annotations.CreatePartition;
+import org.apache.felix.utils.properties.Properties;
+import org.apache.karaf.jaas.boot.principal.RolePrincipal;
+import org.apache.karaf.jaas.boot.principal.UserPrincipal;
+import org.junit.Test;
+import org.junit.runner.RunWith;
+
+import javax.security.auth.Subject;
+import javax.security.auth.callback.*;
+
+import java.io.File;
+import java.io.IOException;
+import java.security.Principal;
+
+import static org.junit.Assert.assertFalse;
+import static org.junit.Assert.assertTrue;
+import static org.junit.Assert.assertEquals;
+
+
+@RunWith ( FrameworkRunner.class )
+@CreateLdapServer(transports = {@CreateTransport(protocol = "LDAP", port=9999)})
+@CreateDS(name = "LdapLoginModuleTest-class",
+ partitions = { @CreatePartition(name = "example", suffix = "dc=example,dc=com") })
+@ApplyLdifFiles(
+   "org/apache/karaf/jaas/modules/ldap/example.com.ldif"
+)
+public class LdapLoginModuleTest extends AbstractLdapTestUnit {
+
+    @Test
+    public void testAdminLogin() throws Exception {
+        Properties options = ldapLoginModuleOptions();
+        LDAPLoginModule module = new LDAPLoginModule();
+        CallbackHandler cb = new CallbackHandler() {
+            public void handle(Callback[] callbacks) throws IOException, UnsupportedCallbackException {
+                for (Callback cb : callbacks) {
+                    if (cb instanceof NameCallback) {
+                        ((NameCallback) cb).setName("admin");
+                    } else if (cb instanceof PasswordCallback) {
+                        ((PasswordCallback) cb).setPassword("admin123".toCharArray());
+                    }
+                }
+            }
+        };
+        Subject subject = new Subject();
+        module.initialize(subject, cb, null, options);
+
+        assertEquals("Precondition", 0, subject.getPrincipals().size());
+        assertTrue(module.login());
+        assertTrue(module.commit());
+
+        assertEquals(2, subject.getPrincipals().size());
+
+        boolean foundUser = false;
+        boolean foundRole = false;
+        for (Principal pr : subject.getPrincipals()) {
+            if (pr instanceof UserPrincipal) {
+                assertEquals("admin", pr.getName());
+                foundUser = true;
+            } else if (pr instanceof RolePrincipal) {
+                assertEquals("admin", pr.getName());
+                foundRole = true;
+            }
+        }
+        assertTrue(foundUser);
+        assertTrue(foundRole);
+
+        assertTrue(module.logout());
+        assertEquals("Principals should be gone as the user has logged out", 0, subject.getPrincipals().size());        
+    }
+
+    protected Properties ldapLoginModuleOptions() throws IOException {
+        return new Properties(new File("src/test/resources/org/apache/karaf/jaas/modules/ldap/ldap.properties"));
+    }
+    
+    @Test
+    public void testNonAdminLogin() throws Exception {
+        Properties options = ldapLoginModuleOptions();
+        LDAPLoginModule module = new LDAPLoginModule();
+        CallbackHandler cb = new CallbackHandler() {
+            public void handle(Callback[] callbacks) throws IOException, UnsupportedCallbackException {
+                for (Callback cb : callbacks) {
+                    if (cb instanceof NameCallback) {
+                        ((NameCallback) cb).setName("cheese");
+                    } else if (cb instanceof PasswordCallback) {
+                        ((PasswordCallback) cb).setPassword("foodie".toCharArray());
+                    }
+                }
+            }
+        };
+        Subject subject = new Subject();
+        module.initialize(subject, cb, null, options);
+
+        assertEquals("Precondition", 0, subject.getPrincipals().size());
+        assertTrue(module.login());
+        assertTrue(module.commit());
+
+        assertEquals(1, subject.getPrincipals().size());
+
+        boolean foundUser = false;
+        boolean foundRole = false;
+        for (Principal pr : subject.getPrincipals()) {
+            if (pr instanceof UserPrincipal) {
+                assertEquals("cheese", pr.getName());
+                foundUser = true;
+            } else if (pr instanceof RolePrincipal) {
+                assertEquals("admin", pr.getName());
+                foundRole = true;
+            }
+        }
+        assertTrue(foundUser);
+        // cheese is not an admin so no roles should be returned
+        assertFalse(foundRole);
+
+        assertTrue(module.logout());
+        assertEquals("Principals should be gone as the user has logged out", 0, subject.getPrincipals().size());        
+    }
+    
+    @Test
+    public void testBadPassword() throws Exception {
+        Properties options = ldapLoginModuleOptions();
+        LDAPLoginModule module = new LDAPLoginModule();
+        CallbackHandler cb = new CallbackHandler() {
+            public void handle(Callback[] callbacks) throws IOException, UnsupportedCallbackException {
+                for (Callback cb : callbacks) {
+                    if (cb instanceof NameCallback) {
+                        ((NameCallback) cb).setName("admin");
+                    } else if (cb instanceof PasswordCallback) {
+                        ((PasswordCallback) cb).setPassword("blahblah".toCharArray());
+                    }
+                }
+            }
+        };
+        Subject subject = new Subject();
+        module.initialize(subject, cb, null, options);
+
+        assertEquals("Precondition", 0, subject.getPrincipals().size());
+        assertFalse(module.login());
+    }
+    
+    @Test
+    public void testUserNotFound() throws Exception {
+        Properties options = ldapLoginModuleOptions();
+        LDAPLoginModule module = new LDAPLoginModule();
+        CallbackHandler cb = new CallbackHandler() {
+            public void handle(Callback[] callbacks) throws IOException, UnsupportedCallbackException {
+                for (Callback cb : callbacks) {
+                    if (cb instanceof NameCallback) {
+                        ((NameCallback) cb).setName("imnothere");
+                    } else if (cb instanceof PasswordCallback) {
+                        ((PasswordCallback) cb).setPassword("admin123".toCharArray());
+                    }
+                }
+            }
+        };
+        Subject subject = new Subject();
+        module.initialize(subject, cb, null, options);
+
+        assertEquals("Precondition", 0, subject.getPrincipals().size());
+        assertFalse(module.login());
+    }
+}
+            
\ No newline at end of file

http://git-wip-us.apache.org/repos/asf/karaf/blob/b7e0aa92/jaas/modules/src/test/java/org/apache/karaf/jaas/modules/ldap/LdapLoginModuleWithEscapesTest.java
----------------------------------------------------------------------
diff --git a/jaas/modules/src/test/java/org/apache/karaf/jaas/modules/ldap/LdapLoginModuleWithEscapesTest.java b/jaas/modules/src/test/java/org/apache/karaf/jaas/modules/ldap/LdapLoginModuleWithEscapesTest.java
new file mode 100644
index 0000000..bb80280
--- /dev/null
+++ b/jaas/modules/src/test/java/org/apache/karaf/jaas/modules/ldap/LdapLoginModuleWithEscapesTest.java
@@ -0,0 +1,35 @@
+/*
+ *
+ *  Licensed 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.
+ *  under the License.
+ */
+package org.apache.karaf.jaas.modules.ldap;
+
+import org.apache.directory.server.core.integ.FrameworkRunner;
+import org.apache.directory.server.annotations.CreateLdapServer;
+import org.apache.directory.server.annotations.CreateTransport;
+import org.apache.directory.server.core.annotations.ApplyLdifFiles;
+import org.apache.directory.server.core.annotations.CreateDS;
+import org.apache.directory.server.core.annotations.CreatePartition;
+import org.junit.runner.RunWith;
+
+@RunWith ( FrameworkRunner.class )
+@CreateLdapServer(transports = {@CreateTransport(protocol = "LDAP", port=9999)})
+@CreateDS(name = "LdapLoginModuleWithEscapesTest-class",
+ partitions = { @CreatePartition(name = "example", suffix = "dc=example,dc=com") })
+@ApplyLdifFiles(
+   "org/apache/karaf/jaas/modules/ldap/example.com_with_escapes.ldif"
+)
+public class LdapLoginModuleWithEscapesTest extends LdapLoginModuleTest {
+}
+            
\ No newline at end of file

http://git-wip-us.apache.org/repos/asf/karaf/blob/b7e0aa92/jaas/modules/src/test/resources/log4j.properties
----------------------------------------------------------------------
diff --git a/jaas/modules/src/test/resources/log4j.properties b/jaas/modules/src/test/resources/log4j.properties
new file mode 100644
index 0000000..a75bae2
--- /dev/null
+++ b/jaas/modules/src/test/resources/log4j.properties
@@ -0,0 +1,34 @@
+## ---------------------------------------------------------------------------
+## 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.
+## ---------------------------------------------------------------------------
+
+#
+# The logging properties used during tests..
+#
+log4j.rootLogger=INFO, console, file
+
+# Console will only display warnings
+log4j.appender.console=org.apache.log4j.ConsoleAppender
+log4j.appender.console.layout=org.apache.log4j.PatternLayout
+log4j.appender.console.layout.ConversionPattern=%d{ISO8601} | %-5.5p | %-16.16t | %-32.32c{1} | %-32.32C %4L | %m%n
+log4j.appender.console.threshold=WARN
+
+# File appender will contain all info messages
+log4j.appender.file=org.apache.log4j.FileAppender
+log4j.appender.file.layout=org.apache.log4j.PatternLayout
+log4j.appender.file.layout.ConversionPattern=%d | %-5p | %m | %c | %t%n
+log4j.appender.file.file=target/test.log
+log4j.appender.file.append=true

http://git-wip-us.apache.org/repos/asf/karaf/blob/b7e0aa92/jaas/modules/src/test/resources/org/apache/karaf/jaas/modules/ldap/example.com.ldif
----------------------------------------------------------------------
diff --git a/jaas/modules/src/test/resources/org/apache/karaf/jaas/modules/ldap/example.com.ldif b/jaas/modules/src/test/resources/org/apache/karaf/jaas/modules/ldap/example.com.ldif
new file mode 100644
index 0000000..39fa562
--- /dev/null
+++ b/jaas/modules/src/test/resources/org/apache/karaf/jaas/modules/ldap/example.com.ldif
@@ -0,0 +1,58 @@
+## ---------------------------------------------------------------------------
+## 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.
+## ---------------------------------------------------------------------------
+
+dn: dc=example,dc=com
+objectclass: top
+objectclass: domain
+dc: example
+
+dn: ou=people,dc=example,dc=com
+objectClass: top
+objectClass: organizationalUnit
+ou: people
+
+dn: ou=groups,dc=example,dc=com
+objectClass: top
+objectClass: organizationalUnit
+ou: groups
+
+dn: cn=admin,ou=groups,dc=example,dc=com
+objectClass: top
+objectClass: groupOfNames
+cn: admin
+member: cn=admin,ou=people,dc=example,dc=com
+
+dn: cn=admin,ou=people,dc=example,dc=com
+objectClass: top
+objectClass: inetOrgPerson
+objectClass: person
+objectClass: organizationalPerson
+cn: admin
+sn: admin
+uid: admin
+userPassword: admin123
+
+dn: cn=cheese,ou=people,dc=example,dc=com
+objectClass: top
+objectClass: inetOrgPerson
+objectClass: person
+objectClass: organizationalPerson
+cn: cheese
+sn: cheese
+uid: cheese
+userPassword: foodie
+

http://git-wip-us.apache.org/repos/asf/karaf/blob/b7e0aa92/jaas/modules/src/test/resources/org/apache/karaf/jaas/modules/ldap/example.com_with_escapes.ldif
----------------------------------------------------------------------
diff --git a/jaas/modules/src/test/resources/org/apache/karaf/jaas/modules/ldap/example.com_with_escapes.ldif b/jaas/modules/src/test/resources/org/apache/karaf/jaas/modules/ldap/example.com_with_escapes.ldif
new file mode 100644
index 0000000..3736aea
--- /dev/null
+++ b/jaas/modules/src/test/resources/org/apache/karaf/jaas/modules/ldap/example.com_with_escapes.ldif
@@ -0,0 +1,58 @@
+## ---------------------------------------------------------------------------
+## 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.
+## ---------------------------------------------------------------------------
+
+dn: dc=example,dc=com
+objectclass: top
+objectclass: domain
+dc: example
+
+dn: ou=people,dc=example,dc=com
+objectClass: top
+objectClass: organizationalUnit
+ou: people
+
+dn: ou=groups,dc=example,dc=com
+objectClass: top
+objectClass: organizationalUnit
+ou: groups
+
+dn: cn=admin,ou=groups,dc=example,dc=com
+objectClass: top
+objectClass: groupOfNames
+cn: admin
+member: cn=admin\,\=\+\<\>#\;\\,ou=people,dc=example,dc=com
+
+dn: cn=admin\,\=\+\<\>#\;\\,ou=people,dc=example,dc=com
+objectClass: top
+objectClass: inetOrgPerson
+objectClass: person
+objectClass: organizationalPerson
+cn: admin,=+<>#;\
+sn: admin
+uid: admin
+userPassword: admin123
+
+dn: cn=cheese,ou=people,dc=example,dc=com
+objectClass: top
+objectClass: inetOrgPerson
+objectClass: person
+objectClass: organizationalPerson
+cn: cheese
+sn: cheese
+uid: cheese
+userPassword: foodie
+

http://git-wip-us.apache.org/repos/asf/karaf/blob/b7e0aa92/jaas/modules/src/test/resources/org/apache/karaf/jaas/modules/ldap/ldap.properties
----------------------------------------------------------------------
diff --git a/jaas/modules/src/test/resources/org/apache/karaf/jaas/modules/ldap/ldap.properties b/jaas/modules/src/test/resources/org/apache/karaf/jaas/modules/ldap/ldap.properties
new file mode 100644
index 0000000..5cb6848
--- /dev/null
+++ b/jaas/modules/src/test/resources/org/apache/karaf/jaas/modules/ldap/ldap.properties
@@ -0,0 +1,36 @@
+################################################################################
+#
+#    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.
+#
+################################################################################
+
+debug=true
+connection.url=ldap://127.0.0.1:9999
+connection.username=uid=admin,ou=system
+connection.password=secret
+connection.protocol=
+authentication=simple
+
+user.base.dn=ou=people,dc=example,dc=com
+user.filter=(uid=%u)
+user.search.subtree=true
+
+role.base.dn=ou=groups,dc=example,dc=com
+role.name.attribute=cn
+role.filter=(member=%fqdn)
+role.search.subtree=true
+
+initialContextFactory=com.sun.jndi.ldap.LdapCtxFactory

http://git-wip-us.apache.org/repos/asf/karaf/blob/b7e0aa92/pom.xml
----------------------------------------------------------------------
diff --git a/pom.xml b/pom.xml
index 14baf41..299476e 100644
--- a/pom.xml
+++ b/pom.xml
@@ -221,6 +221,7 @@
         <spring40.version>4.0.2.RELEASE_1</spring40.version>
         <spring.security31.version>3.1.4.RELEASE</spring.security31.version>
 
+        <directory-version>2.0.0-M16</directory-version>
         <sshd.version>0.9.0</sshd.version>
         <struts.bundle.version>1.3.10_1</struts.bundle.version>
         <xbean.version>3.16</xbean.version>