Ejemplo n.º 1
0
/*
 * Add a persistent sublayer with specified uuid.
 */
static DWORD
add_sublayer(GUID uuid)
{
    FWPM_SESSION0 session;
    HANDLE engine = NULL;
    DWORD err = 0;
    FWPM_SUBLAYER0 sublayer;

    memset(&session, 0, sizeof(session));
    memset(&sublayer, 0, sizeof(sublayer));

    err = FwpmEngineOpen0(NULL, RPC_C_AUTHN_WINNT, NULL, &session, &engine);
    if (err != ERROR_SUCCESS)
    {
        goto out;
    }

    sublayer.subLayerKey = uuid;
    sublayer.displayData.name = FIREWALL_NAME;
    sublayer.displayData.description = FIREWALL_NAME;
    sublayer.flags = 0;
    sublayer.weight = 0x100;

    /* Add sublayer to the session */
    err = FwpmSubLayerAdd0(engine, &sublayer, NULL);

out:
    if (engine)
    {
        FwpmEngineClose0(engine);
    }
    return err;
}
Ejemplo n.º 2
0
void
DDProxyUnregisterCallouts()
{
   FwpmEngineClose0(gEngineHandle);
   gEngineHandle = NULL;

   FwpsCalloutUnregisterById0(gCalloutIdV6);
   FwpsCalloutUnregisterById0(gCalloutIdV4);

   FwpsCalloutUnregisterById0(gFlowEstablishedCalloutIdV6);
   FwpsCalloutUnregisterById0(gFlowEstablishedCalloutIdV4);
}
Ejemplo n.º 3
0
DWORD
delete_block_dns_filters(HANDLE engine_handle)
{
    DWORD err = 0;
    /*
     * For dynamic sessions closing the engine removes all filters added in the session
     */
    if (engine_handle)
    {
        err = FwpmEngineClose0(engine_handle);
    }
    return err;
}
Ejemplo n.º 4
0
void monitor_destroy(void) {
	monitor_stop();

	if (g.session) {
		FWP_VALUE0 val = {0};
		val.type = FWP_UINT32;
		val.uint32 = 0;
		FwpmEngineSetOption0(g.session, FWPM_ENGINE_COLLECT_NET_EVENTS, &val);

		FwpmEngineClose0(g.session);
	}

	SecureZeroMemory(&g, sizeof(g));
}
Ejemplo n.º 5
0
void
TLInspectUnregisterCallouts()
{
    FwpmEngineClose0(gEngineHandle);
    gEngineHandle = NULL;

    FwpsCalloutUnregisterById0(gOutboundTlCalloutIdV6);
    FwpsCalloutUnregisterById0(gOutboundTlCalloutIdV4);
    FwpsCalloutUnregisterById0(gInboundTlCalloutIdV6);
    FwpsCalloutUnregisterById0(gInboundTlCalloutIdV4);

    FwpsCalloutUnregisterById0(gAleConnectCalloutIdV6);
    FwpsCalloutUnregisterById0(gAleConnectCalloutIdV4);
    FwpsCalloutUnregisterById0(gAleRecvAcceptCalloutIdV6);
    FwpsCalloutUnregisterById0(gAleRecvAcceptCalloutIdV4);
}
Ejemplo n.º 6
0
NTSTATUS
DDProxyRegisterCallouts(
   IN void* deviceObject
   )
