Smart questions
Smart answers
Smart people
Join Tek-Tips Forums
INTELLIGENT WORK FORUMS
FOR COMPUTER PROFESSIONALS

Member Login




Remember Me
Forgot Password?
Join Us!

Come Join Us!

Are you a
Computer / IT professional?
Join Tek-Tips now!
  • Talk With Other Members
  • Be Notified Of Responses
    To Your Posts
  • Keyword Search
  • One-Click Access To Your
    Favorite Forums
  • Automated Signatures
    On Your Posts
  • Best Of All, It's Free!

Join Tek-Tips
*Tek-Tips's functionality depends on members receiving e-mail. By joining you are opting in to receive e-mail.

Posting Guidelines

Promoting, selling, recruiting, coursework and thesis posting is forbidden.
Jobs from Indeed

Link To This Forum!

Partner Button
Add Stickiness To Your Site By Linking To This Professionally Managed Technical Forum.
Just copy and paste the
code below into your site.

VBScript FAQ

File and folder security

How to set File and folder security using VBScript
Posted: 3 Mar 05

Once I started on a script to automatically set security on files and foders. I learned a lot from the code below.
Hope to help someone else with it.

Full credit goes to the author Marcin Policht

Explanation beneath code...

CODE

Option Explicit

'**************************************************
'*** Constant Declarations

'**************************************************
'*** Access Control Entry Inheritance Flags
'*** Possible values for the IADsAccessControlEntry::AceFlags property.  

const ADS_ACEFLAG_UNKNOWN                      = &h1

'*** child objects will inherit ACE of current object
const ADS_ACEFLAG_INHERIT_ACE             = &h2    
'*** prevents ACE inherited by the object from further propagation
const ADS_ACEFLAG_NO_PROPAGATE_INHERIT_ACE     = &h4
'*** indicates ACE used only for inheritance (it does not affect permissions on object itself)
const ADS_ACEFLAG_INHERIT_ONLY_ACE         = &h8
'*** indicates that ACE was inherited    
const ADS_ACEFLAG_INHERITED_ACE         = &h10
'*** indicates that inherit flags are valid (provides confirmation of valid settings)
const ADS_ACEFLAG_VALID_INHERIT_FLAGS         = &h1f
'*** for auditing success in system audit ACE
const ADS_ACEFLAG_SUCCESSFUL_ACCESS         = &h40
'*** for auditing failure in system audit ACE
const ADS_ACEFLAG_FAILED_ACCESS         = &h80

'**************************************************
'*** Access Control Entry Type Values
'*** Possible values for the IADsAccessContronEntry::AceType property.  

const ADS_ACETYPE_ACCESS_ALLOWED               = 0
const ADS_ACETYPE_ACCESS_DENIED                = &h1
const ADS_ACETYPE_SYSTEM_AUDIT                 = &h2
const ADS_ACETYPE_ACCESS_ALLOWED_OBJECT        = &h5
const ADS_ACETYPE_ACCESS_DENIED_OBJECT        = &h6
const ADS_ACETYPE_SYSTEM_AUDIT_OBJECT         = &h7

'**************************************************
'*** Access Control Entry Permission Type Values
'*** Possible values for the IADsAccessControlEntry::AccessMask property.  

'*** permission to read data from file or list contents of directory
'*** corresponds to List Folder / Read Data permissions in Windows UI
const FILE_READ_DATA                 = &h1        'bit number 0
const FILE_LIST_DIRECTORY             = &h1        'bit number 0

'*** permission to write data to file or create file in directory
'*** corresponds to Create Files / Write Data permissions in Windows UI
const FILE_WRITE_DATA                 = &h2        'bit number 1
const FILE_ADD_FILE                 = &h2        'bit number 1

'*** permission to append data to file or to create subdirectory
'*** corresponds to Create Folders / Append Data permissions in Windows UI
const FILE_APPEND_DATA                = &h4        'bit number 2
const FILE_ADD_SUBDIRECTORY             = &h4        'bit number 2

'*** permission to read extended attributes
'*** corresponds to Read Extended Attributes permissions in Windows UI
const FILE_READ_EA                 = &h8        'bit number 3

'*** permission to write extended attributes
'*** corresponds to Write Extended Attributes permissions in Windows UI
const FILE_WRITE_EA                = &h10        'bit number 4

'*** permission to execute file or traverse directory
'*** corresponds to Traverse Folder / Execute File permissions in Windows UI
const FILE_EXECUTE                 = &h20        'bit number 5
const FILE_TRAVERSE                 = &h20        'bit number 5

'*** permission to delete directory and all files it contains
'*** corresponds to Delete Subfolders and Files permissions in Windows UI
const FILE_DELETE_CHILD             = &h40        'bit number 6

'*** permission to read file or folder attributes
'*** corresponds to Read Attributes permissions in Windows UI
const FILE_READ_ATTRIBUTES             = &h80        'bit number 7

