00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020
00021
00022
00023
00024
00025
00026
00027
00028
00029
00030
00031
00032
00033
00034
00035
00036
00037
00038
00039
00040
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
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
00108
00109
00110
00111
00112
00113
00114
00115
00116 void SetupFragBits(void)
00117 {
00118
00119 RegisterPlugin("fragbits", FragBitsInit);
00120
00121 DEBUG_WRAP(DebugMessage(DEBUG_PLUGIN, "Plugin: FragBits Setup\n"););
00122 }
00123
00124
00125
00126
00127
00128
00129
00130
00131
00132
00133
00134
00135
00136
00137
00138 void FragBitsInit(char *data, OptTreeNode *otn, int protocol)
00139 {
00140
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
00148
00149 otn->ds_list[PLUGIN_FRAG_BITS] = (FragBitsData *)
00150 SnortAlloc(sizeof(FragBitsData));
00151
00152
00153
00154 ParseFragBits(data, otn);
00155
00156
00157
00158
00159
00160 bitmask = htons(0xE000);
00161
00162
00163
00164 AddOptFuncToList(CheckFragBits, otn);
00165 }
00166
00167
00168
00169
00170
00171
00172
00173
00174
00175
00176
00177
00178
00179
00180
00181
00182 void ParseFragBits(char *data, OptTreeNode *otn)
00183 {
00184 char *fptr;
00185 char *fend;
00186 FragBitsData *ds_ptr;
00187
00188
00189
00190 ds_ptr = otn->ds_list[PLUGIN_FRAG_BITS];
00191
00192
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;
00208
00209 while(fptr < fend)
00210 {
00211 switch((*fptr&0xFF))
00212 {
00213 case 'd':
00214 case 'D':
00215 ds_ptr->frag_bits |= FB_DF;
00216 break;
00217
00218 case 'm':
00219 case 'M':
00220 ds_ptr->frag_bits |= FB_MF;
00221 break;
00222
00223 case 'r':
00224 case 'R':
00225 ds_ptr->frag_bits |= FB_RB;
00226 break;
00227
00228 case '!':
00229 ds_ptr->mode = FB_NOT;
00230 break;
00231
00232 case '*':
00233 ds_ptr->mode = FB_ANY;
00234 break;
00235
00236 case '+':
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
00250 ds_ptr->frag_bits = htons(ds_ptr->frag_bits);
00251
00252
00253 }
00254
00255
00256
00257
00258
00259
00260
00261
00262
00263
00264
00265
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
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
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
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
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
00339 return 0;
00340 }
00341
00342
00343
00344
00345
00346
00347
00348
00349
00350
00351
00352
00353
00354 void SetupFragOffset(void)
00355 {
00356
00357 RegisterPlugin("fragoffset", FragOffsetInit);
00358
00359 DEBUG_WRAP(DebugMessage(DEBUG_PLUGIN, "Plugin: FragOffset Setup\n"););
00360 }
00361
00362
00363
00364
00365
00366
00367
00368
00369
00370
00371
00372
00373
00374
00375 void FragOffsetInit(char *data, OptTreeNode *otn, int protocol)
00376 {
00377
00378
00379 otn->ds_list[PLUGIN_FRAG_OFFSET] = (FragOffsetData *) calloc(sizeof(FragOffsetData),
00380 sizeof(char));
00381
00382
00383
00384 ParseFragOffset(data, otn);
00385
00386
00387
00388 AddOptFuncToList(CheckFragOffset, otn);
00389 }
00390
00391
00392
00393
00394
00395
00396
00397
00398
00399
00400
00401
00402
00403
00404
00405 void ParseFragOffset(char *data, OptTreeNode *otn)
00406 {
00407 char *fptr;
00408
00409 FragOffsetData *ds_ptr;
00410
00411
00412
00413 ds_ptr = otn->ds_list[PLUGIN_FRAG_OFFSET];
00414
00415
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
00458
00459
00460
00461
00462
00463
00464
00465
00466
00467
00468
00469 int CheckFragOffset(Packet *p, struct _OptTreeNode *otn, OptFpList *fp_list)
00470 {
00471 FragOffsetData *ipd;
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
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
00523 return 0;
00524 }