Leaked source code of windows server 2003
You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

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