'*** permission to change file or folder attributes
'*** corresponds to Write Attributes permissions in Windows UI
const FILE_WRITE_ATTRIBUTES            = &h100        'bit number 8

'*** permission to delete file or folder
'*** corresponds to Delete permissions in Windows UI
const DELETE                     = &h10000    'bit number 16

'*** permission to read security descriptor
'*** corresponds to Read Permissions permissions in Windows UI
const READ_CONTROL                = &h20000    'bit number 17

'*** permission to change discretionary ACL
'*** corresponds to Change Permissions permissions in Windows UI
const WRITE_DAC                 = &h40000    'bit number 18

'*** permission to assign owner
'*** corresponds to Take Ownership permissions in Windows UI
const WRITE_OWNER                = &h80000    'bit number 19

'*** permission to synchronize
'*** bit indicating permission to perform synchronize operation, used sometimes during file access
'*** this permission is automaticaly granted with read and write access and revoked when read or
'*** write access is denied. It is not displayed in the list of permissions in Windows UI
const SYNCHRONIZE                 = &h100000    'bit number 20

const ADS_RIGHT_GENERIC_ALL                    = &h10000000    'bit number 28
const ADS_RIGHT_GENERIC_EXECUTE                = &h20000000    'bit number 29
const ADS_RIGHT_GENERIC_WRITE                  = &h40000000    'bit number 30
const ADS_RIGHT_GENERIC_READ                   = &h80000000    'bit number 31

'**************************************************
'*** Variable Declarations

Dim adsFILE_FULL    'value representing sum of access mask corresponding to full file access
Dim adsFOLDER_FULL    'value representing sum of access mask corresponding to full folder access
Dim adsFILE_CHANGE    'value representing sum of access mask corresponding to change file access
Dim adsFOLDER_CHANGE    'value representing sum of access mask corresponding to change folder access
Dim adsFILE_READ    'value representing sum of access mask corresponding to read file access
Dim adsFOLDER_READ    'value representing sum of access mask corresponding to read folder access
Dim adsFILE_NOACCESS    'value representing sum of access mask corresponding to denied full file access
Dim adsFOLDER_NOACCESS    'value representing sum of access mask corresponding to denied full folder access

adsFILE_FULL        = FILE_READ_DATA Or FILE_WRITE_DATA Or FILE_APPEND_DATA Or _
            FILE_READ_EA Or FILE_WRITE_EA Or FILE_EXECUTE Or FILE_DELETE_CHILD Or _
            FILE_READ_ATTRIBUTES Or FILE_WRITE_ATTRIBUTES Or DELETE Or _
            READ_CONTROL Or WRITE_DAC Or WRITE_OWNER Or SYNCHRONIZE
adsFOLDER_FULL         = FILE_LIST_DIRECTORY Or FILE_ADD_FILE Or FILE_ADD_SUBDIRECTORY Or _
            FILE_READ_EA Or FILE_WRITE_EA Or FILE_TRAVERSE Or FILE_DELETE_CHILD Or _
            FILE_READ_ATTRIBUTES Or FILE_WRITE_ATTRIBUTES Or DELETE Or _
            READ_CONTROL Or WRITE_DAC Or WRITE_OWNER Or SYNCHRONIZE
adsFILE_CHANGE         = FILE_READ_DATA Or FILE_WRITE_DATA Or FILE_APPEND_DATA Or _
            FILE_READ_EA Or FILE_WRITE_EA Or FILE_EXECUTE Or _
            FILE_READ_ATTRIBUTES Or FILE_WRITE_ATTRIBUTES Or DELETE Or _
            READ_CONTROL Or SYNCHRONIZE
adsFOLDER_CHANGE    = FILE_LIST_DIRECTORY Or FILE_ADD_FILE Or FILE_ADD_SUBDIRECTORY Or _
            FILE_READ_EA Or FILE_WRITE_EA Or FILE_TRAVERSE Or _
            FILE_READ_ATTRIBUTES Or FILE_WRITE_ATTRIBUTES Or DELETE Or _
            READ_CONTROL Or SYNCHRONIZE
adsFILE_READ         = FILE_READ_DATA Or FILE_READ_EA Or FILE_EXECUTE Or _
            FILE_READ_ATTRIBUTES Or READ_CONTROL Or SYNCHRONIZE
adsFOLDER_READ        = FILE_LIST_DIRECTORY Or FILE_READ_EA Or FILE_TRAVERSE Or _
            FILE_READ_ATTRIBUTES Or READ_CONTROL Or SYNCHRONIZE
adsFILE_NOACCESS     = FILE_READ_DATA Or FILE_WRITE_DATA Or FILE_APPEND_DATA Or _
            FILE_READ_EA Or FILE_WRITE_EA Or FILE_EXECUTE Or FILE_DELETE_CHILD Or _
            FILE_READ_ATTRIBUTES Or FILE_WRITE_ATTRIBUTES Or DELETE Or _
            READ_CONTROL Or WRITE_DAC Or WRITE_OWNER
