Source code of Windows XP (NT5)
You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

987 lines
26 KiB

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