关于源码解读,之前操作文件权限主要依赖salt 的win_dacl 模块的源码
下面的源码提供的功能:
- _getUserSid(user) #根据用户名获取SID
- _get_dacl(path, objectType) #根据文件路径和类型,获取dacl (权限类表)
- get(path, objectType, user=None) # 根据文件路径和类型,获取ACLs
- add_ace(path, objectType, user, permission, acetype, propagation)
- 添加权限
from __future__ import absolute_import
import os
import re
import win32security
import ntsecuritycon
import win32api
class daclConstants(object):
'''
DACL constants used throughout the module
'''
def __init__(self):
self.FILE_ALL_ACCESS = (ntsecuritycon.STANDARD_RIGHTS_REQUIRED | ntsecuritycon.SYNCHRONIZE | 0x1ff)
self.hkeys_security = {
'HKEY_LOCAL_MACHINE': 'MACHINE',
'HKEY_USERS': 'USERS',
'HKEY_CURRENT_USER': 'CURRENT_USER',
'HKEY_CLASSES_ROOT': 'CLASSES_ROOT',
'MACHINE': 'MACHINE',
'USERS': 'USERS',
'CURRENT_USER': 'CURRENT_USER',
'CLASSES_ROOT': 'CLASSES_ROOT',
'HKLM': 'MACHINE',
'HKU': 'USERS',
'HKCU': 'CURRENT_USER',
'HKCR': 'CLASSES_ROOT',
}
self.rights = {
win32security.SE_FILE_OBJECT: {
'READ': {
'BITS': ntsecuritycon.FILE_GENERIC_READ,
'TEXT': 'read'},
'WRITE': {
'BITS': ntsecuritycon.FILE_GENERIC_WRITE,
'TEXT': 'write'},
'READ&EXECUTE': {
'BITS': ntsecuritycon.FILE_GENERIC_EXECUTE |
ntsecuritycon.FILE_GENERIC_READ,
'TEXT': 'read and execute'},#读取和执行
'MODIFY': {
'BITS': ntsecuritycon.FILE_GENERIC_WRITE |
ntsecuritycon.FILE_GENERIC_READ |
ntsecuritycon.FILE_GENERIC_EXECUTE |
ntsecuritycon.DELETE,
'TEXT': 'modify'}, #修改
'FULLCONTROL': {
'BITS': self.FILE_ALL_ACCESS,
'TEXT': 'full control'}#完全控制
}
}
self.validAceTypes = {
'ALLOW': {'TEXT': 'allowed', 'BITS': 0},
'DENY': {'TEXT': 'denied', 'BITS': 1}}
self.validPropagations = {
win32security.SE_REGISTRY_KEY: {
'KEY': {
'TEXT': 'this key only',
'BITS': win32security.NO_INHERITANCE},
'KEY&SUBKEYS': {
'TEXT': 'this key and subkeys',
'BITS': win32security.CONTAINER_INHERIT_ACE},
'SUBKEYS': {
'TEXT': 'subkeys only',
'BITS': win32security.INHERIT_ONLY_ACE |
win32security.CONTAINER_INHERIT_ACE},
'THIS KEY ONLY': {
'TEXT': 'this key only',
'BITS': win32security.NO_INHERITANCE},
'THIS KEY AND SUBKEYS': {
'TEXT': 'this key and subkeys',
'BITS': win32security.CONTAINER_INHERIT_ACE},
'SUBKEYS ONLY': {
'TEXT': 'subkeys only',
'BITS': win32security.INHERIT_ONLY_ACE |
win32security.CONTAINER_INHERIT_ACE}
},
win32security.SE_FILE_OBJECT: {
'FILE': {
'TEXT': 'this file/folder only',
'BITS': win32security.NO_INHERITANCE},
'FOLDER': {
'TEXT': 'this file/folder only',
'BITS': win32security.NO_INHERITANCE},
'FOLDER&SUBFOLDERS&FILES': {
'TEXT': 'this folder, subfolders, and files',
'BITS': win32security.CONTAINER_INHERIT_ACE |
win32security.OBJECT_INHERIT_ACE},
'FOLDER&SUBFOLDERS': {
'TEXT': 'this folder and subfolders',
'BITS': win32security.CONTAINER_INHERIT_ACE},
'FOLDER&FILES': {
'TEXT': 'this folder and files',
'BITS': win32security.OBJECT_INHERIT_ACE},
'SUBFOLDERS&FILES': {
'TEXT': 'subfolders and files',
'BITS': win32security.INHERIT_ONLY_ACE |
win32security.CONTAINER_INHERIT_ACE |
win32security.OBJECT_INHERIT_ACE},
'SUBFOLDERS': {
'TEXT': 'subfolders only',
'BITS': win32security.INHERIT_ONLY_ACE |
win32security.CONTAINER_INHERIT_ACE},
'FILES': {
'TEXT': 'files only',
'BITS': win32security.INHERIT_ONLY_ACE |
win32security.OBJECT_INHERIT_ACE},
'THIS FILE ONLY': {
'TEXT': 'this file/folder only',
'BITS': win32security.NO_INHERITANCE},
'THIS FOLDER ONLY': {
'TEXT': 'this file/folder only',
'BITS': win32security.NO_INHERITANCE},
'THIS FOLDER, SUBFOLDERS, AND FILES': {
'TEXT': 'this folder, subfolders, and files',
'BITS': win32security.CONTAINER_INHERIT_ACE |
win32security.OBJECT_INHERIT_ACE},
'THIS FOLDER AND SUBFOLDERS': {
'TEXT': 'this folder and subfolders',
'BITS': win32security.CONTAINER_INHERIT_ACE},
'THIS FOLDER AND FILES': {
'TEXT': 'this folder and files',
'BITS': win32security.OBJECT_INHERIT_ACE},
'SUBFOLDERS AND FILES': {
'TEXT': 'subfolders and files',
'BITS': win32security.INHERIT_ONLY_ACE |
win32security.CONTAINER_INHERIT_ACE |
win32security.OBJECT_INHERIT_ACE},
'SUBFOLDERS ONLY': {
'TEXT': 'subfolders only',
'BITS': win32security.INHERIT_ONLY_ACE |
win32security.CONTAINER_INHERIT_ACE},
'FILES ONLY': {
'TEXT': 'files only',
'BITS': win32security.INHERIT_ONLY_ACE |
win32security.OBJECT_INHERIT_ACE}
}
}
self.objectType = {
'FILE': win32security.SE_FILE_OBJECT,
'DIRECTORY': win32security.SE_FILE_OBJECT,
'REGISTRY': win32security.SE_REGISTRY_KEY}
def getObjectTypeBit(self, t):
'''
returns the bit value of the string object type
返回字符串对象类型的位值.
'''
if isinstance(t, str):
t = t.upper()
try:
return self.objectType[t]
except KeyError:
print(123)
else:
return t
def getSecurityHkey(self, s):
'''
returns the necessary string value for an HKEY for the win32security module
返回的win32security模块HKEY必要的字符串值
'''
try:
return self.hkeys_security[s]
except KeyError:
print(123)
def getPermissionBit(self, t, m):
'''
returns a permission bit of the string permission value for the specified object type
返回指定对象类型的字符串权限值的权限位.
'''
try:
if isinstance(m, str):
return self.rights[t][m]['BITS']
else:
return m
except KeyError:
print(123)
def getPermissionText(self, t, m):
'''
returns the permission textual representation of a specified permission bit/object type
'''
try:
return self.rights[t][m]['TEXT']
except KeyError:
print(123)
def getAceTypeBit(self, t):
'''
returns the acetype bit of a text value
'''
try:
return self.validAceTypes[t]['BITS']
except KeyError:
print(123)
def getAceTypeText(self, t):
'''
returns the textual representation of a acetype bit
'''
try:
return self.validAceTypes[t]['TEXT']
except KeyError:
print(123)
def getPropagationBit(self, t, p):
'''
returns the propagation bit of a text value
'''
try:
return self.validPropagations[t][p]['BITS']
except KeyError:
print(123)
def getPropagationText(self, t, p):
'''
returns the textual representation of a propagation bit
'''
try:
return self.validPropagations[t][p]['TEXT']
except KeyError:
print(123)
def processPath(self, path, objectType):
'''
processes a path/object type combo and returns:
registry types with the correct HKEY text representation
files/directories with environment variables expanded
'''
if objectType == win32security.SE_REGISTRY_KEY:
splt = path.split("\\")
hive = self.getSecurityHkey(splt.pop(0).upper())
splt.insert(0, hive)
path = r'\\'.join(splt)
else:
path = os.path.expandvars(path)
return path
def _getUserSid(user):
'''
return a state error dictionary, with 'sid' as a field if it could be returned
if user is None, sid will also be None
'''
ret = {}
sid_pattern = r'^S-1(-\d+){1,}$'
if user and re.match(sid_pattern, user, re.I):
try:
sid = win32security.GetBinarySid(user)
except Exception as e:
ret['result'] = False
ret['comment'] = 'Unable to obtain the binary security identifier for {0}. The exception was {1}.'.format(
user, e)
else:
try:
win32security.LookupAccountSid('', sid)
ret['result'] = True
ret['sid'] = sid
except Exception as e:
ret['result'] = False
ret['comment'] = 'Unable to lookup the account for the security identifier {0}. The exception was {1}.'.format(
user, e)
else:
try:
sid = win32security.LookupAccountName('', user)[0] if user else None
ret['result'] = True
ret['sid'] = sid
except Exception as e:
ret['result'] = False
ret['comment'] = 'Unable to obtain the security identifier for {0}. The exception was {1}.'.format(
user, e)
return ret
def _get_dacl(path, objectType):
'''
Gets the DACL of a path
'''
try:
dacl = win32security.GetNamedSecurityInfo(
path, objectType, win32security.DACL_SECURITY_INFORMATION
).GetSecurityDescriptorDacl()
except Exception:
dacl = None
return dacl
def get(path, objectType, user=None):
'''
Get the ACL of an object. Will filter by user if one is provided.
Args:
path: The path to the object
objectType: The type of object (FILE, DIRECTORY, REGISTRY)
user: A user name to filter by
Returns (dict): A dictionary containing the ACL
CLI Example:
.. code-block:: bash
salt 'minion-id' win_dacl.get c:\temp directory
'''
ret = {'Path': path,
'ACLs': []}
sidRet = _getUserSid(user)
if path and objectType:
dc = daclConstants()
objectTypeBit = dc.getObjectTypeBit(objectType)
path = dc.processPath(path, objectTypeBit)
tdacl = _get_dacl(path, objectTypeBit)
if tdacl:
for counter in range(0, tdacl.GetAceCount()):
tAce = tdacl.GetAce(counter)
if not sidRet['sid'] or (tAce[2] == sidRet['sid']):
ret['ACLs'].append(_ace_to_text(tAce, objectTypeBit))
return ret
def add_ace(path, objectType, user, permission, acetype, propagation):
r'''
add an ace to an object
path: path to the object (i.e. c:\\temp\\file, HKEY_LOCAL_MACHINE\\SOFTWARE\\KEY, etc)
user: user to add
permission: permissions for the user
acetype: either allow/deny for each user/permission (ALLOW, DENY)
propagation: how the ACE applies to children for Registry Keys and Directories(KEY, KEY&SUBKEYS, SUBKEYS)
CLI Example:
.. code-block:: bash
allow domain\fakeuser full control on HKLM\\SOFTWARE\\somekey, propagate to this key and subkeys
salt 'myminion' win_dacl.add_ace 'HKEY_LOCAL_MACHINE\\SOFTWARE\\somekey' 'Registry' 'domain\fakeuser' 'FULLCONTROL' 'ALLOW' 'KEY&SUBKEYS'
'''
ret = {'result': None,
'changes': {},
'comment': ''}
if (path and user and
permission and acetype
and propagation):
if objectType.upper() == "FILE":
propagation = "FILE"
dc = daclConstants()
objectTypeBit = dc.getObjectTypeBit(objectType)
path = dc.processPath(path, objectTypeBit)
user = user.strip()
permission = permission.strip().upper()
acetype = acetype.strip().upper()
propagation = propagation.strip().upper()
sidRet = _getUserSid(user)
if not sidRet['result']:
return sidRet
permissionbit = dc.getPermissionBit(objectTypeBit, permission)
acetypebit = dc.getAceTypeBit(acetype)
propagationbit = dc.getPropagationBit(objectTypeBit, propagation)
dacl = _get_dacl(path, objectTypeBit)
if dacl:
acesAdded = []
try:
if acetypebit == 0:
dacl.AddAccessAllowedAceEx(win32security.ACL_REVISION, propagationbit, permissionbit, sidRet['sid'])
elif acetypebit == 1:
dacl.AddAccessDeniedAceEx(win32security.ACL_REVISION, propagationbit, permissionbit, sidRet['sid'])
win32security.SetNamedSecurityInfo(
path, objectTypeBit, win32security.DACL_SECURITY_INFORMATION,
None, None, dacl, None)
acesAdded.append((
'{0} {1} {2} on {3}'
).format(
user, dc.getAceTypeText(acetype), dc.getPermissionText(objectTypeBit, permission),
dc.getPropagationText(objectTypeBit, propagation)))
ret['result'] = True
except Exception as e:
ret['comment'] = 'An error occurred attempting to add the ace. The error was {0}'.format(e)
ret['result'] = False
return ret
if acesAdded:
ret['changes']['Added ACEs'] = acesAdded
else:
ret['comment'] = 'Unable to obtain the DACL of {0}'.format(path)
else:
ret['comment'] = 'An empty value was specified for a required item.'
ret['result'] = False
return ret
def _ace_to_text(ace, objectType):
'''
helper function to convert an ace to a textual representation
'''
dc = daclConstants()
objectType = dc.getObjectTypeBit(objectType)
try:
userSid = win32security.LookupAccountSid('', ace[2])
if userSid[1]:
userSid = '{1}\\{0}'.format(userSid[0], userSid[1])
else:
userSid = '{0}'.format(userSid[0])
except Exception:
userSid = win32security.ConvertSidToStringSid(ace[2])
tPerm = ace[1]
tAceType = ace[0][0]
tProps = ace[0][1]
tInherited = ''
for x in dc.validAceTypes:
if dc.validAceTypes[x]['BITS'] == tAceType:
tAceType = dc.validAceTypes[x]['TEXT']
break
for x in dc.rights[objectType]:
if dc.rights[objectType][x]['BITS'] == tPerm:
tPerm = dc.rights[objectType][x]['TEXT']
break
if (tProps & win32security.INHERITED_ACE) == win32security.INHERITED_ACE:
tInherited = '[Inherited]'
tProps = (tProps ^ win32security.INHERITED_ACE)
for x in dc.validPropagations[objectType]:
if dc.validPropagations[objectType][x]['BITS'] == tProps:
tProps = dc.validPropagations[objectType][x]['TEXT']
break
return ((
'{0} {1} {2} on {3} {4}'
).format(userSid, tAceType, tPerm, tProps, tInherited))
当你需要的功能,在源码里面没有的时候
- 例 (更改文件夹所有者 右键文件夹-属性-安全-高级-所有者)
- 你就需要详细解读下这个源码,顺便看看其他文档
- 我们可以看到核心模块
- win32security 对权限的操作
- win32api 获取一些权限
-
抓住关键的核心代码
- win32security.SetNamedSecurityInfo( path, objectTypeBit, win32security.DACL_SECURITY_INFORMATION, None, None, dacl, None)
- win32security.DACL_SECURITY_INFORMATION #dacl 是权限类表 所有者是 OWNER
- 官方相关网址:Python for Win32 Extensions Help
- http://timgolden.me.uk/pywin32-docs/PyWin32.html
- 对象安全描述符
- https://blog.csdn.net/shineorrain/article/details/18141759
修改文件夹所有者
def set_file_owner(path, sid)
try:
sd = win32security.SECURITY_DESCRIPTOR()
sd.SetSecurityDescriptorOwner(sid, False)
win32security.SetFileSecurity(path,
win32security.OWNER_SECURITY_INFORMATION, sd) #设置文件夹所有者
return True
except win32security.error as e:
print(e)
return False