这是什么原因导致了安全描述符出错?

5

我正在尝试使用以下代码(模仿Tim Golden提出的补丁,使其能够从Windows ACLs中读取文件和目录的访问权限)来读取Windows中的文件和目录的访问权限:

from ctypes import(
    windll,
    wintypes,
    c_char_p,
    c_void_p,
    byref
    )
from win32api import GetCurrentThread
from win32security import (
    GetFileSecurity,
    DACL_SECURITY_INFORMATION,
    ImpersonateSelf,
    SecurityImpersonation,
    OpenThreadToken,
    TOKEN_ALL_ACCESS,
    MapGenericMask
    )
from ntsecuritycon import (
    FILE_READ_DATA,
    FILE_WRITE_DATA,
    FILE_EXECUTE,
    FILE_ALL_ACCESS
    )
import pywintypes
import winnt

TRUE = 1

def CheckAccess(path,AccessDesired):
    result = wintypes.BOOL()
    granted = wintypes.DWORD(0)
    privsetlength = wintypes.DWORD(0)

    fileSD = GetFileSecurity(path, DACL_SECURITY_INFORMATION)
    if not fileSD.IsValid():
        raise Exception("Invalid security descriptor")

    ImpersonateSelf(SecurityImpersonation)
    token = OpenThreadToken(GetCurrentThread(), TOKEN_ALL_ACCESS, TRUE)
    mapping = wintypes.DWORD(MapGenericMask(AccessDesired,
        (FILE_READ_DATA, FILE_WRITE_DATA, FILE_EXECUTE, FILE_ALL_ACCESS)))
    if not windll.advapi32.AccessCheck(
        c_char_p(str(buffer(fileSD))),
        wintypes.HANDLE(int(token)),
        AccessDesired,
        byref(mapping),
        c_void_p(0), #privilege set, optional
        byref(privsetlength), #size of optional privilege set
        byref(granted),
        byref(result)
        ):
            code = GetLastError()
            raise WindowsError(GetLastError(),FormatMessage(code))
    return bool(result)

def HasReadAccess(path):
    return CheckAccess(path,FILE_READ_DATA)

def HasWriteAccess(path):
    return CheckAccess(path,FILE_WRITE_DATA)

if __name__ == "__main__":
    print(HasReadAccess("C:/Python26"))

然而,每次运行时我都会得到以下结果:
WindowsError: [Error 1338] The security descriptor structure is invalid.

我该如何将SecurityDescriptor传递给AccessCheck函数?

编辑:将DACL_SECURITY_INFORMATION参数改为DACL_SECURITY_INFORMATION | GROUP_SECURITY_INFORMATION | OWNER_SECURITY_INFORMATION后,我得到了以下结果:

WindowsError: [Error 122] The data area passed to a system call is too small.
1个回答

5
显然,Windows所谓的“可选”实际上是“必需”的。我通过分配一个缓冲区并传递PRIVILEGE_SET的大小(20)来解决了这个问题。

嗨,Stuart,我现在也在处理同样的问题;你能否请发一下你最终的工作代码? - Ali
2
这是我一年多前实习时写的代码,但我没有带走它。从我在这里所说的内容中可以看出,诀窍在于(根据此处的示例)将 privsetlength = wintypes.DWORD(0) 替换为 privsetlength = wintypes.DWORD(20),并将 c_void_p(0) 替换为类似于 create_string_buffer(20) 的东西。(过去一年半里,我一直很高兴地忘记了所有涉及 Python ctypes 模块的事情。) - Stuart P. Bentley
哈哈 :-) 你很棒把 ctypes 放到后面了!我已经让这个工作了。对于任何感兴趣的人,我的做法是先用 null 调用 AccessCheck 来获取默认行为(privsetlength),然后再使用正确的大小重新调用(请参阅 AccessCheck 在 MSDN 中的注释)。 - Ali
顺便说一下,你的代码至少为我节省了一整天的工作时间。谢谢! - Ali

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接