代码之家  ›  专栏  ›  技术社区  ›  Recker

Windows DACL权限

  •  1
  • Recker  · 技术社区  · 5 年前

    我正在尝试使用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 准备好了吗?

    0 回复  |  直到 5 年前