Santry Technology Solutions, Content Management, DotNetNuke, SharePoint Consulting
Register | Login
Wednesday, January 07, 2009

Sections
  
About Us
  
Partners
Downloads
  
 WWWCoder.com Resource Directory

Active Directory Group Lookup
12/30/2003 6:25:53 PM

In a previous article we show many useful ways to query AD to get user information. However, one point left out is how to get ALL groups from AD when each user has a 'Primary Group' as the property 'MemberOf' does not return the 'Primary Group'. In this article we will provide one method of obtaining the 'Primary Group'.

A method I would like to add to the article "Methods for Active Directory Management" is a way to get the groups the user belongs to. The section titled "Obtaining Group Membership for a User" is a good start to getting your groups, however, it is not fully correct. Just checking the "MemberOf" property will give you the groups the user belongs to but not ALL of the groups. In a corporate environment each user would most likely belong to several groups and have one(1) primary group that they belong to. The property "MemberOf" does not supply the "Primary Group". And in instances when the user has just their "Primary Group" as the only group they belong to, it will show no groups at all. And as you might have guessed, there is little to no information that this is the case. After a lot of digging around and some help on the newsgroups I found a way to get this "Primary Group".

I am not going to go in depth into the code on this one. I have put in many comments to help you through it. The basic idea is to loop through your users or just to query for one user and then use the method Groups below to query for that users information. Groups takes in a single SearchRequest so you can only query one user at a time. However, in my Intranet application we do this for each user that logs in and the speed is very quick. Groups basically loops through the tokenGroups property to retrieve the sid for each group that the user belongs to. This is the only way I know of to get this information at this time. There are a couple of articles on Microsoft's site but the key piece they tend to leave out is how to actually use the Security Identifier (SID) or how to convert the SID.

Public Function Groups(ByVal SearchResult As System.DirectoryServices.SearchResult) As String
    Dim i As Integer
    Dim tmp As String
    Dim groupSid As Object
    Dim sid() As Byte
    Try
        Dim de As DirectoryEntry = SearchResult.GetDirectoryEntry
        'pull username and password from web.config file.
        de.Username = Configuration.ConfigurationSettings.AppSettings("User")
        de.Password = Configuration.ConfigurationSettings.AppSettings("Pass")
        de.RefreshCache(New String() {"tokenGroups"})
        'this line is sometimes necessary to get tokenGroups in the property cache...
        'loop through each sid in the tokenGroups
        For Each groupSid In de.Properties("tokenGroups")
            'just another way of doing a ctype.
            sid = DirectCast(groupSid, Byte())
            'set up the groupentry for query
            'ConvertToOctetString is the important part here. This is where the real work is.
            Dim groupEntry As New DirectoryEntry(String.Format("LDAP://", ConvertToOctetString(sid)))
            Dim propcoll As PropertyCollection = groupEntry.Properties
            Dim key As String
            Dim values As Object

            'loop through all of the properties for this record
            For Each key In propcoll.PropertyNames
                'loop through all the values associated with our key
                For Each values In propcoll(key)
                    If LCase(key) = "distinguishedname" Then
                      Dim temp As String = values.ToString
                      If Not InStr(temp, "ImportedExchange") Then
                        Dim atemp() As String = temp.Split(",")
                        tmp &= Replace(atemp(0).ToString, "CN=", ",")
                        If Left(tmp, 1) = "," Then
                            tmp = Mid(tmp, 2)
                        End If
                      End If
                    End If
                Next
            Next
        Next

    Catch ex As Exception
        'process exception
    End Try

    Return tmp
End Property

'overload for lazy programming
Public Overloads Shared Function ConvertToOctetString(ByVal values As Byte()) As String
    Return ConvertToOctetString(values, False, False)
End Function

'overload for lazy programming
Public Overloads Shared Function ConvertToOctetString(ByVal values As Byte(), _
     ByVal isAddBackslash As Boolean) As String
    Return ConvertToOctetString(values, isAddBackslash, False)
End Function

