Checking Access with Authz API

Applications determine whether to grant access to securable objects by calling the AuthzAccessCheck function.

The AuthzAccessCheck function takes both AUTHZ_ACCESS_REQUEST and SECURITY_DESCRIPTOR structures as parameters. The AUTHZ_ACCESS_REQUEST structure specifies a level of access requested. The AuthzAccessCheck function evaluates the requested access against the specified SECURITY_DESCRIPTOR for a specified client context. For information about how a security descriptor controls access to an object, see How DACLs Control Access to an Object.

Attribute variables must be in the form of an expression when used with logical operators; otherwise, they are evaluated as unknown.

Callback Function

If the discretionary access control list (DACL) of the SECURITY_DESCRIPTOR of the object to be checked contains any callback access control entries (ACEs), AuthzAccessCheck calls the AuthzAccessCheckCallback function for each callback ACE contained in the DACL. A callback ACE is any ACE structure whose ACE type contains the word "callback." The AuthzAccessCheckCallback function is an application-defined function that must be registered when the resource manager is initialized by calling the AuthzInitializeResourceManager function.

A callback function allows an application to define business logic to be evaluated at runtime. When the AuthzAccessCheckCallback function is called, the callback ACE that caused the call is passed to the callback function for evaluation. If the application-defined logic evaluates as TRUE, then the callback ACE is included in the access check. Otherwise, it is ignored.

Caching Access Results

The results of an access check can be cached and used in future calls to the AuthzCachedAccessCheck function. For more information about caching access checks, including an example, see Caching Access Checks.

Example

The following example creates a SECURITY_DESCRIPTOR that allows READ_CONTROL access to built-in administrators. It uses that security descriptor to check access for the client specified by the client context created in the example in Initializing a Client Context.

BOOL CheckAccess(AUTHZ_CLIENT_CONTEXT_HANDLE hClientContext)
{
    #define MY_MAX 4096


    PSECURITY_DESCRIPTOR    pSecurityDescriptor = NULL;
    ULONG                    cbSecurityDescriptorSize = 0;
    AUTHZ_ACCESS_REQUEST    Request;
    CHAR                    ReplyBuffer[MY_MAX];
    PAUTHZ_ACCESS_REPLY        pReply = (PAUTHZ_ACCESS_REPLY)ReplyBuffer;
    DWORD                    AuthzError =0;

    //Allocate memory for the access request structure.
    RtlZeroMemory(&Request, sizeof(AUTHZ_ACCESS_REQUEST));

    //Set up the access request structure.
    Request.DesiredAccess = READ_CONTROL;
    
    //Allocate memory for the access reply structure.
    RtlZeroMemory(ReplyBuffer, MY_MAX);

    //Set up the access reply structure.
    pReply->ResultListLength = 1;
    pReply->Error = (PDWORD) ((PCHAR) pReply + sizeof(AUTHZ_ACCESS_REPLY));
    pReply->GrantedAccessMask = (PACCESS_MASK) (pReply->Error + pReply->ResultListLength);
    pReply->SaclEvaluationResults = NULL;

    //Create security descriptor.
    if(!ConvertStringSecurityDescriptorToSecurityDescriptor(
        L"O:LAG:BAD:(A;;RC;;;BA)",
        SDDL_REVISION_1,
        &pSecurityDescriptor,
        NULL))
    {
        printf_s("ConvertStringSecurityDescriptorToSecurityDescriptor failed with %d\n", GetLastError()); 
        return FALSE;
    }

    //Call AuthzAccessCheck.
    if(!AuthzAccessCheck(
        0,
        hClientContext,
        &Request,
        NULL,
        pSecurityDescriptor,
        NULL,
        0,
        pReply,
        NULL))
    {
        printf_s("AuthzAccessCheck failed with %d\n", GetLastError());
        
    LocalFree(pSecurityDescriptor);
    
        return FALSE;
    }


    //Print results.
    if(*pReply->GrantedAccessMask & READ_CONTROL)
    {
        printf_s("Access granted.\n");
    }
    else
    {
        printf_s("Access denied.\n");
    }

  LocalFree(pSecurityDescriptor);
    return TRUE;

}

Adding SIDs to a Client Context

Caching Access Checks

Initializing a Client Context

Querying a Client Context