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

detect.c

Go to the documentation of this file.
00001 /* $Id$ */
00002 /*
00003 ** Copyright (C) 1998-2002 Martin Roesch <roesch@sourcefire.com>
00004 ** Copyright (C) 2002, Sourcefire, Inc.
00005 **    Dan Roelker <droelker@sourcefire.com>
00006 **    Marc Norton <mnorton@sourcefire.com>
00007 **
00008 ** This program is free software; you can redistribute it and/or modify
00009 ** it under the terms of the GNU General Public License as published by
00010 ** the Free Software Foundation; either version 2 of the License, or
00011 ** (at your option) any later version.
00012 **
00013 ** This program is distributed in the hope that it will be useful,
00014 ** but WITHOUT ANY WARRANTY; without even the implied warranty of
00015 ** MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
00016 ** GNU General Public License for more details.
00017 **
00018 ** You should have received a copy of the GNU General Public License
00019 ** along with this program; if not, write to the Free Software
00020 ** Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
00021 **
00022 ** NOTES
00023 **   5.7.02: Added interface for new detection engine. (Norton/Roelker)
00024 **
00025 */
00026 
00027 #define FASTPKT
00028 
00029 /*  I N C L U D E S  **********************************************/
00030 #ifdef HAVE_CONFIG_H
00031 #include "config.h"
00032 #endif
00033 
00034 #include <string.h>
00035 #include <stdlib.h>
00036 #include <assert.h>
00037 
00038 #include "snort.h"
00039 #include "detect.h"
00040 #include "plugbase.h"
00041 #include "debug.h"
00042 #include "util.h"
00043 #include "mstring.h"
00044 #include "tag.h"
00045 #include "pcrm.h"
00046 #include "fpcreate.h"
00047 #include "fpdetect.h"
00048 #include "sfthreshold.h"
00049 #include "event_wrapper.h"
00050 #include "event_queue.h"
00051 #include "stream.h"
00052 #include "inline.h"
00053 
00054 /* XXX modularization violation */
00055 #include "preprocessors/spp_stream4.h"
00056 #include "preprocessors/spp_flow.h"
00057 
00058 
00059 /* #define ITERATIVE_ENGINE */
00060 
00061 extern ListHead Alert;         /* Alert Block Header */
00062 extern ListHead Log;           /* Log Block Header */
00063 extern ListHead Pass;          /* Pass Block Header */
00064 extern ListHead Activation;    /* Activation Block Header */
00065 extern ListHead Dynamic;       /* Dynamic Block Header */
00066 extern ListHead Drop;
00067 #ifdef GIDS
00068 extern ListHead SDrop;
00069 extern ListHead Reject;
00070 extern ListHead RejectBoth;
00071 extern ListHead RejectSrc;
00072 extern ListHead RejectDst;
00073 #ifdef IPFW
00074 extern ListHead Reinject;
00075 #endif /* IPFW */
00076 #endif /* GIDS */
00077 
00078 extern RuleTreeNode *rtn_tmp;      /* temp data holder */
00079 extern OptTreeNode *otn_tmp;       /* OptTreeNode temp ptr */
00080 extern ListHead *head_tmp;         /* ListHead temp ptr */
00081 
00082 extern RuleListNode *RuleLists;
00083 
00084 extern int dynamic_rules_present;
00085 extern int active_dynamic_nodes;
00086 
00087 extern PreprocessFuncNode *PreprocessList;  /* Preprocessor function list */
00088 extern OutputFuncNode *AlertList;   /* Alert function list */
00089 extern OutputFuncNode *LogList; /* log function list */
00090 
00091 /*
00092 **  The HTTP decode structre
00093 */
00094 extern HttpUri UriBufs[URI_COUNT];
00095 
00096 extern Stream4Data s4data;
00097 
00098 int do_detect;
00099 u_int16_t event_id;
00100 char check_tags_flag;
00101 
00102 void printRuleListOrder(RuleListNode * node);
00103 static int CheckTagging(Packet *p);
00104 static RuleListNode *addNodeToOrderedList(RuleListNode *ordered_list, 
00105         RuleListNode *node, int evalIndex);
00106 
00107 int Preprocess(Packet * p)
00108 {
00109     PreprocessFuncNode *idx;
00110     int retval = 0;
00111 
00112     /*
00113      *  If the packet has an invalid checksum marked, throw that
00114      *  traffic away as no end host should accept it.
00115      *
00116      *  This can be disabled by config checksum_mode: none
00117      */
00118     if(p->csum_flags)
00119     {
00120         return 0;
00121     }
00122     
00123     do_detect = 1;
00124     idx = PreprocessList;
00125 
00126     /*
00127     **  Reset the appropriate application-layer protocol fields
00128     */
00129     p->uri_count = 0;
00130     UriBufs[0].decode_flags = 0;
00131 
00132     /*
00133     **  Turn on all preprocessors
00134     */
00135     p->preprocessors = PP_ALL;
00136 
00137     while(idx != NULL)
00138     {
00139         assert(idx->func != NULL);
00140         idx->func(p, idx->context);
00141         idx = idx->next;
00142     }
00143 
00144     check_tags_flag = 1;
00145     
00146     if ((do_detect) && (p->bytes_to_inspect != -1))
00147     {
00148         /* Check if we are only inspecting a portion of this packet... */
00149         if (p->bytes_to_inspect > 0)
00150         {
00151             DEBUG_WRAP(DebugMessage(DEBUG_DETECT, "Ignoring part of server "
00152             "traffic -- only looking at %d of %d bytes!!!\n",
00153             p->bytes_to_inspect, p->dsize););
00154             p->dsize = (u_int16_t)p->bytes_to_inspect;
00155         }
00156         Detect(p);
00157     }
00158     else if (p->bytes_to_inspect == -1)
00159     {
00160         DEBUG_WRAP(DebugMessage(DEBUG_DETECT, "Ignoring server traffic!!!\n"););
00161     }
00162 
00163     /*
00164     ** By checking tagging here, we make sure that we log the
00165     ** tagged packet whether it generates an alert or not.
00166     */
00167     CheckTagging(p);
00168 
00169     retval = SnortEventqLog(p);
00170     SnortEventqReset();
00171 
00172     otn_tmp = NULL;
00173 
00174     /*
00175     **  If we found events in this packet, let's flush
00176     **  the stream to make sure that we didn't miss any
00177     **  attacks before this packet.
00178     */
00179     if(retval && p->ssnptr)
00180         AlertFlushStream(p);
00181 
00182     /**
00183      * See if we should go ahead and remove this flow from the
00184      * flow_preprocessor -- cmg
00185      */
00186     CheckFlowShutdown(p);
00187     
00188     return retval;
00189 }
00190 
00191 /*
00192 **  NAME
00193 **    CheckTagging::
00194 */
00195 /**
00196 **  This is where we check to see if we tag the packet.  We only do
00197 **  this if we've alerted on a non-pass rule and the packet is not
00198 **  rebuilt.
00199 **
00200 **  We don't log rebuilt packets because the output plugins log the
00201 **  individual packets of a rebuilt stream, so we don't want to dup
00202 **  tagged packets for rebuilt streams.
00203 **
00204 **  @return integer
00205 */
00206 static int CheckTagging(Packet *p)
00207 {
00208     Event event;
00209 
00210     if(check_tags_flag == 1 && !(p->packet_flags & PKT_REBUILT_STREAM)) 
00211     {
00212         DEBUG_WRAP(DebugMessage(DEBUG_FLOW, "calling CheckTagList\n"););
00213 
00214         if(CheckTagList(p, &event))
00215         {
00216             DEBUG_WRAP(DebugMessage(DEBUG_FLOW, "Matching tag node found, "
00217                         "calling log functions\n"););
00218 
00219             /* if we find a match, we want to send the packet to the
00220              * logging mechanism
00221              */
00222             CallLogFuncs(p, "Tagged Packet", NULL, &event);
00223         } 
00224     }
00225 
00226     return 0;
00227 }
00228 
00229 void CallLogFuncs(Packet *p, char *message, ListHead *head, Event *event)
00230 {
00231     OutputFuncNode *idx = NULL;
00232 
00233     /*
00234     **  Don't do thresholding on tagged packets.  The tv_sec check
00235     **  makes sure that we don't.
00236     */
00237     if(p && event->ref_time.tv_sec == 0)
00238     {
00239         /*
00240          *  Perform Thresholding Tests 
00241          */
00242         if(p->iph)
00243         {
00244             if( !sfthreshold_test( event->sig_generator,
00245                                    event->sig_id,
00246                                    p->iph->ip_src.s_addr,
00247                                    p->iph->ip_dst.s_addr,
00248                                    p->pkth->ts.tv_sec ) )
00249             {
00250                 return; /* Don't log it ! */
00251             }
00252         }
00253         else
00254         {
00255             if( !sfthreshold_test( event->sig_generator,
00256                                    event->sig_id,
00257                                    0,
00258                                    0,
00259                                    p->pkth->ts.tv_sec ) )
00260             {
00261                 return; /* Don't log it ! */
00262             }
00263         }
00264 
00265         /*
00266         **  Set the ref time after we check thresholding.
00267         */
00268         event->ref_time.tv_sec = p->pkth->ts.tv_sec;
00269         event->ref_time.tv_usec = p->pkth->ts.tv_usec;
00270     }
00271 
00272     /* set the event number */
00273     event->event_id = event_id | pv.event_log_id;
00274 
00275     if(head == NULL)
00276     {
00277         CallLogPlugins(p, message, NULL, event);
00278         return;
00279     }
00280 
00281     if(p != NULL)
00282     {
00283         if(pv.obfuscation_flag)
00284             ObfuscatePacket(p);
00285     }
00286 
00287     pc.log_pkts++;
00288      
00289     idx = head->LogList;
00290     if(idx == NULL)
00291         idx = LogList;
00292 
00293     while(idx != NULL)
00294     {
00295         idx->func(p, message, idx->arg, event);
00296         idx = idx->next;
00297     }
00298 
00299     return;
00300 }
00301 
00302 void CallLogPlugins(Packet * p, char *message, void *args, Event *event)
00303 {
00304     OutputFuncNode *idx;
00305 
00306     idx = LogList;
00307 
00308     if(p != NULL)
00309     {
00310         if(pv.obfuscation_flag)
00311             ObfuscatePacket(p);
00312     }
00313 
00314     pc.log_pkts++;
00315 
00316     while(idx != NULL)
00317     {
00318         idx->func(p, message, idx->arg, event);
00319         idx = idx->next;
00320     }
00321 
00322     return;
00323 }
00324 
00325 /* Call the output functions that are directly attached to the signature */
00326 void CallSigOutputFuncs(Packet *p, OptTreeNode *otn, Event *event)
00327 {
00328     OutputFuncNode *idx = NULL;
00329 
00330     idx = otn->outputFuncs;
00331 
00332     if(p && pv.obfuscation_flag)
00333         ObfuscatePacket(p);
00334 
00335     while(idx)
00336     {
00337         idx->func(p, otn->sigInfo.message, idx->arg, event);
00338         idx = idx->next;
00339     }
00340 }
00341 
00342 
00343 void CallAlertFuncs(Packet * p, char *message, ListHead * head, Event *event)
00344 {
00345     OutputFuncNode *idx = NULL;
00346 
00347     /*
00348     **  Don't do thresholding on tagged packets.  The tv_sec check
00349     **  makes sure that we don't.
00350     */
00351     if(p && event->ref_time.tv_sec == 0)
00352     {
00353         /*
00354          *  Perform Thresholding Tests 
00355          */
00356         if(p->iph)
00357         {
00358             if( !sfthreshold_test( event->sig_generator,
00359                                    event->sig_id,
00360                                    p->iph->ip_src.s_addr,
00361                                    p->iph->ip_dst.s_addr,
00362                                    p->pkth->ts.tv_sec ) )
00363             {
00364                 return; /* Don't log it ! */
00365             }
00366         }
00367         else
00368         {
00369             if( !sfthreshold_test( event->sig_generator,
00370                                    event->sig_id,
00371                                    0,
00372                                    0,
00373                                    p->pkth->ts.tv_sec ) )
00374             {
00375                 return; /* Don't log it ! */
00376             }
00377         }
00378 
00379         /*
00380         **  Set the ref time after we check thresholding.
00381         */
00382         event->ref_time.tv_sec = p->pkth->ts.tv_sec;
00383         event->ref_time.tv_usec = p->pkth->ts.tv_usec;
00384     }
00385 
00386     /* set the event number */
00387     event->event_id = event_id | pv.event_log_id;
00388     /* set the event reference info */
00389     event->event_reference = event->event_id;
00390 
00391     if(head == NULL)
00392     {
00393         CallAlertPlugins(p, message, NULL, event);
00394         return;
00395     }
00396 
00397     if(p && pv.obfuscation_flag)
00398         ObfuscatePacket(p);
00399 
00400 
00401     pc.alert_pkts++;
00402     idx = head->AlertList;
00403     if(idx == NULL)
00404         idx = AlertList;
00405 
00406     while(idx != NULL)
00407     {
00408         idx->func(p, message, idx->arg, event);
00409         idx = idx->next;
00410     }
00411 
00412     return;
00413 }
00414 
00415 
00416 void CallAlertPlugins(Packet * p, char *message, void *args, Event *event)
00417 {
00418     OutputFuncNode *idx;
00419 
00420     DEBUG_WRAP(DebugMessage(DEBUG_DETECT, "Call Alert Plugins\n"););
00421     idx = AlertList;
00422 
00423     if(p && pv.obfuscation_flag)
00424         ObfuscatePacket(p);
00425 
00426     pc.alert_pkts++;
00427     while(idx != NULL)
00428     {
00429         idx->func(p, message, idx->arg, event);
00430         idx = idx->next;
00431     }
00432 
00433     return;
00434 }
00435 
00436 
00437 
00438 /****************************************************************************
00439  *
00440  * Function: Detect(Packet *)
00441  *
00442  * Purpose: Apply the rules lists to the current packet
00443  *
00444  * Arguments: p => ptr to the decoded packet struct
00445  *
00446  * Returns: 1 == detection event
00447  *          0 == no detection
00448  *
00449  ***************************************************************************/
00450 int Detect(Packet * p)
00451 {
00452     int detected = 0;
00453 
00454     RuleListNode *rule;
00455 
00456     rule = RuleLists;
00457 
00458     if(p && p->iph == NULL)
00459         return 0;
00460 
00461     /*
00462     **  This is where we short circuit so 
00463     **  that we can do IP checks.
00464     */
00465     detected = fpEvalPacket(p);
00466 
00467     return detected;
00468 }
00469 
00470 void TriggerResponses(Packet * p, OptTreeNode * otn)
00471 {
00472 
00473     RspFpList *idx;
00474 
00475     idx = otn->rsp_func;
00476 
00477     DEBUG_WRAP(DebugMessage(DEBUG_DETECT,"Triggering responses %p\n", idx););
00478 
00479     while(idx != NULL)
00480     {
00481         idx->ResponseFunc(p, idx);
00482         idx = idx->next;
00483     }
00484 
00485 }
00486 
00487 int CheckAddrPort(IpAddrSet *rule_addr, u_int16_t hi_port, u_int16_t lo_port, 
00488         Packet *p, u_int32_t flags, int mode)
00489 {
00490     u_long pkt_addr;         /* packet IP address */
00491     u_short pkt_port;        /* packet port */
00492     int global_except_addr_flag = 0; /* global exception flag is set */
00493     int any_port_flag = 0;           /* any port flag set */
00494     int except_addr_flag = 0;        /* any addr flag set */
00495     int except_port_flag = 0;        /* port exception flag set */
00496     int ip_match = 0;                /* flag to indicate addr match made */
00497     IpAddrSet *idx;  /* ip addr struct indexer */
00498 
00499     DEBUG_WRAP(DebugMessage(DEBUG_DETECT, "CheckAddrPort: "););
00500     /* set up the packet particulars */
00501     if(mode & CHECK_SRC)
00502     {
00503         pkt_addr = p->iph->ip_src.s_addr;
00504         pkt_port = p->sp;
00505 
00506         DEBUG_WRAP(DebugMessage(DEBUG_DETECT,"SRC "););
00507 
00508         if(mode & INVERSE)
00509         {
00510             global_except_addr_flag = flags & EXCEPT_DST_IP;
00511             any_port_flag = flags & ANY_DST_PORT;
00512             except_port_flag = flags & EXCEPT_DST_PORT;
00513         }
00514         else
00515         {
00516             global_except_addr_flag = flags & EXCEPT_SRC_IP;
00517             any_port_flag = flags & ANY_SRC_PORT;
00518             except_port_flag = flags & EXCEPT_SRC_PORT;
00519         }
00520     }
00521     else
00522     {
00523         pkt_addr = p->iph->ip_dst.s_addr;
00524         pkt_port = p->dp;
00525 
00526         DEBUG_WRAP(DebugMessage(DEBUG_DETECT, "DST "););
00527 
00528         if(mode & INVERSE)
00529         {
00530             global_except_addr_flag = flags & EXCEPT_SRC_IP;
00531             any_port_flag = flags & ANY_SRC_PORT;
00532             except_port_flag = flags & EXCEPT_SRC_PORT;
00533         }
00534         else
00535         {
00536             global_except_addr_flag = flags & EXCEPT_DST_IP;
00537             any_port_flag = flags & ANY_DST_PORT;
00538             except_port_flag = flags & EXCEPT_DST_PORT;
00539         }
00540     }
00541 
00542     DEBUG_WRAP(DebugMessage(DEBUG_DETECT, "addr %lx, port %d ", pkt_addr, 
00543                 pkt_port););
00544 
00545     idx = rule_addr;
00546     if(!(global_except_addr_flag)) /*modeled after Check{Src,Dst}IP function*/
00547     {
00548         while(idx != NULL)
00549         {
00550             except_addr_flag = idx->addr_flags & EXCEPT_IP;
00551 
00552             /* test the rule address vs. the packet address */
00553             if(!((idx->ip_addr==(pkt_addr & idx->netmask)) ^ except_addr_flag))
00554             {
00555                 idx = idx->next;
00556             }
00557             else
00558             {
00559                 ip_match = 1;
00560                 goto bail;
00561             }
00562         }
00563     }
00564     else
00565     {
00566         DEBUG_WRAP(DebugMessage(DEBUG_DETECT, ", global exception flag set"););
00567         /* global exception flag is up, we can't match on *any* 
00568          * of the source addresses 
00569          */
00570         while(idx != NULL)
00571         {
00572             except_addr_flag = idx->addr_flags & EXCEPT_IP;
00573 
00574             /* test the rule address vs. the packet address */
00575             if(((idx->ip_addr == (pkt_addr & idx->netmask)) ^ 
00576                         except_addr_flag))
00577             {
00578                 DEBUG_WRAP(DebugMessage(DEBUG_DETECT, 
00579                             ", address matched, packet rejected\n"));
00580 
00581                 /* got address match on globally negated rule, fail */
00582                 return 0;
00583             }
00584             idx = idx->next;
00585         }
00586         ip_match = 1;
00587     }
00588 
00589     bail:
00590     if(!ip_match)
00591     {
00592         DEBUG_WRAP(DebugMessage(DEBUG_DETECT, ", no address match,  "
00593                     "packet rejected\n"););
00594         return 0;
00595     }
00596 
00597     DEBUG_WRAP(DebugMessage(DEBUG_DETECT, ", addresses accepted"););
00598     
00599     /* if the any port flag is up, we're all done (success) */
00600     if(any_port_flag)
00601     {
00602         DEBUG_WRAP(DebugMessage(DEBUG_DETECT, ", any port match, "
00603                     "packet accepted\n"););
00604         return 1;
00605     }
00606 
00607     /* check the packet port against the rule port */
00608     if((pkt_port > hi_port) || (pkt_port < lo_port))
00609     {
00610         /* if the exception flag isn't up, fail */
00611         if(!except_port_flag)
00612         {
00613             DEBUG_WRAP(DebugMessage(DEBUG_DETECT, ", port mismatch,  "
00614                         "packet rejected\n"););
00615             return 0;
00616         }
00617         DEBUG_WRAP(DebugMessage(DEBUG_DETECT, ", port mismatch exception"););
00618     }
00619     else
00620     {
00621         /* if the exception flag is up, fail */
00622         if(except_port_flag)
00623         {
00624             DEBUG_WRAP(DebugMessage(DEBUG_DETECT,
00625                                     ", port match exception,  packet rejected\n"););
00626             return 0;
00627         }
00628         DEBUG_WRAP(DebugMessage(DEBUG_DETECT, ", ports match"););
00629     }
00630 
00631     /* ports and address match */
00632     DEBUG_WRAP(DebugMessage(DEBUG_DETECT, ", packet accepted!\n"););
00633     return 1;
00634 
00635 }
00636 
00637 /****************************************************************************
00638  *
00639  * Function: DumpChain(RuleTreeNode *, char *, char *)
00640  *
00641  * Purpose: print out the chain lists by header block node group
00642  *
00643  * Arguments: rtn_idx => the RTN index pointer
00644  *                       rulename => the name of the rule the list belongs to
00645  *            listname => the name of the list being printed out
00646  *
00647  * Returns: void function
00648  *
00649  ***************************************************************************/
00650 void DumpChain(RuleTreeNode * rtn_head, char *rulename, char *listname)
00651 {
00652     RuleTreeNode *rtn_idx;
00653     IpAddrSet *idx;  /* indexing pointer */
00654     int i;
00655 #ifdef DEBUG
00656     OptTreeNode *otn_idx;
00657 #endif
00658 
00659 
00660     
00661     DEBUG_WRAP(DebugMessage(DEBUG_RULES, "%s %s\n", rulename, listname););
00662 
00663     rtn_idx = rtn_head;
00664 
00665     if(rtn_idx == NULL)
00666         DEBUG_WRAP(DebugMessage(DEBUG_RULES, "    Empty!\n\n"););
00667 
00668     /* walk thru the RTN list */
00669     while(rtn_idx != NULL)
00670     {
00671         DEBUG_WRAP(
00672                 DebugMessage(DEBUG_RULES, "Rule type: %d\n", rtn_idx->type);
00673                 DebugMessage(DEBUG_RULES, "SRC IP List:\n");
00674                 );
00675         idx = rtn_idx->sip;
00676         i = 0;
00677         while(idx != NULL)
00678         {
00679             DEBUG_WRAP(DebugMessage(DEBUG_RULES,
00680                         "[%d]    0x%.8lX / 0x%.8lX",
00681                         i++, (u_long) idx->ip_addr,
00682                         (u_long) idx->netmask););
00683 
00684             if(idx->addr_flags & EXCEPT_IP)
00685             {
00686                 DEBUG_WRAP(DebugMessage(DEBUG_RULES, 
00687                             "    (EXCEPTION_FLAG Active)\n"););
00688             }
00689             else
00690             {
00691                 DEBUG_WRAP(DebugMessage(DEBUG_RULES, "\n"););
00692             }
00693             idx = idx->next;
00694         }
00695 
00696         DEBUG_WRAP(DebugMessage(DEBUG_RULES, "DST IP List:\n"););
00697         idx = rtn_idx->dip;
00698         i = 0;
00699 
00700         while(idx != NULL)
00701         {
00702             DEBUG_WRAP(DebugMessage(DEBUG_RULES,
00703                         "[%d]    0x%.8lX / 0x%.8lX",
00704                         i++,(u_long)  idx->ip_addr,
00705                         (u_long)  idx->netmask););    
00706             if(idx->addr_flags & EXCEPT_IP)
00707             {
00708                 DEBUG_WRAP(DebugMessage(DEBUG_RULES, 
00709                             "    (EXCEPTION_FLAG Active)\n"););
00710             }
00711             else
00712             {
00713                 DEBUG_WRAP(DebugMessage(DEBUG_RULES, "\n"););
00714             }
00715 
00716             idx = idx->next;
00717         }
00718 #ifdef DEBUG
00719         DebugMessage(DEBUG_RULES, "SRC PORT: %d - %d \n", rtn_idx->lsp, 
00720                 rtn_idx->hsp);
00721         DebugMessage(DEBUG_RULES, "DST PORT: %d - %d \n", rtn_idx->ldp, 
00722                 rtn_idx->hdp);
00723         DebugMessage(DEBUG_RULES, "Flags: ");
00724 
00725         if(rtn_idx->flags & EXCEPT_SRC_IP)
00726             DebugMessage(DEBUG_RULES, "EXCEPT_SRC_IP ");
00727         if(rtn_idx->flags & EXCEPT_DST_IP)
00728             DebugMessage(DEBUG_RULES, "EXCEPT_DST_IP ");
00729         if(rtn_idx->flags & ANY_SRC_PORT)
00730             DebugMessage(DEBUG_RULES, "ANY_SRC_PORT ");
00731         if(rtn_idx->flags & ANY_DST_PORT)
00732             DebugMessage(DEBUG_RULES, "ANY_DST_PORT ");
00733         if(rtn_idx->flags & EXCEPT_SRC_PORT)
00734             DebugMessage(DEBUG_RULES, "EXCEPT_SRC_PORT ");
00735         if(rtn_idx->flags & EXCEPT_DST_PORT)
00736             DebugMessage(DEBUG_RULES, "EXCEPT_DST_PORT ");
00737         DebugMessage(DEBUG_RULES, "\n");
00738 
00739         otn_idx = rtn_idx->down;
00740 
00741             DEBUG_WRAP(
00742                     /* print the RTN header number */
00743                     DebugMessage(DEBUG_RULES,
00744                         "Head: %d (type: %d)\n",
00745                         rtn_idx->head_node_number, otn_idx->type);
00746                     DebugMessage(DEBUG_RULES, "      |\n");
00747                     DebugMessage(DEBUG_RULES, "       ->");
00748                     );
00749 
00750             /* walk thru the OTN chain */
00751             while(otn_idx != NULL)
00752             {
00753                 DEBUG_WRAP(DebugMessage(DEBUG_RULES,
00754                             " %d", otn_idx->chain_node_number););
00755                 otn_idx = otn_idx->next;
00756             }
00757 
00758         DEBUG_WRAP(DebugMessage(DEBUG_RULES, "|=-\n"););
00759 #endif
00760         rtn_idx = rtn_idx->right;
00761     }
00762 }
00763 
00764 
00765 
00766 void IntegrityCheck(RuleTreeNode * rtn_head, char *rulename, char *listname)
00767 {
00768     RuleTreeNode *rtn_idx = NULL;
00769     OptTreeNode *otn_idx;
00770     OptFpList *ofl_idx;
00771     int opt_func_count;
00772 
00773 #ifdef DEBUG
00774     char chainname[STD_BUF];
00775 
00776     snprintf(chainname, STD_BUF - 1, "%s %s", rulename, listname);
00777 
00778     if(!pv.quiet_flag)
00779         DebugMessage(DEBUG_DETECT, "%-20s: ", chainname);
00780 #endif
00781 
00782     if(rtn_head == NULL)
00783     {
00784 #ifdef DEBUG
00785         if(!pv.quiet_flag)
00786             DebugMessage(DEBUG_DETECT,"Empty list...\n");
00787 #endif
00788         return;
00789     }
00790 
00791     rtn_idx = rtn_head;
00792 
00793     while(rtn_idx != NULL)
00794     {
00795         otn_idx = rtn_idx->down;
00796 
00797         while(otn_idx != NULL)
00798         {
00799             ofl_idx = otn_idx->opt_func;
00800             opt_func_count = 0;
00801 
00802             while(ofl_idx != NULL)
00803             {
00804                 opt_func_count++;
00805                 DEBUG_WRAP(DebugMessage(DEBUG_DETECT, "%p->",ofl_idx->OptTestFunc););
00806                 ofl_idx = ofl_idx->next;
00807             }
00808 
00809             if(opt_func_count == 0)
00810             {
00811                 FatalError("Zero Length OTN List\n");
00812             }
00813             DEBUG_WRAP(DebugMessage(DEBUG_DETECT,"\n"););
00814             otn_idx = otn_idx->next;
00815         }
00816 
00817         rtn_idx = rtn_idx->right;
00818     }
00819 
00820 #ifdef DEBUG
00821     if(!pv.quiet_flag)
00822         DebugMessage(DEBUG_DETECT, "OK\n");
00823 #endif
00824 
00825 }
00826 
00827 
00828 
00829 int CheckBidirectional(Packet *p, struct _RuleTreeNode *rtn_idx, 
00830         RuleFpList *fp_list)
00831 {
00832     DEBUG_WRAP(DebugMessage(DEBUG_DETECT, "Checking bidirectional rule...\n"););
00833     
00834     if(CheckAddrPort(rtn_idx->sip, rtn_idx->hsp, rtn_idx->lsp, p,
00835                      rtn_idx->flags, CHECK_SRC))
00836     {
00837         DEBUG_WRAP(DebugMessage(DEBUG_DETECT, "   Src->Src check passed\n"););
00838         if(! CheckAddrPort(rtn_idx->dip, rtn_idx->hdp, rtn_idx->ldp, p,
00839                            rtn_idx->flags, CHECK_DST))
00840         {
00841             DEBUG_WRAP(DebugMessage(DEBUG_DETECT,
00842                                     "   Dst->Dst check failed,"
00843                                     " checking inverse combination\n"););
00844             if(CheckAddrPort(rtn_idx->dip, rtn_idx->hdp, rtn_idx->ldp, p,
00845                              rtn_idx->flags, (CHECK_SRC | INVERSE)))
00846             {
00847                 DEBUG_WRAP(DebugMessage(DEBUG_DETECT,
00848                                     "   Inverse Dst->Src check passed\n"););
00849                 if(!CheckAddrPort(rtn_idx->sip, rtn_idx->hsp, rtn_idx->lsp, p,
00850                                   rtn_idx->flags, (CHECK_DST | INVERSE)))
00851                 {
00852                     DEBUG_WRAP(DebugMessage(DEBUG_DETECT,
00853                                     "   Inverse Src->Dst check failed\n"););
00854                     return 0;
00855                 }
00856                 else
00857                 {
00858                     DEBUG_WRAP(DebugMessage(DEBUG_DETECT, "Inverse addr/port match\n"););
00859                 }
00860             }
00861             else
00862             {
00863                 DEBUG_WRAP(DebugMessage(DEBUG_DETECT, "   Inverse Dst->Src check failed,"
00864                                         " trying next rule\n"););
00865                 return 0;
00866             }
00867         }
00868         else
00869         {
00870             DEBUG_WRAP(DebugMessage(DEBUG_DETECT, "dest IP/port match\n"););
00871         }
00872     }
00873     else
00874     {
00875         DEBUG_WRAP(DebugMessage(DEBUG_DETECT,
00876                                 "   Src->Src check failed, trying inverse test\n"););
00877         if(CheckAddrPort(rtn_idx->dip, rtn_idx->hdp, rtn_idx->ldp, p,
00878                          rtn_idx->flags, CHECK_SRC | INVERSE))
00879         {
00880             DEBUG_WRAP(DebugMessage(DEBUG_DETECT,
00881                         "   Dst->Src check passed\n"););
00882 
00883             if(! CheckAddrPort(rtn_idx->sip, rtn_idx->hsp, rtn_idx->lsp, p, 
00884                         rtn_idx->flags, CHECK_DST | INVERSE))
00885             {
00886                 DEBUG_WRAP(DebugMessage(DEBUG_DETECT,
00887                             "   Src->Dst check failed\n"););
00888                 return 0;
00889             }
00890             else
00891             {
00892                 DEBUG_WRAP(DebugMessage(DEBUG_DETECT,
00893                             "Inverse addr/port match\n"););
00894             }
00895         }
00896         else
00897         { 
00898             DEBUG_WRAP(DebugMessage(DEBUG_DETECT,"   Inverse test failed, "
00899                         "testing next rule...\n"););
00900             return 0;
00901         }
00902     }
00903 
00904     DEBUG_WRAP(DebugMessage(DEBUG_DETECT,"   Bidirectional success!\n"););
00905     return 1;
00906 }
00907 
00908 
00909 
00910 /****************************************************************************
00911  *
00912  * Function: CheckSrcIpEqual(Packet *, struct _RuleTreeNode *, RuleFpList *)
00913  *
00914  * Purpose: Test the source IP and see if it equals the SIP of the packet
00915  *
00916  * Arguments: p => ptr to the decoded packet data structure
00917  *            rtn_idx => ptr to the current rule data struct
00918  *            fp_list => ptr to the current function pointer node
00919  *
00920  * Returns: 0 on failure (no match), 1 on success (match)
00921  *
00922  ***************************************************************************/
00923 int CheckSrcIP(Packet * p, struct _RuleTreeNode * rtn_idx, RuleFpList * fp_list)
00924 {
00925     IpAddrSet *idx; /* ip address indexer */
00926 
00927     DEBUG_WRAP(DebugMessage(DEBUG_DETECT,"CheckSrcIPEqual: "););
00928 
00929     /* check for global exception flag */
00930     if(!(rtn_idx->flags & EXCEPT_SRC_IP))
00931     {
00932         /* do the check */
00933         for(idx=rtn_idx->sip; idx != NULL; idx=idx->next)
00934         {
00935             if( ((idx->ip_addr == (p->iph->ip_src.s_addr & idx->netmask)) 
00936                         ^ (idx->addr_flags & EXCEPT_IP)) )
00937             {
00938 #ifdef DEBUG
00939                 if(idx->addr_flags & EXCEPT_IP) {
00940                     DebugMessage(DEBUG_DETECT, "  SIP exception match\n");
00941                 } 
00942                 else
00943                 {
00944                     DebugMessage(DEBUG_DETECT, "  SIP match\n");
00945                 }
00946 
00947                 DebugMessage(DEBUG_DETECT, "Rule: 0x%X     Packet: 0x%X\n", 
00948                         idx->ip_addr, (p->iph->ip_src.s_addr & idx->netmask));
00949 #endif /* DEBUG */
00950 
00951                 /* the packet matches this test, proceed to the next test */
00952                 return fp_list->next->RuleHeadFunc(p, rtn_idx, fp_list->next);
00953             }
00954         }
00955     }
00956     else
00957     {
00958         /* global exception flag is up, we can't match on *any* 
00959          * of the source addresses 
00960          */
00961         DEBUG_WRAP(DebugMessage(DEBUG_DETECT,"  global exception flag, \n"););
00962 
00963         /* do the check */
00964         for(idx=rtn_idx->sip; idx != NULL; idx=idx->next)
00965         {
00966             if( ((idx->ip_addr == (p->iph->ip_src.s_addr & idx->netmask)) 
00967                         ^ (idx->addr_flags & EXCEPT_IP)) )
00968             {
00969                 DEBUG_WRAP(DebugMessage(DEBUG_DETECT,"address matched, failing on SIP\n"););
00970                 /* got address match on globally negated rule, fail */
00971                 return 0;
00972             }
00973         }
00974         DEBUG_WRAP(DebugMessage(DEBUG_DETECT,"no matches on SIP, passed\n"););
00975 
00976         return fp_list->next->RuleHeadFunc(p, rtn_idx, fp_list->next);
00977     }
00978     
00979     DEBUG_WRAP(DebugMessage(DEBUG_DETECT,"  Mismatch on SIP\n"););
00980 
00981     /* return 0 on a failed test */
00982     return 0;
00983 }
00984 
00985 
00986 
00987 /****************************************************************************
00988  *
00989  * Function: CheckSrcIpNotEq(Packet *, struct _RuleTreeNode *, RuleFpList *)
00990  *
00991  * Purpose: Test the source IP and see if it's unequal to the SIP of the
00992  *          packet
00993  *
00994  * Arguments: p => ptr to the decoded packet data structure
00995  *            rtn_idx => ptr to the current rule data struct
00996  *            fp_list => ptr to the current function pointer node
00997  *
00998  * Returns: 0 on failure (no match), 1 on success (match)
00999  *
01000  ***************************************************************************/
01001 int CheckSrcIPNotEq(Packet *p, struct _RuleTreeNode *rtn_idx, 
01002         RuleFpList *fp_list)
01003 {
01004     IpAddrSet *idx;  /* IP address indexer */
01005     DEBUG_WRAP(DebugMessage(DEBUG_DETECT, "CheckSrcIPNotEq: "););
01006 
01007     /* do the check */
01008     for(idx=rtn_idx->sip; idx != NULL; idx=idx->next)
01009     {
01010         if( idx->ip_addr != (p->iph->ip_src.s_addr & idx->netmask) )
01011         {
01012             DEBUG_WRAP(DebugMessage(DEBUG_DETECT, "  SIP exception match\n"););
01013             /* the packet matches this test, proceed to the next test */
01014             return fp_list->next->RuleHeadFunc(p, rtn_idx, fp_list->next);
01015         }
01016     }
01017 
01018     DEBUG_WRAP(DebugMessage(DEBUG_DETECT, "  Mismatch on SIP\n"););
01019     
01020     /* return 0 on a failed test */
01021     return 0;
01022 }
01023 
01024 
01025 
01026 /****************************************************************************
01027  *
01028  * Function: CheckDstIpEqual(Packet *, struct _RuleTreeNode *, RuleFpList *)
01029  *
01030  * Purpose: Test the dest IP and see if it equals the DIP of the packet
01031  *
01032  * Arguments: p => ptr to the decoded packet data structure
01033  *            rtn_idx => ptr to the current rule data struct
01034  *            fp_list => ptr to the current function pointer node
01035  *
01036  * Returns: 0 on failure (no match), 1 on success (match)
01037  *
01038  ***************************************************************************/
01039 int CheckDstIP(Packet *p, struct _RuleTreeNode *rtn_idx, RuleFpList *fp_list)
01040 {
01041     IpAddrSet *idx;  /* ip address indexer */
01042 
01043     DEBUG_WRAP(DebugMessage(DEBUG_DETECT, "CheckDstIPEqual: ");)
01044 
01045     /* check for global exception flag */
01046     if(!(rtn_idx->flags & EXCEPT_DST_IP))
01047     {
01048         /* do the check */
01049         for(idx=rtn_idx->dip; idx != NULL; idx=idx->next)
01050         {
01051             if( ((idx->ip_addr == (p->iph->ip_dst.s_addr & idx->netmask)) 
01052                         ^ (idx->addr_flags & EXCEPT_IP)) )
01053             {
01054 #ifdef DEBUG
01055                 if(idx->addr_flags & EXCEPT_IP)
01056                 {
01057                     DebugMessage(DEBUG_DETECT, "  DIP exception match\n");
01058                 }
01059                 else
01060                 {
01061                     DebugMessage(DEBUG_DETECT, "  DIP match\n");
01062                 }
01063                 
01064                 DebugMessage(DEBUG_DETECT, "Rule: 0x%X     Packet: 0x%X\n", 
01065                         idx->ip_addr, (p->iph->ip_src.s_addr & idx->netmask));
01066 #endif /* DEBUG */
01067                 /* the packet matches this test, proceed to the next test */
01068                 return fp_list->next->RuleHeadFunc(p, rtn_idx, fp_list->next);
01069             }
01070         }
01071     }
01072     else
01073     {
01074         /* global exception flag is up, we can't match on *any* 
01075          * of the source addresses 
01076          */
01077         DEBUG_WRAP(DebugMessage(DEBUG_DETECT, "  global exception flag, \n"););
01078 
01079         /* do the check */
01080         for(idx=rtn_idx->dip; idx != NULL; idx=idx->next)
01081         {
01082             if( ((idx->ip_addr == (p->iph->ip_dst.s_addr & idx->netmask)) 
01083                         ^ (idx->addr_flags & EXCEPT_IP)) )
01084             {
01085                 DEBUG_WRAP(DebugMessage(DEBUG_DETECT,
01086                                         "address matched, failing on DIP\n"););
01087                 /* got address match on globally negated rule, fail */
01088                 return 0;
01089             }
01090         }
01091         DEBUG_WRAP(DebugMessage(DEBUG_DETECT, "no matches on DIP, passed\n"););
01092 
01093         return fp_list->next->RuleHeadFunc(p, rtn_idx, fp_list->next);
01094     }
01095 
01096     DEBUG_WRAP(DebugMessage(DEBUG_DETECT, "  Mismatch on DIP\n"););
01097     /* return 0 on a failed test */
01098     return 0;
01099 }
01100 
01101 
01102 /****************************************************************************
01103  *
01104  * Function: CheckDstIpNotEq(Packet *, struct _RuleTreeNode *, RuleFpList *)
01105  *
01106  * Purpose: Test the dest IP and see if it equals the DIP of the packet
01107  *
01108  * Arguments: p => ptr to the decoded packet data structure
01109  *            rtn_idx => ptr to the current rule data struct
01110  *            fp_list => ptr to the current function pointer node
01111  *
01112  * Returns: 0 on failure (no match), 1 on success (match)
01113  *
01114  ***************************************************************************/
01115 int CheckDstIPNotEq(Packet *p, struct _RuleTreeNode *rtn_idx, 
01116         RuleFpList *fp_list)
01117 {
01118     IpAddrSet *idx; /* ip address indexer */
01119 
01120     DEBUG_WRAP(DebugMessage(DEBUG_DETECT,"CheckDstIPNotEq: "););
01121 
01122     /* same as above */
01123     for(idx=rtn_idx->dip;idx != NULL; idx=idx->next)
01124     {
01125         if( idx->ip_addr != (p->iph->ip_dst.s_addr & idx->netmask) )
01126         {
01127             DEBUG_WRAP(DebugMessage(DEBUG_DETECT,"  DIP exception match\n"););
01128             return fp_list->next->RuleHeadFunc(p, rtn_idx, fp_list->next);
01129         }
01130     }
01131 
01132     DEBUG_WRAP(DebugMessage(DEBUG_DETECT,"  Mismatch on DIP\n"););
01133 
01134     return 0;
01135 }
01136 
01137 
01138 
01139 int CheckSrcPortEqual(Packet *p, struct _RuleTreeNode *rtn_idx, 
01140         RuleFpList *fp_list)
01141 {
01142     DEBUG_WRAP(DebugMessage(DEBUG_DETECT,"CheckSrcPortEqual: "););
01143 
01144     if( (p->sp <= rtn_idx->hsp) && (p->sp >= rtn_idx->lsp) )
01145     {
01146         DEBUG_WRAP(DebugMessage(DEBUG_DETECT, "  SP match!\n"););
01147         return fp_list->next->RuleHeadFunc(p, rtn_idx, fp_list->next);
01148     }
01149     else
01150     {
01151         DEBUG_WRAP(DebugMessage(DEBUG_DETECT, "   SP mismatch!\n"););
01152     }
01153 
01154     return 0;
01155 }
01156 
01157 
01158 
01159 
01160 
01161 int CheckSrcPortNotEq(Packet *p, struct _RuleTreeNode *rtn_idx, 
01162         RuleFpList *fp_list)
01163 {
01164     DEBUG_WRAP(DebugMessage(DEBUG_DETECT, "CheckSrcPortNotEq: "););
01165 
01166     if( (p->sp > rtn_idx->hsp) || (p->sp < rtn_idx->lsp) )
01167     {
01168         DEBUG_WRAP(DebugMessage(DEBUG_DETECT, "  SP exception match!\n"););
01169         return fp_list->next->RuleHeadFunc(p, rtn_idx, fp_list->next);
01170     }
01171     else
01172     {
01173         DEBUG_WRAP(DebugMessage(DEBUG_DETECT,"   SP mismatch!\n"););
01174     }
01175 
01176     return 0;
01177 }
01178 
01179 
01180 
01181 
01182 
01183 int CheckDstPortEqual(Packet *p, struct _RuleTreeNode *rtn_idx, 
01184         RuleFpList *fp_list)
01185 {
01186     DEBUG_WRAP(DebugMessage(DEBUG_DETECT,"CheckDstPortEqual: "););
01187 
01188     if( (p->dp <= rtn_idx->hdp) && (p->dp >= rtn_idx->ldp) )
01189     {
01190         DEBUG_WRAP(DebugMessage(DEBUG_DETECT, " DP match!\n"););
01191         return fp_list->next->RuleHeadFunc(p, rtn_idx, fp_list->next);
01192     }
01193     else
01194     {
01195         DEBUG_WRAP(DebugMessage(DEBUG_DETECT," DP mismatch!\n"););
01196     }
01197     return 0;
01198 }
01199 
01200 
01201 
01202 
01203 int CheckDstPortNotEq(Packet *p, struct _RuleTreeNode *rtn_idx, 
01204         RuleFpList *fp_list)
01205 {
01206     DEBUG_WRAP(DebugMessage(DEBUG_DETECT, "CheckDstPortNotEq: "););
01207 
01208     if( (p->dp > rtn_idx->hdp) || (p->dp < rtn_idx->ldp) )
01209     {
01210         DEBUG_WRAP(DebugMessage(DEBUG_DETECT," DP exception match!\n"););
01211         return fp_list->next->RuleHeadFunc(p, rtn_idx, fp_list->next);
01212     }
01213     else
01214     {
01215         DEBUG_WRAP(DebugMessage(DEBUG_DETECT," DP mismatch!\n"););
01216     }
01217 
01218     return 0;
01219 }
01220 
01221 
01222 
01223 int RuleListEnd(Packet *p, struct _RuleTreeNode *rtn_idx, RuleFpList *fp_list)
01224 {
01225     return 1;
01226 }
01227 
01228 
01229 int OptListEnd(Packet *p, struct _OptTreeNode *otn_idx, OptFpList *fp_list)
01230 {
01231     return 1;
01232 }
01233 
01234 
01235 void CreateDefaultRules()
01236 {
01237     CreateRuleType("activation", RULE_ACTIVATE, 1, &Activation);
01238     CreateRuleType("dynamic", RULE_DYNAMIC, 1, &Dynamic);
01239     CreateRuleType("drop", RULE_DROP, 1, &Drop);
01240 #ifdef GIDS
01241     CreateRuleType("sdrop", RULE_SDROP, 0, &SDrop);
01242     CreateRuleType("reject", RULE_REJECT, 1, &Reject);
01243     CreateRuleType("rejectboth", RULE_REJECTBOTH, 1, &RejectBoth);
01244     CreateRuleType("rejectsrc", RULE_REJECTSRC, 1, &RejectSrc);
01245     CreateRuleType("rejectdst", RULE_REJECTDST, 1, &RejectDst);
01246 #ifdef IPFW
01247     CreateRuleType("reinject", RULE_REINJECT, 1, &Reinject);
01248 #endif /* IPFW */
01249 #endif /* GIDS */
01250     CreateRuleType("alert", RULE_ALERT, 1, &Alert);
01251     CreateRuleType("pass", RULE_PASS, 0, &Pass);
01252     CreateRuleType("log", RULE_LOG, 1, &Log);
01253 }
01254 
01255 void printRuleOrder()
01256 {
01257     printRuleListOrder(RuleLists);
01258 }
01259 
01260 /****************************************************************************
01261  *
01262  * Function: CreateRuleType
01263  *
01264  * Purpose: Creates a new type of rule and adds it to the end of the rule list
01265  *
01266  * Arguments: name = name of this rule type
01267  *                       mode = the mode for this rule type
01268  *                   rval = return value for this rule type (for detect events)
01269  *                       head = list head to use (or NULL to create a new one)
01270  *
01271  * Returns: the ListHead for the rule type
01272  *
01273  ***************************************************************************/
01274 ListHead *CreateRuleType(char *name, int mode, int rval, ListHead *head)
01275 {
01276     RuleListNode *node;
01277     int evalIndex = 0;
01278 
01279     /* Using calloc() instead of malloc() because code isn't initializing
01280      * all of the structure fields before returning.  This is a non-
01281      * time-critical function, and is only called a half dozen times
01282      * on startup.
01283      */
01284 
01285     /*
01286      * if this is the first rule list node, then we need to create a new
01287      * list. we do not allow multiple rules with the same name.
01288      */
01289     if(!RuleLists)
01290     {
01291         RuleLists = (RuleListNode *)calloc(1, sizeof(RuleListNode));
01292         node = RuleLists;
01293     }
01294     else
01295     {
01296         node = RuleLists;
01297 
01298         while(1)
01299         {
01300             evalIndex++;
01301             if(!strcmp(node->name, name))
01302                 return NULL;
01303             if(!node->next)
01304                 break;
01305             node = node->next;
01306         }
01307 
01308         node->next = (RuleListNode *) calloc(1, sizeof(RuleListNode));
01309         node = node->next;
01310     }
01311 
01312     if(!head)
01313     {
01314         node->RuleList = (ListHead *)calloc(1, sizeof(ListHead));
01315         node->RuleList->IpList = NULL;
01316         node->RuleList->TcpList = NULL;
01317         node->RuleList->UdpList = NULL;
01318         node->RuleList->IcmpList = NULL;
01319         node->RuleList->LogList = NULL;
01320         node->RuleList->AlertList = NULL;
01321     }
01322     else
01323     {
01324         node->RuleList = head;
01325     }
01326 
01327     node->RuleList->ruleListNode = node;
01328     node->mode = mode;
01329     node->rval = rval;
01330     node->name = strdup(name);
01331     node->evalIndex = evalIndex;
01332     node->next = NULL;
01333     
01334     pv.num_rule_types++;
01335     
01336     return node->RuleList;
01337 }
01338 
01339 
01340 
01341 /****************************************************************************
01342  *
01343  * Function: OrderRuleLists
01344  *
01345  * Purpose: Orders the rule lists into the specefied order.
01346  *
01347  * Returns: void function
01348  *
01349  ***************************************************************************/
01350 void OrderRuleLists(char *order)
01351 {
01352     int i;
01353     int evalIndex = 0;
01354     RuleListNode *ordered_list = NULL;
01355     RuleListNode *prev;
01356     RuleListNode *node;
01357     static int called = 0;
01358     char **toks;
01359     int num_toks;
01360 
01361     if( called > 0 )
01362         LogMessage("Warning: multiple rule order directives.\n");
01363 
01364     toks = mSplit(order, " ", 10, &num_toks, 0);
01365 
01366     for( i = 0; i < num_toks; i++ )
01367     {
01368         prev = NULL;
01369         node = RuleLists;
01370 
01371         while( 1 )
01372         {
01373             if( node == NULL )
01374             {
01375                 FatalError("ruletype %s does not exist or "
01376                            "has already been ordered.\n", toks[i]);
01377                 break;
01378             }
01379             if( !strcmp(toks[i], node->name) )
01380             {
01381                 if( prev == NULL )
01382                     RuleLists = node->next;
01383                 else
01384                     prev->next = node->next;
01385                 /* Add node to ordered list */
01386                 ordered_list = addNodeToOrderedList(ordered_list, node, 
01387                         evalIndex++);
01388                 break;
01389             }
01390             else
01391             {
01392                 prev = node;
01393                 node = node->next;
01394             }
01395         }
01396     }
01397     mSplitFree(&toks, num_toks);
01398 
01399     /* anything left in the rule lists needs to be moved to the ordered lists */
01400     while( RuleLists != NULL )
01401     {
01402         node = RuleLists;
01403         RuleLists = node->next;
01404         /* Add node to ordered list */
01405         ordered_list = addNodeToOrderedList(ordered_list, node, evalIndex++);
01406     }
01407 
01408     /* set the rulelists to the ordered list */
01409     RuleLists = ordered_list;
01410     called = 1;
01411 }
01412 
01413 static RuleListNode *addNodeToOrderedList(RuleListNode *ordered_list, 
01414         RuleListNode *node, int evalIndex)
01415 {
01416     RuleListNode *prev;
01417 
01418     prev = ordered_list;
01419     
01420     /* set the eval order for this rule set */
01421     node->evalIndex = evalIndex;
01422     
01423     if(!prev)
01424     {
01425         ordered_list = node;
01426     }
01427     else
01428     {
01429         while(prev->next)
01430             prev = prev->next;
01431         prev->next = node;
01432     }
01433 
01434     node->next = NULL;
01435 
01436     return ordered_list;
01437 }
01438 
01439 
01440 void printRuleListOrder(RuleListNode * node)
01441 {
01442     char buf[STD_BUF+1];
01443 
01444     snprintf(buf, STD_BUF, "Rule application order: ");
01445 
01446     while( node != NULL )
01447     {
01448         sfsnprintfappend(buf, STD_BUF, "->%s", node->name);
01449         node = node->next;
01450     }
01451 
01452     LogMessage("%s\n", buf);
01453 }
01454 
01455 /* Rule Match Action Functions */
01456 int PassAction()
01457 {
01458     pc.pass_pkts++;
01459 
01460     DEBUG_WRAP(DebugMessage(DEBUG_DETECT,"   => Pass rule, returning...\n"););
01461     return 1;
01462 }
01463 
01464 
01465 
01466 int ActivateAction(Packet * p, OptTreeNode * otn, Event *event)
01467 {
01468     DEBUG_WRAP(DebugMessage(DEBUG_DETECT,
01469                    "        <!!> Activating and generating alert! \"%s\"\n",
01470                    otn->sigInfo.message););
01471     CallAlertFuncs(p, otn->sigInfo.message, otn->rtn->listhead, event);
01472 
01473     if (otn->OTN_activation_ptr == NULL)
01474     {
01475         LogMessage("WARNING: an activation rule with no "
01476                 "dynamic rules matched!\n");
01477         return 0;
01478     }
01479 
01480     otn->OTN_activation_ptr->active_flag = 1;
01481     otn->OTN_activation_ptr->countdown = 
01482         otn->OTN_activation_ptr->activation_counter;
01483 
01484     otn->RTN_activation_ptr->active_flag = 1;
01485     otn->RTN_activation_ptr->countdown += 
01486         otn->OTN_activation_ptr->activation_counter;
01487 
01488     active_dynamic_nodes++;
01489     DEBUG_WRAP(DebugMessage(DEBUG_DETECT,"   => Finishing activation packet!\n"););
01490     
01491     CallLogFuncs(p, otn->sigInfo.message, otn->rtn->listhead, event);
01492     DEBUG_WRAP(DebugMessage(DEBUG_DETECT, 
01493                 "   => Activation packet finished, returning!\n"););
01494 
01495     return 1;
01496 }
01497 
01498 int AlertAction(Packet * p, OptTreeNode * otn, Event *event)
01499 {
01500     DEBUG_WRAP(DebugMessage(DEBUG_DETECT,
01501                 "        <!!> Generating alert! \"%s\"\n", otn->sigInfo.message););
01502 
01503     /* Call OptTreeNode specific output functions */
01504     if(otn->outputFuncs)
01505         CallSigOutputFuncs(p, otn, event);
01506     
01507     CallAlertFuncs(p, otn->sigInfo.message, otn->rtn->listhead, event);
01508 
01509     DEBUG_WRAP(DebugMessage(DEBUG_DETECT, "   => Finishing alert packet!\n"););
01510 
01511     CallLogFuncs(p, otn->sigInfo.message, otn->rtn->listhead, event);
01512 
01513     /*
01514     if(p->ssnptr != NULL)
01515     {
01516         if(AlertFlushStream(p) == 0)
01517         {
01518             CallLogFuncs(p, otn->sigInfo.message, otn->rtn->listhead, event);
01519         }
01520     }
01521     else
01522     {
01523         CallLogFuncs(p, otn->sigInfo.message, otn->rtn->listhead, event);
01524     }
01525     */
01526 
01527     DEBUG_WRAP(DebugMessage(DEBUG_DETECT,"   => Alert packet finished, returning!\n"););
01528 
01529     return 1;
01530 }
01531 
01532 int DropAction(Packet * p, OptTreeNode * otn, Event *event)
01533 {
01534     Session *ssnptr;
01535 
01536     DEBUG_WRAP(DebugMessage(DEBUG_DETECT,
01537                "        <!!> Generating Alert and dropping! \"%s\"\n",
01538                otn->sigInfo.message););
01539     
01540     if(!s4data.ms_inline_alerts)
01541     {
01542         ssnptr = (Session *)p->ssnptr;
01543 
01544         if(ssnptr && ssnptr->session_flags & SSNFLAG_MIDSTREAM) 
01545         {
01546             DEBUG_WRAP(DebugMessage(DEBUG_DETECT,
01547                 " <!!> Alert Came From Midstream Session Silently Drop! "
01548                 "\"%s\"\n", otn->sigInfo.message);); 
01549 
01550             InlineDrop();
01551             return 1;
01552         }
01553     }
01554 
01555     /*
01556     **  Set packet flag so output plugins will know we dropped the
01557     **  packet we just logged.
01558     */
01559     p->packet_flags |= PKT_INLINE_DROP;
01560 
01561     CallAlertFuncs(p, otn->sigInfo.message, otn->rtn->listhead, event);
01562 
01563     CallLogFuncs(p, otn->sigInfo.message, otn->rtn->listhead, event);
01564 
01565     InlineDrop();
01566 
01567     return 1;
01568 }
01569 
01570 #ifdef GIDS
01571 int SDropAction(Packet * p, OptTreeNode * otn, Event *event)
01572 {
01573     DEBUG_WRAP(DebugMessage(DEBUG_DETECT,
01574                "        <!!> Dropping without Alerting! \"%s\"\n",
01575                otn->sigInfo.message););
01576 
01577     // Let's silently drop the packet
01578     InlineDrop();
01579     return 1;
01580 }
01581 
01582 int RejectAction(Packet * p, OptTreeNode * otn, Event *event)
01583 {
01584     DEBUG_WRAP(DebugMessage(DEBUG_DETECT,
01585                "        <!!>Ignoring! \"%s\"\n",
01586                otn->sigInfo.message););
01587 
01588     // Let's log/alert, drop the packet, and mark it for reset.
01589     CallAlertFuncs(p, otn->sigInfo.message, otn->rtn->listhead, event);
01590 
01591     CallLogFuncs(p, otn->sigInfo.message, otn->rtn->listhead, event);
01592 
01593     /*
01594     if(p->ssnptr != NULL)
01595     {
01596         if(AlertFlushStream(p) == 0)
01597         {
01598             CallLogFuncs(p, otn->sigInfo.message, otn->rtn->listhead, event);
01599         }
01600     }
01601     else
01602     {
01603         CallLogFuncs(p, otn->sigInfo.message, otn->rtn->listhead, event);
01604     }
01605 
01606     DEBUG_WRAP(DebugMessage(DEBUG_DETECT,
01607                "   => Alert packet finished, returning!\n"););
01608     */
01609     InlineReject(p);
01610 
01611     return 1;
01612 }
01613 
01614 int RejectBothAction(Packet * p, OptTreeNode * otn, Event *event)
01615 {
01616     DEBUG_WRAP(DebugMessage(DEBUG_DETECT,
01617                "        <!!>Ignoring! \"%s\"\n",
01618                otn->sigInfo.message););
01619 
01620     // Let's log/alert, drop the packet, and mark it for reset.
01621     CallAlertFuncs(p, otn->sigInfo.message, otn->rtn->listhead, event);
01622 
01623     CallLogFuncs(p, otn->sigInfo.message, otn->rtn->listhead, event);
01624 
01625     /*
01626     if(p->ssnptr != NULL)
01627     {
01628         if(AlertFlushStream(p) == 0)
01629         {
01630             CallLogFuncs(p, otn->sigInfo.message, otn->rtn->listhead, event);
01631         }
01632     }
01633     else
01634     {
01635         CallLogFuncs(p, otn->sigInfo.message, otn->rtn->listhead, event);
01636     }
01637 
01638     DEBUG_WRAP(DebugMessage(DEBUG_DETECT,
01639                "   => Alert packet finished, returning!\n"););
01640     */
01641 
01642     InlineRejectBoth(p);
01643     return 1;
01644 }
01645 
01646 int RejectSrcAction(Packet * p, OptTreeNode * otn, Event *event)
01647 {
01648     DEBUG_WRAP(DebugMessage(DEBUG_DETECT,
01649                "        <!!>Ignoring! \"%s\"\n",
01650                otn->sigInfo.message););
01651 
01652     // Let's log/alert, drop the packet, and mark it for reset.
01653     CallAlertFuncs(p, otn->sigInfo.message, otn->rtn->listhead, event);
01654 
01655     CallLogFuncs(p, otn->sigInfo.message, otn->rtn->listhead, event);
01656 
01657     /*
01658     if(p->ssnptr != NULL)
01659     {
01660         if(AlertFlushStream(p) == 0)
01661         {
01662             CallLogFuncs(p, otn->sigInfo.message, otn->rtn->listhead, event);
01663         }
01664     }
01665     else
01666     {
01667         CallLogFuncs(p, otn->sigInfo.message, otn->rtn->listhead, event);
01668     }
01669 
01670     DEBUG_WRAP(DebugMessage(DEBUG_DETECT,
01671                "   => Alert packet finished, returning!\n"););
01672     */
01673 
01674     InlineRejectSrc(p);
01675     return 1;
01676 }
01677 
01678 int RejectDstAction(Packet * p, OptTreeNode * otn, Event *event)
01679 {
01680     DEBUG_WRAP(DebugMessage(DEBUG_DETECT,
01681                "        <!!>Ignoring! \"%s\"\n",
01682                otn->sigInfo.message););
01683 
01684     // Let's log/alert, drop the packet, and mark it for reset.
01685     CallAlertFuncs(p, otn->sigInfo.message, otn->rtn->listhead, event);
01686 
01687     CallLogFuncs(p, otn->sigInfo.message, otn->rtn->listhead, event);
01688 
01689     /*
01690     if(p->ssnptr != NULL)
01691     {
01692         if(AlertFlushStream(p) == 0)
01693         {
01694             CallLogFuncs(p, otn->sigInfo.message, otn->rtn->listhead, event);
01695         }
01696     }
01697     else
01698     {
01699         CallLogFuncs(p, otn->sigInfo.message, otn->rtn->listhead, event);
01700     }
01701 
01702     DEBUG_WRAP(DebugMessage(DEBUG_DETECT,
01703                "   => Alert packet finished, returning!\n"););
01704     */
01705 
01706     InlineRejectDst(p);
01707     return 1;
01708 }
01709 
01710 #ifdef IPFW
01711 int ReinjectAction(Packet * p, OptTreeNode * otn, Event *event)
01712 {
01713     DEBUG_WRAP(DebugMessage(DEBUG_DETECT,
01714                "        <!!>Ignoring! \"%s\"\n",
01715                otn->sigInfo.message););
01716 
01717     // Let's log/alert, drop the packet, and mark it for reinject
01718     CallAlertFuncs(p, otn->sigInfo.message, otn->rtn->listhead, event);
01719 
01720     CallLogFuncs(p, otn->sigInfo.message, otn->rtn->listhead, event);
01721 
01722     InlineReinject(p);
01723 
01724     return 1;
01725 }
01726 #endif /* IPFW */
01727 #endif /* GIDS */
01728 
01729 
01730 int DynamicAction(Packet * p, OptTreeNode * otn, Event *event)
01731 {
01732     RuleTreeNode *rtn = otn->rtn;
01733 
01734     DEBUG_WRAP(DebugMessage(DEBUG_DETECT, "   => Logging packet data and"
01735                             " adjusting dynamic counts (%d/%d)...\n",
01736                             rtn->countdown, otn->countdown););
01737 
01738     CallLogFuncs(p, otn->sigInfo.message, otn->rtn->listhead, event);
01739 
01740     otn->countdown--;
01741 
01742     if( otn->countdown <= 0 )
01743     {
01744         otn->active_flag = 0;
01745         active_dynamic_nodes--;
01746         DEBUG_WRAP(DebugMessage(DEBUG_DETECT, "   <!!> Shutting down dynamic OTN node\n"););
01747     }
01748     
01749     rtn->countdown--;
01750 
01751     if( rtn->countdown <= 0 )
01752     {
01753         rtn->active_flag = 0;
01754         DEBUG_WRAP(DebugMessage(DEBUG_DETECT, "   <!!> Shutting down dynamic RTN node\n"););
01755     }
01756 
01757     return 1;
01758 }
01759 
01760 int LogAction(Packet * p, OptTreeNode * otn, Event *event)
01761 {
01762 
01763     DEBUG_WRAP(DebugMessage(DEBUG_DETECT,"   => Logging packet data and returning...\n"););
01764 
01765     CallLogFuncs(p, otn->sigInfo.message, otn->rtn->listhead, event);
01766 
01767 #ifdef BENCHMARK
01768     printf("        <!!> Check count = %d\n", check_count);
01769     check_count = 0;
01770     printf(" **** cmpcount: %d **** \n", cmpcount);
01771 #endif
01772 
01773     return 1;
01774 }
01775 
01776 void ObfuscatePacket(Packet *p)
01777 {
01778     /* only obfuscate once */
01779     if(p->packet_flags & PKT_OBFUSCATED)
01780         return;
01781     
01782     /* we only obfuscate IP packets */
01783     if(!p->iph)
01784         return;
01785     
01786     if(pv.obfuscation_net == 0)
01787     {
01788         p->iph->ip_src.s_addr = 0x00000000;
01789         p->iph->ip_dst.s_addr = 0x00000000;
01790     }
01791     else
01792     {
01793         if(pv.homenet != 0)
01794         {
01795             if((p->iph->ip_src.s_addr & pv.netmask) == pv.homenet)
01796             {
01797                 p->iph->ip_src.s_addr = pv.obfuscation_net |
01798                     (p->iph->ip_src.s_addr & pv.obfuscation_mask);
01799             }
01800             if((p->iph->ip_dst.s_addr & pv.netmask) == pv.homenet)
01801             {
01802                 p->iph->ip_dst.s_addr = pv.obfuscation_net |
01803                     (p->iph->ip_dst.s_addr & pv.obfuscation_mask);
01804             }
01805         }
01806         else
01807         {
01808             p->iph->ip_src.s_addr = pv.obfuscation_net |
01809                 (p->iph->ip_src.s_addr & pv.obfuscation_mask);
01810             p->iph->ip_dst.s_addr = pv.obfuscation_net |
01811                 (p->iph->ip_dst.s_addr & pv.obfuscation_mask);
01812         }
01813     }
01814     p->packet_flags |= PKT_OBFUSCATED;
01815 }
01816 
01817 /* end of rule action functions */
01818           

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