Flylib.com

Books Software

 
 
 

Setting Directory Security

17.3 Setting Directory Security

Problem

You want to set security permissions for a directory.

Solution

To set directory permissions, two ACLs must be added: one for directory security and one to determine the permissions for files within the directory.

The following sample grants the user account "Freds" add and read access to the directory d:\data :

Const OBJECT_INHERIT_ACE = 1 Const CONTAINER_INHERIT_ACE = 2 Const INHERIT_ONLY_ACE = 8 Const ACETYPE_ACCESS_ALLOWED = 0 'file access types Const FILE_GENERIC_READ = &H120089 Const FILE_GENERIC_WRITE = &H120116 Const FILE_GENERIC_EXECUTE = &H1200A0 Dim objDACL, objNewAce, objACE, objNewAce2 Dim objSecurity, objSD, strTrustee Set objSecurity = CreateObject("ADsSecurity") Set objSD = objSecurity.GetSecurityDescriptor("FILE://d:\data") Set objDACL = objSD.DiscretionaryAcl Set objNewAce = CreateObject("AccessControlEntry") strTrustee = "Acme\Freds" 'set file access to directory so any FredS can 'read existing file in the directory. Set objNewAce = CreateObject("AccessControlEntry") objNewAce.Trustee = strTrustee objNewAce.AccessMask = FILE_GENERIC_READ Or FILE_GENERIC_EXECUTE objNewAce.AceType = ACETYPE_ACCESS_ALLOWED 'permissions are to be inherited to any new files in the directory objNewAce.AceFlags = INHERIT_ONLY_ACE Or OBJECT_INHERIT_ACE objDACL.AddAce objNewAce 'set directory permissions so FredS can add files Set objNewAce2 = CreateObject("AccessControlEntry") objNewAce2.Trustee = strTrustee objNewAce2.AccessMask = FILE_GENERIC_READ Or _ FILE_GENERIC_EXECUTE Or FILE_GENERIC_WRITE objNewAce2.AceType = ACETYPE_ACCESS_ALLOWED objNewAce2.AceFlags = CONTAINER_INHERIT_ACE objDACL.AddAce objNewAce2 objSD.DiscretionaryAcl = objDACL objSecurity.SetSecurityDescriptor objSD

Discussion

A Windows NT/2000/XP directory contains two ACLs: One determines directory permissions and one determines permissions to the files within the directory.

The file permissions determine the access to files in the directory. Any file copied , moved, or created in the directory is automatically assigned the file access permissions.

Note 

The AccessMask property can be set to any combination of file access rights that are specified in Table 17-5.

The AceFlags property must be set so that file properties are inherited by all files that are created or copied to the directory. To do this, the AceFlags property of the ACE object must be set to INHERIT_ONLY_ACE (8) or OBJECT_INHERIT_ACE (1).

The directory rights are similar to file rights. They determine the access a user has to the directory container object. A directory requires a separate ACE object to be applied to the DACL.

Set the AccessMask to determine what access the trustee has. (The rights that can be combined in the AccessMask can be any of the rights listed in Table 17-5 except for file generic read, write, execute, or delete permissions.) These are replaced with values that are listed in Table 17-4.

Table 17-4: File Access Rights

DIRECTORY CONTAINER RIGHT

VALUE

GENERIC_ALL

&H10000000

GENERIC_EXECUTE

&H20000000

GENERIC_WRITE

&H40000000

GENERIC_READ

&H80000000

The AceFlags property must be set so that the properties are inherited by all directories exist in the directory. To do this, the AceFlags property of the ACE object must be set to CONTAINER_INHERIT_ACE .

Setting directory permissions using WMI requires the same steps to be taken. The following script performs the same operation as the Solution script using WMI:

