You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@karaf.apache.org by jb...@apache.org on 2019/10/20 18:55:55 UTC

[karaf] branch master updated: [KARAF-6458] Add new ignorePartialResultException property to jaas-ldap module This property, when set to true and paired with a false value for context.java.naming.referral (the default for that property), will ignore PartialResultExceptions thrown from Active Directory when referrals are nested beneath role base dns.

This is an automated email from the ASF dual-hosted git repository.

jbonofre pushed a commit to branch master
in repository https://gitbox.apache.org/repos/asf/karaf.git


The following commit(s) were added to refs/heads/master by this push:
     new 2a1b963  [KARAF-6458] Add new ignorePartialResultException property to jaas-ldap module This property, when set to true and paired with a false value for context.java.naming.referral (the default for that property), will ignore PartialResultExceptions thrown from Active Directory when referrals are nested beneath role base dns.
     new 6b59598  Merge pull request #958 from coyotesqrl/KARAF-6458
2a1b963 is described below

commit 2a1b963d2f958f70f6968f8f6896fe6c95faf656
Author: R.A. Porter <ri...@connexta.com>
AuthorDate: Wed Oct 16 15:17:17 2019 -0700

    [KARAF-6458] Add new ignorePartialResultException property to jaas-ldap module
    This property, when set to true and paired with a false value for context.java.naming.referral (the default for that property), will ignore PartialResultExceptions thrown from Active Directory when referrals are nested beneath role base dns.
---
 .../apache/karaf/jaas/modules/ldap/LDAPCache.java  | 19 +++++--
 .../karaf/jaas/modules/ldap/LDAPOptions.java       |  4 ++
 .../karaf/jaas/modules/ldap/BadReferenceTest.java  | 62 +++++++++++++++++++++
 .../jaas/modules/ldap/example.com_badref.ldif      | 65 ++++++++++++++++++++++
 .../karaf/jaas/modules/ldap/ldap_badref.properties | 38 +++++++++++++
 .../developer-guide/security-framework.adoc        |  3 +
 6 files changed, 186 insertions(+), 5 deletions(-)

diff --git a/jaas/modules/src/main/java/org/apache/karaf/jaas/modules/ldap/LDAPCache.java b/jaas/modules/src/main/java/org/apache/karaf/jaas/modules/ldap/LDAPCache.java
index b7a4b2d..07efe25 100644
--- a/jaas/modules/src/main/java/org/apache/karaf/jaas/modules/ldap/LDAPCache.java
+++ b/jaas/modules/src/main/java/org/apache/karaf/jaas/modules/ldap/LDAPCache.java
@@ -16,6 +16,7 @@ package org.apache.karaf.jaas.modules.ldap;
 
 import javax.naming.NamingEnumeration;
 import javax.naming.NamingException;
+import javax.naming.PartialResultException;
 import javax.naming.directory.Attribute;
 import javax.naming.directory.Attributes;
 import javax.naming.directory.DirContext;
@@ -261,12 +262,12 @@ public class LDAPCache implements Closeable, NamespaceChangeListener, ObjectChan
             filter = filter.replace("\\", "\\\\");
 
             LOGGER.debug("Looking for the user roles in LDAP with ");
-            LOGGER.debug("  base DN: " + options.getRoleBaseDn());
-            LOGGER.debug("  filter: " + filter);
+            LOGGER.debug("  base DN: {}", options.getRoleBaseDn());
+            LOGGER.debug("  filter: {}", filter);
 
             NamingEnumeration<SearchResult> namingEnumeration = context.search(options.getRoleBaseDn(), filter, controls);
+            List<String> rolesList = new ArrayList<>();
             try {
-                List<String> rolesList = new ArrayList<>();
                 while (namingEnumeration.hasMore()) {
                     SearchResult result = namingEnumeration.next();
                     Attributes attributes = result.getAttributes();
@@ -286,9 +287,15 @@ public class LDAPCache implements Closeable, NamespaceChangeListener, ObjectChan
                             }
                         }
                     }
-
                 }
-                return rolesList.toArray(new String[rolesList.size()]);
+            } catch (PartialResultException e) {
+                // Workaround for AD servers not handling referrals correctly.
+                if (options.getIgnorePartialResultException()) {
+                    LOGGER.debug("PartialResultException encountered and ignored", e);
+                }
+                else {
+                    throw e;
+                }
             } finally {
                 if (namingEnumeration != null) {
                     try {
@@ -298,6 +305,8 @@ public class LDAPCache implements Closeable, NamespaceChangeListener, ObjectChan
                     }
                 }
             }
