我希望能够授权或拒绝对Windows XP和更多的特定目录的写权限。
我尝试了以下,他们都不工作:
os.chmod()
:只能指定文件的只读属性,请参阅Python的文档 win32api.SetFileAttribute()
FILE_ATTRIBUTE_READONLY:一个只读的文件。 […]这个属性不符合目录 ,请参阅MSDN的SetFileAttribute 它看起来像我唯一的select是访问和更新目录的“ 安全信息 ”,我已经尝试了几个小时得到的东西没有太多的成功(我真的不熟悉Win32 API)完成。
任何想法如何做到这一点?
这只是一个具有挑战性的事情。 我已经开始了这个非常好的答案 ,可以帮助你做出类似的事情。
您可以首先列出目录的ACL,这可以使用以下代码完成:
import win32security import ntsecuritycon as con FILENAME = r'D:\tmp\acc_test' sd = win32security.GetFileSecurity(FILENAME, win32security.DACL_SECURITY_INFORMATION) dacl = sd.GetSecurityDescriptorDacl() ace_count = dacl.GetAceCount() print('Ace count:', ace_count) for i in range(0, ace_count): rev, access, usersid = dacl.GetAce(i) user, group, type = win32security.LookupAccountSid('', usersid) print('User: {}/{}'.format(group, user), rev, access)
你可以找到方法PyACL.GetAceCount()
返回ACE的数量。
GetAce(i)
函数返回ACCESS_ALLOWED_ACE
头作为tuple
:
ACE_HEADER
– 两个整数AceType
, AceFlags
– 反复试验显示AceFlags
设置为11
表示继承权限, 3
不继承 ACCESS_MASK
– 这里或ntsecuritycon.py
详细列表 SID
现在你可以阅读旧的ACE, 删除旧的很简单:
for i in range(0, ace_count): dacl.DeleteAce(0)
之后,您可以通过调用AddAccessAllowedAceEx()
[ MSDN ]来添加权限:
userx, domain, type = win32security.LookupAccountName ("", "your.user") usery, domain, type = win32security.LookupAccountName ("", "other.user") dacl.AddAccessAllowedAceEx(win32security.ACL_REVISION, 3, 2032127, userx) # Full control dacl.AddAccessAllowedAceEx(win32security.ACL_REVISION, 3, 1179785, usery) # Read only sd.SetSecurityDescriptorDacl(1, dacl, 0) # may not be necessary win32security.SetFileSecurity(FILENAME, win32security.DACL_SECURITY_INFORMATION, sd)
我已经从脚本的前半部分列表中获取了编号为2032127
和1179785
(在运行脚本之前,我已经在“ 资源管理器” – >“右键单击” – >“属性” – >“安全” – >“高级”中设置了权限)
只是从http://technet.microsoft.com/借用的说明性图像
User: DOMAIN/user (0, 3) 2032127 User: DOMAIN/user2 (0, 3) 1179785
但它对应于:
OBJECT_INHERIT_ACE|CONTAINER_INHERIT_ACE
FILE_ALL_ACCESS
(实际上是con.FILE_ALL_ACCESS = 2032639
,但是一旦你把它应用到文件上并读回来,你将得到2032127 ;差别是512 – 0x0200 – 我在ntsecuritycon.py/file security permissions
) FILE_GENERIC_READ
您也可以删除访问,更改或删除它,但这应该是非常稳固的开始。
import win32security import ntsecuritycon as con FILENAME = r'D:\tmp\acc_test' userx, domain, type = win32security.LookupAccountName ("", "your.user") usery, domain, type = win32security.LookupAccountName ("", "other.user") sd = win32security.GetFileSecurity(FILENAME, win32security.DACL_SECURITY_INFORMATION) dacl = sd.GetSecurityDescriptorDacl() ace_count = dacl.GetAceCount() print('Ace count:', ace_count) # Listing for i in range(0, ace_count): rev, access, usersid = dacl.GetAce(i) user, group, type = win32security.LookupAccountSid('', usersid) print('User: {}/{}'.format(group, user), rev, access) # Removing the old ones for i in range(0, ace_count): dacl.DeleteAce(0) # Add full control for user x dacl.AddAccessAllowedAceEx(win32security.ACL_REVISION, con.OBJECT_INHERIT_ACE|con.CONTAINER_INHERIT_ACE, con.FILE_ALL_ACCESS, userx) # Add read only access for user y dacl.AddAccessAllowedAceEx(win32security.ACL_REVISION, con.OBJECT_INHERIT_ACE|con.CONTAINER_INHERIT_ACE, con.FILE_GENERIC_READ, usery) sd.SetSecurityDescriptorDacl(1, dacl, 0) # may not be necessary win32security.SetFileSecurity(FILENAME, win32security.DACL_SECURITY_INFORMATION, sd)
我只写了一个小脚本来解析所有文件ACE:
import win32security import ntsecuritycon as con import sys # List of all file masks that are interesting ACCESS_MASKS = ['FILE_READ_DATA', 'FILE_LIST_DIRECTORY', 'FILE_WRITE_DATA', 'FILE_ADD_FILE', 'FILE_APPEND_DATA', 'FILE_ADD_SUBDIRECTORY', 'FILE_CREATE_PIPE_INSTANCE', 'FILE_READ_EA', 'FILE_WRITE_EA', 'FILE_EXECUTE', 'FILE_TRAVERSE', 'FILE_DELETE_CHILD', 'FILE_READ_ATTRIBUTES', 'FILE_WRITE_ATTRIBUTES', 'FILE_ALL_ACCESS', 'FILE_GENERIC_READ', 'FILE_GENERIC_WRITE', 'FILE_GENERIC_EXECUTE'] # List of all inheritance flags ACE_FLAGS = ['OBJECT_INHERIT_ACE', 'CONTAINER_INHERIT_ACE', 'NO_PROPAGATE_INHERIT_ACE', 'INHERIT_ONLY_ACE'] # List of all ACE types ACE_TYPES = ['ACCESS_MIN_MS_ACE_TYPE', 'ACCESS_ALLOWED_ACE_TYPE', 'ACCESS_DENIED_ACE_TYPE', 'SYSTEM_AUDIT_ACE_TYPE', 'SYSTEM_ALARM_ACE_TYPE', 'ACCESS_MAX_MS_V2_ACE_TYPE', 'ACCESS_ALLOWED_COMPOUND_ACE_TYPE', 'ACCESS_MAX_MS_V3_ACE_TYPE', 'ACCESS_MIN_MS_OBJECT_ACE_TYPE', 'ACCESS_ALLOWED_OBJECT_ACE_TYPE', 'ACCESS_DENIED_OBJECT_ACE_TYPE', 'SYSTEM_AUDIT_OBJECT_ACE_TYPE', 'SYSTEM_ALARM_OBJECT_ACE_TYPE', 'ACCESS_MAX_MS_OBJECT_ACE_TYPE', 'ACCESS_MAX_MS_V4_ACE_TYPE', 'ACCESS_MAX_MS_ACE_TYPE', 'ACCESS_ALLOWED_CALLBACK_ACE_TYPE', 'ACCESS_DENIED_CALLBACK_ACE_TYPE', 'ACCESS_ALLOWED_CALLBACK_OBJECT_ACE_TYPE', 'ACCESS_DENIED_CALLBACK_OBJECT_ACE_TYPE', 'SYSTEM_AUDIT_CALLBACK_ACE_TYPE', 'SYSTEM_ALARM_CALLBACK_ACE_TYPE', 'SYSTEM_AUDIT_CALLBACK_OBJECT_ACE_TYPE', 'SYSTEM_ALARM_CALLBACK_OBJECT_ACE_TYPE', 'SYSTEM_MANDATORY_LABEL_ACE_TYPE', 'ACCESS_MAX_MS_V5_ACE_TYPE'] ################################################################################ def get_ace_types_str(ace_type): ''' Yields all matching ACE types as strings ''' for t in ACE_TYPES: if getattr(con, t) == ace_type: yield t ################################################################################ def get_ace_flags_str(ace_flag): ''' Yields all matching ACE flags as strings ''' for t in ACE_FLAGS: attr = getattr(con, t) if (attr & ace_flag) == attr: yield t ################################################################################ def get_access_mask_str(access_mask): ''' Yields all matching ACE flags as strings ''' for t in ACCESS_MASKS: attr = getattr(con, t) if (attr & access_mask) == attr: yield t ################################################################################ def list_file_ace(filename): ''' Method for listing of file ACEs ''' # Load data sd = win32security.GetFileSecurity(filename, win32security.DACL_SECURITY_INFORMATION) dacl = sd.GetSecurityDescriptorDacl() # Print ACE count ace_count = dacl.GetAceCount() print('File', filename, 'has', ace_count, 'ACEs') # Go trough individual ACEs for i in range(0, ace_count): (ace_type, ace_flag), access_mask, usersid = dacl.GetAce(i) user, group, usertype = win32security.LookupAccountSid('', usersid) print('\tUser: {}\\{}'.format(group, user)) print('\t\tACE Type ({}):'.format(ace_type), '; '.join(get_ace_types_str(ace_type))) print('\t\tACE Flags ({}):'.format(ace_flag), ' | '.join(get_ace_flags_str(ace_flag))) print('\t\tAccess Mask ({}):'.format(access_mask), ' | '.join(get_access_mask_str(access_mask))) print() ################################################################################ # Execute with some defaults if __name__ == '__main__': for filename in sys.argv[1:]: list_file_ace(filename) print()
它打印出像这样的字符串:
D:\tmp>acc_list.py D:\tmp D:\tmp\main.bat File D:\tmp has 8 ACEs User: BUILTIN\Administrators ACE Type (0): ACCESS_MIN_MS_ACE_TYPE; ACCESS_ALLOWED_ACE_TYPE ACE Flags (0): Access Mask (2032127): FILE_READ_DATA | FILE_LIST_DIRECTORY | FILE_WRITE_DATA | FILE_ADD_FILE | FILE_APPEND_DATA | FILE_ADD_SUBDIRECTORY | FILE_CREATE_PIPE_INSTANCE | FILE_READ_EA | FILE_WRITE_EA | FILE_EXECUTE | FILE_TRAVERSE | FILE_DELETE_CHILD | FILE_READ_ATTRIBUTES | FILE_WRITE_ATTRIBUTES | FILE_GENERIC_READ | FILE_GENERIC_WRITE | FILE_GENERIC_EXECUTE ...
所以,通过嘲笑并试图理解发生了什么事情,我设法找到了和@Vyktor之前发布的东西非常相似的东西。
我发现一些帮助使用这个例子 。
所以,我做的第一件事就是尝试了解Windows设置的标志,当我用GUI手动更改安全信息时,我建立了一组函数来帮助我:
import os import win32con import win32security import win32process import ntsecuritycon d = "toto" f = os.path.join(d, "foo") def build_flags_map(*attrs, **kw): mod = kw.get('mod', win32con) r = {} for attr in attrs: value = getattr(mod, attr) r[value] = attr return r ACE_TYPE = build_flags_map('ACCESS_ALLOWED_ACE_TYPE', 'ACCESS_DENIED_ACE_TYPE') ACCESS_MASK = build_flags_map( 'GENERIC_WRITE', 'GENERIC_ALL', 'GENERIC_EXECUTE', 'GENERIC_READ', 'WRITE_OWNER', 'DELETE', 'READ_CONTROL', 'SYNCHRONIZE', 'WRITE_DAC', 'ACCESS_SYSTEM_SECURITY') ACCESS_MASK_FILES = build_flags_map( 'FILE_ADD_FILE', 'FILE_READ_DATA', 'FILE_LIST_DIRECTORY', 'FILE_WRITE_DATA', 'FILE_ADD_FILE', 'FILE_APPEND_DATA', 'FILE_ADD_SUBDIRECTORY', 'FILE_CREATE_PIPE_INSTANCE', 'FILE_READ_EA', 'FILE_WRITE_EA', 'FILE_EXECUTE', 'FILE_TRAVERSE', 'FILE_DELETE_CHILD', 'FILE_READ_ATTRIBUTES', 'FILE_WRITE_ATTRIBUTES', 'FILE_ALL_ACCESS', 'FILE_GENERIC_READ', 'FILE_GENERIC_WRITE', 'FILE_GENERIC_EXECUTE', mod=ntsecuritycon, ) ACE_FLAGS = build_flags_map( 'CONTAINER_INHERIT_ACE', 'INHERITED_ACE', 'FAILED_ACCESS_ACE_FLAG', 'INHERIT_ONLY_ACE', 'OBJECT_INHERIT_ACE', mod=win32security) def display_flags(map, value): r = [] for flag, name in map.items(): if flag & value: r.append(name) value = value - flag if value != 0: # We didn't specified all the flags in the mapping :( r.append('(flags left 0x%x)' % value) return r' | '.join(r) def show_acls(path): process_handler = win32process.GetCurrentProcess() thread_handler = win32security.OpenProcessToken( process_handler, win32security.TOKEN_ALL_ACCESS) current_sid = win32security.GetTokenInformation(thread_handler, win32security.TokenUser)[0] desc = win32security.GetNamedSecurityInfo( path, win32security.SE_FILE_OBJECT, win32security.DACL_SECURITY_INFORMATION) dacl = desc.GetSecurityDescriptorDacl() print("%d ACE on %s" % (dacl.GetAceCount(), path)) for i in range(0, dacl.GetAceCount()): ace = dacl.GetAce(i) (ace_type, ace_flags), ace_mask, ace_sid = ace if ace_sid == current_sid: user = "me" else: user = str(ace_sid) print(" User: %s =>\n" " ACE type: %s\n" " ACE flags: %s\n" " ACE mask: %s\n" " Raw ACE: %r\n" % ( user, ACE_TYPE[ace_type], display_flags(ACE_FLAGS, ace_flags), display_flags(ACCESS_MASK_FILES, ace_mask), ace))
从那里,我得到以下信息:
7 ACE on toto User: me => ACE type: ACCESS_DENIED_ACE_TYPE ACE flags: CONTAINER_INHERIT_ACE | OBJECT_INHERIT_ACE ACE mask: FILE_ADD_FILE | FILE_CREATE_PIPE_INSTANCE | FILE_WRITE_ATTRIBUTES | FILE_WRITE_EA Raw ACE: ((1, 3), 278, <PySID object at 0x00B02148>) User: me => ACE type: ACCESS_ALLOWED_ACE_TYPE ACE flags: INHERITED_ACE ACE mask: FILE_TRAVERSE | FILE_LIST_DIRECTORY | FILE_ADD_FILE | FILE_CREATE_PIPE_INSTANCE | FILE_READ_EA | FILE_DELETE_CHILD | FILE_READ_ATTRIBUTES | FILE_GENERIC_EXECUTE | FILE_WRITE_EA | FILE_ALL_ACCESS | (flags left 0x-12039f) Raw ACE: ((0, 16), 2032127, <PySID object at 0x00A6FBF0>) User: me => ACE type: ACCESS_ALLOWED_ACE_TYPE ACE flags: INHERITED_ACE | CONTAINER_INHERIT_ACE | INHERIT_ONLY_ACE | OBJECT_INHERIT_ACE ACE mask: (flags left 0x10000000) Raw ACE: ((0, 27), 268435456, <PySID object at 0x00B02148>) User: PySID:S-1-5-18 => ACE type: ACCESS_ALLOWED_ACE_TYPE ACE flags: INHERITED_ACE ACE mask: FILE_TRAVERSE | FILE_LIST_DIRECTORY | FILE_ADD_FILE | FILE_CREATE_PIPE_INSTANCE | FILE_READ_EA | FILE_DELETE_CHILD | FILE_READ_ATTRIBUTES | FILE_GENERIC_EXECUTE | FILE_WRITE_EA | FILE_ALL_ACCESS | (flags left 0x-12039f) Raw ACE: ((0, 16), 2032127, <PySID object at 0x00A6FBF0>) User: PySID:S-1-5-18 => ACE type: ACCESS_ALLOWED_ACE_TYPE ACE flags: INHERITED_ACE | CONTAINER_INHERIT_ACE | INHERIT_ONLY_ACE | OBJECT_INHERIT_ACE ACE mask: (flags left 0x10000000) Raw ACE: ((0, 27), 268435456, <PySID object at 0x00B02148>) User: PySID:S-1-5-32-544 => ACE type: ACCESS_ALLOWED_ACE_TYPE ACE flags: INHERITED_ACE ACE mask: FILE_TRAVERSE | FILE_LIST_DIRECTORY | FILE_ADD_FILE | FILE_CREATE_PIPE_INSTANCE | FILE_READ_EA | FILE_DELETE_CHILD | FILE_READ_ATTRIBUTES | FILE_GENERIC_EXECUTE | FILE_WRITE_EA | FILE_ALL_ACCESS | (flags left 0x-12039f) Raw ACE: ((0, 16), 2032127, <PySID object at 0x00A6FBF0>) User: PySID:S-1-5-32-544 => ACE type: ACCESS_ALLOWED_ACE_TYPE ACE flags: INHERITED_ACE | CONTAINER_INHERIT_ACE | INHERIT_ONLY_ACE | OBJECT_INHERIT_ACE ACE mask: (flags left 0x10000000) Raw ACE: ((0, 27), 268435456, <PySID object at 0x00B02148>)
这个例子显示了我在我的系统+第一个ACL上的默认ACL,这是我自己创建的,并拒绝在目录上写入数据。
所以,使用之前的例子,我建立了这个:
def pipe_str_flags(map, *flags): r = 0 reverse_map = dict((value, key) for key, value in map.items()) for flag in flags: r = r | reverse_map[flag] return r def forbid_write(path): security_info = win32security.DACL_SECURITY_INFORMATION process_handler = win32process.GetCurrentProcess() thread_handler = win32security.OpenProcessToken( process_handler, win32security.TOKEN_ALL_ACCESS) desc = win32security.GetNamedSecurityInfo( path, win32security.SE_FILE_OBJECT, security_info) current_sid = win32security.GetTokenInformation(thread_handler, win32security.TokenUser)[0] dacl = desc.GetSecurityDescriptorDacl() mask = pipe_str_flags(ACCESS_MASK_FILES, 'FILE_ADD_FILE', 'FILE_CREATE_PIPE_INSTANCE', 'FILE_WRITE_ATTRIBUTES', 'FILE_WRITE_EA') ace_flags = pipe_str_flags(ACE_FLAGS, 'CONTAINER_INHERIT_ACE', 'OBJECT_INHERIT_ACE') dacl.AddAccessDeniedAceEx( dacl.GetAclRevision(), ace_flags, mask, current_sid) win32security.SetNamedSecurityInfo( path, win32security.SE_FILE_OBJECT, security_info, None, None, dacl, None)
与@Vyktor解决方案相反,我使用“Denied”ACE拒绝写入访问(而Vyktor添加了“Allowed read-only”ACE)。
我sitll错过了一个正确的方法来删除这个ACE,所以我可以再次写在这个目录中,但我还没有真正看。 有一点很重要,那就是“Denied”ACE优先于“Allowed”ACE,所以我试着用dacl.AddAccessAllowedAceEx()
和我在dacl.AddAccessDeniedAceEx()
上使用的参数完全相同的方法,后来一个优先于前一个,所以我仍然不能写入目录。