Leaked source code of windows server 2003
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.

1691 lines
37 KiB

  1. /*++
  2. Copyright (c) 1999 Microsoft Corporation
  3. Module Name:
  4. qm-policy.c
  5. Abstract:
  6. Author:
  7. Environment: User Mode
  8. Revision History:
  9. --*/
  10. #include "precomp.h"
  11. #ifdef TRACE_ON
  12. #include "qm-policy.tmh"
  13. #endif
  14. DWORD
  15. AddQMPolicyInternal(
  16. LPWSTR pServerName,
  17. DWORD dwVersion,
  18. DWORD dwFlags,
  19. DWORD dwSource,
  20. PIPSEC_QM_POLICY pQMPolicy,
  21. LPVOID pvReserved
  22. )
  23. /*++
  24. Routine Description:
  25. This function adds a quick mode policy to the SPD.
  26. Arguments:
  27. pServerName - Server on which the quick mode policy is to be added.
  28. pQMPolicy - Quick mode policy to be added.
  29. Return Value:
  30. ERROR_SUCCESS - Success.
  31. Win32 Error - Failure.
  32. --*/
  33. {
  34. DWORD dwError = 0;
  35. PINIQMPOLICY pIniQMPolicy = NULL;
  36. //
  37. // Validate the quick mode policy.
  38. //
  39. dwError = ValidateQMPolicy(
  40. pQMPolicy
  41. );
  42. BAIL_ON_WIN32_ERROR(dwError);
  43. ENTER_SPD_SECTION();
  44. dwError = ValidateSecurity(
  45. SPD_OBJECT_SERVER,
  46. SERVER_ACCESS_ADMINISTER,
  47. NULL,
  48. NULL
  49. );
  50. BAIL_ON_LOCK_ERROR(dwError);
  51. pIniQMPolicy = FindQMPolicy(
  52. gpIniQMPolicy,
  53. pQMPolicy->pszPolicyName
  54. );
  55. if (pIniQMPolicy) {
  56. dwError = ERROR_IPSEC_QM_POLICY_EXISTS;
  57. BAIL_ON_LOCK_ERROR(dwError);
  58. }
  59. pIniQMPolicy = FindQMPolicyByGuid(
  60. gpIniQMPolicy,
  61. pQMPolicy->gPolicyID
  62. );
  63. if (pIniQMPolicy) {
  64. dwError = ERROR_IPSEC_QM_POLICY_EXISTS;
  65. BAIL_ON_LOCK_ERROR(dwError);
  66. }
  67. dwError = CreateIniQMPolicy(
  68. pQMPolicy,
  69. &pIniQMPolicy
  70. );
  71. if (dwError != WARNING_IPSEC_QM_POLICY_PRUNED) {
  72. BAIL_ON_LOCK_ERROR(dwError);
  73. }
  74. pIniQMPolicy->dwSource = dwSource;
  75. pIniQMPolicy->pNext = gpIniQMPolicy;
  76. gpIniQMPolicy = pIniQMPolicy;
  77. if ((pIniQMPolicy->dwFlags) & IPSEC_QM_POLICY_DEFAULT_POLICY) {
  78. gpIniDefaultQMPolicy = pIniQMPolicy;
  79. TRACE(
  80. TRC_INFORMATION,
  81. (L"Set default QM policy to \"%ls\" (%!guid!)",
  82. pQMPolicy->pszPolicyName,
  83. &pQMPolicy->gPolicyID)
  84. );
  85. }
  86. LEAVE_SPD_SECTION();
  87. TRACE(
  88. TRC_INFORMATION,
  89. (L"Added QM policy \"%ls\"(%!guid!)",
  90. pQMPolicy->pszPolicyName,
  91. &pQMPolicy->gPolicyID)
  92. );
  93. return (dwError);
  94. lock:
  95. LEAVE_SPD_SECTION();
  96. error:
  97. #ifdef TRACE_ON
  98. if (pQMPolicy) {
  99. TRACE(
  100. TRC_ERROR,
  101. (L"Failed to add QM policy \"%ls\"(%!guid!): %!winerr!",
  102. pQMPolicy->pszPolicyName,
  103. &pQMPolicy->gPolicyID,
  104. dwError)
  105. );
  106. } else {
  107. TRACE(
  108. TRC_ERROR,
  109. (L"Failed to add MM policy. Policy details unavailable since pQMPolicy is null: %!winerr!",
  110. dwError)
  111. );
  112. }
  113. #endif
  114. return (dwError);
  115. }
  116. DWORD
  117. AddQMPolicy(
  118. LPWSTR pServerName,
  119. DWORD dwVersion,
  120. DWORD dwFlags,
  121. PIPSEC_QM_POLICY pQMPolicy,
  122. LPVOID pvReserved
  123. )
  124. {
  125. return
  126. AddQMPolicyInternal(
  127. pServerName,
  128. dwVersion,
  129. dwFlags,
  130. IPSEC_SOURCE_WINIPSEC,
  131. pQMPolicy,
  132. pvReserved);
  133. }
  134. DWORD
  135. ValidateQMPolicy(
  136. PIPSEC_QM_POLICY pQMPolicy
  137. )
  138. {
  139. DWORD dwError = 0;
  140. if (!pQMPolicy) {
  141. dwError = ERROR_INVALID_PARAMETER;
  142. BAIL_ON_WIN32_ERROR(dwError);
  143. }
  144. if (!(pQMPolicy->pszPolicyName) || !(*(pQMPolicy->pszPolicyName))) {
  145. dwError = ERROR_INVALID_PARAMETER;
  146. BAIL_ON_WIN32_ERROR(dwError);
  147. }
  148. dwError = ValidateQMOffers(
  149. pQMPolicy->dwOfferCount,
  150. pQMPolicy->pOffers
  151. );
  152. BAIL_ON_WIN32_ERROR(dwError);
  153. error:
  154. #ifdef TRACE_ON
  155. if (dwError) {
  156. TRACE(TRC_ERROR, ("Failed QM policy validation: %!winerr!", dwError));
  157. }
  158. #endif
  159. return (dwError);
  160. }
  161. DWORD
  162. ValidateQMOffers(
  163. DWORD dwOfferCount,
  164. PIPSEC_QM_OFFER pOffers
  165. )
  166. {
  167. DWORD dwError = 0;
  168. if (!dwOfferCount || !pOffers || (dwOfferCount > IPSEC_MAX_QM_OFFERS)) {
  169. dwError = ERROR_INVALID_PARAMETER;
  170. BAIL_ON_WIN32_ERROR(dwError);
  171. }
  172. error:
  173. #ifdef TRACE_ON
  174. if (dwError) {
  175. TRACE(TRC_ERROR, ("Failed QM offers validation: %!winerr!", dwError));
  176. }
  177. #endif
  178. return (dwError);
  179. }
  180. DWORD
  181. ValidateQMOffer(
  182. PIPSEC_QM_OFFER pOffer,
  183. BOOL *pbInitGroup,
  184. LPDWORD pdwPFSGroup
  185. )
  186. {
  187. DWORD dwError = 0;
  188. DWORD j = 0;
  189. BOOL bAH = FALSE;
  190. BOOL bESP = FALSE;
  191. DWORD dwPFSGroup = *pdwPFSGroup;
  192. BOOL bInitGroup = *pbInitGroup;
  193. if (!bInitGroup) {
  194. if (pOffer->bPFSRequired) {
  195. if ((pOffer->dwPFSGroup != PFS_GROUP_1) &&
  196. (pOffer->dwPFSGroup != PFS_GROUP_2) &&
  197. (pOffer->dwPFSGroup != PFS_GROUP_2048) &&
  198. (pOffer->dwPFSGroup != PFS_GROUP_MM)) {
  199. dwError = ERROR_INVALID_PARAMETER;
  200. BAIL_ON_WIN32_ERROR(dwError);
  201. }
  202. dwPFSGroup=pOffer->dwPFSGroup;
  203. }
  204. else {
  205. if (pOffer->dwPFSGroup != PFS_GROUP_NONE) {
  206. dwError = ERROR_INVALID_PARAMETER;
  207. BAIL_ON_WIN32_ERROR(dwError);
  208. }
  209. dwPFSGroup=PFS_GROUP_NONE;
  210. }
  211. bInitGroup = TRUE;
  212. }
  213. if (dwPFSGroup) {
  214. if ((!pOffer->bPFSRequired) || (pOffer->dwPFSGroup != dwPFSGroup)) {
  215. dwError = ERROR_INVALID_PARAMETER;
  216. BAIL_ON_WIN32_ERROR(dwError);
  217. }
  218. } else {
  219. if ((pOffer->bPFSRequired) || (pOffer->dwPFSGroup != PFS_GROUP_NONE)) {
  220. dwError = ERROR_INVALID_PARAMETER;
  221. BAIL_ON_WIN32_ERROR(dwError);
  222. }
  223. }
  224. if (!(pOffer->dwNumAlgos) || (pOffer->dwNumAlgos > QM_MAX_ALGOS)) {
  225. dwError = ERROR_INVALID_PARAMETER;
  226. BAIL_ON_WIN32_ERROR(dwError);
  227. }
  228. bAH = FALSE;
  229. bESP = FALSE;
  230. for (j = 0; j < (pOffer->dwNumAlgos); j++) {
  231. switch (pOffer->Algos[j].Operation) {
  232. case AUTHENTICATION:
  233. if (bAH) {
  234. dwError = ERROR_INVALID_PARAMETER;
  235. BAIL_ON_WIN32_ERROR(dwError);
  236. }
  237. if ((pOffer->Algos[j].uAlgoIdentifier == AUTH_ALGO_NONE) ||
  238. (pOffer->Algos[j].uAlgoIdentifier >= AUTH_ALGO_MAX)) {
  239. dwError = ERROR_INVALID_PARAMETER;
  240. BAIL_ON_WIN32_ERROR(dwError);
  241. }
  242. if (pOffer->Algos[j].uSecAlgoIdentifier != HMAC_AUTH_ALGO_NONE) {
  243. dwError = ERROR_INVALID_PARAMETER;
  244. BAIL_ON_WIN32_ERROR(dwError);
  245. }
  246. bAH = TRUE;
  247. break;
  248. case ENCRYPTION:
  249. if (bESP) {
  250. dwError = ERROR_INVALID_PARAMETER;
  251. BAIL_ON_WIN32_ERROR(dwError);
  252. }
  253. if (pOffer->Algos[j].uAlgoIdentifier >= CONF_ALGO_MAX) {
  254. dwError = ERROR_INVALID_PARAMETER;
  255. BAIL_ON_WIN32_ERROR(dwError);
  256. }
  257. if (pOffer->Algos[j].uSecAlgoIdentifier >= HMAC_AUTH_ALGO_MAX) {
  258. dwError = ERROR_INVALID_PARAMETER;
  259. BAIL_ON_WIN32_ERROR(dwError);
  260. }
  261. if (pOffer->Algos[j].uAlgoIdentifier == CONF_ALGO_NONE) {
  262. if (pOffer->Algos[j].uSecAlgoIdentifier == HMAC_AUTH_ALGO_NONE) {
  263. dwError = ERROR_INVALID_PARAMETER;
  264. BAIL_ON_WIN32_ERROR(dwError);
  265. }
  266. }
  267. bESP = TRUE;
  268. break;
  269. case NONE:
  270. case COMPRESSION:
  271. default:
  272. dwError = ERROR_INVALID_PARAMETER;
  273. BAIL_ON_WIN32_ERROR(dwError);
  274. break;
  275. }
  276. }
  277. *pdwPFSGroup = dwPFSGroup;
  278. *pbInitGroup = bInitGroup;
  279. error:
  280. #ifdef TRACE_ON
  281. if (dwError) {
  282. TRACE(TRC_ERROR, ("Failed a QM offer validation: %!winerr!", dwError));
  283. }
  284. #endif
  285. return (dwError);
  286. }
  287. DWORD
  288. CreateIniQMPolicy(
  289. PIPSEC_QM_POLICY pQMPolicy,
  290. PINIQMPOLICY * ppIniQMPolicy
  291. )
  292. {
  293. DWORD dwError = 0;
  294. PINIQMPOLICY pIniQMPolicy = NULL;
  295. dwError = AllocateSPDMemory(
  296. sizeof(INIQMPOLICY),
  297. &pIniQMPolicy
  298. );
  299. BAIL_ON_WIN32_ERROR(dwError);
  300. memcpy(
  301. &(pIniQMPolicy->gPolicyID),
  302. &(pQMPolicy->gPolicyID),
  303. sizeof(GUID)
  304. );
  305. dwError = AllocateSPDString(
  306. pQMPolicy->pszPolicyName,
  307. &(pIniQMPolicy->pszPolicyName)
  308. );
  309. BAIL_ON_WIN32_ERROR(dwError);
  310. pIniQMPolicy->cRef = 0;
  311. pIniQMPolicy->dwSource = 0;
  312. pIniQMPolicy->dwFlags = pQMPolicy->dwFlags;
  313. pIniQMPolicy->dwReserved = pQMPolicy->dwReserved;
  314. pIniQMPolicy->pNext = NULL;
  315. dwError = CreateIniQMOffers(
  316. pQMPolicy->dwOfferCount,
  317. pQMPolicy->pOffers,
  318. &(pIniQMPolicy->dwOfferCount),
  319. &(pIniQMPolicy->pOffers)
  320. );
  321. if (dwError != WARNING_IPSEC_QM_POLICY_PRUNED) {
  322. BAIL_ON_WIN32_ERROR(dwError);
  323. }
  324. *ppIniQMPolicy = pIniQMPolicy;
  325. return (dwError);
  326. error:
  327. TRACE(TRC_ERROR, ("Failed to create QM Policy link node: %!winerr!", dwError));
  328. if (pIniQMPolicy) {
  329. FreeIniQMPolicy(
  330. pIniQMPolicy
  331. );
  332. }
  333. *ppIniQMPolicy = NULL;
  334. return (dwError);
  335. }
  336. DWORD
  337. CreateIniQMOffers(
  338. DWORD dwInOfferCount,
  339. PIPSEC_QM_OFFER pInOffers,
  340. PDWORD pdwOfferCount,
  341. PIPSEC_QM_OFFER * ppOffers
  342. )
  343. {
  344. DWORD dwError = 0;
  345. PIPSEC_QM_OFFER pOffers = NULL;
  346. PIPSEC_QM_OFFER pTemp = NULL;
  347. PIPSEC_QM_OFFER pInTempOffer = NULL;
  348. DWORD i = 0;
  349. DWORD j = 0;
  350. BOOL bGroupInit = FALSE;
  351. DWORD dwPFSGroup = PFS_GROUP_NONE;
  352. DWORD dwOfferCount = 0;
  353. DWORD dwCurIndex = 0;
  354. for (i = 0; i < dwInOfferCount; i++) {
  355. dwError = ValidateQMOffer(&pInOffers[i],
  356. &bGroupInit,
  357. &dwPFSGroup);
  358. if (dwError == ERROR_SUCCESS) {
  359. dwOfferCount++;
  360. }
  361. }
  362. if (dwOfferCount == 0) {
  363. dwError = ERROR_INVALID_PARAMETER;
  364. BAIL_ON_WIN32_ERROR(dwError);
  365. }
  366. //
  367. // Offer count and the offers themselves have already been validated.
  368. //
  369. dwError = AllocateSPDMemory(
  370. sizeof(IPSEC_QM_OFFER) * dwOfferCount,
  371. &(pOffers)
  372. );
  373. BAIL_ON_WIN32_ERROR(dwError);
  374. for (i = 0; i < dwInOfferCount; i++) {
  375. pTemp = &pOffers[dwCurIndex];
  376. pInTempOffer = &pInOffers[i];
  377. dwError = ValidateQMOffer(pInTempOffer,
  378. &bGroupInit,
  379. &dwPFSGroup);
  380. if (dwError) {
  381. continue;
  382. }
  383. memcpy(
  384. &(pTemp->Lifetime),
  385. &(pInTempOffer->Lifetime),
  386. sizeof(KEY_LIFETIME)
  387. );
  388. pTemp->dwFlags = pInTempOffer->dwFlags;
  389. pTemp->bPFSRequired = pInTempOffer->bPFSRequired;
  390. pTemp->dwPFSGroup = pInTempOffer->dwPFSGroup;
  391. pTemp->dwNumAlgos = pInTempOffer->dwNumAlgos;
  392. for (j = 0; j < (pInTempOffer->dwNumAlgos); j++) {
  393. memcpy(
  394. &(pTemp->Algos[j]),
  395. &(pInTempOffer->Algos[j]),
  396. sizeof(IPSEC_QM_ALGO)
  397. );
  398. }
  399. pTemp->dwReserved = pInTempOffer->dwReserved;
  400. dwCurIndex++;
  401. }
  402. *pdwOfferCount = dwOfferCount;
  403. *ppOffers = pOffers;
  404. if (dwOfferCount != dwInOfferCount) {
  405. return WARNING_IPSEC_QM_POLICY_PRUNED;
  406. }
  407. return (ERROR_SUCCESS);
  408. error:
  409. TRACE(TRC_ERROR, ("Failed to create QM offers node: %!winerr!", dwError));
  410. if (pOffers) {
  411. FreeIniQMOffers(
  412. i,
  413. pOffers
  414. );
  415. }
  416. *pdwOfferCount = 0;
  417. *ppOffers = NULL;
  418. return (dwError);
  419. }
  420. VOID
  421. FreeIniQMPolicy(
  422. PINIQMPOLICY pIniQMPolicy
  423. )
  424. {
  425. if (pIniQMPolicy) {
  426. if (pIniQMPolicy->pszPolicyName) {
  427. FreeSPDString(pIniQMPolicy->pszPolicyName);
  428. }
  429. FreeIniQMOffers(
  430. pIniQMPolicy->dwOfferCount,
  431. pIniQMPolicy->pOffers
  432. );
  433. FreeSPDMemory(pIniQMPolicy);
  434. }
  435. }
  436. VOID
  437. FreeIniQMOffers(
  438. DWORD dwOfferCount,
  439. PIPSEC_QM_OFFER pOffers
  440. )
  441. {
  442. if (pOffers) {
  443. FreeSPDMemory(pOffers);
  444. }
  445. }
  446. PINIQMPOLICY
  447. FindQMPolicy(
  448. PINIQMPOLICY pIniQMPolicyList,
  449. LPWSTR pszPolicyName
  450. )
  451. {
  452. DWORD dwError = 0;
  453. PINIQMPOLICY pTemp = NULL;
  454. pTemp = pIniQMPolicyList;
  455. while (pTemp) {
  456. if (!_wcsicmp(pTemp->pszPolicyName, pszPolicyName)) {
  457. return (pTemp);
  458. }
  459. pTemp = pTemp->pNext;
  460. }
  461. return (NULL);
  462. }
  463. DWORD
  464. DeleteQMPolicy(
  465. LPWSTR pServerName,
  466. DWORD dwVersion,
  467. LPWSTR pszPolicyName,
  468. LPVOID pvReserved
  469. )
  470. /*++
  471. Routine Description:
  472. This function deletes a quick mode policy from the SPD.
  473. Arguments:
  474. pServerName - Server on which the quick mode policy is to be deleted.
  475. pszPolicyName - Quick mode policy to be deleted.
  476. Return Value:
  477. ERROR_SUCCESS - Success.
  478. Win32 Error - Failure.
  479. --*/
  480. {
  481. DWORD dwError = 0;
  482. PINIQMPOLICY pIniQMPolicy = NULL;
  483. GUID gPolicyID;
  484. if (!pszPolicyName || !*pszPolicyName) {
  485. return (ERROR_INVALID_PARAMETER);
  486. }
  487. ENTER_SPD_SECTION();
  488. dwError = ValidateSecurity(
  489. SPD_OBJECT_SERVER,
  490. SERVER_ACCESS_ADMINISTER,
  491. NULL,
  492. NULL
  493. );
  494. BAIL_ON_LOCK_ERROR(dwError);
  495. pIniQMPolicy = FindQMPolicy(
  496. gpIniQMPolicy,
  497. pszPolicyName
  498. );
  499. if (!pIniQMPolicy) {
  500. dwError = ERROR_IPSEC_QM_POLICY_NOT_FOUND;
  501. BAIL_ON_LOCK_ERROR(dwError);
  502. }
  503. if (pIniQMPolicy->cRef) {
  504. dwError = ERROR_IPSEC_QM_POLICY_IN_USE;
  505. memcpy(&gPolicyID, &pIniQMPolicy->gPolicyID, sizeof(GUID));
  506. BAIL_ON_LOCK_ERROR(dwError);
  507. }
  508. memcpy(&gPolicyID, &pIniQMPolicy->gPolicyID, sizeof(GUID));
  509. dwError = DeleteIniQMPolicy(
  510. pIniQMPolicy
  511. );
  512. BAIL_ON_LOCK_ERROR(dwError);
  513. LEAVE_SPD_SECTION();
  514. if (gbIKENotify) {
  515. (VOID) IKENotifyPolicyChange(
  516. &(gPolicyID),
  517. POLICY_GUID_QM
  518. );
  519. }
  520. TRACE(
  521. TRC_INFORMATION,
  522. ("Deleted QM Policy \"%ls\"(%!guid!)",
  523. pszPolicyName,
  524. &gPolicyID)
  525. );
  526. return (dwError);
  527. lock:
  528. #ifdef TRACE_ON
  529. if (pIniQMPolicy) {
  530. TRACE(
  531. TRC_ERROR,
  532. (L"Failed to delete QM policy \"%ls\"(%!guid!): %!winerr!",
  533. pIniQMPolicy->pszPolicyName,
  534. &pIniQMPolicy->gPolicyID,
  535. dwError)
  536. );
  537. } else {
  538. TRACE(
  539. TRC_ERROR,
  540. (L"Failed to delete QM policy \"%ls\": %!winerr!",
  541. pszPolicyName,
  542. dwError)
  543. );
  544. }
  545. #endif
  546. LEAVE_SPD_SECTION();
  547. if ((dwError == ERROR_IPSEC_QM_POLICY_IN_USE) && gbIKENotify) {
  548. (VOID) IKENotifyPolicyChange(
  549. &(gPolicyID),
  550. POLICY_GUID_QM
  551. );
  552. }
  553. return (dwError);
  554. }
  555. DWORD
  556. EnumQMPolicies(
  557. LPWSTR pServerName,
  558. DWORD dwVersion,
  559. PIPSEC_QM_POLICY pQMTemplatePolicy,
  560. DWORD dwFlags,
  561. DWORD dwPreferredNumEntries,
  562. PIPSEC_QM_POLICY * ppQMPolicies,
  563. LPDWORD pdwNumPolicies,
  564. LPDWORD pdwResumeHandle,
  565. LPVOID pvReserved
  566. )
  567. /*++
  568. Routine Description:
  569. This function enumerates quick mode policies from the SPD.
  570. Arguments:
  571. pServerName - Server on which the quick mode policies are to
  572. be enumerated.
  573. ppQMPolicies - Enumerated quick mode policies returned to the
  574. caller.
  575. dwPreferredNumEntries - Preferred number of enumeration entries.
  576. pdwNumPolicies - Number of quick mode policies actually enumerated.
  577. pdwResumeHandle - Handle to the location in the quick mode policy
  578. list from which to resume enumeration.
  579. Return Value:
  580. ERROR_SUCCESS - Success.
  581. Win32 Error - Failure.
  582. --*/
  583. {
  584. DWORD dwError = 0;
  585. DWORD dwResumeHandle = 0;
  586. DWORD dwNumToEnum = 0;
  587. PINIQMPOLICY pIniQMPolicy = NULL;
  588. DWORD i = 0;
  589. PINIQMPOLICY pTemp = NULL;
  590. DWORD dwNumPolicies = 0;
  591. PIPSEC_QM_POLICY pQMPolicies = NULL;
  592. PIPSEC_QM_POLICY pQMPolicy = NULL;
  593. dwResumeHandle = *pdwResumeHandle;
  594. if (!dwPreferredNumEntries || (dwPreferredNumEntries > MAX_QMPOLICY_ENUM_COUNT)) {
  595. dwNumToEnum = MAX_QMPOLICY_ENUM_COUNT;
  596. }
  597. else {
  598. dwNumToEnum = dwPreferredNumEntries;
  599. }
  600. ENTER_SPD_SECTION();
  601. dwError = ValidateSecurity(
  602. SPD_OBJECT_SERVER,
  603. SERVER_ACCESS_ADMINISTER,
  604. NULL,
  605. NULL
  606. );
  607. BAIL_ON_LOCK_ERROR(dwError);
  608. pIniQMPolicy = gpIniQMPolicy;
  609. for (i = 0; (i < dwResumeHandle) && (pIniQMPolicy != NULL); i++) {
  610. pIniQMPolicy = pIniQMPolicy->pNext;
  611. }
  612. if (!pIniQMPolicy) {
  613. dwError = ERROR_NO_DATA;
  614. BAIL_ON_LOCK_ERROR(dwError);
  615. }
  616. pTemp = pIniQMPolicy;
  617. while (pTemp && (dwNumPolicies < dwNumToEnum)) {
  618. dwNumPolicies++;
  619. pTemp = pTemp->pNext;
  620. }
  621. dwError = SPDApiBufferAllocate(
  622. sizeof(IPSEC_QM_POLICY)*dwNumPolicies,
  623. &pQMPolicies
  624. );
  625. BAIL_ON_LOCK_ERROR(dwError);
  626. pTemp = pIniQMPolicy;
  627. pQMPolicy = pQMPolicies;
  628. for (i = 0; i < dwNumPolicies; i++) {
  629. dwError = CopyQMPolicy(
  630. dwFlags,
  631. pTemp,
  632. pQMPolicy
  633. );
  634. BAIL_ON_LOCK_ERROR(dwError);
  635. pTemp = pTemp->pNext;
  636. pQMPolicy++;
  637. }
  638. *ppQMPolicies = pQMPolicies;
  639. *pdwResumeHandle = dwResumeHandle + dwNumPolicies;
  640. *pdwNumPolicies = dwNumPolicies;
  641. LEAVE_SPD_SECTION();
  642. return (dwError);
  643. lock:
  644. LEAVE_SPD_SECTION();
  645. if (pQMPolicies) {
  646. FreeQMPolicies(
  647. i,
  648. pQMPolicies
  649. );
  650. }
  651. *ppQMPolicies = NULL;
  652. *pdwResumeHandle = dwResumeHandle;
  653. *pdwNumPolicies = 0;
  654. return (dwError);
  655. }
  656. DWORD
  657. SetQMPolicy(
  658. LPWSTR pServerName,
  659. DWORD dwVersion,
  660. LPWSTR pszPolicyName,
  661. PIPSEC_QM_POLICY pQMPolicy,
  662. LPVOID pvReserved
  663. )
  664. /*++
  665. Routine Description:
  666. This function updates a quick mode policy in the SPD.
  667. Arguments:
  668. pServerName - Server on which the quick mode policy is to be
  669. updated.
  670. pszPolicyName - Name of the quick mode policy to be updated.
  671. pQMPolicy - New quick mode policy which will replace the
  672. existing policy.
  673. Return Value:
  674. ERROR_SUCCESS - Success.
  675. Win32 Error - Failure.
  676. --*/
  677. {
  678. DWORD dwError = 0;
  679. PINIQMPOLICY pIniQMPolicy = NULL;
  680. DWORD dwStatus = 0;
  681. if (!pszPolicyName || !*pszPolicyName) {
  682. return (ERROR_INVALID_PARAMETER);
  683. }
  684. //
  685. // Validate quick mode policy.
  686. //
  687. dwError = ValidateQMPolicy(
  688. pQMPolicy
  689. );
  690. BAIL_ON_WIN32_ERROR(dwError);
  691. ENTER_SPD_SECTION();
  692. dwError = ValidateSecurity(
  693. SPD_OBJECT_SERVER,
  694. SERVER_ACCESS_ADMINISTER,
  695. NULL,
  696. NULL
  697. );
  698. BAIL_ON_LOCK_ERROR(dwError);
  699. pIniQMPolicy = FindQMPolicy(
  700. gpIniQMPolicy,
  701. pszPolicyName
  702. );
  703. if (!pIniQMPolicy) {
  704. dwError = ERROR_IPSEC_QM_POLICY_NOT_FOUND;
  705. BAIL_ON_LOCK_ERROR(dwError);
  706. }
  707. if (memcmp(
  708. &(pIniQMPolicy->gPolicyID),
  709. &(pQMPolicy->gPolicyID),
  710. sizeof(GUID))) {
  711. dwError = ERROR_INVALID_PARAMETER;
  712. BAIL_ON_LOCK_ERROR(dwError);
  713. }
  714. dwError = SetIniQMPolicy(
  715. pIniQMPolicy,
  716. pQMPolicy
  717. );
  718. if (dwError != WARNING_IPSEC_QM_POLICY_PRUNED) {
  719. BAIL_ON_LOCK_ERROR(dwError);
  720. } else {
  721. dwStatus = dwError;
  722. }
  723. LEAVE_SPD_SECTION();
  724. (VOID) IKENotifyPolicyChange(
  725. &(pQMPolicy->gPolicyID),
  726. POLICY_GUID_QM
  727. );
  728. TRACE(
  729. TRC_INFORMATION,
  730. (L"Changed QM Policy \"%ls\" (%!guid!)",
  731. pQMPolicy->pszPolicyName,
  732. &pQMPolicy->gPolicyID)
  733. );
  734. return (dwStatus);
  735. lock:
  736. LEAVE_SPD_SECTION();
  737. error:
  738. #ifdef TRACE_ON
  739. if (pIniQMPolicy) {
  740. TRACE(
  741. TRC_ERROR,
  742. (L"Failed to change QM policy \"%ls\"(%!guid!): %!winerr!",
  743. pIniQMPolicy->pszPolicyName,
  744. &pIniQMPolicy->gPolicyID,
  745. dwError)
  746. );
  747. } else {
  748. TRACE(
  749. TRC_ERROR,
  750. (L"Failed to change QM policy \"%ls\": %!winerr!",
  751. pszPolicyName,
  752. dwError)
  753. );
  754. }
  755. #endif
  756. return (dwError);
  757. }
  758. DWORD
  759. GetQMPolicy(
  760. LPWSTR pServerName,
  761. DWORD dwVersion,
  762. LPWSTR pszPolicyName,
  763. DWORD dwFlags,
  764. PIPSEC_QM_POLICY * ppQMPolicy,
  765. LPVOID pvReserved
  766. )
  767. /*++
  768. Routine Description:
  769. This function gets a quick mode policy from the SPD.
  770. Arguments:
  771. pServerName - Server from which to get the quick mode policy.
  772. pszPolicyName - Name of the quick mode policy to get.
  773. ppQMPolicy - Quick mode policy found returned to the caller.
  774. Return Value:
  775. ERROR_SUCCESS - Success.
  776. Win32 Error - Failure.
  777. --*/
  778. {
  779. DWORD dwError = 0;
  780. PINIQMPOLICY pIniQMPolicy = NULL;
  781. PIPSEC_QM_POLICY pQMPolicy = NULL;
  782. if (!pszPolicyName || !*pszPolicyName) {
  783. dwError = ERROR_INVALID_PARAMETER;
  784. BAIL_ON_WIN32_ERROR(dwError);
  785. }
  786. ENTER_SPD_SECTION();
  787. dwError = ValidateSecurity(
  788. SPD_OBJECT_SERVER,
  789. SERVER_ACCESS_ADMINISTER,
  790. NULL,
  791. NULL
  792. );
  793. BAIL_ON_LOCK_ERROR(dwError);
  794. pIniQMPolicy = FindQMPolicy(
  795. gpIniQMPolicy,
  796. pszPolicyName
  797. );
  798. if (!pIniQMPolicy) {
  799. dwError = ERROR_IPSEC_QM_POLICY_NOT_FOUND;
  800. BAIL_ON_LOCK_ERROR(dwError);
  801. }
  802. dwError = GetIniQMPolicy(
  803. dwFlags,
  804. pIniQMPolicy,
  805. &pQMPolicy
  806. );
  807. BAIL_ON_LOCK_ERROR(dwError);
  808. *ppQMPolicy = pQMPolicy;
  809. LEAVE_SPD_SECTION();
  810. return (dwError);
  811. lock:
  812. LEAVE_SPD_SECTION();
  813. error:
  814. *ppQMPolicy = NULL;
  815. return (dwError);
  816. }
  817. DWORD
  818. SetIniQMPolicy(
  819. PINIQMPOLICY pIniQMPolicy,
  820. PIPSEC_QM_POLICY pQMPolicy
  821. )
  822. {
  823. DWORD dwError = 0;
  824. DWORD dwOfferCount = 0;
  825. PIPSEC_QM_OFFER pOffers = NULL;
  826. dwError = CreateIniQMOffers(
  827. pQMPolicy->dwOfferCount,
  828. pQMPolicy->pOffers,
  829. &dwOfferCount,
  830. &pOffers
  831. );
  832. if (dwError != WARNING_IPSEC_QM_POLICY_PRUNED) {
  833. BAIL_ON_WIN32_ERROR(dwError);
  834. }
  835. FreeIniQMOffers(
  836. pIniQMPolicy->dwOfferCount,
  837. pIniQMPolicy->pOffers
  838. );
  839. if ((pIniQMPolicy->dwFlags) & IPSEC_QM_POLICY_DEFAULT_POLICY) {
  840. gpIniDefaultQMPolicy = NULL;
  841. TRACE(
  842. TRC_INFORMATION,
  843. (L"Cleared default QM policy \"%ls\" (%!guid!)",
  844. pIniQMPolicy->pszPolicyName,
  845. &pIniQMPolicy->gPolicyID)
  846. );
  847. }
  848. pIniQMPolicy->dwFlags = pQMPolicy->dwFlags;
  849. pIniQMPolicy->dwReserved = pQMPolicy->dwReserved;
  850. pIniQMPolicy->dwOfferCount = dwOfferCount;
  851. pIniQMPolicy->pOffers = pOffers;
  852. if ((pIniQMPolicy->dwFlags) & IPSEC_QM_POLICY_DEFAULT_POLICY) {
  853. gpIniDefaultQMPolicy = pIniQMPolicy;
  854. TRACE(
  855. TRC_INFORMATION,
  856. (L"Set default QM policy to \"%ls\" (%!guid!)",
  857. pIniQMPolicy->pszPolicyName,
  858. &pIniQMPolicy->gPolicyID)
  859. );
  860. }
  861. error:
  862. return (dwError);
  863. }
  864. DWORD
  865. GetIniQMPolicy(
  866. DWORD dwFlags,
  867. PINIQMPOLICY pIniQMPolicy,
  868. PIPSEC_QM_POLICY * ppQMPolicy
  869. )
  870. {
  871. DWORD dwError = 0;
  872. PIPSEC_QM_POLICY pQMPolicy = NULL;
  873. dwError = SPDApiBufferAllocate(
  874. sizeof(IPSEC_QM_POLICY),
  875. &pQMPolicy
  876. );
  877. BAIL_ON_WIN32_ERROR(dwError);
  878. dwError = CopyQMPolicy(
  879. dwFlags,
  880. pIniQMPolicy,
  881. pQMPolicy
  882. );
  883. BAIL_ON_WIN32_ERROR(dwError);
  884. *ppQMPolicy = pQMPolicy;
  885. return (dwError);
  886. error:
  887. if (pQMPolicy) {
  888. SPDApiBufferFree(pQMPolicy);
  889. }
  890. *ppQMPolicy = NULL;
  891. return (dwError);
  892. }
  893. DWORD
  894. CopyQMPolicy(
  895. DWORD dwFlags,
  896. PINIQMPOLICY pIniQMPolicy,
  897. PIPSEC_QM_POLICY pQMPolicy
  898. )
  899. {
  900. DWORD dwError = 0;
  901. memcpy(
  902. &(pQMPolicy->gPolicyID),
  903. &(pIniQMPolicy->gPolicyID),
  904. sizeof(GUID)
  905. );
  906. dwError = SPDApiBufferAllocate(
  907. wcslen(pIniQMPolicy->pszPolicyName)*sizeof(WCHAR)
  908. + sizeof(WCHAR),
  909. &(pQMPolicy->pszPolicyName)
  910. );
  911. BAIL_ON_WIN32_ERROR(dwError);
  912. wcscpy(pQMPolicy->pszPolicyName, pIniQMPolicy->pszPolicyName);
  913. pQMPolicy->dwFlags = pIniQMPolicy->dwFlags;
  914. pQMPolicy->dwReserved = pIniQMPolicy->dwReserved;
  915. if (dwFlags & RETURN_NON_AH_OFFERS) {
  916. dwError = CreateNonAHQMOffers(
  917. pIniQMPolicy->dwOfferCount,
  918. pIniQMPolicy->pOffers,
  919. &(pQMPolicy->dwOfferCount),
  920. &(pQMPolicy->pOffers)
  921. );
  922. }
  923. else {
  924. dwError = CreateQMOffers(
  925. pIniQMPolicy->dwOfferCount,
  926. pIniQMPolicy->pOffers,
  927. &(pQMPolicy->dwOfferCount),
  928. &(pQMPolicy->pOffers)
  929. );
  930. }
  931. BAIL_ON_WIN32_ERROR(dwError);
  932. return (dwError);
  933. error:
  934. if (pQMPolicy->pszPolicyName) {
  935. SPDApiBufferFree(pQMPolicy->pszPolicyName);
  936. }
  937. return (dwError);
  938. }
  939. DWORD
  940. CreateQMOffers(
  941. DWORD dwInOfferCount,
  942. PIPSEC_QM_OFFER pInOffers,
  943. PDWORD pdwOfferCount,
  944. PIPSEC_QM_OFFER * ppOffers
  945. )
  946. {
  947. DWORD dwError = 0;
  948. PIPSEC_QM_OFFER pOffers = NULL;
  949. PIPSEC_QM_OFFER pTemp = NULL;
  950. PIPSEC_QM_OFFER pInTempOffer = NULL;
  951. DWORD i = 0;
  952. DWORD j = 0;
  953. DWORD k = 0;
  954. //
  955. // Offer count and the offers themselves have already been validated.
  956. //
  957. dwError = SPDApiBufferAllocate(
  958. sizeof(IPSEC_QM_OFFER) * dwInOfferCount,
  959. &(pOffers)
  960. );
  961. BAIL_ON_WIN32_ERROR(dwError);
  962. pTemp = pOffers;
  963. pInTempOffer = pInOffers;
  964. for (i = 0; i < dwInOfferCount; i++) {
  965. memcpy(
  966. &(pTemp->Lifetime),
  967. &(pInTempOffer->Lifetime),
  968. sizeof(KEY_LIFETIME)
  969. );
  970. pTemp->dwFlags = pInTempOffer->dwFlags;
  971. pTemp->bPFSRequired = pInTempOffer->bPFSRequired;
  972. pTemp->dwPFSGroup = pInTempOffer->dwPFSGroup;
  973. pTemp->dwNumAlgos = pInTempOffer->dwNumAlgos;
  974. for (j = 0; j < (pInTempOffer->dwNumAlgos); j++) {
  975. memcpy(
  976. &(pTemp->Algos[j]),
  977. &(pInTempOffer->Algos[j]),
  978. sizeof(IPSEC_QM_ALGO)
  979. );
  980. }
  981. for (k = j; k < QM_MAX_ALGOS; k++) {
  982. memset(&(pTemp->Algos[k]), 0, sizeof(IPSEC_QM_ALGO));
  983. }
  984. pTemp->dwReserved = pInTempOffer->dwReserved;
  985. pInTempOffer++;
  986. pTemp++;
  987. }
  988. *pdwOfferCount = dwInOfferCount;
  989. *ppOffers = pOffers;
  990. return (dwError);
  991. error:
  992. TRACE(TRC_ERROR, ("Failed to create QM offers"));
  993. if (pOffers) {
  994. FreeQMOffers(
  995. i,
  996. pOffers
  997. );
  998. }
  999. *pdwOfferCount = 0;
  1000. *ppOffers = NULL;
  1001. return (dwError);
  1002. }
  1003. DWORD
  1004. DeleteIniQMPolicy(
  1005. PINIQMPOLICY pIniQMPolicy
  1006. )
  1007. {
  1008. DWORD dwError = 0;
  1009. PINIQMPOLICY * ppTemp = NULL;
  1010. ppTemp = &gpIniQMPolicy;
  1011. while (*ppTemp) {
  1012. if (*ppTemp == pIniQMPolicy) {
  1013. break;
  1014. }
  1015. ppTemp = &((*ppTemp)->pNext);
  1016. }
  1017. if (*ppTemp) {
  1018. *ppTemp = pIniQMPolicy->pNext;
  1019. }
  1020. if ((pIniQMPolicy->dwFlags) & IPSEC_QM_POLICY_DEFAULT_POLICY) {
  1021. gpIniDefaultQMPolicy = NULL;
  1022. TRACE(
  1023. TRC_INFORMATION,
  1024. (L"Cleared default QM policy \"%ls\" (%!guid!)",
  1025. pIniQMPolicy->pszPolicyName,
  1026. &pIniQMPolicy->gPolicyID)
  1027. );
  1028. }
  1029. FreeIniQMPolicy(pIniQMPolicy);
  1030. return (dwError);
  1031. }
  1032. VOID
  1033. FreeQMOffers(
  1034. DWORD dwOfferCount,
  1035. PIPSEC_QM_OFFER pOffers
  1036. )
  1037. {
  1038. if (pOffers) {
  1039. SPDApiBufferFree(pOffers);
  1040. }
  1041. }
  1042. VOID
  1043. FreeIniQMPolicyList(
  1044. PINIQMPOLICY pIniQMPolicyList
  1045. )
  1046. {
  1047. PINIQMPOLICY pTemp = NULL;
  1048. PINIQMPOLICY pIniQMPolicy = NULL;
  1049. pTemp = pIniQMPolicyList;
  1050. while (pTemp) {
  1051. pIniQMPolicy = pTemp;
  1052. pTemp = pTemp->pNext;
  1053. FreeIniQMPolicy(pIniQMPolicy);
  1054. }
  1055. }
  1056. PINIQMPOLICY
  1057. FindQMPolicyByGuid(
  1058. PINIQMPOLICY pIniQMPolicyList,
  1059. GUID gPolicyID
  1060. )
  1061. {
  1062. DWORD dwError = 0;
  1063. PINIQMPOLICY pTemp = NULL;
  1064. pTemp = pIniQMPolicyList;
  1065. while (pTemp) {
  1066. if (!memcmp(&(pTemp->gPolicyID), &gPolicyID, sizeof(GUID))) {
  1067. return (pTemp);
  1068. }
  1069. pTemp = pTemp->pNext;
  1070. }
  1071. return (NULL);
  1072. }
  1073. VOID
  1074. FreeQMPolicies(
  1075. DWORD dwNumQMPolicies,
  1076. PIPSEC_QM_POLICY pQMPolicies
  1077. )
  1078. {
  1079. DWORD i = 0;
  1080. if (pQMPolicies) {
  1081. for (i = 0; i < dwNumQMPolicies; i++) {
  1082. if (pQMPolicies[i].pszPolicyName) {
  1083. SPDApiBufferFree(pQMPolicies[i].pszPolicyName);
  1084. }
  1085. FreeQMOffers(
  1086. pQMPolicies[i].dwOfferCount,
  1087. pQMPolicies[i].pOffers
  1088. );
  1089. }
  1090. SPDApiBufferFree(pQMPolicies);
  1091. }
  1092. }
  1093. DWORD
  1094. GetQMPolicyByID(
  1095. LPWSTR pServerName,
  1096. DWORD dwVersion,
  1097. GUID gQMPolicyID,
  1098. DWORD dwFlags,
  1099. PIPSEC_QM_POLICY * ppQMPolicy,
  1100. LPVOID pvReserved
  1101. )
  1102. /*++
  1103. Routine Description:
  1104. This function gets a quick mode policy from the SPD.
  1105. Arguments:
  1106. pServerName - Server from which to get the quick mode policy.
  1107. gQMFilter - Guid of the quick mode policy to get.
  1108. ppQMPolicy - Quick mode policy found returned to the caller.
  1109. Return Value:
  1110. ERROR_SUCCESS - Success.
  1111. Win32 Error - Failure.
  1112. --*/
  1113. {
  1114. DWORD dwError = 0;
  1115. PINIQMPOLICY pIniQMPolicy = NULL;
  1116. PIPSEC_QM_POLICY pQMPolicy = NULL;
  1117. ENTER_SPD_SECTION();
  1118. dwError = ValidateSecurity(
  1119. SPD_OBJECT_SERVER,
  1120. SERVER_ACCESS_ADMINISTER,
  1121. NULL,
  1122. NULL
  1123. );
  1124. BAIL_ON_LOCK_ERROR(dwError);
  1125. pIniQMPolicy = FindQMPolicyByGuid(
  1126. gpIniQMPolicy,
  1127. gQMPolicyID
  1128. );
  1129. if (!pIniQMPolicy) {
  1130. dwError = ERROR_IPSEC_QM_POLICY_NOT_FOUND;
  1131. BAIL_ON_LOCK_ERROR(dwError);
  1132. }
  1133. dwError = GetIniQMPolicy(
  1134. dwFlags,
  1135. pIniQMPolicy,
  1136. &pQMPolicy
  1137. );
  1138. BAIL_ON_LOCK_ERROR(dwError);
  1139. *ppQMPolicy = pQMPolicy;
  1140. LEAVE_SPD_SECTION();
  1141. return (dwError);
  1142. lock:
  1143. LEAVE_SPD_SECTION();
  1144. *ppQMPolicy = NULL;
  1145. return (dwError);
  1146. }
  1147. DWORD
  1148. LocateQMPolicy(
  1149. DWORD dwFlags,
  1150. GUID gPolicyID,
  1151. PINIQMPOLICY * ppIniQMPolicy
  1152. )
  1153. {
  1154. DWORD dwError = 0;
  1155. PINIQMPOLICY pIniQMPolicy = NULL;
  1156. if (dwFlags & IPSEC_QM_POLICY_DEFAULT_POLICY) {
  1157. if (!gpIniDefaultQMPolicy) {
  1158. dwError = ERROR_IPSEC_DEFAULT_QM_POLICY_NOT_FOUND;
  1159. BAIL_ON_WIN32_ERROR(dwError);
  1160. }
  1161. pIniQMPolicy = gpIniDefaultQMPolicy;
  1162. }
  1163. else {
  1164. pIniQMPolicy = FindQMPolicyByGuid(
  1165. gpIniQMPolicy,
  1166. gPolicyID
  1167. );
  1168. if (!pIniQMPolicy) {
  1169. dwError = ERROR_IPSEC_QM_POLICY_NOT_FOUND;
  1170. BAIL_ON_WIN32_ERROR(dwError);
  1171. }
  1172. }
  1173. *ppIniQMPolicy = pIniQMPolicy;
  1174. return (dwError);
  1175. error:
  1176. *ppIniQMPolicy = NULL;
  1177. return (dwError);
  1178. }
  1179. DWORD
  1180. CreateNonAHQMOffers(
  1181. DWORD dwInOfferCount,
  1182. PIPSEC_QM_OFFER pInOffers,
  1183. PDWORD pdwOfferCount,
  1184. PIPSEC_QM_OFFER * ppOffers
  1185. )
  1186. {
  1187. DWORD dwError = 0;
  1188. PIPSEC_QM_OFFER pInTempOffer = NULL;
  1189. DWORD i = 0;
  1190. BOOL bAH = FALSE;
  1191. DWORD dwNonAHOfferCount = 0;
  1192. PIPSEC_QM_OFFER pOffers = NULL;
  1193. PIPSEC_QM_OFFER pTemp = NULL;
  1194. DWORD j = 0;
  1195. DWORD k = 0;
  1196. pInTempOffer = pInOffers;
  1197. for (i = 0; i < dwInOfferCount; i++) {
  1198. bAH = IsAHQMOffer(pInTempOffer);
  1199. if (!bAH) {
  1200. dwNonAHOfferCount++;
  1201. }
  1202. pInTempOffer++;
  1203. }
  1204. if (!dwNonAHOfferCount) {
  1205. *pdwOfferCount = 0;
  1206. *ppOffers = NULL;
  1207. return (dwError);
  1208. }
  1209. dwError = SPDApiBufferAllocate(
  1210. sizeof(IPSEC_QM_OFFER) * dwNonAHOfferCount,
  1211. &(pOffers)
  1212. );
  1213. BAIL_ON_WIN32_ERROR(dwError);
  1214. pTemp = pOffers;
  1215. pInTempOffer = pInOffers;
  1216. for (i = 0; i < dwInOfferCount; i++) {
  1217. bAH = IsAHQMOffer(pInTempOffer);
  1218. if (bAH) {
  1219. pInTempOffer++;
  1220. continue;
  1221. }
  1222. memcpy(
  1223. &(pTemp->Lifetime),
  1224. &(pInTempOffer->Lifetime),
  1225. sizeof(KEY_LIFETIME)
  1226. );
  1227. pTemp->dwFlags = pInTempOffer->dwFlags;
  1228. pTemp->bPFSRequired = pInTempOffer->bPFSRequired;
  1229. pTemp->dwPFSGroup = pInTempOffer->dwPFSGroup;
  1230. pTemp->dwNumAlgos = pInTempOffer->dwNumAlgos;
  1231. for (j = 0; j < (pInTempOffer->dwNumAlgos); j++) {
  1232. memcpy(
  1233. &(pTemp->Algos[j]),
  1234. &(pInTempOffer->Algos[j]),
  1235. sizeof(IPSEC_QM_ALGO)
  1236. );
  1237. }
  1238. for (k = j; k < QM_MAX_ALGOS; k++) {
  1239. memset(&(pTemp->Algos[k]), 0, sizeof(IPSEC_QM_ALGO));
  1240. }
  1241. pTemp->dwReserved = pInTempOffer->dwReserved;
  1242. pInTempOffer++;
  1243. pTemp++;
  1244. }
  1245. *pdwOfferCount = dwNonAHOfferCount;
  1246. *ppOffers = pOffers;
  1247. return (dwError);
  1248. error:
  1249. if (pOffers) {
  1250. FreeQMOffers(
  1251. i,
  1252. pOffers
  1253. );
  1254. }
  1255. *pdwOfferCount = 0;
  1256. *ppOffers = NULL;
  1257. return (dwError);
  1258. }
  1259. BOOL
  1260. IsAHQMOffer(
  1261. PIPSEC_QM_OFFER pIpsecQMOffer
  1262. )
  1263. {
  1264. BOOL bAH = FALSE;
  1265. DWORD j = 0;
  1266. for (j = 0; j < (pIpsecQMOffer->dwNumAlgos); j++) {
  1267. switch (pIpsecQMOffer->Algos[j].Operation) {
  1268. case AUTHENTICATION:
  1269. bAH = TRUE;
  1270. break;
  1271. case ENCRYPTION:
  1272. break;
  1273. case NONE:
  1274. case COMPRESSION:
  1275. default:
  1276. ASSERT(FALSE);
  1277. break;
  1278. }
  1279. if (bAH) {
  1280. break;
  1281. }
  1282. }
  1283. return (bAH);
  1284. }