3

I'd like find the groups list where a user is member. I tried several solution from http://www.codeproject.com/KB/system/everythingInAD.aspx but no result.

This code give me a "true", means LDAP is running :

public static bool Exists(string objectPath)
{
    bool found = false;
    if (DirectoryEntry.Exists("LDAP://" + objectPath))
        found = true;
    return found;
}

Thanks,

Update 1:

public ArrayList Groups(string userDn, bool recursive)
{
    ArrayList groupMemberships = new ArrayList();
    return AttributeValuesMultiString("memberOf", "LDAP-Server",
        groupMemberships, recursive);
}

public ArrayList AttributeValuesMultiString(string attributeName,
string objectDn, ArrayList valuesCollection, bool recursive)
{
    DirectoryEntry ent = new DirectoryEntry(objectDn);
    PropertyValueCollection ValueCollection = ent.Properties[attributeName];
    IEnumerator en = ValueCollection.GetEnumerator();

    while (en.MoveNext())
    {
        if (en.Current != null)
        {
            if (!valuesCollection.Contains(en.Current.ToString()))
            {
                valuesCollection.Add(en.Current.ToString());
                if (recursive)
                {
                    AttributeValuesMultiString(attributeName, "LDAP://" +
                    en.Current.ToString(), valuesCollection, true);
                }
            }
        }
    }
    ent.Close();
    ent.Dispose();
    return valuesCollection;
}

I have an exception on :

PropertyValueCollection ValueCollection = ent.Properties[attributeName];

"COMException was unhandled"

TheBoubou
  • 19,487
  • 54
  • 148
  • 236
  • In the article you link, there is a "Get User Group Memberships" section... did you try that out? – Paolo Tedesco Sep 05 '11 at 07:59
  • can you post code which is not working for you ? – bartosz.lipinski Sep 05 '11 at 08:00
  • And by the way, true in that case means that the object exists, not that LDAP is running. Maybe you should get some more basic knowledge about LDAP and Active Directory. – Paolo Tedesco Sep 05 '11 at 08:01
  • You'll find here a link on another [post with the same question](http://stackoverflow.com/questions/6252819/find-recursive-group-membership-active-directory-using-c/6289205#6289205). – JPBlanc Sep 05 '11 at 12:21

4 Answers4

8

In .NET 4 you can do this very easily with the new UserPrincipal class in the following way:

using (PrincipalContext context = new PrincipalContext(ContextType.Domain))
{
    UserPrincipal user = UserPrincipal.FindByIdentity(context, IdentityType.SamAccountName, "your_login");
    foreach (var group in user.GetGroups())
    {
        Console.WriteLine(group.Name);
    }
}

You have to add a reference to System.DirectoryServices.AccountManagement to bring in the required types.

Jakob Christensen
  • 14,826
  • 2
  • 51
  • 81
1

I found the solution on stackoverflow. The connectionString format is like this :

LDAP://domain.subdomain.com:389/DC=domain,DC=subdomain,DC=com

The Code :

  public IList<string> GetGroupsByUser(string ldapConnectionString, string username)
        {
            IList<string> groupList = new List<string>();

            var identity = WindowsIdentity.GetCurrent().User;
            var allDomains = Forest.GetCurrentForest().Domains.Cast<Domain>();

            var allSearcher = allDomains.Select(domain =>
            {
                var searcher = new DirectorySearcher(new DirectoryEntry(ldapConnectionString));

                // Apply some filter to focus on only some specfic objects
                searcher.Filter = String.Format("(&(&(objectCategory=person)(objectClass=user)(name=*{0}*)))", username);
                return searcher;
            });

            var directoryEntriesFound = allSearcher
                .SelectMany(searcher => searcher.FindAll()
                    .Cast<SearchResult>()
                    .Select(result => result.GetDirectoryEntry()));

            var memberOf = directoryEntriesFound.Select(entry =>
            {
                using (entry)
                {
                    return new
                    {
                        Name = entry.Name,
                        GroupName = ((object[])entry.Properties["MemberOf"].Value).Select(obj => obj.ToString())
                    };
                }
            });

            foreach (var item in memberOf)
                foreach (var groupName in item.GroupName)
                    groupList.Add(groupName);

            return groupList;
        }
TheBoubou
  • 19,487
  • 54
  • 148
  • 236
0

Are you sure that above script is correct and works correctly? I don't think it will take nested group memberships into account, so I fear that you may not be getting the complete set of all groups to which a user belongs.

You see, a user could be a member of Group X, and Group X could in turn be a member of Group Y, so as a result the user would be a member of Group Y as well.

I think the script referenced above may not be able to expand and enumerate nested group memberships.

I would suggest looking into this angle as well, if you are interested in getting the full set of memberships to which the user belongs.

I believe there are some other issues pertaining to determining group membership as well. There is a good discussion here if you are interested in learning more:

http://www.activedirsec.org/t39703252/why-is-it-so-hard-to-enumerate-nested-group-memberships-in-a/

I wish it very easier, but it does not appear to be so :-(

Krishna Raju
  • 91
  • 1
  • 2
0

Use this code instead of your version. This will give you the list. The difference between this and the original one is the usage of DirectorySearcher.

    public ArrayList AttributeValuesMultiString(string attributeName,
         string objectDn, ArrayList valuesCollection, bool recursive)
    {
        using (DirectoryEntry ent = new DirectoryEntry(objectDn))
        {
            using (DirectorySearcher searcher = new DirectorySearcher(ent))
            {
                searcher.PropertiesToLoad.Add(attributeName);
                var result = searcher.FindOne();
                ResultPropertyValueCollection ValueCollection = result.Properties[attributeName];
                IEnumerator en = ValueCollection.GetEnumerator();

                while (en.MoveNext())
                {
                    if (en.Current != null)
                    {
                        if (!valuesCollection.Contains(en.Current.ToString()))
                        {
                            valuesCollection.Add(en.Current.ToString());
                            if (recursive)
                            {
                                AttributeValuesMultiString(attributeName, "LDAP://" +
                                en.Current.ToString(), valuesCollection, true);
                            }
                        }
                    }
                }
            }
        }
        return valuesCollection;
    }