/* ++

   This function registers dynamic callouts and filters that intercept UDP or
   non-error ICMP traffic at WFP FWPM_LAYER_DATAGRAM_DATA_V{4|6} and 
   FWPM_LAYER_ALE_FLOW_ESTABLISHED_V{4|6} layers.

   Callouts and filters will be removed during DriverUnload.

-- */
{
   NTSTATUS status = STATUS_SUCCESS;
   FWPM_SUBLAYER0 DDProxySubLayer;

   BOOLEAN engineOpened = FALSE;
   BOOLEAN inTransaction = FALSE;

   FWPM_SESSION0 session = {0};

   session.flags = FWPM_SESSION_FLAG_DYNAMIC;

   status = FwpmEngineOpen0(
                NULL,
                RPC_C_AUTHN_WINNT,
                NULL,
                &session,
                &gEngineHandle
                );
   if (!NT_SUCCESS(status))
   {
      goto Exit;
   }
   engineOpened = TRUE;

   status = FwpmTransactionBegin0(gEngineHandle, 0);
   if (!NT_SUCCESS(status))
   {
      goto Exit;
   }
   inTransaction = TRUE;

   RtlZeroMemory(&DDProxySubLayer, sizeof(FWPM_SUBLAYER0)); 

   DDProxySubLayer.subLayerKey = DD_PROXY_SUBLAYER;
   DDProxySubLayer.displayData.name = L"Datagram-Data Proxy Sub-Layer";
   DDProxySubLayer.displayData.description = 
      L"Sub-Layer for use by Datagram-Data Proxy callouts";
   DDProxySubLayer.flags = 0;
   DDProxySubLayer.weight = FWP_EMPTY; // auto-weight.;

   status = FwpmSubLayerAdd0(gEngineHandle, &DDProxySubLayer, NULL);
   if (!NT_SUCCESS(status))
   {
      goto Exit;
   }

   status = DDProxyRegisterFlowEstablishedCallouts(
               &FWPM_LAYER_ALE_FLOW_ESTABLISHED_V4,
               &DD_PROXY_FLOW_ESTABLISHED_CALLOUT_V4,
               deviceObject,
               &gFlowEstablishedCalloutIdV4
               );
   if (!NT_SUCCESS(status))
   {
      goto Exit;
   }

   status = DDProxyRegisterFlowEstablishedCallouts(
               &FWPM_LAYER_ALE_FLOW_ESTABLISHED_V6,
               &DD_PROXY_FLOW_ESTABLISHED_CALLOUT_V6,
               deviceObject,
               &gFlowEstablishedCalloutIdV6
               );
   if (!NT_SUCCESS(status))
   {
      goto Exit;
   }

   status = DDProxyRegisterDatagramDataCallouts(
               &FWPM_LAYER_DATAGRAM_DATA_V4,
               &DD_PROXY_CALLOUT_V4,
               deviceObject,
               &gCalloutIdV4
               );
   if (!NT_SUCCESS(status))
   {
      goto Exit;
   }

   status = DDProxyRegisterDatagramDataCallouts(
               &FWPM_LAYER_DATAGRAM_DATA_V6,
               &DD_PROXY_CALLOUT_V6,
               deviceObject,
               &gCalloutIdV6
               );
   if (!NT_SUCCESS(status))
   {
      goto Exit;
   }

   status = FwpmTransactionCommit0(gEngineHandle);
   if (!NT_SUCCESS(status))
   {
      goto Exit;
   }
   inTransaction = FALSE;

Exit:

   if (!NT_SUCCESS(status))
   {
      if (inTransaction)
      {
         FwpmTransactionAbort0(gEngineHandle);
      }
      if (engineOpened)
      {
         FwpmEngineClose0(gEngineHandle);
         gEngineHandle = NULL;
      }
   }

   return status;
}
Ejemplo n.º 7
0
DWORD
GetMatchingEvents(
   __in UINT32 mins,
   __in ADDRESS_FAMILY version,
   __in_opt SOCKADDR_STORAGE* remoteAddr,
   __out FWPM_NET_EVENT0*** matchedEvents,
   __out UINT32* numMatchedEvents
)
/*++

Routine Description:

     This routine creates and fills an event enumeration template, and 
     retrieve events matching the template using WFP API. The diagnostic
     events API is used only in this function

Arguments:

    mins - period in minutes for which events should be retrieved going 
            back from current time.

	version - IP version 

    remoteAddr - pointer to IP address which should match the remote 
            address in events.

    matchedEvents - pointer to an array of pointers to events that have 
            period and/or remote address matching those specified.

    numMatchedEvents - pointer to the number of events matching the
            criterion.

Return Value:

    DWORD - If the function succeeds, the return value is ERROR_SUCCESS.

--*/
{
   DWORD result = ERROR_SUCCESS;
   UINT32 filterCondCount = 0;
   FWPM_NET_EVENT_ENUM_TEMPLATE0 eventTemplate;
   FWPM_FILTER_CONDITION0 filterConditions[NUM_FILTER_CONDITIONS] = {0};
   HANDLE fwpEngineHandle = NULL;
   HANDLE enumHandle = NULL;
   BOOLEAN engineOpen = FALSE;
   SYSTEMTIME curTimeSys;

   //-----------------------------------------
   // The period in which the event happened is set to current sytem time.
   GetSystemTime(&curTimeSys);
   if (!(SystemTimeToFileTime(&curTimeSys, &(eventTemplate.endTime))))
   {
      wprintf(L"Error in converting system time to file time.\n");
      result = GetLastError();
      CHECK_RESULT(result);
   }

   //-----------------------------------------
   // Set the lower end of the period in which events are of interest
   if (0 == mins) 
   {
      eventTemplate.startTime.dwLowDateTime = 0;
      eventTemplate.startTime.dwHighDateTime = 0; 
   } 
   else 
   {
      ULARGE_INTEGER filetime;
      ULONGLONG period;
      
      filetime.LowPart = eventTemplate.endTime.dwLowDateTime;
      filetime.HighPart = eventTemplate.endTime.dwHighDateTime;
      period = ((ULONGLONG)mins)*MIN_FACTOR;
      if (filetime.QuadPart > period)
      {
         filetime.QuadPart -= period;
      }
      else
      {
         filetime.QuadPart = 0;
      }
      eventTemplate.startTime.dwLowDateTime  = filetime.LowPart;
      eventTemplate.startTime.dwHighDateTime = filetime.HighPart;
   }

   //-----------------------------------------
   // Set the filter condition to look for events matching the remote address
   if (remoteAddr)
   {
	   if (AF_INET == version)
	   {
		   SOCKADDR_IN* ipV4Addr = (SOCKADDR_IN*)remoteAddr;
	   
		  filterConditions[filterCondCount].fieldKey = 
											  FWPM_CONDITION_IP_REMOTE_ADDRESS;
		  filterConditions[filterCondCount].matchType = FWP_MATCH_EQUAL;
		  filterConditions[filterCondCount].conditionValue.type = FWP_UINT32;
		  filterConditions[filterCondCount].conditionValue.uint32 = 
											  ntohl(ipV4Addr->sin_addr.s_addr);
		  filterCondCount++;
	   }
	   else if (AF_INET6 == version)
	   {
		   SOCKADDR_IN6* ipV6Addr = (SOCKADDR_IN6*)remoteAddr;
	   
		  filterConditions[filterCondCount].fieldKey = 
							FWPM_CONDITION_IP_REMOTE_ADDRESS;
		  filterConditions[filterCondCount].matchType = FWP_MATCH_EQUAL;
		  filterConditions[filterCondCount].conditionValue.type = 
							FWP_BYTE_ARRAY16_TYPE;
		  filterConditions[filterCondCount].conditionValue.byteArray16 = 
							(FWP_BYTE_ARRAY16 *)(ipV6Addr->sin6_addr.s6_bytes);
		  filterCondCount++;
	   }
   }

   //-----------------------------------------
   // Fill the event enumeration template
   eventTemplate.numFilterConditions = filterCondCount;
   eventTemplate.filterCondition = filterConditions;

   //-----------------------------------------
   // Open a session to the filter engine
   result = FwpmEngineOpen0(
            NULL, 
            RPC_C_AUTHN_WINNT, 
            NULL,
            NULL, 
            &fwpEngineHandle
            );
   CHECK_RESULT(result);

   //-----------------------------------------
   // Create an enumeration handle based on event template
   result = FwpmNetEventCreateEnumHandle0(
            fwpEngineHandle,
            &eventTemplate,
            &enumHandle
            );
   CHECK_RESULT(result);

   //-----------------------------------------
   // Get the events from enumeration
   result = FwpmNetEventEnum0(
            fwpEngineHandle,
            enumHandle, 
            INFINITE, 
            matchedEvents, 
            numMatchedEvents
            );
   CHECK_RESULT(result);
   //
   // fallthrough
   //
cleanup:
   //-----------------------------------------
   // Destroy enumeration handle
   if (enumHandle)   
   {
      FwpmNetEventDestroyEnumHandle0(fwpEngineHandle, enumHandle);
   }
   
   //-----------------------------------------
   // Close session after destroying enumeration handle
   if (fwpEngineHandle)   
   {
      FwpmEngineClose0(fwpEngineHandle);
   }
   
   return result;
}
Ejemplo n.º 8
0
NTSTATUS
TLInspectRegisterCallouts(
    IN void* deviceObject
)
/* ++

   This function registers dynamic callouts and filters that intercept
   transport traffic at ALE AUTH_CONNECT/AUTH_RECV_ACCEPT and
   INBOUND/OUTBOUND transport layers.

   Callouts and filters will be removed during DriverUnload.

-- */
{
    NTSTATUS status = STATUS_SUCCESS;
    FWPM_SUBLAYER0 TLInspectSubLayer;

    BOOLEAN engineOpened = FALSE;
    BOOLEAN inTransaction = FALSE;

    FWPM_SESSION0 session = {0};

    session.flags = FWPM_SESSION_FLAG_DYNAMIC;

    status = FwpmEngineOpen0(
                 NULL,
                 RPC_C_AUTHN_WINNT,
                 NULL,
                 &session,
                 &gEngineHandle
             );
    if (!NT_SUCCESS(status))
    {
        goto Exit;
    }
    engineOpened = TRUE;

    status = FwpmTransactionBegin0(gEngineHandle, 0);
    if (!NT_SUCCESS(status))
    {
        goto Exit;
    }
    inTransaction = TRUE;

    RtlZeroMemory(&TLInspectSubLayer, sizeof(FWPM_SUBLAYER0));

    TLInspectSubLayer.subLayerKey = TL_INSPECT_SUBLAYER;
    TLInspectSubLayer.displayData.name = L"Transport Inspect Sub-Layer";
    TLInspectSubLayer.displayData.description =
        L"Sub-Layer for use by Transport Inspect callouts";
    TLInspectSubLayer.flags = 0;
    TLInspectSubLayer.weight = 0; // must be less than the weight of
    // FWPM_SUBLAYER_UNIVERSAL to be
    // compatible with Vista's IpSec
    // implementation.

    status = FwpmSubLayerAdd0(gEngineHandle, &TLInspectSubLayer, NULL);
    if (!NT_SUCCESS(status))
    {
        goto Exit;
    }

    //if (configInspectRemoteAddrV4 != NULL)
    {
        /*
           status = TLInspectRegisterALEClassifyCallouts(
                       &FWPM_LAYER_ALE_AUTH_CONNECT_V4,
                       &TL_INSPECT_ALE_CONNECT_CALLOUT_V4,
                       deviceObject,
                       &gAleConnectCalloutIdV4
                       );
           if (!NT_SUCCESS(status))
           {
              goto Exit;
           }

           status = TLInspectRegisterALEClassifyCallouts(
                       &FWPM_LAYER_ALE_AUTH_RECV_ACCEPT_V4,
                       &TL_INSPECT_ALE_RECV_ACCEPT_CALLOUT_V4,
                       deviceObject,
                       &gAleRecvAcceptCalloutIdV4
                       );
           if (!NT_SUCCESS(status))
           {
              goto Exit;
           }
        */

        status = TLInspectRegisterTransportCallouts(
                     &FWPM_LAYER_OUTBOUND_TRANSPORT_V4,
                     &TL_INSPECT_OUTBOUND_TRANSPORT_CALLOUT_V4,
                     deviceObject,
                     &gOutboundTlCalloutIdV4
                 );
        if (!NT_SUCCESS(status))
        {
            goto Exit;
        }

        status = TLInspectRegisterTransportCallouts(
                     &FWPM_LAYER_INBOUND_TRANSPORT_V4,
                     &TL_INSPECT_INBOUND_TRANSPORT_CALLOUT_V4,
                     deviceObject,
                     &gInboundTlCalloutIdV4
                 );
        if (!NT_SUCCESS(status))
        {
            goto Exit;
        }
    }
    /*
       if (configInspectRemoteAddrV6 != NULL)
       {
          status = TLInspectRegisterALEClassifyCallouts(
                      &FWPM_LAYER_ALE_AUTH_CONNECT_V6,
                      &TL_INSPECT_ALE_CONNECT_CALLOUT_V6,
                      deviceObject,
                      &gAleConnectCalloutIdV6
                      );
          if (!NT_SUCCESS(status))
          {
             goto Exit;
          }

          status = TLInspectRegisterALEClassifyCallouts(
                      &FWPM_LAYER_ALE_AUTH_RECV_ACCEPT_V6,
                      &TL_INSPECT_ALE_RECV_ACCEPT_CALLOUT_V6,
                      deviceObject,
                      &gAleRecvAcceptCalloutIdV6
                      );
          if (!NT_SUCCESS(status))
          {
             goto Exit;
          }

          status = TLInspectRegisterTransportCallouts(
                      &FWPM_LAYER_OUTBOUND_TRANSPORT_V6,
                      &TL_INSPECT_OUTBOUND_TRANSPORT_CALLOUT_V6,
                      deviceObject,
                      &gOutboundTlCalloutIdV6
                      );
          if (!NT_SUCCESS(status))
          {
             goto Exit;
          }

          status = TLInspectRegisterTransportCallouts(
                      &FWPM_LAYER_INBOUND_TRANSPORT_V6,
                      &TL_INSPECT_INBOUND_TRANSPORT_CALLOUT_V6,
                      deviceObject,
                      &gInboundTlCalloutIdV6
                      );
          if (!NT_SUCCESS(status))
          {
             goto Exit;
          }
       }
    */
    status = FwpmTransactionCommit0(gEngineHandle);
    if (!NT_SUCCESS(status))
    {
        goto Exit;
    }
    inTransaction = FALSE;

Exit:

    if (!NT_SUCCESS(status))
    {
        if (inTransaction)
        {
            FwpmTransactionAbort0(gEngineHandle);
        }
        if (engineOpened)
        {
            FwpmEngineClose0(gEngineHandle);
            gEngineHandle = NULL;
        }
    }

    return status;
}
Ejemplo n.º 9
0
DWORD
add_block_dns_filters(HANDLE *engine_handle,
                      int index,
                      const WCHAR *exe_path,
                      block_dns_msg_handler_t msg_handler
                      )
{
    FWPM_SESSION0 session = {0};
    FWPM_SUBLAYER0 *sublayer_ptr = NULL;
    NET_LUID tapluid;
    UINT64 filterid;
    FWP_BYTE_BLOB *openvpnblob = NULL;
    FWPM_FILTER0 Filter = {0};
    FWPM_FILTER_CONDITION0 Condition[2] = {0};
    DWORD err = 0;

    if (!msg_handler)
    {
        msg_handler = default_msg_handler;
    }

    /* Add temporary filters which don't survive reboots or crashes. */
    session.flags = FWPM_SESSION_FLAG_DYNAMIC;

    *engine_handle = NULL;

    err = FwpmEngineOpen0(NULL, RPC_C_AUTHN_WINNT, NULL, &session, engine_handle);
    CHECK_ERROR(err, "FwpEngineOpen: open fwp session failed");
    msg_handler(0, "Block_DNS: WFP engine opened");

    /* Check sublayer exists and add one if it does not. */
    if (FwpmSubLayerGetByKey0(*engine_handle, &OPENVPN_BLOCK_OUTSIDE_DNS_SUBLAYER, &sublayer_ptr)
        == ERROR_SUCCESS)
    {
        msg_handler(0, "Block_DNS: Using existing sublayer");
        FwpmFreeMemory0((void **)&sublayer_ptr);
    }
    else
    {  /* Add a new sublayer -- as another process may add it in the meantime,
        * do not treat "already exists" as an error */
        err = add_sublayer(OPENVPN_BLOCK_OUTSIDE_DNS_SUBLAYER);

        if (err == FWP_E_ALREADY_EXISTS || err == ERROR_SUCCESS)
        {
            msg_handler(0, "Block_DNS: Added a persistent sublayer with pre-defined UUID");
        }
        else
        {
            CHECK_ERROR(err, "add_sublayer: failed to add persistent sublayer");
        }
    }

    err = ConvertInterfaceIndexToLuid(index, &tapluid);
    CHECK_ERROR(err, "Convert interface index to luid failed");

    err = FwpmGetAppIdFromFileName0(exe_path, &openvpnblob);
    CHECK_ERROR(err, "Get byte blob for openvpn executable name failed");

    /* Prepare filter. */
    Filter.subLayerKey = OPENVPN_BLOCK_OUTSIDE_DNS_SUBLAYER;
    Filter.displayData.name = FIREWALL_NAME;
    Filter.weight.type = FWP_UINT8;
    Filter.weight.uint8 = 0xF;
    Filter.filterCondition = Condition;
    Filter.numFilterConditions = 2;

    /* First filter. Permit IPv4 DNS queries from OpenVPN itself. */
    Filter.layerKey = FWPM_LAYER_ALE_AUTH_CONNECT_V4;
    Filter.action.type = FWP_ACTION_PERMIT;

    Condition[0].fieldKey = FWPM_CONDITION_IP_REMOTE_PORT;
    Condition[0].matchType = FWP_MATCH_EQUAL;
    Condition[0].conditionValue.type = FWP_UINT16;
    Condition[0].conditionValue.uint16 = 53;

    Condition[1].fieldKey = FWPM_CONDITION_ALE_APP_ID;
    Condition[1].matchType = FWP_MATCH_EQUAL;
    Condition[1].conditionValue.type = FWP_BYTE_BLOB_TYPE;
    Condition[1].conditionValue.byteBlob = openvpnblob;

    err = FwpmFilterAdd0(*engine_handle, &Filter, NULL, &filterid);
    CHECK_ERROR(err, "Add filter to permit IPv4 port 53 traffic from OpenVPN failed");

    /* Second filter. Permit IPv6 DNS queries from OpenVPN itself. */
    Filter.layerKey = FWPM_LAYER_ALE_AUTH_CONNECT_V6;

    err = FwpmFilterAdd0(*engine_handle, &Filter, NULL, &filterid);
    CHECK_ERROR(err, "Add filter to permit IPv6 port 53 traffic from OpenVPN failed");

    msg_handler(0, "Block_DNS: Added permit filters for exe_path");

    /* Third filter. Block all IPv4 DNS queries. */
    Filter.layerKey = FWPM_LAYER_ALE_AUTH_CONNECT_V4;
    Filter.action.type = FWP_ACTION_BLOCK;
    Filter.weight.type = FWP_EMPTY;
    Filter.numFilterConditions = 1;

    err = FwpmFilterAdd0(*engine_handle, &Filter, NULL, &filterid);
    CHECK_ERROR(err, "Add filter to block IPv4 DNS traffic failed");

    /* Forth filter. Block all IPv6 DNS queries. */
    Filter.layerKey = FWPM_LAYER_ALE_AUTH_CONNECT_V6;

    err = FwpmFilterAdd0(*engine_handle, &Filter, NULL, &filterid);
    CHECK_ERROR(err, "Add filter to block IPv6 DNS traffic failed");

    msg_handler(0, "Block_DNS: Added block filters for all interfaces");

    /* Fifth filter. Permit IPv4 DNS queries from TAP.
     * Use a non-zero weight so that the permit filters get higher priority
     * over the block filter added with automatic weighting */

    Filter.weight.type = FWP_UINT8;
    Filter.weight.uint8 = 0xE;
    Filter.layerKey = FWPM_LAYER_ALE_AUTH_CONNECT_V4;
    Filter.action.type = FWP_ACTION_PERMIT;
    Filter.numFilterConditions = 2;

    Condition[1].fieldKey = FWPM_CONDITION_IP_LOCAL_INTERFACE;
    Condition[1].matchType = FWP_MATCH_EQUAL;
    Condition[1].conditionValue.type = FWP_UINT64;
    Condition[1].conditionValue.uint64 = &tapluid.Value;

    err = FwpmFilterAdd0(*engine_handle, &Filter, NULL, &filterid);
    CHECK_ERROR(err, "Add filter to permit IPv4 DNS traffic through TAP failed");

    /* Sixth filter. Permit IPv6 DNS queries from TAP.
     * Use same weight as IPv4 filter */
    Filter.layerKey = FWPM_LAYER_ALE_AUTH_CONNECT_V6;

    err = FwpmFilterAdd0(*engine_handle, &Filter, NULL, &filterid);
    CHECK_ERROR(err, "Add filter to permit IPv6 DNS traffic through TAP failed");

    msg_handler(0, "Block_DNS: Added permit filters for TAP interface");

out:

    if (openvpnblob)
    {
        FwpmFreeMemory0((void **)&openvpnblob);
    }

    if (err && *engine_handle)
    {
        FwpmEngineClose0(*engine_handle);
        *engine_handle = NULL;
    }

    return err;
}