最新消息:雨落星辰是一个专注网站SEO优化、网站SEO诊断、搜索引擎研究、网络营销推广、网站策划运营及站长类的自媒体原创博客

c++ - Remove entry from file's DACL - Stack Overflow

programmeradmin1浏览0评论

I have a function that can deny FILE_EXECUTE right in the file's DACL. To deny FILE_EXECUTE right, I call the function like this (see full code in the main function):

AddAceToObjectsSecurityDescriptor(objectName, SE_FILE_OBJECT, (PWSTR)pSid, TRUSTEE_IS_SID, FILE_EXECUTE, DENY_ACCESS, NO_INHERITANCE);

After I deny the FILE_EXECUTE permission, I want to undo that operation. In other words, I want to remove from the DACL the entry that FILE_EXECUTE was denied.

What is the correct way to do this?

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 <stdio.h>

#include <iostream>

DWORD AddAceToObjectsSecurityDescriptor(
    LPTSTR pszObjName,          // name of object
    SE_OBJECT_TYPE ObjectType,  // type of object
    LPTSTR pszTrustee,          // trustee for new ACE
    TRUSTEE_FORM TrusteeForm,   // format of trustee structure
    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 = TrusteeForm;
    ea.Trustee.ptstrName = pszTrustee;

    // 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;
}

#include <sddl.h>

int main()
{
    wchar_t objectName[] = L"C:\\Users\\Username\\Desktop\\acl.txt";

    wchar_t trusteeSID[] = L"S-1-5-21-#-#-#-#";
    PSID pSid;
    if (!ConvertStringSidToSid(trusteeSID, &pSid)) {
        std::cout << "ConvertStringSidToSid failed\n";
        return 0;
    }

    AddAceToObjectsSecurityDescriptor(objectName, SE_FILE_OBJECT, (PWSTR)pSid, TRUSTEE_IS_SID, FILE_EXECUTE, DENY_ACCESS, NO_INHERITANCE);
}

I have a function that can deny FILE_EXECUTE right in the file's DACL. To deny FILE_EXECUTE right, I call the function like this (see full code in the main function):

AddAceToObjectsSecurityDescriptor(objectName, SE_FILE_OBJECT, (PWSTR)pSid, TRUSTEE_IS_SID, FILE_EXECUTE, DENY_ACCESS, NO_INHERITANCE);

After I deny the FILE_EXECUTE permission, I want to undo that operation. In other words, I want to remove from the DACL the entry that FILE_EXECUTE was denied.

What is the correct way to do this?

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 <stdio.h>

#include <iostream>

DWORD AddAceToObjectsSecurityDescriptor(
    LPTSTR pszObjName,          // name of object
    SE_OBJECT_TYPE ObjectType,  // type of object
    LPTSTR pszTrustee,          // trustee for new ACE
    TRUSTEE_FORM TrusteeForm,   // format of trustee structure
    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 = TrusteeForm;
    ea.Trustee.ptstrName = pszTrustee;

    // 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;
}

#include <sddl.h>

int main()
{
    wchar_t objectName[] = L"C:\\Users\\Username\\Desktop\\acl.txt";

    wchar_t trusteeSID[] = L"S-1-5-21-#-#-#-#";
    PSID pSid;
    if (!ConvertStringSidToSid(trusteeSID, &pSid)) {
        std::cout << "ConvertStringSidToSid failed\n";
        return 0;
    }

    AddAceToObjectsSecurityDescriptor(objectName, SE_FILE_OBJECT, (PWSTR)pSid, TRUSTEE_IS_SID, FILE_EXECUTE, DENY_ACCESS, NO_INHERITANCE);
}
Share Improve this question asked Mar 3 at 17:44 Joe JJoe J 4839 bronze badges 1
  • direct remove ace entry from acl – RbMm Commented Mar 3 at 19:40
Add a comment  | 

1 Answer 1

Reset to default 1

