Profile
Kalasag is an Open Source port scan detection and response tool for Unix and Unix-like operating systems such as Linux. It is based on Psionic Portsentry, which was written by Craig Rowland in 2000 and re-released under a Common Public License by Cisco in 2002.
Navigation
Git
This blob has been accessed 1670 times via Git panel.

  1. #include "kalasag.h"
  2. #include "kalasag_io.h"
  3. #include "kalasag_util.h"
  4.  
  5. /* Global variables */
  6. char gblScanDetectHost[MAXSTATE][IPMAXBUF];
  7. char gblKillRoute[MAXBUF];
  8. char gblKillHostsDeny[MAXBUF];
  9. char gblKillRunCmd[MAXBUF];
  10. char gblBlockedFile[MAXBUF];
  11. char gblHistoryFile[MAXBUF];
  12. char gblIgnoreFile[MAXBUF];
  13. char gblDetectionType[MAXBUF];
  14.  
  15. int gblScanDetectCount = 0;
  16. int gblBlockTCP = 0;
  17. int gblBlockUDP = 0;
  18. int gblRunCmdFirst = 0;
  19. int gblResolveHost = 0;
  20. int gblConfigTriggerCount = 0;
  21.  
  22. int main(int argc, char *argv[])
  23. {
  24.     if (argc != 2) {
  25.         Usage();
  26.         Exit(ERROR);
  27.     }
  28.  
  29.     if ((geteuid()) && (getuid()) != 0) {
  30.         printf("You need to be root to run this.\n");
  31.         Exit(ERROR);
  32.     }
  33.  
  34.  
  35.     /* Cheesy arg parser. Some systems don't support getopt and I don't want to port it. */
  36.     if ((strcmp(argv[1], "-tcp")) && (strcmp(argv[1], "-udp"))
  37.         && (strcmp(argv[1], "-stcp")) && (strcmp(argv[1], "-atcp"))
  38.         && (strcmp(argv[1], "-sudp")) && (strcmp(argv[1], "-audp")) != 0) {
  39.         Usage();
  40.         Exit(ERROR);
  41.     } else {
  42.         Start();
  43.         /* This copies the startup type to a global for later use */
  44.         if ((SafeStrncpy
  45.              (gblDetectionType, strstr(argv[1], "-") + 1, MAXBUF))
  46.             == NULL) {
  47.             Log("adminalert: ERROR: Error setting internal scan detection type.\n");
  48.             printf("ERROR: Error setting internal scan detection type.\n");
  49.             printf("ERROR: Kalasag is shutting down!\n");
  50.             Exit(ERROR);
  51.         } else if (CheckConfig() == FALSE) {
  52.             Log("adminalert: ERROR: Configuration files are missing/corrupted. Shutting down.\n");
  53.             printf("ERROR: Configuration files are missing/corrupted.\n");
  54.             printf
  55.                 ("ERROR: Check your syslog for a more detailed error message.\n");
  56.             printf("ERROR: Kalasag is shutting down!\n");
  57.             Exit(ERROR);
  58.         } else if (InitConfig() == FALSE) {
  59.             Log("adminalert: ERROR: Your config file is corrupted/missing mandatory option! Shutting down.\n");
  60.             printf
  61.                 ("ERROR: Your config file is corrupted/missing mandatory option!\n");
  62.             printf
  63.                 ("ERROR: Check your syslog for a more detailed error message.\n");
  64.             printf("ERROR: Kalasag is shutting down!\n");
  65.             Exit(ERROR);
  66.         }
  67. #ifndef NODAEMON
  68.         else if (DaemonSeed() == ERROR) {
  69.             Log("adminalert: ERROR: could not go into daemon mode. Shutting down.\n");
  70.             printf
  71.                 ("ERROR: could not go into daemon mode. Shutting down.\n");
  72.             Exit(ERROR);
  73.         }
  74. #endif
  75.     }
  76.  
  77.  
  78.     if (strcmp(argv[1], "-tcp") == 0) {
  79.         if (KalasagModeTCP() == ERROR) {
  80.             Log("adminalert: ERROR: could not go into Kalasag mode. Shutting down.\n");
  81.             Exit(ERROR);
  82.         }
  83.     }
  84. #ifdef SUPPORT_STEALTH
  85.     else if (strcmp(argv[1], "-stcp") == 0) {
  86.         if (KalasagStealthModeTCP() == ERROR) {
  87.             Log("adminalert: ERROR: could not go into Kalasag mode. Shutting down.\n");
  88.             Exit(ERROR);
  89.         }
  90.     } else if (strcmp(argv[1], "-atcp") == 0) {
  91.         if (KalasagAdvancedStealthModeTCP() == ERROR) {
  92.             Log("adminalert: ERROR: could not go into Kalasag mode. Shutting down.\n");
  93.             Exit(ERROR);
  94.         }
  95.     } else if (strcmp(argv[1], "-sudp") == 0) {
  96.         if (KalasagStealthModeUDP() == ERROR) {
  97.             Log("adminalert: ERROR: could not go into Kalasag mode. Shutting down.\n");
  98.             Exit(ERROR);
  99.         }
  100.     } else if (strcmp(argv[1], "-audp") == 0) {
  101.         if (KalasagAdvancedStealthModeUDP() == ERROR) {
  102.             Log("adminalert: ERROR: could not go into Kalasag mode. Shutting down.\n");
  103.             Exit(ERROR);
  104.         }
  105.     }
  106. #endif
  107.     else if (strcmp(argv[1], "-udp") == 0) {
  108.         if (KalasagModeUDP() == ERROR) {
  109.             Log("adminalert: ERROR: could not go into Kalasag mode. Shutting down.\n");
  110.             Exit(ERROR);
  111.         }
  112.     }
  113.  
  114.     Exit(TRUE);
  115.     /* shuts up compiler warning */
  116.     return (0);
  117. }
  118.  
  119. /****************************************************************/
  120. /* Reads generic config options into global variables           */
  121. /****************************************************************/
  122. int InitConfig(void)
  123. {
  124.     FILE *input;
  125.     char configToken[MAXBUF];
  126.  
  127.     gblBlockTCP = CheckFlag("BLOCK_TCP");
  128.     gblBlockUDP = CheckFlag("BLOCK_UDP");
  129.     gblResolveHost = CheckFlag("RESOLVE_HOST");
  130.  
  131.     memset(gblKillRoute, '\0', MAXBUF);
  132.     memset(gblKillHostsDeny, '\0', MAXBUF);
  133.     memset(gblKillRunCmd, '\0', MAXBUF);
  134.  
  135.     if ((ConfigTokenRetrieve("SCAN_TRIGGER", configToken)) == FALSE) {
  136.         Log("adminalert: ERROR: Could not read SCAN_TRIGGER option from config file. Disabling SCAN DETECTION TRIGGER");
  137.         gblConfigTriggerCount = 0;
  138.     } else {
  139. #ifdef DEBUG
  140.         Log("debug: InitConfig: retrieved SCAN_TRIGGER option: %s \n",
  141.             configToken);
  142. #endif
  143.         gblConfigTriggerCount = atoi(configToken);
  144.     }
  145.  
  146.     if ((ConfigTokenRetrieve("KILL_ROUTE", gblKillRoute)) == TRUE) {
  147. #ifdef DEBUG
  148.         Log("debug: InitConfig: retrieved KILL_ROUTE option: %s \n",
  149.             gblKillRoute);
  150. #endif
  151.     } else {
  152. #ifdef DEBUG
  153.         Log("debug: InitConfig: KILL_ROUTE option NOT FOUND.\n");
  154. #endif
  155.     }
  156.  
  157.     if ((ConfigTokenRetrieve("KILL_HOSTS_DENY", gblKillHostsDeny)) == TRUE) {
  158. #ifdef DEBUG
  159.         Log("debug: InitConfig: retrieved KILL_HOSTS_DENY option: %s \n",
  160.             gblKillHostsDeny);
  161. #endif
  162.     } else {
  163. #ifdef DEBUG
  164.         Log("debug: InitConfig: KILL_HOSTS_DENY option NOT FOUND.\n");
  165. #endif
  166.     }
  167.  
  168.     if ((ConfigTokenRetrieve("KILL_RUN_CMD", gblKillRunCmd)) == TRUE) {
  169. #ifdef DEBUG
  170.         Log("debug: InitConfig: retrieved KILL_RUN_CMD option: %s \n",
  171.             gblKillRunCmd);
  172. #endif
  173.         /* Check the order we should run the KILL_RUN_CMD */
  174.         /* Default is to run the command after blocking */
  175.         gblRunCmdFirst = CheckFlag("KILL_RUN_CMD_FIRST");
  176.     } else {
  177. #ifdef DEBUG
  178.         Log("debug: InitConfig: KILL_RUN_CMD option NOT FOUND.\n");
  179. #endif
  180.     }
  181.  
  182.     if ((ConfigTokenRetrieve("BLOCKED_FILE", gblBlockedFile)) == TRUE) {
  183.         if (strlen(gblBlockedFile) < MAXBUF - 5) {
  184.             strncat(gblBlockedFile, ".", 1);
  185.             strncat(gblBlockedFile, gblDetectionType, 4);
  186.         } else {
  187.             Log("adminalert: ERROR: Blocked filename is too long to append detection type file extension: %s.\n", gblBlockedFile);
  188.             return (FALSE);
  189.         }
  190. #ifdef DEBUG
  191.         Log("debug: InitConfig: retrieved BLOCKED_FILE option: %s \n",
  192.             gblBlockedFile);
  193.         Log("debug: CheckConfig: Removing old block file: %s \n",
  194.             gblBlockedFile);
  195. #endif
  196.  
  197.         if ((input = fopen(gblBlockedFile, "w")) == NULL) {
  198.             Log("adminalert: ERROR: Cannot delete blocked file on startup: %s.\n", gblBlockedFile);
  199.             return (FALSE);
  200.         } else
  201.             fclose(input);
  202.     } else {
  203.         Log("InitConfig: Cannot retrieve BLOCKED_FILE option! Aborting\n");
  204.         return (FALSE);
  205.     }
  206.  
  207.  
  208.     if ((ConfigTokenRetrieve("HISTORY_FILE", gblHistoryFile)) == TRUE) {
  209. #ifdef DEBUG
  210.         Log("debug: InitConfig: retrieved HISTORY_FILE option: %s \n",
  211.             gblHistoryFile);
  212. #endif
  213.     } else {
  214.         Log("InitConfig: Cannot retrieve HISTORY_FILE option! Aborting\n");
  215.         return (FALSE);
  216.     }
  217.  
  218.     if ((ConfigTokenRetrieve("IGNORE_FILE", gblIgnoreFile)) == TRUE) {
  219. #ifdef DEBUG
  220.         Log("debug: InitConfig: retrieved IGNORE_FILE option: %s \n",
  221.             gblIgnoreFile);
  222. #endif
  223.     } else {
  224.         Log("InitConfig: Cannot retrieve IGNORE_FILE option! Aborting\n");
  225.         return (FALSE);
  226.     }
  227.  
  228.     return (TRUE);
  229. }
  230.  
  231.  
  232. #ifdef SUPPORT_STEALTH
  233.  
  234. /* Read in a TCP packet taking into account IP options and other */
  235. /* errors */
  236. int PacketReadTCP(int socket, struct iphdr *ipPtr, struct tcphdr *tcpPtr)
  237. {
  238.     char packetBuffer[TCPPACKETLEN];
  239.     struct in_addr addr;
  240.  
  241.     bzero(ipPtr, sizeof(struct iphdr));
  242.     bzero(tcpPtr, sizeof(struct tcphdr));
  243.  
  244.     if (read(socket, packetBuffer, TCPPACKETLEN) == ERROR)
  245.         return (ERROR);
  246.  
  247.     memcpy(ipPtr, (struct iphdr *) packetBuffer, sizeof(struct iphdr));
  248.  
  249.     if ((ipPtr->ihl < 5) || (ipPtr->ihl > 15)) {
  250.         addr.s_addr = (u_int) ipPtr->saddr;
  251.         Log("attackalert: Illegal IP header length detected in TCP packet: %d from (possible) host: %s\n", ipPtr->ihl, inet_ntoa(addr));
  252.         return (FALSE);
  253.     } else {
  254.         memcpy(tcpPtr,
  255.                (struct tcphdr *) (packetBuffer + ((ipPtr->ihl) * 4)),
  256.                sizeof(struct tcphdr));
  257.         return (TRUE);
  258.     }
  259.  
  260. }
  261.  
  262. /* Read in a UDP packet taking into account IP options and other */
  263. /* errors */
  264. int PacketReadUDP(int socket, struct iphdr *ipPtr, struct udphdr *udpPtr)
  265. {
  266.     char packetBuffer[UDPPACKETLEN];
  267.     struct in_addr addr;
  268.  
  269.     bzero(ipPtr, sizeof(struct iphdr));
  270.     bzero(udpPtr, sizeof(struct udphdr));
  271.  
  272.     if (read(socket, packetBuffer, UDPPACKETLEN) == ERROR)
  273.         return (ERROR);
  274.  
  275.     memcpy(ipPtr, (struct iphdr *) packetBuffer, sizeof(struct iphdr));
  276.  
  277.     if ((ipPtr->ihl < 5) || (ipPtr->ihl > 15)) {
  278.         addr.s_addr = (u_int) ipPtr->saddr;
  279.         Log("attackalert: Illegal IP header length detected in UDP packet: %d from (possible) host: %s\n", ipPtr->ihl, inet_ntoa(addr));
  280.         return (FALSE);
  281.     } else {
  282.         memcpy(udpPtr,
  283.                (struct udphdr *) (packetBuffer + ((ipPtr->ihl) * 4)),
  284.                sizeof(struct udphdr));
  285.         return (TRUE);
  286.     }
  287.  
  288. }
  289.  
  290. /****************************************************************/
  291. /* Stealth scan detection Mode One                              */
  292. /*                                                              */
  293. /* This mode will read in a list of ports to monitor and will   */
  294. /* then open a raw socket to look for packets matching the port. */
  295. /*                                                              */
  296. /****************************************************************/
  297. int KalasagStealthModeTCP(void)
  298. {
  299.     struct sockaddr_in client, server;
  300.     int portCount = 0, portCount2 = 0, ports[MAXSOCKS], ports2[MAXSOCKS];
  301.     int count = 0, scanDetectTrigger = TRUE, gotBound = FALSE, result =
  302.         TRUE;
  303.     int openSockfd = 0, incomingPort = 0;
  304.     char *temp, target[IPMAXBUF], configToken[MAXBUF];
  305.     char resolvedHost[DNSMAXBUF], *packetType;
  306.     struct in_addr addr;
  307.     struct iphdr ip;
  308.     struct tcphdr tcp;
  309.  
  310.     if ((ConfigTokenRetrieve("TCP_PORTS", configToken)) == FALSE) {
  311.         Log("adminalert: ERROR: Could not read TCP_PORTS option from config file");
  312.         return (ERROR);
  313.     }
  314.  
  315.     /* break out the ports */
  316.     if ((temp = (char *) strtok(configToken, ",")) != NULL) {
  317.         ports[0] = atoi(temp);
  318.         for (count = 1; count < MAXSOCKS; count++) {
  319.             if ((temp = (char *) strtok(NULL, ",")) != NULL)
  320.                 ports[count] = atoi(temp);
  321.             else
  322.                 break;
  323.         }
  324.         portCount = count;
  325.     } else {
  326.         Log("adminalert: ERROR: No TCP ports supplied in config file. Aborting");
  327.         return (ERROR);
  328.     }
  329.  
  330.     /* ok, now check if they have a network daemon on the socket already, if they do */
  331.     /* then skip that port because it will cause false alarms */
  332.     for (count = 0; count < portCount; count++) {
  333.         Log("adminalert: Going into stealth listen mode on TCP port: %d\n",
  334.             ports[count]);
  335.         if ((openSockfd = OpenTCPSocket()) == ERROR) {
  336.             Log("adminalert: ERROR: could not open TCP socket. Aborting.\n");
  337.             return (ERROR);
  338.         }
  339.  
  340.         if (BindSocket(openSockfd, client, server, ports[count]) == ERROR)
  341.             Log("adminalert: ERROR: Socket %d is in use and will not be monitored. Attempting to continue\n", ports[count]);
  342.         else {                  /* well we at least bound to one socket so we'll continue */
  343.  
  344.             gotBound = TRUE;
  345.             ports2[portCount2++] = ports[count];
  346.         }
  347.         close(openSockfd);
  348.     }
  349.  
  350.     /* if we didn't bind to anything then abort */
  351.     if (gotBound == FALSE) {
  352.         Log("adminalert: ERROR: All supplied TCP sockets are in use and will not be listened to. Shutting down.\n");
  353.         return (ERROR);
  354.     }
  355.  
  356.     /* Open our raw socket for network IO */
  357.     if ((openSockfd = OpenRAWTCPSocket()) == ERROR) {
  358.         Log("adminalert: ERROR: could not open RAW TCP socket. Aborting.\n");
  359.         return (ERROR);
  360.     }
  361.  
  362.     Log("adminalert: Kalasag is now active and listening.\n");
  363.  
  364.     /* main detection loop */
  365.     for (;;) {
  366.         if (PacketReadTCP(openSockfd, &ip, &tcp) != TRUE)
  367.             continue;
  368.  
  369.  
  370.         incomingPort = ntohs(tcp.dest);
  371.  
  372.         /* check for an ACK/RST to weed out established connections in case the user */
  373.         /* is monitoring high ephemeral port numbers */
  374.         if ((tcp.ack != 1) && (tcp.rst != 1)) {
  375.             /* this iterates the list of ports looking for a match */
  376.             for (count = 0; count < portCount; count++) {
  377.                 if (incomingPort == ports2[count]) {
  378.                     if (SmartVerifyTCP(client, server, incomingPort) ==
  379.                         TRUE)
  380.                         break;
  381.  
  382.                     /* copy the clients address into our buffer for nuking */
  383.                     addr.s_addr = (u_int) ip.saddr;
  384.                     SafeStrncpy(target, (char *) inet_ntoa(addr),
  385.                                 IPMAXBUF);
  386.                     /* check if we should ignore this IP */
  387.                     result = NeverBlock(target, gblIgnoreFile);
  388.  
  389.                     if (result == ERROR) {
  390.                         Log("attackalert: ERROR: cannot open ignore file. Blocking host anyway.\n");
  391.                         result = FALSE;
  392.                     }
  393.  
  394.                     if (result == FALSE) {
  395.                         /* check if they've visited before */
  396.                         scanDetectTrigger = CheckStateEngine(target);
  397.                         if (scanDetectTrigger == TRUE) {
  398.                             if (gblResolveHost) {       /* Do they want DNS resolution? */
  399.                                 if (CleanAndResolve(resolvedHost, target)
  400.                                     != TRUE) {
  401.                                     Log("attackalert: ERROR: Error resolving host. \
  402.                                               resolving disabled for this host.\n");
  403.                                     snprintf(resolvedHost, DNSMAXBUF, "%s",
  404.                                              target);
  405.                                 }
  406.                             } else {
  407.                                 snprintf(resolvedHost, DNSMAXBUF, "%s",
  408.                                          target);
  409.                             }
  410.  
  411.                             packetType = ReportPacketType(tcp);
  412.                             Log("attackalert: %s from host: %s/%s to TCP port: %d", packetType, resolvedHost, target, ports2[count]);
  413.                             /* Report on options present */
  414.                             if (ip.ihl > 5)
  415.                                 Log("attackalert: Packet from host: %s/%s to TCP port: %d has IP options set (detection avoidance technique).", resolvedHost, target, ports2[count]);
  416.  
  417.                             /* check if this target is already blocked */
  418.                             if (IsBlocked(target, gblBlockedFile) == FALSE) {
  419.                                 /* toast the prick */
  420.                                 if (DisposeTCP(target, ports2[count]) !=
  421.                                     TRUE)
  422.                                     Log("attackalert: ERROR: Could not block host %s/%s !!", resolvedHost, target);
  423.                                 else
  424.                                     WriteBlocked(target, resolvedHost,
  425.                                                  ports2[count],
  426.                                                  gblBlockedFile,
  427.                                                  gblHistoryFile, "TCP");
  428.                             } /* end IsBlocked check */
  429.                             else
  430.                                 Log("attackalert: Host: %s/%s is already blocked Ignoring", resolvedHost, target);
  431.                         }       /* end if(scanDetectTrigger) */
  432.                     }           /* end if(never block) check */
  433.                     break;      /* get out of for(count) loop above */
  434.                 }               /* end if(incoming port) ==  protected port */
  435.             }                   /* end for( check for protected port loop ) loop */
  436.         }                       /* end if(TH_ACK) check */
  437.     }                           /* end for( ; ; ) loop */
  438.  
  439. }                               /* end KalasagStealthModeTCP */
  440.  
  441.  
  442. /****************************************************************/
  443. /* Advanced Stealth scan detection Mode One                     */
  444. /*                                                              */
  445. /* This mode will see what ports are listening below 1024       */
  446. /* and will then monitor all the rest. This is very sensitive   */
  447. /* and will react on any packet hitting any monitored port,     */
  448. /* regardless of TCP flags set                                  */
  449. /*                                                              */
  450. /****************************************************************/
  451. int KalasagAdvancedStealthModeTCP(void)
  452. {
  453.     struct sockaddr_in client, server;
  454.     int result = TRUE, scanDetectTrigger = TRUE, hotPort = TRUE;
  455.     int openSockfd = 0, incomingPort = 0, smartVerify = FALSE;
  456.     unsigned int advancedPorts = 1024;
  457.     unsigned int count = 0, inUsePorts[MAXSOCKS], portCount = 0;
  458.     char target[IPMAXBUF], configToken[MAXBUF];
  459.     char resolvedHost[DNSMAXBUF], *temp, *packetType;
  460.     struct in_addr addr;
  461.     struct iphdr ip;
  462.     struct tcphdr tcp;
  463.  
  464.     if ((ConfigTokenRetrieve("ADVANCED_PORTS_TCP", configToken)) == FALSE) {
  465.         Log("adminalert: ERROR: Could not read ADVANCED_PORTS_TCP option from config file. Assuming 1024.");
  466.         advancedPorts = 1024;
  467.     } else
  468.         advancedPorts = atoi(configToken);
  469.  
  470.     Log("adminalert: Advanced mode will monitor first %d ports",
  471.         advancedPorts);
  472.  
  473.     /* try to bind to all ports below 1024, any that are taken we exclude later */
  474.     for (count = 0; count < advancedPorts; count++) {
  475.         if ((openSockfd = OpenTCPSocket()) == ERROR) {
  476.             Log("adminalert: ERROR: could not open TCP socket. Aborting.\n");
  477.             return (ERROR);
  478.         }
  479.         if (BindSocket(openSockfd, client, server, count) == ERROR)
  480.             inUsePorts[portCount++] = count;
  481.  
  482.         close(openSockfd);
  483.     }
  484.  
  485.     if ((ConfigTokenRetrieve("ADVANCED_EXCLUDE_TCP", configToken)) !=
  486.         FALSE) {
  487.         /* break out the ports */
  488.         if ((temp = (char *) strtok(configToken, ",")) != NULL) {
  489.             inUsePorts[portCount++] = atoi(temp);
  490.             Log("adminalert: Advanced mode will manually exclude port: %d ", inUsePorts[portCount - 1]);
  491.             for (count = 0; count < MAXSOCKS; count++) {
  492.                 if ((temp = (char *) strtok(NULL, ",")) != NULL) {
  493.                     inUsePorts[portCount++] = atoi(temp);
  494.                     Log("adminalert: Advanced mode will manually exclude port: %d ", inUsePorts[portCount - 1]);
  495.                 } else
  496.                     break;
  497.             }
  498.         }
  499.     } else
  500.         Log("adminalert: Advanced mode will manually exclude no ports");
  501.  
  502.  
  503.     for (count = 0; count < portCount; count++)
  504.         Log("adminalert: Advanced Stealth scan detection mode activated. Ignored TCP port: %d\n", inUsePorts[count]);
  505.  
  506.     /* open raw socket for reading */
  507.     if ((openSockfd = OpenRAWTCPSocket()) == ERROR) {
  508.         Log("adminalert: ERROR: could not open RAW TCP socket. Aborting.\n");
  509.         return (ERROR);
  510.     }
  511.  
  512.     Log("adminalert: Kalasag is now active and listening.\n");
  513.  
  514.     /* main detection loop */
  515.     for (;;) {
  516.         if (PacketReadTCP(openSockfd, &ip, &tcp) != TRUE)
  517.             continue;
  518.  
  519.         incomingPort = ntohs(tcp.dest);
  520.  
  521.         /* don't monitor packets with ACK set (established) or RST */
  522.         /* This could be a hole in some cases */
  523.         if ((tcp.ack != 1) && (tcp.rst != 1)) {
  524.             /* check if we should ignore this connection to this port */
  525.             for (count = 0; count < portCount; count++) {
  526.                 if ((incomingPort == inUsePorts[count])
  527.                     || (incomingPort >= advancedPorts)) {
  528.                     hotPort = FALSE;
  529.                     break;
  530.                 } else
  531.                     hotPort = TRUE;
  532.             }
  533.  
  534.             if (hotPort) {
  535.                 smartVerify = SmartVerifyTCP(client, server, incomingPort);
  536.  
  537.                 if (smartVerify != TRUE) {
  538.                     addr.s_addr = (u_int) ip.saddr;
  539.                     SafeStrncpy(target, (char *) inet_ntoa(addr),
  540.                                 IPMAXBUF);
  541.                     /* check if we should ignore this IP */
  542.                     result = NeverBlock(target, gblIgnoreFile);
  543.  
  544.                     if (result == ERROR) {
  545.                         Log("attackalert: ERROR: cannot open ignore file. Blocking host anyway.\n");
  546.                         result = FALSE;
  547.                     }
  548.  
  549.                     if (result == FALSE) {
  550.                         /* check if they've visited before */
  551.                         scanDetectTrigger = CheckStateEngine(target);
  552.  
  553.                         if (scanDetectTrigger == TRUE) {
  554.                             if (gblResolveHost) {       /* Do they want DNS resolution? */
  555.                                 if (CleanAndResolve(resolvedHost, target)
  556.                                     != TRUE) {
  557.                                     Log("attackalert: ERROR: Error resolving host. \
  558.                                                 resolving disabled for this host.\n");
  559.                                     snprintf(resolvedHost, DNSMAXBUF, "%s",
  560.                                              target);
  561.                                 }
  562.                             } else {
  563.                                 snprintf(resolvedHost, DNSMAXBUF, "%s",
  564.                                          target);
  565.                             }
  566.  
  567.                             packetType = ReportPacketType(tcp);
  568.                             Log("attackalert: %s from host: %s/%s to TCP port: %d", packetType, resolvedHost, target, incomingPort);
  569.                             /* Report on options present */
  570.                             if (ip.ihl > 5)
  571.                                 Log("attackalert: Packet from host: %s/%s to TCP port: %d has IP options set (detection avoidance technique).", resolvedHost, target, incomingPort);
  572.  
  573.                             /* check if this target is already blocked */
  574.                             if (IsBlocked(target, gblBlockedFile) == FALSE) {
  575.                                 /* toast the prick */
  576.                                 if (DisposeTCP(target, incomingPort) !=
  577.                                     TRUE)
  578.                                     Log("attackalert: ERROR: Could not block host %s/%s!!", resolvedHost, target);
  579.                                 else
  580.                                     WriteBlocked(target, resolvedHost,
  581.                                                  incomingPort,
  582.                                                  gblBlockedFile,
  583.                                                  gblHistoryFile, "TCP");
  584.                             } /* end IsBlocked check */
  585.                             else
  586.                                 Log("attackalert: Host: %s/%s is already blocked Ignoring", resolvedHost, target);
  587.                         }       /* end if(scanDetectTrigger) */
  588.                     }           /* end if(never block) check */
  589.                 }               /* end if(smartVerify) */
  590.             }                   /* end if(hotPort) */
  591.         }                       /* end if(TH_ACK) */
  592.     }                           /* end for( ; ; ) loop */
  593. }
  594.  
  595. /* end KalasagAdvancedStealthModeTCP */
  596.  
  597.  
  598.  
  599. /****************************************************************/
  600. /* UDP "stealth" scan detection                                 */
  601. /*                                                              */
  602. /* This mode will read in a list of ports to monitor and will   */
  603. /* then open a raw socket to look for packets matching the port. */
  604. /*                                                              */
  605. /****************************************************************/
  606. int KalasagStealthModeUDP(void)
  607. {
  608.     struct sockaddr_in client, server;
  609.     int portCount = 0, portCount2 = 0, ports[MAXSOCKS], ports2[MAXSOCKS],
  610.         result = TRUE;
  611.     int count = 0, scanDetectTrigger = TRUE, gotBound = FALSE;
  612.     int openSockfd = 0, incomingPort = 0;
  613.     char *temp, target[IPMAXBUF], configToken[MAXBUF];
  614.     char resolvedHost[DNSMAXBUF];
  615.     struct in_addr addr;
  616.     struct iphdr ip;
  617.     struct udphdr udp;
  618.  
  619.  
  620.     if ((ConfigTokenRetrieve("UDP_PORTS", configToken)) == FALSE) {
  621.         Log("adminalert: ERROR: Could not read UDP_PORTS option from config file");
  622.         return (ERROR);
  623.     }
  624.  
  625.     /* break out the ports */
  626.     if ((temp = (char *) strtok(configToken, ",")) != NULL) {
  627.         ports[0] = atoi(temp);
  628.         for (count = 1; count < MAXSOCKS; count++) {
  629.             if ((temp = (char *) strtok(NULL, ",")) != NULL)
  630.                 ports[count] = atoi(temp);
  631.             else
  632.                 break;
  633.         }
  634.         portCount = count;
  635.     } else {
  636.         Log("adminalert: ERROR: No UDP ports supplied in config file. Aborting");
  637.         return (ERROR);
  638.     }
  639.  
  640.     /* ok, now check if they have a network daemon on the socket already, if they do */
  641.     /* then skip that port because it will cause false alarms */
  642.     for (count = 0; count < portCount; count++) {
  643.         Log("adminalert: Going into stealth listen mode on UDP port: %d\n",
  644.             ports[count]);
  645.         if ((openSockfd = OpenUDPSocket()) == ERROR) {
  646.             Log("adminalert: ERROR: could not open UDP socket. Aborting.\n");
  647.             return (ERROR);
  648.         }
  649.  
  650.         if (BindSocket(openSockfd, client, server, ports[count]) == ERROR)
  651.             Log("adminalert: ERROR: Socket %d is in use and will not be monitored. Attempting to continue\n", ports[count]);
  652.         else {
  653.             gotBound = TRUE;
  654.             ports2[portCount2++] = ports[count];
  655.         }
  656.         close(openSockfd);
  657.     }
  658.  
  659.     if (gotBound == FALSE) {
  660.         Log("adminalert: ERROR: All supplied UDP sockets are in use and will not be listened to. Shutting down.\n");
  661.         return (ERROR);
  662.     }
  663.  
  664.     if ((openSockfd = OpenRAWUDPSocket()) == ERROR) {
  665.         Log("adminalert: ERROR: could not open RAW UDP socket. Aborting.\n");
  666.         return (ERROR);
  667.     }
  668.  
  669.     Log("adminalert: Kalasag is now active and listening.\n");
  670.  
  671.     /* main detection loop */
  672.     for (;;) {
  673.         if (PacketReadUDP(openSockfd, &ip, &udp) != TRUE)
  674.             continue;
  675.  
  676.         incomingPort = ntohs(udp.dest);
  677.  
  678.         /* this iterates the list of ports looking for a match */
  679.         for (count = 0; count < portCount; count++) {
  680.             if (incomingPort == ports2[count]) {
  681.                 if (SmartVerifyUDP(client, server, incomingPort) == TRUE)
  682.                     break;
  683.  
  684.                 addr.s_addr = (u_int) ip.saddr;
  685.                 SafeStrncpy(target, (char *) inet_ntoa(addr), IPMAXBUF);
  686.                 /* check if we should ignore this IP */
  687.                 result = NeverBlock(target, gblIgnoreFile);
  688.  
  689.                 if (result == ERROR) {
  690.                     Log("attackalert: ERROR: cannot open ignore file. Blocking host anyway.\n");
  691.                     result = FALSE;
  692.                 }
  693.  
  694.                 if (result == FALSE) {
  695.                     /* check if they've visited before */
  696.                     scanDetectTrigger = CheckStateEngine(target);
  697.                     if (scanDetectTrigger == TRUE) {
  698.                         if (gblResolveHost) {   /* Do they want DNS resolution? */
  699.                             if (CleanAndResolve(resolvedHost, target) !=
  700.                                 TRUE) {
  701.                                 Log("attackalert: ERROR: Error resolving host. \
  702.                                         resolving disabled for this host.\n");
  703.                                 snprintf(resolvedHost, DNSMAXBUF, "%s",
  704.                                          target);
  705.                             }
  706.                         } else {
  707.                             snprintf(resolvedHost, DNSMAXBUF, "%s",
  708.                                      target);
  709.                         }
  710.  
  711.                         Log("attackalert: UDP scan from host: %s/%s to UDP port: %d", resolvedHost, target, ports2[count]);
  712.                         /* Report on options present */
  713.                         if (ip.ihl > 5)
  714.                             Log("attackalert: Packet from host: %s/%s to UDP port: %d has IP options set (detection avoidance technique).", resolvedHost, target, incomingPort);
  715.  
  716.                         /* check if this target is already blocked */
  717.                         if (IsBlocked(target, gblBlockedFile) == FALSE) {
  718.                             if (DisposeUDP(target, ports2[count]) != TRUE)
  719.                                 Log("attackalert: ERROR: Could not block host %s/%s!!", resolvedHost, target);
  720.                             else
  721.                                 WriteBlocked(target, resolvedHost,
  722.                                              ports2[count], gblBlockedFile,
  723.                                              gblHistoryFile, "UDP");
  724.                         } /* end IsBlocked check */
  725.                         else {
  726.                             Log("attackalert: Host: %s/%s is already blocked Ignoring", resolvedHost, target);
  727.                         }
  728.                     }           /* end if(scanDetectTrigger) */
  729.                 }               /* end if(never block) check */
  730.                 break;          /* get out of for(count) loop above */
  731.             }                   /* end if(incoming port) ==  protected port */
  732.         }                       /* end for( check for protected port loop ) loop */
  733.     }                           /* end for( ; ; ) loop */
  734.  
  735. }                               /* end KalasagStealthModeUDP */
  736.  
  737.  
  738. /****************************************************************/
  739. /* Advanced Stealth scan detection mode for UDP                 */
  740. /*                                                              */
  741. /* This mode will see what ports are listening below 1024       */
  742. /* and will then monitor all the rest. This is very sensitive   */
  743. /* and will react on any packet hitting any monitored port.     */
  744. /* This is a very dangerous option and is for advanced users    */
  745. /*                                                              */
  746. /****************************************************************/
  747. int KalasagAdvancedStealthModeUDP(void)
  748. {
  749.     struct sockaddr_in client, server;
  750.     int result = TRUE, scanDetectTrigger = TRUE, hotPort = TRUE;
  751.     int openSockfd = 0, incomingPort = 0, smartVerify = FALSE;
  752.     unsigned int advancedPorts = 1024;
  753.     unsigned int count = 0, inUsePorts[MAXSOCKS], portCount = 0;
  754.     char target[IPMAXBUF], configToken[MAXBUF];
  755.     char resolvedHost[DNSMAXBUF], *temp;
  756.     struct in_addr addr;
  757.     struct iphdr ip;
  758.     struct udphdr udp;
  759.  
  760.  
  761.     if ((ConfigTokenRetrieve("ADVANCED_PORTS_UDP", configToken)) == FALSE) {
  762.         Log("adminalert: ERROR: Could not read ADVANCED_PORTS_UDP option from config file. Assuming 1024.");
  763.         advancedPorts = 1024;
  764.     } else
  765.         advancedPorts = atoi(configToken);
  766.  
  767.     Log("adminalert: Advanced mode will monitor first %d ports",
  768.         advancedPorts);
  769.  
  770.     /* try to bind to all ports below 1024, any that are taken we exclude later */
  771.     for (count = 0; count < advancedPorts; count++) {
  772.         if ((openSockfd = OpenUDPSocket()) == ERROR) {
  773.             Log("adminalert: ERROR: could not open UDP socket. Aborting.\n");
  774.             return (ERROR);
  775.         }
  776.         if (BindSocket(openSockfd, client, server, count) == ERROR)
  777.             inUsePorts[portCount++] = count;
  778.  
  779.         close(openSockfd);
  780.     }
  781.  
  782.     if ((ConfigTokenRetrieve("ADVANCED_EXCLUDE_UDP", configToken)) !=
  783.         FALSE) {
  784.         /* break out the ports */
  785.         if ((temp = (char *) strtok(configToken, ",")) != NULL) {
  786.             inUsePorts[portCount++] = atoi(temp);
  787.             Log("adminalert: Advanced mode will manually exclude port: %d ", inUsePorts[portCount - 1]);
  788.             for (count = 0; count < MAXSOCKS; count++) {
  789.                 if ((temp = (char *) strtok(NULL, ",")) != NULL) {
  790.                     inUsePorts[portCount++] = atoi(temp);
  791.                     Log("adminalert: Advanced mode will manually exclude port: %d ", inUsePorts[portCount - 1]);
  792.                 } else
  793.                     break;
  794.             }
  795.         }
  796.     } else
  797.         Log("adminalert: Advanced mode will manually exclude no ports");
  798.  
  799.  
  800.     for (count = 0; count < portCount; count++)
  801.         Log("adminalert: Advanced Stealth scan detection mode activated. Ignored UDP port: %d\n", inUsePorts[count]);
  802.  
  803.     if ((openSockfd = OpenRAWUDPSocket()) == ERROR) {
  804.         Log("adminalert: ERROR: could not open RAW UDP socket. Aborting.\n");
  805.         return (ERROR);
  806.     }
  807.  
  808.     Log("adminalert: Kalasag is now active and listening.\n");
  809.  
  810.     /* main detection loop */
  811.     for (;;) {
  812.         if (PacketReadUDP(openSockfd, &ip, &udp) != TRUE)
  813.             continue;
  814.  
  815.         incomingPort = ntohs(udp.dest);
  816.  
  817.         /* check if we should ignore this connection to this port */
  818.         for (count = 0; count < portCount; count++) {
  819.             if ((incomingPort == inUsePorts[count])
  820.                 || (incomingPort >= advancedPorts)) {
  821.                 hotPort = FALSE;
  822.                 break;
  823.             } else
  824.                 hotPort = TRUE;
  825.         }
  826.  
  827.         if (hotPort) {
  828.             smartVerify = SmartVerifyUDP(client, server, incomingPort);
  829.  
  830.             if (smartVerify != TRUE) {
  831.                 /* copy the clients address into our buffer for nuking */
  832.                 addr.s_addr = (u_int) ip.saddr;
  833.                 SafeStrncpy(target, (char *) inet_ntoa(addr), IPMAXBUF);
  834.                 /* check if we should ignore this IP */
  835.                 result = NeverBlock(target, gblIgnoreFile);
  836.  
  837.                 if (result == ERROR) {
  838.                     Log("attackalert: ERROR: cannot open ignore file. Blocking host anyway.\n");
  839.                     result = FALSE;
  840.                 }
  841.  
  842.                 if (result == FALSE) {
  843.                     /* check if they've visited before */
  844.                     scanDetectTrigger = CheckStateEngine(target);
  845.  
  846.                     if (scanDetectTrigger == TRUE) {
  847.                         if (gblResolveHost) {   /* Do they want DNS resolution? */
  848.                             if (CleanAndResolve(resolvedHost, target) !=
  849.                                 TRUE) {
  850.                                 Log("attackalert: ERROR: Error resolving host. \
  851.                                         resolving disabled for this host.\n");
  852.                                 snprintf(resolvedHost, DNSMAXBUF, "%s",
  853.                                          target);
  854.                             }
  855.                         } else {
  856.                             snprintf(resolvedHost, DNSMAXBUF, "%s",
  857.                                      target);
  858.                         }
  859.  
  860.                         Log("attackalert: UDP scan from host: %s/%s to UDP port: %d", resolvedHost, target, incomingPort);
  861.                         /* Report on options present */
  862.                         if (ip.ihl > 5)
  863.                             Log("attackalert: Packet from host: %s/%s to UDP port: %d has IP options set (detection avoidance technique).", resolvedHost, target, incomingPort);
  864.  
  865.                         /* check if this target is already blocked */
  866.                         if (IsBlocked(target, gblBlockedFile) == FALSE) {
  867.                             if (DisposeUDP(target, incomingPort) != TRUE)
  868.                                 Log("attackalert: ERROR: Could not block host %s/%s!!", resolvedHost, target);
  869.                             else
  870.                                 WriteBlocked(target, resolvedHost,
  871.                                              incomingPort, gblBlockedFile,
  872.                                              gblHistoryFile, "UDP");
  873.                         } /* end IsBlocked check */
  874.                         else
  875.                             Log("attackalert: Host: %s/%s is already blocked Ignoring", resolvedHost, target);
  876.                     }           /* end if(scanDetectTrigger) */
  877.                 }               /* end if(never block) check */
  878.             }                   /* end if (smartVerify) */
  879.         }                       /* end if(hotPort) */
  880.     }                           /* end for( ; ; ) loop */
  881. }
  882.  
  883. /* end KalasagAdvancedStealthModeUDP */
  884.  
  885. #endif
  886.  
  887.  
  888.  
  889.  
  890. /****************************************************************/
  891. /* Classic detection Mode                                       */
  892. /*                                                              */
  893. /* This mode will bind to a list of TCP sockets and wait for    */
  894. /* connections to happen. Although the least prone to false     */
  895. /* alarms, it also won't detect stealth scans                   */
  896. /*                                                              */
  897. /****************************************************************/
  898. int KalasagModeTCP(void)
  899. {
  900.  
  901.     struct sockaddr_in client, server;
  902.     int length, portCount = 0, ports[MAXSOCKS];
  903.     int openSockfd[MAXSOCKS], incomingSockfd, result = TRUE;
  904.     int count = 0, scanDetectTrigger = TRUE, showBanner =
  905.         FALSE, boundPortCount = 0;
  906.     int selectResult = 0;
  907.     char *temp, target[IPMAXBUF], bannerBuffer[MAXBUF],
  908.         configToken[MAXBUF];
  909.     char resolvedHost[DNSMAXBUF];
  910.     fd_set selectFds;
  911.  
  912.     if ((ConfigTokenRetrieve("TCP_PORTS", configToken)) == FALSE) {
  913.         Log("adminalert: ERROR: Could not read TCP_PORTS option from config file");
  914.         return (ERROR);
  915.     }
  916.  
  917.     /* break out the ports */
  918.     if ((temp = (char *) strtok(configToken, ",")) != NULL) {
  919.         ports[0] = atoi(temp);
  920.         for (count = 1; count < MAXSOCKS; count++) {
  921.             if ((temp = (char *) strtok(NULL, ",")) != NULL)
  922.                 ports[count] = atoi(temp);
  923.             else
  924.                 break;
  925.         }
  926.         portCount = count;
  927.     } else {
  928.         Log("adminalert: ERROR: No TCP ports supplied in config file. Aborting");
  929.         return (ERROR);
  930.     }
  931.  
  932.     /* read in the banner if one is given */
  933.     if ((ConfigTokenRetrieve("PORT_BANNER", configToken)) == TRUE) {
  934.         showBanner = TRUE;
  935.         SafeStrncpy(bannerBuffer, configToken, MAXBUF);
  936.     }
  937.  
  938.  
  939.     /* setup select call */
  940.     FD_ZERO(&selectFds);
  941.  
  942.     for (count = 0; count < portCount; count++) {
  943.         Log("adminalert: Going into listen mode on TCP port: %d\n",
  944.             ports[count]);
  945.         if ((openSockfd[boundPortCount] = OpenTCPSocket()) == ERROR) {
  946.             Log("adminalert: ERROR: could not open TCP socket. Aborting.\n");
  947.             return (ERROR);
  948.         }
  949.  
  950.         if (BindSocket
  951.             (openSockfd[boundPortCount], client, server,
  952.              ports[count]) == ERROR) {
  953.             Log("adminalert: ERROR: could not bind TCP socket: %d. Attempting to continue\n", ports[count]);
  954.         } else                  /* well we at least bound to one socket so we'll continue */
  955.             boundPortCount++;
  956.     }
  957.  
  958.  
  959.     /* if we didn't bind to anything then abort */
  960.     if (boundPortCount == 0) {
  961.         Log("adminalert: ERROR: could not bind ANY TCP sockets. Shutting down.\n");
  962.         return (ERROR);
  963.     }
  964.  
  965.     length = sizeof(client);
  966.  
  967.     Log("adminalert: Kalasag is now active and listening.\n");
  968.  
  969.     /* main loop for multiplexing/resetting */
  970.     for (;;) {
  971.         /* set up select call */
  972.         for (count = 0; count < boundPortCount; count++)
  973.             FD_SET(openSockfd[count], &selectFds);
  974.         selectResult =
  975.             select(MAXSOCKS, &selectFds, NULL, NULL,
  976.                    (struct timeval *) NULL);
  977.  
  978.         /* something blew up */
  979.         if (selectResult < 0) {
  980.             Log("adminalert: ERROR: select call failed. Shutting down.\n");
  981.             return (ERROR);
  982.         } else if (selectResult == 0) {
  983. #ifdef DEBUG
  984.             Log("Select timeout");
  985. #endif
  986.         }
  987.  
  988.         /* select is reporting a waiting socket. Poll them all to find out which */
  989.         else if (selectResult > 0) {
  990.             for (count = 0; count < boundPortCount; count++) {
  991.                 if (FD_ISSET(openSockfd[count], &selectFds)) {
  992.                     incomingSockfd =
  993.                         accept(openSockfd[count],
  994.                                (struct sockaddr *) &client, &length);
  995.                     if (incomingSockfd < 0) {
  996.                         Log("attackalert: Possible stealth scan from unknown host to TCP port: %d (accept failed)", ports[count]);
  997.                         break;
  998.                     }
  999.  
  1000.                     /* copy the clients address into our buffer for nuking */
  1001.                     SafeStrncpy(target,
  1002.                                 (char *) inet_ntoa(client.sin_addr),
  1003.                                 IPMAXBUF);
  1004.                     /* check if we should ignore this IP */
  1005.                     result = NeverBlock(target, gblIgnoreFile);
  1006.  
  1007.                     if (result == ERROR) {
  1008.                         Log("attackalert: ERROR: cannot open ignore file. Blocking host anyway.\n");
  1009.                         result = FALSE;
  1010.                     }
  1011.  
  1012.                     if (result == FALSE) {
  1013.                         /* check if they've visited before */
  1014.                         scanDetectTrigger = CheckStateEngine(target);
  1015.  
  1016.                         if (scanDetectTrigger == TRUE) {
  1017.                             /* show the banner if one was selected */
  1018.                             if (showBanner == TRUE)
  1019.                                 write(incomingSockfd, bannerBuffer,
  1020.                                       strlen(bannerBuffer));
  1021.                             /* we don't need the bonehead anymore */
  1022.                             close(incomingSockfd);
  1023.                             if (gblResolveHost) {       /* Do they want DNS resolution? */
  1024.                                 if (CleanAndResolve(resolvedHost, target)
  1025.                                     != TRUE) {
  1026.                                     Log("attackalert: ERROR: Error resolving host. \
  1027.                                         resolving disabled for this host.\n");
  1028.                                     snprintf(resolvedHost, DNSMAXBUF, "%s",
  1029.                                              target);
  1030.                                 }
  1031.                             } else {
  1032.                                 snprintf(resolvedHost, DNSMAXBUF, "%s",
  1033.                                          target);
  1034.                             }
  1035.  
  1036.                             Log("attackalert: Connect from host: %s/%s to TCP port: %d", resolvedHost, target, ports[count]);
  1037.  
  1038.                             /* check if this target is already blocked */
  1039.                             if (IsBlocked(target, gblBlockedFile) == FALSE) {
  1040.                                 if (DisposeTCP(target, ports[count]) !=
  1041.                                     TRUE)
  1042.                                     Log("attackalert: ERROR: Could not block host %s !!", target);
  1043.                                 else
  1044.                                     WriteBlocked(target, resolvedHost,
  1045.                                                  ports[count],
  1046.                                                  gblBlockedFile,
  1047.                                                  gblHistoryFile, "TCP");
  1048.                             } else
  1049.                                 Log("attackalert: Host: %s is already blocked. Ignoring", target);
  1050.                         }
  1051.                     }
  1052.                     close(incomingSockfd);
  1053.                     break;
  1054.                 }               /* end if(FD_ISSET) */
  1055.             }                   /* end for() */
  1056.         }                       /* end else (selectResult > 0) */
  1057.     }                           /* end main for(; ; ) loop */
  1058.  
  1059. /* not reached */
  1060.     close(incomingSockfd);
  1061. }
  1062.  
  1063.  
  1064.  
  1065.  
  1066.  
  1067. /****************************************************************/
  1068. /* Classic detection Mode                                       */
  1069. /*                                                              */
  1070. /* This mode will bind to a list of UDP sockets and wait for    */
  1071. /* connections to happen. Stealth scanning really doesn't apply */
  1072. /* here.                                                        */
  1073. /*                                                              */
  1074. /****************************************************************/
  1075. int KalasagModeUDP(void)
  1076. {
  1077.     struct sockaddr_in client, server;
  1078.     int length, ports[MAXSOCKS], openSockfd[MAXSOCKS], result = TRUE;
  1079.     int count = 0, portCount = 0, selectResult = 0, scanDetectTrigger = 0;
  1080.     int boundPortCount = 0, showBanner = FALSE;
  1081.     char *temp, target[IPMAXBUF], bannerBuffer[MAXBUF],
  1082.         configToken[MAXBUF];
  1083.     char buffer[MAXBUF];
  1084.     char resolvedHost[DNSMAXBUF];
  1085.     fd_set selectFds;
  1086.  
  1087.     if ((ConfigTokenRetrieve("UDP_PORTS", configToken)) == FALSE) {
  1088.         Log("adminalert: ERROR: Could not read UDP_PORTS option from config file");
  1089.         return (ERROR);
  1090.     }
  1091.  
  1092.     /* break out the ports */
  1093.     if ((temp = (char *) strtok(configToken, ",")) != NULL) {
  1094.         ports[0] = atoi(temp);
  1095.         for (count = 1; count < MAXSOCKS; count++) {
  1096.             if ((temp = (char *) strtok(NULL, ",")) != NULL)
  1097.                 ports[count] = atoi(temp);
  1098.             else
  1099.                 break;
  1100.         }
  1101.         portCount = count;
  1102.     } else {
  1103.         Log("adminalert: ERROR: No UDP ports supplied in config file. Aborting");
  1104.         return (ERROR);
  1105.     }
  1106.  
  1107.     /* read in the banner if one is given */
  1108.     if ((ConfigTokenRetrieve("PORT_BANNER", configToken)) == TRUE) {
  1109.         showBanner = TRUE;
  1110.         SafeStrncpy(bannerBuffer, configToken, MAXBUF);
  1111.     }
  1112.  
  1113.     /* setup select call */
  1114.     FD_ZERO(&selectFds);
  1115.  
  1116.     for (count = 0; count < portCount; count++) {
  1117.         Log("adminalert: Going into listen mode on UDP port: %d\n",
  1118.             ports[count]);
  1119.         if ((openSockfd[boundPortCount] = OpenUDPSocket()) == ERROR) {
  1120.             Log("adminalert: ERROR: could not open UDP socket. Aborting\n");
  1121.             return (ERROR);
  1122.         }
  1123.         if (BindSocket
  1124.             (openSockfd[boundPortCount], client, server,
  1125.              ports[count]) == ERROR) {
  1126.             Log("adminalert: ERROR: could not bind UDP socket: %d. Attempting to continue\n", ports[count]);
  1127.         } else                  /* well we at least bound to one socket so we'll continue */
  1128.             boundPortCount++;
  1129.     }
  1130.  
  1131. /* if we didn't bind to anything then abort */
  1132.     if (boundPortCount == 0) {
  1133.         Log("adminalert: ERROR: could not bind ANY UDP sockets. Shutting down.\n");
  1134.         return (ERROR);
  1135.     }
  1136.  
  1137.  
  1138.     length = sizeof(client);
  1139.     Log("adminalert: Kalasag is now active and listening.\n");
  1140.  
  1141. /* main loop for multiplexing/resetting */
  1142.     for (;;) {
  1143.         /* set up select call */
  1144.         for (count = 0; count < boundPortCount; count++)
  1145.             FD_SET(openSockfd[count], &selectFds);
  1146.         /* setup the select multiplexing (blocking mode) */
  1147.         selectResult =
  1148.             select(MAXSOCKS, &selectFds, NULL, NULL,
  1149.                    (struct timeval *) NULL);
  1150.  
  1151.         if (selectResult < 0) {
  1152.             Log("adminalert: ERROR: select call failed. Shutting down.\n");
  1153.             return (ERROR);
  1154.         } else if (selectResult == 0) {
  1155. #ifdef DEBUG
  1156.             Log("Select timeout");
  1157. #endif
  1158.         }
  1159.  
  1160.         /* select is reporting a waiting socket. Poll them all to find out which */
  1161.         else if (selectResult > 0) {
  1162.             for (count = 0; count < portCount; count++) {
  1163.                 if (FD_ISSET(openSockfd[count], &selectFds)) {
  1164.                     /* here just read in one byte from the UDP socket, that's all we need to */
  1165.                     /* know that this person is a jerk */
  1166.                     if (recvfrom(openSockfd[count], buffer, 1, 0,
  1167.                                  (struct sockaddr *) &client, &length) < 0)
  1168.                     {
  1169.                         Log("adminalert: ERROR: could not accept incoming socket for UDP port: %d\n", ports[count]);
  1170.                         break;
  1171.                     }
  1172.  
  1173.                     /* copy the clients address into our buffer for nuking */
  1174.                     SafeStrncpy(target,
  1175.                                 (char *) inet_ntoa(client.sin_addr),
  1176.                                 IPMAXBUF);
  1177. #ifdef DEBUG
  1178.                     Log("debug: KalasagModeUDP: accepted UDP connection from: %s\n", target);
  1179. #endif
  1180.                     /* check if we should ignore this IP */
  1181.                     result = NeverBlock(target, gblIgnoreFile);
  1182.                     if (result == ERROR) {
  1183.                         Log("attackalert: ERROR: cannot open ignore file. Blocking host anyway.\n");
  1184.                         result = FALSE;
  1185.                     }
  1186.                     if (result == FALSE) {
  1187.                         /* check if they've visited before */
  1188.                         scanDetectTrigger = CheckStateEngine(target);
  1189.                         if (scanDetectTrigger == TRUE) {
  1190.                             /* show the banner if one was selected */
  1191.                             if (showBanner == TRUE)
  1192.                                 sendto(openSockfd[count], bannerBuffer,
  1193.                                        strlen(bannerBuffer), 0,
  1194.                                        (struct sockaddr *) &client,
  1195.                                        length);
  1196.  
  1197.                             if (gblResolveHost) {       /* Do they want DNS resolution? */
  1198.                                 if (CleanAndResolve(resolvedHost, target)
  1199.                                     != TRUE) {
  1200.                                     Log("attackalert: ERROR: Error resolving host. \
  1201.                                         resolving disabled for this host.\n");
  1202.                                     snprintf(resolvedHost, DNSMAXBUF, "%s",
  1203.                                              target);
  1204.                                 }
  1205.                             } else {
  1206.                                 snprintf(resolvedHost, DNSMAXBUF, "%s",
  1207.                                          target);
  1208.                             }
  1209.  
  1210.                             Log("attackalert: Connect from host: %s/%s to UDP port: %d", resolvedHost, target, ports[count]);
  1211.                             /* check if this target is already blocked */
  1212.                             if (IsBlocked(target, gblBlockedFile) == FALSE) {
  1213.                                 if (DisposeUDP(target, ports[count]) !=
  1214.                                     TRUE)
  1215.                                     Log("attackalert: ERROR: Could not block host %s !!", target);
  1216.                                 else
  1217.                                     WriteBlocked(target, resolvedHost,
  1218.                                                  ports[count],
  1219.                                                  gblBlockedFile,
  1220.                                                  gblHistoryFile, "UDP");
  1221.                             } else
  1222.                                 Log("attackalert: Host: %s is already blocked. Ignoring", target);
  1223.                         }
  1224.                     }
  1225.                     break;
  1226.                 }               /* end if(FD_ISSET) */
  1227.             }                   /* end for() */
  1228.         }                       /* end else (selectResult > 0) */
  1229.     }                           /* end main for(; ; ) loop */
  1230.  
  1231. }                               /* end UDP Kalasag */
  1232.  
  1233.  
  1234.  
  1235.  
  1236. /* kill the TCP connection depending on config option */
  1237. int DisposeTCP(char *target, int port)
  1238. {
  1239.     int status = TRUE;
  1240.  
  1241. #ifdef DEBUG
  1242.     Log("debug: DisposeTCP: disposing of host %s on port %d with option: %d", target, port, gblBlockTCP);
  1243.     Log("debug: DisposeTCP: killRunCmd: %s", gblKillRunCmd);
  1244.     Log("debug: DisposeTCP: gblRunCmdFirst: %d", gblRunCmdFirst);
  1245.     Log("debug: DisposeTCP: killHostsDeny: %s", gblKillHostsDeny);
  1246.     Log("debug: DisposeTCP: killRoute: %s  %d", gblKillRoute,
  1247.         strlen(gblKillRoute));
  1248. #endif
  1249. /* Should we ignore TCP from active response? */
  1250.     if (gblBlockTCP == 1) {
  1251.         /* run external command first, hosts.deny second, dead route last */
  1252.         if (gblRunCmdFirst) {
  1253.             if (strlen(gblKillRunCmd) > 0)
  1254.                 if (KillRunCmd
  1255.                     (target, port, gblKillRunCmd,
  1256.                      gblDetectionType) != TRUE)
  1257.                     status = FALSE;
  1258.             if (strlen(gblKillHostsDeny) > 0)
  1259.                 if (KillHostsDeny
  1260.                     (target, port, gblKillHostsDeny,
  1261.                      gblDetectionType) != TRUE)
  1262.                     status = FALSE;
  1263.             if (strlen(gblKillRoute) > 0)
  1264.                 if (KillRoute(target, port, gblKillRoute, gblDetectionType)
  1265.                     != TRUE)
  1266.                     status = FALSE;
  1267.         }
  1268.         /* run hosts.deny first, dead route second, external command last */
  1269.         else {
  1270.             if (strlen(gblKillHostsDeny) > 0)
  1271.                 if (KillHostsDeny
  1272.                     (target, port, gblKillHostsDeny,
  1273.                      gblDetectionType) != TRUE)
  1274.                     status = FALSE;
  1275.             if (strlen(gblKillRoute) > 0)
  1276.                 if (KillRoute(target, port, gblKillRoute, gblDetectionType)
  1277.                     != TRUE)
  1278.                     status = FALSE;
  1279.             if (strlen(gblKillRunCmd) > 0)
  1280.                 if (KillRunCmd
  1281.                     (target, port, gblKillRunCmd,
  1282.                      gblDetectionType) != TRUE)
  1283.                     status = FALSE;
  1284.         }
  1285.     } else if (gblBlockTCP == 2) {
  1286.         /* run external command only */
  1287.         if (strlen(gblKillRunCmd) > 0)
  1288.             if (KillRunCmd(target, port, gblKillRunCmd, gblDetectionType)
  1289.                 != TRUE)
  1290.                 status = FALSE;
  1291.     } else
  1292.         Log("attackalert: Ignoring TCP response per configuration file setting.");
  1293.  
  1294.     return (status);
  1295. }
  1296.  
  1297.  
  1298. /* kill the UDP connection depending on config option */
  1299. int DisposeUDP(char *target, int port)
  1300. {
  1301.     int status = TRUE;
  1302.  
  1303. #ifdef DEBUG
  1304.     Log("debug: DisposeUDP: disposing of host %s on port %d with option: %d", target, port, gblBlockUDP);
  1305.     Log("debug: DisposeUDP: killRunCmd: %d", gblKillRunCmd);
  1306.     Log("debug: DisposeUDP: gblRunCmdFirst: %s", gblRunCmdFirst);
  1307.     Log("debug: DisposeUDP: killHostsDeny: %s", gblKillHostsDeny);
  1308.     Log("debug: DisposeUDP: killRoute: %s  %d", gblKillRoute,
  1309.         strlen(gblKillRoute));
  1310. #endif
  1311. /* Should we ignore TCP from active response? */
  1312.     if (gblBlockUDP == 1) {
  1313.         /* run external command first, hosts.deny second, dead route last */
  1314.         if (gblRunCmdFirst) {
  1315.             if (strlen(gblKillRunCmd) > 0)
  1316.                 if (KillRunCmd
  1317.                     (target, port, gblKillRunCmd,
  1318.                      gblDetectionType) != TRUE)
  1319.                     status = FALSE;
  1320.             if (strlen(gblKillHostsDeny) > 0)
  1321.                 if (KillHostsDeny
  1322.                     (target, port, gblKillHostsDeny,
  1323.                      gblDetectionType) != TRUE)
  1324.                     status = FALSE;
  1325.             if (strlen(gblKillRoute) > 0)
  1326.                 if (KillRoute(target, port, gblKillRoute, gblDetectionType)
  1327.                     != TRUE)
  1328.                     status = FALSE;
  1329.         }
  1330.         /* run hosts.deny first, dead route second, external command last */
  1331.         else {
  1332.             if (strlen(gblKillHostsDeny) > 0)
  1333.                 if (KillHostsDeny
  1334.                     (target, port, gblKillHostsDeny,
  1335.                      gblDetectionType) != TRUE)
  1336.                     status = FALSE;
  1337.             if (strlen(gblKillRoute) > 0)
  1338.                 if (KillRoute(target, port, gblKillRoute, gblDetectionType)
  1339.                     != TRUE)
  1340.                     status = FALSE;
  1341.             if (strlen(gblKillRunCmd) > 0)
  1342.                 if (KillRunCmd
  1343.                     (target, port, gblKillRunCmd,
  1344.                      gblDetectionType) != TRUE)
  1345.                     status = FALSE;
  1346.         }
  1347.     } else if (gblBlockUDP == 2) {
  1348.         /* run external command only */
  1349.         if (strlen(gblKillRunCmd) > 0)
  1350.             if (KillRunCmd(target, port, gblKillRunCmd, gblDetectionType)
  1351.                 != TRUE)
  1352.                 status = FALSE;
  1353.     } else
  1354.         Log("attackalert: Ignoring UDP response per configuration file setting.");
  1355.  
  1356.     return (status);
  1357. }
  1358.  
  1359.  
  1360. /* duh */
  1361. void Usage(void)
  1362. {
  1363.     printf("Kalasag Port Scan Detector\n");
  1364.     printf("Version: %s\n\n", VERSION);
  1365. #ifdef SUPPORT_STEALTH
  1366.     printf("usage: kalasag [-tcp -udp -stcp -atcp -sudp -audp]\n\n");
  1367. #else
  1368.     printf("Stealth scan detection not supported on this platform\n");
  1369.     printf("usage: kalasag [-tcp -udp]\n\n");
  1370. #endif
  1371. /*
  1372.   printf ("*** PLEASE READ THE DOCS BEFORE USING *** \n\n");
  1373. */
  1374. }
  1375.  
  1376.  
  1377.  
  1378. /* our cheesy state engine to monitor who has connected here before */
  1379. int CheckStateEngine(char *target)
  1380. {
  1381.     int count = 0, scanDetectTrigger = TRUE;
  1382.     int gotOne = 0;
  1383.  
  1384. /* This is the rather basic scan state engine. It maintains     */
  1385. /* an array of past hosts who triggered a connection on a port */
  1386. /* when a new host arrives it is compared against the array */
  1387. /* if it is found in the array it increments a state counter by */
  1388. /* one and checks the remainder of the array. It does this until */
  1389. /* the end is reached or the trigger value has been exceeded */
  1390. /* This would probably be better as a linked list/hash table, */
  1391. /* but for the number of hosts we are tracking this is just as good. */
  1392. /* This will probably change in the future */
  1393.  
  1394.     gotOne = 1;                 /* our flag counter if we get a match */
  1395.     scanDetectTrigger = TRUE;   /* set to TRUE until set otherwise */
  1396.  
  1397.     if (gblConfigTriggerCount > 0) {
  1398.         for (count = 0; count < MAXSTATE; count++) {
  1399.             /* if the array has the IP address then increment the gotOne counter and */
  1400.             /* check the trigger value. If it is exceeded break out of the loop and */
  1401.             /* set the detecttrigger to TRUE */
  1402.             if (strcmp(gblScanDetectHost[count], target) == 0) {
  1403.                 /* compare the number of matches to the configured trigger value */
  1404.                 /* if we've exceeded we can stop this noise */
  1405.                 if (++gotOne >= gblConfigTriggerCount) {
  1406.                     scanDetectTrigger = TRUE;
  1407. #ifdef DEBUG
  1408.                     Log("debug: CheckStateEngine: host: %s has exceeded trigger value: %d\n", gblScanDetectHost[count], gblConfigTriggerCount);
  1409. #endif
  1410.                     break;
  1411.                 }
  1412.             } else
  1413.                 scanDetectTrigger = FALSE;
  1414.         }
  1415.  
  1416.         /* now add the fresh meat into the state engine */
  1417.         /* if our array is still less than MAXSTATE large add it to the end */
  1418.         if (gblScanDetectCount < MAXSTATE) {
  1419.             SafeStrncpy(gblScanDetectHost[gblScanDetectCount], target,
  1420.                         IPMAXBUF);
  1421.             gblScanDetectCount++;
  1422.         } else {
  1423.             /* otherwise tack it to the beginning and start overwriting older ones */
  1424.             gblScanDetectCount = 0;
  1425.             SafeStrncpy(gblScanDetectHost[gblScanDetectCount], target,
  1426.                         IPMAXBUF);
  1427.             gblScanDetectCount++;
  1428.         }
  1429.  
  1430. #ifdef DEBUG
  1431.         for (count = 0; count < MAXSTATE; count++)
  1432.             Log("debug: CheckStateEngine: state engine host: %s -> position: %d Detected: %d\n", gblScanDetectHost[count], count, scanDetectTrigger);
  1433. #endif
  1434.         /* end catch to set state if gblConfigTriggerCount == 0 */
  1435.         if (gotOne >= gblConfigTriggerCount)
  1436.             scanDetectTrigger = TRUE;
  1437.     }
  1438.  
  1439.  
  1440.     if (gblConfigTriggerCount > MAXSTATE) {
  1441.         Log("securityalert: WARNING: Trigger value %d is larger than state engine capacity of %d.\n", gblConfigTriggerCount);
  1442.         Log("Adjust the value lower or recompile with a larger state engine value.\n", MAXSTATE);
  1443.         Log("securityalert: Blocking host anyway because of invalid trigger value");
  1444.         scanDetectTrigger = TRUE;
  1445.     }
  1446.     return (scanDetectTrigger);
  1447. }
  1448.  
  1449.  
  1450. #ifdef SUPPORT_STEALTH
  1451. /* This takes a tcp packet and reports what type of scan it is */
  1452. char *ReportPacketType(struct tcphdr tcpPkt)
  1453. {
  1454.     static char packetDesc[MAXBUF];
  1455.     static char *packetDescPtr = packetDesc;
  1456.  
  1457.     if ((tcpPkt.syn == 0) && (tcpPkt.fin == 0) && (tcpPkt.ack == 0)
  1458.         && (tcpPkt.psh == 0) && (tcpPkt.rst == 0) && (tcpPkt.urg == 0))
  1459.         snprintf(packetDesc, MAXBUF, " TCP NULL scan");
  1460.     else if ((tcpPkt.fin == 1) && (tcpPkt.urg == 1) && (tcpPkt.psh == 1))
  1461.         snprintf(packetDesc, MAXBUF, "TCP XMAS scan");
  1462.     else if ((tcpPkt.fin == 1) && (tcpPkt.syn != 1) && (tcpPkt.ack != 1)
  1463.              && (tcpPkt.psh != 1) && (tcpPkt.rst != 1)
  1464.              && (tcpPkt.urg != 1))
  1465.         snprintf(packetDesc, MAXBUF, "TCP FIN scan");
  1466.     else if ((tcpPkt.syn == 1) && (tcpPkt.fin != 1) && (tcpPkt.ack != 1)
  1467.              && (tcpPkt.psh != 1) && (tcpPkt.rst != 1)
  1468.              && (tcpPkt.urg != 1))
  1469.         snprintf(packetDesc, MAXBUF, "TCP SYN/Normal scan");
  1470.     else
  1471.         snprintf(packetDesc, MAXBUF,
  1472.                  "Unknown Type: TCP Packet Flags: SYN: %d FIN: %d ACK: %d PSH: %d URG: %d RST: %d",
  1473.                  tcpPkt.syn, tcpPkt.fin, tcpPkt.ack, tcpPkt.psh,
  1474.                  tcpPkt.urg, tcpPkt.rst);
  1475.  
  1476.     return (packetDescPtr);
  1477. }
  1478.  
  1479. int
  1480. SmartVerifyTCP(struct sockaddr_in client, struct sockaddr_in server,
  1481.                int port)
  1482. {
  1483.  
  1484.     int testSockfd;
  1485.  
  1486. /* Ok here is where we "Smart-Verify" the socket. If the port was previously */
  1487. /* unbound, but now appears to have someone there, then we will skip responding */
  1488. /* to this inbound packet. This a basic "stateful" inspection of the */
  1489. /* the connection */
  1490.  
  1491.     if ((testSockfd = OpenTCPSocket()) == ERROR) {
  1492.         Log("adminalert: ERROR: could not open TCP socket to smart-verify.\n");
  1493.         return (FALSE);
  1494.     } else {
  1495.         if (BindSocket(testSockfd, client, server, port) == ERROR) {
  1496. #ifdef DEBUG
  1497.             Log("debug: SmartVerify: Smart-Verify Port In Use: %d", port);
  1498. #endif
  1499.             close(testSockfd);
  1500.             return (TRUE);
  1501.         }
  1502.     }
  1503.  
  1504.     close(testSockfd);
  1505.     return (FALSE);
  1506. }
  1507.  
  1508. int
  1509. SmartVerifyUDP(struct sockaddr_in client, struct sockaddr_in server,
  1510.                int port)
  1511. {
  1512.     int testSockfd;
  1513.  
  1514. /* Ok here is where we "Smart-Verify" the socket. If the port was previously */
  1515. /* unbound, but now appears to have someone there, then we will skip responding */
  1516. /* to this inbound packet. This essentially is a "stateful" inspection of the */
  1517. /* the connection */
  1518.  
  1519.     if ((testSockfd = OpenUDPSocket()) == ERROR) {
  1520.         Log("adminalert: ERROR: could not open UDP socket to smart-verify.\n");
  1521.         return (FALSE);
  1522.     } else {
  1523.         if (BindSocket(testSockfd, client, server, port) == ERROR) {
  1524. #ifdef DEBUG
  1525.             Log("debug: SmartVerify: Smart-Verify Port In Use: %d", port);
  1526. #endif
  1527.             close(testSockfd);
  1528.             return (TRUE);
  1529.         }
  1530.     }
  1531.  
  1532.     close(testSockfd);
  1533.     return (FALSE);
  1534. }
  1535.  
  1536. #endif                          /* SUPPORT_STEALTH */
  1537.  
