How to set folder permissions in Windows?
You want the win32security
module, which is a part of pywin32. Here's an example of doing the sort of thing you want to do.
That example creates a new DACL for the file and replaces the old one, but it's easy to modify the existing one; all you need to do is get the existing DACL from the security descriptor instead of creating an empty one, like so:
import win32securityimport ntsecuritycon as conFILENAME = "whatever"userx, domain, type = win32security.LookupAccountName ("", "User X")usery, domain, type = win32security.LookupAccountName ("", "User Y")sd = win32security.GetFileSecurity(FILENAME, win32security.DACL_SECURITY_INFORMATION)dacl = sd.GetSecurityDescriptorDacl() # instead of dacl = win32security.ACL()dacl.AddAccessAllowedAce(win32security.ACL_REVISION, con.FILE_GENERIC_READ | con.FILE_GENERIC_WRITE, userx)dacl.AddAccessAllowedAce(win32security.ACL_REVISION, con.FILE_ALL_ACCESS, usery)sd.SetSecurityDescriptorDacl(1, dacl, 0) # may not be necessarywin32security.SetFileSecurity(FILENAME, win32security.DACL_SECURITY_INFORMATION, sd)
Here's a version of kindall's answer that uses EXPLICIT_ACCESS
entries with SetEntriesInAcl
, which creates a proper ACL with the ACEs in canonical order (e.g. access-denied ACEs are listed first). Also, this version sets the DACL using SetNamedSecurityInfo
, which supports propagating inheritable ACEs, unlike the obsolete function SetFileSecurity
.
import ntsecurityconimport win32securityFILENAME = "whatever"USERX = "UserX"USERY = "UserY"entries = [{'AccessMode': win32security.GRANT_ACCESS, 'AccessPermissions': 0, 'Inheritance': win32security.CONTAINER_INHERIT_ACE | win32security.OBJECT_INHERIT_ACE, 'Trustee': {'TrusteeType': win32security.TRUSTEE_IS_USER, 'TrusteeForm': win32security.TRUSTEE_IS_NAME, 'Identifier': ''}} for i in range(2)]entries[0]['AccessPermissions'] = (ntsecuritycon.GENERIC_READ | ntsecuritycon.GENERIC_WRITE)entries[0]['Trustee']['Identifier'] = USERXentries[1]['AccessPermissions'] = ntsecuritycon.GENERIC_ALLentries[1]['Trustee']['Identifier'] = USERYsd = win32security.GetNamedSecurityInfo(FILENAME, win32security.SE_FILE_OBJECT, win32security.DACL_SECURITY_INFORMATION)dacl = sd.GetSecurityDescriptorDacl()dacl.SetEntriesInAcl(entries)win32security.SetNamedSecurityInfo(FILENAME, win32security.SE_FILE_OBJECT, win32security.DACL_SECURITY_INFORMATION | win32security.UNPROTECTED_DACL_SECURITY_INFORMATION, None, None, dacl, None)
For those interested in the "list" of security descriptors for ACEs, what-have-ya use the following data structures. I had some help awhile back with this and have used this ever since.
typical_aces={ 2032127L:"Full Control(All)", 1179817L:"Read(RX)", 1180086L:"Add", 1180095L:"Add&Read", 1245631L:"Change"}binary_aces={ 1:"ACCESS_READ", #0x00000001 2:"ACCESS_WRITE", #0x00000002 4:"ACCESS_CREATE", #0x00000004 8:"ACCESS_EXEC", #0x00000008 16:"ACCESS_DELETE", #0x00000010 32:"ACCESS_ATRIB", #0x00000020 64:"ACCESS_PERM", #0x00000040 32768:"ACCESS_GROUP", #0x00008000 65536:"DELETE", #0x00010000 131072:"READ_CONTROL", #0x00020000 262144:"WRITE_DAC", #0x00040000 524288:"WRITE_OWNER", #0x00080000 1048576:"SYNCHRONIZE", #0x00100000 16777216:"ACCESS_SYSTEM_SECURITY",#0x01000000 33554432:"MAXIMUM_ALLOWED", #0x02000000 268435456:"GENERIC_ALL", #0x10000000 536870912:"GENERIC_EXECUTE",#0x20000000 1073741824:"GENERIC_WRITE", #0x40000000 65535:"SPECIFIC_RIGHTS_ALL",#0x0000ffff 983040:"STANDARD_RIGHTS_REQUIRED",#0x000f0000 2031616:"STANDARD_RIGHTS_ALL",#0x001f0000 }
Pass the mask from a given DACL / path to:
def calculate_plaintext_mask(mask): a=2147483648L if typical_aces.has_key(mask): return typical_aces[mask] else: result='NONE' while a>>1: a=a>>1 masked=mask&a if masked: if binary_aces.has_key(masked): result=binary_aces[masked]+':'+result return result