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.

5024 lines
147 KiB

  1. /*++
  2. Copyright (c) 1997-2001 Microsoft Corporation
  3. Module Name:
  4. ipsec.c
  5. Abstract:
  6. This module contains the code that handles incoming/outgoing packets.
  7. Author:
  8. Sanjay Anand (SanjayAn) 2-January-1997
  9. ChunYe
  10. Environment:
  11. Kernel mode
  12. Revision History:
  13. --*/
  14. #include "precomp.h"
  15. #ifdef RUN_WPP
  16. #include "ipsec.tmh"
  17. #endif
  18. IPSEC_ACTION
  19. IPSecHandlePacket(
  20. IN PUCHAR pIPHeader,
  21. IN PVOID pData,
  22. IN PVOID IPContext,
  23. IN PNDIS_PACKET Packet,
  24. IN OUT PULONG pExtraBytes,
  25. IN OUT PULONG pMTU,
  26. OUT PVOID *pNewData,
  27. IN OUT PULONG pIpsecFlags,
  28. IN UCHAR DestType
  29. )
  30. /*++
  31. Routine Description:
  32. Called by the Filter Driver to submit a packet for IPSEC processing.
  33. Arguments:
  34. pIPHeader - points to start of IP header.
  35. pData - points to the data after the IP header. On the send side, this is an MDL chain
  36. On the recv side this is an IPRcvBuf pointer.
  37. IPContext - contains the destination interface.
  38. pExtraBytes - IPSEC header expansion value; on coming in, it contains the amount of ipsec
  39. header space that can fit into the MTU. so, if MTU is 1400, say, and the
  40. datasize + option size is 1390, this contains 10, meaning that upto
  41. 10 bytes of IPSEC expansion is allowed. This lets IPSEC know when a packet
  42. would be fragmented, so it can do the right thing on send complete.
  43. pMTU - passes in the link MTU on send path.
  44. pNewData - if packet modified, this points to the new data.
  45. IpsecFlags - flags for SrcRoute, Incoming, Forward and Lookback.
  46. Return Value:
  47. eFORWARD
  48. eDROP
  49. eABSORB
  50. --*/
  51. {
  52. IPSEC_ACTION eAction;
  53. IPSEC_DROP_STATUS DropStatus;
  54. PIPSEC_DROP_STATUS pDropStatus=NULL;
  55. IPSEC_DEBUG(LL_A, DBF_PARSE, ("Entering IPSecHandlePacket"));
  56. #if DBG
  57. {
  58. IPHeader UNALIGNED *pIPH;
  59. pIPH = (IPHeader UNALIGNED *)pIPHeader;
  60. if ((DebugSrc || DebugDst || DebugPro) &&
  61. (!DebugSrc || pIPH->iph_src == DebugSrc) &&
  62. (!DebugDst || pIPH->iph_dest == DebugDst) &&
  63. (!DebugPro || pIPH->iph_protocol == DebugPro)) {
  64. DbgPrint("Packet from %lx to %lx with protocol %lx length %lx id %lx",
  65. pIPH->iph_src,
  66. pIPH->iph_dest,
  67. pIPH->iph_protocol,
  68. NET_SHORT(pIPH->iph_length),
  69. NET_SHORT(pIPH->iph_id));
  70. if (DebugPkt) {
  71. DbgBreakPoint();
  72. }
  73. }
  74. }
  75. #endif
  76. //
  77. // Drop all packets if PA sets us so or if the driver is inactive.
  78. //
  79. if ( IPSEC_DRIVER_IS_INACTIVE()) {
  80. eAction=eDROP;
  81. goto out;
  82. }
  83. //
  84. // Bypass all packets if PA sets us so or no filters are plumbed or the
  85. // packet is broadcast. If multicast filter present, process all multicast
  86. // Once we support any-any tunnels, this check will need to be smarter
  87. //
  88. if (IS_DRIVER_BYPASS() ||
  89. (IS_BCAST_DEST(DestType) && !IPSEC_MANDBCAST_PROCESS())) {
  90. *pExtraBytes = 0;
  91. *pMTU = 0;
  92. eAction= eFORWARD;
  93. goto out;
  94. }
  95. if (IS_DRIVER_BLOCK() || IS_DRIVER_BOOTSTATEFUL()) {
  96. *pExtraBytes = 0;
  97. *pMTU = 0;
  98. eAction = IPSecProcessBoottime(pIPHeader,
  99. pData,
  100. Packet,
  101. *pIpsecFlags,
  102. DestType);
  103. goto out;
  104. }
  105. if (IPSEC_DRIVER_IS_EMPTY()) {
  106. *pExtraBytes = 0;
  107. *pMTU = 0;
  108. eAction= eFORWARD;
  109. goto out;
  110. }
  111. ASSERT(IS_DRIVER_SECURE());
  112. ASSERT(IPContext);
  113. IPSEC_INCREMENT(g_ipsec.NumThreads);
  114. if (IS_DRIVER_DIAGNOSTIC()) {
  115. pDropStatus=&DropStatus;
  116. RtlZeroMemory(pDropStatus,sizeof(IPSEC_DROP_STATUS));
  117. }
  118. if (*pIpsecFlags & IPSEC_FLAG_INCOMING) {
  119. eAction = IPSecRecvPacket( &pIPHeader,
  120. pData,
  121. IPContext,
  122. Packet,
  123. pExtraBytes,
  124. pIpsecFlags,
  125. pDropStatus,
  126. DestType);
  127. } else {
  128. eAction = IPSecSendPacket( pIPHeader,
  129. pData,
  130. IPContext,
  131. Packet,
  132. pExtraBytes,
  133. pMTU,
  134. pNewData,
  135. pIpsecFlags,
  136. pDropStatus,
  137. DestType);
  138. }
  139. IPSEC_DECREMENT(g_ipsec.NumThreads);
  140. out:
  141. if (eAction == eDROP) {
  142. if (IS_DRIVER_DIAGNOSTIC() &&
  143. (!pDropStatus || (pDropStatus && !(pDropStatus->Flags & IPSEC_DROP_STATUS_DONT_LOG)))) {
  144. IPSecBufferPacketDrop(
  145. pIPHeader,
  146. pData,
  147. pIpsecFlags,
  148. pDropStatus);
  149. }
  150. }
  151. return eAction;
  152. }
  153. IPSEC_ACTION
  154. IPSecSendPacket(
  155. IN PUCHAR pIPHeader,
  156. IN PVOID pData,
  157. IN PVOID IPContext,
  158. IN PNDIS_PACKET Packet,
  159. IN OUT PULONG pExtraBytes,
  160. IN OUT PULONG pMTU,
  161. OUT PVOID *pNewData,
  162. IN OUT PULONG pIpsecFlags,
  163. OUT PIPSEC_DROP_STATUS pDropStatus,
  164. IN UCHAR DestType
  165. )
  166. /*++
  167. Routine Description:
  168. Called by the Filter Driver to submit a packet for IPSEC processing.
  169. Arguments:
  170. pIPHeader - points to start of IP header.
  171. pData - points to the data after the IP header, an MDL chain.
  172. IPContext - contains the destination interface.
  173. pExtraBytes - IPSEC header expansion value.
  174. pMTU - passes in the link MTU on send path.
  175. pNewData - if packet modified, this points to the new data.
  176. IpsecFlags - flags for SrcRoute, Incoming, Forward and Lookback.
  177. Return Value:
  178. eFORWARD
  179. eDROP
  180. eABSORB
  181. --*/
  182. {
  183. NTSTATUS status = STATUS_SUCCESS;
  184. IPSEC_ACTION eRetAction = eFORWARD;
  185. PSA_TABLE_ENTRY pSA = NULL;
  186. PSA_TABLE_ENTRY pSaveSA = NULL;
  187. PSA_TABLE_ENTRY pNextSA = NULL;
  188. USHORT FilterFlags = 0;
  189. BOOLEAN fLifetime = FALSE;
  190. ULONG ipsecHdrSpace = *pExtraBytes;
  191. ULONG ipsecOverhead = 0;
  192. ULONG ipsecMTU = *pMTU;
  193. ULONG newMTU = MAX_LONG;
  194. ULONG dataLength = 0;
  195. IPHeader UNALIGNED *pIPH = (IPHeader UNALIGNED *)pIPHeader;
  196. Interface *DestIF = (Interface *)IPContext;
  197. PNDIS_PACKET_EXTENSION PktExt = NULL;
  198. PNDIS_IPSEC_PACKET_INFO IPSecPktInfo = NULL;
  199. BOOLEAN fCryptoOnly = FALSE;
  200. BOOLEAN fFWPacket = FALSE;
  201. BOOLEAN fSrcRoute = FALSE;
  202. BOOLEAN fLoopback = FALSE;
  203. PVOID *ppSCContext;
  204. KIRQL kIrql;
  205. LONG Index;
  206. PNDIS_BUFFER pTemp;
  207. ULONG Length;
  208. PUCHAR pBuffer;
  209. IPSEC_UDP_ENCAP_CONTEXT NatContext;
  210. BOOLEAN fRekeyDone=FALSE;
  211. IPAddr iph_src = 0;
  212. BOOL bSendIcmp = FALSE;
  213. PUCHAR pucIpBufferForICMP = NULL;
  214. PUCHAR pucStorage = NULL;
  215. IPSEC_DEBUG(LL_A, DBF_PARSE, ("Entering IPSecSendPacket"));
  216. if (*pIpsecFlags & IPSEC_FLAG_FORWARD) {
  217. fFWPacket = TRUE;
  218. }
  219. if (*pIpsecFlags & IPSEC_FLAG_SSRR) {
  220. fSrcRoute = TRUE;
  221. }
  222. if (*pIpsecFlags & IPSEC_FLAG_LOOPBACK) {
  223. fLoopback = TRUE;
  224. }
  225. *pExtraBytes = 0;
  226. *pMTU = 0;
  227. if (fLoopback) {
  228. IPSEC_DEBUG(LL_A, DBF_PARSE, ("IPSecSendPacket: Packet on loopback interface - returning"));
  229. status = STATUS_SUCCESS;
  230. goto out;
  231. }
  232. //
  233. // Walk through the MDL chain to make sure we have memory locked.
  234. //
  235. pTemp = (PNDIS_BUFFER)pData;
  236. while (pTemp) {
  237. pBuffer = NULL;
  238. Length = 0;
  239. NdisQueryBufferSafe(pTemp,
  240. &pBuffer,
  241. &Length,
  242. NormalPagePriority);
  243. if (!pBuffer) {
  244. //
  245. // QueryBuffer failed, drop the packet.
  246. //
  247. status = STATUS_UNSUCCESSFUL;
  248. goto out;
  249. }
  250. dataLength += Length;
  251. pTemp = NDIS_BUFFER_LINKAGE(pTemp);
  252. }
  253. dataLength -= sizeof(IPHeader);
  254. //
  255. // Set send complete context in the NDIS packet.
  256. //
  257. if (Packet) {
  258. PacketContext *pContext;
  259. pContext = (PacketContext *)Packet->ProtocolReserved;
  260. ppSCContext = &pContext->pc_common.pc_IpsecCtx;
  261. } else {
  262. ASSERT(FALSE);
  263. status = STATUS_UNSUCCESSFUL;
  264. goto out;
  265. }
  266. status = IPSecClassifyPacket( pIPHeader,
  267. pData,
  268. &pSA,
  269. &pNextSA,
  270. &FilterFlags,
  271. #if GPC
  272. PtrToUlong(NDIS_PER_PACKET_INFO_FROM_PACKET(Packet, ClassificationHandlePacketInfo)),
  273. #endif
  274. TRUE, // fOutbound
  275. fFWPacket,
  276. TRUE, // do bypass check
  277. FALSE, //Not a recv reinject
  278. FALSE, // Not a verify Call
  279. DestType,
  280. &NatContext);
  281. if (status == STATUS_PENDING) {
  282. //
  283. // Negotiation kicked off; drop the packet silently.
  284. //
  285. return eABSORB;
  286. } else if (status != STATUS_SUCCESS) {
  287. status = STATUS_SUCCESS;
  288. goto out;
  289. }
  290. if (FilterFlags) {
  291. ASSERT(pSA == NULL);
  292. //
  293. // This is either a drop or pass thru filter.
  294. //
  295. if (FilterFlags & FILTER_FLAGS_DROP) {
  296. IPSEC_DEBUG(LL_A, DBF_PARSE, ("Drop filter"));
  297. status = STATUS_UNSUCCESSFUL;
  298. } else if (FilterFlags & FILTER_FLAGS_PASS_THRU) {
  299. IPSEC_DEBUG(LL_A, DBF_PARSE, ("Pass thru' filter"));
  300. status = STATUS_SUCCESS;
  301. } else {
  302. ASSERT(FALSE);
  303. }
  304. goto out;
  305. }
  306. //
  307. // Consider only outbound SAs
  308. //
  309. ASSERT(pSA);
  310. ASSERT(pSA->sa_Flags & FLAGS_SA_OUTBOUND);
  311. //
  312. // We don't support Source Route with IPSec Tunneling.
  313. //
  314. if (fSrcRoute && (pSA->sa_Flags & FLAGS_SA_TUNNEL)) {
  315. IPSEC_DEBUG(LL_A, DBF_TUNNEL, ("No tunneling source route: pSA: %p", pSA));
  316. IPSecDerefSANextSA(pSA, pNextSA);
  317. status = STATUS_UNSUCCESSFUL;
  318. goto out;
  319. }
  320. if (pSA->sa_Flags & FLAGS_SA_ENABLE_NLBS_IDLE_CHECK) {
  321. IPSEC_SA_EXPIRED(pSA,fLifetime);
  322. if (fLifetime) {
  323. // Idled out. Force rekey
  324. IPSecRekeyOutboundSA(pSA);
  325. fRekeyDone=TRUE;
  326. }
  327. }
  328. //
  329. // Set the last used time.
  330. //
  331. NdisGetCurrentSystemTime(&pSA->sa_LastUsedTime);
  332. if (!(pSA->sa_Flags & FLAGS_SA_DISABLE_LIFETIME_CHECK)) {
  333. //
  334. // check if we might expire soon - start rekey operation now.
  335. //
  336. IPSEC_CHECK_PADDED_LIFETIME(pSA, fLifetime, pSA->sa_NumOps - 1);
  337. if (fLifetime == FALSE && !fRekeyDone) {
  338. IPSecRekeyOutboundSA(pSA);
  339. }
  340. //
  341. // check the real lifetime - if we have expired, ensure that the
  342. // re-key was submitted and then cancel the current SAs.
  343. //
  344. IPSEC_CHECK_LIFETIME(pSA, fLifetime, pSA->sa_NumOps - 1);
  345. //
  346. // this time it really expired - we are in trouble since this shd have gone away
  347. // earlier.
  348. //
  349. if (fLifetime == FALSE) {
  350. IPSecPuntOutboundSA(pSA);
  351. IPSecDerefSANextSA(pSA, pNextSA);
  352. status = STATUS_UNSUCCESSFUL;
  353. goto out;
  354. }
  355. }
  356. //
  357. // Compute the total IPSec overhead.
  358. //
  359. ipsecOverhead = pSA->sa_IPSecOverhead;
  360. if (pNextSA) {
  361. ipsecOverhead += pNextSA->sa_IPSecOverhead;
  362. }
  363. //
  364. // Check if total data length exceeds 65535.
  365. //
  366. if ((dataLength + ipsecOverhead) > (MAX_IP_DATA_LENGTH - sizeof(IPHeader))) {
  367. IPSecDerefSANextSA(pSA, pNextSA);
  368. status = STATUS_UNSUCCESSFUL;
  369. goto out;
  370. }
  371. //
  372. // If no enough header space, return right away if DF bit is set. We also
  373. // have to adjust for PMTU recorded in the SAs.
  374. //
  375. if (pIPH->iph_offset & IP_DF_FLAG) {
  376. //
  377. // First get MTU recorded from IPSecStatus.
  378. //
  379. if (pNextSA) {
  380. newMTU = MIN(IPSEC_GET_VALUE(pSA->sa_NewMTU),
  381. IPSEC_GET_VALUE(pNextSA->sa_NewMTU));
  382. } else {
  383. newMTU = IPSEC_GET_VALUE(pSA->sa_NewMTU);
  384. }
  385. //
  386. // Use the smaller of link MTU and new MTU from SA.
  387. //
  388. newMTU = MIN(newMTU, ipsecMTU);
  389. //
  390. // See if we have enough header space; if not pass back the new smaller
  391. // MTU minus IPSec overhead to the upper stack.
  392. //
  393. if (newMTU < (ipsecOverhead + dataLength)) {
  394. *pMTU = newMTU - ipsecOverhead;
  395. IPSEC_DEBUG(LL_A, DBF_PMTU, ("OldMTU %lx, HdrSpace: %lx, NewMTU: %lx", ipsecMTU, ipsecHdrSpace, *pMTU));
  396. if (DestIF->if_dfencap == ClearDfEncap) {
  397. if (pNextSA) {
  398. ASSERT((pNextSA->sa_Flags & FLAGS_SA_TUNNEL));
  399. iph_src = pNextSA->sa_SrcTunnelAddr;
  400. bSendIcmp = TRUE;
  401. }
  402. else {
  403. if (pSA->sa_Flags & FLAGS_SA_TUNNEL) {
  404. iph_src = pSA->sa_SrcTunnelAddr;
  405. bSendIcmp = TRUE;
  406. }
  407. }
  408. }
  409. if (bSendIcmp) {
  410. status = GetIpBufferForICMP(
  411. pIPHeader,
  412. pData,
  413. &pucIpBufferForICMP,
  414. &pucStorage
  415. );
  416. if (!NT_SUCCESS(status)) {
  417. IPSecDerefSANextSA(pSA, pNextSA);
  418. goto out;
  419. }
  420. TCPIP_SEND_ICMP_ERR(
  421. iph_src,
  422. (IPHeader UNALIGNED *) pucIpBufferForICMP,
  423. ICMP_DEST_UNREACH,
  424. FRAG_NEEDED,
  425. net_long((ulong)(*pMTU + sizeof(IPHeader))),
  426. 0
  427. );
  428. if (pucStorage) {
  429. IPSecFreeMemory(pucStorage);
  430. }
  431. }
  432. else {
  433. IPSecDerefSANextSA(pSA, pNextSA);
  434. status = STATUS_UNSUCCESSFUL;
  435. goto out;
  436. }
  437. }
  438. }
  439. //
  440. // See if hardware offload can be arranged here. If successful, we pass the
  441. // flag to the create routines so they create only the framing, leaving the
  442. // core crypto to the hardware.
  443. //
  444. if (g_ipsec.EnableOffload && ipsecOverhead <= ipsecHdrSpace) {
  445. IPSecSendOffload( pIPH,
  446. Packet,
  447. DestIF,
  448. pSA,
  449. pNextSA,
  450. ppSCContext,
  451. &fCryptoOnly);
  452. }
  453. //
  454. // Make sure IPSecPktInfo is NULL if there is no offload for this
  455. // packet. This could be set in reinject path which is then
  456. // forwarded.
  457. //
  458. if (!fCryptoOnly) {
  459. ASSERT(Packet != NULL);
  460. PktExt = NDIS_PACKET_EXTENSION_FROM_PACKET(Packet);
  461. PktExt->NdisPacketInfo[IpSecPacketInfo] = NULL;
  462. }
  463. if (fCryptoOnly) {
  464. ADD_TO_LARGE_INTEGER(
  465. &g_ipsec.Statistics.uOffloadedBytesSent,
  466. NET_SHORT(pIPH->iph_length));
  467. if (pDropStatus) {
  468. pDropStatus->Flags |= IPSEC_DROP_STATUS_CRYPTO_DONE;
  469. }
  470. }
  471. do {
  472. ADD_TO_LARGE_INTEGER(
  473. &pSA->sa_Stats.TotalBytesSent,
  474. NET_SHORT(pIPH->iph_length));
  475. if (pSA->sa_Flags & FLAGS_SA_TUNNEL) {
  476. ADD_TO_LARGE_INTEGER(
  477. &g_ipsec.Statistics.uBytesSentInTunnels,
  478. NET_SHORT(pIPH->iph_length));
  479. } else {
  480. ADD_TO_LARGE_INTEGER(
  481. &g_ipsec.Statistics.uTransportBytesSent,
  482. NET_SHORT(pIPH->iph_length));
  483. }
  484. if (fCryptoOnly) {
  485. ADD_TO_LARGE_INTEGER(
  486. &pSA->sa_Stats.OffloadedBytesSent,
  487. NET_SHORT(pIPH->iph_length));
  488. }
  489. //
  490. // Multiple ops here - iterate thru the headers. Inner first.
  491. //
  492. for (Index = 0; Index < pSA->sa_NumOps; Index++) {
  493. switch (pSA->sa_Operation[Index]) {
  494. case Auth:
  495. status = IPSecCreateAH( pIPHeader,
  496. pData,
  497. IPContext,
  498. pSA,
  499. Index,
  500. pNewData,
  501. ppSCContext,
  502. pExtraBytes,
  503. ipsecHdrSpace,
  504. fSrcRoute,
  505. fCryptoOnly);
  506. if (!NT_SUCCESS(status)) {
  507. IPSEC_DEBUG(LL_A, DBF_PARSE, ("AH failed: pSA: %p, status: %lx",
  508. pSA,
  509. status));
  510. IPSecDerefSANextSA(pSA, pNextSA);
  511. goto out;
  512. }
  513. //
  514. // Save the new MDL for future operation; also query the new header (if it changed)
  515. //
  516. if (*pNewData) {
  517. pData = *pNewData;
  518. IPSecQueryNdisBuf((PNDIS_BUFFER)pData, &pIPHeader, &Length);
  519. }
  520. break;
  521. case Encrypt:
  522. status = IPSecCreateHughes( pIPHeader,
  523. pData,
  524. IPContext,
  525. pSA,
  526. Index,
  527. pNewData,
  528. ppSCContext,
  529. pExtraBytes,
  530. ipsecHdrSpace,
  531. Packet,
  532. fCryptoOnly);
  533. if (!NT_SUCCESS(status)) {
  534. IPSEC_DEBUG(LL_A, DBF_PARSE, ("HUGHES failed: pSA: %p, status: %lx",
  535. pSA,
  536. status));
  537. IPSecDerefSANextSA(pSA, pNextSA);
  538. goto out;
  539. }
  540. //
  541. // Save the new MDL for future operation; also query the new header (if it changed)
  542. //
  543. if (*pNewData) {
  544. pData = *pNewData;
  545. IPSecQueryNdisBuf((PNDIS_BUFFER)pData, &pIPHeader, &Length);
  546. }
  547. break;
  548. case None:
  549. status = STATUS_SUCCESS;
  550. break;
  551. default:
  552. IPSEC_DEBUG(LL_A, DBF_PARSE, ("No valid operation: %p", pSA->sa_Operation));
  553. break;
  554. }
  555. }
  556. pSaveSA = pSA;
  557. pSA = pNextSA;
  558. if (!pSA) {
  559. IPSecDerefSA(pSaveSA);
  560. break;
  561. }
  562. pNextSA = NULL;
  563. IPSecDerefSA(pSaveSA);
  564. } while (TRUE);
  565. //
  566. // Remember if we are going to fragment.
  567. //
  568. if (ipsecHdrSpace < *pExtraBytes) {
  569. IPSEC_DEBUG(LL_A, DBF_PARSE, ("ipsecHdrSpace: FRAG"));
  570. ((IPSEC_SEND_COMPLETE_CONTEXT *)*ppSCContext)->Flags |= SCF_FRAG;
  571. }
  572. out:
  573. if (!NT_SUCCESS(status)) {
  574. IPSEC_DEBUG(LL_A, DBF_PARSE, ("IPSecSendPacket failed: %lx", status));
  575. eRetAction = eDROP;
  576. }
  577. if (pDropStatus) {
  578. pDropStatus->IPSecStatus=status;
  579. }
  580. IPSEC_DEBUG(LL_A, DBF_PARSE, ("Exiting IPSecSendPacket; action %lx", eRetAction));
  581. return eRetAction;
  582. }
  583. IPSEC_ACTION
  584. IPSecRecvPacket(
  585. IN PUCHAR *pIPHeader,
  586. IN PVOID pData,
  587. IN PVOID IPContext,
  588. IN PNDIS_PACKET Packet,
  589. IN OUT PULONG pExtraBytes,
  590. IN OUT PULONG pIpsecFlags,
  591. OUT PIPSEC_DROP_STATUS pDropStatus,
  592. IN UCHAR DestType
  593. )
  594. /*++
  595. Routine Description:
  596. This is the IPSecRecvHandler.
  597. Arguments:
  598. pIPHeader - points to start of IP header.
  599. pData - points to the data after the IP header, an IPRcvBuf pointer.
  600. IPContext - contains the destination interface.
  601. pExtraBytes - IPSEC header expansion value.
  602. IpsecFlags - flags for SrcRoute, Incoming, Forward and Lookback.
  603. Return Value:
  604. eFORWARD
  605. eDROP
  606. --*/
  607. {
  608. NTSTATUS status = STATUS_SUCCESS;
  609. IPSEC_ACTION eRetAction = eFORWARD;
  610. PSA_TABLE_ENTRY pSA = NULL;
  611. PSA_TABLE_ENTRY pSaveSA = NULL;
  612. PSA_TABLE_ENTRY pNextSA = NULL;
  613. USHORT FilterFlags = 0;
  614. BOOLEAN fLifetime = FALSE;
  615. IPHeader UNALIGNED *pIPH = (IPHeader UNALIGNED *)*pIPHeader;
  616. Interface *DestIF = (Interface *)IPContext;
  617. PNDIS_PACKET OrigPacket = NULL;
  618. PNDIS_PACKET_EXTENSION PktExt = NULL;
  619. PNDIS_IPSEC_PACKET_INFO IPSecPktInfo = NULL;
  620. BOOLEAN fCryptoOnly = FALSE;
  621. BOOLEAN fFWPacket = FALSE;
  622. BOOLEAN fSrcRoute = FALSE;
  623. BOOLEAN fLoopback = FALSE;
  624. BOOLEAN fFastRcv = FALSE;
  625. tSPI SPI;
  626. KIRQL kIrql;
  627. LONG Index;
  628. BOOLEAN bNatEncap=FALSE;
  629. IPSEC_UDP_ENCAP_CONTEXT NatContext;
  630. IPSEC_UDP_ENCAP_CONTEXT SavedNatContext;
  631. if (*pIpsecFlags & IPSEC_FLAG_FORWARD) {
  632. fFWPacket = TRUE;
  633. }
  634. if (*pIpsecFlags & IPSEC_FLAG_SSRR) {
  635. fSrcRoute = TRUE;
  636. }
  637. if (*pIpsecFlags & IPSEC_FLAG_LOOPBACK) {
  638. fLoopback = TRUE;
  639. }
  640. if (*pIpsecFlags & IPSEC_FLAG_FASTRCV) {
  641. fFastRcv = TRUE;
  642. }
  643. IPSEC_DEBUG(LL_A, DBF_PARSE, ("Entering IPSecRecvPacket"));
  644. *pExtraBytes = 0;
  645. if (Packet) {
  646. OrigPacket = (PNDIS_PACKET)NDIS_GET_ORIGINAL_PACKET(Packet);
  647. if (OrigPacket) {
  648. PktExt = NDIS_PACKET_EXTENSION_FROM_PACKET(OrigPacket);
  649. } else {
  650. PktExt = NDIS_PACKET_EXTENSION_FROM_PACKET(Packet);
  651. }
  652. IPSecPktInfo = PktExt->NdisPacketInfo[IpSecPacketInfo];
  653. }
  654. #if DBG
  655. if (DebugOff) {
  656. if (pIPH->iph_protocol == PROTOCOL_AH ||
  657. pIPH->iph_protocol == PROTOCOL_ESP) {
  658. DbgPrint("Packet %p, OrigPacket %p, CRYPTO %d, CryptoStatus %d",
  659. Packet,
  660. OrigPacket,
  661. IPSecPktInfo? IPSecPktInfo->Receive.CRYPTO_DONE: 0,
  662. IPSecPktInfo? IPSecPktInfo->Receive.CryptoStatus: 0);
  663. if (DebugPkt) {
  664. DbgBreakPoint();
  665. }
  666. }
  667. }
  668. #endif
  669. //
  670. // If the packet is IPSec protected, set the appropriate flags for firewall/NAT.
  671. //
  672. if (pIPH->iph_protocol == PROTOCOL_AH ||
  673. pIPH->iph_protocol == PROTOCOL_ESP) {
  674. *pIpsecFlags |= IPSEC_FLAG_TRANSFORMED;
  675. }
  676. if (IPSecPktInfo && pDropStatus) {
  677. if (IPSecPktInfo->Receive.CRYPTO_DONE) {
  678. pDropStatus->Flags |= IPSEC_DROP_STATUS_CRYPTO_DONE;
  679. }
  680. if (IPSecPktInfo->Receive.NEXT_CRYPTO_DONE) {
  681. pDropStatus->Flags |= IPSEC_DROP_STATUS_NEXT_CRYPTO_DONE;
  682. }
  683. if (IPSecPktInfo->Receive.SA_DELETE_REQ) {
  684. pDropStatus->Flags |= IPSEC_DROP_STATUS_SA_DELETE_REQ;
  685. }
  686. pDropStatus->OffloadStatus=IPSecPktInfo->Receive.CryptoStatus;
  687. }
  688. if (IPSecPktInfo &&
  689. IPSecPktInfo->Receive.CRYPTO_DONE &&
  690. IPSecPktInfo->Receive.CryptoStatus != CRYPTO_SUCCESS) {
  691. //
  692. // Error reported by offload card. Discard the packet and apply
  693. // the necessary acountings.
  694. //
  695. IPSecBufferOffloadEvent(pIPH, IPSecPktInfo);
  696. status = STATUS_UNSUCCESSFUL;
  697. goto out;
  698. }
  699. //
  700. // Walk the packet to determine the SPI
  701. //
  702. status = IPSecParsePacket( *pIPHeader,
  703. pData,
  704. &SPI,
  705. &bNatEncap,
  706. &NatContext);
  707. // IPSecParsePacket initializes both ports to zero
  708. // if this is not a UDP encapsulation
  709. SavedNatContext = NatContext; //Struct Copy
  710. if (!NT_SUCCESS(status)) {
  711. IPSEC_DEBUG(LL_A, DBF_PARSE, ("IPSecParsePkt no IPSEC headers: %lx", status));
  712. if (fLoopback) {
  713. IPSEC_DEBUG(LL_A, DBF_PARSE, ("loopback was on, not doing inbound policy check"));
  714. status = STATUS_SUCCESS;
  715. goto out;
  716. }
  717. status = IPSecClassifyPacket( *pIPHeader,
  718. pData,
  719. &pSA,
  720. &pNextSA,
  721. &FilterFlags,
  722. #if GPC
  723. 0,
  724. #endif
  725. FALSE, // fOutbound
  726. fFWPacket,
  727. TRUE, // do bypass check
  728. FALSE, // Not a recv reinject
  729. FALSE, // Not a verify Call
  730. DestType,
  731. NULL);
  732. if (status != STATUS_SUCCESS) {
  733. ASSERT(pSA == NULL);
  734. //
  735. // If we didnt find an SA, but found a filter, bad, drop.
  736. //
  737. if (status == STATUS_PENDING) {
  738. // This is where we allow cleartext on PASSTHRU filter
  739. // For an SA which is not up yet
  740. if (FilterFlags & FILTER_FLAGS_PASS_THRU) {
  741. // Allow this clear text traffic in
  742. status = STATUS_SUCCESS;
  743. } else {
  744. IPSEC_DEBUG(LL_A, DBF_PARSE, ("IPSecParsePkt cleartext when filter exists: %lx", status));
  745. status = IPSEC_NEGOTIATION_PENDING;
  746. }
  747. } else {
  748. status = STATUS_SUCCESS;
  749. }
  750. goto out;
  751. } else {
  752. if (FilterFlags) {
  753. ASSERT(pSA == NULL);
  754. //
  755. // This is either a drop or pass thru filter.
  756. //
  757. if (FilterFlags & FILTER_FLAGS_DROP) {
  758. IPSEC_DEBUG(LL_A, DBF_PARSE, ("Drop filter"));
  759. status = IPSEC_BLOCK;
  760. } else if (FilterFlags & FILTER_FLAGS_PASS_THRU) {
  761. IPSEC_DEBUG(LL_A, DBF_PARSE, ("Pass thru' filter"));
  762. status = STATUS_SUCCESS;
  763. } else {
  764. ASSERT(FALSE);
  765. }
  766. goto out;
  767. }
  768. ASSERT(pSA);
  769. //
  770. // Set the last used time.
  771. //
  772. NdisGetCurrentSystemTime(&pSA->sa_LastUsedTime);
  773. //
  774. // We found an SA; In case the operation is not none
  775. // or if it is a tunnel SA we have invalid cleartext;
  776. //
  777. if (pSA->sa_Operation[0] != None ||
  778. (pSA->sa_Flags & FLAGS_SA_TUNNEL)
  779. ) {
  780. if (g_ipsec.DiagnosticMode & IPSEC_DIAGNOSTIC_INBOUND) {
  781. IPSecBufferEvent( pIPH->iph_src,
  782. EVENT_IPSEC_UNEXPECTED_CLEARTEXT,
  783. 2,
  784. TRUE);
  785. }
  786. IPSEC_DEBUG(
  787. LL_A,
  788. DBF_CLEARTEXT,
  789. ("Unexpected clear text: src %lx, dest %lx, protocol %lx", pIPH->iph_src, pIPH->iph_dest, pIPH->iph_protocol));
  790. #if DBG
  791. if (IPSecDebug & DBF_EXTRADIAGNOSTIC)
  792. {
  793. PUCHAR pTpt;
  794. ULONG tptLen;
  795. UNALIGNED WORD *pwPort;
  796. IPSecQueryRcvBuf(pData, &pTpt, &tptLen);
  797. pwPort = (UNALIGNED WORD *)(pTpt);
  798. IPSEC_DEBUG(
  799. LL_A,
  800. DBF_CLEARTEXT,
  801. ("Unexpected clear text: src sport %lx, dport %lx", pwPort[0], pwPort[1]));
  802. }
  803. #endif
  804. IPSEC_DEBUG(LL_A, DBF_PARSE, ("Real SA present"));
  805. status = IPSEC_INVALID_CLEARTEXT;
  806. }
  807. IPSecDerefSA(pSA);
  808. }
  809. } else {
  810. pIPH = (UNALIGNED IPHeader *)*pIPHeader;
  811. IPSEC_SPI_TO_ENTRY(SPI, &pSA, pIPH->iph_dest);
  812. //
  813. // Report Bad SPI event only if there is no matching SA.
  814. //
  815. if (!pSA) {
  816. IPSEC_INC_STATISTIC(dwNumBadSPIPackets);
  817. IPSecBufferEvent( pIPH->iph_src,
  818. EVENT_IPSEC_BAD_SPI_RECEIVED,
  819. 1,
  820. TRUE);
  821. IPSEC_DEBUG(LL_A, DBF_PARSE, ("Bad spi: %lx", SPI));
  822. status = IPSEC_BAD_SPI;
  823. goto out;
  824. }
  825. //
  826. // If larval SA exits, silently discard the packet.
  827. //
  828. if (pSA->sa_State != STATE_SA_ACTIVE && pSA->sa_State != STATE_SA_LARVAL_ACTIVE) {
  829. IPSecDerefSA(pSA);
  830. status = STATUS_INVALID_PARAMETER;
  831. goto out;
  832. }
  833. //
  834. // Set the last used time.
  835. //
  836. NdisGetCurrentSystemTime(&pSA->sa_LastUsedTime);
  837. if (!(pSA->sa_Flags & FLAGS_SA_DISABLE_LIFETIME_CHECK)) {
  838. //
  839. // Check if we might expire soon - start rekey operation now.
  840. //
  841. IPSEC_CHECK_PADDED_LIFETIME(pSA, fLifetime, 0);
  842. if (fLifetime == FALSE) {
  843. IPSecRekeyInboundSA(pSA);
  844. }
  845. //
  846. // Check the real lifetime - if we have expired, ensure that the
  847. // rekey was submitted and then cancel the current SAs.
  848. //
  849. IPSEC_CHECK_LIFETIME(pSA, fLifetime, 0);
  850. if (fLifetime == FALSE) {
  851. IPSecPuntInboundSA(pSA);
  852. IPSecDerefSA(pSA);
  853. status = STATUS_UNSUCCESSFUL;
  854. goto out;
  855. }
  856. }
  857. if (pSA->sa_Flags & FLAGS_SA_TUNNEL) {
  858. ADD_TO_LARGE_INTEGER(
  859. &g_ipsec.Statistics.uBytesReceivedInTunnels,
  860. NET_SHORT(pIPH->iph_length));
  861. } else {
  862. ADD_TO_LARGE_INTEGER(
  863. &g_ipsec.Statistics.uTransportBytesReceived,
  864. NET_SHORT(pIPH->iph_length));
  865. }
  866. ADD_TO_LARGE_INTEGER(
  867. &pSA->sa_Stats.TotalBytesReceived,
  868. NET_SHORT(pIPH->iph_length));
  869. //
  870. // If this was supposed to be handled by hardware, then make sure he
  871. // either punted it or this was cryptoonly.
  872. //
  873. if (IPSecPktInfo != NULL) {
  874. if (IPSecPktInfo->Receive.CRYPTO_DONE) {
  875. //
  876. // Offload has been applied to this packet so
  877. // record it. We are here because CryptoStatus
  878. // equals CRYPTO_SUCCESS.
  879. //
  880. ASSERT(IPSecPktInfo->Receive.CryptoStatus == CRYPTO_SUCCESS);
  881. fCryptoOnly = TRUE;
  882. ADD_TO_LARGE_INTEGER(
  883. &pSA->sa_Stats.OffloadedBytesReceived,
  884. NET_SHORT(pIPH->iph_length));
  885. ADD_TO_LARGE_INTEGER(
  886. &g_ipsec.Statistics.uOffloadedBytesReceived,
  887. NET_SHORT(pIPH->iph_length));
  888. }
  889. if (IPSecPktInfo->Receive.SA_DELETE_REQ) {
  890. //
  891. // No more offload on this SA and its corresponding
  892. // outbound SA.
  893. //
  894. AcquireWriteLock(&g_ipsec.SADBLock, &kIrql);
  895. if ((pSA->sa_Flags & FLAGS_SA_HW_PLUMBED) &&
  896. (pSA->sa_IPIF == DestIF)) {
  897. IPSecDelHWSAAtDpc(pSA);
  898. }
  899. if (pSA->sa_AssociatedSA &&
  900. (pSA->sa_AssociatedSA->sa_Flags & FLAGS_SA_HW_PLUMBED) &&
  901. (pSA->sa_AssociatedSA->sa_IPIF == DestIF)) {
  902. IPSecDelHWSAAtDpc(pSA->sa_AssociatedSA);
  903. }
  904. ReleaseWriteLock(&g_ipsec.SADBLock, kIrql);
  905. }
  906. }
  907. //
  908. // If SA is not offloaded, try to offload it now.
  909. //
  910. if (!fCryptoOnly && (g_ipsec.EnableOffload)) {
  911. IPSecRecvOffload(pIPH, DestIF, pSA);
  912. }
  913. //
  914. // With multiple SAs coming in, we need to iterate through the operations,
  915. // last first.
  916. //
  917. for (Index = pSA->sa_NumOps-1; (LONG)Index >= 0; Index--) {
  918. //
  919. // Got to keep resetting pIPH since pIPHeader can change in the
  920. // IPSecVerifyXXX calls
  921. //
  922. pIPH = (UNALIGNED IPHeader *)*pIPHeader;
  923. switch (pSA->sa_Operation[Index]) {
  924. case Auth:
  925. //
  926. // Verify AH
  927. //
  928. if (pIPH->iph_protocol != PROTOCOL_AH) {
  929. IPSecBufferEvent( pIPH->iph_src,
  930. EVENT_IPSEC_BAD_PROTOCOL_RECEIVED,
  931. 1,
  932. TRUE);
  933. status = STATUS_UNSUCCESSFUL;
  934. break;
  935. }
  936. status = IPSecVerifyAH( pIPHeader,
  937. pData,
  938. pSA,
  939. Index,
  940. pExtraBytes,
  941. fSrcRoute,
  942. fCryptoOnly,
  943. fFastRcv);
  944. if (!NT_SUCCESS(status)) {
  945. IPSEC_DEBUG(LL_A, DBF_PARSE, ("AH failed: pSA: %p, status: %lx",
  946. pSA,
  947. status));
  948. IPSecDerefSA(pSA);
  949. goto out;
  950. }
  951. break;
  952. case Encrypt:
  953. //
  954. // Hughes ..
  955. //
  956. if ((pIPH->iph_protocol != PROTOCOL_ESP) &&
  957. !((pIPH->iph_protocol == PROTOCOL_UDP) && bNatEncap &&
  958. (pSA->sa_EncapType != SA_UDP_ENCAP_TYPE_NONE))) {
  959. IPSecBufferEvent( pIPH->iph_src,
  960. EVENT_IPSEC_BAD_PROTOCOL_RECEIVED,
  961. 2,
  962. TRUE);
  963. status = STATUS_UNSUCCESSFUL;
  964. break;
  965. }
  966. status = IPSecVerifyHughes( pIPHeader,
  967. pData,
  968. pSA,
  969. Index,
  970. pExtraBytes,
  971. fCryptoOnly,
  972. fFastRcv);
  973. if (status == IPSEC_SUCCESS_NAT_DECAPSULATE) {
  974. status = STATUS_SUCCESS;
  975. // Since xsum will be wrong through the NAT, tell the stack
  976. // its correct.
  977. if (!(pSA->sa_Flags & FLAGS_SA_TUNNEL)) {
  978. if (pIPH->iph_protocol == PROTOCOL_TCP) {
  979. (*pIpsecFlags) |= IPSEC_FLAG_TCP_CHECKSUM_VALID;
  980. }
  981. if (pIPH->iph_protocol == PROTOCOL_UDP) {
  982. status = IPSecDisableUdpXsum((IPRcvBuf*)pData);
  983. }
  984. status=AddShimContext(pIPHeader,
  985. pData,
  986. &NatContext);
  987. }
  988. }
  989. if (!NT_SUCCESS(status)) {
  990. IPSEC_DEBUG(LL_A, DBF_PARSE, ("Hughes failed: pSA: %p, status: %lx",
  991. pSA,
  992. status));
  993. IPSecDerefSA(pSA);
  994. goto out;
  995. }
  996. break;
  997. case None:
  998. //
  999. // None is useful for down-level clients - if the peer is incapable
  1000. // of IPSEC, we might have a system policy to send in clear. in that
  1001. // case, the Operation will be None.
  1002. //
  1003. status = STATUS_SUCCESS;
  1004. break;
  1005. default:
  1006. IPSEC_DEBUG(LL_A, DBF_PARSE, ("Invalid op in SA: %p, Index: %d", pSA, Index));
  1007. ASSERT(FALSE);
  1008. break;
  1009. }
  1010. }
  1011. //
  1012. // If this was a tunnel SA that succeeded in decrypt/auth,
  1013. // drop this packet and re-inject a copy.
  1014. // In any case perform a lookup
  1015. if (status == STATUS_SUCCESS){
  1016. if (!(pSA->sa_Flags & FLAGS_SA_TUNNEL)){
  1017. status = IPSecVerifyIncomingFilterSA(
  1018. pIPHeader,
  1019. pData,
  1020. pSA,
  1021. DestType,
  1022. fLoopback,
  1023. FALSE,
  1024. &SavedNatContext);
  1025. }
  1026. else
  1027. {
  1028. PNDIS_BUFFER pHdrMdl = NULL, pDataMdl = NULL, pOptMdl = NULL;
  1029. PUCHAR pIPH = NULL;
  1030. PIPSEC_SEND_COMPLETE_CONTEXT pContext = NULL;
  1031. ULONG DataLen;
  1032. NTSTATUS ReinjectStatus;
  1033. // If this function fails it releases memory on it's own
  1034. ReinjectStatus = IPSecPrepareReinjectPacket(
  1035. pData, fCryptoOnly? PktExt: NULL,
  1036. &pHdrMdl,
  1037. &pIPH,
  1038. &pOptMdl,
  1039. &pDataMdl,
  1040. &pContext,
  1041. &DataLen);
  1042. // If we succeeded in creating the new packet
  1043. if (STATUS_SUCCESS == ReinjectStatus){
  1044. status = IPSecVerifyIncomingFilterSA(&pIPH,
  1045. pHdrMdl,
  1046. pSA,
  1047. DestType,
  1048. fLoopback,
  1049. TRUE,
  1050. &SavedNatContext);
  1051. // Drop new packet if verification failed
  1052. if(STATUS_SUCCESS != status){
  1053. NTSTATUS ntstatus;
  1054. IPSecFreeBuffer(&ntstatus, pHdrMdl);
  1055. IPSecFreeBuffer(&ntstatus, pDataMdl);
  1056. if (pOptMdl){
  1057. IPSecFreeBuffer(&ntstatus, pOptMdl);
  1058. }
  1059. if (pContext->PktExt) {
  1060. IPSecFreeMemory(pContext->PktExt);
  1061. }
  1062. IPSecFreeSendCompleteCtx(pContext);
  1063. }
  1064. // New packet creation and filter verfication succeeded
  1065. else {
  1066. // This function always returns success
  1067. ReinjectStatus = IPSecReinjectPreparedPacket(
  1068. pHdrMdl,
  1069. pContext,
  1070. DataLen,
  1071. pIPH);
  1072. }
  1073. }
  1074. // Drop the old packet
  1075. status = STATUS_INVALID_PARAMETER;
  1076. if (pDropStatus) {
  1077. pDropStatus->Flags |= IPSEC_DROP_STATUS_DONT_LOG;
  1078. }
  1079. }
  1080. }
  1081. IPSecDerefSA(pSA);
  1082. }
  1083. out:
  1084. if (!NT_SUCCESS(status)) {
  1085. IPSEC_DEBUG(LL_A, DBF_PARSE, ("IPSecRecvPacket failed: %lx", status));
  1086. eRetAction = eDROP;
  1087. }
  1088. if (pDropStatus) {
  1089. pDropStatus->IPSecStatus=status;
  1090. }
  1091. IPSEC_DEBUG(LL_A, DBF_PARSE, ("Exiting IPSecRecvPacket; action %lx", eRetAction));
  1092. return eRetAction;
  1093. }
  1094. NTSTATUS
  1095. IPSecVerifyIncomingFilterSA(IN PUCHAR * pIPHeader,
  1096. IN PVOID pData,
  1097. IN PSA_TABLE_ENTRY pSA,
  1098. IN UCHAR DestType,
  1099. BOOLEAN fLoopback,
  1100. BOOLEAN fReinject,
  1101. IN PIPSEC_UDP_ENCAP_CONTEXT pNatContext
  1102. )
  1103. /*++
  1104. Routine Description:
  1105. Does a filter lookup on a packet after VerifyHughes or
  1106. VerifyAh to make sure the packet did indeed come in
  1107. on the SA it was supposed to come in over.
  1108. Called on Recv Path
  1109. Arguments:
  1110. pIPHeader: Pointer to pointer to IP Header
  1111. pData : RcvBuf corresponding to start of payload
  1112. pSA : pointer to SA we just applied to the packet
  1113. fLoopback: Is this packet on the loopback.
  1114. Return Value:
  1115. Succesful classification and match: STATUS_SUCCESS
  1116. IPSEC_BLOCK otherwise
  1117. */
  1118. {
  1119. PSA_TABLE_ENTRY pLookupSA = NULL,pLookupNextSA = NULL;
  1120. USHORT FilterFlags;
  1121. NTSTATUS status = STATUS_SUCCESS;
  1122. int dropReason=0;
  1123. if (pNatContext) {
  1124. if ((0 == pNatContext->wSrcEncapPort )
  1125. && (0 == pNatContext->wDesEncapPort )){
  1126. pNatContext = NULL;
  1127. }
  1128. }
  1129. status = IPSecClassifyPacket( *pIPHeader,
  1130. pData,
  1131. &pLookupSA,
  1132. &pLookupNextSA,
  1133. &FilterFlags,
  1134. #if GPC
  1135. 0,
  1136. #endif
  1137. FALSE, //foutbound
  1138. FALSE, //ffwpacket
  1139. TRUE, // do bypass check
  1140. fReinject,
  1141. TRUE, //Verify call
  1142. DestType,
  1143. pNatContext); //NatContext
  1144. if (status!= STATUS_SUCCESS){
  1145. IPSEC_DEBUG(LL_A,DBF_PARSE,("Packet Drop , Classify failed \n"));
  1146. //
  1147. // If we didnt find an SA, but found a filter, Rekey in progress.
  1148. //
  1149. if (status == STATUS_PENDING) {
  1150. status = STATUS_SUCCESS;
  1151. }
  1152. else
  1153. if (status == STATUS_UNSUCCESSFUL) {
  1154. //Happens for bypass traffic in tunnel and traffic for which no filter found
  1155. status = STATUS_SUCCESS;
  1156. }
  1157. else {
  1158. status = IPSEC_BLOCK;
  1159. dropReason = 1;
  1160. }
  1161. goto out;
  1162. }
  1163. if ((pSA->sa_Flags & FLAGS_SA_TUNNEL) && (pLookupNextSA)){
  1164. IPSecDerefSA(pLookupSA);
  1165. pLookupSA = pLookupNextSA;
  1166. pLookupNextSA = NULL;
  1167. FilterFlags = 0;
  1168. }
  1169. if (FilterFlags) {
  1170. if (FilterFlags & FILTER_FLAGS_DROP) {
  1171. IPSEC_DEBUG(LL_A,DBF_PARSE,("Packet Drop , Matched Drop Filter"));
  1172. dropReason = 2;
  1173. status = IPSEC_BLOCK;
  1174. goto out;
  1175. }
  1176. if (FilterFlags & FILTER_FLAGS_PASS_THRU) {
  1177. //We have a zero paylength IP packet
  1178. IPSEC_DEBUG(LL_A, DBF_PARSE, ("Pass thru' filter"));
  1179. status = STATUS_SUCCESS;
  1180. goto out;
  1181. }
  1182. }
  1183. // If this is cleartext and we matched a tunnel
  1184. // SA too,make sure it is on the loopback path.
  1185. // This ensures (for the time being)
  1186. // that the packet did come over a tunnel
  1187. // by checking that it came from the
  1188. // loopback interface (i.e it was reinjected.
  1189. if (!(pSA->sa_Flags && FLAGS_SA_TUNNEL) && pLookupNextSA && !fLoopback){
  1190. status = IPSEC_BLOCK;
  1191. dropReason = 3;
  1192. IPSEC_DEBUG(LL_A,DBF_PARSE,("Packet Drop , Transport over tunnel not over loopback"));
  1193. goto out;
  1194. }
  1195. if (pLookupSA != pSA){
  1196. //Possible Rekey?
  1197. //Compare Sa fields
  1198. IPSEC_DEBUG(LL_A,DBF_PARSE,("Rekey!!"));
  1199. if (!((pLookupSA->sa_uliSrcDstAddr.QuadPart &
  1200. pLookupSA->sa_uliSrcDstMask.QuadPart)
  1201. ==
  1202. (pSA->sa_uliSrcDstAddr.QuadPart &
  1203. pSA->sa_uliSrcDstMask.QuadPart))){
  1204. status = IPSEC_BLOCK;
  1205. IPSEC_DEBUG(LL_A,DBF_PARSE,("Packet drop: Rekey and SA adress dont match"));
  1206. dropReason = 4;
  1207. ASSERT(FALSE);
  1208. goto out;
  1209. }
  1210. if (pLookupSA->sa_uliProtoSrcDstPort.QuadPart
  1211. != pSA->sa_uliProtoSrcDstPort.QuadPart){
  1212. //
  1213. // Check if packet came over a generic SA and the Specifc SA has expired
  1214. //
  1215. if ((pLookupSA->sa_Flags & FLAGS_SA_DELETE_BY_IOCTL) &&
  1216. (IPSecIsGenericPortsProtocolOf(pSA->sa_uliProtoSrcDstPort,pLookupSA->sa_uliProtoSrcDstPort))){
  1217. IPSEC_DEBUG(LL_A,DBF_PARSE,("Packet came over a generic SA and the specific SA has expired"));
  1218. }
  1219. else{
  1220. status = IPSEC_BLOCK;
  1221. IPSEC_DEBUG(LL_A,DBF_PARSE,("Packet Drop: Rekey and SA ports dont match"));
  1222. dropReason = 5;
  1223. // Fix for RRAS stop problem ; specific filters get deleted first
  1224. // and traffic now goes over generic filters triggering this assert
  1225. if ((SA_SRC_PORT(pSA) != IPSEC_L2TP_PORT ) && ( SA_DEST_PORT(pSA) != IPSEC_L2TP_PORT)){
  1226. ASSERT(FALSE);
  1227. }
  1228. else{
  1229. IPSEC_DEBUG(LL_A,DBF_PARSE,("RRAS Filter mismatch\n"));
  1230. }
  1231. goto out;
  1232. }
  1233. }
  1234. if ((SA_UDP_ENCAP_TYPE_NONE != pLookupSA->sa_EncapType) ||
  1235. ( SA_UDP_ENCAP_TYPE_NONE != pSA->sa_EncapType))
  1236. {
  1237. if (!((pLookupSA->sa_EncapType == pSA->sa_EncapType)
  1238. &&
  1239. (pLookupSA->sa_EncapContext.wSrcEncapPort
  1240. ==
  1241. pSA->sa_EncapContext.wSrcEncapPort )
  1242. &&
  1243. (pLookupSA->sa_EncapContext.wDesEncapPort
  1244. ==
  1245. pSA->sa_EncapContext.wDesEncapPort))){
  1246. status = IPSEC_BLOCK;
  1247. IPSEC_DEBUG(LL_A,DBF_PARSE,("Packet Drop: Rekey and UDP encap info dont match "));
  1248. dropReason = 6;
  1249. ASSERT(FALSE);
  1250. goto out;
  1251. }
  1252. }
  1253. }
  1254. out:
  1255. if (STATUS_SUCCESS != status ) {
  1256. InterlockedIncrement(&g_ipsec.dwPacketsOnWrongSA);
  1257. IPSEC_DEBUG(LL_A,DBF_PARSE,("Packet from %lx to %lx with protocol %lx length %lx id %lx ",
  1258. ((IPHeader *)*pIPHeader)->iph_src,
  1259. ((IPHeader *)*pIPHeader)->iph_dest,
  1260. ((IPHeader *)*pIPHeader)->iph_protocol,
  1261. NET_SHORT(((IPHeader*)*pIPHeader)->iph_length),
  1262. NET_SHORT(((IPHeader *)*pIPHeader)->iph_id)));
  1263. IPSEC_DEBUG(LL_A,DBF_PARSE,("Packets Dropped =%d DropReason=%d",g_ipsec.dwPacketsOnWrongSA,dropReason ));
  1264. }
  1265. if (pLookupSA){
  1266. IPSecDerefSANextSA(pLookupSA,pLookupNextSA);
  1267. }
  1268. return status;
  1269. }
  1270. VOID
  1271. IPSecCalcHeaderOverheadFromSA(
  1272. IN PSA_TABLE_ENTRY pSA,
  1273. OUT PULONG pOverhead
  1274. )
  1275. /*++
  1276. Routine Description:
  1277. Called from IP to query the IPSEC header overhead.
  1278. Arguments:
  1279. pIPHeader - points to start of IP header.
  1280. pOverhead - number of bytes in IPSEC header.
  1281. Return Value:
  1282. None
  1283. --*/
  1284. {
  1285. LONG Index;
  1286. ULONG AHSize = sizeof(AH) + pSA->sa_TruncatedLen;
  1287. ULONG ESPSize = sizeof(ESP) + pSA->sa_ivlen + pSA->sa_ReplayLen + MAX_PAD_LEN + pSA->sa_TruncatedLen;
  1288. DWORD dwExtraTransportNat=0;
  1289. //
  1290. // Take the actual SA to get the exact value.
  1291. //
  1292. *pOverhead = 0;
  1293. for (Index = 0; Index < pSA->sa_NumOps; Index++) {
  1294. switch (pSA->sa_Operation[Index]) {
  1295. case Encrypt:
  1296. *pOverhead += ESPSize;
  1297. switch (pSA->sa_EncapType) {
  1298. case SA_UDP_ENCAP_TYPE_NONE:
  1299. break;
  1300. case SA_UDP_ENCAP_TYPE_IKE:
  1301. dwExtraTransportNat= sizeof(NATENCAP);
  1302. break;
  1303. case SA_UDP_ENCAP_TYPE_OTHER:
  1304. dwExtraTransportNat=sizeof(NATENCAP_OTHER);
  1305. break;
  1306. }
  1307. *pOverhead += dwExtraTransportNat;
  1308. IPSEC_DEBUG(LL_A, DBF_PMTU, ("PROTOCOL_ESP: overhead: %lx", *pOverhead));
  1309. break;
  1310. case Auth:
  1311. *pOverhead += AHSize;
  1312. IPSEC_DEBUG(LL_A, DBF_PMTU, ("PROTOCOL_AH: overhead: %lx", *pOverhead));
  1313. break;
  1314. default:
  1315. IPSEC_DEBUG(LL_A, DBF_PMTU, ("No IPSEC headers"));
  1316. break;
  1317. }
  1318. }
  1319. if (pSA->sa_Flags & FLAGS_SA_TUNNEL) {
  1320. *pOverhead += sizeof(IPHeader);
  1321. IPSEC_DEBUG(LL_A, DBF_PMTU, ("TUNNEL: overhead: %lx", *pOverhead));
  1322. }
  1323. }
  1324. NTSTATUS
  1325. IPSecParsePacket(
  1326. IN PUCHAR pIPHeader,
  1327. IN PVOID *pData,
  1328. OUT tSPI *pSPI,
  1329. OUT BOOLEAN *bNatEncap,
  1330. OUT IPSEC_UDP_ENCAP_CONTEXT *pNatContext
  1331. )
  1332. /*++
  1333. Routine Description:
  1334. Walk the packet to determine the SPI, this also returns the
  1335. next header that might be also an IPSEC component.
  1336. Arguments:
  1337. pIPHeader - points to start of IP header.
  1338. pData - points to the data after the IP header.
  1339. pSPI - to return the SPI value.
  1340. Return Value:
  1341. --*/
  1342. {
  1343. IPHeader UNALIGNED *pIPH = (IPHeader UNALIGNED *)pIPHeader;
  1344. AH UNALIGNED *pAH;
  1345. ESP UNALIGNED *pEsp;
  1346. NATENCAP UNALIGNED *pNat;
  1347. NATENCAP_OTHER UNALIGNED *pNatOther;
  1348. NTSTATUS status = STATUS_NOT_FOUND;
  1349. PUCHAR pPyld;
  1350. ULONG Len;
  1351. tSPI TmpSpi;
  1352. IPSEC_DEBUG(LL_A, DBF_PARSE, ("Entering IPSecParsePacket"));
  1353. pNatContext->wSrcEncapPort=0;
  1354. pNatContext->wDesEncapPort=0;
  1355. IPSecQueryRcvBuf(pData, &pPyld, &Len);
  1356. if (pIPH->iph_protocol == PROTOCOL_AH) {
  1357. pAH = (UNALIGNED AH *)pPyld;
  1358. if (Len >= sizeof(AH)) {
  1359. *pSPI = NET_TO_HOST_LONG(pAH->ah_spi);
  1360. status = STATUS_SUCCESS;
  1361. }
  1362. } else if (pIPH->iph_protocol == PROTOCOL_ESP) {
  1363. pEsp = (UNALIGNED ESP *)pPyld;
  1364. if (Len >= sizeof(ESP)) {
  1365. *pSPI = NET_TO_HOST_LONG(pEsp->esp_spi);
  1366. status = STATUS_SUCCESS;
  1367. }
  1368. } else if (pIPH->iph_protocol == PROTOCOL_UDP) {
  1369. if (Len >= sizeof(NATENCAP_OTHER) + sizeof(tSPI)) {
  1370. pNatOther = (UNALIGNED NATENCAP_OTHER *)pPyld;
  1371. pNatContext->wSrcEncapPort=pNatOther->uh_src;
  1372. pNatContext->wDesEncapPort=pNatOther->uh_dest;
  1373. if (pNatOther->uh_dest == IPSEC_ISAKMP_PORT2) {
  1374. if (!(IsAllZero((BYTE*)(pNatOther+1),4))) {
  1375. memcpy(&TmpSpi,pNatOther+1,sizeof(tSPI));
  1376. *pSPI = NET_TO_HOST_LONG(TmpSpi);
  1377. *bNatEncap=TRUE;
  1378. status = STATUS_SUCCESS;
  1379. }
  1380. }
  1381. if (pNatOther->uh_dest == IPSEC_ISAKMP_PORT) {
  1382. pNat = (UNALIGNED NATENCAP *)pPyld;
  1383. if (Len >= sizeof(NATENCAP) + sizeof(tSPI)) {
  1384. if (IsAllZero(pNat->Zero,8)) {
  1385. memcpy(&TmpSpi,pNat+1,sizeof(tSPI));
  1386. *pSPI = NET_TO_HOST_LONG(TmpSpi);
  1387. *bNatEncap=TRUE;
  1388. status = STATUS_SUCCESS;
  1389. }
  1390. }
  1391. }
  1392. }
  1393. }
  1394. IPSEC_DEBUG(LL_A, DBF_PARSE, ("Exiting IPSecParsePacket"));
  1395. return status;
  1396. }
  1397. PSA_TABLE_ENTRY
  1398. IPSecLookupSAInLarval(
  1399. IN ULARGE_INTEGER uliSrcDstAddr,
  1400. IN ULARGE_INTEGER uliProtoSrcDstPort
  1401. )
  1402. /*++
  1403. Routine Description:
  1404. Search for SA (in larval list) matching the input params.
  1405. Arguments:
  1406. Return Value:
  1407. Pointer to SA matched else NULL
  1408. --*/
  1409. {
  1410. PLIST_ENTRY pEntry;
  1411. KIRQL kIrql;
  1412. ULARGE_INTEGER uliAddr;
  1413. ULARGE_INTEGER uliPort;
  1414. PSA_TABLE_ENTRY pSA = NULL;
  1415. IPSEC_BUILD_SRC_DEST_ADDR(uliAddr, DEST_ADDR, SRC_ADDR);
  1416. ACQUIRE_LOCK(&g_ipsec.LarvalListLock, &kIrql);
  1417. for ( pEntry = g_ipsec.LarvalSAList.Flink;
  1418. pEntry != &g_ipsec.LarvalSAList;
  1419. pEntry = pEntry->Flink) {
  1420. pSA = CONTAINING_RECORD(pEntry,
  1421. SA_TABLE_ENTRY,
  1422. sa_LarvalLinkage);
  1423. //
  1424. // responder inbound has no filter ptr
  1425. //
  1426. if (pSA->sa_Filter) {
  1427. uliPort.QuadPart = uliProtoSrcDstPort.QuadPart & pSA->sa_Filter->uliProtoSrcDstMask.QuadPart;
  1428. if ((uliAddr.QuadPart == pSA->sa_uliSrcDstAddr.QuadPart) &&
  1429. (uliPort.QuadPart == pSA->sa_Filter->uliProtoSrcDstPort.QuadPart)) {
  1430. IPSEC_DEBUG(LL_A, DBF_HASH, ("Matched entry: %p", pSA));
  1431. RELEASE_LOCK(&g_ipsec.LarvalListLock, kIrql);
  1432. return pSA;
  1433. }
  1434. } else {
  1435. if (uliAddr.QuadPart == pSA->sa_uliSrcDstAddr.QuadPart) {
  1436. IPSEC_DEBUG(LL_A, DBF_HASH, ("Matched entry: %p", pSA));
  1437. RELEASE_LOCK(&g_ipsec.LarvalListLock, kIrql);
  1438. return pSA;
  1439. }
  1440. }
  1441. }
  1442. RELEASE_LOCK(&g_ipsec.LarvalListLock, kIrql);
  1443. return NULL;
  1444. }
  1445. NTSTATUS
  1446. IPSecClassifyPacket(
  1447. IN PUCHAR pHeader,
  1448. IN PVOID pData,
  1449. OUT PSA_TABLE_ENTRY *ppSA,
  1450. OUT PSA_TABLE_ENTRY *ppNextSA,
  1451. OUT USHORT *pFilterFlags,
  1452. #if GPC
  1453. IN CLASSIFICATION_HANDLE GpcHandle,
  1454. #endif
  1455. IN BOOLEAN fOutbound,
  1456. IN BOOLEAN fFWPacket,
  1457. IN BOOLEAN fDoBypassCheck,
  1458. IN BOOLEAN fReinjectRecvPacket,
  1459. IN BOOLEAN fVerify,
  1460. IN UCHAR DestType,
  1461. IN PIPSEC_UDP_ENCAP_CONTEXT pNatContext
  1462. )
  1463. /*++
  1464. Routine Description:
  1465. Classifies the outgoing packet be matching the Src/Dest Address/Ports
  1466. with the filter database to arrive at an IPSEC_CONTEXT which is a set
  1467. of AH/ESP indices into the SA Table.
  1468. Adapted in most part from the Filter Driver.
  1469. Arguments:
  1470. pIPHeader - points to start of IP header.
  1471. pData - points to the data after the IP header.
  1472. ppSA - returns the SA if found.
  1473. pFilterFlags - flags of the filter if found returned here.
  1474. fOutbound - direction flag used in lookups.
  1475. fDoBypassCheck - if TRUE, we bypass port 500 traffic, else we block it.
  1476. Return Value:
  1477. Pointer to IPSEC_CONTEXT if packet matched else NULL
  1478. --*/
  1479. {
  1480. REGISTER UNALIGNED ULARGE_INTEGER *puliSrcDstAddr;
  1481. REGISTER ULARGE_INTEGER uliProtoSrcDstPort;
  1482. UNALIGNED WORD *pwPort;
  1483. PUCHAR pTpt;
  1484. ULONG tptLen;
  1485. REGISTER ULARGE_INTEGER uliAddr;
  1486. REGISTER ULARGE_INTEGER uliPort;
  1487. KIRQL kIrql;
  1488. REGISTER ULONG dwIndex;
  1489. REGISTER PFILTER_CACHE pCache;
  1490. IPHeader UNALIGNED *pIPHeader = (IPHeader UNALIGNED *)pHeader;
  1491. PSA_TABLE_ENTRY pSA = NULL;
  1492. PSA_TABLE_ENTRY pNextSA = NULL;
  1493. PSA_TABLE_ENTRY pTunnelSA = NULL;
  1494. PFILTER pFilter = NULL;
  1495. NTSTATUS status;
  1496. BOOLEAN fBypass;
  1497. PNDIS_BUFFER pTempBuf;
  1498. WORD wTpt[2];
  1499. PVOID OutContext=NULL;
  1500. IPSEC_UDP_ENCAP_CONTEXT TmpNatContext;
  1501. DWORD dwNatContext;
  1502. *ppSA = NULL;
  1503. *ppNextSA = NULL;
  1504. *pFilterFlags = 0;
  1505. wTpt[0] = wTpt[1] = 0;
  1506. //
  1507. // First buffer in pData chain points to start of IP header
  1508. //
  1509. if (fOutbound || fReinjectRecvPacket) {
  1510. if (((pIPHeader->iph_verlen & (UCHAR)~IP_VER_FLAG) << 2) > sizeof(IPHeader)) {
  1511. //
  1512. // Options -> third MDL has Tpt header
  1513. //
  1514. if (!(pTempBuf = IPSEC_NEXT_BUFFER((PNDIS_BUFFER)pData))) {
  1515. ASSERT(FALSE);
  1516. *pFilterFlags |= FILTER_FLAGS_DROP;
  1517. return STATUS_SUCCESS;
  1518. }
  1519. if (!(pTempBuf = IPSEC_NEXT_BUFFER(pTempBuf))) {
  1520. *pFilterFlags |= FILTER_FLAGS_DROP;
  1521. pwPort = (UNALIGNED WORD *) (wTpt);
  1522. tptLen=4;
  1523. }
  1524. else {
  1525. IPSecQueryNdisBuf(pTempBuf, &pTpt, &tptLen);
  1526. //Bug: 550484
  1527. if (tptLen >= 4){
  1528. pwPort = (UNALIGNED WORD *)(pTpt);
  1529. }
  1530. else{
  1531. // Treat this as having zero value for ports
  1532. pwPort = (UNALIGNED WORD *) (wTpt);
  1533. tptLen=4;
  1534. }
  1535. }
  1536. } else {
  1537. //
  1538. // no options -> second MDL has Tpt header
  1539. //
  1540. if (!(pTempBuf = IPSEC_NEXT_BUFFER((PNDIS_BUFFER)pData))) {
  1541. *pFilterFlags |= FILTER_FLAGS_DROP;
  1542. pwPort = (UNALIGNED WORD *) (wTpt);
  1543. tptLen=4;
  1544. }
  1545. else {
  1546. IPSecQueryNdisBuf(pTempBuf, &pTpt, &tptLen);
  1547. // Bug: 550484
  1548. if (tptLen >= 4){
  1549. pwPort = (UNALIGNED WORD *)(pTpt);
  1550. }
  1551. else{
  1552. // Treat this as having zero value for ports
  1553. pwPort = (UNALIGNED WORD *) (wTpt);
  1554. tptLen=4;
  1555. }
  1556. }
  1557. }
  1558. //
  1559. // We do this because TCPIP does not set the forward flag for reinjected packets
  1560. // which can also be fragments. Nat Shim does not know how to handle fragments
  1561. //
  1562. if (!IPSEC_FORWARD_PATH() && !fReinjectRecvPacket){
  1563. status=(g_ipsec.ShimFunctions.pOutgoingPacketRoutine)(pIPHeader,
  1564. pwPort,
  1565. tptLen,
  1566. (PVOID)&OutContext);
  1567. if (!NT_SUCCESS(status)) {
  1568. // Must not fail or packets go in clear. Drop it
  1569. *pFilterFlags |= FILTER_FLAGS_DROP;
  1570. return STATUS_SUCCESS;
  1571. }
  1572. }
  1573. dwNatContext = HandleToUlong(OutContext);
  1574. memcpy(&TmpNatContext,&dwNatContext,sizeof(IPSEC_UDP_ENCAP_CONTEXT));
  1575. IPSEC_DEBUG(
  1576. LL_A,
  1577. DBF_NATSHIM,
  1578. ("ProcessOutgoing: PreSwapOutContext %d ret %x",
  1579. *((DWORD*)&TmpNatContext),
  1580. status));
  1581. if (pNatContext) {
  1582. memcpy(pNatContext,&TmpNatContext.wDesEncapPort,sizeof(WORD));
  1583. memcpy(((PBYTE)pNatContext)+sizeof(WORD),&TmpNatContext.wSrcEncapPort,sizeof(WORD));
  1584. if (IsAllZero((BYTE*)&TmpNatContext,sizeof(IPSEC_UDP_ENCAP_CONTEXT))) {
  1585. pNatContext = NULL;
  1586. }
  1587. }
  1588. } else {
  1589. //
  1590. // inbound side; tpt starts at pData
  1591. //
  1592. IPSecQueryRcvBuf(pData, &pTpt, &tptLen);
  1593. if (pIPHeader->iph_protocol == PROTOCOL_TCP ||
  1594. pIPHeader->iph_protocol == PROTOCOL_UDP) {
  1595. if (tptLen < sizeof(WORD)*2) {
  1596. pwPort = (UNALIGNED WORD *) (wTpt);
  1597. }
  1598. else {
  1599. pwPort = (UNALIGNED WORD *)(pTpt);
  1600. }
  1601. }
  1602. else {
  1603. pwPort = (UNALIGNED WORD *) (wTpt);
  1604. }
  1605. }
  1606. // NAT Keepalive drop
  1607. if (!fOutbound && tptLen >= 6) {
  1608. if (IPSEC_ISAKMP_TRAFFIC() ||
  1609. IPSEC_ISAKMP_TRAFFIC2()) {
  1610. // Check UDP len for 1 data byte
  1611. if (NET_SHORT(pwPort[2]) == 9) {
  1612. IPSEC_DEBUG(LL_A, DBF_PARSE, ("NAT keep alive,Ports: %d.%d", pwPort[0], pwPort[1]));
  1613. *pFilterFlags |= FILTER_FLAGS_DROP;
  1614. return STATUS_SUCCESS;
  1615. }
  1616. }
  1617. }
  1618. puliSrcDstAddr = (UNALIGNED ULARGE_INTEGER*)(&(pIPHeader->iph_src));
  1619. IPSEC_DEBUG(LL_A, DBF_PARSE, ("Ports: %d.%d", pwPort[0], pwPort[1]));
  1620. IPSEC_BUILD_PROTO_PORT_LI( uliProtoSrcDstPort,
  1621. pIPHeader->iph_protocol,
  1622. pwPort[0],
  1623. pwPort[1]);
  1624. IPSEC_DEBUG(
  1625. LL_A, DBF_PATTERN,
  1626. ("Addr Large Int: High= %lx Low= %lx", puliSrcDstAddr->HighPart, puliSrcDstAddr->LowPart));
  1627. IPSEC_DEBUG(
  1628. LL_A, DBF_PATTERN,
  1629. ("Packet value is Src: %lx Dst: %lx",pIPHeader->iph_src,pIPHeader->iph_dest));
  1630. IPSEC_DEBUG(
  1631. LL_A, DBF_PATTERN,
  1632. ("Proto/Port:High= %lx Low= %lx",uliProtoSrcDstPort.HighPart,uliProtoSrcDstPort.LowPart));
  1633. IPSEC_DEBUG(LL_A, DBF_PATTERN, ("Iph is %px",pIPHeader));
  1634. IPSEC_DEBUG(LL_A, DBF_PATTERN,("Addr of src is %p",&(pIPHeader->iph_src)));
  1635. IPSEC_DEBUG(LL_A, DBF_PATTERN,("Ptr to LI is %p",puliSrcDstAddr));
  1636. //
  1637. // Determine if this is a packet that needs bypass checking
  1638. //
  1639. if (fDoBypassCheck && IPSEC_BYPASS_TRAFFIC() && !IPSEC_FORWARD_PATH()) {
  1640. fBypass = TRUE;
  1641. } else {
  1642. fBypass = FALSE;
  1643. }
  1644. //
  1645. // Sum up the fields and get the cache index. We make sure the sum
  1646. // is assymetric, i.e. a packet from A->B goes to different bucket
  1647. // than one from B->A
  1648. //
  1649. dwIndex = CalcCacheIndex( pIPHeader->iph_src,
  1650. pIPHeader->iph_dest,
  1651. pIPHeader->iph_protocol,
  1652. pwPort[0],
  1653. pwPort[1],
  1654. fOutbound);
  1655. IPSEC_DEBUG(LL_A, DBF_PATTERN, ("Cache Index is %d", dwIndex));
  1656. AcquireReadLock(&g_ipsec.SADBLock, &kIrql);
  1657. pCache = g_ipsec.ppCache[dwIndex];
  1658. if (!pNatContext) {
  1659. //To do, maybe: Build nat into cache??
  1660. //
  1661. // Try for a quick cache probe
  1662. //
  1663. if (!(*pFilterFlags & FILTER_FLAGS_DROP) && IS_VALID_CACHE_ENTRY(pCache) &&
  1664. CacheMatch(*puliSrcDstAddr, uliProtoSrcDstPort, pCache)) {
  1665. if (!pCache->FilterEntry) {
  1666. pSA = pCache->pSAEntry;
  1667. pNextSA = pCache->pNextSAEntry;
  1668. ASSERT(pSA->sa_State == STATE_SA_ACTIVE);
  1669. if (fOutbound == (BOOLEAN)((pSA->sa_Flags & FLAGS_SA_OUTBOUND) != 0)) {
  1670. if (fBypass) {
  1671. if (pNextSA) {
  1672. IPSecRefSA(pNextSA);
  1673. *ppSA = pNextSA;
  1674. status = STATUS_SUCCESS;
  1675. } else {
  1676. status = STATUS_UNSUCCESSFUL;
  1677. }
  1678. } else {
  1679. if (pNextSA) {
  1680. IPSecRefSA(pNextSA);
  1681. *ppNextSA = pNextSA;
  1682. }
  1683. IPSecRefSA(pSA);
  1684. *ppSA = pSA;
  1685. status = STATUS_SUCCESS;
  1686. }
  1687. #if DBG
  1688. ADD_TO_LARGE_INTEGER(&pCache->CacheHitCount, 1);
  1689. ADD_TO_LARGE_INTEGER(&g_ipsec.CacheHitCount, 1);
  1690. #endif
  1691. ReleaseReadLock(&g_ipsec.SADBLock, kIrql);
  1692. return status;
  1693. }
  1694. } else if (!fBypass) {
  1695. pFilter = pCache->pFilter;
  1696. ASSERT(IS_EXEMPT_FILTER(pFilter));
  1697. *pFilterFlags = pFilter->Flags;
  1698. #if DBG
  1699. ADD_TO_LARGE_INTEGER(&pCache->CacheHitCount, 1);
  1700. ADD_TO_LARGE_INTEGER(&g_ipsec.CacheHitCount, 1);
  1701. #endif
  1702. ReleaseReadLock(&g_ipsec.SADBLock, kIrql);
  1703. return STATUS_SUCCESS;
  1704. }
  1705. }
  1706. }
  1707. //
  1708. // check the non-manual filters first.
  1709. //
  1710. #if GPC
  1711. if (fBypass || fFWPacket || !IS_GPC_ACTIVE()) {
  1712. status = IPSecLookupSAByAddr( *puliSrcDstAddr,
  1713. uliProtoSrcDstPort,
  1714. &pFilter,
  1715. &pSA,
  1716. &pNextSA,
  1717. &pTunnelSA,
  1718. fOutbound,
  1719. fFWPacket,
  1720. fBypass,
  1721. fVerify,
  1722. pNatContext);
  1723. } else {
  1724. status = IPSecLookupGpcSA( *puliSrcDstAddr,
  1725. uliProtoSrcDstPort,
  1726. GpcHandle,
  1727. &pFilter,
  1728. &pSA,
  1729. &pNextSA,
  1730. &pTunnelSA,
  1731. fOutbound,
  1732. fVerify,
  1733. pNatContext);
  1734. }
  1735. #else
  1736. status = IPSecLookupSAByAddr( *puliSrcDstAddr,
  1737. uliProtoSrcDstPort,
  1738. &pFilter,
  1739. &pSA,
  1740. &pNextSA,
  1741. &pTunnelSA,
  1742. fOutbound,
  1743. fFWPacket,
  1744. fBypass,
  1745. fVerify,
  1746. pNatContext);
  1747. #endif
  1748. //
  1749. // Special Processing for zero length payload packets.
  1750. //
  1751. if (*pFilterFlags & FILTER_FLAGS_DROP) {
  1752. if (pFilter) {
  1753. if (IS_EXEMPT_FILTER(pFilter)) {
  1754. *pFilterFlags = pFilter->Flags;
  1755. }
  1756. }
  1757. else {
  1758. *pFilterFlags = FILTER_FLAGS_PASS_THRU;
  1759. }
  1760. ReleaseReadLock(&g_ipsec.SADBLock, kIrql);
  1761. return STATUS_SUCCESS;
  1762. }
  1763. if (status == STATUS_SUCCESS) {
  1764. if (fBypass) {
  1765. if (pNextSA) {
  1766. if (pNextSA->sa_State == STATE_SA_ACTIVE || pNextSA->sa_State == STATE_SA_LARVAL_ACTIVE) {
  1767. IPSecRefSA(pNextSA);
  1768. *ppSA = pNextSA;
  1769. status = STATUS_SUCCESS;
  1770. } else {
  1771. *pFilterFlags = pFilter->Flags;
  1772. status = STATUS_PENDING;
  1773. }
  1774. } else {
  1775. status = STATUS_UNSUCCESSFUL;
  1776. }
  1777. ReleaseReadLock(&g_ipsec.SADBLock, kIrql);
  1778. return status;
  1779. }
  1780. if ((pSA->sa_State != STATE_SA_ACTIVE && pSA->sa_State != STATE_SA_LARVAL_ACTIVE) ||
  1781. (pNextSA && pNextSA->sa_State != STATE_SA_ACTIVE && pNextSA->sa_State != STATE_SA_LARVAL_ACTIVE)) {
  1782. IPSEC_DEBUG(LL_A, DBF_PATTERN, ("State is not active: %p, %lx", pSA, pSA->sa_State));
  1783. *pFilterFlags = pFilter->Flags;
  1784. ReleaseReadLock(&g_ipsec.SADBLock, kIrql);
  1785. return STATUS_PENDING;
  1786. } else {
  1787. if (pNextSA) {
  1788. IPSecRefSA(pNextSA);
  1789. *ppNextSA = pNextSA;
  1790. }
  1791. IPSecRefSA(pSA);
  1792. *ppSA = pSA;
  1793. ReleaseReadLockFromDpc(&g_ipsec.SADBLock);
  1794. AcquireWriteLockAtDpc(&g_ipsec.SADBLock);
  1795. if (pSA->sa_State == STATE_SA_ACTIVE &&
  1796. (!pNextSA ||
  1797. pNextSA->sa_State == STATE_SA_ACTIVE)) {
  1798. CacheUpdate(*puliSrcDstAddr,
  1799. uliProtoSrcDstPort,
  1800. pSA,
  1801. pNextSA,
  1802. dwIndex,
  1803. FALSE);
  1804. }
  1805. ReleaseWriteLock(&g_ipsec.SADBLock, kIrql);
  1806. return STATUS_SUCCESS;
  1807. }
  1808. } else if (status == STATUS_PENDING) {
  1809. if (IS_EXEMPT_FILTER(pFilter)) {
  1810. IPSEC_DEBUG(LL_A, DBF_PARSE, ("Drop or Pass thru flags: %p", pFilter));
  1811. *pFilterFlags = pFilter->Flags;
  1812. IPSecRefFilter(pFilter);
  1813. ReleaseReadLockFromDpc(&g_ipsec.SADBLock);
  1814. AcquireWriteLockAtDpc(&g_ipsec.SADBLock);
  1815. if (pFilter->LinkedFilter) {
  1816. CacheUpdate(*puliSrcDstAddr,
  1817. uliProtoSrcDstPort,
  1818. pFilter,
  1819. NULL,
  1820. dwIndex,
  1821. TRUE);
  1822. }
  1823. ReleaseWriteLock(&g_ipsec.SADBLock, kIrql);
  1824. IPSecDerefFilter(pFilter);
  1825. return STATUS_SUCCESS;
  1826. }
  1827. //
  1828. // This is ensure that in a tunnel+tpt mode, the oakley packet for
  1829. // the tpt SA goes thru the tunnel.
  1830. //
  1831. if (pTunnelSA) {
  1832. if (fBypass) {
  1833. if (pTunnelSA->sa_State != STATE_SA_ACTIVE && pTunnelSA->sa_State != STATE_SA_LARVAL_ACTIVE) {
  1834. IPSEC_DEBUG(LL_A, DBF_PATTERN, ("State is not active: %p, %lx", pTunnelSA, pTunnelSA->sa_State));
  1835. *pFilterFlags = pFilter->Flags;
  1836. ReleaseReadLock(&g_ipsec.SADBLock, kIrql);
  1837. return STATUS_PENDING;
  1838. } else {
  1839. IPSecRefSA(pTunnelSA);
  1840. *ppSA = pTunnelSA;
  1841. //
  1842. // we dont update the cache since this SA, once it comes up,
  1843. // it is the one that is looked up first.
  1844. //
  1845. ReleaseReadLock(&g_ipsec.SADBLock, kIrql);
  1846. return STATUS_SUCCESS;
  1847. }
  1848. }
  1849. }
  1850. if (fBypass) {
  1851. ReleaseReadLock(&g_ipsec.SADBLock, kIrql);
  1852. return STATUS_UNSUCCESSFUL;
  1853. }
  1854. //
  1855. // We only negotiate outbound SAs.
  1856. //
  1857. if (!fOutbound) {
  1858. *pFilterFlags = pFilter->Flags;
  1859. ReleaseReadLock(&g_ipsec.SADBLock, kIrql);
  1860. return status;
  1861. }
  1862. //
  1863. // need to negotiate the keys - filter exists.
  1864. //
  1865. IPSEC_DEBUG(LL_A, DBF_PATTERN, ("need to negotiate the keys - filter exists: %p", pFilter));
  1866. ASSERT(pSA == NULL);
  1867. IPSecRefFilter(pFilter);
  1868. ReleaseReadLock(&g_ipsec.SADBLock, kIrql);
  1869. AcquireWriteLock(&g_ipsec.SADBLock, &kIrql);
  1870. //
  1871. // If filter is deleted here we want to discard this packet
  1872. //
  1873. if (!pFilter->LinkedFilter) {
  1874. *pFilterFlags = pFilter->Flags;
  1875. IPSecDerefFilter(pFilter);
  1876. ReleaseWriteLock(&g_ipsec.SADBLock, kIrql);
  1877. return STATUS_PENDING;
  1878. }
  1879. status = IPSecNegotiateSA( pFilter,
  1880. *puliSrcDstAddr,
  1881. uliProtoSrcDstPort,
  1882. MAX_LONG,
  1883. &pSA,
  1884. DestType,
  1885. pNatContext);
  1886. IPSecDerefFilter(pFilter);
  1887. //
  1888. // Duplicate is returned if a neg is already on. Tell the caller to
  1889. // hold on to his horses.
  1890. //
  1891. if ((status != STATUS_DUPLICATE_OBJECTID) &&
  1892. !NT_SUCCESS(status)) {
  1893. IPSEC_DEBUG(LL_A, DBF_PATTERN, ("NegotiateSA failed: %lx", status));
  1894. *pFilterFlags = pFilter->Flags;
  1895. ReleaseWriteLock(&g_ipsec.SADBLock, kIrql);
  1896. return STATUS_PENDING;
  1897. }
  1898. //
  1899. // Pend this packet
  1900. //
  1901. if (pSA) {
  1902. IPSecQueuePacket(pSA, pData);
  1903. }
  1904. IPSEC_DEBUG(LL_A, DBF_PATTERN, ("Packet queued: %p, %p", pSA, pData));
  1905. *pFilterFlags = pFilter->Flags;
  1906. ReleaseWriteLock(&g_ipsec.SADBLock, kIrql);
  1907. return STATUS_PENDING;
  1908. } else {
  1909. ReleaseReadLock(&g_ipsec.SADBLock, kIrql);
  1910. return STATUS_UNSUCCESSFUL;
  1911. }
  1912. }
  1913. VOID
  1914. IPSecSendComplete(
  1915. IN PNDIS_PACKET Packet,
  1916. IN PVOID pData,
  1917. IN PIPSEC_SEND_COMPLETE_CONTEXT pContext,
  1918. IN IP_STATUS Status,
  1919. OUT PVOID *ppNewData
  1920. )
  1921. /*++
  1922. Routine Description:
  1923. Called by the stack on a SendComplete - frees up IPSEC's Mdls
  1924. Arguments:
  1925. pData - points to the data after the IP header. On the send side, this is an MDL chain
  1926. On the recv side this is an IPRcvBuf pointer.
  1927. pContext - send complete context
  1928. pNewData - if packet modified, this points to the new data.
  1929. Return Value:
  1930. STATUS_SUCCESS => Forward - Filter driver passes packet on to IP
  1931. STATUS_PENDING => Drop, IPSEC will re-inject
  1932. Others:
  1933. STATUS_INSUFFICIENT_RESOURCES => Drop
  1934. STATUS_UNSUCCESSFUL (error in algo./bad packet received) => Drop
  1935. --*/
  1936. {
  1937. NTSTATUS status;
  1938. PNDIS_BUFFER pMdl;
  1939. PNDIS_BUFFER pNextMdl;
  1940. BOOLEAN fFreeContext = TRUE;
  1941. *ppNewData = pData;
  1942. if (!pContext) {
  1943. return;
  1944. }
  1945. #if DBG
  1946. IPSEC_DEBUG(LL_A, DBF_MDL, ("Entering IPSecSendComplete"));
  1947. IPSEC_PRINT_CONTEXT(pContext);
  1948. IPSEC_PRINT_MDL(*ppNewData);
  1949. #endif
  1950. if (pContext->Flags & SCF_PKTINFO) {
  1951. IPSecFreePktInfo(pContext->PktInfo);
  1952. if (pContext->pSA) {
  1953. KIRQL kIrql;
  1954. PSA_TABLE_ENTRY pSA;
  1955. AcquireWriteLock(&g_ipsec.SADBLock, &kIrql);
  1956. pSA = (PSA_TABLE_ENTRY)pContext->pSA;
  1957. IPSEC_DECREMENT(pSA->sa_NumSends);
  1958. if (pSA->sa_Flags & FLAGS_SA_HW_DELETE_SA) {
  1959. IPSecDelHWSAAtDpc(pSA);
  1960. }
  1961. IPSecDerefSA(pSA);
  1962. pSA = (PSA_TABLE_ENTRY)pContext->pNextSA;
  1963. if (pSA) {
  1964. IPSEC_DECREMENT(pSA->sa_NumSends);
  1965. if (pSA->sa_Flags & FLAGS_SA_HW_DELETE_SA) {
  1966. IPSecDelHWSAAtDpc(pSA);
  1967. }
  1968. IPSecDerefSA(pSA);
  1969. }
  1970. ReleaseWriteLock(&g_ipsec.SADBLock, kIrql);
  1971. }
  1972. }
  1973. if (pContext->Flags & SCF_PKTEXT) {
  1974. IPSecFreePktExt(pContext->PktExt);
  1975. }
  1976. if (pContext->Flags & SCF_AH_2) {
  1977. IPSEC_DEBUG(LL_A, DBF_SEND, ("SendComplete: Outer AH: pContext: %p", pContext));
  1978. pMdl = pContext->AHMdl2;
  1979. ASSERT(pMdl);
  1980. IPSecFreeBuffer(&status, pMdl);
  1981. //
  1982. // return the older chain
  1983. //
  1984. if (pContext->Flags & SCF_FLUSH) {
  1985. NDIS_BUFFER_LINKAGE(pContext->PrevAHMdl2) = pContext->OriAHMdl2;
  1986. } else if (!(pContext->Flags & SCF_FRAG)) {
  1987. NDIS_BUFFER_LINKAGE(pContext->PrevAHMdl2) = pContext->OriAHMdl2;
  1988. // *ppNewData = (PVOID)(pContext->PrevMdl);
  1989. }
  1990. pContext->OriAHMdl2 = NULL;
  1991. }
  1992. if (pContext->Flags & SCF_AH_TU) {
  1993. IPSEC_DEBUG(LL_A, DBF_SEND, ("SendComplete: AH_TU: pContext: %p", pContext));
  1994. //
  1995. // Free the new IP header and the AH buffer and return the old chain
  1996. //
  1997. pMdl = pContext->AHTuMdl;
  1998. ASSERT(pMdl);
  1999. pNextMdl = NDIS_BUFFER_LINKAGE(pMdl);
  2000. IPSecFreeBuffer(&status, pMdl);
  2001. IPSecFreeBuffer(&status, pNextMdl);
  2002. //
  2003. // return the older chain
  2004. //
  2005. if (pContext->Flags & SCF_FLUSH) {
  2006. NDIS_BUFFER_LINKAGE(pContext->PrevTuMdl) = pContext->OriTuMdl;
  2007. } else if (!(pContext->Flags & SCF_FRAG)) {
  2008. NDIS_BUFFER_LINKAGE(pContext->PrevTuMdl) = pContext->OriTuMdl;
  2009. }
  2010. if (pContext->OptMdl) {
  2011. IPSecFreeBuffer(&status, pContext->OptMdl);
  2012. }
  2013. }
  2014. if (pContext->Flags & SCF_HU_TU) {
  2015. IPSEC_DEBUG(LL_A, DBF_SEND, ("SendComplete: HU_TU: pContext: %p", pContext));
  2016. //
  2017. // Free the encrypt chain and return the old chain
  2018. //
  2019. pMdl = pContext->HUTuMdl;
  2020. ASSERT(pMdl);
  2021. //
  2022. // In none case, free the esp header and the IP header.
  2023. //
  2024. if (pContext->Flags & SCF_NOE_TU) {
  2025. IPSecFreeBuffer(&status, pMdl);
  2026. ASSERT(pContext->PadTuMdl);
  2027. } else {
  2028. ASSERT(NDIS_BUFFER_LINKAGE(pMdl));
  2029. while (pMdl) {
  2030. pNextMdl = NDIS_BUFFER_LINKAGE(pMdl);
  2031. IPSecFreeBuffer(&status, pMdl);
  2032. pMdl = pNextMdl;
  2033. }
  2034. }
  2035. //
  2036. // Free the Pad mdl
  2037. //
  2038. if (pContext->PadTuMdl) {
  2039. IPSecFreeBuffer(&status, pContext->PadTuMdl);
  2040. }
  2041. if (pContext->HUHdrMdl) {
  2042. IPSecFreeBuffer(&status, pContext->HUHdrMdl);
  2043. }
  2044. if (pContext->OptMdl) {
  2045. IPSecFreeBuffer(&status, pContext->OptMdl);
  2046. }
  2047. NDIS_BUFFER_LINKAGE(pContext->BeforePadTuMdl) = NULL;
  2048. //
  2049. // return the older chain
  2050. //
  2051. if (pContext->Flags & SCF_FLUSH) {
  2052. NDIS_BUFFER_LINKAGE(pContext->PrevTuMdl) = pContext->OriTuMdl;
  2053. } else if (!(pContext->Flags & SCF_FRAG)) {
  2054. NDIS_BUFFER_LINKAGE(pContext->PrevTuMdl) = pContext->OriTuMdl;
  2055. }
  2056. }
  2057. if (pContext->Flags & SCF_AH) {
  2058. IPSEC_DEBUG(LL_A, DBF_SEND, ("SendComplete: AH: pContext: %p", pContext));
  2059. pMdl = pContext->AHMdl;
  2060. ASSERT(pMdl);
  2061. IPSecFreeBuffer(&status, pMdl);
  2062. //
  2063. // return the older chain
  2064. //
  2065. if (pContext->Flags & SCF_FLUSH) {
  2066. NDIS_BUFFER_LINKAGE(pContext->PrevMdl) = pContext->OriAHMdl;
  2067. } else if (!(pContext->Flags & SCF_FRAG)) {
  2068. NDIS_BUFFER_LINKAGE(pContext->PrevMdl) = pContext->OriAHMdl;
  2069. // *ppNewData = (PVOID)(pContext->PrevMdl);
  2070. }
  2071. pContext->OriAHMdl = NULL;
  2072. }
  2073. if (pContext->Flags & SCF_HU_TPT) {
  2074. IPSEC_DEBUG(LL_A, DBF_SEND, ("SendComplete: HU_TPT: pContext: %p", pContext));
  2075. //
  2076. // Hook the older chain into the first buffer
  2077. //
  2078. if (pContext->Flags & SCF_FLUSH) {
  2079. NDIS_BUFFER_LINKAGE(pContext->PrevMdl) = pContext->OriHUMdl;
  2080. } else if (!(pContext->Flags & SCF_FRAG)) {
  2081. NDIS_BUFFER_LINKAGE(pContext->PrevMdl) = pContext->OriHUMdl;
  2082. }
  2083. //
  2084. // Free the encryption buffer chain
  2085. //
  2086. pMdl = pContext->HUMdl;
  2087. ASSERT(pMdl);
  2088. //
  2089. // In none case, free the esp header.
  2090. //
  2091. if (pContext->Flags & SCF_NOE_TPT) {
  2092. IPSecFreeBuffer(&status, pMdl);
  2093. ASSERT(pContext->PadMdl);
  2094. } else {
  2095. ASSERT(NDIS_BUFFER_LINKAGE(pMdl));
  2096. while (pMdl) {
  2097. pNextMdl = NDIS_BUFFER_LINKAGE(pMdl);
  2098. IPSecFreeBuffer(&status, pMdl);
  2099. pMdl = pNextMdl;
  2100. }
  2101. }
  2102. //
  2103. // Free the Pad mdl and zero the reference to the pad mdl in the
  2104. // previous (payload) mdl.
  2105. //
  2106. if (pContext->PadMdl) {
  2107. IPSecFreeBuffer(&status, pContext->PadMdl);
  2108. }
  2109. NDIS_BUFFER_LINKAGE(pContext->BeforePadMdl) = NULL;
  2110. }
  2111. //
  2112. // these are freed in IPSecProtocolSendComplete now.
  2113. //
  2114. if (Packet && (pContext->Flags & SCF_FLUSH)) {
  2115. IPSEC_DEBUG(LL_A, DBF_SEND, ("SendComplete: FLUSH: pContext: %p", pContext));
  2116. //
  2117. // Free the encrypt chain and return the old chain
  2118. //
  2119. pMdl = pContext->FlushMdl;
  2120. ASSERT(pMdl);
  2121. //
  2122. // We will be called at ProtocolSendComplete, where we free this chain.
  2123. //
  2124. fFreeContext = FALSE;
  2125. //
  2126. // If this was just a reinjected packet and never IPSEC'ed, then we know
  2127. // that all the buffers are in line - call the ProtocolSendComplete here
  2128. // and NULL the returned buffer.
  2129. //
  2130. // The best way to do this is to do the same trick we apply on fragmented
  2131. // packets (see IPTransmit) viz. attaching another header and 0'ing out
  2132. // the IPSEC header. There is obviously a perf hit when attaching another IP
  2133. // header since we alloc new MDLs, etc. Hence, we take the approach of using
  2134. // the header in the IPSEC buffers directly.
  2135. //
  2136. // So, here we see if the packet was fragmented; in which case, we let
  2137. // ProtocolSendComplete do the freeing. Else, we free the buffers ourselves.
  2138. //
  2139. {
  2140. PacketContext *PContext = (PacketContext *)Packet->ProtocolReserved;
  2141. if (PContext->pc_br == NULL ||
  2142. (PContext->pc_ipsec_flags & IPSEC_FLAG_FLUSH)) {
  2143. //
  2144. // this will also free the context.
  2145. //
  2146. IPSecProtocolSendComplete(pContext, pMdl, IP_SUCCESS);
  2147. *ppNewData = NULL;
  2148. }
  2149. }
  2150. } else if (!Packet && (pContext->Flags & SCF_FLUSH)) {
  2151. //
  2152. // ProtocolSendComplete will be called next in IPFragment.
  2153. //
  2154. fFreeContext = FALSE;
  2155. } else if ((pContext->Flags & SCF_MTU)) {
  2156. ULONG NewMTU=0;
  2157. IP_STATUS IpStatus;
  2158. PIPSEC_MTU_CONTEXT pMTUContext = (PIPSEC_MTU_CONTEXT)pContext->pMTUContext;
  2159. ASSERT(pMTUContext);
  2160. if (Status == IP_PACKET_TOO_BIG) {
  2161. if (pMTUContext->TunnelSPI) {
  2162. IpStatus = TCPIP_GET_PINFO(pMTUContext->TunnelDest,
  2163. pMTUContext->Src,
  2164. &NewMTU,
  2165. NULL,
  2166. NULL);
  2167. if (IpStatus == IP_SUCCESS) {
  2168. IPSecProcessPMTU(pMTUContext->TunnelDest,
  2169. pMTUContext->Src,
  2170. NET_TO_HOST_LONG(pMTUContext->TunnelSPI),
  2171. Encrypt,
  2172. NewMTU);
  2173. }
  2174. }
  2175. if (pMTUContext->TransportSPI) {
  2176. IpStatus = TCPIP_GET_PINFO(pMTUContext->TransportDest,
  2177. pMTUContext->Src,
  2178. &NewMTU,
  2179. NULL,
  2180. NULL);
  2181. if (IpStatus == IP_SUCCESS) {
  2182. IPSecProcessPMTU(pMTUContext->TransportDest,
  2183. pMTUContext->Src,
  2184. NET_TO_HOST_LONG(pMTUContext->TransportSPI),
  2185. Encrypt,
  2186. NewMTU);
  2187. }
  2188. }
  2189. }
  2190. IPSecFreeMemory(pMTUContext);
  2191. pContext->pMTUContext = NULL;
  2192. }
  2193. //
  2194. // If context not needed anymore, free it now.
  2195. //
  2196. if (fFreeContext) {
  2197. IPSecFreeSendCompleteCtx(pContext);
  2198. }
  2199. #if DBG
  2200. IPSEC_DEBUG(LL_A, DBF_MDL, ("Exiting IPSecSendComplete"));
  2201. IPSEC_PRINT_CONTEXT(pContext);
  2202. IPSEC_PRINT_MDL(*ppNewData);
  2203. #endif
  2204. }
  2205. VOID
  2206. IPSecProtocolSendComplete (
  2207. IN PVOID pContext,
  2208. IN PNDIS_BUFFER pMdl,
  2209. IN IP_STATUS Status
  2210. )
  2211. /*++
  2212. Routine Description:
  2213. Called by the stack on a SendComplete - frees up IPSEC's Mdls.
  2214. This is only called when IPSEC injects packets into the stack.
  2215. Arguments:
  2216. pMdl - points to the data after the IP header. On the send side, this is an MDL chain
  2217. On the recv side this is an IPRcvBuf pointer.
  2218. Return Value:
  2219. STATUS_SUCCESS => Forward - Filter driver passes packet on to IP
  2220. STATUS_PENDING => Drop, IPSEC will re-inject
  2221. Others:
  2222. STATUS_INSUFFICIENT_RESOURCES => Drop
  2223. STATUS_UNSUCCESSFUL (error in algo./bad packet received) => Drop
  2224. --*/
  2225. {
  2226. PNDIS_BUFFER pNextMdl;
  2227. NTSTATUS status;
  2228. PIPSEC_SEND_COMPLETE_CONTEXT pSCContext = (PIPSEC_SEND_COMPLETE_CONTEXT)pContext;
  2229. if (!pSCContext->Flags) {
  2230. return;
  2231. }
  2232. ASSERT(pMdl);
  2233. while (pMdl) {
  2234. pNextMdl = NDIS_BUFFER_LINKAGE(pMdl);
  2235. IPSecFreeBuffer(&status, pMdl);
  2236. pMdl = pNextMdl;
  2237. }
  2238. IPSecFreeSendCompleteCtx(pSCContext);
  2239. return;
  2240. }
  2241. NTSTATUS
  2242. IPSecChkReplayWindow(
  2243. IN ULONG Seq,
  2244. IN PSA_TABLE_ENTRY pSA,
  2245. IN ULONG Index
  2246. )
  2247. /*++
  2248. Routine Description:
  2249. Checks if the received packet is in the received window to prevent against
  2250. replay attacks.
  2251. We keep track of the last Sequence number received and ensure that the
  2252. received packets is within the packet window (currently 32 packets).
  2253. Arguments:
  2254. Seq - received Sequence number
  2255. pSA - points to the security association
  2256. Return Value:
  2257. STATUS_SUCCESS => packet in window
  2258. STATUS_UNSUCCESSFUL => packet rejected
  2259. --*/
  2260. {
  2261. ULONG diff;
  2262. ULONG ReplayWindowSize = REPLAY_WINDOW_SIZE;
  2263. ULONG lastSeq = pSA->sa_ReplayLastSeq[Index];
  2264. ULONGLONG bitmap = pSA->sa_ReplayBitmap[Index];
  2265. ULONGLONG dbgbitmap = bitmap;
  2266. if (pSA->sa_Flags & FLAGS_SA_DISABLE_ANTI_REPLAY_CHECK) {
  2267. return STATUS_SUCCESS;
  2268. }
  2269. if (Seq == pSA->sa_ReplayStartPoint) {
  2270. //
  2271. // first == 0 or wrapped
  2272. //
  2273. IPSEC_DEBUG(LL_A, DBF_SEND, ("Replay: out @1 - Seq: %lx, pSA->sa_ReplayStartPoint: %lx",
  2274. Seq, pSA->sa_ReplayStartPoint));
  2275. return IPSEC_INVALID_REPLAY_WINDOW1;
  2276. }
  2277. #if DBG
  2278. IPSEC_DEBUG(LL_A, DBF_SEND, ("Replay: Last Seq.: %lx, Cur Seq.: %lx, window size %d & bit window (in nibbles) %08lx%08lx",
  2279. lastSeq, Seq, sizeof(bitmap)*8, (ULONG) (dbgbitmap >> 32), (ULONG) dbgbitmap));
  2280. #endif
  2281. //
  2282. // new larger Sequence number
  2283. //
  2284. if (Seq > lastSeq) {
  2285. diff = Seq - lastSeq;
  2286. if (diff < ReplayWindowSize) {
  2287. //
  2288. // In window
  2289. // set bit for this packet
  2290. bitmap = (bitmap << diff) | 1;
  2291. } else {
  2292. //
  2293. // This packet has a "way larger" Seq
  2294. //
  2295. bitmap = 1;
  2296. }
  2297. lastSeq = Seq;
  2298. pSA->sa_ReplayLastSeq[Index] = lastSeq;
  2299. pSA->sa_ReplayBitmap[Index] = bitmap;
  2300. //
  2301. // larger is good
  2302. //
  2303. return STATUS_SUCCESS;
  2304. }
  2305. diff = lastSeq - Seq;
  2306. if (diff >= ReplayWindowSize) {
  2307. //
  2308. // too old or wrapped
  2309. //
  2310. IPSEC_DEBUG(LL_A, DBF_SEND, ("Replay: out @3 - Seq: %lx, lastSeq: %lx",
  2311. Seq, lastSeq));
  2312. return IPSEC_INVALID_REPLAY_WINDOW2;
  2313. }
  2314. if (bitmap & ((ULONG64)1 << diff)) {
  2315. //
  2316. // this packet already seen
  2317. //
  2318. IPSEC_DEBUG(LL_A, DBF_SEND, ("Replay: out @4 - Seq: %lx, lastSeq: %lx",
  2319. Seq, lastSeq));
  2320. return IPSEC_DUPE_PACKET;
  2321. }
  2322. //
  2323. // mark as seen
  2324. //
  2325. bitmap |= ((ULONG64)1 << diff);
  2326. pSA->sa_ReplayLastSeq[Index] = lastSeq;
  2327. pSA->sa_ReplayBitmap[Index] = bitmap;
  2328. //
  2329. // out of order but good
  2330. //
  2331. return STATUS_SUCCESS;
  2332. }
  2333. NTSTATUS
  2334. IPSecPrepareReinjectPacket(
  2335. IN PVOID pData,
  2336. IN PNDIS_PACKET_EXTENSION pPktExt,
  2337. OUT PNDIS_BUFFER * ppHdrMdl,
  2338. OUT PUCHAR * ppIPH,
  2339. OUT PNDIS_BUFFER * ppOptMdl,
  2340. OUT PNDIS_BUFFER * ppDataMdl,
  2341. OUT PIPSEC_SEND_COMPLETE_CONTEXT * ppContext,
  2342. OUT PULONG pLen
  2343. )
  2344. {
  2345. PNDIS_BUFFER pOptMdl = NULL;
  2346. PNDIS_BUFFER pHdrMdl = NULL;
  2347. PNDIS_BUFFER pDataMdl = NULL;
  2348. ULONG len, ulOptLen=0;
  2349. ULONG len1;
  2350. ULONG hdrLen;
  2351. IPRcvBuf *pNextData;
  2352. IPHeader UNALIGNED * pIPH;
  2353. IPHeader UNALIGNED * pIPH1;
  2354. ULONG offset;
  2355. NTSTATUS status;
  2356. ULONG tag = IPSEC_TAG_REINJECT;
  2357. PIPSEC_SEND_COMPLETE_CONTEXT pContext;
  2358. //NDIS_PACKET_EXTENSION PktExt = {0};
  2359. PNDIS_IPSEC_PACKET_INFO IPSecPktInfo;
  2360. //
  2361. // Allocate context for IPSecSencComplete use
  2362. //
  2363. pContext = IPSecAllocateSendCompleteCtx(tag);
  2364. if (!pContext) {
  2365. IPSEC_DEBUG(LL_A, DBF_ESP, ("Failed to alloc. SendCtx"));
  2366. return STATUS_INSUFFICIENT_RESOURCES;
  2367. }
  2368. IPSEC_INCREMENT(g_ipsec.NumSends);
  2369. IPSecZeroMemory(pContext, sizeof(IPSEC_SEND_COMPLETE_CONTEXT));
  2370. #if DBG
  2371. RtlCopyMemory(pContext->Signature, "ISC5", 4);
  2372. #endif
  2373. //
  2374. // Pass along IPSEC_PKT_INFO for transport offload if needed
  2375. //
  2376. if (pPktExt) {
  2377. IPSecPktInfo = pPktExt->NdisPacketInfo[IpSecPacketInfo];
  2378. if (IPSecPktInfo) {
  2379. ASSERT(IPSecPktInfo->Receive.CryptoStatus == CRYPTO_SUCCESS);
  2380. ASSERT(IPSecPktInfo->Receive.CRYPTO_DONE);
  2381. //
  2382. // Only interested in NEXT_CRYPTO_DONE if packet is reinjected.
  2383. //
  2384. if (!(IPSecPktInfo->Receive.NEXT_CRYPTO_DONE)) {
  2385. IPSecPktInfo = NULL;
  2386. }
  2387. }
  2388. } else {
  2389. IPSecPktInfo = NULL;
  2390. }
  2391. if (IPSecPktInfo) {
  2392. //
  2393. // Pass the IPSecPktInfo to IPTransmit.
  2394. //
  2395. pContext->PktExt = IPSecAllocatePktExt(IPSEC_TAG_HW_PKTEXT);
  2396. if (!pContext->PktExt) {
  2397. IPSEC_DEBUG(LL_A, DBF_ESP, ("Failed to alloc. PktInfo"));
  2398. IPSecFreeSendCompleteCtx(pContext);
  2399. return STATUS_INSUFFICIENT_RESOURCES;
  2400. }
  2401. pContext->Flags |= SCF_PKTEXT;
  2402. RtlCopyMemory( pContext->PktExt,
  2403. IPSecPktInfo,
  2404. sizeof(NDIS_IPSEC_PACKET_INFO));
  2405. //PktExt.NdisPacketInfo[IpSecPacketInfo] = (PNDIS_IPSEC_PACKET_INFO)(pContext->PktExt);
  2406. }
  2407. //
  2408. // Re-package into MDLs for the send - these will be released on the
  2409. // SendComplete.
  2410. //
  2411. // FUTURE WORK: right now we copy the data out, this shd be optimized
  2412. // by calling IPRcvPacket and using buffer ownership.
  2413. //
  2414. IPSEC_GET_TOTAL_LEN_RCV_BUF(pData, &len);
  2415. //
  2416. // IPH is at head of pData
  2417. //
  2418. IPSecQueryRcvBuf(pData, (PVOID)&pIPH, &len1);
  2419. //
  2420. // Allocate MDL for the IP header
  2421. //
  2422. hdrLen = (pIPH->iph_verlen & (UCHAR)~IP_VER_FLAG) << 2;
  2423. if (len <= hdrLen) {
  2424. IPSEC_DEBUG(LL_A, DBF_ESP, ("TotLen of the buffers %d <= hdrLen %d", len, hdrLen));
  2425. if (pContext->PktExt) {
  2426. IPSecFreeMemory(pContext->PktExt);
  2427. }
  2428. IPSecFreeSendCompleteCtx(pContext);
  2429. return STATUS_INVALID_PARAMETER;
  2430. }
  2431. IPSecAllocateBuffer(&status,
  2432. &pHdrMdl,
  2433. (PUCHAR *)&pIPH1,
  2434. sizeof(IPHeader),
  2435. tag);
  2436. if (!NT_SUCCESS(status)) {
  2437. IPSEC_DEBUG(LL_A, DBF_ESP, ("Failed to alloc. header MDL"));
  2438. if (pContext->PktExt) {
  2439. IPSecFreeMemory(pContext->PktExt);
  2440. }
  2441. IPSecFreeSendCompleteCtx(pContext);
  2442. return status;
  2443. }
  2444. //
  2445. // Copy over the header
  2446. //
  2447. RtlCopyMemory(pIPH1, pIPH, sizeof(IPHeader));
  2448. len -= hdrLen;
  2449. offset = hdrLen;
  2450. IPSecAllocateBuffer(&status,
  2451. &pDataMdl,
  2452. NULL,
  2453. len,
  2454. tag);
  2455. if (!NT_SUCCESS(status)) {
  2456. NTSTATUS ntstatus;
  2457. IPSEC_DEBUG(LL_A, DBF_ESP, ("Failed to alloc. encrypt MDL"));
  2458. IPSecFreeBuffer(&ntstatus, pHdrMdl);
  2459. if (pContext->PktExt) {
  2460. IPSecFreeMemory(pContext->PktExt);
  2461. }
  2462. IPSecFreeSendCompleteCtx(pContext);
  2463. return status;
  2464. }
  2465. if (hdrLen > sizeof(IPHeader)) {
  2466. PUCHAR Options;
  2467. PUCHAR pOpt;
  2468. //
  2469. // Options present - another Mdl
  2470. //
  2471. IPSecAllocateBuffer(&status,
  2472. &pOptMdl,
  2473. &Options,
  2474. hdrLen - sizeof(IPHeader),
  2475. tag);
  2476. ulOptLen = hdrLen - sizeof(IPHeader);
  2477. if (!NT_SUCCESS(status)) {
  2478. NTSTATUS ntstatus;
  2479. IPSecFreeBuffer(&ntstatus, pHdrMdl);
  2480. IPSecFreeBuffer(&ntstatus, pDataMdl);
  2481. if (pContext->PktExt) {
  2482. IPSecFreeMemory(pContext->PktExt);
  2483. }
  2484. IPSecFreeSendCompleteCtx(pContext);
  2485. IPSEC_DEBUG(LL_A, DBF_ESP, ("Failed to alloc. options MDL"));
  2486. return status;
  2487. }
  2488. //
  2489. // Copy over the options - we need to fish for it - could be in next MDL
  2490. //
  2491. if (len1 >= hdrLen) {
  2492. //
  2493. // all in this buffer - jump over IP header
  2494. //
  2495. RtlCopyMemory(Options, (PUCHAR)(pIPH + 1), hdrLen - sizeof(IPHeader));
  2496. } else {
  2497. //
  2498. // next buffer, copy from next
  2499. //
  2500. pData = IPSEC_BUFFER_LINKAGE(pData);
  2501. IPSecQueryRcvBuf(pData, (PVOID)&pOpt, &len1);
  2502. RtlCopyMemory(Options, pOpt, hdrLen - sizeof(IPHeader));
  2503. offset = hdrLen - sizeof(IPHeader);
  2504. }
  2505. //
  2506. // Link in the Options buffer
  2507. //
  2508. NDIS_BUFFER_LINKAGE(pHdrMdl) = pOptMdl;
  2509. NDIS_BUFFER_LINKAGE(pOptMdl) = pDataMdl;
  2510. } else {
  2511. //
  2512. // Link in the Data buffer
  2513. //
  2514. NDIS_BUFFER_LINKAGE(pHdrMdl) = pDataMdl;
  2515. }
  2516. //
  2517. // Now bulk copy the entire data
  2518. //
  2519. IPSEC_COPY_FROM_RCVBUF( pDataMdl,
  2520. pData,
  2521. len,
  2522. offset);
  2523. //
  2524. // Fill up the SendCompleteContext
  2525. //
  2526. pContext->FlushMdl = pHdrMdl;
  2527. pContext->Flags |= SCF_FLUSH;
  2528. *ppHdrMdl = pHdrMdl;
  2529. *ppOptMdl = pOptMdl;
  2530. *ppDataMdl = pDataMdl;
  2531. *ppContext = pContext;
  2532. //
  2533. // Per SanjayKa (tcpipdev) this should include the option
  2534. // length too
  2535. //
  2536. *pLen = len + ulOptLen ;
  2537. *ppIPH = (PUCHAR)pIPH;
  2538. return STATUS_SUCCESS;
  2539. }
  2540. NTSTATUS
  2541. IPSecReinjectPreparedPacket(
  2542. IN PNDIS_BUFFER pHdrMdl,
  2543. IN PIPSEC_SEND_COMPLETE_CONTEXT pContext,
  2544. IN ULONG len,
  2545. IN PUCHAR pIPHeader
  2546. )
  2547. {
  2548. IPOptInfo optInfo;
  2549. IPHeader UNALIGNED * pIPH = (IPHeader UNALIGNED *)pIPHeader;
  2550. NTSTATUS status;
  2551. NDIS_PACKET_EXTENSION PktExt = {0};
  2552. if (pContext->PktExt){
  2553. PktExt.NdisPacketInfo[IpSecPacketInfo] = (PNDIS_IPSEC_PACKET_INFO)(pContext->PktExt);
  2554. }
  2555. //
  2556. // Call IPTransmit with proper Protocol type so it takes this packet
  2557. // at *face* value.
  2558. //
  2559. optInfo = g_ipsec.OptInfo;
  2560. optInfo.ioi_options = (PUCHAR)&PktExt;
  2561. optInfo.ioi_flags |= IP_FLAG_IPSEC;
  2562. status = TCPIP_IP_TRANSMIT( &g_ipsec.IPProtInfo,
  2563. pContext,
  2564. pHdrMdl,
  2565. len,
  2566. pIPH->iph_dest,
  2567. pIPH->iph_src,
  2568. &optInfo,
  2569. NULL,
  2570. pIPH->iph_protocol,
  2571. NULL);
  2572. //
  2573. // IPTransmit may fail to allocate a Packet so it returns
  2574. // IP_NO_RESOURCES. If this is the case, we need to free the MDL chain.
  2575. // This is taken care of in IPTransmit().
  2576. //
  2577. // Even in the synchronous case, we free the MDL chain in ProtocolSendComplete (called by IPSecSendComplete).
  2578. // So, we dont call anything here.
  2579. //
  2580. return STATUS_SUCCESS;
  2581. }
  2582. NTSTATUS
  2583. IPSecReinjectPacket(
  2584. IN PVOID pData,
  2585. IN PNDIS_PACKET_EXTENSION pPktExt
  2586. )
  2587. /*++
  2588. Routine Description:
  2589. Re-injects packet into the stack's send path - makes a copy
  2590. of the packet then calls into IPTransmit, making sure the SendComplete
  2591. Context is setup properly.
  2592. Arguments:
  2593. pData - Points to "un-tunneled" data, starting at the encapsulated IP header
  2594. pPktExt - Points to the NDIS Packet extension structure
  2595. Return Value:
  2596. Status of copy/transmit operation
  2597. --*/
  2598. {
  2599. PNDIS_BUFFER pHdrMdl = NULL, pDataMdl = NULL, pOptMdl = NULL;
  2600. PUCHAR pIPH = NULL;
  2601. PIPSEC_SEND_COMPLETE_CONTEXT pContext = NULL;
  2602. ULONG DataLen;
  2603. NTSTATUS ReinjectStatus;
  2604. // If this function fails it releases memory on it's own
  2605. ReinjectStatus = IPSecPrepareReinjectPacket(
  2606. pData,
  2607. pPktExt,
  2608. &pHdrMdl,
  2609. &pIPH,
  2610. &pOptMdl,
  2611. &pDataMdl,
  2612. &pContext
  2613. ,&DataLen);
  2614. if (STATUS_SUCCESS != ReinjectStatus){
  2615. return ReinjectStatus;
  2616. }
  2617. // This function always returns success
  2618. ReinjectStatus = IPSecReinjectPreparedPacket(
  2619. pHdrMdl,
  2620. pContext,
  2621. DataLen,
  2622. pIPH);
  2623. return ReinjectStatus;
  2624. }
  2625. NTSTATUS
  2626. IPSecQueuePacket(
  2627. IN PSA_TABLE_ENTRY pSA,
  2628. IN PVOID pDataBuf
  2629. )
  2630. /*++
  2631. Routine Description:
  2632. Copies the packet into the SAs Stall Queue.
  2633. Arguments:
  2634. Return Value:
  2635. --*/
  2636. {
  2637. ULONG len;
  2638. ULONG len1;
  2639. PNDIS_BUFFER pOptMdl;
  2640. PNDIS_BUFFER pHdrMdl;
  2641. PNDIS_BUFFER pDataMdl;
  2642. KIRQL kIrql;
  2643. ULONG hdrLen;
  2644. IPHeader UNALIGNED * pIPH;
  2645. IPHeader UNALIGNED * pIPH1;
  2646. NTSTATUS status;
  2647. ULONG offset;
  2648. ULONG tag = IPSEC_TAG_STALL_QUEUE;
  2649. PNDIS_BUFFER pData = (PNDIS_BUFFER)pDataBuf;
  2650. //
  2651. // Queue last packet so if we already have one free it first.
  2652. //
  2653. if (pSA->sa_BlockedBuffer != NULL) {
  2654. IPSecFlushQueuedPackets(pSA, STATUS_ABANDONED);
  2655. }
  2656. ACQUIRE_LOCK(&pSA->sa_Lock, &kIrql);
  2657. //
  2658. // Need a lock here - sa_Lock.
  2659. //
  2660. if (pSA->sa_State == STATE_SA_LARVAL) {
  2661. IPSEC_DEBUG(LL_A, DBF_ACQUIRE, ("Pending packet: %p", pSA));
  2662. //
  2663. // Copy over the Mdl chain to this SAs pend queue.
  2664. //
  2665. IPSEC_GET_TOTAL_LEN(pData, &len);
  2666. //
  2667. // IPH is at head of pData
  2668. //
  2669. IPSecQueryNdisBuf(pData, &pIPH, &len1);
  2670. hdrLen = (pIPH->iph_verlen & (UCHAR)~IP_VER_FLAG) << 2;
  2671. IPSecAllocateBuffer(&status,
  2672. &pHdrMdl,
  2673. (PUCHAR *)&pIPH1,
  2674. sizeof(IPHeader),
  2675. tag);
  2676. if (!NT_SUCCESS(status)) {
  2677. NTSTATUS ntstatus;
  2678. IPSEC_DEBUG(LL_A, DBF_ESP, ("Failed to alloc. header MDL"));
  2679. RELEASE_LOCK(&pSA->sa_Lock, kIrql);
  2680. return status;
  2681. }
  2682. IPSEC_DEBUG(LL_A, DBF_POOL, ("IPSecQueuePacket: pHdrMdl: %p, pIPH1: %p", pHdrMdl, pIPH1));
  2683. //
  2684. // Copy over the header
  2685. //
  2686. RtlCopyMemory(pIPH1, pIPH, sizeof(IPHeader));
  2687. len -= hdrLen;
  2688. offset = hdrLen;
  2689. IPSecAllocateBuffer(&status,
  2690. &pDataMdl,
  2691. NULL,
  2692. len,
  2693. tag);
  2694. if (!NT_SUCCESS(status)) {
  2695. NTSTATUS ntstatus;
  2696. IPSEC_DEBUG(LL_A, DBF_ESP, ("Failed to alloc. encrypt MDL"));
  2697. IPSecFreeBuffer(&status, pHdrMdl);
  2698. RELEASE_LOCK(&pSA->sa_Lock, kIrql);
  2699. return status;
  2700. }
  2701. if (hdrLen > sizeof(IPHeader)) {
  2702. PUCHAR Options;
  2703. PUCHAR pOpt;
  2704. //
  2705. // Options present - another Mdl
  2706. //
  2707. IPSecAllocateBuffer(&status,
  2708. &pOptMdl,
  2709. &Options,
  2710. hdrLen - sizeof(IPHeader),
  2711. tag);
  2712. if (!NT_SUCCESS(status)) {
  2713. IPSecFreeBuffer(&status, pHdrMdl);
  2714. IPSecFreeBuffer(&status, pDataMdl);
  2715. IPSEC_DEBUG(LL_A, DBF_ESP, ("Failed to alloc. options MDL"));
  2716. RELEASE_LOCK(&pSA->sa_Lock, kIrql);
  2717. return status;
  2718. }
  2719. //
  2720. // Copy over the options - we need to fish for it - could be in next MDL
  2721. //
  2722. if (len1 >= hdrLen) {
  2723. //
  2724. // all in this buffer - jump over IP header
  2725. //
  2726. RtlCopyMemory(Options, (PUCHAR)(pIPH + 1), hdrLen - sizeof(IPHeader));
  2727. } else {
  2728. //
  2729. // next buffer, copy from next
  2730. //
  2731. pData = NDIS_BUFFER_LINKAGE(pData);
  2732. IPSecQueryNdisBuf(pData, &pOpt, &len1);
  2733. RtlCopyMemory(Options, pOpt, hdrLen - sizeof(IPHeader));
  2734. offset = hdrLen - sizeof(IPHeader);
  2735. }
  2736. //
  2737. // Link in the Options buffer
  2738. //
  2739. NDIS_BUFFER_LINKAGE(pHdrMdl) = pOptMdl;
  2740. NDIS_BUFFER_LINKAGE(pOptMdl) = pDataMdl;
  2741. } else {
  2742. //
  2743. // Link in the Data buffer
  2744. //
  2745. NDIS_BUFFER_LINKAGE(pHdrMdl) = pDataMdl;
  2746. }
  2747. //
  2748. // Now bulk copy the entire data
  2749. //
  2750. IPSEC_COPY_FROM_NDISBUF(pDataMdl,
  2751. pData,
  2752. len,
  2753. offset);
  2754. pSA->sa_BlockedBuffer = pHdrMdl;
  2755. pSA->sa_BlockedDataLen = len;
  2756. IPSEC_DEBUG(LL_A, DBF_ACQUIRE, ("Queued buffer: %p on SA: %p, psa->sa_BlockedBuffer: %p", pHdrMdl, pSA, &pSA->sa_BlockedBuffer));
  2757. }
  2758. RELEASE_LOCK(&pSA->sa_Lock, kIrql);
  2759. return STATUS_SUCCESS;
  2760. }
  2761. VOID
  2762. IPSecIPAddrToUnicodeString(
  2763. IN IPAddr Addr,
  2764. OUT PWCHAR UCIPAddrBuffer
  2765. )
  2766. /*++
  2767. Routine Description:
  2768. Converts an IP addr into a wchar string
  2769. Arguments:
  2770. Return Value:
  2771. --*/
  2772. {
  2773. UINT IPAddrCharCount=0;
  2774. UINT i;
  2775. UCHAR IPAddrBuffer[(sizeof(IPAddr) * 4)];
  2776. UNICODE_STRING unicodeString;
  2777. ANSI_STRING ansiString;
  2778. //
  2779. // Convert the IP address into a string.
  2780. //
  2781. for (i = 0; i < sizeof(IPAddr); i++) {
  2782. UINT CurrentByte;
  2783. CurrentByte = Addr & 0xff;
  2784. if (CurrentByte > 99) {
  2785. IPAddrBuffer[IPAddrCharCount++] = (CurrentByte / 100) + '0';
  2786. CurrentByte %= 100;
  2787. IPAddrBuffer[IPAddrCharCount++] = (CurrentByte / 10) + '0';
  2788. CurrentByte %= 10;
  2789. } else if (CurrentByte > 9) {
  2790. IPAddrBuffer[IPAddrCharCount++] = (CurrentByte / 10) + '0';
  2791. CurrentByte %= 10;
  2792. }
  2793. IPAddrBuffer[IPAddrCharCount++] = CurrentByte + '0';
  2794. if (i != (sizeof(IPAddr) - 1))
  2795. IPAddrBuffer[IPAddrCharCount++] = '.';
  2796. Addr >>= 8;
  2797. }
  2798. //
  2799. // Unicode the strings.
  2800. //
  2801. *UCIPAddrBuffer = UNICODE_NULL;
  2802. unicodeString.Buffer = UCIPAddrBuffer;
  2803. unicodeString.Length = 0;
  2804. unicodeString.MaximumLength =
  2805. (USHORT)(sizeof(WCHAR) * ((sizeof(IPAddr) * 4) + 1));
  2806. ansiString.Buffer = IPAddrBuffer;
  2807. ansiString.Length = (USHORT)IPAddrCharCount;
  2808. ansiString.MaximumLength = (USHORT)IPAddrCharCount;
  2809. RtlAnsiStringToUnicodeString( &unicodeString,
  2810. &ansiString,
  2811. FALSE);
  2812. }
  2813. VOID
  2814. IPSecCountToUnicodeString(
  2815. IN ULONG Count,
  2816. OUT PWCHAR UCCountBuffer
  2817. )
  2818. /*++
  2819. Routine Description:
  2820. Converts a count a wchar string
  2821. Arguments:
  2822. Return Value:
  2823. --*/
  2824. {
  2825. UNICODE_STRING unicodeString;
  2826. //
  2827. // Unicode the strings.
  2828. //
  2829. *UCCountBuffer = UNICODE_NULL;
  2830. unicodeString.Buffer = UCCountBuffer;
  2831. unicodeString.Length = 0;
  2832. unicodeString.MaximumLength = (USHORT)sizeof(WCHAR) * (MAX_COUNT_STRING_LEN + 1);
  2833. RtlIntegerToUnicodeString ( Count,
  2834. 10, // Base
  2835. &unicodeString);
  2836. }
  2837. VOID
  2838. IPSecESPStatus(
  2839. IN UCHAR StatusType,
  2840. IN IP_STATUS StatusCode,
  2841. IN IPAddr OrigDest,
  2842. IN IPAddr OrigSrc,
  2843. IN IPAddr Src,
  2844. IN ULONG Param,
  2845. IN PVOID Data
  2846. )
  2847. /*++
  2848. Routine Description:
  2849. Handle a status indication for ESP, mostly for PMTU handling.
  2850. Arguments:
  2851. StatusType - Type of status.
  2852. StatusCode - Code identifying IP_STATUS.
  2853. OrigDest - If this is NET status, the original dest. of DG that
  2854. triggered it.
  2855. OrigSrc - The original src corr. OrigDest.
  2856. Src - IP address of status originator (could be local or remote).
  2857. Param - Additional information for status - i.e. the param field of
  2858. an ICMP message.
  2859. Data - Data pertaining to status - for NET status, this is the
  2860. first 8 bytes of the original DG.
  2861. Return Value:
  2862. --*/
  2863. {
  2864. IPSEC_DEBUG(LL_A, DBF_PMTU, ("PMTU for ESP recieved from %lx to %lx", OrigSrc, OrigDest));
  2865. if (StatusType == IP_NET_STATUS && StatusCode == IP_SPEC_MTU_CHANGE) {
  2866. IPSecProcessPMTU( OrigDest,
  2867. OrigSrc,
  2868. NET_TO_HOST_LONG(((UNALIGNED ESP *)Data)->esp_spi),
  2869. Encrypt,
  2870. Param);
  2871. }
  2872. }
  2873. VOID
  2874. IPSecAHStatus(
  2875. IN UCHAR StatusType,
  2876. IN IP_STATUS StatusCode,
  2877. IN IPAddr OrigDest,
  2878. IN IPAddr OrigSrc,
  2879. IN IPAddr Src,
  2880. IN ULONG Param,
  2881. IN PVOID Data
  2882. )
  2883. /*++
  2884. Routine Description:
  2885. Handle a status indication for AH, mostly for PMTU handling.
  2886. Arguments:
  2887. StatusType - Type of status.
  2888. StatusCode - Code identifying IP_STATUS.
  2889. OrigDest - If this is NET status, the original dest. of DG that
  2890. triggered it.
  2891. OrigSrc - The original src corr. OrigDest.
  2892. Src - IP address of status originator (could be local or remote).
  2893. Param - Additional information for status - i.e. the param field of
  2894. an ICMP message.
  2895. Data - Data pertaining to status - for NET status, this is the
  2896. first 8 bytes of the original DG.
  2897. Return Value:
  2898. --*/
  2899. {
  2900. IPSEC_DEBUG(LL_A, DBF_PMTU, ("PMTU for AH recieved from %lx to %lx", OrigSrc, OrigDest));
  2901. if (StatusType == IP_NET_STATUS && StatusCode == IP_SPEC_MTU_CHANGE) {
  2902. IPSecProcessPMTU( OrigDest,
  2903. OrigSrc,
  2904. NET_TO_HOST_LONG(((UNALIGNED AH *)Data)->ah_spi),
  2905. Auth,
  2906. Param);
  2907. }
  2908. }
  2909. VOID
  2910. IPSecProcessPMTU(
  2911. IN IPAddr OrigDest,
  2912. IN IPAddr OrigSrc,
  2913. IN tSPI SPI,
  2914. IN OPERATION_E Operation,
  2915. IN ULONG NewMTU
  2916. )
  2917. /*++
  2918. Routine Description:
  2919. Process PMTU.
  2920. Arguments:
  2921. OrigDest - The original dest. of DG that triggered it.
  2922. OrigSrc - The original src corr. OrigDest.
  2923. SPI - SPI of the outer IPSec header.
  2924. Operation - AH or ESP operation of IPSec.
  2925. NewMTU - The new MTU indicated by the intermediate gateway.
  2926. Return Value:
  2927. --*/
  2928. {
  2929. PLIST_ENTRY pFilterEntry;
  2930. PLIST_ENTRY pSAEntry;
  2931. PFILTER pFilter;
  2932. PSA_TABLE_ENTRY pSA;
  2933. IPAddr SADest;
  2934. KIRQL kIrql;
  2935. LONG Index;
  2936. LONG SAIndex;
  2937. BOOLEAN fFound = FALSE;
  2938. IPSEC_DEBUG(LL_A, DBF_PMTU, ("IPSecProcessPMTU: NewMTU arrived %lx", NewMTU));
  2939. AcquireWriteLock(&g_ipsec.SADBLock, &kIrql);
  2940. //
  2941. // Search Tunnel and Masked filter list for an outbound SA that matches
  2942. // OrigDest, OrigSrc and SPI. If such an SA is found, update its NewMTU
  2943. // field so that next packet using the SA propogate a smaller MTU
  2944. // back to TCP/IP stack. Tunnel filter should be searched first because
  2945. // if in the case transport over tunnel operation, the packet going out
  2946. // will have the Tunnel header.
  2947. //
  2948. for ( Index = OUTBOUND_TUNNEL_FILTER;
  2949. (Index >= OUTBOUND_TRANSPORT_FILTER) && !fFound;
  2950. Index -= TRANSPORT_TUNNEL_INCREMENT) {
  2951. for ( pFilterEntry = g_ipsec.FilterList[Index].Flink;
  2952. !fFound && pFilterEntry != &g_ipsec.FilterList[Index];
  2953. pFilterEntry = pFilterEntry->Flink) {
  2954. pFilter = CONTAINING_RECORD(pFilterEntry,
  2955. FILTER,
  2956. MaskedLinkage);
  2957. for ( SAIndex = 0;
  2958. (SAIndex < pFilter->SAChainSize) && !fFound;
  2959. SAIndex++) {
  2960. for ( pSAEntry = pFilter->SAChain[SAIndex].Flink;
  2961. pSAEntry != &pFilter->SAChain[SAIndex];
  2962. pSAEntry = pSAEntry->Flink) {
  2963. pSA = CONTAINING_RECORD(pSAEntry,
  2964. SA_TABLE_ENTRY,
  2965. sa_FilterLinkage);
  2966. if (pSA->sa_Flags & FLAGS_SA_TUNNEL) {
  2967. SADest = pSA->sa_TunnelAddr;
  2968. } else {
  2969. SADest = pSA->SA_DEST_ADDR;
  2970. }
  2971. if (SADest == OrigDest &&
  2972. pSA->sa_SPI == SPI &&
  2973. pSA->sa_Operation[pSA->sa_NumOps - 1] == Operation) {
  2974. //
  2975. // We matched the triple for a unique SA so this must be it.
  2976. //
  2977. fFound = TRUE;
  2978. break;
  2979. }
  2980. }
  2981. }
  2982. }
  2983. }
  2984. //
  2985. // Update the NewMTU field of the found SA. We only do this if the new
  2986. // MTU is lower than the current one.
  2987. //
  2988. if (fFound && NewMTU < pSA->sa_NewMTU && NewMTU > sizeof(IPHeader)) {
  2989. IPSEC_SET_VALUE(pSA->sa_NewMTU, NewMTU);
  2990. IPSEC_DEBUG(LL_A, DBF_PMTU, ("NewMTU %lx for pSA %p", NewMTU, pSA));
  2991. }
  2992. ReleaseWriteLock(&g_ipsec.SADBLock, kIrql);
  2993. }
  2994. IPSEC_ACTION
  2995. IPSecRcvFWPacket(
  2996. IN PCHAR pIPHeader,
  2997. IN PVOID pData,
  2998. IN UINT DataLength,
  2999. IN UCHAR DestType
  3000. )
  3001. /*++
  3002. Routine Description:
  3003. To match a inbound tunnel rule for a packet received on the inbound forward path.
  3004. Arguments:
  3005. pIPHeader - the IP header
  3006. pData - the data portion of the packet
  3007. DataLength - data length
  3008. Return Value:
  3009. eFORWARD
  3010. eDROP
  3011. --*/
  3012. {
  3013. PSA_TABLE_ENTRY pSA;
  3014. PSA_TABLE_ENTRY pNextSA;
  3015. USHORT FilterFlags;
  3016. NTSTATUS status;
  3017. IPSEC_ACTION action = eFORWARD;
  3018. IPRcvBuf RcvBuf = {0};
  3019. //
  3020. // We are not interested in non multicast broadcast packets.
  3021. //
  3022. if (IS_BCAST_DEST(DestType) && !IPSEC_MANDBCAST_PROCESS()) {
  3023. return action;
  3024. }
  3025. //
  3026. // Build a fake IPRcvBuf so we can reuse the classification routine.
  3027. //
  3028. RcvBuf.ipr_buffer = pData;
  3029. RcvBuf.ipr_size = DataLength;
  3030. status = IPSecClassifyPacket( (PUCHAR)pIPHeader,
  3031. &RcvBuf,
  3032. &pSA,
  3033. &pNextSA,
  3034. &FilterFlags,
  3035. #if GPC
  3036. 0,
  3037. #endif
  3038. FALSE,
  3039. TRUE,
  3040. TRUE,
  3041. FALSE, //Not a recv reinject
  3042. FALSE, // Not a verify Call
  3043. DestType,
  3044. NULL);
  3045. if (status != STATUS_SUCCESS) {
  3046. if (status == STATUS_PENDING) {
  3047. //
  3048. // SA is being negotiated - drop.
  3049. //
  3050. action = eDROP;
  3051. } else {
  3052. //
  3053. // No Filter/SA match found - forward.
  3054. //
  3055. //action = eFORWARD;
  3056. }
  3057. } else {
  3058. if (FilterFlags) {
  3059. if (FilterFlags & FILTER_FLAGS_DROP) {
  3060. //
  3061. // Drop filter matched - drop.
  3062. //
  3063. action = eDROP;
  3064. } else if (FilterFlags & FILTER_FLAGS_PASS_THRU) {
  3065. //
  3066. // Pass-thru filter matched - forward.
  3067. //
  3068. //action = eFORWARD;
  3069. } else {
  3070. ASSERT(FALSE);
  3071. }
  3072. } else {
  3073. ASSERT(pSA);
  3074. //
  3075. // Bug 708118 ; PolicyAgent does not respond
  3076. // fast enough to a local interface going away
  3077. // leading to spurious assert below.
  3078. // Caused multiple BVT breaks.
  3079. // ASSERT(pSA->sa_Flags & FLAGS_SA_TUNNEL);
  3080. //
  3081. //
  3082. // A real SA is matched - drop.
  3083. //
  3084. action = eDROP;
  3085. IPSecDerefSA(pSA);
  3086. }
  3087. }
  3088. return action;
  3089. }
  3090. NTSTATUS
  3091. IPSecRekeyInboundSA(
  3092. IN PSA_TABLE_ENTRY pSA
  3093. )
  3094. /*++
  3095. Routine Description:
  3096. Rekey a SA because we hit the rekey threshold.
  3097. Arguments:
  3098. Return Value:
  3099. --*/
  3100. {
  3101. PSA_TABLE_ENTRY pLarvalSA;
  3102. PSA_TABLE_ENTRY pOutboundSA;
  3103. NTSTATUS status;
  3104. KIRQL kIrql;
  3105. AcquireWriteLock(&g_ipsec.SADBLock, &kIrql);
  3106. //
  3107. // If SA already expired, no rekey is necessary.
  3108. //
  3109. pOutboundSA = pSA->sa_AssociatedSA;
  3110. if (!pOutboundSA) {
  3111. ReleaseWriteLock(&g_ipsec.SADBLock, kIrql);
  3112. return STATUS_UNSUCCESSFUL;
  3113. }
  3114. if (!(pOutboundSA->sa_Flags & FLAGS_SA_REKEY_ORI)) {
  3115. pOutboundSA->sa_Flags |= FLAGS_SA_REKEY_ORI;
  3116. IPSEC_DEBUG(LL_A, DBF_SA, ("SA: %p expiring soon", pOutboundSA));
  3117. //
  3118. // Rekey, but still continue to use this SA until the actual expiry.
  3119. //
  3120. status = IPSecNegotiateSA( pOutboundSA->sa_Filter,
  3121. pOutboundSA->sa_uliSrcDstAddr,
  3122. pOutboundSA->sa_uliProtoSrcDstPort,
  3123. pOutboundSA->sa_NewMTU,
  3124. &pLarvalSA,
  3125. pOutboundSA->sa_DestType,
  3126. &pOutboundSA->sa_EncapContext);
  3127. if (!NT_SUCCESS(status) && status != STATUS_DUPLICATE_OBJECTID) {
  3128. pOutboundSA->sa_Flags &= ~FLAGS_SA_REKEY_ORI;
  3129. status = STATUS_UNSUCCESSFUL;
  3130. }
  3131. }
  3132. ReleaseWriteLock(&g_ipsec.SADBLock, kIrql);
  3133. return status;
  3134. }
  3135. NTSTATUS
  3136. IPSecRekeyOutboundSA(
  3137. IN PSA_TABLE_ENTRY pSA
  3138. )
  3139. /*++
  3140. Routine Description:
  3141. Rekey a SA because we hit the rekey threshold.
  3142. Arguments:
  3143. Return Value:
  3144. --*/
  3145. {
  3146. PSA_TABLE_ENTRY pLarvalSA;
  3147. NTSTATUS status=STATUS_FAIL_CHECK;
  3148. KIRQL kIrql;
  3149. AcquireWriteLock(&g_ipsec.SADBLock, &kIrql);
  3150. if (!(pSA->sa_Flags & FLAGS_SA_REKEY_ORI)) {
  3151. pSA->sa_Flags |= FLAGS_SA_REKEY_ORI;
  3152. IPSEC_DEBUG(LL_A, DBF_SA, ("SA: %p expiring soon", pSA));
  3153. //
  3154. // Rekey, but still continue to use this SA until the actual expiry.
  3155. //
  3156. status = IPSecNegotiateSA( pSA->sa_Filter,
  3157. pSA->sa_uliSrcDstAddr,
  3158. pSA->sa_uliProtoSrcDstPort,
  3159. pSA->sa_NewMTU,
  3160. &pLarvalSA,
  3161. pSA->sa_DestType,
  3162. &pSA->sa_EncapContext);
  3163. if (!NT_SUCCESS(status) && status != STATUS_DUPLICATE_OBJECTID) {
  3164. pSA->sa_Flags &= ~FLAGS_SA_REKEY_ORI;
  3165. status = STATUS_UNSUCCESSFUL;
  3166. }
  3167. }
  3168. ReleaseWriteLock(&g_ipsec.SADBLock, kIrql);
  3169. return status;
  3170. }
  3171. NTSTATUS
  3172. IPSecPuntInboundSA(
  3173. IN PSA_TABLE_ENTRY pSA
  3174. )
  3175. /*++
  3176. Routine Description:
  3177. Punt a SA because we have exceeded the rekey threshold.
  3178. Arguments:
  3179. Return Value:
  3180. --*/
  3181. {
  3182. PSA_TABLE_ENTRY pOutboundSA;
  3183. KIRQL kIrql;
  3184. AcquireWriteLock(&g_ipsec.SADBLock, &kIrql);
  3185. //
  3186. // If SA already expired, no punt is necessary.
  3187. //
  3188. pOutboundSA = pSA->sa_AssociatedSA;
  3189. if (pOutboundSA && IPSEC_GET_VALUE(pOutboundSA->sa_Reference) > 1 &&
  3190. !(pOutboundSA->sa_Flags & FLAGS_SA_EXPIRED) &&
  3191. pOutboundSA->sa_State == STATE_SA_ACTIVE) {
  3192. pOutboundSA->sa_Flags |= FLAGS_SA_EXPIRED;
  3193. IPSEC_DEBUG(LL_A, DBF_SA, ("SA: %p has expired", pOutboundSA));
  3194. if (pOutboundSA->sa_Flags & FLAGS_SA_REKEY_ORI) {
  3195. pOutboundSA->sa_Flags &= ~FLAGS_SA_REKEY_ORI;
  3196. if (pOutboundSA->sa_RekeyLarvalSA) {
  3197. if (pOutboundSA->sa_RekeyLarvalSA->sa_RekeyOriginalSA) {
  3198. pOutboundSA->sa_RekeyLarvalSA->sa_RekeyOriginalSA = NULL;
  3199. }
  3200. }
  3201. }
  3202. }
  3203. if (NULL == pOutboundSA) {
  3204. if (pSA->sa_State == STATE_SA_LARVAL_ACTIVE) {
  3205. IPSecDeleteLarvalSA(pSA);
  3206. }
  3207. } else {
  3208. //
  3209. // Delete this SA and expire the corresponding inbound SA.
  3210. //
  3211. IPSecDeleteInboundSA(pSA);
  3212. }
  3213. ReleaseWriteLock(&g_ipsec.SADBLock, kIrql);
  3214. return STATUS_SUCCESS;
  3215. }
  3216. NTSTATUS
  3217. IPSecPuntOutboundSA(
  3218. IN PSA_TABLE_ENTRY pSA
  3219. )
  3220. /*++
  3221. Routine Description:
  3222. Punt a SA because we have exceeded the rekey threshold.
  3223. Arguments:
  3224. Return Value:
  3225. --*/
  3226. {
  3227. KIRQL kIrql;
  3228. AcquireWriteLock(&g_ipsec.SADBLock, &kIrql);
  3229. if (IPSEC_GET_VALUE(pSA->sa_Reference) > 1 &&
  3230. !(pSA->sa_Flags & FLAGS_SA_EXPIRED) &&
  3231. pSA->sa_State == STATE_SA_ACTIVE &&
  3232. pSA->sa_AssociatedSA != NULL) {
  3233. pSA->sa_Flags |= FLAGS_SA_EXPIRED;
  3234. IPSEC_DEBUG(LL_A, DBF_SA, ("SA: %p has expired", pSA));
  3235. if (pSA->sa_Flags & FLAGS_SA_REKEY_ORI) {
  3236. pSA->sa_Flags &= ~FLAGS_SA_REKEY_ORI;
  3237. if (pSA->sa_RekeyLarvalSA) {
  3238. if (pSA->sa_RekeyLarvalSA->sa_RekeyOriginalSA) {
  3239. pSA->sa_RekeyLarvalSA->sa_RekeyOriginalSA = NULL;
  3240. }
  3241. }
  3242. }
  3243. //
  3244. // Delete this SA and expire the corresponding inbound SA.
  3245. //
  3246. IPSecExpireInboundSA(pSA->sa_AssociatedSA);
  3247. }
  3248. ReleaseWriteLock(&g_ipsec.SADBLock, kIrql);
  3249. return STATUS_SUCCESS;
  3250. }
  3251. BOOLEAN
  3252. IPSecQueryStatus(
  3253. IN CLASSIFICATION_HANDLE GpcHandle
  3254. )
  3255. /*++
  3256. Routine Description:
  3257. Query IPSec to see if IPSec applies to this flow. TCP/IP then decides whether
  3258. to take fast or slow path in IPTransmit.
  3259. Arguments:
  3260. GpcHandle
  3261. Return Value:
  3262. TRUE - if IPSec applies to this packet; slow path
  3263. FALSE - if IPSec doesn't apply to this packet; fast path
  3264. --*/
  3265. {
  3266. PLIST_ENTRY pFilterList;
  3267. PFILTER pFilter;
  3268. NTSTATUS status;
  3269. #if DBG
  3270. //
  3271. // This should force all traffic going through IPSecHandlePacket.
  3272. //
  3273. if (DebugQry) {
  3274. return TRUE;
  3275. }
  3276. #endif
  3277. if ((IS_DRIVER_BLOCK()) || (IS_DRIVER_BOOTSTATEFUL()))
  3278. return TRUE;
  3279. if (IS_DRIVER_BYPASS() || IPSEC_DRIVER_IS_EMPTY()) {
  3280. return FALSE;
  3281. }
  3282. //
  3283. // If no GpcHandle passed in, take slow path.
  3284. //
  3285. if (!GpcHandle) {
  3286. return TRUE;
  3287. }
  3288. //
  3289. // Search in the tunnel filter list first.
  3290. //
  3291. pFilterList = &g_ipsec.FilterList[OUTBOUND_TUNNEL_FILTER];
  3292. //
  3293. // If any tunnel filters exist, take slow path.
  3294. //
  3295. if (!IsListEmpty(pFilterList)) {
  3296. return TRUE;
  3297. }
  3298. #if GPC
  3299. //
  3300. // Search the local GPC filter list.
  3301. //
  3302. pFilterList = &g_ipsec.GpcFilterList[OUTBOUND_TRANSPORT_FILTER];
  3303. //
  3304. // If any generic filters exist, take slow path.
  3305. //
  3306. if (!IsListEmpty(pFilterList)) {
  3307. return TRUE;
  3308. }
  3309. pFilter = NULL;
  3310. //
  3311. // Use GpcHandle directly to get the filter installed.
  3312. //
  3313. status = GPC_GET_CLIENT_CONTEXT(g_ipsec.GpcClients[GPC_CF_IPSEC_OUT],
  3314. GpcHandle,
  3315. &pFilter);
  3316. if (status == STATUS_INVALID_HANDLE) {
  3317. //
  3318. // Handle has expired, take slow path because re-classification will
  3319. // have to be applied to this flow from now on until connection breaks.
  3320. // So why bother performing a re-classification here?
  3321. //
  3322. return TRUE;
  3323. }
  3324. return pFilter != NULL;
  3325. #else
  3326. return TRUE;
  3327. #endif
  3328. }
  3329. NTSTATUS IPSecDisableUdpXsum(
  3330. IN IPRcvBuf *pData
  3331. )
  3332. {
  3333. LONG UdpLen;
  3334. NATENCAP *pUdp;
  3335. NTSTATUS status;
  3336. IPSecQueryRcvBuf(pData, &pUdp, &UdpLen);
  3337. if (UdpLen > 8) {
  3338. pUdp->uh_xsum = 0;
  3339. return STATUS_SUCCESS;
  3340. }
  3341. status=IPSecSetRecvByteByOffset(pData,6,0);
  3342. if (!NT_SUCCESS(status)) {
  3343. return status;
  3344. }
  3345. status=IPSecSetRecvByteByOffset(pData,7,0);
  3346. if (!NT_SUCCESS(status)) {
  3347. return status;
  3348. }
  3349. return status;
  3350. }
  3351. NTSTATUS AddShimContext(IN PUCHAR *pIpHeader,
  3352. IN PVOID pData,
  3353. IPSEC_UDP_ENCAP_CONTEXT *pNatContext)
  3354. {
  3355. LONG DataLen;
  3356. PUCHAR pRcvData;
  3357. BYTE Ports[TCP_HEADER_SIZE];
  3358. NTSTATUS status=STATUS_SUCCESS;
  3359. PUCHAR pProtocolData=NULL;
  3360. IPHeader UNALIGNED *pIPH = (IPHeader UNALIGNED *)*pIpHeader;
  3361. BOOL bSlowPath=FALSE;
  3362. int i;
  3363. LONG MinLen;
  3364. DWORD TmpContext;
  3365. IPSecQueryRcvBuf((IPRcvBuf *)pData, &pRcvData, &DataLen);
  3366. if (pIPH->iph_protocol == PROTOCOL_UDP ||
  3367. pIPH->iph_protocol == PROTOCOL_TCP) {
  3368. if (pIPH->iph_protocol == PROTOCOL_UDP) {
  3369. MinLen=UDP_HEADER_SIZE;
  3370. } else {
  3371. MinLen = TCP_HEADER_SIZE;
  3372. }
  3373. if (DataLen >= MinLen) {
  3374. pProtocolData=pRcvData;
  3375. } else {
  3376. pProtocolData=&Ports[0];
  3377. bSlowPath=TRUE;
  3378. DataLen= MinLen;
  3379. status = IPSecGetRecvBytesByOffset(pData,
  3380. 0,
  3381. Ports,
  3382. MinLen);
  3383. if (!NT_SUCCESS(status)) {
  3384. return status;
  3385. }
  3386. }
  3387. } else {
  3388. pProtocolData = pRcvData;
  3389. }
  3390. memcpy(&TmpContext,pNatContext,sizeof(DWORD));
  3391. status=(g_ipsec.ShimFunctions.pIncomingPacketRoutine)(pIPH,
  3392. pProtocolData,
  3393. DataLen,
  3394. ULongToHandle(TmpContext));
  3395. IPSEC_DEBUG(LL_A, DBF_NATSHIM,("ProcessIncoming: InContext %x ret %x",TmpContext,status));
  3396. return status;
  3397. }
  3398. NTSTATUS
  3399. GetIpBufferForICMP(
  3400. PUCHAR pucIPHeader,
  3401. PVOID pvData,
  3402. PUCHAR * ppucIpBuffer,
  3403. PUCHAR * ppucStorage
  3404. )
  3405. {
  3406. NTSTATUS ntStatus = STATUS_SUCCESS;
  3407. IPHeader UNALIGNED * pIPHdr = (IPHeader UNALIGNED *) pucIPHeader;
  3408. PMDL pMdlChain = (PMDL) pvData;
  3409. ULONG uOffset = 0;
  3410. ULONG uDataSize = 0;
  3411. PUCHAR pucStorage = NULL;
  3412. ULONG uLastWalkedMdlOffset = 0;
  3413. PUCHAR pucIpBuffer = NULL;
  3414. uDataSize = ((pIPHdr->iph_verlen & (UCHAR)~IP_VER_FLAG) << 2) + 8;
  3415. ntStatus = IPSecGetSendBuffer(
  3416. &pMdlChain,
  3417. uOffset,
  3418. uDataSize,
  3419. (PVOID) pucStorage,
  3420. &uLastWalkedMdlOffset,
  3421. &pucIpBuffer
  3422. );
  3423. if (ntStatus == STATUS_BUFFER_OVERFLOW) {
  3424. pucStorage = IPSecAllocateMemory(uDataSize, IPSEC_TAG_ICMP);
  3425. if (!pucStorage) {
  3426. ntStatus = STATUS_INSUFFICIENT_RESOURCES;
  3427. BAIL_ON_NTSTATUS_ERROR(ntStatus);
  3428. }
  3429. ntStatus = IPSecGetSendBuffer(
  3430. &pMdlChain,
  3431. uOffset,
  3432. uDataSize,
  3433. (PVOID) pucStorage,
  3434. &uLastWalkedMdlOffset,
  3435. &pucIpBuffer
  3436. );
  3437. }
  3438. BAIL_ON_NTSTATUS_ERROR(ntStatus);
  3439. *ppucIpBuffer = pucIpBuffer;
  3440. *ppucStorage = pucStorage;
  3441. return (ntStatus);
  3442. error:
  3443. if (pucStorage) {
  3444. IPSecFreeMemory(pucStorage);
  3445. }
  3446. *ppucIpBuffer = NULL;
  3447. *ppucStorage = NULL;
  3448. return (ntStatus);
  3449. }
  3450. NTSTATUS
  3451. IPSecGetSendBuffer(
  3452. PMDL * ppMdlChain,
  3453. ULONG uOffset,
  3454. ULONG uBytesNeeded,
  3455. PVOID pvStorage,
  3456. PULONG puLastWalkedMdlOffset,
  3457. PUCHAR * ppucReturnBuf
  3458. )
  3459. /*++
  3460. Routine Description:
  3461. Provides a flat buffer of the specified size from a MDL chain
  3462. starting at the specified offset.
  3463. Arguments:
  3464. ppMdlChain - Pointer to a pointer to a chain of MDLs describing the source
  3465. data. On successful return, this points to the last walked MDL.
  3466. uOffset - Number of initial bytes to skip in the MDL chain.
  3467. uBytesNeeded - Number of bytes needed from the specified offset.
  3468. pvStorage - Pointer to the flat buffer of uBytesNeeded size.
  3469. Client of this call should free this buffer only when its
  3470. done using *ppucReturnBuf.
  3471. puLastWalkedMdlOffset - Pointer to a location that will contain the offset
  3472. into the last walked MDL from where the next send
  3473. buffer can be retrieved.
  3474. ppucReturnBuf - Pointer to a location that will contain the pointer to
  3475. the flat buffer. Must not be freed by the client.
  3476. Return Value:
  3477. Success - STATUS_SUCCESS.
  3478. Failure - NT STATUS FAILURE CODE.
  3479. --*/
  3480. {
  3481. NTSTATUS ntStatus = STATUS_SUCCESS;
  3482. PMDL pMdl = *ppMdlChain;
  3483. ULONG uMdlOffset = uOffset;
  3484. ULONG uMdlByteCount = 0;
  3485. PUCHAR pucVa = NULL;
  3486. PUCHAR pucReturnBuf = NULL;
  3487. ULONG uLastWalkedMdlOffset = 0;
  3488. ULONG uBytesCopied = 0;
  3489. //
  3490. // Find which MDL.
  3491. //
  3492. if (!pMdl) {
  3493. ntStatus = STATUS_BUFFER_TOO_SMALL;
  3494. BAIL_ON_NTSTATUS_ERROR(ntStatus);
  3495. }
  3496. while (uMdlOffset >= (uMdlByteCount = MmGetMdlByteCount(pMdl))) {
  3497. uMdlOffset -= uMdlByteCount;
  3498. pMdl = pMdl->Next;
  3499. if (!pMdl) {
  3500. ntStatus = STATUS_BUFFER_TOO_SMALL;
  3501. BAIL_ON_NTSTATUS_ERROR(ntStatus);
  3502. }
  3503. }
  3504. //
  3505. // See if the found MDL contains uMdlOffset + uBytesNeeded bytes of data.
  3506. //
  3507. if (uMdlOffset + uBytesNeeded <= uMdlByteCount) {
  3508. pucVa = MmGetSystemAddressForMdlSafe(pMdl, LowPagePriority);
  3509. if (!pucVa) {
  3510. ntStatus = STATUS_INSUFFICIENT_RESOURCES;
  3511. BAIL_ON_NTSTATUS_ERROR(ntStatus);
  3512. }
  3513. pucReturnBuf = pucVa + uMdlOffset;
  3514. if (uMdlOffset + uBytesNeeded < uMdlByteCount) {
  3515. uLastWalkedMdlOffset = uMdlOffset + uBytesNeeded;
  3516. }
  3517. else {
  3518. pMdl = pMdl->Next;
  3519. uLastWalkedMdlOffset = 0;
  3520. }
  3521. }
  3522. else {
  3523. if (!pvStorage) {
  3524. ntStatus = STATUS_BUFFER_OVERFLOW;
  3525. BAIL_ON_NTSTATUS_ERROR(ntStatus);
  3526. }
  3527. ntStatus = IPSecCopyMdlToBuffer(
  3528. &pMdl,
  3529. uMdlOffset,
  3530. pvStorage,
  3531. uBytesNeeded,
  3532. &uLastWalkedMdlOffset,
  3533. &uBytesCopied
  3534. );
  3535. BAIL_ON_NTSTATUS_ERROR(ntStatus);
  3536. if (uBytesCopied != uBytesNeeded) {
  3537. ntStatus = STATUS_BUFFER_TOO_SMALL;
  3538. BAIL_ON_NTSTATUS_ERROR(ntStatus);
  3539. }
  3540. pucReturnBuf = pvStorage;
  3541. }
  3542. *ppMdlChain = pMdl;
  3543. *puLastWalkedMdlOffset = uLastWalkedMdlOffset;
  3544. *ppucReturnBuf = pucReturnBuf;
  3545. return (ntStatus);
  3546. error:
  3547. *puLastWalkedMdlOffset = 0;
  3548. *ppucReturnBuf = NULL;
  3549. return (ntStatus);
  3550. }
  3551. NTSTATUS
  3552. IPSecCopyMdlToBuffer(
  3553. PMDL * ppMdlChain,
  3554. ULONG uOffset,
  3555. PVOID pvBuffer,
  3556. ULONG uBytesToCopy,
  3557. PULONG puLastWalkedMdlOffset,
  3558. PULONG puBytesCopied
  3559. )
  3560. /*++
  3561. Routine Description:
  3562. Copies a maximum of uBytesToCopy bytes of data from an MDL chain
  3563. to a flat buffer.
  3564. Arguments:
  3565. ppMdlChain - Pointer to a pointer to a chain of MDLs describing the source
  3566. data. On successfully copying uBytesToCopy bytes of data, this
  3567. points to the last walked MDL.
  3568. uOffset - Number of initial bytes to skip in the MDL chain.
  3569. pvBuffer - Pointer to the flat buffer to copy into.
  3570. uBytesToCopy - Number of bytes to copy.
  3571. puLastWalkedMdlOffset - Pointer to a location that will contain the offset
  3572. into the last walked MDL from where the next send
  3573. buffer can be retrieved.
  3574. puBytesCopied - Pointer to a location to contain the actual number of bytes
  3575. copied.
  3576. Return Value:
  3577. Success - STATUS_SUCCESS.
  3578. Failure - NT STATUS FAILURE CODE.
  3579. --*/
  3580. {
  3581. PMDL pMdl = *ppMdlChain;
  3582. ULONG uMdlOffset = uOffset;
  3583. ULONG uMdlByteCount = 0;
  3584. ULONG uNumBytes = uBytesToCopy;
  3585. PUCHAR pucSysVa = NULL;
  3586. ULONG uCopySize = 0;
  3587. PMDL pLastWalkedMdl = NULL;
  3588. *puBytesCopied = 0;
  3589. //
  3590. // Skip the offset bytes in the MDL chain.
  3591. //
  3592. while (pMdl && uMdlOffset >= (uMdlByteCount = MmGetMdlByteCount(pMdl))) {
  3593. uMdlOffset -= uMdlByteCount;
  3594. pMdl = pMdl->Next;
  3595. }
  3596. while (pMdl && (uNumBytes > 0)) {
  3597. uMdlByteCount = MmGetMdlByteCount(pMdl);
  3598. if (uMdlByteCount == 0) {
  3599. pLastWalkedMdl = pMdl;
  3600. pMdl = pMdl->Next;
  3601. continue;
  3602. }
  3603. pucSysVa = MmGetSystemAddressForMdlSafe(pMdl, LowPagePriority);
  3604. if (!pucSysVa) {
  3605. return (STATUS_INSUFFICIENT_RESOURCES);
  3606. }
  3607. pucSysVa += uMdlOffset;
  3608. uMdlByteCount -= uMdlOffset;
  3609. uMdlOffset = 0;
  3610. //
  3611. // uMdlByteCount can never be zero because at this point its always
  3612. // greater than uMdlOffset.
  3613. //
  3614. uCopySize = MIN(uNumBytes, uMdlByteCount);
  3615. RtlCopyMemory(pvBuffer, pucSysVa, uCopySize);
  3616. (PUCHAR) pvBuffer += uCopySize;
  3617. uNumBytes -= uCopySize;
  3618. pLastWalkedMdl = pMdl;
  3619. pMdl = pMdl->Next;
  3620. }
  3621. if (!uNumBytes) {
  3622. if (uCopySize < uMdlByteCount) {
  3623. *ppMdlChain = pLastWalkedMdl;
  3624. *puLastWalkedMdlOffset = uCopySize;
  3625. }
  3626. else {
  3627. pLastWalkedMdl = pLastWalkedMdl->Next;
  3628. *ppMdlChain = pLastWalkedMdl;
  3629. *puLastWalkedMdlOffset = 0;
  3630. }
  3631. }
  3632. *puBytesCopied = uBytesToCopy - uNumBytes;
  3633. return (STATUS_SUCCESS);
  3634. }
  3635. NTSTATUS ConvertPacketToStatefulEntry(IN PUCHAR pHeader,
  3636. IN PVOID pData,
  3637. IN BOOL bInbound,
  3638. OUT PIPSEC_STATEFUL_ENTRY pStatefulEntry)
  3639. {
  3640. PNDIS_BUFFER pTempBuf;
  3641. WORD wTpt[2];
  3642. UNALIGNED WORD *pwPort;
  3643. IPHeader UNALIGNED *pIPHeader = (IPHeader UNALIGNED *)pHeader;
  3644. PUCHAR pTpt;
  3645. ULONG tptLen;
  3646. wTpt[0] = wTpt[1] = 0;
  3647. //
  3648. // First buffer in pData chain points to start of IP header
  3649. //
  3650. if (!bInbound) {
  3651. if (((pIPHeader->iph_verlen & (UCHAR)~IP_VER_FLAG) << 2) > sizeof(IPHeader)) {
  3652. //
  3653. // Options -> third MDL has Tpt header
  3654. //
  3655. if (!(pTempBuf = IPSEC_NEXT_BUFFER((PNDIS_BUFFER)pData))) {
  3656. return STATUS_UNSUCCESSFUL;
  3657. }
  3658. if (!(pTempBuf = IPSEC_NEXT_BUFFER(pTempBuf))) {
  3659. pwPort = (UNALIGNED WORD *) (wTpt);
  3660. } else {
  3661. IPSecQueryNdisBuf(pTempBuf, &pTpt, &tptLen);
  3662. if (tptLen < 4) {
  3663. pwPort = (UNALIGNED WORD *) (wTpt);
  3664. } else {
  3665. pwPort = (UNALIGNED WORD *)(pTpt);
  3666. }
  3667. }
  3668. } else {
  3669. //
  3670. // no options -> second MDL has Tpt header
  3671. //
  3672. if (!(pTempBuf = IPSEC_NEXT_BUFFER((PNDIS_BUFFER)pData))) {
  3673. pwPort = (UNALIGNED WORD *) (wTpt);
  3674. } else {
  3675. IPSecQueryNdisBuf(pTempBuf, &pTpt, &tptLen);
  3676. if (tptLen < 4) {
  3677. pwPort = (UNALIGNED WORD *) (wTpt);
  3678. } else {
  3679. pwPort = (UNALIGNED WORD *)(pTpt);
  3680. }
  3681. }
  3682. }
  3683. if (pIPHeader->iph_protocol != PROTOCOL_TCP &&
  3684. pIPHeader->iph_protocol != PROTOCOL_UDP) {
  3685. pwPort = (UNALIGNED WORD *) (wTpt);
  3686. }
  3687. pStatefulEntry->SrcAddr = pIPHeader->iph_src;
  3688. pStatefulEntry->DestAddr = pIPHeader->iph_dest;
  3689. pStatefulEntry->Protocol = pIPHeader->iph_protocol;
  3690. pStatefulEntry->SrcPort = pwPort[0];
  3691. pStatefulEntry->DestPort = pwPort[1];
  3692. IPSEC_DEBUG(LL_A,DBF_BOOTTIME,("Out Packet: src %x dst %x proto %x sport %x dport %x\n",
  3693. pStatefulEntry->SrcAddr,
  3694. pStatefulEntry->DestAddr,
  3695. pStatefulEntry->Protocol,
  3696. pStatefulEntry->SrcPort,
  3697. pStatefulEntry->DestPort));
  3698. } else {
  3699. IPSecQueryRcvBuf(pData, &pTpt, &tptLen);
  3700. if (pIPHeader->iph_protocol == PROTOCOL_TCP ||
  3701. pIPHeader->iph_protocol == PROTOCOL_UDP) {
  3702. if (tptLen < sizeof(WORD)*2) {
  3703. pwPort = (UNALIGNED WORD *) (wTpt);
  3704. } else {
  3705. pwPort = (UNALIGNED WORD *)(pTpt);
  3706. }
  3707. } else {
  3708. pwPort = (UNALIGNED WORD *) (wTpt);
  3709. }
  3710. pStatefulEntry->SrcAddr = pIPHeader->iph_src;
  3711. pStatefulEntry->DestAddr = pIPHeader->iph_dest;
  3712. pStatefulEntry->Protocol = pIPHeader->iph_protocol;
  3713. pStatefulEntry->SrcPort = pwPort[0];
  3714. pStatefulEntry->DestPort = pwPort[1];
  3715. IPSEC_DEBUG(LL_A,DBF_BOOTTIME,("In Packet: src %x dst %x proto %x sport %x dport %x\n",
  3716. pStatefulEntry->SrcAddr,
  3717. pStatefulEntry->DestAddr,
  3718. pStatefulEntry->Protocol,
  3719. pStatefulEntry->SrcPort,
  3720. pStatefulEntry->DestPort));
  3721. }
  3722. return STATUS_SUCCESS;
  3723. }
  3724. BOOL EntryMatch(PIPSEC_STATEFUL_ENTRY pSEntry,
  3725. PIPSEC_EXEMPT_ENTRY pEEntry,
  3726. BOOL fIncoming)
  3727. /*++
  3728. Routine Description:
  3729. Arguments:
  3730. pSEntry - stateful entry for packet.
  3731. PEEntry - exempt entry.
  3732. fIncoming - Is this an incoming packet?
  3733. Return Value:
  3734. TRUE - entry matches
  3735. --*/
  3736. {
  3737. USHORT srcPort,dstPort;
  3738. // If the direction of the packet is not the same as the direction in which the
  3739. // filter is specified , reverse the ports
  3740. if ((fIncoming && pEEntry->Direction != EXEMPT_DIRECTION_INBOUND) ||
  3741. (!fIncoming && pEEntry->Direction != EXEMPT_DIRECTION_OUTBOUND)){
  3742. return FALSE;
  3743. }
  3744. else
  3745. {
  3746. // Else get the ports
  3747. srcPort = pSEntry->SrcPort;
  3748. dstPort = pSEntry->DestPort;
  3749. }
  3750. if (pSEntry->Protocol == pEEntry->Protocol) {
  3751. //Dest port matches or is configured to be any (0)
  3752. if ((dstPort == pEEntry->DestPort ||pEEntry->DestPort == 0) &&
  3753. //Source port matches or is configured to be any (0)
  3754. (srcPort == pEEntry->SrcPort ||pEEntry->SrcPort == 0)) {
  3755. return TRUE;
  3756. }
  3757. }
  3758. return FALSE;
  3759. }
  3760. //Should not hold the g_ipsec.SADBLock when calling this function
  3761. BOOL IsEntryExempt(PIPSEC_STATEFUL_ENTRY pSEntry, BOOL fIncoming)
  3762. {
  3763. ULONG i;
  3764. KIRQL kIrql;
  3765. AcquireReadLock(&g_ipsec.SADBLock, &kIrql);
  3766. if (g_ipsec.BootExemptList){
  3767. for (i=0; i < g_ipsec.BootExemptListSize; i++) {
  3768. if (EntryMatch(pSEntry,
  3769. &g_ipsec.BootExemptList[i],fIncoming)) {
  3770. ReleaseReadLock(&g_ipsec.SADBLock,kIrql);
  3771. return (TRUE);
  3772. }
  3773. }
  3774. }
  3775. ReleaseReadLock(&g_ipsec.SADBLock,kIrql);
  3776. return FALSE;
  3777. }
  3778. ULONG
  3779. CalcStatefulCacheIndex(
  3780. PIPSEC_STATEFUL_ENTRY pSEntry,
  3781. BOOL fUnicast
  3782. )
  3783. {
  3784. ULONG dwIndex;
  3785. ULONG Address;
  3786. USHORT Port;
  3787. IPAddr SrcAddr;
  3788. IPAddr DestAddr;
  3789. UCHAR Protocol;
  3790. USHORT SrcPort;
  3791. USHORT DestPort;
  3792. if (fUnicast){
  3793. SrcAddr = pSEntry->SrcAddr;
  3794. DestAddr = pSEntry->DestAddr;
  3795. }
  3796. else{
  3797. SrcAddr = 0;
  3798. DestAddr = 0;
  3799. }
  3800. SrcPort = pSEntry->SrcPort;
  3801. DestPort = pSEntry->DestPort;
  3802. Protocol = pSEntry->Protocol;
  3803. Address = SrcAddr ^ DestAddr;
  3804. Port = SrcPort ^ DestPort;
  3805. dwIndex = NET_TO_HOST_LONG(Address);
  3806. dwIndex += Protocol;
  3807. dwIndex += NET_TO_HOST_SHORT(Port);
  3808. dwIndex %= IPSEC_STATEFUL_HASH_TABLE_SIZE;
  3809. return dwIndex;
  3810. }
  3811. BOOL SearchCollisionChain(
  3812. IN LIST_ENTRY * pHead,
  3813. IN PIPSEC_STATEFUL_ENTRY pSMatch,
  3814. IN BOOL fUnicast
  3815. )
  3816. {
  3817. LIST_ENTRY * pEntry=NULL;
  3818. PIPSEC_STATEFUL_ENTRY pSEntry=NULL;
  3819. pEntry = pHead;
  3820. for ( pEntry = pHead->Flink;
  3821. pEntry != pHead;
  3822. pEntry = pEntry->Flink) {
  3823. pSEntry = CONTAINING_RECORD(pEntry,
  3824. IPSEC_STATEFUL_ENTRY,
  3825. CollisionLinkage);
  3826. if (fUnicast){
  3827. if ((pSEntry->SrcAddr != pSMatch->SrcAddr) ||
  3828. (pSEntry->DestAddr!= pSMatch->DestAddr)){
  3829. continue;
  3830. }
  3831. }
  3832. else {
  3833. //Check for destination address it should be the same
  3834. // multicast / broadcast address both inbound and
  3835. // outbound.
  3836. if (pSEntry->DestAddr != pSMatch->DestAddr){
  3837. continue;
  3838. }
  3839. }
  3840. if ((pSEntry->SrcPort == pSMatch->SrcPort)&&
  3841. (pSEntry->DestPort == pSMatch->DestPort) &&
  3842. (pSEntry->Protocol == pSMatch->Protocol)){
  3843. return TRUE;
  3844. }
  3845. }
  3846. return FALSE;
  3847. }
  3848. BOOL FindStatefulEntry(PIPSEC_STATEFUL_ENTRY pSEntry,
  3849. BOOL fOutbound,
  3850. BOOL fUnicast)
  3851. {
  3852. ULONG i;
  3853. PIPSEC_STATEFUL_ENTRY pOutSEntry;
  3854. IPSEC_STATEFUL_ENTRY TmpEntry;
  3855. BOOL fRetValue;
  3856. ULONG index;
  3857. // Acquire multiple reader single writer lock
  3858. // While the hash table is being read
  3859. // it can not be altered
  3860. if (fOutbound) {
  3861. pOutSEntry = pSEntry;
  3862. } else {
  3863. //Stateful entries are symmetrical
  3864. //Flip inbound to look like outbound
  3865. //for lookup.
  3866. pOutSEntry = &TmpEntry;
  3867. TmpEntry.SrcAddr = pSEntry->DestAddr;
  3868. TmpEntry.DestAddr = pSEntry->SrcAddr;
  3869. TmpEntry.Protocol = pSEntry->Protocol;
  3870. TmpEntry.SrcPort = pSEntry->DestPort;
  3871. TmpEntry.DestPort = pSEntry->SrcPort;
  3872. }
  3873. //Calculate the has index in the table
  3874. index =
  3875. CalcStatefulCacheIndex(pOutSEntry, fUnicast);
  3876. //Do we have a collision chain here?
  3877. if (!IsListEmpty(&(g_ipsec.BootStatefulHT->Entry[index]))){
  3878. // Search the collision chain if it exists
  3879. fRetValue = SearchCollisionChain
  3880. (&(g_ipsec.BootStatefulHT->Entry[index]),
  3881. pOutSEntry,
  3882. fUnicast);
  3883. }
  3884. else{
  3885. fRetValue = FALSE;
  3886. }
  3887. if (fRetValue){
  3888. IPSEC_DEBUG(LL_A,DBF_BOOTTIME,("FoundStatefulEntry.\n"));
  3889. }
  3890. return fRetValue;
  3891. }
  3892. NTSTATUS InsertStatefulEntry(PIPSEC_STATEFUL_ENTRY pSEntry,
  3893. BOOL fUnicast)
  3894. {
  3895. NTSTATUS Status = STATUS_SUCCESS;
  3896. ULONG index;
  3897. // Else insert the new entry.
  3898. //
  3899. index =
  3900. CalcStatefulCacheIndex(pSEntry, fUnicast);
  3901. InsertTailList(&(g_ipsec.BootStatefulHT->Entry[index]),&(pSEntry->CollisionLinkage));
  3902. IPSEC_DEBUG(LL_A,DBF_BOOTTIME,("Inserted statefulentry into slot %d \n",index));
  3903. return Status;
  3904. }
  3905. IPSEC_ACTION IPSecProcessBoottime(IN PUCHAR pIPHeader,
  3906. IN PVOID pData,
  3907. IN PNDIS_PACKET Packet,
  3908. IN ULONG IpsecFlags,
  3909. IN UCHAR DestType)
  3910. /*++
  3911. Routine Description:
  3912. This is the IPSec handler for boottime traffic
  3913. Arguments:
  3914. pIPHeader - points to start of IP header.
  3915. pData - points to the data after the IP header, an IPRcvBuf or MDL
  3916. IpsecFlags - flags for SrcRoute, Incoming, Forward and Lookback.
  3917. Return Value:
  3918. eFORWARD
  3919. eDROP
  3920. --*/
  3921. {
  3922. IPSEC_ACTION eAction = eDROP;
  3923. NTSTATUS Status;
  3924. IPSEC_STATEFUL_ENTRY StatefulEntry;
  3925. PIPSEC_STATEFUL_ENTRY pSSaveEntry;
  3926. KIRQL kIrql;
  3927. if (IpsecFlags & IPSEC_FLAG_LOOPBACK) {
  3928. eAction = eFORWARD;
  3929. goto out;
  3930. }
  3931. if (IpsecFlags & IPSEC_FLAG_FORWARD){
  3932. if ( IS_DRIVER_FORWARD_BLOCK()){
  3933. goto out ; // Drop the packet
  3934. }
  3935. else{
  3936. eAction = eFORWARD;//bypass traffic on forwarding path
  3937. goto out;
  3938. }
  3939. }
  3940. if (IpsecFlags & IPSEC_FLAG_INCOMING) {
  3941. Status = ConvertPacketToStatefulEntry(pIPHeader,
  3942. pData,
  3943. TRUE,
  3944. &StatefulEntry);
  3945. if (!NT_SUCCESS(Status)) {
  3946. goto out;
  3947. }
  3948. if (IsEntryExempt(&StatefulEntry,TRUE)) {
  3949. eAction = eFORWARD;
  3950. goto out;
  3951. }
  3952. if (IS_DRIVER_BLOCK()) {
  3953. goto out;
  3954. }
  3955. AcquireReadLock(&g_ipsec.SADBLock, &kIrql);
  3956. if (g_ipsec.BootBufferPool == NULL){
  3957. //We have moved out of boot mode
  3958. ReleaseReadLock(&g_ipsec.SADBLock,kIrql);
  3959. goto out;
  3960. }
  3961. if (FindStatefulEntry(&StatefulEntry,FALSE,!IS_BCAST_DEST(DestType))) {
  3962. eAction = eFORWARD;
  3963. }
  3964. ReleaseReadLock(&g_ipsec.SADBLock, kIrql);
  3965. } else {
  3966. //eAction is eDROP here
  3967. Status = ConvertPacketToStatefulEntry(pIPHeader,
  3968. pData,
  3969. FALSE,
  3970. &StatefulEntry);
  3971. if (!NT_SUCCESS(Status)) {
  3972. goto out;
  3973. }
  3974. if (IsEntryExempt(&StatefulEntry,FALSE)) {
  3975. eAction = eFORWARD;
  3976. goto out;
  3977. }
  3978. if (IS_DRIVER_BLOCK()) {
  3979. goto out;
  3980. }
  3981. AcquireWriteLock(&g_ipsec.SADBLock, &kIrql);
  3982. if (g_ipsec.BootBufferPool == NULL){
  3983. //We have moved out of boot mode
  3984. ReleaseWriteLock(&g_ipsec.SADBLock, kIrql);
  3985. goto out;
  3986. }
  3987. // Do we have a preexisting entry?
  3988. //
  3989. if (FindStatefulEntry(&StatefulEntry,TRUE,!IS_BCAST_DEST(DestType))) {
  3990. eAction = eFORWARD;
  3991. ReleaseWriteLock(&g_ipsec.SADBLock, kIrql);
  3992. goto out;
  3993. }
  3994. // This call cant fail. We recycle memory if we run
  3995. // out of it.
  3996. pSSaveEntry = IPSecAllocateFromHashPool();
  3997. RtlCopyMemory(pSSaveEntry,&StatefulEntry,sizeof(IPSEC_STATEFUL_ENTRY));
  3998. Status = InsertStatefulEntry(pSSaveEntry,!IS_BCAST_DEST(DestType));
  3999. if (NT_SUCCESS(Status)) {
  4000. // Yup we can forward it
  4001. eAction = eFORWARD;
  4002. }
  4003. ReleaseWriteLock(&g_ipsec.SADBLock, kIrql);
  4004. }
  4005. out:
  4006. IPSEC_DEBUG(LL_A,DBF_BOOTTIME,("Leaving Boottime action %d\n",eAction));
  4007. return eAction;
  4008. }
  4009. BOOLEAN
  4010. IPSecIsGenericPortsProtocolOf(
  4011. ULARGE_INTEGER uliGenericPortProtocol,
  4012. ULARGE_INTEGER uliSpecificPortProtocol
  4013. )
  4014. /*++
  4015. Routine Description:
  4016. This routine determines if one unsigned large integer representing
  4017. port and protocols as commonly used in our SA and FILTER structures
  4018. is more generic than another such value
  4019. Arguments:
  4020. uliGenericPortProtocol - the unsigned integer that should be more generic.
  4021. uliSpecificPortProtocol - the unsigned integer that should be more specific.
  4022. Return Value:
  4023. TRUE: Param1 is more generic than Param2 or at least equal
  4024. FALSE:
  4025. --*/
  4026. {
  4027. DWORD dwGenericProtocol , dwSpecificProtocol;
  4028. DWORD dwGenericPorts, dwSpecificPorts;
  4029. dwGenericProtocol = uliGenericPortProtocol.LowPart;
  4030. dwSpecificProtocol = uliSpecificPortProtocol.LowPart;
  4031. dwGenericPorts = uliGenericPortProtocol.HighPart;
  4032. dwSpecificPorts = uliSpecificPortProtocol.HighPart;
  4033. if ((dwGenericProtocol != 0) && (dwGenericProtocol != dwSpecificProtocol)){
  4034. return FALSE;
  4035. }
  4036. if ((dwGenericPorts == dwSpecificPorts) || (0 == dwGenericPorts)) {
  4037. return TRUE;
  4038. }
  4039. if ((dwSpecificPorts & 0xffff0000) == (dwGenericPorts) ){
  4040. return TRUE;
  4041. }
  4042. if ((dwSpecificPorts & 0x0000ffff) == (dwGenericPorts) ){
  4043. return TRUE;
  4044. }
  4045. return FALSE;
  4046. }