#include "kalasag.h"
#include "kalasag_io.h"
#include "kalasag_util.h"
/* Global variables */
char gblScanDetectHost[MAXSTATE][IPMAXBUF];
char gblKillRoute[MAXBUF];
char gblKillHostsDeny[MAXBUF];
char gblKillRunCmd[MAXBUF];
char gblBlockedFile[MAXBUF];
char gblHistoryFile[MAXBUF];
char gblIgnoreFile[MAXBUF];
char gblDetectionType[MAXBUF];
int gblScanDetectCount = 0;
int gblBlockTCP = 0;
int gblBlockUDP = 0;
int gblRunCmdFirst = 0;
int gblResolveHost = 0;
int gblConfigTriggerCount = 0;
int main(int argc, char *argv[])
{
if (argc != 2) {
Usage();
Exit(ERROR);
}
if ((geteuid()) && (getuid()) != 0) {
printf("You need to be root to run this.\n");
Exit(ERROR);
}
/* Cheesy arg parser. Some systems don't support getopt and I don't want to port it. */
&& (strcmp(argv
[1], "-sudp")) && (strcmp(argv
[1], "-audp")) != 0) {
Usage();
Exit(ERROR);
} else {
Start();
/* This copies the startup type to a global for later use */
if ((SafeStrncpy
(gblDetectionType
, strstr(argv
[1], "-") + 1, MAXBUF
))
== NULL) {
Log("adminalert: ERROR: Error setting internal scan detection type.\n");
printf("ERROR: Error setting internal scan detection type.\n");
printf("ERROR: Kalasag is shutting down!\n");
Exit(ERROR);
} else if (CheckConfig() == FALSE) {
Log("adminalert: ERROR: Configuration files are missing/corrupted. Shutting down.\n");
printf("ERROR: Configuration files are missing/corrupted.\n");
("ERROR: Check your syslog for a more detailed error message.\n");
printf("ERROR: Kalasag is shutting down!\n");
Exit(ERROR);
} else if (InitConfig() == FALSE) {
Log("adminalert: ERROR: Your config file is corrupted/missing mandatory option! Shutting down.\n");
("ERROR: Your config file is corrupted/missing mandatory option!\n");
("ERROR: Check your syslog for a more detailed error message.\n");
printf("ERROR: Kalasag is shutting down!\n");
Exit(ERROR);
}
#ifndef NODAEMON
else if (DaemonSeed() == ERROR) {
Log("adminalert: ERROR: could not go into daemon mode. Shutting down.\n");
("ERROR: could not go into daemon mode. Shutting down.\n");
Exit(ERROR);
}
#endif
}
if (strcmp(argv
[1], "-tcp") == 0) {
if (KalasagModeTCP() == ERROR) {
Log("adminalert: ERROR: could not go into Kalasag mode. Shutting down.\n");
Exit(ERROR);
}
}
#ifdef SUPPORT_STEALTH
else if (strcmp(argv
[1], "-stcp") == 0) {
if (KalasagStealthModeTCP() == ERROR) {
Log("adminalert: ERROR: could not go into Kalasag mode. Shutting down.\n");
Exit(ERROR);
}
} else if (strcmp(argv
[1], "-atcp") == 0) {
if (KalasagAdvancedStealthModeTCP() == ERROR) {
Log("adminalert: ERROR: could not go into Kalasag mode. Shutting down.\n");
Exit(ERROR);
}
} else if (strcmp(argv
[1], "-sudp") == 0) {
if (KalasagStealthModeUDP() == ERROR) {
Log("adminalert: ERROR: could not go into Kalasag mode. Shutting down.\n");
Exit(ERROR);
}
} else if (strcmp(argv
[1], "-audp") == 0) {
if (KalasagAdvancedStealthModeUDP() == ERROR) {
Log("adminalert: ERROR: could not go into Kalasag mode. Shutting down.\n");
Exit(ERROR);
}
}
#endif
else if (strcmp(argv
[1], "-udp") == 0) {
if (KalasagModeUDP() == ERROR) {
Log("adminalert: ERROR: could not go into Kalasag mode. Shutting down.\n");
Exit(ERROR);
}
}
Exit(TRUE);
/* shuts up compiler warning */
return (0);
}
/****************************************************************/
/* Reads generic config options into global variables */
/****************************************************************/
int InitConfig(void)
{
FILE *input;
char configToken[MAXBUF];
gblBlockTCP = CheckFlag("BLOCK_TCP");
gblBlockUDP = CheckFlag("BLOCK_UDP");
gblResolveHost = CheckFlag("RESOLVE_HOST");
memset(gblKillRoute
, '\0', MAXBUF
);
memset(gblKillHostsDeny
, '\0', MAXBUF
);
memset(gblKillRunCmd
, '\0', MAXBUF
);
if ((ConfigTokenRetrieve("SCAN_TRIGGER", configToken)) == FALSE) {
Log("adminalert: ERROR: Could not read SCAN_TRIGGER option from config file. Disabling SCAN DETECTION TRIGGER");
gblConfigTriggerCount = 0;
} else {
#ifdef DEBUG
Log("debug: InitConfig: retrieved SCAN_TRIGGER option: %s \n",
configToken);
#endif
gblConfigTriggerCount
= atoi(configToken
);
}
if ((ConfigTokenRetrieve("KILL_ROUTE", gblKillRoute)) == TRUE) {
#ifdef DEBUG
Log("debug: InitConfig: retrieved KILL_ROUTE option: %s \n",
gblKillRoute);
#endif
} else {
#ifdef DEBUG
Log("debug: InitConfig: KILL_ROUTE option NOT FOUND.\n");
#endif
}
if ((ConfigTokenRetrieve("KILL_HOSTS_DENY", gblKillHostsDeny)) == TRUE) {
#ifdef DEBUG
Log("debug: InitConfig: retrieved KILL_HOSTS_DENY option: %s \n",
gblKillHostsDeny);
#endif
} else {
#ifdef DEBUG
Log("debug: InitConfig: KILL_HOSTS_DENY option NOT FOUND.\n");
#endif
}
if ((ConfigTokenRetrieve("KILL_RUN_CMD", gblKillRunCmd)) == TRUE) {
#ifdef DEBUG
Log("debug: InitConfig: retrieved KILL_RUN_CMD option: %s \n",
gblKillRunCmd);
#endif
/* Check the order we should run the KILL_RUN_CMD */
/* Default is to run the command after blocking */
gblRunCmdFirst = CheckFlag("KILL_RUN_CMD_FIRST");
} else {
#ifdef DEBUG
Log("debug: InitConfig: KILL_RUN_CMD option NOT FOUND.\n");
#endif
}
if ((ConfigTokenRetrieve("BLOCKED_FILE", gblBlockedFile)) == TRUE) {
if (strlen(gblBlockedFile
) < MAXBUF
- 5) {
strncat(gblBlockedFile
, gblDetectionType
, 4);
} else {
Log("adminalert: ERROR: Blocked filename is too long to append detection type file extension: %s.\n", gblBlockedFile);
return (FALSE);
}
#ifdef DEBUG
Log("debug: InitConfig: retrieved BLOCKED_FILE option: %s \n",
gblBlockedFile);
Log("debug: CheckConfig: Removing old block file: %s \n",
gblBlockedFile);
#endif
if ((input
= fopen(gblBlockedFile
, "w")) == NULL
) {
Log("adminalert: ERROR: Cannot delete blocked file on startup: %s.\n", gblBlockedFile);
return (FALSE);
} else
} else {
Log("InitConfig: Cannot retrieve BLOCKED_FILE option! Aborting\n");
return (FALSE);
}
if ((ConfigTokenRetrieve("HISTORY_FILE", gblHistoryFile)) == TRUE) {
#ifdef DEBUG
Log("debug: InitConfig: retrieved HISTORY_FILE option: %s \n",
gblHistoryFile);
#endif
} else {
Log("InitConfig: Cannot retrieve HISTORY_FILE option! Aborting\n");
return (FALSE);
}
if ((ConfigTokenRetrieve("IGNORE_FILE", gblIgnoreFile)) == TRUE) {
#ifdef DEBUG
Log("debug: InitConfig: retrieved IGNORE_FILE option: %s \n",
gblIgnoreFile);
#endif
} else {
Log("InitConfig: Cannot retrieve IGNORE_FILE option! Aborting\n");
return (FALSE);
}
return (TRUE);
}
#ifdef SUPPORT_STEALTH
/* Read in a TCP packet taking into account IP options and other */
/* errors */
int PacketReadTCP(int socket, struct iphdr *ipPtr, struct tcphdr *tcpPtr)
{
char packetBuffer[TCPPACKETLEN];
struct in_addr addr;
bzero(ipPtr, sizeof(struct iphdr));
bzero(tcpPtr, sizeof(struct tcphdr));
if (read(socket, packetBuffer, TCPPACKETLEN) == ERROR)
return (ERROR);
memcpy(ipPtr
, (struct iphdr
*) packetBuffer
, sizeof(struct iphdr
));
if ((ipPtr->ihl < 5) || (ipPtr->ihl > 15)) {
addr.s_addr = (u_int) ipPtr->saddr;
Log("attackalert: Illegal IP header length detected in TCP packet: %d from (possible) host: %s\n", ipPtr->ihl, inet_ntoa(addr));
return (FALSE);
} else {
(struct tcphdr *) (packetBuffer + ((ipPtr->ihl) * 4)),
sizeof(struct tcphdr));
return (TRUE);
}
}
/* Read in a UDP packet taking into account IP options and other */
/* errors */
int PacketReadUDP(int socket, struct iphdr *ipPtr, struct udphdr *udpPtr)
{
char packetBuffer[UDPPACKETLEN];
struct in_addr addr;
bzero(ipPtr, sizeof(struct iphdr));
bzero(udpPtr, sizeof(struct udphdr));
if (read(socket, packetBuffer, UDPPACKETLEN) == ERROR)
return (ERROR);
memcpy(ipPtr
, (struct iphdr
*) packetBuffer
, sizeof(struct iphdr
));
if ((ipPtr->ihl < 5) || (ipPtr->ihl > 15)) {
addr.s_addr = (u_int) ipPtr->saddr;
Log("attackalert: Illegal IP header length detected in UDP packet: %d from (possible) host: %s\n", ipPtr->ihl, inet_ntoa(addr));
return (FALSE);
} else {
(struct udphdr *) (packetBuffer + ((ipPtr->ihl) * 4)),
sizeof(struct udphdr));
return (TRUE);
}
}
/****************************************************************/
/* Stealth scan detection Mode One */
/* */
/* This mode will read in a list of ports to monitor and will */
/* then open a raw socket to look for packets matching the port. */
/* */
/****************************************************************/
int KalasagStealthModeTCP(void)
{
struct sockaddr_in client, server;
int portCount = 0, portCount2 = 0, ports[MAXSOCKS], ports2[MAXSOCKS];
int count = 0, scanDetectTrigger = TRUE, gotBound = FALSE, result =
TRUE;
int openSockfd = 0, incomingPort = 0;
char *temp, target[IPMAXBUF], configToken[MAXBUF];
char resolvedHost[DNSMAXBUF], *packetType;
struct in_addr addr;
struct iphdr ip;
struct tcphdr tcp;
if ((ConfigTokenRetrieve("TCP_PORTS", configToken)) == FALSE) {
Log("adminalert: ERROR: Could not read TCP_PORTS option from config file");
return (ERROR);
}
/* break out the ports */
if ((temp
= (char *) strtok(configToken
, ",")) != NULL
) {
for (count = 1; count < MAXSOCKS; count++) {
if ((temp
= (char *) strtok(NULL
, ",")) != NULL
)
ports
[count
] = atoi(temp
);
else
break;
}
portCount = count;
} else {
Log("adminalert: ERROR: No TCP ports supplied in config file. Aborting");
return (ERROR);
}
/* ok, now check if they have a network daemon on the socket already, if they do */
/* then skip that port because it will cause false alarms */
for (count = 0; count < portCount; count++) {
Log("adminalert: Going into stealth listen mode on TCP port: %d\n",
ports[count]);
if ((openSockfd = OpenTCPSocket()) == ERROR) {
Log("adminalert: ERROR: could not open TCP socket. Aborting.\n");
return (ERROR);
}
if (BindSocket(openSockfd, client, server, ports[count]) == ERROR)
Log("adminalert: ERROR: Socket %d is in use and will not be monitored. Attempting to continue\n", ports[count]);
else { /* well we at least bound to one socket so we'll continue */
gotBound = TRUE;
ports2[portCount2++] = ports[count];
}
close(openSockfd);
}
/* if we didn't bind to anything then abort */
if (gotBound == FALSE) {
Log("adminalert: ERROR: All supplied TCP sockets are in use and will not be listened to. Shutting down.\n");
return (ERROR);
}
/* Open our raw socket for network IO */
if ((openSockfd = OpenRAWTCPSocket()) == ERROR) {
Log("adminalert: ERROR: could not open RAW TCP socket. Aborting.\n");
return (ERROR);
}
Log("adminalert: Kalasag is now active and listening.\n");
/* main detection loop */
for (;;) {
if (PacketReadTCP(openSockfd, &ip, &tcp) != TRUE)
continue;
incomingPort = ntohs(tcp.dest);
/* check for an ACK/RST to weed out established connections in case the user */
/* is monitoring high ephemeral port numbers */
if ((tcp.ack != 1) && (tcp.rst != 1)) {
/* this iterates the list of ports looking for a match */
for (count = 0; count < portCount; count++) {
if (incomingPort == ports2[count]) {
if (SmartVerifyTCP(client, server, incomingPort) ==
TRUE)
break;
/* copy the clients address into our buffer for nuking */
addr.s_addr = (u_int) ip.saddr;
SafeStrncpy(target, (char *) inet_ntoa(addr),
IPMAXBUF);
/* check if we should ignore this IP */
result = NeverBlock(target, gblIgnoreFile);
if (result == ERROR) {
Log("attackalert: ERROR: cannot open ignore file. Blocking host anyway.\n");
result = FALSE;
}
if (result == FALSE) {
/* check if they've visited before */
scanDetectTrigger = CheckStateEngine(target);
if (scanDetectTrigger == TRUE) {
if (gblResolveHost) { /* Do they want DNS resolution? */
if (CleanAndResolve(resolvedHost, target)
!= TRUE) {
Log("attackalert: ERROR: Error resolving host. \
resolving disabled for this host.\n");
target);
}
} else {
target);
}
packetType = ReportPacketType(tcp);
Log("attackalert: %s from host: %s/%s to TCP port: %d", packetType, resolvedHost, target, ports2[count]);
/* Report on options present */
if (ip.ihl > 5)
Log("attackalert: Packet from host: %s/%s to TCP port: %d has IP options set (detection avoidance technique).", resolvedHost, target, ports2[count]);
/* check if this target is already blocked */
if (IsBlocked(target, gblBlockedFile) == FALSE) {
/* toast the prick */
if (DisposeTCP(target, ports2[count]) !=
TRUE)
Log("attackalert: ERROR: Could not block host %s/%s !!", resolvedHost, target);
else
WriteBlocked(target, resolvedHost,
ports2[count],
gblBlockedFile,
gblHistoryFile, "TCP");
} /* end IsBlocked check */
else
Log("attackalert: Host: %s/%s is already blocked Ignoring", resolvedHost, target);
} /* end if(scanDetectTrigger) */
} /* end if(never block) check */
break; /* get out of for(count) loop above */
} /* end if(incoming port) == protected port */
} /* end for( check for protected port loop ) loop */
} /* end if(TH_ACK) check */
} /* end for( ; ; ) loop */
} /* end KalasagStealthModeTCP */
/****************************************************************/
/* Advanced Stealth scan detection Mode One */
/* */
/* This mode will see what ports are listening below 1024 */
/* and will then monitor all the rest. This is very sensitive */
/* and will react on any packet hitting any monitored port, */
/* regardless of TCP flags set */
/* */
/****************************************************************/
int KalasagAdvancedStealthModeTCP(void)
{
struct sockaddr_in client, server;
int result = TRUE, scanDetectTrigger = TRUE, hotPort = TRUE;
int openSockfd = 0, incomingPort = 0, smartVerify = FALSE;
unsigned int advancedPorts = 1024;
unsigned int count = 0, inUsePorts[MAXSOCKS], portCount = 0;
char target[IPMAXBUF], configToken[MAXBUF];
char resolvedHost[DNSMAXBUF], *temp, *packetType;
struct in_addr addr;
struct iphdr ip;
struct tcphdr tcp;
if ((ConfigTokenRetrieve("ADVANCED_PORTS_TCP", configToken)) == FALSE) {
Log("adminalert: ERROR: Could not read ADVANCED_PORTS_TCP option from config file. Assuming 1024.");
advancedPorts = 1024;
} else
advancedPorts
= atoi(configToken
);
Log("adminalert: Advanced mode will monitor first %d ports",
advancedPorts);
/* try to bind to all ports below 1024, any that are taken we exclude later */
for (count = 0; count < advancedPorts; count++) {
if ((openSockfd = OpenTCPSocket()) == ERROR) {
Log("adminalert: ERROR: could not open TCP socket. Aborting.\n");
return (ERROR);
}
if (BindSocket(openSockfd, client, server, count) == ERROR)
inUsePorts[portCount++] = count;
close(openSockfd);
}
if ((ConfigTokenRetrieve("ADVANCED_EXCLUDE_TCP", configToken)) !=
FALSE) {
/* break out the ports */
if ((temp
= (char *) strtok(configToken
, ",")) != NULL
) {
inUsePorts
[portCount
++] = atoi(temp
);
Log("adminalert: Advanced mode will manually exclude port: %d ", inUsePorts[portCount - 1]);
for (count = 0; count < MAXSOCKS; count++) {
if ((temp
= (char *) strtok(NULL
, ",")) != NULL
) {
inUsePorts
[portCount
++] = atoi(temp
);
Log("adminalert: Advanced mode will manually exclude port: %d ", inUsePorts[portCount - 1]);
} else
break;
}
}
} else
Log("adminalert: Advanced mode will manually exclude no ports");
for (count = 0; count < portCount; count++)
Log("adminalert: Advanced Stealth scan detection mode activated. Ignored TCP port: %d\n", inUsePorts[count]);
/* open raw socket for reading */
if ((openSockfd = OpenRAWTCPSocket()) == ERROR) {
Log("adminalert: ERROR: could not open RAW TCP socket. Aborting.\n");
return (ERROR);
}
Log("adminalert: Kalasag is now active and listening.\n");
/* main detection loop */
for (;;) {
if (PacketReadTCP(openSockfd, &ip, &tcp) != TRUE)
continue;
incomingPort = ntohs(tcp.dest);
/* don't monitor packets with ACK set (established) or RST */
/* This could be a hole in some cases */
if ((tcp.ack != 1) && (tcp.rst != 1)) {
/* check if we should ignore this connection to this port */
for (count = 0; count < portCount; count++) {
if ((incomingPort == inUsePorts[count])
|| (incomingPort >= advancedPorts)) {
hotPort = FALSE;
break;
} else
hotPort = TRUE;
}
if (hotPort) {
smartVerify = SmartVerifyTCP(client, server, incomingPort);
if (smartVerify != TRUE) {
addr.s_addr = (u_int) ip.saddr;
SafeStrncpy(target, (char *) inet_ntoa(addr),
IPMAXBUF);
/* check if we should ignore this IP */
result = NeverBlock(target, gblIgnoreFile);
if (result == ERROR) {
Log("attackalert: ERROR: cannot open ignore file. Blocking host anyway.\n");
result = FALSE;
}
if (result == FALSE) {
/* check if they've visited before */
scanDetectTrigger = CheckStateEngine(target);
if (scanDetectTrigger == TRUE) {
if (gblResolveHost) { /* Do they want DNS resolution? */
if (CleanAndResolve(resolvedHost, target)
!= TRUE) {
Log("attackalert: ERROR: Error resolving host. \
resolving disabled for this host.\n");
target);
}
} else {
target);
}
packetType = ReportPacketType(tcp);
Log("attackalert: %s from host: %s/%s to TCP port: %d", packetType, resolvedHost, target, incomingPort);
/* Report on options present */
if (ip.ihl > 5)
Log("attackalert: Packet from host: %s/%s to TCP port: %d has IP options set (detection avoidance technique).", resolvedHost, target, incomingPort);
/* check if this target is already blocked */
if (IsBlocked(target, gblBlockedFile) == FALSE) {
/* toast the prick */
if (DisposeTCP(target, incomingPort) !=
TRUE)
Log("attackalert: ERROR: Could not block host %s/%s!!", resolvedHost, target);
else
WriteBlocked(target, resolvedHost,
incomingPort,
gblBlockedFile,
gblHistoryFile, "TCP");
} /* end IsBlocked check */
else
Log("attackalert: Host: %s/%s is already blocked Ignoring", resolvedHost, target);
} /* end if(scanDetectTrigger) */
} /* end if(never block) check */
} /* end if(smartVerify) */
} /* end if(hotPort) */
} /* end if(TH_ACK) */
} /* end for( ; ; ) loop */
}
/* end KalasagAdvancedStealthModeTCP */
/****************************************************************/
/* UDP "stealth" scan detection */
/* */
/* This mode will read in a list of ports to monitor and will */
/* then open a raw socket to look for packets matching the port. */
/* */
/****************************************************************/
int KalasagStealthModeUDP(void)
{
struct sockaddr_in client, server;
int portCount = 0, portCount2 = 0, ports[MAXSOCKS], ports2[MAXSOCKS],
result = TRUE;
int count = 0, scanDetectTrigger = TRUE, gotBound = FALSE;
int openSockfd = 0, incomingPort = 0;
char *temp, target[IPMAXBUF], configToken[MAXBUF];
char resolvedHost[DNSMAXBUF];
struct in_addr addr;
struct iphdr ip;
struct udphdr udp;
if ((ConfigTokenRetrieve("UDP_PORTS", configToken)) == FALSE) {
Log("adminalert: ERROR: Could not read UDP_PORTS option from config file");
return (ERROR);
}
/* break out the ports */
if ((temp
= (char *) strtok(configToken
, ",")) != NULL
) {
for (count = 1; count < MAXSOCKS; count++) {
if ((temp
= (char *) strtok(NULL
, ",")) != NULL
)
ports
[count
] = atoi(temp
);
else
break;
}
portCount = count;
} else {
Log("adminalert: ERROR: No UDP ports supplied in config file. Aborting");
return (ERROR);
}
/* ok, now check if they have a network daemon on the socket already, if they do */
/* then skip that port because it will cause false alarms */
for (count = 0; count < portCount; count++) {
Log("adminalert: Going into stealth listen mode on UDP port: %d\n",
ports[count]);
if ((openSockfd = OpenUDPSocket()) == ERROR) {
Log("adminalert: ERROR: could not open UDP socket. Aborting.\n");
return (ERROR);
}
if (BindSocket(openSockfd, client, server, ports[count]) == ERROR)
Log("adminalert: ERROR: Socket %d is in use and will not be monitored. Attempting to continue\n", ports[count]);
else {
gotBound = TRUE;
ports2[portCount2++] = ports[count];
}
close(openSockfd);
}
if (gotBound == FALSE) {
Log("adminalert: ERROR: All supplied UDP sockets are in use and will not be listened to. Shutting down.\n");
return (ERROR);
}
if ((openSockfd = OpenRAWUDPSocket()) == ERROR) {
Log("adminalert: ERROR: could not open RAW UDP socket. Aborting.\n");
return (ERROR);
}
Log("adminalert: Kalasag is now active and listening.\n");
/* main detection loop */
for (;;) {
if (PacketReadUDP(openSockfd, &ip, &udp) != TRUE)
continue;
incomingPort = ntohs(udp.dest);
/* this iterates the list of ports looking for a match */
for (count = 0; count < portCount; count++) {
if (incomingPort == ports2[count]) {
if (SmartVerifyUDP(client, server, incomingPort) == TRUE)
break;
addr.s_addr = (u_int) ip.saddr;
SafeStrncpy(target, (char *) inet_ntoa(addr), IPMAXBUF);
/* check if we should ignore this IP */
result = NeverBlock(target, gblIgnoreFile);
if (result == ERROR) {
Log("attackalert: ERROR: cannot open ignore file. Blocking host anyway.\n");
result = FALSE;
}
if (result == FALSE) {
/* check if they've visited before */
scanDetectTrigger = CheckStateEngine(target);
if (scanDetectTrigger == TRUE) {
if (gblResolveHost) { /* Do they want DNS resolution? */
if (CleanAndResolve(resolvedHost, target) !=
TRUE) {
Log("attackalert: ERROR: Error resolving host. \
resolving disabled for this host.\n");
target);
}
} else {
target);
}
Log("attackalert: UDP scan from host: %s/%s to UDP port: %d", resolvedHost, target, ports2[count]);
/* Report on options present */
if (ip.ihl > 5)
Log("attackalert: Packet from host: %s/%s to UDP port: %d has IP options set (detection avoidance technique).", resolvedHost, target, incomingPort);
/* check if this target is already blocked */
if (IsBlocked(target, gblBlockedFile) == FALSE) {
if (DisposeUDP(target, ports2[count]) != TRUE)
Log("attackalert: ERROR: Could not block host %s/%s!!", resolvedHost, target);
else
WriteBlocked(target, resolvedHost,
ports2[count], gblBlockedFile,
gblHistoryFile, "UDP");
} /* end IsBlocked check */
else {
Log("attackalert: Host: %s/%s is already blocked Ignoring", resolvedHost, target);
}
} /* end if(scanDetectTrigger) */
} /* end if(never block) check */
break; /* get out of for(count) loop above */
} /* end if(incoming port) == protected port */
} /* end for( check for protected port loop ) loop */
} /* end for( ; ; ) loop */
} /* end KalasagStealthModeUDP */
/****************************************************************/
/* Advanced Stealth scan detection mode for UDP */
/* */
/* This mode will see what ports are listening below 1024 */
/* and will then monitor all the rest. This is very sensitive */
/* and will react on any packet hitting any monitored port. */
/* This is a very dangerous option and is for advanced users */
/* */
/****************************************************************/
int KalasagAdvancedStealthModeUDP(void)
{
struct sockaddr_in client, server;
int result = TRUE, scanDetectTrigger = TRUE, hotPort = TRUE;
int openSockfd = 0, incomingPort = 0, smartVerify = FALSE;
unsigned int advancedPorts = 1024;
unsigned int count = 0, inUsePorts[MAXSOCKS], portCount = 0;
char target[IPMAXBUF], configToken[MAXBUF];
char resolvedHost[DNSMAXBUF], *temp;
struct in_addr addr;
struct iphdr ip;
struct udphdr udp;
if ((ConfigTokenRetrieve("ADVANCED_PORTS_UDP", configToken)) == FALSE) {
Log("adminalert: ERROR: Could not read ADVANCED_PORTS_UDP option from config file. Assuming 1024.");
advancedPorts = 1024;
} else
advancedPorts
= atoi(configToken
);
Log("adminalert: Advanced mode will monitor first %d ports",
advancedPorts);
/* try to bind to all ports below 1024, any that are taken we exclude later */
for (count = 0; count < advancedPorts; count++) {
if ((openSockfd = OpenUDPSocket()) == ERROR) {
Log("adminalert: ERROR: could not open UDP socket. Aborting.\n");
return (ERROR);
}
if (BindSocket(openSockfd, client, server, count) == ERROR)
inUsePorts[portCount++] = count;
close(openSockfd);
}
if ((ConfigTokenRetrieve("ADVANCED_EXCLUDE_UDP", configToken)) !=
FALSE) {
/* break out the ports */
if ((temp
= (char *) strtok(configToken
, ",")) != NULL
) {
inUsePorts
[portCount
++] = atoi(temp
);
Log("adminalert: Advanced mode will manually exclude port: %d ", inUsePorts[portCount - 1]);
for (count = 0; count < MAXSOCKS; count++) {
if ((temp
= (char *) strtok(NULL
, ",")) != NULL
) {
inUsePorts
[portCount
++] = atoi(temp
);
Log("adminalert: Advanced mode will manually exclude port: %d ", inUsePorts[portCount - 1]);
} else
break;
}
}
} else
Log("adminalert: Advanced mode will manually exclude no ports");
for (count = 0; count < portCount; count++)
Log("adminalert: Advanced Stealth scan detection mode activated. Ignored UDP port: %d\n", inUsePorts[count]);
if ((openSockfd = OpenRAWUDPSocket()) == ERROR) {
Log("adminalert: ERROR: could not open RAW UDP socket. Aborting.\n");
return (ERROR);
}
Log("adminalert: Kalasag is now active and listening.\n");
/* main detection loop */
for (;;) {
if (PacketReadUDP(openSockfd, &ip, &udp) != TRUE)
continue;
incomingPort = ntohs(udp.dest);
/* check if we should ignore this connection to this port */
for (count = 0; count < portCount; count++) {
if ((incomingPort == inUsePorts[count])
|| (incomingPort >= advancedPorts)) {
hotPort = FALSE;
break;
} else
hotPort = TRUE;
}
if (hotPort) {
smartVerify = SmartVerifyUDP(client, server, incomingPort);
if (smartVerify != TRUE) {
/* copy the clients address into our buffer for nuking */
addr.s_addr = (u_int) ip.saddr;
SafeStrncpy(target, (char *) inet_ntoa(addr), IPMAXBUF);
/* check if we should ignore this IP */
result = NeverBlock(target, gblIgnoreFile);
if (result == ERROR) {
Log("attackalert: ERROR: cannot open ignore file. Blocking host anyway.\n");
result = FALSE;
}
if (result == FALSE) {
/* check if they've visited before */
scanDetectTrigger = CheckStateEngine(target);
if (scanDetectTrigger == TRUE) {
if (gblResolveHost) { /* Do they want DNS resolution? */
if (CleanAndResolve(resolvedHost, target) !=
TRUE) {
Log("attackalert: ERROR: Error resolving host. \
resolving disabled for this host.\n");
target);
}
} else {
target);
}
Log("attackalert: UDP scan from host: %s/%s to UDP port: %d", resolvedHost, target, incomingPort);
/* Report on options present */
if (ip.ihl > 5)
Log("attackalert: Packet from host: %s/%s to UDP port: %d has IP options set (detection avoidance technique).", resolvedHost, target, incomingPort);
/* check if this target is already blocked */
if (IsBlocked(target, gblBlockedFile) == FALSE) {
if (DisposeUDP(target, incomingPort) != TRUE)
Log("attackalert: ERROR: Could not block host %s/%s!!", resolvedHost, target);
else
WriteBlocked(target, resolvedHost,
incomingPort, gblBlockedFile,
gblHistoryFile, "UDP");
} /* end IsBlocked check */
else
Log("attackalert: Host: %s/%s is already blocked Ignoring", resolvedHost, target);
} /* end if(scanDetectTrigger) */
} /* end if(never block) check */
} /* end if (smartVerify) */
} /* end if(hotPort) */
} /* end for( ; ; ) loop */
}
/* end KalasagAdvancedStealthModeUDP */
#endif
/****************************************************************/
/* Classic detection Mode */
/* */
/* This mode will bind to a list of TCP sockets and wait for */
/* connections to happen. Although the least prone to false */
/* alarms, it also won't detect stealth scans */
/* */
/****************************************************************/
int KalasagModeTCP(void)
{
struct sockaddr_in client, server;
int length, portCount = 0, ports[MAXSOCKS];
int openSockfd[MAXSOCKS], incomingSockfd, result = TRUE;
int count = 0, scanDetectTrigger = TRUE, showBanner =
FALSE, boundPortCount = 0;
int selectResult = 0;
char *temp, target[IPMAXBUF], bannerBuffer[MAXBUF],
configToken[MAXBUF];
char resolvedHost[DNSMAXBUF];
fd_set selectFds;
if ((ConfigTokenRetrieve("TCP_PORTS", configToken)) == FALSE) {
Log("adminalert: ERROR: Could not read TCP_PORTS option from config file");
return (ERROR);
}
/* break out the ports */
if ((temp
= (char *) strtok(configToken
, ",")) != NULL
) {
for (count = 1; count < MAXSOCKS; count++) {
if ((temp
= (char *) strtok(NULL
, ",")) != NULL
)
ports
[count
] = atoi(temp
);
else
break;
}
portCount = count;
} else {
Log("adminalert: ERROR: No TCP ports supplied in config file. Aborting");
return (ERROR);
}
/* read in the banner if one is given */
if ((ConfigTokenRetrieve("PORT_BANNER", configToken)) == TRUE) {
showBanner = TRUE;
SafeStrncpy(bannerBuffer, configToken, MAXBUF);
}
/* setup select call */
FD_ZERO(&selectFds);
for (count = 0; count < portCount; count++) {
Log("adminalert: Going into listen mode on TCP port: %d\n",
ports[count]);
if ((openSockfd[boundPortCount] = OpenTCPSocket()) == ERROR) {
Log("adminalert: ERROR: could not open TCP socket. Aborting.\n");
return (ERROR);
}
if (BindSocket
(openSockfd[boundPortCount], client, server,
ports[count]) == ERROR) {
Log("adminalert: ERROR: could not bind TCP socket: %d. Attempting to continue\n", ports[count]);
} else /* well we at least bound to one socket so we'll continue */
boundPortCount++;
}
/* if we didn't bind to anything then abort */
if (boundPortCount == 0) {
Log("adminalert: ERROR: could not bind ANY TCP sockets. Shutting down.\n");
return (ERROR);
}
length = sizeof(client);
Log("adminalert: Kalasag is now active and listening.\n");
/* main loop for multiplexing/resetting */
for (;;) {
/* set up select call */
for (count = 0; count < boundPortCount; count++)
FD_SET(openSockfd[count], &selectFds);
selectResult =
select(MAXSOCKS, &selectFds, NULL, NULL,
(struct timeval *) NULL);
/* something blew up */
if (selectResult < 0) {
Log("adminalert: ERROR: select call failed. Shutting down.\n");
return (ERROR);
} else if (selectResult == 0) {
#ifdef DEBUG
Log("Select timeout");
#endif
}
/* select is reporting a waiting socket. Poll them all to find out which */
else if (selectResult > 0) {
for (count = 0; count < boundPortCount; count++) {
if (FD_ISSET(openSockfd[count], &selectFds)) {
incomingSockfd =
accept(openSockfd[count],
(struct sockaddr *) &client, &length);
if (incomingSockfd < 0) {
Log("attackalert: Possible stealth scan from unknown host to TCP port: %d (accept failed)", ports[count]);
break;
}
/* copy the clients address into our buffer for nuking */
SafeStrncpy(target,
(char *) inet_ntoa(client.sin_addr),
IPMAXBUF);
/* check if we should ignore this IP */
result = NeverBlock(target, gblIgnoreFile);
if (result == ERROR) {
Log("attackalert: ERROR: cannot open ignore file. Blocking host anyway.\n");
result = FALSE;
}
if (result == FALSE) {
/* check if they've visited before */
scanDetectTrigger = CheckStateEngine(target);
if (scanDetectTrigger == TRUE) {
/* show the banner if one was selected */
if (showBanner == TRUE)
write(incomingSockfd, bannerBuffer,
/* we don't need the bonehead anymore */
close(incomingSockfd);
if (gblResolveHost) { /* Do they want DNS resolution? */
if (CleanAndResolve(resolvedHost, target)
!= TRUE) {
Log("attackalert: ERROR: Error resolving host. \
resolving disabled for this host.\n");
target);
}
} else {
target);
}
Log("attackalert: Connect from host: %s/%s to TCP port: %d", resolvedHost, target, ports[count]);
/* check if this target is already blocked */
if (IsBlocked(target, gblBlockedFile) == FALSE) {
if (DisposeTCP(target, ports[count]) !=
TRUE)
Log("attackalert: ERROR: Could not block host %s !!", target);
else
WriteBlocked(target, resolvedHost,
ports[count],
gblBlockedFile,
gblHistoryFile, "TCP");
} else
Log("attackalert: Host: %s is already blocked. Ignoring", target);
}
}
close(incomingSockfd);
break;
} /* end if(FD_ISSET) */
} /* end for() */
} /* end else (selectResult > 0) */
} /* end main for(; ; ) loop */
/* not reached */
close(incomingSockfd);
}
/****************************************************************/
/* Classic detection Mode */
/* */
/* This mode will bind to a list of UDP sockets and wait for */
/* connections to happen. Stealth scanning really doesn't apply */
/* here. */
/* */
/****************************************************************/
int KalasagModeUDP(void)
{
struct sockaddr_in client, server;
int length, ports[MAXSOCKS], openSockfd[MAXSOCKS], result = TRUE;
int count = 0, portCount = 0, selectResult = 0, scanDetectTrigger = 0;
int boundPortCount = 0, showBanner = FALSE;
char *temp, target[IPMAXBUF], bannerBuffer[MAXBUF],
configToken[MAXBUF];
char buffer[MAXBUF];
char resolvedHost[DNSMAXBUF];
fd_set selectFds;
if ((ConfigTokenRetrieve("UDP_PORTS", configToken)) == FALSE) {
Log("adminalert: ERROR: Could not read UDP_PORTS option from config file");
return (ERROR);
}
/* break out the ports */
if ((temp
= (char *) strtok(configToken
, ",")) != NULL
) {
for (count = 1; count < MAXSOCKS; count++) {
if ((temp
= (char *) strtok(NULL
, ",")) != NULL
)
ports
[count
] = atoi(temp
);
else
break;
}
portCount = count;
} else {
Log("adminalert: ERROR: No UDP ports supplied in config file. Aborting");
return (ERROR);
}
/* read in the banner if one is given */
if ((ConfigTokenRetrieve("PORT_BANNER", configToken)) == TRUE) {
showBanner = TRUE;
SafeStrncpy(bannerBuffer, configToken, MAXBUF);
}
/* setup select call */
FD_ZERO(&selectFds);
for (count = 0; count < portCount; count++) {
Log("adminalert: Going into listen mode on UDP port: %d\n",
ports[count]);
if ((openSockfd[boundPortCount] = OpenUDPSocket()) == ERROR) {
Log("adminalert: ERROR: could not open UDP socket. Aborting\n");
return (ERROR);
}
if (BindSocket
(openSockfd[boundPortCount], client, server,
ports[count]) == ERROR) {
Log("adminalert: ERROR: could not bind UDP socket: %d. Attempting to continue\n", ports[count]);
} else /* well we at least bound to one socket so we'll continue */
boundPortCount++;
}
/* if we didn't bind to anything then abort */
if (boundPortCount == 0) {
Log("adminalert: ERROR: could not bind ANY UDP sockets. Shutting down.\n");
return (ERROR);
}
length = sizeof(client);
Log("adminalert: Kalasag is now active and listening.\n");
/* main loop for multiplexing/resetting */
for (;;) {
/* set up select call */
for (count = 0; count < boundPortCount; count++)
FD_SET(openSockfd[count], &selectFds);
/* setup the select multiplexing (blocking mode) */
selectResult =
select(MAXSOCKS, &selectFds, NULL, NULL,
(struct timeval *) NULL);
if (selectResult < 0) {
Log("adminalert: ERROR: select call failed. Shutting down.\n");
return (ERROR);
} else if (selectResult == 0) {
#ifdef DEBUG
Log("Select timeout");
#endif
}
/* select is reporting a waiting socket. Poll them all to find out which */
else if (selectResult > 0) {
for (count = 0; count < portCount; count++) {
if (FD_ISSET(openSockfd[count], &selectFds)) {
/* here just read in one byte from the UDP socket, that's all we need to */
/* know that this person is a jerk */
if (recvfrom(openSockfd[count], buffer, 1, 0,
(struct sockaddr *) &client, &length) < 0)
{
Log("adminalert: ERROR: could not accept incoming socket for UDP port: %d\n", ports[count]);
break;
}
/* copy the clients address into our buffer for nuking */
SafeStrncpy(target,
(char *) inet_ntoa(client.sin_addr),
IPMAXBUF);
#ifdef DEBUG
Log("debug: KalasagModeUDP: accepted UDP connection from: %s\n", target);
#endif
/* check if we should ignore this IP */
result = NeverBlock(target, gblIgnoreFile);
if (result == ERROR) {
Log("attackalert: ERROR: cannot open ignore file. Blocking host anyway.\n");
result = FALSE;
}
if (result == FALSE) {
/* check if they've visited before */
scanDetectTrigger = CheckStateEngine(target);
if (scanDetectTrigger == TRUE) {
/* show the banner if one was selected */
if (showBanner == TRUE)
sendto(openSockfd[count], bannerBuffer,
(struct sockaddr *) &client,
length);
if (gblResolveHost) { /* Do they want DNS resolution? */
if (CleanAndResolve(resolvedHost, target)
!= TRUE) {
Log("attackalert: ERROR: Error resolving host. \
resolving disabled for this host.\n");
target);
}
} else {
target);
}
Log("attackalert: Connect from host: %s/%s to UDP port: %d", resolvedHost, target, ports[count]);
/* check if this target is already blocked */
if (IsBlocked(target, gblBlockedFile) == FALSE) {
if (DisposeUDP(target, ports[count]) !=
TRUE)
Log("attackalert: ERROR: Could not block host %s !!", target);
else
WriteBlocked(target, resolvedHost,
ports[count],
gblBlockedFile,
gblHistoryFile, "UDP");
} else
Log("attackalert: Host: %s is already blocked. Ignoring", target);
}
}
break;
} /* end if(FD_ISSET) */
} /* end for() */
} /* end else (selectResult > 0) */
} /* end main for(; ; ) loop */
} /* end UDP Kalasag */
/* kill the TCP connection depending on config option */
int DisposeTCP(char *target, int port)
{
int status = TRUE;
#ifdef DEBUG
Log("debug: DisposeTCP: disposing of host %s on port %d with option: %d", target, port, gblBlockTCP);
Log("debug: DisposeTCP: killRunCmd: %s", gblKillRunCmd);
Log("debug: DisposeTCP: gblRunCmdFirst: %d", gblRunCmdFirst);
Log("debug: DisposeTCP: killHostsDeny: %s", gblKillHostsDeny);
Log("debug: DisposeTCP: killRoute: %s %d", gblKillRoute,
#endif
/* Should we ignore TCP from active response? */
if (gblBlockTCP == 1) {
/* run external command first, hosts.deny second, dead route last */
if (gblRunCmdFirst) {
if (strlen(gblKillRunCmd
) > 0)
if (KillRunCmd
(target, port, gblKillRunCmd,
gblDetectionType) != TRUE)
status = FALSE;
if (strlen(gblKillHostsDeny
) > 0)
if (KillHostsDeny
(target, port, gblKillHostsDeny,
gblDetectionType) != TRUE)
status = FALSE;
if (KillRoute(target, port, gblKillRoute, gblDetectionType)
!= TRUE)
status = FALSE;
}
/* run hosts.deny first, dead route second, external command last */
else {
if (strlen(gblKillHostsDeny
) > 0)
if (KillHostsDeny
(target, port, gblKillHostsDeny,
gblDetectionType) != TRUE)
status = FALSE;
if (KillRoute(target, port, gblKillRoute, gblDetectionType)
!= TRUE)
status = FALSE;
if (strlen(gblKillRunCmd
) > 0)
if (KillRunCmd
(target, port, gblKillRunCmd,
gblDetectionType) != TRUE)
status = FALSE;
}
} else if (gblBlockTCP == 2) {
/* run external command only */
if (strlen(gblKillRunCmd
) > 0)
if (KillRunCmd(target, port, gblKillRunCmd, gblDetectionType)
!= TRUE)
status = FALSE;
} else
Log("attackalert: Ignoring TCP response per configuration file setting.");
return (status);
}
/* kill the UDP connection depending on config option */
int DisposeUDP(char *target, int port)
{
int status = TRUE;
#ifdef DEBUG
Log("debug: DisposeUDP: disposing of host %s on port %d with option: %d", target, port, gblBlockUDP);
Log("debug: DisposeUDP: killRunCmd: %d", gblKillRunCmd);
Log("debug: DisposeUDP: gblRunCmdFirst: %s", gblRunCmdFirst);
Log("debug: DisposeUDP: killHostsDeny: %s", gblKillHostsDeny);
Log("debug: DisposeUDP: killRoute: %s %d", gblKillRoute,
#endif
/* Should we ignore TCP from active response? */
if (gblBlockUDP == 1) {
/* run external command first, hosts.deny second, dead route last */
if (gblRunCmdFirst) {
if (strlen(gblKillRunCmd
) > 0)
if (KillRunCmd
(target, port, gblKillRunCmd,
gblDetectionType) != TRUE)
status = FALSE;
if (strlen(gblKillHostsDeny
) > 0)
if (KillHostsDeny
(target, port, gblKillHostsDeny,
gblDetectionType) != TRUE)
status = FALSE;
if (KillRoute(target, port, gblKillRoute, gblDetectionType)
!= TRUE)
status = FALSE;
}
/* run hosts.deny first, dead route second, external command last */
else {
if (strlen(gblKillHostsDeny
) > 0)
if (KillHostsDeny
(target, port, gblKillHostsDeny,
gblDetectionType) != TRUE)
status = FALSE;
if (KillRoute(target, port, gblKillRoute, gblDetectionType)
!= TRUE)
status = FALSE;
if (strlen(gblKillRunCmd
) > 0)
if (KillRunCmd
(target, port, gblKillRunCmd,
gblDetectionType) != TRUE)
status = FALSE;
}
} else if (gblBlockUDP == 2) {
/* run external command only */
if (strlen(gblKillRunCmd
) > 0)
if (KillRunCmd(target, port, gblKillRunCmd, gblDetectionType)
!= TRUE)
status = FALSE;
} else
Log("attackalert: Ignoring UDP response per configuration file setting.");
return (status);
}
/* duh */
void Usage(void)
{
printf("Kalasag Port Scan Detector\n");
printf("Version: %s\n\n", VERSION
);
#ifdef SUPPORT_STEALTH
printf("usage: kalasag [-tcp -udp -stcp -atcp -sudp -audp]\n\n");
#else
printf("Stealth scan detection not supported on this platform\n");
printf("usage: kalasag [-tcp -udp]\n\n");
#endif
/*
printf ("*** PLEASE READ THE DOCS BEFORE USING *** \n\n");
*/
}
/* our cheesy state engine to monitor who has connected here before */
int CheckStateEngine(char *target)
{
int count = 0, scanDetectTrigger = TRUE;
int gotOne = 0;
/* This is the rather basic scan state engine. It maintains */
/* an array of past hosts who triggered a connection on a port */
/* when a new host arrives it is compared against the array */
/* if it is found in the array it increments a state counter by */
/* one and checks the remainder of the array. It does this until */
/* the end is reached or the trigger value has been exceeded */
/* This would probably be better as a linked list/hash table, */
/* but for the number of hosts we are tracking this is just as good. */
/* This will probably change in the future */
gotOne = 1; /* our flag counter if we get a match */
scanDetectTrigger = TRUE; /* set to TRUE until set otherwise */
if (gblConfigTriggerCount > 0) {
for (count = 0; count < MAXSTATE; count++) {
/* if the array has the IP address then increment the gotOne counter and */
/* check the trigger value. If it is exceeded break out of the loop and */
/* set the detecttrigger to TRUE */
if (strcmp(gblScanDetectHost
[count
], target
) == 0) {
/* compare the number of matches to the configured trigger value */
/* if we've exceeded we can stop this noise */
if (++gotOne >= gblConfigTriggerCount) {
scanDetectTrigger = TRUE;
#ifdef DEBUG
Log("debug: CheckStateEngine: host: %s has exceeded trigger value: %d\n", gblScanDetectHost[count], gblConfigTriggerCount);
#endif
break;
}
} else
scanDetectTrigger = FALSE;
}
/* now add the fresh meat into the state engine */
/* if our array is still less than MAXSTATE large add it to the end */
if (gblScanDetectCount < MAXSTATE) {
SafeStrncpy(gblScanDetectHost[gblScanDetectCount], target,
IPMAXBUF);
gblScanDetectCount++;
} else {
/* otherwise tack it to the beginning and start overwriting older ones */
gblScanDetectCount = 0;
SafeStrncpy(gblScanDetectHost[gblScanDetectCount], target,
IPMAXBUF);
gblScanDetectCount++;
}
#ifdef DEBUG
for (count = 0; count < MAXSTATE; count++)
Log("debug: CheckStateEngine: state engine host: %s -> position: %d Detected: %d\n", gblScanDetectHost[count], count, scanDetectTrigger);
#endif
/* end catch to set state if gblConfigTriggerCount == 0 */
if (gotOne >= gblConfigTriggerCount)
scanDetectTrigger = TRUE;
}
if (gblConfigTriggerCount > MAXSTATE) {
Log("securityalert: WARNING: Trigger value %d is larger than state engine capacity of %d.\n", gblConfigTriggerCount);
Log("Adjust the value lower or recompile with a larger state engine value.\n", MAXSTATE);
Log("securityalert: Blocking host anyway because of invalid trigger value");
scanDetectTrigger = TRUE;
}
return (scanDetectTrigger);
}
#ifdef SUPPORT_STEALTH
/* This takes a tcp packet and reports what type of scan it is */
char *ReportPacketType(struct tcphdr tcpPkt)
{
static char packetDesc[MAXBUF];
static char *packetDescPtr = packetDesc;
if ((tcpPkt.syn == 0) && (tcpPkt.fin == 0) && (tcpPkt.ack == 0)
&& (tcpPkt.psh == 0) && (tcpPkt.rst == 0) && (tcpPkt.urg == 0))
snprintf(packetDesc
, MAXBUF
, " TCP NULL scan");
else if ((tcpPkt.fin == 1) && (tcpPkt.urg == 1) && (tcpPkt.psh == 1))
snprintf(packetDesc
, MAXBUF
, "TCP XMAS scan");
else if ((tcpPkt.fin == 1) && (tcpPkt.syn != 1) && (tcpPkt.ack != 1)
&& (tcpPkt.psh != 1) && (tcpPkt.rst != 1)
&& (tcpPkt.urg != 1))
snprintf(packetDesc
, MAXBUF
, "TCP FIN scan");
else if ((tcpPkt.syn == 1) && (tcpPkt.fin != 1) && (tcpPkt.ack != 1)
&& (tcpPkt.psh != 1) && (tcpPkt.rst != 1)
&& (tcpPkt.urg != 1))
snprintf(packetDesc
, MAXBUF
, "TCP SYN/Normal scan");
else
"Unknown Type: TCP Packet Flags: SYN: %d FIN: %d ACK: %d PSH: %d URG: %d RST: %d",
tcpPkt.syn, tcpPkt.fin, tcpPkt.ack, tcpPkt.psh,
tcpPkt.urg, tcpPkt.rst);
return (packetDescPtr);
}
int
SmartVerifyTCP(struct sockaddr_in client, struct sockaddr_in server,
int port)
{
int testSockfd;
/* Ok here is where we "Smart-Verify" the socket. If the port was previously */
/* unbound, but now appears to have someone there, then we will skip responding */
/* to this inbound packet. This a basic "stateful" inspection of the */
/* the connection */
if ((testSockfd = OpenTCPSocket()) == ERROR) {
Log("adminalert: ERROR: could not open TCP socket to smart-verify.\n");
return (FALSE);
} else {
if (BindSocket(testSockfd, client, server, port) == ERROR) {
#ifdef DEBUG
Log("debug: SmartVerify: Smart-Verify Port In Use: %d", port);
#endif
close(testSockfd);
return (TRUE);
}
}
close(testSockfd);
return (FALSE);
}
int
SmartVerifyUDP(struct sockaddr_in client, struct sockaddr_in server,
int port)
{
int testSockfd;
/* Ok here is where we "Smart-Verify" the socket. If the port was previously */
/* unbound, but now appears to have someone there, then we will skip responding */
/* to this inbound packet. This essentially is a "stateful" inspection of the */
/* the connection */
if ((testSockfd = OpenUDPSocket()) == ERROR) {
Log("adminalert: ERROR: could not open UDP socket to smart-verify.\n");
return (FALSE);
} else {
if (BindSocket(testSockfd, client, server, port) == ERROR) {
#ifdef DEBUG
Log("debug: SmartVerify: Smart-Verify Port In Use: %d", port);
#endif
close(testSockfd);
return (TRUE);
}
}
close(testSockfd);
return (FALSE);
}
#endif /* SUPPORT_STEALTH */