|
|
/*++
Copyright (c) 1999 Microsoft Corporation
Module Name:
mmspecific.c
Abstract:
This module contains all of the code to drive the mm specific filter list management of IPSecSPD Service.
Author:
abhisheV 08-December-1999
Environment
User Level: Win32
Revision History:
--*/
#include "precomp.h"
DWORD ApplyMMTransform( PINIMMFILTER pFilter, MATCHING_ADDR * pMatchingAddresses, DWORD dwAddrCnt, PSPECIAL_ADDR pSpecialAddrsList, PINIMMSFILTER * ppSpecificFilters ) /*++
Routine Description:
This function expands a generic mm 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; PINIMMSFILTER pSpecificFilters = NULL; PINIMMSFILTER pOutboundSpecificFilters = NULL; PINIMMSFILTER pInboundSpecificFilters = NULL;
PADDR_V4 pOutSrcAddrList = NULL; DWORD dwOutSrcAddrCnt = 0; PADDR_V4 pInSrcAddrList = NULL; DWORD dwInSrcAddrCnt = 0;
PADDR_V4 pOutDesAddrList = NULL; DWORD dwOutDesAddrCnt = 0; PADDR_V4 pInDesAddrList = NULL; DWORD dwInDesAddrCnt = 0;
//
// Form the outbound and inbound source and destination
// address lists.
//
dwError = FormMMOutboundInboundAddresses( pFilter, pMatchingAddresses, dwAddrCnt, pSpecialAddrsList, &pOutSrcAddrList, &dwOutSrcAddrCnt, &pInSrcAddrList, &dwInSrcAddrCnt, &pOutDesAddrList, &dwOutDesAddrCnt, &pInDesAddrList, &dwInDesAddrCnt ); BAIL_ON_WIN32_ERROR(dwError);
//
// Form outbound specific filters.
//
dwError = FormSpecificMMFilters( pFilter, pOutSrcAddrList, dwOutSrcAddrCnt, pOutDesAddrList, dwOutDesAddrCnt, FILTER_DIRECTION_OUTBOUND, &pOutboundSpecificFilters ); BAIL_ON_WIN32_ERROR(dwError);
//
// Form inbound specific filters.
//
dwError = FormSpecificMMFilters( pFilter, pInSrcAddrList, dwInSrcAddrCnt, pInDesAddrList, dwInDesAddrCnt, FILTER_DIRECTION_INBOUND, &pInboundSpecificFilters ); BAIL_ON_WIN32_ERROR(dwError);
pSpecificFilters = pOutboundSpecificFilters;
AddToSpecificMMList( &pSpecificFilters, pInboundSpecificFilters );
*ppSpecificFilters = pSpecificFilters;
cleanup:
if (pOutSrcAddrList) { FreeSPDMemory(pOutSrcAddrList); }
if (pInSrcAddrList) { FreeSPDMemory(pInSrcAddrList); }
if (pOutDesAddrList) { FreeSPDMemory(pOutDesAddrList); }
if (pInDesAddrList) { FreeSPDMemory(pInDesAddrList); }
return (dwError);
error:
if (pOutboundSpecificFilters) { FreeIniMMSFilterList(pOutboundSpecificFilters); }
if (pInboundSpecificFilters) { FreeIniMMSFilterList(pInboundSpecificFilters); }
*ppSpecificFilters = NULL; goto cleanup; }
DWORD FormMMOutboundInboundAddresses( PINIMMFILTER pFilter, MATCHING_ADDR * pMatchingAddresses, DWORD dwAddrCnt, PSPECIAL_ADDR pSpecialAddrsList, PADDR_V4 * ppOutSrcAddrList, PDWORD pdwOutSrcAddrCnt, PADDR_V4 * ppInSrcAddrList, PDWORD pdwInSrcAddrCnt, PADDR_V4 * ppOutDesAddrList, PDWORD pdwOutDesAddrCnt, PADDR_V4 * ppInDesAddrList, PDWORD pdwInDesAddrCnt ) /*++
Routine Description:
This function forms the outbound and inbound source and destination 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.
ppOutSrcAddrList - List of outbound source addresses.
pdwOutSrcAddrCnt - Number of addresses in the outbound source address list.
ppInSrcAddrList - List of inbound source addresses.
pdwInSrcAddrCnt - Number of addresses in the inbound source address list.
ppOutDesAddrList - List of outbound destination addresses.
pdwOutDesAddrCnt - Number of addresses in the outbound destination address list.
ppInDesAddrList - List of inbound destination addresses.
pdwInDesAddrCnt - Number of addresses in the inbound destination address list.
Return Value:
ERROR_SUCCESS - Success.
Win32 Error - Failure.
--*/ { DWORD dwError = 0;
PADDR_V4 pSrcAddrList = NULL; DWORD dwSrcAddrCnt = 0; PADDR_V4 pDesAddrList = NULL; DWORD dwDesAddrCnt = 0;
PADDR_V4 pOutSrcAddrList = NULL; DWORD dwOutSrcAddrCnt = 0; PADDR_V4 pInSrcAddrList = NULL; DWORD dwInSrcAddrCnt = 0;
PADDR_V4 pOutDesAddrList = NULL; DWORD dwOutDesAddrCnt = 0; PADDR_V4 pInDesAddrList = NULL; DWORD dwInDesAddrCnt = 0;
//
// Replace wild card information to generate the new source
// address list.
//
dwError = FormAddressList( pFilter->SrcAddr, pMatchingAddresses, dwAddrCnt, pSpecialAddrsList, pFilter->InterfaceType, &pSrcAddrList, &dwSrcAddrCnt ); BAIL_ON_WIN32_ERROR(dwError);
//
// Replace wild card information to generate the new destination
// address list.
//
dwError = FormAddressList( pFilter->DesAddr, pMatchingAddresses, dwAddrCnt, pSpecialAddrsList, pFilter->InterfaceType, &pDesAddrList, &dwDesAddrCnt ); BAIL_ON_WIN32_ERROR(dwError);
//
// Separate the source address list into outbound and inbound
// source address sets based on the local machine's ip addresses.
//
dwError = SeparateAddrList( pFilter->SrcAddr.AddrType, pSrcAddrList, dwSrcAddrCnt, pMatchingAddresses, dwAddrCnt, &pOutSrcAddrList, &dwOutSrcAddrCnt, &pInSrcAddrList, &dwInSrcAddrCnt ); BAIL_ON_WIN32_ERROR(dwError);
//
// Separate the destination address list into outbound and inbound
// destination address sets based on the local machine's ip
// addresses.
//
dwError = SeparateAddrList( pFilter->DesAddr.AddrType, pDesAddrList, dwDesAddrCnt, pMatchingAddresses, dwAddrCnt, &pInDesAddrList, &dwInDesAddrCnt, &pOutDesAddrList, &dwOutDesAddrCnt ); BAIL_ON_WIN32_ERROR(dwError);
*ppOutSrcAddrList = pOutSrcAddrList; *pdwOutSrcAddrCnt = dwOutSrcAddrCnt; *ppInSrcAddrList = pInSrcAddrList; *pdwInSrcAddrCnt = dwInSrcAddrCnt;
*ppOutDesAddrList = pOutDesAddrList; *pdwOutDesAddrCnt = dwOutDesAddrCnt; *ppInDesAddrList = pInDesAddrList; *pdwInDesAddrCnt = dwInDesAddrCnt;
cleanup:
if (pSrcAddrList) { FreeSPDMemory(pSrcAddrList); }
if (pDesAddrList) { FreeSPDMemory(pDesAddrList); }
return (dwError);
error:
if (pOutSrcAddrList) { FreeSPDMemory(pOutSrcAddrList); }
if (pInSrcAddrList) { FreeSPDMemory(pInSrcAddrList); }
if (pOutDesAddrList) { FreeSPDMemory(pOutDesAddrList); }
if (pInDesAddrList) { FreeSPDMemory(pInDesAddrList); }
*ppOutSrcAddrList = NULL; *pdwOutSrcAddrCnt = 0; *ppInSrcAddrList = NULL; *pdwInSrcAddrCnt = 0;
*ppOutDesAddrList = NULL; *pdwOutDesAddrCnt = 0; *ppInDesAddrList = NULL; *pdwInDesAddrCnt = 0;
goto cleanup; }
DWORD FormSpecificMMFilters( PINIMMFILTER pFilter, PADDR_V4 pSrcAddrList, DWORD dwSrcAddrCnt, PADDR_V4 pDesAddrList, DWORD dwDesAddrCnt, DWORD dwDirection, PINIMMSFILTER * ppSpecificFilters ) /*++
Routine Description:
This function forms the specific main mode 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.
ppSpecificFilters - Specific filters created for the given generic filter and the given addresses.
Return Value:
ERROR_SUCCESS - Success.
Win32 Error - Failure.
--*/ { DWORD dwError = 0; PINIMMSFILTER pSpecificFilters = NULL; DWORD i = 0, j = 0; PINIMMSFILTER pSpecificFilter = NULL;
for (i = 0; i < dwSrcAddrCnt; i++) {
for (j = 0; j < dwDesAddrCnt; j++) {
dwError = CreateSpecificMMFilter( pFilter, pSrcAddrList[i], pDesAddrList[j], &pSpecificFilter ); BAIL_ON_WIN32_ERROR(dwError);
//
// Set the direction of the filter.
//
pSpecificFilter->dwDirection = dwDirection;
AssignMMFilterWeight(pSpecificFilter);
AddToSpecificMMList( &pSpecificFilters, pSpecificFilter );
}
}
*ppSpecificFilters = pSpecificFilters; return (dwError);
error:
if (pSpecificFilters) { FreeIniMMSFilterList(pSpecificFilters); }
*ppSpecificFilters = NULL; return (dwError); }
DWORD CreateSpecificMMFilter( PINIMMFILTER pGenericFilter, ADDR_V4 SrcAddr, ADDR_V4 DesAddr, PINIMMSFILTER * ppSpecificFilter ) { DWORD dwError = 0; PINIMMSFILTER pSpecificFilter = NULL;
dwError = AllocateSPDMemory( sizeof(INIMMSFILTER), &pSpecificFilter ); BAIL_ON_WIN32_ERROR(dwError);
pSpecificFilter->cRef = 0;
pSpecificFilter->IpVersion = pGenericFilter->IpVersion;
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));
//
// Direction must be set in the calling routine.
//
pSpecificFilter->dwDirection = 0;
//
// Weight must be set in the calling routine.
//
pSpecificFilter->dwWeight = 0;
CopyGuid(pGenericFilter->gMMAuthID, &(pSpecificFilter->gMMAuthID));
CopyGuid(pGenericFilter->gPolicyID, &(pSpecificFilter->gPolicyID));
pSpecificFilter->pIniMMAuthMethods = NULL;
pSpecificFilter->pIniMMPolicy = NULL;
pSpecificFilter->pNext = NULL;
*ppSpecificFilter = pSpecificFilter; return (dwError);
error:
if (pSpecificFilter) { FreeIniMMSFilter(pSpecificFilter); }
*ppSpecificFilter = NULL; return (dwError); }
VOID AssignMMFilterWeight( PINIMMSFILTER pSpecificFilter ) /*++
Routine Description:
Computes and assigns the weight to a specific mm filter.
The mm filter weight consists of the following:
31 16 12 8 0 +-----------+--------+-----------+--------+ |AddrMaskWgt| Reserved | +-----------+--------+-----------+--------+
Arguments:
pSpecificFilter - Specific mm filter to which the weight is to be assigned.
Return Value:
None.
--*/ { DWORD dwWeight = 0; ULONG SrcMask = 0; ULONG DesMask = 0; DWORD dwSrcMaskWeight = 0; DWORD dwDesMaskWeight = 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.
//
//
// 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); dwDesMaskWeight += (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); dwSrcMaskWeight += (i+1); }
//
// Move to the next bit position.
//
SrcMask = SrcMask >> 1;
}
if (dwDesMaskWeight >= dwSrcMaskWeight) { dwWeight |= WEIGHT_ADDRESS_TIE_BREAKER; }
//
// 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 AddToSpecificMMList( PINIMMSFILTER * ppSpecificMMFilterList, PINIMMSFILTER pSpecificMMFilters ) { PINIMMSFILTER pListOne = NULL; PINIMMSFILTER pListTwo = NULL; PINIMMSFILTER pListMerge = NULL; PINIMMSFILTER pLast = NULL;
if (!(*ppSpecificMMFilterList) && !pSpecificMMFilters) { return; }
if (!(*ppSpecificMMFilterList)) { *ppSpecificMMFilterList = pSpecificMMFilters; return; }
if (!pSpecificMMFilters) { return; }
pListOne = *ppSpecificMMFilterList; pListTwo = pSpecificMMFilters;
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 (pListMerge) { if (pListOne) { pLast->pNext = pListOne; } else { pLast->pNext = pListTwo; } }
*ppSpecificMMFilterList = pListMerge; return; }
VOID FreeIniMMSFilterList( PINIMMSFILTER pIniMMSFilterList ) { PINIMMSFILTER pFilter = NULL; PINIMMSFILTER pTempFilter = NULL;
pFilter = pIniMMSFilterList;
while (pFilter) { pTempFilter = pFilter; pFilter = pFilter->pNext; FreeIniMMSFilter(pTempFilter); } }
VOID FreeIniMMSFilter( PINIMMSFILTER pIniMMSFilter ) { if (pIniMMSFilter) { if (pIniMMSFilter->pszFilterName) { FreeSPDString(pIniMMSFilter->pszFilterName); }
//
// Must not ever free pIniMMSFilter->pIniMMPolicy.
//
FreeSPDMemory(pIniMMSFilter); } }
VOID LinkMMSpecificFiltersToPolicy( PINIMMPOLICY pIniMMPolicy, PINIMMSFILTER pIniMMSFilters ) { PINIMMSFILTER pTemp = NULL;
pTemp = pIniMMSFilters;
while (pTemp) { pTemp->pIniMMPolicy = pIniMMPolicy; pTemp = pTemp->pNext; }
return; }
VOID LinkMMSpecificFiltersToAuth( PINIMMAUTHMETHODS pIniMMAuthMethods, PINIMMSFILTER pIniMMSFilters ) { PINIMMSFILTER pTemp = NULL;
pTemp = pIniMMSFilters;
while (pTemp) { pTemp->pIniMMAuthMethods = pIniMMAuthMethods; pTemp = pTemp->pNext; }
return; }
VOID RemoveIniMMSFilter( PINIMMSFILTER pIniMMSFilter ) { PINIMMSFILTER * ppTemp = NULL;
ppTemp = &gpIniMMSFilter;
while (*ppTemp) {
if (*ppTemp == pIniMMSFilter) { break; } ppTemp = &((*ppTemp)->pNext); }
if (*ppTemp) { *ppTemp = pIniMMSFilter->pNext; }
return; }
DWORD EnumSpecificMMFilters( PINIMMSFILTER pIniMMSFilterList, DWORD dwResumeHandle, DWORD dwPreferredNumEntries, PMM_FILTER * ppMMFilters, PDWORD pdwNumMMFilters ) /*++
Routine Description:
This function creates enumerated specific filters.
Arguments:
pIniMMSFilterList - List of specific filters to enumerate.
dwResumeHandle - Location in the specific filter list from which to resume enumeration.
dwPreferredNumEntries - Preferred number of enumeration entries.
ppMMFilters - Enumerated filters returned to the caller.
pdwNumMMFilters - Number of filters actually enumerated.
Return Value:
ERROR_SUCCESS - Success.
Win32 Error - Failure.
--*/ { DWORD dwError = 0; DWORD dwNumToEnum = 0; PINIMMSFILTER pIniMMSFilter = NULL; DWORD i = 0; PINIMMSFILTER pTemp = NULL; DWORD dwNumMMFilters = 0; PMM_FILTER pMMFilters = 0; PMM_FILTER pMMFilter = 0;
if (!dwPreferredNumEntries || (dwPreferredNumEntries > MAX_MMFILTER_ENUM_COUNT)) { dwNumToEnum = MAX_MMFILTER_ENUM_COUNT; } else { dwNumToEnum = dwPreferredNumEntries; }
pIniMMSFilter = pIniMMSFilterList;
for (i = 0; (i < dwResumeHandle) && (pIniMMSFilter != NULL); i++) { pIniMMSFilter = pIniMMSFilter->pNext; }
if (!pIniMMSFilter) { dwError = ERROR_NO_DATA; BAIL_ON_WIN32_ERROR(dwError); }
pTemp = pIniMMSFilter;
while (pTemp && (dwNumMMFilters < dwNumToEnum)) { dwNumMMFilters++; pTemp = pTemp->pNext; }
dwError = SPDApiBufferAllocate( sizeof(MM_FILTER)*dwNumMMFilters, &pMMFilters ); BAIL_ON_WIN32_ERROR(dwError);
pTemp = pIniMMSFilter; pMMFilter = pMMFilters;
for (i = 0; i < dwNumMMFilters; i++) {
dwError = CopyMMSFilter( pTemp, pMMFilter ); BAIL_ON_WIN32_ERROR(dwError);
pTemp = pTemp->pNext; pMMFilter++;
}
*ppMMFilters = pMMFilters; *pdwNumMMFilters = dwNumMMFilters; return (dwError);
error:
if (pMMFilters) { FreeMMFilters( i, pMMFilters ); }
*ppMMFilters = NULL; *pdwNumMMFilters = 0;
return (dwError); }
DWORD CopyMMSFilter( PINIMMSFILTER pIniMMSFilter, PMM_FILTER pMMFilter ) /*++
Routine Description:
This function copies an internal filter into an external filter container.
Arguments:
pIniMMSFilter - Internal filter to copy.
pMMFilter - External filter container in which to copy.
Return Value:
ERROR_SUCCESS - Success.
Win32 Error - Failure.
--*/ { DWORD dwError = 0;
pMMFilter->IpVersion = pIniMMSFilter->IpVersion;
CopyGuid(pIniMMSFilter->gParentID, &(pMMFilter->gFilterID));
dwError = CopyName( pIniMMSFilter->pszFilterName, &(pMMFilter->pszFilterName) ); BAIL_ON_WIN32_ERROR(dwError);
pMMFilter->InterfaceType = pIniMMSFilter->InterfaceType;
pMMFilter->bCreateMirror = FALSE;
pMMFilter->dwFlags = pIniMMSFilter->dwFlags;
dwError = CopyIntToExtAddresses(pIniMMSFilter->SrcAddr, &(pMMFilter->SrcAddr)); BAIL_ON_WIN32_ERROR(dwError);
dwError = CopyIntToExtAddresses(pIniMMSFilter->DesAddr, &(pMMFilter->DesAddr)); BAIL_ON_WIN32_ERROR(dwError);
pMMFilter->dwDirection = pIniMMSFilter->dwDirection;
pMMFilter->dwWeight = pIniMMSFilter->dwWeight;
CopyGuid(pIniMMSFilter->gMMAuthID, &(pMMFilter->gMMAuthID));
CopyGuid(pIniMMSFilter->gPolicyID, &(pMMFilter->gPolicyID));
return (dwError);
error:
if (pMMFilter->pszFilterName) { SPDApiBufferFree(pMMFilter->pszFilterName); pMMFilter->pszFilterName = NULL; }
if (pMMFilter->SrcAddr.pgInterfaceID) { SPDApiBufferFree(pMMFilter->SrcAddr.pgInterfaceID); pMMFilter->SrcAddr.pgInterfaceID = NULL; }
if (pMMFilter->DesAddr.pgInterfaceID) { SPDApiBufferFree(pMMFilter->DesAddr.pgInterfaceID); pMMFilter->DesAddr.pgInterfaceID = NULL; }
return (dwError); }
DWORD EnumSelectSpecificMMFilters( PINIMMFILTER pIniMMFilter, DWORD dwResumeHandle, DWORD dwPreferredNumEntries, PMM_FILTER * ppMMFilters, PDWORD pdwNumMMFilters ) /*++
Routine Description:
This function creates enumerated specific filters for the given generic filter.
Arguments:
pIniMMFilter - 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.
ppMMFilters - Enumerated filters returned to the caller.
pdwNumMMFilters - Number of filters actually enumerated.
Return Value:
ERROR_SUCCESS - Success.
Win32 Error - Failure.
--*/ { DWORD dwError = 0; DWORD dwNumToEnum = 0; DWORD dwNumMMSFilters = 0; PINIMMSFILTER * ppIniMMSFilters = NULL; DWORD i = 0; DWORD dwNumMMFilters = 0; PMM_FILTER pMMFilters = 0; PMM_FILTER pMMFilter = 0;
if (!dwPreferredNumEntries || (dwPreferredNumEntries > MAX_MMFILTER_ENUM_COUNT)) { dwNumToEnum = MAX_MMFILTER_ENUM_COUNT; } else { dwNumToEnum = dwPreferredNumEntries; }
dwNumMMSFilters = pIniMMFilter->dwNumMMSFilters; ppIniMMSFilters = pIniMMFilter->ppIniMMSFilters;
if (!dwNumMMSFilters || (dwNumMMSFilters <= dwResumeHandle)) { dwError = ERROR_NO_DATA; BAIL_ON_WIN32_ERROR(dwError); }
dwNumMMFilters = min((dwNumMMSFilters-dwResumeHandle), dwNumToEnum); dwError = SPDApiBufferAllocate( sizeof(MM_FILTER)*dwNumMMFilters, &pMMFilters ); BAIL_ON_WIN32_ERROR(dwError);
pMMFilter = pMMFilters;
for (i = 0; i < dwNumMMFilters; i++) {
dwError = CopyMMSFilter( *(ppIniMMSFilters + (dwResumeHandle + i)), pMMFilter ); BAIL_ON_WIN32_ERROR(dwError); pMMFilter++;
}
*ppMMFilters = pMMFilters; *pdwNumMMFilters = dwNumMMFilters; return (dwError);
error:
if (pMMFilters) { FreeMMFilters( i, pMMFilters ); }
*ppMMFilters = NULL; *pdwNumMMFilters = 0;
return (dwError); }
DWORD IntMatchMMFilter( LPWSTR pServerName, DWORD dwVersion, PMM_FILTER pMMFilter, DWORD dwFlags, DWORD dwPreferredNumEntries, PMM_FILTER * ppMatchedMMFilters, PIPSEC_MM_POLICY * ppMatchedMMPolicies, PINT_MM_AUTH_METHODS * ppMatchedMMAuthMethods, LPDWORD pdwNumMatches, LPDWORD pdwResumeHandle, LPVOID pvReserved ) /*++
Routine Description:
This function finds the matching mm filters for the given mm 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.
pMMFilter - Filter template to match.
dwFlags - Flags.
ppMatchedMMFilters - Matched main mode filters returned to the caller.
ppMatchedMMPolicies - Main mode policies corresponding to the matched main mode filters returned to the caller.
ppMatchedMMAuthMethods - Main mode auth methods corresponding to the matched main mode 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; PINIMMSFILTER pIniMMSFilter = NULL; DWORD i = 0; BOOL bMatches = FALSE; PINIMMSFILTER pTemp = NULL; DWORD dwNumMatches = 0; PINIMMSFILTER pLastMatchedFilter = NULL; PMM_FILTER pMatchedMMFilters = NULL; PIPSEC_MM_POLICY pMatchedMMPolicies = NULL; PINT_MM_AUTH_METHODS pMatchedMMAuthMethods = NULL; DWORD dwNumFilters = 0; DWORD dwNumPolicies = 0; DWORD dwNumAuthMethods = 0; PMM_FILTER pMatchedMMFilter = NULL; PIPSEC_MM_POLICY pMatchedMMPolicy = NULL; PINT_MM_AUTH_METHODS pTempMMAuthMethods = NULL;
dwError = ValidateMMFilterTemplate( pMMFilter ); BAIL_ON_WIN32_ERROR(dwError);
dwResumeHandle = *pdwResumeHandle;
if (!dwPreferredNumEntries) { dwNumToMatch = 1; } else if (dwPreferredNumEntries > MAX_MMFILTER_ENUM_COUNT) { dwNumToMatch = MAX_MMFILTER_ENUM_COUNT; } else { dwNumToMatch = dwPreferredNumEntries; }
ENTER_SPD_SECTION();
dwError = ValidateMMSecurity( SPD_OBJECT_SERVER, SERVER_ACCESS_ADMINISTER, NULL, NULL ); BAIL_ON_LOCK_ERROR(dwError);
pIniMMSFilter = gpIniMMSFilter;
while ((i < dwResumeHandle) && (pIniMMSFilter != NULL)) { bMatches = MatchIniMMSFilter( pIniMMSFilter, pMMFilter ); if (bMatches) { i++; } pIniMMSFilter = pIniMMSFilter->pNext; }
if (!pIniMMSFilter) { if (!(dwFlags & RETURN_DEFAULTS_ON_NO_MATCH)) { dwError = ERROR_NO_DATA; BAIL_ON_LOCK_ERROR(dwError); } else { dwError = CopyMMMatchDefaults( &pMatchedMMFilters, &pMatchedMMAuthMethods, &pMatchedMMPolicies, &dwNumMatches ); BAIL_ON_LOCK_ERROR(dwError); BAIL_ON_LOCK_SUCCESS(dwError); } }
pTemp = pIniMMSFilter;
while (pTemp && (dwNumMatches < dwNumToMatch)) { bMatches = MatchIniMMSFilter( pTemp, pMMFilter ); 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 = CopyMMMatchDefaults( &pMatchedMMFilters, &pMatchedMMAuthMethods, &pMatchedMMPolicies, &dwNumMatches ); BAIL_ON_LOCK_ERROR(dwError); BAIL_ON_LOCK_SUCCESS(dwError); } }
dwError = SPDApiBufferAllocate( sizeof(MM_FILTER)*dwNumMatches, &pMatchedMMFilters ); BAIL_ON_LOCK_ERROR(dwError);
dwError = SPDApiBufferAllocate( sizeof(IPSEC_MM_POLICY)*dwNumMatches, &pMatchedMMPolicies ); BAIL_ON_LOCK_ERROR(dwError);
dwError = SPDApiBufferAllocate( sizeof(INT_MM_AUTH_METHODS)*dwNumMatches, &pMatchedMMAuthMethods ); BAIL_ON_LOCK_ERROR(dwError);
if (dwNumMatches == 1) {
dwError = CopyMMSFilter( pLastMatchedFilter, pMatchedMMFilters ); BAIL_ON_LOCK_ERROR(dwError); dwNumFilters++;
if (pLastMatchedFilter->pIniMMPolicy) { dwError = CopyMMPolicy( pLastMatchedFilter->pIniMMPolicy, pMatchedMMPolicies ); BAIL_ON_LOCK_ERROR(dwError); } else { memset(pMatchedMMPolicies, 0, sizeof(IPSEC_MM_POLICY)); } dwNumPolicies++;
if (pLastMatchedFilter->pIniMMAuthMethods) { dwError = CopyMMAuthMethods( pLastMatchedFilter->pIniMMAuthMethods, pMatchedMMAuthMethods ); BAIL_ON_LOCK_ERROR(dwError); } else { memset(pMatchedMMAuthMethods, 0, sizeof(INT_MM_AUTH_METHODS)); } dwNumAuthMethods++;
} else {
pTemp = pIniMMSFilter; pMatchedMMFilter = pMatchedMMFilters; pMatchedMMPolicy = pMatchedMMPolicies; pTempMMAuthMethods = pMatchedMMAuthMethods; i = 0;
while (i < dwNumMatches) {
bMatches = MatchIniMMSFilter( pTemp, pMMFilter ); if (bMatches) {
dwError = CopyMMSFilter( pTemp, pMatchedMMFilter ); BAIL_ON_LOCK_ERROR(dwError); pMatchedMMFilter++; dwNumFilters++;
if (pTemp->pIniMMPolicy) { dwError = CopyMMPolicy( pTemp->pIniMMPolicy, pMatchedMMPolicy ); BAIL_ON_LOCK_ERROR(dwError); } else { memset(pMatchedMMPolicy, 0, sizeof(IPSEC_MM_POLICY)); } pMatchedMMPolicy++; dwNumPolicies++;
if (pTemp->pIniMMAuthMethods) { dwError = CopyMMAuthMethods( pTemp->pIniMMAuthMethods, pTempMMAuthMethods ); BAIL_ON_LOCK_ERROR(dwError); } else { memset(pTempMMAuthMethods, 0, sizeof(INT_MM_AUTH_METHODS)); } pTempMMAuthMethods++; dwNumAuthMethods++;
i++;
}
pTemp = pTemp->pNext;
}
}
lock_success:
LEAVE_SPD_SECTION();
*ppMatchedMMFilters = pMatchedMMFilters; *ppMatchedMMPolicies = pMatchedMMPolicies; *ppMatchedMMAuthMethods = pMatchedMMAuthMethods; *pdwNumMatches = dwNumMatches; *pdwResumeHandle = dwResumeHandle + dwNumMatches;
return (dwError);
lock:
LEAVE_SPD_SECTION();
error:
if (pMatchedMMFilters) { FreeMMFilters( dwNumFilters, pMatchedMMFilters ); }
if (pMatchedMMPolicies) { FreeMMPolicies( dwNumPolicies, pMatchedMMPolicies ); }
if (pMatchedMMAuthMethods) { FreeMMAuthMethods( dwNumAuthMethods, pMatchedMMAuthMethods ); }
*ppMatchedMMFilters = NULL; *ppMatchedMMPolicies = NULL; *ppMatchedMMAuthMethods = NULL; *pdwNumMatches = 0; *pdwResumeHandle = dwResumeHandle;
return (dwError); }
DWORD ValidateMMFilterTemplate( PMM_FILTER pMMFilter ) { DWORD dwError = 0; BOOL bConflicts = FALSE;
if (!pMMFilter) { dwError = ERROR_INVALID_PARAMETER; BAIL_ON_WIN32_ERROR(dwError); }
dwError = VerifyAddresses(&(pMMFilter->SrcAddr), TRUE, FALSE); BAIL_ON_WIN32_ERROR(dwError);
dwError = VerifyAddresses(&(pMMFilter->DesAddr), TRUE, TRUE); BAIL_ON_WIN32_ERROR(dwError);
bConflicts = AddressesConflict( pMMFilter->SrcAddr, pMMFilter->DesAddr ); if (bConflicts) { dwError = ERROR_INVALID_PARAMETER; BAIL_ON_WIN32_ERROR(dwError); }
if (pMMFilter->dwDirection) { if ((pMMFilter->dwDirection != FILTER_DIRECTION_INBOUND) && (pMMFilter->dwDirection != FILTER_DIRECTION_OUTBOUND)) { dwError = ERROR_INVALID_PARAMETER; BAIL_ON_WIN32_ERROR(dwError); } }
error:
return (dwError); }
BOOL MatchIniMMSFilter( PINIMMSFILTER pIniMMSFilter, PMM_FILTER pMMFilter ) { BOOL bMatches = FALSE;
if (pMMFilter->dwDirection) { if (pMMFilter->dwDirection != pIniMMSFilter->dwDirection) { return (FALSE); } }
bMatches = MatchAddresses( pIniMMSFilter->SrcAddr, pMMFilter->SrcAddr ); if (!bMatches) { return (FALSE); }
bMatches = MatchAddresses( pIniMMSFilter->DesAddr, pMMFilter->DesAddr ); if (!bMatches) { return (FALSE); }
return (TRUE); }
DWORD CopyMMMatchDefaults( PMM_FILTER * ppMMFilters, PINT_MM_AUTH_METHODS * ppMMAuthMethods, PIPSEC_MM_POLICY * ppMMPolicies, PDWORD pdwNumMatches ) { DWORD dwError = 0; PMM_FILTER pMMFilters = NULL; PINT_MM_AUTH_METHODS pMMAuthMethods = NULL; PIPSEC_MM_POLICY pMMPolicies = NULL; DWORD dwNumFilters = 0; DWORD dwNumAuthMethods = 0; DWORD dwNumPolicies = 0;
if (!gpIniDefaultMMPolicy) { dwError = ERROR_IPSEC_DEFAULT_MM_POLICY_NOT_FOUND; BAIL_ON_WIN32_ERROR(dwError); }
if (!gpIniDefaultMMAuthMethods) { dwError = ERROR_IPSEC_DEFAULT_MM_AUTH_NOT_FOUND; BAIL_ON_WIN32_ERROR(dwError); }
dwError = SPDApiBufferAllocate( sizeof(MM_FILTER), &pMMFilters ); BAIL_ON_WIN32_ERROR(dwError);
dwError = SPDApiBufferAllocate( sizeof(IPSEC_MM_POLICY), &pMMPolicies ); BAIL_ON_WIN32_ERROR(dwError);
dwError = SPDApiBufferAllocate( sizeof(INT_MM_AUTH_METHODS), &pMMAuthMethods ); BAIL_ON_WIN32_ERROR(dwError);
dwError = CopyDefaultMMFilter( pMMFilters, gpIniDefaultMMAuthMethods, gpIniDefaultMMPolicy ); BAIL_ON_WIN32_ERROR(dwError); dwNumFilters++;
dwError = CopyMMPolicy( gpIniDefaultMMPolicy, pMMPolicies ); BAIL_ON_WIN32_ERROR(dwError); pMMPolicies->dwFlags |= IPSEC_MM_POLICY_ON_NO_MATCH; dwNumPolicies++;
dwError = CopyMMAuthMethods( gpIniDefaultMMAuthMethods, pMMAuthMethods ); BAIL_ON_WIN32_ERROR(dwError); pMMAuthMethods->dwFlags |= IPSEC_MM_AUTH_ON_NO_MATCH; dwNumAuthMethods++;
*ppMMFilters = pMMFilters; *ppMMPolicies = pMMPolicies; *ppMMAuthMethods = pMMAuthMethods; *pdwNumMatches = 1;
return (dwError);
error:
if (pMMFilters) { FreeMMFilters( dwNumFilters, pMMFilters ); }
if (pMMPolicies) { FreeMMPolicies( dwNumPolicies, pMMPolicies ); }
if (pMMAuthMethods) { FreeMMAuthMethods( dwNumAuthMethods, pMMAuthMethods ); }
*ppMMFilters = NULL; *ppMMPolicies = NULL; *ppMMAuthMethods = NULL; *pdwNumMatches = 0;
return (dwError); }
DWORD CopyDefaultMMFilter( PMM_FILTER pMMFilter, PINIMMAUTHMETHODS pIniMMAuthMethods, PINIMMPOLICY pIniMMPolicy ) { DWORD dwError = 0; RPC_STATUS RpcStatus = RPC_S_OK;
pMMFilter->IpVersion = IPSEC_PROTOCOL_V4;
RpcStatus = UuidCreate(&(pMMFilter->gFilterID)); if (!(RpcStatus == RPC_S_OK || RpcStatus == RPC_S_UUID_LOCAL_ONLY)) { dwError = RPC_S_CALL_FAILED; BAIL_ON_WIN32_ERROR(dwError); }
dwError = CopyName( L"0", &(pMMFilter->pszFilterName) ); BAIL_ON_WIN32_ERROR(dwError);
pMMFilter->InterfaceType = INTERFACE_TYPE_ALL;
pMMFilter->bCreateMirror = TRUE;
pMMFilter->dwFlags = 0;
pMMFilter->dwFlags |= IPSEC_MM_POLICY_DEFAULT_POLICY; pMMFilter->dwFlags |= IPSEC_MM_AUTH_DEFAULT_AUTH;
pMMFilter->SrcAddr.AddrType = IP_ADDR_SUBNET; pMMFilter->SrcAddr.uIpAddr = SUBNET_ADDRESS_ANY; pMMFilter->SrcAddr.uSubNetMask = SUBNET_MASK_ANY; pMMFilter->SrcAddr.pgInterfaceID = NULL;
pMMFilter->DesAddr.AddrType = IP_ADDR_SUBNET; pMMFilter->DesAddr.uIpAddr = SUBNET_ADDRESS_ANY; pMMFilter->DesAddr.uSubNetMask = SUBNET_MASK_ANY; pMMFilter->DesAddr.pgInterfaceID = NULL;
pMMFilter->dwDirection = 0;
pMMFilter->dwWeight = 0;
CopyGuid(pIniMMAuthMethods->gMMAuthID, &(pMMFilter->gMMAuthID));
CopyGuid(pIniMMPolicy->gPolicyID, &(pMMFilter->gPolicyID));
error:
return (dwError); }
|