adsFOLDER_NOACCESS     = FILE_LIST_DIRECTORY Or FILE_ADD_FILE Or FILE_ADD_SUBDIRECTORY Or _
            FILE_READ_EA Or FILE_WRITE_EA Or FILE_TRAVERSE Or FILE_DELETE_CHILD Or _
            FILE_READ_ATTRIBUTES Or FILE_WRITE_ATTRIBUTES Or DELETE Or _
            READ_CONTROL Or WRITE_DAC Or WRITE_OWNER

Dim sAction        'type of action to perform (show or set)
Dim sPermission        'permission type (read, change, full, or no access)
Dim sAccount        'user or group account for which permissions are shown/set
Dim sTarget        'target file or folder path
Dim iTarget        'integer indicating type of target 0 - file, 1 - folder
Dim iOffset        'value used for display only (left justifying displayed values)

Dim oADSSecurity    'object representing ADsSecurity class
Dim oFSO        'object representing Scripting.FileSystemObject ProgID

'**************************************************
'*** Retrieve script arguments

Call GetArguments(Wscript.Arguments, sAction, sTarget, sAccount, sPermission)

'**************************************************
'*** Set variables

iOffset         = 20
Set oFSO         = CreateObject("Scripting.FileSystemObject")
Set oADSSecurity     = CreateObject("ADsSecurity")

If oFSO.FileExists(sTarget) Then
    iTarget = 0
ElseIf oFSO.FolderExists(sTarget) Then
    iTarget = 1
Else
    Call MsgBox("Target File or Folder does not exist", vbOKOnly, "Incorrect argument")
    WScript.Quit
End If

Select Case UCase(sAction)
    Case "SHOW"    
            Call DisplayACLs(sTarget, sAccount)
    Case "SET"    
            Call RecurseACLs(sTarget, sAccount, sPermission)
    Case Else
            Call DisplayUsage("ERROR: Incorrect ACTION type")            
End Select

Wscript.Quit

'**************************************************
'*** Subroutine reading command line arguments
'
Sub GetArguments(oArgs, sAction, sTarget, sAccount, sPermission)

Dim iCount

For iCount=0 To oArgs.Count - 1
    Select Case UCase(Split(WScript.Arguments(iCount), "=")(0))
        Case "ACTION"     sAction     = Split(WScript.Arguments(iCount), "=")(1)    
        Case "TARGET"    sTarget     = Split(WScript.Arguments(iCount), "=")(1)
        Case "ACCOUNT"     sAccount    = Split(WScript.Arguments(iCount), "=")(1)
        Case "PERM"     sPermission     = Split(WScript.Arguments(iCount), "=")(1)
    End Select
Next

If sAction = "" or sTarget = "" or (sAction = "SET" and (sTarget = "" or sAccount = "" or sPermission = "")) Then
    Call DisplayUsage("ERROR: Missing argument(s)")
    WScript.Quit
End If

end sub    


'**************************************************
'*** Subroutine displaying usage of the script from the command line
'
sub DisplayUsage(sHeader)

Dim sMsg

    sMsg = "To display permissions on file/folder (ACCOUNT parameter is optional) run:"
    sMsg = sMsg & VbCrLf & _
        "cscript //nologo ACLs.vbs ACTION=SHOW TARGET=[File|Folder] [ACCOUNT=Domain\Account]"
    sMsg = sMsg & VbCrLf & vbCrLf & "To set permissions on file/folder (ACCOUNT parameter is mandatory) run:"
    sMsg = sMsg & VbCrLf & _
        "cscript //nologo ACLs.vbs ACTION=SET TARGET=[File|Folder] ACCOUNT=Domain\Account PERM=[Read|Change|Full|NoAccess]"
    sMsg = sMsg & VbCrLf & vbCrLf & "Where:"
    sMsg = sMsg & VbCrLf & String(7," ") & "ACTION is set to SHOW to display permissions"
    sMsg = sMsg & VbCrLf & String(7," ") & "TARGET is full path to the file or folder"
    sMsg = sMsg & VbCrLf & String(7," ") & "ACCOUNT is user or group account in the DOMAIN\AccountName format"
    sMsg = sMsg & VbCrLf & String(7," ") & "PERM specifies type of permissions to be set"

    Call MsgBox(sMsg, vbOKOnly, sHeader)

end sub

'**************************************************
'*** Subroutine displaying list of Trustees, AcL Types, and ACL Masks
'
Sub DisplayACLs(sTarget, sAccount)

Dim oACE        'object representing an Access Control Entry
Dim sMsg, sAccessMask    'strings containing message to be displayed
Dim hAccessMask        'number representing Access Mask value
Dim oTargetSD        'object representing security descriptor of target file or folder
Dim oDACL        'object representing Discretionary Access Control List

set oTargetSD = oADsSecurity.GetSecurityDescriptor("FILE://" & Cstr(sTarget))
set oDACL = oTargetSD.DiscretionaryACL

