User tokenGroups -> All Groups? Help!!


C

Chad Beckner

First, sorry for crossposting, not sure exactly where to place this
question...

I can not seem to find a way to get a users (or my) tokenGroups from ADS
using VB.NET. I have seen several examples, but I can't get them to work.
Please check out my code below and let me know what I'm doing wrong...

Thanks!

Chad

CODE:

Public Shared Function GetGroups(ByVal strUsername As String) As SortedList
Dim i As Integer
Dim tmp As String
'Dim groupSid As Object
Dim sid() As Byte
Dim slGroupMembers As New SortedList
'Try
Dim dsUser As DirectorySearcher = New DirectorySearcher("(sAMAccountName=" +
strUsername + ")")
Dim res As SearchResult = dsUser.FindOne()
If res Is Nothing Then
HttpContext.Current.Response.Write("User not found!<br>")
Else
HttpContext.Current.Response.Write("User found!<br>")
Dim de As DirectoryEntry = res.GetDirectoryEntry
HttpContext.Current.Response.Write(de.Path & "<br>")
Dim props() As String = {"tokenGroups"}
de.RefreshCache(props)
HttpContext.Current.Response.Write(de.Properties("tokenGroups").Count.ToString()
& " Groups Found<br>")
'loop through each sid in the tokenGroups
For Each groupSid As Byte() In de.Properties("tokenGroups")
HttpContext.Current.Response.Write(ConvertToOctetString(sid, False, False) &
"<br>")
'Next
'For Each groupSid In de.Properties("tokenGroups")
'just another way of doing a ctype.
'sid = DirectCast(groupSid, Byte())
sid = groupSid
'set up the groupentry for query
'ConvertToOctetString is the important part here. This is where the real
work is.
HttpContext.Current.Response.Write(String.Format("LDAP://{0}",
ConvertToOctetString(sid, False, False)) & "<br>")
Dim groupEntry As New DirectoryEntry(String.Format("LDAP://{0}",
ConvertToOctetString(sid, False, False)))
Dim propcoll As PropertyCollection = groupEntry.Properties
slGroupMembers.Add(propcoll.Item("sn").Value.ToString,
propcoll.Item("sAMAccountName").Value.ToString & "|;|" &
propcoll.Item("sn").Value.ToString)
Next
End If
'Catch ex As Exception
' 'process exception
'End Try
Return slGroupMembers
End Function


RESULTS (what is outputted to the web page)

User found!
LDAP://CN=cbeckner,OU=Accounts,DC=XX,DC=XX,DC=XX
0 Groups Found
 
Ad

Advertisements

J

Joe Kaplan \(MVP - ADSI\)

The approach here is basically right (and looks pretty similar to samples
I've posted in the past). My first guess is that it could be a security
issue with the account you are using to access AD not being able to read the
tokenGroups attribute.

Your code isn't specifying an account to use (or even a DirectoryEntry for
the searcher, so you are getting "default" one), so the security will be
determined by the current security context,
System.Security.Principal.WindowsIdentity.GetCurrent().Name.

It is also possible that the local security context cannot "hop" to the
remote machine, in which case you might be getting authenticated as
anonymous remotely. That significantly lowers the possibility that you
could read tokenGroups, although it also makes it less likely that you could
do the original search for the user.

One thing that you might consider doing is getting Microsoft's ldp.exe tool
(from the adminpack for server 2003 or something) and trying to access
tokenGroups that way. It is done with a base level search on the object in
question. If you are careful to bind with the same security context that
your web code is using, you should be able to see if you can read that
attribute value.

HTH,

Joe K.
 
C

Chad Beckner

Update on this: I have been able to take the following code and run it in a
VB app just fine. However, in ASP.NET (using VB.NET), I still can't get the
token groups! HELP! :) The output is:

ADS\cbeckner
User found!
LDAP://CN=cbeckner,OU=Accounts,DC=xxx,DC=xx,DC=xxx
CN=cbeckner
0 Groups Found

CODE:

Dim slUserGroups As New SortedList
Dim Chad() As String
slUserGroups = GetUser_ADS_Groups("cbeckner")
For Each strUsername As String In slUserGroups.Values
Chad = strUsername.Split("|;|".ToCharArray)
Response.Write(Trim(Chad(0)) & "<br>")
Next

