
Win2K/Net user group enumeration with LDAP?
Hi,
The short answer is that it can be done with LDAP.
However, it can quickly get complicated. I note that you
use a loop to retrieve objNet.UserName, so I assume you
have Win9x clients. I find that objNet.UserDomain returns
blank on Win9x clients. Also, to use Wscript.Sleep, all
the clients must have WSH 5.1 or above.
LDAP has many advantages, such as revealing membership in
nested groups. It also reveals many more attributes. If
you don't need these features, you can stick with WinNT.
If you use LDAP, I assume you want to take advantage of
it, so I include an IsMember function that handles nested
groups. It doesn't crash if the nested groups are
circular. However, it does NOT reveal membership in
the "primary" group. This is a limitation of LDAP.
The first problem with LDAP (after you get
objNet.UserName) is binding to the user object.
objNet.UserName must be translated. Also, getting the DNS
Domain name is required. All of this is handled below.
Note that group objects do not support the .Groups method,
so you must use the .MemberOf collection in a recursive
function to get nested groups. The code has to handle
cases where this collection is empty, has one item, or has
many items.
Option Explicit
Dim oRoot, oTrans, sNetBIOSDomain, oNet, sNTUser, sAdsPath
Dim oGroupList, sGroup, oUser, sDNSDomain
Set oNet = CreateObject("Wscript.Network")
sNTName = ""
On Error Resume Next
Err.Clear
Do While sNTName = ""
sNTName = oNet.UserName
Err.Clear
If Wscript.Version > 5 Then
Wscript.Sleep 100
End If
Loop
On Error GoTo 0
Set oRoot = GetObject("LDAP://RootDSE")
Set oTrans = CreateObject("NameTranslate")
sDNSDomain = oRoot.Get("DefaultNamingContext")
oTrans.Init 3, sDNSDomain
oTrans.Set 1, sDNSDomain
sNetBIOSDomain = oTrans.Get(3)
oTrans.Init 1, _
Left(sNetBIOSDomain, Len(sNetBIOSDomain) - 1)
oTrans.Set 3, sNetBIOSDomain & sNTUser
sAdsPath = oTrans.Get(1)
Set oUser = GetObject("LDAP://" & sAdsPath)
If IsMember("Domain Admin") Then
oNet.MapNetworkDrive "M:", "\\filesrv01\admin"
End If
Function IsMember(sGroup)
' Function to test for group membership.
If IsEmpty(oGroupList) Then
Set oGroupList = CreateObject("Scripting.Dictionary")
Call LoadGroups(oUser)
End If
IsMember = oGroupList.Exists(sGroup)
End Function
Sub LoadGroups(oADObject)
' Recursive subroutine to populate dictionary object.
Dim sGroups, oGroup, j
oGroupList.CompareMode = vbTextCompare
sGroups = oADObject.MemberOf
If IsEmpty(sGroups) Then
Exit Sub
End If
If TypeName(sGroups) = "String" Then
Set oGroup = GetObject("LDAP://" & sGroups)
If Not oGroupList.Exists(oGroup.sAMAccountName) Then
oGroupList(oGroup.sAMAccountName) = True
Call LoadGroups(oGroup)
End If
Set oGroup = Nothing
Exit Sub
End If
For j = 0 To UBound(sGroups)
Set oGroup = GetObject("LDAP://" & sGroups(j))
If Not oGroupList.Exists(oGroup.sAMAccountName) Then
oGroupList(oGroup.sAMAccountName) = True
Call LoadGroups(oGroup)
End If
Next
Set oGroup = Nothing
End Sub
If you need a routine that reveals "primary" group
membership, reply. In most networks this is left as the
default "Domain User" for users and "Domain Computers" for
computer objects, but it can be changed. There are ways to
handle it. Note that the IsMember function above also
works with computer objects. You could map printers
according to which group the computer belongs to.
Richard
Quote:
>-----Original Message-----
>I know user group enumeration has been beaten to death in
this
>newsgroup and I have read many of the articles. Michael
Harris's
>script and knowledge are the basis of what I have so far
and it works
>well. I will include my modified logon script below...
>My question is, can this script be modified to use LDAP?
It might be
>simple... I just don't understand LDAP that well. Here is
one entry of
>what my User container looks like:
>LDAP://yamato/CN=Test
User,CN=Users,DC=Command,DC=starbase-01,DC=com
Quote:
>And here is the basic LDAP connection to pull the data:
>Set UserContainer =
>GetObject("LDAP://yamato/CN=Users,DC=Command,DC=starbase-
01,DC=com")
>Hope this helps someone answer my question.
>Thanks!
>/*Raj*/
>=-=-=-=-=-=-=-=-=-=-=-=-=
>Logon script
>=-=-=-=-=-=-=-=-=-=-=-=-=
>Option Explicit
>Dim strDomainName, strUsername
>Dim objNet
>Dim objGroupList
>Dim objUser
>Set objNet = createObject("Wscript.Network")
>On Error Resume Next
> strUsername = ""
> While strUsername = ""
> Err.Clear: strUsername = objNet.Username
> If Err Then WScript.Sleep 100
> Wend
>On Error Goto 0
>'Get the Domain Name
>strDomainName = objNet.UserDomain
>Set objGroupList = CreateObject("Scripting.Dictionary")
>Call LoadNTGroups(strDomainName, strUsername)
>'Print some information for the user
>Set objUser = GetObject("WinNT://" & strDomainName & "/" &
>strUsername)
>Wscript.Echo "Hello " & objUser.FullName
>Wscript.Echo "Password expires on: " &
objUser.passwordexpirationdate
Quote:
>If InGroup("domain users") Then
> 'do this....
> Wscript.Echo "User is a Domain User"
> 'Map drive(s)
> 'objNet.MapNetworkDrive "l:", "\\filesrv01\applics"
>End if
>If InGroup("domain admins") Then
> 'do that...
> Wscript.Echo "User is a Domain Admin"
> 'Map drive(s)
> 'objNet.MapNetworkDrive "m:", "\\filesrv01\admin"
>End If
>'=========================================================
===========
>' Load objGroupList (Dictionary) with user's NT group
membership...
>'=========================================================
===========
>Sub LoadNTGroups(vDomainName, vUsername)
> Dim objUser
> Dim objGrp
> Set objUser = GetObject("WinNT://" & vDomainName & "/"
& vUsername)
> objGroupList.CompareMode = vbTextCompare
> For Each objGrp In objUser.Groups
> objGroupList(objGrp.name) = True
> Next
>End Sub
>'=========================================================
===========
>' Emulate the KIX InGroup function...
>'=========================================================
===========
>Function InGroup(sGroup)
> InGroup = objGroupList.Exists(sGroup)
>End Function
>Wscript.Quit
>.