For Each oACE in oDACL
    If sAccount = "" or UCase(sAccount) = UCase(oACE.Trustee) Then
        sMsg = vbCrLf & "Trustee:" & String(iOffset - Len("Trustee:"), Chr(32)) & oACE.Trustee & vbCrLf
        sMsg = sMsg & "ACE Type:" & String(iOffset - Len("ACE Type:"), Chr(32))
        Select Case oACE.AceType    
            Case ADS_ACETYPE_ACCESS_ALLOWED       
                'Implicit Allow ACE
                sMsg = sMsg & "ACCESS_ALLOWED"
            Case ADS_ACETYPE_ACCESS_DENIED       
                'Implicit Deny ACE
                sMsg = sMsg & "ACCESS_DENIED"
            Case ADS_ACETYPE_ACCESS_ALLOWED_OBJECT       
                'Object Allowed ACE
                sMsg = sMsg & "ACCESS_ALLOWED_OBJECT"    
            Case ADS_ACETYPE_ACCESS_DENIED_OBJECT        
                'Object Deny ACE
                sMsg = sMsg & "ACCESS_DENIED_OBJECT"
        End Select
        Wscript.Echo sMsg

        sAccessMask = ""
        hAccessMask = 0
        If iTarget = 0 Then
            If (oACE.AccessMask AND FILE_READ_DATA) Then
                sAccessMask = String(iOffset, Chr(32)) & "FILE_READ_DATA" & vbCrLf
                hAccessMask = hAccessMask + FILE_READ_DATA
            End If
            If (oACE.AccessMask AND FILE_WRITE_DATA) Then
                sAccessMask = sAccessMask & String(iOffset, Chr(32)) & "FILE_WRITE_DATA" & vbCrLf
                hAccessMask = hAccessMask + FILE_WRITE_DATA
            End If
            If (oACE.AccessMask AND FILE_APPEND_DATA) Then
                sAccessMask = sAccessMask & String(iOffset, Chr(32)) & "FILE_APPEND_DATA" & vbCrLf
                hAccessMask = hAccessMask + FILE_APPEND_DATA
            End If
            If (oACE.AccessMask AND FILE_READ_EA) Then
                sAccessMask = sAccessMask & String(iOffset, Chr(32)) & "FILE_READ_EA" & vbCrLf
                hAccessMask = hAccessMask + FILE_READ_EA
            End If
            If (oACE.AccessMask AND FILE_WRITE_EA) Then
                sAccessMask = sAccessMask & String(iOffset, Chr(32)) & "FILE_WRITE_EA" & vbCrLf
                hAccessMask = hAccessMask + FILE_WRITE_EA
            End If
            If (oACE.AccessMask AND FILE_EXECUTE) Then
                sAccessMask = sAccessMask & String(iOffset, Chr(32)) & "FILE_EXECUTE" & vbCrLf
                hAccessMask = hAccessMask + FILE_EXECUTE
            End If
            If (oACE.AccessMask AND FILE_DELETE_CHILD) Then
                sAccessMask = sAccessMask & String(iOffset, Chr(32)) & "FILE_DELETE_CHILD" & vbCrLf
                hAccessMask = hAccessMask + FILE_DELETE_CHILD
            End If
            If (oACE.AccessMask AND FILE_READ_ATTRIBUTES) Then
                sAccessMask = sAccessMask & String(iOffset, Chr(32)) & "FILE_READ_ATTRIBUTES" & vbCrLf
                hAccessMask = hAccessMask + FILE_READ_ATTRIBUTES
            End If
            If (oACE.AccessMask AND FILE_WRITE_ATTRIBUTES) Then
                sAccessMask = sAccessMask & String(iOffset, Chr(32)) & "FILE_WRITE_ATTRIBUTES" & vbCrLf
                hAccessMask = hAccessMask + FILE_WRITE_ATTRIBUTES
            End If
            If (oACE.AccessMask AND DELETE) Then
                sAccessMask = sAccessMask & String(iOffset, Chr(32)) & "DELETE" & vbCrLf
                hAccessMask = hAccessMask + DELETE
            End If
            If (oACE.AccessMask AND READ_CONTROL) Then
                sAccessMask = sAccessMask & String(iOffset, Chr(32)) & "READ_CONTROL" & vbCrLf
                hAccessMask = hAccessMask + READ_CONTROL
            End If
            If (oACE.AccessMask AND WRITE_DAC) Then
                sAccessMask = sAccessMask & String(iOffset, Chr(32)) & "WRITE_DAC" & vbCrLf
                hAccessMask = hAccessMask + WRITE_DAC
            End If
            If (oACE.AccessMask AND WRITE_OWNER) Then
                sAccessMask = sAccessMask & String(iOffset, Chr(32)) & "WRITE_OWNER" & vbCrLf
                hAccessMask = hAccessMask + WRITE_OWNER
            End If
            If (oACE.AccessMask AND SYNCHRONIZE) Then
                sAccessMask = sAccessMask & String(iOffset, Chr(32)) & "SYNCHRONIZE" & vbCrLf
                hAccessMask = hAccessMask + SYNCHRONIZE
            End If
        End If

        If iTarget = 1 Then
            If (oACE.AccessMask AND FILE_LIST_DIRECTORY) Then
                sAccessMask = String(iOffset, Chr(32)) & "FILE_LIST_DIRECTORY" & vbCrLf
                hAccessMask = hAccessMask + FILE_LIST_DIRECTORY
            End If
            If (oACE.AccessMask AND FILE_ADD_FILE) Then
                sAccessMask = sAccessMask & String(iOffset, Chr(32)) & "FILE_ADD_FILE" & vbCrLf
                hAccessMask = hAccessMask + FILE_ADD_FILE
            End If
            If (oACE.AccessMask AND FILE_ADD_SUBDIRECTORY) Then
                sAccessMask = sAccessMask & String(iOffset, Chr(32)) & "FILE_ADD_SUBDIRECTORY" & vbCrLf
                hAccessMask = hAccessMask + FILE_ADD_SUBDIRECTORY
            End If
            If (oACE.AccessMask AND FILE_READ_EA) Then
                sAccessMask = sAccessMask & String(iOffset, Chr(32)) & "FILE_READ_EA" & vbCrLf
                hAccessMask = hAccessMask + FILE_READ_EA
            End If
            If (oACE.AccessMask AND FILE_WRITE_EA) Then
                sAccessMask = sAccessMask & String(iOffset, Chr(32)) & "FILE_WRITE_EA" & vbCrLf
                hAccessMask = hAccessMask + FILE_WRITE_EA
            End If
            If (oACE.AccessMask AND FILE_TRAVERSE) Then
                sAccessMask = sAccessMask & String(iOffset, Chr(32)) & "FILE_TRAVERSE" & vbCrLf
                hAccessMask = hAccessMask + FILE_TRAVERSE
            End If
            If (oACE.AccessMask AND FILE_DELETE_CHILD) Then
                sAccessMask = sAccessMask & String(iOffset, Chr(32)) & "FILE_DELETE_CHILD" & vbCrLf
                hAccessMask = hAccessMask + FILE_DELETE_CHILD
            End If
            If (oACE.AccessMask AND FILE_READ_ATTRIBUTES) Then
                sAccessMask = sAccessMask & String(iOffset, Chr(32)) & "FILE_READ_ATTRIBUTES" & vbCrLf
                hAccessMask = hAccessMask + FILE_READ_ATTRIBUTES
            End If
            If (oACE.AccessMask AND FILE_WRITE_ATTRIBUTES) Then
                sAccessMask = sAccessMask & String(iOffset, Chr(32)) & "FILE_WRITE_ATTRIBUTES" & vbCrLf
                hAccessMask = hAccessMask + FILE_WRITE_ATTRIBUTES
            End If
            If (oACE.AccessMask AND DELETE) Then
                sAccessMask = sAccessMask & String(iOffset, Chr(32)) & "DELETE" & vbCrLf
                hAccessMask = hAccessMask + DELETE
            End If
            If (oACE.AccessMask AND READ_CONTROL) Then
                sAccessMask = sAccessMask & String(iOffset, Chr(32)) & "READ_CONTROL" & vbCrLf
                hAccessMask = hAccessMask + READ_CONTROL
            End If
            If (oACE.AccessMask AND WRITE_DAC) Then
                sAccessMask = sAccessMask & String(iOffset, Chr(32)) & "WRITE_DAC" & vbCrLf
                hAccessMask = hAccessMask + WRITE_DAC
            End If
            If (oACE.AccessMask AND WRITE_OWNER) Then
                sAccessMask = sAccessMask & String(iOffset, Chr(32)) & "WRITE_OWNER" & vbCrLf
                hAccessMask = hAccessMask + WRITE_OWNER
            End If
            If (oACE.AccessMask AND SYNCHRONIZE) Then
                sAccessMask = sAccessMask & String(iOffset, Chr(32)) & "SYNCHRONIZE" & vbCrLf
                hAccessMask = hAccessMask + SYNCHRONIZE
            End If
        End If
        sMsg = "ACE Permissions:" & String(iOffset - Len("ACE Permissions:"), Chr(32))
        Select Case hAccessMask
            Case adsFILE_FULL     Wscript.Echo sMsg & "FULL CONTROL"
            Case adsFOLDER_FULL     Wscript.Echo sMsg & "FULL CONTROL"
            Case adsFILE_CHANGE     Wscript.Echo sMsg & "CHANGE"
            Case adsFOLDER_CHANGE     Wscript.Echo sMsg & "CHANGE"
            Case adsFILE_READ     Wscript.Echo sMsg & "READ"
            Case adsFOLDER_READ     Wscript.Echo sMsg & "READ"
            Case adsFILE_NOACCESS     Wscript.Echo sMsg & "NO ACCESS"
            Case adsFOLDER_NOACCESS Wscript.Echo sMsg & "NO ACCESS"
            Case Else        WScript.Echo sMsg & "" & oACE.AccessMask
                        WScript.Echo sAccessMask
        End Select

        sMsg = "ACE Flags:" & String(iOffset - Len("ACE Flags:"), Chr(32))
        If (oACE.AceFlags AND ADS_ACEFLAG_INHERIT_ACE) Then
            WScript.Echo sMsg & "ADS_ACEFLAG_INHERIT_ACE"
        End If
        If (oACE.AceFlags AND ADS_ACEFLAG_NO_PROPAGATE_INHERIT_ACE) Then
            WScript.Echo sMsg & "ADS_ACEFLAG_NO_PROPAGATE_INHERIT_ACE"
        End If
        If (oACE.AceFlags AND ADS_ACEFLAG_INHERIT_ONLY_ACE) Then
            WScript.Echo sMsg & "ADS_ACEFLAG_INHERIT_ONLY_ACE"
        End If
        If (oACE.AceFlags AND ADS_ACEFLAG_INHERITED_ACE) Then
            WScript.Echo sMsg & "ADS_ACEFLAG_INHERITED_ACE"
        End If
        If (oACE.AceFlags AND ADS_ACEFLAG_VALID_INHERIT_FLAGS) Then
            WScript.Echo sMsg & "ADS_ACEFLAG_VALID_INHERIT_FLAGS"
        End If
        If (oACE.AceFlags AND ADS_ACEFLAG_SUCCESSFUL_ACCESS) Then
            WScript.Echo sMsg & "ADS_ACEFLAG_SUCCESSFUL_ACCESS"
        End If
        If (oACE.AceFlags AND ADS_ACEFLAG_FAILED_ACCESS) Then
            WScript.Echo sMsg & "ADS_ACEFLAG_FAILED_ACCESS"
        End If
        If (oACE.AceFlags AND ADS_ACEFLAG_UNKNOWN) Then
            WScript.Echo sMsg & "ADS_ACEFLAG_UNKNOWN"
        End If
    End If
