User tokenGroups -> All Groups? Help!!

  • Thread starter Thread starter Chad Beckner
  • Start date Start date
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
 
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
 
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.
 
Thanks, I updated the code and added in a DirectoryEntry and put in the
credentials and it now works great! Appreciate the help.

Chad
 
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.
 
Back
Top