'This is where the work really comes in. This method allows us to convert the sid
'into a usable string that LDAP can use to search for the groups this user belongs to.
Public Overloads Shared Function ConvertToOctetString(ByVal values As Byte(), _
     ByVal isAddBackslash As Boolean, ByVal isUpperCase As Boolean) As String
    Dim iterator As Integer
    Dim builder As System.Text.StringBuilder

    Dim slash As String
    If isAddBackslash Then
        slash = "\"
    Else
        slash = String.Empty
    End If
    Dim formatCode As String
    If isUpperCase Then
        formatCode = "X2"
    Else
        formatCode = "x2"
    End If
    builder = New System.Text.StringBuilder(values.Length * 2)
    For iterator = 0 To values.Length - 1
        builder.Append(slash)
        builder.Append(values(iterator).ToString(formatCode))
    Next

    Return builder.ToString()

End Function

So until next time. Cya.
Stanley
http:///www.glass-images.com

Author Name: Stanley Glass Jr
Bio: Stanley has been programming for about 10 years now. Starting first with Basic. With the introduction of the Internet he found a new desire. A desire to create web pages. Once he created his first he was addicted to it. Html, then javascript, then Perl, on to ASP, and then on to VB and now ending with VB.NET and ASP.NET.
 

Related Articles
   Related Document Methods for Active Directory Management
   Related Document Obtaining Active Directory User Information Using System.DirectoryServices


Page Options:
format for printing  Format for Printer
email article  Email Page
add to your favorites   Add to Favorites
How would you rate the quality of this content?
Poor - - Excellent
Comments?
Overall Rating:
Comments Left:
Left on 9/10/2007 2:50:29 PM by Anonymous
Comments: loser
No ratings available.
Left on 5/25/2007 9:25:17 AM by Anonymous
Comments: Looks like you won't be getting a job offer, eh? :-)
Left on 5/15/2007 12:52:35 PM by Anonymous
Comments: this is not a job posting site you assholes
Left on 3/30/2007 9:44:31 AM by Anonymous
Comments: great stuff!

http://www.tabernusdelectatio.com
Left on 3/15/2007 3:37:38 PM by Anonymous
Comments:
Left on 7/6/2006 10:58:19 AM by Anonymous
Comments: Can someone please give an example of how to pass SearchResult to the groups function and to call this function? thanks
No ratings available.
Left on 2/19/2006 9:25:57 PM by Sean Howell
Comments: Well Done
Left on 8/8/2005 2:52:29 PM by Anonymous
Comments: There is an error in this code.  The line:
Dim groupEntry As New DirectoryEntry(String.Format("LDAP://", ConvertToOctetString(sid)))

should read:
                Dim groupEntry As New DirectoryEntry(String.Format("LDAP://", ConvertToOctetString(sid)))


No ratings available.
Left on 6/24/2005 9:44:52 AM by Anonymous
Comments: Can someone please give an example of how to pass SearchResult to the groups function
No ratings available.
Left on 6/16/2005 4:27:12 PM by Anonymous
Comments: I tried using your code, but I need to do this in C#.  memberOf does not return the root group, and that is what I need.
Left on 4/1/2005 4:21:25 PM by Anonymous
Comments: i ran down my leg

Left on 4/1/2005 4:19:59 PM by Anonymous
Comments: I just crapped myself

Left on 2/22/2005 9:36:15 AM by Anonymous
Comments: Job requirement.
Hello

I have following job requirements. If you are interested, please send your resume.
-------------
Exchange/Active Directory Architect with Cluster skills
And must have architected solutions in a 40,000+ user environment.  Must have Exchange 2003 skills.

Salary: up to 135,000/Year base + 50% Bonus.

Location: You can work out of any location in Sount East

Duration: Contract or Permanent

Please answer these questions
1. Have you architected and implemented exchange in 50,000+ user environment? 
2. Do you have experience with Exchange Cluster? 
3. Have you worked with exchange 2003? If not how many years in exchange 2000? 
4. have you migrated from a different messaging platform to exchange ? 
5. Are you willing to travel for the job?
---------------
Sr. Level Active Directory  Architect for Contract-Hire opportunities with a very HIGH Profile client. Very High Pay Range  Contract corp to corp bill rate is 90$ to 100$ / hour.

MS Active Directory Architect

Multiple Position Open at Multiple Locations: NY, NJ, Washington DC, Raleigh, Tampa, Ft Lauderdale, Atlanta, Philly, Boston, Reston, VA.

