使用ACL不一致行为检查远程文件权限

时间:2015-11-03 16:18:48

标签: c++ windows winapi acl

我想检查当前用户的远程文件的文件权限。但是,在使用Qt的QFileInfo课程时,我的行为不一致。一个网络位置上的文件将报告它是可读的,而另一个网络位置上的同一文件会报告它不可读,即使两者在现实中都是可读的。

在深入了解实施后,似乎当功能“成功”时发生了什么。 is GetNamedSecurityInfo正在将指向ACL(pDacl)的指针设置为null,这显然只有在安全描述符不包含ACL且传入DACL_SECURITY_INFORMATION标志时才会发生。不应该发生,因为函数的错误代码报告成功。然后将空ACL指针传递给GetEffectiveRightsFromAcl,这会导致它将ACCESS_MASK参数设置为完全权限。文档似乎没有说明在将空指针传递给ACL(GetEffectiveRightsFromAcl)时pacl的预期行为是什么,但我很惊讶报告完全访问权限是出现的内容即将发生。它还返回ERROR_SUCCESS而不是ERROR_INVALID_ACL,这正是我所期望的。

当功能失败时' GetNamedSecurityInfo返回指向ACL的实际指针,当传递给GetEffectiveRightsFromAcl时,导致ACCESS_MASK被设置为无权访问,即使当前用户应具有完全访问权限。

当处理本地系统上的文件时,一切正常,因为我希望返回ACL并正确报告权限。

我在GetEffectiveRightsFromAcl的文档页面上读到了它的使用已被弃用,但推荐的替代方法表现出与此完全相同的行为。

我使用Win32 API编写了一个小例子程序,它可以重现问题。

#include "Aclapi.h"

const wchar_t* files[] =
{
    L"\\\\?\\UNC\\share1\\fileThatSucceeds.txt",
    L"\\\\?\\UNC\\share2\\fileThatFails.txt" 
};

int main(void)
{
    TRUSTEE_W currentUserTrusteeW;
    PSID currentUserSID = 0;
    HANDLE hnd = ::GetCurrentProcess();
    HANDLE token = 0;
    if (::OpenProcessToken(hnd, TOKEN_QUERY, &token)) {
        DWORD retsize = 0;
        ::GetTokenInformation(token, TokenUser, 0, 0, &retsize);
        if (retsize) {
            void *tokenBuffer = malloc(retsize);
            if (::GetTokenInformation(token, TokenUser, tokenBuffer, retsize, &retsize)) {
                PSID tokenSid = ((PTOKEN_USER)(tokenBuffer))->User.Sid;
                DWORD sidLen = ::GetLengthSid(tokenSid);
                currentUserSID = (PSID)(malloc(sidLen));
                if (::CopySid(sidLen, currentUserSID, tokenSid))
                    BuildTrusteeWithSid(&currentUserTrusteeW, currentUserSID);
            }
            free(tokenBuffer);
        }
        ::CloseHandle(token);
    }
    for (int i = 0; i < 2; i++) {
        wchar_t* file = (wchar_t*)files[i];
        PSID pOwner = 0;
        PSID pGroup = 0;
        PACL pDacl = 0;
        PSECURITY_DESCRIPTOR pSD;
        DWORD res = GetNamedSecurityInfoW(file, SE_FILE_OBJECT, 
            OWNER_SECURITY_INFORMATION | GROUP_SECURITY_INFORMATION | DACL_SECURITY_INFORMATION,
            &pOwner, &pGroup, &pDacl, 0, &pSD);
        if (res == ERROR_SUCCESS) {
            ACCESS_MASK mask;
            res = GetEffectiveRightsFromAclW(pDacl, &currentUserTrusteeW, &mask);
            if (res == ERROR_SUCCESS)
            {
                wprintf(file);
                printf(" Permissions:\n");
                if (((mask & GENERIC_READ) == GENERIC_READ)
                || ((mask & FILE_GENERIC_READ) == FILE_GENERIC_READ))
                    wprintf_s(L"\tRead\n");
                if (((mask & GENERIC_WRITE) == GENERIC_WRITE)
                || ((mask & FILE_GENERIC_WRITE) == FILE_GENERIC_WRITE))
                    wprintf_s(L"\tWrite\n");
                if (((mask & GENERIC_EXECUTE) == GENERIC_EXECUTE)
                || ((mask & FILE_GENERIC_EXECUTE) == FILE_GENERIC_EXECUTE))
                    wprintf_s(L"\tExecute\n");
            }
        }
    }
    free(currentUserSID);
    getchar();
    return 0;
}

修改:当我运行

ConvertSecurityDescriptorToStringSecurityDescriptor(pSD, SDDL_REVISION_1, DACL_SECURITY_INFORMATION, &StringSecurityDescriptor, &StringSecurityDescriptorLen);

根据评论中的建议,我得到了以下输出文件“&{39;成功”D:NO_ACCESS_CONTROL以及“失败的文件”D:(A;ID;0x1301ff;;;S-1-5-21-4567658000-3444563456-7654345676-3475)(A;ID;0x1301ff;;;S-1-5-21-4567658000-3444563456-7654345676-4576)...

这两台服务器都是使用CIFS进行通信的NAS。

0 个答案:

没有答案