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.

4217 lines
110 KiB

  1. /*++
  2. Copyright (c) 1997-2001 Microsoft Corporation
  3. Module Name:
  4. saapi.c
  5. Abstract:
  6. This module contains the SAAPI implementation
  7. Author:
  8. Sanjay Anand (SanjayAn) 12-May-1997
  9. ChunYe
  10. Environment:
  11. Kernel mode
  12. Revision History:
  13. --*/
  14. #include "precomp.h"
  15. #pragma hdrstop
  16. #ifdef ALLOC_PRAGMA
  17. #pragma alloc_text(PAGE, IPSecInitRandom)
  18. #endif
  19. BOOLEAN
  20. IPSecInitRandom(
  21. VOID
  22. )
  23. /*++
  24. Routine Description:
  25. Initialize the IPSecRngKey by calling into ksecdd to get 2048 bits of random
  26. and create the RC4 key.
  27. Arguments:
  28. Called at PASSIVE level.
  29. Return Value:
  30. TRUE/FALSE
  31. --*/
  32. {
  33. UCHAR pBuf[RNG_KEY_SIZE];
  34. PAGED_CODE();
  35. if (IPSEC_GEN_RANDOM(pBuf, RNG_KEY_SIZE) == FALSE) {
  36. IPSEC_DEBUG(LOAD, ("IPSEC_GEN_RANDOM failure.\n"));
  37. return FALSE;
  38. }
  39. //
  40. // Generate the key control structure.
  41. //
  42. IPSEC_RC4_KEY(&IPSecRngKey, RNG_KEY_SIZE, pBuf);
  43. return TRUE;
  44. }
  45. VOID
  46. IPSecRngRekey(
  47. IN PVOID Context
  48. )
  49. /*++
  50. Routine Description:
  51. Initialize the IPSecRngKey by calling into ksecdd to get 2048 bits of random
  52. and create the RC4 key.
  53. Arguments:
  54. Called at PASSIVE level.
  55. Return Value:
  56. None.
  57. --*/
  58. {
  59. IPSecInitRandom();
  60. IPSEC_DECREMENT(g_ipsec.NumWorkers);
  61. #if DBG
  62. IPSecRngInRekey = 0;
  63. #endif
  64. IPSEC_SET_VALUE(IPSecRngBytes, 0);
  65. }
  66. BOOLEAN
  67. IPSecGenerateRandom(
  68. IN PUCHAR pBuf,
  69. IN ULONG BytesNeeded
  70. )
  71. /*++
  72. Routine Description:
  73. Generate a positive pseudo-random number between Lower and Upper bounds;
  74. simple linear congruential algorithm. ANSI C "rand()" function. Courtesy JameelH.
  75. Arguments:
  76. LowerBound, UpperBound - range of random number.
  77. Return Value:
  78. a random number.
  79. --*/
  80. {
  81. ULONG RngBytes;
  82. IPSEC_RC4(&IPSecRngKey, BytesNeeded, pBuf);
  83. //
  84. // Rekey if we have exceeded the threshold.
  85. //
  86. RngBytes = IPSEC_ADD_VALUE(IPSecRngBytes, BytesNeeded);
  87. if (RngBytes <= RNG_REKEY_THRESHOLD &&
  88. (RngBytes + BytesNeeded) > RNG_REKEY_THRESHOLD) {
  89. //
  90. // Create a worker thread to perform the rekey since it has to be done
  91. // as paged code.
  92. //
  93. #if DBG
  94. ASSERT(IPSecRngInRekey == 0);
  95. IPSecRngInRekey = 1;
  96. #endif
  97. ExInitializeWorkItem( &IPSecRngQueueItem,
  98. IPSecRngRekey,
  99. NULL);
  100. ExQueueWorkItem(&IPSecRngQueueItem, DelayedWorkQueue);
  101. IPSEC_INCREMENT(g_ipsec.NumWorkers);
  102. }
  103. return TRUE;
  104. }
  105. VOID
  106. IPSecCleanupOutboundSA(
  107. IN PSA_TABLE_ENTRY pInboundSA,
  108. IN PSA_TABLE_ENTRY pOutboundSA,
  109. IN BOOLEAN fNoDelete
  110. )
  111. /*++
  112. Routine Description:
  113. Deletes an outbound SA.
  114. Called with SADB lock held, returns with it.
  115. Arguments:
  116. Return Value:
  117. The final status from the operation.
  118. --*/
  119. {
  120. KIRQL kIrql;
  121. IPSEC_DEBUG(ACQUIRE, ("Deleting assoc (outbound) SA: %lx\n", pOutboundSA));
  122. pInboundSA->sa_AssociatedSA = NULL;
  123. //
  124. // de-link from the Filter lists
  125. //
  126. if (pOutboundSA->sa_Flags & FLAGS_SA_ON_FILTER_LIST) {
  127. pOutboundSA->sa_Flags &= ~FLAGS_SA_ON_FILTER_LIST;
  128. IPSecRemoveEntryList(&pOutboundSA->sa_FilterLinkage);
  129. }
  130. //
  131. // So, we dont delete the Rekeyoriginal SA again.
  132. //
  133. if (pOutboundSA->sa_Flags & FLAGS_SA_REKEY_ORI) {
  134. pOutboundSA->sa_Flags &= ~FLAGS_SA_REKEY_ORI;
  135. if (pOutboundSA->sa_RekeyLarvalSA) {
  136. ASSERT(pOutboundSA->sa_RekeyLarvalSA->sa_Flags & FLAGS_SA_REKEY);
  137. pOutboundSA->sa_RekeyLarvalSA->sa_RekeyOriginalSA = NULL;
  138. }
  139. }
  140. //
  141. // invalidate the associated cache entry
  142. //
  143. IPSecInvalidateSACacheEntry(pOutboundSA);
  144. pOutboundSA->sa_State = STATE_SA_ZOMBIE;
  145. pOutboundSA->sa_AssociatedSA = NULL;
  146. if (pOutboundSA->sa_Flags & FLAGS_SA_HW_PLUMBED) {
  147. IPSecDelHWSAAtDpc(pOutboundSA);
  148. }
  149. IPSEC_DEBUG(REF, ("Out Deref IPSecCleanupOutboundSA\n"));
  150. IPSecStopTimerDerefSA(pOutboundSA);
  151. IPSEC_INC_STATISTIC(dwNumKeyDeletions);
  152. }
  153. VOID
  154. IPSecCleanupLarvalSA(
  155. IN PSA_TABLE_ENTRY pSA
  156. )
  157. /*++
  158. Routine Description:
  159. Delete the LarvalSA.
  160. Called with Outbound Lock held, returns with it.
  161. Arguments:
  162. Return Value:
  163. The final status from the operation.
  164. --*/
  165. {
  166. PSA_TABLE_ENTRY pOutboundSA;
  167. KIRQL kIrql1;
  168. KIRQL kIrql2;
  169. //
  170. // Also remove from Pending list if queued there.
  171. //
  172. ACQUIRE_LOCK(&g_ipsec.AcquireInfo.Lock, &kIrql1);
  173. if (pSA->sa_Flags & FLAGS_SA_PENDING) {
  174. ASSERT(pSA->sa_State == STATE_SA_LARVAL);
  175. IPSEC_DEBUG(ACQUIRE, ("IPSecSAExpired: Removed from pending too: %lx\n", pSA));
  176. IPSecRemoveEntryList(&pSA->sa_PendingLinkage);
  177. pSA->sa_Flags &= ~FLAGS_SA_PENDING;
  178. }
  179. RELEASE_LOCK(&g_ipsec.AcquireInfo.Lock, kIrql1);
  180. //
  181. // Flush all the queued packets
  182. //
  183. IPSecFlushQueuedPackets(pSA, STATUS_TIMEOUT);
  184. //
  185. // remove from inbound sa list
  186. //
  187. AcquireWriteLock(&g_ipsec.SPIListLock, &kIrql1);
  188. IPSecRemoveSPIEntry(pSA);
  189. ReleaseWriteLock(&g_ipsec.SPIListLock, kIrql1);
  190. //
  191. // invalidate the associated cache entry
  192. //
  193. ACQUIRE_LOCK(&pSA->sa_Lock, &kIrql2);
  194. if (pSA->sa_AcquireCtx) {
  195. IPSecInvalidateHandle(pSA->sa_AcquireCtx);
  196. pSA->sa_AcquireCtx = NULL;
  197. }
  198. RELEASE_LOCK(&pSA->sa_Lock, kIrql2);
  199. IPSecInvalidateSACacheEntry(pSA);
  200. if (pSA->sa_Flags & FLAGS_SA_ON_FILTER_LIST) {
  201. pSA->sa_Flags &= ~FLAGS_SA_ON_FILTER_LIST;
  202. IPSecRemoveEntryList(&pSA->sa_FilterLinkage);
  203. }
  204. if (pSA->sa_RekeyOriginalSA) {
  205. ASSERT(pSA->sa_Flags & FLAGS_SA_REKEY);
  206. ASSERT(pSA->sa_RekeyOriginalSA->sa_RekeyLarvalSA == pSA);
  207. ASSERT(pSA->sa_RekeyOriginalSA->sa_Flags & FLAGS_SA_REKEY_ORI);
  208. pSA->sa_RekeyOriginalSA->sa_Flags &= ~FLAGS_SA_REKEY_ORI;
  209. pSA->sa_RekeyOriginalSA->sa_RekeyLarvalSA = NULL;
  210. pSA->sa_RekeyOriginalSA = NULL;
  211. }
  212. if (pOutboundSA = pSA->sa_AssociatedSA) {
  213. IPSEC_DEC_STATISTIC(dwNumActiveAssociations);
  214. IPSEC_DEC_TUNNELS(pOutboundSA);
  215. IPSEC_DECREMENT(g_ipsec.NumOutboundSAs);
  216. IPSecCleanupOutboundSA(pSA, pOutboundSA, FALSE);
  217. }
  218. IPSEC_DEBUG(REF, ("In Deref DeleteLarvalSA\n"));
  219. IPSecStopTimerDerefSA(pSA);
  220. }
  221. VOID
  222. IPSecDeleteLarvalSA(
  223. IN PSA_TABLE_ENTRY pSA
  224. )
  225. /*++
  226. Routine Description:
  227. Delete the LarvalSA.
  228. Called with Outbound Lock held, returns with it.
  229. Arguments:
  230. Return Value:
  231. The final status from the operation.
  232. --*/
  233. {
  234. KIRQL kIrql;
  235. ASSERT((pSA->sa_Flags & FLAGS_SA_OUTBOUND) == 0);
  236. //
  237. // Remove from larval list
  238. //
  239. ACQUIRE_LOCK(&g_ipsec.LarvalListLock, &kIrql);
  240. IPSecRemoveEntryList(&pSA->sa_LarvalLinkage);
  241. IPSEC_DEC_STATISTIC(dwNumPendingKeyOps);
  242. RELEASE_LOCK(&g_ipsec.LarvalListLock, kIrql);
  243. //
  244. // Cleanup the rest of larval SA
  245. //
  246. IPSecCleanupLarvalSA(pSA);
  247. }
  248. VOID
  249. IPSecDeleteInboundSA(
  250. IN PSA_TABLE_ENTRY pInboundSA
  251. )
  252. /*++
  253. Routine Description:
  254. Deletes the corresponding outbound SA, and then deletes itself.
  255. Called with Outbound Lock held, returns with it.
  256. Arguments:
  257. Return Value:
  258. The final status from the operation.
  259. --*/
  260. {
  261. PSA_TABLE_ENTRY pOutboundSA;
  262. PSA_TABLE_ENTRY pSA;
  263. KIRQL kIrql;
  264. PLIST_ENTRY pEntry;
  265. PFILTER pFilter;
  266. ACQUIRE_LOCK(&g_ipsec.AcquireInfo.Lock, &kIrql);
  267. IPSecNotifySAExpiration(pInboundSA, NULL, kIrql, FALSE);
  268. if (pOutboundSA = pInboundSA->sa_AssociatedSA) {
  269. IPSEC_DEC_STATISTIC(dwNumActiveAssociations);
  270. IPSEC_DEC_TUNNELS(pOutboundSA);
  271. IPSEC_DECREMENT(g_ipsec.NumOutboundSAs);
  272. IPSecCleanupOutboundSA(pInboundSA, pOutboundSA, FALSE);
  273. }
  274. IPSEC_DEBUG(ACQUIRE, ("Deleting inbound SA: %lx\n", pInboundSA));
  275. //
  276. // remove from inbound sa list
  277. //
  278. AcquireWriteLock(&g_ipsec.SPIListLock, &kIrql);
  279. IPSecRemoveSPIEntry(pInboundSA);
  280. ReleaseWriteLock(&g_ipsec.SPIListLock, kIrql);
  281. //
  282. // invalidate the associated cache entry
  283. //
  284. IPSecInvalidateSACacheEntry(pInboundSA);
  285. //
  286. // also remove from the filter list
  287. //
  288. if (pInboundSA->sa_Flags & FLAGS_SA_ON_FILTER_LIST) {
  289. pInboundSA->sa_Flags &= ~FLAGS_SA_ON_FILTER_LIST;
  290. IPSecRemoveEntryList(&pInboundSA->sa_FilterLinkage);
  291. }
  292. if (pInboundSA->sa_Flags & FLAGS_SA_HW_PLUMBED) {
  293. IPSecDelHWSAAtDpc(pInboundSA);
  294. }
  295. ASSERT(pInboundSA->sa_AssociatedSA == NULL);
  296. IPSEC_DEBUG(REF, ("In Deref DeleteInboundSA\n"));
  297. IPSecStopTimerDerefSA(pInboundSA);
  298. }
  299. VOID
  300. IPSecExpireInboundSA(
  301. IN PSA_TABLE_ENTRY pInboundSA
  302. )
  303. /*++
  304. Routine Description:
  305. Deletes the corresponding outbound SA, and places itself (inbound) on timer
  306. Queue for later.
  307. NOTE: Called with SADB lock held.
  308. Arguments:
  309. Return Value:
  310. The final status from the operation.
  311. --*/
  312. {
  313. PSA_TABLE_ENTRY pOutboundSA;
  314. KIRQL OldIrq;
  315. KIRQL kIrql;
  316. if (pInboundSA->sa_Flags & FLAGS_SA_HW_PLUMBED) {
  317. IPSecDelHWSAAtDpc(pInboundSA);
  318. }
  319. ACQUIRE_LOCK(&g_ipsec.AcquireInfo.Lock, &OldIrq);
  320. IPSecNotifySAExpiration(pInboundSA, NULL, OldIrq, FALSE);
  321. if (pOutboundSA = pInboundSA->sa_AssociatedSA) {
  322. IPSEC_DEC_STATISTIC(dwNumActiveAssociations);
  323. IPSEC_DEC_TUNNELS(pOutboundSA);
  324. IPSEC_DECREMENT(g_ipsec.NumOutboundSAs);
  325. IPSecCleanupOutboundSA(pInboundSA, pOutboundSA, TRUE);
  326. }
  327. IPSEC_DEBUG(ACQUIRE, ("Queueing inbound SA: %lx\n", pInboundSA));
  328. //
  329. // Place this on the timer Q so it gets cleared when the next interval hits.
  330. //
  331. ACQUIRE_LOCK(&pInboundSA->sa_Lock, &kIrql);
  332. if (pInboundSA->sa_AcquireCtx) {
  333. IPSecInvalidateHandle(pInboundSA->sa_AcquireCtx);
  334. pInboundSA->sa_AcquireCtx = NULL;
  335. }
  336. IPSecStartSATimer( pInboundSA,
  337. IPSecSAExpired,
  338. IPSEC_INBOUND_KEEPALIVE_TIME);
  339. RELEASE_LOCK(&pInboundSA->sa_Lock, kIrql);
  340. }
  341. NTSTATUS
  342. IPSecCheckInboundSA(
  343. IN PSA_STRUCT pSAStruct,
  344. IN PSA_TABLE_ENTRY pSA
  345. )
  346. /*++
  347. Routine Description:
  348. Ensures that the SA being updated is actually the SA we initially
  349. kicked off negotiation for.
  350. Arguments:
  351. pSAInfo - information about the SA
  352. pSA - SA to be populated.
  353. Return Value:
  354. STATUS_PENDING if the buffer is to be held on to, the normal case.
  355. Notes:
  356. --*/
  357. {
  358. LARGE_INTEGER uliSrcDstAddr;
  359. LARGE_INTEGER uliSrcDstMask;
  360. LARGE_INTEGER uliProtoSrcDstPort;
  361. PSECURITY_ASSOCIATION pSAInfo = &pSAStruct->SecAssoc[pSAStruct->NumSAs - 1];
  362. IPSEC_BUILD_SRC_DEST_ADDR( uliSrcDstAddr,
  363. pSAStruct->InstantiatedFilter.SrcAddr,
  364. pSAStruct->InstantiatedFilter.DestAddr);
  365. IPSEC_BUILD_SRC_DEST_MASK( uliSrcDstMask,
  366. pSAStruct->InstantiatedFilter.SrcMask,
  367. pSAStruct->InstantiatedFilter.DestMask);
  368. IPSEC_BUILD_PROTO_PORT_LI( uliProtoSrcDstPort,
  369. pSAStruct->InstantiatedFilter.Protocol,
  370. pSAStruct->InstantiatedFilter.SrcPort,
  371. pSAStruct->InstantiatedFilter.DestPort);
  372. IPSEC_DEBUG(ACQUIRE, ("IPSecCheckInboundSA: S: %lx-%lx, D: %lx-%lx\n",
  373. SRC_ADDR, SRC_MASK, DEST_ADDR, DEST_MASK));
  374. IPSEC_DEBUG(ACQUIRE, ("IPSecCheckInboundSA: SA->S: %lx-%lx, SA->D: %lx-%lx\n",
  375. pSA->SA_SRC_ADDR, pSA->SA_SRC_MASK, pSA->SA_DEST_ADDR, pSA->SA_DEST_MASK));
  376. if ((pSA->sa_TunnelAddr != 0) || (pSA->sa_Flags & FLAGS_SA_TUNNEL)) {
  377. if (((SRC_ADDR & pSA->SA_SRC_MASK) ==
  378. (pSA->SA_SRC_ADDR & pSA->SA_SRC_MASK)) &&
  379. ((DEST_ADDR & pSA->SA_DEST_MASK) ==
  380. (pSA->SA_DEST_ADDR & pSA->SA_DEST_MASK)) &&
  381. (pSA->sa_SPI == pSAInfo->SPI)) {
  382. return STATUS_SUCCESS;
  383. }
  384. } else {
  385. if ((uliSrcDstAddr.QuadPart == pSA->sa_uliSrcDstAddr.QuadPart) &&
  386. (pSA->sa_SPI == pSAInfo->SPI)) {
  387. return STATUS_SUCCESS;
  388. }
  389. }
  390. return STATUS_FAIL_CHECK;
  391. }
  392. BOOLEAN
  393. IPSecIsWeakDESKey(
  394. IN PUCHAR Key
  395. )
  396. /*++
  397. Routine Description:
  398. Checks for weak DES keys
  399. Arguments:
  400. Key - the key to be checked.
  401. Return Value:
  402. TRUE/FALSE
  403. Notes:
  404. --*/
  405. {
  406. ULONG j;
  407. for (j = 0; j < NUM_WEAK_KEYS; j++) {
  408. if (IPSecEqualMemory(Key, weak_keys[j], DES_BLOCKLEN)) {
  409. return TRUE;
  410. }
  411. }
  412. return FALSE;
  413. }
  414. BOOLEAN
  415. IPSecIsWeak3DESKey(
  416. IN PUCHAR Key
  417. )
  418. /*++
  419. Routine Description:
  420. Checks for weak Triple DES keys
  421. Arguments:
  422. Key - the key to be checked.
  423. Return Value:
  424. TRUE/FALSE
  425. Notes:
  426. --*/
  427. {
  428. if (IPSecEqualMemory(Key, Key + DES_BLOCKLEN, DES_BLOCKLEN) ||
  429. IPSecEqualMemory(Key + DES_BLOCKLEN, Key + 2 * DES_BLOCKLEN, DES_BLOCKLEN)) {
  430. return TRUE;
  431. }
  432. return FALSE;
  433. }
  434. NTSTATUS
  435. IPSecPopulateSA(
  436. IN PSA_STRUCT pSAStruct,
  437. IN ULONG KeyLen,
  438. IN PSA_TABLE_ENTRY pSA
  439. )
  440. /*++
  441. Routine Description:
  442. Populates an SA with info passed in the SECURITY_ASSOCIATION block
  443. Arguments:
  444. pSAInfo - information about the SA
  445. KeyLen - the length of the composite key (we do the slicing/dicing here)
  446. pSA - SA to be populated.
  447. Return Value:
  448. STATUS_PENDING if the buffer is to be held on to, the normal case.
  449. Notes:
  450. --*/
  451. {
  452. PSECURITY_ASSOCIATION pSAInfo = &pSAStruct->SecAssoc[0];
  453. ULONG Index;
  454. ULONG len = 0;
  455. IPSEC_BUILD_SRC_DEST_ADDR( pSA->sa_uliSrcDstAddr,
  456. pSAStruct->InstantiatedFilter.SrcAddr,
  457. pSAStruct->InstantiatedFilter.DestAddr);
  458. IPSEC_BUILD_SRC_DEST_MASK( pSA->sa_uliSrcDstMask,
  459. pSAStruct->InstantiatedFilter.SrcMask,
  460. pSAStruct->InstantiatedFilter.DestMask);
  461. IPSEC_BUILD_PROTO_PORT_LI( pSA->sa_uliProtoSrcDstPort,
  462. pSAStruct->InstantiatedFilter.Protocol,
  463. pSAStruct->InstantiatedFilter.SrcPort,
  464. pSAStruct->InstantiatedFilter.DestPort);
  465. if ((pSAStruct->NumSAs < 1) ||
  466. (pSAStruct->NumSAs > MAX_SAS)) {
  467. IPSEC_DEBUG(SAAPI, ("Invalid NumOps count: %d\n", pSAStruct->NumSAs));
  468. return STATUS_INVALID_PARAMETER;
  469. }
  470. //
  471. // If inbound SA, ensure that the last SPI is the one we returned.
  472. //
  473. if (!(pSA->sa_Flags & FLAGS_SA_OUTBOUND)) {
  474. if (pSA->sa_SPI != pSAStruct->SecAssoc[pSAStruct->NumSAs - 1].SPI) {
  475. IPSEC_DEBUG(SAAPI, ("SPI in invalid location: SPI: %lx, in loc: %lx\n",
  476. pSA->sa_SPI,
  477. pSAStruct->SecAssoc[pSAStruct->NumSAs - 1].SPI));
  478. return STATUS_INVALID_PARAMETER;
  479. }
  480. }
  481. if (pSAStruct->Flags & IPSEC_SA_TUNNEL) {
  482. IPSEC_DEBUG(TUNNEL, ("SA %lx tunneled to %lx\n", pSA, pSAStruct->TunnelAddr));
  483. pSA->sa_TunnelAddr = pSAStruct->TunnelAddr;
  484. pSA->sa_Flags |= FLAGS_SA_TUNNEL;
  485. }
  486. if (pSAStruct->Flags & IPSEC_SA_DISABLE_IDLE_OUT) {
  487. pSA->sa_Flags |= FLAGS_SA_DISABLE_IDLE_OUT;
  488. }
  489. if (pSAStruct->Flags & IPSEC_SA_DISABLE_ANTI_REPLAY_CHECK) {
  490. pSA->sa_Flags |= FLAGS_SA_DISABLE_ANTI_REPLAY_CHECK;
  491. }
  492. if (pSAStruct->Flags & IPSEC_SA_DISABLE_LIFETIME_CHECK) {
  493. pSA->sa_Flags |= FLAGS_SA_DISABLE_LIFETIME_CHECK;
  494. }
  495. pSA->sa_NumOps = pSAStruct->NumSAs;
  496. pSA->sa_Lifetime = pSAStruct->Lifetime;
  497. pSA->sa_TruncatedLen = TRUNCATED_HASH_LEN;
  498. pSA->sa_ReplayLen = sizeof(ULONG);
  499. pSA->sa_QMPFSGroup = pSAStruct->dwQMPFSGroup;
  500. RtlCopyMemory( &pSA->sa_CookiePair,
  501. &pSAStruct->CookiePair,
  502. sizeof(IKE_COOKIE_PAIR));
  503. for (Index = 0; Index < pSAStruct->NumSAs; Index++) {
  504. pSAInfo = &pSAStruct->SecAssoc[Index];
  505. pSA->sa_OtherSPIs[Index] = pSAInfo->SPI;
  506. pSA->sa_Operation[Index] = pSAInfo->Operation;
  507. pSA->sa_ReplaySendSeq[Index] = pSA->sa_ReplayStartPoint;
  508. pSA->sa_ReplayLastSeq[Index] = pSA->sa_ReplayStartPoint + 1;
  509. //
  510. // Now parse the Algorithm info..
  511. //
  512. switch (pSA->sa_Operation[Index]) {
  513. case None:
  514. IPSEC_DEBUG(ACQUIRE, ("NULL operation.\n"));
  515. if (pSA->sa_NumOps > 1) {
  516. IPSEC_DEBUG(SAAPI, ("Invalid NumOps count; none specified, but more ops than 1\n"));
  517. return STATUS_INVALID_PARAMETER;
  518. }
  519. break;
  520. case Auth: {
  521. pSA->INT_ALGO(Index) = pSAInfo->EXT_INT_ALGO;
  522. if (pSA->INT_ALGO(Index) >= IPSEC_AH_MAX) {
  523. IPSEC_DEBUG(SAAPI, ("Invalid int algo: %d %d\n", pSA->INT_ALGO(Index), IPSEC_AH_MAX));
  524. return STATUS_INVALID_PARAMETER;
  525. }
  526. pSA->INT_KEYLEN(Index) = pSAInfo->EXT_INT_KEYLEN;
  527. pSA->INT_ROUNDS(Index) = pSAInfo->EXT_INT_ROUNDS;
  528. //
  529. // Make sure the right key len was passed in
  530. //
  531. if (KeyLen > 0 && pSAInfo->EXT_INT_KEYLEN == (KeyLen - len)) {
  532. IPSEC_DEBUG(SAAPI, ("Key len more than reserved, allocing new keys\n"));
  533. if (!(pSA->INT_KEY(Index) = IPSecAllocateKeyBuffer(KeyLen))) {
  534. return STATUS_INSUFFICIENT_RESOURCES;
  535. }
  536. RtlCopyMemory( pSA->INT_KEY(Index),
  537. (UCHAR UNALIGNED *)(pSAStruct->KeyMat + len),
  538. pSAInfo->EXT_INT_KEYLEN);
  539. } else {
  540. //
  541. // bogus - reject
  542. //
  543. IPSEC_DEBUG(SAAPI, ("AH: Key len is bogus - extra bytes: %d, keylen in struct: %d.\n",
  544. KeyLen-len,
  545. pSAInfo->EXT_INT_KEYLEN));
  546. return STATUS_INVALID_PARAMETER;
  547. }
  548. len = pSAInfo->EXT_INT_KEYLEN;
  549. break;
  550. }
  551. case Encrypt: {
  552. pSA->INT_ALGO(Index) = pSAInfo->EXT_INT_ALGO;
  553. if (pSA->INT_ALGO(Index) >= IPSEC_AH_MAX) {
  554. IPSEC_DEBUG(SAAPI, ("Invalid int algo: %d %d\n", pSA->INT_ALGO(Index), IPSEC_AH_MAX));
  555. return STATUS_INVALID_PARAMETER;
  556. }
  557. if (pSA->INT_ALGO(Index) == IPSEC_AH_NONE) {
  558. IPSEC_DEBUG(SAAPI, ("None Auth algo\n"));
  559. //pSA->sa_TruncatedLen = 0;
  560. }
  561. pSA->INT_KEYLEN(Index) = pSAInfo->EXT_INT_KEYLEN;
  562. pSA->INT_ROUNDS(Index) = pSAInfo->EXT_INT_ROUNDS;
  563. pSA->CONF_ALGO(Index) = pSAInfo->EXT_CONF_ALGO;
  564. if (pSA->CONF_ALGO(Index) >= IPSEC_ESP_MAX) {
  565. IPSEC_DEBUG(SAAPI, ("Invalid conf algo: %d %d\n", pSA->CONF_ALGO(Index), IPSEC_ESP_MAX));
  566. return STATUS_INVALID_PARAMETER;
  567. }
  568. if ((pSA->CONF_ALGO(Index) == IPSEC_ESP_DES) ||
  569. (pSA->CONF_ALGO(Index) == IPSEC_ESP_3_DES) ||
  570. (pSA->CONF_ALGO(Index) == IPSEC_ESP_NONE)) {
  571. LARGE_INTEGER Li;
  572. NdisGetCurrentSystemTime(&Li);
  573. pSA->sa_ivlen = DES_BLOCKLEN;
  574. *(UNALIGNED ULONG *)&pSA->sa_iv[Index][0] = Li.LowPart;
  575. *(UNALIGNED ULONG *)&pSA->sa_iv[Index][4] = Li.HighPart;
  576. IPSecGenerateRandom((PUCHAR)&pSA->sa_iv[Index][0], DES_BLOCKLEN);
  577. IPSEC_DEBUG(SAAPI, ("IV: %lx-%lx\n", *(PULONG)&pSA->sa_iv[Index][0], *(PULONG)&pSA->sa_iv[Index][4]));
  578. pSA->CONF_KEYLEN(Index) = pSAInfo->EXT_CONF_KEYLEN;
  579. pSA->CONF_ROUNDS(Index) = pSAInfo->EXT_CONF_ROUNDS;
  580. //
  581. // Make sure the right key len was passed in
  582. //
  583. if ((KeyLen-len == pSAStruct->KeyLen) &&
  584. (pSAInfo->EXT_INT_KEYLEN + pSAInfo->EXT_CONF_KEYLEN <= KeyLen-len)) {
  585. //
  586. // confKeyMatLen is the amount of conf key material that came down.
  587. // this is the reduced (weakened) length for export.
  588. // it is expanded to the real length later.
  589. //
  590. ULONG confKeyMatLen = pSAInfo->EXT_CONF_KEYLEN;
  591. ULONG realConfKeyLen = 0;
  592. realConfKeyLen = confKeyMatLen;
  593. if (pSA->CONF_ALGO(Index) == IPSEC_ESP_DES) {
  594. if (pSAInfo->EXT_CONF_KEYLEN != DES_BLOCKLEN) {
  595. ASSERT(FALSE);
  596. IPSEC_DEBUG(SAAPI, ("Bad DES key length: pSAInfo->EXT_CONF_KEYLEN: %lx, conf: %lx, DES_BLOCKLEN: %lx\n",
  597. pSAInfo->EXT_CONF_KEYLEN, confKeyMatLen, DES_BLOCKLEN));
  598. return STATUS_INVALID_PARAMETER;
  599. }
  600. } else if (pSA->CONF_ALGO(Index) == IPSEC_ESP_3_DES) {
  601. if (pSAInfo->EXT_CONF_KEYLEN != 3 * DES_BLOCKLEN) {
  602. ASSERT(FALSE);
  603. IPSEC_DEBUG(SAAPI, ("Bad 3DES key length\n"));
  604. return STATUS_INVALID_PARAMETER;
  605. }
  606. }
  607. IPSEC_DEBUG(SAAPI, ("Key len more than reserved, allocing new keys\n"));
  608. if (pSAInfo->EXT_INT_KEYLEN > 0 &&
  609. !(pSA->INT_KEY(Index) = IPSecAllocateKeyBuffer(pSAInfo->EXT_INT_KEYLEN))) {
  610. return STATUS_INSUFFICIENT_RESOURCES;
  611. }
  612. if (realConfKeyLen > 0 &&
  613. !(pSA->CONF_KEY(Index) = IPSecAllocateKeyBuffer(realConfKeyLen))) {
  614. if (pSA->INT_KEY(Index)) {
  615. IPSecFreeKeyBuffer(pSA->INT_KEY(Index));
  616. pSA->INT_KEY(Index) = NULL;
  617. }
  618. return STATUS_INSUFFICIENT_RESOURCES;
  619. }
  620. if (pSA->CONF_KEY(Index) && confKeyMatLen) {
  621. RtlCopyMemory( pSA->CONF_KEY(Index),
  622. pSAStruct->KeyMat,
  623. confKeyMatLen);
  624. if (confKeyMatLen < realConfKeyLen) {
  625. if (pSA->INT_KEY(Index)) {
  626. IPSecFreeKeyBuffer(pSA->INT_KEY(Index));
  627. pSA->INT_KEY(Index) = NULL;
  628. }
  629. if (pSA->CONF_KEY(Index)) {
  630. IPSecFreeKeyBuffer(pSA->CONF_KEY(Index));
  631. pSA->CONF_KEY(Index) = NULL;
  632. }
  633. return STATUS_INVALID_PARAMETER;
  634. }
  635. if ((pSA->CONF_ALGO(Index) == IPSEC_ESP_DES &&
  636. IPSecIsWeakDESKey(pSA->CONF_KEY(Index))) ||
  637. (pSA->CONF_ALGO(Index) == IPSEC_ESP_3_DES &&
  638. IPSecIsWeak3DESKey(pSA->CONF_KEY(Index)))) {
  639. PSA_TABLE_ENTRY pLarvalSA;
  640. IPSEC_DEBUG(SAAPI, ("Got a weak key!!: %lx\n", pSA->CONF_KEY(Index)));
  641. //
  642. // if initiator, re-start a new negotiation and throw away this one
  643. //
  644. if (pSA->sa_Flags & FLAGS_SA_INITIATOR) {
  645. IPSecNegotiateSA( pSA->sa_Filter,
  646. pSA->sa_uliSrcDstAddr,
  647. pSA->sa_uliProtoSrcDstPort,
  648. pSA->sa_NewMTU,
  649. &pLarvalSA,
  650. pSA->sa_DestType);
  651. IPSecQueuePacket(pLarvalSA, pSA->sa_BlockedBuffer);
  652. }
  653. return STATUS_INVALID_PARAMETER;
  654. }
  655. } else {
  656. if (pSA->CONF_ALGO(Index) != IPSEC_ESP_NONE) {
  657. IPSEC_DEBUG(SAAPI, ("Algo: %lx with no keymat!!: %lx\n", pSA->CONF_ALGO(Index)));
  658. ASSERT(FALSE);
  659. return STATUS_INVALID_PARAMETER;
  660. }
  661. pSA->sa_ivlen = 0;
  662. }
  663. if (pSAInfo->EXT_INT_KEYLEN > 0) {
  664. RtlCopyMemory( pSA->INT_KEY(Index),
  665. (UCHAR UNALIGNED *)(pSAStruct->KeyMat + pSAInfo->EXT_CONF_KEYLEN),
  666. pSAInfo->EXT_INT_KEYLEN);
  667. }
  668. len = pSAInfo->EXT_CONF_KEYLEN + pSAInfo->EXT_INT_KEYLEN;
  669. } else {
  670. //
  671. // bogus - reject
  672. //
  673. IPSEC_DEBUG(SAAPI, ("ESP: Key len is bogus - extra bytes: %lx, keylen in struct: %lx.\n",
  674. KeyLen-len,
  675. pSAInfo->EXT_INT_KEYLEN + pSAInfo->EXT_CONF_KEYLEN));
  676. return STATUS_INVALID_PARAMETER;
  677. }
  678. }
  679. break;
  680. }
  681. default:
  682. IPSEC_DEBUG(SAAPI, ("IPSecPopulateSA: Bad operation\n"));
  683. break;
  684. }
  685. }
  686. return STATUS_SUCCESS;
  687. }
  688. NTSTATUS
  689. IPSecCreateSA(
  690. OUT PSA_TABLE_ENTRY *ppSA
  691. )
  692. /*++
  693. Routine Description:
  694. Creates a Security Association block.
  695. Arguments:
  696. ppSA - returns the SA pointer
  697. Return Value:
  698. STATUS_PENDING if the buffer is to be held on to, the normal case.
  699. Notes:
  700. --*/
  701. {
  702. PSA_TABLE_ENTRY pSA;
  703. IPSEC_DEBUG(SAAPI, ("Entering IPSecCreateSA\n"));
  704. pSA = IPSecAllocateMemory(sizeof(SA_TABLE_ENTRY), IPSEC_TAG_SA);
  705. if (!pSA) {
  706. return STATUS_INSUFFICIENT_RESOURCES;
  707. }
  708. IPSecZeroMemory(pSA, sizeof(SA_TABLE_ENTRY));
  709. pSA->sa_Signature = IPSEC_SA_SIGNATURE;
  710. pSA->sa_NewMTU = MAX_LONG;
  711. #if DBG
  712. pSA->sa_d1 = IPSEC_SA_D_1;
  713. pSA->sa_d2 = IPSEC_SA_D_2;
  714. pSA->sa_d3 = IPSEC_SA_D_3;
  715. pSA->sa_d4 = IPSEC_SA_D_4;
  716. #endif
  717. INIT_LOCK(&pSA->sa_Lock);
  718. InitializeListHead(&pSA->sa_SPILinkage);
  719. InitializeListHead(&pSA->sa_FilterLinkage);
  720. InitializeListHead(&pSA->sa_LarvalLinkage);
  721. InitializeListHead(&pSA->sa_PendingLinkage);
  722. pSA->sa_Reference = 1;
  723. pSA->sa_State = STATE_SA_CREATED;
  724. pSA->sa_ExpiryTime = IPSEC_SA_EXPIRY_TIME;
  725. *ppSA = pSA;
  726. return STATUS_SUCCESS;
  727. }
  728. PSA_TABLE_ENTRY
  729. IPSecLookupSABySPI(
  730. IN tSPI SPI,
  731. IN IPAddr DestAddr
  732. )
  733. /*++
  734. Routine Description:
  735. Looks up the SA given the SPI and Filter variables.
  736. Arguments:
  737. Return Value:
  738. Notes:
  739. --*/
  740. {
  741. KIRQL kIrql;
  742. PSA_TABLE_ENTRY pSA;
  743. AcquireReadLock(&g_ipsec.SPIListLock, &kIrql);
  744. pSA = IPSecLookupSABySPIWithLock(SPI, DestAddr);
  745. ReleaseReadLock(&g_ipsec.SPIListLock, kIrql);
  746. return pSA;
  747. }
  748. PSA_TABLE_ENTRY
  749. IPSecLookupSABySPIWithLock(
  750. IN tSPI SPI,
  751. IN IPAddr DestAddr
  752. )
  753. /*++
  754. Routine Description:
  755. Looks up the SA given the SPI and Filter variables.
  756. NOTE: Always call with the SPIListLock held.
  757. Arguments:
  758. Return Value:
  759. Notes:
  760. --*/
  761. {
  762. PSA_HASH pHash;
  763. PLIST_ENTRY pEntry;
  764. PSA_TABLE_ENTRY pSA;
  765. //
  766. // get to hash bucket
  767. //
  768. IPSEC_HASH_SPI(DestAddr, SPI, pHash);
  769. //
  770. // search for specific entry in collision chain
  771. //
  772. for ( pEntry = pHash->SAList.Flink;
  773. pEntry != &pHash->SAList;
  774. pEntry = pEntry->Flink) {
  775. pSA = CONTAINING_RECORD(pEntry,
  776. SA_TABLE_ENTRY,
  777. sa_SPILinkage);
  778. if (pSA->sa_TunnelAddr) {
  779. if ((DestAddr == pSA->sa_TunnelAddr) &&
  780. (pSA->sa_SPI == SPI)) {
  781. IPSEC_DEBUG(HASH, ("Matched Tunnel entry: %lx\n", pSA));
  782. return pSA;
  783. }
  784. } else {
  785. if ((DestAddr == pSA->SA_DEST_ADDR) &&
  786. (pSA->sa_SPI == SPI)) {
  787. IPSEC_DEBUG(HASH, ("Matched entry: %lx\n", pSA));
  788. return pSA;
  789. }
  790. }
  791. }
  792. //
  793. // no entry found
  794. //
  795. return NULL;
  796. }
  797. NTSTATUS
  798. IPSecLookupSAByAddr(
  799. IN ULARGE_INTEGER uliSrcDstAddr,
  800. IN ULARGE_INTEGER uliProtoSrcDstPort,
  801. OUT PFILTER *ppFilter,
  802. OUT PSA_TABLE_ENTRY *ppSA,
  803. OUT PSA_TABLE_ENTRY *ppNextSA,
  804. OUT PSA_TABLE_ENTRY *ppTunnelSA,
  805. IN BOOLEAN fOutbound,
  806. IN BOOLEAN fFWPacket,
  807. IN BOOLEAN fBypass
  808. )
  809. /*++
  810. Routine Description:
  811. Looks up the SA given the relevant addresses.
  812. Arguments:
  813. uliSrcDstAddr - src/dest IP addr
  814. uliProtoSrcDstPort - protocol, src/dest port
  815. ppFilter - filter found
  816. ppSA - SA found
  817. ppTunnelSA - tunnel SA found
  818. fOutbound - direction flag
  819. Return Value:
  820. STATUS_SUCCESS - both filter and SA found
  821. STATUS_UNSUCCESSFUL - none found
  822. STATUS_PENDING - filter found, but no SA
  823. Notes:
  824. Called with SADBLock held.
  825. --*/
  826. {
  827. PFILTER pFilter;
  828. PLIST_ENTRY pEntry;
  829. PLIST_ENTRY pFilterList;
  830. PLIST_ENTRY pSAChain;
  831. PSA_TABLE_ENTRY pSA;
  832. REGISTER ULARGE_INTEGER uliPort;
  833. REGISTER ULARGE_INTEGER uliAddr;
  834. BOOLEAN fFound = FALSE;
  835. *ppSA = NULL;
  836. *ppFilter = NULL;
  837. *ppTunnelSA = NULL;
  838. //
  839. // Search in Tunnel filters list
  840. //
  841. pFilterList = IPSecResolveFilterList(TRUE, fOutbound);
  842. for ( pEntry = pFilterList->Flink;
  843. pEntry != pFilterList;
  844. pEntry = pEntry->Flink) {
  845. pFilter = CONTAINING_RECORD(pEntry,
  846. FILTER,
  847. MaskedLinkage);
  848. if (fBypass && IS_EXEMPT_FILTER(pFilter)) {
  849. //
  850. // Don't search block/pass-thru filters for host bypass traffic
  851. //
  852. continue;
  853. }
  854. uliAddr.QuadPart = uliSrcDstAddr.QuadPart & pFilter->uliSrcDstMask.QuadPart;
  855. uliPort.QuadPart = uliProtoSrcDstPort.QuadPart & pFilter->uliProtoSrcDstMask.QuadPart;
  856. if ((uliAddr.QuadPart == pFilter->uliSrcDstAddr.QuadPart) &&
  857. (uliPort.QuadPart == pFilter->uliProtoSrcDstPort.QuadPart)) {
  858. IPSEC_DEBUG(HASH, ("Matched entry: %lx\n", pFilter));
  859. fFound = TRUE;
  860. break;
  861. }
  862. }
  863. if (fFound) {
  864. fFound = FALSE;
  865. //
  866. // Search for the particular SA now.
  867. //
  868. pSAChain = IPSecResolveSAChain(pFilter, fOutbound? DEST_ADDR: SRC_ADDR);
  869. for ( pEntry = pSAChain->Flink;
  870. pEntry != pSAChain;
  871. pEntry = pEntry->Flink) {
  872. pSA = CONTAINING_RECORD(pEntry,
  873. SA_TABLE_ENTRY,
  874. sa_FilterLinkage);
  875. ASSERT(pSA->sa_Flags & FLAGS_SA_TUNNEL);
  876. if (pFilter->TunnelAddr != 0) {
  877. //
  878. // match the outbound flag also
  879. //
  880. IPSEC_DEBUG(HASH, ("Matched specific tunnel entry: %lx\n", pSA));
  881. ASSERT(fOutbound == (BOOLEAN)((pSA->sa_Flags & FLAGS_SA_OUTBOUND) != 0));
  882. fFound = TRUE;
  883. *ppTunnelSA = pSA;
  884. break;
  885. }
  886. }
  887. if (fFound) {
  888. fFound = FALSE;
  889. *ppFilter = pFilter;
  890. } else {
  891. //
  892. // Found a filter entry, but need to negotiate keys
  893. //
  894. *ppFilter = pFilter;
  895. return STATUS_PENDING;
  896. }
  897. }
  898. //
  899. // Search in Masked filters list
  900. //
  901. pFilterList = IPSecResolveFilterList(FALSE, fOutbound);
  902. for ( pEntry = pFilterList->Flink;
  903. pEntry != pFilterList;
  904. pEntry = pEntry->Flink) {
  905. pFilter = CONTAINING_RECORD(pEntry,
  906. FILTER,
  907. MaskedLinkage);
  908. if (fFWPacket && !IS_EXEMPT_FILTER(pFilter)) {
  909. //
  910. // Search only block/pass-thru filters in forward path
  911. //
  912. continue;
  913. }
  914. if (fBypass && IS_EXEMPT_FILTER(pFilter)) {
  915. //
  916. // Don't search block/pass-thru filters for host bypass traffic
  917. //
  918. continue;
  919. }
  920. uliAddr.QuadPart = uliSrcDstAddr.QuadPart & pFilter->uliSrcDstMask.QuadPart;
  921. uliPort.QuadPart = uliProtoSrcDstPort.QuadPart & pFilter->uliProtoSrcDstMask.QuadPart;
  922. if ((uliAddr.QuadPart == pFilter->uliSrcDstAddr.QuadPart) &&
  923. (uliPort.QuadPart == pFilter->uliProtoSrcDstPort.QuadPart)) {
  924. IPSEC_DEBUG(HASH, ("Matched entry: %lx\n", pFilter));
  925. fFound = TRUE;
  926. break;
  927. }
  928. }
  929. if (fFound) {
  930. //
  931. // Search for the particular SA now.
  932. //
  933. fFound=FALSE;
  934. pSAChain = IPSecResolveSAChain(pFilter, fOutbound? DEST_ADDR: SRC_ADDR);
  935. for ( pEntry = pSAChain->Flink;
  936. pEntry != pSAChain;
  937. pEntry = pEntry->Flink) {
  938. pSA = CONTAINING_RECORD(pEntry,
  939. SA_TABLE_ENTRY,
  940. sa_FilterLinkage);
  941. if (IS_CLASSD(NET_LONG(pSA->SA_SRC_ADDR))
  942. || IS_CLASSD(NET_LONG(pSA->SA_DEST_ADDR))) {
  943. uliAddr.QuadPart = uliSrcDstAddr.QuadPart & pSA->sa_uliSrcDstMask.QuadPart;
  944. IPSEC_DEBUG(HASH, ("MCAST: %d %d %d %d", uliAddr.LowPart, uliAddr.HighPart,
  945. pSA->sa_uliSrcDstAddr.LowPart,pSA->sa_uliSrcDstAddr.HighPart));
  946. if (uliAddr.QuadPart == pSA->sa_uliSrcDstAddr.QuadPart) {
  947. fFound=TRUE;
  948. }
  949. } else if (uliSrcDstAddr.QuadPart == pSA->sa_uliSrcDstAddr.QuadPart) {
  950. fFound=TRUE;
  951. }
  952. if (fFound) {
  953. IPSEC_DEBUG(HASH, ("Matched entry: %lx\n", pSA));
  954. ASSERT(fOutbound == (BOOLEAN)((pSA->sa_Flags & FLAGS_SA_OUTBOUND) != 0));
  955. //
  956. // if there is also a tunnel SA, associate it here.
  957. //
  958. if (*ppTunnelSA && fOutbound) {
  959. *ppNextSA = *ppTunnelSA;
  960. IPSEC_DEBUG(SAAPI, ("linked next sa: %lx, next: %lx", pSA, *ppTunnelSA));
  961. *ppTunnelSA = NULL;
  962. }
  963. *ppFilter = pFilter;
  964. *ppSA = pSA;
  965. return STATUS_SUCCESS;
  966. }
  967. }
  968. //
  969. // Found a filter entry, but need to negotiate keys
  970. //
  971. // Also, ppTunnelSA is set to the proper tunnel SA we need
  972. // to hook to this end-2-end SA once it is negotiated.
  973. //
  974. *ppFilter = pFilter;
  975. return STATUS_PENDING;
  976. } else {
  977. //
  978. // if only tunnel SA found, return that as the SA
  979. // found.
  980. //
  981. if (*ppTunnelSA) {
  982. *ppSA = *ppTunnelSA;
  983. *ppTunnelSA = NULL;
  984. return STATUS_SUCCESS;
  985. }
  986. }
  987. //
  988. // no entry found
  989. //
  990. return STATUS_NOT_FOUND;
  991. }
  992. NTSTATUS
  993. IPSecLookupTunnelSA(
  994. IN ULARGE_INTEGER uliSrcDstAddr,
  995. IN ULARGE_INTEGER uliProtoSrcDstPort,
  996. OUT PFILTER *ppFilter,
  997. OUT PSA_TABLE_ENTRY *ppSA,
  998. IN BOOLEAN fOutbound
  999. )
  1000. /*++
  1001. Routine Description:
  1002. Looks up the SA given the relevant addresses.
  1003. Arguments:
  1004. uliSrcDstAddr - src/dest IP addr
  1005. uliProtoSrcDstPort - protocol, src/dest port
  1006. ppFilter - filter found
  1007. ppSA - SA found
  1008. fOutbound - direction flag
  1009. Return Value:
  1010. STATUS_SUCCESS - both filter and SA found
  1011. STATUS_UNSUCCESSFUL - none found
  1012. STATUS_PENDING - filter found, but no SA
  1013. Notes:
  1014. Called with SADBLock held.
  1015. --*/
  1016. {
  1017. PFILTER pFilter;
  1018. PLIST_ENTRY pEntry;
  1019. PLIST_ENTRY pFilterList;
  1020. PLIST_ENTRY pSAChain;
  1021. PSA_TABLE_ENTRY pSA;
  1022. REGISTER ULARGE_INTEGER uliPort;
  1023. REGISTER ULARGE_INTEGER uliAddr;
  1024. BOOLEAN fFound = FALSE;
  1025. *ppSA = NULL;
  1026. *ppFilter = NULL;
  1027. //
  1028. // Search in Tunnel filters list
  1029. //
  1030. pFilterList = IPSecResolveFilterList(TRUE, fOutbound);
  1031. for ( pEntry = pFilterList->Flink;
  1032. pEntry != pFilterList;
  1033. pEntry = pEntry->Flink) {
  1034. pFilter = CONTAINING_RECORD(pEntry,
  1035. FILTER,
  1036. MaskedLinkage);
  1037. uliAddr.QuadPart = uliSrcDstAddr.QuadPart & pFilter->uliSrcDstMask.QuadPart;
  1038. uliPort.QuadPart = uliProtoSrcDstPort.QuadPart & pFilter->uliProtoSrcDstMask.QuadPart;
  1039. if ((uliAddr.QuadPart == pFilter->uliSrcDstAddr.QuadPart) &&
  1040. (uliPort.QuadPart == pFilter->uliProtoSrcDstPort.QuadPart)) {
  1041. IPSEC_DEBUG(HASH, ("Matched entry: %lx\n", pFilter));
  1042. fFound = TRUE;
  1043. break;
  1044. }
  1045. }
  1046. if (fFound) {
  1047. //
  1048. // Search for the particular SA now.
  1049. //
  1050. pSAChain = IPSecResolveSAChain(pFilter, fOutbound? DEST_ADDR: SRC_ADDR);
  1051. for ( pEntry = pSAChain->Flink;
  1052. pEntry != pSAChain;
  1053. pEntry = pEntry->Flink) {
  1054. pSA = CONTAINING_RECORD(pEntry,
  1055. SA_TABLE_ENTRY,
  1056. sa_FilterLinkage);
  1057. ASSERT(pSA->sa_Flags & FLAGS_SA_TUNNEL);
  1058. if (pFilter->TunnelAddr != 0) {
  1059. //
  1060. // match the outbound flag also
  1061. //
  1062. IPSEC_DEBUG(HASH, ("Matched specific tunnel entry: %lx\n", pSA));
  1063. ASSERT(fOutbound == (BOOLEAN)((pSA->sa_Flags & FLAGS_SA_OUTBOUND) != 0));
  1064. *ppFilter = pFilter;
  1065. *ppSA = pSA;
  1066. return STATUS_SUCCESS;
  1067. }
  1068. }
  1069. //
  1070. // Found a filter entry, but need to negotiate keys
  1071. //
  1072. *ppFilter = pFilter;
  1073. return STATUS_PENDING;
  1074. }
  1075. //
  1076. // no entry found
  1077. //
  1078. return STATUS_NOT_FOUND;
  1079. }
  1080. NTSTATUS
  1081. IPSecLookupMaskedSA(
  1082. IN ULARGE_INTEGER uliSrcDstAddr,
  1083. IN ULARGE_INTEGER uliProtoSrcDstPort,
  1084. OUT PFILTER *ppFilter,
  1085. OUT PSA_TABLE_ENTRY *ppSA,
  1086. IN BOOLEAN fOutbound
  1087. )
  1088. /*++
  1089. Routine Description:
  1090. Looks up the SA given the relevant addresses.
  1091. Arguments:
  1092. uliSrcDstAddr - src/dest IP addr
  1093. uliProtoSrcDstPort - protocol, src/dest port
  1094. ppFilter - filter found
  1095. ppSA - SA found
  1096. fOutbound - direction flag
  1097. Return Value:
  1098. STATUS_SUCCESS - both filter and SA found
  1099. STATUS_UNSUCCESSFUL - none found
  1100. STATUS_PENDING - filter found, but no SA
  1101. Notes:
  1102. Called with SADBLock held.
  1103. --*/
  1104. {
  1105. PFILTER pFilter;
  1106. PLIST_ENTRY pEntry;
  1107. PLIST_ENTRY pFilterList;
  1108. PLIST_ENTRY pSAChain;
  1109. PSA_TABLE_ENTRY pSA;
  1110. REGISTER ULARGE_INTEGER uliPort;
  1111. REGISTER ULARGE_INTEGER uliAddr;
  1112. BOOLEAN fFound = FALSE;
  1113. *ppSA = NULL;
  1114. *ppFilter = NULL;
  1115. //
  1116. // Search in Masked filters list
  1117. //
  1118. pFilterList = IPSecResolveFilterList(FALSE, fOutbound);
  1119. for ( pEntry = pFilterList->Flink;
  1120. pEntry != pFilterList;
  1121. pEntry = pEntry->Flink) {
  1122. pFilter = CONTAINING_RECORD(pEntry,
  1123. FILTER,
  1124. MaskedLinkage);
  1125. uliAddr.QuadPart = uliSrcDstAddr.QuadPart & pFilter->uliSrcDstMask.QuadPart;
  1126. uliPort.QuadPart = uliProtoSrcDstPort.QuadPart & pFilter->uliProtoSrcDstMask.QuadPart;
  1127. if ((uliAddr.QuadPart == pFilter->uliSrcDstAddr.QuadPart) &&
  1128. (uliPort.QuadPart == pFilter->uliProtoSrcDstPort.QuadPart)) {
  1129. IPSEC_DEBUG(HASH, ("Matched entry: %lx\n", pFilter));
  1130. fFound = TRUE;
  1131. break;
  1132. }
  1133. }
  1134. if (fFound) {
  1135. //
  1136. // Search for the particular SA now.
  1137. //
  1138. pSAChain = IPSecResolveSAChain(pFilter, fOutbound? DEST_ADDR: SRC_ADDR);
  1139. for ( pEntry = pSAChain->Flink;
  1140. pEntry != pSAChain;
  1141. pEntry = pEntry->Flink) {
  1142. pSA = CONTAINING_RECORD(pEntry,
  1143. SA_TABLE_ENTRY,
  1144. sa_FilterLinkage);
  1145. if (uliSrcDstAddr.QuadPart == pSA->sa_uliSrcDstAddr.QuadPart) {
  1146. IPSEC_DEBUG(HASH, ("Matched entry: %lx\n", pSA));
  1147. ASSERT(fOutbound == (BOOLEAN)((pSA->sa_Flags & FLAGS_SA_OUTBOUND) != 0));
  1148. *ppFilter = pFilter;
  1149. *ppSA = pSA;
  1150. return STATUS_SUCCESS;
  1151. }
  1152. }
  1153. //
  1154. // Found a filter entry, but need to negotiate keys
  1155. //
  1156. *ppFilter = pFilter;
  1157. return STATUS_PENDING;
  1158. }
  1159. //
  1160. // no entry found
  1161. //
  1162. return STATUS_NOT_FOUND;
  1163. }
  1164. NTSTATUS
  1165. IPSecAllocateSPI(
  1166. OUT tSPI * pSpi,
  1167. IN PSA_TABLE_ENTRY pSA
  1168. )
  1169. /*++
  1170. Routine Description:
  1171. Allocates an SPI for an incoming SA - guards against collisions
  1172. Arguments:
  1173. pSpi - the SPI allocated is filled in here
  1174. pSA - SA for which SPI is needed
  1175. Return Value:
  1176. Notes:
  1177. --*/
  1178. {
  1179. ULONG rand;
  1180. ULONG numRetries = 0;
  1181. IPAddr DestAddr;
  1182. if (pSA->sa_TunnelAddr) {
  1183. DestAddr = pSA->sa_TunnelAddr;
  1184. } else {
  1185. DestAddr = pSA->SA_DEST_ADDR;
  1186. }
  1187. //
  1188. // if SPI passed in, use that spi else allocate one.
  1189. //
  1190. if (*pSpi) {
  1191. if (IPSecLookupSABySPIWithLock(
  1192. *pSpi,
  1193. DestAddr)) {
  1194. return STATUS_UNSUCCESSFUL;
  1195. } else {
  1196. return STATUS_SUCCESS;
  1197. }
  1198. } else {
  1199. rand = (ULONG)(ULONG_PTR)pSA;
  1200. IPSecGenerateRandom((PUCHAR)&rand, sizeof(ULONG));
  1201. rand = LOWER_BOUND_SPI + rand % (UPPER_BOUND_SPI - LOWER_BOUND_SPI);
  1202. while (numRetries++ < MAX_SPI_RETRIES) {
  1203. if (!IPSecLookupSABySPIWithLock(
  1204. (tSPI)rand,
  1205. DestAddr)) {
  1206. *pSpi = (tSPI)rand;
  1207. return STATUS_SUCCESS;
  1208. }
  1209. rand++;
  1210. //
  1211. // Collision, retry
  1212. //
  1213. IPSEC_DEBUG(ACQUIRE, ("IPSecAllocateSPI: collision for: %lx\n", rand));
  1214. }
  1215. }
  1216. return STATUS_UNSUCCESSFUL;
  1217. }
  1218. NTSTATUS
  1219. IPSecNegotiateSA(
  1220. IN PFILTER pFilter,
  1221. IN ULARGE_INTEGER uliSrcDstAddr,
  1222. IN ULARGE_INTEGER uliProtoSrcDstPort,
  1223. IN ULONG NewMTU,
  1224. OUT PSA_TABLE_ENTRY *ppSA,
  1225. IN UCHAR DestType
  1226. )
  1227. /*++
  1228. Routine Description:
  1229. Allocates a Larval Inbound SA block then kicks off key manager to negotiate
  1230. the algorithms/keys.
  1231. Called with SADB lock held, returns with it.
  1232. Arguments:
  1233. pFilter - the filter and policy that matched this packet.
  1234. ppSA - returns the SA created here.
  1235. Return Value:
  1236. STATUS_PENDING if the buffer is to be held on to, the normal case.
  1237. Notes:
  1238. --*/
  1239. {
  1240. KIRQL kIrql;
  1241. KIRQL OldIrq;
  1242. NTSTATUS status;
  1243. PSA_TABLE_ENTRY pSA;
  1244. //
  1245. // Make sure we dont already have this SA under negotiation
  1246. // walk the LarvalSA list to see if we can find another SA.
  1247. //
  1248. pSA = IPSecLookupSAInLarval(uliSrcDstAddr, uliProtoSrcDstPort);
  1249. if (pSA != NULL) {
  1250. IPSEC_DEBUG(PATTERN, ("Found in Larval: %lx\n", pSA));
  1251. *ppSA = pSA;
  1252. return STATUS_DUPLICATE_OBJECTID;
  1253. }
  1254. IPSEC_DEBUG(ACQUIRE, ("IPSecNegotiateSA: SA: %lx, DA: %lx, P: %lx, SP: %lx, DP: %lx\n", SRC_ADDR, DEST_ADDR, PROTO, SRC_PORT, DEST_PORT));
  1255. //
  1256. // Initiator
  1257. //
  1258. status = IPSecInitiatorCreateLarvalSA(
  1259. pFilter,
  1260. uliSrcDstAddr,
  1261. ppSA,
  1262. DestType
  1263. );
  1264. if (!NT_SUCCESS(status)) {
  1265. IPSEC_DEBUG(SAAPI, ("IPSecNegotiateSA: IPSecCreateSA failed: %lx\n", status));
  1266. return status;
  1267. }
  1268. //
  1269. // Save the NewMTU value if this SA has been PMTU'd.
  1270. //
  1271. (*ppSA)->sa_NewMTU = NewMTU;
  1272. //
  1273. // If this is a tunnel filter to be negotiated, save off the tunnel addr in the
  1274. // SA.
  1275. //
  1276. if (pFilter->TunnelFilter) {
  1277. IPSEC_DEBUG(TUNNEL, ("Negotiating tunnel SA: %lx\n", (*ppSA)));
  1278. // (*ppSA)->sa_TunnelAddr = pFilter->TunnelAddr;
  1279. }
  1280. //
  1281. // Now send this up to the Key Manager to negotiate the keys
  1282. //
  1283. ACQUIRE_LOCK(&g_ipsec.AcquireInfo.Lock, &OldIrq);
  1284. status = IPSecSubmitAcquire(*ppSA, OldIrq, FALSE);
  1285. if (!NT_SUCCESS(status)) {
  1286. IPSEC_DEBUG(SAAPI, ("IPSecNegotiateSA: IPSecSubmitAcquire failed: %lx\n", status));
  1287. ACQUIRE_LOCK(&g_ipsec.LarvalListLock, &kIrql);
  1288. IPSecRemoveEntryList(&(*ppSA)->sa_LarvalLinkage);
  1289. IPSEC_DEC_STATISTIC(dwNumPendingKeyOps);
  1290. RELEASE_LOCK(&g_ipsec.LarvalListLock, kIrql);
  1291. AcquireWriteLock(&g_ipsec.SPIListLock, &kIrql);
  1292. IPSecRemoveSPIEntry(*ppSA);
  1293. ReleaseWriteLock(&g_ipsec.SPIListLock, kIrql);
  1294. //
  1295. // also remove from the filter list
  1296. //
  1297. if ((*ppSA)->sa_Flags & FLAGS_SA_ON_FILTER_LIST) {
  1298. (*ppSA)->sa_Flags &= ~FLAGS_SA_ON_FILTER_LIST;
  1299. IPSecRemoveEntryList(&(*ppSA)->sa_FilterLinkage);
  1300. (*ppSA)->sa_Filter = NULL;
  1301. }
  1302. if ((*ppSA)->sa_RekeyOriginalSA) {
  1303. ASSERT((*ppSA)->sa_Flags & FLAGS_SA_REKEY);
  1304. ASSERT((*ppSA)->sa_RekeyOriginalSA->sa_RekeyLarvalSA == (*ppSA));
  1305. ASSERT((*ppSA)->sa_RekeyOriginalSA->sa_Flags & FLAGS_SA_REKEY_ORI);
  1306. (*ppSA)->sa_RekeyOriginalSA->sa_Flags &= ~FLAGS_SA_REKEY_ORI;
  1307. (*ppSA)->sa_RekeyOriginalSA->sa_RekeyLarvalSA = NULL;
  1308. (*ppSA)->sa_RekeyOriginalSA = NULL;
  1309. }
  1310. (*ppSA)->sa_Flags &= ~FLAGS_SA_TIMER_STARTED;
  1311. IPSecStopTimer(&(*ppSA)->sa_Timer);
  1312. IPSecDerefSA(*ppSA);
  1313. return status;
  1314. }
  1315. return status;
  1316. }
  1317. VOID
  1318. IPSecFlushQueuedPackets(
  1319. IN PSA_TABLE_ENTRY pSA,
  1320. IN NTSTATUS status
  1321. )
  1322. /*++
  1323. Routine Description:
  1324. Flushes queued packets now that the keys are known
  1325. Arguments:
  1326. Return Value:
  1327. Notes:
  1328. --*/
  1329. {
  1330. PIPSEC_SEND_COMPLETE_CONTEXT pContext;
  1331. IPOptInfo optInfo;
  1332. ULONG len;
  1333. PNDIS_BUFFER pHdrMdl;
  1334. ULONG dataLen;
  1335. IPHeader UNALIGNED * pIPH;
  1336. KIRQL kIrql;
  1337. //
  1338. // We need to acquire a lock here because this routine can be called in
  1339. // parallel with one in SA delete and the other in SA update (normal).
  1340. //
  1341. ACQUIRE_LOCK(&pSA->sa_Lock, &kIrql);
  1342. pHdrMdl = pSA->sa_BlockedBuffer;
  1343. dataLen = pSA->sa_BlockedDataLen;
  1344. pSA->sa_BlockedBuffer = NULL;
  1345. pSA->sa_BlockedDataLen = 0;
  1346. RELEASE_LOCK(&pSA->sa_Lock, kIrql);
  1347. if (!pHdrMdl) {
  1348. IPSEC_DEBUG(ACQUIRE, ("FlushQueuedPackets: pHdrMdl == NULL\n"));
  1349. return;
  1350. }
  1351. if (status == STATUS_SUCCESS) {
  1352. ASSERT(pSA->sa_State == STATE_SA_ACTIVE);
  1353. ASSERT((pSA->sa_Flags & FLAGS_SA_OUTBOUND) == 0);
  1354. ASSERT(pHdrMdl);
  1355. pContext = IPSecAllocateSendCompleteCtx(IPSEC_TAG_ESP);
  1356. if (!pContext) {
  1357. PNDIS_BUFFER pNextMdl;
  1358. PNDIS_BUFFER pMdl = pHdrMdl;
  1359. NTSTATUS status;
  1360. IPSEC_DEBUG(ESP, ("Failed to alloc. SendCtx\n"));
  1361. ASSERT(pMdl);
  1362. while (pMdl) {
  1363. pNextMdl = NDIS_BUFFER_LINKAGE(pMdl);
  1364. IPSecFreeBuffer(&status, pMdl);
  1365. pMdl = pNextMdl;
  1366. }
  1367. return;
  1368. }
  1369. IPSEC_INCREMENT(g_ipsec.NumSends);
  1370. IPSecZeroMemory(pContext, sizeof(IPSEC_SEND_COMPLETE_CONTEXT));
  1371. #if DBG
  1372. RtlCopyMemory(pContext->Signature, "ISC6", 4);
  1373. #endif
  1374. pContext->FlushMdl = pHdrMdl;
  1375. pContext->Flags |= SCF_FLUSH;
  1376. IPSecQueryNdisBuf(pHdrMdl, (PVOID)&pIPH, &len);
  1377. //
  1378. // Call IPTransmit with proper Protocol type so it takes this packet
  1379. // at *face* value.
  1380. //
  1381. optInfo = g_ipsec.OptInfo;
  1382. optInfo.ioi_flags |= IP_FLAG_IPSEC;
  1383. status = TCPIP_IP_TRANSMIT( &g_ipsec.IPProtInfo,
  1384. pContext,
  1385. pHdrMdl,
  1386. dataLen,
  1387. pIPH->iph_dest,
  1388. pIPH->iph_src,
  1389. &optInfo,
  1390. NULL,
  1391. pIPH->iph_protocol,
  1392. NULL);
  1393. //
  1394. // Even in the synchronous case, we free the MDL chain in ProtocolSendComplete
  1395. // (called by IPSecSendComplete). So, we dont call anything here.
  1396. // See IPSecReinjectPacket.
  1397. //
  1398. } else {
  1399. PNDIS_BUFFER pNextMdl;
  1400. PNDIS_BUFFER pMdl = pHdrMdl;
  1401. NTSTATUS status;
  1402. ASSERT(pMdl);
  1403. while (pMdl) {
  1404. pNextMdl = NDIS_BUFFER_LINKAGE(pMdl);
  1405. IPSecFreeBuffer(&status, pMdl);
  1406. pMdl = pNextMdl;
  1407. }
  1408. }
  1409. return;
  1410. }
  1411. NTSTATUS
  1412. IPSecInsertOutboundSA(
  1413. IN PSA_TABLE_ENTRY pSA,
  1414. IN PIPSEC_ACQUIRE_CONTEXT pAcquireCtx,
  1415. IN BOOLEAN fTunnelFilter
  1416. )
  1417. /*++
  1418. Routine Description:
  1419. Adds an SA into the database, typically called to add outbound SAs as a
  1420. result of successful negotiation of keys corresponding to the inbound SA
  1421. specified in the context that comes down.
  1422. NOTE: Called with SADB lock held.
  1423. Arguments:
  1424. pSA - SA to be inserted
  1425. pAcquireContext - The Acquire context
  1426. Return Value:
  1427. Notes:
  1428. --*/
  1429. {
  1430. PSA_TABLE_ENTRY pInboundSA = pAcquireCtx->pSA;
  1431. PSA_TABLE_ENTRY pAssociatedSA;
  1432. KIRQL kIrql;
  1433. KIRQL kIrql1;
  1434. NTSTATUS status;
  1435. PFILTER pFilter;
  1436. PSA_TABLE_ENTRY pOutboundSA = NULL;
  1437. PSA_TABLE_ENTRY pTunnelSA = NULL;
  1438. PLIST_ENTRY pSAChain;
  1439. ASSERT(pSA->sa_Flags & FLAGS_SA_OUTBOUND);
  1440. ASSERT((pInboundSA->sa_Flags & FLAGS_SA_OUTBOUND) == 0);
  1441. ASSERT(pInboundSA->sa_State == STATE_SA_LARVAL);
  1442. //
  1443. // Potential dangling pointer, always go through the lookup path.
  1444. //
  1445. if (fTunnelFilter) {
  1446. status = IPSecLookupTunnelSA( pSA->sa_uliSrcDstAddr,
  1447. pSA->sa_uliProtoSrcDstPort,
  1448. &pFilter,
  1449. &pOutboundSA,
  1450. TRUE);
  1451. } else {
  1452. #if GPC
  1453. if (IS_GPC_ACTIVE()) {
  1454. status = IPSecLookupGpcMaskedSA(pSA->sa_uliSrcDstAddr,
  1455. pSA->sa_uliProtoSrcDstPort,
  1456. &pFilter,
  1457. &pOutboundSA,
  1458. TRUE);
  1459. } else {
  1460. status = IPSecLookupMaskedSA( pSA->sa_uliSrcDstAddr,
  1461. pSA->sa_uliProtoSrcDstPort,
  1462. &pFilter,
  1463. &pOutboundSA,
  1464. TRUE);
  1465. }
  1466. #else
  1467. status = IPSecLookupMaskedSA( pSA->sa_uliSrcDstAddr,
  1468. pSA->sa_uliProtoSrcDstPort,
  1469. &pFilter,
  1470. &pOutboundSA,
  1471. TRUE);
  1472. #endif
  1473. }
  1474. if (!NT_SUCCESS(status)) {
  1475. IPSEC_DEBUG(ACQUIRE, ("IPSecInsertOutboundSA: IPSecLookupSAByAddr failed: %lx\n", status));
  1476. return status;
  1477. }
  1478. pSAChain = IPSecResolveSAChain(pFilter, pSA->SA_DEST_ADDR);
  1479. if (status == STATUS_SUCCESS) {
  1480. //
  1481. // re-negotiate case: delete the outbound; expire the inbound; add the new one.
  1482. //
  1483. IPSEC_DEBUG(ACQUIRE, ("IPSecInsertOutboundSA: found another: %lx\n", pOutboundSA));
  1484. ASSERT(pOutboundSA);
  1485. ASSERT(pOutboundSA->sa_Flags & FLAGS_SA_OUTBOUND);
  1486. pSA->sa_Filter = pFilter;
  1487. pSA->sa_Flags |= FLAGS_SA_ON_FILTER_LIST;
  1488. InsertHeadList(pSAChain, &pSA->sa_FilterLinkage);
  1489. IPSEC_INC_STATISTIC(dwNumReKeys);
  1490. pAssociatedSA = pOutboundSA->sa_AssociatedSA;
  1491. if (pAssociatedSA &&
  1492. ((pOutboundSA->sa_Flags & FLAGS_SA_REKEY_ORI) ||
  1493. !(pInboundSA->sa_Filter))) {
  1494. IPSecExpireInboundSA(pAssociatedSA);
  1495. }
  1496. } else {
  1497. //
  1498. // pending => this will be the add.
  1499. //
  1500. ASSERT(pOutboundSA == NULL);
  1501. pSA->sa_Filter = pFilter;
  1502. pSA->sa_Flags |= FLAGS_SA_ON_FILTER_LIST;
  1503. InsertHeadList(pSAChain, &pSA->sa_FilterLinkage);
  1504. }
  1505. if (pFilter->TunnelAddr != 0) {
  1506. pSA->sa_Flags |= FLAGS_SA_TUNNEL;
  1507. pSA->sa_TunnelAddr = pFilter->TunnelAddr;
  1508. }
  1509. //
  1510. // Initiator if the original SA had a filter pointer.
  1511. //
  1512. if (pInboundSA->sa_Filter) {
  1513. pSA->sa_Flags |= FLAGS_SA_INITIATOR;
  1514. }
  1515. //
  1516. // Flush this filter from cache table so we match the SA next.
  1517. //
  1518. if (IS_EXEMPT_FILTER(pFilter)) {
  1519. IPSecInvalidateFilterCacheEntry(pFilter);
  1520. }
  1521. return STATUS_SUCCESS;
  1522. }
  1523. NTSTATUS
  1524. IPSecAddSA(
  1525. IN PIPSEC_ADD_SA pAddSA,
  1526. IN ULONG TotalSize
  1527. )
  1528. /*++
  1529. Routine Description:
  1530. Adds an SA into the database, typically called to add outbound SAs as a
  1531. result of successful negotiation of keys corresponding to the inbound SA
  1532. specified in the context that comes down.
  1533. Arguments:
  1534. pAddSA - Add SA context and info.
  1535. TotalSize - the total size of the input buffer.
  1536. Return Value:
  1537. Notes:
  1538. --*/
  1539. {
  1540. NTSTATUS status = STATUS_SUCCESS;
  1541. PSA_STRUCT saInfo = &pAddSA->SAInfo;
  1542. PSA_TABLE_ENTRY pSA;
  1543. ULONG keyLen = 0;
  1544. PSA_TABLE_ENTRY pInboundSA;
  1545. KIRQL kIrql;
  1546. KIRQL kIrql1;
  1547. PIPSEC_ACQUIRE_CONTEXT pAcquireContext = (PIPSEC_ACQUIRE_CONTEXT)(saInfo->Context);
  1548. //
  1549. // Lock the larval list so this SA does not go away.
  1550. //
  1551. AcquireWriteLock(&g_ipsec.SADBLock, &kIrql1);
  1552. ACQUIRE_LOCK(&g_ipsec.LarvalListLock, &kIrql);
  1553. //
  1554. // Sanity check the incoming context to see if it is actually
  1555. // an SA block
  1556. //
  1557. if (!NT_SUCCESS(IPSecValidateHandle(pAcquireContext, STATE_SA_LARVAL))) {
  1558. IPSEC_DEBUG(SAAPI, ("IPSecAddSA: invalid context: %lx\n", pAcquireContext));
  1559. RELEASE_LOCK(&g_ipsec.LarvalListLock, kIrql);
  1560. ReleaseWriteLock(&g_ipsec.SADBLock, kIrql1);
  1561. return STATUS_INVALID_PARAMETER;
  1562. }
  1563. //
  1564. // figure out the key length and pass that in
  1565. //
  1566. keyLen = TotalSize - IPSEC_ADD_SA_NO_KEY_SIZE;
  1567. IPSEC_DEBUG(SAAPI, ("IPSecAddSA: keyLen: %d\n", keyLen));
  1568. //
  1569. // create SA block
  1570. //
  1571. status = IPSecCreateSA(&pSA);
  1572. if (!NT_SUCCESS(status)) {
  1573. IPSEC_DEBUG(SAAPI, ("IPSecAddSA: IPSecCreateSA failed: %lx\n", status));
  1574. IPSecAbortAcquire(pAcquireContext);
  1575. RELEASE_LOCK(&g_ipsec.LarvalListLock, kIrql);
  1576. ReleaseWriteLock(&g_ipsec.SADBLock, kIrql1);
  1577. return status;
  1578. }
  1579. pSA->sa_Flags |= FLAGS_SA_OUTBOUND;
  1580. //
  1581. // Populate with the info in AddSA
  1582. //
  1583. status = IPSecPopulateSA(saInfo, keyLen, pSA);
  1584. if (!NT_SUCCESS(status)) {
  1585. IPSEC_DEBUG(SAAPI, ("IPSecAddSA: IPSecPopulateSA failed: %lx\n", status));
  1586. // IPSecPopulateSA will not free the outbound SA so we have to do it.
  1587. IPSecFreeSA(pSA);
  1588. IPSecAbortAcquire(pAcquireContext);
  1589. RELEASE_LOCK(&g_ipsec.LarvalListLock, kIrql);
  1590. ReleaseWriteLock(&g_ipsec.SADBLock, kIrql1);
  1591. return status;
  1592. }
  1593. //
  1594. // Stash the outermost spi
  1595. //
  1596. pSA->sa_SPI = pSA->sa_OtherSPIs[pSA->sa_NumOps-1];
  1597. //
  1598. // insert into proper tables
  1599. //
  1600. status = IPSecInsertOutboundSA(pSA, pAcquireContext, (BOOLEAN)((pSA->sa_Flags & FLAGS_SA_TUNNEL) != 0));
  1601. if (!NT_SUCCESS(status)) {
  1602. IPSEC_DEBUG(SAAPI, ("IPSecAddSA: IPSecInsertOutboundSA failed: %lx\n", status));
  1603. IPSecFreeSA(pSA);
  1604. IPSecAbortAcquire(pAcquireContext);
  1605. RELEASE_LOCK(&g_ipsec.LarvalListLock, kIrql);
  1606. ReleaseWriteLock(&g_ipsec.SADBLock, kIrql1);
  1607. return status;
  1608. }
  1609. pInboundSA = pAcquireContext->pSA;
  1610. //
  1611. // Associate the inbound and outbound SAs
  1612. //
  1613. pSA->sa_AssociatedSA = pInboundSA;
  1614. pInboundSA->sa_AssociatedSA = pSA;
  1615. pInboundSA->sa_State = STATE_SA_ASSOCIATED;
  1616. //
  1617. // Initialize IPSec overhead for the outbound SA.
  1618. //
  1619. IPSecCalcHeaderOverheadFromSA(pSA, &pSA->sa_IPSecOverhead);
  1620. // Copy the NewMTU value over to the new SA.
  1621. //
  1622. pSA->sa_NewMTU = pInboundSA->sa_NewMTU;
  1623. //
  1624. // Adjust SA lifetime to the maximum/minimum allowed in driver
  1625. //
  1626. if (pSA->sa_Lifetime.KeyExpirationTime > IPSEC_MAX_EXPIRE_TIME) {
  1627. pSA->sa_Lifetime.KeyExpirationTime = IPSEC_MAX_EXPIRE_TIME;
  1628. }
  1629. if (pSA->sa_Lifetime.KeyExpirationTime &&
  1630. pSA->sa_Lifetime.KeyExpirationTime < IPSEC_MIN_EXPIRE_TIME) {
  1631. pSA->sa_Lifetime.KeyExpirationTime = IPSEC_MIN_EXPIRE_TIME;
  1632. }
  1633. //
  1634. // Setup lifetime characteristics
  1635. //
  1636. IPSecSetupSALifetime(pSA);
  1637. //
  1638. // Init the LastUsedTime
  1639. //
  1640. NdisGetCurrentSystemTime(&pSA->sa_LastUsedTime);
  1641. //
  1642. // outbound is ready to go!
  1643. //
  1644. pSA->sa_State = STATE_SA_ACTIVE;
  1645. IPSEC_DEBUG(SA, ("IPSecAddSA: SA: %lx, S:%lx, D:%lx, O: %c\n",
  1646. pSA,
  1647. pSA->SA_SRC_ADDR,
  1648. pSA->SA_DEST_ADDR,
  1649. (pSA->sa_Operation[0] == Auth) ?
  1650. 'A' : (pSA->sa_Operation[0] == Encrypt) ?
  1651. 'E' : 'N'));
  1652. IPSEC_INC_STATISTIC(dwNumActiveAssociations);
  1653. IPSEC_INC_TUNNELS(pSA);
  1654. IPSEC_INCREMENT(g_ipsec.NumOutboundSAs);
  1655. IPSEC_INC_STATISTIC(dwNumKeyAdditions);
  1656. if (pSA->sa_Operation[0] != None) {
  1657. RELEASE_LOCK(&g_ipsec.LarvalListLock, kIrql);
  1658. ReleaseWriteLock(&g_ipsec.SADBLock, kIrql1);
  1659. } else {
  1660. //
  1661. // The key manager doesnt call update for None;
  1662. // call it ourselves.
  1663. //
  1664. IPSEC_UPDATE_SA updSA;
  1665. ASSERT(pInboundSA->sa_Flags & FLAGS_SA_TIMER_STARTED);
  1666. IPSEC_DEBUG(SA, ("Calling update on InboundSA: %lx\n", pInboundSA));
  1667. RELEASE_LOCK(&g_ipsec.LarvalListLock, kIrql);
  1668. ReleaseWriteLock(&g_ipsec.SADBLock, kIrql1);
  1669. //
  1670. // Reverse the addresses/ports here (by copying from the InboundSA)
  1671. //
  1672. updSA.SAInfo.Context = pAddSA->SAInfo.Context;
  1673. updSA.SAInfo.NumSAs = pAddSA->SAInfo.NumSAs;
  1674. updSA.SAInfo.Flags = pAddSA->SAInfo.Flags;
  1675. updSA.SAInfo.TunnelAddr = pAddSA->SAInfo.TunnelAddr;
  1676. updSA.SAInfo.Lifetime = pAddSA->SAInfo.Lifetime;
  1677. updSA.SAInfo.InstantiatedFilter = pAddSA->SAInfo.InstantiatedFilter;
  1678. updSA.SAInfo.SecAssoc[0] = pAddSA->SAInfo.SecAssoc[0];
  1679. updSA.SAInfo.SecAssoc[0].SPI = pInboundSA->sa_SPI;
  1680. updSA.SAInfo.InstantiatedFilter.SrcAddr = pInboundSA->SA_SRC_ADDR;
  1681. updSA.SAInfo.InstantiatedFilter.DestAddr = pInboundSA->SA_DEST_ADDR;
  1682. updSA.SAInfo.InstantiatedFilter.Protocol = pInboundSA->SA_PROTO;
  1683. updSA.SAInfo.InstantiatedFilter.SrcPort = SA_SRC_PORT(pInboundSA);
  1684. updSA.SAInfo.InstantiatedFilter.DestPort = SA_DEST_PORT(pInboundSA);
  1685. status = IPSecUpdateSA(&updSA, TotalSize);
  1686. }
  1687. return status;
  1688. }
  1689. NTSTATUS
  1690. IPSecUpdateSA(
  1691. IN PIPSEC_UPDATE_SA pUpdateSA,
  1692. IN ULONG TotalSize
  1693. )
  1694. /*++
  1695. Routine Description:
  1696. Updates an inbound SA for which negotiation was kicked off via AcquireSA with
  1697. the relevant keys/algorithms etc.
  1698. By the time this routine is called, the SA should be ASSOCIATED with an outbound
  1699. SA.
  1700. Arguments:
  1701. pUpdateSA - Update SA context and info.
  1702. TotalSize - the total size of the input buffer.
  1703. Return Value:
  1704. Notes:
  1705. --*/
  1706. {
  1707. NTSTATUS status = STATUS_SUCCESS;
  1708. PSA_STRUCT saInfo = &pUpdateSA->SAInfo;
  1709. PSA_TABLE_ENTRY pSA;
  1710. PSA_TABLE_ENTRY pOutboundSA;
  1711. PSA_HASH pHash;
  1712. ULONG keyLen = 0;
  1713. KIRQL kIrql;
  1714. KIRQL kIrql1;
  1715. KIRQL kIrql2;
  1716. PIPSEC_ACQUIRE_CONTEXT pAcquireContext = (PIPSEC_ACQUIRE_CONTEXT)(saInfo->Context);
  1717. IPSEC_DEBUG(SAAPI, ("IPSecUpdateSA\n"));
  1718. //
  1719. // Lock the larval list so this SA does not go away.
  1720. //
  1721. AcquireWriteLock(&g_ipsec.SADBLock, &kIrql1);
  1722. ACQUIRE_LOCK(&g_ipsec.LarvalListLock, &kIrql);
  1723. //
  1724. // Sanity check the incoming context to see if it is actually
  1725. // an SA block
  1726. //
  1727. if (!NT_SUCCESS(IPSecValidateHandle(pAcquireContext, STATE_SA_ASSOCIATED))) {
  1728. IPSEC_DEBUG(SAAPI, ("IPSecUpdSA: invalid context: %lx\n", pAcquireContext));
  1729. RELEASE_LOCK(&g_ipsec.LarvalListLock, kIrql);
  1730. ReleaseWriteLock(&g_ipsec.SADBLock, kIrql1);
  1731. return STATUS_INVALID_PARAMETER;
  1732. }
  1733. pSA = pAcquireContext->pSA;
  1734. ASSERT((pSA->sa_Flags & FLAGS_SA_OUTBOUND) == 0);
  1735. ASSERT(pSA->sa_State == STATE_SA_ASSOCIATED);
  1736. //
  1737. // figure out the key length and pass that in
  1738. //
  1739. keyLen = TotalSize - IPSEC_UPDATE_SA_NO_KEY_SIZE;
  1740. IPSEC_DEBUG(SAAPI, ("IPSecUpdSA: keyLen: %d\n", keyLen));
  1741. //
  1742. // sanity check the info passed in against the initial SA
  1743. //
  1744. if (pSA->sa_Filter) {
  1745. status = IPSecCheckInboundSA(saInfo, pSA);
  1746. if (!NT_SUCCESS(status) ||
  1747. !pSA->sa_AssociatedSA) {
  1748. IPSEC_DEBUG(SAAPI, ("IPSecUpdSA: IPSecCheckInboundSA failed: %lx\n", status));
  1749. IPSecAbortAcquire(pAcquireContext);
  1750. RELEASE_LOCK(&g_ipsec.LarvalListLock, kIrql);
  1751. ReleaseWriteLock(&g_ipsec.SADBLock, kIrql1);
  1752. return status;
  1753. }
  1754. }
  1755. //
  1756. // Populate the SA block
  1757. //
  1758. status = IPSecPopulateSA(saInfo, keyLen, pSA);
  1759. if (!NT_SUCCESS(status)) {
  1760. IPSEC_DEBUG(SAAPI, ("IPSecUpdSA: IPSecPopulateSA failed: %lx\n", status));
  1761. // No need to free inbound SA since IPSecAbortAcquire will do it.
  1762. IPSecAbortAcquire(pAcquireContext);
  1763. RELEASE_LOCK(&g_ipsec.LarvalListLock, kIrql);
  1764. ReleaseWriteLock(&g_ipsec.SADBLock, kIrql1);
  1765. return status;
  1766. }
  1767. //
  1768. // Set the source Tunnel IP address in outbound SA
  1769. //
  1770. if (pOutboundSA = pSA->sa_AssociatedSA) {
  1771. //
  1772. // See if we have well-associated SAs
  1773. //
  1774. ASSERT(pSA == pSA->sa_AssociatedSA->sa_AssociatedSA);
  1775. if (pSA->sa_Flags & FLAGS_SA_TUNNEL) {
  1776. pOutboundSA->sa_SrcTunnelAddr = pSA->sa_TunnelAddr;
  1777. }
  1778. if (pOutboundSA->sa_Flags & FLAGS_SA_TUNNEL) {
  1779. pSA->sa_SrcTunnelAddr = pOutboundSA->sa_TunnelAddr;
  1780. }
  1781. }
  1782. //
  1783. // Expire the original SA that kicked off this rekey
  1784. //
  1785. if (pSA->sa_Flags & FLAGS_SA_REKEY) {
  1786. PSA_TABLE_ENTRY pOriSA;
  1787. if (pOriSA = pSA->sa_RekeyOriginalSA) {
  1788. KIRQL kIrql;
  1789. pSA->sa_RekeyOriginalSA = NULL;
  1790. IPSEC_DEBUG(SA, ("Deleting original SA: pSA: %lx\n", pOriSA));
  1791. if (pOriSA->sa_AssociatedSA) {
  1792. IPSecExpireInboundSA(pOriSA->sa_AssociatedSA);
  1793. }
  1794. IPSEC_INC_STATISTIC(dwNumReKeys);
  1795. }
  1796. }
  1797. //
  1798. // inbound is ready to go!
  1799. //
  1800. pSA->sa_State = STATE_SA_ACTIVE;
  1801. IPSEC_DEBUG(SA, ("IPSecUpdateSA: SA: %lx, S:%lx, D:%lx, O: %c\n",
  1802. pSA,
  1803. pSA->SA_SRC_ADDR,
  1804. pSA->SA_DEST_ADDR,
  1805. (pSA->sa_Operation[0] == Auth) ?
  1806. 'A' : (pSA->sa_Operation[0] == Encrypt) ?
  1807. 'E' : 'N'));
  1808. //
  1809. // Remove from larval list
  1810. //
  1811. IPSecRemoveEntryList(&pSA->sa_LarvalLinkage);
  1812. IPSEC_DEC_STATISTIC(dwNumPendingKeyOps);
  1813. RELEASE_LOCK(&g_ipsec.LarvalListLock, kIrql);
  1814. ASSERT(pSA->sa_Flags & FLAGS_SA_TIMER_STARTED);
  1815. //
  1816. // Bump the SA count for flush SA use; this is necessary because we flush
  1817. // SA after releasing the lock because classification routine needs
  1818. // it and the SA can be deleted right after we release the lock.
  1819. //
  1820. IPSecRefSA(pSA);
  1821. //
  1822. // Free the Acquire Context
  1823. //
  1824. ACQUIRE_LOCK(&pSA->sa_Lock, &kIrql);
  1825. if (pSA->sa_AcquireCtx) {
  1826. IPSecInvalidateHandle(pSA->sa_AcquireCtx);
  1827. pSA->sa_AcquireCtx = NULL;
  1828. }
  1829. //
  1830. // Adjust SA lifetime to the maximum/minimum allowed in driver
  1831. //
  1832. if (pSA->sa_Lifetime.KeyExpirationTime > IPSEC_MAX_EXPIRE_TIME) {
  1833. pSA->sa_Lifetime.KeyExpirationTime = IPSEC_MAX_EXPIRE_TIME;
  1834. }
  1835. if (pSA->sa_Lifetime.KeyExpirationTime &&
  1836. pSA->sa_Lifetime.KeyExpirationTime < IPSEC_MIN_EXPIRE_TIME) {
  1837. pSA->sa_Lifetime.KeyExpirationTime = IPSEC_MIN_EXPIRE_TIME;
  1838. }
  1839. //
  1840. // Setup lifetime characteristics
  1841. //
  1842. IPSecSetupSALifetime(pSA);
  1843. //
  1844. // Init the LastUsedTime
  1845. //
  1846. NdisGetCurrentSystemTime(&pSA->sa_LastUsedTime);
  1847. if ((pSA->sa_Flags & FLAGS_SA_DISABLE_LIFETIME_CHECK)) {
  1848. if (!IPSecStopTimer(&(pSA->sa_Timer))) {
  1849. IPSEC_DEBUG(TIMER, ("Update: couldnt stop timer: %lx\n", pSA));
  1850. }
  1851. pSA->sa_Flags &= ~FLAGS_SA_TIMER_STARTED;
  1852. } else {
  1853. //
  1854. // Reschedules the timer on this new value.
  1855. //
  1856. if (pSA->sa_Lifetime.KeyExpirationTime) {
  1857. if (IPSecStopTimer(&pSA->sa_Timer)) {
  1858. IPSecStartTimer(&pSA->sa_Timer,
  1859. IPSecSAExpired,
  1860. pSA->sa_Lifetime.KeyExpirationTime, // expire in key expiration secs
  1861. (PVOID)pSA);
  1862. }
  1863. } else {
  1864. ASSERT(FALSE);
  1865. if (!IPSecStopTimer(&(pSA->sa_Timer))) {
  1866. IPSEC_DEBUG(TIMER, ("Update: couldnt stop timer: %lx\n", pSA));
  1867. }
  1868. pSA->sa_Flags &= ~FLAGS_SA_TIMER_STARTED;
  1869. }
  1870. }
  1871. RELEASE_LOCK(&pSA->sa_Lock, kIrql);
  1872. ReleaseWriteLock(&g_ipsec.SADBLock, kIrql1);
  1873. //
  1874. // Flush all the queued packets
  1875. //
  1876. IPSecFlushQueuedPackets(pSA, STATUS_SUCCESS);
  1877. IPSecDerefSA(pSA);
  1878. return status;
  1879. }
  1880. VOID
  1881. IPSecRefSA(
  1882. IN PSA_TABLE_ENTRY pSA
  1883. )
  1884. /*++
  1885. Routine Description:
  1886. Reference the SA passed in
  1887. Arguments:
  1888. pSA - SA to be refed
  1889. Return Value:
  1890. The final status from the operation.
  1891. --*/
  1892. {
  1893. if (IPSEC_INCREMENT(pSA->sa_Reference) == 1) {
  1894. ASSERT(FALSE);
  1895. }
  1896. }
  1897. VOID
  1898. IPSecDerefSA(
  1899. IN PSA_TABLE_ENTRY pSA
  1900. )
  1901. /*++
  1902. Routine Description:
  1903. Dereference the SA passed in; if refcount drops to 0, free the block.
  1904. Arguments:
  1905. pSA - SA to be derefed
  1906. Return Value:
  1907. The final status from the operation.
  1908. --*/
  1909. {
  1910. ULONG val;
  1911. if ((val = IPSEC_DECREMENT(pSA->sa_Reference)) == 0) {
  1912. //
  1913. // last reference - destroy SA
  1914. //
  1915. IPSEC_DEBUG(REF, ("Freeing SA: %lx\n", pSA));
  1916. #if DBG
  1917. if ((pSA->sa_Flags & FLAGS_SA_HW_PLUMBED)) {
  1918. DbgPrint("Freeing SA: %lx with offload on\n", pSA);
  1919. DbgBreakPoint();
  1920. }
  1921. if (IPSEC_GET_VALUE(pSA->sa_NumSends) != 0) {
  1922. DbgPrint("Freeing SA: %lx with numsends > 0\n", pSA);
  1923. DbgBreakPoint();
  1924. }
  1925. if ((pSA->sa_Flags & FLAGS_SA_TIMER_STARTED)) {
  1926. DbgPrint("Freeing SA: %lx with timer on\n", pSA);
  1927. DbgBreakPoint();
  1928. }
  1929. if (pSA->sa_Signature != IPSEC_SA_SIGNATURE) {
  1930. DbgPrint("Signature doesnt match for SA: %lx\n", pSA);
  1931. DbgBreakPoint();
  1932. }
  1933. if (!IPSEC_DRIVER_IS_INACTIVE() &&
  1934. (pSA->sa_Flags & FLAGS_SA_ON_FILTER_LIST)) {
  1935. DbgPrint("Freeing SA: %lx while still on filter list\n", pSA);
  1936. DbgBreakPoint();
  1937. }
  1938. #endif
  1939. pSA->sa_Signature = IPSEC_SA_SIGNATURE + 1;
  1940. IPSecFreeSA(pSA);
  1941. }
  1942. ASSERT((LONG)val >= 0);
  1943. }
  1944. VOID
  1945. IPSecStopSATimers()
  1946. /*++
  1947. Routine Description:
  1948. Stop all timers active on Larval SA list and Filter list.
  1949. Arguments:
  1950. Return Value:
  1951. The final status from the operation.
  1952. --*/
  1953. {
  1954. PLIST_ENTRY pFilterEntry;
  1955. PLIST_ENTRY pSAEntry;
  1956. PFILTER pFilter;
  1957. PSA_TABLE_ENTRY pSA;
  1958. KIRQL kIrql;
  1959. LONG Index;
  1960. LONG SAIndex;
  1961. AcquireWriteLock(&g_ipsec.SADBLock, &kIrql);
  1962. //
  1963. // Go through all SA's and stop its timers
  1964. //
  1965. for ( Index = MIN_FILTER;
  1966. Index <= MAX_FILTER;
  1967. Index++) {
  1968. for ( pFilterEntry = g_ipsec.FilterList[Index].Flink;
  1969. pFilterEntry != &g_ipsec.FilterList[Index];
  1970. pFilterEntry = pFilterEntry->Flink) {
  1971. pFilter = CONTAINING_RECORD(pFilterEntry,
  1972. FILTER,
  1973. MaskedLinkage);
  1974. for ( SAIndex = 0;
  1975. SAIndex < pFilter->SAChainSize;
  1976. SAIndex++) {
  1977. for ( pSAEntry = pFilter->SAChain[SAIndex].Flink;
  1978. pSAEntry != &pFilter->SAChain[SAIndex];
  1979. pSAEntry = pSAEntry->Flink) {
  1980. pSA = CONTAINING_RECORD(pSAEntry,
  1981. SA_TABLE_ENTRY,
  1982. sa_FilterLinkage);
  1983. IPSecStopSATimer(pSA);
  1984. }
  1985. }
  1986. }
  1987. }
  1988. ReleaseWriteLock(&g_ipsec.SADBLock, kIrql);
  1989. }
  1990. VOID
  1991. IPSecFlushLarvalSAList()
  1992. /*++
  1993. Routine Description:
  1994. When the Acquire Irp is cancelled, this is called to flush all Larval SAs
  1995. Called with SADB lock held (first); returns with it.
  1996. Called with AcquireInfo.Lock held; returns with it.
  1997. Arguments:
  1998. Return Value:
  1999. The final status from the operation.
  2000. --*/
  2001. {
  2002. KIRQL OldIrq;
  2003. KIRQL OldIrq1;
  2004. KIRQL kIrql;
  2005. PSA_TABLE_ENTRY pLarvalSA;
  2006. LIST_ENTRY FreeList;
  2007. InitializeListHead(&FreeList);
  2008. while (TRUE) {
  2009. if (!IsListEmpty(&g_ipsec.AcquireInfo.PendingAcquires)) {
  2010. PLIST_ENTRY pEntry;
  2011. pEntry = RemoveHeadList(&g_ipsec.AcquireInfo.PendingAcquires);
  2012. pLarvalSA = CONTAINING_RECORD( pEntry,
  2013. SA_TABLE_ENTRY,
  2014. sa_PendingLinkage);
  2015. ASSERT(pLarvalSA->sa_State == STATE_SA_LARVAL);
  2016. ASSERT(pLarvalSA->sa_Flags & FLAGS_SA_PENDING);
  2017. pLarvalSA->sa_Flags &= ~FLAGS_SA_PENDING;
  2018. //
  2019. // Insert into another list, which we walk without the lock
  2020. //
  2021. InsertTailList(&FreeList, &pLarvalSA->sa_PendingLinkage);
  2022. //
  2023. // also remove from Larval list
  2024. //
  2025. ACQUIRE_LOCK(&g_ipsec.LarvalListLock, &OldIrq1);
  2026. IPSecRemoveEntryList(&pLarvalSA->sa_LarvalLinkage);
  2027. IPSEC_DEC_STATISTIC(dwNumPendingKeyOps);
  2028. RELEASE_LOCK(&g_ipsec.LarvalListLock, OldIrq1);
  2029. } else {
  2030. break;
  2031. }
  2032. }
  2033. //
  2034. // get the remaining Larval SAs
  2035. //
  2036. ACQUIRE_LOCK(&g_ipsec.LarvalListLock, &OldIrq);
  2037. while (TRUE) {
  2038. if (!IsListEmpty(&g_ipsec.LarvalSAList)) {
  2039. PLIST_ENTRY pEntry;
  2040. pEntry = RemoveHeadList(&g_ipsec.LarvalSAList);
  2041. pLarvalSA = CONTAINING_RECORD( pEntry,
  2042. SA_TABLE_ENTRY,
  2043. sa_LarvalLinkage);
  2044. //
  2045. // Insert into another list, which we walk without the lock
  2046. //
  2047. InsertTailList(&FreeList, &pLarvalSA->sa_PendingLinkage);
  2048. } else {
  2049. break;
  2050. }
  2051. }
  2052. RELEASE_LOCK(&g_ipsec.LarvalListLock, OldIrq);
  2053. while (TRUE) {
  2054. if (!IsListEmpty(&FreeList)) {
  2055. PLIST_ENTRY pEntry;
  2056. pEntry = RemoveHeadList(&FreeList);
  2057. pLarvalSA = CONTAINING_RECORD( pEntry,
  2058. SA_TABLE_ENTRY,
  2059. sa_PendingLinkage);
  2060. AcquireWriteLock(&g_ipsec.SPIListLock, &kIrql);
  2061. IPSecRemoveSPIEntry(pLarvalSA);
  2062. ReleaseWriteLock(&g_ipsec.SPIListLock, kIrql);
  2063. //
  2064. // Flush all the queued packets
  2065. //
  2066. IPSecFlushQueuedPackets(pLarvalSA, STATUS_TIMEOUT);
  2067. //
  2068. // also remove from the filter list
  2069. //
  2070. if (pLarvalSA->sa_Flags & FLAGS_SA_ON_FILTER_LIST) {
  2071. pLarvalSA->sa_Flags &= ~FLAGS_SA_ON_FILTER_LIST;
  2072. IPSecRemoveEntryList(&pLarvalSA->sa_FilterLinkage);
  2073. }
  2074. if (pLarvalSA->sa_RekeyOriginalSA) {
  2075. ASSERT(pLarvalSA->sa_Flags & FLAGS_SA_REKEY);
  2076. ASSERT(pLarvalSA->sa_RekeyOriginalSA->sa_RekeyLarvalSA == pLarvalSA);
  2077. ASSERT(pLarvalSA->sa_RekeyOriginalSA->sa_Flags & FLAGS_SA_REKEY_ORI);
  2078. pLarvalSA->sa_RekeyOriginalSA->sa_Flags &= ~FLAGS_SA_REKEY_ORI;
  2079. pLarvalSA->sa_RekeyOriginalSA->sa_RekeyLarvalSA = NULL;
  2080. pLarvalSA->sa_RekeyOriginalSA = NULL;
  2081. }
  2082. //
  2083. // release acquire context and invalidate the associated cache entry
  2084. //
  2085. ACQUIRE_LOCK(&pLarvalSA->sa_Lock, &kIrql);
  2086. if (pLarvalSA->sa_AcquireCtx) {
  2087. IPSecInvalidateHandle(pLarvalSA->sa_AcquireCtx);
  2088. pLarvalSA->sa_AcquireCtx = NULL;
  2089. }
  2090. RELEASE_LOCK(&pLarvalSA->sa_Lock, kIrql);
  2091. IPSecInvalidateSACacheEntry(pLarvalSA);
  2092. IPSecStopTimerDerefSA(pLarvalSA);
  2093. } else {
  2094. break;
  2095. }
  2096. }
  2097. return;
  2098. }
  2099. NTSTATUS
  2100. IPSecDeleteSA(
  2101. IN PIPSEC_DELETE_SA pDeleteSA
  2102. )
  2103. /*++
  2104. Routine Description:
  2105. Delete the SA matching the particulars passed in. Both inbound and
  2106. outbound SAs are deleted. No timer set for inbound SA.
  2107. Arguments:
  2108. Return Value:
  2109. The final status from the operation.
  2110. --*/
  2111. {
  2112. PFILTER pFilter;
  2113. PSA_TABLE_ENTRY pSA, pInboundSA;
  2114. PLIST_ENTRY pEntry, pSAEntry;
  2115. KIRQL kIrql;
  2116. LONG Index;
  2117. LONG SAIndex;
  2118. AcquireWriteLock(&g_ipsec.SADBLock, &kIrql);
  2119. //
  2120. // Walk through the outbound SAs and delete matched ones.
  2121. //
  2122. for ( Index = OUTBOUND_TRANSPORT_FILTER;
  2123. Index <= OUTBOUND_TUNNEL_FILTER;
  2124. Index += TRANSPORT_TUNNEL_INCREMENT) {
  2125. for ( pEntry = g_ipsec.FilterList[Index].Flink;
  2126. pEntry != &g_ipsec.FilterList[Index];
  2127. pEntry = pEntry->Flink) {
  2128. pFilter = CONTAINING_RECORD(pEntry,
  2129. FILTER,
  2130. MaskedLinkage);
  2131. for ( SAIndex = 0;
  2132. SAIndex < pFilter->SAChainSize;
  2133. SAIndex++) {
  2134. pSAEntry = pFilter->SAChain[SAIndex].Flink;
  2135. while (pSAEntry != &pFilter->SAChain[SAIndex]) {
  2136. pSA = CONTAINING_RECORD(pSAEntry,
  2137. SA_TABLE_ENTRY,
  2138. sa_FilterLinkage);
  2139. pSAEntry = pSAEntry->Flink;
  2140. if (IPSecMatchSATemplate(pSA, &pDeleteSA->SATemplate)) {
  2141. ASSERT(pSA->sa_State == STATE_SA_ACTIVE);
  2142. ASSERT(pSA->sa_Flags & FLAGS_SA_OUTBOUND);
  2143. ASSERT(pSA->sa_AssociatedSA);
  2144. pInboundSA = pSA->sa_AssociatedSA;
  2145. if (pInboundSA) {
  2146. IPSecDeleteInboundSA(pInboundSA);
  2147. }
  2148. }
  2149. }
  2150. }
  2151. }
  2152. }
  2153. ReleaseWriteLock(&g_ipsec.SADBLock, kIrql);
  2154. return STATUS_SUCCESS;
  2155. }
  2156. NTSTATUS
  2157. IPSecExpireSA(
  2158. IN PIPSEC_EXPIRE_SA pExpireSA
  2159. )
  2160. /*++
  2161. Routine Description:
  2162. Expires the SA matching the particulars passed in.
  2163. Applied to Inbound SAs - we place the SA in the timer queue
  2164. for the next time the timer hits. Also, we delete the
  2165. corresponding outbound SA so no further packets match that
  2166. SA.
  2167. Arguments:
  2168. Return Value:
  2169. The final status from the operation.
  2170. --*/
  2171. {
  2172. PSA_TABLE_ENTRY pInboundSA;
  2173. KIRQL kIrql;
  2174. NTSTATUS status;
  2175. AcquireWriteLock(&g_ipsec.SADBLock, &kIrql);
  2176. pInboundSA = IPSecLookupSABySPI(pExpireSA->DelInfo.SPI,
  2177. pExpireSA->DelInfo.DestAddr);
  2178. if (pInboundSA) {
  2179. ASSERT((pInboundSA->sa_Flags & FLAGS_SA_OUTBOUND) == 0);
  2180. if (pInboundSA->sa_State == STATE_SA_ACTIVE) {
  2181. IPSEC_DEBUG(ACQUIRE, ("Expiring SA: %lx\n", pInboundSA));
  2182. if (pInboundSA->sa_Flags & FLAGS_SA_ON_FILTER_LIST) {
  2183. pInboundSA->sa_Flags &= ~FLAGS_SA_ON_FILTER_LIST;
  2184. IPSecRemoveEntryList(&pInboundSA->sa_FilterLinkage);
  2185. }
  2186. pInboundSA->sa_Flags |= FLAGS_SA_DELETE_BY_IOCTL;
  2187. IPSecExpireInboundSA(pInboundSA);
  2188. }
  2189. status = STATUS_SUCCESS;
  2190. } else {
  2191. IPSEC_DEBUG(ACQUIRE, ("Expire for a non-existent SA: %lx\n", pExpireSA));
  2192. status = STATUS_NO_MATCH;
  2193. }
  2194. ReleaseWriteLock(&g_ipsec.SADBLock, kIrql);
  2195. return status;
  2196. }
  2197. VOID
  2198. IPSecSAExpired(
  2199. IN PIPSEC_TIMER pTimer,
  2200. IN PVOID Context
  2201. )
  2202. /*++
  2203. Routine Description:
  2204. Called when an SA has expired or when a Larval SA has timed out.
  2205. Arguments:
  2206. pTimer - the timer struct
  2207. Context - SA ptr
  2208. Return Value:
  2209. STATUS_PENDING if the buffer is to be held on to, the normal case.
  2210. Notes:
  2211. --*/
  2212. {
  2213. PSA_TABLE_ENTRY pSA = (PSA_TABLE_ENTRY)Context;
  2214. PSA_TABLE_ENTRY pOutboundSA;
  2215. KIRQL kIrql;
  2216. KIRQL kIrql1;
  2217. KIRQL kIrql2;
  2218. KIRQL OldIrq;
  2219. IPSEC_DEBUG(TIMER, ("IPSecSAExpired: pSA: %lx state: %lx\n", pSA, pSA->sa_State));
  2220. AcquireWriteLock(&g_ipsec.SADBLock, &kIrql1);
  2221. ACQUIRE_LOCK(&g_ipsec.LarvalListLock, &kIrql);
  2222. switch (pSA->sa_State) {
  2223. case STATE_SA_CREATED:
  2224. ASSERT(FALSE);
  2225. break;
  2226. case STATE_SA_LARVAL:
  2227. case STATE_SA_ASSOCIATED:
  2228. //
  2229. // Lock the larval list so this SA does not go away.
  2230. //
  2231. ASSERT((pSA->sa_Flags & FLAGS_SA_OUTBOUND) == 0);
  2232. //
  2233. // Remove from larval list
  2234. //
  2235. IPSecRemoveEntryList(&pSA->sa_LarvalLinkage);
  2236. IPSEC_DEC_STATISTIC(dwNumPendingKeyOps);
  2237. //
  2238. // Also remove from Pending list if queued there.
  2239. //
  2240. ACQUIRE_LOCK(&g_ipsec.AcquireInfo.Lock, &kIrql1);
  2241. if (pSA->sa_Flags & FLAGS_SA_PENDING) {
  2242. ASSERT(pSA->sa_State == STATE_SA_LARVAL);
  2243. IPSEC_DEBUG(ACQUIRE, ("IPSecSAExpired: Removed from pending too: %lx\n", pSA));
  2244. IPSecRemoveEntryList(&pSA->sa_PendingLinkage);
  2245. pSA->sa_Flags &= ~FLAGS_SA_PENDING;
  2246. }
  2247. RELEASE_LOCK(&g_ipsec.AcquireInfo.Lock, kIrql1);
  2248. //
  2249. // Flush all the queued packets
  2250. //
  2251. IPSecFlushQueuedPackets(pSA, STATUS_TIMEOUT);
  2252. //
  2253. // remove from inbound sa list
  2254. //
  2255. AcquireWriteLock(&g_ipsec.SPIListLock, &kIrql1);
  2256. IPSecRemoveSPIEntry(pSA);
  2257. ReleaseWriteLock(&g_ipsec.SPIListLock, kIrql1);
  2258. //
  2259. // also remove from the filter list
  2260. //
  2261. if (pSA->sa_Flags & FLAGS_SA_ON_FILTER_LIST) {
  2262. pSA->sa_Flags &= ~FLAGS_SA_ON_FILTER_LIST;
  2263. IPSecRemoveEntryList(&pSA->sa_FilterLinkage);
  2264. }
  2265. //
  2266. // invalidate the associated cache entry
  2267. //
  2268. ACQUIRE_LOCK(&pSA->sa_Lock, &kIrql2);
  2269. if (pSA->sa_AcquireCtx) {
  2270. IPSecInvalidateHandle(pSA->sa_AcquireCtx);
  2271. pSA->sa_AcquireCtx = NULL;
  2272. }
  2273. RELEASE_LOCK(&pSA->sa_Lock, kIrql2);
  2274. IPSecInvalidateSACacheEntry(pSA);
  2275. pSA->sa_Flags &= ~FLAGS_SA_TIMER_STARTED;
  2276. if (pSA->sa_RekeyOriginalSA) {
  2277. ASSERT(pSA->sa_Flags & FLAGS_SA_REKEY);
  2278. ASSERT(pSA->sa_RekeyOriginalSA->sa_RekeyLarvalSA == pSA);
  2279. ASSERT(pSA->sa_RekeyOriginalSA->sa_Flags & FLAGS_SA_REKEY_ORI);
  2280. pSA->sa_RekeyOriginalSA->sa_Flags &= ~FLAGS_SA_REKEY_ORI;
  2281. pSA->sa_RekeyOriginalSA->sa_RekeyLarvalSA = NULL;
  2282. pSA->sa_RekeyOriginalSA = NULL;
  2283. }
  2284. if (pOutboundSA = pSA->sa_AssociatedSA) {
  2285. IPSEC_DEC_STATISTIC(dwNumActiveAssociations);
  2286. IPSEC_DEC_TUNNELS(pOutboundSA);
  2287. IPSEC_DECREMENT(g_ipsec.NumOutboundSAs);
  2288. IPSecCleanupOutboundSA(pSA, pOutboundSA, FALSE);
  2289. }
  2290. IPSEC_DEBUG(REF, ("Timer in Deref\n"));
  2291. IPSecDerefSA(pSA);
  2292. break;
  2293. case STATE_SA_ZOMBIE:
  2294. ASSERT(FALSE);
  2295. break;
  2296. case STATE_SA_ACTIVE:
  2297. //
  2298. // Inbound SA being expired; outbound was deleted immediately
  2299. //
  2300. ASSERT((pSA->sa_Flags & FLAGS_SA_OUTBOUND) == 0);
  2301. ACQUIRE_LOCK(&g_ipsec.AcquireInfo.Lock, &OldIrq);
  2302. IPSecNotifySAExpiration(pSA, NULL, OldIrq, FALSE);
  2303. //
  2304. // remove from inbound sa list
  2305. //
  2306. AcquireWriteLock(&g_ipsec.SPIListLock, &kIrql1);
  2307. IPSecRemoveSPIEntry(pSA);
  2308. ReleaseWriteLock(&g_ipsec.SPIListLock, kIrql1);
  2309. //
  2310. // also remove from the filter list
  2311. //
  2312. if (pSA->sa_Flags & FLAGS_SA_ON_FILTER_LIST) {
  2313. pSA->sa_Flags &= ~FLAGS_SA_ON_FILTER_LIST;
  2314. IPSecRemoveEntryList(&pSA->sa_FilterLinkage);
  2315. }
  2316. //
  2317. // invalidate the associated cache entry
  2318. //
  2319. IPSecInvalidateSACacheEntry(pSA);
  2320. pSA->sa_Flags &= ~FLAGS_SA_TIMER_STARTED;
  2321. if (pOutboundSA = pSA->sa_AssociatedSA) {
  2322. IPSEC_DEC_STATISTIC(dwNumActiveAssociations);
  2323. IPSEC_DEC_TUNNELS(pOutboundSA);
  2324. IPSEC_DECREMENT(g_ipsec.NumOutboundSAs);
  2325. IPSecCleanupOutboundSA(pSA, pOutboundSA, FALSE);
  2326. }
  2327. if (pSA->sa_Flags & FLAGS_SA_HW_PLUMBED) {
  2328. IPSecDelHWSAAtDpc(pSA);
  2329. }
  2330. ASSERT(pSA->sa_AssociatedSA == NULL);
  2331. IPSEC_DEBUG(REF, ("Timer#2 in Deref\n"));
  2332. IPSecDerefSA(pSA);
  2333. break;
  2334. default:
  2335. ASSERT(FALSE);
  2336. }
  2337. RELEASE_LOCK(&g_ipsec.LarvalListLock, kIrql);
  2338. ReleaseWriteLock(&g_ipsec.SADBLock, kIrql1);
  2339. }
  2340. VOID
  2341. IPSecFillSAInfo(
  2342. IN PSA_TABLE_ENTRY pSA,
  2343. OUT PIPSEC_SA_INFO pBuf
  2344. )
  2345. /*++
  2346. Routine Description:
  2347. Fill out the SA_INFO structure.
  2348. Arguments:
  2349. pSA - SA to be filled in
  2350. pBuf - where to fill in
  2351. Returns:
  2352. None.
  2353. --*/
  2354. {
  2355. LONG Index;
  2356. PSA_TABLE_ENTRY pAssociatedSA = pSA->sa_AssociatedSA;
  2357. RtlZeroMemory(pBuf, sizeof(IPSEC_SA_INFO));
  2358. pBuf->PolicyId = pSA->sa_Filter->PolicyId;
  2359. pBuf->FilterId = pSA->sa_Filter->FilterId;
  2360. pBuf->Lifetime = pSA->sa_Lifetime;
  2361. pBuf->InboundTunnelAddr = pSA->sa_SrcTunnelAddr;
  2362. pBuf->NumOps = pSA->sa_NumOps;
  2363. pBuf->dwQMPFSGroup = pSA->sa_QMPFSGroup;
  2364. RtlCopyMemory( &pBuf->CookiePair,
  2365. &pSA->sa_CookiePair,
  2366. sizeof(IKE_COOKIE_PAIR));
  2367. for (Index = 0; Index < pSA->sa_NumOps; Index++) {
  2368. pBuf->Operation[Index] = pSA->sa_Operation[Index];
  2369. pBuf->EXT_INT_ALGO_EX(Index) = pSA->INT_ALGO(Index);
  2370. pBuf->EXT_INT_KEYLEN_EX(Index) = pSA->INT_KEYLEN(Index);
  2371. pBuf->EXT_INT_ROUNDS_EX(Index) = pSA->INT_ROUNDS(Index);
  2372. pBuf->EXT_CONF_ALGO_EX(Index) = pSA->CONF_ALGO(Index);
  2373. pBuf->EXT_CONF_KEYLEN_EX(Index) = pSA->CONF_KEYLEN(Index);
  2374. pBuf->EXT_CONF_ROUNDS_EX(Index) = pSA->CONF_ROUNDS(Index);
  2375. if (pAssociatedSA) {
  2376. pBuf->InboundSPI[Index] = pAssociatedSA->sa_OtherSPIs[Index];
  2377. }
  2378. pBuf->OutboundSPI[Index] = pSA->sa_OtherSPIs[Index];
  2379. }
  2380. pBuf->AssociatedFilter.SrcAddr = pSA->SA_SRC_ADDR & pSA->SA_SRC_MASK;
  2381. pBuf->AssociatedFilter.SrcMask = pSA->SA_SRC_MASK;
  2382. pBuf->AssociatedFilter.DestAddr = pSA->SA_DEST_ADDR & pSA->SA_DEST_MASK;
  2383. pBuf->AssociatedFilter.DestMask = pSA->SA_DEST_MASK;
  2384. pBuf->AssociatedFilter.Protocol = pSA->SA_PROTO;
  2385. pBuf->AssociatedFilter.SrcPort = SA_SRC_PORT(pSA);
  2386. pBuf->AssociatedFilter.DestPort = SA_DEST_PORT(pSA);
  2387. pBuf->AssociatedFilter.TunnelAddr = pSA->sa_TunnelAddr;
  2388. pBuf->AssociatedFilter.TunnelFilter = (pSA->sa_Flags & FLAGS_SA_TUNNEL) != 0;
  2389. if (pSA->sa_Flags & FLAGS_SA_OUTBOUND) {
  2390. pBuf->AssociatedFilter.Flags = FILTER_FLAGS_OUTBOUND;
  2391. } else {
  2392. pBuf->AssociatedFilter.Flags = FILTER_FLAGS_INBOUND;
  2393. }
  2394. if (pSA->sa_Flags & FLAGS_SA_INITIATOR) {
  2395. pBuf->EnumFlags |= SA_ENUM_FLAGS_INITIATOR;
  2396. }
  2397. if (pSA->sa_Flags & FLAGS_SA_MTU_BUMPED) {
  2398. pBuf->EnumFlags |= SA_ENUM_FLAGS_MTU_BUMPED;
  2399. }
  2400. if (pSA->sa_Flags & FLAGS_SA_HW_PLUMBED) {
  2401. pBuf->EnumFlags |= SA_ENUM_FLAGS_OFFLOADED;
  2402. }
  2403. if (pSA->sa_Flags & FLAGS_SA_HW_PLUMB_FAILED) {
  2404. pBuf->EnumFlags |= SA_ENUM_FLAGS_OFFLOAD_FAILED;
  2405. }
  2406. if (pSA->sa_Flags & FLAGS_SA_OFFLOADABLE) {
  2407. pBuf->EnumFlags |= SA_ENUM_FLAGS_OFFLOADABLE;
  2408. }
  2409. if (pSA->sa_Flags & FLAGS_SA_REKEY_ORI) {
  2410. pBuf->EnumFlags |= SA_ENUM_FLAGS_IN_REKEY;
  2411. }
  2412. pBuf->Stats.ConfidentialBytesSent = pSA->sa_Stats.ConfidentialBytesSent;
  2413. pBuf->Stats.AuthenticatedBytesSent = pSA->sa_Stats.AuthenticatedBytesSent;
  2414. pBuf->Stats.TotalBytesSent = pSA->sa_Stats.TotalBytesSent;
  2415. pBuf->Stats.OffloadedBytesSent = pSA->sa_Stats.OffloadedBytesSent;
  2416. if (pAssociatedSA) {
  2417. pBuf->Stats.ConfidentialBytesReceived =
  2418. pAssociatedSA->sa_Stats.ConfidentialBytesReceived;
  2419. pBuf->Stats.AuthenticatedBytesReceived =
  2420. pAssociatedSA->sa_Stats.AuthenticatedBytesReceived;
  2421. pBuf->Stats.TotalBytesReceived =
  2422. pAssociatedSA->sa_Stats.TotalBytesReceived;
  2423. pBuf->Stats.OffloadedBytesReceived =
  2424. pAssociatedSA->sa_Stats.OffloadedBytesReceived;
  2425. }
  2426. }
  2427. NTSTATUS
  2428. IPSecEnumSAs(
  2429. IN PIRP pIrp,
  2430. OUT PULONG pBytesCopied
  2431. )
  2432. /*++
  2433. Routine Description:
  2434. Fills in the request to enumerate SAs.
  2435. Arguments:
  2436. pIrp - The actual Irp
  2437. pBytesCopied - the number of bytes copied.
  2438. Returns:
  2439. Status of the operation.
  2440. --*/
  2441. {
  2442. PNDIS_BUFFER NdisBuffer = NULL;
  2443. PIPSEC_ENUM_SAS pEnum = NULL;
  2444. ULONG BufferLength = 0;
  2445. KIRQL kIrql;
  2446. PLIST_ENTRY pEntry;
  2447. PLIST_ENTRY pSAEntry;
  2448. IPSEC_SA_INFO infoBuff = {0};
  2449. NTSTATUS status = STATUS_SUCCESS;
  2450. ULONG BytesCopied = 0;
  2451. ULONG Offset = 0;
  2452. PFILTER pFilter;
  2453. PSA_TABLE_ENTRY pSA;
  2454. LONG Index;
  2455. LONG FilterIndex;
  2456. LONG SAIndex;
  2457. //
  2458. // Get at the IO buffer - its in the MDL
  2459. //
  2460. NdisBuffer = REQUEST_NDIS_BUFFER(pIrp);
  2461. if (NdisBuffer == NULL) {
  2462. return STATUS_INVALID_PARAMETER;
  2463. }
  2464. NdisQueryBufferSafe(NdisBuffer,
  2465. (PVOID *)&pEnum,
  2466. &BufferLength,
  2467. NormalPagePriority);
  2468. //
  2469. // Make sure NdisQueryBufferSafe succeeds.
  2470. //
  2471. if (!pEnum) {
  2472. IPSEC_DEBUG (IOCTL, ("EnumSAs failed, no resources\n"));
  2473. return STATUS_INSUFFICIENT_RESOURCES;
  2474. }
  2475. //
  2476. // Make sure we have enough room for just the header not
  2477. // including the data.
  2478. //
  2479. if (BufferLength < (UINT)(FIELD_OFFSET(IPSEC_ENUM_SAS, pInfo[0]))) {
  2480. IPSEC_DEBUG (IOCTL, ("EnumSAs failed, buffer too small\n"));
  2481. return STATUS_BUFFER_TOO_SMALL;
  2482. }
  2483. //
  2484. // Make sure we are naturally aligned.
  2485. //
  2486. if (((ULONG_PTR)(pEnum)) & (TYPE_ALIGNMENT(IPSEC_ENUM_SAS) - 1)) {
  2487. IPSEC_DEBUG (IOCTL, ("EnumSAs failed, alignment\n"));
  2488. return STATUS_DATATYPE_MISALIGNMENT_ERROR;
  2489. }
  2490. pEnum->NumEntries = 0;
  2491. pEnum->NumEntriesPresent = 0;
  2492. //
  2493. // Now copy over the SA data into the user buffer and fit as many as possible.
  2494. //
  2495. BufferLength -= FIELD_OFFSET(IPSEC_ENUM_SAS, pInfo[0]);
  2496. Offset = FIELD_OFFSET(IPSEC_ENUM_SAS, pInfo[0]);
  2497. Index = pEnum->Index; // where to start?
  2498. AcquireReadLock(&g_ipsec.SADBLock, &kIrql);
  2499. for ( FilterIndex = MIN_FILTER;
  2500. FilterIndex <= MAX_FILTER;
  2501. FilterIndex++) {
  2502. for ( pEntry = g_ipsec.FilterList[FilterIndex].Flink;
  2503. pEntry != &g_ipsec.FilterList[FilterIndex];
  2504. pEntry = pEntry->Flink) {
  2505. pFilter = CONTAINING_RECORD(pEntry,
  2506. FILTER,
  2507. MaskedLinkage);
  2508. for ( SAIndex = 0;
  2509. SAIndex < pFilter->SAChainSize;
  2510. SAIndex ++) {
  2511. for ( pSAEntry = pFilter->SAChain[SAIndex].Flink;
  2512. pSAEntry != &pFilter->SAChain[SAIndex];
  2513. pSAEntry = pSAEntry->Flink) {
  2514. pSA = CONTAINING_RECORD(pSAEntry,
  2515. SA_TABLE_ENTRY,
  2516. sa_FilterLinkage);
  2517. //
  2518. // Only interested in outbound or multicast SAs.
  2519. //
  2520. if (!(pSA->sa_Flags & FLAGS_SA_OUTBOUND)) {
  2521. continue;
  2522. }
  2523. //
  2524. // Dump only SAs that match the template.
  2525. //
  2526. if (IPSecMatchSATemplate(pSA, &pEnum->SATemplate)) {
  2527. if (Index > 0) {
  2528. Index--; // Skip number of Index SAs.
  2529. continue;
  2530. }
  2531. pEnum->NumEntriesPresent++;
  2532. if ((INT)(BufferLength - BytesCopied) >= (INT)sizeof(IPSEC_SA_INFO)) {
  2533. IPSecFillSAInfo(pSA, &infoBuff);
  2534. BytesCopied += sizeof(IPSEC_SA_INFO);
  2535. NdisBuffer = CopyToNdis(NdisBuffer, (UCHAR *)&infoBuff, sizeof(IPSEC_SA_INFO), &Offset);
  2536. if (!NdisBuffer) {
  2537. ReleaseReadLock(&g_ipsec.SADBLock, kIrql);
  2538. return STATUS_INSUFFICIENT_RESOURCES;
  2539. }
  2540. }
  2541. }
  2542. }
  2543. }
  2544. }
  2545. }
  2546. ReleaseReadLock(&g_ipsec.SADBLock, kIrql);
  2547. pEnum->NumEntries = BytesCopied / sizeof(IPSEC_SA_INFO);
  2548. *pBytesCopied = BytesCopied + FIELD_OFFSET(IPSEC_ENUM_SAS, pInfo[0]);
  2549. if (pEnum->NumEntries < pEnum->NumEntriesPresent) {
  2550. status = STATUS_BUFFER_OVERFLOW;
  2551. }
  2552. return status;
  2553. }
  2554. VOID
  2555. IPSecReaper(
  2556. IN PIPSEC_TIMER pTimer,
  2557. IN PVOID Context
  2558. )
  2559. /*++
  2560. Routine Description:
  2561. Called every 5 mins; reaps the (active) SA list
  2562. Arguments:
  2563. pTimer - the timer struct
  2564. Context - NULL
  2565. Return Value:
  2566. STATUS_PENDING if the buffer is to be held on to, the normal case.
  2567. Notes:
  2568. --*/
  2569. {
  2570. KIRQL kIrql;
  2571. IPSEC_DEBUG(TIMER, ("Entering IPSecReaper\n"));
  2572. AcquireWriteLock(&g_ipsec.SADBLock, &kIrql);
  2573. //
  2574. // walk the outbound SAs and delete/expire them if they have been
  2575. // idle for sometime (lets say 5 mins for now).
  2576. //
  2577. IPSecReapIdleSAs();
  2578. ReleaseWriteLock(&g_ipsec.SADBLock, kIrql);
  2579. IPSEC_DEBUG(TIMER, ("Exiting IPSecReaper\n"));
  2580. if (!IPSEC_DRIVER_IS_INACTIVE()) {
  2581. IPSecStartTimer(&g_ipsec.ReaperTimer,
  2582. IPSecReaper,
  2583. IPSEC_REAPER_TIME,
  2584. (PVOID)NULL);
  2585. }
  2586. }
  2587. VOID
  2588. IPSecReapIdleSAs()
  2589. /*++
  2590. Routine Description:
  2591. Called to reap the idle SA list
  2592. Arguments:
  2593. Return Value:
  2594. --*/
  2595. {
  2596. PSA_TABLE_ENTRY pSA;
  2597. PFILTER pFilter;
  2598. PLIST_ENTRY pEntry;
  2599. PLIST_ENTRY pSAEntry;
  2600. BOOLEAN fExpired;
  2601. LONG Index;
  2602. LONG SAIndex;
  2603. IPSEC_DEBUG(TIMER, ("Entering IPSecReapIdleSAs\n"));
  2604. //
  2605. // Walk the inbound SAs and delete/expire them if they have been
  2606. // idle for sometime (lets say 5 mins for now).
  2607. //
  2608. for ( Index = INBOUND_TRANSPORT_FILTER;
  2609. Index <= INBOUND_TUNNEL_FILTER;
  2610. Index += TRANSPORT_TUNNEL_INCREMENT) {
  2611. for ( pEntry = g_ipsec.FilterList[Index].Flink;
  2612. pEntry != &g_ipsec.FilterList[Index];
  2613. pEntry = pEntry->Flink) {
  2614. pFilter = CONTAINING_RECORD(pEntry,
  2615. FILTER,
  2616. MaskedLinkage);
  2617. for ( SAIndex = 0;
  2618. SAIndex < pFilter->SAChainSize;
  2619. SAIndex++) {
  2620. pSAEntry = pFilter->SAChain[SAIndex].Flink;
  2621. while (pSAEntry != &pFilter->SAChain[SAIndex]) {
  2622. pSA = CONTAINING_RECORD(pSAEntry,
  2623. SA_TABLE_ENTRY,
  2624. sa_FilterLinkage);
  2625. ASSERT(!(pSA->sa_Flags & FLAGS_SA_OUTBOUND));
  2626. pSAEntry = pSAEntry->Flink;
  2627. if (!(pSA->sa_Flags & FLAGS_SA_IDLED_OUT) &&
  2628. (pSA->sa_State == STATE_SA_ACTIVE) &&
  2629. !(pSA->sa_Flags & FLAGS_SA_DISABLE_IDLE_OUT)) {
  2630. IPSEC_SA_EXPIRED(pSA, fExpired);
  2631. if (fExpired) {
  2632. pSA->sa_Flags |= FLAGS_SA_IDLED_OUT;
  2633. IPSecExpireInboundSA(pSA);
  2634. }
  2635. }
  2636. }
  2637. }
  2638. }
  2639. }
  2640. IPSEC_DEBUG(TIMER, ("Exiting IPSecReapIdleSAs\n"));
  2641. }
  2642. VOID
  2643. IPSecFlushEventLog(
  2644. IN PIPSEC_TIMER pTimer,
  2645. IN PVOID Context
  2646. )
  2647. /*++
  2648. Routine Description:
  2649. Called every LogInterval seconds; flush all events currently logged.
  2650. Arguments:
  2651. pTimer - the timer struct
  2652. Context - NULL
  2653. Return Value:
  2654. Notes:
  2655. --*/
  2656. {
  2657. KIRQL kIrql;
  2658. IPSEC_DEBUG(TIMER, ("Entering IPSecFlushEventLog\n"));
  2659. ACQUIRE_LOCK(&g_ipsec.EventLogLock, &kIrql);
  2660. if (g_ipsec.IPSecLogMemoryLoc > g_ipsec.IPSecLogMemory) {
  2661. //
  2662. // Flush the logs.
  2663. //
  2664. IPSecQueueLogEvent();
  2665. }
  2666. RELEASE_LOCK(&g_ipsec.EventLogLock, kIrql);
  2667. if (!IPSEC_DRIVER_IS_INACTIVE()) {
  2668. IPSecStartTimer(&g_ipsec.EventLogTimer,
  2669. IPSecFlushEventLog,
  2670. g_ipsec.LogInterval,
  2671. (PVOID)NULL);
  2672. }
  2673. }
  2674. NTSTATUS
  2675. IPSecQuerySpi(
  2676. IN OUT PIPSEC_QUERY_SPI pQuerySpi
  2677. )
  2678. /*++
  2679. Routine Description:
  2680. Queries IPSEC for spis corresponding to given filter
  2681. Arguments:
  2682. Return Value:
  2683. Notes:
  2684. --*/
  2685. {
  2686. NTSTATUS status;
  2687. ULARGE_INTEGER uliSrcDstAddr;
  2688. ULARGE_INTEGER uliProtoSrcDstPort;
  2689. PFILTER pFilter = NULL;
  2690. PSA_TABLE_ENTRY pSA = NULL;
  2691. PSA_TABLE_ENTRY pNextSA = NULL;
  2692. PSA_TABLE_ENTRY pTunnelSA = NULL;
  2693. KIRQL kIrql;
  2694. pQuerySpi->Spi = 0;
  2695. pQuerySpi->OtherSpi = 0;
  2696. pQuerySpi->Operation = 0;
  2697. IPSEC_DEBUG(ACQUIRE, ("IPSecQuerySPI: Src %08x.%04x Dst %08x.%04x Protocol %d",
  2698. pQuerySpi->Filter.SrcAddr,
  2699. pQuerySpi->Filter.SrcPort,
  2700. pQuerySpi->Filter.DestAddr,
  2701. pQuerySpi->Filter.DestPort,
  2702. pQuerySpi->Filter.Protocol));
  2703. IPSEC_BUILD_SRC_DEST_ADDR( uliSrcDstAddr,
  2704. pQuerySpi->Filter.SrcAddr,
  2705. pQuerySpi->Filter.DestAddr);
  2706. IPSEC_BUILD_PROTO_PORT_LI( uliProtoSrcDstPort,
  2707. pQuerySpi->Filter.Protocol,
  2708. pQuerySpi->Filter.SrcPort,
  2709. pQuerySpi->Filter.DestPort);
  2710. AcquireReadLock(&g_ipsec.SADBLock, &kIrql);
  2711. //
  2712. // search for SA
  2713. //
  2714. status = IPSecLookupSAByAddr( uliSrcDstAddr,
  2715. uliProtoSrcDstPort,
  2716. &pFilter,
  2717. &pSA,
  2718. &pNextSA,
  2719. &pTunnelSA,
  2720. FALSE,
  2721. FALSE,
  2722. FALSE);
  2723. if (!NT_SUCCESS(status)) {
  2724. IPSEC_DEBUG(ACQUIRE, ("IPSecQuerySPI: IPSecLookupSAByAddr failed: %lx\n", status));
  2725. ReleaseReadLock(&g_ipsec.SADBLock, kIrql);
  2726. return status;
  2727. }
  2728. if (status == STATUS_SUCCESS) {
  2729. ASSERT(pSA);
  2730. } else {
  2731. ReleaseReadLock(&g_ipsec.SADBLock, kIrql);
  2732. return STATUS_SUCCESS;
  2733. }
  2734. pQuerySpi->Spi = pSA->sa_SPI;
  2735. if (pSA->sa_AssociatedSA) {
  2736. pQuerySpi->OtherSpi = pSA->sa_AssociatedSA->sa_SPI;
  2737. }
  2738. pQuerySpi->Operation = pSA->sa_Operation[pSA->sa_NumOps-1];
  2739. ReleaseReadLock(&g_ipsec.SADBLock, kIrql);
  2740. return STATUS_SUCCESS;
  2741. }
  2742. NTSTATUS
  2743. IPSecSetOperationMode(
  2744. IN PIPSEC_SET_OPERATION_MODE pSetOperationMode
  2745. )
  2746. /*++
  2747. Routine Description:
  2748. Set the driver operation mode.
  2749. Arguments:
  2750. Return Value:
  2751. Notes:
  2752. --*/
  2753. {
  2754. g_ipsec.OperationMode = pSetOperationMode->OperationMode;
  2755. return STATUS_SUCCESS;
  2756. }
  2757. NTSTATUS
  2758. IPSecInitializeTcpip(
  2759. IN PIPSEC_SET_TCPIP_STATUS pSetTcpipStatus
  2760. )
  2761. /*++
  2762. Routine Description:
  2763. Initialize TCP/IP.
  2764. Arguments:
  2765. Return Value:
  2766. Notes:
  2767. --*/
  2768. {
  2769. IPInfo Info;
  2770. if (IPSEC_DRIVER_INIT_TCPIP()) {
  2771. return STATUS_SUCCESS;
  2772. }
  2773. //
  2774. // Store all TCP/IP function pointers for future use. There is no check
  2775. // for NULL pointer here because the function pointer can also be stale
  2776. // address. We trust TCP/IP to pass in the values corretly.
  2777. //
  2778. TCPIP_FREE_BUFF = pSetTcpipStatus->TcpipFreeBuff;
  2779. TCPIP_ALLOC_BUFF = pSetTcpipStatus->TcpipAllocBuff;
  2780. TCPIP_GET_INFO = pSetTcpipStatus->TcpipGetInfo;
  2781. TCPIP_NDIS_REQUEST = pSetTcpipStatus->TcpipNdisRequest;
  2782. TCPIP_SET_IPSEC_STATUS = pSetTcpipStatus->TcpipSetIPSecStatus;
  2783. TCPIP_SET_IPSEC = pSetTcpipStatus->TcpipSetIPSecPtr;
  2784. TCPIP_UNSET_IPSEC = pSetTcpipStatus->TcpipUnSetIPSecPtr;
  2785. TCPIP_UNSET_IPSEC_SEND = pSetTcpipStatus->TcpipUnSetIPSecSendPtr;
  2786. TCPIP_TCP_XSUM = pSetTcpipStatus->TcpipTCPXsum;
  2787. //
  2788. // Initialize IPInfo for reinjecting packets to TCP/IP.
  2789. //
  2790. if (TCPIP_GET_INFO(&Info, sizeof(IPInfo)) != IP_SUCCESS) {
  2791. ASSERT(FALSE);
  2792. return STATUS_BUFFER_TOO_SMALL;
  2793. }
  2794. Info.ipi_initopts(&g_ipsec.OptInfo);
  2795. //
  2796. // The followings come from IPInfo.
  2797. //
  2798. TCPIP_REGISTER_PROTOCOL = Info.ipi_protreg;
  2799. TCPIP_DEREGISTER_PROTOCOL = Info.ipi_protdereg;
  2800. TCPIP_IP_TRANSMIT = Info.ipi_xmit;
  2801. TCPIP_GET_ADDRTYPE = Info.ipi_getaddrtype;
  2802. TCPIP_GEN_IPID = Info.ipi_getipid;
  2803. //
  2804. // Don't register IPSecStatus function for AH and ESP protocol here.
  2805. // Registration occurs with filter addition.
  2806. //
  2807. //
  2808. // Everything is ready to go, bind to IP so we will intercept traffic.
  2809. //
  2810. IPSecBindToIP();
  2811. IPSEC_DRIVER_INIT_TCPIP() = TRUE;
  2812. return STATUS_SUCCESS;
  2813. }
  2814. NTSTATUS
  2815. IPSecDeinitializeTcpip(
  2816. VOID
  2817. )
  2818. /*++
  2819. Routine Description:
  2820. Deinitialize TCP/IP.
  2821. Arguments:
  2822. Return Value:
  2823. Notes:
  2824. --*/
  2825. {
  2826. if (!IPSEC_DRIVER_INIT_TCPIP()) {
  2827. return STATUS_SUCCESS;
  2828. }
  2829. IPSEC_DRIVER_INIT_TCPIP() = FALSE;
  2830. //
  2831. // Unbind IPSecHandlerPtr from TCP/IP and wait for all transmits, pending
  2832. // sends, worker threads and iotcls to complete.
  2833. //
  2834. IPSecUnbindSendFromIP();
  2835. //
  2836. // Wait for all threads (transmits) to finish.
  2837. //
  2838. while (IPSEC_GET_VALUE(g_ipsec.NumThreads) != 0) {
  2839. IPSEC_DELAY_EXECUTION();
  2840. }
  2841. //
  2842. // Wait for all pending IOCTLs to finish. Note this current IOCTL also
  2843. // takes one count.
  2844. //
  2845. while (IPSEC_GET_VALUE(g_ipsec.NumIoctls) != 1) {
  2846. IPSEC_DELAY_EXECUTION();
  2847. }
  2848. //
  2849. // Wait for all worker threads (logs or plumbs) to finish.
  2850. //
  2851. while (IPSEC_GET_VALUE(g_ipsec.NumWorkers) != 0) {
  2852. IPSEC_DELAY_EXECUTION();
  2853. }
  2854. //
  2855. // Wait for all send completes to go through.
  2856. //
  2857. while (IPSEC_GET_VALUE(g_ipsec.NumSends) != 0) {
  2858. IPSEC_DELAY_EXECUTION();
  2859. }
  2860. //
  2861. // Reset IPSecStatus functions in TCP/IP to NULL.
  2862. //
  2863. if (IPSEC_GET_VALUE(gdwInitEsp)) {
  2864. TCPIP_DEREGISTER_PROTOCOL(PROTOCOL_ESP);
  2865. IPSEC_SET_VALUE(gdwInitEsp, 0);
  2866. }
  2867. if (IPSEC_GET_VALUE(gdwInitAh)) {
  2868. TCPIP_DEREGISTER_PROTOCOL(PROTOCOL_AH);
  2869. IPSEC_SET_VALUE(gdwInitAh, 0);
  2870. }
  2871. //
  2872. // Unbind the rest of IPSec routines from TCP/IP.
  2873. //
  2874. IPSecUnbindFromIP();
  2875. return STATUS_SUCCESS;
  2876. }
  2877. NTSTATUS
  2878. IPSecSetTcpipStatus(
  2879. IN PIPSEC_SET_TCPIP_STATUS pSetTcpipStatus
  2880. )
  2881. /*++
  2882. Routine Description:
  2883. Set the TCP/IP driver status indicating whether can register with it.
  2884. Arguments:
  2885. Return Value:
  2886. Notes:
  2887. --*/
  2888. {
  2889. PAGED_CODE();
  2890. if (pSetTcpipStatus->TcpipStatus) {
  2891. return IPSecInitializeTcpip(pSetTcpipStatus);
  2892. } else {
  2893. return IPSecDeinitializeTcpip();
  2894. }
  2895. }
  2896. NTSTATUS
  2897. IPSecResetCacheTable(
  2898. VOID
  2899. )
  2900. /*++
  2901. Routine Description:
  2902. Invalidate all cache entries and its associated SA or Filter.
  2903. Arguments:
  2904. Return Value:
  2905. Notes:
  2906. --*/
  2907. {
  2908. PFILTER_CACHE pCache;
  2909. ULONG i;
  2910. for (i = 0; i < g_ipsec.CacheSize; i ++) {
  2911. pCache = g_ipsec.ppCache[i];
  2912. if (pCache && IS_VALID_CACHE_ENTRY(pCache)) {
  2913. if (pCache->FilterEntry) {
  2914. pCache->pFilter->FilterCache = NULL;
  2915. } else {
  2916. pCache->pSAEntry->sa_FilterCache = NULL;
  2917. if (pCache->pNextSAEntry) {
  2918. pCache->pNextSAEntry->sa_FilterCache = NULL;
  2919. }
  2920. }
  2921. INVALIDATE_CACHE_ENTRY(pCache);
  2922. }
  2923. }
  2924. return STATUS_SUCCESS;
  2925. }
  2926. NTSTATUS
  2927. IPSecPurgeFilterSAs(
  2928. IN PFILTER pFilter
  2929. )
  2930. /*++
  2931. Routine Description
  2932. Delete all SAs that are related to this filter.
  2933. Locks
  2934. Called with SADB held.
  2935. Arguments
  2936. pFilter - filter of interest
  2937. Return Value
  2938. STATUS_SUCCESS
  2939. --*/
  2940. {
  2941. PLIST_ENTRY pEntry;
  2942. PSA_TABLE_ENTRY pSA;
  2943. KIRQL kIrql;
  2944. LONG Index;
  2945. //
  2946. // Expire each inbound SA and delete outbound SA
  2947. //
  2948. for (Index = 0; Index < pFilter->SAChainSize; Index ++) {
  2949. pEntry = pFilter->SAChain[Index].Flink;
  2950. while (pEntry != &pFilter->SAChain[Index]) {
  2951. pSA = CONTAINING_RECORD(pEntry,
  2952. SA_TABLE_ENTRY,
  2953. sa_FilterLinkage);
  2954. pEntry = pEntry->Flink;
  2955. if (pSA->sa_State == STATE_SA_ACTIVE) {
  2956. IPSEC_DEBUG(ACQUIRE, ("Destroying active SA: %lx\n", pSA));
  2957. //
  2958. // Filter is going away, SA must be deleted now
  2959. //
  2960. if (!(pSA->sa_Flags & FLAGS_SA_OUTBOUND)) {
  2961. //ASSERT(pSA->sa_AssociatedSA);
  2962. IPSecDeleteInboundSA(pSA);
  2963. } else {
  2964. ASSERT(pSA->sa_AssociatedSA);
  2965. if (pSA->sa_AssociatedSA->sa_State == STATE_SA_ASSOCIATED) {
  2966. IPSecDeleteLarvalSA(pSA->sa_AssociatedSA);
  2967. } else {
  2968. IPSecDeleteInboundSA(pSA->sa_AssociatedSA);
  2969. }
  2970. }
  2971. } else {
  2972. IPSEC_DEBUG(ACQUIRE, ("Destroying larval SA: %lx\n", pSA));
  2973. //
  2974. // SA undergoing negotiation - just invalidate the context.
  2975. // the timer will take care of the rest
  2976. //
  2977. if (pSA->sa_AssociatedSA) {
  2978. if (pSA->sa_AssociatedSA->sa_AcquireCtx) {
  2979. IPSecInvalidateHandle(pSA->sa_AssociatedSA->sa_AcquireCtx);
  2980. pSA->sa_AssociatedSA->sa_AcquireCtx = NULL;
  2981. }
  2982. }
  2983. IPSecDeleteLarvalSA(pSA);
  2984. }
  2985. }
  2986. }
  2987. //
  2988. // Also need to remove all those larval SAs whose sa_Filter is pointing
  2989. // to the filter being deleted.
  2990. //
  2991. ACQUIRE_LOCK(&g_ipsec.LarvalListLock, &kIrql);
  2992. pEntry = g_ipsec.LarvalSAList.Flink;
  2993. while (pEntry != &g_ipsec.LarvalSAList) {
  2994. pSA = CONTAINING_RECORD(pEntry,
  2995. SA_TABLE_ENTRY,
  2996. sa_LarvalLinkage);
  2997. pEntry = pEntry->Flink;
  2998. if (pSA->sa_Filter == pFilter) {
  2999. IPSecRemoveEntryList(&pSA->sa_LarvalLinkage);
  3000. IPSEC_DEC_STATISTIC(dwNumPendingKeyOps);
  3001. IPSecCleanupLarvalSA(pSA);
  3002. }
  3003. }
  3004. RELEASE_LOCK(&g_ipsec.LarvalListLock, kIrql);
  3005. return STATUS_SUCCESS;
  3006. }
  3007. NTSTATUS
  3008. IPSecSetupSALifetime(
  3009. IN PSA_TABLE_ENTRY pSA
  3010. )
  3011. /*++
  3012. Routine Description:
  3013. Setup the SA lifetime characteristics for rekey and idle timeout.
  3014. Arguments:
  3015. Return Value:
  3016. --*/
  3017. {
  3018. LARGE_INTEGER CurrentTime;
  3019. LARGE_INTEGER Delta = {0};
  3020. LARGE_INTEGER Pad = {(pSA->sa_Flags & FLAGS_SA_INITIATOR)?
  3021. IPSEC_EXPIRE_TIME_PAD_I :
  3022. IPSEC_EXPIRE_TIME_PAD_R,
  3023. 0};
  3024. //
  3025. // pSA->sa_Lifetime.KeyExpirationTime is in seconds.
  3026. //
  3027. if (pSA->sa_Lifetime.KeyExpirationTime) {
  3028. IPSEC_CONVERT_SECS_TO_100NS(Delta, pSA->sa_Lifetime.KeyExpirationTime);
  3029. NdisGetCurrentSystemTime(&CurrentTime);
  3030. pSA->sa_KeyExpirationTime.QuadPart = (CurrentTime.QuadPart + Delta.QuadPart);
  3031. pSA->sa_KeyExpirationTimeWithPad.QuadPart = pSA->sa_KeyExpirationTime.QuadPart - Pad.QuadPart;
  3032. if (!(pSA->sa_KeyExpirationTimeWithPad.QuadPart > 0i64)) {
  3033. pSA->sa_KeyExpirationTimeWithPad.QuadPart = 0i64;
  3034. }
  3035. }
  3036. //
  3037. // pSA->sa_Lifetime.KeyExpirationBytes is in Kbytes.
  3038. //
  3039. if (pSA->sa_Lifetime.KeyExpirationBytes) {
  3040. pSA->sa_KeyExpirationBytes.LowPart = pSA->sa_Lifetime.KeyExpirationBytes;
  3041. pSA->sa_KeyExpirationBytes = EXTENDED_MULTIPLY(pSA->sa_KeyExpirationBytes, 1024);
  3042. if (pSA->sa_Flags & FLAGS_SA_INITIATOR) {
  3043. pSA->sa_KeyExpirationBytesWithPad.LowPart = pSA->sa_Lifetime.KeyExpirationBytes * IPSEC_EXPIRE_THRESHOLD_I / 100;
  3044. } else {
  3045. pSA->sa_KeyExpirationBytesWithPad.LowPart = pSA->sa_Lifetime.KeyExpirationBytes * IPSEC_EXPIRE_THRESHOLD_R / 100;
  3046. }
  3047. pSA->sa_KeyExpirationBytesWithPad = EXTENDED_MULTIPLY(pSA->sa_KeyExpirationBytesWithPad, 1024);
  3048. }
  3049. //
  3050. // Also setup the idle timeout characteristics.
  3051. //
  3052. if (pSA->sa_Flags & FLAGS_SA_INITIATOR) {
  3053. IPSEC_CONVERT_SECS_TO_100NS(pSA->sa_IdleTime,
  3054. (g_ipsec.DefaultSAIdleTime + IPSEC_DEFAULT_SA_IDLE_TIME_PAD_I));
  3055. } else {
  3056. IPSEC_CONVERT_SECS_TO_100NS(pSA->sa_IdleTime,
  3057. (g_ipsec.DefaultSAIdleTime + IPSEC_DEFAULT_SA_IDLE_TIME_PAD_R));
  3058. }
  3059. return STATUS_SUCCESS;
  3060. }
  3061. DWORD ConvertAddr(IPAddr Addr, IPAddr Mask, ADDR* OutAddr)
  3062. {
  3063. if (Mask == 0xffffffff) {
  3064. OutAddr->AddrType=IP_ADDR_UNIQUE;
  3065. } else {
  3066. OutAddr->AddrType=IP_ADDR_SUBNET;
  3067. }
  3068. OutAddr->uSubNetMask=Mask;
  3069. OutAddr->uIpAddr=Addr;
  3070. return STATUS_SUCCESS;
  3071. }
  3072. DWORD ConvertSAToIPSecQMSA(PIPSEC_QM_SA pOutSA,
  3073. PSA_TABLE_ENTRY pInSA)
  3074. /*++
  3075. Routine Description:
  3076. Convert SA_TABLE_ENTRY to IPSEC_QM_SA
  3077. Arguments:
  3078. Return Value:
  3079. --*/
  3080. {
  3081. int i;
  3082. memcpy(&pOutSA->gQMPolicyID,&pInSA->sa_Filter->PolicyId,sizeof(GUID));
  3083. memcpy(&pOutSA->gQMFilterID,&pInSA->sa_Filter->FilterId,sizeof(GUID));
  3084. memcpy(&pOutSA->MMSpi.Initiator,&pInSA->sa_CookiePair.Initiator,sizeof(IKE_COOKIE));
  3085. memcpy(&pOutSA->MMSpi.Responder,&pInSA->sa_CookiePair.Responder,sizeof(IKE_COOKIE));
  3086. ConvertAddr(pInSA->SA_SRC_ADDR,pInSA->SA_SRC_MASK,&pOutSA->IpsecQMFilter.SrcAddr);
  3087. ConvertAddr(pInSA->SA_DEST_ADDR,pInSA->SA_DEST_MASK,&pOutSA->IpsecQMFilter.DesAddr);
  3088. pOutSA->IpsecQMFilter.Protocol.ProtocolType=PROTOCOL_UNIQUE;
  3089. pOutSA->IpsecQMFilter.Protocol.dwProtocol=pInSA->SA_PROTO;
  3090. pOutSA->IpsecQMFilter.SrcPort.PortType=PORT_UNIQUE;
  3091. pOutSA->IpsecQMFilter.SrcPort.wPort=NET_SHORT(SA_SRC_PORT(pInSA));
  3092. pOutSA->IpsecQMFilter.DesPort.PortType=PORT_UNIQUE;
  3093. pOutSA->IpsecQMFilter.DesPort.wPort=NET_SHORT(SA_DEST_PORT(pInSA));
  3094. if (pInSA->sa_Flags & FLAGS_SA_TUNNEL) {
  3095. pOutSA->IpsecQMFilter.QMFilterType = QM_TUNNEL_FILTER;
  3096. ConvertAddr(pInSA->sa_SrcTunnelAddr,0xffffffff,&pOutSA->IpsecQMFilter.MyTunnelEndpt);
  3097. ConvertAddr(pInSA->sa_TunnelAddr,0xffffffff,&pOutSA->IpsecQMFilter.PeerTunnelEndpt);
  3098. } else {
  3099. pOutSA->IpsecQMFilter.QMFilterType = QM_TRANSPORT_FILTER;
  3100. }
  3101. pOutSA->SelectedQMOffer.dwPFSGroup=pInSA->sa_QMPFSGroup;
  3102. if (pOutSA->SelectedQMOffer.dwPFSGroup) {
  3103. pOutSA->SelectedQMOffer.bPFSRequired=TRUE;
  3104. }
  3105. pOutSA->SelectedQMOffer.Lifetime.uKeyExpirationTime=pInSA->sa_Lifetime.KeyExpirationTime;
  3106. pOutSA->SelectedQMOffer.Lifetime.uKeyExpirationKBytes=pInSA->sa_Lifetime.KeyExpirationBytes;
  3107. pOutSA->SelectedQMOffer.dwNumAlgos=pInSA->sa_NumOps;
  3108. for (i=0; i < pInSA->sa_NumOps;i++) {
  3109. pOutSA->SelectedQMOffer.Algos[i].Operation=pInSA->sa_Operation[i];
  3110. if (pInSA->sa_AssociatedSA) {
  3111. pOutSA->SelectedQMOffer.Algos[i].MySpi= pInSA->sa_AssociatedSA->sa_OtherSPIs[i];
  3112. }
  3113. pOutSA->SelectedQMOffer.Algos[i].PeerSpi= pInSA->sa_OtherSPIs[i];
  3114. switch(pOutSA->SelectedQMOffer.Algos[i].Operation) {
  3115. case AUTHENTICATION:
  3116. pOutSA->SelectedQMOffer.Algos[i].uAlgoIdentifier=pInSA->INT_ALGO(i);
  3117. pOutSA->SelectedQMOffer.Algos[i].uAlgoKeyLen=pInSA->INT_KEYLEN(i);
  3118. pOutSA->SelectedQMOffer.Algos[i].uAlgoRounds=pInSA->INT_ROUNDS(i);
  3119. break;
  3120. case ENCRYPTION:
  3121. pOutSA->SelectedQMOffer.Algos[i].uAlgoIdentifier=pInSA->CONF_ALGO(i);
  3122. pOutSA->SelectedQMOffer.Algos[i].uAlgoKeyLen=pInSA->CONF_KEYLEN(i);
  3123. pOutSA->SelectedQMOffer.Algos[i].uAlgoRounds=pInSA->CONF_ROUNDS(i);
  3124. pOutSA->SelectedQMOffer.Algos[i].uSecAlgoIdentifier=pInSA->INT_ALGO(i);
  3125. pOutSA->SelectedQMOffer.Algos[i].uSecAlgoKeyLen=pInSA->INT_KEYLEN(i);
  3126. break;
  3127. default:
  3128. break;
  3129. }
  3130. }
  3131. return STATUS_SUCCESS;
  3132. }
  3133. BOOLEAN
  3134. IPSecMatchSATemplate(
  3135. IN PSA_TABLE_ENTRY pSA,
  3136. IN PIPSEC_QM_SA pSATemplate
  3137. )
  3138. /*++
  3139. Routine Description:
  3140. Try to see if the SA passed in matches the template.
  3141. Arguments:
  3142. pSA - SA of interest
  3143. pSATemplate - SA template
  3144. Return Value:
  3145. TRUE/FALSE
  3146. --*/
  3147. {
  3148. LARGE_INTEGER ZeroLI = {0};
  3149. ADDR ZeroADDR = {0};
  3150. PROTOCOL ZeroPROTOCOL = {0};
  3151. PORT ZeroPORT = {0};
  3152. IPSEC_QM_SA CurSA;
  3153. memset(&CurSA,0,sizeof(IPSEC_QM_SA));
  3154. ConvertSAToIPSecQMSA(&CurSA,pSA);
  3155. return((BOOLEAN)MatchQMSATemplate(pSATemplate,&CurSA));
  3156. }