diff options
| author | Dave Wilson <[email protected]> | 2015-03-17 19:50:07 -0700 |
|---|---|---|
| committer | Dave Wilson <[email protected]> | 2015-03-17 19:50:07 -0700 |
| commit | 97cf5197cf5b882b2c689d8dc2b555f2edf8f418 (patch) | |
| tree | 46f3701832d70b420eb0fc0eb93261f9da45db3f /network/trans/inspect/sys/utils.c | |
| parent | ef1905bf1e8825bb31120dfb27e0daf3154d859a (diff) | |
Initial publish
Diffstat (limited to 'network/trans/inspect/sys/utils.c')
| -rw-r--r-- | network/trans/inspect/sys/utils.c | 448 |
1 files changed, 448 insertions, 0 deletions
diff --git a/network/trans/inspect/sys/utils.c b/network/trans/inspect/sys/utils.c new file mode 100644 index 00000000..b6cbf0ce --- /dev/null +++ b/network/trans/inspect/sys/utils.c @@ -0,0 +1,448 @@ +/*++ + +Copyright (c) Microsoft Corporation. All rights reserved + +Abstract: + + This file implements the utility/helper functions for use by the classify + functions and worker thread of the Transport Inspect sample. + +Environment: + + Kernel mode + +--*/ + + +#include <ntddk.h> +#include <wdf.h> + +#pragma warning(push) +#pragma warning(disable:4201) // unnamed struct/union + +#include <fwpsk.h> + +#pragma warning(pop) + +#include <fwpmk.h> + +#include "inspect.h" +#include "utils.h" + + +BOOLEAN IsAleReauthorize( + _In_ const FWPS_INCOMING_VALUES* inFixedValues + ) +{ + UINT flagsIndex; + + GetFlagsIndexesForLayer( + inFixedValues->layerId, + &flagsIndex + ); + + if((flagsIndex != UINT_MAX) && ((inFixedValues->incomingValue\ + [flagsIndex].value.uint32 & FWP_CONDITION_FLAG_IS_REAUTHORIZE) != 0)) + { + return TRUE; + } + + return FALSE; +} + +BOOLEAN IsSecureConnection( + _In_ const FWPS_INCOMING_VALUES* inFixedValues + ) +{ + UINT flagsIndex; + + GetFlagsIndexesForLayer( + inFixedValues->layerId, + &flagsIndex + ); + + if ((flagsIndex != UINT_MAX) && ((inFixedValues->incomingValue\ + [flagsIndex].value.uint32 & FWP_CONDITION_FLAG_IS_IPSEC_SECURED) != 0)) + { + return TRUE; + } + + return FALSE; +} + +BOOLEAN +IsAleClassifyRequired( + _In_ const FWPS_INCOMING_VALUES* inFixedValues, + _In_ const FWPS_INCOMING_METADATA_VALUES* inMetaValues + ) +{ + // + // Note that use of FWP_CONDITION_FLAG_REQUIRES_ALE_CLASSIFY has been + // deprecated in Vista SP1 and Windows Server 2008. + // + UNREFERENCED_PARAMETER(inFixedValues); + return FWPS_IS_METADATA_FIELD_PRESENT( + inMetaValues, + FWPS_METADATA_FIELD_ALE_CLASSIFY_REQUIRED + ); +} + +BOOLEAN +IsMatchingConnectPacket( + _In_ const FWPS_INCOMING_VALUES* inFixedValues, + _In_ ADDRESS_FAMILY addressFamily, + _In_ FWP_DIRECTION direction, + _Inout_ TL_INSPECT_PENDED_PACKET* pendedPacket + ) +{ + UINT localAddrIndex; + UINT remoteAddrIndex; + UINT localPortIndex; + UINT remotePortIndex; + UINT protocolIndex; + + NT_ASSERT(pendedPacket->type == TL_INSPECT_CONNECT_PACKET); + + GetNetwork5TupleIndexesForLayer( + inFixedValues->layerId, + &localAddrIndex, + &remoteAddrIndex, + &localPortIndex, + &remotePortIndex, + &protocolIndex + ); + + if(localAddrIndex == UINT_MAX) + { + return FALSE; + } + + if (addressFamily != pendedPacket->addressFamily) + { + return FALSE; + } + + if (direction != pendedPacket->direction) + { + return FALSE; + } + + if (inFixedValues->incomingValue[protocolIndex].value.uint8 != + pendedPacket->protocol) + { + return FALSE; + } + + if (RtlUshortByteSwap( + inFixedValues->incomingValue[localPortIndex].value.uint16 + ) != pendedPacket->localPort) + { + return FALSE; + } + + if (RtlUshortByteSwap( + inFixedValues->incomingValue[remotePortIndex].value.uint16 + ) != pendedPacket->remotePort) + { + return FALSE; + } + + if (addressFamily == AF_INET) + { + UINT32 ipv4LocalAddr = + RtlUlongByteSwap( + inFixedValues->incomingValue[localAddrIndex].value.uint32 + ); + UINT32 ipv4RemoteAddr = + // Prefast thinks we are ignoring this return value. + // If driver is unloading, we give up and ignore it on purpose. + // Otherwise, we put the pointer onto the list, but we make it opaque + // by casting it as a UINT64, and this tricks Prefast. + RtlUlongByteSwap( /* host-order -> network-order conversion */ + inFixedValues->incomingValue[remoteAddrIndex].value.uint32 + ); + if (ipv4LocalAddr != pendedPacket->ipv4LocalAddr) + { + return FALSE; + } + + if (ipv4RemoteAddr != pendedPacket->ipv4RemoteAddr) + { + return FALSE; + } + } + else + { + if (RtlCompareMemory( + inFixedValues->incomingValue[localAddrIndex].value.byteArray16, + &pendedPacket->localAddr, + sizeof(FWP_BYTE_ARRAY16)) != sizeof(FWP_BYTE_ARRAY16)) + { + return FALSE; + } + + if (RtlCompareMemory( + inFixedValues->incomingValue[remoteAddrIndex].value.byteArray16, + &pendedPacket->remoteAddr, + sizeof(FWP_BYTE_ARRAY16)) != sizeof(FWP_BYTE_ARRAY16)) + { + return FALSE; + } + } + + return TRUE; +} + +void +FillNetwork5Tuple( + _In_ const FWPS_INCOMING_VALUES* inFixedValues, + _In_ ADDRESS_FAMILY addressFamily, + _Inout_ TL_INSPECT_PENDED_PACKET* packet + ) +{ + UINT localAddrIndex; + UINT remoteAddrIndex; + UINT localPortIndex; + UINT remotePortIndex; + UINT protocolIndex; + + GetNetwork5TupleIndexesForLayer( + inFixedValues->layerId, + &localAddrIndex, + &remoteAddrIndex, + &localPortIndex, + &remotePortIndex, + &protocolIndex + ); + + if (addressFamily == AF_INET) + { + packet->ipv4LocalAddr = + RtlUlongByteSwap( /* host-order -> network-order conversion */ + inFixedValues->incomingValue[localAddrIndex].value.uint32 + ); + packet->ipv4RemoteAddr = + RtlUlongByteSwap( /* host-order -> network-order conversion */ + inFixedValues->incomingValue[remoteAddrIndex].value.uint32 + ); + } + else + { + RtlCopyMemory( + (UINT8*)&packet->localAddr, + inFixedValues->incomingValue[localAddrIndex].value.byteArray16, + sizeof(FWP_BYTE_ARRAY16) + ); + RtlCopyMemory( + (UINT8*)&packet->remoteAddr, + inFixedValues->incomingValue[remoteAddrIndex].value.byteArray16, + sizeof(FWP_BYTE_ARRAY16) + ); + } + + packet->localPort = + RtlUshortByteSwap( + inFixedValues->incomingValue[localPortIndex].value.uint16 + ); + packet->remotePort = + RtlUshortByteSwap( + inFixedValues->incomingValue[remotePortIndex].value.uint16 + ); + + packet->protocol = inFixedValues->incomingValue[protocolIndex].value.uint8; + + return; +} + +void +FreePendedPacket( + _Inout_ __drv_freesMem(Mem) TL_INSPECT_PENDED_PACKET* packet + ) +{ + if (packet->netBufferList != NULL) + { + FwpsDereferenceNetBufferList(packet->netBufferList, FALSE); + } + if (packet->controlData != NULL) + { + ExFreePoolWithTag(packet->controlData, TL_INSPECT_CONTROL_DATA_POOL_TAG); + } + if (packet->completionContext != NULL) + { + NT_ASSERT(packet->type == TL_INSPECT_CONNECT_PACKET); + NT_ASSERT(packet->direction == FWP_DIRECTION_INBOUND); // complete for ALE connect + // is done prior to freeing + // of the packet. + FwpsCompleteOperation(packet->completionContext, NULL); + } + ExFreePoolWithTag(packet, TL_INSPECT_PENDED_PACKET_POOL_TAG); +} + +__drv_allocatesMem(Mem) +TL_INSPECT_PENDED_PACKET* +AllocateAndInitializePendedPacket( + _In_ const FWPS_INCOMING_VALUES* inFixedValues, + _In_ const FWPS_INCOMING_METADATA_VALUES* inMetaValues, + _In_ ADDRESS_FAMILY addressFamily, + _Inout_opt_ void* layerData, + _In_ TL_INSPECT_PACKET_TYPE packetType, + _In_ FWP_DIRECTION packetDirection + ) +{ + TL_INSPECT_PENDED_PACKET* pendedPacket; + + pendedPacket = ExAllocatePoolWithTag( + NonPagedPool, + sizeof(TL_INSPECT_PENDED_PACKET), + TL_INSPECT_PENDED_PACKET_POOL_TAG + ); + + if (pendedPacket == NULL) + { + return NULL; + } + + RtlZeroMemory(pendedPacket, sizeof(TL_INSPECT_PENDED_PACKET)); + + pendedPacket->type = packetType; + pendedPacket->direction = packetDirection; + + pendedPacket->addressFamily = addressFamily; + + FillNetwork5Tuple( + inFixedValues, + addressFamily, + pendedPacket + ); + + if (layerData != NULL) + { + pendedPacket->netBufferList = layerData; + + // + // Reference the net buffer list to make it accessible outside of + // classifyFn. + // + FwpsReferenceNetBufferList(pendedPacket->netBufferList, TRUE); + } + + NT_ASSERT(FWPS_IS_METADATA_FIELD_PRESENT(inMetaValues, + FWPS_METADATA_FIELD_COMPARTMENT_ID)); + pendedPacket->compartmentId = inMetaValues->compartmentId; + + if ((pendedPacket->direction == FWP_DIRECTION_OUTBOUND) && + (layerData != NULL)) + { + NT_ASSERT(FWPS_IS_METADATA_FIELD_PRESENT( + inMetaValues, + FWPS_METADATA_FIELD_TRANSPORT_ENDPOINT_HANDLE)); + pendedPacket->endpointHandle = inMetaValues->transportEndpointHandle; + + pendedPacket->remoteScopeId = inMetaValues->remoteScopeId; + + if (FWPS_IS_METADATA_FIELD_PRESENT( + inMetaValues, + FWPS_METADATA_FIELD_TRANSPORT_CONTROL_DATA)) + { + NT_ASSERT(inMetaValues->controlDataLength > 0); + + pendedPacket->controlData = ExAllocatePoolWithTag( + NonPagedPool, + inMetaValues->controlDataLength, + TL_INSPECT_CONTROL_DATA_POOL_TAG + ); + if (pendedPacket->controlData == NULL) + { + goto Exit; + } + + RtlCopyMemory( + pendedPacket->controlData, + inMetaValues->controlData, + inMetaValues->controlDataLength + ); + + pendedPacket->controlDataLength = inMetaValues->controlDataLength; + } + } + else if (pendedPacket->direction == FWP_DIRECTION_INBOUND) + { + UINT interfaceIndexIndex = 0; + UINT subInterfaceIndexIndex = 0; + + GetDeliveryInterfaceIndexesForLayer( + inFixedValues->layerId, + &interfaceIndexIndex, + &subInterfaceIndexIndex + ); + + pendedPacket->interfaceIndex = + inFixedValues->incomingValue[interfaceIndexIndex].value.uint32; + pendedPacket->subInterfaceIndex = + inFixedValues->incomingValue[subInterfaceIndexIndex].value.uint32; + + NT_ASSERT(FWPS_IS_METADATA_FIELD_PRESENT( + inMetaValues, + FWPS_METADATA_FIELD_IP_HEADER_SIZE)); + NT_ASSERT(FWPS_IS_METADATA_FIELD_PRESENT( + inMetaValues, + FWPS_METADATA_FIELD_TRANSPORT_HEADER_SIZE)); + pendedPacket->ipHeaderSize = inMetaValues->ipHeaderSize; + pendedPacket->transportHeaderSize = inMetaValues->transportHeaderSize; + + if (pendedPacket->netBufferList != NULL) + { + FWPS_PACKET_LIST_INFORMATION packetInfo = {0}; + FwpsGetPacketListSecurityInformation( + pendedPacket->netBufferList, + FWPS_PACKET_LIST_INFORMATION_QUERY_IPSEC | + FWPS_PACKET_LIST_INFORMATION_QUERY_INBOUND, + &packetInfo + ); + + pendedPacket->ipSecProtected = + (BOOLEAN)packetInfo.ipsecInformation.inbound.isSecure; + + pendedPacket->nblOffset = + NET_BUFFER_DATA_OFFSET(\ + NET_BUFFER_LIST_FIRST_NB(pendedPacket->netBufferList)); + } + } + + return pendedPacket; + +Exit: + + if (pendedPacket != NULL) + { + FreePendedPacket(pendedPacket); + } + + return NULL; +} + +extern WDFKEY gParametersKey; + +BOOLEAN +IsTrafficPermitted(void) +{ + NTSTATUS status; + + DECLARE_CONST_UNICODE_STRING(valueName, L"PermitTraffic"); + ULONG result; + + status = WdfRegistryQueryULong( + gParametersKey, + &valueName, + &result + ); + + if (!NT_SUCCESS(status)) + { + result = 1; + } + + return (result != 0); +} + + |