Next

WScript.Echo "Total ACE entries:" &_
        String(iOffset - Len("Total ACE entries:"), Chr(32)) & oDACL.AceCount
WScript.Echo "ACL revision:" &_
        String(iOffset - Len("ACL revision:"), Chr(32)) & oDACL.ACLRevision

End Sub

'**************************************************
'*** Subroutine recursing through content of folder (when setting permissions)
'*** necessary to propagate permissions set on parent folder (per Q266461)
'
Public Sub RecurseACLs(sTarget, sAccount, sPermission)

Dim oTarget        'object representing target folder or file
Dim oSubfolders        'collection representing subfolders of target folder
Dim oFiles        'collection representing files in target folder
Dim oSubfolder        'object representing a subfolder (used for enumeration)
Dim oFile        'object representing a file (used for enumeration)

If oFSO.FileExists(sTarget) Then
    Call SetACLs(sTarget, sAccount, sPermission)
Else
    Set oTarget = oFSO.GetFolder(sTarget)
    WScript.Echo "Processing folder " & sTarget
    Call SetACLs(oTarget.Path, sAccount, sPermission)

    Set oFiles = oTarget.Files

    '*** Apply permissions to files
    For Each oFile in oFiles
        WScript.Echo "Processing file " & oFile.Path
        Call SetACLs(oFile.Path, sAccount, sPermission)
    Next  

    Set oSubFolders = oTarget.SubFolders

    '*** Apply permissions to subfolders
    For Each oSubFolder in oSubFolders
        Call RecurseACLs(oSubFolder.Path, sAccount, sPermission)
    Next

    Set oSubFolders = Nothing
    Set oFiles = Nothing