Must have strong technical expertise in Large scale enterprise active directory architecture design experience (100,000 users), large scale Windows 2003, Active Directory design. We are looking for top of line Solutions Architects. Excellent client Facing skills is a 100% Must. Must have worked for very Large Enterprise Environments.
--------------
Also I have other job requirements at diffrent locations in U S. If you are interested, please send your resume with your all inclusive contract bill rate / salary, and choice of job location.
Best regards
Milind
--------------------------------------------
Milind Adkar.
Formulasys Inc.
19925 Stevens creek blvd.
Cupertino. Ca 95014 2358.
Phone - 408 850 8100.
Fax - 408 904 7208.
www.formulasys.com
milind.adkar@formulasys.com



No ratings available.
Left on 2/21/2005 10:54:31 PM by Anonymous
Comments: this looks great, but I'm having troubles with this line:
Dim groupEntry As New DirectoryEntry(String.Format("LDAP://", ConvertToOctetString(sid))) and have also tried Dim groupEntry As New DirectoryEntry(String.Format("LDAP://", ConvertToOctetString(sid))) but both give errors.

Can anyone help?

Thanks
No ratings available.
Left on 1/28/2005 9:33:22 AM by Anonymous
Comments: Job requirement.
Hello

I have following job requirement. If you are interested, please send your resume with your expected minimum contract bill rate, and minimum permanent salary, all inclusive.

Sr. Level Active Directory  Architect for Contract-Hire opportunities with a very HIGH Profile client. Very High Pay Range

MS Active Directory Architect

Multiple Position Open at Multiple Locations: NY, NJ, Washington DC, Raleigh, Tampa, Ft Lauderdale, Atlanta, Philly, Boston, Reston, VA.

Must have strong technical expertise in Large scale enterprise active directory architecture design experience (100,000 users), large scale Windows 2003, Active Directory design. We are looking for top of line Solutions Architects. Excellent client Facing skills is a 100% Must. Must have worked for very Large Enterprise Environments.


Best regards
Milind
--------------------------------------------
Milind Adkar.
Formulasys Inc.
19925 Stevens creek blvd.
Cupertino. Ca 95014 2358.
Phone - 408 850 8100.
Fax - 408 904 7208.
www.formulasys.com
milind.adkar@formulasys.com





Job requirement.
Hello

I have following job requirement. If you are interested, please send your resume with your expected minimum contract bill rate, and minimum permanent salary, all inclusive.

Sr. Level Active Directory  Architect for Contract-Hire opportunities with a very HIGH Profile client. Very High Pay Range

MS Active Directory Architect

Multiple Position Open at Multiple Locations: NY, NJ, Washington DC, Raleigh, Tampa, Ft Lauderdale, Atlanta, Philly, Boston, Reston, VA.

Must have strong technical expertise in Large scale enterprise active directory architecture design experience (100,000 users), large scale Windows 2003, Active Directory design. We are looking for top of line Solutions Architects. Excellent client Facing skills is a 100% Must. Must have worked for very Large Enterprise Environments.


Best regards
Milind
--------------------------------------------
Milind Adkar.
Formulasys Inc.
19925 Stevens creek blvd.
Cupertino. Ca 95014 2358.
Phone - 408 850 8100.
Fax - 408 904 7208.
www.formulasys.com
milind.adkar@formulasys.com
















No ratings available.
Left on 12/28/2004 5:26:39 PM by Anonymous
Comments: One question: How can I query every group active directory their members, then output to a txt file ?  - Thanks
Left on 12/15/2004 4:32:04 AM by Anonymous
Comments: Hi, Thank you for your solution but there is a small problem with this..the line below that i have pasted needs the proper formatting to display in the browser.. it is missing the below:
LDAP:// and is displayed like below:
Dim groupEntry As New DirectoryEntry(String.Format("LDAP://", ConvertToOctetString(sid)))

No ratings available.
Left on 11/26/2004 11:15:43 AM by Anonymous
Comments: Thanks,
gave me an idea to solve a related problem.
No ratings available.
Left on 10/5/2004 5:15:21 PM by Anonymous
Comments: I am very impressed by the tech quality ofg this article, and yet wonder why you have never had a full time 40 hour per week job?
Terry Alan Klasek, Disabled Veteran
Left on 7/2/2004 2:31:26 PM by Anonymous
Comments: Hi Stanley,

The next time you take someone's code out of a newsgroup post, copy it nearly verbatim and post it as an article, the polite thing to do would be to give credit to the original author. 

