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

sp_ip_fragbits.c

Go to the documentation of this file.
00001 /* $Id$ */
00002 /*
00003 ** Copyright (C) 1998-2002 Martin Roesch <roesch@sourcefire.com>
00004 **
00005 ** This program is free software; you can redistribute it and/or modify
00006 ** it under the terms of the GNU General Public License as published by
00007 ** the Free Software Foundation; either version 2 of the License, or
00008 ** (at your option) any later version.
00009 **
00010 ** This program is distributed in the hope that it will be useful,
00011 ** but WITHOUT ANY WARRANTY; without even the implied warranty of
00012 ** MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
00013 ** GNU General Public License for more details.
00014 **
00015 ** You should have received a copy of the GNU General Public License
00016 ** along with this program; if not, write to the Free Software
00017 ** Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
00018 */
00019 
00020 /* Snort Detection Plugin Source File for IP Fragment Bits plugin */
00021 
00022 /* sp_ip_fragbits 
00023  * 
00024  * Purpose:
00025  *
00026  * Check the fragmentation bits of the IP header for set values.  Possible
00027  * bits are don't fragment (DF), more fragments (MF), and reserved (RB).
00028  *
00029  * Arguments:
00030  *   
00031  * The keyword to reference this plugin is "fragbits".  Possible arguments are
00032  * D, M and R for DF, MF and RB, respectively.  
00033  *
00034  * Effect:
00035  *
00036  * Inidicates whether any of the specified bits have been set.
00037  *
00038  * Comments:
00039  *
00040  * Ofir Arkin should be a little happier now. :)
00041  *
00042  */
00043 
00044 #ifdef HAVE_CONFIG_H
00045 #include "config.h"
00046 #endif
00047 
00048 #include <sys/types.h>
00049 #include <stdlib.h>
00050 #include <ctype.h>
00051 #include <string.h>
00052 
00053 #include "rules.h"
00054 #include "plugbase.h"
00055 #include "decode.h"
00056 #include "parser.h"
00057 #include "debug.h"
00058 #include "util.h"
00059 #include "plugin_enum.h"
00060 
00061 
00062 
00063 #define GREATER_THAN            1
00064 #define LESS_THAN               2
00065 
00066 
00067 #define FB_NORMAL   0
00068 #define FB_ALL      1
00069 #define FB_ANY      2
00070 #define FB_NOT      3
00071 
00072 #define FB_RB  0x8000
00073 #define FB_DF  0x4000
00074 #define FB_MF  0x2000
00075 
00076 
00077 
00078 typedef struct _FragBitsData
00079 {
00080     char mode;
00081     u_int16_t frag_bits;
00082 
00083 } FragBitsData;
00084 
00085 
00086 typedef struct _FragOffsetData
00087 {
00088     u_int8_t  comparison_flag;
00089     u_int8_t  not_flag;
00090     u_int16_t offset;
00091 } FragOffsetData;
00092 
00093 
00094 void FragBitsInit(char *, OptTreeNode *, int);
00095 void ParseFragBits(char *, OptTreeNode *);
00096 int CheckFragBits(Packet *, struct _OptTreeNode *, OptFpList *);
00097 
00098 /* offset checks */
00099 void FragOffsetInit(char *, OptTreeNode *, int);
00100 void ParseFragOffset(char *, OptTreeNode *);
00101 int CheckFragOffset(Packet *, struct _OptTreeNode *, OptFpList *);
00102 
00103 static u_int16_t bitmask;
00104 
00105 /****************************************************************************
00106  * 
00107  * Function: SetupFragBits()
00108  *
00109  * Purpose: Assign the keyword to the rules parser.
00110  *
00111  * Arguments: None.
00112  *
00113  * Returns: void function
00114  *
00115  ****************************************************************************/
00116 void SetupFragBits(void)
00117 {
00118     /* map the keyword to an initialization/processing function */
00119     RegisterPlugin("fragbits", FragBitsInit);
00120 
00121     DEBUG_WRAP(DebugMessage(DEBUG_PLUGIN, "Plugin: FragBits Setup\n"););
00122 }
00123 
00124 
00125 /****************************************************************************
00126  * 
00127  * Function: FragBitsInit(char *, OptTreeNode *)
00128  *
00129  * Purpose: Initialize the detection function and parse the arguments.
00130  *
00131  * Arguments: data => rule arguments/data
00132  *            otn => pointer to the current rule option list node
00133  *            protocol => protocol that must be specified to use this plugin
00134  *
00135  * Returns: void function
00136  *
00137  ****************************************************************************/
00138 void FragBitsInit(char *data, OptTreeNode *otn, int protocol)
00139 {
00140     /* multiple declaration check */ 
00141     if(otn->ds_list[PLUGIN_FRAG_BITS])
00142     {
00143         FatalError("%s(%d): Multiple fragbits options in rule\n", file_name,
00144                 file_line);
00145     }
00146         
00147     /* allocate the data structure and attach it to the
00148        rule's data struct list */
00149     otn->ds_list[PLUGIN_FRAG_BITS] = (FragBitsData *)
00150             SnortAlloc(sizeof(FragBitsData));
00151 
00152     /* this is where the keyword arguments are processed and placed into the 
00153        rule option's data structure */
00154     ParseFragBits(data, otn);
00155 
00156     /* 
00157      * set the bitmask needed to mask off the IP offset field 
00158      * in the check function
00159      */
00160     bitmask = htons(0xE000);
00161 
00162     /* finally, attach the option's detection function to the rule's 
00163        detect function pointer list */
00164     AddOptFuncToList(CheckFragBits, otn);
00165 }
00166 
00167 
00168 
00169 /****************************************************************************
00170  * 
00171  * Function: ParseFragBits(char *, OptTreeNode *)
00172  *
00173  * Purpose: This is the function that is used to process the option keyword's
00174  *          arguments and attach them to the rule's data structures.
00175  *
00176  * Arguments: data => argument data
00177  *            otn => pointer to the current rule's OTN
00178  *
00179  * Returns: void function
00180  *
00181  ****************************************************************************/
00182 void ParseFragBits(char *data, OptTreeNode *otn)
00183 {
00184     char *fptr;
00185     char *fend;
00186     FragBitsData *ds_ptr;  /* data struct pointer */
00187 
00188     /* set the ds pointer to make it easier to reference the option's
00189        particular data struct */
00190     ds_ptr = otn->ds_list[PLUGIN_FRAG_BITS];
00191 
00192     /* manipulate the option arguments here */
00193     fptr = data;
00194 
00195     while(isspace((u_char) *fptr))
00196     {
00197         fptr++;
00198     }
00199 
00200     if(strlen(fptr) == 0)
00201     {
00202         FatalError("[!] ERROR Line %s (%d): No arguments to the fragbits keyword\n", file_name, file_line);
00203     }
00204 
00205     fend = fptr + strlen(fptr);
00206 
00207     ds_ptr->mode = FB_NORMAL;  /* default value */
00208 
00209     while(fptr < fend)
00210     {
00211         switch((*fptr&0xFF))
00212         {
00213             case 'd':
00214             case 'D': /* don't frag bit */
00215                 ds_ptr->frag_bits |= FB_DF;
00216                 break;
00217 
00218             case 'm':
00219             case 'M': /* more frags bit */
00220                 ds_ptr->frag_bits |= FB_MF;
00221                 break;
00222                 
00223             case 'r':
00224             case 'R': /* reserved bit */
00225                 ds_ptr->frag_bits |= FB_RB;
00226                 break;
00227 
00228             case '!': /* NOT flag, fire if flags are not set */
00229                 ds_ptr->mode = FB_NOT;
00230                 break;
00231                     
00232             case '*': /* ANY flag, fire on any of these bits */
00233                 ds_ptr->mode = FB_ANY;
00234                 break;
00235                     
00236             case '+': /* ALL flag, fire on these bits plus any others */
00237                 ds_ptr->mode = FB_ALL;
00238                 break;
00239 
00240             default:
00241                 FatalError("[!] ERROR Line %s (%d): Bad Frag Bits = \"%c\"\n"
00242                            "     Valid options are: RDM+!*\n", file_name, 
00243                            file_line, *fptr);
00244         }
00245         
00246         fptr++;
00247     }
00248                     
00249     /* put the bits in network order for fast comparisons */
00250     ds_ptr->frag_bits = htons(ds_ptr->frag_bits);
00251 
00252     /* set the final option arguments here */
00253 }
00254 
00255 
00256 /****************************************************************************
00257  * 
00258  * Function: CheckFragBits(Packet *p, OptTreeNode *otn, OptFpList *fp_list)
00259  *
00260  * Purpose: This function checks the frag bits in the packets
00261  *
00262  * Arguments: data => argument data
00263  *            otn => pointer to the current rule's OTN
00264  *
00265  * Returns: If the mask matches return true, else return 0.
00266  *
00267  ****************************************************************************/
00268 int CheckFragBits(Packet *p, struct _OptTreeNode *otn, OptFpList *fp_list)
00269 {
00270     FragBitsData *fb;
00271 
00272     if(!p->iph)
00273     {
00274         return 0;
00275     }
00276     
00277     fb = otn->ds_list[PLUGIN_FRAG_BITS];
00278 
00279     DEBUG_WRAP(DebugMessage(DEBUG_PLUGIN, "           <!!> CheckFragBits: ");
00280                DebugMessage(DEBUG_PLUGIN, "[rule: 0x%X:%d   pkt: 0x%X] ",
00281                             fb->frag_bits, fb->mode, (p->iph->ip_off&bitmask)););
00282 
00283     switch(fb->mode)
00284     {
00285         case FB_NORMAL:
00286             /* check if the rule bits match the bits in the packet */
00287             if(fb->frag_bits == (p->iph->ip_off&bitmask)) 
00288             {
00289                 DEBUG_WRAP(DebugMessage(DEBUG_PLUGIN,"Got Normal bits match\n"););
00290                 return fp_list->next->OptTestFunc(p, otn, fp_list->next);
00291             }
00292             else
00293             {
00294                 DEBUG_WRAP(DebugMessage(DEBUG_PLUGIN,"Normal test failed\n"););
00295             }
00296             break;
00297 
00298         case FB_NOT:
00299             /* check if the rule bits don't match the bits in the packet */
00300             if((fb->frag_bits & (p->iph->ip_off&bitmask)) == 0)
00301             {
00302                 DEBUG_WRAP(DebugMessage(DEBUG_PLUGIN,"Got NOT bits match\n"););
00303                 return fp_list->next->OptTestFunc(p, otn, fp_list->next);
00304             }
00305             else
00306             {
00307                 DEBUG_WRAP(DebugMessage(DEBUG_PLUGIN,"NOT test failed\n"););
00308             }
00309             break;
00310             
00311         case FB_ALL:
00312             /* check if the rule bits are present in the packet */
00313             if((fb->frag_bits & (p->iph->ip_off&bitmask)) == fb->frag_bits)
00314             {
00315                 DEBUG_WRAP(DebugMessage(DEBUG_PLUGIN,"Got ALL bits match\n"););
00316                 return fp_list->next->OptTestFunc(p, otn, fp_list->next);
00317             }
00318             else
00319             {
00320                 DEBUG_WRAP(DebugMessage(DEBUG_PLUGIN,"ALL test failed\n"););
00321             }
00322             break;
00323             
00324         case FB_ANY:
00325             /* check if any of the rule bits match the bits in the packet */
00326             if((fb->frag_bits & (p->iph->ip_off&bitmask)) != 0)
00327             {
00328                 DEBUG_WRAP(DebugMessage(DEBUG_PLUGIN,"Got ANY bits match\n"););
00329                 return fp_list->next->OptTestFunc(p, otn, fp_list->next);
00330             }
00331             else
00332             {
00333                 DEBUG_WRAP(DebugMessage(DEBUG_PLUGIN,"ANY test failed\n"););
00334             }
00335             break;
00336     }
00337 
00338     /* if the test isn't successful, this function *must* return 0 */
00339     return 0;
00340 }
00341 
00342 
00343 /****************************************************************************
00344  * 
00345  * Function: SetupFragOffset()
00346  *
00347  * Purpose: Assign the keyword to the rules parser.
00348  *
00349  * Arguments: None.
00350  *
00351  * Returns: void function
00352  *
00353  ****************************************************************************/
00354 void SetupFragOffset(void)
00355 {
00356     /* map the keyword to an initialization/processing function */
00357     RegisterPlugin("fragoffset", FragOffsetInit);
00358 
00359     DEBUG_WRAP(DebugMessage(DEBUG_PLUGIN, "Plugin: FragOffset Setup\n"););
00360 }
00361 
00362 /****************************************************************************
00363  * 
00364  * Function: FragOffsetInit(char *, OptTreeNode *)
00365  *
00366  * Purpose: Initialize the detection function and parse the arguments.
00367  *
00368  * Arguments: data => rule arguments/data
00369  *            otn => pointer to the current rule option list node
00370  *            protocol => protocol that must be specified to use this plugin
00371  * 
00372  * Returns: void function
00373  *
00374  ****************************************************************************/
00375 void FragOffsetInit(char *data, OptTreeNode *otn, int protocol)
00376 {
00377     /* allocate the data structure and attach it to the
00378        rule's data struct list */
00379     otn->ds_list[PLUGIN_FRAG_OFFSET] = (FragOffsetData *) calloc(sizeof(FragOffsetData),
00380                                                                sizeof(char));
00381 
00382     /* this is where the keyword arguments are processed and placed into the 
00383        rule option's data structure */
00384     ParseFragOffset(data, otn);
00385 
00386     /* finally, attach the option's detection function to the rule's 
00387        detect function pointer list */
00388     AddOptFuncToList(CheckFragOffset, otn);
00389 }
00390 
00391 
00392 /****************************************************************************
00393  * 
00394  * Function: ParseFragOffset(char *, OptTreeNode *)
00395  *
00396  * Purpose: This is the function that is used to process the option keyword's
00397  *          arguments and attach them to the rule's data structures.
00398  *
00399  * Arguments: data => argument data
00400  *            otn => pointer to the current rule's OTN
00401  *
00402  * Returns: void function
00403  *
00404  ****************************************************************************/
00405 void ParseFragOffset(char *data, OptTreeNode *otn)
00406 {
00407     char *fptr;
00408 
00409     FragOffsetData *ds_ptr;  /* data struct pointer */
00410 
00411     /* set the ds pointer to make it easier to reference the option's
00412        particular data struct */
00413     ds_ptr = otn->ds_list[PLUGIN_FRAG_OFFSET];
00414 
00415     /* manipulate the option arguments here */
00416     fptr = data;
00417 
00418     while(isspace((u_char) *fptr))
00419     {
00420         fptr++;
00421     }
00422 
00423     if(strlen(fptr) == 0)
00424     {
00425         FatalError("[!] ERROR Line %s (%d): No arguments to the fragoffset keyword\n", file_name, file_line);
00426     }
00427 
00428     if(*fptr == '!')
00429     {
00430         ds_ptr->not_flag = 1;
00431         fptr++;
00432     }
00433 
00434     if(*fptr == '>')
00435     {
00436         ds_ptr->comparison_flag = GREATER_THAN; 
00437         fptr++;
00438     }
00439 
00440     if(*fptr == '<')
00441     {
00442         ds_ptr->comparison_flag = LESS_THAN; 
00443         fptr++;
00444     }
00445 
00446     if(isdigit((int)*fptr))
00447     {
00448         ds_ptr->offset = atoi(fptr);
00449     } else {
00450         FatalError("[!] ERROR Line %s (%d): Argument to fragoffset is not a number: %s\n",
00451                    file_name, file_line, fptr);
00452     }
00453 }
00454 
00455 /****************************************************************************
00456  * 
00457  * Function: CheckFragOffset(char *, OptTreeNode *)
00458  *
00459  * Purpose: Use this function to perform the particular detection routine
00460  *          that this rule keyword is supposed to encompass.
00461  *
00462  * Arguments: data => argument data
00463  *            otn => pointer to the current rule's OTN
00464  *
00465  * Returns: If the detection test fails, this function *must* return a zero!
00466  *          On success, it calls the next function in the detection list 
00467  *
00468  ****************************************************************************/
00469 int CheckFragOffset(Packet *p, struct _OptTreeNode *otn, OptFpList *fp_list)
00470 {
00471     FragOffsetData *ipd;  /* data struct pointer */
00472     int p_offset = p->frag_offset * 8;
00473     
00474     ipd = otn->ds_list[PLUGIN_FRAG_OFFSET];
00475 
00476     
00477 
00478 #ifdef DEBUG
00479     DebugMessage(DEBUG_PLUGIN,
00480                  "[!] Checking fragoffset %d against %d\n",
00481                  ipd->offset, p->frag_offset * 8);
00482 
00483     if(p->frag_flag)
00484     {
00485         DebugMessage(DEBUG_PLUGIN, "Frag Offset: 0x%04X   Frag Size: 0x%04X\n",
00486                      (p->frag_offset & 0x1FFF) * 8,
00487                      (ntohs(p->iph->ip_len) - p->frag_offset - IP_HEADER_LEN));
00488     }
00489 #endif
00490 
00491 
00492     if(!ipd->comparison_flag)
00493     {
00494         if((ipd->offset == p_offset) ^ ipd->not_flag)
00495         {
00496             return fp_list->next->OptTestFunc(p, otn, fp_list->next);
00497         }
00498         else
00499         {
00500             /* you can put debug comments here or not */
00501             DEBUG_WRAP(DebugMessage(DEBUG_PLUGIN,"No match\n"););
00502         }
00503     }
00504     else
00505     {
00506         if(ipd->comparison_flag == GREATER_THAN)
00507         {
00508             if(p_offset > ipd->offset)
00509             {
00510                 return fp_list->next->OptTestFunc(p, otn, fp_list->next);
00511             }
00512         }
00513         else
00514         {
00515             if(p_offset < ipd->offset)
00516             {
00517                 return fp_list->next->OptTestFunc(p, otn, fp_list->next);
00518             }
00519         }
00520     }
00521     
00522     /* if the test isn't successful, this function *must* return 0 */
00523     return 0;
00524 }

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