End If

End Sub

'**************************************************
'*** Subroutine applying permissions for specified account
'
Sub SetACLs(sTarget, sAccount, sPermission)

Dim hMask        'value representing Access Mask
Dim hType        'value representing Access Type
Dim oSID        'object representing SID of a Security Principal
Dim oACE        'object representing ACE of target object
Dim hSID        'hexadecimal representation of SID
Dim oTarget        'object representing target folder or file
Dim oTargetSD        'object representing security descriptor of target file or folder
Dim oDACL        'object representing Discretionary Access Control List

Select Case UCase(sPermission)
    Case "FULL"
        hType = ADS_ACETYPE_ACCESS_ALLOWED
        If iTarget = 0 Then
            hMask = adsFILE_FULL
        Else
            hMask = adsFOLDER_FULL
        End If
    Case "CHANGE"
        hType = ADS_ACETYPE_ACCESS_ALLOWED
        If iTarget = 0 Then
            hMask = adsFILE_CHANGE
        Else
            hMask = adsFOLDER_CHANGE
        End If
    Case "READ"
        hType = ADS_ACETYPE_ACCESS_ALLOWED
        If iTarget = 0 Then
            hMask = adsFILE_READ
        Else
            hMask = adsFOLDER_READ
        End If
    Case "NOACCESS"
        hType = ADS_ACETYPE_ACCESS_DENIED
        If iTarget = 0 Then
            hMask = adsFILE_NOACCESS
        Else
            hMask = adsFOLDER_NOACCESS
        End If
    Case Else
        Call DisplayUsage("ERROR: Incorrect permission type.")
        WScript.Quit