Public Shared Function GetUser_ADS_Groups(ByVal strUsername As String) As
SortedList
Dim objRootDSE As New DirectoryEntry("LDAP://RootDSE")
Dim searchRoot As DirectoryEntry = New DirectoryEntry("LDAP://" &
objRootDSE.Properties("defaultNamingContext")(0).ToString(), Nothing,
Nothing, AuthenticationTypes.Secure)
Dim slGroups As New SortedList

Try
Dim dsUser As DirectorySearcher = New
DirectorySearcher(String.Format("(&(objectCategory=person)(sAMAccountName={0}))",
strUsername))
Dim srcUser As SearchResultCollection = dsUser.FindAll()
If IsNothing(srcUser) Then
HttpContext.Current.Response.Write("User not found!<br>")
Else
HttpContext.Current.Response.Write("User found!<br>")
Dim de As DirectoryEntry = srcUser(0).GetDirectoryEntry
HttpContext.Current.Response.Write(de.Path & "<br>")
Dim props() As String = {"tokenGroups"}
de.RefreshCache(props)

HttpContext.Current.Response.Write(de.Name() & "<br>")
HttpContext.Current.Response.Flush()

HttpContext.Current.Response.Write(de.Properties("tokenGroups").Count.ToString()
& " Groups Found<br>")
HttpContext.Current.Response.Flush()

If de.Properties("tokenGroups").Count > 0 Then
<---------------- THIS IS WHERE IT "STOPS" ------------------------
Dim sb As New StringBuilder
sb.Append("(|")
For Each groupSid As Byte() In
de.Properties("tokenGroups")
sb.AppendFormat("(objectSid={0})",
ConvertToOctetString(groupSid))
Next
sb.Append(")")

Dim ds As DirectorySearcher
ds = New DirectorySearcher(searchRoot, sb.ToString(),
New String() {"cn", "distinguishedName"}, SearchScope.Subtree)

Dim src As SearchResultCollection
src = ds.FindAll

HttpContext.Current.Response.Write("IsNothing? " &
IsNothing(src).TrueString & "<br>")
HttpContext.Current.Response.Flush()

If Not IsNothing(src) Then
'slGroups = New SortedList
For intGroupIndex As Integer = 0 To src.Count - 1
slGroups.Add(src(intGroupIndex).Properties("cn")(0).ToString(),
src(intGroupIndex).Properties("cn")(0).ToString() & "|;|" &
src(intGroupIndex).Properties("distinguishedName")(0).ToString())
Next
End If
End If
End If
Catch ex As Exception
Throw
End Try

Return slGroups
End Function


Thanks!

Chad
 
J

Joe Kaplan \(MVP - ADSI\)

Like I said, this sounds like a security problem then. Your credentials are
probably not "hopping" to AD correctly and your are being authenticated as
anonymous remotely. You can check this with the class I posted here that
can show your remote auth status:

http://groups-beta.google.com/group...neral/msg/770818bc50c6ae68?dmode=source&hl=en

Note that also, your code below seems to create a DirectoryEntry object to
use as the search root for the DirectorySearcher and then does not use it on
the DirectorySearcher. This is mysterious.

The first thing I would suggest you do for troubleshooting purposes is
create a DirectoryEntry using the 4 parameter constructor that takes a
username, password and authentication types (use
AuthenticationTypes.Secure). Hard code the same credentials you are logging
in with and see if that works.

Joe K.
 
C

Chad Beckner

Thanks, I updated the code and added in a DirectoryEntry and put in the
credentials and it now works great! Appreciate the help.

Chad
 
Ad

Advertisements

J

Joe Kaplan \(MVP - ADSI\)

Ok, so that means it was definitely a security problem. The question is
then whether you want to leave it that way or try to solve the problem with
a default credentials bind. The default credentials approach is generally
considered "better" because you aren't hardcoding credentials in your code,
but it can also be harder to make work (as you have seen!) and is much
easier to have problems with due to environmental changes (e.g. the security
context you are using changes out from under you due to some changes made on
the server).

Best of luck with whichever approach you take.

Joe K.
 
Ad

Advertisements


Ask a Question

Want to reply to this thread or ask your own question?

You'll need to choose a username for the site, which only take a couple of moments. After that, you can post your question and our members will help you out.

Ask a Question

Top