c++ - Effect of FILE_READ_ATTRIBUTES and FILE_READ_EA attributes on a file - Stack Overflow

admin2025-04-20  0

  1. MSDN defines FILE_READ_ATTRIBUTES as "The right to read file attributes."

  2. MSDN defines FILE_READ_EA as "The right to read extended file attributes."

As far as I understand, if these rights are missing, we lose access to file attributes. However, if I take these rights away from a file, GetFileAttributes continues to return file attributes.

So what does the absence of FILE_READ_ATTRIBUTES and FILE_READ_EA affect?

To run my code, set the variable trusteeSID to the correct value and the variable objectName to the correct path to the file

#include <aclapi.h>
#include <windows.h>
#include <sddl.h>
#include <wil/resource.h>
#include <securitybaseapi.h>
#include <map>
#include <iostream>

DWORD GetSecurityDescriptor(HANDLE handle, std::unique_ptr<BYTE[]>& pSD)
{
    DWORD dwSDLen;
    std::unique_ptr<BYTE[]> buffer;

    if (GetKernelObjectSecurity(handle, DACL_SECURITY_INFORMATION, NULL, 0, &dwSDLen) == 0)
    {
        DWORD err = GetLastError();

        if (err == ERROR_INSUFFICIENT_BUFFER)
        {
            buffer.reset(new(std::nothrow) BYTE[dwSDLen]);

            if (!buffer)
            {
                return ERROR_NOT_ENOUGH_MEMORY;
            }

            if (GetKernelObjectSecurity(handle, DACL_SECURITY_INFORMATION, buffer.get(), dwSDLen, &dwSDLen) == 0)
            {
                return GetLastError();
            }

            pSD = std::move(buffer);
        }
        else
        {
            return err;
        }
    }

    return ERROR_SUCCESS;
}

DWORD ToAbsoluteSD(const std::unique_ptr<BYTE[]>& selfRelativeSD, std::unique_ptr<BYTE[]>& absoluteSD)
{
    DWORD absSDSize = 0;
    DWORD dwDaclSize = 0;
    DWORD dwSaclSize = 0;
    DWORD dwOwnerSize = 0;
    DWORD dwPrimaryGroupSize = 0;
    
    DWORD result = MakeAbsoluteSD(selfRelativeSD.get(), NULL, &absSDSize, 
        NULL, &dwDaclSize, 
        NULL, &dwSaclSize, 
        NULL, &dwOwnerSize, 
        NULL, &dwPrimaryGroupSize);

    if (result != 0)
    {
        return ERROR_INSUFFICIENT_BUFFER;
    }

    DWORD err = GetLastError();

    if (err == ERROR_INSUFFICIENT_BUFFER)
    {
        std::unique_ptr<BYTE[]> absSD(new(std::nothrow) BYTE[absSDSize]);
        std::unique_ptr<BYTE[]> dacl(new(std::nothrow) BYTE[dwDaclSize]);
        std::unique_ptr<BYTE[]> sacl(new(std::nothrow) BYTE[dwSaclSize]);
        std::unique_ptr<BYTE[]> owner(new(std::nothrow) BYTE[dwOwnerSize]);
        std::unique_ptr<BYTE[]> primaryGroup(new(std::nothrow) BYTE[dwPrimaryGroupSize]);

        if (!absSD || !dacl || !sacl || !owner || !primaryGroup)
        {
            return ERROR_NOT_ENOUGH_MEMORY;
        }
            
        result = MakeAbsoluteSD(selfRelativeSD.get(), absSD.get(), &absSDSize, 
            (PACL)dacl.get(), &dwDaclSize, 
            (PACL)sacl.get(), &dwSaclSize,
            (PSID)owner.get(), &dwOwnerSize,
            (PSID)primaryGroup.get(), &dwPrimaryGroupSize);

        if (result == 0)
        {
            return GetLastError();
        }

        absoluteSD = std::move(absSD);
    }
    else
    {
        return err;
    }

    return ERROR_SUCCESS;
}

