[Sample of Mar 2nd] Get User Group Membership in AD

 

Homepage image
Sample of the Day RSS Feed

Sample download: https://code.msdn.microsoft.com/VBGetUserGroupInAD-a94dc080

Today’s code sample illustrates how to perform a search on the user’s group membership in Active Directory. This demonstrates the recursive looping method. Also it shows how to get the Object SID for the group.   The sample was written by Microsoft Support Escalation Engineer Shaleen Thapa.

imageYou can find more code samples that demonstrate the most typical programming scenarios by using Microsoft All-In-One Code Framework Sample Browser or Sample Browser Visual Studio extension. They give you the flexibility to search samples, download samples on demand, manage the downloaded samples in a centralized place, and automatically be notified about sample updates. If it is the first time that you hear about Microsoft All-In-One Code Framework, please watch the introduction video on Microsoft Showcase, or read the introduction on our homepage https://1code.codeplex.com/.

 

Introduction

This sample application demonstrates how to perform a search on the user’s group membership in Active Directory. This demonstrates the recursive looping method. Also it shows how to get the Object SID for the group

 

Running the Sample

You can execute this sample by creating the exe via Visual Studio.

In order to execute the application, you must need to consider the followings:

  • Please change the distingusihedName of the domain as per your domain environment. This you should find at the line# 31 in the file VBGetUserGroupInAD.VB. Currently it is using DC=contoso,DC=com
  • Please pass the appropriate user’s sAMAccountName as the second parameter, for which we are searching the group membership in AD

 

Using the Code

We are using System.DirectoryServices namespace to perform a search on AD. We will be passing the distinguishedName of the domain with the username whose membership we would like to fetch.

