Processing of ACEs inside AuthzAccessCheckCallback function

Yury Strozhevsky 116 Reputation points
2021-12-07T06:36:39.037+00:00

Hello!

So, initially I had this question. But after finding an answer on initial question (thank you very much, Jeff McCashland) I found two more.

  1. When I have ACCESS_DENIED_CALLBACK_OBJECT_ACE in my ACL I do have a call to AuthzAccessCheckCallback function. But when I have ACCESS_ALLOWED_CALLBACK_OBJECT_ACE no calls to AuthzAccessCheckCallback. Is it as intended to be? But in this link it is clearly stated that such call should exists
  2. It is possible to run AuthzAccessCheck without AuthzAccessCheckCallback in resource? I did assume that with AuthzAccessCheck = NULL the AuthzAccessCheck function would be equal with AccessCheckByTypeResultListAndAuditAlarmByHandle function. But when I make completely same GUID tree with same ACL (just replaced all ACEs like _OBJECT_ACE to _CALLBACK_OBJECT_ACE and put there additional simple condition which is always true) I had completely different result.

I do hope to find related specialists with knowledge in this very specific area on this forum :)

Best regards,
Yury Strozhevsky

Windows API - Win32
Windows API - Win32
A core set of Windows application programming interfaces (APIs) for desktop and server applications. Previously known as Win32 API.
2,585 questions
Windows 10 Security
Windows 10 Security
Windows 10: A Microsoft operating system that runs on personal computers and tablets.Security: The precautions taken to guard against crime, attack, sabotage, espionage, or another threat.
2,887 questions
Windows Server Security
Windows Server Security
Windows Server: A family of Microsoft server operating systems that support enterprise-level management, data storage, applications, and communications.Security: The precautions taken to guard against crime, attack, sabotage, espionage, or another threat.
1,807 questions
{count} votes

1 answer