<?xml version="1.0" ?> <job> <!--comment Script:dirsec.wsf Description: Sets security permissions on a directory --> <script language=" VBScript" src=" wmiinc.vbs"> <![CDATA[ Option Explicit Const OBJECT_INHERIT_ACE = 1 Const CONTAINER_INHERIT_ACE = 2 Const INHERIT_ONLY_ACE = 8 Const ACETYPE_ACCESS_ALLOWED = 0 'file access types Const FILE_GENERIC_READ = &H120089 Const FILE_GENERIC_WRITE = &H120116 Const FILE_GENERIC_EXECUTE = &H1200A0 Dim objDescriptor, objACE, retval, objServices Dim objFileSec, objTrustee, aDACL, objACE2 Set objServices = GetObject("

winmgmts

:{impersonationLevel=impersonate}") Set objFileSec = objServices.Get(_ "Win32_LogicalFileSecuritySetting.

Path

='d:\data'") Set objACE = objServices.Get("Win32_ACE") Set objACE2 = objServices.Get("Win32_ACE") Set objTrustee = objServices.Get("Win32_Trustee") Set objDescriptor = objServices.Get("Win32_SecurityDescriptor") retval = objFileSec.GetSecurityDescriptor(objDescriptor) aDACL = objDescriptor.dacl 'set trustee information objTrustee.

Name

= "Acme\Freds" objTrustee.sid = GetBinarySID("Freds") 'set the file permissions for the directory objACE.AccessMask = FILE_GENERIC_READ Or FILE_GENERIC_EXECUTE objACE.AceType = ACETYPE_ACCESS_ALLOWED objACE.AceFlags = INHERIT_ONLY_ACE Or OBJECT_INHERIT_ACE objACE.Trustee = objTrustee 'set directory permissions objACE2.AccessMask = FILE_GENERIC_READ Or _ FILE_GENERIC_EXECUTE Or FILE_GENERIC_WRITE objACE2.AceType = ACETYPE_ACCESS_ALLOWED objACE2.AceFlags = CONTAINER_INHERIT_ACE objACE2.Trustee = objTrustee 'resize DACL array and add new ACEs to DACL ReDim Preserve aDACL(UBound(aDACL) + 2) Set aDACL(UBound(aDACL) - 1) = objACE Set aDACL(UBound(aDACL)) = objACE2 objDescriptor.dacl = aDACL 'set the security descriptor retval = objFileSec.SetSecurityDescriptor(objDescriptor) ]]> </script> </job>

The rules and limitations for referencing directories and applying security to them using WMI are the same that apply to setting file security using WMI, as outlined in Solution 17.2.

To simplify permissions management, the following script component, ADSIFileSecurity.wsc , provides file security operations. The component performs permissions setting and enumeration on any specified file or directory:

