共用方式為


範例 SHV

注意

從 Windows 10 開始,無法使用網路存取保護平臺

 

下列範例會在 NAP 健康情況原則伺服器上設定系統健康情況驗證程式 (SHV) 。

注意

NAP SDK 也包含一組完整的範例程式碼,可在 ...\Samples\NetDS\NAP 中找到...SDK 安裝的目錄。 此範例集包含和系統健康情況代理程式 (SHA) 、SHV 和強制執行用戶端 (EC) 。 它具有完整的 NAP 案例,可設定 SHA-SHV 與 SHA-EC 之間的通訊。

 

#include <windows.h>
#include "stdafx.h"
#include "NapUtil.h"
#include "NapTypes.h"
#include "NapProtocol.h"
#include "NapMicrosoftVendorIds.h"
#include "NapSystemHealthValidator.h"
#include "NapError.h"

STDMETHODIMP CSampleShv::Validate(
    /*[in]*/ INapSystemHealthValidationRequest* pShvRequest,
    /*[in]*/ UINT32 hintTimeOutInMsec,
    /*[in]*/ INapServerCallback* pCallback)

{
    HRESULT hr = S_OK;

    //
    // SDK Note:
    //
    // If a SoH validation code determines that it needs to contact an external 
    // server to assist with validation, it must start a separate helper thread
    // to contact the server, and return E_PENDING in this thread. When that 
    // occurs, this thread must exit to the SHV Host, returning the E_PENDING 
    // result; the helper thread should independently determine the final 
    // validation result, generate the response SoH, and call the SHV Host's 
    // Callback interface.
    //
    // This SHV handles the Validate() call asynchronously. Validate() method 
    // return with hr = E_PENDING and does the processing of SoH request and 
    // generating SoHResponse in a separate thread.

    //
    // SDK Note:
    //
    // If a SHV does not require processing in a separate thread but can return 
    // the response immediately, it should call the function QShvRespondSHVHost() 
    // below.

    // Store the callback and request pointers.
    m_pShvRequest = pShvRequest;
    m_callback = pCallback;

    //
    // SDK Note:
    //
    // Creating a separate helper thread is done whenever a SHV must contact 
    // the external server. Therefore, the following code that creates a thread 
    // should be executed whenever the need arises.
    //
    // Here we assume the SHV will always contact an external server. Therefore,
    // create the thread at the very start and do all the processing in the helper
    // thread.
    
    // Create Thread to process the SoHRequest and reply with SoHResponse.
    hr = QShvCreateThread();

    // AddRef the request and callback pointers.
    pShvRequest->AddRef();
    pCallback->AddRef();

    return hr;
}

// Creates a thread for asynchronous handling of the Validate() call.
HRESULT CSampleShv::QShvCreateThread()
{
    HRESULT hr = S_OK;
    threadHandle = NULL;
    DWORD threadId = 0;

    // Windows API to create a thread.
    threadHandle = (HANDLE) CreateThread( NULL, 0, AsyncThreadHandler, (LPVOID) this, 
                                          0, &threadId );
    //
    // SDK Note:
    //
    // Here we assume the thread was created successfully and respond with status =       
    // E_PENDING to the SHV Host. 
    hr = E_PENDING;
    return hr;
}

// This is the thread handler. The input parameter is the pointer to this object.
DWORD CSampleShv::AsyncThreadHandler(LPVOID lpParameter)
{
    DWORD errCode = ERROR_SUCCESS;
    errCode = reinterpret_cast<CSampleShv *>(lpParameter)->AsyncThreadHandlerMain(); 
    return errCode;
}

// The thread handler calls this method that has access to member variables.
DWORD __stdcall CSampleShv::AsyncThreadHandlerMain()
{
    DWORD errCode = ERROR_SUCCESS;
    HRESULT hr = S_OK;
    hr = QShvRespondSHVHost();
    CloseHandle(threadHandle);
    errCode = HRESULT_CODE(hr);
    return errCode;        
}

// Handles processing of incoming SoH Request and generating SoH Response.
HRESULT CSampleShv::QShvRespondSHVHost()
{
    HRESULT hr = S_OK;
    hr = HandleRequestSoH(m_pShvRequest);
    if (FAILED(hr))
    {
        //
        // SDK Note:
        //
        // If errors occur here, do not terminate this method -- the SHV should
        // still generate an SoH response.
    }
    hr = HandleResponseSoH(hr, m_pShvRequest);

    // SoH Response is now set. Calling OnComplete() notifies setting of SoHResponse.
    hr = m_callback->OnComplete(m_pShvRequest, hr);

    // Release the request and callback pointers.
    m_pShvRequest->Release();
    m_callback->Release();

    return hr;    
}

