summaryrefslogtreecommitdiff
path: root/network/trans/WFPSampler/sys/ClassifyFunctions_PendAuthorizationCallouts.cpp
diff options
context:
space:
mode:
Diffstat (limited to 'network/trans/WFPSampler/sys/ClassifyFunctions_PendAuthorizationCallouts.cpp')
-rw-r--r--network/trans/WFPSampler/sys/ClassifyFunctions_PendAuthorizationCallouts.cpp1015
1 files changed, 1015 insertions, 0 deletions
diff --git a/network/trans/WFPSampler/sys/ClassifyFunctions_PendAuthorizationCallouts.cpp b/network/trans/WFPSampler/sys/ClassifyFunctions_PendAuthorizationCallouts.cpp
new file mode 100644
index 00000000..f4f23eba
--- /dev/null
+++ b/network/trans/WFPSampler/sys/ClassifyFunctions_PendAuthorizationCallouts.cpp
@@ -0,0 +1,1015 @@
+////////////////////////////////////////////////////////////////////////////////////////////////////
+//
+// Copyright (c) 2014 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:
+// PendAuthorizationDeferredProcedureCall(),
+// ClassifyPendAuthorization(),
+//
+// Revision History:
+//
+// [ Month ][Day] [Year] - [Revision]-[ Comments ]
+// May 01, 2010 - 1.0 - Creation
+// December 13, 2013 - 1.1 - Enhance function declaration for IntelliSense, enhance
+// traces, and add support for controlData.
+//
+////////////////////////////////////////////////////////////////////////////////////////////////////
+
+#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 = DEFAULT_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->pSendParams->controlData = (WSACMSGHDR*)pCompletionData->pInjectionData->pControlData;
+ pCompletionData->pSendParams->controlDataLength = pCompletionData->pInjectionData->controlDataLength;
+
+ 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;
+}
+
+#pragma warning(push)
+#pragma warning(disable: 6101) /// *ppClassifyData and *ppPendData are freed and set to 0 on successful completion
+
+/**
+ @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)
+ {
+
+#pragma warning(push)
+#pragma warning(disable: 28118) /// IRQL check has already been performed
+
+ KrnlHlprWorkItemSleep(delay);
+
+#pragma warning(pop)
+
+ }
+
+#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;
+};
+
+#pragma warning(pop)
+
+/**
+ @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_V{4/6} <br>
+ FWPM_LAYER_ALE_AUTH_LISTEN_V{4/6} <br>
+ FWPM_LAYER_ALE_AUTH_RECV_ACCEPT_V{4/6} <br>
+ FWPM_LAYER_ALE_AUTH_CONNECT_V{4/6} <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 NTAPI 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)
+{
+ 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);
+
+ DbgPrintEx(DPFLTR_IHVNETWORK_ID,
+ DPFLTR_INFO_LEVEL,
+ " ---> ClassifyPendAuthorization() [Layer: %s][FilterID: %#I64x][Rights: %#x][Reauth: %s]",
+ KrnlHlprFwpsLayerIDToString(pClassifyValues->layerId),
+ pFilter->filterId,
+ pClassifyOut->rights,
+ KrnlHlprFwpsIncomingValueConditionFlagsAreSet(pClassifyValues,
+ FWP_CONDITION_FLAG_IS_REAUTHORIZE) ? "TRUE" : "FALSE");
+
+ PC_PEND_AUTHORIZATION_DATA* pPendAuthorizationData = (PC_PEND_AUTHORIZATION_DATA*)pFilter->providerContext->dataBuffer->data;
+ BOOLEAN isReauth = KrnlHlprFwpsIncomingValueConditionFlagsAreSet(pClassifyValues,
+ FWP_CONDITION_FLAG_IS_REAUTHORIZE);
+
+ /// RESOURCE_ASSIGNTMENT & AUTH_LISTEN will Reauthorize after the completion of the pend.
+ /// AUTH_CONNECT's completeOperation will trigger a Reauthorization
+ if(isReauth)
+ {
+ if(pClassifyOut->rights & FWPS_RIGHT_ACTION_WRITE)
+ pClassifyOut->actionType = pPendAuthorizationData->finalAction;
+ }
+ else
+ {
+ BOOLEAN actionSet = FALSE;
+
+ if(pClassifyOut->rights & FWPS_RIGHT_ACTION_WRITE)
+ {
+ NTSTATUS status = STATUS_SUCCESS;
+ 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,
+ pFilter);
+ 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)
+ {
+ isReauth = TRUE;
+
+ 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,
+ pClassifyValues,
+ 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;
+ }
+ }
+ }
+
+ DbgPrintEx(DPFLTR_IHVNETWORK_ID,
+ DPFLTR_INFO_LEVEL,
+ " <--- ClassifyPendAuthorization() [Layer: %s][FilterID: %#I64x][Action: %#x][Rights: %#x][Absorb: %s][ReAuth: %s]\n",
+ KrnlHlprFwpsLayerIDToString(pClassifyValues->layerId),
+ pFilter->filterId,
+ pClassifyOut->actionType,
+ pClassifyOut->rights,
+ (pClassifyOut->flags & FWPS_CLASSIFY_OUT_FLAG_ABSORB) ? "TRUE" : "FALSE",
+ isReauth ? "TRUE" : "FALSE");
+
+ 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_V{4/6} <br>
+ FWPM_LAYER_ALE_AUTH_LISTEN_V{4/6} <br>
+ FWPM_LAYER_ALE_AUTH_RECV_ACCEPT_V{4/6} <br>
+ FWPM_LAYER_ALE_AUTH_CONNECT_V{4/6} <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 NTAPI 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)
+{
+ 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);
+
+ DbgPrintEx(DPFLTR_IHVNETWORK_ID,
+ DPFLTR_INFO_LEVEL,
+ " ---> ClassifyPendAuthorization() [Layer: %s][FilterID: %#I64x][Rights: %#x][ReAuth: %s]",
+ KrnlHlprFwpsLayerIDToString(pClassifyValues->layerId),
+ pFilter->filterId,
+ pClassifyOut->rights,
+ KrnlHlprFwpsIncomingValueConditionFlagsAreSet(pClassifyValues,
+ FWP_CONDITION_FLAG_IS_REAUTHORIZE) ? "TRUE" : "FALSE");
+
+ PC_PEND_AUTHORIZATION_DATA* pPendAuthorizationData = (PC_PEND_AUTHORIZATION_DATA*)pFilter->providerContext->dataBuffer->data;
+ BOOLEAN isReauth = KrnlHlprFwpsIncomingValueConditionFlagsAreSet(pClassifyValues,
+ FWP_CONDITION_FLAG_IS_REAUTHORIZE);
+
+ /// RESOURCE_ASSIGNTMENT & AUTH_LISTEN will Reauthorize after the completion of the pend.
+ /// AUTH_CONNECT's completeOperation will trigger a Reauthorization
+ if(isReauth)
+ {
+ if(pClassifyOut->rights & FWPS_RIGHT_ACTION_WRITE)
+ pClassifyOut->actionType = pPendAuthorizationData->finalAction;
+ }
+ else
+ {
+ BOOLEAN actionSet = FALSE;
+
+ if(pClassifyOut->rights & FWPS_RIGHT_ACTION_WRITE)
+ {
+ NTSTATUS status = STATUS_SUCCESS;
+ 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,
+ pFilter);
+ HLPR_BAIL_ON_FAILURE(status);
+ }
+
+#pragma warning(pop)
+
+ /// AUTH_RECV_ACCEPT's injection will be indicative of ReAuth
+ if(pInjectionData &&
+ pInjectionData->injectionState == FWPS_PACKET_INJECTED_BY_SELF)
+ {
+ isReauth = TRUE;
+
+ 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,
+ pClassifyValues,
+ 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;
+ }
+ }
+ }
+
+ DbgPrintEx(DPFLTR_IHVNETWORK_ID,
+ DPFLTR_INFO_LEVEL,
+ " <--- ClassifyPendAuthorization() [Layer: %s][FilterID: %#I64x][Action: %#x][Rights: %#x][Absorb: %s][ReAuth: %s]\n",
+ KrnlHlprFwpsLayerIDToString(pClassifyValues->layerId),
+ pFilter->filterId,
+ pClassifyOut->actionType,
+ pClassifyOut->rights,
+ (pClassifyOut->flags & FWPS_CLASSIFY_OUT_FLAG_ABSORB) ? "TRUE" : "FALSE",
+ isReauth ? "TRUE" : "FALSE");
+
+ return;
+}
+
+#endif // (NTDDI_VERSION >= NTDDI_WIN7)