www.pudn.com > NETINFO.rar > acl.cpp
#include "acl.h"
char* GetByteRange(char*p, BYTE* low, BYTE* high)
{
for(;isspace(*p); p++)NULL; //skip space chars
if( *p == '*' )
{
*low = 0;
*high = 255;
p++;
}
else
{
*low = (BYTE)strtoul(p, &p, 10);
if( *p == '-' )
{
if( isdigit(p[1]) )
*high = (BYTE)strtoul(p+1, &p, 10);
else
*high = 255;
}
else
*high = *low;
}
return p;
}
char* GetWordRange(char*p, WORD* low, WORD* high)
{
for(;isspace(*p); p++)NULL; //skip space chars
if( *p == '*' )
{
*low = 0;
*high = 0xffff;
p++;
}
else
{
*low = (WORD)strtoul(p, &p, 10);
if( *p == '-' )
{
if( isdigit(p[1]) )
*high = (WORD)strtoul(p+1, &p, 10);
else
*high = 0xffff;
}
else
*high = *low;
}
return p;
}
char *SkipChar(char*p, char ch)
{
if( !p ) return NULL;
while( *p != 0 && *p != ch ) p++;
if( *p == 0 )
return NULL;
return p+1;
}
BOOL LoadAcl(const char* filename, CPtrList *pList)
{
FILE *fp = fopen(filename, "rt");
if( !fp )
return FALSE;
BOOL retVal = TRUE;
char line[1000];
strcpy(line, "");
while( fgets(line, sizeof(line), fp) )
{
ACL_ITEM item;
memset(&item, 0, sizeof(item));
char* p = line, *p2;
while( isspace(*p) ) p++; //skip white space
if( strcmp(p,"")==0 || memcmp(p, "//", 2) == 0 ) //empty line or comment line, just skip this line
continue;
//get permission type
char temp[1000];
for(p2 = p; *p2 != 0 && !isspace(*p2); p2++)NULL;
memcpy(temp, p, p2-p);
temp[p2-p] = 0;
if( stricmp(temp, "ALLOW") == 0 )
item.permit = ACL_ALLOW;
else if( stricmp(temp, "DENY") == 0 )
item.permit = ACL_DENY;
else
{
retVal = FALSE;
break;
}
p = p2;
//get src acl range
//get src b1
p = GetByteRange(p, &item.src.addrLow.b1, &item.src.addrHigh.b1);
p = SkipChar(p, '.');
if( !p )
{
retVal = FALSE;
break;
}
//get src b2
p = GetByteRange(p, &item.src.addrLow.b2, &item.src.addrHigh.b2);
p = SkipChar(p, '.');
if( !p )
{
retVal = FALSE;
break;
}
//get src b3
p = GetByteRange(p, &item.src.addrLow.b3, &item.src.addrHigh.b3);
p = SkipChar(p, '.');
if( !p )
{
retVal = FALSE;
break;
}
//get src b4
p = GetByteRange(p, &item.src.addrLow.b4, &item.src.addrHigh.b4);
p = SkipChar(p, ':');
if( !p )
{
retVal = FALSE;
break;
}
//get src port
p = GetWordRange(p, &item.src.portLow, &item.src.portHigh);
if( !p )
{
retVal = FALSE;
break;
}
//get dst acl range
//get dst b1
p = GetByteRange(p, &item.dst.addrLow.b1, &item.dst.addrHigh.b1);
p = SkipChar(p, '.');
if( !p )
{
retVal = FALSE;
break;
}
//get dst b2
p = GetByteRange(p, &item.dst.addrLow.b2, &item.dst.addrHigh.b2);
p = SkipChar(p, '.');
if( !p )
{
retVal = FALSE;
break;
}
//get dst b3
p = GetByteRange(p, &item.dst.addrLow.b3, &item.dst.addrHigh.b3);
p = SkipChar(p, '.');
if( !p )
{
retVal = FALSE;
break;
}
//get dst b4
p = GetByteRange(p, &item.dst.addrLow.b4, &item.dst.addrHigh.b4);
p = SkipChar(p, ':');
if( !p )
{
retVal = FALSE;
break;
}
//get dst port
p = GetWordRange(p, &item.dst.portLow, &item.dst.portHigh);
if( !p )
{
retVal = FALSE;
break;
}
ACL_ITEM *pItem = new ACL_ITEM;
*pItem = item;
pList->AddTail(pItem);
}
fclose(fp);
if( !retVal )
{
printf("ACL systax error: %s", line);
}
return retVal;
}
BOOL TcpShouldDeny(const CPtrList *pList, const IP* ip, const TCP* tcp)
{
BOOL result = FALSE;
if( !pList || tcp->fin || tcp->rst )
return result;
for(POSITION pos = pList->GetHeadPosition(); pos != NULL; )
{
ACL_ITEM *pItem = (ACL_ITEM *)pList->GetNext( pos );
if( ( (pItem->src.addrLow.b1 <= ip->src.b1 && ip->src.b1 <= pItem->src.addrHigh.b1)
&& (pItem->src.addrLow.b2 <= ip->src.b2 && ip->src.b2 <= pItem->src.addrHigh.b2)
&& (pItem->src.addrLow.b3 <= ip->src.b3 && ip->src.b3 <= pItem->src.addrHigh.b3)
&& (pItem->src.addrLow.b4 <= ip->src.b4 && ip->src.b4 <= pItem->src.addrHigh.b4)
&& (pItem->src.portLow <= tcp->srcPort && tcp->srcPort <= pItem->src.portHigh)
&& (pItem->dst.addrLow.b1 <= ip->dst.b1 && ip->dst.b1 <= pItem->dst.addrHigh.b1)
&& (pItem->dst.addrLow.b2 <= ip->dst.b2 && ip->dst.b2 <= pItem->dst.addrHigh.b2)
&& (pItem->dst.addrLow.b3 <= ip->dst.b3 && ip->dst.b3 <= pItem->dst.addrHigh.b3)
&& (pItem->dst.addrLow.b4 <= ip->dst.b4 && ip->dst.b4 <= pItem->dst.addrHigh.b4)
&& (pItem->dst.portLow <= tcp->dstPort && tcp->dstPort <= pItem->dst.portHigh) )
||
( ( pItem->src.addrLow.b1 <= ip->dst.b1 && ip->dst.b1 <= pItem->src.addrHigh.b1)
&& (pItem->src.addrLow.b2 <= ip->dst.b2 && ip->dst.b2 <= pItem->src.addrHigh.b2)
&& (pItem->src.addrLow.b3 <= ip->dst.b3 && ip->dst.b3 <= pItem->src.addrHigh.b3)
&& (pItem->src.addrLow.b4 <= ip->dst.b4 && ip->dst.b4 <= pItem->src.addrHigh.b4)
&& (pItem->src.portLow <= tcp->dstPort && tcp->dstPort <= pItem->src.portHigh)
&& (pItem->dst.addrLow.b1 <= ip->src.b1 && ip->src.b1 <= pItem->dst.addrHigh.b1)
&& (pItem->dst.addrLow.b2 <= ip->src.b2 && ip->src.b2 <= pItem->dst.addrHigh.b2)
&& (pItem->dst.addrLow.b3 <= ip->src.b3 && ip->src.b3 <= pItem->dst.addrHigh.b3)
&& (pItem->dst.addrLow.b4 <= ip->src.b4 && ip->src.b4 <= pItem->dst.addrHigh.b4)
&& (pItem->dst.portLow <= tcp->srcPort && tcp->srcPort <= pItem->dst.portHigh) ) )
{
if( pItem->permit == ACL_DENY )
result = TRUE;
else
result = FALSE;
break;
}
}
return result;
}
void ClearAcl(CPtrList *pList)
{
if( !pList )
return;
for(POSITION pos = pList->GetHeadPosition(); pos != NULL; )
{
ACL_ITEM *pItem = (ACL_ITEM *)pList->GetNext( pos );
delete pItem;
}
pList->RemoveAll();
}
//make a reset tcp packet in ether packet
BOOL MakeRstTcpPacket(const ETHERNET* ether, const IP* ip, const TCP* tcp, BOOL bSameDirection,
WORD dataLen, BYTE* buffer, DWORD bufferSize, DWORD *packetLength,
BOOL bReplySynToSyn, BOOL bImpostureData)
{
//check size of buffer
if( bufferSize < sizeof(ETHERNET) + sizeof(IP) + sizeof(TCP) )
return FALSE;
if( bImpostureData )
{
if( dataLen == 0 )
return FALSE;
if( dataLen >= 100 && (dataLen - 100) % 20 == 0 )
return FALSE;
}
//preparation
ETHERNET *pEther = (ETHERNET*)buffer;
IP *pIp = (IP*)(pEther+1);
TCP *pTcp = (TCP*)(pIp+1);
BYTE *pData = (BYTE *)(pTcp+1);
DWORD fakeDataLength = 0;
*packetLength = sizeof(ETHERNET) + sizeof(IP) + sizeof(TCP);
if( bImpostureData )
{
fakeDataLength = 100 + (rand()%20)*20;
*packetLength = sizeof(ETHERNET) + sizeof(IP) + sizeof(TCP) + fakeDataLength;
}
//main process start here
//hardware address setting
if( bSameDirection )
{
*pEther = *ether;
}
else
{
memcpy(pEther->dst, ether->src, ETHERNET_ADDR_LEN);
memcpy(pEther->src, ether->dst, ETHERNET_ADDR_LEN);
pEther->protocol = ether->protocol;
}
//ip layer setting
pIp->hl = 5;
pIp->v = 4;
pIp->tos = 0;
if( bImpostureData )
pIp->len = htons(sizeof(IP) + sizeof(TCP) + fakeDataLength); //include ip header and tcp header and tcp data
else
pIp->len = htons(sizeof(IP) + sizeof(TCP));
pIp->id = htons(rand());
pIp->offset = 0;
pIp->mf = 0;
pIp->rv = 0;
pIp->df = 1;
*(WORD*)( (BYTE*)pIp + 6 ) = htons( *(WORD*)( (BYTE*)pIp + 6 ) );
pIp->ttl = 0x80;
pIp->protocol = IP_PROTOCOL_TCP;
pIp->checksum = htons(0);
if( bSameDirection )
{
pIp->src = ip->src;
pIp->dst = ip->dst;
}
else
{
pIp->src = ip->dst;
pIp->dst = ip->src;
}
pIp->checksum = GetCheckSum((const WORD*)pIp, 20);
//tcp layer setting
if( bSameDirection )
{
pTcp->srcPort = htons(tcp->srcPort);
pTcp->dstPort = htons(tcp->dstPort);
}
else
{
pTcp->srcPort = htons(tcp->dstPort);
pTcp->dstPort = htons(tcp->srcPort);
}
*(WORD*)(((BYTE*)pTcp)+12) = 0;
pTcp->hl = 5;
pTcp->window = htons(32345); //htons(0);
pTcp->checksum = htons(0);
pTcp->urgPoint = htons(0);
if( bSameDirection )
{
if( tcp->syn && !tcp->ack )
{
pTcp->rst = 1;
pTcp->ack = 0;
pTcp->seqNum = htonl(tcp->seqNum + 1);
pTcp->ackNum = htonl(0);
}
else if( tcp->syn && tcp->ack )
{
pTcp->rst = 1;
pTcp->ack = 1;
pTcp->seqNum = htonl(tcp->seqNum + 1);
pTcp->ackNum = htonl(tcp->ackNum); //htonl(0);
}
else
{
if( bImpostureData )
{
pTcp->window = htons(32345); //htons(tcp->window);
pTcp->ack = 1;
pTcp->seqNum = htonl(tcp->seqNum + dataLen);
pTcp->ackNum = htonl(tcp->ackNum);
for(int i=(fakeDataLength/2)-1; i>=0; i--) ((WORD*)pData)[i] = rand();
}
else
{
pTcp->rst = 1;
pTcp->ack = 1;
pTcp->seqNum = htonl(tcp->seqNum + dataLen);
pTcp->ackNum = htonl(tcp->ackNum); //htonl(0);
}
}
}
else
{
if( tcp->syn && !tcp->ack )
{
if( bReplySynToSyn )
{
//another method to break down a TCP connection
//we can send a fake SYN+ACK packet repling a SYN packet
//instead of send a fake RST+ACK
pTcp->syn = 1;
pTcp->ack = 1;
pTcp->seqNum = htonl( (rand() << 16) + rand() );
pTcp->ackNum = htonl(tcp->seqNum + 1);
pTcp->window = htons(32345); //htons(0x8000);
}
else
{
pTcp->rst = 1;
pTcp->ack = 1;
pTcp->seqNum = htonl(0);
pTcp->ackNum = htonl(tcp->seqNum + 1);
}
}
else if( tcp->syn && tcp->ack )
{
pTcp->rst = 1;
pTcp->ack = 1;
pTcp->seqNum = htonl(tcp->ackNum);
pTcp->ackNum = htonl(tcp->seqNum + 1);//htonl(0);
}
else
{
if( bImpostureData )
{
pTcp->window = htons(32345); //htons(tcp->window);
pTcp->ack = 1;
pTcp->seqNum = htonl(tcp->ackNum);
pTcp->ackNum = htonl(tcp->seqNum + dataLen);
for(int i=(fakeDataLength/2)-1; i>=0; i--) ((WORD*)pData)[i] = rand();
}
else
{
pTcp->rst = 1;
pTcp->ack = 1;
pTcp->seqNum = htonl(tcp->ackNum);
pTcp->ackNum = htonl(tcp->seqNum + dataLen); //htonl(0);
}
}
}
//convert control field from host format to network format
*(WORD*)( (BYTE*)pTcp+12 ) = htons( *(WORD*)( (BYTE*)pTcp+12 ) );
//calculate tcp checksum
if( bImpostureData )
pTcp->checksum = GetTcpCheckSum(pTcp, pIp, sizeof(TCP) + fakeDataLength);
else
pTcp->checksum = GetTcpCheckSum(pTcp, pIp, sizeof(TCP));
return TRUE;
}
struct ICMP_UNREACHABLE
{
BYTE type; //must be 3
BYTE code;
WORD checksum;
DWORD unused;
};
//make a reset tcp packet in ether packet
BOOL MakeICMPUnreachablePacket(const ETHERNET* ether, const IP* ip, const BYTE* ipDigest, DWORD ipDigestLen,
BYTE* buffer, DWORD bufferSize, DWORD *packetLength)
{
//check size of buffer
if( bufferSize < sizeof(ETHERNET) + sizeof(IP) + sizeof(ICMP_UNREACHABLE) + ipDigestLen )
return FALSE;
//preparation
*packetLength = sizeof(ETHERNET) + sizeof(IP) + sizeof(ICMP_UNREACHABLE) + ipDigestLen;
ETHERNET *pEther = (ETHERNET*)buffer;
IP *pIp = (IP*)(pEther+1);
ICMP_UNREACHABLE *pIcmp = (ICMP_UNREACHABLE *)(pIp+1);
//main process start here
//hardware setting
memcpy(pEther->dst, ether->src, ETHERNET_ADDR_LEN);
memcpy(pEther->src, ether->dst, ETHERNET_ADDR_LEN);
pEther->protocol = ether->protocol;
//ip layer setting
pIp->hl = 5;
pIp->v = 4;
pIp->tos = 0;
pIp->len = htons(sizeof(IP) + sizeof(ICMP_UNREACHABLE) + ipDigestLen); //include ip header and tcp header
pIp->id = htons(rand());
pIp->offset = 0;
pIp->mf = 0;
pIp->rv = 0;
pIp->df = 1;
*(WORD*)( (BYTE*)pIp + 6 ) = htons( *(WORD*)( (BYTE*)pIp + 6 ) );
pIp->ttl = 0x80;
pIp->protocol = IP_PROTOCOL_ICMP;
pIp->checksum = htons(0);
pIp->src = ip->dst;
pIp->dst = ip->src;
pIp->checksum = GetCheckSum((const WORD*)pIp, 20);
//icmp layer setting
pIcmp->type = 3;
pIcmp->code = 0;
pIcmp->checksum = htons(0);
pIcmp->unused = htonl(0);
memcpy( pIcmp + 1, ipDigest, ipDigestLen);
pIcmp->checksum = GetCheckSum( (const WORD*)pIcmp, sizeof(*pIcmp)+ipDigestLen );
return TRUE;
}
BOOL MakeRstTcpPacketV2(const BYTE etherSrc[ETHERNET_ADDR_LEN], const BYTE etherDst[ETHERNET_ADDR_LEN],
const IP_ADDR *ipSrc, const IP_ADDR *ipDst,
const WORD portSrc, const WORD portDst,
const DWORD seqSrc, const DWORD seqDst,
BYTE* buffer, DWORD bufferSize, DWORD *packetLength)
{
//check size of buffer
if( bufferSize < sizeof(ETHERNET) + sizeof(IP) + sizeof(TCP) )
return FALSE;
//preparation
ETHERNET *pEther = (ETHERNET*)buffer;
IP *pIp = (IP*)(pEther+1);
TCP *pTcp = (TCP*)(pIp+1);
*packetLength = sizeof(ETHERNET) + sizeof(IP) + sizeof(TCP);
//hardware address setting
memcpy(pEther->dst, etherSrc, ETHERNET_ADDR_LEN);
memcpy(pEther->src, etherDst, ETHERNET_ADDR_LEN);
pEther->protocol = ETHER_PROTOCOL_IP;
//ip layer setting
pIp->hl = 5;
pIp->v = 4;
pIp->tos = 0;
pIp->len = htons(sizeof(IP) + sizeof(TCP));
pIp->id = htons(rand());
pIp->offset = 0;
pIp->mf = 0;
pIp->rv = 0;
pIp->df = 1;
*(WORD*)( (BYTE*)pIp + 6 ) = htons( *(WORD*)( (BYTE*)pIp + 6 ) );
pIp->ttl = 0xff;
pIp->protocol = IP_PROTOCOL_TCP;
pIp->checksum = htons(0);
pIp->src = *ipSrc;
pIp->dst = *ipDst;
pIp->checksum = GetCheckSum((const WORD*)pIp, 20);
//tcp layer setting
pTcp->srcPort = htons(portSrc);
pTcp->dstPort = htons(portDst);
pTcp->seqNum = htonl(seqSrc);
pTcp->ackNum = htonl(seqDst);
*(WORD*)(((BYTE*)pTcp)+12) = 0;
pTcp->hl = 5;
pTcp->rst = 1;
pTcp->ack = 1;
pTcp->window = htons(32346); //htons(0);
pTcp->checksum = htons(0);
pTcp->urgPoint = htons(0);
//convert control field from host format to network format
*(WORD*)( (BYTE*)pTcp+12 ) = htons( *(WORD*)( (BYTE*)pTcp+12 ) );
pTcp->checksum = GetTcpCheckSum(pTcp, pIp, sizeof(TCP));
return TRUE;
}