It would also make a lot more sense if your code returned an array of strings containing the samAccountName attribute of each group.  To make it really valid for security purposes, you should also dynamically calculate the domain for the SID and include that in the returned string so you have the form domain\samAccountName.  You cannot assume that all groups in tokenGroups come from the same domain.

Cheers,

Joe Kaplan
No ratings available.
Left on 5/31/2004 12:21:20 PM by Anonymous
Comments: How would I use this code? What objects to I pass to the Groups function?
Left on 2/26/2004 6:07:59 AM by Anonymous
Comments: I am developing a utility by means of which the data from AD is retrieved and put up into staging tables. I am not a very experiened programmer and this article has helped me a lot. Thanks Stanlry
Left on 1/23/2004 2:46:21 AM by Anonymous
Comments: Here is another way http://dotnetjunkies.com/weblog/robwalker/posts/5965.aspx
No ratings available.
Left on 1/14/2004 1:26:13 PM by Anonymous
Comments: yes, its pinging... do need I special permissions in AD? To have access to the groups that this user belongs?
No ratings available.
Left on 1/14/2004 12:59:51 PM by Anonymous
Comments: try to ping the domain, i.e: ping mydomain at the command prompt.
No ratings available.
Left on 1/14/2004 12:52:28 PM by Anonymous
Comments: how should I test this?
No ratings available.
Left on 1/14/2004 11:34:23 AM by Anonymous
Comments: Are you able to run to the share on the Web server? First see if you can do it manually via Explorer.
No ratings available.
Left on 1/14/2004 8:00:00 AM by Anonymous
Comments: I'm getting this error: Someone knows why??
{System.Runtime.InteropServices.COMException}
    [System.Runtime.InteropServices.COMException]: {System.Runtime.InteropServices.COMException}
    HelpLink: Nothing
    InnerException: Nothing
    Message: "The specified domain either does not exist or could not be contacted"
    Source: "System.DirectoryServices"
    StackTrace: "  at System.DirectoryServices.DirectoryEntry.Bind(Boolean throwIfFail)
  at System.DirectoryServices.DirectoryEntry.Bind()
  at System.DirectoryServices.DirectoryEntry.RefreshCache()
  at System.DirectoryServices.DirectoryEntry.FillCache(String propertyName)
  at System.DirectoryServices.KeysCollection.GetEnumerator()
  at SIM.WebForm1.Groups(SearchResult SearchResult) in c:\inetpub\wwwroot\SIM\WebForm1.aspx.vb:line 103"
    TargetSite: {System.Reflection.RuntimeMethodInfo}

No ratings available.
Left on 1/13/2004 6:33:26 PM by Anonymous
Comments: There is a problem in this code. The line with the format statement is incomplete. It should read Dim groupEntry As New DirectoryEntry(String.Format("LDAP://", ConvertToOctetString(sid)))
Left on 1/13/2004 5:15:21 PM by Anonymous
Comments: Great article.  Just what I was looking for.
Left on 1/11/2004 8:19:16 PM by Anonymous
Comments: Stupid people who get in a flame war over syntax C# vs VB.NET.  Its all CLR you moron.  Performance is the same. 
Left on 1/9/2004 3:56:54 PM by Anonymous
Comments: And what is VB.Net a pretend language, Mr. "Real" they all get compiled into the same CLR, give me a break. Programming languages are a preference for people, like chocolate versus vanilla ice cream. If you can accomplish what you need to do in one language as you could in another who really cares what it is written in? I can easily convert VB.Net code into C# and C# into VB.Net, the main thing I get out reading the various articles are concepts and ways of doing things, I really don't care what language it is in just convert it. What you need to do is become multi lingual, then maybe you can increase your salary.
No ratings available.
Left on 1/9/2004 3:48:12 PM by Anonymous
Comments: Should do things in a real language like C#
No ratings available.
Left on 1/6/2004 12:03:53 AM by Anonymous
Comments: hello, I am .net programmer too. that's nice. thanks very much :)
Left on 12/30/2003 8:10:15 PM by Anonymous
Comments: Great just what I was looking for.
  

 Latest Articles
  

 Latest News
  

 

Spotlight
Syndication

 


 


Digg This
 


DotNetNuke Platinum Benefactor

  
 

 Terms Of Use | Privacy Statement
 Copyright 2008 - Santry Technology Solutions, Box 172, Girard, PA 16417, (814) 774-0970