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

sp_icmp_seq_check.c

Go to the documentation of this file.
00001 /*
00002 ** Copyright (C) 1998-2002 Martin Roesch <roesch@sourcefire.com>
00003 **
00004 ** This program is free software; you can redistribute it and/or modify
00005 ** it under the terms of the GNU General Public License as published by
00006 ** the Free Software Foundation; either version 2 of the License, or
00007 ** (at your option) any later version.
00008 **
00009 ** This program is distributed in the hope that it will be useful,
00010 ** but WITHOUT ANY WARRANTY; without even the implied warranty of
00011 ** MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
00012 ** GNU General Public License for more details.
00013 **
00014 ** You should have received a copy of the GNU General Public License
00015 ** along with this program; if not, write to the Free Software
00016 ** Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
00017 */
00018 
00019 /* $Id$ */
00020 /* sp_icmp_seq_check 
00021  * 
00022  * Purpose:
00023  *
00024  * Test the Sequence number field of ICMP ECHO and ECHO_REPLY packets for 
00025  * specified values.  This is useful for detecting TFN attacks, amongst others.
00026  *
00027  * Arguments:
00028  *   
00029  * The ICMP Seq plugin takes a number as an option argument.
00030  *
00031  * Effect:
00032  *
00033  * Tests ICMP ECHO and ECHO_REPLY packet Seq field values and returns a 
00034  * "positive" detection result (i.e. passthrough) upon a value match.
00035  *
00036  * Comments:
00037  *
00038  * This plugin was developed to detect TFN distributed attacks.
00039  *
00040  */
00041 
00042 #ifdef HAVE_CONFIG_H
00043 #include "config.h"
00044 #endif
00045 
00046 #include <stdlib.h>
00047 #include <ctype.h>
00048 
00049 #include "rules.h"
00050 #include "decode.h"
00051 #include "plugbase.h"
00052 #include "parser.h"
00053 #include "debug.h"
00054 #include "util.h"
00055 #include "plugin_enum.h"
00056 
00057 
00058 typedef struct _IcmpSeqData
00059 {
00060     unsigned short icmpseq;
00061 
00062 } IcmpSeqData; 
00063 
00064 void IcmpSeqCheckInit(char *, OptTreeNode *, int);
00065 void ParseIcmpSeq(char *, OptTreeNode *);
00066 int IcmpSeqCheck(Packet *, struct _OptTreeNode *, OptFpList *);
00067 
00068 
00069 
00070 
00071 /****************************************************************************
00072  * 
00073  * Function: SetupIcmpSeqCheck()
00074  *
00075  * Purpose: Registers the configuration function and links it to a rule
00076  *          keyword.  This is the function that gets called from InitPlugins
00077  *          in plugbase.c.
00078  *
00079  * Arguments: None.
00080  *
00081  * Returns: void function
00082  *
00083  ****************************************************************************/
00084 void SetupIcmpSeqCheck(void)
00085 {
00086     /* map the keyword to an initialization/processing function */
00087     RegisterPlugin("icmp_seq", IcmpSeqCheckInit);
00088 
00089     DEBUG_WRAP(DebugMessage(DEBUG_PLUGIN, "Plugin: IcmpSeqCheck Setup\n"););
00090 }
00091 
00092 
00093 /****************************************************************************
00094  * 
00095  * Function: IcmpSeqCheckInit(char *, OptTreeNode *)
00096  *
00097  * Purpose: Handles parsing the rule information and attaching the associated
00098  *          detection function to the OTN.
00099  *
00100  * Arguments: data => rule arguments/data
00101  *            otn => pointer to the current rule option list node
00102  *
00103  * Returns: void function
00104  *
00105  ****************************************************************************/
00106 void IcmpSeqCheckInit(char *data, OptTreeNode *otn, int protocol)
00107 {
00108     if(protocol != IPPROTO_ICMP)
00109     {
00110         FatalError("%s(%d): ICMP Options on non-ICMP rule\n", file_name, file_line);
00111     }
00112 
00113     /* multiple declaration check */ 
00114     if(otn->ds_list[PLUGIN_ICMP_SEQ_CHECK])
00115     {
00116         FatalError("%s(%d): Multiple ICMP seq options in rule\n", file_name,
00117                 file_line);
00118     }
00119 
00120     /* allocate the data structure and attach it to the
00121        rule's data struct list */
00122     otn->ds_list[PLUGIN_ICMP_SEQ_CHECK] = (IcmpSeqData *)
00123         SnortAlloc(sizeof(IcmpSeqData));
00124 
00125     /* this is where the keyword arguments are processed and placed into the 
00126        rule option's data structure */
00127     ParseIcmpSeq(data, otn);
00128 
00129     /* finally, attach the option's detection function to the rule's 
00130        detect function pointer list */
00131     AddOptFuncToList(IcmpSeqCheck, otn);
00132 }
00133 
00134 
00135 
00136 /****************************************************************************
00137  * 
00138  * Function: ParseIcmpSeq(char *, OptTreeNode *)
00139  *
00140  * Purpose: Convert the rule option argument to program data.
00141  *
00142  * Arguments: data => argument data
00143  *            otn => pointer to the current rule's OTN
00144  *
00145  * Returns: void function
00146  *
00147  ****************************************************************************/
00148 void ParseIcmpSeq(char *data, OptTreeNode *otn)
00149 {
00150     IcmpSeqData *ds_ptr;  /* data struct pointer */
00151 
00152     /* set the ds pointer to make it easier to reference the option's
00153        particular data struct */
00154     ds_ptr = otn->ds_list[PLUGIN_ICMP_SEQ_CHECK];
00155 
00156     /* advance past whitespace */
00157     while(isspace((int)*data)) data++;
00158 
00159     ds_ptr->icmpseq = atoi(data);
00160     ds_ptr->icmpseq = htons(ds_ptr->icmpseq);
00161     
00162     DEBUG_WRAP(DebugMessage(DEBUG_PLUGIN, "Set ICMP Seq test value to %d\n", ds_ptr->icmpseq););
00163 }
00164 
00165 
00166 /****************************************************************************
00167  * 
00168  * Function: IcmpSeqCheck(char *, OptTreeNode *)
00169  *
00170  * Purpose: Compare the ICMP Sequence field to the rule value.
00171  *
00172  * Arguments: data => argument data
00173  *            otn => pointer to the current rule's OTN
00174  *
00175  * Returns: If the detection test fails, this function *must* return a zero!
00176  *          On success, it calls the next function in the detection list 
00177  *
00178  ****************************************************************************/
00179 int IcmpSeqCheck(Packet *p, struct _OptTreeNode *otn, OptFpList *fp_list)
00180 {
00181     if(!p->icmph)
00182         return 0; /* if error occured while icmp header
00183                    * was processed, return 0 automagically.
00184                */
00185     if(p->icmph->type == ICMP_ECHO || p->icmph->type == ICMP_ECHOREPLY)
00186     {
00187         /* test the rule ID value against the ICMP extension ID field */
00188         if(((IcmpSeqData *) otn->ds_list[PLUGIN_ICMP_SEQ_CHECK])->icmpseq == 
00189            p->icmph->s_icmp_seq)
00190         {
00191             /* call the next function in the function list recursively */
00192             return fp_list->next->OptTestFunc(p, otn, fp_list->next);
00193         }
00194         else
00195         {
00196             /* you can put debug comments here or not */
00197             DEBUG_WRAP(DebugMessage(DEBUG_PLUGIN,"ICMP Seq check failed\n"););
00198         }
00199     }
00200 
00201     /* if the test isn't successful, this function *must* return 0 */
00202     return 0;
00203 }

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