1659 lines
37 KiB
C
1659 lines
37 KiB
C
|
/*++
|
||
|
|
||
|
Copyright (c) 1999 Microsoft Corporation
|
||
|
|
||
|
|
||
|
Module Name:
|
||
|
|
||
|
tnspecific.c
|
||
|
|
||
|
Abstract:
|
||
|
|
||
|
This module contains all of the code to drive the
|
||
|
specific tunnel filter list management of IPSecSPD
|
||
|
Service.
|
||
|
|
||
|
Author:
|
||
|
|
||
|
abhisheV 29-October-1999
|
||
|
|
||
|
Environment
|
||
|
|
||
|
User Level: Win32
|
||
|
|
||
|
Revision History:
|
||
|
|
||
|
|
||
|
--*/
|
||
|
|
||
|
|
||
|
#include "precomp.h"
|
||
|
|
||
|
|
||
|
DWORD
|
||
|
ApplyTnTransform(
|
||
|
PINITNFILTER pFilter,
|
||
|
MATCHING_ADDR * pMatchingAddresses,
|
||
|
DWORD dwAddrCnt,
|
||
|
PINITNSFILTER * ppSpecificFilters
|
||
|
)
|
||
|
/*++
|
||
|
|
||
|
Routine Description:
|
||
|
|
||
|
This function expands a generic tunnel filter into its
|
||
|
corresponding specific filters.
|
||
|
|
||
|
Arguments:
|
||
|
|
||
|
pFilter - Generic filter to expand.
|
||
|
|
||
|
pMatchingAddresses - List of local ip addresses whose interface
|
||
|
type matches that of the filter.
|
||
|
|
||
|
dwAddrCnt - Number of local ip addresses in the list.
|
||
|
|
||
|
ppSpecificFilters - List of specific filters expanded for the
|
||
|
given generic filter.
|
||
|
|
||
|
Return Value:
|
||
|
|
||
|
ERROR_SUCCESS - Success.
|
||
|
|
||
|
Win32 Error - Failure.
|
||
|
|
||
|
--*/
|
||
|
{
|
||
|
DWORD dwError = 0;
|
||
|
PINITNSFILTER pSpecificFilters = NULL;
|
||
|
PINITNSFILTER pOutboundSpecificFilters = NULL;
|
||
|
PINITNSFILTER pInboundSpecificFilters = NULL;
|
||
|
|
||
|
PADDR pSrcAddrList = NULL;
|
||
|
DWORD dwSrcAddrCnt = 0;
|
||
|
PADDR pDesAddrList = NULL;
|
||
|
DWORD dwDesAddrCnt = 0;
|
||
|
|
||
|
PADDR pOutDesTunAddrList = NULL;
|
||
|
DWORD dwOutDesTunAddrCnt = 0;
|
||
|
PADDR pInDesTunAddrList = NULL;
|
||
|
DWORD dwInDesTunAddrCnt = 0;
|
||
|
|
||
|
|
||
|
//
|
||
|
// Replace wild card information to generate the new source
|
||
|
// address list.
|
||
|
//
|
||
|
|
||
|
dwError = FormAddressList(
|
||
|
pFilter->SrcAddr,
|
||
|
pMatchingAddresses,
|
||
|
dwAddrCnt,
|
||
|
&pSrcAddrList,
|
||
|
&dwSrcAddrCnt
|
||
|
);
|
||
|
BAIL_ON_WIN32_ERROR(dwError);
|
||
|
|
||
|
//
|
||
|
// Replace wild card information to generate the new destination
|
||
|
// address list.
|
||
|
//
|
||
|
|
||
|
dwError = FormAddressList(
|
||
|
pFilter->DesAddr,
|
||
|
pMatchingAddresses,
|
||
|
dwAddrCnt,
|
||
|
&pDesAddrList,
|
||
|
&dwDesAddrCnt
|
||
|
);
|
||
|
BAIL_ON_WIN32_ERROR(dwError);
|
||
|
|
||
|
//
|
||
|
// Form the outbound and inbound destination tunnel address lists.
|
||
|
//
|
||
|
|
||
|
dwError = FormTnOutboundInboundAddresses(
|
||
|
pFilter,
|
||
|
pMatchingAddresses,
|
||
|
dwAddrCnt,
|
||
|
&pOutDesTunAddrList,
|
||
|
&dwOutDesTunAddrCnt,
|
||
|
&pInDesTunAddrList,
|
||
|
&dwInDesTunAddrCnt
|
||
|
);
|
||
|
BAIL_ON_WIN32_ERROR(dwError);
|
||
|
|
||
|
|
||
|
//
|
||
|
// Form outbound specific filters.
|
||
|
//
|
||
|
|
||
|
dwError = FormSpecificTnFilters(
|
||
|
pFilter,
|
||
|
pSrcAddrList,
|
||
|
dwSrcAddrCnt,
|
||
|
pDesAddrList,
|
||
|
dwDesAddrCnt,
|
||
|
pOutDesTunAddrList,
|
||
|
dwOutDesTunAddrCnt,
|
||
|
FILTER_DIRECTION_OUTBOUND,
|
||
|
&pOutboundSpecificFilters
|
||
|
);
|
||
|
BAIL_ON_WIN32_ERROR(dwError);
|
||
|
|
||
|
|
||
|
//
|
||
|
// Form inbound specific filters.
|
||
|
//
|
||
|
|
||
|
dwError = FormSpecificTnFilters(
|
||
|
pFilter,
|
||
|
pSrcAddrList,
|
||
|
dwSrcAddrCnt,
|
||
|
pDesAddrList,
|
||
|
dwDesAddrCnt,
|
||
|
pInDesTunAddrList,
|
||
|
dwInDesTunAddrCnt,
|
||
|
FILTER_DIRECTION_INBOUND,
|
||
|
&pInboundSpecificFilters
|
||
|
);
|
||
|
BAIL_ON_WIN32_ERROR(dwError);
|
||
|
|
||
|
|
||
|
pSpecificFilters = pOutboundSpecificFilters;
|
||
|
|
||
|
AddToSpecificTnList(
|
||
|
&pSpecificFilters,
|
||
|
pInboundSpecificFilters
|
||
|
);
|
||
|
|
||
|
|
||
|
*ppSpecificFilters = pSpecificFilters;
|
||
|
|
||
|
cleanup:
|
||
|
|
||
|
if (pSrcAddrList) {
|
||
|
FreeSPDMemory(pSrcAddrList);
|
||
|
}
|
||
|
|
||
|
if (pDesAddrList) {
|
||
|
FreeSPDMemory(pDesAddrList);
|
||
|
}
|
||
|
|
||
|
if (pOutDesTunAddrList) {
|
||
|
FreeSPDMemory(pOutDesTunAddrList);
|
||
|
}
|
||
|
|
||
|
if (pInDesTunAddrList) {
|
||
|
FreeSPDMemory(pInDesTunAddrList);
|
||
|
}
|
||
|
|
||
|
return (dwError);
|
||
|
|
||
|
error:
|
||
|
|
||
|
if (pOutboundSpecificFilters) {
|
||
|
FreeIniTnSFilterList(pOutboundSpecificFilters);
|
||
|
}
|
||
|
|
||
|
if (pInboundSpecificFilters) {
|
||
|
FreeIniTnSFilterList(pInboundSpecificFilters);
|
||
|
}
|
||
|
|
||
|
|
||
|
*ppSpecificFilters = NULL;
|
||
|
goto cleanup;
|
||
|
}
|
||
|
|
||
|
|
||
|
DWORD
|
||
|
FormTnOutboundInboundAddresses(
|
||
|
PINITNFILTER pFilter,
|
||
|
MATCHING_ADDR * pMatchingAddresses,
|
||
|
DWORD dwAddrCnt,
|
||
|
PADDR * ppOutDesTunAddrList,
|
||
|
PDWORD pdwOutDesTunAddrCnt,
|
||
|
PADDR * ppInDesTunAddrList,
|
||
|
PDWORD pdwInDesTunAddrCnt
|
||
|
)
|
||
|
/*++
|
||
|
|
||
|
Routine Description:
|
||
|
|
||
|
This function forms the outbound and inbound
|
||
|
destination tunnel address sets for a generic filter.
|
||
|
|
||
|
Arguments:
|
||
|
|
||
|
pFilter - Generic filter under consideration.
|
||
|
|
||
|
pMatchingAddresses - List of local ip addresses whose interface
|
||
|
type matches that of the filter.
|
||
|
|
||
|
dwAddrCnt - Number of local ip addresses in the list.
|
||
|
|
||
|
ppOutDesTunAddrList - List of outbound destination tunnel addresses.
|
||
|
|
||
|
pdwOutDesTunAddrCnt - Number of addresses in the outbound
|
||
|
destination tunnel address list.
|
||
|
|
||
|
ppInDesTunAddrList - List of inbound destination tunnel addresses.
|
||
|
|
||
|
pdwInDesTunAddrCnt - Number of addresses in the inbound
|
||
|
destination tunnel address list.
|
||
|
|
||
|
Return Value:
|
||
|
|
||
|
ERROR_SUCCESS - Success.
|
||
|
|
||
|
Win32 Error - Failure.
|
||
|
|
||
|
--*/
|
||
|
{
|
||
|
DWORD dwError = 0;
|
||
|
|
||
|
PADDR pDesTunAddrList = NULL;
|
||
|
DWORD dwDesTunAddrCnt = 0;
|
||
|
|
||
|
PADDR pOutDesTunAddrList = NULL;
|
||
|
DWORD dwOutDesTunAddrCnt = 0;
|
||
|
PADDR pInDesTunAddrList = NULL;
|
||
|
DWORD dwInDesTunAddrCnt = 0;
|
||
|
|
||
|
|
||
|
//
|
||
|
// Replace wild card information to generate the new destination
|
||
|
// tunnel address list.
|
||
|
//
|
||
|
|
||
|
dwError = FormAddressList(
|
||
|
pFilter->DesTunnelAddr,
|
||
|
pMatchingAddresses,
|
||
|
dwAddrCnt,
|
||
|
&pDesTunAddrList,
|
||
|
&dwDesTunAddrCnt
|
||
|
);
|
||
|
BAIL_ON_WIN32_ERROR(dwError);
|
||
|
|
||
|
//
|
||
|
// Separate the destination tunnel address list into outbound
|
||
|
// and inbound destination tunnel address sets based on the local
|
||
|
// machine's ip addresses.
|
||
|
//
|
||
|
|
||
|
dwError = SeparateAddrList(
|
||
|
pFilter->DesTunnelAddr.AddrType,
|
||
|
pDesTunAddrList,
|
||
|
dwDesTunAddrCnt,
|
||
|
pMatchingAddresses,
|
||
|
dwAddrCnt,
|
||
|
&pInDesTunAddrList,
|
||
|
&dwInDesTunAddrCnt,
|
||
|
&pOutDesTunAddrList,
|
||
|
&dwOutDesTunAddrCnt
|
||
|
);
|
||
|
BAIL_ON_WIN32_ERROR(dwError);
|
||
|
|
||
|
*ppOutDesTunAddrList = pOutDesTunAddrList;
|
||
|
*pdwOutDesTunAddrCnt = dwOutDesTunAddrCnt;
|
||
|
*ppInDesTunAddrList = pInDesTunAddrList;
|
||
|
*pdwInDesTunAddrCnt = dwInDesTunAddrCnt;
|
||
|
|
||
|
cleanup:
|
||
|
|
||
|
if (pDesTunAddrList) {
|
||
|
FreeSPDMemory(pDesTunAddrList);
|
||
|
}
|
||
|
|
||
|
return (dwError);
|
||
|
|
||
|
error:
|
||
|
|
||
|
if (pOutDesTunAddrList) {
|
||
|
FreeSPDMemory(pOutDesTunAddrList);
|
||
|
}
|
||
|
|
||
|
if (pInDesTunAddrList) {
|
||
|
FreeSPDMemory(pInDesTunAddrList);
|
||
|
}
|
||
|
|
||
|
*ppOutDesTunAddrList = NULL;
|
||
|
*pdwOutDesTunAddrCnt = 0;
|
||
|
*ppInDesTunAddrList = NULL;
|
||
|
*pdwInDesTunAddrCnt = 0;
|
||
|
|
||
|
goto cleanup;
|
||
|
}
|
||
|
|
||
|
|
||
|
DWORD
|
||
|
FormSpecificTnFilters(
|
||
|
PINITNFILTER pFilter,
|
||
|
PADDR pSrcAddrList,
|
||
|
DWORD dwSrcAddrCnt,
|
||
|
PADDR pDesAddrList,
|
||
|
DWORD dwDesAddrCnt,
|
||
|
PADDR pDesTunAddrList,
|
||
|
DWORD dwDesTunAddrCnt,
|
||
|
DWORD dwDirection,
|
||
|
PINITNSFILTER * ppSpecificFilters
|
||
|
)
|
||
|
/*++
|
||
|
|
||
|
Routine Description:
|
||
|
|
||
|
This function forms the specific tunnel filters
|
||
|
for the given generic filter and the source and
|
||
|
destination address sets.
|
||
|
|
||
|
Arguments:
|
||
|
|
||
|
pFilter - Generic filter for which specific filters
|
||
|
are to be created.
|
||
|
|
||
|
pSrcAddrList - List of source addresses.
|
||
|
|
||
|
dwSrcAddrCnt - Number of addresses in the source
|
||
|
address list.
|
||
|
|
||
|
pDesAddrList - List of destination addresses.
|
||
|
|
||
|
dwDesAddrCnt - Number of addresses in the destination
|
||
|
address list.
|
||
|
|
||
|
pDesTunAddrList - List of destination tunnel addresses.
|
||
|
|
||
|
dwDesTunAddrCnt - Number of addresses in the destination
|
||
|
tunnel address list.
|
||
|
|
||
|
dwDirection - direction of the resulting specific filters.
|
||
|
|
||
|
ppSpecificFilters - Specific filters created for the given
|
||
|
generic filter and the given addresses.
|
||
|
|
||
|
Return Value:
|
||
|
|
||
|
ERROR_SUCCESS - Success.
|
||
|
|
||
|
Win32 Error - Failure.
|
||
|
|
||
|
--*/
|
||
|
{
|
||
|
DWORD dwError = 0;
|
||
|
PINITNSFILTER pSpecificFilters = NULL;
|
||
|
DWORD i = 0, j = 0, k = 0;
|
||
|
PINITNSFILTER pSpecificFilter = NULL;
|
||
|
|
||
|
|
||
|
for (k = 0; k < dwDesTunAddrCnt; k++) {
|
||
|
|
||
|
for (i = 0; i < dwSrcAddrCnt; i++) {
|
||
|
|
||
|
for (j = 0; j < dwDesAddrCnt; j++) {
|
||
|
|
||
|
dwError = CreateSpecificTnFilter(
|
||
|
pFilter,
|
||
|
pSrcAddrList[i],
|
||
|
pDesAddrList[j],
|
||
|
pDesTunAddrList[k],
|
||
|
&pSpecificFilter
|
||
|
);
|
||
|
BAIL_ON_WIN32_ERROR(dwError);
|
||
|
|
||
|
//
|
||
|
// Set the direction of the filter.
|
||
|
//
|
||
|
|
||
|
pSpecificFilter->dwDirection = dwDirection;
|
||
|
|
||
|
AssignTnFilterWeight(pSpecificFilter);
|
||
|
|
||
|
AddToSpecificTnList(
|
||
|
&pSpecificFilters,
|
||
|
pSpecificFilter
|
||
|
);
|
||
|
|
||
|
}
|
||
|
|
||
|
}
|
||
|
|
||
|
}
|
||
|
|
||
|
*ppSpecificFilters = pSpecificFilters;
|
||
|
return (dwError);
|
||
|
|
||
|
error:
|
||
|
|
||
|
if (pSpecificFilters) {
|
||
|
FreeIniTnSFilterList(pSpecificFilters);
|
||
|
}
|
||
|
|
||
|
*ppSpecificFilters = NULL;
|
||
|
return (dwError);
|
||
|
}
|
||
|
|
||
|
|
||
|
DWORD
|
||
|
CreateSpecificTnFilter(
|
||
|
PINITNFILTER pGenericFilter,
|
||
|
ADDR SrcAddr,
|
||
|
ADDR DesAddr,
|
||
|
ADDR DesTunnelAddr,
|
||
|
PINITNSFILTER * ppSpecificFilter
|
||
|
)
|
||
|
{
|
||
|
DWORD dwError = 0;
|
||
|
PINITNSFILTER pSpecificFilter = NULL;
|
||
|
|
||
|
|
||
|
dwError = AllocateSPDMemory(
|
||
|
sizeof(INITNSFILTER),
|
||
|
&pSpecificFilter
|
||
|
);
|
||
|
BAIL_ON_WIN32_ERROR(dwError);
|
||
|
|
||
|
pSpecificFilter->cRef = 0;
|
||
|
|
||
|
CopyGuid(pGenericFilter->gFilterID, &(pSpecificFilter->gParentID));
|
||
|
|
||
|
dwError = AllocateSPDString(
|
||
|
pGenericFilter->pszFilterName,
|
||
|
&(pSpecificFilter->pszFilterName)
|
||
|
);
|
||
|
BAIL_ON_WIN32_ERROR(dwError);
|
||
|
|
||
|
pSpecificFilter->InterfaceType = pGenericFilter->InterfaceType;
|
||
|
|
||
|
pSpecificFilter->dwFlags = pGenericFilter->dwFlags;
|
||
|
|
||
|
CopyAddresses(SrcAddr, &(pSpecificFilter->SrcAddr));
|
||
|
|
||
|
CopyAddresses(DesAddr, &(pSpecificFilter->DesAddr));
|
||
|
|
||
|
CopyAddresses(
|
||
|
pGenericFilter->SrcTunnelAddr,
|
||
|
&(pSpecificFilter->SrcTunnelAddr)
|
||
|
);
|
||
|
|
||
|
CopyAddresses(DesTunnelAddr, &(pSpecificFilter->DesTunnelAddr));
|
||
|
|
||
|
CopyPorts(pGenericFilter->SrcPort, &(pSpecificFilter->SrcPort));
|
||
|
|
||
|
CopyPorts(pGenericFilter->DesPort, &(pSpecificFilter->DesPort));
|
||
|
|
||
|
CopyProtocols(pGenericFilter->Protocol, &(pSpecificFilter->Protocol));
|
||
|
|
||
|
pSpecificFilter->InboundFilterFlag = pGenericFilter->InboundFilterFlag;
|
||
|
|
||
|
pSpecificFilter->OutboundFilterFlag = pGenericFilter->OutboundFilterFlag;
|
||
|
|
||
|
//
|
||
|
// Direction must be set in the calling routine.
|
||
|
//
|
||
|
|
||
|
pSpecificFilter->dwDirection = 0;
|
||
|
|
||
|
//
|
||
|
// Weight must be set in the calling routine.
|
||
|
//
|
||
|
|
||
|
pSpecificFilter->dwWeight = 0;
|
||
|
|
||
|
CopyGuid(pGenericFilter->gPolicyID, &(pSpecificFilter->gPolicyID));
|
||
|
|
||
|
pSpecificFilter->pIniQMPolicy = NULL;
|
||
|
|
||
|
pSpecificFilter->pNext = NULL;
|
||
|
|
||
|
*ppSpecificFilter = pSpecificFilter;
|
||
|
return (dwError);
|
||
|
|
||
|
error:
|
||
|
|
||
|
if (pSpecificFilter) {
|
||
|
FreeIniTnSFilter(pSpecificFilter);
|
||
|
}
|
||
|
|
||
|
*ppSpecificFilter = NULL;
|
||
|
return (dwError);
|
||
|
}
|
||
|
|
||
|
|
||
|
VOID
|
||
|
AssignTnFilterWeight(
|
||
|
PINITNSFILTER pSpecificFilter
|
||
|
)
|
||
|
/*++
|
||
|
|
||
|
Routine Description:
|
||
|
|
||
|
Computes and assigns the weight to a specific tunnel filter.
|
||
|
|
||
|
The tunnel filter weight consists of the following:
|
||
|
|
||
|
31 16 12 8 0
|
||
|
+-----------+-----------+-----------+--------+
|
||
|
|AddrMaskWgt| TunnelWgt |ProtocolWgt|PortWgts|
|
||
|
+-----------+-----------+-----------+--------+
|
||
|
|
||
|
Arguments:
|
||
|
|
||
|
pSpecificFilter - Specific tunnel filter to which the weight
|
||
|
is to be assigned.
|
||
|
|
||
|
Return Value:
|
||
|
|
||
|
None.
|
||
|
|
||
|
--*/
|
||
|
{
|
||
|
DWORD dwWeight = 0;
|
||
|
ULONG SrcMask = 0;
|
||
|
ULONG DesMask = 0;
|
||
|
DWORD dwMaskWeight = 0;
|
||
|
DWORD i = 0;
|
||
|
|
||
|
|
||
|
//
|
||
|
// Weight Rule:
|
||
|
// A field with a more specific value gets a higher weight than
|
||
|
// the same field with a lesser specific value.
|
||
|
//
|
||
|
|
||
|
//
|
||
|
// If the protocol is specific then assign the specific protocol
|
||
|
// weight else the weight is zero.
|
||
|
// All the specific filters that have a specific protocol and
|
||
|
// differ only in the protocol field will have the same weight.
|
||
|
//
|
||
|
|
||
|
if (pSpecificFilter->Protocol.dwProtocol != 0) {
|
||
|
dwWeight |= WEIGHT_SPECIFIC_PROTOCOL;
|
||
|
}
|
||
|
|
||
|
//
|
||
|
// If the source port is specific then assign the specific source
|
||
|
// port weight else the weight is zero.
|
||
|
// All the specific filters that have a specific source port and
|
||
|
// differ only in the source port field will have the same weight.
|
||
|
//
|
||
|
|
||
|
if (pSpecificFilter->SrcPort.wPort != 0) {
|
||
|
dwWeight |= WEIGHT_SPECIFIC_SOURCE_PORT;
|
||
|
}
|
||
|
|
||
|
//
|
||
|
// If the destination port is specific then assign the specific
|
||
|
// destination port weight else the weight is zero.
|
||
|
// All the specific filters that have a specific destination port
|
||
|
// and differ only in the destination port field will have the
|
||
|
// same weight.
|
||
|
//
|
||
|
|
||
|
if (pSpecificFilter->DesPort.wPort != 0) {
|
||
|
dwWeight |= WEIGHT_SPECIFIC_DESTINATION_PORT;
|
||
|
}
|
||
|
|
||
|
dwWeight |= WEIGHT_TUNNEL_FILTER;
|
||
|
|
||
|
if (pSpecificFilter->DesTunnelAddr.uIpAddr != SUBNET_ADDRESS_ANY) {
|
||
|
dwWeight |= WEIGHT_SPECIFIC_TUNNEL_FILTER;
|
||
|
}
|
||
|
|
||
|
//
|
||
|
// IP addresses get the weight values based on their mask values.
|
||
|
// In the address case, the weight is computed as a sum of the
|
||
|
// bit positions starting from the position that contains the
|
||
|
// first least significant non-zero bit to the most significant
|
||
|
// bit position of the mask.
|
||
|
// All unique ip addresses have a mask of 0xFFFFFFFF and thus get
|
||
|
// the same weight, which is 1 + 2 + .... + 32.
|
||
|
// A subnet address has a mask with atleast the least significant
|
||
|
// bit zero and thus gets weight in the range (2 + .. + 32) to 0.
|
||
|
//
|
||
|
|
||
|
DesMask = ntohl(pSpecificFilter->DesAddr.uSubNetMask);
|
||
|
|
||
|
for (i = 0; i < sizeof(ULONG) * 8; i++) {
|
||
|
|
||
|
//
|
||
|
// If the bit position contains a non-zero bit, add the bit
|
||
|
// position to the sum.
|
||
|
//
|
||
|
|
||
|
if ((DesMask & 0x1) == 0x1) {
|
||
|
dwMaskWeight += (i+1);
|
||
|
}
|
||
|
|
||
|
//
|
||
|
// Move to the next bit position.
|
||
|
//
|
||
|
|
||
|
DesMask = DesMask >> 1;
|
||
|
|
||
|
}
|
||
|
|
||
|
|
||
|
SrcMask = ntohl(pSpecificFilter->SrcAddr.uSubNetMask);
|
||
|
|
||
|
for (i = 0; i < sizeof(ULONG) * 8; i++) {
|
||
|
|
||
|
//
|
||
|
// If the bit position contains a non-zero bit, add the bit
|
||
|
// position to the sum.
|
||
|
//
|
||
|
|
||
|
if ((SrcMask & 0x1) == 0x1) {
|
||
|
dwMaskWeight += (i+1);
|
||
|
}
|
||
|
|
||
|
//
|
||
|
// Move to the next bit position.
|
||
|
//
|
||
|
|
||
|
SrcMask = SrcMask >> 1;
|
||
|
|
||
|
}
|
||
|
|
||
|
//
|
||
|
// Move the mask weight to the set of bits in the overall weight
|
||
|
// that it occupies.
|
||
|
//
|
||
|
|
||
|
dwMaskWeight = dwMaskWeight << 16;
|
||
|
|
||
|
dwWeight += dwMaskWeight;
|
||
|
|
||
|
pSpecificFilter->dwWeight = dwWeight;
|
||
|
}
|
||
|
|
||
|
|
||
|
VOID
|
||
|
AddToSpecificTnList(
|
||
|
PINITNSFILTER * ppSpecificTnFilterList,
|
||
|
PINITNSFILTER pSpecificTnFilters
|
||
|
)
|
||
|
{
|
||
|
PINITNSFILTER pListOne = NULL;
|
||
|
PINITNSFILTER pListTwo = NULL;
|
||
|
PINITNSFILTER pListMerge = NULL;
|
||
|
PINITNSFILTER pLast = NULL;
|
||
|
|
||
|
if (!(*ppSpecificTnFilterList) && !pSpecificTnFilters) {
|
||
|
return;
|
||
|
}
|
||
|
|
||
|
if (!(*ppSpecificTnFilterList)) {
|
||
|
*ppSpecificTnFilterList = pSpecificTnFilters;
|
||
|
return;
|
||
|
}
|
||
|
|
||
|
if (!pSpecificTnFilters) {
|
||
|
return;
|
||
|
}
|
||
|
|
||
|
pListOne = *ppSpecificTnFilterList;
|
||
|
pListTwo = pSpecificTnFilters;
|
||
|
|
||
|
while (pListOne && pListTwo) {
|
||
|
|
||
|
if ((pListOne->dwWeight) > (pListTwo->dwWeight)) {
|
||
|
|
||
|
if (!pListMerge) {
|
||
|
pListMerge = pListOne;
|
||
|
pLast = pListOne;
|
||
|
pListOne = pListOne->pNext;
|
||
|
}
|
||
|
else {
|
||
|
pLast->pNext = pListOne;
|
||
|
pListOne = pListOne->pNext;
|
||
|
pLast = pLast->pNext;
|
||
|
}
|
||
|
|
||
|
}
|
||
|
else {
|
||
|
|
||
|
if (!pListMerge) {
|
||
|
pListMerge = pListTwo;
|
||
|
pLast = pListTwo;
|
||
|
pListTwo = pListTwo->pNext;
|
||
|
}
|
||
|
else {
|
||
|
pLast->pNext = pListTwo;
|
||
|
pListTwo = pListTwo->pNext;
|
||
|
pLast = pLast->pNext;
|
||
|
}
|
||
|
|
||
|
}
|
||
|
|
||
|
}
|
||
|
|
||
|
if (pListOne) {
|
||
|
pLast->pNext = pListOne;
|
||
|
}
|
||
|
else {
|
||
|
pLast->pNext = pListTwo;
|
||
|
}
|
||
|
|
||
|
*ppSpecificTnFilterList = pListMerge;
|
||
|
return;
|
||
|
}
|
||
|
|
||
|
|
||
|
VOID
|
||
|
FreeIniTnSFilterList(
|
||
|
PINITNSFILTER pIniTnSFilterList
|
||
|
)
|
||
|
{
|
||
|
PINITNSFILTER pFilter = NULL;
|
||
|
PINITNSFILTER pTempFilter = NULL;
|
||
|
|
||
|
pFilter = pIniTnSFilterList;
|
||
|
|
||
|
while (pFilter) {
|
||
|
pTempFilter = pFilter;
|
||
|
pFilter = pFilter->pNext;
|
||
|
FreeIniTnSFilter(pTempFilter);
|
||
|
}
|
||
|
}
|
||
|
|
||
|
|
||
|
VOID
|
||
|
FreeIniTnSFilter(
|
||
|
PINITNSFILTER pIniTnSFilter
|
||
|
)
|
||
|
{
|
||
|
if (pIniTnSFilter) {
|
||
|
if (pIniTnSFilter->pszFilterName) {
|
||
|
FreeSPDString(pIniTnSFilter->pszFilterName);
|
||
|
}
|
||
|
|
||
|
//
|
||
|
// Must not ever free pIniTnSFilter->pIniQMPolicy.
|
||
|
//
|
||
|
|
||
|
FreeSPDMemory(pIniTnSFilter);
|
||
|
}
|
||
|
}
|
||
|
|
||
|
|
||
|
VOID
|
||
|
LinkTnSpecificFilters(
|
||
|
PINIQMPOLICY pIniQMPolicy,
|
||
|
PINITNSFILTER pIniTnSFilters
|
||
|
)
|
||
|
{
|
||
|
PINITNSFILTER pTemp = NULL;
|
||
|
|
||
|
pTemp = pIniTnSFilters;
|
||
|
|
||
|
while (pTemp) {
|
||
|
pTemp->pIniQMPolicy = pIniQMPolicy;
|
||
|
pTemp = pTemp->pNext;
|
||
|
}
|
||
|
|
||
|
return;
|
||
|
}
|
||
|
|
||
|
|
||
|
VOID
|
||
|
RemoveIniTnSFilter(
|
||
|
PINITNSFILTER pIniTnSFilter
|
||
|
)
|
||
|
{
|
||
|
PINITNSFILTER * ppTemp = NULL;
|
||
|
|
||
|
ppTemp = &gpIniTnSFilter;
|
||
|
|
||
|
while (*ppTemp) {
|
||
|
|
||
|
if (*ppTemp == pIniTnSFilter) {
|
||
|
break;
|
||
|
}
|
||
|
ppTemp = &((*ppTemp)->pNext);
|
||
|
}
|
||
|
|
||
|
if (*ppTemp) {
|
||
|
*ppTemp = pIniTnSFilter->pNext;
|
||
|
}
|
||
|
|
||
|
return;
|
||
|
}
|
||
|
|
||
|
|
||
|
DWORD
|
||
|
EnumSpecificTnFilters(
|
||
|
PINITNSFILTER pIniTnSFilterList,
|
||
|
DWORD dwResumeHandle,
|
||
|
DWORD dwPreferredNumEntries,
|
||
|
PTUNNEL_FILTER * ppTnFilters,
|
||
|
PDWORD pdwNumTnFilters
|
||
|
)
|
||
|
/*++
|
||
|
|
||
|
Routine Description:
|
||
|
|
||
|
This function creates enumerated specific filters.
|
||
|
|
||
|
Arguments:
|
||
|
|
||
|
pIniTnSFilterList - List of specific filters to enumerate.
|
||
|
|
||
|
dwResumeHandle - Location in the specific filter list from which
|
||
|
to resume enumeration.
|
||
|
|
||
|
dwPreferredNumEntries - Preferred number of enumeration entries.
|
||
|
|
||
|
ppTnFilters - Enumerated filters returned to the caller.
|
||
|
|
||
|
pdwNumTnFilters - Number of filters actually enumerated.
|
||
|
|
||
|
Return Value:
|
||
|
|
||
|
ERROR_SUCCESS - Success.
|
||
|
|
||
|
Win32 Error - Failure.
|
||
|
|
||
|
--*/
|
||
|
{
|
||
|
DWORD dwError = 0;
|
||
|
DWORD dwNumToEnum = 0;
|
||
|
PINITNSFILTER pIniTnSFilter = NULL;
|
||
|
DWORD i = 0;
|
||
|
PINITNSFILTER pTemp = NULL;
|
||
|
DWORD dwNumTnFilters = 0;
|
||
|
PTUNNEL_FILTER pTnFilters = 0;
|
||
|
PTUNNEL_FILTER pTnFilter = 0;
|
||
|
|
||
|
|
||
|
if (!dwPreferredNumEntries ||
|
||
|
(dwPreferredNumEntries > MAX_TUNNELFILTER_ENUM_COUNT)) {
|
||
|
dwNumToEnum = MAX_TUNNELFILTER_ENUM_COUNT;
|
||
|
}
|
||
|
else {
|
||
|
dwNumToEnum = dwPreferredNumEntries;
|
||
|
}
|
||
|
|
||
|
pIniTnSFilter = pIniTnSFilterList;
|
||
|
|
||
|
for (i = 0; (i < dwResumeHandle) && (pIniTnSFilter != NULL); i++) {
|
||
|
pIniTnSFilter = pIniTnSFilter->pNext;
|
||
|
}
|
||
|
|
||
|
if (!pIniTnSFilter) {
|
||
|
dwError = ERROR_NO_DATA;
|
||
|
BAIL_ON_WIN32_ERROR(dwError);
|
||
|
}
|
||
|
|
||
|
pTemp = pIniTnSFilter;
|
||
|
|
||
|
while (pTemp && (dwNumTnFilters < dwNumToEnum)) {
|
||
|
dwNumTnFilters++;
|
||
|
pTemp = pTemp->pNext;
|
||
|
}
|
||
|
|
||
|
dwError = SPDApiBufferAllocate(
|
||
|
sizeof(TUNNEL_FILTER)*dwNumTnFilters,
|
||
|
&pTnFilters
|
||
|
);
|
||
|
BAIL_ON_WIN32_ERROR(dwError);
|
||
|
|
||
|
pTemp = pIniTnSFilter;
|
||
|
pTnFilter = pTnFilters;
|
||
|
|
||
|
for (i = 0; i < dwNumTnFilters; i++) {
|
||
|
|
||
|
dwError = CopyTnSFilter(
|
||
|
pTemp,
|
||
|
pTnFilter
|
||
|
);
|
||
|
BAIL_ON_WIN32_ERROR(dwError);
|
||
|
|
||
|
pTemp = pTemp->pNext;
|
||
|
pTnFilter++;
|
||
|
|
||
|
}
|
||
|
|
||
|
*ppTnFilters = pTnFilters;
|
||
|
*pdwNumTnFilters = dwNumTnFilters;
|
||
|
return (dwError);
|
||
|
|
||
|
error:
|
||
|
|
||
|
if (pTnFilters) {
|
||
|
FreeTnFilters(
|
||
|
i,
|
||
|
pTnFilters
|
||
|
);
|
||
|
}
|
||
|
|
||
|
*ppTnFilters = NULL;
|
||
|
*pdwNumTnFilters = 0;
|
||
|
|
||
|
return (dwError);
|
||
|
}
|
||
|
|
||
|
|
||
|
DWORD
|
||
|
CopyTnSFilter(
|
||
|
PINITNSFILTER pIniTnSFilter,
|
||
|
PTUNNEL_FILTER pTnFilter
|
||
|
)
|
||
|
/*++
|
||
|
|
||
|
Routine Description:
|
||
|
|
||
|
This function copies an internal filter into an external filter
|
||
|
container.
|
||
|
|
||
|
Arguments:
|
||
|
|
||
|
pIniTnSFilter - Internal filter to copy.
|
||
|
|
||
|
pTnFilter - External filter container in which to copy.
|
||
|
|
||
|
Return Value:
|
||
|
|
||
|
ERROR_SUCCESS - Success.
|
||
|
|
||
|
Win32 Error - Failure.
|
||
|
|
||
|
--*/
|
||
|
{
|
||
|
DWORD dwError = 0;
|
||
|
|
||
|
CopyGuid(pIniTnSFilter->gParentID, &(pTnFilter->gFilterID));
|
||
|
|
||
|
dwError = CopyName(
|
||
|
pIniTnSFilter->pszFilterName,
|
||
|
&(pTnFilter->pszFilterName)
|
||
|
);
|
||
|
BAIL_ON_WIN32_ERROR(dwError);
|
||
|
|
||
|
pTnFilter->InterfaceType = pIniTnSFilter->InterfaceType;
|
||
|
|
||
|
pTnFilter->bCreateMirror = FALSE;
|
||
|
|
||
|
pTnFilter->dwFlags = pIniTnSFilter->dwFlags;
|
||
|
|
||
|
CopyAddresses(pIniTnSFilter->SrcAddr, &(pTnFilter->SrcAddr));
|
||
|
|
||
|
CopyAddresses(pIniTnSFilter->DesAddr, &(pTnFilter->DesAddr));
|
||
|
|
||
|
CopyAddresses(pIniTnSFilter->SrcTunnelAddr, &(pTnFilter->SrcTunnelAddr));
|
||
|
|
||
|
CopyAddresses(pIniTnSFilter->DesTunnelAddr, &(pTnFilter->DesTunnelAddr));
|
||
|
|
||
|
CopyProtocols(pIniTnSFilter->Protocol, &(pTnFilter->Protocol));
|
||
|
|
||
|
CopyPorts(pIniTnSFilter->SrcPort, &(pTnFilter->SrcPort));
|
||
|
|
||
|
CopyPorts(pIniTnSFilter->DesPort, &(pTnFilter->DesPort));
|
||
|
|
||
|
pTnFilter->InboundFilterFlag = pIniTnSFilter->InboundFilterFlag;
|
||
|
|
||
|
pTnFilter->OutboundFilterFlag = pIniTnSFilter->OutboundFilterFlag;
|
||
|
|
||
|
pTnFilter->dwDirection = pIniTnSFilter->dwDirection;
|
||
|
|
||
|
pTnFilter->dwWeight = pIniTnSFilter->dwWeight;
|
||
|
|
||
|
CopyGuid(pIniTnSFilter->gPolicyID, &(pTnFilter->gPolicyID));
|
||
|
|
||
|
error:
|
||
|
|
||
|
return (dwError);
|
||
|
}
|
||
|
|
||
|
|
||
|
DWORD
|
||
|
EnumSelectSpecificTnFilters(
|
||
|
PINITNFILTER pIniTnFilter,
|
||
|
DWORD dwResumeHandle,
|
||
|
DWORD dwPreferredNumEntries,
|
||
|
PTUNNEL_FILTER * ppTnFilters,
|
||
|
PDWORD pdwNumTnFilters
|
||
|
)
|
||
|
/*++
|
||
|
|
||
|
Routine Description:
|
||
|
|
||
|
This function creates enumerated specific filters for
|
||
|
the given generic filter.
|
||
|
|
||
|
Arguments:
|
||
|
|
||
|
pIniTnFilter - Generic filter for which specific filters
|
||
|
are to be enumerated.
|
||
|
|
||
|
dwResumeHandle - Location in the specific filter list for the
|
||
|
given generic filter from which to resume
|
||
|
enumeration.
|
||
|
|
||
|
dwPreferredNumEntries - Preferred number of enumeration entries.
|
||
|
|
||
|
ppTnFilters - Enumerated filters returned to the caller.
|
||
|
|
||
|
pdwNumTnFilters - Number of filters actually enumerated.
|
||
|
|
||
|
Return Value:
|
||
|
|
||
|
ERROR_SUCCESS - Success.
|
||
|
|
||
|
Win32 Error - Failure.
|
||
|
|
||
|
--*/
|
||
|
{
|
||
|
DWORD dwError = 0;
|
||
|
DWORD dwNumToEnum = 0;
|
||
|
DWORD dwNumTnSFilters = 0;
|
||
|
PINITNSFILTER * ppIniTnSFilters = NULL;
|
||
|
DWORD i = 0;
|
||
|
DWORD dwNumTnFilters = 0;
|
||
|
PTUNNEL_FILTER pTnFilters = 0;
|
||
|
PTUNNEL_FILTER pTnFilter = 0;
|
||
|
|
||
|
|
||
|
if (!dwPreferredNumEntries ||
|
||
|
(dwPreferredNumEntries > MAX_TUNNELFILTER_ENUM_COUNT)) {
|
||
|
dwNumToEnum = MAX_TUNNELFILTER_ENUM_COUNT;
|
||
|
}
|
||
|
else {
|
||
|
dwNumToEnum = dwPreferredNumEntries;
|
||
|
}
|
||
|
|
||
|
dwNumTnSFilters = pIniTnFilter->dwNumTnSFilters;
|
||
|
ppIniTnSFilters = pIniTnFilter->ppIniTnSFilters;
|
||
|
|
||
|
if (!dwNumTnSFilters || (dwNumTnSFilters <= dwResumeHandle)) {
|
||
|
dwError = ERROR_NO_DATA;
|
||
|
BAIL_ON_WIN32_ERROR(dwError);
|
||
|
}
|
||
|
|
||
|
dwNumTnFilters = min((dwNumTnSFilters-dwResumeHandle),
|
||
|
dwNumToEnum);
|
||
|
|
||
|
dwError = SPDApiBufferAllocate(
|
||
|
sizeof(TUNNEL_FILTER)*dwNumTnFilters,
|
||
|
&pTnFilters
|
||
|
);
|
||
|
BAIL_ON_WIN32_ERROR(dwError);
|
||
|
|
||
|
pTnFilter = pTnFilters;
|
||
|
|
||
|
for (i = 0; i < dwNumTnFilters; i++) {
|
||
|
|
||
|
dwError = CopyTnSFilter(
|
||
|
*(ppIniTnSFilters + (dwResumeHandle + i)),
|
||
|
pTnFilter
|
||
|
);
|
||
|
BAIL_ON_WIN32_ERROR(dwError);
|
||
|
pTnFilter++;
|
||
|
|
||
|
}
|
||
|
|
||
|
*ppTnFilters = pTnFilters;
|
||
|
*pdwNumTnFilters = dwNumTnFilters;
|
||
|
return (dwError);
|
||
|
|
||
|
error:
|
||
|
|
||
|
if (pTnFilters) {
|
||
|
FreeTnFilters(
|
||
|
i,
|
||
|
pTnFilters
|
||
|
);
|
||
|
}
|
||
|
|
||
|
*ppTnFilters = NULL;
|
||
|
*pdwNumTnFilters = 0;
|
||
|
|
||
|
return (dwError);
|
||
|
}
|
||
|
|
||
|
|
||
|
DWORD
|
||
|
MatchTunnelFilter(
|
||
|
LPWSTR pServerName,
|
||
|
PTUNNEL_FILTER pTnFilter,
|
||
|
DWORD dwFlags,
|
||
|
PTUNNEL_FILTER * ppMatchedTnFilters,
|
||
|
PIPSEC_QM_POLICY * ppMatchedQMPolicies,
|
||
|
DWORD dwPreferredNumEntries,
|
||
|
LPDWORD pdwNumMatches,
|
||
|
LPDWORD pdwResumeHandle
|
||
|
)
|
||
|
/*++
|
||
|
|
||
|
Routine Description:
|
||
|
|
||
|
This function finds the matching tunnel filters for the
|
||
|
given tunnel filter template. The matched filters can not
|
||
|
be more specific than the given filter template.
|
||
|
|
||
|
Arguments:
|
||
|
|
||
|
pServerName - Server on which a filter template is to be matched.
|
||
|
|
||
|
pTnFilter - Filter template to match.
|
||
|
|
||
|
dwFlags - Flags.
|
||
|
|
||
|
ppMatchedTnFilters - Matched tunnel filters returned to the
|
||
|
caller.
|
||
|
|
||
|
ppMatchedQMPolicies - Quick mode policies corresponding to the
|
||
|
matched tunnel filters returned to the
|
||
|
caller.
|
||
|
|
||
|
dwPreferredNumEntries - Preferred number of matched entries.
|
||
|
|
||
|
pdwNumMatches - Number of filters actually matched.
|
||
|
|
||
|
pdwResumeHandle - Handle to the location in the matched filter
|
||
|
list from which to resume enumeration.
|
||
|
|
||
|
Return Value:
|
||
|
|
||
|
ERROR_SUCCESS - Success.
|
||
|
|
||
|
Win32 Error - Failure.
|
||
|
|
||
|
--*/
|
||
|
{
|
||
|
DWORD dwError = 0;
|
||
|
DWORD dwResumeHandle = 0;
|
||
|
DWORD dwNumToMatch = 0;
|
||
|
PINITNSFILTER pIniTnSFilter = NULL;
|
||
|
DWORD i = 0;
|
||
|
BOOL bMatches = FALSE;
|
||
|
PINITNSFILTER pTemp = NULL;
|
||
|
DWORD dwNumMatches = 0;
|
||
|
PINITNSFILTER pLastMatchedFilter = NULL;
|
||
|
PTUNNEL_FILTER pMatchedTnFilters = NULL;
|
||
|
PIPSEC_QM_POLICY pMatchedQMPolicies = NULL;
|
||
|
DWORD dwNumFilters = 0;
|
||
|
DWORD dwNumPolicies = 0;
|
||
|
PTUNNEL_FILTER pMatchedTnFilter = NULL;
|
||
|
PIPSEC_QM_POLICY pMatchedQMPolicy = NULL;
|
||
|
|
||
|
|
||
|
dwError = ValidateTnFilterTemplate(
|
||
|
pTnFilter
|
||
|
);
|
||
|
BAIL_ON_WIN32_ERROR(dwError);
|
||
|
|
||
|
dwResumeHandle = *pdwResumeHandle;
|
||
|
|
||
|
if (!dwPreferredNumEntries) {
|
||
|
dwNumToMatch = 1;
|
||
|
}
|
||
|
else if (dwPreferredNumEntries > MAX_TUNNELFILTER_ENUM_COUNT) {
|
||
|
dwNumToMatch = MAX_TUNNELFILTER_ENUM_COUNT;
|
||
|
}
|
||
|
else {
|
||
|
dwNumToMatch = dwPreferredNumEntries;
|
||
|
}
|
||
|
|
||
|
ENTER_SPD_SECTION();
|
||
|
|
||
|
dwError = ValidateTnSecurity(
|
||
|
SPD_OBJECT_SERVER,
|
||
|
SERVER_ACCESS_ADMINISTER,
|
||
|
NULL,
|
||
|
NULL
|
||
|
);
|
||
|
BAIL_ON_LOCK_ERROR(dwError);
|
||
|
|
||
|
pIniTnSFilter = gpIniTnSFilter;
|
||
|
|
||
|
while ((i < dwResumeHandle) && (pIniTnSFilter != NULL)) {
|
||
|
bMatches = MatchIniTnSFilter(
|
||
|
pIniTnSFilter,
|
||
|
pTnFilter
|
||
|
);
|
||
|
if (bMatches) {
|
||
|
i++;
|
||
|
}
|
||
|
pIniTnSFilter = pIniTnSFilter->pNext;
|
||
|
}
|
||
|
|
||
|
if (!pIniTnSFilter) {
|
||
|
if (!(dwFlags & RETURN_DEFAULTS_ON_NO_MATCH)) {
|
||
|
dwError = ERROR_NO_DATA;
|
||
|
BAIL_ON_LOCK_ERROR(dwError);
|
||
|
}
|
||
|
else {
|
||
|
dwError = CopyTnMatchDefaults(
|
||
|
&pMatchedTnFilters,
|
||
|
&pMatchedQMPolicies,
|
||
|
&dwNumMatches
|
||
|
);
|
||
|
BAIL_ON_LOCK_ERROR(dwError);
|
||
|
BAIL_ON_LOCK_SUCCESS(dwError);
|
||
|
}
|
||
|
}
|
||
|
|
||
|
pTemp = pIniTnSFilter;
|
||
|
|
||
|
while (pTemp && (dwNumMatches < dwNumToMatch)) {
|
||
|
bMatches = MatchIniTnSFilter(
|
||
|
pTemp,
|
||
|
pTnFilter
|
||
|
);
|
||
|
if (bMatches) {
|
||
|
pLastMatchedFilter = pTemp;
|
||
|
dwNumMatches++;
|
||
|
}
|
||
|
pTemp = pTemp->pNext;
|
||
|
}
|
||
|
|
||
|
if (!dwNumMatches) {
|
||
|
if (!(dwFlags & RETURN_DEFAULTS_ON_NO_MATCH)) {
|
||
|
dwError = ERROR_NO_DATA;
|
||
|
BAIL_ON_LOCK_ERROR(dwError);
|
||
|
}
|
||
|
else {
|
||
|
dwError = CopyTnMatchDefaults(
|
||
|
&pMatchedTnFilters,
|
||
|
&pMatchedQMPolicies,
|
||
|
&dwNumMatches
|
||
|
);
|
||
|
BAIL_ON_LOCK_ERROR(dwError);
|
||
|
BAIL_ON_LOCK_SUCCESS(dwError);
|
||
|
}
|
||
|
}
|
||
|
|
||
|
dwError = SPDApiBufferAllocate(
|
||
|
sizeof(TUNNEL_FILTER)*dwNumMatches,
|
||
|
&pMatchedTnFilters
|
||
|
);
|
||
|
BAIL_ON_LOCK_ERROR(dwError);
|
||
|
|
||
|
dwError = SPDApiBufferAllocate(
|
||
|
sizeof(IPSEC_QM_POLICY)*dwNumMatches,
|
||
|
&pMatchedQMPolicies
|
||
|
);
|
||
|
BAIL_ON_LOCK_ERROR(dwError);
|
||
|
|
||
|
|
||
|
if (dwNumMatches == 1) {
|
||
|
|
||
|
dwError = CopyTnSFilter(
|
||
|
pLastMatchedFilter,
|
||
|
pMatchedTnFilters
|
||
|
);
|
||
|
BAIL_ON_LOCK_ERROR(dwError);
|
||
|
dwNumFilters++;
|
||
|
|
||
|
if (pLastMatchedFilter->pIniQMPolicy) {
|
||
|
dwError = CopyQMPolicy(
|
||
|
pLastMatchedFilter->pIniQMPolicy,
|
||
|
pMatchedQMPolicies
|
||
|
);
|
||
|
BAIL_ON_LOCK_ERROR(dwError);
|
||
|
}
|
||
|
else {
|
||
|
memset(pMatchedQMPolicies, 0, sizeof(IPSEC_QM_POLICY));
|
||
|
}
|
||
|
dwNumPolicies++;
|
||
|
|
||
|
}
|
||
|
else {
|
||
|
|
||
|
pTemp = pIniTnSFilter;
|
||
|
pMatchedTnFilter = pMatchedTnFilters;
|
||
|
pMatchedQMPolicy = pMatchedQMPolicies;
|
||
|
i = 0;
|
||
|
|
||
|
while (i < dwNumMatches) {
|
||
|
|
||
|
bMatches = MatchIniTnSFilter(
|
||
|
pTemp,
|
||
|
pTnFilter
|
||
|
);
|
||
|
if (bMatches) {
|
||
|
|
||
|
dwError = CopyTnSFilter(
|
||
|
pTemp,
|
||
|
pMatchedTnFilter
|
||
|
);
|
||
|
BAIL_ON_LOCK_ERROR(dwError);
|
||
|
pMatchedTnFilter++;
|
||
|
dwNumFilters++;
|
||
|
|
||
|
if (pTemp->pIniQMPolicy) {
|
||
|
dwError = CopyQMPolicy(
|
||
|
pTemp->pIniQMPolicy,
|
||
|
pMatchedQMPolicy
|
||
|
);
|
||
|
BAIL_ON_LOCK_ERROR(dwError);
|
||
|
}
|
||
|
else {
|
||
|
memset(pMatchedQMPolicy, 0, sizeof(IPSEC_QM_POLICY));
|
||
|
}
|
||
|
pMatchedQMPolicy++;
|
||
|
dwNumPolicies++;
|
||
|
|
||
|
i++;
|
||
|
|
||
|
}
|
||
|
|
||
|
pTemp = pTemp->pNext;
|
||
|
|
||
|
}
|
||
|
|
||
|
}
|
||
|
|
||
|
lock_success:
|
||
|
|
||
|
LEAVE_SPD_SECTION();
|
||
|
|
||
|
*ppMatchedTnFilters = pMatchedTnFilters;
|
||
|
*ppMatchedQMPolicies = pMatchedQMPolicies;
|
||
|
*pdwNumMatches = dwNumMatches;
|
||
|
*pdwResumeHandle = dwResumeHandle + dwNumMatches;
|
||
|
|
||
|
return (dwError);
|
||
|
|
||
|
lock:
|
||
|
|
||
|
LEAVE_SPD_SECTION();
|
||
|
|
||
|
error:
|
||
|
|
||
|
if (pMatchedTnFilters) {
|
||
|
FreeTnFilters(
|
||
|
dwNumFilters,
|
||
|
pMatchedTnFilters
|
||
|
);
|
||
|
}
|
||
|
|
||
|
if (pMatchedQMPolicies) {
|
||
|
FreeQMPolicies(
|
||
|
dwNumPolicies,
|
||
|
pMatchedQMPolicies
|
||
|
);
|
||
|
}
|
||
|
|
||
|
*ppMatchedTnFilters = NULL;
|
||
|
*ppMatchedQMPolicies = NULL;
|
||
|
*pdwNumMatches = 0;
|
||
|
*pdwResumeHandle = dwResumeHandle;
|
||
|
|
||
|
return (dwError);
|
||
|
}
|
||
|
|
||
|
|
||
|
DWORD
|
||
|
ValidateTnFilterTemplate(
|
||
|
PTUNNEL_FILTER pTnFilter
|
||
|
)
|
||
|
{
|
||
|
DWORD dwError = 0;
|
||
|
BOOL bConflicts = FALSE;
|
||
|
|
||
|
|
||
|
if (!pTnFilter) {
|
||
|
dwError = ERROR_INVALID_PARAMETER;
|
||
|
BAIL_ON_WIN32_ERROR(dwError);
|
||
|
}
|
||
|
|
||
|
dwError = VerifyAddresses(pTnFilter->SrcAddr, TRUE, FALSE);
|
||
|
BAIL_ON_WIN32_ERROR(dwError);
|
||
|
|
||
|
dwError = VerifyAddresses(pTnFilter->DesAddr, TRUE, TRUE);
|
||
|
BAIL_ON_WIN32_ERROR(dwError);
|
||
|
|
||
|
bConflicts = AddressesConflict(
|
||
|
pTnFilter->SrcAddr,
|
||
|
pTnFilter->DesAddr
|
||
|
);
|
||
|
if (bConflicts) {
|
||
|
dwError = ERROR_INVALID_PARAMETER;
|
||
|
BAIL_ON_WIN32_ERROR(dwError);
|
||
|
}
|
||
|
|
||
|
dwError = VerifyAddresses(pTnFilter->DesTunnelAddr, TRUE, FALSE);
|
||
|
BAIL_ON_WIN32_ERROR(dwError);
|
||
|
|
||
|
dwError = VerifyProtocols(pTnFilter->Protocol);
|
||
|
BAIL_ON_WIN32_ERROR(dwError);
|
||
|
|
||
|
dwError = VerifyPortsForProtocol(
|
||
|
pTnFilter->SrcPort,
|
||
|
pTnFilter->Protocol
|
||
|
);
|
||
|
BAIL_ON_WIN32_ERROR(dwError);
|
||
|
|
||
|
dwError = VerifyPortsForProtocol(
|
||
|
pTnFilter->DesPort,
|
||
|
pTnFilter->Protocol
|
||
|
);
|
||
|
BAIL_ON_WIN32_ERROR(dwError);
|
||
|
|
||
|
if (pTnFilter->dwDirection) {
|
||
|
if ((pTnFilter->dwDirection != FILTER_DIRECTION_INBOUND) &&
|
||
|
(pTnFilter->dwDirection != FILTER_DIRECTION_OUTBOUND)) {
|
||
|
dwError = ERROR_INVALID_PARAMETER;
|
||
|
BAIL_ON_WIN32_ERROR(dwError);
|
||
|
}
|
||
|
}
|
||
|
|
||
|
error:
|
||
|
|
||
|
return (dwError);
|
||
|
}
|
||
|
|
||
|
|
||
|
BOOL
|
||
|
MatchIniTnSFilter(
|
||
|
PINITNSFILTER pIniTnSFilter,
|
||
|
PTUNNEL_FILTER pTnFilter
|
||
|
)
|
||
|
{
|
||
|
BOOL bMatches = FALSE;
|
||
|
|
||
|
if (pTnFilter->dwDirection) {
|
||
|
if (pTnFilter->dwDirection != pIniTnSFilter->dwDirection) {
|
||
|
return (FALSE);
|
||
|
}
|
||
|
}
|
||
|
|
||
|
if ((pIniTnSFilter->InboundFilterFlag != NEGOTIATE_SECURITY) &&
|
||
|
(pIniTnSFilter->OutboundFilterFlag != NEGOTIATE_SECURITY)) {
|
||
|
return (FALSE);
|
||
|
}
|
||
|
|
||
|
bMatches = MatchAddresses(
|
||
|
pIniTnSFilter->SrcAddr,
|
||
|
pTnFilter->SrcAddr
|
||
|
);
|
||
|
if (!bMatches) {
|
||
|
return (FALSE);
|
||
|
}
|
||
|
|
||
|
bMatches = MatchAddresses(
|
||
|
pIniTnSFilter->DesAddr,
|
||
|
pTnFilter->DesAddr
|
||
|
);
|
||
|
if (!bMatches) {
|
||
|
return (FALSE);
|
||
|
}
|
||
|
|
||
|
bMatches = MatchAddresses(
|
||
|
pIniTnSFilter->DesTunnelAddr,
|
||
|
pTnFilter->DesTunnelAddr
|
||
|
);
|
||
|
if (!bMatches) {
|
||
|
return (FALSE);
|
||
|
}
|
||
|
|
||
|
bMatches = MatchPorts(
|
||
|
pIniTnSFilter->SrcPort,
|
||
|
pTnFilter->SrcPort
|
||
|
);
|
||
|
if (!bMatches) {
|
||
|
return (FALSE);
|
||
|
}
|
||
|
|
||
|
bMatches = MatchPorts(
|
||
|
pIniTnSFilter->DesPort,
|
||
|
pTnFilter->DesPort
|
||
|
);
|
||
|
if (!bMatches) {
|
||
|
return (FALSE);
|
||
|
}
|
||
|
|
||
|
bMatches = MatchProtocols(
|
||
|
pIniTnSFilter->Protocol,
|
||
|
pTnFilter->Protocol
|
||
|
);
|
||
|
if (!bMatches) {
|
||
|
return (FALSE);
|
||
|
}
|
||
|
|
||
|
return (TRUE);
|
||
|
}
|
||
|
|
||
|
|
||
|
DWORD
|
||
|
CopyTnMatchDefaults(
|
||
|
PTUNNEL_FILTER * ppTnFilters,
|
||
|
PIPSEC_QM_POLICY * ppQMPolicies,
|
||
|
PDWORD pdwNumMatches
|
||
|
)
|
||
|
{
|
||
|
DWORD dwError = 0;
|
||
|
PTUNNEL_FILTER pTnFilters = NULL;
|
||
|
PIPSEC_QM_POLICY pQMPolicies = NULL;
|
||
|
DWORD dwNumFilters = 0;
|
||
|
DWORD dwNumPolicies = 0;
|
||
|
|
||
|
|
||
|
if (!gpIniDefaultQMPolicy) {
|
||
|
dwError = ERROR_IPSEC_DEFAULT_QM_POLICY_NOT_FOUND;
|
||
|
BAIL_ON_WIN32_ERROR(dwError);
|
||
|
}
|
||
|
|
||
|
dwError = SPDApiBufferAllocate(
|
||
|
sizeof(TUNNEL_FILTER),
|
||
|
&pTnFilters
|
||
|
);
|
||
|
BAIL_ON_WIN32_ERROR(dwError);
|
||
|
|
||
|
dwError = SPDApiBufferAllocate(
|
||
|
sizeof(IPSEC_QM_POLICY),
|
||
|
&pQMPolicies
|
||
|
);
|
||
|
BAIL_ON_WIN32_ERROR(dwError);
|
||
|
|
||
|
dwError = CopyDefaultTnFilter(
|
||
|
pTnFilters,
|
||
|
gpIniDefaultQMPolicy
|
||
|
);
|
||
|
BAIL_ON_WIN32_ERROR(dwError);
|
||
|
dwNumFilters++;
|
||
|
|
||
|
dwError = CopyQMPolicy(
|
||
|
gpIniDefaultQMPolicy,
|
||
|
pQMPolicies
|
||
|
);
|
||
|
BAIL_ON_WIN32_ERROR(dwError);
|
||
|
dwNumPolicies++;
|
||
|
|
||
|
*ppTnFilters = pTnFilters;
|
||
|
*ppQMPolicies = pQMPolicies;
|
||
|
*pdwNumMatches = 1;
|
||
|
|
||
|
return (dwError);
|
||
|
|
||
|
error:
|
||
|
|
||
|
if (pTnFilters) {
|
||
|
FreeTnFilters(
|
||
|
dwNumFilters,
|
||
|
pTnFilters
|
||
|
);
|
||
|
}
|
||
|
|
||
|
if (pQMPolicies) {
|
||
|
FreeQMPolicies(
|
||
|
dwNumPolicies,
|
||
|
pQMPolicies
|
||
|
);
|
||
|
}
|
||
|
|
||
|
*ppTnFilters = NULL;
|
||
|
*ppQMPolicies = NULL;
|
||
|
*pdwNumMatches = 0;
|
||
|
|
||
|
return (dwError);
|
||
|
}
|
||
|
|
||
|
|
||
|
DWORD
|
||
|
CopyDefaultTnFilter(
|
||
|
PTUNNEL_FILTER pTnFilter,
|
||
|
PINIQMPOLICY pIniQMPolicy
|
||
|
)
|
||
|
{
|
||
|
DWORD dwError = 0;
|
||
|
|
||
|
|
||
|
UuidCreate(&(pTnFilter->gFilterID));
|
||
|
|
||
|
dwError = CopyName(
|
||
|
L"0",
|
||
|
&(pTnFilter->pszFilterName)
|
||
|
);
|
||
|
BAIL_ON_WIN32_ERROR(dwError);
|
||
|
|
||
|
pTnFilter->InterfaceType = INTERFACE_TYPE_ALL;
|
||
|
|
||
|
pTnFilter->bCreateMirror = TRUE;
|
||
|
|
||
|
pTnFilter->dwFlags = 0;
|
||
|
pTnFilter->dwFlags |= IPSEC_QM_POLICY_DEFAULT_POLICY;
|
||
|
|
||
|
pTnFilter->SrcAddr.AddrType = IP_ADDR_SUBNET;
|
||
|
pTnFilter->SrcAddr.uIpAddr = SUBNET_ADDRESS_ANY;
|
||
|
pTnFilter->SrcAddr.uSubNetMask = SUBNET_MASK_ANY;
|
||
|
|
||
|
pTnFilter->DesAddr.AddrType = IP_ADDR_SUBNET;
|
||
|
pTnFilter->DesAddr.uIpAddr = SUBNET_ADDRESS_ANY;
|
||
|
pTnFilter->DesAddr.uSubNetMask = SUBNET_MASK_ANY;
|
||
|
|
||
|
pTnFilter->SrcTunnelAddr.AddrType = IP_ADDR_SUBNET;
|
||
|
pTnFilter->SrcTunnelAddr.uIpAddr = SUBNET_ADDRESS_ANY;
|
||
|
pTnFilter->SrcTunnelAddr.uSubNetMask = SUBNET_MASK_ANY;
|
||
|
|
||
|
pTnFilter->DesTunnelAddr.AddrType = IP_ADDR_SUBNET;
|
||
|
pTnFilter->DesTunnelAddr.uIpAddr = SUBNET_ADDRESS_ANY;
|
||
|
pTnFilter->DesTunnelAddr.uSubNetMask = SUBNET_MASK_ANY;
|
||
|
|
||
|
pTnFilter->Protocol.ProtocolType = PROTOCOL_UNIQUE;
|
||
|
pTnFilter->Protocol.dwProtocol = 0;
|
||
|
|
||
|
pTnFilter->SrcPort.PortType = PORT_UNIQUE;
|
||
|
pTnFilter->SrcPort.wPort = 0;
|
||
|
|
||
|
pTnFilter->DesPort.PortType = PORT_UNIQUE;
|
||
|
pTnFilter->DesPort.wPort = 0;
|
||
|
|
||
|
pTnFilter->InboundFilterFlag = NEGOTIATE_SECURITY;
|
||
|
|
||
|
pTnFilter->OutboundFilterFlag = NEGOTIATE_SECURITY;
|
||
|
|
||
|
pTnFilter->dwDirection = 0;
|
||
|
|
||
|
pTnFilter->dwWeight = 0;
|
||
|
|
||
|
CopyGuid(pIniQMPolicy->gPolicyID, &(pTnFilter->gPolicyID));
|
||
|
|
||
|
error:
|
||
|
|
||
|
return (dwError);
|
||
|
}
|
||
|
|