Sample Code

windows driver samples/ Windows Filtering Platform Sample/ C++/ sys/ ClassifyFunctions_PendAuthorizationCallouts.cpp/

////////////////////////////////////////////////////////////////////////////////////////////////////
//
//   Copyright (c) 2012 Microsoft Corporation.  All Rights Reserved.
//
//   Module Name:
//      ClassifyFunctions_PendAuthorizationCallouts.cpp
//
//   Abstract:
//      This module contains WFP Classify functions for pending and completing authorizations.
//
//   Naming Convention:
//
//      <Module><Scenario>
//  
//      i.e.
//
//       ClassifyPendAuthorization
//
//       <Module>
//          Classify               -       Function is an FWPS_CALLOUT_CLASSIFY_FN.
//          Perform                -       Function executes the desired scenario.
//          Prv                    -       Function is a private helper to this module.
//          Trigger                -
//       <Scenario>
//          PendAuthorization      -       Function demonstates pending authorization requests.
//
//   Author:
//      Dusty Harper      (DHarper)
//
//   Private Functions:
//      PendAuthorizationWorkItemRoutine(),
//      PerformPendAuthorization(),
//      PrvCloneAuthorizedNBLAndInject()
//      TriggerPendAuthorizationOutOfBand(),
//
//   Public Functions:
//      ClassifyPendAuthorization(),
//
//   Revision History:
//
//      [ Month ][Day] [Year] - [Revision]-[ Comments ]
//      May       01,   2010  -     1.0   -  Creation
//
////////////////////////////////////////////////////////////////////////////////////////////////////

#include "Framework_WFPSamplerCalloutDriver.h"             /// .
#include "ClassifyFunctions_PendAuthorizationCallouts.tmh" /// $(OBJ_PATH)\$(O)\

