我想检查当前用户的远程文件的文件权限。但是,在使用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(¤tUserTrusteeW, 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, ¤tUserTrusteeW, &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。