ASF Bugzilla – Attachment 23420 Details for
Bug 46925
Nested groups in JNDI realm with non-recursive implementation
Home
|
New
|
Browse
|
Search
|
[?]
|
Reports
|
Help
|
New Account
|
Log In
Remember
[x]
|
Forgot Password
Login:
[x]
[patch]
Patch which replaced the recursive method with a while loop ("memberOf Algorithm")
nestedGroups.patch (text/plain), 9.86 KB, created by
Stefan Zoerner
on 2009-03-27 03:58:28 UTC
(
hide
)
Description:
Patch which replaced the recursive method with a while loop ("memberOf Algorithm")
Filename:
MIME Type:
Creator:
Stefan Zoerner
Created:
2009-03-27 03:58:28 UTC
Size:
9.86 KB
patch
obsolete
>Index: java/org/apache/catalina/realm/JNDIRealm.java >=================================================================== >--- java/org/apache/catalina/realm/JNDIRealm.java (revision 758654) >+++ java/org/apache/catalina/realm/JNDIRealm.java (working copy) >@@ -317,15 +317,7 @@ > */ > protected MessageFormat[] userPatternFormatArray = null; > >- > /** >- * The maximum recursion depth when resolving roles recursively. >- * By default we don't resolve roles recursively. >- */ >- protected int roleRecursionLimit = 0; >- >- >- /** > * The base element for role searches. > */ > protected String roleBase = ""; >@@ -362,7 +354,13 @@ > * Should we search the entire subtree for matching memberships? > */ > protected boolean roleSubtree = false; >+ >+ /** >+ * Should we look for nested group in order to determine roles? >+ */ >+ protected boolean roleNested = false; > >+ > /** > * An alternate URL, to which, we should connect if connectionURL fails. > */ >@@ -652,28 +650,6 @@ > > > /** >- * Return the maximum recursion depth for role searches. >- */ >- public int getRoleRecursionLimit() { >- >- return (this.roleRecursionLimit); >- >- } >- >- >- /** >- * Set the maximum recursion depth for role searches. >- * >- * @param roleRecursionLimit The new recursion limit >- */ >- public void setRoleRecursionLimit(int roleRecursionLimit) { >- >- this.roleRecursionLimit = roleRecursionLimit; >- >- } >- >- >- /** > * Return the base element for role searches. > */ > public String getRoleBase() { >@@ -763,9 +739,31 @@ > this.roleSubtree = roleSubtree; > > } >+ >+ /** >+ * Return the "The nested group search flag" flag. >+ */ >+ public boolean getRoleNested() { > >+ return (this.roleNested); > >+ } >+ >+ > /** >+ * Set the "search subtree for roles" flag. >+ * >+ * @param roleNested The nested group search flag >+ */ >+ public void setRoleNested(boolean roleNested) { >+ >+ this.roleNested = roleNested; >+ >+ } >+ >+ >+ >+ /** > * Return the password attribute used to retrieve the user password. > */ > public String getUserPassword() { >@@ -1546,72 +1544,7 @@ > return (validated); > } > >- > /** >- * Add roles to a user and search for other roles containing them themselves. >- * We search recursively with a limited depth. >- * By default the depth is 0, and we only use direct roles. >- * The search needs to use the distinguished role names, >- * but to return the role names. >- * >- * @param depth Recursion depth, starting at zero >- * @param context The directory context we are searching >- * @param recursiveMap The cumulative result map of role names and DNs. >- * @param recursiveSet The cumulative result set of role names. >- * @param groupName The role name to add to the list. >- * @param groupDName The distinguished name of the role. >- * >- * @exception NamingException if a directory server error occurs >- */ >- private void getRolesRecursive(int depth, DirContext context, Map<String, String> recursiveMap, Set<String> recursiveSet, >- String groupName, String groupDName) throws NamingException { >- if (containerLog.isTraceEnabled()) >- containerLog.trace("Recursive search depth " + depth + " for group '" + groupDName + " (" + groupName + ")'"); >- // Adding the given group to the result set if not already found >- if (!recursiveSet.contains(groupDName)) { >- recursiveSet.add(groupDName); >- recursiveMap.put(groupDName, groupName); >- if (depth >= roleRecursionLimit) { >- if (roleRecursionLimit > 0) >- containerLog.warn("Terminating recursive role search because of recursion limit " + >- roleRecursionLimit + ", results might be incomplete"); >- return; >- } >- // Prepare the parameters for searching groups >- String filter = roleFormat.format(new String[] { groupDName }); >- SearchControls controls = new SearchControls(); >- controls.setSearchScope(roleSubtree ? SearchControls.SUBTREE_SCOPE : SearchControls.ONELEVEL_SCOPE); >- controls.setReturningAttributes(new String[] { roleName }); >- if (containerLog.isTraceEnabled()) { >- containerLog.trace("Recursive search in role base '" + roleBase + "' for attribute '" + roleName + "'" + >- " with filter expression '" + filter + "'"); >- } >- // Searching groups that assign the given group >- NamingEnumeration<SearchResult> results = >- context.search(roleBase, filter, controls); >- if (results != null) { >- // Iterate over the resulting groups >- try { >- while (results.hasMore()) { >- SearchResult result = results.next(); >- Attributes attrs = result.getAttributes(); >- if (attrs == null) >- continue; >- String dname = getDistinguishedName(context, roleBase, result); >- String name = getAttributeValue(roleName, attrs); >- if (name != null && dname != null) { >- getRolesRecursive(depth+1, context, recursiveMap, recursiveSet, name, dname); >- } >- } >- } catch (PartialResultException ex) { >- if (!adCompat) >- throw ex; >- } >- } >- } >- } >- >- /** > * Return a List of roles associated with the given User. Any > * roles present in the user's directory entry are supplemented by > * a directory search. If no roles are associated with this user, >@@ -1654,7 +1587,7 @@ > // Are we configured to do role searches? > if ((roleFormat == null) || (roleName == null)) > return (list); >- >+ > // Set up parameters for an appropriate search > String filter = roleFormat.format(new String[] { doRFC2254Encoding(dn), username }); > SearchControls controls = new SearchControls(); >@@ -1691,30 +1624,60 @@ > Set<String> keys = groupMap.keySet(); > if (containerLog.isTraceEnabled()) { > containerLog.trace(" Found " + keys.size() + " direct roles"); >- for (Iterator<String> i = keys.iterator(); i.hasNext();) { >- Object k = i.next(); >- containerLog.trace( " Found direct role " + k + " -> " + groupMap.get(k)); >+ for (String key: keys) { >+ containerLog.trace( " Found direct role " + key + " -> " + groupMap.get(key)); > } > } >+ >+ // if nested group search is enabled, perform searches for nested groups until no new group is found >+ if (getRoleNested()) { >+ >+ // The following efficient algorithm is known as memberOf Algorithm, as described in "Practices in >+ // Directory Groups". It avoids group slurping and handles cyclic group memberships as well. >+ // See http://middleware.internet2.edu/dir/ for details >+ >+ Set<String> newGroupDNs = new HashSet<String>(groupMap.keySet()); >+ while (!newGroupDNs.isEmpty()) { >+ Set<String> newThisRound = new HashSet<String>(); // Stores the groups we find in this iteration >+ >+ for (String groupDN : newGroupDNs) { >+ filter = roleFormat.format(new String[] { groupDN }); >+ >+ if (containerLog.isTraceEnabled()) { >+ containerLog.trace("Perform a nested group search with base "+ roleBase + " and filter " + filter); >+ } >+ >+ results = context.search(roleBase, filter, controls); >+ >+ try { >+ while (results.hasMore()) { >+ SearchResult result = results.next(); >+ Attributes attrs = result.getAttributes(); >+ if (attrs == null) >+ continue; >+ String dname = getDistinguishedName(context, roleBase, result); >+ String name = getAttributeValue(roleName, attrs); >+ if (name != null && dname != null && !groupMap.keySet().contains(dname)) { >+ groupMap.put(dname, name); >+ newThisRound.add(dname); >+ >+ if (containerLog.isTraceEnabled()) { >+ containerLog.trace(" Found nested role " + dname + " -> " + name); >+ } >+ >+ } >+ } >+ } catch (PartialResultException ex) { >+ if (!adCompat) >+ throw ex; >+ } >+ } >+ >+ newGroupDNs = newThisRound; >+ } >+ } > >- HashSet<String> recursiveSet = new HashSet<String>(); >- HashMap<String, String> recursiveMap = new HashMap<String, String>(); >- >- for (Iterator<String> i = keys.iterator(); i.hasNext();) { >- String k = i.next(); >- getRolesRecursive(0, context, recursiveMap, recursiveSet, groupMap.get(k), k); >- } >- >- HashSet<String> resultSet = new HashSet<String>(list); >- resultSet.addAll(recursiveMap.values()); >- >- if (containerLog.isTraceEnabled()) { >- containerLog.trace(" Returning " + resultSet.size() + " roles"); >- for (Iterator<String> i = resultSet.iterator(); i.hasNext();) >- containerLog.trace( " Found role " + i.next()); >- } >- >- return new ArrayList<String>(resultSet); >+ return new ArrayList<String>(groupMap.values()); > } > >
You cannot view the attachment while viewing its details because your browser does not support IFRAMEs.
View the attachment on a separate page
.
View Attachment As Diff
View Attachment As Raw
Actions:
View
|
Diff
Attachments on
bug 46925
: 23420