Wednesday, July 24, 2013 at 4:30 PM

A short time ago I had a situation come up where I needed to determine the Active Directory groups a user had membership in, up to and including the inner-most nested group. Here's the situation:

User A belongs to Group X
Group X is in Group Y
Group Y is in Group Z

and so on...

To determine which groups User A has immediate membership in is trivial, but, from what I could find, there is not a simple, one-liner LDAP query that will return all group memberships including nested groups. A typical LDAP query will return Group X when I really need to know that User A is a member of Group Z. My solution was to recursively query Active Directory until we've parsed the user's entire group membership tree or gone X-levels deep.

/// <summary>
/// This method gets all groups that a user belongs to.
/// </summary>
/// <param name="path">The LDAP path to the Active Directory server.</param>
/// <param name="username">The username of the account for which all groups will be fetched.</param>
/// <param name="accountName">Name of the account performing the search. This should be a service account with the appropriate permissions.</param>
/// <param name="accountPassword">The password to the account performing the search.</param>
/// <param name="iterations">The the number of iterations to perform before exiting a branch.</param>
/// <returns>
/// Returns returns a list of groups to which the user belongs.
/// </returns>
public List<string> GetGroups(string path, string username, string accountName, string accountPassword, int iterations)
{
    DirectoryEntry entry = new DirectoryEntry(path, accountName, accountPassword);
    DirectorySearcher searcher = new DirectorySearcher(entry);
    searcher.PropertiesToLoad.Add("memberOf");

    List<string> groups = new List<string>();

    GetGroupsRecursively(searcher, username, groups, iterations);

    return groups;
}

/// <summary>
/// Recursively gets the groups to which a user belongs.
/// </summary>
/// <param name="searcher">The DirectorySearcher performing the search.</param>
/// <param name="filter">The username or group to search for.</param>
/// <param name="groups">The list of groups found.</param>
/// <param name="iteration">The number of iterations left before exiting.</param>
/// <exception cref="System.Exception">Error obtaining group names.</exception>
private void GetGroupsRecursively(DirectorySearcher searcher, string filter, List<string> groups, int iteration)
{
    // Exit if the max number of iterations have been performed
    if (iteration > 0)
    {
        try
        {
            // Perform an Abiguous Name Resolution search
            searcher.Filter = "(aNR=" + filter + ")";

            SearchResult result = searcher.FindOne();

            // Check for failed search
            if (result == null)
            {
                return;
            }

            for (int i = 0; i < result.Properties["memberOf"].Count; i++)
            {
                string dn = (string)result.Properties["memberOf"][i];
                int equalsIndex = dn.IndexOf("=", 1);
                int commaIndex = dn.IndexOf(",", 1);
                        
                if (equalsIndex != -1)
                {
                    string role = dn.Substring((equalsIndex + 1), (commaIndex - equalsIndex) - 1);

                    // Don't add or iterate over a group that has already been found
                    if (!groups.Contains(role))
                    {
                        groups.Add(role);

                        // Now find all groups that this group belongs to
                        GetGroupsRecursively(searcher, role, groups, iteration - 1);
                    }
                }

            }
        }
        catch (Exception ex)
        {
            throw new Exception("Error obtaining group names.", ex);
        }
    }
}

 


Monday, May 6, 2013 at 6:00 PM


An old oak tree at the end of my parents' road.

I've wanted to photograph this tree and field for a number of years, but it seems that the conditions or timing have never been right. A week or so ago, we were at my parents' house to see my visiting aunts. It had been overcast and cloudy all day, when, at about 3pm, there was a break in the west. I grabbed my camera and GorillaPod Focus and quickly set up for this shot. I reallly like the framing that I was lucky enough to capture. All the lines, from the edges of the gravel path to the horizon to the clouds above, direct the viewer's eye toward the base of the tree. From there they naturally move upward into the detail of the branches. I also like how the sun is just peeking out from the corner in the upper-right.

I hope you enjoy this photo as much as I do. Be sure to click through the image to view a HD copy at 1900x1200. Also feel free to download it for use as a wallpaper, and, as always, leave a comment to let me know what you think.

Click the link below for details on the camera, lens, and settings used to take the photo as well as an overview of the image processing.


Sunday, May 5, 2013 at 12:59 PM

It's been a while since I've made a post, so I thought I would give a quick update on the progress I have been making on my blog. I haven't had as much time lately to work on it as I would have liked. I have gotten a few things accomplished, though. Click through to the full post to see what I've been up to.


Wednesday, April 3, 2013 at 6:00 PM

So I've had this domain for a couple of years, and I haven't really done anything with it. It's just been sitting here begging me to use it for something, anything. Well a couple weeks ago I finally decide to host a blog here. I looked into some of the .NET blog / CMS projects that were available: 

I didn't get very far when I realized that, even though all of them could be good choices in their own right, they are probably overkill for my little blog. I got to thinking that what I really should (and want to) do is write my own. Follow me after the jump for what I thought I would I need, what's been done so far, and what I plan to implement in the future.