/**
 @private_function="PrvCloneAuthorizedNBLAndInject"
 
   Purpose:                                                                                     <br>
                                                                                                <br>
   Notes:                                                                                       <br>
                                                                                                <br>
   MSDN_Ref:                                                                                    <br>
*/
_IRQL_requires_min_(PASSIVE_LEVEL)
_IRQL_requires_max_(DISPATCH_LEVEL)
_IRQL_requires_same_
_Check_return_
_Success_(return == STATUS_SUCCESS)
NTSTATUS PrvCloneAuthorizedNBLAndInject(_Inout_ CLASSIFY_DATA** ppClassifyData,
                                        _Inout_ INJECTION_DATA** ppInjectionData)
{
#if DBG
   
   DbgPrintEx(DPFLTR_IHVNETWORK_ID,
              DPFLTR_INFO_LEVEL,
              " ---> PrvCloneAuthorizedNBLAndInject()\n");

#endif /// DBG
   
   NT_ASSERT(ppClassifyData);
   NT_ASSERT(ppInjectionData);
   NT_ASSERT(*ppClassifyData);
   NT_ASSERT(*ppInjectionData);

   NTSTATUS                            status          = STATUS_SUCCESS;
   FWPS_INCOMING_VALUES*               pClassifyValues = (FWPS_INCOMING_VALUES*)(*ppClassifyData)->pClassifyValues;
   FWPS_INCOMING_METADATA_VALUES*      pMetadata       = (FWPS_INCOMING_METADATA_VALUES*)(*ppClassifyData)->pMetadataValues;
   UINT32                              bytesRetreated  = 0;
   COMPARTMENT_ID                      compartmentID   = UNSPECIFIED_COMPARTMENT_ID;
   BOOLEAN                             isInbound       = FALSE;
   NET_BUFFER_LIST*                    pNetBufferList  = 0;
   PEND_AUTHORIZATION_COMPLETION_DATA* pCompletionData = 0;
   FWPS_TRANSPORT_SEND_PARAMS*         pSendParams     = 0;
   BYTE*                               pRemoteAddress  = 0;

#pragma warning(push)
#pragma warning(disable: 6014) /// pCompletionData will be freed in completionFn using PendAuthorizationCompletionDataDestroy

   HLPR_NEW(pCompletionData,
            PEND_AUTHORIZATION_COMPLETION_DATA,
            WFPSAMPLER_CALLOUT_DRIVER_TAG);
   HLPR_BAIL_ON_ALLOC_FAILURE(pCompletionData,
                              status);

   HLPR_NEW(pSendParams,
            FWPS_TRANSPORT_SEND_PARAMS,
            WFPSAMPLER_CALLOUT_DRIVER_TAG);
   HLPR_BAIL_ON_ALLOC_FAILURE(pSendParams,
                              status);

#pragma warning(pop)

   KeInitializeSpinLock(&(pCompletionData->spinLock));

   pCompletionData->performedInline = FALSE;
   pCompletionData->pClassifyData   = *ppClassifyData;
   pCompletionData->pInjectionData  = *ppInjectionData;
   pCompletionData->pSendParams     = pSendParams;

   /// Responsibility for freeing this memory has been transferred to the pCompletionData
   *ppClassifyData = 0;

   *ppInjectionData = 0;

   pSendParams = 0;

   if(pCompletionData->pInjectionData->direction == FWP_DIRECTION_INBOUND)
      isInbound = TRUE;

   if(FWPS_IS_METADATA_FIELD_PRESENT(pMetadata,
                                     FWPS_METADATA_FIELD_COMPARTMENT_ID))
      compartmentID = (COMPARTMENT_ID)pMetadata->compartmentId;

   if(FWPS_IS_METADATA_FIELD_PRESENT(pMetadata,
                                     FWPS_METADATA_FIELD_IP_HEADER_SIZE))
      bytesRetreated = pMetadata->ipHeaderSize;

   if(FWPS_IS_METADATA_FIELD_PRESENT(pMetadata,
                                     FWPS_METADATA_FIELD_TRANSPORT_HEADER_SIZE))
      bytesRetreated += pMetadata->transportHeaderSize;

   if(pClassifyValues->layerId == FWPS_LAYER_ALE_AUTH_RECV_ACCEPT_V4 ||
      pClassifyValues->layerId == FWPS_LAYER_ALE_AUTH_RECV_ACCEPT_V6)
   {
      if(isInbound) /// NBL offset is at the start of the transport header ...
      {
         if(bytesRetreated)
         {
            /// so retreat (size of IP Header) to clone the whole NBL
            status = NdisRetreatNetBufferDataStart(NET_BUFFER_LIST_FIRST_NB((NET_BUFFER_LIST*)pCompletionData->pClassifyData->pPacket),
                                                   bytesRetreated,
                                                   0,
                                                   0);
            if(status != STATUS_SUCCESS)
            {
               DbgPrintEx(DPFLTR_IHVNETWORK_ID,
                          DPFLTR_ERROR_LEVEL,
                          " !!!! PrvCloneAuthorizedNBLAndInject: NdisRetreatNetBufferDataStart() [status: %#x]\n",
                          status);

               HLPR_BAIL;
            }
         }
      }
   }
   else if(pClassifyValues->layerId == FWPS_LAYER_ALE_AUTH_CONNECT_V4 ||
           pClassifyValues->layerId == FWPS_LAYER_ALE_AUTH_CONNECT_V6)
   {
      /// NBL offset is at the Transport Header, and no IP Header is present yet
      bytesRetreated = 0;

      isInbound = FALSE;
   }
   else
   {
      status = STATUS_FWP_INCOMPATIBLE_LAYER;

      HLPR_BAIL;
   }

   status = FwpsAllocateCloneNetBufferList((NET_BUFFER_LIST*)(pCompletionData->pClassifyData->pPacket),
                                           g_pNDISPoolData->nblPoolHandle,
                                           g_pNDISPoolData->nbPoolHandle,
                                           0,
                                           &pNetBufferList);

   if(bytesRetreated)
   {
      /// Advance the NBL offset so we are back at the expected position in the NET_BUFFER_LIST
      NdisAdvanceNetBufferDataStart(NET_BUFFER_LIST_FIRST_NB((NET_BUFFER_LIST*)pCompletionData->pClassifyData->pPacket),
                                    bytesRetreated,
                                    FALSE,
                                    0);
   }

   if(status != STATUS_SUCCESS)
   {
      DbgPrintEx(DPFLTR_IHVNETWORK_ID,
                 DPFLTR_ERROR_LEVEL,
                 " !!!! PrvCloneAuthorizedNBLAndInject : FwpsAllocateCloneNetBufferList() [status: %#x]\n",
                 status);

      HLPR_BAIL;
   }

   if(isInbound)
   {
      FWP_VALUE* pInterfaceIndex    = KrnlHlprFwpValueGetFromFwpsIncomingValues(pClassifyValues,
                                                                                &FWPM_CONDITION_INTERFACE_INDEX);
      FWP_VALUE* pSubInterfaceIndex = KrnlHlprFwpValueGetFromFwpsIncomingValues(pClassifyValues,
                                                                                &FWPM_CONDITION_SUB_INTERFACE_INDEX);
      IF_INDEX   interfaceIndex     = 0;
      IF_INDEX   subInterfaceIndex  = 0;

      if(pInterfaceIndex &&
         pInterfaceIndex->type == FWP_UINT32)
         interfaceIndex = (IF_INDEX)pInterfaceIndex->uint32;

      if(pSubInterfaceIndex &&
         pSubInterfaceIndex->type == FWP_UINT32)
         subInterfaceIndex = (IF_INDEX)pSubInterfaceIndex->uint32;

      status = FwpsInjectTransportReceiveAsync(pCompletionData->pInjectionData->injectionHandle,
                                               pCompletionData->pInjectionData->injectionContext,
                                               0,
                                               0,
                                               pCompletionData->pInjectionData->addressFamily,
                                               compartmentID,
                                               interfaceIndex,
                                               subInterfaceIndex,
                                               pNetBufferList,
                                               CompletePendAuthorization,
                                               pCompletionData);
   }
   else
   {
      UINT64     endpointHandle = 0;
      FWP_VALUE* pAddressValue  = 0;

      if(FWPS_IS_METADATA_FIELD_PRESENT(pMetadata,
                                        FWPS_METADATA_FIELD_TRANSPORT_ENDPOINT_HANDLE))
         endpointHandle = pMetadata->transportEndpointHandle;

      pAddressValue = KrnlHlprFwpValueGetFromFwpsIncomingValues(pClassifyValues,
                                                                &FWPM_CONDITION_IP_REMOTE_ADDRESS);
      if(pAddressValue)
      {
         if(pCompletionData->pInjectionData->addressFamily == AF_INET)
         {
            UINT32 tempAddress = htonl(pAddressValue->uint32);

#pragma warning(push)
#pragma warning(disable: 6014) /// pRemoteAddress will be freed in completionFn using PendAuthorizationCompletionDataDestroy

            HLPR_NEW_ARRAY(pRemoteAddress,
                           BYTE,
                           IPV4_ADDRESS_SIZE,
                           WFPSAMPLER_CALLOUT_DRIVER_TAG);
            HLPR_BAIL_ON_ALLOC_FAILURE(pRemoteAddress,
                                       status);

#pragma warning(pop)

            RtlCopyMemory(pRemoteAddress,
                          &tempAddress,
                          IPV4_ADDRESS_SIZE);
         }
         else
         {

#pragma warning(push)
#pragma warning(disable: 6014) /// pRemoteAddress will be freed in completionFn using PendAuthorizationCompletionDataDestroy

            HLPR_NEW_ARRAY(pRemoteAddress,
                           BYTE,
                           IPV6_ADDRESS_SIZE,
                           WFPSAMPLER_CALLOUT_DRIVER_TAG);
            HLPR_BAIL_ON_ALLOC_FAILURE(pRemoteAddress,
                                       status);

#pragma warning(pop)

            RtlCopyMemory(pRemoteAddress,
                          pAddressValue->byteArray16->byteArray16,
                          IPV6_ADDRESS_SIZE);

            if(FWPS_IS_METADATA_FIELD_PRESENT(pMetadata,
                                              FWPS_METADATA_FIELD_REMOTE_SCOPE_ID))
               pCompletionData->pSendParams->remoteScopeId = pMetadata->remoteScopeId;
         }

         pCompletionData->pSendParams->remoteAddress = pRemoteAddress;
      }

      pCompletionData->refCount = KrnlHlprNBLGetRequiredRefCount(pNetBufferList);

      status = FwpsInjectTransportSendAsync(pCompletionData->pInjectionData->injectionHandle,
                                            pCompletionData->pInjectionData->injectionContext,
                                            endpointHandle,
                                            0,
                                            pCompletionData->pSendParams,
                                            pCompletionData->pInjectionData->addressFamily,
                                            compartmentID,
                                            pNetBufferList,
                                            CompletePendAuthorization,
                                            pCompletionData);
   }

   HLPR_BAIL_LABEL:

   if(status != STATUS_SUCCESS)
   {
      if(pNetBufferList)
      {
         FwpsFreeCloneNetBufferList(pNetBufferList,
                                    0);

         pNetBufferList = 0;
      }

      if(pCompletionData)
         PendAuthorizationCompletionDataDestroy(&pCompletionData,
                                                TRUE);
   }

#if DBG
   
   DbgPrintEx(DPFLTR_IHVNETWORK_ID,
              DPFLTR_INFO_LEVEL,
              " <--- PrvCloneAuthorizedNBLAndInject() [status: %#x]\n",
              status);

#endif /// DBG
   
   return status;
}