Sort by: Most helpful
  1. Jeanine Zhang-MSFT 9,661 Reputation points Microsoft Vendor
    2022-02-09T02:13:58.557+00:00

    Hi,

    Welcome to Microsoft Q&A!

    When I have ACCESS_DENIED_CALLBACK_OBJECT_ACE in my ACL I do have a call to AuthzAccessCheckCallback function. But when I have ACCESS_ALLOWED_CALLBACK_OBJECT_ACE no calls to AuthzAccessCheckCallback. Is it as intended to be? But in this link it is clearly stated that such call should exists

    This is not true. I was able to modify the sample. You could refer to the following code:

    /*++  
      
    THIS CODE AND INFORMATION IS PROVIDED "AS IS" WITHOUT WARRANTY OF  
    ANY KIND, EITHER EXPRESSED OR IMPLIED, INCLUDING BUT NOT LIMITED  
    TO THE IMPLIED WARRANTIES OF MERCHANTABILITY AND/OR FITNESS FOR A  
    PARTICULAR PURPOSE.  
      
    Copyright (C) 2022 Microsoft Corporation.  All rights reserved.  
      
    --*/  
      
    #define SECURITY_WIN32  
      
    #include<windows.h>  
    #include<security.h>  
    #include<lmcons.h>  
    #include<authz.h>  
    #include<stdio.h>  
      
    #define READ_BUFFER_SIZE 512  
      
    #define FirstAce(Acl) ((PVOID)((PUCHAR)(Acl) + sizeof(ACL)))  
      
    //  
    // The callback routines used with AuthZ  
    //  
      
    BOOL  
    WINAPI  
    AuthzAccessCheckCallback(  
        IN AUTHZ_CLIENT_CONTEXT_HANDLE hAuthzClientContext,  
        IN PACE_HEADER pAce,  
        IN PVOID pArgs OPTIONAL,  
        IN OUT PBOOL pbAceApplicable  
    )  
    {  
        wprintf(L"AuthzAccessCheckCallback called\n");  
      
        return TRUE;  
    }  
      
    //  
    // Personal expenditures  
    //  
    #define ACCESS_FUND_PERSONAL   0x00000001  
      
      
    //  
    // Company spending  
    //  
    #define ACCESS_FUND_CORPORATE  0x00000002  
      
      
    //  
    // Transfer to other funds  
    //  
    #define ACCESS_FUND_TRANSFER   0x00000004  
      
      
    int main(void)  
    {  
        AUTHZ_RESOURCE_MANAGER_HANDLE hAuthzResourceManager;  
        PACL pDaclFund = NULL;  
      
        if (!AuthzInitializeResourceManager(  
            AUTHZ_RM_FLAG_NO_AUDIT,    // no flags          
            AuthzAccessCheckCallback,  
            NULL,  
            NULL,  
            L"SampRM", // no auditing  
            &hAuthzResourceManager))  
        {  
            wprintf(L"AuthzInitializeResourceManager failed with %u\n", GetLastError());  
            return 0;  
        }  
        else  
            wprintf(L"AuthzInitializeResourceManager SUCCESS\n");  
      
        SECURITY_DESCRIPTOR sd = { 0 };  
      
        PSID psidEveryone = NULL;  
        SID_IDENTIFIER_AUTHORITY siaWorld = SECURITY_WORLD_SID_AUTHORITY;  
          
      
        if (!InitializeSecurityDescriptor(&sd, SECURITY_DESCRIPTOR_REVISION))  
        {  
            wprintf(L"InitializeSecurityDescriptor failed with %u\n", GetLastError());  
            return 0;  
        }  
      
        if (!SetSecurityDescriptorGroup(&sd, NULL, FALSE))  
        {  
            wprintf(L"SetSecurityDescriptorGroup failed with %u\n", GetLastError());  
            return 0;  
        }  
      
        if (!SetSecurityDescriptorSacl(&sd, FALSE, NULL, FALSE))  
        {  
            wprintf(L"SetSecurityDescriptorSacl failed with %u\n", GetLastError());  
            return 0;  
        }  
      
        DWORD VPSidBuf[] = { 0x00000501, 0x05000000, 0x00000015, 0x17b85159, 0x255d7266, 0x0b3b6364, 0x00010001 };  
        DWORD ManagerSidBuf[] = { 0x00000501, 0x05000000, 0x00000015, 0x17b85159, 0x255d7266, 0x0b3b6364, 0x00010002 };  
        DWORD EmployeeSidBuf[] = { 0x00000501, 0x05000000, 0x00000015, 0x17b85159, 0x255d7266, 0x0b3b6364, 0x00010003 };  
      
        PSID VPSid = (PSID)VPSidBuf;  
        PSID ManagerSid = (PSID)ManagerSidBuf;  
        PSID EmployeeSid = (PSID)EmployeeSidBuf;  
      
        // an owner must be specified.  Since VPs are the highest privileged group  
        // this sample we'll make them the owner.  
        if (!SetSecurityDescriptorOwner(&sd, VPSid, FALSE))  
        {  
            wprintf(L"SetSecurityDescriptorOwnerfailed with %u\n", GetLastError());  
            return 0;  
        }  
      
        //  
       // Initialize the DACL for the fund  
       //  
        pDaclFund = (PACL)malloc(1024);  
        InitializeAcl(pDaclFund, 1024, ACL_REVISION_DS);  
      
        //  
        // Add an access-allowed ACE for Everyone  
        // Only company spending and transfers are allowed for this fund  
        //  
      
        // build EVERYONE SID  
        if (!AllocateAndInitializeSid(  
            &siaWorld, 1, SECURITY_WORLD_RID,  
            0, 0, 0, 0, 0, 0, 0,  
            &psidEveryone  
        ))  
        {  
            wprintf(L"AllocateAndInitializeSid with %u\n", GetLastError());  
            return 0;  
        }  
      
        if (!AddAccessAllowedAce(pDaclFund,  
            ACL_REVISION_DS,  
            ACCESS_FUND_CORPORATE | ACCESS_FUND_TRANSFER,  
            psidEveryone))  
        {  
            wprintf(L"AddAccessAllowedAce with %u\n", GetLastError());  
            return 0;  
        }  
      
        //  
        // Now set that ACE to a callback ACE  
        //  
      
        ((PACE_HEADER)FirstAce(pDaclFund))->AceType =  
            ACCESS_ALLOWED_CALLBACK_ACE_TYPE;  
      
        //  
        // Add that ACL as the security descriptor's DACL  
        //  
      
        if (!SetSecurityDescriptorDacl(&sd, TRUE, pDaclFund, FALSE))  
        {  
            wprintf(L"SetSecurityDescriptorDacl with %u\n", GetLastError());  
            return 0;  
        }  
      
        AUTHZ_CLIENT_CONTEXT_HANDLE AuthzClient;  
        LUID     luid = { 0x0,0x0 };  
      
        HANDLE hToken = NULL;  
      
        if (!OpenProcessToken(GetCurrentProcess(), TOKEN_QUERY, &hToken))  
        {  
            wprintf(L"OpenProcessToken failed with %u\n", GetLastError());  
            return 0;  
        }  
        else  
            wprintf(L"OpenProcessToken SUCCESS\n");  
      
        // access check  
        if (!AuthzInitializeContextFromToken(  
            0,  
            hToken,  
            hAuthzResourceManager,  
            NULL,  
            luid,  
            NULL,  
            &AuthzClient))   
        {  
            wprintf(L"AuthzInitializeContextFromToken failed with %u\n", GetLastError());  
            return 0;  
        }  
      
        AUTHZ_ACCESS_REQUEST AccessRequest = { 0 };  
        AUTHZ_ACCESS_REPLY AccessReply = { 0 };  
        BYTE     Buffer[1024];  
      
        AccessRequest.DesiredAccess = ACCESS_FUND_PERSONAL | ACCESS_FUND_CORPORATE | ACCESS_FUND_TRANSFER;  
        AccessRequest.PrincipalSelfSid = NULL;  
        AccessRequest.ObjectTypeList = NULL;  
        AccessRequest.ObjectTypeListLength = 0;  
        AccessRequest.OptionalArguments = NULL;  
      
        RtlZeroMemory(Buffer, sizeof(Buffer));  
        AccessReply.ResultListLength = 1;  
        AccessReply.GrantedAccessMask = (PACCESS_MASK)(Buffer);  
        AccessReply.Error = (PDWORD)(Buffer + sizeof(ACCESS_MASK));  
      
        if (!AuthzAccessCheck(0,  
            AuthzClient,  
            &AccessRequest,  
            NULL,  
            &sd,  
            NULL,  
            0,  
            &AccessReply,  
            NULL))   
        {  
            wprintf(L"AuthzAccessCheck failed with %u\n", GetLastError());  
            return 0;  
        }  
      
        wprintf(L"GRANTED ACCESS MASK: 0x%X\n", *AccessReply.GrantedAccessMask);  
      
        AuthzFreeContext(AuthzClient);  
      
        if (!AuthzFreeResourceManager(hAuthzResourceManager))  
        {  
            wprintf(L"AuthzFreeResourceManager failed with %u\n", GetLastError());  
            return 0;  
        }  
        else  
            wprintf(L"AuthzFreeResourceManager SUCCESS\n");  
      
        FreeSid(psidEveryone);  
    }  
      
    

    to demonstrate that no ACCESS_DENIED_CALLBACK_OBJECT_ACE is required in order for ACCESS_ALLOWED_CALLBACK_OBJECT_ACE to trigger AuthzAccessCheckCallback().

    It is possible to run AuthzAccessCheck without AuthzAccessCheckCallback in resource?

    Yes, you do not need a callback to call AuthzAccessCheck().

    I suggest you could review the code and if you have further questions, I would suggest you could create an incident with Microsoft for further research.

    Best Regards,

    Jeanine


    If the answer is the right solution, please click "Accept Answer" and kindly upvote it. If you have extra questions about this answer, please click "Comment".

    Note: Please follow the steps in our documentation to enable e-mail notifications if you want to receive the related email notification for this thread.


Your answer

Answers can be marked as Accepted Answers by the question author, which helps users to know the answer solved the author's problem.