From 5553441a21c27d50423957068b8136dbae092d71 Mon Sep 17 00:00:00 2001 From: Nodir Temirkhodjaev Date: Tue, 7 Nov 2017 07:28:25 +0500 Subject: [PATCH] Driver: Refactor filters provider. --- src/common/fortprov.c | 114 +++++++++++++++++++++++------------------- src/driver/fortdrv.c | 93 +++++++++++++++++++++++++++------- src/ui/fortcommon.cpp | 2 +- 3 files changed, 139 insertions(+), 70 deletions(-) diff --git a/src/common/fortprov.c b/src/common/fortprov.c index 98806858..c560dc1f 100644 --- a/src/common/fortprov.c +++ b/src/common/fortprov.c @@ -1,11 +1,5 @@ /* Fort Firewall Driver Provider (Un)Registration */ -typedef struct fort_prov_data { - UINT32 version : 24; - UINT32 is_boot : 1; -} FORT_PROV_DATA, *PFORT_PROV_DATA; - - static DWORD fort_prov_open (HANDLE *enginep) { @@ -19,8 +13,13 @@ fort_prov_close (HANDLE engine) } static void -fort_prov_delete (HANDLE engine) +fort_prov_unregister (void) { + HANDLE engine; + + if (fort_prov_open(&engine)) + return; + FwpmFilterDeleteByKey0(engine, (GUID *) &FORT_GUID_FILTER_CONNECT_V4); FwpmFilterDeleteByKey0(engine, (GUID *) &FORT_GUID_FILTER_ACCEPT_V4); FwpmFilterDeleteByKey0(engine, (GUID *) &FORT_GUID_FILTER_FLOW_V4); @@ -30,61 +29,37 @@ fort_prov_delete (HANDLE engine) FwpmCalloutDeleteByKey0(engine, (GUID *) &FORT_GUID_CALLOUT_ACCEPT_V4); FwpmCalloutDeleteByKey0(engine, (GUID *) &FORT_GUID_CALLOUT_FLOW_V4); FwpmProviderDeleteByKey0(engine, (GUID *) &FORT_GUID_PROVIDER); + + fort_prov_close(engine); } static void -fort_prov_unregister (void) +fort_prov_flow_unregister (void) { HANDLE engine; if (fort_prov_open(&engine)) return; - fort_prov_delete(engine); + FwpmFilterDeleteByKey0(engine, (GUID *) &FORT_GUID_FILTER_FLOW_V4); fort_prov_close(engine); } static DWORD -fort_prov_register (BOOL is_boot, BOOL *is_bootp) +fort_prov_register (BOOL is_boot) { - FWPM_PROVIDER0 *old_provider, provider; + FWPM_PROVIDER0 provider; FWPM_CALLOUT0 ocallout4, icallout4, fcallout4; FWPM_SUBLAYER0 sublayer; - FWPM_FILTER0 ofilter4, ifilter4, ffilter4; + FWPM_FILTER0 ofilter4, ifilter4; HANDLE engine; - FORT_PROV_DATA provider_data; UINT32 filter_flags; DWORD status; if ((status = fort_prov_open(&engine))) goto end; - if (!(status = FwpmProviderGetByKey0( - engine, (GUID *) &FORT_GUID_PROVIDER, &old_provider))) { - PFORT_PROV_DATA old_provider_data = - (PFORT_PROV_DATA) old_provider->providerData.data; - - if (old_provider_data) { - provider_data = *old_provider_data; - } - - FwpmFreeMemory0((void **) &old_provider); - - if (old_provider_data) { - is_boot = is_bootp ? provider_data.is_boot : is_boot; - - if (is_boot == provider_data.is_boot - && provider_data.version == APP_VERSION) - goto end_close; - - fort_prov_delete(engine); - } - } - - provider_data.version = APP_VERSION; - provider_data.is_boot = is_boot; - filter_flags = is_boot ? 0 : FWPM_FILTER_FLAG_PERMIT_IF_CALLOUT_UNREGISTERED; RtlZeroMemory(&provider, sizeof(FWPM_PROVIDER0)); @@ -93,8 +68,6 @@ fort_prov_register (BOOL is_boot, BOOL *is_bootp) 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; @@ -143,6 +116,34 @@ fort_prov_register (BOOL is_boot, BOOL *is_bootp) ifilter4.action.type = FWP_ACTION_CALLOUT_UNKNOWN; ifilter4.action.calloutKey = FORT_GUID_CALLOUT_ACCEPT_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 = FwpmTransactionCommit0(engine))) { + FwpmTransactionAbort0(engine); + } + + fort_prov_close(engine); + + end: + return status; +} + +static DWORD +fort_prov_flow_register (void) +{ + FWPM_FILTER0 ffilter4; + HANDLE engine; + DWORD status; + + if ((status = fort_prov_open(&engine))) + goto end; + RtlZeroMemory(&ffilter4, sizeof(FWPM_FILTER0)); ffilter4.filterKey = FORT_GUID_FILTER_FLOW_V4; ffilter4.layerKey = FWPM_LAYER_STREAM_V4; @@ -153,29 +154,38 @@ fort_prov_register (BOOL is_boot, BOOL *is_bootp) 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); } - end_close: fort_prov_close(engine); - if (is_bootp) { - *is_bootp = is_boot; - } - end: return status; } +static BOOL +fort_prov_is_boot (void) +{ + HANDLE engine; + BOOL is_boot = FALSE; + + if (!fort_prov_open(&engine)) { + FWPM_PROVIDER0 *provider; + + if (!FwpmProviderGetByKey0(engine, (GUID *) &FORT_GUID_PROVIDER, &provider)) { + is_boot = (provider->flags & FWPM_PROVIDER_FLAG_PERSISTENT); + + FwpmFreeMemory0((void **) &provider); + } + + fort_prov_close(engine); + } + + return is_boot; +} + static DWORD fort_prov_reauth (void) { diff --git a/src/driver/fortdrv.c b/src/driver/fortdrv.c index ced9b074..f967090d 100644 --- a/src/driver/fortdrv.c +++ b/src/driver/fortdrv.c @@ -290,20 +290,18 @@ fort_callout_install (PDEVICE_OBJECT device) return status; } - if (g_device->conf_flags.log_stat) { - /* IPv4 flow callout */ - c.calloutKey = FORT_GUID_CALLOUT_FLOW_V4; - c.classifyFn = fort_callout_flow_v4; + /* 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; + 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; - } + 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; @@ -328,6 +326,61 @@ fort_callout_remove (void) } } +static NTSTATUS +fort_callout_force_reauth (PDEVICE_OBJECT device, + FORT_CONF_FLAGS old_conf_flags) +{ + const FORT_CONF_FLAGS conf_flags = g_device->conf_flags; + BOOL prov_changed = FALSE; + NTSTATUS status; + + // Check provider filters + if (old_conf_flags.prov_boot != conf_flags.prov_boot) { + fort_prov_unregister(); + + old_conf_flags.log_stat = 0; // flow filter unregistered + + status = fort_prov_register(conf_flags.prov_boot); + if (!NT_SUCCESS(status)) { + DbgPrintEx(DPFLTR_IHVNETWORK_ID, DPFLTR_ERROR_LEVEL, + "FORT: Prov. Register: Error: %d\n", status); + return status; + } + + prov_changed = TRUE; + } + + // Check flow filter + if (old_conf_flags.log_stat != conf_flags.log_stat) { + if (old_conf_flags.log_stat) { + fort_prov_flow_unregister(); + } + + if (conf_flags.log_stat) { + status = fort_prov_flow_register(); + if (!NT_SUCCESS(status)) { + DbgPrintEx(DPFLTR_IHVNETWORK_ID, DPFLTR_ERROR_LEVEL, + "FORT: Prov. Flow Register: Error: %d\n", status); + return status; + } + } + + prov_changed = TRUE; + } + + // Check reauth filter + if (!prov_changed) { + status = fort_prov_reauth(); + if (!NT_SUCCESS(status)) { + DbgPrintEx(DPFLTR_IHVNETWORK_ID, DPFLTR_ERROR_LEVEL, + "FORT: Prov. Reauth: Error: %d\n", status); + return status; + } + } + + return STATUS_SUCCESS; +} + static NTSTATUS fort_device_create (PDEVICE_OBJECT device, PIRP irp) { @@ -356,6 +409,7 @@ fort_device_cleanup (PDEVICE_OBJECT device, PIRP irp) UNUSED(device); fort_callout_remove(); + fort_prov_reauth(); fort_conf_ref_set(NULL); @@ -399,8 +453,10 @@ fort_device_control (PDEVICE_OBJECT device, PIRP irp) if (conf_ref == NULL) { status = STATUS_INSUFFICIENT_RESOURCES; } else { + const FORT_CONF_FLAGS old_conf_flags = g_device->conf_flags; + fort_conf_ref_set(conf_ref); - status = fort_prov_reauth(); + status = fort_callout_force_reauth(device, old_conf_flags); } } break; @@ -411,8 +467,10 @@ fort_device_control (PDEVICE_OBJECT device, PIRP irp) if (conf_flags->driver_version == FORT_DRIVER_VERSION && len == sizeof(FORT_CONF_FLAGS)) { + const FORT_CONF_FLAGS old_conf_flags = g_device->conf_flags; + fort_conf_ref_flags_set(conf_flags); - status = fort_prov_reauth(); + status = fort_callout_force_reauth(device, old_conf_flags); } break; } @@ -530,11 +588,12 @@ DriverEntry (PDRIVER_OBJECT driver, PUNICODE_STRING reg_path) // Register filters provider { - BOOL is_boot = FALSE; - - status = fort_prov_register(FALSE, &is_boot); + const BOOL is_boot = fort_prov_is_boot(); g_device->conf_flags.prov_boot = is_boot; + + fort_prov_unregister(); // to upgrade from old version + status = fort_prov_register(is_boot); } } } diff --git a/src/ui/fortcommon.cpp b/src/ui/fortcommon.cpp index 1f2b7954..c34d50bf 100644 --- a/src/ui/fortcommon.cpp +++ b/src/ui/fortcommon.cpp @@ -100,7 +100,7 @@ bool FortCommon::confAppBlocked(const void *drvConf, uint FortCommon::provRegister(bool isBoot) { - return fort_prov_register(isBoot, NULL); + return fort_prov_register(isBoot); } void FortCommon::provUnregister()