/**
 @private_function="PerformPendAuthorization"
 
   Purpose:                                                                                     <br>
                                                                                                <br>
   Notes:                                                                                       <br>
                                                                                                <br>
   MSDN_Ref:                                                                                    <br>
*/
_IRQL_requires_min_(PASSIVE_LEVEL)
_IRQL_requires_max_(DISPATCH_LEVEL)
_IRQL_requires_same_
_Success_(return == STATUS_SUCCESS)
NTSTATUS PerformPendAuthorization(_Inout_ CLASSIFY_DATA** ppClassifyData,
                                  _Inout_ PEND_DATA** ppPendData,
                                  _Inout_ INJECTION_DATA** ppInjectionData)
{
#if DBG
   
   DbgPrintEx(DPFLTR_IHVNETWORK_ID,
              DPFLTR_INFO_LEVEL,
              " ---> PerformPendAuthorization()\n");

#endif /// DBG
   
   NT_ASSERT(ppClassifyData);
   NT_ASSERT(ppPendData);
   NT_ASSERT(ppInjectionData);
   NT_ASSERT(*ppClassifyData);
   NT_ASSERT(*ppPendData);

   NTSTATUS         status      = STATUS_SUCCESS;
   NET_BUFFER_LIST* pNBL        = (*ppPendData)->pNBL;
   UINT32           finalAction = (*ppPendData)->pPendAuthorizationData->finalAction;
   UINT32           delay       = (*ppPendData)->pPendAuthorizationData->delay;
   BOOLEAN          reInjected  = FALSE;

   if(delay &&
      KeGetCurrentIrql() < DISPATCH_LEVEL)
      KrnlHlprWorkItemSleep(delay);

#pragma warning(push)
#pragma warning(disable: 6001) /// *ppPendData initialized prior to call to this function

   /// Completes the Pend
   KrnlHlprPendDataDestroy(ppPendData);

#pragma warning(pop)

   if(pNBL &&
      finalAction == FWP_ACTION_PERMIT)
   {
      status = PrvCloneAuthorizedNBLAndInject(ppClassifyData,
                                              ppInjectionData);
      if(status != STATUS_SUCCESS)
      {
         DbgPrintEx(DPFLTR_IHVNETWORK_ID,
                    DPFLTR_ERROR_LEVEL,
                    " !!!! PerformPendAuthorization : PrvCloneAuthorizedNBLAndInject() [status: %#x]\n",
                    status);
      }
      else
         reInjected = TRUE;
   }

#pragma warning(push)
#pragma warning(disable: 6001) /// *ppClassifyData initialized prior to call to this function

   if(!reInjected)
      KrnlHlprClassifyDataDestroyLocalCopy(ppClassifyData);

#pragma warning(pop)

#if DBG
   
   DbgPrintEx(DPFLTR_IHVNETWORK_ID,
              DPFLTR_INFO_LEVEL,
              " <--- PerformPendAuthorization() [status: %#x]\n",
              status);

#endif /// DBG
   
   return status;
};