End Select

set oTargetSD = oADsSecurity.GetSecurityDescriptor("FILE://" & Cstr(sTarget))
set oDACL = oTargetSD.DiscretionaryACL

For Each oACE in oDACL
    If UCase(oACE.Trustee) = UCase(sAccount) Then
        oDACL.RemoveACE oACE
    End If
Next

Set oACE = CreateObject("AccessControlEntry")
oACE.Trustee = sAccount
oAce.AceType = hType
oAce.AccessMask = hMask
oACE.AceFlags = ADS_ACEFLAG_INHERIT_ACE Or ADS_ACEFLAG_UNKNOWN
oDACL.AddAce oACE

Call ReorderDACL(oDACL)

oTargetSD.DiscretionaryACL = oDACL
oADsSecurity.SetSecurityDescriptor oTargetSD

End Sub

'**************************************************
'*** Subroutine reordering the ACLs (per Q279682)
'*** ACEs need to be properly ordered, since AddAce method does not perform ordering.
'*** If an access-allowed ACE appears before access-denied, a trustee will be granted access.

'*** The preferred order of ACEs in a DACL is described in MSDN Library (at msdn.microsoft.com).
'*** For Windows 2000, ACEs should be arranged into two main groups - non-inherited and inherited.
'*** Non-inherited ACEs should be listed first, followed by the inherited ones. Within each group
'*** (non-inherited and inherited), ACEs are arranged in the following fashion:
'*** - access-denied ACEs that apply to the object itself
'*** - access-denied ACEs that apply to subobjects of the object (including its properties)
'*** - access-allowed ACEs that apply to the object itself
'*** - access-allowed ACEs that apply to subobjects of the object (including its properties)
'***
'*** Since the script does not affect inherited ACEs (it sets permission directly on target object)
'*** they do not have to be rearranged. We only need to rearrange non-inherited ACEs

Sub ReorderDACL(oDACL)

Dim oNewDACL            'object used to temporarily store DACL (during ordering)
Dim oInheritedDACL        'object representing list of all Inherited ACEs
Dim oDenyDACL            'object representing list of non-Inherited Deny ACEs
Dim oAllowDACL            'object representing list of non-Inherited Allow ACEs
Dim oACE            'object representing ACE (used for enumeration)

'**************************************************
'*** Create Access Control List objects

Set oNewDACL = CreateObject("AccessControlList")
Set oInheritedDACL = CreateObject("AccessControlList")
Set oAllowDACL = CreateObject("AccessControlList")
Set oDenyDACL = CreateObject("AccessControlList")

'**************************************************
'*** Add individual ACEs into each of the lists
'*** based on the ACE Flags and ACE Type values

For Each oACE In oDACL
    If ((oACE.AceFlags AND ADS_ACEFLAG_INHERITED_ACE) = ADS_ACEFLAG_INHERITED_ACE) Then    

    '**************************************************
    '*** as explained, no sorting is needed for Inherited ACEs, they are simply
    '*** added to the list and retrieved at the end of the sub in the same order
        oInheritedDACL.AddAce oACE

    Else

    '**************************************************
    '*** non-Inherited ACEs need to be placed in their respective list to be re-ordered

        Select Case oACE.AceType    
            Case ADS_ACETYPE_ACCESS_ALLOWED        
                oAllowDACL.AddAce oACE    
            Case ADS_ACETYPE_ACCESS_DENIED        
                oDenyDACL.AddAce oACE    
        End Select
    End If
Next

'**************************************************
'*** Recreate the Access Control List following the appropriate order
'*** - non-Inherited Deny ACEs
'*** - non-Inherited Allow ACEs
'*** - Inherited ACEs

For Each oACE In oDenyDACL
     oNewDACL.AddAce oACE
Next
For Each oACE In oAllowDACL
      oNewDACL.AddAce oACE
Next
For Each oACE In oInheritedDACL
      oNewDACL.AddAce oACE
Next

Set oInheritedDACL = Nothing
Set oDenyDACL = Nothing
Set oAllowDACL = Nothing

'**************************************************
'*** Set appropriate DACL revision level

oNewDACL.AclRevision = oDACL.AclRevision

'**************************************************
'*** Reset the original DACL
Set oDACL = Nothing
Set oDACL = oNewDACL

end Sub


http://www.serverwatch.com/tutorials/article.php/1476751