// Perform all handling of inbound SoH requests from clients.
HRESULT CSampleShv::HandleRequestSoH(INapSystemHealthValidationRequest* pShvRequest) throw()
{
    HRESULT hr = S_OK;
    SoH *pSohRequest = NULL;
    INapSoHProcessor *pSohProcessor = NULL;
    SystemHealthEntityId systemHealthId = 0;
    BOOL napAgentGenerated = FALSE;

    // Obtain the client's SoH data from the SHV Host.
    hr = pShvRequest->GetSoHRequest(&pSohRequest, &napAgentGenerated);
     
    // Wrap it inside an INapSoHProcessor object.
    hr = CreateInputSoHProcessor(pSohProcessor, systemHealthId, SOH_REQUEST, pSohRequest);

    // Verify whether the client's SoH request data is considered "healthy".
    hr = CheckRequestSoHHealth(systemHealthId, pSohProcessor);

    // Release the SoH handler object.
    ReleaseObject(pSohProcessor);

    // Free the temporary SoH struct.
    FreeSoH(pSohRequest);

    return hr;
}


// Verify whether the client's SoH data is considered healthy.
HRESULT CSampleShv::CheckRequestSoHHealth( SystemHealthEntityId systemHealthId, 
                                           INapSoHProcessor *pSohRequest) throw()
{
    HRESULT hr = S_OK;

    //
    // SDK Note:
    //
    // Each vendor should update this method & its helper functions, based upon their 
    // own business logic.

    // Sanity check -- if no SoH data was passed in, leave client data unset.
    if (! pSohRequest)
    {
        //
        // SDK Note:
        //
        //  - If this SHV is acting as an intrusion detection system, it
        //    should use its specific business logic to determine whether
        //    the client is trusted or malicious, and should create an
        //    SoH Response containing the appropriate error code to
        //    convey the result to the SHV Host.
        //  - All other SHVs should return NAP_E_MISSING_SOH.

        hr = NAP_E_MISSING_SOH;
        goto Cleanup;
    }

    //
    // SDK Note:
    //
    // Check for the existence and values for each attribute that are expected 
    // from the client and determine if the client is healthy or needs to be 
    // quarantined.

    Cleanup:
        return hr;
}

// Perform all handling of outbound SoH responses sent back to clients.
HRESULT CSampleShv::HandleResponseSoH(HRESULT validationResult, 
                                      INapSystemHealthValidationRequest* pShvRequest) throw()
{
    HRESULT hr = S_OK;
    INapSoHConstructor *pSohConstructor = NULL;
    SoH *pSohResponse = NULL;

    // Create an empty SoH response.
    hr = CreateOutputSoHConstructor(pSohConstructor, QuarSampleSystemHealthId, SOH_RESPONSE);

    // Populate the SoH response based on the client's health state.
    hr = FillResponseSoH(validationResult, pSohConstructor);

    // Get portable SoH interface.
    hr = pSohConstructor->GetSoH(&pSohResponse);
    if (! pSohResponse){
        hr = E_POINTER; 
    }

    // Pass the SoH response along to the SHV Host where it is saved.
    hr = pShvRequest->SetSoHResponse(pSohResponse);

    // Release the SoH handler object.
    ReleaseObject(pSohConstructor);

    // Free the temporary SoH struct.
    FreeSoH(pSohResponse);

    return hr;
}

// Fill the specified response SoH object, given the current client's health state.
HRESULT CSampleShv::FillResponseSoH(HRESULT validationResult, 
                                    INapSoHConstructor* &pSohResponse) throw()
{
    HRESULT hr = S_OK;
    SoHAttributeValue value = {0};

    //
    // SDK Note:
    //
    // Append the manditory attribute: Compliance Result Codes. If SHV was not able to 
    // contact the external server (due to network failure, the is server down, etc...),
    // then the SHV should return the failure category attribute instead of the 
    // compliance result with FailureCategory = failureCategoryServerCommunication. 
    // Here we assume there is no such failure.

    value.codesVal.count = 1;
    value.codesVal.results = &validationResult;
    hr = pSohResponse->AppendAttribute(sohAttributeTypeComplianceResultCodes, &value);
    ZeroMemory(&value, sizeof(value));

    //
    // Append any optional attributes.
    //

    return hr;
}