From 6df4648277ca54e5868a5e464a85b9f1e5d85c15 Mon Sep 17 00:00:00 2001
From: neil_a_wilson <neil_a_wilson@localhost>
Date: Wed, 08 Aug 2007 18:19:31 +0000
Subject: [PATCH] Make a change to the Group API that will allow for better nesting support. There are now variants of the isMember methods that include an additional Set<DN> argument to which the current group's DN should be added whenever a check is made to determine whether a user is a member.  This will help provide a mechanism for avoiding infinite recursion loops if two groups both reference each other as nested groups.

---
 opendj-sdk/opends/src/server/org/opends/server/extensions/VirtualStaticGroup.java |   15 ++++
 opendj-sdk/opends/src/server/org/opends/server/extensions/StaticGroup.java        |   15 ++++
 opendj-sdk/opends/src/server/org/opends/server/extensions/DynamicGroup.java       |   14 ++++
 opendj-sdk/opends/src/server/org/opends/server/api/Group.java                     |   82 ++++++++++++++++++++++++++-
 4 files changed, 117 insertions(+), 9 deletions(-)

diff --git a/opendj-sdk/opends/src/server/org/opends/server/api/Group.java b/opendj-sdk/opends/src/server/org/opends/server/api/Group.java
index 88728ec..f3101b4 100644
--- a/opendj-sdk/opends/src/server/org/opends/server/api/Group.java
+++ b/opendj-sdk/opends/src/server/org/opends/server/api/Group.java
@@ -28,7 +28,9 @@
 
 
 
+import java.util.HashSet;
 import java.util.List;
+import java.util.Set;
 
 import org.opends.server.admin.std.server.GroupImplementationCfg;
 import org.opends.server.config.ConfigException;
@@ -277,7 +279,43 @@
    * @throws  DirectoryException  If a problem occurs while attempting
    *                              to make the determination.
    */
-  public abstract boolean isMember(DN userDN)
+  public boolean isMember(DN userDN)
+         throws DirectoryException
+  {
+    return isMember(userDN, new HashSet<DN>());
+  }
+
+
+
+  /**
+   * Indicates whether the user with the specified DN is a member of
+   * this group.  Note that this is a point-in-time determination and
+   * the caller must not cache the result.  Also note that group
+   * implementations that support nesting should use this version of
+   * the method ratehr than the version that does not take a set of
+   * DNs when attempting to determine whether a nested group includes
+   * the target member.
+   *
+   * @param  userDN          The DN of the user for which to make the
+   *                         determination.
+   * @param  examinedGroups  A set of groups that have already been
+   *                         examined in the process of making the
+   *                         determination.  This provides a mechanism
+   *                         to prevent infinite recursion due to
+   *                         circular references (e.g., two groups
+   *                         include each other as nested groups).
+   *                         Each time a group instance is checked,
+   *                         its DN should be added to the list, and
+   *                         any DN already contained in the list
+   *                         should be skipped.
+   *
+   * @return  {@code true} if the specified user is currently a member
+   *          of this group, or {@code false} if not.
+   *
+   * @throws  DirectoryException  If a problem occurs while attempting
+   *                              to make the determination.
+   */
+  public abstract boolean isMember(DN userDN, Set<DN> examinedGroups)
          throws DirectoryException;
 
 
@@ -296,7 +334,44 @@
    * @throws  DirectoryException  If a problem occurs while attempting
    *                              to make the determination.
    */
-  public abstract boolean isMember(Entry userEntry)
+  public boolean isMember(Entry userEntry)
+         throws DirectoryException
+  {
+    return isMember(userEntry, new HashSet<DN>());
+  }
+
+
+
+  /**
+   * Indicates whether the user described by the provided user entry
+   * is a member of this group.  Note that this is a point-in-time
+   * determination and the caller must not cache the result.  Also
+   * note that group implementations that support nesting should use
+   * this version of the method ratehr than the version that does not
+   * take a set of DNs when attempting to determine whether a nested
+   * group includes the target member.
+   *
+   * @param  userEntry       The entry for the user for which to make
+   *                         the determination.
+   * @param  examinedGroups  A set of groups that have already been
+   *                         examined in the process of making the
+   *                         determination.  This provides a mechanism
+   *                         to prevent infinite recursion due to
+   *                         circular references (e.g., two groups
+   *                         include each other as nested groups).
+   *                         Each time a group instance is checked,
+   *                         its DN should be added to the list, and
+   *                         any DN already contained in the list
+   *                         should be skipped.
+   *
+   * @return  {@code true} if the specified user is currently a member
+   *          of this group, or {@code false} if not.
+   *
+   * @throws  DirectoryException  If a problem occurs while attempting
+   *                              to make the determination.
+   */
+  public abstract boolean isMember(Entry userEntry,
+                                   Set<DN> examinedGroups)
          throws DirectoryException;
 
 