Scripting NTFS Permissions with ADSI (Part 3)

by Marcin Policht

This is the third article in the series discussing a scripting approach to modifying Security Descriptors. In the first two articles, I introduced the concept of the Security Descriptor and described its components. Next, I described a way to extract information about it through ADSI-based scripting. In this article, you will find out how to make modifications to Security Descriptors that control permissions to files and folders on NTFS-based partitions. As before, keep in mind that in order for the script to work, you will need to obtain ADsSecurity.DLL file (which is included in the ADSI Software Development Kit, freely downloadable from the Microsoft Web Site), copy it to the computer where the script will be run, and register it using REGSVR32.EXE (refer to the first article of the series for details).
After you have registered ADsSecurity.DLL, copy the script to a text file and and save it as ACLs.vbs. This version combines the capability included in the script presented in the previous article, which allowed displaying permissions with the ability to set permissions.
After saving the script, you can execute it by typing appropriate command at the Command Prompt:

To display the Security Descriptor (Trustees, ACE Flags, and Access Control Entries) for a file or folder, you would use the following syntax:

cscript //nologo ACLs.wsf ACTION=SHOW TARGET=[File|Folder] [ACCOUNT=Domain\Account]

where
•    SHOW is used to indicate type of action (displaying Access Control Entries)
•    File|Folder is a full path to the file or folder
•    Domain\Account is an optional argument that allows you to limit the listing to a specific user or group account (in the format domain\account)
To set ACE of a file or folder for a particular user or group, you would type the following:

cscript //nologo ACLs.wsf ACTION=SET TARGET=[File|Folder] ACCOUNT=Domain\Account PERM=[Read|Change|Full|NoAccess]

where
•    SET is used to indicate the type of action (setting Access Control Entry)
•    File|Folder is a full path to the file or folder on which permissions will be set
•    Domain\Account is a mandatory argument and specifies the user or group account for which permissions to file/folder will be set
•    Read|Change|Full|NoAccess is the type of permissions set on the target file or folder (can be any one of these four)
You can find out the proper syntax simply by double-clicking on the file. The same message box is displayed if you happen to provide the wrong number of arguments. Here are some examples of a proper use of the script:

To display the full content of security descriptor for a file c:\boot.ini, you would run:
cscript //nologo ACLs.wsf ACTION=SHOW TARGET=c:\boot.ini

If you wanted to limit the display of ACEs to a single trustee only (e.g. MPolicht account from the SWYNK domain), you would execute:
cscript //nologo ACLs.wsf ACTION=SHOW TARGET=c:\boot.ini ACCOUNT=SWYNK\MPolicht

And the following command would grant FULL CONTROL permissions on c:\boot.ini to a trustee (SWYNK\MPolicht in this case):
cscript //nologo ACLs.wsf ACTION=SET TARGET=c:\boot.ini ACCOUNT=SWYNK\MPolicht PERM=FULL
The target parameter for both SHOW and SET actions can be either a file or folder. When used with a file, SHOW (and SET) will display (and modify) permissions on the target file. When applied to folders, SHOW will display permissions on the folder only; SET however, will modify permissions on the folder and all of its content (including subfolders and their content, recursively). Note that the permissions will be replaced by the one you provide on the command line (i.e. Read, Change, Full, or No Access) but only for the account you specify with the ACCOUNT parameter. Permissions for any other user or group accounts will remain unaffected.
It is also important to realize that, when performing SET action on a folder, permissions are assigned explicitly (not through inheritance). In other words, the script will traverse each file and subfolder within the target folder and assign permissions directly to each. This is different from the default Windows 2000 behavior, which assigns explicit permissions only to the parent folder (while effective permissions on its content are determined based on inheritance settings).
Any new files or subfolders created in the target folder, do, however, properly inherit permissions from their parent.
The script consists of the following subroutines:
•    GetArguments - Reading command line arguments
•    DisplayUsage - Displaying MessageBox listing proper syntax for script execution
•    DisplayACLs - Displaying a list of Access Control Entries for the target file or folder (explained in the previous article)
•    RecurseACLs - Recursing through the folder hierarchy in order to allow changing permissions for all child files and folders
•    SetACLs - Setting appropriate access control entry on a file or folder for the account specified as the input argument (this is the critical part of the script, which actually modifies the ACE)
•    ReorderDACL - Rearranging the sequence of Access Control Entries in the Access Control List. This step is necessary, since access control entries are supposed to follow a certain order -- those denying access should always precede those that allow it. Unfortunately, the process used to set ACEs (in SetACLs sub) does not maintain this ordering, hence the additional cleanup.

Back to VBScript FAQ Index
Back to VBScript Forum

My Archive

Close Box

Join Tek-Tips® Today!

Join your peers on the Internet's largest technical computer professional community.
It's easy to join and it's free.

Here's Why Members Love Tek-Tips Forums:

Register now while it's still free!

Already a member? Close this window and log in.

Join Us             Close