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; 
}