@@ -305,7 +380,8 @@
    * Retrieves an iterator that may be used to cursor through the
    * entries of the members contained in this group.  Note that this
    * is a point-in-time determination, and the caller must not cache
-   * the result.
+   * the result.  Further, the determination should only include this
+   * group and not members from nested groups.
    *
    * @return  An iterator that may be used to cursor through the
    *          entries of the members contained in this group.
diff --git a/opendj-sdk/opends/src/server/org/opends/server/extensions/DynamicGroup.java b/opendj-sdk/opends/src/server/org/opends/server/extensions/DynamicGroup.java
index 11916c4..35c52e5 100644
--- a/opendj-sdk/opends/src/server/org/opends/server/extensions/DynamicGroup.java
+++ b/opendj-sdk/opends/src/server/org/opends/server/extensions/DynamicGroup.java
@@ -299,9 +299,14 @@
    * {@inheritDoc}
    */
   @Override()
-  public boolean isMember(DN userDN)
+  public boolean isMember(DN userDN, Set<DN> examinedGroups)
          throws DirectoryException
   {
+    if (! examinedGroups.add(getGroupDN()))
+    {
+      return false;
+    }
+
     Entry entry = DirectoryConfig.getEntry(userDN);
     if (entry == null)
     {
@@ -319,9 +324,14 @@
    * {@inheritDoc}
    */
   @Override()
-  public boolean isMember(Entry userEntry)
+  public boolean isMember(Entry userEntry, Set<DN> examinedGroups)
          throws DirectoryException
   {
+    if (! examinedGroups.add(getGroupDN()))
+    {
+      return false;
+    }
+
     for (LDAPURL memberURL : memberURLs)
     {
       if (memberURL.matchesEntry(userEntry))
diff --git a/opendj-sdk/opends/src/server/org/opends/server/extensions/StaticGroup.java b/opendj-sdk/opends/src/server/org/opends/server/extensions/StaticGroup.java
index 95e2b05..338b0d4 100644
--- a/opendj-sdk/opends/src/server/org/opends/server/extensions/StaticGroup.java
+++ b/opendj-sdk/opends/src/server/org/opends/server/extensions/StaticGroup.java
@@ -32,6 +32,7 @@
 import java.util.LinkedHashSet;
 import java.util.LinkedList;
 import java.util.List;
+import java.util.Set;
 
 import org.opends.server.admin.std.server.GroupImplementationCfg;
 import org.opends.server.api.Group;
@@ -358,9 +359,14 @@
    * {@inheritDoc}
    */
   @Override()
-  public boolean isMember(DN userDN)
+  public boolean isMember(DN userDN, Set<DN> examinedGroups)
          throws DirectoryException
   {
+    if (! examinedGroups.add(getGroupDN()))
+    {
+      return false;
+    }
+
     return memberDNs.contains(userDN);
   }
 
@@ -370,9 +376,14 @@
    * {@inheritDoc}
    */
   @Override()
-  public boolean isMember(Entry userEntry)
+  public boolean isMember(Entry userEntry, Set<DN> examinedGroups)
          throws DirectoryException
   {
+    if (! examinedGroups.add(getGroupDN()))
+    {
+      return false;
+    }
+
     return memberDNs.contains(userEntry.getDN());
   }
 
diff --git a/opendj-sdk/opends/src/server/org/opends/server/extensions/VirtualStaticGroup.java b/opendj-sdk/opends/src/server/org/opends/server/extensions/VirtualStaticGroup.java
index b73e90d..b90d62d 100644
--- a/opendj-sdk/opends/src/server/org/opends/server/extensions/VirtualStaticGroup.java
+++ b/opendj-sdk/opends/src/server/org/opends/server/extensions/VirtualStaticGroup.java
@@ -30,6 +30,7 @@
 
 import java.util.Collections;
 import java.util.List;
+import java.util.Set;
 
 import org.opends.server.admin.std.server.GroupImplementationCfg;
 import org.opends.server.api.Group;
@@ -305,9 +306,14 @@
    * {@inheritDoc}
    */
   @Override()
-  public boolean isMember(DN userDN)
+  public boolean isMember(DN userDN, Set<DN> examinedGroups)
          throws DirectoryException
   {
+    if (! examinedGroups.add(getGroupDN()))
+    {
+      return false;
+    }
+
     Group targetGroup =
          DirectoryServer.getGroupManager().getGroupInstance(targetGroupDN);
     if (targetGroup == null)
@@ -338,9 +344,14 @@
    * {@inheritDoc}
    */
   @Override()
-  public boolean isMember(Entry userEntry)
+  public boolean isMember(Entry userEntry, Set<DN> examinedGroups)
          throws DirectoryException
   {
+    if (! examinedGroups.add(getGroupDN()))
+    {
+      return false;
+    }
+
     Group targetGroup =
          DirectoryServer.getGroupManager().getGroupInstance(targetGroupDN);
     if (targetGroup == null)

--
Gitblit v1.10.0