/**
 @private_function="PendAuthorizationDeferredProcedureCall"
 
   Purpose:  Invokes the appropriate private injection routine to perform the injection at 
             DISPATCH_LEVEL.                                                                    <br>
                                                                                                <br>
   Notes:                                                                                       <br>
                                                                                                <br>
   MSDN_Ref: HTTP://MSDN.Microsoft.com/En-US/Library/Windows/Hardware/FF542972.aspx             <br>
*/
_IRQL_requires_(DISPATCH_LEVEL)
_IRQL_requires_same_
_Function_class_(KDEFERRED_ROUTINE)
VOID PendAuthorizationDeferredProcedureCall(_In_ KDPC* pDPC,
                                            _In_opt_ PVOID pContext,
                                            _In_opt_ PVOID pArg1,
                                            _In_opt_ PVOID pArg2)
{
#if DBG
   
   DbgPrintEx(DPFLTR_IHVNETWORK_ID,
              DPFLTR_INFO_LEVEL,
              " ---> PendAuthorizationDeferredProcedureCall()\n");

#endif /// DBG
   
   UNREFERENCED_PARAMETER(pDPC);
   UNREFERENCED_PARAMETER(pContext);
   UNREFERENCED_PARAMETER(pArg2);

   NT_ASSERT(pDPC);
   NT_ASSERT(pArg1);
   NT_ASSERT(((DPC_DATA*)pArg1)->pClassifyData);
   NT_ASSERT(((DPC_DATA*)pArg1)->pInjectionData);

   DPC_DATA* pDPCData = (DPC_DATA*)pArg1;

   if(pDPCData)
   {
      NTSTATUS status = STATUS_SUCCESS;

      status = PerformPendAuthorization(&(pDPCData->pClassifyData),
                                        &(pDPCData->pPendData),
                                        (INJECTION_DATA**)&(pDPCData->pContext));
      if(status != STATUS_SUCCESS)
      {
         if(pDPCData->pClassifyData)
            KrnlHlprClassifyDataDestroyLocalCopy(&(pDPCData->pClassifyData));

         if(pDPCData->pInjectionData)
            KrnlHlprInjectionDataDestroy(&(pDPCData->pInjectionData));

         DbgPrintEx(DPFLTR_IHVNETWORK_ID,
                    DPFLTR_ERROR_LEVEL,
                    " !!!! PendAuthorizationDeferredProcedureCall() [status: %#x]\n",
                    status);
      }

      KrnlHlprDPCDataDestroy(&pDPCData);
   }

#if DBG
   
   DbgPrintEx(DPFLTR_IHVNETWORK_ID,
              DPFLTR_INFO_LEVEL,
              " <--- PendAuthorizationDeferredProcedureCall()\n");

#endif /// DBG
   
   return;
}

/**
 @private_function="PendAuthorizationWorkItemRoutine"
 
   Purpose:                                                                                     <br>
                                                                                                <br>
   Notes:                                                                                       <br>
                                                                                                <br>
   MSDN_Ref:                                                                                    <br>
*/
_IRQL_requires_(PASSIVE_LEVEL)
_IRQL_requires_same_
_Function_class_(IO_WORKITEM_ROUTINE)
VOID PendAuthorizationWorkItemRoutine(_In_ PDEVICE_OBJECT pDeviceObject,
                                      _In_opt_ PVOID pContext)
{
#if DBG
   
   DbgPrintEx(DPFLTR_IHVNETWORK_ID,
              DPFLTR_INFO_LEVEL,
              " ---> PendAuthorizationWorkItemRoutine()\n");

#endif /// DBG
   
   UNREFERENCED_PARAMETER(pDeviceObject);

   NT_ASSERT(pContext);
   NT_ASSERT(((WORKITEM_DATA*)pContext)->pClassifyData);
   NT_ASSERT(((WORKITEM_DATA*)pContext)->pInjectionData);

   WORKITEM_DATA* pWorkItemData = (WORKITEM_DATA*)pContext;

   if(pWorkItemData)
   {
      NTSTATUS status = STATUS_SUCCESS;

      status = PerformPendAuthorization(&(pWorkItemData->pClassifyData),
                                        &(pWorkItemData->pPendData),
                                        (INJECTION_DATA**)&(pWorkItemData->pContext));
      if(status != STATUS_SUCCESS)
      {
         if(pWorkItemData->pClassifyData)
            KrnlHlprClassifyDataDestroyLocalCopy(&(pWorkItemData->pClassifyData));

         if(pWorkItemData->pInjectionData)
            KrnlHlprInjectionDataDestroy(&(pWorkItemData->pInjectionData));

         DbgPrintEx(DPFLTR_IHVNETWORK_ID,
                    DPFLTR_ERROR_LEVEL,
                    " !!!! PendAuthorizationWorkItemRoutine() [status: %#x]\n",
                    status);
      }

      KrnlHlprWorkItemDataDestroy(&pWorkItemData);
   }

#if DBG
   
   DbgPrintEx(DPFLTR_IHVNETWORK_ID,
              DPFLTR_INFO_LEVEL,
              " <--- PendAuthorizationWorkItemRoutine()\n");

#endif /// DBG
   
   return;
}

