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

3389 lines
94 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. IPSEC_ACTION
  16. IPSecHandlePacket(
  17. IN PUCHAR pIPHeader,
  18. IN PVOID pData,
  19. IN PVOID IPContext,
  20. IN PNDIS_PACKET Packet,
  21. IN OUT PULONG pExtraBytes,
  22. IN OUT PULONG pMTU,
  23. OUT PVOID *pNewData,
  24. IN OUT PULONG pIpsecFlags,
  25. IN UCHAR DestType
  26. )
  27. /*++
  28. Routine Description:
  29. Called by the Filter Driver to submit a packet for IPSEC processing.
  30. Arguments:
  31. pIPHeader - points to start of IP header.
  32. pData - points to the data after the IP header. On the send side, this is an MDL chain
  33. On the recv side this is an IPRcvBuf pointer.
  34. IPContext - contains the destination interface.
  35. pExtraBytes - IPSEC header expansion value; on coming in, it contains the amount of ipsec
  36. header space that can fit into the MTU. so, if MTU is 1400, say, and the
  37. datasize + option size is 1390, this contains 10, meaning that upto
  38. 10 bytes of IPSEC expansion is allowed. This lets IPSEC know when a packet
  39. would be fragmented, so it can do the right thing on send complete.
  40. pMTU - passes in the link MTU on send path.
  41. pNewData - if packet modified, this points to the new data.
  42. IpsecFlags - flags for SrcRoute, Incoming, Forward and Lookback.
  43. Return Value:
  44. eFORWARD
  45. eDROP
  46. eABSORB
  47. --*/
  48. {
  49. IPSEC_ACTION eAction;
  50. IPSEC_DROP_STATUS DropStatus;
  51. PIPSEC_DROP_STATUS pDropStatus=NULL;
  52. IPSEC_DEBUG(PARSE, ("Entering IPSecHandlePacket\n"));
  53. #if DBG
  54. {
  55. IPHeader UNALIGNED *pIPH;
  56. pIPH = (IPHeader UNALIGNED *)pIPHeader;
  57. if ((DebugSrc || DebugDst || DebugPro) &&
  58. (!DebugSrc || pIPH->iph_src == DebugSrc) &&
  59. (!DebugDst || pIPH->iph_dest == DebugDst) &&
  60. (!DebugPro || pIPH->iph_protocol == DebugPro)) {
  61. DbgPrint("Packet from %lx to %lx with protocol %lx length %lx id %lx\n",
  62. pIPH->iph_src,
  63. pIPH->iph_dest,
  64. pIPH->iph_protocol,
  65. NET_SHORT(pIPH->iph_length),
  66. NET_SHORT(pIPH->iph_id));
  67. if (DebugPkt) {
  68. DbgBreakPoint();
  69. }
  70. }
  71. }
  72. #endif
  73. //
  74. // Drop all packets if PA sets us so or if the driver is inactive.
  75. //
  76. if (IS_DRIVER_BLOCK() || IPSEC_DRIVER_IS_INACTIVE()) {
  77. eAction=eDROP;
  78. goto out;
  79. }
  80. //
  81. // Bypass all packets if PA sets us so or no filters are plumbed or the
  82. // packet is broadcast. If multicast filter present, process all multicast
  83. // Once we support any-any tunnels, this check will need to be smarter
  84. //
  85. if (IS_DRIVER_BYPASS() || IPSEC_DRIVER_IS_EMPTY() ||
  86. (IS_BCAST_DEST(DestType) && !IPSEC_MANDBCAST_PROCESS())) {
  87. *pExtraBytes = 0;
  88. *pMTU = 0;
  89. eAction= eFORWARD;
  90. goto out;
  91. }
  92. ASSERT(IS_DRIVER_SECURE());
  93. ASSERT(IPContext);
  94. IPSEC_INCREMENT(g_ipsec.NumThreads);
  95. if (IS_DRIVER_DIAGNOSTIC()) {
  96. pDropStatus=&DropStatus;
  97. RtlZeroMemory(pDropStatus,sizeof(IPSEC_DROP_STATUS));
  98. }
  99. if (*pIpsecFlags & IPSEC_FLAG_INCOMING) {
  100. eAction = IPSecRecvPacket( &pIPHeader,
  101. pData,
  102. IPContext,
  103. Packet,
  104. pExtraBytes,
  105. pIpsecFlags,
  106. pDropStatus,
  107. DestType);
  108. } else {
  109. eAction = IPSecSendPacket( pIPHeader,
  110. pData,
  111. IPContext,
  112. Packet,
  113. pExtraBytes,
  114. pMTU,
  115. pNewData,
  116. pIpsecFlags,
  117. pDropStatus,
  118. DestType);
  119. }
  120. IPSEC_DECREMENT(g_ipsec.NumThreads);
  121. out:
  122. if (eAction == eDROP) {
  123. if (IS_DRIVER_DIAGNOSTIC() &&
  124. (!pDropStatus || (pDropStatus && !(pDropStatus->Flags & IPSEC_DROP_STATUS_DONT_LOG)))) {
  125. IPSecBufferPacketDrop(
  126. pIPHeader,
  127. pData,
  128. pIpsecFlags,
  129. pDropStatus);
  130. }
  131. }
  132. return eAction;
  133. }
  134. IPSEC_ACTION
  135. IPSecSendPacket(
  136. IN PUCHAR pIPHeader,
  137. IN PVOID pData,
  138. IN PVOID IPContext,
  139. IN PNDIS_PACKET Packet,
  140. IN OUT PULONG pExtraBytes,
  141. IN OUT PULONG pMTU,
  142. OUT PVOID *pNewData,
  143. IN OUT PULONG pIpsecFlags,
  144. OUT PIPSEC_DROP_STATUS pDropStatus,
  145. IN UCHAR DestType
  146. )
  147. /*++
  148. Routine Description:
  149. Called by the Filter Driver to submit a packet for IPSEC processing.
  150. Arguments:
  151. pIPHeader - points to start of IP header.
  152. pData - points to the data after the IP header, an MDL chain.
  153. IPContext - contains the destination interface.
  154. pExtraBytes - IPSEC header expansion value.
  155. pMTU - passes in the link MTU on send path.
  156. pNewData - if packet modified, this points to the new data.
  157. IpsecFlags - flags for SrcRoute, Incoming, Forward and Lookback.
  158. Return Value:
  159. eFORWARD
  160. eDROP
  161. eABSORB
  162. --*/
  163. {
  164. NTSTATUS status = STATUS_SUCCESS;
  165. IPSEC_ACTION eRetAction = eFORWARD;
  166. PSA_TABLE_ENTRY pSA = NULL;
  167. PSA_TABLE_ENTRY pSaveSA = NULL;
  168. PSA_TABLE_ENTRY pNextSA = NULL;
  169. USHORT FilterFlags = 0;
  170. BOOLEAN fLifetime = FALSE;
  171. ULONG ipsecHdrSpace = *pExtraBytes;
  172. ULONG ipsecOverhead = 0;
  173. ULONG ipsecMTU = *pMTU;
  174. ULONG newMTU = MAX_LONG;
  175. ULONG dataLength = 0;
  176. IPHeader UNALIGNED *pIPH = (IPHeader UNALIGNED *)pIPHeader;
  177. Interface *DestIF = (Interface *)IPContext;
  178. PNDIS_PACKET_EXTENSION PktExt = NULL;
  179. PNDIS_IPSEC_PACKET_INFO IPSecPktInfo = NULL;
  180. BOOLEAN fCryptoOnly = FALSE;
  181. BOOLEAN fFWPacket = FALSE;
  182. BOOLEAN fSrcRoute = FALSE;
  183. BOOLEAN fLoopback = FALSE;
  184. PVOID *ppSCContext;
  185. KIRQL kIrql;
  186. LONG Index;
  187. PNDIS_BUFFER pTemp;
  188. ULONG Length;
  189. PUCHAR pBuffer;
  190. IPSEC_DEBUG(PARSE, ("Entering IPSecSendPacket\n"));
  191. if (*pIpsecFlags & IPSEC_FLAG_FORWARD) {
  192. fFWPacket = TRUE;
  193. }
  194. if (*pIpsecFlags & IPSEC_FLAG_SSRR) {
  195. fSrcRoute = TRUE;
  196. }
  197. if (*pIpsecFlags & IPSEC_FLAG_LOOPBACK) {
  198. fLoopback = TRUE;
  199. }
  200. *pExtraBytes = 0;
  201. *pMTU = 0;
  202. if (fLoopback) {
  203. IPSEC_DEBUG(PARSE, ("IPSecSendPacket: Packet on loopback interface - returning\n"));
  204. status = STATUS_SUCCESS;
  205. goto out;
  206. }
  207. //
  208. // Walk through the MDL chain to make sure we have memory locked.
  209. //
  210. pTemp = (PNDIS_BUFFER)pData;
  211. while (pTemp) {
  212. pBuffer = NULL;
  213. Length = 0;
  214. NdisQueryBufferSafe(pTemp,
  215. &pBuffer,
  216. &Length,
  217. NormalPagePriority);
  218. if (!pBuffer) {
  219. //
  220. // QueryBuffer failed, drop the packet.
  221. //
  222. status = STATUS_UNSUCCESSFUL;
  223. goto out;
  224. }
  225. dataLength += Length;
  226. pTemp = NDIS_BUFFER_LINKAGE(pTemp);
  227. }
  228. dataLength -= sizeof(IPHeader);
  229. //
  230. // Set send complete context in the NDIS packet.
  231. //
  232. if (Packet) {
  233. PacketContext *pContext;
  234. pContext = (PacketContext *)Packet->ProtocolReserved;
  235. ppSCContext = &pContext->pc_common.pc_IpsecCtx;
  236. } else {
  237. ASSERT(FALSE);
  238. status = STATUS_UNSUCCESSFUL;
  239. goto out;
  240. }
  241. status = IPSecClassifyPacket( pIPHeader,
  242. pData,
  243. &pSA,
  244. &pNextSA,
  245. &FilterFlags,
  246. #if GPC
  247. PtrToUlong(NDIS_PER_PACKET_INFO_FROM_PACKET(Packet, ClassificationHandlePacketInfo)),
  248. #endif
  249. TRUE, // fOutbound
  250. fFWPacket,
  251. TRUE, // do bypass check
  252. DestType);
  253. if (status == STATUS_PENDING) {
  254. //
  255. // Negotiation kicked off; drop the packet silently.
  256. //
  257. return eABSORB;
  258. } else if (status != STATUS_SUCCESS) {
  259. status = STATUS_SUCCESS;
  260. goto out;
  261. }
  262. if (FilterFlags) {
  263. ASSERT(pSA == NULL);
  264. //
  265. // This is either a drop or pass thru filter.
  266. //
  267. if (FilterFlags & FILTER_FLAGS_DROP) {
  268. IPSEC_DEBUG(PARSE, ("Drop filter\n"));
  269. status = STATUS_UNSUCCESSFUL;
  270. } else if (FilterFlags & FILTER_FLAGS_PASS_THRU) {
  271. IPSEC_DEBUG(PARSE, ("Pass thru' filter\n"));
  272. status = STATUS_SUCCESS;
  273. } else {
  274. ASSERT(FALSE);
  275. }
  276. goto out;
  277. }
  278. //
  279. // Consider only outbound SAs
  280. //
  281. ASSERT(pSA);
  282. ASSERT(pSA->sa_Flags & FLAGS_SA_OUTBOUND);
  283. //
  284. // We don't support Source Route with IPSec Tunneling.
  285. //
  286. if (fSrcRoute && (pSA->sa_Flags & FLAGS_SA_TUNNEL)) {
  287. IPSEC_DEBUG(TUNNEL, ("No tunneling source route: pSA: %lx\n", pSA));
  288. IPSecDerefSANextSA(pSA, pNextSA);
  289. status = STATUS_UNSUCCESSFUL;
  290. goto out;
  291. }
  292. //
  293. // Set the last used time.
  294. //
  295. NdisGetCurrentSystemTime(&pSA->sa_LastUsedTime);
  296. if (!(pSA->sa_Flags & FLAGS_SA_DISABLE_LIFETIME_CHECK)) {
  297. //
  298. // check if we might expire soon - start rekey operation now.
  299. //
  300. IPSEC_CHECK_PADDED_LIFETIME(pSA, fLifetime, pSA->sa_NumOps - 1);
  301. if (fLifetime == FALSE) {
  302. IPSecRekeyOutboundSA(pSA);
  303. }
  304. //
  305. // check the real lifetime - if we have expired, ensure that the
  306. // re-key was submitted and then cancel the current SAs.
  307. //
  308. IPSEC_CHECK_LIFETIME(pSA, fLifetime, pSA->sa_NumOps - 1);
  309. //
  310. // this time it really expired - we are in trouble since this shd have gone away
  311. // earlier.
  312. //
  313. if (fLifetime == FALSE) {
  314. IPSecPuntOutboundSA(pSA);
  315. IPSecDerefSANextSA(pSA, pNextSA);
  316. status = STATUS_UNSUCCESSFUL;
  317. goto out;
  318. }
  319. }
  320. //
  321. // Compute the total IPSec overhead.
  322. //
  323. ipsecOverhead = pSA->sa_IPSecOverhead;
  324. if (pNextSA) {
  325. ipsecOverhead += pNextSA->sa_IPSecOverhead;
  326. }
  327. //
  328. // Check if total data length exceeds 65535.
  329. //
  330. if ((dataLength + ipsecOverhead) > (MAX_IP_DATA_LENGTH - sizeof(IPHeader))) {
  331. IPSecDerefSANextSA(pSA, pNextSA);
  332. status = STATUS_UNSUCCESSFUL;
  333. goto out;
  334. }
  335. //
  336. // If no enough header space, return right away if DF bit is set. We also
  337. // have to adjust for PMTU recorded in the SAs.
  338. //
  339. if (pIPH->iph_offset & IP_DF_FLAG) {
  340. //
  341. // First get MTU recorded from IPSecStatus.
  342. //
  343. if (pNextSA) {
  344. newMTU = MIN(IPSEC_GET_VALUE(pSA->sa_NewMTU),
  345. IPSEC_GET_VALUE(pNextSA->sa_NewMTU));
  346. } else {
  347. newMTU = IPSEC_GET_VALUE(pSA->sa_NewMTU);
  348. }
  349. //
  350. // Use the smaller of link MTU and new MTU from SA.
  351. //
  352. newMTU = MIN(newMTU, ipsecMTU);
  353. //
  354. // See if we have enough header space; if not pass back the new smaller
  355. // MTU minus IPSec overhead to the upper stack.
  356. //
  357. if (newMTU < (ipsecOverhead + dataLength)) {
  358. *pMTU = newMTU - ipsecOverhead;
  359. IPSecDerefSANextSA(pSA, pNextSA);
  360. IPSEC_DEBUG(PMTU, ("OldMTU %lx, HdrSpace: %lx, NewMTU: %lx\n", ipsecMTU, ipsecHdrSpace, *pMTU));
  361. status = STATUS_UNSUCCESSFUL;
  362. goto out;
  363. }
  364. }
  365. //
  366. // See if hardware offload can be arranged here. If successful, we pass the
  367. // flag to the create routines so they create only the framing, leaving the
  368. // core crypto to the hardware.
  369. //
  370. if (g_ipsec.EnableOffload && ipsecOverhead <= ipsecHdrSpace) {
  371. IPSecSendOffload( pIPH,
  372. Packet,
  373. DestIF,
  374. pSA,
  375. pNextSA,
  376. ppSCContext,
  377. &fCryptoOnly);
  378. }
  379. //
  380. // Make sure IPSecPktInfo is NULL if there is no offload for this
  381. // packet. This could be set in reinject path which is then
  382. // forwarded.
  383. //
  384. if (!fCryptoOnly) {
  385. ASSERT(Packet != NULL);
  386. PktExt = NDIS_PACKET_EXTENSION_FROM_PACKET(Packet);
  387. PktExt->NdisPacketInfo[IpSecPacketInfo] = NULL;
  388. }
  389. if (fCryptoOnly) {
  390. ADD_TO_LARGE_INTEGER(
  391. &g_ipsec.Statistics.uOffloadedBytesSent,
  392. NET_SHORT(pIPH->iph_length));
  393. if (pDropStatus) {
  394. pDropStatus->Flags |= IPSEC_DROP_STATUS_CRYPTO_DONE;
  395. }
  396. }
  397. do {
  398. ADD_TO_LARGE_INTEGER(
  399. &pSA->sa_Stats.TotalBytesSent,
  400. NET_SHORT(pIPH->iph_length));
  401. if (pSA->sa_Flags & FLAGS_SA_TUNNEL) {
  402. ADD_TO_LARGE_INTEGER(
  403. &g_ipsec.Statistics.uBytesSentInTunnels,
  404. NET_SHORT(pIPH->iph_length));
  405. } else {
  406. ADD_TO_LARGE_INTEGER(
  407. &g_ipsec.Statistics.uTransportBytesSent,
  408. NET_SHORT(pIPH->iph_length));
  409. }
  410. if (fCryptoOnly) {
  411. ADD_TO_LARGE_INTEGER(
  412. &pSA->sa_Stats.OffloadedBytesSent,
  413. NET_SHORT(pIPH->iph_length));
  414. }
  415. //
  416. // Multiple ops here - iterate thru the headers. Inner first.
  417. //
  418. for (Index = 0; Index < pSA->sa_NumOps; Index++) {
  419. switch (pSA->sa_Operation[Index]) {
  420. case Auth:
  421. status = IPSecCreateAH( pIPHeader,
  422. pData,
  423. pSA,
  424. Index,
  425. pNewData,
  426. ppSCContext,
  427. pExtraBytes,
  428. ipsecHdrSpace,
  429. fSrcRoute,
  430. fCryptoOnly);
  431. if (!NT_SUCCESS(status)) {
  432. IPSEC_DEBUG(PARSE, ("AH failed: pSA: %lx, status: %lx\n",
  433. pSA,
  434. status));
  435. IPSecDerefSANextSA(pSA, pNextSA);
  436. goto out;
  437. }
  438. //
  439. // Save the new MDL for future operation; also query the new header (if it changed)
  440. //
  441. if (*pNewData) {
  442. pData = *pNewData;
  443. IPSecQueryNdisBuf((PNDIS_BUFFER)pData, &pIPHeader, &Length);
  444. }
  445. break;
  446. case Encrypt:
  447. status = IPSecCreateHughes( pIPHeader,
  448. pData,
  449. pSA,
  450. Index,
  451. pNewData,
  452. ppSCContext,
  453. pExtraBytes,
  454. ipsecHdrSpace,
  455. Packet,
  456. fCryptoOnly);
  457. if (!NT_SUCCESS(status)) {
  458. IPSEC_DEBUG(PARSE, ("HUGHES failed: pSA: %lx, status: %lx\n",
  459. pSA,
  460. status));
  461. IPSecDerefSANextSA(pSA, pNextSA);
  462. goto out;
  463. }
  464. //
  465. // Save the new MDL for future operation; also query the new header (if it changed)
  466. //
  467. if (*pNewData) {
  468. pData = *pNewData;
  469. IPSecQueryNdisBuf((PNDIS_BUFFER)pData, &pIPHeader, &Length);
  470. }
  471. break;
  472. case None:
  473. status = STATUS_SUCCESS;
  474. break;
  475. default:
  476. IPSEC_DEBUG(PARSE, ("No valid operation: %lx\n", pSA->sa_Operation));
  477. break;
  478. }
  479. }
  480. pSaveSA = pSA;
  481. pSA = pNextSA;
  482. if (!pSA) {
  483. IPSecDerefSA(pSaveSA);
  484. break;
  485. }
  486. pNextSA = NULL;
  487. IPSecDerefSA(pSaveSA);
  488. } while (TRUE);
  489. //
  490. // Remember if we are going to fragment.
  491. //
  492. if (ipsecHdrSpace < *pExtraBytes) {
  493. IPSEC_DEBUG(PARSE, ("ipsecHdrSpace: FRAG\n"));
  494. ((IPSEC_SEND_COMPLETE_CONTEXT *)*ppSCContext)->Flags |= SCF_FRAG;
  495. }
  496. out:
  497. if (!NT_SUCCESS(status)) {
  498. IPSEC_DEBUG(PARSE, ("IPSecSendPacket failed: %lx\n", status));
  499. eRetAction = eDROP;
  500. }
  501. if (pDropStatus) {
  502. pDropStatus->IPSecStatus=status;
  503. }
  504. IPSEC_DEBUG(PARSE, ("Exiting IPSecSendPacket; action %lx\n", eRetAction));
  505. return eRetAction;
  506. }
  507. IPSEC_ACTION
  508. IPSecRecvPacket(
  509. IN PUCHAR *pIPHeader,
  510. IN PVOID pData,
  511. IN PVOID IPContext,
  512. IN PNDIS_PACKET Packet,
  513. IN OUT PULONG pExtraBytes,
  514. IN OUT PULONG pIpsecFlags,
  515. OUT PIPSEC_DROP_STATUS pDropStatus,
  516. IN UCHAR DestType
  517. )
  518. /*++
  519. Routine Description:
  520. This is the IPSecRecvHandler.
  521. Arguments:
  522. pIPHeader - points to start of IP header.
  523. pData - points to the data after the IP header, an IPRcvBuf pointer.
  524. IPContext - contains the destination interface.
  525. pExtraBytes - IPSEC header expansion value.
  526. IpsecFlags - flags for SrcRoute, Incoming, Forward and Lookback.
  527. Return Value:
  528. eFORWARD
  529. eDROP
  530. --*/
  531. {
  532. NTSTATUS status = STATUS_SUCCESS;
  533. IPSEC_ACTION eRetAction = eFORWARD;
  534. PSA_TABLE_ENTRY pSA = NULL;
  535. PSA_TABLE_ENTRY pSaveSA = NULL;
  536. PSA_TABLE_ENTRY pNextSA = NULL;
  537. USHORT FilterFlags = 0;
  538. BOOLEAN fLifetime = FALSE;
  539. IPHeader UNALIGNED *pIPH = (IPHeader UNALIGNED *)*pIPHeader;
  540. Interface *DestIF = (Interface *)IPContext;
  541. PNDIS_PACKET OrigPacket = NULL;
  542. PNDIS_PACKET_EXTENSION PktExt = NULL;
  543. PNDIS_IPSEC_PACKET_INFO IPSecPktInfo = NULL;
  544. BOOLEAN fCryptoOnly = FALSE;
  545. BOOLEAN fFWPacket = FALSE;
  546. BOOLEAN fSrcRoute = FALSE;
  547. BOOLEAN fLoopback = FALSE;
  548. BOOLEAN fFastRcv = FALSE;
  549. tSPI SPI;
  550. KIRQL kIrql;
  551. LONG Index;
  552. IPSEC_DEBUG(PARSE, ("Entering IPSecRecvPacket\n"));
  553. if (*pIpsecFlags & IPSEC_FLAG_FORWARD) {
  554. fFWPacket = TRUE;
  555. }
  556. if (*pIpsecFlags & IPSEC_FLAG_SSRR) {
  557. fSrcRoute = TRUE;
  558. }
  559. if (*pIpsecFlags & IPSEC_FLAG_LOOPBACK) {
  560. fLoopback = TRUE;
  561. }
  562. if (*pIpsecFlags & IPSEC_FLAG_FASTRCV) {
  563. fFastRcv = TRUE;
  564. }
  565. *pExtraBytes = 0;
  566. if (Packet) {
  567. OrigPacket = (PNDIS_PACKET)NDIS_GET_ORIGINAL_PACKET(Packet);
  568. if (OrigPacket) {
  569. PktExt = NDIS_PACKET_EXTENSION_FROM_PACKET(OrigPacket);
  570. } else {
  571. PktExt = NDIS_PACKET_EXTENSION_FROM_PACKET(Packet);
  572. }
  573. IPSecPktInfo = PktExt->NdisPacketInfo[IpSecPacketInfo];
  574. }
  575. #if DBG
  576. if (DebugOff) {
  577. if (pIPH->iph_protocol == PROTOCOL_AH ||
  578. pIPH->iph_protocol == PROTOCOL_ESP) {
  579. DbgPrint("Packet %lx, OrigPacket %lx, CRYPTO %d, CryptoStatus %d\n",
  580. Packet,
  581. OrigPacket,
  582. IPSecPktInfo? IPSecPktInfo->Receive.CRYPTO_DONE: 0,
  583. IPSecPktInfo? IPSecPktInfo->Receive.CryptoStatus: 0);
  584. if (DebugPkt) {
  585. DbgBreakPoint();
  586. }
  587. }
  588. }
  589. #endif
  590. //
  591. // If the packet is IPSec protected, set the appropriate flags for firewall/NAT.
  592. //
  593. if (pIPH->iph_protocol == PROTOCOL_AH ||
  594. pIPH->iph_protocol == PROTOCOL_ESP) {
  595. *pIpsecFlags |= IPSEC_FLAG_TRANSFORMED;
  596. }
  597. if (IPSecPktInfo && pDropStatus) {
  598. if (IPSecPktInfo->Receive.CRYPTO_DONE) {
  599. pDropStatus->Flags |= IPSEC_DROP_STATUS_CRYPTO_DONE;
  600. }
  601. if (IPSecPktInfo->Receive.NEXT_CRYPTO_DONE) {
  602. pDropStatus->Flags |= IPSEC_DROP_STATUS_NEXT_CRYPTO_DONE;
  603. }
  604. if (IPSecPktInfo->Receive.SA_DELETE_REQ) {
  605. pDropStatus->Flags |= IPSEC_DROP_STATUS_SA_DELETE_REQ;
  606. }
  607. pDropStatus->OffloadStatus=IPSecPktInfo->Receive.CryptoStatus;
  608. }
  609. if (IPSecPktInfo &&
  610. IPSecPktInfo->Receive.CRYPTO_DONE &&
  611. IPSecPktInfo->Receive.CryptoStatus != CRYPTO_SUCCESS) {
  612. //
  613. // Error reported by offload card. Discard the packet and apply
  614. // the necessary acountings.
  615. //
  616. IPSecBufferOffloadEvent(pIPH, IPSecPktInfo);
  617. status = STATUS_UNSUCCESSFUL;
  618. goto out;
  619. }
  620. //
  621. // Walk the packet to determine the SPI
  622. //
  623. status = IPSecParsePacket( *pIPHeader,
  624. pData,
  625. &SPI);
  626. if (!NT_SUCCESS(status)) {
  627. IPSEC_DEBUG(PARSE, ("IPSecParsePkt no IPSEC headers: %lx\n", status));
  628. if (fLoopback) {
  629. IPSEC_DEBUG(PARSE, ("loopback was on, not doing inbound policy check\n"));
  630. status = STATUS_SUCCESS;
  631. goto out;
  632. }
  633. status = IPSecClassifyPacket( *pIPHeader,
  634. pData,
  635. &pSA,
  636. &pNextSA,
  637. &FilterFlags,
  638. #if GPC
  639. 0,
  640. #endif
  641. FALSE, // fOutbound
  642. fFWPacket,
  643. TRUE, // do bypass check
  644. DestType);
  645. if (status != STATUS_SUCCESS) {
  646. ASSERT(pSA == NULL);
  647. //
  648. // If we didnt find an SA, but found a filter, bad, drop.
  649. //
  650. if (status == STATUS_PENDING) {
  651. if (FilterFlags & FILTER_FLAGS_PASS_THRU) {
  652. // Allow this clear text traffic in
  653. status = STATUS_SUCCESS;
  654. } else {
  655. IPSEC_DEBUG(PARSE, ("IPSecParsePkt cleartext when filter exists: %lx\n", status));
  656. status = IPSEC_NEGOTIATION_PENDING;
  657. }
  658. } else {
  659. status = STATUS_SUCCESS;
  660. }
  661. goto out;
  662. } else {
  663. if (FilterFlags) {
  664. ASSERT(pSA == NULL);
  665. //
  666. // This is either a drop or pass thru filter.
  667. //
  668. if (FilterFlags & FILTER_FLAGS_DROP) {
  669. IPSEC_DEBUG(PARSE, ("Drop filter\n"));
  670. status = IPSEC_BLOCK;
  671. } else if (FilterFlags & FILTER_FLAGS_PASS_THRU) {
  672. IPSEC_DEBUG(PARSE, ("Pass thru' filter\n"));
  673. status = STATUS_SUCCESS;
  674. } else {
  675. ASSERT(FALSE);
  676. }
  677. goto out;
  678. }
  679. ASSERT(pSA);
  680. //
  681. // Set the last used time.
  682. //
  683. NdisGetCurrentSystemTime(&pSA->sa_LastUsedTime);
  684. //
  685. // We found an SA; we are OK if the SA is set to None
  686. // or if it is a tunnel SA; we are here because
  687. // IPSecClassifyPacket finds and SA and returns SUCCESS.
  688. //
  689. if (pSA->sa_Operation[0] != None &&
  690. !(pSA->sa_Flags & FLAGS_SA_TUNNEL) &&
  691. !(pSA->sa_Flags & FLAGS_SA_PASSTHRU_FILTER)) {
  692. if (g_ipsec.DiagnosticMode & IPSEC_DIAGNOSTIC_INBOUND) {
  693. IPSecBufferEvent( pIPH->iph_src,
  694. EVENT_IPSEC_UNEXPECTED_CLEARTEXT,
  695. 2,
  696. TRUE);
  697. }
  698. #if DBG
  699. if (IPSecDebug & IPSEC_DEBUG_CLEARTEXT) {
  700. PUCHAR pTpt;
  701. ULONG tptLen;
  702. UNALIGNED WORD *pwPort;
  703. IPSecQueryRcvBuf(pData, &pTpt, &tptLen);
  704. pwPort = (UNALIGNED WORD *)(pTpt);
  705. DbgPrint("Unexpected clear text: src %lx, dest %lx, protocol %lx, sport %lx, dport %lx\n", pIPH->iph_src, pIPH->iph_dest, pIPH->iph_protocol, pwPort[0], pwPort[1]);
  706. }
  707. #endif
  708. IPSEC_DEBUG(PARSE, ("Real SA present\n"));
  709. status = IPSEC_INVALID_CLEARTEXT;
  710. }
  711. IPSecDerefSA(pSA);
  712. }
  713. } else {
  714. IPHeader UNALIGNED *pIPH = (UNALIGNED IPHeader *)*pIPHeader;
  715. IPSEC_SPI_TO_ENTRY(SPI, &pSA, pIPH->iph_dest);
  716. //
  717. // Report Bad SPI event only if there is no matching SA.
  718. //
  719. if (!pSA) {
  720. IPSEC_INC_STATISTIC(dwNumBadSPIPackets);
  721. IPSecBufferEvent( pIPH->iph_src,
  722. EVENT_IPSEC_BAD_SPI_RECEIVED,
  723. 1,
  724. TRUE);
  725. IPSEC_DEBUG(PARSE, ("Bad spi: %lx\n", SPI));
  726. status = IPSEC_BAD_SPI;
  727. goto out;
  728. }
  729. //
  730. // If larval SA exits, silently discard the packet.
  731. //
  732. if (pSA->sa_State != STATE_SA_ACTIVE) {
  733. IPSecDerefSA(pSA);
  734. status = STATUS_INVALID_PARAMETER;
  735. goto out;
  736. }
  737. //
  738. // Set the last used time.
  739. //
  740. NdisGetCurrentSystemTime(&pSA->sa_LastUsedTime);
  741. if (!(pSA->sa_Flags & FLAGS_SA_DISABLE_LIFETIME_CHECK)) {
  742. //
  743. // Check if we might expire soon - start rekey operation now.
  744. //
  745. IPSEC_CHECK_PADDED_LIFETIME(pSA, fLifetime, 0);
  746. if (fLifetime == FALSE) {
  747. IPSecRekeyInboundSA(pSA);
  748. }
  749. //
  750. // Check the real lifetime - if we have expired, ensure that the
  751. // rekey was submitted and then cancel the current SAs.
  752. //
  753. IPSEC_CHECK_LIFETIME(pSA, fLifetime, 0);
  754. if (fLifetime == FALSE) {
  755. IPSecPuntInboundSA(pSA);
  756. IPSecDerefSA(pSA);
  757. status = STATUS_UNSUCCESSFUL;
  758. goto out;
  759. }
  760. }
  761. if (pSA->sa_Flags & FLAGS_SA_TUNNEL) {
  762. ADD_TO_LARGE_INTEGER(
  763. &g_ipsec.Statistics.uBytesReceivedInTunnels,
  764. NET_SHORT(pIPH->iph_length));
  765. } else {
  766. ADD_TO_LARGE_INTEGER(
  767. &g_ipsec.Statistics.uTransportBytesReceived,
  768. NET_SHORT(pIPH->iph_length));
  769. }
  770. ADD_TO_LARGE_INTEGER(
  771. &pSA->sa_Stats.TotalBytesReceived,
  772. NET_SHORT(pIPH->iph_length));
  773. //
  774. // If this was supposed to be handled by hardware, then make sure he
  775. // either punted it or this was cryptoonly.
  776. //
  777. if (IPSecPktInfo != NULL) {
  778. if (IPSecPktInfo->Receive.CRYPTO_DONE) {
  779. //
  780. // Offload has been applied to this packet so
  781. // record it. We are here because CryptoStatus
  782. // equals CRYPTO_SUCCESS.
  783. //
  784. ASSERT(IPSecPktInfo->Receive.CryptoStatus == CRYPTO_SUCCESS);
  785. fCryptoOnly = TRUE;
  786. ADD_TO_LARGE_INTEGER(
  787. &pSA->sa_Stats.OffloadedBytesReceived,
  788. NET_SHORT(pIPH->iph_length));
  789. ADD_TO_LARGE_INTEGER(
  790. &g_ipsec.Statistics.uOffloadedBytesReceived,
  791. NET_SHORT(pIPH->iph_length));
  792. }
  793. if (IPSecPktInfo->Receive.SA_DELETE_REQ) {
  794. //
  795. // No more offload on this SA and its corresponding
  796. // outbound SA.
  797. //
  798. AcquireWriteLock(&g_ipsec.SADBLock, &kIrql);
  799. if ((pSA->sa_Flags & FLAGS_SA_HW_PLUMBED) &&
  800. (pSA->sa_IPIF == DestIF)) {
  801. IPSecDelHWSAAtDpc(pSA);
  802. }
  803. if (pSA->sa_AssociatedSA &&
  804. (pSA->sa_AssociatedSA->sa_Flags & FLAGS_SA_HW_PLUMBED) &&
  805. (pSA->sa_AssociatedSA->sa_IPIF == DestIF)) {
  806. IPSecDelHWSAAtDpc(pSA->sa_AssociatedSA);
  807. }
  808. ReleaseWriteLock(&g_ipsec.SADBLock, kIrql);
  809. }
  810. }
  811. //
  812. // If SA is not offloaded, try to offload it now.
  813. //
  814. if (!fCryptoOnly) {
  815. IPSecRecvOffload(pIPH, DestIF, pSA);
  816. }
  817. //
  818. // With multiple SAs coming in, we need to iterate through the operations,
  819. // last first.
  820. //
  821. for (Index = pSA->sa_NumOps-1; (LONG)Index >= 0; Index--) {
  822. //
  823. // Got to keep resetting pIPH since pIPHeader can change in the
  824. // IPSecVerifyXXX calls
  825. //
  826. pIPH = (UNALIGNED IPHeader *)*pIPHeader;
  827. switch (pSA->sa_Operation[Index]) {
  828. case Auth:
  829. //
  830. // Verify AH
  831. //
  832. if (pIPH->iph_protocol != PROTOCOL_AH) {
  833. IPSecBufferEvent( pIPH->iph_src,
  834. EVENT_IPSEC_BAD_PROTOCOL_RECEIVED,
  835. 1,
  836. TRUE);
  837. status = STATUS_UNSUCCESSFUL;
  838. break;
  839. }
  840. status = IPSecVerifyAH( pIPHeader,
  841. pData,
  842. pSA,
  843. Index,
  844. pExtraBytes,
  845. fSrcRoute,
  846. fCryptoOnly,
  847. fFastRcv);
  848. if (!NT_SUCCESS(status)) {
  849. IPSEC_DEBUG(PARSE, ("AH failed: pSA: %lx, status: %lx\n",
  850. pSA,
  851. status));
  852. IPSecDerefSA(pSA);
  853. goto out;
  854. }
  855. break;
  856. case Encrypt:
  857. //
  858. // Hughes ..
  859. //
  860. if (pIPH->iph_protocol != PROTOCOL_ESP) {
  861. IPSecBufferEvent( pIPH->iph_src,
  862. EVENT_IPSEC_BAD_PROTOCOL_RECEIVED,
  863. 2,
  864. TRUE);
  865. status = STATUS_UNSUCCESSFUL;
  866. break;
  867. }
  868. status = IPSecVerifyHughes( pIPHeader,
  869. pData,
  870. pSA,
  871. Index,
  872. pExtraBytes,
  873. fCryptoOnly,
  874. fFastRcv);
  875. if (!NT_SUCCESS(status)) {
  876. IPSEC_DEBUG(PARSE, ("Hughes failed: pSA: %lx, status: %lx\n",
  877. pSA,
  878. status));
  879. IPSecDerefSA(pSA);
  880. goto out;
  881. }
  882. break;
  883. case None:
  884. //
  885. // None is useful for down-level clients - if the peer is incapable
  886. // of IPSEC, we might have a system policy to send in clear. in that
  887. // case, the Operation will be None.
  888. //
  889. status = STATUS_SUCCESS;
  890. break;
  891. default:
  892. IPSEC_DEBUG(PARSE, ("Invalid op in SA: %lx, Index: %d\n", pSA, Index));
  893. ASSERT(FALSE);
  894. break;
  895. }
  896. }
  897. //
  898. // If this was a tunnel SA that succeeded in decrypt/auth,
  899. // drop this packet and re-inject a copy.
  900. //
  901. if ((status == STATUS_SUCCESS) &&
  902. (pSA->sa_Flags & FLAGS_SA_TUNNEL)) {
  903. IPSecReinjectPacket(pData, fCryptoOnly? PktExt: NULL);
  904. status = STATUS_INVALID_PARAMETER;
  905. if (pDropStatus) {
  906. pDropStatus->Flags |= IPSEC_DROP_STATUS_DONT_LOG;
  907. }
  908. }
  909. IPSecDerefSA(pSA);
  910. }
  911. out:
  912. if (!NT_SUCCESS(status)) {
  913. IPSEC_DEBUG(PARSE, ("IPSecRecvPacket failed: %lx\n", status));
  914. eRetAction = eDROP;
  915. }
  916. if (pDropStatus) {
  917. pDropStatus->IPSecStatus=status;
  918. }
  919. IPSEC_DEBUG(PARSE, ("Exiting IPSecRecvPacket; action %lx\n", eRetAction));
  920. return eRetAction;
  921. }
  922. VOID
  923. IPSecCalcHeaderOverheadFromSA(
  924. IN PSA_TABLE_ENTRY pSA,
  925. OUT PULONG pOverhead
  926. )
  927. /*++
  928. Routine Description:
  929. Called from IP to query the IPSEC header overhead.
  930. Arguments:
  931. pIPHeader - points to start of IP header.
  932. pOverhead - number of bytes in IPSEC header.
  933. Return Value:
  934. None
  935. --*/
  936. {
  937. LONG Index;
  938. ULONG AHSize = sizeof(AH) + pSA->sa_TruncatedLen;
  939. ULONG ESPSize = sizeof(ESP) + pSA->sa_ivlen + pSA->sa_ReplayLen + MAX_PAD_LEN + pSA->sa_TruncatedLen;
  940. //
  941. // Take the actual SA to get the exact value.
  942. //
  943. *pOverhead = 0;
  944. for (Index = 0; Index < pSA->sa_NumOps; Index++) {
  945. switch (pSA->sa_Operation[Index]) {
  946. case Encrypt:
  947. *pOverhead += ESPSize;
  948. IPSEC_DEBUG(PMTU, ("PROTOCOL_ESP: overhead: %lx\n", *pOverhead));
  949. break;
  950. case Auth:
  951. *pOverhead += AHSize;
  952. IPSEC_DEBUG(PMTU, ("PROTOCOL_AH: overhead: %lx\n", *pOverhead));
  953. break;
  954. default:
  955. IPSEC_DEBUG(PMTU, ("No IPSEC headers\n"));
  956. break;
  957. }
  958. }
  959. if (pSA->sa_Flags & FLAGS_SA_TUNNEL) {
  960. *pOverhead += sizeof(IPHeader);
  961. IPSEC_DEBUG(PMTU, ("TUNNEL: overhead: %lx\n", *pOverhead));
  962. }
  963. }
  964. NTSTATUS
  965. IPSecParsePacket(
  966. IN PUCHAR pIPHeader,
  967. IN PVOID *pData,
  968. OUT tSPI *pSPI
  969. )
  970. /*++
  971. Routine Description:
  972. Walk the packet to determine the SPI, this also returns the
  973. next header that might be also an IPSEC component.
  974. Arguments:
  975. pIPHeader - points to start of IP header.
  976. pData - points to the data after the IP header.
  977. pSPI - to return the SPI value.
  978. Return Value:
  979. --*/
  980. {
  981. IPHeader UNALIGNED *pIPH = (IPHeader UNALIGNED *)pIPHeader;
  982. AH UNALIGNED *pAH;
  983. ESP UNALIGNED *pEsp;
  984. NTSTATUS status = STATUS_NOT_FOUND;
  985. PUCHAR pPyld;
  986. ULONG Len;
  987. IPSEC_DEBUG(PARSE, ("Entering IPSecParsePacket\n"));
  988. IPSecQueryRcvBuf(pData, &pPyld, &Len);
  989. if (pIPH->iph_protocol == PROTOCOL_AH) {
  990. pAH = (UNALIGNED AH *)pPyld;
  991. if (Len >= sizeof(AH)) {
  992. *pSPI = NET_TO_HOST_LONG(pAH->ah_spi);
  993. status = STATUS_SUCCESS;
  994. }
  995. } else if (pIPH->iph_protocol == PROTOCOL_ESP) {
  996. pEsp = (UNALIGNED ESP *)pPyld;
  997. if (Len >= sizeof(ESP)) {
  998. *pSPI = NET_TO_HOST_LONG(pEsp->esp_spi);
  999. status = STATUS_SUCCESS;
  1000. }
  1001. }
  1002. IPSEC_DEBUG(PARSE, ("Exiting IPSecParsePacket\n"));
  1003. return status;
  1004. }
  1005. PSA_TABLE_ENTRY
  1006. IPSecLookupSAInLarval(
  1007. IN ULARGE_INTEGER uliSrcDstAddr,
  1008. IN ULARGE_INTEGER uliProtoSrcDstPort
  1009. )
  1010. /*++
  1011. Routine Description:
  1012. Search for SA (in larval list) matching the input params.
  1013. Arguments:
  1014. Return Value:
  1015. Pointer to SA matched else NULL
  1016. --*/
  1017. {
  1018. PLIST_ENTRY pEntry;
  1019. KIRQL kIrql;
  1020. ULARGE_INTEGER uliAddr;
  1021. ULARGE_INTEGER uliPort;
  1022. PSA_TABLE_ENTRY pSA = NULL;
  1023. IPSEC_BUILD_SRC_DEST_ADDR(uliAddr, DEST_ADDR, SRC_ADDR);
  1024. ACQUIRE_LOCK(&g_ipsec.LarvalListLock, &kIrql);
  1025. for ( pEntry = g_ipsec.LarvalSAList.Flink;
  1026. pEntry != &g_ipsec.LarvalSAList;
  1027. pEntry = pEntry->Flink) {
  1028. pSA = CONTAINING_RECORD(pEntry,
  1029. SA_TABLE_ENTRY,
  1030. sa_LarvalLinkage);
  1031. //
  1032. // responder inbound has no filter ptr
  1033. //
  1034. if (pSA->sa_Filter) {
  1035. uliPort.QuadPart = uliProtoSrcDstPort.QuadPart & pSA->sa_Filter->uliProtoSrcDstMask.QuadPart;
  1036. if ((uliAddr.QuadPart == pSA->sa_uliSrcDstAddr.QuadPart) &&
  1037. (uliPort.QuadPart == pSA->sa_Filter->uliProtoSrcDstPort.QuadPart)) {
  1038. IPSEC_DEBUG(HASH, ("Matched entry: %lx\n", pSA));
  1039. RELEASE_LOCK(&g_ipsec.LarvalListLock, kIrql);
  1040. return pSA;
  1041. }
  1042. } else {
  1043. if (uliAddr.QuadPart == pSA->sa_uliSrcDstAddr.QuadPart) {
  1044. IPSEC_DEBUG(HASH, ("Matched entry: %lx\n", pSA));
  1045. RELEASE_LOCK(&g_ipsec.LarvalListLock, kIrql);
  1046. return pSA;
  1047. }
  1048. }
  1049. }
  1050. RELEASE_LOCK(&g_ipsec.LarvalListLock, kIrql);
  1051. return NULL;
  1052. }
  1053. NTSTATUS
  1054. IPSecClassifyPacket(
  1055. IN PUCHAR pHeader,
  1056. IN PVOID pData,
  1057. OUT PSA_TABLE_ENTRY *ppSA,
  1058. OUT PSA_TABLE_ENTRY *ppNextSA,
  1059. OUT USHORT *pFilterFlags,
  1060. #if GPC
  1061. IN CLASSIFICATION_HANDLE GpcHandle,
  1062. #endif
  1063. IN BOOLEAN fOutbound,
  1064. IN BOOLEAN fFWPacket,
  1065. IN BOOLEAN fDoBypassCheck,
  1066. IN UCHAR DestType
  1067. )
  1068. /*++
  1069. Routine Description:
  1070. Classifies the outgoing packet be matching the Src/Dest Address/Ports
  1071. with the filter database to arrive at an IPSEC_CONTEXT which is a set
  1072. of AH/ESP indices into the SA Table.
  1073. Adapted in most part from the Filter Driver.
  1074. Arguments:
  1075. pIPHeader - points to start of IP header.
  1076. pData - points to the data after the IP header.
  1077. ppSA - returns the SA if found.
  1078. pFilterFlags - flags of the filter if found returned here.
  1079. fOutbound - direction flag used in lookups.
  1080. fDoBypassCheck - if TRUE, we bypass port 500 traffic, else we block it.
  1081. Return Value:
  1082. Pointer to IPSEC_CONTEXT if packet matched else NULL
  1083. --*/
  1084. {
  1085. REGISTER UNALIGNED ULARGE_INTEGER *puliSrcDstAddr;
  1086. REGISTER ULARGE_INTEGER uliProtoSrcDstPort;
  1087. UNALIGNED WORD *pwPort;
  1088. PUCHAR pTpt;
  1089. ULONG tptLen;
  1090. REGISTER ULARGE_INTEGER uliAddr;
  1091. REGISTER ULARGE_INTEGER uliPort;
  1092. KIRQL kIrql;
  1093. REGISTER ULONG dwIndex;
  1094. REGISTER PFILTER_CACHE pCache;
  1095. IPHeader UNALIGNED *pIPHeader = (IPHeader UNALIGNED *)pHeader;
  1096. PSA_TABLE_ENTRY pSA = NULL;
  1097. PSA_TABLE_ENTRY pNextSA = NULL;
  1098. PSA_TABLE_ENTRY pTunnelSA = NULL;
  1099. PFILTER pFilter = NULL;
  1100. NTSTATUS status;
  1101. BOOLEAN fBypass;
  1102. PNDIS_BUFFER pTempBuf;
  1103. WORD wTpt[2];
  1104. *ppSA = NULL;
  1105. *ppNextSA = NULL;
  1106. *pFilterFlags = 0;
  1107. wTpt[0] = wTpt[1] = 0;
  1108. //
  1109. // First buffer in pData chain points to start of IP header
  1110. //
  1111. if (fOutbound) {
  1112. if (((pIPHeader->iph_verlen & (UCHAR)~IP_VER_FLAG) << 2) > sizeof(IPHeader)) {
  1113. //
  1114. // Options -> third MDL has Tpt header
  1115. //
  1116. if (!(pTempBuf = IPSEC_NEXT_BUFFER((PNDIS_BUFFER)pData))) {
  1117. ASSERT(FALSE);
  1118. *pFilterFlags |= FILTER_FLAGS_DROP;
  1119. return STATUS_SUCCESS;
  1120. }
  1121. if (!(pTempBuf = IPSEC_NEXT_BUFFER(pTempBuf))) {
  1122. *pFilterFlags |= FILTER_FLAGS_DROP;
  1123. pwPort = (UNALIGNED WORD *) (wTpt);
  1124. }
  1125. else {
  1126. IPSecQueryNdisBuf(pTempBuf, &pTpt, &tptLen);
  1127. pwPort = (UNALIGNED WORD *)(pTpt);
  1128. }
  1129. } else {
  1130. //
  1131. // no options -> second MDL has Tpt header
  1132. //
  1133. if (!(pTempBuf = IPSEC_NEXT_BUFFER((PNDIS_BUFFER)pData))) {
  1134. *pFilterFlags |= FILTER_FLAGS_DROP;
  1135. pwPort = (UNALIGNED WORD *) (wTpt);
  1136. }
  1137. else {
  1138. IPSecQueryNdisBuf(pTempBuf, &pTpt, &tptLen);
  1139. pwPort = (UNALIGNED WORD *)(pTpt);
  1140. }
  1141. }
  1142. } else {
  1143. //
  1144. // inbound side; tpt starts at pData
  1145. //
  1146. IPSecQueryRcvBuf(pData, &pTpt, &tptLen);
  1147. if (pIPHeader->iph_protocol == PROTOCOL_TCP ||
  1148. pIPHeader->iph_protocol == PROTOCOL_UDP) {
  1149. if (tptLen < sizeof(WORD)*2) {
  1150. pwPort = (UNALIGNED WORD *) (wTpt);
  1151. }
  1152. else {
  1153. pwPort = (UNALIGNED WORD *)(pTpt);
  1154. }
  1155. }
  1156. else {
  1157. pwPort = (UNALIGNED WORD *) (wTpt);
  1158. }
  1159. }
  1160. puliSrcDstAddr = (UNALIGNED ULARGE_INTEGER*)(&(pIPHeader->iph_src));
  1161. IPSEC_DEBUG(PARSE, ("Ports: %d.%d\n", pwPort[0], pwPort[1]));
  1162. IPSEC_BUILD_PROTO_PORT_LI( uliProtoSrcDstPort,
  1163. pIPHeader->iph_protocol,
  1164. pwPort[0],
  1165. pwPort[1]);
  1166. #if DBG
  1167. if (IPSecDebug & (IPSEC_DEBUG_PATTERN)) {
  1168. DbgPrint("Addr Large Int: High= %0#8x Low= %0#8x\n",
  1169. puliSrcDstAddr->HighPart,
  1170. puliSrcDstAddr->LowPart);
  1171. DbgPrint("Packet value is Src: %0#8x Dst: %0#8x\n",
  1172. pIPHeader->iph_src,
  1173. pIPHeader->iph_dest);
  1174. DbgPrint("Proto/Port:High= %0#8x Low= %0#8x\n",
  1175. uliProtoSrcDstPort.HighPart,
  1176. uliProtoSrcDstPort.LowPart);
  1177. DbgPrint("Iph is %x\n",pIPHeader);
  1178. DbgPrint("Addr of src is %x\n",&(pIPHeader->iph_src));
  1179. DbgPrint("Ptr to LI is %x\n",puliSrcDstAddr);
  1180. }
  1181. #endif
  1182. //
  1183. // Determine if this is a packet that needs bypass checking
  1184. //
  1185. if (fDoBypassCheck && IPSEC_BYPASS_TRAFFIC() && !IPSEC_FORWARD_PATH()) {
  1186. fBypass = TRUE;
  1187. } else {
  1188. fBypass = FALSE;
  1189. }
  1190. //
  1191. // Sum up the fields and get the cache index. We make sure the sum
  1192. // is assymetric, i.e. a packet from A->B goes to different bucket
  1193. // than one from B->A
  1194. //
  1195. dwIndex = CalcCacheIndex( pIPHeader->iph_src,
  1196. pIPHeader->iph_dest,
  1197. pIPHeader->iph_protocol,
  1198. pwPort[0],
  1199. pwPort[1],
  1200. fOutbound);
  1201. IPSEC_DEBUG(PATTERN, ("Cache Index is %d\n", dwIndex));
  1202. AcquireReadLock(&g_ipsec.SADBLock, &kIrql);
  1203. pCache = g_ipsec.ppCache[dwIndex];
  1204. //
  1205. // Try for a quick cache probe
  1206. //
  1207. if (!(*pFilterFlags & FILTER_FLAGS_DROP) && IS_VALID_CACHE_ENTRY(pCache) &&
  1208. CacheMatch(*puliSrcDstAddr, uliProtoSrcDstPort, pCache)) {
  1209. if (!pCache->FilterEntry) {
  1210. pSA = pCache->pSAEntry;
  1211. pNextSA = pCache->pNextSAEntry;
  1212. ASSERT(pSA->sa_State == STATE_SA_ACTIVE);
  1213. if (fOutbound == (BOOLEAN)((pSA->sa_Flags & FLAGS_SA_OUTBOUND) != 0)) {
  1214. if (fBypass) {
  1215. if (pNextSA) {
  1216. IPSecRefSA(pNextSA);
  1217. *ppSA = pNextSA;
  1218. status = STATUS_SUCCESS;
  1219. } else {
  1220. status = STATUS_UNSUCCESSFUL;
  1221. }
  1222. } else {
  1223. if (pNextSA) {
  1224. IPSecRefSA(pNextSA);
  1225. *ppNextSA = pNextSA;
  1226. }
  1227. IPSecRefSA(pSA);
  1228. *ppSA = pSA;
  1229. status = STATUS_SUCCESS;
  1230. }
  1231. #if DBG
  1232. ADD_TO_LARGE_INTEGER(&pCache->CacheHitCount, 1);
  1233. ADD_TO_LARGE_INTEGER(&g_ipsec.CacheHitCount, 1);
  1234. #endif
  1235. ReleaseReadLock(&g_ipsec.SADBLock, kIrql);
  1236. return status;
  1237. }
  1238. } else if (!fBypass) {
  1239. pFilter = pCache->pFilter;
  1240. ASSERT(IS_EXEMPT_FILTER(pFilter));
  1241. *pFilterFlags = pFilter->Flags;
  1242. #if DBG
  1243. ADD_TO_LARGE_INTEGER(&pCache->CacheHitCount, 1);
  1244. ADD_TO_LARGE_INTEGER(&g_ipsec.CacheHitCount, 1);
  1245. #endif
  1246. ReleaseReadLock(&g_ipsec.SADBLock, kIrql);
  1247. return STATUS_SUCCESS;
  1248. }
  1249. }
  1250. //
  1251. // check the non-manual filters first.
  1252. //
  1253. #if GPC
  1254. if (fBypass || fFWPacket || !IS_GPC_ACTIVE()) {
  1255. status = IPSecLookupSAByAddr( *puliSrcDstAddr,
  1256. uliProtoSrcDstPort,
  1257. &pFilter,
  1258. &pSA,
  1259. &pNextSA,
  1260. &pTunnelSA,
  1261. fOutbound,
  1262. fFWPacket,
  1263. fBypass);
  1264. } else {
  1265. status = IPSecLookupGpcSA( *puliSrcDstAddr,
  1266. uliProtoSrcDstPort,
  1267. GpcHandle,
  1268. &pFilter,
  1269. &pSA,
  1270. &pNextSA,
  1271. &pTunnelSA,
  1272. fOutbound);
  1273. }
  1274. #else
  1275. status = IPSecLookupSAByAddr( *puliSrcDstAddr,
  1276. uliProtoSrcDstPort,
  1277. &pFilter,
  1278. &pSA,
  1279. &pNextSA,
  1280. &pTunnelSA,
  1281. fOutbound,
  1282. fFWPacket,
  1283. fBypass);
  1284. #endif
  1285. //
  1286. // Special Processing for zero length payload packets.
  1287. //
  1288. if (*pFilterFlags & FILTER_FLAGS_DROP) {
  1289. if (pFilter) {
  1290. if (IS_EXEMPT_FILTER(pFilter)) {
  1291. *pFilterFlags = pFilter->Flags;
  1292. }
  1293. }
  1294. else {
  1295. *pFilterFlags = FILTER_FLAGS_PASS_THRU;
  1296. }
  1297. ReleaseReadLock(&g_ipsec.SADBLock, kIrql);
  1298. return STATUS_SUCCESS;
  1299. }
  1300. if (status == STATUS_SUCCESS) {
  1301. if (fBypass) {
  1302. if (pNextSA) {
  1303. if (pNextSA->sa_State == STATE_SA_ACTIVE) {
  1304. IPSecRefSA(pNextSA);
  1305. *ppSA = pNextSA;
  1306. status = STATUS_SUCCESS;
  1307. } else {
  1308. *pFilterFlags = pFilter->Flags;
  1309. status = STATUS_PENDING;
  1310. }
  1311. } else {
  1312. status = STATUS_UNSUCCESSFUL;
  1313. }
  1314. ReleaseReadLock(&g_ipsec.SADBLock, kIrql);
  1315. return status;
  1316. }
  1317. if (pSA->sa_State != STATE_SA_ACTIVE ||
  1318. (pNextSA && pNextSA->sa_State != STATE_SA_ACTIVE)) {
  1319. IPSEC_DEBUG(PATTERN, ("State is not active: %lx, %lx\n", pSA, pSA->sa_State));
  1320. *pFilterFlags = pFilter->Flags;
  1321. ReleaseReadLock(&g_ipsec.SADBLock, kIrql);
  1322. return STATUS_PENDING;
  1323. } else {
  1324. if (pNextSA) {
  1325. IPSecRefSA(pNextSA);
  1326. *ppNextSA = pNextSA;
  1327. }
  1328. IPSecRefSA(pSA);
  1329. *ppSA = pSA;
  1330. ReleaseReadLockFromDpc(&g_ipsec.SADBLock);
  1331. AcquireWriteLockAtDpc(&g_ipsec.SADBLock);
  1332. if (pSA->sa_State == STATE_SA_ACTIVE &&
  1333. (!pNextSA ||
  1334. pNextSA->sa_State == STATE_SA_ACTIVE)) {
  1335. CacheUpdate(*puliSrcDstAddr,
  1336. uliProtoSrcDstPort,
  1337. pSA,
  1338. pNextSA,
  1339. dwIndex,
  1340. FALSE);
  1341. }
  1342. ReleaseWriteLock(&g_ipsec.SADBLock, kIrql);
  1343. return STATUS_SUCCESS;
  1344. }
  1345. } else if (status == STATUS_PENDING) {
  1346. if (IS_EXEMPT_FILTER(pFilter)) {
  1347. IPSEC_DEBUG(PARSE, ("Drop or Pass thru flags: %lx\n", pFilter));
  1348. *pFilterFlags = pFilter->Flags;
  1349. IPSecRefFilter(pFilter);
  1350. ReleaseReadLockFromDpc(&g_ipsec.SADBLock);
  1351. AcquireWriteLockAtDpc(&g_ipsec.SADBLock);
  1352. if (pFilter->LinkedFilter) {
  1353. CacheUpdate(*puliSrcDstAddr,
  1354. uliProtoSrcDstPort,
  1355. pFilter,
  1356. NULL,
  1357. dwIndex,
  1358. TRUE);
  1359. }
  1360. ReleaseWriteLock(&g_ipsec.SADBLock, kIrql);
  1361. IPSecDerefFilter(pFilter);
  1362. return STATUS_SUCCESS;
  1363. }
  1364. //
  1365. // This is ensure that in a tunnel+tpt mode, the oakley packet for
  1366. // the tpt SA goes thru the tunnel.
  1367. //
  1368. if (pTunnelSA) {
  1369. if (fBypass) {
  1370. if (pTunnelSA->sa_State != STATE_SA_ACTIVE) {
  1371. IPSEC_DEBUG(PATTERN, ("State is not active: %lx, %lx\n", pTunnelSA, pTunnelSA->sa_State));
  1372. *pFilterFlags = pFilter->Flags;
  1373. ReleaseReadLock(&g_ipsec.SADBLock, kIrql);
  1374. return STATUS_PENDING;
  1375. } else {
  1376. IPSecRefSA(pTunnelSA);
  1377. *ppSA = pTunnelSA;
  1378. //
  1379. // we dont update the cache since this SA, once it comes up,
  1380. // it is the one that is looked up first.
  1381. //
  1382. ReleaseReadLock(&g_ipsec.SADBLock, kIrql);
  1383. return STATUS_SUCCESS;
  1384. }
  1385. }
  1386. }
  1387. if (fBypass) {
  1388. ReleaseReadLock(&g_ipsec.SADBLock, kIrql);
  1389. return STATUS_UNSUCCESSFUL;
  1390. }
  1391. //
  1392. // We only negotiate outbound SAs.
  1393. //
  1394. if (!fOutbound) {
  1395. *pFilterFlags = pFilter->Flags;
  1396. ReleaseReadLock(&g_ipsec.SADBLock, kIrql);
  1397. return status;
  1398. }
  1399. //
  1400. // need to negotiate the keys - filter exists.
  1401. //
  1402. IPSEC_DEBUG(PATTERN, ("need to negotiate the keys - filter exists: %lx\n", pFilter));
  1403. ASSERT(pSA == NULL);
  1404. IPSecRefFilter(pFilter);
  1405. ReleaseReadLock(&g_ipsec.SADBLock, kIrql);
  1406. AcquireWriteLock(&g_ipsec.SADBLock, &kIrql);
  1407. //
  1408. // If filter is deleted here we want to discard this packet
  1409. //
  1410. if (!pFilter->LinkedFilter) {
  1411. *pFilterFlags = pFilter->Flags;
  1412. IPSecDerefFilter(pFilter);
  1413. ReleaseWriteLock(&g_ipsec.SADBLock, kIrql);
  1414. return STATUS_PENDING;
  1415. }
  1416. status = IPSecNegotiateSA( pFilter,
  1417. *puliSrcDstAddr,
  1418. uliProtoSrcDstPort,
  1419. MAX_LONG,
  1420. &pSA,
  1421. DestType);
  1422. IPSecDerefFilter(pFilter);
  1423. //
  1424. // Duplicate is returned if a neg is already on. Tell the caller to
  1425. // hold on to his horses.
  1426. //
  1427. if ((status != STATUS_DUPLICATE_OBJECTID) &&
  1428. !NT_SUCCESS(status)) {
  1429. IPSEC_DEBUG(PATTERN, ("NegotiateSA failed: %lx\n", status));
  1430. *pFilterFlags = pFilter->Flags;
  1431. ReleaseWriteLock(&g_ipsec.SADBLock, kIrql);
  1432. return STATUS_PENDING;
  1433. }
  1434. //
  1435. // Pend this packet
  1436. //
  1437. if (pSA) {
  1438. IPSecQueuePacket(pSA, pData);
  1439. }
  1440. IPSEC_DEBUG(PATTERN, ("Packet queued: %lx, %lx\n", pSA, pData));
  1441. *pFilterFlags = pFilter->Flags;
  1442. ReleaseWriteLock(&g_ipsec.SADBLock, kIrql);
  1443. return STATUS_PENDING;
  1444. } else {
  1445. ReleaseReadLock(&g_ipsec.SADBLock, kIrql);
  1446. return STATUS_UNSUCCESSFUL;
  1447. }
  1448. }
  1449. VOID
  1450. IPSecSendComplete(
  1451. IN PNDIS_PACKET Packet,
  1452. IN PVOID pData,
  1453. IN PIPSEC_SEND_COMPLETE_CONTEXT pContext,
  1454. IN IP_STATUS Status,
  1455. OUT PVOID *ppNewData
  1456. )
  1457. /*++
  1458. Routine Description:
  1459. Called by the stack on a SendComplete - frees up IPSEC's Mdls
  1460. Arguments:
  1461. pData - points to the data after the IP header. On the send side, this is an MDL chain
  1462. On the recv side this is an IPRcvBuf pointer.
  1463. pContext - send complete context
  1464. pNewData - if packet modified, this points to the new data.
  1465. Return Value:
  1466. STATUS_SUCCESS => Forward - Filter driver passes packet on to IP
  1467. STATUS_PENDING => Drop, IPSEC will re-inject
  1468. Others:
  1469. STATUS_INSUFFICIENT_RESOURCES => Drop
  1470. STATUS_UNSUCCESSFUL (error in algo./bad packet received) => Drop
  1471. --*/
  1472. {
  1473. NTSTATUS status;
  1474. PNDIS_BUFFER pMdl;
  1475. PNDIS_BUFFER pNextMdl;
  1476. BOOLEAN fFreeContext = TRUE;
  1477. *ppNewData = pData;
  1478. if (!pContext) {
  1479. return;
  1480. }
  1481. #if DBG
  1482. IPSEC_DEBUG(MDL, ("Entering IPSecSendComplete\n"));
  1483. IPSEC_PRINT_CONTEXT(pContext);
  1484. IPSEC_PRINT_MDL(*ppNewData);
  1485. #endif
  1486. if (pContext->Flags & SCF_PKTINFO) {
  1487. IPSecFreePktInfo(pContext->PktInfo);
  1488. if (pContext->pSA) {
  1489. KIRQL kIrql;
  1490. PSA_TABLE_ENTRY pSA;
  1491. AcquireWriteLock(&g_ipsec.SADBLock, &kIrql);
  1492. pSA = (PSA_TABLE_ENTRY)pContext->pSA;
  1493. IPSEC_DECREMENT(pSA->sa_NumSends);
  1494. if (pSA->sa_Flags & FLAGS_SA_HW_DELETE_SA) {
  1495. IPSecDelHWSAAtDpc(pSA);
  1496. }
  1497. IPSecDerefSA(pSA);
  1498. pSA = (PSA_TABLE_ENTRY)pContext->pNextSA;
  1499. if (pSA) {
  1500. IPSEC_DECREMENT(pSA->sa_NumSends);
  1501. if (pSA->sa_Flags & FLAGS_SA_HW_DELETE_SA) {
  1502. IPSecDelHWSAAtDpc(pSA);
  1503. }
  1504. IPSecDerefSA(pSA);
  1505. }
  1506. ReleaseWriteLock(&g_ipsec.SADBLock, kIrql);
  1507. }
  1508. }
  1509. if (pContext->Flags & SCF_PKTEXT) {
  1510. IPSecFreePktExt(pContext->PktExt);
  1511. }
  1512. if (pContext->Flags & SCF_AH_2) {
  1513. IPSEC_DEBUG(SEND, ("SendComplete: Outer AH: pContext: %lx\n", pContext));
  1514. pMdl = pContext->AHMdl2;
  1515. ASSERT(pMdl);
  1516. IPSecFreeBuffer(&status, pMdl);
  1517. //
  1518. // return the older chain
  1519. //
  1520. if (pContext->Flags & SCF_FLUSH) {
  1521. NDIS_BUFFER_LINKAGE(pContext->PrevAHMdl2) = pContext->OriAHMdl2;
  1522. } else if (!(pContext->Flags & SCF_FRAG)) {
  1523. NDIS_BUFFER_LINKAGE(pContext->PrevAHMdl2) = pContext->OriAHMdl2;
  1524. // *ppNewData = (PVOID)(pContext->PrevMdl);
  1525. }
  1526. pContext->OriAHMdl2 = NULL;
  1527. }
  1528. if (pContext->Flags & SCF_AH_TU) {
  1529. IPSEC_DEBUG(SEND, ("SendComplete: AH_TU: pContext: %lx\n", pContext));
  1530. //
  1531. // Free the new IP header and the AH buffer and return the old chain
  1532. //
  1533. pMdl = pContext->AHTuMdl;
  1534. ASSERT(pMdl);
  1535. pNextMdl = NDIS_BUFFER_LINKAGE(pMdl);
  1536. IPSecFreeBuffer(&status, pMdl);
  1537. IPSecFreeBuffer(&status, pNextMdl);
  1538. //
  1539. // return the older chain
  1540. //
  1541. if (pContext->Flags & SCF_FLUSH) {
  1542. NDIS_BUFFER_LINKAGE(pContext->PrevTuMdl) = pContext->OriTuMdl;
  1543. } else if (!(pContext->Flags & SCF_FRAG)) {
  1544. NDIS_BUFFER_LINKAGE(pContext->PrevTuMdl) = pContext->OriTuMdl;
  1545. }
  1546. if (pContext->OptMdl) {
  1547. IPSecFreeBuffer(&status, pContext->OptMdl);
  1548. }
  1549. }
  1550. if (pContext->Flags & SCF_HU_TU) {
  1551. IPSEC_DEBUG(SEND, ("SendComplete: HU_TU: pContext: %lx\n", pContext));
  1552. //
  1553. // Free the encrypt chain and return the old chain
  1554. //
  1555. pMdl = pContext->HUTuMdl;
  1556. ASSERT(pMdl);
  1557. //
  1558. // In none case, free the esp header and the IP header.
  1559. //
  1560. if (pContext->Flags & SCF_NOE_TU) {
  1561. IPSecFreeBuffer(&status, pMdl);
  1562. ASSERT(pContext->PadTuMdl);
  1563. } else {
  1564. ASSERT(NDIS_BUFFER_LINKAGE(pMdl));
  1565. while (pMdl) {
  1566. pNextMdl = NDIS_BUFFER_LINKAGE(pMdl);
  1567. IPSecFreeBuffer(&status, pMdl);
  1568. pMdl = pNextMdl;
  1569. }
  1570. }
  1571. //
  1572. // Free the Pad mdl
  1573. //
  1574. if (pContext->PadTuMdl) {
  1575. IPSecFreeBuffer(&status, pContext->PadTuMdl);
  1576. }
  1577. if (pContext->HUHdrMdl) {
  1578. IPSecFreeBuffer(&status, pContext->HUHdrMdl);
  1579. }
  1580. if (pContext->OptMdl) {
  1581. IPSecFreeBuffer(&status, pContext->OptMdl);
  1582. }
  1583. NDIS_BUFFER_LINKAGE(pContext->BeforePadTuMdl) = NULL;
  1584. //
  1585. // return the older chain
  1586. //
  1587. if (pContext->Flags & SCF_FLUSH) {
  1588. NDIS_BUFFER_LINKAGE(pContext->PrevTuMdl) = pContext->OriTuMdl;
  1589. } else if (!(pContext->Flags & SCF_FRAG)) {
  1590. NDIS_BUFFER_LINKAGE(pContext->PrevTuMdl) = pContext->OriTuMdl;
  1591. }
  1592. }
  1593. if (pContext->Flags & SCF_AH) {
  1594. IPSEC_DEBUG(SEND, ("SendComplete: AH: pContext: %lx\n", pContext));
  1595. pMdl = pContext->AHMdl;
  1596. ASSERT(pMdl);
  1597. IPSecFreeBuffer(&status, pMdl);
  1598. //
  1599. // return the older chain
  1600. //
  1601. if (pContext->Flags & SCF_FLUSH) {
  1602. NDIS_BUFFER_LINKAGE(pContext->PrevMdl) = pContext->OriAHMdl;
  1603. } else if (!(pContext->Flags & SCF_FRAG)) {
  1604. NDIS_BUFFER_LINKAGE(pContext->PrevMdl) = pContext->OriAHMdl;
  1605. // *ppNewData = (PVOID)(pContext->PrevMdl);
  1606. }
  1607. pContext->OriAHMdl = NULL;
  1608. }
  1609. if (pContext->Flags & SCF_HU_TPT) {
  1610. IPSEC_DEBUG(SEND, ("SendComplete: HU_TPT: pContext: %lx\n", pContext));
  1611. //
  1612. // Hook the older chain into the first buffer
  1613. //
  1614. if (pContext->Flags & SCF_FLUSH) {
  1615. NDIS_BUFFER_LINKAGE(pContext->PrevMdl) = pContext->OriHUMdl;
  1616. } else if (!(pContext->Flags & SCF_FRAG)) {
  1617. NDIS_BUFFER_LINKAGE(pContext->PrevMdl) = pContext->OriHUMdl;
  1618. }
  1619. //
  1620. // Free the encryption buffer chain
  1621. //
  1622. pMdl = pContext->HUMdl;
  1623. ASSERT(pMdl);
  1624. //
  1625. // In none case, free the esp header.
  1626. //
  1627. if (pContext->Flags & SCF_NOE_TPT) {
  1628. IPSecFreeBuffer(&status, pMdl);
  1629. ASSERT(pContext->PadMdl);
  1630. } else {
  1631. ASSERT(NDIS_BUFFER_LINKAGE(pMdl));
  1632. while (pMdl) {
  1633. pNextMdl = NDIS_BUFFER_LINKAGE(pMdl);
  1634. IPSecFreeBuffer(&status, pMdl);
  1635. pMdl = pNextMdl;
  1636. }
  1637. }
  1638. //
  1639. // Free the Pad mdl and zero the reference to the pad mdl in the
  1640. // previous (payload) mdl.
  1641. //
  1642. if (pContext->PadMdl) {
  1643. IPSecFreeBuffer(&status, pContext->PadMdl);
  1644. }
  1645. NDIS_BUFFER_LINKAGE(pContext->BeforePadMdl) = NULL;
  1646. }
  1647. //
  1648. // these are freed in IPSecProtocolSendComplete now.
  1649. //
  1650. if (Packet && (pContext->Flags & SCF_FLUSH)) {
  1651. IPSEC_DEBUG(SEND, ("SendComplete: FLUSH: pContext: %lx\n", pContext));
  1652. //
  1653. // Free the encrypt chain and return the old chain
  1654. //
  1655. pMdl = pContext->FlushMdl;
  1656. ASSERT(pMdl);
  1657. //
  1658. // We will be called at ProtocolSendComplete, where we free this chain.
  1659. //
  1660. fFreeContext = FALSE;
  1661. //
  1662. // If this was just a reinjected packet and never IPSEC'ed, then we know
  1663. // that all the buffers are in line - call the ProtocolSendComplete here
  1664. // and NULL the returned buffer.
  1665. //
  1666. // The best way to do this is to do the same trick we apply on fragmented
  1667. // packets (see IPTransmit) viz. attaching another header and 0'ing out
  1668. // the IPSEC header. There is obviously a perf hit when attaching another IP
  1669. // header since we alloc new MDLs, etc. Hence, we take the approach of using
  1670. // the header in the IPSEC buffers directly.
  1671. //
  1672. // So, here we see if the packet was fragmented; in which case, we let
  1673. // ProtocolSendComplete do the freeing. Else, we free the buffers ourselves.
  1674. //
  1675. {
  1676. PacketContext *PContext = (PacketContext *)Packet->ProtocolReserved;
  1677. if (PContext->pc_br == NULL ||
  1678. (PContext->pc_ipsec_flags & IPSEC_FLAG_FLUSH)) {
  1679. //
  1680. // this will also free the context.
  1681. //
  1682. IPSecProtocolSendComplete(pContext, pMdl, IP_SUCCESS);
  1683. *ppNewData = NULL;
  1684. }
  1685. }
  1686. } else if (!Packet && (pContext->Flags & SCF_FLUSH)) {
  1687. //
  1688. // ProtocolSendComplete will be called next in IPFragment.
  1689. //
  1690. fFreeContext = FALSE;
  1691. }
  1692. //
  1693. // If context not needed anymore, free it now.
  1694. //
  1695. if (fFreeContext) {
  1696. IPSecFreeSendCompleteCtx(pContext);
  1697. }
  1698. #if DBG
  1699. IPSEC_DEBUG(MDL, ("Exiting IPSecSendComplete\n"));
  1700. IPSEC_PRINT_CONTEXT(pContext);
  1701. IPSEC_PRINT_MDL(*ppNewData);
  1702. #endif
  1703. }
  1704. VOID
  1705. IPSecProtocolSendComplete (
  1706. IN PVOID pContext,
  1707. IN PNDIS_BUFFER pMdl,
  1708. IN IP_STATUS Status
  1709. )
  1710. /*++
  1711. Routine Description:
  1712. Called by the stack on a SendComplete - frees up IPSEC's Mdls.
  1713. This is only called when IPSEC injects packets into the stack.
  1714. Arguments:
  1715. pMdl - points to the data after the IP header. On the send side, this is an MDL chain
  1716. On the recv side this is an IPRcvBuf pointer.
  1717. Return Value:
  1718. STATUS_SUCCESS => Forward - Filter driver passes packet on to IP
  1719. STATUS_PENDING => Drop, IPSEC will re-inject
  1720. Others:
  1721. STATUS_INSUFFICIENT_RESOURCES => Drop
  1722. STATUS_UNSUCCESSFUL (error in algo./bad packet received) => Drop
  1723. --*/
  1724. {
  1725. PNDIS_BUFFER pNextMdl;
  1726. NTSTATUS status;
  1727. PIPSEC_SEND_COMPLETE_CONTEXT pSCContext = (PIPSEC_SEND_COMPLETE_CONTEXT)pContext;
  1728. if (!pSCContext->Flags) {
  1729. return;
  1730. }
  1731. ASSERT(pMdl);
  1732. while (pMdl) {
  1733. pNextMdl = NDIS_BUFFER_LINKAGE(pMdl);
  1734. IPSecFreeBuffer(&status, pMdl);
  1735. pMdl = pNextMdl;
  1736. }
  1737. IPSecFreeSendCompleteCtx(pSCContext);
  1738. return;
  1739. }
  1740. NTSTATUS
  1741. IPSecChkReplayWindow(
  1742. IN ULONG Seq,
  1743. IN PSA_TABLE_ENTRY pSA,
  1744. IN ULONG Index
  1745. )
  1746. /*++
  1747. Routine Description:
  1748. Checks if the received packet is in the received window to prevent against
  1749. replay attacks.
  1750. We keep track of the last Sequence number received and ensure that the
  1751. received packets is within the packet window (currently 32 packets).
  1752. Arguments:
  1753. Seq - received Sequence number
  1754. pSA - points to the security association
  1755. Return Value:
  1756. STATUS_SUCCESS => packet in window
  1757. STATUS_UNSUCCESSFUL => packet rejected
  1758. --*/
  1759. {
  1760. ULONG diff;
  1761. ULONG ReplayWindowSize = REPLAY_WINDOW_SIZE;
  1762. ULONG lastSeq = pSA->sa_ReplayLastSeq[Index];
  1763. ULONGLONG bitmap = pSA->sa_ReplayBitmap[Index];
  1764. ULONGLONG dbgbitmap = bitmap;
  1765. if (pSA->sa_Flags & FLAGS_SA_DISABLE_ANTI_REPLAY_CHECK) {
  1766. return STATUS_SUCCESS;
  1767. }
  1768. if (Seq == pSA->sa_ReplayStartPoint) {
  1769. //
  1770. // first == 0 or wrapped
  1771. //
  1772. IPSEC_DEBUG(SEND, ("Replay: out @1 - Seq: %lx, pSA->sa_ReplayStartPoint: %lx\n",
  1773. Seq, pSA->sa_ReplayStartPoint));
  1774. return IPSEC_INVALID_REPLAY_WINDOW1;
  1775. }
  1776. #if DBG
  1777. IPSEC_DEBUG(SEND, ("Replay: Last Seq.: %lx, Cur Seq.: %lx, window size %d & bit window (in nibbles) %08lx%08lx\n",
  1778. lastSeq, Seq, sizeof(bitmap)*8, (ULONG) (dbgbitmap >> 32), (ULONG) dbgbitmap));
  1779. #endif
  1780. //
  1781. // new larger Sequence number
  1782. //
  1783. if (Seq > lastSeq) {
  1784. diff = Seq - lastSeq;
  1785. if (diff < ReplayWindowSize) {
  1786. //
  1787. // In window
  1788. // set bit for this packet
  1789. bitmap = (bitmap << diff) | 1;
  1790. } else {
  1791. //
  1792. // This packet has a "way larger" Seq
  1793. //
  1794. bitmap = 1;
  1795. }
  1796. lastSeq = Seq;
  1797. pSA->sa_ReplayLastSeq[Index] = lastSeq;
  1798. pSA->sa_ReplayBitmap[Index] = bitmap;
  1799. //
  1800. // larger is good
  1801. //
  1802. return STATUS_SUCCESS;
  1803. }
  1804. diff = lastSeq - Seq;
  1805. if (diff >= ReplayWindowSize) {
  1806. //
  1807. // too old or wrapped
  1808. //
  1809. IPSEC_DEBUG(SEND, ("Replay: out @3 - Seq: %lx, lastSeq: %lx\n",
  1810. Seq, lastSeq));
  1811. return IPSEC_INVALID_REPLAY_WINDOW2;
  1812. }
  1813. if (bitmap & (1l << diff)) {
  1814. //
  1815. // this packet already seen
  1816. //
  1817. IPSEC_DEBUG(SEND, ("Replay: out @4 - Seq: %lx, lastSeq: %lx\n",
  1818. Seq, lastSeq));
  1819. return IPSEC_DUPE_PACKET;
  1820. }
  1821. //
  1822. // mark as seen
  1823. //
  1824. bitmap |= (1l << diff);
  1825. pSA->sa_ReplayLastSeq[Index] = lastSeq;
  1826. pSA->sa_ReplayBitmap[Index] = bitmap;
  1827. //
  1828. // out of order but good
  1829. //
  1830. return STATUS_SUCCESS;
  1831. }
  1832. NTSTATUS
  1833. IPSecReinjectPacket(
  1834. IN PVOID pData,
  1835. IN PNDIS_PACKET_EXTENSION pPktExt
  1836. )
  1837. /*++
  1838. Routine Description:
  1839. Re-injects packet into the stack's send path - makes a copy
  1840. of the packet then calls into IPTransmit, making sure the SendComplete
  1841. Context is setup properly.
  1842. Arguments:
  1843. pData - Points to "un-tunneled" data, starting at the encapsulated IP header
  1844. pPktExt - Points to the NDIS Packet extension structure
  1845. Return Value:
  1846. Status of copy/transmit operation
  1847. --*/
  1848. {
  1849. IPOptInfo optInfo;
  1850. PNDIS_BUFFER pOptMdl;
  1851. PNDIS_BUFFER pHdrMdl;
  1852. PNDIS_BUFFER pDataMdl;
  1853. ULONG len;
  1854. ULONG len1;
  1855. ULONG hdrLen;
  1856. IPRcvBuf *pNextData;
  1857. IPHeader UNALIGNED * pIPH;
  1858. IPHeader UNALIGNED * pIPH1;
  1859. ULONG offset;
  1860. NTSTATUS status;
  1861. ULONG tag = IPSEC_TAG_REINJECT;
  1862. PIPSEC_SEND_COMPLETE_CONTEXT pContext;
  1863. NDIS_PACKET_EXTENSION PktExt = {0};
  1864. PNDIS_IPSEC_PACKET_INFO IPSecPktInfo;
  1865. //
  1866. // Allocate context for IPSecSencComplete use
  1867. //
  1868. pContext = IPSecAllocateSendCompleteCtx(tag);
  1869. if (!pContext) {
  1870. IPSEC_DEBUG(ESP, ("Failed to alloc. SendCtx\n"));
  1871. return STATUS_INSUFFICIENT_RESOURCES;
  1872. }
  1873. IPSEC_INCREMENT(g_ipsec.NumSends);
  1874. IPSecZeroMemory(pContext, sizeof(IPSEC_SEND_COMPLETE_CONTEXT));
  1875. #if DBG
  1876. RtlCopyMemory(pContext->Signature, "ISC5", 4);
  1877. #endif
  1878. //
  1879. // Pass along IPSEC_PKT_INFO for transport offload if needed
  1880. //
  1881. if (pPktExt) {
  1882. IPSecPktInfo = pPktExt->NdisPacketInfo[IpSecPacketInfo];
  1883. if (IPSecPktInfo) {
  1884. ASSERT(IPSecPktInfo->Receive.CryptoStatus == CRYPTO_SUCCESS);
  1885. ASSERT(IPSecPktInfo->Receive.CRYPTO_DONE);
  1886. //
  1887. // Only interested in NEXT_CRYPTO_DONE if packet is reinjected.
  1888. //
  1889. if (!(IPSecPktInfo->Receive.NEXT_CRYPTO_DONE)) {
  1890. IPSecPktInfo = NULL;
  1891. }
  1892. }
  1893. } else {
  1894. IPSecPktInfo = NULL;
  1895. }
  1896. if (IPSecPktInfo) {
  1897. //
  1898. // Pass the IPSecPktInfo to IPTransmit.
  1899. //
  1900. pContext->PktExt = IPSecAllocatePktExt(IPSEC_TAG_HW_PKTEXT);
  1901. if (!pContext->PktExt) {
  1902. IPSEC_DEBUG(ESP, ("Failed to alloc. PktInfo\n"));
  1903. IPSecFreeSendCompleteCtx(pContext);
  1904. return STATUS_INSUFFICIENT_RESOURCES;
  1905. }
  1906. pContext->Flags |= SCF_PKTEXT;
  1907. RtlCopyMemory( pContext->PktExt,
  1908. IPSecPktInfo,
  1909. sizeof(NDIS_IPSEC_PACKET_INFO));
  1910. PktExt.NdisPacketInfo[IpSecPacketInfo] = (PNDIS_IPSEC_PACKET_INFO)(pContext->PktExt);
  1911. }
  1912. //
  1913. // Re-package into MDLs for the send - these will be released on the
  1914. // SendComplete.
  1915. //
  1916. // FUTURE WORK: right now we copy the data out, this shd be optimized
  1917. // by calling IPRcvPacket and using buffer ownership.
  1918. //
  1919. IPSEC_GET_TOTAL_LEN_RCV_BUF(pData, &len);
  1920. //
  1921. // IPH is at head of pData
  1922. //
  1923. IPSecQueryRcvBuf(pData, (PVOID)&pIPH, &len1);
  1924. //
  1925. // Allocate MDL for the IP header
  1926. //
  1927. hdrLen = (pIPH->iph_verlen & (UCHAR)~IP_VER_FLAG) << 2;
  1928. if (len <= hdrLen) {
  1929. IPSEC_DEBUG(ESP, ("TotLen of the buffers %d <= hdrLen %d\n", len, hdrLen));
  1930. if (pContext->PktExt) {
  1931. IPSecFreeMemory(pContext->PktExt);
  1932. }
  1933. IPSecFreeSendCompleteCtx(pContext);
  1934. return STATUS_INVALID_PARAMETER;
  1935. }
  1936. IPSecAllocateBuffer(&status,
  1937. &pHdrMdl,
  1938. (PUCHAR *)&pIPH1,
  1939. sizeof(IPHeader),
  1940. tag);
  1941. if (!NT_SUCCESS(status)) {
  1942. IPSEC_DEBUG(ESP, ("Failed to alloc. header MDL\n"));
  1943. if (pContext->PktExt) {
  1944. IPSecFreeMemory(pContext->PktExt);
  1945. }
  1946. IPSecFreeSendCompleteCtx(pContext);
  1947. return status;
  1948. }
  1949. //
  1950. // Copy over the header
  1951. //
  1952. RtlCopyMemory(pIPH1, pIPH, sizeof(IPHeader));
  1953. len -= hdrLen;
  1954. offset = hdrLen;
  1955. IPSecAllocateBuffer(&status,
  1956. &pDataMdl,
  1957. NULL,
  1958. len,
  1959. tag);
  1960. if (!NT_SUCCESS(status)) {
  1961. NTSTATUS ntstatus;
  1962. IPSEC_DEBUG(ESP, ("Failed to alloc. encrypt MDL\n"));
  1963. IPSecFreeBuffer(&ntstatus, pHdrMdl);
  1964. if (pContext->PktExt) {
  1965. IPSecFreeMemory(pContext->PktExt);
  1966. }
  1967. IPSecFreeSendCompleteCtx(pContext);
  1968. return status;
  1969. }
  1970. if (hdrLen > sizeof(IPHeader)) {
  1971. PUCHAR Options;
  1972. PUCHAR pOpt;
  1973. //
  1974. // Options present - another Mdl
  1975. //
  1976. IPSecAllocateBuffer(&status,
  1977. &pOptMdl,
  1978. &Options,
  1979. hdrLen - sizeof(IPHeader),
  1980. tag);
  1981. if (!NT_SUCCESS(status)) {
  1982. NTSTATUS ntstatus;
  1983. IPSecFreeBuffer(&ntstatus, pHdrMdl);
  1984. IPSecFreeBuffer(&ntstatus, pDataMdl);
  1985. if (pContext->PktExt) {
  1986. IPSecFreeMemory(pContext->PktExt);
  1987. }
  1988. IPSecFreeSendCompleteCtx(pContext);
  1989. IPSEC_DEBUG(ESP, ("Failed to alloc. options MDL\n"));
  1990. return status;
  1991. }
  1992. //
  1993. // Copy over the options - we need to fish for it - could be in next MDL
  1994. //
  1995. if (len1 >= hdrLen) {
  1996. //
  1997. // all in this buffer - jump over IP header
  1998. //
  1999. RtlCopyMemory(Options, (PUCHAR)(pIPH + 1), hdrLen - sizeof(IPHeader));
  2000. } else {
  2001. //
  2002. // next buffer, copy from next
  2003. //
  2004. pData = IPSEC_BUFFER_LINKAGE(pData);
  2005. IPSecQueryRcvBuf(pData, (PVOID)&pOpt, &len1);
  2006. RtlCopyMemory(Options, pOpt, hdrLen - sizeof(IPHeader));
  2007. offset = hdrLen - sizeof(IPHeader);
  2008. }
  2009. //
  2010. // Link in the Options buffer
  2011. //
  2012. NDIS_BUFFER_LINKAGE(pHdrMdl) = pOptMdl;
  2013. NDIS_BUFFER_LINKAGE(pOptMdl) = pDataMdl;
  2014. } else {
  2015. //
  2016. // Link in the Data buffer
  2017. //
  2018. NDIS_BUFFER_LINKAGE(pHdrMdl) = pDataMdl;
  2019. }
  2020. //
  2021. // Now bulk copy the entire data
  2022. //
  2023. IPSEC_COPY_FROM_RCVBUF( pDataMdl,
  2024. pData,
  2025. len,
  2026. offset);
  2027. //
  2028. // Fill up the SendCompleteContext
  2029. //
  2030. pContext->FlushMdl = pHdrMdl;
  2031. pContext->Flags |= SCF_FLUSH;
  2032. //
  2033. // Call IPTransmit with proper Protocol type so it takes this packet
  2034. // at *face* value.
  2035. //
  2036. optInfo = g_ipsec.OptInfo;
  2037. optInfo.ioi_options = (PUCHAR)&PktExt;
  2038. optInfo.ioi_flags |= IP_FLAG_IPSEC;
  2039. status = TCPIP_IP_TRANSMIT( &g_ipsec.IPProtInfo,
  2040. pContext,
  2041. pHdrMdl,
  2042. len,
  2043. pIPH->iph_dest,
  2044. pIPH->iph_src,
  2045. &optInfo,
  2046. NULL,
  2047. pIPH->iph_protocol,
  2048. NULL);
  2049. //
  2050. // IPTransmit may fail to allocate a Packet so it returns
  2051. // IP_NO_RESOURCES. If this is the case, we need to free the MDL chain.
  2052. // This is taken care of in IPTransmit().
  2053. //
  2054. // Even in the synchronous case, we free the MDL chain in ProtocolSendComplete (called by IPSecSendComplete).
  2055. // So, we dont call anything here.
  2056. //
  2057. return STATUS_SUCCESS;
  2058. }
  2059. NTSTATUS
  2060. IPSecQueuePacket(
  2061. IN PSA_TABLE_ENTRY pSA,
  2062. IN PVOID pDataBuf
  2063. )
  2064. /*++
  2065. Routine Description:
  2066. Copies the packet into the SAs Stall Queue.
  2067. Arguments:
  2068. Return Value:
  2069. --*/
  2070. {
  2071. ULONG len;
  2072. ULONG len1;
  2073. PNDIS_BUFFER pOptMdl;
  2074. PNDIS_BUFFER pHdrMdl;
  2075. PNDIS_BUFFER pDataMdl;
  2076. KIRQL kIrql;
  2077. ULONG hdrLen;
  2078. IPHeader UNALIGNED * pIPH;
  2079. IPHeader UNALIGNED * pIPH1;
  2080. NTSTATUS status;
  2081. ULONG offset;
  2082. ULONG tag = IPSEC_TAG_STALL_QUEUE;
  2083. PNDIS_BUFFER pData = (PNDIS_BUFFER)pDataBuf;
  2084. //
  2085. // Queue last packet so if we already have one free it first.
  2086. //
  2087. if (pSA->sa_BlockedBuffer != NULL) {
  2088. IPSecFlushQueuedPackets(pSA, STATUS_ABANDONED);
  2089. }
  2090. ACQUIRE_LOCK(&pSA->sa_Lock, &kIrql);
  2091. //
  2092. // Need a lock here - sa_Lock.
  2093. //
  2094. if (pSA->sa_State == STATE_SA_LARVAL) {
  2095. IPSEC_DEBUG(ACQUIRE, ("Pending packet: %lx\n", pSA));
  2096. //
  2097. // Copy over the Mdl chain to this SAs pend queue.
  2098. //
  2099. IPSEC_GET_TOTAL_LEN(pData, &len);
  2100. //
  2101. // IPH is at head of pData
  2102. //
  2103. IPSecQueryNdisBuf(pData, &pIPH, &len1);
  2104. hdrLen = (pIPH->iph_verlen & (UCHAR)~IP_VER_FLAG) << 2;
  2105. IPSecAllocateBuffer(&status,
  2106. &pHdrMdl,
  2107. (PUCHAR *)&pIPH1,
  2108. sizeof(IPHeader),
  2109. tag);
  2110. if (!NT_SUCCESS(status)) {
  2111. NTSTATUS ntstatus;
  2112. IPSEC_DEBUG(ESP, ("Failed to alloc. header MDL\n"));
  2113. RELEASE_LOCK(&pSA->sa_Lock, kIrql);
  2114. return status;
  2115. }
  2116. IPSEC_DEBUG(POOL, ("IPSecQueuePacket: pHdrMdl: %lx, pIPH1: %lx\n", pHdrMdl, pIPH1));
  2117. //
  2118. // Copy over the header
  2119. //
  2120. RtlCopyMemory(pIPH1, pIPH, sizeof(IPHeader));
  2121. len -= hdrLen;
  2122. offset = hdrLen;
  2123. IPSecAllocateBuffer(&status,
  2124. &pDataMdl,
  2125. NULL,
  2126. len,
  2127. tag);
  2128. if (!NT_SUCCESS(status)) {
  2129. NTSTATUS ntstatus;
  2130. IPSEC_DEBUG(ESP, ("Failed to alloc. encrypt MDL\n"));
  2131. IPSecFreeBuffer(&status, pHdrMdl);
  2132. RELEASE_LOCK(&pSA->sa_Lock, kIrql);
  2133. return status;
  2134. }
  2135. if (hdrLen > sizeof(IPHeader)) {
  2136. PUCHAR Options;
  2137. PUCHAR pOpt;
  2138. //
  2139. // Options present - another Mdl
  2140. //
  2141. IPSecAllocateBuffer(&status,
  2142. &pOptMdl,
  2143. &Options,
  2144. hdrLen - sizeof(IPHeader),
  2145. tag);
  2146. if (!NT_SUCCESS(status)) {
  2147. IPSecFreeBuffer(&status, pHdrMdl);
  2148. IPSecFreeBuffer(&status, pDataMdl);
  2149. IPSEC_DEBUG(ESP, ("Failed to alloc. options MDL\n"));
  2150. RELEASE_LOCK(&pSA->sa_Lock, kIrql);
  2151. return status;
  2152. }
  2153. //
  2154. // Copy over the options - we need to fish for it - could be in next MDL
  2155. //
  2156. if (len1 >= hdrLen) {
  2157. //
  2158. // all in this buffer - jump over IP header
  2159. //
  2160. RtlCopyMemory(Options, (PUCHAR)(pIPH + 1), hdrLen - sizeof(IPHeader));
  2161. } else {
  2162. //
  2163. // next buffer, copy from next
  2164. //
  2165. pData = NDIS_BUFFER_LINKAGE(pData);
  2166. IPSecQueryNdisBuf(pData, &pOpt, &len1);
  2167. RtlCopyMemory(Options, pOpt, hdrLen - sizeof(IPHeader));
  2168. offset = hdrLen - sizeof(IPHeader);
  2169. }
  2170. //
  2171. // Link in the Options buffer
  2172. //
  2173. NDIS_BUFFER_LINKAGE(pHdrMdl) = pOptMdl;
  2174. NDIS_BUFFER_LINKAGE(pOptMdl) = pDataMdl;
  2175. } else {
  2176. //
  2177. // Link in the Data buffer
  2178. //
  2179. NDIS_BUFFER_LINKAGE(pHdrMdl) = pDataMdl;
  2180. }
  2181. //
  2182. // Now bulk copy the entire data
  2183. //
  2184. IPSEC_COPY_FROM_NDISBUF(pDataMdl,
  2185. pData,
  2186. len,
  2187. offset);
  2188. pSA->sa_BlockedBuffer = pHdrMdl;
  2189. pSA->sa_BlockedDataLen = len;
  2190. IPSEC_DEBUG(ACQUIRE, ("Queued buffer: %lx on SA: %lx, psa->sa_BlockedBuffer: %lx\n", pHdrMdl, pSA, &pSA->sa_BlockedBuffer));
  2191. }
  2192. RELEASE_LOCK(&pSA->sa_Lock, kIrql);
  2193. return STATUS_SUCCESS;
  2194. }
  2195. VOID
  2196. IPSecIPAddrToUnicodeString(
  2197. IN IPAddr Addr,
  2198. OUT PWCHAR UCIPAddrBuffer
  2199. )
  2200. /*++
  2201. Routine Description:
  2202. Converts an IP addr into a wchar string
  2203. Arguments:
  2204. Return Value:
  2205. --*/
  2206. {
  2207. UINT IPAddrCharCount=0;
  2208. UINT i;
  2209. UCHAR IPAddrBuffer[(sizeof(IPAddr) * 4)];
  2210. UNICODE_STRING unicodeString;
  2211. ANSI_STRING ansiString;
  2212. //
  2213. // Convert the IP address into a string.
  2214. //
  2215. for (i = 0; i < sizeof(IPAddr); i++) {
  2216. UINT CurrentByte;
  2217. CurrentByte = Addr & 0xff;
  2218. if (CurrentByte > 99) {
  2219. IPAddrBuffer[IPAddrCharCount++] = (CurrentByte / 100) + '0';
  2220. CurrentByte %= 100;
  2221. IPAddrBuffer[IPAddrCharCount++] = (CurrentByte / 10) + '0';
  2222. CurrentByte %= 10;
  2223. } else if (CurrentByte > 9) {
  2224. IPAddrBuffer[IPAddrCharCount++] = (CurrentByte / 10) + '0';
  2225. CurrentByte %= 10;
  2226. }
  2227. IPAddrBuffer[IPAddrCharCount++] = CurrentByte + '0';
  2228. if (i != (sizeof(IPAddr) - 1))
  2229. IPAddrBuffer[IPAddrCharCount++] = '.';
  2230. Addr >>= 8;
  2231. }
  2232. //
  2233. // Unicode the strings.
  2234. //
  2235. *UCIPAddrBuffer = UNICODE_NULL;
  2236. unicodeString.Buffer = UCIPAddrBuffer;
  2237. unicodeString.Length = 0;
  2238. unicodeString.MaximumLength =
  2239. (USHORT)(sizeof(WCHAR) * ((sizeof(IPAddr) * 4) + 1));
  2240. ansiString.Buffer = IPAddrBuffer;
  2241. ansiString.Length = (USHORT)IPAddrCharCount;
  2242. ansiString.MaximumLength = (USHORT)IPAddrCharCount;
  2243. RtlAnsiStringToUnicodeString( &unicodeString,
  2244. &ansiString,
  2245. FALSE);
  2246. }
  2247. VOID
  2248. IPSecCountToUnicodeString(
  2249. IN ULONG Count,
  2250. OUT PWCHAR UCCountBuffer
  2251. )
  2252. /*++
  2253. Routine Description:
  2254. Converts a count a wchar string
  2255. Arguments:
  2256. Return Value:
  2257. --*/
  2258. {
  2259. UNICODE_STRING unicodeString;
  2260. //
  2261. // Unicode the strings.
  2262. //
  2263. *UCCountBuffer = UNICODE_NULL;
  2264. unicodeString.Buffer = UCCountBuffer;
  2265. unicodeString.Length = 0;
  2266. unicodeString.MaximumLength = (USHORT)sizeof(WCHAR) * (MAX_COUNT_STRING_LEN + 1);
  2267. RtlIntegerToUnicodeString ( Count,
  2268. 10, // Base
  2269. &unicodeString);
  2270. }
  2271. VOID
  2272. IPSecESPStatus(
  2273. IN UCHAR StatusType,
  2274. IN IP_STATUS StatusCode,
  2275. IN IPAddr OrigDest,
  2276. IN IPAddr OrigSrc,
  2277. IN IPAddr Src,
  2278. IN ULONG Param,
  2279. IN PVOID Data
  2280. )
  2281. /*++
  2282. Routine Description:
  2283. Handle a status indication for ESP, mostly for PMTU handling.
  2284. Arguments:
  2285. StatusType - Type of status.
  2286. StatusCode - Code identifying IP_STATUS.
  2287. OrigDest - If this is NET status, the original dest. of DG that
  2288. triggered it.
  2289. OrigSrc - The original src corr. OrigDest.
  2290. Src - IP address of status originator (could be local or remote).
  2291. Param - Additional information for status - i.e. the param field of
  2292. an ICMP message.
  2293. Data - Data pertaining to status - for NET status, this is the
  2294. first 8 bytes of the original DG.
  2295. Return Value:
  2296. --*/
  2297. {
  2298. IPSEC_DEBUG(PMTU, ("PMTU for ESP recieved from %lx to %lx\n", OrigSrc, OrigDest));
  2299. if (StatusType == IP_NET_STATUS && StatusCode == IP_SPEC_MTU_CHANGE) {
  2300. IPSecProcessPMTU( OrigDest,
  2301. OrigSrc,
  2302. NET_TO_HOST_LONG(((UNALIGNED ESP *)Data)->esp_spi),
  2303. Encrypt,
  2304. Param);
  2305. }
  2306. }
  2307. VOID
  2308. IPSecAHStatus(
  2309. IN UCHAR StatusType,
  2310. IN IP_STATUS StatusCode,
  2311. IN IPAddr OrigDest,
  2312. IN IPAddr OrigSrc,
  2313. IN IPAddr Src,
  2314. IN ULONG Param,
  2315. IN PVOID Data
  2316. )
  2317. /*++
  2318. Routine Description:
  2319. Handle a status indication for AH, mostly for PMTU handling.
  2320. Arguments:
  2321. StatusType - Type of status.
  2322. StatusCode - Code identifying IP_STATUS.
  2323. OrigDest - If this is NET status, the original dest. of DG that
  2324. triggered it.
  2325. OrigSrc - The original src corr. OrigDest.
  2326. Src - IP address of status originator (could be local or remote).
  2327. Param - Additional information for status - i.e. the param field of
  2328. an ICMP message.
  2329. Data - Data pertaining to status - for NET status, this is the
  2330. first 8 bytes of the original DG.
  2331. Return Value:
  2332. --*/
  2333. {
  2334. IPSEC_DEBUG(PMTU, ("PMTU for AH recieved from %lx to %lx\n", OrigSrc, OrigDest));
  2335. if (StatusType == IP_NET_STATUS && StatusCode == IP_SPEC_MTU_CHANGE) {
  2336. IPSecProcessPMTU( OrigDest,
  2337. OrigSrc,
  2338. NET_TO_HOST_LONG(((UNALIGNED AH *)Data)->ah_spi),
  2339. Auth,
  2340. Param);
  2341. }
  2342. }
  2343. VOID
  2344. IPSecProcessPMTU(
  2345. IN IPAddr OrigDest,
  2346. IN IPAddr OrigSrc,
  2347. IN tSPI SPI,
  2348. IN OPERATION_E Operation,
  2349. IN ULONG NewMTU
  2350. )
  2351. /*++
  2352. Routine Description:
  2353. Process PMTU.
  2354. Arguments:
  2355. OrigDest - The original dest. of DG that triggered it.
  2356. OrigSrc - The original src corr. OrigDest.
  2357. SPI - SPI of the outer IPSec header.
  2358. Operation - AH or ESP operation of IPSec.
  2359. NewMTU - The new MTU indicated by the intermediate gateway.
  2360. Return Value:
  2361. --*/
  2362. {
  2363. PLIST_ENTRY pFilterEntry;
  2364. PLIST_ENTRY pSAEntry;
  2365. PFILTER pFilter;
  2366. PSA_TABLE_ENTRY pSA;
  2367. IPAddr SADest;
  2368. KIRQL kIrql;
  2369. LONG Index;
  2370. LONG SAIndex;
  2371. BOOLEAN fFound = FALSE;
  2372. IPSEC_DEBUG(PMTU, ("IPSecProcessPMTU: NewMTU arrived %lx\n", NewMTU));
  2373. AcquireWriteLock(&g_ipsec.SADBLock, &kIrql);
  2374. //
  2375. // Search Tunnel and Masked filter list for an outbound SA that matches
  2376. // OrigDest, OrigSrc and SPI. If such an SA is found, update its NewMTU
  2377. // field so that next packet using the SA propogate a smaller MTU
  2378. // back to TCP/IP stack. Tunnel filter should be searched first because
  2379. // if in the case transport over tunnel operation, the packet going out
  2380. // will have the Tunnel header.
  2381. //
  2382. for ( Index = OUTBOUND_TUNNEL_FILTER;
  2383. (Index >= OUTBOUND_TRANSPORT_FILTER) && !fFound;
  2384. Index -= TRANSPORT_TUNNEL_INCREMENT) {
  2385. for ( pFilterEntry = g_ipsec.FilterList[Index].Flink;
  2386. !fFound && pFilterEntry != &g_ipsec.FilterList[Index];
  2387. pFilterEntry = pFilterEntry->Flink) {
  2388. pFilter = CONTAINING_RECORD(pFilterEntry,
  2389. FILTER,
  2390. MaskedLinkage);
  2391. for ( SAIndex = 0;
  2392. (SAIndex < pFilter->SAChainSize) && !fFound;
  2393. SAIndex++) {
  2394. for ( pSAEntry = pFilter->SAChain[SAIndex].Flink;
  2395. pSAEntry != &pFilter->SAChain[SAIndex];
  2396. pSAEntry = pSAEntry->Flink) {
  2397. pSA = CONTAINING_RECORD(pSAEntry,
  2398. SA_TABLE_ENTRY,
  2399. sa_FilterLinkage);
  2400. if (pSA->sa_Flags & FLAGS_SA_TUNNEL) {
  2401. SADest = pSA->sa_TunnelAddr;
  2402. } else {
  2403. SADest = pSA->SA_DEST_ADDR;
  2404. }
  2405. if (SADest == OrigDest &&
  2406. pSA->sa_SPI == SPI &&
  2407. pSA->sa_Operation[pSA->sa_NumOps - 1] == Operation) {
  2408. //
  2409. // We matched the triple for a unique SA so this must be it.
  2410. //
  2411. fFound = TRUE;
  2412. break;
  2413. }
  2414. }
  2415. }
  2416. }
  2417. }
  2418. //
  2419. // Update the NewMTU field of the found SA. We only do this if the new
  2420. // MTU is lower than the current one.
  2421. //
  2422. if (fFound && NewMTU < pSA->sa_NewMTU && NewMTU > sizeof(IPHeader)) {
  2423. IPSEC_SET_VALUE(pSA->sa_NewMTU, NewMTU);
  2424. IPSEC_DEBUG(PMTU, ("NewMTU %lx for pSA %lx\n", NewMTU, pSA));
  2425. }
  2426. ReleaseWriteLock(&g_ipsec.SADBLock, kIrql);
  2427. }
  2428. IPSEC_ACTION
  2429. IPSecRcvFWPacket(
  2430. IN PCHAR pIPHeader,
  2431. IN PVOID pData,
  2432. IN UINT DataLength,
  2433. IN UCHAR DestType
  2434. )
  2435. /*++
  2436. Routine Description:
  2437. To match a inbound tunnel rule for a packet received on the inbound forward path.
  2438. Arguments:
  2439. pIPHeader - the IP header
  2440. pData - the data portion of the packet
  2441. DataLength - data length
  2442. Return Value:
  2443. eFORWARD
  2444. eDROP
  2445. --*/
  2446. {
  2447. PSA_TABLE_ENTRY pSA;
  2448. PSA_TABLE_ENTRY pNextSA;
  2449. USHORT FilterFlags;
  2450. NTSTATUS status;
  2451. IPSEC_ACTION action = eFORWARD;
  2452. IPRcvBuf RcvBuf = {0};
  2453. //
  2454. // We are not interested in non multicast broadcast packets.
  2455. //
  2456. if (IS_BCAST_DEST(DestType) && !IPSEC_MANDBCAST_PROCESS()) {
  2457. return action;
  2458. }
  2459. //
  2460. // Build a fake IPRcvBuf so we can reuse the classification routine.
  2461. //
  2462. RcvBuf.ipr_buffer = pData;
  2463. RcvBuf.ipr_size = DataLength;
  2464. status = IPSecClassifyPacket( (PUCHAR)pIPHeader,
  2465. &RcvBuf,
  2466. &pSA,
  2467. &pNextSA,
  2468. &FilterFlags,
  2469. #if GPC
  2470. 0,
  2471. #endif
  2472. FALSE,
  2473. TRUE,
  2474. TRUE,
  2475. DestType);
  2476. if (status != STATUS_SUCCESS) {
  2477. if (status == STATUS_PENDING) {
  2478. //
  2479. // SA is being negotiated - drop.
  2480. //
  2481. action = eDROP;
  2482. } else {
  2483. //
  2484. // No Filter/SA match found - forward.
  2485. //
  2486. //action = eFORWARD;
  2487. }
  2488. } else {
  2489. if (FilterFlags) {
  2490. if (FilterFlags & FILTER_FLAGS_DROP) {
  2491. //
  2492. // Drop filter matched - drop.
  2493. //
  2494. action = eDROP;
  2495. } else if (FilterFlags & FILTER_FLAGS_PASS_THRU) {
  2496. //
  2497. // Pass-thru filter matched - forward.
  2498. //
  2499. //action = eFORWARD;
  2500. } else {
  2501. ASSERT(FALSE);
  2502. }
  2503. } else {
  2504. ASSERT(pSA);
  2505. ASSERT(pSA->sa_Flags & FLAGS_SA_TUNNEL);
  2506. //
  2507. // A real SA is matched - drop.
  2508. //
  2509. action = eDROP;
  2510. IPSecDerefSA(pSA);
  2511. }
  2512. }
  2513. return action;
  2514. }
  2515. NTSTATUS
  2516. IPSecRekeyInboundSA(
  2517. IN PSA_TABLE_ENTRY pSA
  2518. )
  2519. /*++
  2520. Routine Description:
  2521. Rekey a SA because we hit the rekey threshold.
  2522. Arguments:
  2523. Return Value:
  2524. --*/
  2525. {
  2526. PSA_TABLE_ENTRY pLarvalSA;
  2527. PSA_TABLE_ENTRY pOutboundSA;
  2528. NTSTATUS status;
  2529. KIRQL kIrql;
  2530. AcquireWriteLock(&g_ipsec.SADBLock, &kIrql);
  2531. //
  2532. // If SA already expired, no rekey is necessary.
  2533. //
  2534. pOutboundSA = pSA->sa_AssociatedSA;
  2535. if (!pOutboundSA) {
  2536. ReleaseWriteLock(&g_ipsec.SADBLock, kIrql);
  2537. return STATUS_UNSUCCESSFUL;
  2538. }
  2539. if (!(pOutboundSA->sa_Flags & FLAGS_SA_REKEY_ORI)) {
  2540. pOutboundSA->sa_Flags |= FLAGS_SA_REKEY_ORI;
  2541. IPSEC_DEBUG(SA, ("SA: %lx expiring soon\n", pOutboundSA));
  2542. //
  2543. // Rekey, but still continue to use this SA until the actual expiry.
  2544. //
  2545. status = IPSecNegotiateSA( pOutboundSA->sa_Filter,
  2546. pOutboundSA->sa_uliSrcDstAddr,
  2547. pOutboundSA->sa_uliProtoSrcDstPort,
  2548. pOutboundSA->sa_NewMTU,
  2549. &pLarvalSA,
  2550. pOutboundSA->sa_DestType);
  2551. if (!NT_SUCCESS(status) && status != STATUS_DUPLICATE_OBJECTID) {
  2552. pOutboundSA->sa_Flags &= ~FLAGS_SA_REKEY_ORI;
  2553. status = STATUS_UNSUCCESSFUL;
  2554. }
  2555. }
  2556. ReleaseWriteLock(&g_ipsec.SADBLock, kIrql);
  2557. return status;
  2558. }
  2559. NTSTATUS
  2560. IPSecRekeyOutboundSA(
  2561. IN PSA_TABLE_ENTRY pSA
  2562. )
  2563. /*++
  2564. Routine Description:
  2565. Rekey a SA because we hit the rekey threshold.
  2566. Arguments:
  2567. Return Value:
  2568. --*/
  2569. {
  2570. PSA_TABLE_ENTRY pLarvalSA;
  2571. NTSTATUS status;
  2572. KIRQL kIrql;
  2573. AcquireWriteLock(&g_ipsec.SADBLock, &kIrql);
  2574. if (!(pSA->sa_Flags & FLAGS_SA_REKEY_ORI)) {
  2575. pSA->sa_Flags |= FLAGS_SA_REKEY_ORI;
  2576. IPSEC_DEBUG(SA, ("SA: %lx expiring soon\n", pSA));
  2577. //
  2578. // Rekey, but still continue to use this SA until the actual expiry.
  2579. //
  2580. status = IPSecNegotiateSA( pSA->sa_Filter,
  2581. pSA->sa_uliSrcDstAddr,
  2582. pSA->sa_uliProtoSrcDstPort,
  2583. pSA->sa_NewMTU,
  2584. &pLarvalSA,
  2585. pSA->sa_DestType);
  2586. if (!NT_SUCCESS(status) && status != STATUS_DUPLICATE_OBJECTID) {
  2587. pSA->sa_Flags &= ~FLAGS_SA_REKEY_ORI;
  2588. status = STATUS_UNSUCCESSFUL;
  2589. }
  2590. }
  2591. ReleaseWriteLock(&g_ipsec.SADBLock, kIrql);
  2592. return status;
  2593. }
  2594. NTSTATUS
  2595. IPSecPuntInboundSA(
  2596. IN PSA_TABLE_ENTRY pSA
  2597. )
  2598. /*++
  2599. Routine Description:
  2600. Punt a SA because we have exceeded the rekey threshold.
  2601. Arguments:
  2602. Return Value:
  2603. --*/
  2604. {
  2605. PSA_TABLE_ENTRY pOutboundSA;
  2606. KIRQL kIrql;
  2607. AcquireWriteLock(&g_ipsec.SADBLock, &kIrql);
  2608. //
  2609. // If SA already expired, no punt is necessary.
  2610. //
  2611. pOutboundSA = pSA->sa_AssociatedSA;
  2612. if (!pOutboundSA) {
  2613. ReleaseWriteLock(&g_ipsec.SADBLock, kIrql);
  2614. return STATUS_SUCCESS;
  2615. }
  2616. if (IPSEC_GET_VALUE(pOutboundSA->sa_Reference) > 1 &&
  2617. !(pOutboundSA->sa_Flags & FLAGS_SA_EXPIRED) &&
  2618. pOutboundSA->sa_State == STATE_SA_ACTIVE) {
  2619. pOutboundSA->sa_Flags |= FLAGS_SA_EXPIRED;
  2620. IPSEC_DEBUG(SA, ("SA: %lx has expired\n", pOutboundSA));
  2621. if (pOutboundSA->sa_Flags & FLAGS_SA_REKEY_ORI) {
  2622. pOutboundSA->sa_Flags &= ~FLAGS_SA_REKEY_ORI;
  2623. if (pOutboundSA->sa_RekeyLarvalSA) {
  2624. if (pOutboundSA->sa_RekeyLarvalSA->sa_RekeyOriginalSA) {
  2625. pOutboundSA->sa_RekeyLarvalSA->sa_RekeyOriginalSA = NULL;
  2626. }
  2627. }
  2628. }
  2629. //
  2630. // Delete this SA and expire the corresponding inbound SA.
  2631. //
  2632. IPSecDeleteInboundSA(pSA);
  2633. }
  2634. ReleaseWriteLock(&g_ipsec.SADBLock, kIrql);
  2635. return STATUS_SUCCESS;
  2636. }
  2637. NTSTATUS
  2638. IPSecPuntOutboundSA(
  2639. IN PSA_TABLE_ENTRY pSA
  2640. )
  2641. /*++
  2642. Routine Description:
  2643. Punt a SA because we have exceeded the rekey threshold.
  2644. Arguments:
  2645. Return Value:
  2646. --*/
  2647. {
  2648. KIRQL kIrql;
  2649. AcquireWriteLock(&g_ipsec.SADBLock, &kIrql);
  2650. if (IPSEC_GET_VALUE(pSA->sa_Reference) > 1 &&
  2651. !(pSA->sa_Flags & FLAGS_SA_EXPIRED) &&
  2652. pSA->sa_State == STATE_SA_ACTIVE &&
  2653. pSA->sa_AssociatedSA != NULL) {
  2654. pSA->sa_Flags |= FLAGS_SA_EXPIRED;
  2655. IPSEC_DEBUG(SA, ("SA: %lx has expired\n", pSA));
  2656. if (pSA->sa_Flags & FLAGS_SA_REKEY_ORI) {
  2657. pSA->sa_Flags &= ~FLAGS_SA_REKEY_ORI;
  2658. if (pSA->sa_RekeyLarvalSA) {
  2659. if (pSA->sa_RekeyLarvalSA->sa_RekeyOriginalSA) {
  2660. pSA->sa_RekeyLarvalSA->sa_RekeyOriginalSA = NULL;
  2661. }
  2662. }
  2663. }
  2664. //
  2665. // Delete this SA and expire the corresponding inbound SA.
  2666. //
  2667. IPSecExpireInboundSA(pSA->sa_AssociatedSA);
  2668. }
  2669. ReleaseWriteLock(&g_ipsec.SADBLock, kIrql);
  2670. return STATUS_SUCCESS;
  2671. }
  2672. BOOLEAN
  2673. IPSecQueryStatus(
  2674. IN CLASSIFICATION_HANDLE GpcHandle
  2675. )
  2676. /*++
  2677. Routine Description:
  2678. Query IPSec to see if IPSec applies to this flow. TCP/IP then decides whether
  2679. to take fast or slow path in IPTransmit.
  2680. Arguments:
  2681. GpcHandle
  2682. Return Value:
  2683. TRUE - if IPSec applies to this packet; slow path
  2684. FALSE - if IPSec doesn't apply to this packet; fast path
  2685. --*/
  2686. {
  2687. PLIST_ENTRY pFilterList;
  2688. PFILTER pFilter;
  2689. NTSTATUS status;
  2690. #if DBG
  2691. //
  2692. // This should force all traffic going through IPSecHandlePacket.
  2693. //
  2694. if (DebugQry) {
  2695. return TRUE;
  2696. }
  2697. #endif
  2698. if (IS_DRIVER_BYPASS() || IPSEC_DRIVER_IS_EMPTY()) {
  2699. return FALSE;
  2700. }
  2701. //
  2702. // If no GpcHandle passed in, take slow path.
  2703. //
  2704. if (!GpcHandle) {
  2705. return TRUE;
  2706. }
  2707. //
  2708. // Search in the tunnel filter list first.
  2709. //
  2710. pFilterList = &g_ipsec.FilterList[OUTBOUND_TUNNEL_FILTER];
  2711. //
  2712. // If any tunnel filters exist, take slow path.
  2713. //
  2714. if (!IsListEmpty(pFilterList)) {
  2715. return TRUE;
  2716. }
  2717. #if GPC
  2718. //
  2719. // Search the local GPC filter list.
  2720. //
  2721. pFilterList = &g_ipsec.GpcFilterList[OUTBOUND_TRANSPORT_FILTER];
  2722. //
  2723. // If any generic filters exist, take slow path.
  2724. //
  2725. if (!IsListEmpty(pFilterList)) {
  2726. return TRUE;
  2727. }
  2728. pFilter = NULL;
  2729. //
  2730. // Use GpcHandle directly to get the filter installed.
  2731. //
  2732. status = GPC_GET_CLIENT_CONTEXT(g_ipsec.GpcClients[GPC_CF_IPSEC_OUT],
  2733. GpcHandle,
  2734. &pFilter);
  2735. if (status == STATUS_INVALID_HANDLE) {
  2736. //
  2737. // Handle has expired, take slow path because re-classification will
  2738. // have to be applied to this flow from now on until connection breaks.
  2739. // So why bother performing a re-classification here?
  2740. //
  2741. return TRUE;
  2742. }
  2743. return pFilter != NULL;
  2744. #else
  2745. return TRUE;
  2746. #endif
  2747. }