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.

1348 lines
27 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. DWORD
  12. AddQMPolicy(
  13. LPWSTR pServerName,
  14. DWORD dwFlags,
  15. PIPSEC_QM_POLICY pQMPolicy
  16. )
  17. /*++
  18. Routine Description:
  19. This function adds a quick mode policy to the SPD.
  20. Arguments:
  21. pServerName - Server on which the quick mode policy is to be added.
  22. pQMPolicy - Quick mode policy to be added.
  23. Return Value:
  24. ERROR_SUCCESS - Success.
  25. Win32 Error - Failure.
  26. --*/
  27. {
  28. DWORD dwError = 0;
  29. PINIQMPOLICY pIniQMPolicy = NULL;
  30. BOOL bPersist = FALSE;
  31. bPersist = (BOOL) (dwFlags & PERSIST_SPD_OBJECT);
  32. //
  33. // Validate the quick mode policy.
  34. //
  35. dwError = ValidateQMPolicy(
  36. pQMPolicy
  37. );
  38. BAIL_ON_WIN32_ERROR(dwError);
  39. ENTER_SPD_SECTION();
  40. dwError = ValidateSecurity(
  41. SPD_OBJECT_SERVER,
  42. SERVER_ACCESS_ADMINISTER,
  43. NULL,
  44. NULL
  45. );
  46. BAIL_ON_LOCK_ERROR(dwError);
  47. pIniQMPolicy = FindQMPolicy(
  48. gpIniQMPolicy,
  49. pQMPolicy->pszPolicyName
  50. );
  51. if (pIniQMPolicy) {
  52. dwError = ERROR_IPSEC_QM_POLICY_EXISTS;
  53. BAIL_ON_LOCK_ERROR(dwError);
  54. }
  55. pIniQMPolicy = FindQMPolicyByGuid(
  56. gpIniQMPolicy,
  57. pQMPolicy->gPolicyID
  58. );
  59. if (pIniQMPolicy) {
  60. dwError = ERROR_IPSEC_QM_POLICY_EXISTS;
  61. BAIL_ON_LOCK_ERROR(dwError);
  62. }
  63. if (bPersist && !gbLoadingPersistence) {
  64. dwError = PersistQMPolicy(
  65. pQMPolicy
  66. );
  67. BAIL_ON_LOCK_ERROR(dwError);
  68. }
  69. dwError = CreateIniQMPolicy(
  70. pQMPolicy,
  71. &pIniQMPolicy
  72. );
  73. BAIL_ON_LOCK_ERROR(dwError);
  74. pIniQMPolicy->bIsPersisted = bPersist;
  75. pIniQMPolicy->pNext = gpIniQMPolicy;
  76. gpIniQMPolicy = pIniQMPolicy;
  77. if ((pIniQMPolicy->dwFlags) & IPSEC_QM_POLICY_DEFAULT_POLICY) {
  78. gpIniDefaultQMPolicy = pIniQMPolicy;
  79. }
  80. LEAVE_SPD_SECTION();
  81. return (dwError);
  82. lock:
  83. LEAVE_SPD_SECTION();
  84. error:
  85. if (pQMPolicy && bPersist && !gbLoadingPersistence) {
  86. (VOID) SPDPurgeQMPolicy(
  87. pQMPolicy->gPolicyID
  88. );
  89. }
  90. return (dwError);
  91. }
  92. DWORD
  93. ValidateQMPolicy(
  94. PIPSEC_QM_POLICY pQMPolicy
  95. )
  96. {
  97. DWORD dwError = 0;
  98. if (!pQMPolicy) {
  99. dwError = ERROR_INVALID_PARAMETER;
  100. BAIL_ON_WIN32_ERROR(dwError);
  101. }
  102. if (!(pQMPolicy->pszPolicyName) || !(*(pQMPolicy->pszPolicyName))) {
  103. dwError = ERROR_INVALID_PARAMETER;
  104. BAIL_ON_WIN32_ERROR(dwError);
  105. }
  106. dwError = ValidateQMOffers(
  107. pQMPolicy->dwOfferCount,
  108. pQMPolicy->pOffers
  109. );
  110. BAIL_ON_WIN32_ERROR(dwError);
  111. error:
  112. return (dwError);
  113. }
  114. DWORD
  115. ValidateQMOffers(
  116. DWORD dwOfferCount,
  117. PIPSEC_QM_OFFER pOffers
  118. )
  119. {
  120. DWORD dwError = 0;
  121. DWORD i = 0;
  122. PIPSEC_QM_OFFER pTemp = NULL;
  123. DWORD j = 0;
  124. BOOL bAH = FALSE;
  125. BOOL bESP = FALSE;
  126. DWORD dwQMGroup = PFS_GROUP_NONE;
  127. if (!dwOfferCount || !pOffers || (dwOfferCount > IPSEC_MAX_QM_OFFERS)) {
  128. dwError = ERROR_INVALID_PARAMETER;
  129. BAIL_ON_WIN32_ERROR(dwError);
  130. }
  131. //
  132. // Need to catch the exception when the number of offers
  133. // specified is more than the actual number of offers.
  134. //
  135. pTemp = pOffers;
  136. if (pTemp->bPFSRequired) {
  137. if ((pTemp->dwPFSGroup != PFS_GROUP_1) &&
  138. (pTemp->dwPFSGroup != PFS_GROUP_2) &&
  139. (pTemp->dwPFSGroup != PFS_GROUP_MM)) {
  140. dwError = ERROR_INVALID_PARAMETER;
  141. BAIL_ON_WIN32_ERROR(dwError);
  142. }
  143. dwQMGroup=pTemp->dwPFSGroup;
  144. }
  145. else {
  146. if (pTemp->dwPFSGroup != PFS_GROUP_NONE) {
  147. dwError = ERROR_INVALID_PARAMETER;
  148. BAIL_ON_WIN32_ERROR(dwError);
  149. }
  150. }
  151. for (i = 0; i < dwOfferCount; i++) {
  152. if (dwQMGroup) {
  153. if ((!pTemp->bPFSRequired) || (pTemp->dwPFSGroup != dwQMGroup)) {
  154. dwError = ERROR_INVALID_PARAMETER;
  155. BAIL_ON_WIN32_ERROR(dwError);
  156. }
  157. } else {
  158. if ((pTemp->bPFSRequired) || (pTemp->dwPFSGroup != PFS_GROUP_NONE)) {
  159. dwError = ERROR_INVALID_PARAMETER;
  160. BAIL_ON_WIN32_ERROR(dwError);
  161. }
  162. }
  163. if (!(pTemp->dwNumAlgos) || (pTemp->dwNumAlgos > QM_MAX_ALGOS)) {
  164. dwError = ERROR_INVALID_PARAMETER;
  165. BAIL_ON_WIN32_ERROR(dwError);
  166. }
  167. bAH = FALSE;
  168. bESP = FALSE;
  169. for (j = 0; j < (pTemp->dwNumAlgos); j++) {
  170. switch (pTemp->Algos[j].Operation) {
  171. case AUTHENTICATION:
  172. if (bAH) {
  173. dwError = ERROR_INVALID_PARAMETER;
  174. BAIL_ON_WIN32_ERROR(dwError);
  175. }
  176. if ((pTemp->Algos[j].uAlgoIdentifier == IPSEC_DOI_AH_NONE) ||
  177. (pTemp->Algos[j].uAlgoIdentifier >= IPSEC_DOI_AH_MAX)) {
  178. dwError = ERROR_INVALID_PARAMETER;
  179. BAIL_ON_WIN32_ERROR(dwError);
  180. }
  181. if (pTemp->Algos[j].uSecAlgoIdentifier != HMAC_AH_NONE) {
  182. dwError = ERROR_INVALID_PARAMETER;
  183. BAIL_ON_WIN32_ERROR(dwError);
  184. }
  185. bAH = TRUE;
  186. break;
  187. case ENCRYPTION:
  188. if (bESP) {
  189. dwError = ERROR_INVALID_PARAMETER;
  190. BAIL_ON_WIN32_ERROR(dwError);
  191. }
  192. if (pTemp->Algos[j].uAlgoIdentifier >= IPSEC_DOI_ESP_MAX) {
  193. dwError = ERROR_INVALID_PARAMETER;
  194. BAIL_ON_WIN32_ERROR(dwError);
  195. }
  196. if (pTemp->Algos[j].uSecAlgoIdentifier >= HMAC_AH_MAX) {
  197. dwError = ERROR_INVALID_PARAMETER;
  198. BAIL_ON_WIN32_ERROR(dwError);
  199. }
  200. if (pTemp->Algos[j].uAlgoIdentifier == IPSEC_DOI_ESP_NONE) {
  201. if (pTemp->Algos[j].uSecAlgoIdentifier == HMAC_AH_NONE) {
  202. dwError = ERROR_INVALID_PARAMETER;
  203. BAIL_ON_WIN32_ERROR(dwError);
  204. }
  205. }
  206. bESP = TRUE;
  207. break;
  208. case NONE:
  209. case COMPRESSION:
  210. default:
  211. dwError = ERROR_INVALID_PARAMETER;
  212. BAIL_ON_WIN32_ERROR(dwError);
  213. break;
  214. }
  215. }
  216. pTemp++;
  217. }
  218. error:
  219. return (dwError);
  220. }
  221. DWORD
  222. CreateIniQMPolicy(
  223. PIPSEC_QM_POLICY pQMPolicy,
  224. PINIQMPOLICY * ppIniQMPolicy
  225. )
  226. {
  227. DWORD dwError = 0;
  228. PINIQMPOLICY pIniQMPolicy = NULL;
  229. dwError = AllocateSPDMemory(
  230. sizeof(INIQMPOLICY),
  231. &pIniQMPolicy
  232. );
  233. BAIL_ON_WIN32_ERROR(dwError);
  234. memcpy(
  235. &(pIniQMPolicy->gPolicyID),
  236. &(pQMPolicy->gPolicyID),
  237. sizeof(GUID)
  238. );
  239. dwError = AllocateSPDString(
  240. pQMPolicy->pszPolicyName,
  241. &(pIniQMPolicy->pszPolicyName)
  242. );
  243. BAIL_ON_WIN32_ERROR(dwError);
  244. pIniQMPolicy->cRef = 0;
  245. pIniQMPolicy->bIsPersisted = FALSE;
  246. pIniQMPolicy->dwFlags = pQMPolicy->dwFlags;
  247. pIniQMPolicy->pNext = NULL;
  248. dwError = CreateIniQMOffers(
  249. pQMPolicy->dwOfferCount,
  250. pQMPolicy->pOffers,
  251. &(pIniQMPolicy->dwOfferCount),
  252. &(pIniQMPolicy->pOffers)
  253. );
  254. BAIL_ON_WIN32_ERROR(dwError);
  255. *ppIniQMPolicy = pIniQMPolicy;
  256. return (dwError);
  257. error:
  258. if (pIniQMPolicy) {
  259. FreeIniQMPolicy(
  260. pIniQMPolicy
  261. );
  262. }
  263. *ppIniQMPolicy = NULL;
  264. return (dwError);
  265. }
  266. DWORD
  267. CreateIniQMOffers(
  268. DWORD dwInOfferCount,
  269. PIPSEC_QM_OFFER pInOffers,
  270. PDWORD pdwOfferCount,
  271. PIPSEC_QM_OFFER * ppOffers
  272. )
  273. {
  274. DWORD dwError = 0;
  275. PIPSEC_QM_OFFER pOffers = NULL;
  276. PIPSEC_QM_OFFER pTemp = NULL;
  277. PIPSEC_QM_OFFER pInTempOffer = NULL;
  278. DWORD i = 0;
  279. DWORD j = 0;
  280. //
  281. // Offer count and the offers themselves have already been validated.
  282. //
  283. dwError = AllocateSPDMemory(
  284. sizeof(IPSEC_QM_OFFER) * dwInOfferCount,
  285. &(pOffers)
  286. );
  287. BAIL_ON_WIN32_ERROR(dwError);
  288. pTemp = pOffers;
  289. pInTempOffer = pInOffers;
  290. for (i = 0; i < dwInOfferCount; i++) {
  291. memcpy(
  292. &(pTemp->Lifetime),
  293. &(pInTempOffer->Lifetime),
  294. sizeof(KEY_LIFETIME)
  295. );
  296. pTemp->dwFlags = pInTempOffer->dwFlags;
  297. pTemp->bPFSRequired = pInTempOffer->bPFSRequired;
  298. pTemp->dwPFSGroup = pInTempOffer->dwPFSGroup;
  299. pTemp->dwNumAlgos = pInTempOffer->dwNumAlgos;
  300. for (j = 0; j < (pInTempOffer->dwNumAlgos); j++) {
  301. memcpy(
  302. &(pTemp->Algos[j]),
  303. &(pInTempOffer->Algos[j]),
  304. sizeof(IPSEC_QM_ALGO)
  305. );
  306. }
  307. pInTempOffer++;
  308. pTemp++;
  309. }
  310. *pdwOfferCount = dwInOfferCount;
  311. *ppOffers = pOffers;
  312. return (dwError);
  313. error:
  314. if (pOffers) {
  315. FreeIniQMOffers(
  316. i,
  317. pOffers
  318. );
  319. }
  320. *pdwOfferCount = 0;
  321. *ppOffers = NULL;
  322. return (dwError);
  323. }
  324. VOID
  325. FreeIniQMPolicy(
  326. PINIQMPOLICY pIniQMPolicy
  327. )
  328. {
  329. if (pIniQMPolicy) {
  330. if (pIniQMPolicy->pszPolicyName) {
  331. FreeSPDString(pIniQMPolicy->pszPolicyName);
  332. }
  333. FreeIniQMOffers(
  334. pIniQMPolicy->dwOfferCount,
  335. pIniQMPolicy->pOffers
  336. );
  337. FreeSPDMemory(pIniQMPolicy);
  338. }
  339. }
  340. VOID
  341. FreeIniQMOffers(
  342. DWORD dwOfferCount,
  343. PIPSEC_QM_OFFER pOffers
  344. )
  345. {
  346. if (pOffers) {
  347. FreeSPDMemory(pOffers);
  348. }
  349. }
  350. PINIQMPOLICY
  351. FindQMPolicy(
  352. PINIQMPOLICY pIniQMPolicyList,
  353. LPWSTR pszPolicyName
  354. )
  355. {
  356. DWORD dwError = 0;
  357. PINIQMPOLICY pTemp = NULL;
  358. pTemp = pIniQMPolicyList;
  359. while (pTemp) {
  360. if (!_wcsicmp(pTemp->pszPolicyName, pszPolicyName)) {
  361. return (pTemp);
  362. }
  363. pTemp = pTemp->pNext;
  364. }
  365. return (NULL);
  366. }
  367. DWORD
  368. DeleteQMPolicy(
  369. LPWSTR pServerName,
  370. LPWSTR pszPolicyName
  371. )
  372. /*++
  373. Routine Description:
  374. This function deletes a quick mode policy from the SPD.
  375. Arguments:
  376. pServerName - Server on which the quick mode policy is to be deleted.
  377. pszPolicyName - Quick mode policy to be deleted.
  378. Return Value:
  379. ERROR_SUCCESS - Success.
  380. Win32 Error - Failure.
  381. --*/
  382. {
  383. DWORD dwError = 0;
  384. PINIQMPOLICY pIniQMPolicy = NULL;
  385. GUID gPolicyID;
  386. if (!pszPolicyName || !*pszPolicyName) {
  387. return (ERROR_INVALID_PARAMETER);
  388. }
  389. ENTER_SPD_SECTION();
  390. dwError = ValidateSecurity(
  391. SPD_OBJECT_SERVER,
  392. SERVER_ACCESS_ADMINISTER,
  393. NULL,
  394. NULL
  395. );
  396. BAIL_ON_LOCK_ERROR(dwError);
  397. pIniQMPolicy = FindQMPolicy(
  398. gpIniQMPolicy,
  399. pszPolicyName
  400. );
  401. if (!pIniQMPolicy) {
  402. dwError = ERROR_IPSEC_QM_POLICY_NOT_FOUND;
  403. BAIL_ON_LOCK_ERROR(dwError);
  404. }
  405. if (pIniQMPolicy->cRef) {
  406. dwError = ERROR_IPSEC_QM_POLICY_IN_USE;
  407. memcpy(&gPolicyID, &pIniQMPolicy->gPolicyID, sizeof(GUID));
  408. BAIL_ON_LOCK_ERROR(dwError);
  409. }
  410. memcpy(&gPolicyID, &pIniQMPolicy->gPolicyID, sizeof(GUID));
  411. if (pIniQMPolicy->bIsPersisted) {
  412. dwError = SPDPurgeQMPolicy(
  413. gPolicyID
  414. );
  415. BAIL_ON_LOCK_ERROR(dwError);
  416. }
  417. dwError = DeleteIniQMPolicy(
  418. pIniQMPolicy
  419. );
  420. BAIL_ON_LOCK_ERROR(dwError);
  421. LEAVE_SPD_SECTION();
  422. if (gbIKENotify) {
  423. (VOID) IKENotifyPolicyChange(
  424. &(gPolicyID),
  425. POLICY_GUID_QM
  426. );
  427. }
  428. return (dwError);
  429. lock:
  430. LEAVE_SPD_SECTION();
  431. if ((dwError == ERROR_IPSEC_QM_POLICY_IN_USE) && gbIKENotify) {
  432. (VOID) IKENotifyPolicyChange(
  433. &(gPolicyID),
  434. POLICY_GUID_QM
  435. );
  436. }
  437. return (dwError);
  438. }
  439. DWORD
  440. EnumQMPolicies(
  441. LPWSTR pServerName,
  442. PIPSEC_QM_POLICY * ppQMPolicies,
  443. DWORD dwPreferredNumEntries,
  444. LPDWORD pdwNumPolicies,
  445. LPDWORD pdwResumeHandle
  446. )
  447. /*++
  448. Routine Description:
  449. This function enumerates quick mode policies from the SPD.
  450. Arguments:
  451. pServerName - Server on which the quick mode policies are to
  452. be enumerated.
  453. ppQMPolicies - Enumerated quick mode policies returned to the
  454. caller.
  455. dwPreferredNumEntries - Preferred number of enumeration entries.
  456. pdwNumPolicies - Number of quick mode policies actually enumerated.
  457. pdwResumeHandle - Handle to the location in the quick mode policy
  458. list from which to resume enumeration.
  459. Return Value:
  460. ERROR_SUCCESS - Success.
  461. Win32 Error - Failure.
  462. --*/
  463. {
  464. DWORD dwError = 0;
  465. DWORD dwResumeHandle = 0;
  466. DWORD dwNumToEnum = 0;
  467. PINIQMPOLICY pIniQMPolicy = NULL;
  468. DWORD i = 0;
  469. PINIQMPOLICY pTemp = NULL;
  470. DWORD dwNumPolicies = 0;
  471. PIPSEC_QM_POLICY pQMPolicies = NULL;
  472. PIPSEC_QM_POLICY pQMPolicy = NULL;
  473. dwResumeHandle = *pdwResumeHandle;
  474. if (!dwPreferredNumEntries || (dwPreferredNumEntries > MAX_QMPOLICY_ENUM_COUNT)) {
  475. dwNumToEnum = MAX_QMPOLICY_ENUM_COUNT;
  476. }
  477. else {
  478. dwNumToEnum = dwPreferredNumEntries;
  479. }
  480. ENTER_SPD_SECTION();
  481. dwError = ValidateSecurity(
  482. SPD_OBJECT_SERVER,
  483. SERVER_ACCESS_ADMINISTER,
  484. NULL,
  485. NULL
  486. );
  487. BAIL_ON_LOCK_ERROR(dwError);
  488. pIniQMPolicy = gpIniQMPolicy;
  489. for (i = 0; (i < dwResumeHandle) && (pIniQMPolicy != NULL); i++) {
  490. pIniQMPolicy = pIniQMPolicy->pNext;
  491. }
  492. if (!pIniQMPolicy) {
  493. dwError = ERROR_NO_DATA;
  494. BAIL_ON_LOCK_ERROR(dwError);
  495. }
  496. pTemp = pIniQMPolicy;
  497. while (pTemp && (dwNumPolicies < dwNumToEnum)) {
  498. dwNumPolicies++;
  499. pTemp = pTemp->pNext;
  500. }
  501. dwError = SPDApiBufferAllocate(
  502. sizeof(IPSEC_QM_POLICY)*dwNumPolicies,
  503. &pQMPolicies
  504. );
  505. BAIL_ON_LOCK_ERROR(dwError);
  506. pTemp = pIniQMPolicy;
  507. pQMPolicy = pQMPolicies;
  508. for (i = 0; i < dwNumPolicies; i++) {
  509. dwError = CopyQMPolicy(
  510. pTemp,
  511. pQMPolicy
  512. );
  513. BAIL_ON_LOCK_ERROR(dwError);
  514. pTemp = pTemp->pNext;
  515. pQMPolicy++;
  516. }
  517. *ppQMPolicies = pQMPolicies;
  518. *pdwResumeHandle = dwResumeHandle + dwNumPolicies;
  519. *pdwNumPolicies = dwNumPolicies;
  520. LEAVE_SPD_SECTION();
  521. return (dwError);
  522. lock:
  523. LEAVE_SPD_SECTION();
  524. if (pQMPolicies) {
  525. FreeQMPolicies(
  526. i,
  527. pQMPolicies
  528. );
  529. }
  530. *ppQMPolicies = NULL;
  531. *pdwResumeHandle = dwResumeHandle;
  532. *pdwNumPolicies = 0;
  533. return (dwError);
  534. }
  535. DWORD
  536. SetQMPolicy(
  537. LPWSTR pServerName,
  538. LPWSTR pszPolicyName,
  539. PIPSEC_QM_POLICY pQMPolicy
  540. )
  541. /*++
  542. Routine Description:
  543. This function updates a quick mode policy in the SPD.
  544. Arguments:
  545. pServerName - Server on which the quick mode policy is to be
  546. updated.
  547. pszPolicyName - Name of the quick mode policy to be updated.
  548. pQMPolicy - New quick mode policy which will replace the
  549. existing policy.
  550. Return Value:
  551. ERROR_SUCCESS - Success.
  552. Win32 Error - Failure.
  553. --*/
  554. {
  555. DWORD dwError = 0;
  556. PINIQMPOLICY pIniQMPolicy = NULL;
  557. if (!pszPolicyName || !*pszPolicyName) {
  558. return (ERROR_INVALID_PARAMETER);
  559. }
  560. //
  561. // Validate quick mode policy.
  562. //
  563. dwError = ValidateQMPolicy(
  564. pQMPolicy
  565. );
  566. BAIL_ON_WIN32_ERROR(dwError);
  567. ENTER_SPD_SECTION();
  568. dwError = ValidateSecurity(
  569. SPD_OBJECT_SERVER,
  570. SERVER_ACCESS_ADMINISTER,
  571. NULL,
  572. NULL
  573. );
  574. BAIL_ON_LOCK_ERROR(dwError);
  575. pIniQMPolicy = FindQMPolicy(
  576. gpIniQMPolicy,
  577. pszPolicyName
  578. );
  579. if (!pIniQMPolicy) {
  580. dwError = ERROR_IPSEC_QM_POLICY_NOT_FOUND;
  581. BAIL_ON_LOCK_ERROR(dwError);
  582. }
  583. if (memcmp(
  584. &(pIniQMPolicy->gPolicyID),
  585. &(pQMPolicy->gPolicyID),
  586. sizeof(GUID))) {
  587. dwError = ERROR_INVALID_PARAMETER;
  588. BAIL_ON_LOCK_ERROR(dwError);
  589. }
  590. dwError = SetIniQMPolicy(
  591. pIniQMPolicy,
  592. pQMPolicy
  593. );
  594. BAIL_ON_LOCK_ERROR(dwError);
  595. if (pIniQMPolicy->bIsPersisted) {
  596. dwError = PersistQMPolicy(
  597. pQMPolicy
  598. );
  599. BAIL_ON_LOCK_ERROR(dwError);
  600. }
  601. LEAVE_SPD_SECTION();
  602. (VOID) IKENotifyPolicyChange(
  603. &(pQMPolicy->gPolicyID),
  604. POLICY_GUID_QM
  605. );
  606. return (dwError);
  607. lock:
  608. LEAVE_SPD_SECTION();
  609. error:
  610. return (dwError);
  611. }
  612. DWORD
  613. GetQMPolicy(
  614. LPWSTR pServerName,
  615. LPWSTR pszPolicyName,
  616. PIPSEC_QM_POLICY * ppQMPolicy
  617. )
  618. /*++
  619. Routine Description:
  620. This function gets a quick mode policy from the SPD.
  621. Arguments:
  622. pServerName - Server from which to get the quick mode policy.
  623. pszPolicyName - Name of the quick mode policy to get.
  624. ppQMPolicy - Quick mode policy found returned to the caller.
  625. Return Value:
  626. ERROR_SUCCESS - Success.
  627. Win32 Error - Failure.
  628. --*/
  629. {
  630. DWORD dwError = 0;
  631. PINIQMPOLICY pIniQMPolicy = NULL;
  632. PIPSEC_QM_POLICY pQMPolicy = NULL;
  633. if (!pszPolicyName || !*pszPolicyName) {
  634. dwError = ERROR_INVALID_PARAMETER;
  635. BAIL_ON_WIN32_ERROR(dwError);
  636. }
  637. ENTER_SPD_SECTION();
  638. dwError = ValidateSecurity(
  639. SPD_OBJECT_SERVER,
  640. SERVER_ACCESS_ADMINISTER,
  641. NULL,
  642. NULL
  643. );
  644. BAIL_ON_LOCK_ERROR(dwError);
  645. pIniQMPolicy = FindQMPolicy(
  646. gpIniQMPolicy,
  647. pszPolicyName
  648. );
  649. if (!pIniQMPolicy) {
  650. dwError = ERROR_IPSEC_QM_POLICY_NOT_FOUND;
  651. BAIL_ON_LOCK_ERROR(dwError);
  652. }
  653. dwError = GetIniQMPolicy(
  654. pIniQMPolicy,
  655. &pQMPolicy
  656. );
  657. BAIL_ON_LOCK_ERROR(dwError);
  658. *ppQMPolicy = pQMPolicy;
  659. LEAVE_SPD_SECTION();
  660. return (dwError);
  661. lock:
  662. LEAVE_SPD_SECTION();
  663. error:
  664. *ppQMPolicy = NULL;
  665. return (dwError);
  666. }
  667. DWORD
  668. SetIniQMPolicy(
  669. PINIQMPOLICY pIniQMPolicy,
  670. PIPSEC_QM_POLICY pQMPolicy
  671. )
  672. {
  673. DWORD dwError = 0;
  674. DWORD dwOfferCount = 0;
  675. PIPSEC_QM_OFFER pOffers = NULL;
  676. dwError = CreateIniQMOffers(
  677. pQMPolicy->dwOfferCount,
  678. pQMPolicy->pOffers,
  679. &dwOfferCount,
  680. &pOffers
  681. );
  682. BAIL_ON_WIN32_ERROR(dwError);
  683. FreeIniQMOffers(
  684. pIniQMPolicy->dwOfferCount,
  685. pIniQMPolicy->pOffers
  686. );
  687. if ((pIniQMPolicy->dwFlags) & IPSEC_QM_POLICY_DEFAULT_POLICY) {
  688. gpIniDefaultQMPolicy = NULL;
  689. }
  690. pIniQMPolicy->dwFlags = pQMPolicy->dwFlags;
  691. pIniQMPolicy->dwOfferCount = dwOfferCount;
  692. pIniQMPolicy->pOffers = pOffers;
  693. if ((pIniQMPolicy->dwFlags) & IPSEC_QM_POLICY_DEFAULT_POLICY) {
  694. gpIniDefaultQMPolicy = pIniQMPolicy;
  695. }
  696. error:
  697. return (dwError);
  698. }
  699. DWORD
  700. GetIniQMPolicy(
  701. PINIQMPOLICY pIniQMPolicy,
  702. PIPSEC_QM_POLICY * ppQMPolicy
  703. )
  704. {
  705. DWORD dwError = 0;
  706. PIPSEC_QM_POLICY pQMPolicy = NULL;
  707. dwError = SPDApiBufferAllocate(
  708. sizeof(IPSEC_QM_POLICY),
  709. &pQMPolicy
  710. );
  711. BAIL_ON_WIN32_ERROR(dwError);
  712. dwError = CopyQMPolicy(
  713. pIniQMPolicy,
  714. pQMPolicy
  715. );
  716. BAIL_ON_WIN32_ERROR(dwError);
  717. *ppQMPolicy = pQMPolicy;
  718. return (dwError);
  719. error:
  720. if (pQMPolicy) {
  721. SPDApiBufferFree(pQMPolicy);
  722. }
  723. *ppQMPolicy = NULL;
  724. return (dwError);
  725. }
  726. DWORD
  727. CopyQMPolicy(
  728. PINIQMPOLICY pIniQMPolicy,
  729. PIPSEC_QM_POLICY pQMPolicy
  730. )
  731. {
  732. DWORD dwError = 0;
  733. memcpy(
  734. &(pQMPolicy->gPolicyID),
  735. &(pIniQMPolicy->gPolicyID),
  736. sizeof(GUID)
  737. );
  738. dwError = SPDApiBufferAllocate(
  739. wcslen(pIniQMPolicy->pszPolicyName)*sizeof(WCHAR)
  740. + sizeof(WCHAR),
  741. &(pQMPolicy->pszPolicyName)
  742. );
  743. BAIL_ON_WIN32_ERROR(dwError);
  744. wcscpy(pQMPolicy->pszPolicyName, pIniQMPolicy->pszPolicyName);
  745. pQMPolicy->dwFlags = pIniQMPolicy->dwFlags;
  746. dwError = CreateQMOffers(
  747. pIniQMPolicy->dwOfferCount,
  748. pIniQMPolicy->pOffers,
  749. &(pQMPolicy->dwOfferCount),
  750. &(pQMPolicy->pOffers)
  751. );
  752. BAIL_ON_WIN32_ERROR(dwError);
  753. return (dwError);
  754. error:
  755. if (pQMPolicy->pszPolicyName) {
  756. SPDApiBufferFree(pQMPolicy->pszPolicyName);
  757. }
  758. return (dwError);
  759. }
  760. DWORD
  761. CreateQMOffers(
  762. DWORD dwInOfferCount,
  763. PIPSEC_QM_OFFER pInOffers,
  764. PDWORD pdwOfferCount,
  765. PIPSEC_QM_OFFER * ppOffers
  766. )
  767. {
  768. DWORD dwError = 0;
  769. PIPSEC_QM_OFFER pOffers = NULL;
  770. PIPSEC_QM_OFFER pTemp = NULL;
  771. PIPSEC_QM_OFFER pInTempOffer = NULL;
  772. DWORD i = 0;
  773. DWORD j = 0;
  774. DWORD k = 0;
  775. //
  776. // Offer count and the offers themselves have already been validated.
  777. //
  778. dwError = SPDApiBufferAllocate(
  779. sizeof(IPSEC_QM_OFFER) * dwInOfferCount,
  780. &(pOffers)
  781. );
  782. BAIL_ON_WIN32_ERROR(dwError);
  783. pTemp = pOffers;
  784. pInTempOffer = pInOffers;
  785. for (i = 0; i < dwInOfferCount; i++) {
  786. memcpy(
  787. &(pTemp->Lifetime),
  788. &(pInTempOffer->Lifetime),
  789. sizeof(KEY_LIFETIME)
  790. );
  791. pTemp->dwFlags = pInTempOffer->dwFlags;
  792. pTemp->bPFSRequired = pInTempOffer->bPFSRequired;
  793. pTemp->dwPFSGroup = pInTempOffer->dwPFSGroup;
  794. pTemp->dwNumAlgos = pInTempOffer->dwNumAlgos;
  795. for (j = 0; j < (pInTempOffer->dwNumAlgos); j++) {
  796. memcpy(
  797. &(pTemp->Algos[j]),
  798. &(pInTempOffer->Algos[j]),
  799. sizeof(IPSEC_QM_ALGO)
  800. );
  801. }
  802. for (k = j; k < QM_MAX_ALGOS; k++) {
  803. memset(&(pTemp->Algos[k]), 0, sizeof(IPSEC_QM_ALGO));
  804. }
  805. pInTempOffer++;
  806. pTemp++;
  807. }
  808. *pdwOfferCount = dwInOfferCount;
  809. *ppOffers = pOffers;
  810. return (dwError);
  811. error:
  812. if (pOffers) {
  813. FreeQMOffers(
  814. i,
  815. pOffers
  816. );
  817. }
  818. *pdwOfferCount = 0;
  819. *ppOffers = NULL;
  820. return (dwError);
  821. }
  822. DWORD
  823. DeleteIniQMPolicy(
  824. PINIQMPOLICY pIniQMPolicy
  825. )
  826. {
  827. DWORD dwError = 0;
  828. PINIQMPOLICY * ppTemp = NULL;
  829. ppTemp = &gpIniQMPolicy;
  830. while (*ppTemp) {
  831. if (*ppTemp == pIniQMPolicy) {
  832. break;
  833. }
  834. ppTemp = &((*ppTemp)->pNext);
  835. }
  836. if (*ppTemp) {
  837. *ppTemp = pIniQMPolicy->pNext;
  838. }
  839. if ((pIniQMPolicy->dwFlags) & IPSEC_QM_POLICY_DEFAULT_POLICY) {
  840. gpIniDefaultQMPolicy = NULL;
  841. }
  842. FreeIniQMPolicy(pIniQMPolicy);
  843. return (dwError);
  844. }
  845. VOID
  846. FreeQMOffers(
  847. DWORD dwOfferCount,
  848. PIPSEC_QM_OFFER pOffers
  849. )
  850. {
  851. if (pOffers) {
  852. SPDApiBufferFree(pOffers);
  853. }
  854. }
  855. VOID
  856. FreeIniQMPolicyList(
  857. PINIQMPOLICY pIniQMPolicyList
  858. )
  859. {
  860. PINIQMPOLICY pTemp = NULL;
  861. PINIQMPOLICY pIniQMPolicy = NULL;
  862. pTemp = pIniQMPolicyList;
  863. while (pTemp) {
  864. pIniQMPolicy = pTemp;
  865. pTemp = pTemp->pNext;
  866. FreeIniQMPolicy(pIniQMPolicy);
  867. }
  868. }
  869. PINIQMPOLICY
  870. FindQMPolicyByGuid(
  871. PINIQMPOLICY pIniQMPolicyList,
  872. GUID gPolicyID
  873. )
  874. {
  875. DWORD dwError = 0;
  876. PINIQMPOLICY pTemp = NULL;
  877. pTemp = pIniQMPolicyList;
  878. while (pTemp) {
  879. if (!memcmp(&(pTemp->gPolicyID), &gPolicyID, sizeof(GUID))) {
  880. return (pTemp);
  881. }
  882. pTemp = pTemp->pNext;
  883. }
  884. return (NULL);
  885. }
  886. VOID
  887. FreeQMPolicies(
  888. DWORD dwNumQMPolicies,
  889. PIPSEC_QM_POLICY pQMPolicies
  890. )
  891. {
  892. DWORD i = 0;
  893. if (pQMPolicies) {
  894. for (i = 0; i < dwNumQMPolicies; i++) {
  895. if (pQMPolicies[i].pszPolicyName) {
  896. SPDApiBufferFree(pQMPolicies[i].pszPolicyName);
  897. }
  898. FreeQMOffers(
  899. pQMPolicies[i].dwOfferCount,
  900. pQMPolicies[i].pOffers
  901. );
  902. }
  903. SPDApiBufferFree(pQMPolicies);
  904. }
  905. }
  906. DWORD
  907. GetQMPolicyByID(
  908. LPWSTR pServerName,
  909. GUID gQMPolicyID,
  910. PIPSEC_QM_POLICY * ppQMPolicy
  911. )
  912. /*++
  913. Routine Description:
  914. This function gets a quick mode policy from the SPD.
  915. Arguments:
  916. pServerName - Server from which to get the quick mode policy.
  917. gQMFilter - Guid of the quick mode policy to get.
  918. ppQMPolicy - Quick mode policy found returned to the caller.
  919. Return Value:
  920. ERROR_SUCCESS - Success.
  921. Win32 Error - Failure.
  922. --*/
  923. {
  924. DWORD dwError = 0;
  925. PINIQMPOLICY pIniQMPolicy = NULL;
  926. PIPSEC_QM_POLICY pQMPolicy = NULL;
  927. ENTER_SPD_SECTION();
  928. dwError = ValidateSecurity(
  929. SPD_OBJECT_SERVER,
  930. SERVER_ACCESS_ADMINISTER,
  931. NULL,
  932. NULL
  933. );
  934. BAIL_ON_LOCK_ERROR(dwError);
  935. pIniQMPolicy = FindQMPolicyByGuid(
  936. gpIniQMPolicy,
  937. gQMPolicyID
  938. );
  939. if (!pIniQMPolicy) {
  940. dwError = ERROR_IPSEC_QM_POLICY_NOT_FOUND;
  941. BAIL_ON_LOCK_ERROR(dwError);
  942. }
  943. dwError = GetIniQMPolicy(
  944. pIniQMPolicy,
  945. &pQMPolicy
  946. );
  947. BAIL_ON_LOCK_ERROR(dwError);
  948. *ppQMPolicy = pQMPolicy;
  949. LEAVE_SPD_SECTION();
  950. return (dwError);
  951. lock:
  952. LEAVE_SPD_SECTION();
  953. *ppQMPolicy = NULL;
  954. return (dwError);
  955. }
  956. DWORD
  957. LocateQMPolicy(
  958. DWORD dwFlags,
  959. GUID gPolicyID,
  960. PINIQMPOLICY * ppIniQMPolicy
  961. )
  962. {
  963. DWORD dwError = 0;
  964. PINIQMPOLICY pIniQMPolicy = NULL;
  965. if (dwFlags & IPSEC_QM_POLICY_DEFAULT_POLICY) {
  966. if (!gpIniDefaultQMPolicy) {
  967. dwError = ERROR_IPSEC_DEFAULT_QM_POLICY_NOT_FOUND;
  968. BAIL_ON_WIN32_ERROR(dwError);
  969. }
  970. pIniQMPolicy = gpIniDefaultQMPolicy;
  971. }
  972. else {
  973. pIniQMPolicy = FindQMPolicyByGuid(
  974. gpIniQMPolicy,
  975. gPolicyID
  976. );
  977. if (!pIniQMPolicy) {
  978. dwError = ERROR_IPSEC_QM_POLICY_NOT_FOUND;
  979. BAIL_ON_WIN32_ERROR(dwError);
  980. }
  981. }
  982. *ppIniQMPolicy = pIniQMPolicy;
  983. return (dwError);
  984. error:
  985. *ppIniQMPolicy = NULL;
  986. return (dwError);
  987. }