Spaces:
Sleeping
Sleeping
import os | |
import ntsecuritycon | |
import pythoncom | |
import win32api | |
import win32com.server.policy | |
import win32con | |
import win32security | |
from ntsecuritycon import ( | |
CONTAINER_INHERIT_ACE, | |
FILE_ALL_ACCESS, | |
FILE_APPEND_DATA, | |
FILE_GENERIC_EXECUTE, | |
FILE_GENERIC_READ, | |
FILE_GENERIC_WRITE, | |
FILE_READ_ATTRIBUTES, | |
FILE_READ_DATA, | |
FILE_READ_EA, | |
FILE_WRITE_ATTRIBUTES, | |
FILE_WRITE_DATA, | |
FILE_WRITE_EA, | |
INHERIT_ONLY_ACE, | |
OBJECT_INHERIT_ACE, | |
PSPCB_SI_INITDIALOG, | |
READ_CONTROL, | |
SI_ACCESS_CONTAINER, | |
SI_ACCESS_GENERAL, | |
SI_ACCESS_PROPERTY, | |
SI_ACCESS_SPECIFIC, | |
SI_ADVANCED, | |
SI_CONTAINER, | |
SI_EDIT_ALL, | |
SI_EDIT_AUDITS, | |
SI_EDIT_PROPERTIES, | |
SI_PAGE_ADVPERM, | |
SI_PAGE_AUDIT, | |
SI_PAGE_OWNER, | |
SI_PAGE_PERM, | |
SI_PAGE_TITLE, | |
SI_RESET, | |
STANDARD_RIGHTS_EXECUTE, | |
STANDARD_RIGHTS_READ, | |
STANDARD_RIGHTS_WRITE, | |
SYNCHRONIZE, | |
WRITE_DAC, | |
WRITE_OWNER, | |
) | |
from pythoncom import IID_NULL | |
from win32com.authorization import authorization | |
from win32com.shell.shellcon import ( # # Msg parameter to PropertySheetPageCallback | |
PSPCB_CREATE, | |
PSPCB_RELEASE, | |
) | |
from win32security import CONTAINER_INHERIT_ACE, INHERIT_ONLY_ACE, OBJECT_INHERIT_ACE | |
class SecurityInformation(win32com.server.policy.DesignatedWrapPolicy): | |
_com_interfaces_ = [authorization.IID_ISecurityInformation] | |
_public_methods_ = [ | |
"GetObjectInformation", | |
"GetSecurity", | |
"SetSecurity", | |
"GetAccessRights", | |
"GetInheritTypes", | |
"MapGeneric", | |
"PropertySheetPageCallback", | |
] | |
def __init__(self, FileName): | |
self.FileName = FileName | |
self._wrap_(self) | |
def GetObjectInformation(self): | |
"""Identifies object whose security will be modified, and determines options available | |
to the end user""" | |
flags = SI_ADVANCED | SI_EDIT_ALL | SI_PAGE_TITLE | SI_RESET | |
if os.path.isdir(self.FileName): | |
flags |= SI_CONTAINER | |
hinstance = 0 ## handle to module containing string resources | |
servername = "" ## name of authenticating server if not local machine | |
objectname = os.path.split(self.FileName)[1] | |
pagetitle = "Python ACL Editor" | |
if os.path.isdir(self.FileName): | |
pagetitle += " (dir)" | |
else: | |
pagetitle += " (file)" | |
objecttype = IID_NULL | |
return flags, hinstance, servername, objectname, pagetitle, objecttype | |
def GetSecurity(self, requestedinfo, bdefault): | |
"""Requests the existing permissions for object""" | |
if bdefault: | |
## This is invoked if the 'Default' button is pressed (only present if SI_RESET is passed | |
## with the flags in GetObjectInfo). Passing an empty SD with a NULL Dacl | |
## should cause inherited ACL from parent dir or default dacl from user's token to be used | |
return win32security.SECURITY_DESCRIPTOR() | |
else: | |
## GetFileSecurity sometimes fails to return flags indicating that an ACE is inherited | |
return win32security.GetNamedSecurityInfo( | |
self.FileName, win32security.SE_FILE_OBJECT, requestedinfo | |
) | |
def SetSecurity(self, requestedinfo, sd): | |
"""Applies permissions to the object""" | |
owner = sd.GetSecurityDescriptorOwner() | |
group = sd.GetSecurityDescriptorGroup() | |
dacl = sd.GetSecurityDescriptorDacl() | |
sacl = sd.GetSecurityDescriptorSacl() | |
win32security.SetNamedSecurityInfo( | |
self.FileName, | |
win32security.SE_FILE_OBJECT, | |
requestedinfo, | |
owner, | |
group, | |
dacl, | |
sacl, | |
) | |
## should also handle recursive operations here | |
def GetAccessRights(self, objecttype, flags): | |
"""Returns a tuple of (AccessRights, DefaultAccess), where AccessRights is a sequence of tuples representing | |
SI_ACCESS structs, containing (guid, access mask, Name, flags). DefaultAccess indicates which of the | |
AccessRights will be used initially when a new ACE is added (zero based). | |
Flags can contain SI_ACCESS_SPECIFIC,SI_ACCESS_GENERAL,SI_ACCESS_CONTAINER,SI_ACCESS_PROPERTY, | |
CONTAINER_INHERIT_ACE,INHERIT_ONLY_ACE,OBJECT_INHERIT_ACE | |
""" | |
## input flags: SI_ADVANCED,SI_EDIT_AUDITS,SI_EDIT_PROPERTIES indicating which property sheet is requesting the rights | |
if (objecttype is not None) and (objecttype != IID_NULL): | |
## Should not be true for file objects. Usually only used with DS objects that support security for | |
## their properties | |
raise NotImplementedError("Object type is not supported") | |
if os.path.isdir(self.FileName): | |
file_append_data_desc = "Create subfolders" | |
file_write_data_desc = "Create Files" | |
else: | |
file_append_data_desc = "Append data" | |
file_write_data_desc = "Write data" | |
accessrights = [ | |
( | |
IID_NULL, | |
FILE_GENERIC_READ, | |
"Generic read", | |
SI_ACCESS_GENERAL | |
| SI_ACCESS_SPECIFIC | |
| OBJECT_INHERIT_ACE | |
| CONTAINER_INHERIT_ACE, | |
), | |
( | |
IID_NULL, | |
FILE_GENERIC_WRITE, | |
"Generic write", | |
SI_ACCESS_GENERAL | |
| SI_ACCESS_SPECIFIC | |
| OBJECT_INHERIT_ACE | |
| CONTAINER_INHERIT_ACE, | |
), | |
( | |
IID_NULL, | |
win32con.DELETE, | |
"Delete", | |
SI_ACCESS_SPECIFIC | OBJECT_INHERIT_ACE | CONTAINER_INHERIT_ACE, | |
), | |
( | |
IID_NULL, | |
WRITE_OWNER, | |
"Change owner", | |
SI_ACCESS_SPECIFIC | OBJECT_INHERIT_ACE | CONTAINER_INHERIT_ACE, | |
), | |
( | |
IID_NULL, | |
READ_CONTROL, | |
"Read Permissions", | |
SI_ACCESS_SPECIFIC | OBJECT_INHERIT_ACE | CONTAINER_INHERIT_ACE, | |
), | |
( | |
IID_NULL, | |
WRITE_DAC, | |
"Change permissions", | |
SI_ACCESS_SPECIFIC | OBJECT_INHERIT_ACE | CONTAINER_INHERIT_ACE, | |
), | |
( | |
IID_NULL, | |
FILE_APPEND_DATA, | |
file_append_data_desc, | |
SI_ACCESS_SPECIFIC | OBJECT_INHERIT_ACE | CONTAINER_INHERIT_ACE, | |
), | |
( | |
IID_NULL, | |
FILE_WRITE_DATA, | |
file_write_data_desc, | |
SI_ACCESS_SPECIFIC | OBJECT_INHERIT_ACE | CONTAINER_INHERIT_ACE, | |
), | |
] | |
return (accessrights, 0) | |
def MapGeneric(self, guid, aceflags, mask): | |
"""Converts generic access rights to specific rights. This implementation uses standard file system rights, | |
but you can map them any way that suits your application. | |
""" | |
return win32security.MapGenericMask( | |
mask, | |
( | |
FILE_GENERIC_READ, | |
FILE_GENERIC_WRITE, | |
FILE_GENERIC_EXECUTE, | |
FILE_ALL_ACCESS, | |
), | |
) | |
def GetInheritTypes(self): | |
"""Specifies which types of ACE inheritance are supported. | |
Returns a sequence of tuples representing SI_INHERIT_TYPE structs, containing | |
(object type guid, inheritance flags, display name). Guid is usually only used with | |
Directory Service objects. | |
""" | |
return ( | |
(IID_NULL, 0, "Only current object"), | |
(IID_NULL, OBJECT_INHERIT_ACE, "Files inherit permissions"), | |
(IID_NULL, CONTAINER_INHERIT_ACE, "Sub Folders inherit permissions"), | |
( | |
IID_NULL, | |
CONTAINER_INHERIT_ACE | OBJECT_INHERIT_ACE, | |
"Files and subfolders", | |
), | |
) | |
def PropertySheetPageCallback(self, hwnd, msg, pagetype): | |
"""Invoked each time a property sheet page is created or destroyed.""" | |
## page types from SI_PAGE_TYPE enum: SI_PAGE_PERM SI_PAGE_ADVPERM SI_PAGE_AUDIT SI_PAGE_OWNER | |
## msg: PSPCB_CREATE, PSPCB_RELEASE, PSPCB_SI_INITDIALOG | |
return None | |
def EditSecurity(self, owner_hwnd=0): | |
"""Creates an ACL editor dialog based on parameters returned by interface methods""" | |
isi = pythoncom.WrapObject( | |
self, authorization.IID_ISecurityInformation, pythoncom.IID_IUnknown | |
) | |
authorization.EditSecurity(owner_hwnd, isi) | |
## folder permissions | |
temp_dir = win32api.GetTempPath() | |
dir_name = win32api.GetTempFileName(temp_dir, "isi")[0] | |
print(dir_name) | |
os.remove(dir_name) | |
os.mkdir(dir_name) | |
si = SecurityInformation(dir_name) | |
si.EditSecurity() | |
## file permissions | |
fname = win32api.GetTempFileName(dir_name, "isi")[0] | |
si = SecurityInformation(fname) | |
si.EditSecurity() | |