<?xml version="1.0"?> <component> <registration description=" ADSIFileSecurity" progid=" ENTWSH.FileSecurity" version="1.00" classid="{f27d40d0-7a43-11d3-bc2c-00104b164591}" > </registration> <public> <method name=" SetSecurity"> </method> <method name=" ListSecurity"> <PARAMETER name=" strPath"/> </method> </public> <script language=" VBScript"> <![CDATA[ 'ADSIFileSecurity.wsc 'Description: Sets and lists file/folder security Option Explicit Const OBJECT_INHERIT_ACE = 1 Const CONTAINER_INHERIT_ACE = 2 Const NO_PROPAGATE_INHERIT_ACE = 4 Const INHERIT_ONLY_ACE = 8 Const VALID_INHERIT_FLAGS = 15 Const GENERIC_ALL = &H10000000 Const GENERIC_EXECUTE = &H20000000 Const GENERIC_WRITE = &H40000000 Const GENERIC_READ = &H80000000 Const ACETYPE_ACCESS_DENIED = 1 Const ACETYPE_ACCESS_ALLOWED = 0 'file access types Const FILE_GENERIC_READ = 1179785 Const FILE_GENERIC_WRITE = 1179926 Const FILE_GENERIC_EXECUTE = 1179808 Const FILE_GENERIC_DELETE = 65536 Const FILE_FULL_ACCESS = 2032127 Const FILE_PERMISSION_ACCESS = 262144 Const FILE_OWNERSHIP_ACCESS = 524288 Dim objSecurity, objSD, objDACL, objAce Dim ErrorString Function get_Error() get_Error = ErrorString End Function 'Description:Sets specified file or folder security Function SetSecurity(strPath, strRights, strTrustee) Dim objNewAce, objNewAce2 Dim strType, strRights2, nF Dim objfolder, objFSO Set objFSO = CreateObject("Scripting.FileSystemObject") 'determine if the path is a file or a folder If objFSO.FileExists(strPath) Then strType = "F" 'file ElseIf objFSO.FolderExists(strPath) Then strType = "D" 'folder/directory Else ' not found SetSecurity = False ErrorString = CreateErrMsg(Err, _ "File "& strPath & "does not exist") Exit Function End If Set objSecurity = CreateObject("ADsSecurity") Set objSD = objSecurity.GetSecurityDescriptor("FILE://" & strPath) Set objDACL = objSD.DiscretionaryAcl 'check if object is a file If strType = "F" Then Set objNewAce = CreateObject("AccessControlEntry") objNewAce.Trustee = strTrustee objNewAce.AccessMask = FileRightsID(strRights, "F") FileSetSecurityRemove strTrustee 'check if no access is specified If strRights = "N" Then objNewAce.AceType = ACETYPE_ACCESS_DENIED Else objNewAce.AceType = ACETYPE_ACCESS_ALLOWED End If 'add the new ACE to the DACL objDACL.AddAce objNewAce Else 'set security on a folder 'check if folder container and file access rights are specified nF = InStr(strRights, ":") If nF > 0 Then strRights2 = Mid(strRights, nF + 1) strRights = Left(strRights, nF - 1) Else strRights2 = strRights End If 'remove the trustee from the existing ACL FileSetSecurityRemove strTrustee 'set file access Set objNewAce = CreateObject("AccessControlEntry") objNewAce.Trustee = strTrustee 'set file trustee objNewAce.AccessMask = FileRightsID(strRights2, "F") objNewAce.AceType = ACETYPE_ACCESS_ALLOWED objNewAce.AceFlags = INHERIT_ONLY_ACE Or OBJECT_INHERIT_ACE objDACL.AddAce objNewAce 'set folder container access Set objNewAce2 = CreateObject("AccessControlEntry") objNewAce2.Trustee = strTrustee objNewAce2.AccessMask = FileRightsID(strRights, "D") objNewAce2.AceType = ACETYPE_ACCESS_ALLOWED objNewAce2.AceFlags = CONTAINER_INHERIT_ACE objDACL.AddAce objNewAce2 'add ACE to DACL End If objSD.DiscretionaryAcl = objDACL 'set the DACL objSecurity.SetSecurityDescriptor objSD SetSecurity = True End Function Function ListSecurity(strPath) Dim objSecurity Dim objSD, objDACL, objAce Dim strUser, strLastUser, strLine, strRights Set objSecurity = CreateObject("ADsSecurity") On Error Resume Next Set objSD = objSecurity.GetSecurityDescriptor("FILE://" & strPath) Set objDACL = objSD.DiscretionaryAcl strUser = "" For Each objAce In objDACL strUser = objAce.Trustee If strUser <> strLastUser And strLastUser <> "" Then strRights = strRights & vbCrLf & objAce.Trustee & "," & _ FileRights(objAce.AccessMask, objAce.AceType) ElseIf strLastUser = "" Then strRights = strRights & objAce.Trustee & "," & _ FileRights(objAce.AccessMask, objAce.AceType) Else strRights = strRights & ":" & _ FileRights(objAce.AccessMask, objAce.AceType) End If strLastUser = strUser Next ListSecurity = strRights End Function 'Description:removes trustee from DACL 'Parameters: 'strTrustee Name of trustee account to remove from DACL Sub FileSetSecurityRemove(strTrustee) Dim bChange bChange = False For Each objAce In objDACL If StrComp(strTrustee, objAce.Trustee, vbTextCompare) = 0 _ Or strTrustee = "" Then objDACL.RemoveAce objAce bChange = True End If Next If bChange Then objSD.DiscretionaryAcl = objDACL objSecurity.SetSecurityDescriptor objSD End If End Sub 'Description:returns a string of security settings for specified value 'Parameters: 'rights access rights 'nType Access type. 0 = access allowed, 1 - access

denied

'Returns: String containing security flags Function FileRights(rights, nType) Dim strRet strRet = "" Select Case rights Case FILE_FULL_ACCESS, GENERIC_ALL If nType = ACETYPE_ACCESS_DENIED Then strRet = "N" Else strRet = "F" End If Case FILE_GENERIC_READ Or FILE_GENERIC_EXECUTE Or _ FILE_GENERIC_DELETE Or FILE_GENERIC_READ _ Or FILE_GENERIC_WRITE, GENERIC_READ _ Or GENERIC_WRITE Or GENERIC_EXECUTE Or FILE_GENERIC_DELETE strRet = "C" Case Else If rights = (rights Or FILE_GENERIC_READ) Or _ rights = (rights Or GENERIC_READ) Then strRet = strRet & "R" If rights = (rights Or FILE_GENERIC_EXECUTE) Or _ rights = (rights Or GENERIC_EXECUTE) Then strRet= strRet & "X" If rights = (rights Or FILE_GENERIC_WRITE) Or _ rights = (rights Or GENERIC_WRITE) Then strRet = strRet & "W" If rights = (rights Or FILE_GENERIC_DELETE) Then _ strRet = strRet & "D" If rights = (rights Or 524288) Then strRet = strRet & "O" If rights = (rights Or 262144) Then strRet = strRet & "P" End Select FileRights = strRet End Function 'Description:returns the access value for specified string type 'Parameters: 'rights string of acces rights 'strType object . F = file, D - folder/directory 'Returns: value for specified access string Function FileRightsID(rights, strType) Dim lret, counter For counter = 1 To Len(rights) Select Case Mid(rights, counter, 1) Case "F", "N" If strType = "F" Then lret = lret Or FILE_FULL_ACCESS Else lret = lret Or GENERIC_ALL End If Case "W" If strType = "F" Then lret = lret Or FILE_GENERIC_WRITE Else lret = lret Or GENERIC_WRITE End If Case "X" If strType = "F" Then lret = lret Or FILE_GENERIC_EXECUTE Else lret = lret Or GENERIC_EXECUTE End If Case "D" lret = lret Or FILE_GENERIC_DELETE Case "C" If strType = "F" Then lret = lret Or FILE_GENERIC_READ Or FILE_GENERIC_EXECUTE _ Or FILE_GENERIC_DELETE Or FILE_GENERIC_WRITE Else lret = lret Or GENERIC_READ Or GENERIC_WRITE _ Or GENERIC_EXECUTE Or FILE_GENERIC_DELETE End If Case "P" lret = lret Or FILE_PERMISSION_ACCESS Case "O" lret = lret Or FILE_OWNERSHIP_ACCESS Case "R" If strType = "F" Then lret = lret Or FILE_GENERIC_READ Else lret = lret Or GENERIC_READ End If End Select Next FileRightsID = lret End Function 'Description:

removes

trustee from DACL 'Parameters: 'strTrustee Name of trustee account to remove from DACL Sub FileSetSecurityRemove(strTrustee) Dim bChange bChange = False 'loop through each ACE in DACL and search for specified account name For Each objAce In objDACL If StrComp(strTrustee, objAce.Trustee, vbTextCompare) = 0 Or _ strTrustee = "" Then objDACL.RemoveAce objAce bChange = True End If Next 'if ACE removed, set security descriptor for file If bChange Then objSD.DiscretionaryAcl = objDACL objSecurity.SetSecurityDescriptor objSD End If End Sub Function CreateErrMsg(objErr,sMsg) Dim sTemp sTemp = "Error# ["& Err & "] "& Err.Description If Not sMsg = "" Then sTemp = sTemp & vbCrLf & sMsg [<>?] CreateErrMsg = sTemp End Function ]]> </script> </component>