/**
 @private_function="TriggerPendAuthorizationOutOfBand"
 
   Purpose:                                                                                     <br>
                                                                                                <br>
   Notes:                                                                                       <br>
                                                                                                <br>
   MSDN_Ref:                                                                                    <br>
*/
_IRQL_requires_min_(PASSIVE_LEVEL)
_IRQL_requires_max_(DISPATCH_LEVEL)
_IRQL_requires_same_
_Success_(return == STATUS_SUCCESS)
NTSTATUS TriggerPendAuthorizationOutOfBand(_In_ const FWPS_INCOMING_VALUES* pClassifyValues,
                                           _In_ const FWPS_INCOMING_METADATA_VALUES* pMetadata,
                                           _Inout_opt_ VOID* pLayerData,
                                           _In_opt_ const VOID* pClassifyContext,
                                           _In_ const FWPS_FILTER* pFilter,
                                           _In_ UINT64 flowContext,
                                           _In_ FWPS_CLASSIFY_OUT* pClassifyOut,
                                           _Inout_opt_ INJECTION_DATA* pInjectionData,
                                           _Inout_ PEND_DATA* pPendData,
                                           _In_ PC_PEND_AUTHORIZATION_DATA* pPCData)
{
#if DBG
   
   DbgPrintEx(DPFLTR_IHVNETWORK_ID,
              DPFLTR_INFO_LEVEL,
              " ---> TriggerPendAuthorizationOutOfBand()\n");

#endif /// DBG
   
   NT_ASSERT(pClassifyValues);
   NT_ASSERT(pMetadata);
   NT_ASSERT(pFilter);
   NT_ASSERT(pClassifyOut);
   NT_ASSERT(pPendData);
   NT_ASSERT(pPCData);
 
   NTSTATUS       status        = STATUS_SUCCESS;
   CLASSIFY_DATA* pClassifyData = 0;

#pragma warning(push)
#pragma warning(disable: 6014) /// pInjectionData will be freed in completionFn using PendAuthorizationCompletionDataDestroy

   status = KrnlHlprClassifyDataCreateLocalCopy(&pClassifyData,
                                                pClassifyValues,
                                                pMetadata,
                                                pLayerData,
                                                pClassifyContext,
                                                pFilter,
                                                flowContext,
                                                pClassifyOut);
   HLPR_BAIL_ON_FAILURE(status);

#pragma warning(pop)

   if(pPCData->useWorkItems ||
      pPCData->delay)
   {
      /// introducing the delay requires PASSIVE_LEVEL, so force use of a Work Item
      status = KrnlHlprWorkItemQueue(g_pWDMDevice,
                                     PendAuthorizationWorkItemRoutine,
                                     pClassifyData,
                                     pPendData,
                                     (VOID*)pInjectionData);
   }
   else
   {
      if(pPCData->useThreadedDPC)
         status = KrnlHlprThreadedDPCQueue(PendAuthorizationDeferredProcedureCall,
                                           pClassifyData,
                                           pPendData,
                                           pInjectionData);
      else
         status = KrnlHlprDPCQueue(PendAuthorizationDeferredProcedureCall,
                                   pClassifyData,
                                   pPendData,
                                   pInjectionData);
   }

   HLPR_BAIL_ON_FAILURE(status);

   pClassifyOut->actionType = FWP_ACTION_BLOCK;

   HLPR_BAIL_LABEL:

   if(status != STATUS_SUCCESS)
   {
      if(pClassifyData)
         KrnlHlprClassifyDataDestroyLocalCopy(&pClassifyData);
   }

#if DBG
   
   DbgPrintEx(DPFLTR_IHVNETWORK_ID,
              DPFLTR_INFO_LEVEL,
              " <--- TriggerPendAuthorizationOutOfBand() [status: %#x]\n",
              status);

#endif /// DBG
   
   return status;
}

#if(NTDDI_VERSION >= NTDDI_WIN7)