Once we found the user, we will read the memberOF attribute’s value. It is one of the possibilities that the group can be member of another group as well; in this case we would need to do a recursive looping.

     ''' <summary> 
    ''' This function will search the user. 
    ''' Once user is found, it will get it's memberOF attribute's value. 
    ''' </summary> 
    ''' <param name="domainDN">distinguishedName of the domain</param> 
    ''' <param name="sAMAccountName"> 
    ''' sAMAccountName of the user for which we are searching the group membership in AD 
    ''' </param> 
    ''' <returns></returns> 
    ''' <remarks></remarks> 
    Public Function GetUserGroups(ByVal domainDN As String, ByVal sAMAccountName As String) As List(Of String) 
        Try 
            'Create the DirectoryEntry object to bind the distingusihedName of your domain 
            Using rootDE As New DirectoryEntry("LDAP://" & domainDN) 
 
                'Create a DirectorySearcher for performing a search on abiove created DirectoryEntry 
                Using dSearcher As New DirectorySearcher(rootDE) 
 
                    'Create the sAMAccountName as filter 
                    dSearcher.Filter = "(&(sAMAccountName=" & sAMAccountName & ")(objectClass=User)(objectCategory=Person))" 
                    dSearcher.PropertiesToLoad.Add("memberOf") 
                    dSearcher.ClientTimeout.Add(New TimeSpan(0, 20, 0)) 
                    dSearcher.ServerTimeLimit.Add(New TimeSpan(0, 20, 0)) 
 
                    'Search the user in AD 
                    Dim sResult As SearchResult = dSearcher.FindOne 
                    If sResult Is Nothing Then 
                        Throw New ApplicationException("No user with username " & sAMAccountName & " could be found in the domain") 
                    Else 
                        Dim lGroups As New List(Of String) 
                        'Once we get the userm let us get all the memberOF attibute's value 
                        For Each grp In sResult.Properties("memberOf") 
                            Dim sGrpName As String = CStr(grp).Remove(0, 3) 
                            'Bind to this group 
                            Dim deTempForSID As New DirectoryEntry("LDAP://" + grp.ToString().Replace("/", "\/")) 
                            Try 
                                deTempForSID.RefreshCache() 
 
                                'Get the objectSID which is Byte array 
                                Dim objectSid As Byte() = DirectCast(deTempForSID.Properties("objectSid").Value, Byte()) 
 
                                'Pass this Byte array to Security.Principal.SecurityIdentifier to convert this 
                                'byte array to SDDL format 
                                Dim SID As New System.Security.Principal.SecurityIdentifier(objectSid, 0) 
 
                                If sGrpName.Contains(",CN") Then 
                                    sGrpName = sGrpName.Remove(sGrpName.IndexOf(",CN")) 
                                ElseIf sGrpName.Contains(",OU") Then 
                                    sGrpName = sGrpName.Remove(sGrpName.IndexOf(",OU")) 
                                End If 
 
                                'Perform a recursive search on these groups. 
                                RecursivelyGetGroups(dSearcher, lGroups, sGrpName, SID.ToString()) 
                            Catch ex As Exception 
                                Console.WriteLine("Error while binding to path : " + grp.ToString()) 
                                Console.WriteLine(ex.Message.ToString()) 
                            End Try 
                        Next 
                        Return lGroups 
                    End If 
                End Using 
            End Using 
        Catch ex As Exception 
            Console.WriteLine("Please check the distinguishedName of the domain if it is as per your domain or not?") 
            Console.WriteLine(ex.Message.ToString()) 
            End 
        End Try 
    End Function 
 
    ''' <summary> 
    ''' This function will perform a recursive search and will add only one occurance of 
    ''' the group found in the enumeration. 
    ''' </summary> 
    ''' <param name="dSearcher">DirectorySearcher object to perform search</param> 
    ''' <param name="lGroups">List of the Groups from AD</param> 
    ''' <param name="sGrpName"> 
    ''' Group name which needs to be checked inside the Groups collection 
    ''' </param> 
    ''' <param name="SID">objectSID of the object</param> 
    ''' <remarks></remarks> 
    Public Sub RecursivelyGetGroups(ByVal dSearcher As DirectorySearcher, ByVal lGroups As List(Of String), ByVal sGrpName As String, ByVal SID As String) 
        'Check if the group has already not found 
        If Not lGroups.Contains(sGrpName) Then 
            lGroups.Add(sGrpName & " : " & SID) 
 
            'Now perform the search based on this group 
            dSearcher.Filter = "(&(objectClass=grp)(CN=" & sGrpName & "))".Replace("\", "\\") 
            dSearcher.ClientTimeout.Add(New TimeSpan(0, 2, 0)) 
            dSearcher.ServerTimeLimit.Add(New TimeSpan(0, 2, 0)) 
 
            'Search this group 
            Dim GroupSearchResult As SearchResult = dSearcher.FindOne 
            If Not GroupSearchResult Is Nothing Then 
                For Each grp In GroupSearchResult.Properties("memberOf") 
                    Dim ParentGroupName As String = CStr(grp).Remove(0, 3) 
 
                    'Bind to this group 
                    Dim deTempForSID As New DirectoryEntry("LDAP://" + grp.ToString().Replace("/", "\/")) 
                    Try 
                        'Get the objectSID which is Byte array 
                        Dim objectSid As Byte() = DirectCast(deTempForSID.Properties("objectSid").Value, Byte()) 
 
                        'Pass this Byte array to Security.Principal.SecurityIdentifier to convert this 
                        'byte array to SDDL format 
                        Dim ParentSID As New System.Security.Principal.SecurityIdentifier(objectSid, 0) 
 
                        If ParentGroupName.Contains(",CN") Then 
                            ParentGroupName = ParentGroupName.Remove(ParentGroupName.IndexOf(",CN")) 
                        ElseIf ParentGroupName.Contains(",OU") Then 
                            ParentGroupName = ParentGroupName.Remove(ParentGroupName.IndexOf(",OU")) 
                        End If 
                        RecursivelyGetGroups(dSearcher, lGroups, ParentGroupName, ParentSID.ToString()) 
                    Catch ex As Exception 
                        Console.WriteLine("Error while binding to path : " + grp.ToString()) 
                        Console.WriteLine(ex.Message.ToString()) 
                    End Try 
                Next 
            End If 
        End If 
    End Sub 

 

More Information

For more information on System.DirectoryServices Namespace https://msdn.microsoft.com/en-us/library/system.directoryservices.aspx , DirectoryEntry Class https://msdn.microsoft.com/en-us/library/system.directoryservices.directoryentry.aspx & DirectorySearcher Class https://msdn.microsoft.com/en-us/library/system.directoryservices.directorysearcher.aspx

For System.Security.Principal.SecurityIdentifier https://msdn.microsoft.com/en-us/library/system.security.principal.securityidentifier.aspx