Partager via


4.11 RDS AAD Auth and CloudAP

The Cloud Authentication Provider (CloudAP) package provides several APIs that can help with an RDS AAD Auth protocol implementation on Windows operating systems. The ID of the CloudAP package can be obtained by calling LsaLookupAuthenticationPackage function. It can be used by calling the LsaCallAuthenticationPackage function.<51>

    #include <iostream>
    #include <Windows.h>
    #include <NTSecAPI.h>
    
    #define SECURITY_WIN32
    #include <security.h>
    
    using namespace std;
    
    #define STATUS_SUCCESS ((NTSTATUS) 0x00000000L) 
    #define STATUS_ACCOUNT_RESTRICTION ((NTSTATUS) 0xC000006EL) 
    
    #define CALLPKG_GENERIC (2)
    
    typedef struct _tagCloudAPGenericCallPkgInput 
    {
        ULONG ulMessageType; 
        GUID  ProviderGuid;
        ULONG ulInputSize;
        BYTE  abInput[ANYSIZE_ARRAY];
    } CAP_PKG_INPUT, *PCAP_PKG_INPUT;
    
    // {B16898C6-A148-4967-9171-64D755DA8520}
    static const GUID AadGlobalIdProviderGuid = 
    { 
        0xB16898C6,
        0xA148,
        0x4967,
        { 0x91, 0x71, 0x64, 0xD7, 0x55, 0xDA, 0x85, 0x20 }
    };
    
    //
    // Get the CloudAP Authentication Package ID.
    //
    ULONG 
    GetCloudApPackageId(
        HANDLE hLsa
        )
    {
        char szCloudAPName[] = "CloudAP";
        LSA_STRING cloudApPackageName = 
        { 
            (USHORT)(sizeof(szCloudAPName) - sizeof(char)), 
            (USHORT)(sizeof(szCloudAPName)), 
            szCloudAPName 
        };
        ULONG cloudApPackageId;
    
        NTSTATUS status = LsaLookupAuthenticationPackage(
            hLsa, 
            &cloudApPackageName, 
            &cloudApPackageId
            );
    
        if (status != STATUS_SUCCESS) 
        {
            throw runtime_error("LsaLookupAuthenticationPackage failed");
        }
    }
    
    //
    // Call the CloudAP Authentication Package.
    //
    string 
    CallCloudAP(
        HANDLE hLsa, 
        ULONG cloudApPackageId, 
        const string& requestJson
        )
    {
        HRESULT hr = E_NOTIMPL;
        NTSTATUS status;
        NTSTATUS subStatus;
    
        PCAP_PKG_INPUT pCloudApRequest = nullptr;
        DWORD cbCloudApRequest = 0;
        char* pCloudApResponse = nullptr;
        DWORD cbCloudApResponse = 0;
    
        cbCloudApRequest = (DWORD) (
            sizeof(CAP_PKG_INPUT) - 
            ANYSIZE_ARRAY + 
            requestJson.length()
            );
        pCloudApRequest = (PCAP_PKG_INPUT)(new BYTE[cbCloudApRequest]);
    
        pCloudApRequest->ulMessageType = CALLPKG_GENERIC;
        pCloudApRequest->ProviderGuid = AadGlobalIdProviderGuid;
        pCloudApRequest->ulInputSize = (ULONG) requestJson.length();
    
        memcpy(
            pCloudApRequest->abInput, 
            requestJson.data(), 
            requestJson.length()
            );
    
        try
        {
            status = LsaCallAuthenticationPackage(
                hLsa,
                cloudApPackageId,
                pCloudApRequest,
                cbCloudApRequest,
                (PVOID*) &pCloudApResponse,
                &cbCloudApResponse,
                &subStatus
                );
    
            if (status != STATUS_SUCCESS) 
            {
                throw runtime_error("LsaCallAuthenticationPackage failed");
            }
            if (subStatus != STATUS_SUCCESS) 
            {
                throw runtime_error("LsaCallAuthenticationPackage failed");
            }
    
            if (pCloudApResponse != nullptr)
            {
                string response(pCloudApResponse, cbCloudApResponse);
                LsaFreeReturnBuffer((PVOID)pCloudApResponse);
                delete [] pCloudApRequest;
                return response;
            }
            else
            {
                return "";
            }
        }
        catch (...)
        {
            delete[] pCloudApRequest;
            throw;
        }
 }