Sign in to follow this  
Followers 0
zenmaster

Help with VBS to AU3 Script. (Nested ADS Groups)

6 posts in this topic

I have written some AU3 Scripts that pull a user's group membership list and I have even seen some examples here. However, I have not been able to script the return of "nested groups". (If you are a member of GroupB and GroupB is a Member of GroupA then you would be listed as a member of both GroupA and GroupB instead of just GroupB.

Below is a quite complex VBS script that actually returns results quite efficiently.

I am currently using this script in a large tree (It returns hundreds of group memberships in about 2 seconds.) However, I would like to be able to launch not need to have to pass the info into my AutoIt Apps. The amount of data is quite large and I would find it more secure if I was querying AD directly and not depending on the fact that the data being passed to my app is not being sent by a source other than the real VBS script that is querying AD.

------------------------------------------------------------------------------------------------------------

' IsMember8.vbs

' _VBScript program demonstrating the use of Function IsMember.

'

' ----------------------------------------------------------------------

' Copyright © 2004 Richard L. Mueller

' Hilltop Lab web site - http://www.rlmueller.net

' Version 1.0 - March 28, 2004

' An efficient IsMember function to test group membership for any number

' of users or computers, using the "tokenGroups" attribute. The function

' reveals membership in nested groups and the primary group. It requires

' that the user or computer object be bound with the LDAP provider.

' Based on an idea by Joe Kaplan.

'

' You have a royalty-free right to use, modify, reproduce, and

' distribute this script file in any way you find useful, provided that

' you agree that the copyright owner above has no warranty, obligations,

' or liability for such use.

Option Explicit

Dim objADUser, objGroupList, allGroups, oADsSysInfo, objMyWin

Dim objCommand, objConnection, strBase, strAttributes

Set oADsSysInfo = CreateObject("ADSystemInfo")

'WScript.Echo "Distinguished name of the current user: " & oADsSysInfo.UserName

' Bind to the user or computer object in Active Directory with the LDAP

' provider.

Set objADUser = GetObject("LDAP://" & oADsSysInfo.UserName)

' Test for group membership.

allGroups=""

IsMember(objADUser)

'Wscript.Echo allGroups

'MsgBox allGroups,, "AllADGroups"

Set objMyWin = WScript.CreateObject("Wscript.Shell")

objMyWin.Popup allGroups

' Clean up.

If IsObject(objConnection) Then

objConnection.Close

Set objCommand = Nothing

Set objConnection = Nothing

Set objGroupList = Nothing

End If

Set objADUser = Nothing

Function IsMember(objADObject)

' Function to test for group membership.

' objADObject is a user or computer object.

' strGroupNTName is the NT name (sAMAccountName) of the group to test.

' objGroupList is a dictionary object, with global scope.

' Returns True if the user or computer is a member of the group.

' Subroutine LoadGroups is called once for each different objADObject.

Dim objRootDSE, strDNSDomain

' The first time IsMember is called, setup the dictionary object

' and objects required for ADO.

If IsEmpty(objGroupList) Then

Set objGroupList = CreateObject("Scripting.Dictionary")

objGroupList.CompareMode = vbTextCompare

Set objCommand = CreateObject("ADODB.Command")

Set objConnection = CreateObject("ADODB.Connection")

objConnection.Provider = "ADsDSOObject"

objConnection.Open "Active Directory Provider"

objCommand.ActiveConnection = objConnection

Set objRootDSE = GetObject("LDAP://RootDSE")

strDNSDomain = objRootDSE.Get("defaultNamingContext")

objCommand.Properties("Page Size") = 100

objCommand.Properties("Timeout") = 30

objCommand.Properties("Cache Results") = False

' Search entire domain.

strBase = "<LDAP://" & strDNSDomain & ">"

' Retrieve NT name of each group.

strAttributes = "sAMAccountName"

' Load group memberships for this user or computer into dictionary

' object.

Call LoadGroups(objADObject)

Set objRootDSE = Nothing

End If

End Function

Sub LoadGroups(objADObject)

' Subroutine to populate dictionary object with group memberships.

' objGroupList is a dictionary object, with global scope. It keeps track

' of group memberships for each user or computer separately. ADO is used

' to retrieve the name of the group corresponding to each objectSid in

' the tokenGroup array. Based on an idea by Joe Kaplan.

Dim arrbytGroups, k, strFilter, objRecordSet, strGroupName, strQuery

' Add user name to dictionary object, so LoadGroups need only be

' called once for each user or computer.