really only way here manual parse ACL and remove some ACE. as example such function add/remove ACCESS_DENIED_ACE with concrete SID and FILE_EXECUTE access

extern volatile const UCHAR guz = 0;

ULONG AddRemoveAce(PCWSTR lpFileName, PSID Sid, BOOL bSet)
{
    UNICODE_STRING ObjectName;
    NTSTATUS status = RtlDosPathNameToNtPathName_U_WithStatus(lpFileName, &ObjectName, 0, 0);
    if (0 <= status)
    {
        HANDLE hFile;
        OBJECT_ATTRIBUTES oa = { sizeof(oa), 0, &ObjectName };

        IO_STATUS_BLOCK iosb;
        status = NtOpenFile(&hFile, READ_CONTROL|WRITE_DAC, &oa, &iosb, 0, FILE_OPEN_REPARSE_POINT);
        RtlFreeUnicodeString(&ObjectName);

        if (0 <= status)
        {
            PVOID stack = alloca(guz);

            ULONG cb = 0, rcb = 0x100;

            PSECURITY_DESCRIPTOR SecurityDescriptor = 0;

            do 
            {
                if (cb < rcb)
                {
                    cb = RtlPointerToOffset(SecurityDescriptor = alloca(rcb - cb), stack);
                }

                status = NtQuerySecurityObject(hFile, DACL_SECURITY_INFORMATION, SecurityDescriptor, cb, &rcb);

            } while (STATUS_BUFFER_TOO_SMALL == status);

            PACL Dacl;

            BOOLEAN bPresent, bDefault;

            if (0 <= status && 0 <= (status = RtlGetDaclSecurityDescriptor(SecurityDescriptor, &bPresent, &Dacl, &bDefault)))
            {
                if (bPresent && Dacl)
                {
                    SECURITY_DESCRIPTOR sd = {
                        SECURITY_DESCRIPTOR_REVISION, 0, SE_DACL_PRESENT
                    };

                    if (bSet)
                    {
                        EXPLICIT_ACCESS ea = { 
                            FILE_EXECUTE, 
                            DENY_ACCESS, 
                            NO_INHERITANCE, 
                            {0, NO_MULTIPLE_TRUSTEE, TRUSTEE_IS_SID, TRUSTEE_IS_UNKNOWN, (PWSTR)Sid } 
                        };

                        bPresent = (NOERROR == (status = SetEntriesInAcl(1, &ea, Dacl, &sd.Dacl)));

                        SecurityDescriptor = &sd;
                    }
                    else
                    {
                        if (ULONG AceCount = Dacl->AceCount)
                        {
                            bPresent = FALSE;

                            union {
                                PACE_HEADER pah;
                                PVOID pv;
                                PACCESS_DENIED_ACE pada;
                                ULONG_PTR up;
                            };

                            pv = Dacl + 1;

                            union {
                                PACE_HEADER pah_new;
                                ULONG_PTR up_new;
                            };

                            pah_new = pah;

                            do 
                            {
                                USHORT AceSize = pah->AceSize;

                                if (ACCESS_DENIED_ACE_TYPE == pah->AceType &&
                                    FILE_EXECUTE == pada->Mask &&
                                    RtlEqualSid(&pada->SidStart, Sid))
                                {
                                    Dacl->AceCount--;
                                    Dacl->AclSize -= AceSize;
                                    bPresent = TRUE;
                                }
                                else
                                {
                                    if (pah_new != pah)
                                    {
                                        memcpy(pah_new, pah, AceSize);
                                        up_new += AceSize;
                                    }
                                }

                                up += AceSize;

                            } while (--AceCount);
                        }
                    }

                    if (bPresent)
                    {
                        status = NtSetSecurityObject(hFile, DACL_SECURITY_INFORMATION, SecurityDescriptor);
                    }

                    if (sd.Dacl)
                    {
                        LocalFree(sd.Dacl);
                    }
                }
            }

            NtClose(hFile);
        }
    }

    return status;
}
发布评论

评论列表(0)

  1. 暂无评论