How to get indirect groups of an AD user? - C#
I'm using DirectorySearcher to get the groups of an AD user in which he is a member of using the 'memberof' property. But according to this msdn page the 'memberof' property only returns the direct groups in which the user is a member. How can I get the indirect groups of the user too.
Group A -> User X, User Y, Group B Group B -> User Z Group C -> User Z
I want to get the result as Group A, Group B, Group C for the user Z since he is an indirect user of Group A.
Okie. I've followed this codeproject article to get the groups recursively. But still the builtin group 'Domain Users' is missing from the list. So does that mean Built in groups wont appear in the directory searcher?
You have to define your own method of iterating through the direct groups until you reach the common root for all. You will need to perform an LDAP query against each group and use the same memberOf attribute to determine which groups that group belongs to. This can be time intensive, particularly if the groups are numerous and laid out web-like.
My answer follows the same lines as Joel Etherton's, but with code. I implemented this a while ago in one of my apps. All you need to do is interpret the VB.Net to C# :). The code below will take a group and return all of the child groups. So you just need to loop through for each group and put them in a list. I reference a few methods that I didn't include but should be self explanatory. I did include PrincipalGenericCollection, since it can be handy.
Public Function GetSubGroups(ByVal groupname As String) As List(Of String) Dim result As New List(Of String)() GetSubGroups(groupname, result) Return result End Function Public Sub GetSubGroups(ByVal Group As String, ByRef l As List(Of String)) Dim grp = GetGroup(Group) 'sometimes group will be null if its a system built in group like "authenticated users"' If grp Is Nothing Then Exit Sub End If Dim sGroups = GetGroupMembership(Group, False).Where(Function(c) TypeOf c Is GroupPrincipal) For Each g In sGroups Dim n As String = FormatPrincipalName(g.Name) If Not l.Contains(n) Then l.Add(n) GetSubGroups(g.Name, l) End If Next End Sub Public Function GetGroupMembership(ByVal GroupName As String, Optional ByVal Recursive As Boolean = True) As PrincipalGenericCollection(Of Principal) Dim group As GroupPrincipal = GetGroup(GroupName) If group Is Nothing Then Return Nothing End If Dim prinCol As New PrincipalGenericCollection(Of Principal)(group.GetMembers(Recursive)) prinCol.SortByName() Return prinCol End Function Public Class PrincipalGenericCollection(Of T As Principal) Inherits List(Of T) Public Sub New() MyBase.New() End Sub Public Sub New(ByVal collection As PrincipalCollection) For Each p As Principal In collection Me.Add(p) Next End Sub Public Sub New(ByVal collection As IEnumerable(Of T)) MyBase.New(collection) End Sub Public Sub SortByName() Sort(New PrincipalSorter(Of T)) End Sub End Class
The primary group of the user won't be shown in the "memberOf" property. Instead, it's RID is stored in the "primaryGroupID" property, and you have to calculate the group's SID from that RID (which is domain SID+group RID).
Thats why you couldn't find the Domain Users group (which is the user's primary group)
Sounds to me like a simple recursive approach. Find the groups, the user is member of and for each group, find the groups, the group is member of. Repeat until no more memberships are found.