objGroupList(objADObject.sAMAccountName & "\") = True

' Retrieve tokenGroups array, a calculated attribute.

objADObject.GetInfoEx Array("tokenGroups"), 0

arrbytGroups = objADObject.Get("tokenGroups")

' Create a filter to search for groups with objectSid equal to each

' value in tokenGroups array.

strFilter = "(|"

If TypeName(arrbytGroups) = "Byte()" Then

' tokenGroups has one entry.

strFilter = strFilter & "(objectSid=" _

& OctetToHexStr(arrbytGroups) & ")"

ElseIf UBound(arrbytGroups) > -1 Then

' TokenGroups is an array of two or more objectSid's.

For k = 0 To UBound(arrbytGroups)

strFilter = strFilter & "(objectSid=" _

& OctetToHexStr(arrbytGroups(k)) & ")"

Next

Else

' tokenGroups has no objectSid's.

Exit Sub

End If

strFilter = strFilter & ")"

' Use ADO to search for groups whose objectSid matches any of the

' tokenGroups values for this user or computer.

strQuery = strBase & ";" & strFilter & ";" _

& strAttributes & ";subtree"

objCommand.CommandText = strQuery

Set objRecordSet = objCommand.Execute

' Enumerate groups and add NT name to dictionary object.

Do Until objRecordSet.EOF

strGroupName = objRecordSet.Fields("sAMAccountName")

'Wscript.Echo "strGroupName - " & strGroupName

allGroups=allGroups & "," & strGroupName

objGroupList(objADObject.sAMAccountName & "\" _

& strGroupName) = True

objRecordSet.MoveNext

Loop

' Wscript.Echo allGroups

Set objRecordSet = Nothing

End Sub

Function OctetToHexStr(arrbytOctet)

' Function to convert OctetString (byte array) to Hex string,

' with bytes delimited by \ for an ADO filter.

Dim k

OctetToHexStr = ""

For k = 1 To Lenb(arrbytOctet)

OctetToHexStr = OctetToHexStr & "\" _

& Right("0" & Hex(Ascb(Midb(arrbytOctet, k, 1))), 2)

Next

End Functio

Share this post


Link to post
Share on other sites



hey guy ^^

i'm just working on the same source and script LOL

i just need to managa to convert a byte array to string (like the last function in VBS)

and i'm done

I'm try usinf ADODB.Stream but without success

if you have any ideas, please PM me


-- Arck System _ Soon -- Ideas make everything

"La critique est facile, l'art est difficile"

Projects :

[list] [*]Au3Service : Run your exe as service V3 / Updated 29/07/2013 Get it Here [/list]

Share this post


Link to post
Share on other sites

did either of you guys get this script converted to Autoit ? it would be handy if i could have a look at your script - i need to check for the following situation

user (a) is member of group (a)

user (:whistle: is member of group (:P

user © is member of group ©

user (d) is member of group (d)

all of these groups are a member of of group (z)

i want to check if the user is a member of group (z) which would in turn check all sub groups to see if the user is a member of that group

cheers

Craig

Share this post


Link to post
Share on other sites

@All

This is as far as I get.

#include <array.au3>

; IsMember8.vbs
; _VBScript program demonstrating the use of Function IsMember.()
;
; ----------------------------------------------------------------------
; Copyright © 2004 Richard L. Mueller
; Hilltop Lab web site - http://www.rlmueller.net
; Version 1.0 - March 28, 2004
; An efficient IsMember function to test group membership for any number()
; of users or computers, using the "tokenGroups" attribute. The function
; reveals membership in nested groups and the primary group. It requires
; that the user or computer object be bound with the LDAP provider.
; Based on an idea by Joe Kaplan.
;
; You have a royalty-free right to use, modify, reproduce, and
; distribute this script file in any way you find useful, provided that
; you agree that the copyright owner above has no warranty, obligations,
; or liability for such use.

AutoItSetOption("MustDeclareVars", 1)

Dim $objADUser, $objGroupList, $allGroups, $oADsSysInfo, $objMyWin
Dim $objCommand, $objConnection, $strBase, $strAttributes

 $oADsSysInfo = ObjCreate("ADSystemInfo")
ConsoleWrite( "Distinguished name of the current user: " & $oADsSysInfo.UserName & @CR)

; Bind to the user or computer object in Active Directory with the LDAP
; provider.
 $objADUser = ObjGet("LDAP://" & $oADsSysInfo.UserName)
 
; Test for group membership.
$allGroups=""
IsMember($objADUser)
; Consolewrite( $allGroups)
MsgBox(0,"", $allGroups & "AllADGroups")

$objMyWin = Objcreate("Wscript.Shell")
$objMyWin.Popup ($allGroups)

; Clean up.
If IsObj($objConnection) Then
$objConnection.Close()
 $objCommand = ""
 $objConnection = ""
 $objGroupList = ""
EndIf

 $objADUser = ""

Func IsMember($objADObject)
; Function to test for group membership.
; $objADObject is a user or computer object.
; strGroupNTName is the NT name (sAMAccountName) of the group to test.
; $objGroupList is a dictionary object, with global scope.
; Returns True if the user or computer is a member of the group.
; Subroutine LoadGroups is called once for each different $objADObject.()

Dim $objRootDSE, $strDNSDomain, $vbTextCompare
; The first time IsMember is called, setup the dictionary object()
; and objects required for ADO.

If ($objGroupList) ="" Then
 $objGroupList = ObjCreate("Scripting.Dictionary")
 ;$objGroupList.CompareMode = $vbTextCompare
 $objCommand = ObjCreate("ADODB.Command")
 $objConnection = ObjCreate("ADODB.Connection")
 $objConnection.Provider = "ADsDSOObject"
 $objConnection.Open ("Active Directory Provider")
 $objCommand.ActiveConnection = $objConnection
 $objRootDSE = ObjGet("LDAP://RootDSE")
 $strDNSDomain = $objRootDSE.Get("defaultNamingContext")
 $objCommand.Properties("Page Size") = 100
 $objCommand.Properties("Timeout") = 30
 $objCommand.Properties("Cache Results") = 0
 
; Search entire domain.
$strBase = "<LDAP://" & $strDNSDomain & ">"

; Retrieve NT name of each group.
$strAttributes = "sAMAccountName"

; Load group memberships for this user or computer into dictionary
; object.
 LoadGroups($objADObject)
 $objRootDSE = ""
 EndIf
EndFunc

Func LoadGroups($objADObject)
; Subroutine to populate dictionary object with group memberships.
; $objGroupList is a dictionary object, with global scope. It keeps track
; of group memberships for each user or computer separately. ADO is used
; to retrieve the name of the group corresponding to each objectSid in
; the tokenGroup array. Based on an idea by Joe Kaplan.

Dim $arrbytGroups
Dim $k, $strFilter, $objRecordSet, $strGroupName, $strQuery
; Add user name to dictionary object, so LoadGroups need only be()
; called once for each user or computer.

$objGroupList($objADObject.sAMAccountName & "\") = 1
; Retrieve tokenGroups array, a calculated attribute.

$objADObject.GetInfoEx (_ArrayCreate("tokenGroups"), 0)
$arrbytGroups = _ArrayCreate($objADObject.Get("tokenGroups"))
; Create a filter to search for groups with objectSid equal to each
; value in tokenGroups array.

$strFilter = "(|"
;If TypeName($arrbytGroups) = "Byte()" Then => TYPENAME does not exist ??
    ; tokenGroups has one entry.
;$strFilter = $strFilter & "(objectSid=" & OctetToHexStr($arrbytGroups) & ")"
; ElseIf UBound($arrbytGroups) > -1 Then

If UBound($arrbytGroups) > -1 Then  
; TokenGroups is an array of two or more objectSid;s.
    For $k = 0 To UBound($arrbytGroups)
    $strFilter = $strFilter & "(objectSid=" & OctetToHexStr($arrbytGroups[$k]) & ")"
    Next
Else
; tokenGroups has no objectSid;s.
  Exit
EndIf

$strFilter = $strFilter & ")"

; Use ADO to search for groups whose objectSid matches any of the
; tokenGroups values for this user or computer.
$strQuery = $strBase & ";" & $strFilter & ";" & $strAttributes & ";subtree"
$objCommand.CommandText = $strQuery

$objRecordSet = $objCommand.Execute
; Enumerate groups and add NT name to dictionary object.

 Do 
    $strGroupName = $objRecordSet.Fields("sAMAccountName")
    Consolewrite( "strGroupName - " & $strGroupName & @CR)
    $allGroups=$allGroups & "," & $strGroupName
    $objGroupList($objADObject.sAMAccountName & "\" & $strGroupName) = 1
    $objRecordSet.MoveNext()
 Until $objRecordSet.EOF()
    ConsoleWrite($allGroups & @CR)
    $objRecordSet = ""
EndFunc

Func OctetToHexStr($arrbytOctet)
    Local $OctetToHexStr,$k
    local $Lenb[1]
    ; Function to convert OctetString (byte array) to Hex string,
    ; with bytes delimited by \ for an ADO filter.

$OctetToHexStr = ""

For $k = 1 To $Lenb[$arrbytOctet]
$OctetToHexStr = $OctetToHexStr & "\" & StringRight("0" & Hex(Asc(StringMid($arrbytOctet, $k, 1))), 2)
Next
EndFunc

There are some errors occurring in the OctetTOHexStr function, but Arcker got that to work as it seems.

There is also an error in the source script according to me, because the Var or Fucntion "TypeName"

is nowhere declared !! see line 112.

If you guys get it to work let me know.

regards

ptrex

Share this post


Link to post
Share on other sites

hi,

on the request feature topic, you can see that PaulIA need autoit supports safearray

i don't know if autoit can support it know

if it can, so the conversion can be really fast using an api

i'll ask PaulIA about this feature if it's implemented, and i'll see if i can make the last part to make this script working


-- Arck System _ Soon -- Ideas make everything

"La critique est facile, l'art est difficile"

Projects :

[list] [*]Au3Service : Run your exe as service V3 / Updated 29/07/2013 Get it Here [/list]

Share this post


Link to post
Share on other sites

Create an account or sign in to comment

You need to be a member in order to leave a comment

Create an account

Sign up for a new account in our community. It's easy!


Register a new account

Sign in

Already have an account? Sign in here.


Sign In Now
Sign in to follow this  
Followers 0