John Livermore
John Livermore

Reputation: 31343

LDAP query to return all users in a group

I am writing an LDAP interface that, for a given group's objectguid, must return a list of all users in those groups along with the user's SID.

For a given group's objectguid the code below returns the users in that group. However they are all in the form...

CN=Chad Hutchins,OU=Contractors,DC=RM,DC=LOCAL

... but I need the user's SID vs. the above string. Is there a way to obtain a user's SID starting from a group and querying for all users in that group?

using System.DirectoryServices;

public void GetUsers(Guid groupId, string domain, string username, string password)
{
    var rootEntry = new DirectoryEntry("LDAP://" + domain);
    rootEntry.Username = username;
    rootEntry.Password = password;

    var searcher = new DirectorySearcher(rootEntry);
    searcher.Filter = @"(objectguid=" + ConvertGuidToOctectString(groupId) + ")";

    var groupResult = searcher.FindOne();
    foreach (DictionaryEntry prop in groupResult.Properties)
    {
        var key = (string)prop.Key;

        switch (key)
        {
            case "member":
                foreach (string name in groupResult.Properties[key])
                    Console.WriteLine(name);
                break;
        }
    }
}

private string ConvertGuidToOctectString(Guid guid)
{
    var byteGuid = guid.ToByteArray();
    var queryGuid = string.Empty;
    foreach (var b in byteGuid)
    {
        queryGuid += @"\" + b.ToString("x2");
    }
    return queryGuid;
}

Upvotes: 2

Views: 926

Answers (1)

smr5
smr5

Reputation: 2793

You have few options on how to retrieve user SIDs from a particular group.

  1. Use GroupPrincipal in AccountManagement namepsace.

    public static List<string> GetUsersFromGroupByGroupID(string ID)
    {
        using (PrincipalContext ctx = new PrincipalContext(ContextType.Domain, "yourdomain.com")
        {
            using (GroupPrincipal group = GroupPrincipal.FindByIdentity(ctx, IdentityType.Guid, ID))
            {
                if (group != null)
                {
                    List<string> memberSIDs = new List<string>();
                    var members = group.GetMembers(true);
                    foreach(var member in members)
                    {
                        memberSIDs.Add(member.Sid.ToString());
                    }
                    return memberSIDs;
                }
            }
        }
        return null;
    }
    
  2. You can store the DistinguishedName of all the users from your query into a List<string> and then do a look up for user SID using UserPrincipal class.

    public static List<string> GetUserSIDs(List<string>userDNs)
    {
        List<string> userSIDs = new List<string>();
        using (PrincipalContext ctx = new PrincipalContext(ContextType.Domain, "yourdomain.com"))
        {
            foreach(string userDN in userDNs)
            {
                using (UserPrincipal user = UserPrincipal.FindByIdentity(ctx, IdentityType.DistinguishedName, userDN))
                {
                    if (user != null)
                    {
                        userSIDs.Add(user.Sid.ToString());
                    }
                }
            }
        }
        return userSIDs;
    }
    
  3. And the last option you can still get the list of DistiniguishedName from you query and still use DirectoryEntry

    using (DirectoryEntry entry = new DirectoryEntry("LDAP://userDistinguishedName")
    {
        var userSID = entry.Properties["objectSID"][0];
    }
    

NOTE* in this case userSID will be returned as byte[] array.

Upvotes: 2

Related Questions