kalasag.org

kalasag.org

Git

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