Source code of Windows XP (NT5)
You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

1657 lines
37 KiB

  1. /*++
  2. Copyright (c) 1999 Microsoft Corporation
  3. Module Name:
  4. mmspecific.c
  5. Abstract:
  6. This module contains all of the code to drive the
  7. mm specific filter list management of IPSecSPD Service.
  8. Author:
  9. abhisheV 08-December-1999
  10. Environment
  11. User Level: Win32
  12. Revision History:
  13. --*/
  14. #include "precomp.h"
  15. DWORD
  16. ApplyMMTransform(
  17. PINIMMFILTER pFilter,
  18. MATCHING_ADDR * pMatchingAddresses,
  19. DWORD dwAddrCnt,
  20. PINIMMSFILTER * ppSpecificFilters
  21. )
  22. /*++
  23. Routine Description:
  24. This function expands a generic mm filter into its
  25. corresponding specific filters.
  26. Arguments:
  27. pFilter - Generic filter to expand.
  28. pMatchingAddresses - List of local ip addresses whose interface
  29. type matches that of the filter.
  30. dwAddrCnt - Number of local ip addresses in the list.
  31. ppSpecificFilters - List of specific filters expanded for the
  32. given generic filter.
  33. Return Value:
  34. ERROR_SUCCESS - Success.
  35. Win32 Error - Failure.
  36. --*/
  37. {
  38. DWORD dwError = 0;
  39. PINIMMSFILTER pSpecificFilters = NULL;
  40. PINIMMSFILTER pOutboundSpecificFilters = NULL;
  41. PINIMMSFILTER pInboundSpecificFilters = NULL;
  42. PADDR pOutSrcAddrList = NULL;
  43. DWORD dwOutSrcAddrCnt = 0;
  44. PADDR pInSrcAddrList = NULL;
  45. DWORD dwInSrcAddrCnt = 0;
  46. PADDR pOutDesAddrList = NULL;
  47. DWORD dwOutDesAddrCnt = 0;
  48. PADDR pInDesAddrList = NULL;
  49. DWORD dwInDesAddrCnt = 0;
  50. //
  51. // Form the outbound and inbound source and destination
  52. // address lists.
  53. //
  54. dwError = FormMMOutboundInboundAddresses(
  55. pFilter,
  56. pMatchingAddresses,
  57. dwAddrCnt,
  58. &pOutSrcAddrList,
  59. &dwOutSrcAddrCnt,
  60. &pInSrcAddrList,
  61. &dwInSrcAddrCnt,
  62. &pOutDesAddrList,
  63. &dwOutDesAddrCnt,
  64. &pInDesAddrList,
  65. &dwInDesAddrCnt
  66. );
  67. BAIL_ON_WIN32_ERROR(dwError);
  68. //
  69. // Form outbound specific filters.
  70. //
  71. dwError = FormSpecificMMFilters(
  72. pFilter,
  73. pOutSrcAddrList,
  74. dwOutSrcAddrCnt,
  75. pOutDesAddrList,
  76. dwOutDesAddrCnt,
  77. FILTER_DIRECTION_OUTBOUND,
  78. &pOutboundSpecificFilters
  79. );
  80. BAIL_ON_WIN32_ERROR(dwError);
  81. //
  82. // Form inbound specific filters.
  83. //
  84. dwError = FormSpecificMMFilters(
  85. pFilter,
  86. pInSrcAddrList,
  87. dwInSrcAddrCnt,
  88. pInDesAddrList,
  89. dwInDesAddrCnt,
  90. FILTER_DIRECTION_INBOUND,
  91. &pInboundSpecificFilters
  92. );
  93. BAIL_ON_WIN32_ERROR(dwError);
  94. pSpecificFilters = pOutboundSpecificFilters;
  95. AddToSpecificMMList(
  96. &pSpecificFilters,
  97. pInboundSpecificFilters
  98. );
  99. *ppSpecificFilters = pSpecificFilters;
  100. cleanup:
  101. if (pOutSrcAddrList) {
  102. FreeSPDMemory(pOutSrcAddrList);
  103. }
  104. if (pInSrcAddrList) {
  105. FreeSPDMemory(pInSrcAddrList);
  106. }
  107. if (pOutDesAddrList) {
  108. FreeSPDMemory(pOutDesAddrList);
  109. }
  110. if (pInDesAddrList) {
  111. FreeSPDMemory(pInDesAddrList);
  112. }
  113. return (dwError);
  114. error:
  115. if (pOutboundSpecificFilters) {
  116. FreeIniMMSFilterList(pOutboundSpecificFilters);
  117. }
  118. if (pInboundSpecificFilters) {
  119. FreeIniMMSFilterList(pInboundSpecificFilters);
  120. }
  121. *ppSpecificFilters = NULL;
  122. goto cleanup;
  123. }
  124. DWORD
  125. FormMMOutboundInboundAddresses(
  126. PINIMMFILTER pFilter,
  127. MATCHING_ADDR * pMatchingAddresses,
  128. DWORD dwAddrCnt,
  129. PADDR * ppOutSrcAddrList,
  130. PDWORD pdwOutSrcAddrCnt,
  131. PADDR * ppInSrcAddrList,
  132. PDWORD pdwInSrcAddrCnt,
  133. PADDR * ppOutDesAddrList,
  134. PDWORD pdwOutDesAddrCnt,
  135. PADDR * ppInDesAddrList,
  136. PDWORD pdwInDesAddrCnt
  137. )
  138. /*++
  139. Routine Description:
  140. This function forms the outbound and inbound source and
  141. destination address sets for a generic filter.
  142. Arguments:
  143. pFilter - Generic filter under consideration.
  144. pMatchingAddresses - List of local ip addresses whose interface
  145. type matches that of the filter.
  146. dwAddrCnt - Number of local ip addresses in the list.
  147. ppOutSrcAddrList - List of outbound source addresses.
  148. pdwOutSrcAddrCnt - Number of addresses in the outbound
  149. source address list.
  150. ppInSrcAddrList - List of inbound source addresses.
  151. pdwInSrcAddrCnt - Number of addresses in the inbound
  152. source address list.
  153. ppOutDesAddrList - List of outbound destination addresses.
  154. pdwOutDesAddrCnt - Number of addresses in the outbound
  155. destination address list.
  156. ppInDesAddrList - List of inbound destination addresses.
  157. pdwInDesAddrCnt - Number of addresses in the inbound
  158. destination address list.
  159. Return Value:
  160. ERROR_SUCCESS - Success.
  161. Win32 Error - Failure.
  162. --*/
  163. {
  164. DWORD dwError = 0;
  165. PADDR pSrcAddrList = NULL;
  166. DWORD dwSrcAddrCnt = 0;
  167. PADDR pDesAddrList = NULL;
  168. DWORD dwDesAddrCnt = 0;
  169. PADDR pOutSrcAddrList = NULL;
  170. DWORD dwOutSrcAddrCnt = 0;
  171. PADDR pInSrcAddrList = NULL;
  172. DWORD dwInSrcAddrCnt = 0;
  173. PADDR pOutDesAddrList = NULL;
  174. DWORD dwOutDesAddrCnt = 0;
  175. PADDR pInDesAddrList = NULL;
  176. DWORD dwInDesAddrCnt = 0;
  177. //
  178. // Replace wild card information to generate the new source
  179. // address list.
  180. //
  181. dwError = FormAddressList(
  182. pFilter->SrcAddr,
  183. pMatchingAddresses,
  184. dwAddrCnt,
  185. &pSrcAddrList,
  186. &dwSrcAddrCnt
  187. );
  188. BAIL_ON_WIN32_ERROR(dwError);
  189. //
  190. // Replace wild card information to generate the new destination
  191. // address list.
  192. //
  193. dwError = FormAddressList(
  194. pFilter->DesAddr,
  195. pMatchingAddresses,
  196. dwAddrCnt,
  197. &pDesAddrList,
  198. &dwDesAddrCnt
  199. );
  200. BAIL_ON_WIN32_ERROR(dwError);
  201. //
  202. // Separate the source address list into outbound and inbound
  203. // source address sets based on the local machine's ip addresses.
  204. //
  205. dwError = SeparateAddrList(
  206. pFilter->SrcAddr.AddrType,
  207. pSrcAddrList,
  208. dwSrcAddrCnt,
  209. pMatchingAddresses,
  210. dwAddrCnt,
  211. &pOutSrcAddrList,
  212. &dwOutSrcAddrCnt,
  213. &pInSrcAddrList,
  214. &dwInSrcAddrCnt
  215. );
  216. BAIL_ON_WIN32_ERROR(dwError);
  217. //
  218. // Separate the destination address list into outbound and inbound
  219. // destination address sets based on the local machine's ip
  220. // addresses.
  221. //
  222. dwError = SeparateAddrList(
  223. pFilter->DesAddr.AddrType,
  224. pDesAddrList,
  225. dwDesAddrCnt,
  226. pMatchingAddresses,
  227. dwAddrCnt,
  228. &pInDesAddrList,
  229. &dwInDesAddrCnt,
  230. &pOutDesAddrList,
  231. &dwOutDesAddrCnt
  232. );
  233. BAIL_ON_WIN32_ERROR(dwError);
  234. *ppOutSrcAddrList = pOutSrcAddrList;
  235. *pdwOutSrcAddrCnt = dwOutSrcAddrCnt;
  236. *ppInSrcAddrList = pInSrcAddrList;
  237. *pdwInSrcAddrCnt = dwInSrcAddrCnt;
  238. *ppOutDesAddrList = pOutDesAddrList;
  239. *pdwOutDesAddrCnt = dwOutDesAddrCnt;
  240. *ppInDesAddrList = pInDesAddrList;
  241. *pdwInDesAddrCnt = dwInDesAddrCnt;
  242. cleanup:
  243. if (pSrcAddrList) {
  244. FreeSPDMemory(pSrcAddrList);
  245. }
  246. if (pDesAddrList) {
  247. FreeSPDMemory(pDesAddrList);
  248. }
  249. return (dwError);
  250. error:
  251. if (pOutSrcAddrList) {
  252. FreeSPDMemory(pOutSrcAddrList);
  253. }
  254. if (pInSrcAddrList) {
  255. FreeSPDMemory(pInSrcAddrList);
  256. }
  257. if (pOutDesAddrList) {
  258. FreeSPDMemory(pOutDesAddrList);
  259. }
  260. if (pInDesAddrList) {
  261. FreeSPDMemory(pInDesAddrList);
  262. }
  263. *ppOutSrcAddrList = NULL;
  264. *pdwOutSrcAddrCnt = 0;
  265. *ppInSrcAddrList = NULL;
  266. *pdwInSrcAddrCnt = 0;
  267. *ppOutDesAddrList = NULL;
  268. *pdwOutDesAddrCnt = 0;
  269. *ppInDesAddrList = NULL;
  270. *pdwInDesAddrCnt = 0;
  271. goto cleanup;
  272. }
  273. DWORD
  274. FormSpecificMMFilters(
  275. PINIMMFILTER pFilter,
  276. PADDR pSrcAddrList,
  277. DWORD dwSrcAddrCnt,
  278. PADDR pDesAddrList,
  279. DWORD dwDesAddrCnt,
  280. DWORD dwDirection,
  281. PINIMMSFILTER * ppSpecificFilters
  282. )
  283. /*++
  284. Routine Description:
  285. This function forms the specific main mode filters
  286. for the given generic filter and the source and
  287. destination address sets.
  288. Arguments:
  289. pFilter - Generic filter for which specific filters
  290. are to be created.
  291. pSrcAddrList - List of source addresses.
  292. dwSrcAddrCnt - Number of addresses in the source
  293. address list.
  294. pDesAddrList - List of destination addresses.
  295. dwDesAddrCnt - Number of addresses in the destination
  296. address list.
  297. ppSpecificFilters - Specific filters created for the given
  298. generic filter and the given addresses.
  299. Return Value:
  300. ERROR_SUCCESS - Success.
  301. Win32 Error - Failure.
  302. --*/
  303. {
  304. DWORD dwError = 0;
  305. PINIMMSFILTER pSpecificFilters = NULL;
  306. DWORD i = 0, j = 0;
  307. PINIMMSFILTER pSpecificFilter = NULL;
  308. for (i = 0; i < dwSrcAddrCnt; i++) {
  309. for (j = 0; j < dwDesAddrCnt; j++) {
  310. dwError = CreateSpecificMMFilter(
  311. pFilter,
  312. pSrcAddrList[i],
  313. pDesAddrList[j],
  314. &pSpecificFilter
  315. );
  316. BAIL_ON_WIN32_ERROR(dwError);
  317. //
  318. // Set the direction of the filter.
  319. //
  320. pSpecificFilter->dwDirection = dwDirection;
  321. AssignMMFilterWeight(pSpecificFilter);
  322. AddToSpecificMMList(
  323. &pSpecificFilters,
  324. pSpecificFilter
  325. );
  326. }
  327. }
  328. *ppSpecificFilters = pSpecificFilters;
  329. return (dwError);
  330. error:
  331. if (pSpecificFilters) {
  332. FreeIniMMSFilterList(pSpecificFilters);
  333. }
  334. *ppSpecificFilters = NULL;
  335. return (dwError);
  336. }
  337. DWORD
  338. CreateSpecificMMFilter(
  339. PINIMMFILTER pGenericFilter,
  340. ADDR SrcAddr,
  341. ADDR DesAddr,
  342. PINIMMSFILTER * ppSpecificFilter
  343. )
  344. {
  345. DWORD dwError = 0;
  346. PINIMMSFILTER pSpecificFilter = NULL;
  347. dwError = AllocateSPDMemory(
  348. sizeof(INIMMSFILTER),
  349. &pSpecificFilter
  350. );
  351. BAIL_ON_WIN32_ERROR(dwError);
  352. pSpecificFilter->cRef = 0;
  353. CopyGuid(pGenericFilter->gFilterID, &(pSpecificFilter->gParentID));
  354. dwError = AllocateSPDString(
  355. pGenericFilter->pszFilterName,
  356. &(pSpecificFilter->pszFilterName)
  357. );
  358. BAIL_ON_WIN32_ERROR(dwError);
  359. pSpecificFilter->InterfaceType = pGenericFilter->InterfaceType;
  360. pSpecificFilter->dwFlags = pGenericFilter->dwFlags;
  361. CopyAddresses(SrcAddr, &(pSpecificFilter->SrcAddr));
  362. CopyAddresses(DesAddr, &(pSpecificFilter->DesAddr));
  363. //
  364. // Direction must be set in the calling routine.
  365. //
  366. pSpecificFilter->dwDirection = 0;
  367. //
  368. // Weight must be set in the calling routine.
  369. //
  370. pSpecificFilter->dwWeight = 0;
  371. CopyGuid(pGenericFilter->gMMAuthID, &(pSpecificFilter->gMMAuthID));
  372. CopyGuid(pGenericFilter->gPolicyID, &(pSpecificFilter->gPolicyID));
  373. pSpecificFilter->pIniMMAuthMethods = NULL;
  374. pSpecificFilter->pIniMMPolicy = NULL;
  375. pSpecificFilter->pNext = NULL;
  376. *ppSpecificFilter = pSpecificFilter;
  377. return (dwError);
  378. error:
  379. if (pSpecificFilter) {
  380. FreeIniMMSFilter(pSpecificFilter);
  381. }
  382. *ppSpecificFilter = NULL;
  383. return (dwError);
  384. }
  385. VOID
  386. AssignMMFilterWeight(
  387. PINIMMSFILTER pSpecificFilter
  388. )
  389. /*++
  390. Routine Description:
  391. Computes and assigns the weight to a specific mm filter.
  392. The mm filter weight consists of the following:
  393. 31 16 12 8 0
  394. +-----------+--------+-----------+--------+
  395. |AddrMaskWgt| Reserved |
  396. +-----------+--------+-----------+--------+
  397. Arguments:
  398. pSpecificFilter - Specific mm filter to which the weight
  399. is to be assigned.
  400. Return Value:
  401. None.
  402. --*/
  403. {
  404. DWORD dwWeight = 0;
  405. ULONG SrcMask = 0;
  406. ULONG DesMask = 0;
  407. DWORD dwMaskWeight = 0;
  408. DWORD i = 0;
  409. //
  410. // Weight Rule:
  411. // A field with a more specific value gets a higher weight than
  412. // the same field with a lesser specific value.
  413. //
  414. //
  415. // IP addresses get the weight values based on their mask values.
  416. // In the address case, the weight is computed as a sum of the
  417. // bit positions starting from the position that contains the
  418. // first least significant non-zero bit to the most significant
  419. // bit position of the mask.
  420. // All unique ip addresses have a mask of 0xFFFFFFFF and thus get
  421. // the same weight, which is 1 + 2 + .... + 32.
  422. // A subnet address has a mask with atleast the least significant
  423. // bit zero and thus gets weight in the range (2 + .. + 32) to 0.
  424. //
  425. DesMask = ntohl(pSpecificFilter->DesAddr.uSubNetMask);
  426. for (i = 0; i < sizeof(ULONG) * 8; i++) {
  427. //
  428. // If the bit position contains a non-zero bit, add the bit
  429. // position to the sum.
  430. //
  431. if ((DesMask & 0x1) == 0x1) {
  432. dwMaskWeight += (i+1);
  433. }
  434. //
  435. // Move to the next bit position.
  436. //
  437. DesMask = DesMask >> 1;
  438. }
  439. SrcMask = ntohl(pSpecificFilter->SrcAddr.uSubNetMask);
  440. for (i = 0; i < sizeof(ULONG) * 8; i++) {
  441. //
  442. // If the bit position contains a non-zero bit, add the bit
  443. // position to the sum.
  444. //
  445. if ((SrcMask & 0x1) == 0x1) {
  446. dwMaskWeight += (i+1);
  447. }
  448. //
  449. // Move to the next bit position.
  450. //
  451. SrcMask = SrcMask >> 1;
  452. }
  453. //
  454. // Move the mask weight to the set of bits in the overall weight
  455. // that it occupies.
  456. //
  457. dwMaskWeight = dwMaskWeight << 16;
  458. dwWeight += dwMaskWeight;
  459. pSpecificFilter->dwWeight = dwWeight;
  460. }
  461. VOID
  462. AddToSpecificMMList(
  463. PINIMMSFILTER * ppSpecificMMFilterList,
  464. PINIMMSFILTER pSpecificMMFilters
  465. )
  466. {
  467. PINIMMSFILTER pListOne = NULL;
  468. PINIMMSFILTER pListTwo = NULL;
  469. PINIMMSFILTER pListMerge = NULL;
  470. PINIMMSFILTER pLast = NULL;
  471. if (!(*ppSpecificMMFilterList) && !pSpecificMMFilters) {
  472. return;
  473. }
  474. if (!(*ppSpecificMMFilterList)) {
  475. *ppSpecificMMFilterList = pSpecificMMFilters;
  476. return;
  477. }
  478. if (!pSpecificMMFilters) {
  479. return;
  480. }
  481. pListOne = *ppSpecificMMFilterList;
  482. pListTwo = pSpecificMMFilters;
  483. while (pListOne && pListTwo) {
  484. if ((pListOne->dwWeight) > (pListTwo->dwWeight)) {
  485. if (!pListMerge) {
  486. pListMerge = pListOne;
  487. pLast = pListOne;
  488. pListOne = pListOne->pNext;
  489. }
  490. else {
  491. pLast->pNext = pListOne;
  492. pListOne = pListOne->pNext;
  493. pLast = pLast->pNext;
  494. }
  495. }
  496. else {
  497. if (!pListMerge) {
  498. pListMerge = pListTwo;
  499. pLast = pListTwo;
  500. pListTwo = pListTwo->pNext;
  501. }
  502. else {
  503. pLast->pNext = pListTwo;
  504. pListTwo = pListTwo->pNext;
  505. pLast = pLast->pNext;
  506. }
  507. }
  508. }
  509. if (pListOne) {
  510. pLast->pNext = pListOne;
  511. }
  512. else {
  513. pLast->pNext = pListTwo;
  514. }
  515. *ppSpecificMMFilterList = pListMerge;
  516. return;
  517. }
  518. VOID
  519. FreeIniMMSFilterList(
  520. PINIMMSFILTER pIniMMSFilterList
  521. )
  522. {
  523. PINIMMSFILTER pFilter = NULL;
  524. PINIMMSFILTER pTempFilter = NULL;
  525. pFilter = pIniMMSFilterList;
  526. while (pFilter) {
  527. pTempFilter = pFilter;
  528. pFilter = pFilter->pNext;
  529. FreeIniMMSFilter(pTempFilter);
  530. }
  531. }
  532. VOID
  533. FreeIniMMSFilter(
  534. PINIMMSFILTER pIniMMSFilter
  535. )
  536. {
  537. if (pIniMMSFilter) {
  538. if (pIniMMSFilter->pszFilterName) {
  539. FreeSPDString(pIniMMSFilter->pszFilterName);
  540. }
  541. //
  542. // Must not ever free pIniMMSFilter->pIniMMPolicy.
  543. //
  544. FreeSPDMemory(pIniMMSFilter);
  545. }
  546. }
  547. VOID
  548. LinkMMSpecificFiltersToPolicy(
  549. PINIMMPOLICY pIniMMPolicy,
  550. PINIMMSFILTER pIniMMSFilters
  551. )
  552. {
  553. PINIMMSFILTER pTemp = NULL;
  554. pTemp = pIniMMSFilters;
  555. while (pTemp) {
  556. pTemp->pIniMMPolicy = pIniMMPolicy;
  557. pTemp = pTemp->pNext;
  558. }
  559. return;
  560. }
  561. VOID
  562. LinkMMSpecificFiltersToAuth(
  563. PINIMMAUTHMETHODS pIniMMAuthMethods,
  564. PINIMMSFILTER pIniMMSFilters
  565. )
  566. {
  567. PINIMMSFILTER pTemp = NULL;
  568. pTemp = pIniMMSFilters;
  569. while (pTemp) {
  570. pTemp->pIniMMAuthMethods = pIniMMAuthMethods;
  571. pTemp = pTemp->pNext;
  572. }
  573. return;
  574. }
  575. VOID
  576. RemoveIniMMSFilter(
  577. PINIMMSFILTER pIniMMSFilter
  578. )
  579. {
  580. PINIMMSFILTER * ppTemp = NULL;
  581. ppTemp = &gpIniMMSFilter;
  582. while (*ppTemp) {
  583. if (*ppTemp == pIniMMSFilter) {
  584. break;
  585. }
  586. ppTemp = &((*ppTemp)->pNext);
  587. }
  588. if (*ppTemp) {
  589. *ppTemp = pIniMMSFilter->pNext;
  590. }
  591. return;
  592. }
  593. DWORD
  594. EnumSpecificMMFilters(
  595. PINIMMSFILTER pIniMMSFilterList,
  596. DWORD dwResumeHandle,
  597. DWORD dwPreferredNumEntries,
  598. PMM_FILTER * ppMMFilters,
  599. PDWORD pdwNumMMFilters
  600. )
  601. /*++
  602. Routine Description:
  603. This function creates enumerated specific filters.
  604. Arguments:
  605. pIniMMSFilterList - List of specific filters to enumerate.
  606. dwResumeHandle - Location in the specific filter list from which
  607. to resume enumeration.
  608. dwPreferredNumEntries - Preferred number of enumeration entries.
  609. ppMMFilters - Enumerated filters returned to the caller.
  610. pdwNumMMFilters - Number of filters actually enumerated.
  611. Return Value:
  612. ERROR_SUCCESS - Success.
  613. Win32 Error - Failure.
  614. --*/
  615. {
  616. DWORD dwError = 0;
  617. DWORD dwNumToEnum = 0;
  618. PINIMMSFILTER pIniMMSFilter = NULL;
  619. DWORD i = 0;
  620. PINIMMSFILTER pTemp = NULL;
  621. DWORD dwNumMMFilters = 0;
  622. PMM_FILTER pMMFilters = 0;
  623. PMM_FILTER pMMFilter = 0;
  624. if (!dwPreferredNumEntries ||
  625. (dwPreferredNumEntries > MAX_MMFILTER_ENUM_COUNT)) {
  626. dwNumToEnum = MAX_MMFILTER_ENUM_COUNT;
  627. }
  628. else {
  629. dwNumToEnum = dwPreferredNumEntries;
  630. }
  631. pIniMMSFilter = pIniMMSFilterList;
  632. for (i = 0; (i < dwResumeHandle) && (pIniMMSFilter != NULL); i++) {
  633. pIniMMSFilter = pIniMMSFilter->pNext;
  634. }
  635. if (!pIniMMSFilter) {
  636. dwError = ERROR_NO_DATA;
  637. BAIL_ON_WIN32_ERROR(dwError);
  638. }
  639. pTemp = pIniMMSFilter;
  640. while (pTemp && (dwNumMMFilters < dwNumToEnum)) {
  641. dwNumMMFilters++;
  642. pTemp = pTemp->pNext;
  643. }
  644. dwError = SPDApiBufferAllocate(
  645. sizeof(MM_FILTER)*dwNumMMFilters,
  646. &pMMFilters
  647. );
  648. BAIL_ON_WIN32_ERROR(dwError);
  649. pTemp = pIniMMSFilter;
  650. pMMFilter = pMMFilters;
  651. for (i = 0; i < dwNumMMFilters; i++) {
  652. dwError = CopyMMSFilter(
  653. pTemp,
  654. pMMFilter
  655. );
  656. BAIL_ON_WIN32_ERROR(dwError);
  657. pTemp = pTemp->pNext;
  658. pMMFilter++;
  659. }
  660. *ppMMFilters = pMMFilters;
  661. *pdwNumMMFilters = dwNumMMFilters;
  662. return (dwError);
  663. error:
  664. if (pMMFilters) {
  665. FreeMMFilters(
  666. i,
  667. pMMFilters
  668. );
  669. }
  670. *ppMMFilters = NULL;
  671. *pdwNumMMFilters = 0;
  672. return (dwError);
  673. }
  674. DWORD
  675. CopyMMSFilter(
  676. PINIMMSFILTER pIniMMSFilter,
  677. PMM_FILTER pMMFilter
  678. )
  679. /*++
  680. Routine Description:
  681. This function copies an internal filter into an external filter
  682. container.
  683. Arguments:
  684. pIniMMSFilter - Internal filter to copy.
  685. pMMFilter - External filter container in which to copy.
  686. Return Value:
  687. ERROR_SUCCESS - Success.
  688. Win32 Error - Failure.
  689. --*/
  690. {
  691. DWORD dwError = 0;
  692. CopyGuid(pIniMMSFilter->gParentID, &(pMMFilter->gFilterID));
  693. dwError = CopyName(
  694. pIniMMSFilter->pszFilterName,
  695. &(pMMFilter->pszFilterName)
  696. );
  697. BAIL_ON_WIN32_ERROR(dwError);
  698. pMMFilter->InterfaceType = pIniMMSFilter->InterfaceType;
  699. pMMFilter->bCreateMirror = FALSE;
  700. pMMFilter->dwFlags = pIniMMSFilter->dwFlags;
  701. CopyAddresses(pIniMMSFilter->SrcAddr, &(pMMFilter->SrcAddr));
  702. CopyAddresses(pIniMMSFilter->DesAddr, &(pMMFilter->DesAddr));
  703. pMMFilter->dwDirection = pIniMMSFilter->dwDirection;
  704. pMMFilter->dwWeight = pIniMMSFilter->dwWeight;
  705. CopyGuid(pIniMMSFilter->gMMAuthID, &(pMMFilter->gMMAuthID));
  706. CopyGuid(pIniMMSFilter->gPolicyID, &(pMMFilter->gPolicyID));
  707. error:
  708. return (dwError);
  709. }
  710. DWORD
  711. EnumSelectSpecificMMFilters(
  712. PINIMMFILTER pIniMMFilter,
  713. DWORD dwResumeHandle,
  714. DWORD dwPreferredNumEntries,
  715. PMM_FILTER * ppMMFilters,
  716. PDWORD pdwNumMMFilters
  717. )
  718. /*++
  719. Routine Description:
  720. This function creates enumerated specific filters for
  721. the given generic filter.
  722. Arguments:
  723. pIniMMFilter - Generic filter for which specific filters
  724. are to be enumerated.
  725. dwResumeHandle - Location in the specific filter list for the
  726. given generic filter from which to resume
  727. enumeration.
  728. dwPreferredNumEntries - Preferred number of enumeration entries.
  729. ppMMFilters - Enumerated filters returned to the caller.
  730. pdwNumMMFilters - Number of filters actually enumerated.
  731. Return Value:
  732. ERROR_SUCCESS - Success.
  733. Win32 Error - Failure.
  734. --*/
  735. {
  736. DWORD dwError = 0;
  737. DWORD dwNumToEnum = 0;
  738. DWORD dwNumMMSFilters = 0;
  739. PINIMMSFILTER * ppIniMMSFilters = NULL;
  740. DWORD i = 0;
  741. DWORD dwNumMMFilters = 0;
  742. PMM_FILTER pMMFilters = 0;
  743. PMM_FILTER pMMFilter = 0;
  744. if (!dwPreferredNumEntries ||
  745. (dwPreferredNumEntries > MAX_MMFILTER_ENUM_COUNT)) {
  746. dwNumToEnum = MAX_MMFILTER_ENUM_COUNT;
  747. }
  748. else {
  749. dwNumToEnum = dwPreferredNumEntries;
  750. }
  751. dwNumMMSFilters = pIniMMFilter->dwNumMMSFilters;
  752. ppIniMMSFilters = pIniMMFilter->ppIniMMSFilters;
  753. if (!dwNumMMSFilters || (dwNumMMSFilters <= dwResumeHandle)) {
  754. dwError = ERROR_NO_DATA;
  755. BAIL_ON_WIN32_ERROR(dwError);
  756. }
  757. dwNumMMFilters = min((dwNumMMSFilters-dwResumeHandle),
  758. dwNumToEnum);
  759. dwError = SPDApiBufferAllocate(
  760. sizeof(MM_FILTER)*dwNumMMFilters,
  761. &pMMFilters
  762. );
  763. BAIL_ON_WIN32_ERROR(dwError);
  764. pMMFilter = pMMFilters;
  765. for (i = 0; i < dwNumMMFilters; i++) {
  766. dwError = CopyMMSFilter(
  767. *(ppIniMMSFilters + (dwResumeHandle + i)),
  768. pMMFilter
  769. );
  770. BAIL_ON_WIN32_ERROR(dwError);
  771. pMMFilter++;
  772. }
  773. *ppMMFilters = pMMFilters;
  774. *pdwNumMMFilters = dwNumMMFilters;
  775. return (dwError);
  776. error:
  777. if (pMMFilters) {
  778. FreeMMFilters(
  779. i,
  780. pMMFilters
  781. );
  782. }
  783. *ppMMFilters = NULL;
  784. *pdwNumMMFilters = 0;
  785. return (dwError);
  786. }
  787. DWORD
  788. MatchMMFilter(
  789. LPWSTR pServerName,
  790. PMM_FILTER pMMFilter,
  791. DWORD dwFlags,
  792. PMM_FILTER * ppMatchedMMFilters,
  793. PIPSEC_MM_POLICY * ppMatchedMMPolicies,
  794. PMM_AUTH_METHODS * ppMatchedMMAuthMethods,
  795. DWORD dwPreferredNumEntries,
  796. LPDWORD pdwNumMatches,
  797. LPDWORD pdwResumeHandle
  798. )
  799. /*++
  800. Routine Description:
  801. This function finds the matching mm filters for the given mm
  802. filter template. The matched filters can not be more specific
  803. than the given filter template.
  804. Arguments:
  805. pServerName - Server on which a filter template is to be matched.
  806. pMMFilter - Filter template to match.
  807. dwFlags - Flags.
  808. ppMatchedMMFilters - Matched main mode filters returned to the
  809. caller.
  810. ppMatchedMMPolicies - Main mode policies corresponding to the
  811. matched main mode filters returned to the
  812. caller.
  813. ppMatchedMMAuthMethods - Main mode auth methods corresponding to the
  814. matched main mode filters returned to the
  815. caller.
  816. dwPreferredNumEntries - Preferred number of matched entries.
  817. pdwNumMatches - Number of filters actually matched.
  818. pdwResumeHandle - Handle to the location in the matched filter
  819. list from which to resume enumeration.
  820. Return Value:
  821. ERROR_SUCCESS - Success.
  822. Win32 Error - Failure.
  823. --*/
  824. {
  825. DWORD dwError = 0;
  826. DWORD dwResumeHandle = 0;
  827. DWORD dwNumToMatch = 0;
  828. PINIMMSFILTER pIniMMSFilter = NULL;
  829. DWORD i = 0;
  830. BOOL bMatches = FALSE;
  831. PINIMMSFILTER pTemp = NULL;
  832. DWORD dwNumMatches = 0;
  833. PINIMMSFILTER pLastMatchedFilter = NULL;
  834. PMM_FILTER pMatchedMMFilters = NULL;
  835. PIPSEC_MM_POLICY pMatchedMMPolicies = NULL;
  836. PMM_AUTH_METHODS pMatchedMMAuthMethods = NULL;
  837. DWORD dwNumFilters = 0;
  838. DWORD dwNumPolicies = 0;
  839. DWORD dwNumAuthMethods = 0;
  840. PMM_FILTER pMatchedMMFilter = NULL;
  841. PIPSEC_MM_POLICY pMatchedMMPolicy = NULL;
  842. PMM_AUTH_METHODS pTempMMAuthMethods = NULL;
  843. dwError = ValidateMMFilterTemplate(
  844. pMMFilter
  845. );
  846. BAIL_ON_WIN32_ERROR(dwError);
  847. dwResumeHandle = *pdwResumeHandle;
  848. if (!dwPreferredNumEntries) {
  849. dwNumToMatch = 1;
  850. }
  851. else if (dwPreferredNumEntries > MAX_MMFILTER_ENUM_COUNT) {
  852. dwNumToMatch = MAX_MMFILTER_ENUM_COUNT;
  853. }
  854. else {
  855. dwNumToMatch = dwPreferredNumEntries;
  856. }
  857. ENTER_SPD_SECTION();
  858. dwError = ValidateMMSecurity(
  859. SPD_OBJECT_SERVER,
  860. SERVER_ACCESS_ADMINISTER,
  861. NULL,
  862. NULL
  863. );
  864. BAIL_ON_LOCK_ERROR(dwError);
  865. pIniMMSFilter = gpIniMMSFilter;
  866. while ((i < dwResumeHandle) && (pIniMMSFilter != NULL)) {
  867. bMatches = MatchIniMMSFilter(
  868. pIniMMSFilter,
  869. pMMFilter
  870. );
  871. if (bMatches) {
  872. i++;
  873. }
  874. pIniMMSFilter = pIniMMSFilter->pNext;
  875. }
  876. if (!pIniMMSFilter) {
  877. if (!(dwFlags & RETURN_DEFAULTS_ON_NO_MATCH)) {
  878. dwError = ERROR_NO_DATA;
  879. BAIL_ON_LOCK_ERROR(dwError);
  880. }
  881. else {
  882. dwError = CopyMMMatchDefaults(
  883. &pMatchedMMFilters,
  884. &pMatchedMMAuthMethods,
  885. &pMatchedMMPolicies,
  886. &dwNumMatches
  887. );
  888. BAIL_ON_LOCK_ERROR(dwError);
  889. BAIL_ON_LOCK_SUCCESS(dwError);
  890. }
  891. }
  892. pTemp = pIniMMSFilter;
  893. while (pTemp && (dwNumMatches < dwNumToMatch)) {
  894. bMatches = MatchIniMMSFilter(
  895. pTemp,
  896. pMMFilter
  897. );
  898. if (bMatches) {
  899. pLastMatchedFilter = pTemp;
  900. dwNumMatches++;
  901. }
  902. pTemp = pTemp->pNext;
  903. }
  904. if (!dwNumMatches) {
  905. if (!(dwFlags & RETURN_DEFAULTS_ON_NO_MATCH)) {
  906. dwError = ERROR_NO_DATA;
  907. BAIL_ON_LOCK_ERROR(dwError);
  908. }
  909. else {
  910. dwError = CopyMMMatchDefaults(
  911. &pMatchedMMFilters,
  912. &pMatchedMMAuthMethods,
  913. &pMatchedMMPolicies,
  914. &dwNumMatches
  915. );
  916. BAIL_ON_LOCK_ERROR(dwError);
  917. BAIL_ON_LOCK_SUCCESS(dwError);
  918. }
  919. }
  920. dwError = SPDApiBufferAllocate(
  921. sizeof(MM_FILTER)*dwNumMatches,
  922. &pMatchedMMFilters
  923. );
  924. BAIL_ON_LOCK_ERROR(dwError);
  925. dwError = SPDApiBufferAllocate(
  926. sizeof(IPSEC_MM_POLICY)*dwNumMatches,
  927. &pMatchedMMPolicies
  928. );
  929. BAIL_ON_LOCK_ERROR(dwError);
  930. dwError = SPDApiBufferAllocate(
  931. sizeof(MM_AUTH_METHODS)*dwNumMatches,
  932. &pMatchedMMAuthMethods
  933. );
  934. BAIL_ON_LOCK_ERROR(dwError);
  935. if (dwNumMatches == 1) {
  936. dwError = CopyMMSFilter(
  937. pLastMatchedFilter,
  938. pMatchedMMFilters
  939. );
  940. BAIL_ON_LOCK_ERROR(dwError);
  941. dwNumFilters++;
  942. if (pLastMatchedFilter->pIniMMPolicy) {
  943. dwError = CopyMMPolicy(
  944. pLastMatchedFilter->pIniMMPolicy,
  945. pMatchedMMPolicies
  946. );
  947. BAIL_ON_LOCK_ERROR(dwError);
  948. }
  949. else {
  950. memset(pMatchedMMPolicies, 0, sizeof(IPSEC_MM_POLICY));
  951. }
  952. dwNumPolicies++;
  953. if (pLastMatchedFilter->pIniMMAuthMethods) {
  954. dwError = CopyMMAuthMethods(
  955. pLastMatchedFilter->pIniMMAuthMethods,
  956. pMatchedMMAuthMethods
  957. );
  958. BAIL_ON_LOCK_ERROR(dwError);
  959. }
  960. else {
  961. memset(pMatchedMMAuthMethods, 0, sizeof(MM_AUTH_METHODS));
  962. }
  963. dwNumAuthMethods++;
  964. }
  965. else {
  966. pTemp = pIniMMSFilter;
  967. pMatchedMMFilter = pMatchedMMFilters;
  968. pMatchedMMPolicy = pMatchedMMPolicies;
  969. pTempMMAuthMethods = pMatchedMMAuthMethods;
  970. i = 0;
  971. while (i < dwNumMatches) {
  972. bMatches = MatchIniMMSFilter(
  973. pTemp,
  974. pMMFilter
  975. );
  976. if (bMatches) {
  977. dwError = CopyMMSFilter(
  978. pTemp,
  979. pMatchedMMFilter
  980. );
  981. BAIL_ON_LOCK_ERROR(dwError);
  982. pMatchedMMFilter++;
  983. dwNumFilters++;
  984. if (pTemp->pIniMMPolicy) {
  985. dwError = CopyMMPolicy(
  986. pTemp->pIniMMPolicy,
  987. pMatchedMMPolicy
  988. );
  989. BAIL_ON_LOCK_ERROR(dwError);
  990. }
  991. else {
  992. memset(pMatchedMMPolicy, 0, sizeof(IPSEC_MM_POLICY));
  993. }
  994. pMatchedMMPolicy++;
  995. dwNumPolicies++;
  996. if (pTemp->pIniMMAuthMethods) {
  997. dwError = CopyMMAuthMethods(
  998. pTemp->pIniMMAuthMethods,
  999. pTempMMAuthMethods
  1000. );
  1001. BAIL_ON_LOCK_ERROR(dwError);
  1002. }
  1003. else {
  1004. memset(pTempMMAuthMethods, 0, sizeof(MM_AUTH_METHODS));
  1005. }
  1006. pTempMMAuthMethods++;
  1007. dwNumAuthMethods++;
  1008. i++;
  1009. }
  1010. pTemp = pTemp->pNext;
  1011. }
  1012. }
  1013. lock_success:
  1014. LEAVE_SPD_SECTION();
  1015. *ppMatchedMMFilters = pMatchedMMFilters;
  1016. *ppMatchedMMPolicies = pMatchedMMPolicies;
  1017. *ppMatchedMMAuthMethods = pMatchedMMAuthMethods;
  1018. *pdwNumMatches = dwNumMatches;
  1019. *pdwResumeHandle = dwResumeHandle + dwNumMatches;
  1020. return (dwError);
  1021. lock:
  1022. LEAVE_SPD_SECTION();
  1023. error:
  1024. if (pMatchedMMFilters) {
  1025. FreeMMFilters(
  1026. dwNumFilters,
  1027. pMatchedMMFilters
  1028. );
  1029. }
  1030. if (pMatchedMMPolicies) {
  1031. FreeMMPolicies(
  1032. dwNumPolicies,
  1033. pMatchedMMPolicies
  1034. );
  1035. }
  1036. if (pMatchedMMAuthMethods) {
  1037. FreeMMAuthMethods(
  1038. dwNumAuthMethods,
  1039. pMatchedMMAuthMethods
  1040. );
  1041. }
  1042. *ppMatchedMMFilters = NULL;
  1043. *ppMatchedMMPolicies = NULL;
  1044. *ppMatchedMMAuthMethods = NULL;
  1045. *pdwNumMatches = 0;
  1046. *pdwResumeHandle = dwResumeHandle;
  1047. return (dwError);
  1048. }
  1049. DWORD
  1050. ValidateMMFilterTemplate(
  1051. PMM_FILTER pMMFilter
  1052. )
  1053. {
  1054. DWORD dwError = 0;
  1055. BOOL bConflicts = FALSE;
  1056. if (!pMMFilter) {
  1057. dwError = ERROR_INVALID_PARAMETER;
  1058. BAIL_ON_WIN32_ERROR(dwError);
  1059. }
  1060. dwError = VerifyAddresses(pMMFilter->SrcAddr, TRUE, FALSE);
  1061. BAIL_ON_WIN32_ERROR(dwError);
  1062. dwError = VerifyAddresses(pMMFilter->DesAddr, TRUE, TRUE);
  1063. BAIL_ON_WIN32_ERROR(dwError);
  1064. bConflicts = AddressesConflict(
  1065. pMMFilter->SrcAddr,
  1066. pMMFilter->DesAddr
  1067. );
  1068. if (bConflicts) {
  1069. dwError = ERROR_INVALID_PARAMETER;
  1070. BAIL_ON_WIN32_ERROR(dwError);
  1071. }
  1072. if (pMMFilter->dwDirection) {
  1073. if ((pMMFilter->dwDirection != FILTER_DIRECTION_INBOUND) &&
  1074. (pMMFilter->dwDirection != FILTER_DIRECTION_OUTBOUND)) {
  1075. dwError = ERROR_INVALID_PARAMETER;
  1076. BAIL_ON_WIN32_ERROR(dwError);
  1077. }
  1078. }
  1079. error:
  1080. return (dwError);
  1081. }
  1082. BOOL
  1083. MatchIniMMSFilter(
  1084. PINIMMSFILTER pIniMMSFilter,
  1085. PMM_FILTER pMMFilter
  1086. )
  1087. {
  1088. BOOL bMatches = FALSE;
  1089. if (pMMFilter->dwDirection) {
  1090. if (pMMFilter->dwDirection != pIniMMSFilter->dwDirection) {
  1091. return (FALSE);
  1092. }
  1093. }
  1094. bMatches = MatchAddresses(
  1095. pIniMMSFilter->SrcAddr,
  1096. pMMFilter->SrcAddr
  1097. );
  1098. if (!bMatches) {
  1099. return (FALSE);
  1100. }
  1101. bMatches = MatchAddresses(
  1102. pIniMMSFilter->DesAddr,
  1103. pMMFilter->DesAddr
  1104. );
  1105. if (!bMatches) {
  1106. return (FALSE);
  1107. }
  1108. return (TRUE);
  1109. }
  1110. DWORD
  1111. CopyMMMatchDefaults(
  1112. PMM_FILTER * ppMMFilters,
  1113. PMM_AUTH_METHODS * ppMMAuthMethods,
  1114. PIPSEC_MM_POLICY * ppMMPolicies,
  1115. PDWORD pdwNumMatches
  1116. )
  1117. {
  1118. DWORD dwError = 0;
  1119. PMM_FILTER pMMFilters = NULL;
  1120. PMM_AUTH_METHODS pMMAuthMethods = NULL;
  1121. PIPSEC_MM_POLICY pMMPolicies = NULL;
  1122. DWORD dwNumFilters = 0;
  1123. DWORD dwNumAuthMethods = 0;
  1124. DWORD dwNumPolicies = 0;
  1125. if (!gpIniDefaultMMPolicy) {
  1126. dwError = ERROR_IPSEC_DEFAULT_MM_POLICY_NOT_FOUND;
  1127. BAIL_ON_WIN32_ERROR(dwError);
  1128. }
  1129. if (!gpIniDefaultMMAuthMethods) {
  1130. dwError = ERROR_IPSEC_DEFAULT_MM_AUTH_NOT_FOUND;
  1131. BAIL_ON_WIN32_ERROR(dwError);
  1132. }
  1133. dwError = SPDApiBufferAllocate(
  1134. sizeof(MM_FILTER),
  1135. &pMMFilters
  1136. );
  1137. BAIL_ON_WIN32_ERROR(dwError);
  1138. dwError = SPDApiBufferAllocate(
  1139. sizeof(IPSEC_MM_POLICY),
  1140. &pMMPolicies
  1141. );
  1142. BAIL_ON_WIN32_ERROR(dwError);
  1143. dwError = SPDApiBufferAllocate(
  1144. sizeof(MM_AUTH_METHODS),
  1145. &pMMAuthMethods
  1146. );
  1147. BAIL_ON_WIN32_ERROR(dwError);
  1148. dwError = CopyDefaultMMFilter(
  1149. pMMFilters,
  1150. gpIniDefaultMMAuthMethods,
  1151. gpIniDefaultMMPolicy
  1152. );
  1153. BAIL_ON_WIN32_ERROR(dwError);
  1154. dwNumFilters++;
  1155. dwError = CopyMMPolicy(
  1156. gpIniDefaultMMPolicy,
  1157. pMMPolicies
  1158. );
  1159. BAIL_ON_WIN32_ERROR(dwError);
  1160. pMMPolicies->dwFlags |= IPSEC_MM_POLICY_ON_NO_MATCH;
  1161. dwNumPolicies++;
  1162. dwError = CopyMMAuthMethods(
  1163. gpIniDefaultMMAuthMethods,
  1164. pMMAuthMethods
  1165. );
  1166. BAIL_ON_WIN32_ERROR(dwError);
  1167. pMMAuthMethods->dwFlags |= IPSEC_MM_AUTH_ON_NO_MATCH;
  1168. dwNumAuthMethods++;
  1169. *ppMMFilters = pMMFilters;
  1170. *ppMMPolicies = pMMPolicies;
  1171. *ppMMAuthMethods = pMMAuthMethods;
  1172. *pdwNumMatches = 1;
  1173. return (dwError);
  1174. error:
  1175. if (pMMFilters) {
  1176. FreeMMFilters(
  1177. dwNumFilters,
  1178. pMMFilters
  1179. );
  1180. }
  1181. if (pMMPolicies) {
  1182. FreeMMPolicies(
  1183. dwNumPolicies,
  1184. pMMPolicies
  1185. );
  1186. }
  1187. if (pMMAuthMethods) {
  1188. FreeMMAuthMethods(
  1189. dwNumAuthMethods,
  1190. pMMAuthMethods
  1191. );
  1192. }
  1193. *ppMMFilters = NULL;
  1194. *ppMMPolicies = NULL;
  1195. *ppMMAuthMethods = NULL;
  1196. *pdwNumMatches = 0;
  1197. return (dwError);
  1198. }
  1199. DWORD
  1200. CopyDefaultMMFilter(
  1201. PMM_FILTER pMMFilter,
  1202. PINIMMAUTHMETHODS pIniMMAuthMethods,
  1203. PINIMMPOLICY pIniMMPolicy
  1204. )
  1205. {
  1206. DWORD dwError = 0;
  1207. UuidCreate(&(pMMFilter->gFilterID));
  1208. dwError = CopyName(
  1209. L"0",
  1210. &(pMMFilter->pszFilterName)
  1211. );
  1212. BAIL_ON_WIN32_ERROR(dwError);
  1213. pMMFilter->InterfaceType = INTERFACE_TYPE_ALL;
  1214. pMMFilter->bCreateMirror = TRUE;
  1215. pMMFilter->dwFlags = 0;
  1216. pMMFilter->dwFlags |= IPSEC_MM_POLICY_DEFAULT_POLICY;
  1217. pMMFilter->dwFlags |= IPSEC_MM_AUTH_DEFAULT_AUTH;
  1218. pMMFilter->SrcAddr.AddrType = IP_ADDR_SUBNET;
  1219. pMMFilter->SrcAddr.uIpAddr = SUBNET_ADDRESS_ANY;
  1220. pMMFilter->SrcAddr.uSubNetMask = SUBNET_MASK_ANY;
  1221. pMMFilter->DesAddr.AddrType = IP_ADDR_SUBNET;
  1222. pMMFilter->DesAddr.uIpAddr = SUBNET_ADDRESS_ANY;
  1223. pMMFilter->DesAddr.uSubNetMask = SUBNET_MASK_ANY;
  1224. pMMFilter->dwDirection = 0;
  1225. pMMFilter->dwWeight = 0;
  1226. CopyGuid(pIniMMAuthMethods->gMMAuthID, &(pMMFilter->gMMAuthID));
  1227. CopyGuid(pIniMMPolicy->gPolicyID, &(pMMFilter->gPolicyID));
  1228. error:
  1229. return (dwError);
  1230. }