Taking directory ownership on Windows with Python results in “Access denied” error

强颜欢笑 提交于 2020-04-11 08:22:20

问题


I'm trying to take ownership of a directory with the following code:

sd = win32security.SECURITY_DESCRIPTOR()
sd.SetSecurityDescriptorOwner(curUser, False)
win32security.SetFileSecurity("C:/ProgramData/Test", 
    win32security.OWNER_SECURITY_INFORMATION, sd)

The SetFileSecurity call fails with an "Access denied" error.

The access rights for the current user have been removed from this directory. In Explorer I can see it, but when I try to open it, I first have to take ownership as an administrator. That works in Explorer, but the above code is executed with elevated permissions, and for some reason it still fails. Any suggestions?


回答1:


You can forcefully take ownership by enabling SeTakeOwnerShipPrivilege, but of course only if your access token has this privilege (e.g. an elevated administrator). Also, you can forcefully assign ownership to another security principal, such as SYSTEM, by enabling SeRestorePrivilege. Without the latter, the assignment may fail with the error code ERROR_INVALID_OWNER.

The following set_file_owner function has a force option that attempts to temporarily enable both of these privileges.

import win32api
import win32security

def set_file_owner(path, sid=None, force=False):
    try:
        hToken = win32security.OpenThreadToken(win32api.GetCurrentThread(),
                    win32security.TOKEN_ALL_ACCESS, True)
    except win32security.error:
        hToken = win32security.OpenProcessToken(win32api.GetCurrentProcess(),
                    win32security.TOKEN_ALL_ACCESS)
    if sid is None:
        sid = win32security.GetTokenInformation(hToken,
                win32security.TokenOwner)
    prev_state = ()
    if force:
        new_state = [(win32security.LookupPrivilegeValue(None, name),
                      win32security.SE_PRIVILEGE_ENABLED)
                        for name in (win32security.SE_TAKE_OWNERSHIP_NAME,
                                     win32security.SE_RESTORE_NAME)]
        prev_state = win32security.AdjustTokenPrivileges(hToken, False,
                        new_state)
    try:
        sd = win32security.SECURITY_DESCRIPTOR()
        sd.SetSecurityDescriptorOwner(sid, False)
        win32security.SetFileSecurity(path, 
            win32security.OWNER_SECURITY_INFORMATION, sd)
    finally:
        if prev_state:
            win32security.AdjustTokenPrivileges(hToken, False, prev_state)

def get_file_owner(path):
    sd = win32security.GetFileSecurity(path,
            win32security.OWNER_SECURITY_INFORMATION)
    sid = sd.GetSecurityDescriptorOwner()
    return win32security.LookupAccountSid(None, sid)

Example

if __name__ == '__main__':
    import os
    import tempfile
    import subprocess

    username = os.environ['UserName']
    test_path = tempfile.mkdtemp()
    print('Test path: {}'.format(test_path))
    subprocess.call(['icacls.exe', test_path, '/setowner', 'SYSTEM'],
                     creationflags=8)
    owner = get_file_owner(test_path)
    print('Initial owner: {}\\{}'.format(owner[1], owner[0]))
    try:
        print('Denying write owner access')
        subprocess.call(['icacls.exe', test_path, '/deny',
                         '{}:(WO)'.format(username)], creationflags=8)
        try:
            set_file_owner(test_path)
        except win32security.error:
            print('Trying with force=True')
            try:
                set_file_owner(test_path, force=True)
            except win32security.error:
                pass
    finally:
        owner = get_file_owner(test_path)
        print('Final owner: {}\\{}'.format(owner[1], owner[0]))
        os.rmdir(test_path)

Output

Test path: C:\Users\eryksun\AppData\Local\Temp\tmpizgemrdz
Initial owner: NT AUTHORITY\SYSTEM
Denying write owner access
Trying with force=True
Final owner: BUILTIN\Administrators



回答2:


I've based on Eryk's work to make a full recursive ACL and onwership handling routing for NTFS files under Windows here: https://stackoverflow.com/a/61041460/2635443



来源:https://stackoverflow.com/questions/41081263/taking-directory-ownership-on-windows-with-python-results-in-access-denied-err

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!