DWORD SetPermissions(const std::wstring& fileName, PSID pSID, bool allowed, ACCESS_MASK accessRights, bool set)
{
    if (fileName.size() == 0)
    {
        return ERROR_INVALID_PARAMETER;
    }

    if (!pSID)
    {
        return ERROR_INVALID_PARAMETER;
    }

    wil::unique_handle hFile(CreateFile(fileName.c_str(), READ_CONTROL | WRITE_DAC, 0, NULL, OPEN_EXISTING, FILE_FLAG_BACKUP_SEMANTICS, NULL));
    if (!hFile)
    {
        return GetLastError();
    }

    std::unique_ptr<BYTE[]> pSD;
    DWORD result = GetSecurityDescriptor(hFile.get(), pSD);
    if (result != ERROR_SUCCESS)
    {
        return result;
    }

    PACL dacl = nullptr;
    BOOL present;
    BOOL defaulted;

    if (GetSecurityDescriptorDacl(pSD.get(), &present, &dacl, &defaulted) == 0)
    {
        return GetLastError();
    }

    if (!present)
    {
        return ERROR_NOT_SUPPORTED;
    }

    bool aceType = allowed ? ACCESS_ALLOWED_ACE_TYPE : ACCESS_DENIED_ACE_TYPE;

    // if DACL present and not NULL
    if (dacl)
    {
        for (WORD i = 0; i < dacl->AceCount; i++)
        {
            PACE_HEADER header;
            if (GetAce(dacl, i, (PVOID*)&header) != 0)
            {
                if (header->AceType == aceType)
                {
                    auto ace = (ACCESS_ALLOWED_ACE*)header; // have the same binary layout as ACCESS_DENIED_ACE
                    if (EqualSid((PSID)&ace->SidStart, pSID) != 0)
                    {
                        set ? ace->Mask |= accessRights : ace->Mask &= ~accessRights;
                        if (SetKernelObjectSecurity(hFile.get(), DACL_SECURITY_INFORMATION, pSD.get()) == 0)
                        {
                            return GetLastError();
                        }

                        return ERROR_SUCCESS;
                    }
                }
            }
        }
    }

    EXPLICIT_ACCESS ea;
    PACL pNewDACL = NULL;

    // Initialize an EXPLICIT_ACCESS structure for the new ACE. 
    ZeroMemory(&ea, sizeof(EXPLICIT_ACCESS));
    ea.grfAccessPermissions = accessRights;
    ea.grfAccessMode = allowed ? SET_ACCESS : DENY_ACCESS;
    ea.grfInheritance = NO_INHERITANCE;
    ea.Trustee.TrusteeForm = TRUSTEE_IS_SID;
    ea.Trustee.ptstrName = (PWSTR)pSID;

    result = SetEntriesInAcl(1, &ea, dacl, &pNewDACL);
    if (result != ERROR_SUCCESS) {
        return result;
    }

    std::unique_ptr<BYTE[]> absoluteSD;
    result = ToAbsoluteSD(pSD, absoluteSD);
    if (result != ERROR_SUCCESS)
    {
        return result;
    }

    if (SetSecurityDescriptorDacl(absoluteSD.get(), TRUE, pNewDACL, FALSE) == 0)
    {
        return GetLastError();
    }

    if (SetKernelObjectSecurity(hFile.get(), DACL_SECURITY_INFORMATION, absoluteSD.get()) == 0)
    {
        return GetLastError();
    }

    return ERROR_SUCCESS;
}

int main()
{
    wchar_t trusteeSID[] = L"S-1-5-21-#-#-#-#";
    PSID pSid;
    if (!ConvertStringSidToSid(trusteeSID, &pSid)) {
        std::cout << "ConvertStringSidToSid failed\n";
        return 0;
    }
    wchar_t objectName[] = L"C:\\Users\\Username\\Desktop\\acl.txt";
    // deny FILE_READ_ATTRIBUTES  and FILE_READ_EA
    std::cout << "Res: " << SetPermissions(objectName, pSid, false, FILE_READ_ATTRIBUTES | FILE_READ_EA, true) << std::endl;
    // check file attributes
    std::cout << "Is valid attributes: " << (GetFileAttributes(objectName) != INVALID_FILE_ATTRIBUTES) << std::endl;

    LocalFree(pSid);
}
转载请注明原文地址:http://conceptsofalgorithm.com/Algorithm/1745123026a286260.html

最新回复(0)