/**
 @classify_function="ClassifyPendAuthorization"
 
   Purpose:  Classify Function which will pend an authorization request, and send the request 
             for further processing to a worker thread.  On a reauthorization the final decided 
             action is returned as the actionType.                                              <br>
                                                                                                <br>
   Notes:    Applies to the following layers:                                                   <br>
                FWPM_LAYER_ALE_RESOURCE_ASSIGNMENT_V4                                           <br>
                FWPM_LAYER_ALE_RESOURCE_ASSIGNMENT_V6                                           <br>
                FWPM_LAYER_ALE_AUTH_LISTEN_V4                                                   <br>
                FWPM_LAYER_ALE_AUTH_LISTEN_V6                                                   <br>
                FWPM_LAYER_ALE_AUTH_RECV_ACCEPT_V4                                              <br>
                FWPM_LAYER_ALE_AUTH_RECV_ACCEPT_V6                                              <br>
                FWPM_LAYER_ALE_AUTH_CONNECT_V4                                                  <br>
                FWPM_LAYER_ALE_AUTH_CONNECT_V6                                                  <br>
                                                                                                <br>
   MSDN_Ref: HTTP://MSDN.Microsoft.com/En-US/Library/Windows/Hardware/FF551229.aspx             <br>
             HTTP://MSDN.Microsoft.com/En-US/Library/Windows/Hardware/FF544893.aspx             <br>
*/
_IRQL_requires_min_(PASSIVE_LEVEL)
_IRQL_requires_max_(DISPATCH_LEVEL)
_IRQL_requires_same_
VOID ClassifyPendAuthorization(_In_ const FWPS_INCOMING_VALUES* pClassifyValues,
                               _In_ const FWPS_INCOMING_METADATA_VALUES* pMetadata,
                               _Inout_opt_ VOID* pNetBufferList,
                               _In_opt_ const VOID* pClassifyContext,
                               _In_ const FWPS_FILTER* pFilter,
                               _In_ UINT64 flowContext,
                               _Inout_ FWPS_CLASSIFY_OUT* pClassifyOut)
{
#if DBG
   
   DbgPrintEx(DPFLTR_IHVNETWORK_ID,
              DPFLTR_INFO_LEVEL,
              " ---> ClassifyPendAuthorization()\n");

#endif /// DBG
   
   NT_ASSERT(pClassifyValues);
   NT_ASSERT(pMetadata);
   NT_ASSERT(pFilter);
   NT_ASSERT(pClassifyOut);
   NT_ASSERT(pClassifyValues->layerId == FWPS_LAYER_ALE_RESOURCE_ASSIGNMENT_V4 ||
             pClassifyValues->layerId == FWPS_LAYER_ALE_RESOURCE_ASSIGNMENT_V6 ||
             pClassifyValues->layerId == FWPS_LAYER_ALE_AUTH_LISTEN_V4 ||
             pClassifyValues->layerId == FWPS_LAYER_ALE_AUTH_LISTEN_V6 ||
             pClassifyValues->layerId == FWPS_LAYER_ALE_AUTH_RECV_ACCEPT_V4 ||
             pClassifyValues->layerId == FWPS_LAYER_ALE_AUTH_RECV_ACCEPT_V6 ||
             pClassifyValues->layerId == FWPS_LAYER_ALE_AUTH_CONNECT_V4 ||
             pClassifyValues->layerId == FWPS_LAYER_ALE_AUTH_CONNECT_V6);
   NT_ASSERT(pFilter->providerContext);
   NT_ASSERT(pFilter->providerContext->type == FWPM_GENERAL_CONTEXT);
   NT_ASSERT(pFilter->providerContext->dataBuffer);
   NT_ASSERT(pFilter->providerContext->dataBuffer->size == sizeof(PC_PEND_AUTHORIZATION_DATA));
   NT_ASSERT(pFilter->providerContext->dataBuffer->data);

   NTSTATUS                    status                 = STATUS_SUCCESS;
   PC_PEND_AUTHORIZATION_DATA* pPendAuthorizationData = (PC_PEND_AUTHORIZATION_DATA*)pFilter->providerContext->dataBuffer->data;


   /// RESOURCE_ASSIGNTMENT & AUTH_LISTEN will Reauthorize after the completion of the pend.
   /// AUTH_CONNECT's completeOperation will trigger a Reauthorization
   if(KrnlHlprFwpsIncomingValueConditionFlagsAreSet(pClassifyValues,
                                                    FWP_CONDITION_FLAG_IS_REAUTHORIZE))
   {
      if(pClassifyOut->rights & FWPS_RIGHT_ACTION_WRITE)
         pClassifyOut->actionType = pPendAuthorizationData->finalAction;
   }
   else
   {
      BOOLEAN actionSet = FALSE;

      if(pClassifyOut->rights & FWPS_RIGHT_ACTION_WRITE)
      {
         INJECTION_DATA* pInjectionData = 0;
         PEND_DATA*      pPendData      = 0;

#pragma warning(push)
#pragma warning(disable: 6014) /// pInjectionData will be freed in completionFn using PendAuthorizationCompletionDataDestroy

         if(pClassifyValues->layerId == FWPS_LAYER_ALE_AUTH_RECV_ACCEPT_V4 ||
             pClassifyValues->layerId == FWPS_LAYER_ALE_AUTH_RECV_ACCEPT_V6 ||
             pClassifyValues->layerId == FWPS_LAYER_ALE_AUTH_CONNECT_V4 ||
             pClassifyValues->layerId == FWPS_LAYER_ALE_AUTH_CONNECT_V6)
         {
            status = KrnlHlprInjectionDataCreate(&pInjectionData,
                                                 pClassifyValues,
                                                 pMetadata,
                                                 (NET_BUFFER_LIST*)pNetBufferList);
            HLPR_BAIL_ON_FAILURE(status);
         }

#pragma warning(pop)

         /// AUTH_RECV_ACCEPT's injection will be indicative of PERMIT
         if(pInjectionData &&
            pInjectionData->injectionState == FWPS_PACKET_INJECTED_BY_SELF)
         {
            pClassifyOut->actionType = pPendAuthorizationData->finalAction;

            actionSet = TRUE;
         }
         else
         {
#pragma warning(push)
#pragma warning(disable: 6014) /// pPendData will be freed in completionFn using PendAuthorizationCompletionDataDestroy

            status = KrnlHlprPendDataCreate(&pPendData,
                                            pMetadata,
                                            (NET_BUFFER_LIST*)pNetBufferList,
                                            pFilter);
            HLPR_BAIL_ON_FAILURE(status);

#pragma warning(pop)

            status = TriggerPendAuthorizationOutOfBand(pClassifyValues,
                                                       pMetadata,
                                                       pNetBufferList,
                                                       pClassifyContext,
                                                       pFilter,
                                                       flowContext,
                                                       pClassifyOut,
                                                       pInjectionData,
                                                       pPendData,
                                                       pPendAuthorizationData);
         }

         HLPR_BAIL_LABEL:

         if(status != STATUS_SUCCESS)
         {
            DbgPrintEx(DPFLTR_IHVNETWORK_ID,
                       DPFLTR_ERROR_LEVEL,
                       " !!!! ClassifyPendAuthorization() [status: %#x]\n",
                       status);

            if(pInjectionData)
               KrnlHlprInjectionDataDestroy(&pInjectionData);

            if(pPendData)
               KrnlHlprPendDataDestroy(&pPendData);
         }

         if(!actionSet)
         {
            pClassifyOut->actionType  = FWP_ACTION_BLOCK;
            pClassifyOut->flags      |= FWPS_CLASSIFY_OUT_FLAG_ABSORB;
         }
      }
   }

#if DBG
   
   DbgPrintEx(DPFLTR_IHVNETWORK_ID,
              DPFLTR_INFO_LEVEL,
              " <--- ClassifyPendAuthorization()\n");

#endif /// DBG
   
   return;
}

