1040 lines
32 KiB
C
1040 lines
32 KiB
C
/*
|
|
* Copyright 2021 David Xanatos, xanasoft.com
|
|
*
|
|
* This program is free software: you can redistribute it and/or modify
|
|
* it under the terms of the GNU General Public License as published by
|
|
* the Free Software Foundation, either version 3 of the License, or
|
|
* (at your option) any later version.
|
|
*
|
|
* This program is distributed in the hope that it will be useful,
|
|
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
|
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
|
* GNU General Public License for more details.
|
|
*
|
|
* You should have received a copy of the GNU General Public License
|
|
* along with this program. If not, see <https://www.gnu.org/licenses/>.
|
|
*/
|
|
|
|
//---------------------------------------------------------------------------
|
|
// Windows Filtering Platform
|
|
//---------------------------------------------------------------------------
|
|
|
|
|
|
#include "wfp.h"
|
|
#include "process.h"
|
|
#include "conf.h"
|
|
#include "session.h"
|
|
#include "api_flags.h"
|
|
#include "common/map.h"
|
|
#include "common/netfw.h"
|
|
#include "common/my_version.h"
|
|
#define NO_IP_DEFS
|
|
#include "common/my_wsa.h"
|
|
|
|
|
|
extern DEVICE_OBJECT *Api_DeviceObject;
|
|
|
|
#ifdef _M_ARM64
|
|
#define NDIS630 1 // windows 8.1
|
|
#else
|
|
#define NDIS61 1 // windows 7
|
|
#endif
|
|
|
|
|
|
#include "Ntifs.h"
|
|
#include <ntddk.h> // Windows Driver Development Kit
|
|
|
|
#pragma warning(push)
|
|
#pragma warning(disable: 4201) // Disable "Nameless struct/union" compiler warning for fwpsk.h only!
|
|
#include <fwpsk.h> // Functions and enumerated types used to implement callouts in kernel mode
|
|
#pragma warning(pop) // Re-enable "Nameless struct/union" compiler warning
|
|
|
|
#include <guiddef.h> // Used to define GUID's
|
|
#include <initguid.h> // Used to define GUID's
|
|
#include <fwpmk.h> // Functions used for managing IKE and AuthIP main mode (MM) policy and security associations
|
|
#include <fwpvi.h> // Mappings of OS specific function versions (i.e. fn's that end in 0 or 1)
|
|
#include "devguid.h"
|
|
|
|
|
|
//---------------------------------------------------------------------------
|
|
// Defines
|
|
//---------------------------------------------------------------------------
|
|
|
|
#define WFP_SUBLAYER_NAME L"SbieSublayer"
|
|
#define WFP_SUBLAYER_DESCRIPTION L"A sublayer used by sandboxie to implement internet restrictions"
|
|
|
|
DEFINE_GUID(WFP_SUBLAYER_GUID, // e1d364e9-cd84-4a48-aba4-608ce83e31ee
|
|
0xe1d364e9, 0xcd84, 0x4a48, 0xab, 0xa4, 0x60, 0x8c, 0xe8, 0x3e, 0x31, 0xee);
|
|
|
|
#define WFP_CALLOUT_NAME L"SbieCallout"
|
|
#define WFP_CALLOUT_DESCRIPTION L"A callout used by sandboxie to implement internet restrictions"
|
|
|
|
//DEFINE_GUID(WPF_CALLOUT_GUID_V4, // 0bf56435-71e4-4de7-bd0b-1af0b4cbb8f4
|
|
// 0x0bf56435, 0x71e4, 0x4de7, 0xbd, 0x0b, 0x1a, 0xf0, 0xb4, 0xcb, 0xb8, 0xf4);
|
|
//DEFINE_GUID(WPF_CALLOUT_GUID_V6, // 0bf56435-71e4-4de7-bd0b-1af0b4cbb9f5
|
|
// 0x0bf56435, 0x71e4, 0x4de7, 0xbd, 0x0b, 0x1a, 0xf0, 0xb4, 0xcb, 0xb9, 0xf5);
|
|
DEFINE_GUID(WPF_SEND_CALLOUT_GUID_V4, // 0bf56435-71e4-4de7-bd0b-1af0b4cbb8f6
|
|
0x0bf56435, 0x71e4, 0x4de7, 0xbd, 0x0b, 0x1a, 0xf0, 0xb4, 0xcb, 0xb8, 0xf6);
|
|
DEFINE_GUID(WPF_SEND_CALLOUT_GUID_V6, // 0bf56435-71e4-4de7-bd0b-1af0b4cbb9f7
|
|
0x0bf56435, 0x71e4, 0x4de7, 0xbd, 0x0b, 0x1a, 0xf0, 0xb4, 0xcb, 0xb9, 0xf7);
|
|
DEFINE_GUID(WPF_RECV_CALLOUT_GUID_V4, // 0bf56435-71e4-4de7-bd0b-1af0b4cbb8f8
|
|
0x0bf56435, 0x71e4, 0x4de7, 0xbd, 0x0b, 0x1a, 0xf0, 0xb4, 0xcb, 0xb8, 0xf8);
|
|
DEFINE_GUID(WPF_RECV_CALLOUT_GUID_V6, // 0bf56435-71e4-4de7-bd0b-1af0b4cbb9f9
|
|
0x0bf56435, 0x71e4, 0x4de7, 0xbd, 0x0b, 0x1a, 0xf0, 0xb4, 0xcb, 0xb9, 0xf9);
|
|
|
|
#define WFP_FILTER_NAME L"SbieFilter"
|
|
#define WFP_FILTER_DESCRIPTION L"A filter that uses by sandboxie to implement internet restrictions"
|
|
|
|
|
|
//---------------------------------------------------------------------------
|
|
// Structures and Types
|
|
//---------------------------------------------------------------------------
|
|
|
|
|
|
typedef struct _WFP_PROCESS {
|
|
|
|
HANDLE ProcessId;
|
|
BOOLEAN LogTraffic;
|
|
BOOLEAN BlockInternet;
|
|
LIST NetFwRules;
|
|
|
|
} WFP_PROCESS;
|
|
|
|
|
|
//---------------------------------------------------------------------------
|
|
// Functions
|
|
//---------------------------------------------------------------------------
|
|
|
|
BOOLEAN WFP_Install_Callbacks(void);
|
|
|
|
void WFP_Uninstall_Callbacks(void);
|
|
|
|
NTSTATUS WFP_RegisterSubLayer();
|
|
|
|
NTSTATUS WFP_RegisterCallout(const GUID* calloutKey, const GUID* applicableLayer, UINT32* callout_id, UINT64* filter_id);
|
|
|
|
const WCHAR* Process_MatchImageAndGetValue(BOX* box, const WCHAR* value, const WCHAR* ImageName, ULONG* pLevel);
|
|
|
|
ULONG Process_GetTraceFlag(PROCESS *proc, const WCHAR *setting);
|
|
|
|
void WFP_FreeRules(LIST* NetFwRules);
|
|
|
|
#ifdef ALLOC_PRAGMA
|
|
#pragma alloc_text (INIT, WFP_Init)
|
|
#endif // ALLOC_PRAGMA
|
|
|
|
void WFP_state_changed(
|
|
_Inout_ void* context,
|
|
_In_ FWPM_SERVICE_STATE newState);
|
|
|
|
/* The "classifyFn" callout function for this Callout.
|
|
For more information about a Callout's classifyFn, see:
|
|
http://msdn.microsoft.com/en-us/library/windows/hardware/ff544893(v=vs.85).aspx
|
|
*/
|
|
void WFP_classify(
|
|
const FWPS_INCOMING_VALUES * inFixedValues,
|
|
const FWPS_INCOMING_METADATA_VALUES * inMetaValues,
|
|
void * layerData,
|
|
const void * classifyContext,
|
|
const FWPS_FILTER * filter,
|
|
UINT64 flowContext,
|
|
FWPS_CLASSIFY_OUT * classifyOut);
|
|
|
|
/* The "notifyFn" callout function for this Callout.
|
|
This function manages setting up global resources and a worker thread
|
|
managed by this Callout. For more information about a Callout's notifyFn, see:
|
|
http://msdn.microsoft.com/en-us/library/windows/hardware/ff568804(v=vs.85).aspx
|
|
*/
|
|
NTSTATUS WFP_notify(
|
|
FWPS_CALLOUT_NOTIFY_TYPE notifyType,
|
|
const GUID * filterKey,
|
|
const FWPS_FILTER * filter);
|
|
|
|
/* The "flowDeleteFn" callout function for this Callout.
|
|
This function doesn't do anything.
|
|
http://msdn.microsoft.com/en-us/library/windows/hardware/ff550025(v=vs.85).aspx
|
|
*/
|
|
NTSTATUS WFP_flow_delete(
|
|
UINT16 layerId,
|
|
UINT32 calloutId,
|
|
UINT64 flowContext);
|
|
|
|
void GetNetwork5TupleIndexesForLayer(
|
|
_In_ UINT16 layerId,
|
|
_Out_ UINT* localAddressIndex,
|
|
_Out_ UINT* remoteAddressIndex,
|
|
_Out_ UINT* localPortIndex,
|
|
_Out_ UINT* remotePortIndex,
|
|
_Out_ UINT* protocolIndex);
|
|
|
|
|
|
//---------------------------------------------------------------------------
|
|
// Variables
|
|
//---------------------------------------------------------------------------
|
|
|
|
|
|
BOOLEAN WFP_Enabled = FALSE;
|
|
static PERESOURCE WFP_InitLock = NULL;
|
|
|
|
static HANDLE WFP_state_handle = NULL;
|
|
|
|
// Global handle to the WFP Base Filter Engine
|
|
static HANDLE WFP_engine_handle = NULL;
|
|
|
|
//static UINT32 WFP_callout_id_v4 = 0;
|
|
//static UINT32 WFP_callout_id_v6 = 0;
|
|
static UINT32 WFP_send_callout_id_v4 = 0;
|
|
static UINT32 WFP_send_callout_id_v6 = 0;
|
|
static UINT32 WFP_recv_callout_id_v4 = 0;
|
|
static UINT32 WFP_recv_callout_id_v6 = 0;
|
|
|
|
//static UINT64 WFP_filter_id_v4 = 0;
|
|
//static UINT64 WFP_filter_id_v6 = 0;
|
|
static UINT64 WFP_send_filter_id_v4 = 0;
|
|
static UINT64 WFP_send_filter_id_v6 = 0;
|
|
static UINT64 WFP_recv_filter_id_v4 = 0;
|
|
static UINT64 WFP_recv_filter_id_v6 = 0;
|
|
|
|
static BOOLEAN WPF_MapInitialized = FALSE;
|
|
static map_base_t WFP_Processes;
|
|
static KSPIN_LOCK WFP_MapLock;
|
|
|
|
|
|
//---------------------------------------------------------------------------
|
|
// WFP_Alloc
|
|
//---------------------------------------------------------------------------
|
|
|
|
|
|
_FX VOID* WFP_Alloc(void* pool, size_t size)
|
|
{
|
|
return ExAllocatePoolWithTag(NonPagedPool, size, tzuk);
|
|
}
|
|
|
|
|
|
//---------------------------------------------------------------------------
|
|
// WFP_Free
|
|
//---------------------------------------------------------------------------
|
|
|
|
|
|
_FX VOID WFP_Free(void* pool, void* ptr)
|
|
{
|
|
ExFreePoolWithTag(ptr, tzuk);
|
|
}
|
|
|
|
|
|
//---------------------------------------------------------------------------
|
|
// WFP_Init
|
|
//---------------------------------------------------------------------------
|
|
|
|
|
|
_FX BOOLEAN WFP_Init(void)
|
|
{
|
|
map_init(&WFP_Processes, NULL);
|
|
WFP_Processes.func_malloc = &WFP_Alloc;
|
|
WFP_Processes.func_free = &WFP_Free;
|
|
|
|
KeInitializeSpinLock(&WFP_MapLock);
|
|
|
|
WPF_MapInitialized = TRUE;
|
|
|
|
if (!Conf_Get_Boolean(NULL, L"NetworkEnableWFP", 0, FALSE))
|
|
return TRUE;
|
|
|
|
return WFP_Load();
|
|
}
|
|
|
|
|
|
//---------------------------------------------------------------------------
|
|
// WFP_Load
|
|
//---------------------------------------------------------------------------
|
|
|
|
|
|
_FX BOOLEAN WFP_Load(void)
|
|
{
|
|
if (WFP_Enabled)
|
|
return TRUE;
|
|
|
|
WFP_Enabled = TRUE;
|
|
|
|
map_resize(&WFP_Processes, 128); // prepare some buckets for better performance
|
|
|
|
DbgPrint("Sbie WFP enabled\r\n");
|
|
|
|
if (!Mem_GetLockResource(&WFP_InitLock, TRUE))
|
|
return FALSE;
|
|
|
|
NTSTATUS status = FwpmBfeStateSubscribeChanges((void*)Api_DeviceObject, WFP_state_changed, NULL, &WFP_state_handle);
|
|
if (!NT_SUCCESS(status)) {
|
|
DbgPrint("Sbie WFP failed to install state change callback\r\n");
|
|
Mem_FreeLockResource(&WFP_InitLock);
|
|
WFP_InitLock = NULL;
|
|
return FALSE;
|
|
}
|
|
|
|
if (FwpmBfeStateGet() == FWPM_SERVICE_RUNNING) {
|
|
|
|
KeEnterCriticalRegion();
|
|
|
|
ExAcquireResourceSharedLite(WFP_InitLock, TRUE);
|
|
|
|
WFP_Install_Callbacks();
|
|
|
|
ExReleaseResourceLite(WFP_InitLock);
|
|
|
|
KeLeaveCriticalRegion();
|
|
}
|
|
else
|
|
DbgPrint("Sbie WFP is not ready\r\n");
|
|
|
|
return TRUE;
|
|
}
|
|
|
|
|
|
//---------------------------------------------------------------------------
|
|
// WFP_Unload
|
|
//---------------------------------------------------------------------------
|
|
|
|
|
|
_FX void WFP_Unload(void)
|
|
{
|
|
WFP_Enabled = FALSE;
|
|
|
|
if (WFP_state_handle != NULL) {
|
|
|
|
FwpmBfeStateUnsubscribeChanges(WFP_state_handle);
|
|
WFP_state_handle = NULL;
|
|
}
|
|
|
|
if (WFP_InitLock) {
|
|
|
|
KeEnterCriticalRegion();
|
|
|
|
ExAcquireResourceSharedLite(WFP_InitLock, TRUE);
|
|
|
|
WFP_Uninstall_Callbacks();
|
|
|
|
ExReleaseResourceLite(WFP_InitLock);
|
|
|
|
KeLeaveCriticalRegion();
|
|
|
|
Mem_FreeLockResource(&WFP_InitLock);
|
|
WFP_InitLock = NULL;
|
|
}
|
|
|
|
if (WPF_MapInitialized) {
|
|
|
|
KIRQL irql;
|
|
|
|
#ifdef _WIN64
|
|
irql = KeAcquireSpinLockRaiseToDpc(&WFP_MapLock);
|
|
#else
|
|
KeAcquireSpinLock(&WFP_MapLock, &irql);
|
|
#endif
|
|
|
|
map_iter_t iter = map_iter();
|
|
while (map_next(&WFP_Processes, &iter)) {
|
|
WFP_PROCESS* wfp_proc = iter.value;
|
|
|
|
WFP_FreeRules(&wfp_proc->NetFwRules);
|
|
WFP_Free(NULL, wfp_proc);
|
|
}
|
|
|
|
map_clear(&WFP_Processes);
|
|
|
|
KeReleaseSpinLock(&WFP_MapLock, irql);
|
|
}
|
|
}
|
|
|
|
|
|
//---------------------------------------------------------------------------
|
|
// WFP_state_changed
|
|
//---------------------------------------------------------------------------
|
|
|
|
|
|
_FX void WFP_state_changed(_Inout_ void* context, _In_ FWPM_SERVICE_STATE newState)
|
|
{
|
|
KeEnterCriticalRegion();
|
|
|
|
ExAcquireResourceSharedLite(WFP_InitLock, TRUE);
|
|
|
|
if (newState == FWPM_SERVICE_STOP_PENDING)
|
|
WFP_Uninstall_Callbacks();
|
|
else if (newState == FWPM_SERVICE_RUNNING)
|
|
WFP_Install_Callbacks();
|
|
|
|
ExReleaseResourceLite(WFP_InitLock);
|
|
|
|
KeLeaveCriticalRegion();
|
|
}
|
|
|
|
|
|
//---------------------------------------------------------------------------
|
|
// WFP_Install_Callbacks
|
|
//---------------------------------------------------------------------------
|
|
|
|
|
|
_FX BOOLEAN WFP_Install_Callbacks(void)
|
|
{
|
|
if (WFP_engine_handle != NULL)
|
|
return TRUE; // already initialized
|
|
|
|
NTSTATUS status = STATUS_SUCCESS;
|
|
DWORD stage = 0;
|
|
|
|
FWPM_SESSION wdf_session = { 0 };
|
|
BOOLEAN in_transaction = FALSE;
|
|
BOOLEAN callout_registered = FALSE;
|
|
|
|
|
|
// Begin a transaction to the FilterEngine. You must register objects (filter, callouts, sublayers)
|
|
//to the filter engine in the context of a 'transaction'
|
|
wdf_session.flags = FWPM_SESSION_FLAG_DYNAMIC; // <-- Automatically destroys all filters and removes all callouts after this wdf_session ends
|
|
status = FwpmEngineOpen(NULL, RPC_C_AUTHN_WINNT, NULL, &wdf_session, &WFP_engine_handle);
|
|
stage = 0x10; if (!NT_SUCCESS(status)) goto Exit;
|
|
status = FwpmTransactionBegin(WFP_engine_handle, 0);
|
|
stage = 0x20; if (!NT_SUCCESS(status)) goto Exit;
|
|
in_transaction = TRUE;
|
|
|
|
// Register a new sublayer to the filter engine
|
|
status = WFP_RegisterSubLayer();
|
|
stage = 0x30; if (!NT_SUCCESS(status)) goto Exit;
|
|
|
|
//status = WFP_RegisterCallout(&WPF_CALLOUT_GUID_V4, &FWPM_LAYER_ALE_RESOURCE_ASSIGNMENT_V4, &WFP_callout_id_v4, &WFP_filter_id_v4);
|
|
//if (!NT_SUCCESS(status)) goto Exit;
|
|
//status = WFP_RegisterCallout(&WPF_CALLOUT_GUID_V6, &FWPM_LAYER_ALE_RESOURCE_ASSIGNMENT_V6, &WFP_callout_id_v6, &WFP_filter_id_v6);
|
|
//if (!NT_SUCCESS(status)) goto Exit;
|
|
status = WFP_RegisterCallout(&WPF_SEND_CALLOUT_GUID_V4, &FWPM_LAYER_ALE_AUTH_CONNECT_V4, &WFP_send_callout_id_v4, &WFP_send_filter_id_v4);
|
|
stage = 0x41; if (!NT_SUCCESS(status)) goto Exit;
|
|
callout_registered = TRUE;
|
|
status = WFP_RegisterCallout(&WPF_SEND_CALLOUT_GUID_V6, &FWPM_LAYER_ALE_AUTH_CONNECT_V6, &WFP_send_callout_id_v6, &WFP_send_filter_id_v6);
|
|
stage = 0x42; if (!NT_SUCCESS(status)) goto Exit;
|
|
status = WFP_RegisterCallout(&WPF_RECV_CALLOUT_GUID_V4, &FWPM_LAYER_ALE_AUTH_RECV_ACCEPT_V4, &WFP_recv_callout_id_v4, &WFP_recv_filter_id_v4);
|
|
stage = 0x43; if (!NT_SUCCESS(status)) goto Exit;
|
|
status = WFP_RegisterCallout(&WPF_RECV_CALLOUT_GUID_V6, &FWPM_LAYER_ALE_AUTH_RECV_ACCEPT_V6, &WFP_recv_callout_id_v6, &WFP_recv_filter_id_v6);
|
|
stage = 0x44; if (!NT_SUCCESS(status)) goto Exit;
|
|
|
|
// note: we could also setup FWPM_LAYER_ALE_AUTH_LISTEN_V4 but since we block all accepts we don't have to
|
|
|
|
|
|
// Commit transaction to the Filter Engine
|
|
status = FwpmTransactionCommit(WFP_engine_handle);
|
|
stage = 0x50; if (!NT_SUCCESS(status)) goto Exit;
|
|
in_transaction = FALSE;
|
|
|
|
// Cleanup and handle any errors
|
|
Exit:
|
|
if (!NT_SUCCESS(status)) {
|
|
DbgPrint("Sbie WFP initialization failed, stage %02x, status 0x%08x\r\n", stage, status);
|
|
|
|
if (in_transaction == TRUE) {
|
|
FwpmTransactionAbort(WFP_engine_handle);
|
|
_Analysis_assume_lock_not_held_(WFP_engine_handle); // Potential leak if "FwpmTransactionAbort" fails
|
|
}
|
|
if (callout_registered) {
|
|
FwpsCalloutUnregisterById(WFP_send_callout_id_v4);
|
|
FwpsCalloutUnregisterById(WFP_send_callout_id_v6);
|
|
FwpsCalloutUnregisterById(WFP_recv_callout_id_v4);
|
|
FwpsCalloutUnregisterById(WFP_recv_callout_id_v6);
|
|
}
|
|
if (WFP_engine_handle) {
|
|
FwpmEngineClose(WFP_engine_handle);
|
|
WFP_engine_handle = NULL;
|
|
}
|
|
|
|
return FALSE;
|
|
}
|
|
|
|
DbgPrint("Sbie WFP initialized successfully\r\n");
|
|
return TRUE;
|
|
}
|
|
|
|
|
|
//---------------------------------------------------------------------------
|
|
// WFP_Uninstall_Callbacks
|
|
//---------------------------------------------------------------------------
|
|
|
|
|
|
_FX void WFP_Uninstall_Callbacks(void)
|
|
{
|
|
if (WFP_engine_handle == NULL)
|
|
return; // not initialized
|
|
|
|
NTSTATUS status = STATUS_SUCCESS;
|
|
UNICODE_STRING symlink = { 0 };
|
|
|
|
//status = FwpsCalloutUnregisterById(WFP_callout_id_v4);
|
|
//if (!NT_SUCCESS(status)) DbgPrint("Failed to unregister callout, status: 0x%08x\r\n", status);
|
|
//status = FwpsCalloutUnregisterById(WFP_callout_id_v6);
|
|
//if (!NT_SUCCESS(status)) DbgPrint("Failed to unregister callout, status: 0x%08x\r\n", status);
|
|
status = FwpsCalloutUnregisterById(WFP_send_callout_id_v4);
|
|
//if (!NT_SUCCESS(status)) DbgPrint("Failed to unregister callout, status: 0x%08x\r\n", status);
|
|
status = FwpsCalloutUnregisterById(WFP_send_callout_id_v6);
|
|
//if (!NT_SUCCESS(status)) DbgPrint("Failed to unregister callout, status: 0x%08x\r\n", status);
|
|
status = FwpsCalloutUnregisterById(WFP_recv_callout_id_v4);
|
|
//if (!NT_SUCCESS(status)) DbgPrint("Failed to unregister callout, status: 0x%08x\r\n", status);
|
|
status = FwpsCalloutUnregisterById(WFP_recv_callout_id_v6);
|
|
//if (!NT_SUCCESS(status)) DbgPrint("Failed to unregister callout, status: 0x%08x\r\n", status);
|
|
|
|
// Close handle to the WFP Filter Engine
|
|
if (WFP_engine_handle) {
|
|
FwpmEngineClose(WFP_engine_handle);
|
|
WFP_engine_handle = NULL;
|
|
}
|
|
|
|
DbgPrint("Sbie WFP uninitialized\r\n");
|
|
}
|
|
|
|
|
|
//---------------------------------------------------------------------------
|
|
// WFP_RegisterSubLayer
|
|
//---------------------------------------------------------------------------
|
|
|
|
|
|
NTSTATUS WFP_RegisterSubLayer()
|
|
{
|
|
NTSTATUS status = STATUS_SUCCESS;
|
|
|
|
FWPM_SUBLAYER sublayer = { 0 };
|
|
sublayer.subLayerKey = WFP_SUBLAYER_GUID;
|
|
sublayer.displayData.name = WFP_SUBLAYER_NAME;
|
|
sublayer.displayData.description = WFP_SUBLAYER_DESCRIPTION;
|
|
sublayer.flags = 0;
|
|
sublayer.weight = 0x0f;
|
|
status = FwpmSubLayerAdd(WFP_engine_handle, &sublayer, NULL);
|
|
if (!NT_SUCCESS(status)){
|
|
//DbgPrint("Failed to register Sbie sublayer, status 0x%08x\r\n", status);
|
|
goto Exit;
|
|
}
|
|
|
|
Exit:
|
|
return status;
|
|
}
|
|
|
|
|
|
//---------------------------------------------------------------------------
|
|
// WFP_RegisterCallout
|
|
//---------------------------------------------------------------------------
|
|
|
|
|
|
NTSTATUS WFP_RegisterCallout(const GUID* calloutKey, const GUID* applicableLayer, UINT32* callout_id, UINT64* filter_id)
|
|
{
|
|
NTSTATUS status = STATUS_SUCCESS;
|
|
|
|
if (WFP_engine_handle == NULL)
|
|
return STATUS_INVALID_HANDLE;
|
|
|
|
// Register a new Callout with the Filter Engine using the provided callout functions
|
|
FWPS_CALLOUT s_callout = { 0 };
|
|
s_callout.calloutKey = *calloutKey;
|
|
s_callout.classifyFn = WFP_classify;
|
|
s_callout.notifyFn = WFP_notify;
|
|
s_callout.flowDeleteFn = WFP_flow_delete;
|
|
status = FwpsCalloutRegister((void *)Api_DeviceObject, &s_callout, callout_id);
|
|
if (!NT_SUCCESS(status)){
|
|
//DbgPrint("Failed to register callout functions for sbie callout, status 0x%08x\r\n", status);
|
|
goto Exit;
|
|
}
|
|
|
|
// Setup a FWPM_CALLOUT structure to store/track the state associated with the FWPS_CALLOUT
|
|
FWPM_CALLOUT m_callout = { 0 };
|
|
m_callout.displayData.name = WFP_CALLOUT_NAME;
|
|
m_callout.displayData.description = WFP_CALLOUT_DESCRIPTION;
|
|
m_callout.calloutKey = *calloutKey;
|
|
m_callout.applicableLayer = *applicableLayer;
|
|
m_callout.flags = 0;
|
|
status = FwpmCalloutAdd(WFP_engine_handle, &m_callout, NULL, NULL);
|
|
if (!NT_SUCCESS(status)){
|
|
//DbgPrint("Failed to register sbie callout, status 0x%08x\r\n", status);
|
|
goto Exit;
|
|
}
|
|
|
|
// Setup a FWPM_FILTER structure
|
|
FWPM_FILTER filter = { 0 };
|
|
filter.displayData.name = WFP_FILTER_NAME;
|
|
filter.displayData.description = WFP_FILTER_DESCRIPTION;
|
|
filter.action.type = FWP_ACTION_CALLOUT_TERMINATING; // Says this filter's callout MUST make a block/permit decision
|
|
filter.subLayerKey = WFP_SUBLAYER_GUID;
|
|
filter.weight.type = FWP_UINT8;
|
|
filter.weight.uint8 = 0xf; // The weight of this filter within its sublayer
|
|
filter.numFilterConditions = 0; // If you specify 0, this filter invokes its callout for all traffic in its layer
|
|
filter.layerKey = *applicableLayer; // This layer must match the layer that ExampleCallout is registered to
|
|
filter.action.calloutKey = *calloutKey;
|
|
status = FwpmFilterAdd(WFP_engine_handle, &filter, NULL, filter_id);
|
|
if (status != STATUS_SUCCESS){
|
|
//DbgPrint("Failed to register Sbie filter, status 0x%08x\r\n", status);
|
|
goto Exit;
|
|
}
|
|
|
|
Exit:
|
|
return status;
|
|
}
|
|
|
|
|
|
//---------------------------------------------------------------------------
|
|
// WFP_FreeRules
|
|
//---------------------------------------------------------------------------
|
|
|
|
|
|
void WFP_FreeRules(LIST* NetFwRules)
|
|
{
|
|
// clear Firewall Rules
|
|
while (1) {
|
|
NETFW_RULE* rule = List_Head(NetFwRules);
|
|
if (!rule)
|
|
break;
|
|
List_Remove(NetFwRules, rule);
|
|
NetFw_FreeRule(rule);
|
|
}
|
|
}
|
|
|
|
|
|
//---------------------------------------------------------------------------
|
|
// WFP_LoadRules
|
|
//---------------------------------------------------------------------------
|
|
|
|
|
|
BOOLEAN WFP_LoadRules(LIST* NetFwRules, PROCESS* proc)
|
|
{
|
|
List_Init(NetFwRules);
|
|
|
|
for (ULONG index = 0; ; ++index) {
|
|
|
|
const WCHAR *value = Conf_Get(proc->box->name, L"NetworkAccess", index);
|
|
if (! value)
|
|
break;
|
|
|
|
ULONG level = -1;
|
|
const WCHAR *found_value = Process_MatchImageAndGetValue(proc->box, value, proc->image_name, &level);
|
|
if (!found_value)
|
|
continue;
|
|
|
|
NETFW_RULE* rule = NetFw_AllocRule(NULL, level);
|
|
if (!rule) {
|
|
Log_Msg_Process(MSG_1201, NULL, NULL, proc->box->session_id, proc->pid);
|
|
return FALSE;
|
|
}
|
|
|
|
NetFw_ParseRule(rule, found_value);
|
|
|
|
NetFw_AddRule(NetFwRules, rule);
|
|
}
|
|
|
|
return TRUE;
|
|
}
|
|
|
|
|
|
//---------------------------------------------------------------------------
|
|
// WFP_InitProcess
|
|
//---------------------------------------------------------------------------
|
|
|
|
|
|
BOOLEAN WFP_InitProcess(PROCESS* proc)
|
|
{
|
|
if (!WFP_Enabled)
|
|
return TRUE; // nothing to do
|
|
|
|
if (WFP_engine_handle == NULL)
|
|
return FALSE; // WFP was not ready report failure, cancel process creation
|
|
|
|
BOOLEAN ok = TRUE;
|
|
KIRQL irql;
|
|
|
|
WFP_PROCESS* wfp_proc = WFP_Alloc(NULL, sizeof(WFP_PROCESS));
|
|
if (wfp_proc == NULL) {
|
|
ok = FALSE;
|
|
goto finish;
|
|
}
|
|
memzero(wfp_proc, sizeof(WFP_PROCESS));
|
|
|
|
wfp_proc->ProcessId = proc->pid;
|
|
|
|
List_Init(&wfp_proc->NetFwRules);
|
|
|
|
#ifdef _WIN64
|
|
irql = KeAcquireSpinLockRaiseToDpc(&WFP_MapLock);
|
|
#else
|
|
KeAcquireSpinLock(&WFP_MapLock, &irql);
|
|
#endif
|
|
|
|
if(map_get(&WFP_Processes, wfp_proc->ProcessId) != NULL)
|
|
ok = FALSE; // that would be a duplicate, should not happen, but in case
|
|
else if (!map_insert(&WFP_Processes, wfp_proc->ProcessId, wfp_proc, 0))
|
|
ok = FALSE;
|
|
|
|
KeReleaseSpinLock(&WFP_MapLock, irql);
|
|
|
|
finish:
|
|
if(!ok && wfp_proc)
|
|
WFP_Free(NULL, wfp_proc);
|
|
return ok;
|
|
}
|
|
|
|
|
|
//---------------------------------------------------------------------------
|
|
// WFP_UpdateProcess
|
|
//---------------------------------------------------------------------------
|
|
|
|
|
|
BOOLEAN WFP_UpdateProcess(PROCESS* proc)
|
|
{
|
|
if (!WFP_Enabled)
|
|
return TRUE; // nothing to do
|
|
|
|
BOOLEAN ok = FALSE;
|
|
KIRQL irql;
|
|
WFP_PROCESS* wfp_proc;
|
|
HANDLE processId = proc->pid;
|
|
BOOLEAN LogTraffic = FALSE;
|
|
BOOLEAN BlockInternet = FALSE;
|
|
LIST NewNetFwRules, OldNetFwRules;
|
|
|
|
List_Init(&NewNetFwRules);
|
|
List_Init(&OldNetFwRules);
|
|
|
|
LogTraffic = Process_GetTraceFlag(proc, L"NetFwTrace") != 0;
|
|
|
|
if (!proc->AllowInternetAccess) { // if the process isn't exempted check the config
|
|
|
|
BlockInternet = !Process_GetConf_bool(proc, L"AllowNetworkAccess", TRUE);
|
|
}
|
|
|
|
if (!BlockInternet) {
|
|
|
|
ok = WFP_LoadRules(&NewNetFwRules, proc);
|
|
|
|
if (!ok) {
|
|
memcpy(&OldNetFwRules, &NewNetFwRules, sizeof(LIST));
|
|
BlockInternet = TRUE; // on roule failure we lust block everything
|
|
// todo: log error
|
|
}
|
|
}
|
|
|
|
#ifdef _WIN64
|
|
irql = KeAcquireSpinLockRaiseToDpc(&WFP_MapLock);
|
|
#else
|
|
KeAcquireSpinLock(&WFP_MapLock, &irql);
|
|
#endif
|
|
|
|
wfp_proc = map_get(&WFP_Processes, processId);
|
|
if (wfp_proc) {
|
|
|
|
wfp_proc->LogTraffic = LogTraffic;
|
|
wfp_proc->BlockInternet = BlockInternet;
|
|
|
|
if (ok) {
|
|
memcpy(&OldNetFwRules, &wfp_proc->NetFwRules, sizeof(LIST));
|
|
memcpy(&wfp_proc->NetFwRules, &NewNetFwRules, sizeof(LIST));
|
|
}
|
|
ok = TRUE;
|
|
}
|
|
else {
|
|
if (ok) {
|
|
memcpy(&OldNetFwRules, &NewNetFwRules, sizeof(LIST));
|
|
}
|
|
ok = FALSE;
|
|
}
|
|
|
|
KeReleaseSpinLock(&WFP_MapLock, irql);
|
|
|
|
WFP_FreeRules(&OldNetFwRules);
|
|
|
|
return ok;
|
|
}
|
|
|
|
|
|
//---------------------------------------------------------------------------
|
|
// WFP_DeleteProcess
|
|
//---------------------------------------------------------------------------
|
|
|
|
|
|
void WFP_DeleteProcess(PROCESS* proc)
|
|
{
|
|
if (!WFP_Enabled)
|
|
return; // nothing to do
|
|
|
|
KIRQL irql;
|
|
WFP_PROCESS* wfp_proc = NULL;
|
|
HANDLE processId = proc->pid;
|
|
|
|
#ifdef _WIN64
|
|
irql = KeAcquireSpinLockRaiseToDpc(&WFP_MapLock);
|
|
#else
|
|
KeAcquireSpinLock(&WFP_MapLock, &irql);
|
|
#endif
|
|
|
|
map_take(&WFP_Processes, processId, &wfp_proc, 0);
|
|
|
|
KeReleaseSpinLock(&WFP_MapLock, irql);
|
|
|
|
if (wfp_proc)
|
|
{
|
|
WFP_FreeRules(&wfp_proc->NetFwRules);
|
|
WFP_Free(NULL, wfp_proc);
|
|
}
|
|
}
|
|
|
|
//---------------------------------------------------------------------------
|
|
// WFP_classify
|
|
//---------------------------------------------------------------------------
|
|
|
|
|
|
void WFP_classify(
|
|
const FWPS_INCOMING_VALUES * inFixedValues,
|
|
const FWPS_INCOMING_METADATA_VALUES * inMetaValues,
|
|
void * layerData,
|
|
const void * classifyContext,
|
|
const FWPS_FILTER * filter,
|
|
UINT64 flowContext,
|
|
FWPS_CLASSIFY_OUT * classifyOut)
|
|
{
|
|
// https://docs.microsoft.com/en-us/windows-hardware/drivers/network/metadata-fields-at-each-filtering-layer
|
|
|
|
UNREFERENCED_PARAMETER(inMetaValues);
|
|
UNREFERENCED_PARAMETER(layerData);
|
|
UNREFERENCED_PARAMETER(classifyContext);
|
|
UNREFERENCED_PARAMETER(flowContext);
|
|
UNREFERENCED_PARAMETER(filter);
|
|
|
|
//
|
|
// We don't have the necessary right to alter the classify, exit.
|
|
//
|
|
if ((classifyOut->rights & FWPS_RIGHT_ACTION_WRITE) == 0)
|
|
{
|
|
return;
|
|
}
|
|
|
|
if (FWPS_IS_METADATA_FIELD_PRESENT(inMetaValues, FWPS_METADATA_FIELD_PROCESS_ID))
|
|
{
|
|
UINT localAddrIndex, remoteAddrIndex, localPortIndex, remotePortIndex, protocolIndex;
|
|
GetNetwork5TupleIndexesForLayer(inFixedValues->layerId,
|
|
&localAddrIndex, &remoteAddrIndex, &localPortIndex, &remotePortIndex,&protocolIndex);
|
|
|
|
|
|
int protocol = inFixedValues->incomingValue[protocolIndex].value.uint8;
|
|
IP_ADDRESS remote_ip;
|
|
if ((filter->filterId == WFP_send_filter_id_v6) || (filter->filterId == WFP_recv_filter_id_v6))
|
|
{
|
|
//remote_ip.Type = AF_INET6;
|
|
//UINT8* local_address = inFixedValues->incomingValue[localAddrIndex].value.byteArray16->byteArray16;
|
|
UINT8* remote_address = inFixedValues->incomingValue[remoteAddrIndex].value.byteArray16->byteArray16;
|
|
|
|
memcpy(remote_ip.Data, remote_address, 16);
|
|
}
|
|
else
|
|
{
|
|
//remote_ip.Type = AF_INET;
|
|
//UINT32 local_address = inFixedValues->incomingValue[localAddrIndex].value.uint32;
|
|
UINT32 remote_address = inFixedValues->incomingValue[remoteAddrIndex].value.uint32;
|
|
|
|
// IPv4-mapped IPv6 addresses, eg. ::FFFF:192.168.0.1
|
|
remote_ip.Data32[0] = 0;
|
|
remote_ip.Data32[1] = 0;
|
|
remote_ip.Data32[2] = 0xFFFF0000;
|
|
remote_ip.Data32[3] = _ntohl(remote_address); // to network order, as ipv6 is also in network order
|
|
//*((ULONG*)remote_ip.Data) = _ntohl(remote_address);
|
|
}
|
|
//UINT16 local_port = inFixedValues->incomingValue[localPortIndex].value.uint16;
|
|
UINT16 remote_port = inFixedValues->incomingValue[remotePortIndex].value.uint16;
|
|
|
|
|
|
BOOLEAN log = FALSE;
|
|
BOOLEAN block = FALSE;
|
|
|
|
|
|
KIRQL irql;
|
|
WFP_PROCESS* wfp_proc;
|
|
HANDLE processId = (HANDLE)inMetaValues->processId;
|
|
|
|
#ifdef _WIN64
|
|
irql = KeAcquireSpinLockRaiseToDpc(&WFP_MapLock);
|
|
#else
|
|
KeAcquireSpinLock(&WFP_MapLock, &irql);
|
|
#endif
|
|
|
|
wfp_proc = map_get(&WFP_Processes, processId);
|
|
if (wfp_proc) {
|
|
|
|
log = wfp_proc->LogTraffic;
|
|
block = wfp_proc->BlockInternet;
|
|
|
|
if (!block) {
|
|
|
|
block = NetFw_BlockTraffic(&wfp_proc->NetFwRules, &remote_ip, remote_port, protocol);
|
|
}
|
|
}
|
|
|
|
KeReleaseSpinLock(&WFP_MapLock, irql);
|
|
|
|
|
|
if (log){
|
|
|
|
BOOLEAN send = (filter->filterId == WFP_send_filter_id_v4) || (filter->filterId == WFP_send_filter_id_v6);
|
|
BOOLEAN v6 = (filter->filterId == WFP_send_filter_id_v6) || (filter->filterId == WFP_recv_filter_id_v6);
|
|
|
|
/*
|
|
RtlStringCbPrintfW at DISPATCH_LEVEL or higher can cause a BSOD,
|
|
the issue is with accessing unicode tables, which may be paged out.
|
|
|
|
The documentation for KdPrint() states it this way:
|
|
|
|
<wdk>
|
|
Format
|
|
Specifies a pointer to the format string to print. The Format string
|
|
supports all the printf-style formatting codes. However, the Unicode format
|
|
codes (%C, %S, %lc, %ls, %wc, %ws, and %wZ) can only be used with IRQL =
|
|
PASSIVE_LEVEL.
|
|
</wdk>
|
|
|
|
RtlStringCbPrintfA is technically also not permitted so a better solution needs to be found
|
|
*/
|
|
|
|
char trace_strA[256];
|
|
if (v6) {
|
|
RtlStringCbPrintfA(trace_strA, sizeof(trace_strA), "%s Network Traffic; Port: %u; Prot: %u; IPv6: %02x%02x:%02x%02x:%02x%02x:%02x%02x:%02x%02x:%02x%02x:%02x%02x:%02x%02x",
|
|
send ? "Outgoing " : "Incoming ", remote_port, protocol,
|
|
remote_ip.Data[0], remote_ip.Data[1], remote_ip.Data[2], remote_ip.Data[3], remote_ip.Data[4], remote_ip.Data[5], remote_ip.Data[6], remote_ip.Data[7],
|
|
remote_ip.Data[8], remote_ip.Data[9], remote_ip.Data[10], remote_ip.Data[11], remote_ip.Data[12], remote_ip.Data[13], remote_ip.Data[14], remote_ip.Data[15]);
|
|
}
|
|
else {
|
|
RtlStringCbPrintfA(trace_strA, sizeof(trace_strA), "%s Network Traffic; Port: %u; Prot: %u; IPv4: %d.%d.%d.%d",
|
|
send ? "Outgoing " : "Incoming ", remote_port, protocol,
|
|
remote_ip.Data[12], remote_ip.Data[13], remote_ip.Data[14], remote_ip.Data[15]);
|
|
}
|
|
|
|
WCHAR trace_str[256];
|
|
char* cptr = trace_strA;
|
|
WCHAR* wptr = trace_str;
|
|
while (*cptr != '\0')
|
|
*wptr++ = *cptr++;
|
|
*wptr = L'\0';
|
|
|
|
Session_MonitorPut(MONITOR_NETFW | (block ? MONITOR_DENY : MONITOR_OPEN), trace_str, PsGetCurrentProcessId());
|
|
}
|
|
|
|
if (block) {
|
|
|
|
classifyOut->actionType = FWP_ACTION_BLOCK;
|
|
classifyOut->rights &= ~FWPS_RIGHT_ACTION_WRITE;
|
|
return;
|
|
}
|
|
}
|
|
|
|
classifyOut->actionType = FWP_ACTION_PERMIT;
|
|
return;
|
|
}
|
|
|
|
|
|
//---------------------------------------------------------------------------
|
|
// WFP_notify
|
|
//---------------------------------------------------------------------------
|
|
|
|
|
|
NTSTATUS WFP_notify(
|
|
FWPS_CALLOUT_NOTIFY_TYPE notifyType,
|
|
const GUID * filterKey,
|
|
const FWPS_FILTER * filter)
|
|
{
|
|
UNREFERENCED_PARAMETER(notifyType);
|
|
UNREFERENCED_PARAMETER(filterKey);
|
|
UNREFERENCED_PARAMETER(filter);
|
|
return STATUS_SUCCESS;
|
|
}
|
|
|
|
|
|
//---------------------------------------------------------------------------
|
|
// WFP_flow_delete
|
|
//---------------------------------------------------------------------------
|
|
|
|
|
|
NTSTATUS WFP_flow_delete(UINT16 layerId, UINT32 calloutId, UINT64 flowContext)
|
|
{
|
|
UNREFERENCED_PARAMETER(layerId);
|
|
UNREFERENCED_PARAMETER(calloutId);
|
|
UNREFERENCED_PARAMETER(flowContext);
|
|
return STATUS_SUCCESS;
|
|
}
|
|
|
|
|
|
//---------------------------------------------------------------------------
|
|
// GetNetwork5TupleIndexesForLayer
|
|
//---------------------------------------------------------------------------
|
|
|
|
|
|
void
|
|
GetNetwork5TupleIndexesForLayer(
|
|
_In_ UINT16 layerId,
|
|
_Out_ UINT* localAddressIndex,
|
|
_Out_ UINT* remoteAddressIndex,
|
|
_Out_ UINT* localPortIndex,
|
|
_Out_ UINT* remotePortIndex,
|
|
_Out_ UINT* protocolIndex
|
|
)
|
|
{
|
|
switch (layerId)
|
|
{
|
|
case FWPS_LAYER_ALE_AUTH_CONNECT_V4:
|
|
*localAddressIndex = FWPS_FIELD_ALE_AUTH_CONNECT_V4_IP_LOCAL_ADDRESS;
|
|
*remoteAddressIndex = FWPS_FIELD_ALE_AUTH_CONNECT_V4_IP_REMOTE_ADDRESS;
|
|
*localPortIndex = FWPS_FIELD_ALE_AUTH_CONNECT_V4_IP_LOCAL_PORT;
|
|
*remotePortIndex = FWPS_FIELD_ALE_AUTH_CONNECT_V4_IP_REMOTE_PORT;
|
|
*protocolIndex = FWPS_FIELD_ALE_AUTH_CONNECT_V4_IP_PROTOCOL;
|
|
break;
|
|
case FWPS_LAYER_ALE_AUTH_CONNECT_V6:
|
|
*localAddressIndex = FWPS_FIELD_ALE_AUTH_CONNECT_V6_IP_LOCAL_ADDRESS;
|
|
*remoteAddressIndex = FWPS_FIELD_ALE_AUTH_CONNECT_V6_IP_REMOTE_ADDRESS;
|
|
*localPortIndex = FWPS_FIELD_ALE_AUTH_CONNECT_V6_IP_LOCAL_PORT;
|
|
*remotePortIndex = FWPS_FIELD_ALE_AUTH_CONNECT_V6_IP_REMOTE_PORT;
|
|
*protocolIndex = FWPS_FIELD_ALE_AUTH_CONNECT_V6_IP_PROTOCOL;
|
|
break;
|
|
case FWPS_LAYER_ALE_AUTH_RECV_ACCEPT_V4:
|
|
*localAddressIndex = FWPS_FIELD_ALE_AUTH_RECV_ACCEPT_V4_IP_LOCAL_ADDRESS;
|
|
*remoteAddressIndex = FWPS_FIELD_ALE_AUTH_RECV_ACCEPT_V4_IP_REMOTE_ADDRESS;
|
|
*localPortIndex = FWPS_FIELD_ALE_AUTH_RECV_ACCEPT_V4_IP_LOCAL_PORT;
|
|
*remotePortIndex = FWPS_FIELD_ALE_AUTH_RECV_ACCEPT_V4_IP_REMOTE_PORT;
|
|
*protocolIndex = FWPS_FIELD_ALE_AUTH_RECV_ACCEPT_V4_IP_PROTOCOL;
|
|
break;
|
|
case FWPS_LAYER_ALE_AUTH_RECV_ACCEPT_V6:
|
|
*localAddressIndex = FWPS_FIELD_ALE_AUTH_RECV_ACCEPT_V6_IP_LOCAL_ADDRESS;
|
|
*remoteAddressIndex = FWPS_FIELD_ALE_AUTH_RECV_ACCEPT_V6_IP_REMOTE_ADDRESS;
|
|
*localPortIndex = FWPS_FIELD_ALE_AUTH_RECV_ACCEPT_V6_IP_LOCAL_PORT;
|
|
*remotePortIndex = FWPS_FIELD_ALE_AUTH_RECV_ACCEPT_V6_IP_REMOTE_PORT;
|
|
*protocolIndex = FWPS_FIELD_ALE_AUTH_RECV_ACCEPT_V6_IP_PROTOCOL;
|
|
break;
|
|
case FWPS_LAYER_OUTBOUND_TRANSPORT_V4:
|
|
*localAddressIndex = FWPS_FIELD_OUTBOUND_TRANSPORT_V4_IP_LOCAL_ADDRESS;
|
|
*remoteAddressIndex = FWPS_FIELD_OUTBOUND_TRANSPORT_V4_IP_REMOTE_ADDRESS;
|
|
*localPortIndex = FWPS_FIELD_OUTBOUND_TRANSPORT_V4_IP_LOCAL_PORT;
|
|
*remotePortIndex = FWPS_FIELD_OUTBOUND_TRANSPORT_V4_IP_REMOTE_PORT;
|
|
*protocolIndex = FWPS_FIELD_OUTBOUND_TRANSPORT_V4_IP_PROTOCOL;
|
|
break;
|
|
case FWPS_LAYER_OUTBOUND_TRANSPORT_V6:
|
|
*localAddressIndex = FWPS_FIELD_OUTBOUND_TRANSPORT_V6_IP_LOCAL_ADDRESS;
|
|
*remoteAddressIndex = FWPS_FIELD_OUTBOUND_TRANSPORT_V6_IP_REMOTE_ADDRESS;
|
|
*localPortIndex = FWPS_FIELD_OUTBOUND_TRANSPORT_V6_IP_LOCAL_PORT;
|
|
*remotePortIndex = FWPS_FIELD_OUTBOUND_TRANSPORT_V6_IP_REMOTE_PORT;
|
|
*protocolIndex = FWPS_FIELD_OUTBOUND_TRANSPORT_V6_IP_PROTOCOL;
|
|
break;
|
|
case FWPS_LAYER_INBOUND_TRANSPORT_V4:
|
|
*localAddressIndex = FWPS_FIELD_INBOUND_TRANSPORT_V4_IP_LOCAL_ADDRESS;
|
|
*remoteAddressIndex = FWPS_FIELD_INBOUND_TRANSPORT_V4_IP_REMOTE_ADDRESS;
|
|
*localPortIndex = FWPS_FIELD_INBOUND_TRANSPORT_V4_IP_LOCAL_PORT;
|
|
*remotePortIndex = FWPS_FIELD_INBOUND_TRANSPORT_V4_IP_REMOTE_PORT;
|
|
*protocolIndex = FWPS_FIELD_INBOUND_TRANSPORT_V4_IP_PROTOCOL;
|
|
break;
|
|
case FWPS_LAYER_INBOUND_TRANSPORT_V6:
|
|
*localAddressIndex = FWPS_FIELD_INBOUND_TRANSPORT_V6_IP_LOCAL_ADDRESS;
|
|
*remoteAddressIndex = FWPS_FIELD_INBOUND_TRANSPORT_V6_IP_REMOTE_ADDRESS;
|
|
*localPortIndex = FWPS_FIELD_INBOUND_TRANSPORT_V6_IP_LOCAL_PORT;
|
|
*remotePortIndex = FWPS_FIELD_INBOUND_TRANSPORT_V6_IP_REMOTE_PORT;
|
|
*protocolIndex = FWPS_FIELD_INBOUND_TRANSPORT_V6_IP_PROTOCOL;
|
|
break;
|
|
default:
|
|
*localAddressIndex = -1;
|
|
*remoteAddressIndex = -1;
|
|
*localPortIndex = -1;
|
|
*remotePortIndex = -1;
|
|
*protocolIndex = -1;
|
|
NT_ASSERT(0);
|
|
}
|
|
}
|