Tek-Tips is the largest IT community on the Internet today!

Members share and learn making Tek-Tips Forums the best source of peer-reviewed technical information on the Internet!

  • Congratulations strongm on being selected by the Tek-Tips community for having the most helpful posts in the forums last week. Way to Go!

How to set File and folder security using VBScript

File and folder security

How to set File and folder security using VBScript

by  SaMaLaKo  Posted    (Edited  )
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.
Register to rate this FAQ  : BAD 1 2 3 4 5 6 7 8 9 10 GOOD
Please Note: 1 is Bad, 10 is Good :-)

Part and Inventory Search

Back
Top