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.

1048 lines
29 KiB

  1. #include "precomp.h"
  2. #ifdef RUN_WPP
  3. #include "acquire.tmh"
  4. #endif
  5. #pragma hdrstop
  6. VOID
  7. IPSecCompleteIrp(
  8. PIRP pIrp,
  9. NTSTATUS ntStatus
  10. )
  11. /*++
  12. Routine Description:
  13. This Routine handles calling the NT I/O system to complete an I/O.
  14. Arguments:
  15. pIrp - Irp which needs to be completed.
  16. ntStatus - The completion status for the Irp.
  17. Return Value:
  18. None.
  19. --*/
  20. {
  21. KIRQL kIrql;
  22. #if DBG
  23. if (!NT_SUCCESS(ntStatus)) {
  24. IPSEC_DEBUG(LL_A,DBF_ACQUIRE, ("IPSecCompleteIrp: Completion status = %X", ntStatus));
  25. }
  26. #endif
  27. pIrp->IoStatus.Status = ntStatus;
  28. //
  29. // Set the cancel routine for the Irp to NULL or the system may bugcheck
  30. // with a bug code of CANCEL_STATE_IN_COMPLETED_IRP.
  31. //
  32. IoAcquireCancelSpinLock(&kIrql);
  33. IoSetCancelRoutine(pIrp, NULL);
  34. IoReleaseCancelSpinLock(kIrql);
  35. IoCompleteRequest(pIrp, IO_NETWORK_INCREMENT);
  36. return;
  37. }
  38. VOID
  39. IPSecInvalidateHandle(
  40. PIPSEC_ACQUIRE_CONTEXT pIpsecAcquireContext
  41. )
  42. /*++
  43. Routine Description:
  44. This routine invalidates an acquire handle by freeing the memory location.
  45. Arguments:
  46. pIpsecAcquireContext - The Acquire context.
  47. Return Value:
  48. None.
  49. --*/
  50. {
  51. ASSERT(pIpsecAcquireContext);
  52. if (pIpsecAcquireContext) {
  53. ASSERT(pIpsecAcquireContext->pSA);
  54. ASSERT(
  55. pIpsecAcquireContext->pSA->sa_AcquireId ==
  56. pIpsecAcquireContext->AcquireId
  57. );
  58. pIpsecAcquireContext->AcquireId = 0;
  59. IPSecFreeMemory(pIpsecAcquireContext);
  60. }
  61. return;
  62. }
  63. NTSTATUS
  64. IPSecValidateHandle(
  65. ULONG AcquireId,
  66. PIPSEC_ACQUIRE_CONTEXT *pIpsecAcquireContext,
  67. SA_STATE SAState
  68. )
  69. /*++
  70. Routine Description:
  71. This routine validates an acquire handle by matching the unique signature
  72. in the handle with that in the SA and ensuring that the SA state matches
  73. the SA state in the input.
  74. Called with Larval List Lock held; returns with it.
  75. Arguments:
  76. pIpsecAcquireContext - The Acquire context.
  77. SAState - State in which the SA is expected to be in.
  78. Return Value:
  79. NTSTATUS - Status after the validation.
  80. --*/
  81. {
  82. PSA_TABLE_ENTRY pSA = NULL;
  83. BOOL bFound = FALSE;
  84. PLIST_ENTRY pEntry = NULL;
  85. if (AcquireId < MIN_ACQUIRE_ID) {
  86. return STATUS_UNSUCCESSFUL;
  87. }
  88. //
  89. // Walk through the larval SA list to see if there is an SA
  90. // with this context value.
  91. //
  92. for (pEntry = g_ipsec.LarvalSAList.Flink;
  93. pEntry != &g_ipsec.LarvalSAList;
  94. pEntry = pEntry->Flink) {
  95. pSA = CONTAINING_RECORD(
  96. pEntry,
  97. SA_TABLE_ENTRY,
  98. sa_LarvalLinkage
  99. );
  100. if (pSA->sa_AcquireId == AcquireId) {
  101. bFound = TRUE;
  102. break;
  103. }
  104. }
  105. if (bFound) {
  106. *pIpsecAcquireContext = pSA->sa_AcquireCtx;
  107. if (!(*pIpsecAcquireContext)) {
  108. return STATUS_UNSUCCESSFUL;
  109. }
  110. if (!(*pIpsecAcquireContext)->pSA) {
  111. return STATUS_UNSUCCESSFUL;
  112. }
  113. if ((*pIpsecAcquireContext)->pSA != pSA) {
  114. return STATUS_UNSUCCESSFUL;
  115. }
  116. if (pSA->sa_Signature == IPSEC_SA_SIGNATURE) {
  117. if (pSA->sa_State == SAState) {
  118. return STATUS_SUCCESS;
  119. }
  120. }
  121. }
  122. return STATUS_UNSUCCESSFUL;
  123. }
  124. VOID
  125. IPSecAbortAcquire(
  126. PIPSEC_ACQUIRE_CONTEXT pIpsecAcquireContext
  127. )
  128. /*++
  129. Routine Description:
  130. This routine aborts the acquire operation because of insufficient
  131. resources or invalid parameters.
  132. Arguments:
  133. pIpsecAcquireContext - The acquire context.
  134. Called with both the SADB and the LarvalSAList locks held; returns with them.
  135. Return Value:
  136. None.
  137. --*/
  138. {
  139. PSA_TABLE_ENTRY pSA = NULL;
  140. PSA_TABLE_ENTRY pOutboundSA = NULL;
  141. BOOL bIsTimerStopped = FALSE;
  142. KIRQL kSPIIrql;
  143. pSA = pIpsecAcquireContext->pSA;
  144. ASSERT(pSA->sa_Flags & FLAGS_SA_TIMER_STARTED);
  145. bIsTimerStopped = IPSecStopTimer(&pSA->sa_Timer);
  146. if (!bIsTimerStopped) {
  147. return;
  148. }
  149. pSA->sa_Flags &= ~FLAGS_SA_TIMER_STARTED;
  150. //
  151. // The larval list is already locked so that this SA does not go away.
  152. //
  153. ASSERT((pSA->sa_Flags & FLAGS_SA_OUTBOUND) == 0);
  154. if (pSA->sa_AcquireCtx) {
  155. IPSecInvalidateHandle(pSA->sa_AcquireCtx);
  156. pSA->sa_AcquireCtx = NULL;
  157. }
  158. //
  159. // Remove from the larval list.
  160. //
  161. IPSecRemoveEntryList(&pSA->sa_LarvalLinkage);
  162. IPSEC_DEC_STATISTIC(dwNumPendingKeyOps);
  163. //
  164. // Flush all the queued packets for this SA.
  165. //
  166. IPSecFlushQueuedPackets(pSA, STATUS_TIMEOUT);
  167. //
  168. // Remove the SA from the inbound SA list.
  169. //
  170. AcquireWriteLock(&g_ipsec.SPIListLock, &kSPIIrql);
  171. IPSecRemoveSPIEntry(pSA);
  172. ReleaseWriteLock(&g_ipsec.SPIListLock, kSPIIrql);
  173. //
  174. // Also remove the SA from the filter list.
  175. //
  176. if (pSA->sa_Flags & FLAGS_SA_ON_FILTER_LIST) {
  177. pSA->sa_Flags &= ~FLAGS_SA_ON_FILTER_LIST;
  178. IPSecRemoveEntryList(&pSA->sa_FilterLinkage);
  179. }
  180. if (pSA->sa_RekeyOriginalSA) {
  181. ASSERT(pSA->sa_Flags & FLAGS_SA_REKEY);
  182. ASSERT(pSA->sa_RekeyOriginalSA->sa_RekeyLarvalSA == pSA);
  183. ASSERT(pSA->sa_RekeyOriginalSA->sa_Flags & FLAGS_SA_REKEY_ORI);
  184. pSA->sa_RekeyOriginalSA->sa_Flags &= ~FLAGS_SA_REKEY_ORI;
  185. pSA->sa_RekeyOriginalSA->sa_RekeyLarvalSA = NULL;
  186. pSA->sa_RekeyOriginalSA = NULL;
  187. }
  188. //
  189. // Invalidate the associated cache entry.
  190. //
  191. IPSecInvalidateSACacheEntry(pSA);
  192. pOutboundSA = pSA->sa_AssociatedSA;
  193. if (pOutboundSA) {
  194. pSA->sa_AssociatedSA = NULL;
  195. if (pOutboundSA->sa_Flags & FLAGS_SA_ON_FILTER_LIST) {
  196. pOutboundSA->sa_Flags &= ~FLAGS_SA_ON_FILTER_LIST;
  197. IPSecRemoveEntryList(&pOutboundSA->sa_FilterLinkage);
  198. }
  199. //
  200. // Invalidate the associated cache entry.
  201. //
  202. IPSecInvalidateSACacheEntry(pOutboundSA);
  203. IPSEC_DEC_STATISTIC(dwNumActiveAssociations);
  204. IPSEC_DEC_TUNNELS(pOutboundSA);
  205. IPSEC_DECREMENT(g_ipsec.NumOutboundSAs);
  206. IPSEC_DEBUG(LL_A,DBF_REF, ("IPSecAbortAcquire: Outbound SA Dereference."));
  207. IPSecStopTimerDerefSA(pOutboundSA);
  208. } else {
  209. ASSERT (pSA->sa_State == STATE_SA_LARVAL_ACTIVE || pSA->sa_State == STATE_SA_LARVAL);
  210. }
  211. IPSecDerefSA(pSA);
  212. return;
  213. }
  214. NTSTATUS
  215. IPSecCheckSetCancelRoutine(
  216. PIRP pIrp,
  217. PVOID pCancelRoutine
  218. )
  219. /*++
  220. Routine Description:
  221. This Routine sets the cancel routine for an Irp.
  222. Arguments:
  223. pIrp - Irp for which the cancel routine is to be set.
  224. pCancelRoutine - Cancel routine to be set in the Irp.
  225. Return Value:
  226. NTSTATUS - Status for the request.
  227. --*/
  228. {
  229. NTSTATUS ntStatus = STATUS_SUCCESS;
  230. //
  231. // Check if the irp has been cancelled and if not, then set the
  232. // irp cancel routine.
  233. //
  234. IoAcquireCancelSpinLock(&pIrp->CancelIrql);
  235. if (pIrp->Cancel) {
  236. pIrp->IoStatus.Status = STATUS_CANCELLED;
  237. ntStatus = STATUS_CANCELLED;
  238. }
  239. else {
  240. IoMarkIrpPending(pIrp);
  241. IoSetCancelRoutine(pIrp, pCancelRoutine);
  242. ntStatus = STATUS_SUCCESS;
  243. }
  244. IoReleaseCancelSpinLock(pIrp->CancelIrql);
  245. return (ntStatus);
  246. }
  247. NTSTATUS
  248. IPSecSubmitAcquire(
  249. PSA_TABLE_ENTRY pLarvalSA,
  250. KIRQL OldIrq,
  251. BOOLEAN PostAcquire
  252. )
  253. /*++
  254. Routine Description:
  255. This function is used to submit an Acquire request to the key manager
  256. Arguments:
  257. pLarvalSA - larval SA that needs to be negotiated
  258. OldIrq - prev irq - lock released here.
  259. NOTE: called with AcquireInfo lock held.
  260. Return Value:
  261. STATUS_PENDING if the buffer is to be held on to , the normal case.
  262. Notes:
  263. --*/
  264. {
  265. NTSTATUS status;
  266. PIRP pIrp;
  267. if (!g_ipsec.AcquireInfo.Irp) {
  268. //
  269. // the irp either never made it down here, or it was cancelled,
  270. // so drop all frames
  271. //
  272. IPSEC_DEBUG(LL_A,DBF_ACQUIRE, ("IPSecSubmitAcquire: Irp is NULL, returning\r"));
  273. if (!PostAcquire) {
  274. RELEASE_LOCK(&g_ipsec.AcquireInfo.Lock, OldIrq);
  275. }
  276. return STATUS_BAD_NETWORK_PATH;
  277. } else if (!g_ipsec.AcquireInfo.ResolvingNow) {
  278. PIPSEC_ACQUIRE_CONTEXT pAcquireCtx;
  279. PVOID pvIoBuffer;
  280. //
  281. // Irp is free now - use it
  282. //
  283. pIrp = g_ipsec.AcquireInfo.Irp;
  284. IPSEC_DEBUG(LL_A,DBF_ACQUIRE, ("Using Irp.. : %p", pIrp));
  285. //
  286. // Get the Acquire Context and associate with the Larval SA
  287. //
  288. pAcquireCtx = IPSecGetAcquireContext();
  289. if (!pAcquireCtx) {
  290. IPSEC_DEBUG(LL_A,DBF_ACQUIRE, ("Failed to get acquire ctx"));
  291. if (!PostAcquire){
  292. RELEASE_LOCK(&g_ipsec.AcquireInfo.Lock,OldIrq);
  293. }
  294. return STATUS_INSUFFICIENT_RESOURCES;
  295. }
  296. //
  297. // Set ResolvingNow only after memory allocation (282645).
  298. //
  299. g_ipsec.AcquireInfo.ResolvingNow = TRUE;
  300. pAcquireCtx->AcquireId = IPSecGetAcquireId();
  301. pAcquireCtx->pSA = pLarvalSA;
  302. pLarvalSA->sa_AcquireCtx = pAcquireCtx;
  303. pLarvalSA->sa_AcquireId = pAcquireCtx->AcquireId;
  304. //
  305. // Set up the Irp params
  306. //
  307. pvIoBuffer = pIrp->AssociatedIrp.SystemBuffer;
  308. ((PIPSEC_POST_FOR_ACQUIRE_SA)pvIoBuffer)->IdentityInfo = NULL;
  309. ((PIPSEC_POST_FOR_ACQUIRE_SA)pvIoBuffer)->Context = UlongToHandle(pAcquireCtx->AcquireId);
  310. ((PIPSEC_POST_FOR_ACQUIRE_SA)pvIoBuffer)->PolicyId = pLarvalSA->sa_Filter->PolicyId;
  311. //
  312. // Instead of reversing, use the originating filters addresses
  313. //
  314. ((PIPSEC_POST_FOR_ACQUIRE_SA)pvIoBuffer)->SrcAddr = pLarvalSA->SA_DEST_ADDR;
  315. ((PIPSEC_POST_FOR_ACQUIRE_SA)pvIoBuffer)->SrcMask = pLarvalSA->SA_DEST_MASK;
  316. ((PIPSEC_POST_FOR_ACQUIRE_SA)pvIoBuffer)->DestAddr = pLarvalSA->SA_SRC_ADDR;
  317. ((PIPSEC_POST_FOR_ACQUIRE_SA)pvIoBuffer)->DestMask = pLarvalSA->SA_SRC_MASK;
  318. ((PIPSEC_POST_FOR_ACQUIRE_SA)pvIoBuffer)->Protocol = pLarvalSA->SA_PROTO;
  319. ((PIPSEC_POST_FOR_ACQUIRE_SA)pvIoBuffer)->TunnelFilter = pLarvalSA->sa_Filter->TunnelFilter;
  320. //
  321. // the tunnel addr is in the corresp. outbound filter.
  322. //
  323. ((PIPSEC_POST_FOR_ACQUIRE_SA)pvIoBuffer)->TunnelAddr = pLarvalSA->sa_Filter->TunnelAddr;
  324. ((PIPSEC_POST_FOR_ACQUIRE_SA)pvIoBuffer)->InboundTunnelAddr = pLarvalSA->sa_TunnelAddr;
  325. ((PIPSEC_POST_FOR_ACQUIRE_SA)pvIoBuffer)->SrcPort = SA_DEST_PORT(pLarvalSA);
  326. ((PIPSEC_POST_FOR_ACQUIRE_SA)pvIoBuffer)->DestPort = SA_SRC_PORT(pLarvalSA);
  327. ((PIPSEC_POST_FOR_ACQUIRE_SA)pvIoBuffer)->DestType = 0;
  328. if (IS_BCAST_DEST(pLarvalSA->sa_DestType)) {
  329. ((PIPSEC_POST_FOR_ACQUIRE_SA)pvIoBuffer)->DestType |= IPSEC_BCAST;
  330. }
  331. if (IS_MCAST_DEST(pLarvalSA->sa_DestType)) {
  332. ((PIPSEC_POST_FOR_ACQUIRE_SA)pvIoBuffer)->DestType |= IPSEC_MCAST;
  333. }
  334. ((PIPSEC_POST_FOR_ACQUIRE_SA)pvIoBuffer)->SrcEncapPort = pLarvalSA->sa_EncapContext.wSrcEncapPort;
  335. ((PIPSEC_POST_FOR_ACQUIRE_SA)pvIoBuffer)->DestEncapPort = pLarvalSA->sa_EncapContext.wDesEncapPort;
  336. pIrp->IoStatus.Information = sizeof(IPSEC_POST_FOR_ACQUIRE_SA);
  337. g_ipsec.AcquireInfo.InMe = FALSE;
  338. pLarvalSA->sa_Flags &= ~FLAGS_SA_PENDING;
  339. if (PostAcquire) {
  340. status = STATUS_SUCCESS;
  341. } else {
  342. RELEASE_LOCK(&g_ipsec.AcquireInfo.Lock,OldIrq);
  343. IPSEC_DEBUG(LL_A,DBF_ACQUIRE, ("Completing Irp.. : %p", pIrp));
  344. IPSecCompleteIrp(pIrp, STATUS_SUCCESS);
  345. status = STATUS_PENDING;
  346. }
  347. IPSEC_DEBUG(LL_A,DBF_ACQUIRE, ("IPSecSubmitAcquire: submitted context: %p, SA: %p",
  348. pAcquireCtx,
  349. pLarvalSA));
  350. } else {
  351. //
  352. // The irp is busy negotiating another SA
  353. // Queue the Larval SA
  354. //
  355. InsertTailList( &g_ipsec.AcquireInfo.PendingAcquires,
  356. &pLarvalSA->sa_PendingLinkage);
  357. pLarvalSA->sa_Flags |= FLAGS_SA_PENDING;
  358. status = STATUS_PENDING;
  359. if (!PostAcquire){
  360. RELEASE_LOCK(&g_ipsec.AcquireInfo.Lock, OldIrq);
  361. }
  362. IPSEC_DEBUG(LL_A,DBF_ACQUIRE, ("IPSecSubmitAcquire: queued SA: %p", pLarvalSA));
  363. }
  364. return status;
  365. }
  366. NTSTATUS
  367. IPSecHandleAcquireRequest(
  368. PIRP pIrp,
  369. PIPSEC_POST_FOR_ACQUIRE_SA pIpsecPostAcquireSA
  370. )
  371. /*++
  372. Routine Description:
  373. This routine receives an acquire request from the key manager and
  374. either completes it instantly to submit a new SA negotiation or pends
  375. it for further negotiations.
  376. Arguments:
  377. pIrp - The Irp.
  378. pIpsecPostAcquireSA - Buffer for filling in the policy ID for forcing
  379. an SA negotiation.
  380. Return Value:
  381. STATUS_PENDING - If the buffer is to be held on to, the normal case.
  382. --*/
  383. {
  384. NTSTATUS status = STATUS_PENDING;
  385. KIRQL OldIrq;
  386. PVOID Context;
  387. BOOLEAN fIrpCompleted = FALSE;
  388. PSA_TABLE_ENTRY pLarvalSA;
  389. // Make sure this lock is not released till the end of
  390. // this function
  391. ACQUIRE_LOCK(&g_ipsec.AcquireInfo.Lock, &OldIrq);
  392. if (g_ipsec.AcquireInfo.InMe) {
  393. IPSEC_DEBUG(LL_A,DBF_ACQUIRE, ("Irp re-submited!: %p", g_ipsec.AcquireInfo.Irp));
  394. RELEASE_LOCK(&g_ipsec.AcquireInfo.Lock, OldIrq);
  395. return STATUS_INVALID_PARAMETER;
  396. }
  397. g_ipsec.AcquireInfo.Irp = pIrp;
  398. // ASSERT(g_ipsec.AcquireInfo.ResolvingNow);
  399. g_ipsec.AcquireInfo.ResolvingNow = FALSE;
  400. //
  401. // if there are pending SA negotiations, submit next
  402. //
  403. while (TRUE) {
  404. if (!IsListEmpty(&g_ipsec.AcquireInfo.PendingAcquires)) {
  405. PLIST_ENTRY pEntry;
  406. pEntry = RemoveHeadList(&g_ipsec.AcquireInfo.PendingAcquires);
  407. pLarvalSA = CONTAINING_RECORD( pEntry,
  408. SA_TABLE_ENTRY,
  409. sa_PendingLinkage);
  410. ASSERT(pLarvalSA->sa_State == STATE_SA_LARVAL);
  411. ASSERT(pLarvalSA->sa_Flags & FLAGS_SA_PENDING);
  412. pLarvalSA->sa_Flags &= ~FLAGS_SA_PENDING;
  413. //
  414. // submit... will not release the AcquireInfo lock if PostAcquire is true
  415. //
  416. status = IPSecSubmitAcquire(pLarvalSA, OldIrq, TRUE);
  417. //
  418. // if it failed then complete the irp now
  419. //
  420. if (NT_SUCCESS(status)) {
  421. fIrpCompleted = TRUE;
  422. IPSEC_DEBUG(LL_A,DBF_ACQUIRE, ("Acquire Irp completed inline"));
  423. break;
  424. }
  425. } else if (!IsListEmpty(&g_ipsec.AcquireInfo.PendingNotifies)) {
  426. PLIST_ENTRY pEntry;
  427. PIPSEC_NOTIFY_EXPIRE pNotifyExpire;
  428. pEntry = RemoveHeadList(&g_ipsec.AcquireInfo.PendingNotifies);
  429. pNotifyExpire = CONTAINING_RECORD( pEntry,
  430. IPSEC_NOTIFY_EXPIRE,
  431. notify_PendingLinkage);
  432. ASSERT(pNotifyExpire);
  433. //
  434. // submit... releases the AcquireInfo lock
  435. //
  436. status = IPSecNotifySAExpiration(NULL, pNotifyExpire, OldIrq, TRUE);
  437. //
  438. // if it failed then complete the irp now
  439. //
  440. if (NT_SUCCESS(status)) {
  441. fIrpCompleted = TRUE;
  442. IPSEC_DEBUG(LL_A,DBF_ACQUIRE, ("Acquire Irp completed inline"));
  443. break;
  444. }
  445. } else {
  446. break;
  447. }
  448. }
  449. //
  450. // We are holding onto the Irp, so set the cancel routine.
  451. //
  452. if (!fIrpCompleted) {
  453. status = IPSecCheckSetCancelRoutine(pIrp, IPSecAcquireIrpCancel);
  454. if (!NT_SUCCESS(status)) {
  455. //
  456. // the irp got cancelled so complete it now
  457. //
  458. g_ipsec.AcquireInfo.Irp = NULL;
  459. RELEASE_LOCK(&g_ipsec.AcquireInfo.Lock, OldIrq);
  460. // IPSecCompleteIrp(pIrp, status);
  461. } else {
  462. g_ipsec.AcquireInfo.InMe = TRUE;
  463. RELEASE_LOCK(&g_ipsec.AcquireInfo.Lock, OldIrq);
  464. status = STATUS_PENDING;
  465. }
  466. } else {
  467. g_ipsec.AcquireInfo.InMe = FALSE;
  468. RELEASE_LOCK(&g_ipsec.AcquireInfo.Lock, OldIrq);
  469. }
  470. return status;
  471. }
  472. VOID
  473. IPSecAcquireIrpCancel(
  474. PDEVICE_OBJECT pDeviceObject,
  475. PIRP pIrp
  476. )
  477. /*++
  478. Routine Description:
  479. This is the cancel routine for the Acquire Irp.
  480. It is called with IoCancelSpinLock held - must release this lock before exit.
  481. Arguments:
  482. pDeviceObject - Device object for the Irp.
  483. pIrp - The irp itself.
  484. Return Value:
  485. None.
  486. --*/
  487. {
  488. KIRQL kIrql;
  489. KIRQL kAcquireIrql;
  490. IoReleaseCancelSpinLock(pIrp->CancelIrql);
  491. IPSEC_DEBUG(LL_A,DBF_ACQUIRE, ("IPSecAcquireIrpCancel: Acquire Irp cancelled"));
  492. AcquireWriteLock(&g_ipsec.SADBLock, &kIrql);
  493. ACQUIRE_LOCK(&g_ipsec.AcquireInfo.Lock, &kAcquireIrql);
  494. if (g_ipsec.AcquireInfo.Irp && g_ipsec.AcquireInfo.InMe) {
  495. pIrp->IoStatus.Status = STATUS_CANCELLED;
  496. g_ipsec.AcquireInfo.Irp = NULL;
  497. g_ipsec.AcquireInfo.InMe = FALSE;
  498. //
  499. // Flush larval SAs.
  500. //
  501. IPSecFlushLarvalSAList();
  502. //
  503. // Flush SA expiration notifies.
  504. //
  505. IPSecFlushSAExpirations();
  506. RELEASE_LOCK(&g_ipsec.AcquireInfo.Lock, kAcquireIrql);
  507. ReleaseWriteLock(&g_ipsec.SADBLock, kIrql);
  508. IoCompleteRequest(pIrp, IO_NETWORK_INCREMENT);
  509. }
  510. else {
  511. RELEASE_LOCK(&g_ipsec.AcquireInfo.Lock, kAcquireIrql);
  512. ReleaseWriteLock(&g_ipsec.SADBLock, kIrql);
  513. }
  514. return;
  515. }
  516. NTSTATUS
  517. IPSecNotifySAExpiration(
  518. PSA_TABLE_ENTRY pInboundSA,
  519. PIPSEC_NOTIFY_EXPIRE pNotifyExpire,
  520. KIRQL OldIrq,
  521. BOOLEAN PostAcquire
  522. )
  523. /*++
  524. Routine Description:
  525. Notify Oakley through Acquire that SA has expired.
  526. Arguments:
  527. SA that is to expire
  528. Return Value:
  529. None
  530. --*/
  531. {
  532. PIPSEC_NOTIFY_EXPIRE pNewNotifyExpire;
  533. NTSTATUS status;
  534. PIRP pIrp;
  535. #if DBG
  536. if ((IPSecDebug & DBF_EXTRADIAGNOSTIC) && pInboundSA) {
  537. LARGE_INTEGER CurrentTime;
  538. NdisGetCurrentSystemTime(&CurrentTime);
  539. IPSEC_DEBUG(LL_A, DBF_REKEY,
  540. ("NotifySAExpiration: %lx, %lx, %lx, %lx, %lx",
  541. CurrentTime.LowPart,
  542. pInboundSA->SA_DEST_ADDR,
  543. pInboundSA->SA_SRC_ADDR,
  544. pInboundSA->sa_SPI,
  545. pInboundSA->sa_AssociatedSA? pInboundSA->sa_AssociatedSA->sa_SPI: 0));
  546. }
  547. #endif
  548. //
  549. // Check if there is a need to notify.
  550. //
  551. if (pInboundSA &&
  552. ((pInboundSA->sa_Flags & FLAGS_SA_NOTIFY_PERFORMED) ||
  553. (pInboundSA->sa_State == STATE_SA_LARVAL))) {
  554. IPSEC_DEBUG(LL_A,DBF_ACQUIRE, ("IPSecSubmitAcquire: already notified, returning"));
  555. if (!PostAcquire){
  556. RELEASE_LOCK(&g_ipsec.AcquireInfo.Lock, OldIrq);
  557. }
  558. return STATUS_UNSUCCESSFUL;
  559. }
  560. //
  561. // Set the flag so we won't notify again - only set flag in non-queued case.
  562. //
  563. if (pInboundSA) {
  564. pInboundSA->sa_Flags |= FLAGS_SA_NOTIFY_PERFORMED;
  565. }
  566. if (!g_ipsec.AcquireInfo.Irp) {
  567. //
  568. // the irp either never made it down here, or it was cancelled,
  569. // so drop all frames
  570. //
  571. IPSEC_DEBUG(LL_A,DBF_ACQUIRE, ("IPSecSubmitAcquire: Irp is NULL, returning\r"));
  572. if (!PostAcquire){
  573. RELEASE_LOCK(&g_ipsec.AcquireInfo.Lock, OldIrq);
  574. }
  575. return STATUS_BAD_NETWORK_PATH;
  576. } else if (!g_ipsec.AcquireInfo.ResolvingNow) {
  577. PIPSEC_POST_EXPIRE_NOTIFY pNotify;
  578. //
  579. // Irp is free now - use it
  580. //
  581. g_ipsec.AcquireInfo.ResolvingNow = TRUE;
  582. pIrp = g_ipsec.AcquireInfo.Irp;
  583. IPSEC_DEBUG(LL_A,DBF_ACQUIRE, ("Using Irp.. : %p", pIrp));
  584. pNotify = (PIPSEC_POST_EXPIRE_NOTIFY)pIrp->AssociatedIrp.SystemBuffer;
  585. pNotify->IdentityInfo = NULL;
  586. pNotify->Context = NULL;
  587. if (pInboundSA) {
  588. // Reverse everything since notifies notify for Outbound SAs
  589. pNotify->SrcAddr = pInboundSA->SA_DEST_ADDR;
  590. pNotify->SrcMask = pInboundSA->SA_DEST_MASK;
  591. pNotify->DestAddr = pInboundSA->SA_SRC_ADDR;
  592. pNotify->DestMask = pInboundSA->SA_SRC_MASK;
  593. pNotify->Protocol = pInboundSA->SA_PROTO;
  594. pNotify->SrcPort = SA_DEST_PORT(pInboundSA);
  595. pNotify->DestPort = SA_SRC_PORT(pInboundSA);
  596. pNotify->InboundSpi = pInboundSA->sa_SPI;
  597. pNotify->SrcEncapPort= pInboundSA->sa_EncapContext.wDesEncapPort;
  598. pNotify->DestEncapPort= pInboundSA->sa_EncapContext.wSrcEncapPort;
  599. pNotify->PeerPrivateAddr =pInboundSA->sa_PeerPrivateAddr;
  600. RtlCopyMemory( &pNotify->CookiePair,
  601. &pInboundSA->sa_CookiePair,
  602. sizeof(IKE_COOKIE_PAIR));
  603. if (pInboundSA->sa_Flags & FLAGS_SA_DELETE_BY_IOCTL) {
  604. pNotify->Flags = IPSEC_SA_INTERNAL_IOCTL_DELETE;
  605. } else {
  606. pNotify->Flags = 0;
  607. }
  608. if (pInboundSA->sa_AssociatedSA) {
  609. pNotify->OutboundSpi = pInboundSA->sa_AssociatedSA->sa_SPI;
  610. if (pInboundSA->sa_AssociatedSA->sa_Filter) {
  611. pNotify->TunnelAddr = pInboundSA->sa_AssociatedSA->sa_Filter->TunnelAddr;
  612. pNotify->InboundTunnelAddr = pInboundSA->sa_TunnelAddr;
  613. } else {
  614. pNotify->TunnelAddr = IPSEC_INVALID_ADDR;
  615. }
  616. } else {
  617. ASSERT (pInboundSA->sa_State == STATE_SA_LARVAL_ACTIVE ||
  618. pInboundSA->sa_State == STATE_SA_LARVAL);
  619. pNotify->OutboundSpi = IPSEC_INVALID_SPI;
  620. pNotify->TunnelAddr = IPSEC_INVALID_ADDR;
  621. }
  622. } else {
  623. ASSERT(pNotifyExpire);
  624. if (pNotifyExpire) {
  625. pNotify->SrcAddr = pNotifyExpire->SA_DEST_ADDR;
  626. pNotify->SrcMask = pNotifyExpire->SA_DEST_MASK;
  627. pNotify->DestAddr = pNotifyExpire->SA_SRC_ADDR;
  628. pNotify->DestMask = pNotifyExpire->SA_SRC_MASK;
  629. pNotify->Protocol = pNotifyExpire->SA_PROTO;
  630. pNotify->TunnelAddr = pNotifyExpire->sa_TunnelAddr;
  631. pNotify->InboundTunnelAddr = pNotifyExpire->sa_TunnelAddr;
  632. pNotify->SrcPort = SA_DEST_PORT(pNotifyExpire);
  633. pNotify->DestPort = SA_SRC_PORT(pNotifyExpire);
  634. pNotify->InboundSpi = pNotifyExpire->InboundSpi;
  635. pNotify->OutboundSpi = pNotifyExpire->OutboundSpi;
  636. pNotify->SrcEncapPort = pNotifyExpire->sa_EncapContext.wDesEncapPort;
  637. pNotify->DestEncapPort = pNotifyExpire->sa_EncapContext.wSrcEncapPort;
  638. pNotify->PeerPrivateAddr =pNotifyExpire->sa_PeerPrivateAddr;
  639. RtlCopyMemory( &pNotify->CookiePair,
  640. &pNotifyExpire->sa_CookiePair,
  641. sizeof(IKE_COOKIE_PAIR));
  642. pNotify->Flags = pNotifyExpire->Flags;
  643. IPSecFreeMemory(pNotifyExpire);
  644. }
  645. }
  646. pIrp->IoStatus.Information = sizeof(IPSEC_POST_FOR_ACQUIRE_SA);
  647. g_ipsec.AcquireInfo.InMe = FALSE;
  648. if (PostAcquire) {
  649. IPSEC_DEBUG(LL_A,DBF_ACQUIRE, ("Completing Irp in driver.c.. : %p", pIrp));
  650. status = STATUS_SUCCESS;
  651. } else {
  652. RELEASE_LOCK(&g_ipsec.AcquireInfo.Lock,OldIrq);
  653. IPSEC_DEBUG(LL_A,DBF_ACQUIRE, ("Completing Irp.. : %p", pIrp));
  654. IPSecCompleteIrp(pIrp, STATUS_SUCCESS);
  655. status = STATUS_PENDING;
  656. }
  657. IPSEC_DEBUG(LL_A,DBF_ACQUIRE, ("IPSecSubmitAcquire(Notify)"));
  658. } else {
  659. ASSERT(pInboundSA);
  660. //
  661. // The irp is busy negotiating another SA
  662. // Queue the Larval SA
  663. //
  664. if (pNotifyExpire) {
  665. //
  666. // Somethings bad. We've already queued up once, and we still
  667. // can't send. Just drop it.
  668. //
  669. IPSecFreeMemory(pNotifyExpire);
  670. if (!PostAcquire){
  671. RELEASE_LOCK(&g_ipsec.AcquireInfo.Lock, OldIrq);
  672. }
  673. return STATUS_UNSUCCESSFUL;
  674. }
  675. pNewNotifyExpire = IPSecGetNotifyExpire();
  676. if (!pNewNotifyExpire || !pInboundSA) {
  677. IPSEC_DEBUG(LL_A,DBF_ACQUIRE, ("Failed to get Notify Memory"));
  678. if (!PostAcquire){
  679. RELEASE_LOCK(&g_ipsec.AcquireInfo.Lock,OldIrq);
  680. }
  681. return STATUS_INSUFFICIENT_RESOURCES;
  682. }
  683. pNewNotifyExpire->sa_uliSrcDstAddr = pInboundSA->sa_uliSrcDstAddr;
  684. pNewNotifyExpire->sa_uliSrcDstMask = pInboundSA->sa_uliSrcDstMask;
  685. pNewNotifyExpire->sa_uliProtoSrcDstPort=pInboundSA->sa_uliProtoSrcDstPort;
  686. pNewNotifyExpire->InboundSpi = pInboundSA->sa_SPI;
  687. pNewNotifyExpire->sa_InboundTunnelAddr = pInboundSA->sa_TunnelAddr;
  688. RtlCopyMemory(&pNewNotifyExpire->sa_EncapContext,
  689. &pInboundSA->sa_EncapContext,
  690. sizeof(IPSEC_UDP_ENCAP_CONTEXT));
  691. RtlCopyMemory( &pNewNotifyExpire->sa_CookiePair,
  692. &pInboundSA->sa_CookiePair,
  693. sizeof(IKE_COOKIE_PAIR));
  694. if (pInboundSA->sa_Flags & FLAGS_SA_DELETE_BY_IOCTL) {
  695. pNewNotifyExpire->Flags = IPSEC_SA_INTERNAL_IOCTL_DELETE;
  696. } else {
  697. pNewNotifyExpire->Flags = 0;
  698. }
  699. if (pInboundSA->sa_AssociatedSA) {
  700. pNewNotifyExpire->OutboundSpi = pInboundSA->sa_AssociatedSA->sa_SPI;
  701. if (pInboundSA->sa_AssociatedSA->sa_Filter) {
  702. pNewNotifyExpire->sa_TunnelAddr = pInboundSA->sa_AssociatedSA->sa_Filter->TunnelAddr;
  703. } else {
  704. pNewNotifyExpire->sa_TunnelAddr = IPSEC_INVALID_ADDR;
  705. }
  706. } else {
  707. ASSERT (pInboundSA->sa_State == STATE_SA_LARVAL_ACTIVE ||
  708. pInboundSA->sa_State == STATE_SA_LARVAL);
  709. pNewNotifyExpire->OutboundSpi = IPSEC_INVALID_SPI;
  710. pNewNotifyExpire->sa_TunnelAddr = IPSEC_INVALID_ADDR;
  711. }
  712. InsertTailList( &g_ipsec.AcquireInfo.PendingNotifies,
  713. &pNewNotifyExpire->notify_PendingLinkage);
  714. status = STATUS_PENDING;
  715. if (!PostAcquire){
  716. RELEASE_LOCK(&g_ipsec.AcquireInfo.Lock, OldIrq);
  717. }
  718. IPSEC_DEBUG(LL_A,DBF_ACQUIRE, ("IPSecSubmitAcquire(Notify): queue SA"));
  719. }
  720. return status;
  721. }
  722. VOID
  723. IPSecFlushSAExpirations(
  724. )
  725. /*++
  726. Routine Description:
  727. When the Acquire Irp is cancelled, this routine is called to flush all the
  728. pending SA expiration notifies.
  729. Called with SADB lock held (first acquisition); returns with it.
  730. Called with AcquireInfo.Lock held (second acquisition); returns with it.
  731. Arguments:
  732. None.
  733. Return Value:
  734. None.
  735. --*/
  736. {
  737. PIPSEC_NOTIFY_EXPIRE pIpsecNotifyExpire = NULL;
  738. PLIST_ENTRY pListEntry = NULL;
  739. while (!IsListEmpty(&g_ipsec.AcquireInfo.PendingNotifies)) {
  740. pListEntry = RemoveHeadList(
  741. &g_ipsec.AcquireInfo.PendingNotifies
  742. );
  743. pIpsecNotifyExpire = CONTAINING_RECORD(
  744. pListEntry,
  745. IPSEC_NOTIFY_EXPIRE,
  746. notify_PendingLinkage
  747. );
  748. IPSecFreeMemory(pIpsecNotifyExpire);
  749. }
  750. return;
  751. }
  752. ULONG IPSecGetAcquireId()
  753. {
  754. static ULONG LocalAcquireId = MIN_ACQUIRE_ID;
  755. ULONG NewAcquireId;
  756. NewAcquireId = IPSEC_INCREMENT(LocalAcquireId);
  757. while (NewAcquireId < MIN_ACQUIRE_ID) {
  758. NewAcquireId = IPSEC_INCREMENT(LocalAcquireId);
  759. }
  760. return NewAcquireId;
  761. }