Main Page | Modules | Class List | Directories | File List | Class Members | File Members | Related Pages

spp_stickydrop.c

Go to the documentation of this file.
00001 /* $Id: spp_template.c,v 1.5 2004/02/13 16:19:03 roesch Exp $ */
00002 /* Snort Preprocessor Plugin Source File Template */
00003 
00004 /* spp_stickydrop 
00005  *
00006  * Purpose:
00007  *
00008  * Sticky Drop is a simple packet filter that drops packets based on a timeout 
00009  * specified by the user through the sticky-drop rule keyword, or through special
00010  * options added to preprocessors.   
00011  *
00012  *
00013  * Arguments:
00014  *
00015  * Ummmmmm nil at the moment, will add a whitlist or never drop list
00016  * Effect:
00017  *
00018  * Drop packets from people we don't like because they are messing with our stuff.
00019  *
00020  *
00021  */
00022 
00023 
00024 /* stickydrop is for inline */
00025 #ifdef GIDS
00026 
00027 
00028 #include <sys/types.h>
00029 #include <stdlib.h>
00030 #include <ctype.h>
00031 #include <rpc/types.h>
00032 #include "generators.h"
00033 #include "event_wrapper.h"
00034 #include "assert.h"
00035 #include "util.h"
00036 #include "plugbase.h"
00037 #include "parser.h"
00038 #include "mempool.h"
00039 #include "plugbase.h"
00040 #include "mstring.h"
00041 #include "util.h"
00042 #include "log.h"
00043 #include "parser.h"
00044 #include "detect.h"
00045 #include "rules.h"
00046 #include "decode.h"
00047 #include "debug.h"
00048 #include "ubi_SplayTree.h"
00049 #include "ubi_BinTree.h"
00050 
00051 #ifndef WIN32
00052 #include <sys/socket.h>
00053 #include <netinet/in.h>
00054 #include <arpa/inet.h>
00055 #endif /* WIN32 */
00056 
00057 #include "spp_stickydrop.h"
00058 #include "inline.h"
00059 
00060 #define MAX_PORTS               64
00061 #define MEM_CHUNK               32
00062 #define DIRECTION_SOURCE        0
00063 #define DIRECTION_DST           1
00064 
00065 /* Data Used for Sticky Drop */
00066 typedef struct _StickyD
00067 {
00068     ubi_trRoot attackerRoot;  /* this tree is for the blocker ip addy's */
00069     ubi_trRootPtr attackerRootPtr;
00070     MemPool AttackerPool;
00071     u_int32_t max_block_entries;
00072     char log;
00073     FILE *logfile;
00074     char *logpath;
00075 
00076 } StickyD;
00077 
00078 StickyD stickd;
00079 
00080 
00081 typedef struct _Attacker
00082 {
00083     ubi_trNode Node;             /* for the splay tree */
00084     MemBucket *bucket;
00085     u_int32_t ip;
00086     u_int32_t timeout;
00087     struct timeval blocktime;
00088     struct timeval unblocktime;
00089 
00090 } Attacker;
00091 
00092 Attacker attacker;
00093 
00094 typedef struct _sdhostNode
00095 {
00096     IpAddrSet *address;
00097     u_short hsp;         /* hi src port */
00098     u_short lsp;         /* lo src port */
00099     u_int32_t flags;     /* control flags */
00100     struct _sdhostNode *nextNode;
00101 
00102 } sdHostNode;
00103 
00104 sdHostNode *sdignoreList; /* for ignore-hosts */
00105 int num_ports_from;
00106 int num_ports_to;
00107 u_int32_t *sdignorePortFrom;
00108 u_int32_t *sdignorePortTo;
00109 
00110 
00111 static void StickyDropInit(u_char *);
00112 static void ParseStickyDropArgs(char *);
00113 void StickyDrop(Packet *, void *);
00114 void SDLog(Packet *);
00115 static int IpAddressCompareFunction(ubi_trItemPtr, ubi_trNodePtr);
00116 static int PruneAttackers(u_int32_t now, int tokill, Attacker *saveme);
00117 static void PreprocCleanExitFunction(int, void *);
00118 static void PreprocRestartFunction(int, void *);
00119 
00120 /* For portscan args */
00121 static void sdInitTimeouts(u_char *);
00122 static void ParseSDTimeoutArgs(char *);
00123  
00124 /* For ignore hosts */
00125 void sdInitIgnoreHosts(u_char *);
00126 IpAddrSet* sdIgnoreAllocAddrNode(sdHostNode *);
00127 void sdScanParseIp(char *, sdHostNode *);
00128 
00129 /* For ignore ports */
00130 void sdInitIgnoreFrom(u_char *);
00131 void sdInitIgnoreTo(u_char *);
00132 void sdInitIgnorePorts(u_char *, u_int32_t **, int *);
00133 u_int32_t sdScanParsePort(char *);
00134 
00135 int sdIsIgnored(Packet *, char);
00136 int sdBlockTreeSearch(Packet *, char);
00137 
00138 static int s_stickyd_running = 0;
00139  
00140 SDtimeout sdt;
00141 extern int do_detect;
00142 
00143 
00144 /*
00145  * Function: SetupStickyDrop()
00146  *
00147  * Purpose: Registers the preprocessor keyword and initialization 
00148  *          function into the preprocessor list.  This is the function that
00149  *          gets called from InitPreprocessors() in plugbase.c.
00150  *
00151  * Arguments: None.
00152  *
00153  * Returns: void function
00154  *
00155  */
00156 void SetupStickyDrop()
00157 {
00158     /* 
00159      * link the preprocessor keyword to the init function in 
00160      * the preproc list 
00161      */
00162     RegisterPreprocessor("stickydrop", StickyDropInit);
00163     RegisterPreprocessor("stickydrop-timeouts",sdInitTimeouts);
00164     RegisterPreprocessor("stickydrop-ignorehosts", sdInitIgnoreHosts);
00165     RegisterPreprocessor("stickydrop-ignoreports-from", sdInitIgnoreFrom);
00166     RegisterPreprocessor("stickydrop-ignoreports-to", sdInitIgnoreTo);
00167     DEBUG_WRAP(DebugMessage(DEBUG_PLUGIN,"Preprocessor: StickyDrop is setup...\n"););
00168 }
00169 
00170 
00171 /*
00172  * Function: StickyDropInit(u_char *)
00173  *
00174  * Purpose: Calls the argument parsing function, performs final setup on data
00175  *          structs, links the preproc function into the function list.
00176  *
00177  * Arguments: args => ptr to argument string
00178  *
00179  * Returns: void function
00180  *
00181  */
00182 static void StickyDropInit(u_char *args)
00183 {
00184     DEBUG_WRAP(DebugMessage(DEBUG_PLUGIN,"Preprocessor: StickyDrop Initialized\n"););
00185 
00186     memset(&stickd, 0, sizeof(StickyD));
00187     ParseStickyDropArgs(args);
00188     stickd.attackerRootPtr = &stickd.attackerRoot;
00189 
00190     ubi_trInitTree(stickd.attackerRootPtr, IpAddressCompareFunction, 0);
00191     if(mempool_init(&stickd.AttackerPool , stickd.max_block_entries, sizeof(Attacker)))
00192     {
00193       FatalError("ERROR: Could not alloc memory for stickydrop entries\n");
00194     }
00195     else if(!InlineMode()) 
00196     {
00197       FatalError("ERROR: We have to be in InlineMode() to use stickydrop\n"); 
00198     }
00199 
00200     s_stickyd_running = 1;
00201     AddFuncToPreprocList(StickyDrop);
00202     AddFuncToCleanExitList(PreprocCleanExitFunction, NULL);
00203     AddFuncToRestartList(PreprocRestartFunction, NULL);
00204 }
00205 
00206 
00207 /*
00208  * Function: ParseStickyDropArgs(char *)
00209  *
00210  * Purpose: Process the preprocessor arguements from the rules file and 
00211  *          initialize the preprocessor's data struct.  This function doesn't
00212  *          have to exist if it makes sense to parse the args in the init 
00213  *          function.
00214  *
00215  * Arguments: args => argument list
00216  *
00217  * Returns: void function
00218  *
00219  */
00220 static void ParseStickyDropArgs(char *args)
00221 {
00222     int num_toks, s_toks;
00223     char **toks = NULL;
00224     char **stoks;
00225     int i;
00226     char* index;
00227     char logpath[STD_BUF], tmp[STD_BUF];
00228 
00229     /* setup the defaults */
00230     strlcpy(logpath, pv.log_dir, STD_BUF);
00231     strlcpy(tmp, "/stickyd.log", STD_BUF);
00232     strlcat(logpath, tmp, STD_BUF);
00233 
00234     stickd.max_block_entries = 5000;
00235     stickd.log = 0;
00236     if (args)
00237     {
00238 
00239         toks = mSplit(args, ",", 5, &num_toks, 0);
00240 
00241         i=0;
00242 
00243         while (i < num_toks)
00244         {
00245             index = toks[i];
00246 
00247             while(isspace((int)*index)) index++;
00248 
00249             stoks = mSplit(index, " ", 4, &s_toks, 0);
00250             if(!strcasecmp(stoks[0], "max_entries"))
00251             {
00252                 if(isdigit((int)(stoks[1][0])))
00253                 {
00254                     /* number of tgtnodes */
00255                     stickd.max_block_entries = atoi(stoks[1]);
00256                     i++;
00257                 }
00258                 else
00259                 {
00260                     FatalError("Bad Sticky-Drop Max Entries Arg",file_name,file_line);
00261                 }
00262     
00263             }
00264             else if(!strcasecmp(stoks[0], "log"))
00265             {
00266                 stickd.log = 1;
00267                 i++;
00268             } 
00269             else if(!strcasecmp(stoks[0], "log-file"))
00270             {
00271                 if(isascii((int)(stoks[1][0])))
00272                 {
00273                     if (stoks[1][0] == '/')
00274                         strlcpy (logpath, stoks[1], STD_BUF);
00275                     else
00276                     {
00277                         strlcpy(logpath, pv.log_dir, STD_BUF);
00278                         strlcat(logpath, "/", STD_BUF);
00279                         strlcat(logpath, stoks[1], STD_BUF);
00280                     }
00281                     i++;
00282                 }
00283                 else
00284                 {
00285                     FatalError(" %s(%d) => '%s' has invalid value '%s'. ",
00286                                 file_name, file_line,
00287                                stoks[0], stoks[1]);
00288                 }
00289             }
00290             else
00291             {
00292                 FatalError("%s(%d) => option '%s' is undefined. ",
00293                             file_name, file_line, stoks[0]);
00294             }
00295 
00296             mSplitFree(&stoks, s_toks);
00297         }
00298         mSplitFree(&toks, num_toks);
00299 
00300     }
00301     if(stickd.log)
00302     {
00303         stickd.logfile = fopen(logpath, "a+");
00304 
00305         if(stickd.logfile == NULL)
00306         {
00307             FatalError("Can't open logfile: %s", stickd.logpath);
00308         }
00309     }
00310 }
00311 
00312 
00313 static void sdInitTimeouts(u_char *targs)
00314 {
00315     DEBUG_WRAP(DebugMessage(DEBUG_PLUGIN,"Preprocessor: stickydrop-timeouts Initialized\n"););
00316 
00317     ParseSDTimeoutArgs(targs);
00318 }
00319 
00320 
00321 static void ParseSDTimeoutArgs(char *targs)
00322 {
00323     int num_toks, s_toks;
00324     char **toks = NULL;
00325     char **stoks;
00326     int i;
00327     char* index;
00328 
00329     sdt.sfportscan = 0;
00330     sdt.portscan2 = 0 ;
00331     sdt.clamav = 0;
00332 
00333     if (targs)
00334     {
00335 
00336         toks = mSplit(targs, ",", 4, &num_toks, 0);
00337 
00338         i=0;
00339 
00340         while (i < num_toks)
00341         {
00342             index = toks[i];
00343 
00344             while(isspace((int)*index)) index++;
00345 
00346             stoks = mSplit(index, " ", 1, &s_toks, 0);
00347             if(!strcasecmp(stoks[0], "sfportscan"))
00348             {
00349                 if(isdigit((int)(stoks[1][0])))
00350                 {
00351                     /* in the immortal words of socrates, "I drank what" */
00352                     sdt.sfportscan = atoi(stoks[1]);
00353                     i++;
00354                 }
00355                 else
00356                 {
00357                     FatalError("Bad Sticky-Drop sfportscan timeout entry",file_name,file_line);
00358                 }
00359 
00360             }
00361             else if(!strcasecmp(stoks[0], "portscan2"))  
00362             {
00363                 if(isdigit((int)(stoks[1][0])))            
00364                 {
00365                     /* in the immortal words of socrates, "I drank what" */
00366                     sdt.portscan2 = atoi(stoks[1]);  
00367                     i++;
00368                 }
00369                 else
00370                 {
00371                     FatalError("Bad Sticky-Drop portscan2 timeout entry",file_name,file_line);  
00372                 }
00373             }
00374             else if(!strcasecmp(stoks[0], "clamav"))
00375             {
00376                 if(isdigit((int)(stoks[1][0])))
00377                 {
00378                     /* in the immortal words of socrates, "I drank what" */
00379                     sdt.clamav = atoi(stoks[1]);
00380                     i++;
00381                 }
00382                 else
00383                 {
00384                     FatalError("Bad Sticky-Drop clamav timeout entry",file_name,file_line);
00385                 }
00386             }
00387             else
00388             {
00389                 FatalError("%s(%d) => option '%s' is undefined. ",
00390                             file_name, file_line, stoks[0]);
00391             }
00392 
00393             mSplitFree(&stoks, s_toks);
00394         }
00395         mSplitFree(&toks, num_toks);
00396 
00397     }
00398 }
00399 
00400 
00401 void sdInitIgnoreHosts(u_char *hosts)
00402 {
00403     char **toks;
00404     int num_toks;
00405     int num_hosts = 0;
00406     sdHostNode *sdcurrentHost;
00407     /*int i;*/
00408 
00409     sdcurrentHost = NULL;
00410     sdignoreList = NULL;
00411 
00412     if(hosts == NULL)
00413     {
00414         ErrorMessage(" ERROR: %s(%d)=> No arguments to "
00415                      "stickydrop-ignorehosts, ignoring.\n",
00416                      file_name, file_line);
00417         return;
00418     }
00419 
00420     toks = mSplit(hosts, " ", 127, &num_toks, '\\');
00421 
00422     for(num_hosts = 0; num_hosts < num_toks; num_hosts++)
00423     {
00424         if((sdcurrentHost = (sdHostNode *) calloc(1, sizeof(sdHostNode))) == NULL)
00425         {
00426             FatalError("[!] ERROR: Unable to allocate space for "
00427                        "sticky-drop IgnoreHost");
00428         }
00429         sdcurrentHost->address = NULL; /* be paranoid */
00430         sdcurrentHost->nextNode = sdignoreList;
00431         sdignoreList = sdcurrentHost;
00432 
00433 
00434         sdScanParseIp(toks[num_hosts], sdcurrentHost);
00435     }
00436 
00437     mSplitFree(&toks, num_toks);
00438 }
00439 
00440 
00441 IpAddrSet* sdIgnoreAllocAddrNode(sdHostNode *host)
00442 {
00443     IpAddrSet *idx;
00444 
00445     if((idx = (IpAddrSet *) calloc(1, sizeof(IpAddrSet))) == NULL)
00446       {
00447         FatalError("[!] ERROR: Unable to allocate space for "
00448                        "stickyd IP addr\n");
00449       }
00450 
00451     idx->next = host->address;
00452     host->address = idx;
00453 
00454     return idx;
00455 }
00456 
00457 
00458 void sdScanParseIp(char *addr, sdHostNode *host)
00459 {
00460     char **toks;
00461     int num_toks;
00462     int i, not_flag;
00463     IpAddrSet *tmp_addr;
00464     char *enbracket, *ports;
00465     char *tmp;
00466 
00467     if(addr == NULL)
00468     {
00469         ErrorMessage("ERROR %s(%d) => Undefine address in "
00470                      "stickydrop-ignorehosts directive, igoring.\n", file_name,
00471                      file_line);
00472 
00473         return;
00474     }
00475 
00476     if(*addr == '!')
00477     {
00478         host->flags |= EXCEPT_SRC_IP;
00479         addr++;
00480     }
00481 
00482     if(*addr == '$')
00483     {
00484         if((tmp = VarGet(addr + 1)) == NULL)
00485         {
00486             ErrorMessage("ERROR %s (%d) => Undefined variable \"%s\", "
00487                          "ignoring\n", file_name, file_line, addr);
00488 
00489             return;
00490         }
00491     }
00492     else
00493     {
00494         tmp = addr;
00495     }
00496 
00497     ports = strrchr(tmp, (int)'@');
00498 
00499     if (*tmp == '[')
00500     {
00501         enbracket = strrchr(tmp, (int)']');
00502         if (enbracket) *enbracket = '\x0'; /* null out the en-bracket */
00503 
00504         if (ports && enbracket && (ports < enbracket))
00505         {
00506           FatalError("[!] ERROR %s(%d) => syntax error in"
00507                      "stickydrop-ignorehosts \"%s\"\n",
00508                      file_name, file_line, tmp);
00509         }
00510         toks = mSplit(tmp+1, ",", 128, &num_toks, 0);
00511 
00512         for(i = 0; i < num_toks; i++)
00513         {
00514             tmp_addr = sdIgnoreAllocAddrNode(host);
00515 
00516             ParseIP(toks[i], tmp_addr);
00517         }
00518 
00519         mSplitFree(&toks, num_toks);
00520     }
00521     else
00522     {
00523         if (ports) *ports = '\x0'; /* null out the at */
00524 
00525         tmp_addr = sdIgnoreAllocAddrNode(host);
00526         ParseIP(tmp, tmp_addr);
00527     }
00528 
00529     if (ports)
00530     {
00531       ports++;
00532       if (ParsePort(ports, &(host->hsp), &(host->lsp), "ip", &not_flag))
00533         host->flags |= ANY_SRC_PORT;
00534       if (not_flag)
00535         host->flags |= EXCEPT_SRC_PORT;
00536     } else {
00537         host->flags |= ANY_SRC_PORT;
00538     }
00539 
00540 }
00541 
00542 
00543 void sdInitIgnoreFrom(u_char *args)
00544 {
00545   sdInitIgnorePorts(args, &sdignorePortFrom, &num_ports_from);
00546 }
00547 
00548 
00549 void sdInitIgnoreTo(u_char *args)
00550 {
00551   sdInitIgnorePorts(args, &sdignorePortTo, &num_ports_to);
00552 }
00553 
00554 
00555 void sdInitIgnorePorts(u_char *list, u_int32_t **ports, int *num)
00556 {
00557     int new_ports, max_ports;
00558     u_int32_t *pool;
00559     char **toks;
00560     int num_toks;
00561 
00562     *ports = NULL;
00563     *num = 0;
00564     max_ports = 0;
00565 
00566     if(list == NULL)
00567     {
00568         ErrorMessage(" ERROR: %s(%d)=> No arguments to "
00569                      "stickydrop-ignoreports, ignoring.\n",
00570                      file_name, file_line);
00571         return;
00572     }
00573 
00574     toks = mSplit(list, " ", MAX_PORTS, &num_toks, '\\');
00575 
00576     for(;*num < num_toks; (*num)++)
00577     {
00578       if(*num >= max_ports)
00579       {
00580         new_ports = max_ports + MEM_CHUNK;
00581         if((pool = (u_int32_t *) calloc(new_ports, sizeof(u_int32_t))) == NULL)
00582         {
00583           FatalError("[!] ERROR: Unable to allocate space for "
00584                      "stickydrop-ignoreports");
00585         }
00586         if (*ports != NULL)
00587         {
00588           memcpy(pool, *ports, max_ports * sizeof(u_int32_t));
00589           free(*ports);
00590         }
00591         max_ports = new_ports;
00592         *ports = pool;
00593       }
00594       (*ports)[*num] = sdScanParsePort(toks[*num]);
00595     }
00596 
00597     mSplitFree(&toks, num_toks);
00598 
00599 }
00600 
00601 
00602 u_int32_t sdScanParsePort(char *port)
00603 {
00604     char *tmp;
00605 
00606     if(port == NULL)
00607     {
00608       FatalError("ERROR %s(%d) => Undefined ports in "
00609                  "stickydrop-ignoreports directive\n",
00610                  file_name, file_line);
00611     }
00612 
00613     if(*port == '$')
00614     {
00615       if((tmp = VarGet(port + 1)) == NULL)
00616         {
00617           FatalError("ERROR %s (%d) => Undefined variable \"%s\"\n",
00618                      file_name, file_line, port);
00619 
00620         }
00621     }
00622     else
00623     {
00624         tmp = port;
00625     }
00626 
00627     if(!isdigit((int)tmp[0]))
00628     {
00629       FatalError("ERROR %s(%d) => Bad port list to "
00630                  "stickydrop-ignoreports\n", file_name, file_line);
00631     }
00632 
00633     return((u_int32_t)atol(tmp));
00634 }
00635 
00636 
00637 /*
00638     search the tree for the ipaddresses src or dst in direction 'direction'.
00639 
00640     Returns 1 of the ip is in our list, 0 otherwise.
00641 */
00642 int sdBlockTreeSearch(Packet *p, char direction)
00643 {
00644    Attacker tmp;
00645    Attacker *searchval;
00646    
00647    if(direction == DIRECTION_SOURCE) 
00648    { 
00649        tmp.ip = (u_int32_t)p->iph->ip_src.s_addr;
00650       
00651        DEBUG_WRAP(DebugMessage(DEBUG_STICKYDROP,
00652                   "Going to search for source ip of: of %s\n",inet_ntoa(p->iph->ip_src)););
00653    }
00654    else if(direction == DIRECTION_DST)
00655    {
00656        tmp.ip = (u_int32_t)p->iph->ip_dst.s_addr;
00657    
00658        DEBUG_WRAP(DebugMessage(DEBUG_STICKYDROP,
00659                   "Going to search for source ip of: of %s\n",inet_ntoa(p->iph->ip_dst)););
00660 
00661    }
00662 
00663    searchval = (Attacker *) ubi_sptFind(stickd.attackerRootPtr, (ubi_btItemPtr)&tmp);
00664  
00665    if (searchval != NULL)
00666    {
00667        /* found, lets inspect the attacker */
00668         
00669        /* check the timeout */
00670        if(p->pkth->ts.tv_sec >= (searchval->unblocktime.tv_sec))
00671        {
00672            DEBUG_WRAP(DebugMessage(DEBUG_STICKYDROP,
00673                                    "Pruning out Attacker due to timeout\n"););
00674 
00675            PruneAttackers(p->pkth->ts.tv_sec, 1, NULL);
00676            
00677            return(0);
00678        }
00679        else if(direction == DIRECTION_SOURCE)
00680        {
00681            DEBUG_WRAP(DebugMessage(DEBUG_STICKYDROP,
00682                                    "Attacker %s was found in tree and we haven't past our unblock mark\n",inet_ntoa(p->iph->ip_src)););
00683 
00684            return(1);
00685        }
00686        else if(direction == DIRECTION_DST)
00687        { 
00688            DEBUG_WRAP(DebugMessage(DEBUG_STICKYDROP,
00689                                    "Attacker %s was found in tree and we haven't past our unblock mark\n",inet_ntoa(p->iph->ip_dst)););
00690 
00691            return(1);
00692        }          
00693    }
00694    else if(direction == DIRECTION_SOURCE) 
00695    { 
00696         DEBUG_WRAP(DebugMessage(DEBUG_STICKYDROP,
00697                                 "ip address %s not found in block tree\n",inet_ntoa(p->iph->ip_src)););
00698         
00699         return(0);
00700    }
00701    else if(direction == DIRECTION_DST)
00702    {
00703         DEBUG_WRAP(DebugMessage(DEBUG_STICKYDROP,  
00704                                 "ip address %s not found in block tree passing\n",inet_ntoa(p->iph->ip_dst)););
00705 
00706         return(0); 
00707    }                
00708 
00709     /* default case: not found */
00710     return(0);
00711 }
00712 
00713 
00714 int sdIsIgnored(Packet *p, char dir)
00715 {                 
00716     sdHostNode *sdcurrentHost = sdignoreList;
00717     int i;                
00718 
00719     for(i = 0; i < num_ports_from; i++)
00720     {
00721       if (p->sp == sdignorePortFrom[i])   
00722       {
00723         return(1);               
00724       }      
00725     }
00726 
00727     for(i = 0; i < num_ports_to; i++)
00728     {            
00729       if (p->dp == sdignorePortTo[i])
00730       {
00731         return(1);
00732       }
00733     }
00734 
00735     while(sdcurrentHost)
00736     {
00737         /*
00738          * Return 1 if the source addr is in the serverlist, 0 if nothing is
00739          * found.
00740          */
00741         if(dir == DIRECTION_SOURCE)
00742         {
00743             if(CheckAddrPort(sdcurrentHost->address, sdcurrentHost->hsp,
00744                              sdcurrentHost->lsp, p, sdcurrentHost->flags, CHECK_SRC))
00745             {
00746                 return(1);
00747             }
00748         }
00749         else if(dir == DIRECTION_DST)
00750         {
00751             if(CheckAddrPort(sdcurrentHost->address, sdcurrentHost->hsp,
00752                              sdcurrentHost->lsp, p, sdcurrentHost->flags, INVERSE))
00753             {
00754                 return(1);
00755             }
00756         }
00757         sdcurrentHost = sdcurrentHost->nextNode;
00758     }
00759     return(0);
00760 }
00761 
00762 
00763 /*
00764  * Function: AddIpToBlockTree(Packet *p, char bdirection, u_int32_timeout) 
00765  *
00766  * Purpose: Add source ip addy's into the splay tree 
00767  *         
00768  * Returns: void function
00769  *
00770  */
00771 void AddIpToBlockTree(Packet *p, char bdirection, u_int32_t timeout)
00772 {
00773     if((bdirection == DIRECTION_SOURCE) && (sdIsIgnored(p, DIRECTION_SOURCE)))
00774     {
00775         DEBUG_WRAP(DebugMessage(DEBUG_STICKYDROP,"Host %s  matched ignore list, not adding to block tree.\n",inet_ntoa(p->iph->ip_src)););
00776         return;
00777     }
00778     else if((bdirection == DIRECTION_DST) && (sdIsIgnored(p, DIRECTION_DST)))
00779     {
00780         DEBUG_WRAP(DebugMessage(DEBUG_STICKYDROP,"Host %s  matched ignore list, not adding to block tree.\n",inet_ntoa(p->iph->ip_dst)););
00781         return;
00782     }
00783     else if((bdirection == DIRECTION_SOURCE) && (sdBlockTreeSearch(p, DIRECTION_SOURCE)))
00784     {
00785             DEBUG_WRAP(DebugMessage(DEBUG_STICKYDROP,"Host %s already has an entry in block tree, why in the hell is this true we set p->preprocessors and do_detect to 0.\n",inet_ntoa(p->iph->ip_src)););
00786             return;
00787     }
00788     else if((bdirection == DIRECTION_DST) && (sdBlockTreeSearch(p, DIRECTION_DST)))
00789     {
00790             DEBUG_WRAP(DebugMessage(DEBUG_STICKYDROP,"Host %s already has an entry in block tree, why in the hell is this true we set p->preprocessors and do_detect to 0.\n",inet_ntoa(p->iph->ip_dst)););
00791             return;
00792     }
00793 
00794     else
00795     {
00796         Attacker *a = NULL;
00797         MemBucket *mb = NULL;
00798    
00799         /* borrow a attacker node from the attacker node pool */
00800         mb = mempool_alloc(&stickd.AttackerPool);
00801 
00802         if(mb == NULL)
00803         {
00804             /* Nuke 5 nodes we are out of memory */
00805             PruneAttackers(p->pkth->ts.tv_sec, 5, NULL);    
00806         }
00807 
00808         a = (Attacker *) mb->data;
00809         a->bucket = mb;
00810 
00811         /* fill in the attacker struct */
00812         if(bdirection == DIRECTION_SOURCE)
00813         {
00814             a->ip = (u_int32_t)p->iph->ip_src.s_addr;
00815             DEBUG_WRAP(DebugMessage(DEBUG_STICKYDROP,"AddIpToBlockTree called going to add ip address %s to block tree\n",inet_ntoa(p->iph->ip_src)););
00816         }
00817         else if(bdirection == DIRECTION_DST)
00818         {
00819             a->ip = (u_int32_t)p->iph->ip_dst.s_addr;
00820             DEBUG_WRAP(DebugMessage(DEBUG_STICKYDROP,"AddIpToBlockTree called going to add ip address %s to block tree\n",inet_ntoa(p->iph->ip_dst));); 
00821         }
00822         else
00823         {
00824             DEBUG_WRAP(DebugMessage(DEBUG_STICKYDROP,
00825                        "not inserting into tree we need src or dst\n"););
00826         
00827         }
00828         
00829         a->blocktime.tv_sec = p->pkth->ts.tv_sec;
00830         a->unblocktime.tv_sec = a->blocktime.tv_sec + timeout;
00831         if(ubi_sptInsert(stickd.attackerRootPtr,
00832                          (ubi_btNodePtr)a,
00833                          (ubi_btNodePtr)a, NULL) == ubi_trFALSE)
00834         {
00835             DEBUG_WRAP(DebugMessage(DEBUG_STICKYDROP,
00836                        "Entry already exists, or something has gone terribly wrong\n"););
00837             /* We allocated memory let's clean it up */
00838              mempool_free(&stickd.AttackerPool,a->bucket);
00839         }
00840         else
00841         {
00842             DEBUG_WRAP(DebugMessage(DEBUG_STICKYDROP,
00843                        "Insert into block tree was successful\n"););
00844             do_detect = 0;
00845             p->preprocessors = 0;
00846             InlineDrop();
00847         }
00848     }
00849 }
00850 
00851 
00852 void SDLog(Packet *p)
00853 {
00854     char src[STD_BUF];
00855     char dst[STD_BUF];
00856     char timestamp[TIMEBUF_SIZE];
00857     char flagString[9]; 
00858    
00859     strlcpy(src, (char *)inet_ntoa(p->iph->ip_src), sizeof(src));
00860     strlcpy(dst, (char *)inet_ntoa(p->iph->ip_dst), sizeof(dst));
00861     ts_print((struct timeval *) &p->pkth->ts, timestamp);         
00862 
00863     if(p->tcph)
00864     {
00865         CreateTCPFlagString(p, flagString);
00866         fprintf(stickd.logfile,"Dropped %s TCP %s:%u->%s:%u %s\n", timestamp, src, p->sp, dst, p->dp, flagString);
00867                 
00868     }
00869     else if(p->udph)
00870     {
00871         fprintf(stickd.logfile,"Dropped %s UDP %s:%u->%s:%u\n", timestamp, src, p->sp, dst, p->dp); 
00872 
00873     }
00874     else if(p->icmph)      
00875     {
00876         fprintf(stickd.logfile, "Dropped %s ICMP %s->%s type: %u code: %u \n", timestamp, src, dst, p->icmph->type, p->icmph->code);
00877 
00878     }             
00879 
00880     fflush(stickd.logfile);
00881 }
00882 
00883 
00884 /*
00885  * Function: PreprocFunction(Packet *)
00886  *
00887  * Purpose: Perform the preprocessor's intended function.  This can be
00888  *          simple (statistics collection) or complex (IP defragmentation)
00889  *          as you like.  Try not to destroy the performance of the whole
00890  *          system by trying to do too much....
00891  *
00892  * Arguments: p => pointer to the current packet data struct 
00893  *
00894  * Returns: void function
00895  *
00896  */
00897 void StickyDrop(Packet *p, void *context)
00898 {
00899     if(sdBlockTreeSearch(p, DIRECTION_SOURCE))
00900     {
00901        DEBUG_WRAP(DebugMessage(DEBUG_STICKYDROP,
00902                                "Attacker was found, lets log if specified and drop the packet\n"););
00903        if(stickd.log)
00904        {
00905            /* Log the packet */
00906            SDLog(p);
00907        }
00908            
00909        /* Disable Detection to save resources and Drop The Packet */
00910 
00911        do_detect = 0;
00912        p->preprocessors = 0; 
00913        InlineDrop();
00914            
00915     }
00916     if(sdBlockTreeSearch(p, DIRECTION_DST))
00917     {
00918        DEBUG_WRAP(DebugMessage(DEBUG_STICKYDROP,
00919                                "Attacker was found, lets log if specified and drop the packet\n"););
00920        if(stickd.log)
00921        {
00922            /* Log the packet */
00923            SDLog(p);
00924        }
00925 
00926        /* Disable Detection to save resources and Drop The Packet */
00927 
00928        do_detect = 0;
00929        p->preprocessors = 0;
00930        InlineDrop();
00931 
00932     }
00933     else
00934     {
00935          DEBUG_WRAP(DebugMessage(DEBUG_STICKYDROP,
00936                                  "ip address not found in drop list passing\n"););
00937     }
00938     DEBUG_WRAP(DebugMessage(DEBUG_STICKYDROP,   
00939                             "Calling Global Prune Check \n"););                         
00940 
00941     PruneAttackers(p->pkth->ts.tv_sec,0,NULL);
00942 }
00943 
00944 
00945 static int IpAddressCompareFunction(ubi_trItemPtr ItemPtr, ubi_trNodePtr NodePtr)
00946 {            
00947     Attacker *A = (Attacker *) NodePtr;     
00948     Attacker *B = (Attacker *) ItemPtr;
00949 
00950     if(A->ip < B->ip)
00951     {               
00952         return 1;   
00953     }         
00954     else if(A->ip > B->ip)
00955     {
00956         return -1;
00957     }         
00958 
00959     return 0;
00960 }
00961 
00962 
00963 static void DeleteAttacker(Attacker *a)
00964 {               
00965     Attacker *olda;
00966 
00967     DEBUG_WRAP(DebugMessage(DEBUG_STICKYDROP, "Deleteing Attacker %p\n", a);
00968                DebugMessage(DEBUG_STICKYDROP,
00969                             "a->ip: %X\n", a->ip);
00970                DebugMessage(DEBUG_STICKYDROP,
00971                             "a->blocktime: %u\n", a->blocktime.tv_sec);
00972                DebugMessage(DEBUG_STICKYDROP,
00973                             "a->unblocktime: %u\n", a->unblocktime.tv_sec);
00974 
00975                );
00976 
00977 
00978     olda = (Attacker *) ubi_sptRemove(stickd.attackerRootPtr,
00979                                           (ubi_btNodePtr) a);
00980 
00981     mempool_free(&stickd.AttackerPool,a->bucket);
00982 }    
00983 
00984 
00985 static int PruneAttackers(u_int32_t now, int tokill, Attacker *saveme)
00986 {
00987     Attacker *idx;
00988     u_int32_t pruned = 0;
00989 
00990     DEBUG_WRAP(DebugMessage(DEBUG_STICKYDROP,
00991                             "PruneAttackers called now: "
00992                             " %u tokill: %d: saveme: %p, count: %u\n",
00993                             now, tokill, saveme,
00994                             ubi_trCount(stickd.attackerRootPtr)););
00995 
00996     if(ubi_trCount(stickd.attackerRootPtr) == 0)
00997     {
00998         return 0;
00999     }
01000 
01001     if(tokill == 0)
01002     {
01003         DEBUG_WRAP(DebugMessage(DEBUG_STICKYDROP,  
01004                                 "Running Through Global Prune Check Loop\n"););
01005 
01006         idx = (Attacker *) ubi_btFirst((ubi_btNodePtr)stickd.attackerRootPtr->root);
01007 
01008         if(idx == NULL)
01009         {
01010             return 0;
01011         }
01012 
01013         do
01014         {
01015             if(idx == saveme)
01016             {
01017                 idx = (Attacker *) ubi_btNext((ubi_btNodePtr)idx);
01018                 continue;
01019             }
01020 
01021             if((idx->unblocktime.tv_sec) <  now)
01022             {
01023                 Attacker *savidx = idx;
01024 
01025                 if(ubi_trCount(stickd.attackerRootPtr) > 1)
01026                 {
01027                     idx = (Attacker *) ubi_btNext((ubi_btNodePtr)idx);
01028                     DEBUG_WRAP(DebugMessage(DEBUG_STICKYDROP,
01029                                             "pruning stale sticky-drop entry\n"););
01030                     DeleteAttacker(savidx);
01031                     pruned++;
01032                 }
01033                 else
01034                 {
01035                     DeleteAttacker(savidx); 
01036                     pruned++;
01037                     return pruned;
01038                 }
01039             }
01040             else
01041             {
01042                 if(idx != NULL && ubi_trCount(stickd.attackerRootPtr) > 1)
01043                 {
01044                     idx = (Attacker *) ubi_btNext((ubi_btNodePtr)idx);
01045                 }
01046                 else
01047                 {
01048                     return pruned;
01049                 }
01050             }
01051         } while(idx != NULL);
01052 
01053         return pruned;
01054     }
01055     else
01056     {
01057         while(tokill-- &&  ubi_trCount(stickd.attackerRootPtr) > 0) 
01058         {
01059             idx = (Attacker *) ubi_btLeafNode((ubi_btNodePtr)stickd.attackerRootPtr);
01060             DeleteAttacker(idx);
01061             return 0;
01062         }
01063     }
01064        return 0;
01065 }
01066 
01067 
01068 int SppStickydIsRunning(void)
01069 {                
01070     return s_stickyd_running;
01071 }     
01072 
01073 
01074 /* 
01075  * Function: PreprocCleanExitFunction(int, void *)
01076  *
01077  * Purpose: This function gets called when Snort is exiting, if there's
01078  *          any cleanup that needs to be performed (e.g. closing files)
01079  *          it should be done here.
01080  *
01081  * Arguments: signal => the code of the signal that was issued to Snort
01082  *            data => any arguments or data structs linked to this 
01083  *                    functioin when it was registered, may be
01084  *                    needed to properly exit
01085  *       
01086  * Returns: void function
01087  */                   
01088 static void PreprocCleanExitFunction(int signal, void *data)
01089 {
01090 }
01091 
01092 
01093 /* 
01094  * Function: PreprocRestartFunction(int, void *)
01095  *
01096  * Purpose: This function gets called when Snort is restarting on a SIGHUP,
01097  *          if there's any initialization or cleanup that needs to happen
01098  *          it should be done here.
01099  *
01100  * Arguments: signal => the code of the signal that was issued to Snort
01101  *            data => any arguments or data structs linked to this 
01102  *                    functioin when it was registered, may be
01103  *                    needed to properly exit
01104  *       
01105  * Returns: void function
01106  */                   
01107 static void PreprocRestartFunction(int signal, void *foo)
01108 {
01109 }
01110 
01111 
01112 #endif /* GIDS */

Generated on Sun May 14 14:51:17 2006 by  doxygen 1.4.2