The ProgID for the component is ENTWSH.FileSecurity . The component exposes two methods : ListSecurity and SetSecurity .

ListSecurity returns file and directory permissions in a similar format displayed using the Windows NT command-line permissions CACLS.EXE . To list security permissions, create an instance of the FileSecurity object and invoke the ListSecurity method:

strRights = objWS.ListSecurity(strPath)

The strPath parameter represents the path to a file or directory.

ListSecurity returns the account(s) with access followed by associated permissions on a separate line for each account:

'list the permissions for a file 'create an instance of the ENTWSH.FileSecurity object Set objWS = CreateObject("ENTWSH.FileSecurity") 'list the permissions associated with a file Wscript.Echo objWS.ListSecurity("D:\data\

reports

.htm")

Permissions are represented with a single letter code that corresponds to a level of security access, as listed in Table 17-5.

Table 17-5: File and Directory Rights

ATTRIBUTE

DESCRIPTION

F

Full access

C

Change-read, write, execute

R

Read

W

Write

D

Delete

O

Ownership

P

Permissions

N

None

{% if main.adsdop %}{% include 'adsenceinline.tpl' %}{% endif %}

To set permissions, invoke the SetSecurity method:

bSuccess =objWS.SetSecurity(strPath, strPermissions, strTrustee)

The strPath parameter is the path to the directory of the file to set the security for. strPermissions is a string of one or more permissions to be assigned to the file or directory. The strTrustee parameter represents the user or group to be assigned the rights, and it must be in the format Domain\Accountname .

To set the read, execute, delete, ownership, and permissions rights for the file d:\data\reports.doc for account ACME\Freds , use the following:

bSuccess = objWS.SetSecurity("d:\data\reports.doc", "RXDOP", "ACME\Freds")

SetSecurity returns True if the security was successfully set; otherwise , it returns False .

If you are setting or listing permissions for a directory, you can specify two sets of security. One is the directory container access, which determines the access a trustee has to the directory. The second is file rights. The following example grants the user account Freds add and read permissions to the directory d:\data :

bSuccess = objWS.SetSecurity("d:\data ", "RWX:RX", "ACME\Freds")