cwinapiwindows-security

Checking the existence of ACE in windows object DACL


is there a way to check if an ACE already exists in the DACL of an object?

I want to use the RtlAddAccessAllowedAce API call to add an ACE to an object, but I want to do that only if the ACE doesn't exist already.

Does someone know how can I either check if the ACE already exist, or to try to remove the given ACE before adding it, or any other solution which will achieve the same goal? Thanks!


Solution

  • you can or use winapi or direct walk by ACL ACEs - enumerate ACE one by one and check are some specific ACE exist:

    variant 1:

    void WalkAcl(PACL acl)
    {
        ACL_SIZE_INFORMATION asi;
        if (GetAclInformation(acl, &asi, sizeof(asi), AclSizeInformation))
        {
            if (asi.AceCount)
            {
                do 
                {
                    union {
                        PVOID pvAce;
                        PACE_HEADER pAceHeader;
                        PACCESS_ALLOWED_ACE pAllowedAce;
                    };
    
                    PWSTR szSid;
                    if (GetAce(acl, --asi.AceCount, &pvAce))
                    {
                        switch (pAceHeader->AceType)
                        {
                        case ACCESS_ALLOWED_ACE_TYPE:
                            if (ConvertSidToStringSid(&pAllowedAce->SidStart, &szSid))
                            {
                                DbgPrint("%08x %S\n", pAllowedAce->Mask, szSid);
                                LocalFree(szSid);
                            }
                            break;
                        }
                    }
    
                } while (asi.AceCount);
            }
        }
    }
    

    variant 2:

    void WalkAcl(PACL acl)
    {
        if (USHORT AceCount = acl->AceCount)
        {
            union {
                PVOID pv;
                PBYTE pb;
                PACE_HEADER pAceHeader;
                PACCESS_ALLOWED_ACE pAllowedAce;
            };
    
            pv = acl + 1;
    
            do 
            {
                UNICODE_STRING usSid;
                switch (pAceHeader->AceType)
                {
                case ACCESS_ALLOWED_ACE_TYPE:
                    if (0 <= RtlConvertSidToUnicodeString(&usSid, &pAllowedAce->SidStart, TRUE))
                    {
                        DbgPrint("%08x %wZ\n", pAllowedAce->Mask, usSid);
                        RtlFreeUnicodeString(&usSid);
                    }
                    break;
                }
    
            } while (pb += pAceHeader->AceSize, --AceCount);
        }
    }