Driver: Prepare flow stats.

This commit is contained in:
Nodir Temirkhodjaev 2017-11-05 09:40:11 +05:00
parent d9dc2288c7
commit 51c2beec63
7 changed files with 126 additions and 65 deletions

View File

@ -6,6 +6,8 @@
#define INITGUID
#include <guiddef.h>
/* GUID-s generated by guidgen.exe */
/* {012B3999-B791-463E-918C-C32B53E9350E} */
DEFINE_GUID(FORT_GUID_PROVIDER,
0x12b3999, 0xb791, 0x463e, 0x91, 0x8c, 0xc3, 0x2b, 0x53, 0xe9, 0x35, 0xe);
@ -18,6 +20,10 @@ DEFINE_GUID(FORT_GUID_CALLOUT_CONNECT_V4,
DEFINE_GUID(FORT_GUID_CALLOUT_ACCEPT_V4,
0xced9c0fc, 0xdf22, 0x4f39, 0x91, 0x85, 0xb4, 0x35, 0x72, 0x6c, 0xab, 0xb2);
/* {1F50005D-CDBC-42A0-A0C0-53E43081FABE} */
DEFINE_GUID(FORT_GUID_CALLOUT_FLOW_V4,
0x1f50005d, 0xcdbc, 0x42a0, 0xa0, 0xc0, 0x53, 0xe4, 0x30, 0x81, 0xfa, 0xbe);
/* {AFA06CD5-4942-4FDF-8A4A-2EDEB25BBECE} */
DEFINE_GUID(FORT_GUID_SUBLAYER,
0xafa06cd5, 0x4942, 0x4fdf, 0x8a, 0x4a, 0x2e, 0xde, 0xb2, 0x5b, 0xbe, 0xce);
@ -30,6 +36,10 @@ DEFINE_GUID(FORT_GUID_FILTER_CONNECT_V4,
DEFINE_GUID(FORT_GUID_FILTER_ACCEPT_V4,
0x544a3e25, 0x7beb, 0x4970, 0x88, 0xef, 0xb4, 0xbc, 0xa2, 0xce, 0x24, 0x82);
/* {ED0F2527-A787-4CA2-9493-C96320422FCF} */
DEFINE_GUID(FORT_GUID_FILTER_FLOW_V4,
0xed0f2527, 0xa787, 0x4ca2, 0x94, 0x93, 0xc9, 0x63, 0x20, 0x42, 0x2f, 0xcf);
#define FORT_DEVICE_NAME "\\\\.\\fortfw"
#define FORT_DEVICE_TYPE 0xD000

View File

@ -103,7 +103,7 @@ fort_conf_app_index (UINT32 path_len, const char *path, UINT32 count,
static BOOL
fort_conf_app_blocked (const PFORT_CONF conf,
UINT32 path_len, const char *path, BOOL *notify)
UINT32 path_len, const char *path)
{
const char *data = (const char *) conf + conf->data_off;
const int app_index = fort_conf_app_index(path_len, path, conf->apps_n,
@ -117,11 +117,7 @@ fort_conf_app_blocked (const PFORT_CONF conf,
const BOOL app_perm_allowed = (app_perm & conf->app_perms_allow_mask);
const BOOL app_allowed = conf->flags.app_allow_all ? TRUE : app_perm_allowed;
const BOOL blocked = app_blocked && !app_allowed;
*notify = blocked && conf->flags.log_blocked;
return blocked;
return app_blocked && !app_allowed;
}
static void

View File

@ -23,9 +23,11 @@ fort_prov_delete (HANDLE engine)
{
FwpmFilterDeleteByKey0(engine, (GUID *) &FORT_GUID_FILTER_CONNECT_V4);
FwpmFilterDeleteByKey0(engine, (GUID *) &FORT_GUID_FILTER_ACCEPT_V4);
FwpmFilterDeleteByKey0(engine, (GUID *) &FORT_GUID_FILTER_FLOW_V4);
FwpmSubLayerDeleteByKey0(engine, (GUID *) &FORT_GUID_SUBLAYER);
FwpmCalloutDeleteByKey0(engine, (GUID *) &FORT_GUID_CALLOUT_CONNECT_V4);
FwpmCalloutDeleteByKey0(engine, (GUID *) &FORT_GUID_CALLOUT_ACCEPT_V4);
FwpmCalloutDeleteByKey0(engine, (GUID *) &FORT_GUID_CALLOUT_FLOW_V4);
FwpmProviderDeleteByKey0(engine, (GUID *) &FORT_GUID_PROVIDER);
}
@ -46,9 +48,9 @@ static DWORD
fort_prov_register (BOOL is_boot, BOOL *is_bootp)
{
FWPM_PROVIDER0 *old_provider, provider;
FWPM_CALLOUT0 ocallout4, icallout4;
FWPM_CALLOUT0 ocallout4, icallout4, fcallout4;
FWPM_SUBLAYER0 sublayer;
FWPM_FILTER0 ofilter4, ifilter4;
FWPM_FILTER0 ofilter4, ifilter4, ffilter4;
HANDLE engine;
FORT_PROV_DATA provider_data;
UINT32 filter_flags;
@ -87,30 +89,37 @@ fort_prov_register (BOOL is_boot, BOOL *is_bootp)
RtlZeroMemory(&provider, sizeof(FWPM_PROVIDER0));
provider.flags = is_boot ? FWPM_PROVIDER_FLAG_PERSISTENT : 0;
provider.providerKey = FORT_GUID_PROVIDER;
provider.displayData.name = (wchar_t *) L"FortProvider";
provider.displayData.description = (wchar_t *) L"Fort Firewall Provider";
provider.serviceName = (wchar_t *) L"fortfw";
provider.displayData.name = (PWCHAR) L"FortProvider";
provider.displayData.description = (PWCHAR) L"Fort Firewall Provider";
provider.serviceName = (PWCHAR) L"fortfw";
provider.providerData.size = sizeof(FORT_PROV_DATA);
provider.providerData.data = (UINT8 *) &provider_data;
RtlZeroMemory(&ocallout4, sizeof(FWPM_CALLOUT0));
ocallout4.calloutKey = FORT_GUID_CALLOUT_CONNECT_V4;
ocallout4.displayData.name = (wchar_t *) L"FortCalloutConnect4";
ocallout4.displayData.description = (wchar_t *) L"Fort Firewall Callout Connect V4";
ocallout4.displayData.name = (PWCHAR) L"FortCalloutConnect4";
ocallout4.displayData.description = (PWCHAR) L"Fort Firewall Callout Connect V4";
ocallout4.providerKey = (GUID *) &FORT_GUID_PROVIDER;
ocallout4.applicableLayer = FWPM_LAYER_ALE_AUTH_CONNECT_V4;
RtlZeroMemory(&icallout4, sizeof(FWPM_CALLOUT0));
icallout4.calloutKey = FORT_GUID_CALLOUT_ACCEPT_V4;
icallout4.displayData.name = (wchar_t *) L"FortCalloutAccept4";
icallout4.displayData.description = (wchar_t *) L"Fort Firewall Callout Accept V4";
icallout4.displayData.name = (PWCHAR) L"FortCalloutAccept4";
icallout4.displayData.description = (PWCHAR) L"Fort Firewall Callout Accept V4";
icallout4.providerKey = (GUID *) &FORT_GUID_PROVIDER;
icallout4.applicableLayer = FWPM_LAYER_ALE_AUTH_RECV_ACCEPT_V4;
RtlZeroMemory(&fcallout4, sizeof(FWPM_CALLOUT0));
fcallout4.calloutKey = FORT_GUID_CALLOUT_FLOW_V4;
fcallout4.displayData.name = (PWCHAR) L"FortCalloutFlow4";
fcallout4.displayData.description = (PWCHAR) L"Fort Firewall Callout Flow V4";
fcallout4.providerKey = (GUID *) &FORT_GUID_PROVIDER;
fcallout4.applicableLayer = FWPM_LAYER_STREAM_V4;
RtlZeroMemory(&sublayer, sizeof(FWPM_SUBLAYER0));
sublayer.subLayerKey = FORT_GUID_SUBLAYER;
sublayer.displayData.name = (wchar_t *) L"FortSublayer";
sublayer.displayData.description = (wchar_t *) L"Fort Firewall Sublayer";
sublayer.displayData.name = (PWCHAR) L"FortSublayer";
sublayer.displayData.description = (PWCHAR) L"Fort Firewall Sublayer";
sublayer.providerKey = (GUID *) &FORT_GUID_PROVIDER;
RtlZeroMemory(&ofilter4, sizeof(FWPM_FILTER0));
@ -118,8 +127,8 @@ fort_prov_register (BOOL is_boot, BOOL *is_bootp)
ofilter4.filterKey = FORT_GUID_FILTER_CONNECT_V4;
ofilter4.layerKey = FWPM_LAYER_ALE_AUTH_CONNECT_V4;
ofilter4.subLayerKey = FORT_GUID_SUBLAYER;
ofilter4.displayData.name = (wchar_t *) L"FortFilterConnect4";
ofilter4.displayData.description = (wchar_t *) L"Fort Firewall Connect V4";
ofilter4.displayData.name = (PWCHAR) L"FortFilterConnect4";
ofilter4.displayData.description = (PWCHAR) L"Fort Firewall Filter Connect V4";
ofilter4.action.type = FWP_ACTION_CALLOUT_UNKNOWN;
ofilter4.action.calloutKey = FORT_GUID_CALLOUT_CONNECT_V4;
@ -128,18 +137,29 @@ fort_prov_register (BOOL is_boot, BOOL *is_bootp)
ifilter4.filterKey = FORT_GUID_FILTER_ACCEPT_V4;
ifilter4.layerKey = FWPM_LAYER_ALE_AUTH_RECV_ACCEPT_V4;
ifilter4.subLayerKey = FORT_GUID_SUBLAYER;
ifilter4.displayData.name = (wchar_t *) L"FortFilterAccept4";
ifilter4.displayData.description = (wchar_t *) L"Fort Firewall Accept V4";
ifilter4.displayData.name = (PWCHAR) L"FortFilterAccept4";
ifilter4.displayData.description = (PWCHAR) L"Fort Firewall Filter Accept V4";
ifilter4.action.type = FWP_ACTION_CALLOUT_UNKNOWN;
ifilter4.action.calloutKey = FORT_GUID_CALLOUT_ACCEPT_V4;
RtlZeroMemory(&ffilter4, sizeof(FWPM_FILTER0));
ffilter4.filterKey = FORT_GUID_FILTER_FLOW_V4;
ffilter4.layerKey = FWPM_LAYER_STREAM_V4;
ffilter4.subLayerKey = FORT_GUID_SUBLAYER;
ffilter4.displayData.name = (PWCHAR) L"FortFilterFlow4";
ffilter4.displayData.description = (PWCHAR) L"Fort Firewall Filter Flow V4";
ffilter4.action.type = FWP_ACTION_CALLOUT_INSPECTION;
ffilter4.action.calloutKey = FORT_GUID_CALLOUT_FLOW_V4;
if ((status = FwpmTransactionBegin0(engine, 0))
|| (status = FwpmProviderAdd0(engine, &provider, NULL))
|| (status = FwpmCalloutAdd0(engine, &ocallout4, NULL, NULL))
|| (status = FwpmCalloutAdd0(engine, &icallout4, NULL, NULL))
|| (status = FwpmCalloutAdd0(engine, &fcallout4, NULL, NULL))
|| (status = FwpmSubLayerAdd0(engine, &sublayer, NULL))
|| (status = FwpmFilterAdd0(engine, &ofilter4, NULL, NULL))
|| (status = FwpmFilterAdd0(engine, &ifilter4, NULL, NULL))
|| (status = FwpmFilterAdd0(engine, &ffilter4, NULL, NULL))
|| (status = FwpmTransactionCommit0(engine))) {
FwpmTransactionAbort0(engine);
}

View File

@ -19,6 +19,7 @@
#include "../common/fortconf.c"
#include "../common/fortprov.c"
#include "fortbuf.c"
#include "fortstat.c"
typedef struct fort_conf_ref {
UINT32 volatile refcount;
@ -27,12 +28,11 @@ typedef struct fort_conf_ref {
} FORT_CONF_REF, *PFORT_CONF_REF;
typedef struct fort_device {
BOOL active : 1;
BOOL prov_boot : 1;
BOOL filter_enabled : 1;
FORT_CONF_FLAGS conf_flags;
UINT32 connect4_id;
UINT32 accept4_id;
UINT32 flow4_id;
FORT_BUFFER buffer;
@ -108,12 +108,7 @@ fort_conf_ref_set (PFORT_CONF_REF conf_ref)
g_device->conf_ref = conf_ref;
if (conf_ref != NULL) {
const FORT_CONF_FLAGS conf_flags = conf_ref->conf.flags;
g_device->prov_boot = conf_flags.prov_boot;
g_device->filter_enabled = conf_flags.filter_enabled;
} else {
g_device->filter_enabled = FALSE;
g_device->conf_flags = conf_ref->conf.flags;
}
}
KeReleaseSpinLock(&g_device->conf_lock, irq);
@ -134,12 +129,11 @@ fort_conf_ref_flags_set (const PFORT_CONF_FLAGS conf_flags)
if (conf_ref) {
PFORT_CONF conf = &conf_ref->conf;
g_device->prov_boot = conf_flags->prov_boot;
g_device->filter_enabled = conf_flags->filter_enabled;
conf->flags = *conf_flags;
fort_conf_app_perms_mask_init(conf);
g_device->conf_flags = conf->flags;
}
}
KeReleaseSpinLock(&g_device->conf_lock, irq);
@ -154,24 +148,25 @@ fort_callout_classify_v4 (const FWPS_INCOMING_VALUES0 *inFixedValues,
FWPS_CLASSIFY_OUT0 *classifyOut,
int flagsField, int localIpField, int remoteIpField)
{
const FORT_CONF_FLAGS conf_flags = g_device->conf_flags;
PFORT_CONF_REF conf_ref;
UINT32 flags;
UINT32 remote_ip;
UINT32 path_len;
PVOID path;
BOOL blocked, notify;
BOOL blocked;
UNUSED(layerData);
UNUSED(flowContext);
if (!g_device->filter_enabled) {
if (!conf_flags.filter_enabled) {
return;
}
conf_ref = fort_conf_ref_take();
if (conf_ref == NULL) {
if (g_device->prov_boot)
if (conf_flags.prov_boot)
goto block;
return;
}
@ -181,13 +176,9 @@ fort_callout_classify_v4 (const FWPS_INCOMING_VALUES0 *inFixedValues,
path_len = inMetaValues->processPath->size - sizeof(WCHAR); // chop terminating zero
path = inMetaValues->processPath->data;
if (!(flags & FWP_CONDITION_FLAG_IS_LOOPBACK)
&& fort_conf_ip_included(&conf_ref->conf, remote_ip)) {
blocked = fort_conf_app_blocked(&conf_ref->conf, path_len, path, &notify);
} else {
blocked = FALSE;
notify = FALSE;
}
blocked = !(flags & FWP_CONDITION_FLAG_IS_LOOPBACK)
&& fort_conf_ip_included(&conf_ref->conf, remote_ip)
&& fort_conf_app_blocked(&conf_ref->conf, path_len, path);
fort_conf_ref_put(conf_ref);
@ -196,10 +187,14 @@ fort_callout_classify_v4 (const FWPS_INCOMING_VALUES0 *inFixedValues,
if ((filter->flags & FWPS_FILTER_FLAG_CLEAR_ACTION_RIGHT)) {
classifyOut->rights &= ~FWPS_RIGHT_ACTION_WRITE;
}
if (conf_flags.log_stat) {
fort_stat_flow_associate(inMetaValues->flowHandle);
}
return;
}
if (notify) {
if (conf_flags.log_blocked) {
PIRP irp = NULL;
NTSTATUS irp_status;
ULONG_PTR info;
@ -265,15 +260,15 @@ fort_callout_install (PDEVICE_OBJECT device)
FWPS_CALLOUT0 c;
NTSTATUS status;
if (g_device->active)
if (g_device->connect4_id) {
return STATUS_SHARING_VIOLATION; // Only one client may connect
}
RtlZeroMemory(&c, sizeof(FWPS_CALLOUT0));
c.notifyFn = fort_callout_notify;
/* IPv4 connect filter */
/* IPv4 connect callout */
c.calloutKey = FORT_GUID_CALLOUT_CONNECT_V4;
c.classifyFn = fort_callout_connect_v4;
@ -284,8 +279,7 @@ fort_callout_install (PDEVICE_OBJECT device)
return status;
}
/* IPv4 accept filter */
/* IPv4 accept callout */
c.calloutKey = FORT_GUID_CALLOUT_ACCEPT_V4;
c.classifyFn = fort_callout_accept_v4;
@ -296,7 +290,19 @@ fort_callout_install (PDEVICE_OBJECT device)
return status;
}
g_device->active = TRUE;
/* IPv4 flow callout */
c.calloutKey = FORT_GUID_CALLOUT_FLOW_V4;
c.classifyFn = fort_callout_flow_v4;
c.flowDeleteFn = fort_callout_flow_delete_v4;
c.flags = FWP_CALLOUT_FLAG_CONDITIONAL_ON_FLOW;
status = FwpsCalloutRegister0(device, &c, &g_device->flow4_id);
if (!NT_SUCCESS(status)) {
DbgPrintEx(DPFLTR_IHVNETWORK_ID, DPFLTR_ERROR_LEVEL,
"FORT: Register Flow V4: Error: %d\n", status);
return status;
}
return STATUS_SUCCESS;
}
@ -306,13 +312,18 @@ fort_callout_remove (void)
{
if (g_device->connect4_id) {
FwpsCalloutUnregisterById0(g_device->connect4_id);
g_device->connect4_id = 0;
}
if (g_device->accept4_id) {
FwpsCalloutUnregisterById0(g_device->accept4_id);
g_device->accept4_id = 0;
}
g_device->active = FALSE;
if (g_device->flow4_id) {
FwpsCalloutUnregisterById0(g_device->flow4_id);
g_device->flow4_id = 0;
}
}
static NTSTATUS
@ -325,9 +336,9 @@ fort_callout_force_reauth (PDEVICE_OBJECT device)
fort_prov_unregister();
// Register
status = fort_prov_register(g_device->prov_boot, NULL);
status = fort_prov_register(g_device->conf_flags.prov_boot, NULL);
if (status == STATUS_SUCCESS) {
if (NT_SUCCESS(status)) {
status = fort_callout_install(device);
}
@ -462,8 +473,9 @@ fort_driver_unload (PDRIVER_OBJECT driver)
if (g_device != NULL) {
fort_buffer_close(&g_device->buffer);
if (!g_device->prov_boot)
if (!g_device->conf_flags.prov_boot) {
fort_prov_unregister();
}
}
RtlInitUnicodeString(&device_link, DOS_DEVICE_NAME);
@ -539,7 +551,7 @@ DriverEntry (PDRIVER_OBJECT driver, PUNICODE_STRING reg_path)
status = fort_prov_register(FALSE, &is_boot);
g_device->prov_boot = is_boot;
g_device->conf_flags.prov_boot = is_boot;
}
}
}

30
src/driver/fortstat.c Normal file
View File

@ -0,0 +1,30 @@
/* Fort Firewall Usage Statistics */
static void
fort_stat_flow_associate(UINT64 flowId)
{
//DbgPrintEx(DPFLTR_IHVNETWORK_ID, DPFLTR_ERROR_LEVEL,
// "FORT: Classify V4: %d %d %d\n", FWPS_IS_METADATA_FIELD_PRESENT(
// inMetaValues, FWPS_METADATA_FIELD_FLOW_HANDLE),
// inMetaValues->flowHandle, (UINT32) flowContext);
//const NTSTATUS status = FwpsFlowAssociateContext0(
// flowId, FWPM_LAYER_STREAM_V4, FORT_GUID_CALLOUT_FLOW_V4, 1);
}
static void
fort_callout_flow_delete_v4 (UINT16 layerId,
UINT32 calloutId,
UINT64 flowContext)
{
}
static void
fort_callout_flow_v4 (const FWPS_INCOMING_VALUES0 *inFixedValues,
const FWPS_INCOMING_METADATA_VALUES0 *inMetaValues,
void *layerData,
const FWPS_FILTER0 *filter,
UINT64 flowContext,
FWPS_CLASSIFY_OUT0 *classifyOut)
{
}

View File

@ -88,21 +88,14 @@ bool FortCommon::confIpInRange(const void *drvConf, quint32 ip,
}
bool FortCommon::confAppBlocked(const void *drvConf,
const QString &kernelPath, bool *notify)
const QString &kernelPath)
{
const PFORT_CONF conf = (const PFORT_CONF) drvConf;
const QString kernelPathLower = kernelPath.toLower();
const int len = kernelPathLower.size() * sizeof(wchar_t);
const wchar_t *p = (const wchar_t *) kernelPathLower.utf16();
BOOL blocked, notifyUser;
blocked = fort_conf_app_blocked(conf, len, (const char *) p, &notifyUser);
if (notify) {
*notify = notifyUser;
}
return blocked;
return fort_conf_app_blocked(conf, len, (const char *) p);
}
uint FortCommon::provRegister(bool isBoot)

View File

@ -33,7 +33,7 @@ public:
static bool confIpInRange(const void *drvConf, quint32 ip,
bool included = false);
static bool confAppBlocked(const void *drvConf,
const QString &kernelPath, bool *notify = nullptr);
const QString &kernelPath);
static uint provRegister(bool isBoot);
static void provUnregister();