Esempio n. 1
0
void
TlInspectCompletePendedConnection(
   _Inout_ TL_INSPECT_PENDED_PACKET** pendedConnect,
   _In_ BOOLEAN permitTraffic
   )
/* ++

   This function completes the pended connection (inbound or outbound)
   with the inspection result.

-- */
{

   TL_INSPECT_PENDED_PACKET* pendedConnectLocal = *pendedConnect;

   if (pendedConnectLocal->direction == FWP_DIRECTION_OUTBOUND)
   {
      HANDLE completionContext = pendedConnectLocal->completionContext;

      pendedConnectLocal->authConnectDecision = 
         permitTraffic ? FWP_ACTION_PERMIT : FWP_ACTION_BLOCK;

      //
      // For pended ALE_AUTH_CONNECT, FwpsCompleteOperation will trigger
      // a re-auth during which the inspection decision is to be returned.
      // Here we don't remove the pended entry from the list such that the
      // re-auth can find it along with the recorded inspection result.
      //
      pendedConnectLocal->completionContext = NULL;

      FwpsCompleteOperation(
         completionContext,
         NULL
         );

      *pendedConnect = NULL; // ownership transferred to the re-auth path.
   }
   else
   {
      if (!configPermitTraffic)
      {
         FreePendedPacket(pendedConnectLocal);
         *pendedConnect = NULL;
      }

      //
      // Permitted ALE_RECV_ACCEPT will pass thru and be processed by
      // TLInspectCloneReinjectInbound. FwpsCompleteOperation will be called
      // then when the net buffer list is cloned; after which the clone will
      // be recv-injected.
      //
   }
}
Esempio n. 2
0
NTSTATUS
TLInspectCloneReinjectInbound(
   _Inout_ TL_INSPECT_PENDED_PACKET* packet
   )
/* ++

   This function clones the inbound net buffer list and, if needed, 
   rebuild the IP header to remove the IpSec headers and receive-injects 
   the clone back to the tcpip stack.

-- */
{
   NTSTATUS status = STATUS_SUCCESS;

   NET_BUFFER_LIST* clonedNetBufferList = NULL;
   NET_BUFFER* netBuffer;
   ULONG nblOffset;
   NDIS_STATUS ndisStatus;

   //
   // For inbound net buffer list, we can assume it contains only one 
   // net buffer.
   //
   netBuffer = NET_BUFFER_LIST_FIRST_NB(packet->netBufferList);
   
   nblOffset = NET_BUFFER_DATA_OFFSET(netBuffer);

   //
   // The TCP/IP stack could have retreated the net buffer list by the 
   // transportHeaderSize amount; detect the condition here to avoid
   // retreating twice.
   //
   if (nblOffset != packet->nblOffset)
   {
      NT_ASSERT(packet->nblOffset - nblOffset == packet->transportHeaderSize);
      packet->transportHeaderSize = 0;
   }

   //
   // Adjust the net buffer list offset to the start of the IP header.
   //
   ndisStatus = NdisRetreatNetBufferDataStart(
      netBuffer,
      packet->ipHeaderSize + packet->transportHeaderSize,
      0,
      NULL
      );
   _Analysis_assume_(ndisStatus == NDIS_STATUS_SUCCESS);

   //
   // Note that the clone will inherit the original net buffer list's offset.
   //

   status = FwpsAllocateCloneNetBufferList(
               packet->netBufferList,
               NULL,
               NULL,
               0,
               &clonedNetBufferList
               );

   //
   // Undo the adjustment on the original net buffer list.
   //

   NdisAdvanceNetBufferDataStart(
      netBuffer,
      packet->ipHeaderSize + packet->transportHeaderSize,
      FALSE,
      NULL
      );

   if (!NT_SUCCESS(status))
   {
      goto Exit;
   }

   if (packet->ipSecProtected)
   {
      //
      // When an IpSec protected packet is indicated to AUTH_RECV_ACCEPT or 
      // INBOUND_TRANSPORT layers, for performance reasons the tcpip stack
      // does not remove the AH/ESP header from the packet. And such 
      // packets cannot be recv-injected back to the stack w/o removing the
      // AH/ESP header. Therefore before re-injection we need to "re-build"
      // the cloned packet.
      // 
      status = FwpsConstructIpHeaderForTransportPacket(
                  clonedNetBufferList,
                  packet->ipHeaderSize,
                  packet->addressFamily,
                  (UINT8*)&packet->remoteAddr, 
                  (UINT8*)&packet->localAddr,  
                  packet->protocol,
                  0,
                  NULL,
                  0,
                  0,
                  NULL,
                  0,
                  0
                  );

      if (!NT_SUCCESS(status))
      {
         goto Exit;
      }
   }

   if (packet->completionContext != NULL)
   {
      NT_ASSERT(packet->type == TL_INSPECT_CONNECT_PACKET);

      FwpsCompleteOperation(
         packet->completionContext,
         clonedNetBufferList
         );

      packet->completionContext = NULL;
   }

   status = FwpsInjectTransportReceiveAsync(
               gInjectionHandle,
               NULL,
               NULL,
               0,
               packet->addressFamily,
               packet->compartmentId,
               packet->interfaceIndex,
               packet->subInterfaceIndex,
               clonedNetBufferList,
               TLInspectInjectComplete,
               packet
               );

   if (!NT_SUCCESS(status))
   {
      goto Exit;
   }

   clonedNetBufferList = NULL; // ownership transferred to the 
                               // completion function.

Exit:

   if (clonedNetBufferList != NULL)
   {
      FwpsFreeCloneNetBufferList(clonedNetBufferList, 0);
   }

   return status;
}
_IRQL_requires_same_
inline VOID KrnlHlprPendDataPurge(_Inout_ PEND_DATA* pPendData)
{
#if DBG
   
   DbgPrintEx(DPFLTR_IHVNETWORK_ID,
              DPFLTR_INFO_LEVEL,
              " ---> KrnlHlprPendDataPurge()\n");

#endif /// DBG
   
   NT_ASSERT(pPendData);

#if(NTDDI_VERSION >= NTDDI_WIN7)

   if(pPendData->layerID == FWPS_LAYER_ALE_ENDPOINT_CLOSURE_V4 ||
      pPendData->layerID == FWPS_LAYER_ALE_ENDPOINT_CLOSURE_V6)
   {
      if(pPendData->classifyHandle &&
         pPendData->isPended)
      {
         FwpsCompleteClassify(pPendData->classifyHandle,
                              0,
                              &(pPendData->classifyOut));


         FwpsReleaseClassifyHandle(pPendData->classifyHandle);

         pPendData->classifyHandle = 0;
         pPendData->pPCPendData    = 0;
         pPendData->isPended       = FALSE;
      }
   }
   else

#endif /// (NTDDI_VERSION >= NTDDI_WIN7)

   {
      if(pPendData->completionContext &&
         pPendData->isPended)
      {
         FwpsCompleteOperation(pPendData->completionContext,
                               pPendData->pNBL);

         pPendData->completionContext      = 0;
         pPendData->pNBL                   = 0;
         pPendData->pPendAuthorizationData = 0;
         pPendData->isPended               = FALSE;
      }
   }

   RtlZeroMemory(pPendData,
                 sizeof(PEND_DATA));

#if DBG
   
   DbgPrintEx(DPFLTR_IHVNETWORK_ID,
              DPFLTR_INFO_LEVEL,
              " <--- KrnlHlprPendDataPurge()\n");

#endif /// DBG
   
   return;
}