>-----Original Message-----
>I need help in creating a script that can list all the
>user and group memberships of a given folder. This wll
>also apply to subfolders beneath the root folder. Info
>needs to be extracted to a file.
>
>Thanks,
>Randolph
>.
>
Heh, you don't want much... You can buy Security Explorer
from Small Wonders Software. It can do this exactly (list
all user and group memberships, permissions on a folder
and all sub-folders, saved to a Excel spreadsheet or an
Access database.
I can give you my EnumFolderPerms.vbs script which
returns the permissions for a SINGLE folder (it does
enumerate all subgroups), and then write a Enumerate
SubFolders wrapper around it.
It's pretty big, and follows my own strange standard.
Copy and paste it in a text editor before you even try to
read it. Hope it helps.
'On Error Resume Next
'Set Log File Name
LogFileName = "c:\EnumFolderPerms.log"
'Set File Constants
Const ForReading = 1
Const ForWriting = 2
Const ForAppending = 8
'Setting the Arguments
Set objArgs = Wscript.Arguments
If ObjArgs.Count > 0 Then
Arg1 = objArgs(0)
Else
wscript.echo "Please specify all required arguments.
Run this script again "
wscript.echo "with a /? as the first argument to see
the help file"
Wscript.Quit
End If
'Checking if Help file is needed
HELP = 0
If Arg1 = "help" Then HELP = 1
If Arg1 = "/?" Then HELP = 1
If Arg1 = "?" Then HELP = 1
' Doubles as Help document and Purpose of script REMARKS
If HELP = 1 then
wscript.echo " ******************************"
wscript.echo " * Script: EnumFolderPerms.vbs"
wscript.echo " * Creation Date: 6-17-2003"
wscript.echo " * Author: Ron Rosenkoetter"
wscript.echo " * E-mail:
Ronald.Rosenkoetter.DeleteThis@gentiva.com"
wscript.echo " *"
wscript.echo " * Description: This script will list
the groups that have"
wscript.echo " * access to a folder and enumerate
those groups"
wscript.echo " * (and sub-groups) membership"
wscript.echo " *"
wscript.echo " * Limitations: This script will show
any groups that have"
wscript.echo " * access other than Read, Modify,
or Full Control as Special"
wscript.echo " *"
wscript.echo " * Usage: EnumFolderPerms.vbs
[options]"
wscript.echo " *"
wscript.echo " * /f: Folder Name (UNC Path)"
wscript.echo " * [required]"
wscript.echo " *"
wscript.echo " * NOTE: This script uses an UNC Path
to connect to the folder"
wscript.echo " * in question. For a local machine,
just use the local admin"
wscript.echo " * shares (c$, e$, etc.)"
wscript.echo " *"
wscript.echo " * Example:
EnumFolderPerms.vbs /f:\\KSOVEPFNP001\Users\rarosenk"
wscript.echo " * This will list all the groups
that have permission to this"
wscript.echo " * folder, listing their permission
level, and enumerating all"
wscript.echo " * members of each group (and
subgroups)."
wscript.echo " *"
wscript.echo " ******************************"
Wscript.Quit
End If
'Make sure required options are specified
If NOT Wscript.Arguments.Named.Exists("f") Then
wscript.echo "Please specify all required arguments.
Run this script again "
wscript.echo "with a /? as the first argument to see
the help file"
Wscript.Quit
End If
'Set Option Variables
UNCPath = Wscript.Arguments.Named("f")
'Create the File System Object
Set objFSO = CreateObject("Scripting.FileSystemObject")
'Open a log file for printing results
Wscript.Echo "Opening Log File"
Set LogFile = objFSO.OpenTextFile
(LogFileName,ForWriting,True)
If Err.Number <> 0 then
Wscript.Echo "Unable to open the " & LogFileName
Wscript.Quit
End If
'Get Domain name
Set RootDSE = GetObject("LDAP://rootDSE")
Domain = RootDSE.Get("DefaultNamingContext")
'Searching Active Directory
'Create the Connection object and open it
Set objConnection = CreateObject("ADODB.Connection")
objConnection.Open "Provider=ADsDSOObject;"
'Create the Command object and set its ActiveConnection
to the Connection object
Set objCommand = CreateObject("ADODB.Command")
objCommand.ActiveConnection = objConnection
'A WMI call needs a server name and an explicit path to
the folder.
'Use the functions GetServerFromUNC and
GetExplicitPathFromUNC to
'extract this information.
ServerName = GetServerFromUNC(UNCPath)
ExplicitPath = GetExplicitPathFromUNC(UNCPath)
'Create an Security object
Set objSecurity = GetObject("winmgmts:\\" & ServerName
& "\root\cimv2:Win32_LogicalFileSecuritySetting='" &
ExplicitPath & "'")
'Get a Security Descriptor object
objSecurity.GetSecurityDescriptor objSD
'Create an Owner object
Set objOwner = objSD.Owner
Message objSecurity.Path & " on " & ServerName & " is
owned by " & objOwner.Name & vbCrLF
'Loop through each ACE object inside the DACL
For Each objACE in objSD.DACL
Permissions = "--Special--"
If objAce.AccessMask = 2032127 Then Permissions
= "Full"
If objAce.AccessMask = 1245631 Then Permissions
= "Change"
If objAce.AccessMask = 1179817 Then Permissions
= "Read"
'Checking for List permissions here (List is Read
permission on This Folder Only (AceFlags = 0)
'or This Folder and Subfolders Only (AceFlags = 2)
If (objAce.AccessMask = 1179817) AND
((objAce.AceFlags = 0) OR (objAce.AceFlags = 2)) _
Then Permissions = "List"
'Make the output pretty by standardizing the length by
adding spaces. The first
'IsNull is to make sure an Trustee.Name exists for the
ACE. The second IsNull
'is to make sure there is a domain associated with the
Name (The Everyone group
'will come back with a Domain of null for example)
If NOT IsNull(objACE.Trustee.Name) Then
If IsNull(objAce.Trustee.Domain) Then
ACEName = objAce.Trustee.Name
Else
ACEName = objAce.Trustee.Domain & "\" &
objACE.Trustee.Name
End If
LengthACEName = Len(ACEName)
ACENameWithSpaces = ACEName & Space(50 -
LengthACEName)
Message vbCrLf & " " & ACENameWithSpaces
& " " & Permissions
'Don't bother enumerating the members of the
Administrators group or Information Security
If NOT objAce.Trustee.Domain & "\" &
objAce.Trustee.Name = "BUILTIN\Administrators" Then
If Instr
(objAce.Trustee.Name,"InformationSecurity") = 0 Then
'Run a LDAP query on AD, looking for Groups that match
the objAce.Trustee.Name.
'Set the CommandText property of the Command object.
objCommand.CommandText = _
"<LDAP://" & Domain & ">;(&
(objectCategory=Group)(name=" & objACE.Trustee.Name
& "));" & _
"name,ADsPath,member,memberof;subtree"
'To search for more than 1000 records, add the following
line. This will return ALL objects
'in the search.
objCommand.Properties("Page Size")=1000
'Sort the Record Set
objCommand.Properties("Sort On") = "Name"
'Execute the Command and place the results in the
RecordSet object
Set objRecordSet = objCommand.Execute
CheckForErrorQuit
'Loop through the results (Should be just one group)
Do Until objRecordSet.EOF
'Create a group object
Set objGroup = GetObject
(objRecordSet.Fields("ADsPath"))
'Get the members of the group using the EnumerateGroup
subroutine
EnumerateGroup objGroup," "
objRecordSet.MoveNext
Loop
End If
End If
Else
Message " No name for SID <----"
End If
Next
QuitProgram
'#####################
'Subroutine EnumerateGroup
'Variables
'objADGroup - Group Object
'strOffSet - Start with " ", and this script will
indent
' all subgroups and users with
additional " "
'Returns
'a list of all user names in the parent group and ALL
'subgroups
Sub EnumerateGroup(objADGroup, strOffset)
For Each objMember In objADGroup.Members
If UCase(Left(objMember.objectCategory,

)
= "CN=GROUP" Then
Message strOffset & objMember.sAMAccountName
& " (Sub-Group)"
Call EnumerateGroup(objMember, strOffset & " ")
Else
Message strOffset & objMember.DisplayName
End If
Next
End Sub
'#####################
'#############################
'Function GetServerFromUNC
'Takes a UNC Path and extracts the Server Name
'Variables
'UNC
'Returns
'Server Name
Function GetServerFromUNC (UNC)
'Split the FolderPath on the backslashes
Folders = split(UNC,"\")
'The first two elements of the Folders array are empty
(because of the leading two backslashes).
'The third element is the Server name.
GetServerFromUNC = Folders(2)
End Function
'#############################
'#############################
'Function GetExplicitPathFromUNC
' Takes a UNC Path and extracts the explicit Path on the
Server
' i.e. \\Server\Programs\Software could return
E:\Apps\Programs\Software
' (In this case, the Programs share on Server is found
on E:\Apps\Programs)
'Variables
'UNC
'Returns
'Explicit Path of the Share and subfolders specified in
the UNC
'See example above
Function GetExplicitPathFromUNC (UNC)
'Split the FolderPath on the backslashes
Folders = split(UNC,"\")
'Grab the share name, create a share object and get it's
explicit path
'The first two elements of the Folders array are empty
(because of the leading two backslashes).
'The third element is the Server name, and the fourth
element is the Share name.
ServerName = Folders(2)
FileShareName = Folders(3)
Set objFileShare = GetObject("WinNT://" & ServerName
& "/LanmanServer/" & FileShareName)
'Get the path of the FileShare
ExplicitPath = objFileShare.Path
'Add on the rest of the Explicit Path (the folders after
the share)
For i = 4 to UBound(Folders)
ExplicitPath = ExplicitPath & "\" & Folders(i)
Next
GetExplicitPathFromUNC = ExplicitPath
End Function
'#############################
'#############################
'Function CheckForErrorQuit
Function CheckForErrorQuit()
If Err.Number <> 0 then
Message "Error #" & Err.Number & " - " &
Err.Description
CheckForErrorQuit = Err.Description
QuitProgram
End If
End Function
'#############################
'Function CheckForErrorClear
Function CheckForErrorClear()
If Err.Number <> 0 then
Message "Error # " & Err.Number & " - " &
Err.Description
CheckForErrorClear = Err.Description
Err.Clear
End If
End Function
'#############################
'Subroutine Message
Sub Message (Text)
Wscript.Echo Text
LogFile.WriteLine Text
End Sub
'#############################
'Subrountine QuitProgram
Sub QuitProgram
LogFile.Close
Wscript.Echo " "
Wscript.Echo "********************************************
********"
Wscript.Echo "* Use notepad " & LogFileName & " to
see a log of these results"
Wscript.Echo "********************************************
********"
Wscript.Quit
End Sub
'############################