我正在尝试使用Windows权限API修改权限。
我有一个独立的用例代码,如下所示,我首先撤销所有的访问权限,然后授予读写权限。
#include <fstream>
#include <iostream>
#include <aclapi.h>
#include <windows.h>
#include <string>
using namespace std;
#include <memory>
bool CanAccessFolder(LPCTSTR folderName, DWORD genericAccessRights,DWORD& grantedRights)
{
bool bRet = false;
DWORD length = 0;
if (!::GetFileSecurity(folderName, OWNER_SECURITY_INFORMATION | GROUP_SECURITY_INFORMATION
| DACL_SECURITY_INFORMATION, NULL, NULL, &length) &&
ERROR_INSUFFICIENT_BUFFER == ::GetLastError()) {
PSECURITY_DESCRIPTOR security = static_cast< PSECURITY_DESCRIPTOR >(::malloc(length));
if (security && ::GetFileSecurity(folderName, OWNER_SECURITY_INFORMATION | GROUP_SECURITY_INFORMATION
| DACL_SECURITY_INFORMATION, security, length, &length)) {
HANDLE hToken = NULL;
if (::OpenProcessToken(::GetCurrentProcess(), TOKEN_IMPERSONATE | TOKEN_QUERY |
TOKEN_DUPLICATE | STANDARD_RIGHTS_READ, &hToken)) {
HANDLE hImpersonatedToken = NULL;
if (::DuplicateToken(hToken, SecurityImpersonation, &hImpersonatedToken)) {
GENERIC_MAPPING mapping = { 0xFFFFFFFF };
PRIVILEGE_SET privileges = { 0 };
DWORD grantedAccess = 0, privilegesLength = sizeof(privileges);
BOOL result = FALSE;
mapping.GenericRead = FILE_GENERIC_READ;
mapping.GenericWrite = FILE_GENERIC_WRITE;
mapping.GenericExecute = FILE_GENERIC_EXECUTE;
mapping.GenericAll = FILE_ALL_ACCESS;
::MapGenericMask(&genericAccessRights, &mapping);
if (::AccessCheck(security, hImpersonatedToken, genericAccessRights,
&mapping, &privileges, &privilegesLength, &grantedAccess, &result))
{
bRet = (result == TRUE);
grantedRights = grantedAccess;
}
::CloseHandle(hImpersonatedToken);
}
::CloseHandle(hToken);
}
::free(security);
}
}
return bRet;
}
void printMasks(DWORD Mask)
{
// This evaluation of the ACCESS_MASK is an example.
// Applications should evaluate the ACCESS_MASK as necessary.
std::wcout << "Effective Allowed Access Mask : "<< Mask << std::hex << std::endl;
if (((Mask & GENERIC_ALL) == GENERIC_ALL)
|| ((Mask & FILE_ALL_ACCESS) == FILE_ALL_ACCESS))
{
wprintf_s(L"Full Control\n");
//return;
}
if (((Mask & GENERIC_READ) == GENERIC_READ)
|| ((Mask & FILE_GENERIC_READ) == FILE_GENERIC_READ))
wprintf_s(L"Read\n");
if (((Mask & GENERIC_WRITE) == GENERIC_WRITE)
|| ((Mask & FILE_GENERIC_WRITE) == FILE_GENERIC_WRITE))
wprintf_s(L"Write\n");
if (((Mask & GENERIC_EXECUTE) == GENERIC_EXECUTE)
|| ((Mask & FILE_GENERIC_EXECUTE) == FILE_GENERIC_EXECUTE))
wprintf_s(L"Execute\n");
}
DWORD AddAceToObjectsSecurityDescriptor(
LPTSTR pszObjName, // name of object
SE_OBJECT_TYPE ObjectType, // type of object
DWORD dwAccessRights, // access mask for new ACE
ACCESS_MODE AccessMode, // type of ACE
DWORD dwInheritance // inheritance flags for new ACE
)
{
DWORD dwRes = 0;
PACL pOldDACL = NULL, pNewDACL = NULL;
PSECURITY_DESCRIPTOR pSD = NULL;
EXPLICIT_ACCESS ea;
if (NULL == pszObjName)
return ERROR_INVALID_PARAMETER;
// Get a pointer to the existing DACL.
dwRes = GetNamedSecurityInfo(pszObjName, ObjectType,
DACL_SECURITY_INFORMATION,
NULL, NULL, &pOldDACL, NULL, &pSD);
if (ERROR_SUCCESS != dwRes) {
printf("GetNamedSecurityInfo Error %u\n", dwRes);
goto Cleanup;
}
// Initialize an EXPLICIT_ACCESS structure for the new ACE.
ZeroMemory(&ea, sizeof(EXPLICIT_ACCESS));
ea.grfAccessPermissions = dwAccessRights;
ea.grfAccessMode = AccessMode;
ea.grfInheritance = dwInheritance;
ea.Trustee.TrusteeForm = TRUSTEE_IS_NAME;
ea.Trustee.ptstrName = L"CURRENT_USER";
ea.Trustee.TrusteeType = TRUSTEE_IS_USER;
// Create a new ACL that merges the new ACE
// into the existing DACL.
dwRes = SetEntriesInAcl(1, &ea, pOldDACL, &pNewDACL);
if (ERROR_SUCCESS != dwRes) {
printf("SetEntriesInAcl Error %u\n", dwRes);
goto Cleanup;
}
// Attach the new ACL as the object's DACL.
dwRes = SetNamedSecurityInfo(pszObjName, ObjectType,
DACL_SECURITY_INFORMATION,
NULL, NULL, pNewDACL, NULL);
if (ERROR_SUCCESS != dwRes) {
printf("SetNamedSecurityInfo Error %u\n", dwRes);
goto Cleanup;
}
Cleanup:
if (pSD != NULL)
LocalFree((HLOCAL)pSD);
if (pNewDACL != NULL)
LocalFree((HLOCAL)pNewDACL);
return dwRes;
}
int main()
{
DWORD access_mask = FILE_GENERIC_READ | FILE_GENERIC_WRITE | FILE_GENERIC_EXECUTE | FILE_ALL_ACCESS;
DWORD grant = 0;
std::cout << "Before modification \n";
bool b = CanAccessFolder(L"C:\\Deny\\file.txt", access_mask, grant);
printMasks(grant);
std::cout << "After removing access \n";
DWORD dwres = AddAceToObjectsSecurityDescriptor(
L"C:\\Deny\\file.txt",
SE_FILE_OBJECT,
FILE_ALL_ACCESS,
DENY_ACCESS,
NO_INHERITANCE);
if (dwres == ERROR_SUCCESS)
{
grant = 0;
bool b = CanAccessFolder(L"C:\\Deny\\file.txt", access_mask, grant);
printMasks(grant);
}
else
{
std::cout << "Error : " << GetLastError() << '\n';
}
HANDLE hFile = CreateFileW(L"C:\\Deny\\file.txt", // file name
GENERIC_READ, // open for reading
0, // do not share
NULL, // default security
OPEN_EXISTING, // existing file only
FILE_ATTRIBUTE_NORMAL, // normal file
NULL); // no template
if (hFile == INVALID_HANDLE_VALUE)
{
std::cout << "CreateFileW1 Error : " << GetLastError() << '\n';
}
// ?????????????????????? GRANT ACCESS ?????????????????????????????????
std::cout << "After granting access \n";
DWORD dwres1 = AddAceToObjectsSecurityDescriptor(
L"C:\\Deny\\file.txt",
SE_FILE_OBJECT,
FILE_GENERIC_READ | FILE_GENERIC_WRITE,
GRANT_ACCESS,
NO_INHERITANCE);
if (dwres1 == ERROR_SUCCESS)
{
grant = 0;
bool b = CanAccessFolder(L"C:\\Deny\\file.txt", access_mask, grant);
printMasks(grant);
}
else
{
std::cout << "Error : " << GetLastError() << '\n';
}
HANDLE hFile1 = CreateFileW(L"C:\\Deny\\file.txt", // file name
GENERIC_READ, // open for reading
0, // do not share
NULL, // default security
OPEN_EXISTING, // existing file only
FILE_ATTRIBUTE_NORMAL, // normal file
NULL); // no template
if (hFile1 == INVALID_HANDLE_VALUE)
{
std::cout << "CreateFileW2 Error : " << GetLastError() << '\n';
}
return 0;
}
Before modification
Effective Allowed Access Mask : 2032127
Full Control
Read
Write
Execute
After removing access
Effective Allowed Access Mask : 0
CreateFileW1 Error : 5
After granting access
Effective Allowed Access Mask : 0
授予权限后,我可以访问文件“file.txt”,我可以打开/写入它(例如CreateFileW passes)
我不明白的是,许可文件背后的秘密,显示为
0
即使我已经批准了
FILE_GENERIC_READ | FILE_GENERIC_WRITE
致
CURRENT_USER
我还使用
icacls
它给了我以下的输出
C:\>icacls C:\Deny\file.txt
C:\Deny\file.txt DOMAIN\user:(DENY)(D,WDAC,WO,X,DC)
DOMAIN\user:(R,W)
NT AUTHORITY\Authenticated Users:(I)(F)
DOMAIN\user:(I)(F)
BUILTIN\Users:(I)(F)
BUILTIN\Administrators:(I)(F)
NT AUTHORITY\SYSTEM:(I)(F)
GRANT
权限ACE被推到
DENY
一个,这是一个
well documented behavior
这就是为什么我得到的标志值是
?
有没有任何方法/API/函数可以给我正确的标志,也就是说,它可以告诉我
FILE_GENERIC_READ
和
FILE_GENERIC_WRITE
准备好了吗?