Driver: Refactor filters provider.

This commit is contained in:
Nodir Temirkhodjaev 2017-11-07 07:28:25 +05:00
parent 20889f3664
commit 5553441a21
3 changed files with 139 additions and 70 deletions

View File

@ -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)
{

View File

@ -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);
}
}
}

View File

@ -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()