#else

/**
 @classify_function="ClassifyPendAuthorization"
 
   Purpose:  Classify Function which will pend an authorization request, and send the request 
             for further processing to a worker thread.  On a reauthorization the final decided 
             action is returned as the actionType.                                              <br>
                                                                                                <br>
   Notes:    Applies to the following layers:                                                   <br>
                FWPM_LAYER_ALE_RESOURCE_ASSIGNMENT_V4                                           <br>
                FWPM_LAYER_ALE_RESOURCE_ASSIGNMENT_V6                                           <br>
                FWPM_LAYER_ALE_AUTH_LISTEN_V4                                                   <br>
                FWPM_LAYER_ALE_AUTH_LISTEN_V6                                                   <br>
                FWPM_LAYER_ALE_AUTH_RECV_ACCEPT_V4                                              <br>
                FWPM_LAYER_ALE_AUTH_RECV_ACCEPT_V6                                              <br>
                FWPM_LAYER_ALE_AUTH_CONNECT_V4                                                  <br>
                FWPM_LAYER_ALE_AUTH_CONNECT_V6                                                  <br>
                                                                                                <br>
   MSDN_Ref: HTTP://MSDN.Microsoft.com/En-US/Library/Windows/Hardware/FF551229.aspx             <br>
             HTTP://MSDN.Microsoft.com/En-US/Library/Windows/Hardware/FF544890.aspx             <br>
*/
_IRQL_requires_min_(PASSIVE_LEVEL)
_IRQL_requires_max_(DISPATCH_LEVEL)
_IRQL_requires_same_
VOID ClassifyPendAuthorization(_In_ const FWPS_INCOMING_VALUES* pClassifyValues,
                               _In_ const FWPS_INCOMING_METADATA_VALUES* pMetadata,
                               _Inout_opt_ VOID* pNetBufferList,
                               _In_ const FWPS_FILTER* pFilter,
                               _In_ UINT64 flowContext,
                               _Inout_ FWPS_CLASSIFY_OUT* pClassifyOut)
{
#if DBG
   
   DbgPrintEx(DPFLTR_IHVNETWORK_ID,
              DPFLTR_INFO_LEVEL,
              " ---> ClassifyPendAuthorization()\n");

#endif /// DBG
   
   NT_ASSERT(pClassifyValues);
   NT_ASSERT(pMetadata);
   NT_ASSERT(pFilter);
   NT_ASSERT(pClassifyOut);
   NT_ASSERT(pClassifyValues->layerId == FWPS_LAYER_ALE_RESOURCE_ASSIGNMENT_V4 ||
             pClassifyValues->layerId == FWPS_LAYER_ALE_RESOURCE_ASSIGNMENT_V6 ||
             pClassifyValues->layerId == FWPS_LAYER_ALE_AUTH_LISTEN_V4 ||
             pClassifyValues->layerId == FWPS_LAYER_ALE_AUTH_LISTEN_V6 ||
             pClassifyValues->layerId == FWPS_LAYER_ALE_AUTH_RECV_ACCEPT_V4 ||
             pClassifyValues->layerId == FWPS_LAYER_ALE_AUTH_RECV_ACCEPT_V6 ||
             pClassifyValues->layerId == FWPS_LAYER_ALE_AUTH_CONNECT_V4 ||
             pClassifyValues->layerId == FWPS_LAYER_ALE_AUTH_CONNECT_V6);
   NT_ASSERT(pFilter->providerContext);
   NT_ASSERT(pFilter->providerContext->type == FWPM_GENERAL_CONTEXT);
   NT_ASSERT(pFilter->providerContext->dataBuffer);
   NT_ASSERT(pFilter->providerContext->dataBuffer->size == sizeof(PC_PEND_AUTHORIZATION_DATA));
   NT_ASSERT(pFilter->providerContext->dataBuffer->data);

   NTSTATUS                    status                 = STATUS_SUCCESS;
   PC_PEND_AUTHORIZATION_DATA* pPendAuthorizationData = (PC_PEND_AUTHORIZATION_DATA*)pFilter->providerContext->dataBuffer->data;

   /// RESOURCE_ASSIGNTMENT & AUTH_LISTEN will Reauthorize after the completion of the pend.
   /// AUTH_CONNECT's completeOperation will trigger a Reauthorization
   if(KrnlHlprFwpsIncomingValueConditionFlagsAreSet(pClassifyValues,
                                                    FWP_CONDITION_FLAG_IS_REAUTHORIZE))
   {
      if(pClassifyOut->rights & FWPS_RIGHT_ACTION_WRITE)
         pClassifyOut->actionType = pPendAuthorizationData->finalAction;
   }
   else
   {
      BOOLEAN actionSet = FALSE;

      if(pClassifyOut->rights & FWPS_RIGHT_ACTION_WRITE)
      {
         INJECTION_DATA* pInjectionData = 0;
         PEND_DATA*      pPendData      = 0;

#pragma warning(push)
#pragma warning(disable: 6014) /// pInjectionData will be freed in completionFn using PendAuthorizationCompletionDataDestroy

         if(pClassifyValues->layerId == FWPS_LAYER_ALE_AUTH_RECV_ACCEPT_V4 ||
             pClassifyValues->layerId == FWPS_LAYER_ALE_AUTH_RECV_ACCEPT_V6 ||
             pClassifyValues->layerId == FWPS_LAYER_ALE_AUTH_CONNECT_V4 ||
             pClassifyValues->layerId == FWPS_LAYER_ALE_AUTH_CONNECT_V6)
         {
            status = KrnlHlprInjectionDataCreate(&pInjectionData,
                                                 pClassifyValues,
                                                 pMetadata,
                                                 (NET_BUFFER_LIST*)pNetBufferList);
            HLPR_BAIL_ON_FAILURE(status);
         }

#pragma warning(pop)

         /// AUTH_RECV_ACCEPT's injection will be indicative of PERMIT
         if(pInjectionData &&
            pInjectionData->injectionState == FWPS_PACKET_INJECTED_BY_SELF)
         {
            pClassifyOut->actionType = pPendAuthorizationData->finalAction;

            actionSet = TRUE;
         }
         else
         {
#pragma warning(push)
#pragma warning(disable: 6014) /// pInjectionData will be freed in completionFn using PendAuthorizationCompletionDataDestroy

            status = KrnlHlprPendDataCreate(&pPendData,
                                            pMetadata,
                                            (NET_BUFFER_LIST*)pNetBufferList,
                                            pFilter);
            HLPR_BAIL_ON_FAILURE(status);

#pragma warning(pop)

            status = TriggerPendAuthorizationOutOfBand(pClassifyValues,
                                                       pMetadata,
                                                       pNetBufferList,
                                                       0,
                                                       pFilter,
                                                       flowContext,
                                                       pClassifyOut,
                                                       pInjectionData,
                                                       pPendData,
                                                       pPendAuthorizationData);
         }

         HLPR_BAIL_LABEL:

         if(status != STATUS_SUCCESS)
         {
            DbgPrintEx(DPFLTR_IHVNETWORK_ID,
                       DPFLTR_ERROR_LEVEL,
                       " !!!! ClassifyPendAuthorization() [status: %#x]\n",
                       status);

            if(pInjectionData)
               KrnlHlprInjectionDataDestroy(&pInjectionData);

            if(pPendData)
               KrnlHlprPendDataDestroy(&pPendData);
         }

         if(!actionSet)
         {
            pClassifyOut->actionType  = FWP_ACTION_BLOCK;
            pClassifyOut->flags      |= FWPS_CLASSIFY_OUT_FLAG_ABSORB;
         }
      }
   }

#if DBG
   
   DbgPrintEx(DPFLTR_IHVNETWORK_ID,
              DPFLTR_INFO_LEVEL,
              " <--- ClassifyPendAuthorization()\n");

#endif /// DBG
   
   return;
}

#endif // (NTDDI_VERSION >= NTDDI_WIN7)

Our Services

  • What our customers say about us?

© 2011-2025 All Rights Reserved. Joya Systems. 4425 South Mopac Building II Suite 101 Austin, TX 78735 Tel: 800-DEV-KERNEL

Privacy Policy. Terms of use. Valid XHTML & CSS