How to handle special characters when getting a DirectoryEntry for an AD group member?

414 views Asked by At

I am trying to get all members of a (configurable) AD group in my application and I noticed that in some cases I am getting errors such as System.Runtime.InteropServices.COMException (0x80005000). Getting a DirectoryEntry for the group itself works just fine but the problems occur in this piece of code where I am iterating over the group members:

int membersFound = 0;

while (true)
{
    PropertyValueCollection members = group.Properties["member"];

    foreach (string member in members)
    {
        using (DirectoryEntry memberEntry = new DirectoryEntry($"GC://{member}"))
        {
            memberEntry.RefreshCache(new[] { "objectClass", "msDS-PrincipalName", "displayname", "cn" });
            bool isGroup = memberEntry.Properties["objectClass"]?.Contains("group") == true;
            string userName = memberEntry.Properties["msDS-PrincipalName"]?.Value?.ToString();

            if (!isGroup && !string.IsNullOrEmpty(userName))
            {
                // ...
            }
        }
    }

    if (members.Count == 0)
    {
        break;
    }

    membersFound += members.Count;

    try
    {
        group.RefreshCache(new[] { $"member;range={membersFound}-*" });
    }
    catch (COMException e)
    {
        if (e.ErrorCode == unchecked((int)0x80072020))
        {
            break;
        }

        throw;
    }
}

It seems like I cannot simply pass the member string to the DirectoryEntry constructor like I am currently doing because if the string contains certain characters such as "/", I get an exception when calling memberEntry.RefreshCache(). I also noticed that it seems to fix the problem in case of the "/" when I escape it with a backslash before passing it to the DirectoryEntry constructor. However, I do not know what else I need to do here to make sure that my code always works no matter what special characters might be in the member string. Is there any function I can use to format the string which already takes care of this or what do I have to do to prevent any problems caused by special characters in my code?

1

There are 1 answers

0
Gabriel Luci On

You will have to escape the slashes yourself. The member attribute contains a list of the distinguishedName of each member. But in distinguishedName, a forward slash has no special meaning, so the slash isn't escaped. But in an LDAP string, a forward slash does have a special meaning.

So just use a string Replace:

new DirectoryEntry($"GC://{member.Replace("/", "\\/")}")