BZ2
Auto-generated tar archives of git commits on the current branch are here.
Filedrop
download filekalasag.git-97c89e1.tar.bz2
20.82 KB
12 downloads
download filekalasag.git-1141d13.tar.bz2
20.65 KB
559 downloads
download filekalasag.git-ee3c17b.tar.bz2
20.65 KB
535 downloads
download filekalasag.git-4032c54.tar.bz2
20.63 KB
7 downloads
download filekalasag.git-e51a2a6.tar.bz2
20.65 KB
8 downloads
download filekalasag.git-599c93a.tar.bz2
20.63 KB
6 downloads
download filekalasag.git-acdc640.tar.bz2
20.63 KB
8 downloads
ZIP
Friday, Aug 26, 2011, 3:47 AM
Auto-generated zip archives of git commits on the current branch are here.
Filedrop
download filekalasag.git-97c89e1.zip
25.68 KB
8 downloads
download filekalasag.git-1141d13.zip
25.37 KB
8 downloads
download filekalasag.git-ee3c17b.zip
25.34 KB
7 downloads
download filekalasag.git-4032c54.zip
25.13 KB
10 downloads
download filekalasag.git-e51a2a6.zip
25.13 KB
10 downloads
download filekalasag.git-599c93a.zip
25.11 KB
1326 downloads
download filekalasag.git-acdc640.zip
25.10 KB
10 downloads