+
+            return rolesList.toArray(new String[rolesList.size()]);
         } else {
             LOGGER.debug("The user role filter is null so no roles are retrieved");
             return new String[] {};
diff --git a/jaas/modules/src/main/java/org/apache/karaf/jaas/modules/ldap/LDAPOptions.java b/jaas/modules/src/main/java/org/apache/karaf/jaas/modules/ldap/LDAPOptions.java
index 1ccde52..0261f5e 100644
--- a/jaas/modules/src/main/java/org/apache/karaf/jaas/modules/ldap/LDAPOptions.java
+++ b/jaas/modules/src/main/java/org/apache/karaf/jaas/modules/ldap/LDAPOptions.java
@@ -61,6 +61,7 @@ public class LDAPOptions {
     public static final String USERNAMES_TRIM = "usernames.trim";
     public static final String DEFAULT_INITIAL_CONTEXT_FACTORY = "com.sun.jndi.ldap.LdapCtxFactory";
     public static final String DEFAULT_AUTHENTICATION = "simple";
+    public static final String IGNORE_PARTIAL_RESULT_EXCEPTION = "ignorePartialResultException";
     public static final int DEFAULT_SSL_TIMEOUT = 10;
 
     private static Logger LOGGER = LoggerFactory.getLogger(LDAPLoginModule.class);
@@ -275,4 +276,7 @@ public class LDAPOptions {
         return object == null || Boolean.parseBoolean((String) object);
     }
 
+    public boolean getIgnorePartialResultException() {
+        return Boolean.parseBoolean((String) options.get(IGNORE_PARTIAL_RESULT_EXCEPTION));
+    }
 }
diff --git a/jaas/modules/src/test/java/org/apache/karaf/jaas/modules/ldap/BadReferenceTest.java b/jaas/modules/src/test/java/org/apache/karaf/jaas/modules/ldap/BadReferenceTest.java
new file mode 100644
index 0000000..3f3c7ca
--- /dev/null
+++ b/jaas/modules/src/test/java/org/apache/karaf/jaas/modules/ldap/BadReferenceTest.java
@@ -0,0 +1,62 @@
+/*
+ *
+ *  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 static org.apache.karaf.jaas.modules.ldap.LdapPropsUpdater.ldapProps;
+
+import java.io.File;
+import java.io.IOException;
+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.directory.server.core.integ.FrameworkRunner;
+import org.apache.felix.utils.properties.Properties;
+import org.junit.After;
+import org.junit.Before;
+import org.junit.runner.RunWith;
+
+@RunWith(FrameworkRunner.class)
+@CreateLdapServer(transports = {@CreateTransport(protocol = "LDAP")})
+@CreateDS(name = "BadReferenceTest-class",
+    partitions = {@CreatePartition(name = "example", suffix = "dc=example,dc=com")})
+@ApplyLdifFiles(
+    "org/apache/karaf/jaas/modules/ldap/example.com_badref.ldif"
+)
+public class BadReferenceTest extends LdapCacheTest {
+
+    @Before
+    public void updatePort() throws Exception {
+        ldapProps("org/apache/karaf/jaas/modules/ldap/ldap_badref.properties",
+                  LdapLoginModuleTest::replacePort);
+    }
+
+    @After
+    public void tearDown() {
+        LDAPCache.clear();
+    }
+
+    @Override
+    protected Properties ldapLoginModuleOptions() throws IOException {
+        String basedir = System.getProperty("basedir");
+        if (basedir == null) {
+            basedir = new File(".").getCanonicalPath();
+        }
+        File file = new File(basedir + "/target/test-classes/org/apache/karaf/jaas/modules/ldap/ldap_badref.properties");
+        return new Properties(file);
+    }
+}
diff --git a/jaas/modules/src/test/resources/org/apache/karaf/jaas/modules/ldap/example.com_badref.ldif b/jaas/modules/src/test/resources/org/apache/karaf/jaas/modules/ldap/example.com_badref.ldif
new file mode 100644
index 0000000..2783af9
--- /dev/null
+++ b/jaas/modules/src/test/resources/org/apache/karaf/jaas/modules/ldap/example.com_badref.ldif
@@ -0,0 +1,65 @@
+## ---------------------------------------------------------------------------
+## 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
+description: cn=admin,ou=groups,dc=example,dc=com
+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
+
+dn: ou=badreference,ou=groups,dc=example,dc=com
+objectclass: top
+objectclass: extensibleObject
+objectclass: referral
+ou: badreference
+ref: ldap://badreference:1389/dc=example,dc=com
diff --git a/jaas/modules/src/test/resources/org/apache/karaf/jaas/modules/ldap/ldap_badref.properties b/jaas/modules/src/test/resources/org/apache/karaf/jaas/modules/ldap/ldap_badref.properties
new file mode 100644
index 0000000..07221d8
--- /dev/null
+++ b/jaas/modules/src/test/resources/org/apache/karaf/jaas/modules/ldap/ldap_badref.properties
@@ -0,0 +1,38 @@
+################################################################################
+#
+#    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:portno
+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
+
+ignorePartialResultException=true
+
+initialContextFactory=com.sun.jndi.ldap.LdapCtxFactory
diff --git a/manual/src/main/asciidoc/developer-guide/security-framework.adoc b/manual/src/main/asciidoc/developer-guide/security-framework.adoc
index ba638f7..c0e757a 100644
--- a/manual/src/main/asciidoc/developer-guide/security-framework.adoc
+++ b/manual/src/main/asciidoc/developer-guide/security-framework.adoc
@@ -423,6 +423,9 @@ The LDAPLoginModule supports the following parameters:
 
 |`ssl.truststore`
 |The trust store name to use for SSL. The trust store must be deployed using a `jaas:keystore` configuration.
+
+|`ignorePartialResultException`
+|Workaround for Active Directory servers not handling referrals correctly. When the `context.java.naming.referral` parameter is `false` (as it is by default), this will prevent `PartialResultException`s from being thrown during enumeration of search results.
 |===
 
 A example of LDAPLoginModule usage follows: