📄 pgpnetpolicymanager.c
字号:
/*
* Copyright (c) 1998, Network Associates, Inc.
* All rights reserved.
*
* $Id: pgpNetPolicyManager.c,v 1.63.4.2 1999/06/17 21:15:20 elowe Exp $
*
*/
#include <ndis.h>
#include "ipdef.h"
#include "vpn.h"
#include "vpndbg.h"
#include "pgpMem.h"
#include "pgpNetKernel.h"
#include "pgpNetKernelXChng.h"
#include "pgpNetPMConfig.h"
#include "pgpNetPMHost.h"
#include "pgpNetPMSA.h"
#include "pgpNetPMEvents.h"
/* some IPSEC helper functions */
#include "pgpIPsecBuffer.h"
#include "pgpIPsecESP.h"
#include "pgpIPsecAH.h"
#include "pgpIPheader.h"
#define ESP_HEADERSIZE 8
#define AH_HEADERSIZE 12
#ifndef PM_EMULATION
static void sCheckRekey(PVPN_ADAPTER adapter, PGPnetKernelSA *pSA);
static void sCopySrcToxForm(PGPNDIS_PACKET *start);
static void sCopyPacketXformToSrc(const PGPNDIS_PACKET *source, PGPNDIS_PACKET *dest,PVPN_ADAPTER adapter);
static PGPBoolean sCheckExpiration(PVPN_ADAPTER adapter,
PGPnetKernelSA *pSA);
static PGPnetPMStatus sDoTransformOutgoing(PGPnetPMContext *pContext,
PGPNDIS_PACKET *packet,
PVPN_ADAPTER adapter);
static PGPnetPMStatus sDoTransformIncoming(PGPnetPMContext *pContext,
PGPNDIS_PACKET *packet,
PVPN_ADAPTER adapter);
static PGPnetPMStatus sAcquireSA(PGPnetPMContext *pContext,
PGPUInt32 ipAddress,
PGPUInt32 ipAddrStart,
PGPUInt32 ipMaskEnd,
PGPBoolean incoming,
void * ipBuffer,
PGPUInt32 ipBufferSize,
PVPN_ADAPTER adapter,
PGPnetKernelSA **pSA);
static PGPnetPMStatus sLookHardForSA(PGPnetPMContext *pContext,
PVPN_ADAPTER adapter,
PGPNetHostEntry *host,
PGPUInt32 ipAddress,
PGPUInt16 port,
void *ipBuffer,
PGPUInt32 ipBufferSize,
PGPnetKernelSA **ppTransport,
PGPnetKernelSA **ppTunnel,
PGPBoolean incoming);
void
PGPnetRASdisconnect(PVPN_ADAPTER adapter)
{
/* fire event */
DBG_FUNC("PGPnetRASdisconnect")
PGPMESSAGE_CONTEXT * kernelMessageContext;
PGPnetMessageHeader * kernelMessageHeader;
PGPUInt32 head = 0;
DBG_ENTER();
if ((adapter != NULL) && (adapter->pgpMessage != NULL)) {
kernelMessageContext = (PGPMESSAGE_CONTEXT*)(adapter->pgpMessage);
kernelMessageHeader = &kernelMessageContext->header;
NdisAcquireSpinLock(&adapter->general_lock);
head = kernelMessageHeader->head + 1;
if (head > kernelMessageHeader->maxSlots)
head = 1;
kernelMessageContext = &kernelMessageContext[head];
kernelMessageContext->messageType = PGPnetMessageRASdisconnect;
kernelMessageHeader->head = head;
NdisReleaseSpinLock(&adapter->general_lock);
PgpEventSet(&adapter->pgpEvent);
}
DBG_LEAVE(0);
}
void
PGPnetRASconnect(PVPN_ADAPTER adaptor, ULONG ipAddress)
{
DBG_FUNC("PGPnetRASconnect")
DBG_ENTER();
DBG_PRINT(("New IP address Report, ipAddress: %xh\n", ipAddress););
DBG_LEAVE(0);
}
/*
* This is the Heavy (or default) NeedTransform. It starts
* the SA acquisition process.
*/
PGPnetPMStatus
PGPnetPMNeedTransform(PGPnetPMContext *pContext,
PGPUInt32 ipAddress,
PGPUInt16 port,
PGPBoolean incoming,
void * ipBuffer,
PGPUInt32 ipBufferSize,
void * reserved)
{
PGPNetHostEntry * host = PMFindHost(pContext, ipAddress);
PVPN_ADAPTER adapter = (PVPN_ADAPTER) reserved;
PGPnetPMStatus ret;
PGPnetKernelSA * pSA;
DBG_FUNC("PGPnetPMNeedTransform")
DBG_ENTER();
ret = PGPnetPMNeedTransformLight(pContext, ipAddress, incoming, adapter);
if (ret == kPGPNetPMPacketEncrypt) {
ret = sLookHardForSA(pContext,
adapter,
host,
ipAddress,
port,
ipBuffer,
ipBufferSize,
&pSA,
&pSA,
incoming);
if (ret != kPGPNetPMPacketEncrypt && port == UDP_PORT_IKE_NET)
ret = kPGPNetPMPacketClear;
DBG_LEAVE(ret);
return ret;
}
DBG_LEAVE(ret);
return ret;
}
/*
* This is the lightweight version of NeedTransform. It does not
* start the SA acquisition process.
*/
PGPnetPMStatus
PGPnetPMNeedTransformLight(PGPnetPMContext *pContext,
PGPUInt32 ipAddress,
PGPBoolean incoming,
void * reserved)
{
PGPNetHostEntry * host = PMFindHost(pContext, ipAddress);
PGPNetHostEntry * secureGW = 0;
PVPN_ADAPTER adapter = (PVPN_ADAPTER) reserved;
DBG_FUNC("PGPnetPMNeedTransformLight")
DBG_ENTER();
/* configuration not here yet, default to clear */
if (!pContext->pConfig) {
DBG_PRINT(("kPGPNetPMPacketClear because no config yet\n"););
DBG_LEAVE(kPGPNetPMPacketClear);
return kPGPNetPMPacketClear;
}
if (!pContext->pConfig->bPGPnetEnabled){
DBG_PRINT(("kPGPNetPMPacketClear because PGPnet disabled by user\n"););
DBG_LEAVE(kPGPNetPMPacketClear);
return kPGPNetPMPacketClear;
}
if (host) {
/* Check for insecure host and no gateway */
if (host->hostType == kPGPnetInsecureHost && host->childOf == -1) {
DBG_PRINT(("kPGPNetPMPacketClear because host is insecure\n"););
DBG_LEAVE(kPGPNetPMPacketClear);
return kPGPNetPMPacketClear;
}
DBG_PRINT(("kPGPNetPMPacketEncrypt\n"););
DBG_LEAVE(kPGPNetPMPacketEncrypt);
return kPGPNetPMPacketEncrypt;
}
if (pContext->pConfig->bAllowUnconfigHost &&
pContext->pConfig->bAttemptUnconfigHost) {
DBG_PRINT(("kPGPNetPMPacketEncrypt\n"););
DBG_LEAVE(kPGPNetPMPacketEncrypt);
return kPGPNetPMPacketEncrypt;
}
if (pContext->pConfig->bAllowUnconfigHost &&
!pContext->pConfig->bAttemptUnconfigHost) {
/*
* There may be an SA for this host that was initiated by the peer.
* So we need to look for an SA, before sending it in the clear
*/
if (PMFindSA(pContext, ipAddress, 0, incoming)) {
DBG_PRINT(("kPGPNetPMPacketEncrypt because SA exists\n"););
DBG_LEAVE(kPGPNetPMPacketEncrypt);
return kPGPNetPMPacketEncrypt;
} else {
DBG_PRINT(("kPGPNetPMPacketClear because bAllow && !bAttempt\n"););
DBG_LEAVE(kPGPNetPMPacketClear);
return kPGPNetPMPacketClear;
}
}
if (!pContext->pConfig->bAllowUnconfigHost) {
DBG_PRINT(("kPGPNetPMPacketDrop because !bAllow\n"););
DBG_LEAVE(kPGPNetPMPacketDrop);
return kPGPNetPMPacketDrop;
}
DBG_PRINT(("kPGPNetPMPacketDrop because default\n"););
DBG_LEAVE(kPGPNetPMPacketDrop);
return kPGPNetPMPacketDrop;
}
PGPnetPMStatus
PGPnetPMDoTransform(PGPnetPMContext *pContext,
PGPNDIS_PACKET *packet,
PGPBoolean incoming,
PVPN_ADAPTER adapter)
{
PGPnetPMStatus retCode;
PGPUInt32 i = 0;
DBG_FUNC("PGPnetPMDoTransform")
DBG_ENTER();
packet->xformBlockLen = 0;
if (!incoming) {
retCode = sDoTransformOutgoing(pContext, packet, adapter);
} else {
retCode = sDoTransformIncoming(pContext, packet, adapter);
}
#if/*def*/ 0 /*DBG*/
/* write out packet src info */
DBG_PRINT(("Incoming: %s\n", incoming ? "TRUE" : "FALSE"););
DBG_PRINT(("packet->srcBlockLen: %d\n", packet->srcBlockLen););
DBG_PRINT(("packet->srcBlock: %X\n", packet->srcBlock););
for (i = 0; i<packet->srcBlockLen; i++) {
DbgPrint("%X ", packet->srcBlock[i]);
if (((i+1) % 16) == 0) {
DbgPrint("\n");
}
}
DbgPrint("\n");
/* write out packet xform info */
DBG_PRINT(("packet->xformBlockLen: %d\n", packet->xformBlockLen););
DBG_PRINT(("packet->xformBlock: %X\n", packet->xformBlock););
for (i = 0; i<packet->xformBlockLen; i++) {
DbgPrint("%X ", packet->xformBlock[i]);
if (((i+1) % 16) == 0) {
DbgPrint("\n");
}
}
DbgPrint("\n");
#endif
return retCode;
}
#endif // !PM_EMULATION
PGPnetPMStatus
sAcquireSA(PGPnetPMContext *pContext,
PGPUInt32 ipAddress,
PGPUInt32 ipAddrStart,
PGPUInt32 ipMaskEnd,
PGPBoolean incoming,
void *ipBuffer,
PGPUInt32 ipBufferSize,
PVPN_ADAPTER adapter,
PGPnetKernelSA **pSA)
{
PGPnetPMStatus ret;
PGPUInt32 spi = 0;
PGPError err = kPGPError_NoErr;
PGPIPsecBuffer inPacket;
DBG_FUNC("sAcquireSA")
DBG_ENTER();
if (incoming) {
PGPUInt32 unused;
if (ipBufferSize == 0) {
/* assume ipBuffer is an PGPNDIS_PACKET */
/* Bad Assumption? XXX */
PGPNDIS_PACKET *packet = (PGPNDIS_PACKET*)ipBuffer;
packet->xformBlockLen = 0;
err = PGPnetIPsecGetAddrAndSPI(pContext,
packet,
&unused,
&spi);
} else {
// look for spi in the ipBuffer, hopefully we have
// read in enough data. If not, then say we will encrypt
// and deal with any problems later
if (ipBufferSize < (sizeof(IP_HEADER) + ESP_HEADERSIZE) ) {
DBG_LEAVE(kPGPNetPMPacketEncrypt);
return kPGPNetPMPacketEncrypt;
}
inPacket.data = ipBuffer;
inPacket.dataSize = ipBufferSize;
inPacket.allocatedSize = ipBufferSize;
inPacket.next = NULL;
pgpIPsecESPGetSPI(&inPacket, &spi);
if (!spi) {
if (ipBufferSize < (sizeof(IP_HEADER) + AH_HEADERSIZE) ) {
DBG_LEAVE(kPGPNetPMPacketEncrypt);
return kPGPNetPMPacketEncrypt;
}
pgpIPsecAHGetSPI(&inPacket, &spi);
}
}
}
/* try to find existing SA */
if (IsntPGPError(err) && spi) {
*pSA = PMFindSAspi(pContext, ipAddress, spi);
if (!*pSA) {
/* Ok, this is odd, the packet had an SPI, but we can't
* find a matching SA. So we check to see if we have a
* different SA with this machine. If so, we don't ask
* for a new one. In any event, we must drop the packet
* since we can't process it.
*/
/* generate error for now */
PMfireErrorEvent(adapter, ipAddress, kPGPIPsecError_NoSAFound);
if (PMFindSA(pContext, ipAddress, ipAddrStart, incoming)) {
DBG_PRINT(("kPGPNetPMPacketDrop because we could not find SA\n"););
return kPGPNetPMPacketDrop;
}
}
} else
*pSA = PMFindSA(pContext, ipAddress, ipAddrStart, incoming);
if (*pSA && !(*pSA)->pending) {
/* An SA is ready to go */
DBG_PRINT(("kPGPNetPMPacketEncrypt because host is secure\n"););
ret = kPGPNetPMPacketEncrypt;
} else if (*pSA && (*pSA)->pending) {
/* already waiting for one */
DBG_PRINT(("kPGPNetPMPacketWaiting because no SA yet\n"););
ret = kPGPNetPMPacketWaiting;
} else {
/* no SA */
DBG_PRINT(("Asking for SA\n"););
/* fire kernel event and ask service for SA */
ret = PMfireSARequestEvent(adapter, ipAddress, ipAddrStart, ipMaskEnd);
if (ret == kPGPNetPMPacketDrop) {
DBG_LEAVE(kPGPNetPMPacketDrop);
return kPGPNetPMPacketDrop;
}
if (!PMAddPendingSA(pContext, ipAddress, ipAddrStart, ipMaskEnd)) {
DBG_LEAVE(kPGPNetPMPacketDrop);
return kPGPNetPMPacketDrop;
}
}
DBG_LEAVE(ret);
return ret;
}
PGPBoolean
sCheckExpiration(PVPN_ADAPTER adapter, PGPnetKernelSA *pSA)
{
DBG_FUNC("sCheckExpiration")
if (!pSA)
return FALSE;
/* check for expiration */
if ((pSA->ikeSA.kbLifeTime != 0 &&
pSA->bytesSent >= (pSA->ikeSA.kbLifeTime * 1024)) ||
(pSA->packetsSent >= (MAX_PGPUInt32-1))) {
/*(pSA->packetsSent == 8)) {*/
/* SA expired so generate SADied */
PMfireSADiedEvent(adapter, pSA->ikeSA.transform[0].u.ipsec.inSPI);
DBG_LEAVE(TRUE);
return TRUE;
}
return FALSE;
}
void
sCheckRekey(PVPN_ADAPTER adapter, PGPnetKernelSA *pSA)
{
DBG_FUNC("sCheckRekey")
PGPBoolean bRekey = FALSE;
PGPUInt32 kbSent = 1;
if (!pSA)
return;
/* OK, this is a little verbose, but I can understand it */
/* 1st: already rekeying */
if (pSA->reKeyInProgress)
return;
/* 2nd: packet count overload */
if (pSA->packetsSent >= 0xFFFF7FFF) {
bRekey = TRUE;
goto rekey;
}
/* 3rd: no rekey timeout or only a few bytes sent */
if ((pSA->ikeSA.kbLifeTime == 0) || (pSA->bytesSent < 1024))
return;
/* Ok calculating whether or not we should rekey */
kbSent = pSA->bytesSent / 1024;
#ifdef CHICAGO
//NdisGetCurrentSystemTime(&nowLarge);
// KeQuerySystemTime(&nowLarge);
/*
VxDCall( Get_Last_Updated_System_Time ); //puts return value in eax
_asm mov timeVal, eax ;get return value into variable
*/
#if 0
pgpCopyMemory(&(nowLarge.HighPart) /*src*/,
&now64 /*dest*/,
4);
pgpCopyMemory(&(nowLarge.LowPart) /*src*/,
(&now64) + 4 /*dest*/,
4);
avgkb = kbSent / ((now64 - pSA->birthTime) / 10000000);
#endif
#else
{
PGPInt64 avgkb = 0;
LARGE_INTEGER nowLarge;
PGPInt64 now64 = 0, t1 = 0;
KeQuerySystemTime(&nowLarge);
now64 = nowLarge.QuadPart;
t1 = (now64 - pSA->birthTime) / 10000000;
if (t1 != 0)
avgkb = kbSent / t1;
#define kPGPnetRekeyKBSeconds 30
/* 4th: going to hit the limit in 30 seconds, better rekey */
if ((avgkb != 0) &&
(((pSA->ikeSA.kbLifeTime - kbSent) / avgkb)
<= kPGPnetRekeyKBSeconds)) {
bRekey = TRUE;
goto rekey;
}
}
#endif
/* 5th: only 1 meg left, better rekey */
if (kbSent >= (pSA->ikeSA.kbLifeTime - 2048)) {
bRekey = TRUE;
goto rekey;
}
rekey:
if (bRekey) {
DBG_PRINT(("Firing Rekey event\n"););
PMfireSARekeyEvent(adapter, pSA->ikeSA.transform[0].u.ipsec.inSPI);
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -