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

sp_isdataat.c

Go to the documentation of this file.
00001 /* $Id$ */
00002 
00003 /* sp_isdataat
00004  * 
00005  * Purpose:
00006  *    Test a specific byte to see if there is data.  (Basicly, rule keyword
00007  *    into inBounds)
00008  *
00009  * Arguments:
00010  *    <int>         byte location to check if there is data
00011  *    ["relative"]  look for byte location relative to the end of the last
00012  *                  pattern match
00013  *   
00014  * Sample:
00015  *   alert tcp any any -> any 110 (msg:"POP3 user overflow"; \
00016  *      content:"USER"; isdataat:30,relative; content:!"|0a|"; within:30;)
00017  */
00018 
00019 #ifdef HAVE_CONFIG_H
00020 #include "config.h"
00021 #endif
00022 
00023 #include <sys/types.h>
00024 #include <stdlib.h>
00025 #include <ctype.h>
00026 #ifdef HAVE_STRINGS_H
00027 #include <strings.h>
00028 #endif
00029 #include <errno.h>
00030 
00031 #include "bounds.h"
00032 #include "rules.h"
00033 #include "decode.h"
00034 #include "plugbase.h"
00035 #include "parser.h"
00036 #include "debug.h"
00037 #include "util.h"
00038 #include "mstring.h"
00039 
00040 extern char *file_name;  /* this is the file name from rules.c, generally used
00041                             for error messages */
00042 
00043 extern int file_line;    /* this is the file line number from rules.c that is
00044                             used to indicate file lines for error messages */
00045 
00046 extern u_int8_t *doe_ptr;
00047 
00048 typedef struct _IsDataAtData
00049 {
00050     u_int32_t offset;        /* byte location into the packet */
00051     u_int8_t  relative_flag; /* relative to the doe_ptr? */
00052 } IsDataAtData;
00053 
00054 extern u_int8_t DecodeBuffer[DECODE_BLEN];
00055 
00056 void IsDataAtInit(char *, OptTreeNode *, int);
00057 void IsDataAtParse(char *, IsDataAtData *, OptTreeNode *);
00058 int  IsDataAt(Packet *, struct _OptTreeNode *, OptFpList *);
00059 
00060 /****************************************************************************
00061  * 
00062  * Function: SetupIsDataAt()
00063  *
00064  * Purpose: Load 'er up
00065  *
00066  * Arguments: None.
00067  *
00068  * Returns: void function
00069  *
00070  ****************************************************************************/
00071 void SetupIsDataAt(void)
00072 {
00073     /* map the keyword to an initialization/processing function */
00074     RegisterPlugin("isdataat", IsDataAtInit);
00075 
00076     DEBUG_WRAP(DebugMessage(DEBUG_PLUGIN,"Plugin: IsDataAt Setup\n"););
00077 }
00078 
00079 
00080 /****************************************************************************
00081  * 
00082  * Function: IsDataAt(char *, OptTreeNode *, int protocol)
00083  *
00084  * Purpose: Generic rule configuration function.  Handles parsing the rule 
00085  *          information and attaching the associated detection function to
00086  *          the OTN.
00087  *
00088  * Arguments: data => rule arguments/data
00089  *            otn => pointer to the current rule option list node
00090  *            protocol => protocol the rule is on (we don't care in this case)
00091  *
00092  * Returns: void function
00093  *
00094  ****************************************************************************/
00095 void IsDataAtInit(char *data, OptTreeNode *otn, int protocol)
00096 {
00097     IsDataAtData *idx;
00098     OptFpList *fpl;
00099 
00100     /* allocate the data structure and attach it to the
00101        rule's data struct list */
00102     idx = (IsDataAtData *) SnortAlloc(sizeof(IsDataAtData));
00103 
00104     if(idx == NULL)
00105     {
00106         FatalError("%s(%d): Unable to allocate IsDataAt data node\n", 
00107                 file_name, file_line);
00108     }
00109 
00110     /* this is where the keyword arguments are processed and placed into the 
00111        rule option's data structure */
00112     IsDataAtParse(data, idx, otn);
00113 
00114     fpl = AddOptFuncToList(IsDataAt, otn);
00115     
00116     /* attach it to the context node so that we can call each instance
00117      * individually
00118      */
00119     fpl->context = (void *) idx;
00120 }
00121 
00122 
00123 
00124 /****************************************************************************
00125  * 
00126  * Function: IsDataAt(char *, IsDataAtData *, OptTreeNode *)
00127  *
00128  * Purpose: This is the function that is used to process the option keyword's
00129  *          arguments and attach them to the rule's data structures.
00130  *
00131  * Arguments: data => argument data
00132  *            idx => pointer to the processed argument storage
00133  *            otn => pointer to the current rule's OTN
00134  *
00135  * Returns: void function
00136  *
00137  ****************************************************************************/
00138 void IsDataAtParse(char *data, IsDataAtData *idx, OptTreeNode *otn)
00139 {
00140     char **toks;
00141     int num_toks;
00142     char *cptr;
00143     char *endp;
00144 
00145     toks = mSplit(data, ",", 2, &num_toks, 0);
00146 
00147     if(num_toks > 2) 
00148         FatalError("ERROR %s (%d): Bad arguments to IsDataAt: %s\n", file_name,
00149                 file_line, data);
00150 
00151     /* set how many bytes to process from the packet */
00152     idx->offset = strtol(toks[0], &endp, 10);
00153 
00154     if(toks[0] == endp)
00155     {
00156         FatalError("%s(%d): Unable to parse as byte value %s\n",
00157                    file_name, file_line, toks[0]);
00158     }
00159 
00160     if(idx->offset > 65535)
00161     {
00162         FatalError("%s(%d): IsDataAt offset greater than max IPV4 packet size",
00163                 file_name, file_line);
00164     }
00165 
00166     if(num_toks > 1)
00167     {
00168         cptr = toks[1];
00169 
00170         while(isspace((int)*cptr)) {cptr++;}
00171 
00172         if(!strcasecmp(cptr, "relative"))
00173         {
00174             /* the offset is relative to the last pattern match */
00175             idx->relative_flag = 1;
00176         }
00177         else
00178         {
00179             FatalError("%s(%d): unknown modifier \"%s\"\n",
00180                     file_name, file_line, toks[1]);
00181         }
00182     }
00183 
00184     mSplitFree(&toks,num_toks);
00185 }
00186 
00187 
00188 /****************************************************************************
00189  * 
00190  * Function: IsDataAt(char *, OptTreeNode *, OptFpList *)
00191  *
00192  * Purpose: Use this function to perform the particular detection routine
00193  *          that this rule keyword is supposed to encompass.
00194  *
00195  * Arguments: p => pointer to the decoded packet
00196  *            otn => pointer to the current rule's OTN
00197  *            fp_list => pointer to the function pointer list
00198  *
00199  * Returns: If the detection test fails, this function *must* return a zero!
00200  *          On success, it calls the next function in the detection list 
00201  *
00202  ****************************************************************************/
00203 int IsDataAt(Packet *p, struct _OptTreeNode *otn, OptFpList *fp_list)
00204 {
00205     IsDataAtData *isdata;
00206     int dsize;
00207     char *base_ptr, *end_ptr, *start_ptr;
00208 
00209     if(p->packet_flags & PKT_ALT_DECODE)
00210     {
00211         dsize = p->alt_dsize;
00212         start_ptr = (char *)DecodeBuffer;
00213         DEBUG_WRAP(DebugMessage(DEBUG_PATTERN_MATCH, 
00214                     "Using Alternative Decode buffer!\n"););
00215     }
00216     else
00217     {
00218         dsize = p->dsize;
00219         start_ptr = (char *) p->data;
00220     }
00221 
00222     base_ptr = start_ptr;
00223     end_ptr = start_ptr + dsize;
00224     
00225     if(doe_ptr)
00226     {
00227         if(!inBounds(start_ptr, end_ptr, doe_ptr))
00228         {
00229             DEBUG_WRAP(DebugMessage(DEBUG_PATTERN_MATCH,
00230                                     "[*] isdataat bounds check failed..\n"););
00231             return 0;
00232         }
00233     }
00234 
00235     isdata = (IsDataAtData *) fp_list->context;
00236 
00237     if(isdata->relative_flag && doe_ptr)
00238     {
00239         DEBUG_WRAP(DebugMessage(DEBUG_PATTERN_MATCH,
00240                                 "Checking relative offset!\n"););
00241         base_ptr = doe_ptr + isdata->offset;
00242     }
00243     else
00244     {
00245         DEBUG_WRAP(DebugMessage(DEBUG_PATTERN_MATCH,
00246                                 "checking absolute offset %d\n", isdata->offset););
00247         base_ptr = start_ptr + isdata->offset;
00248     }
00249 
00250     if(inBounds(start_ptr, end_ptr, base_ptr))
00251     {
00252         DEBUG_WRAP(DebugMessage(DEBUG_PATTERN_MATCH,
00253                     "[*] IsDataAt succeeded!  there is data...\n"););
00254         return fp_list->next->OptTestFunc(p, otn, fp_list->next);
00255     }
00256 
00257 
00258     /* otherwise dump */
00259     return 0;
00260 
00261 }

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