diff --git a/src/common/common.h b/src/common/common.h index 07f7d2ad..68d0915d 100644 --- a/src/common/common.h +++ b/src/common/common.h @@ -6,6 +6,8 @@ #define INITGUID #include +/* 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 diff --git a/src/common/fortconf.c b/src/common/fortconf.c index 5536f465..fa4ee286 100644 --- a/src/common/fortconf.c +++ b/src/common/fortconf.c @@ -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 diff --git a/src/common/fortprov.c b/src/common/fortprov.c index e58c5255..a7daa574 100644 --- a/src/common/fortprov.c +++ b/src/common/fortprov.c @@ -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); } diff --git a/src/driver/fortdrv.c b/src/driver/fortdrv.c index 17babd42..94975024 100644 --- a/src/driver/fortdrv.c +++ b/src/driver/fortdrv.c @@ -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, ¬ify); - } 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; } } } diff --git a/src/driver/fortstat.c b/src/driver/fortstat.c new file mode 100644 index 00000000..f0c22b89 --- /dev/null +++ b/src/driver/fortstat.c @@ -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) +{ +} diff --git a/src/ui/fortcommon.cpp b/src/ui/fortcommon.cpp index e17e2b2d..1f2b7954 100644 --- a/src/ui/fortcommon.cpp +++ b/src/ui/fortcommon.cpp @@ -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, ¬ifyUser); - - if (notify) { - *notify = notifyUser; - } - - return blocked; + return fort_conf_app_blocked(conf, len, (const char *) p); } uint FortCommon::provRegister(bool isBoot) diff --git a/src/ui/fortcommon.h b/src/ui/fortcommon.h index 0b124f9a..fd7dd397 100644 --- a/src/ui/fortcommon.h +++ b/src/ui/fortcommon.h @@ -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();