00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020 #include <errno.h>
00021
00022 #ifdef HAVE_CONFIG_H
00023 #include "config.h"
00024 #endif
00025
00026 #ifdef HAVE_STRINGS_H
00027 #include <strings.h>
00028 #endif
00029
00030 #ifdef DEBUG
00031 #include <assert.h>
00032 #endif
00033
00034 #include "sp_pattern_match.h"
00035 #include "bounds.h"
00036 #include "rules.h"
00037 #include "plugbase.h"
00038 #include "debug.h"
00039 #include "mstring.h"
00040 #include "util.h"
00041 #include "parser.h"
00042 #include "plugin_enum.h"
00043 #include "checksum.h"
00044 #include "inline.h"
00045
00046 static void PayloadSearchInit(char *, OptTreeNode *, int);
00047 static void PayloadSearchListInit(char *, OptTreeNode *, int);
00048 static void ParseContentListFile(char *, OptTreeNode *, int);
00049 static void PayloadSearchUri(char *, OptTreeNode *, int);
00050 static void ParsePattern(char *, OptTreeNode *, int);
00051 static int CheckANDPatternMatch(Packet *, struct _OptTreeNode *, OptFpList *);
00052 static int CheckORPatternMatch(Packet *, struct _OptTreeNode *, OptFpList *);
00053 static int CheckUriPatternMatch(Packet *, struct _OptTreeNode *, OptFpList *);
00054 static void PayloadSearchOffset(char *, OptTreeNode *, int);
00055 static void PayloadSearchDepth(char *, OptTreeNode *, int);
00056 static void PayloadSearchNocase(char *, OptTreeNode *, int);
00057 static void PayloadSearchRegex(char *, OptTreeNode *, int);
00058 static void PayloadSearchDistance(char *, OptTreeNode *, int);
00059 static void PayloadSearchWithin(char *, OptTreeNode *, int);
00060 static void PayloadSearchRawbytes(char *, OptTreeNode *, int);
00061 static void PayloadReplaceInit(char *, OptTreeNode *, int);
00062 static PatternMatchData * ParseReplacePattern(char *, OptTreeNode *);
00063 int PayloadReplace(Packet *, struct _OptTreeNode *, OptFpList *, int
00064 depth);
00065 static int uniSearchReal(char *data, int dlen, PatternMatchData *pmd, int nocase);
00066
00067 static PatternMatchData * NewNode(OptTreeNode *, int);
00068 void PayloadSearchCompile();
00069
00070 int list_file_line;
00071 int lastType = PLUGIN_PATTERN_MATCH;
00072 u_int8_t *doe_ptr;
00073
00074 int detect_depth;
00075
00076 extern HttpUri UriBufs[URI_COUNT];
00077
00078 extern u_int8_t DecodeBuffer[DECODE_BLEN];
00079
00080 extern char *file_name;
00081 extern int file_line;
00082
00083
00084 void SetupPatternMatch()
00085 {
00086 RegisterPlugin("content", PayloadSearchInit);
00087 RegisterPlugin("content-list", PayloadSearchListInit);
00088 RegisterPlugin("offset", PayloadSearchOffset);
00089 RegisterPlugin("depth", PayloadSearchDepth);
00090 RegisterPlugin("nocase", PayloadSearchNocase);
00091 RegisterPlugin("rawbytes", PayloadSearchRawbytes);
00092 RegisterPlugin("regex", PayloadSearchRegex);
00093 RegisterPlugin("uricontent", PayloadSearchUri);
00094 RegisterPlugin("distance", PayloadSearchDistance);
00095 RegisterPlugin("within", PayloadSearchWithin);
00096 RegisterPlugin("replace", PayloadReplaceInit);
00097
00098 DEBUG_WRAP(DebugMessage(DEBUG_PATTERN_MATCH,
00099 "Plugin: PatternMatch Initialized!\n"););
00100 }
00101
00102 void PayloadReplaceInit(char *data, OptTreeNode * otn, int protocol)
00103 {
00104 PatternMatchData *idx;
00105 PatternMatchData *test_idx;
00106
00107 if(!InlineMode())
00108 return;
00109
00110 idx = (PatternMatchData *) otn->ds_list[PLUGIN_PATTERN_MATCH];
00111
00112 if(idx == NULL)
00113 {
00114 FatalError("ERROR %s Line %d => Please place \"content\" rules "
00115 "before depth, nocase, replace or offset modifiers.\n",
00116 file_name, file_line);
00117 }
00118
00119 test_idx = ParseReplacePattern(data, otn);
00120 #ifdef DEBUG
00121 printf("idx (%p) pattern_size (%d) replace_size (%d)\n", test_idx,
00122 test_idx->pattern_size, test_idx->replace_size);
00123 #endif
00124 if (test_idx && test_idx->pattern_size != test_idx->replace_size)
00125 {
00126 FatalError("ERROR %s Line %d => The length of the replacement "
00127 "string must be the same length as the content string.\n",
00128 file_name, file_line);
00129 }
00130
00131 #ifdef DEBUG
00132 printf("PayLoadReplaceInit Added to rule!\n");
00133 #endif
00134 }
00135
00136
00137
00138
00139
00140
00141
00142 PatternMatchData * ParseReplacePattern(char *rule, OptTreeNode * otn)
00143 {
00144 unsigned char tmp_buf[2048];
00145
00146
00147 char *start_ptr;
00148 char *end_ptr;
00149 char *idx;
00150 char *dummy_idx;
00151 char *dummy_end;
00152 char hex_buf[3];
00153 u_int dummy_size = 0;
00154 int size;
00155 int hexmode = 0;
00156 int hexsize = 0;
00157 int pending = 0;
00158 int cnt = 0;
00159 int literal = 0;
00160 int exception_flag = 0;
00161 PatternMatchData *ds_idx;
00162
00163
00164 bzero(tmp_buf, 2048);
00165
00166 while(isspace((int)*rule))
00167 rule++;
00168
00169 if(*rule == '!')
00170 {
00171 exception_flag = 1;
00172 }
00173
00174
00175 start_ptr = index(rule, '"');
00176
00177 if(start_ptr == NULL)
00178 {
00179 FatalError("ERROR %s Line %d => Replace data needs to be "
00180 "enclosed in quotation marks (\")!\n",
00181 file_name, file_line);
00182 }
00183
00184
00185 start_ptr++;
00186
00187
00188 end_ptr = strrchr(start_ptr, '"');
00189
00190 if(end_ptr == NULL)
00191 {
00192 FatalError("ERROR %s Line %d => Replace data needs to be enclosed "
00193 "in quotation marks (\")!\n", file_name, file_line);
00194 }
00195
00196
00197 *end_ptr = '\0';
00198
00199
00200 size = end_ptr - start_ptr;
00201
00202
00203 if(size <= 0)
00204 {
00205 FatalError("ERROR %s Line %d => Bad pattern length!\n",
00206 file_name, file_line);
00207 }
00208
00209 idx = start_ptr;
00210
00211
00212 dummy_idx = tmp_buf;
00213 dummy_end = (dummy_idx + size);
00214
00215
00216 bzero(hex_buf, 3);
00217 memset(hex_buf, '0', 2);
00218
00219
00220 while(idx < end_ptr)
00221 {
00222 DEBUG_WRAP(DebugMessage(DEBUG_PARSER, "processing char: %c\n", *idx););
00223
00224 switch(*idx)
00225 {
00226 case '|':
00227
00228 DEBUG_WRAP(DebugMessage(DEBUG_PARSER, "Got bar... "););
00229
00230 if(!literal)
00231 {
00232
00233 DEBUG_WRAP(DebugMessage(DEBUG_PARSER,
00234 "not in literal mode... "););
00235
00236 if(!hexmode)
00237 {
00238 DEBUG_WRAP(DebugMessage(DEBUG_PARSER,
00239 "Entering hexmode\n"););
00240
00241 hexmode = 1;
00242 }
00243 else
00244 {
00245
00246 DEBUG_WRAP(DebugMessage(DEBUG_PARSER,
00247 "Exiting hexmode\n"););
00248
00249 hexmode = 0;
00250 pending = 0;
00251 }
00252
00253 if(hexmode)
00254 hexsize = 0;
00255 }
00256 else
00257 {
00258
00259 DEBUG_WRAP(DebugMessage(DEBUG_PARSER,
00260 "literal set, Clearing\n"););
00261
00262 literal = 0;
00263 tmp_buf[dummy_size] = start_ptr[cnt];
00264 dummy_size++;
00265 }
00266
00267 break;
00268
00269 case '\\':
00270
00271 DEBUG_WRAP(DebugMessage(DEBUG_PARSER, "Got literal char... "););
00272
00273 if(!literal)
00274 {
00275 DEBUG_WRAP(DebugMessage(DEBUG_PARSER,
00276 "Setting literal\n"););
00277
00278 literal = 1;
00279 }
00280 else
00281 {
00282 DEBUG_WRAP(DebugMessage(DEBUG_PARSER,
00283 "Clearing literal\n"););
00284
00285 tmp_buf[dummy_size] = start_ptr[cnt];
00286 literal = 0;
00287 dummy_size++;
00288 }
00289 break;
00290
00291 default:
00292 if(hexmode)
00293 {
00294 if(isxdigit((int) *idx))
00295 {
00296 hexsize++;
00297
00298 if(!pending)
00299 {
00300 hex_buf[0] = *idx;
00301 pending++;
00302 }
00303 else
00304 {
00305 hex_buf[1] = *idx;
00306 pending--;
00307
00308 if(dummy_idx < dummy_end)
00309 {
00310 tmp_buf[dummy_size] = (u_char)
00311 strtol(hex_buf, (char **) NULL, 16)&0xFF;
00312
00313 dummy_size++;
00314 bzero(hex_buf, 3);
00315 memset(hex_buf, '0', 2);
00316 }
00317 else
00318 {
00319 FatalError("ERROR => ParsePattern() dummy "
00320 "buffer overflow, make a smaller "
00321 "pattern please! (Max size = 2048)\n");
00322 }
00323 }
00324 }
00325 else
00326 {
00327 if(*idx != ' ')
00328 {
00329 FatalError("ERROR Line %d => What is this "
00330 "\"%c\"(0x%X) doing in your binary "
00331 "buffer? Valid hex values only please! "
00332 "(0x0 -0xF) Position: %d\n",
00333 file_line, (char) *idx, (char) *idx, cnt);
00334 }
00335 }
00336 }
00337 else
00338 {
00339 if(*idx >= 0x1F && *idx <= 0x7e)
00340 {
00341 if(dummy_idx < dummy_end)
00342 {
00343 tmp_buf[dummy_size] = start_ptr[cnt];
00344 dummy_size++;
00345 }
00346 else
00347 {
00348 FatalError("ERROR Line %d=> ParsePattern() dummy "
00349 "buffer overflow!\n", file_line);
00350 }
00351
00352 if(literal)
00353 {
00354 literal = 0;
00355 }
00356 }
00357 else
00358 {
00359 if(literal)
00360 {
00361 tmp_buf[dummy_size] = start_ptr[cnt];
00362 dummy_size++;
00363
00364 DEBUG_WRAP(DebugMessage(DEBUG_PARSER,
00365 "Clearing literal\n"););
00366
00367 literal = 0;
00368 }
00369 else
00370 {
00371 FatalError("%s(%d)=> character value out "
00372 "of range, only hex characters allowed in binary content buffers\n",
00373 file_name, file_line);
00374 }
00375 }
00376 }
00377
00378 break;
00379
00380 }
00381
00382 dummy_idx++;
00383 idx++;
00384 cnt++;
00385 }
00386
00387
00388
00389
00390 if (literal) {
00391 FatalError("%s(%d)=> backslash escape is not "
00392 "completed\n", file_name, file_line);
00393 }
00394 if (hexmode) {
00395 FatalError("%s(%d)=> hexmode is not "
00396 "completed\n", file_name, file_line);
00397 }
00398 ds_idx = (PatternMatchData *) otn->ds_list[PLUGIN_PATTERN_MATCH];
00399
00400 while(ds_idx->next != NULL)
00401 ds_idx = ds_idx->next;
00402
00403 if((ds_idx->replace_buf = (char *) calloc(dummy_size+1,
00404 sizeof(char))) == NULL)
00405 {
00406 FatalError("ERROR => ParsePattern() pattern_buf malloc filed!\n");
00407 }
00408
00409
00410 SafeMemcpy(ds_idx->replace_buf, tmp_buf, dummy_size,
00411 ds_idx->replace_buf, (ds_idx->replace_buf+dummy_size+1));
00412
00413 ds_idx->replace_size = dummy_size;
00414
00415 DEBUG_WRAP(DebugMessage(DEBUG_PARSER,
00416 "ds_idx (%p) replace_size(%d) replace_buf(%s)\n", ds_idx,
00417 ds_idx->replace_size, ds_idx->replace_buf););
00418
00419 return ds_idx;
00420 }
00421
00422 int PayloadReplace(Packet *p, struct _OptTreeNode *otn,
00423 OptFpList *fp_list, int depth)
00424 {
00425 struct pseudoheader
00426 {
00427 u_int32_t sip, dip;
00428 u_int8_t zero;
00429 u_int8_t protocol;
00430 u_int16_t len;
00431 };
00432
00433 PatternMatchData *idx;
00434 struct pseudoheader ph;
00435 unsigned int ip_len;
00436 unsigned int hlen;
00437
00438
00439 idx = (PatternMatchData *)fp_list->context;
00440
00441 if (depth >= 0)
00442 {
00443
00444 SafeMemcpy( (p->data + depth), idx->replace_buf, strlen(idx->replace_buf),
00445 p->data, (p->data + p->dsize + 1) );
00446
00447 #ifdef GIDS
00448 InlineReplace();
00449 #endif
00450
00451
00452 p->iph->ip_csum=0;
00453 hlen = IP_HLEN(p->iph) << 2;
00454 ip_len=ntohs(p->iph->ip_len);
00455 ip_len -= hlen;
00456 p->iph->ip_csum = in_chksum_ip((u_short *)p->iph, hlen);
00457
00458 if (p->tcph)
00459 {
00460 p->tcph->th_sum = 0;
00461 ph.sip = (u_int32_t)(p->iph->ip_src.s_addr);
00462 ph.dip = (u_int32_t)(p->iph->ip_dst.s_addr);
00463 ph.zero = 0;
00464 ph.protocol = p->iph->ip_proto;
00465 ph.len = htons((u_short)ip_len);
00466 p->tcph->th_sum = in_chksum_tcp((u_short *)&ph,
00467 (u_short *)(p->tcph), ip_len);
00468 }
00469 else if (p->udph)
00470 {
00471 p->udph->uh_chk = 0;
00472 ph.sip = (u_int32_t)(p->iph->ip_src.s_addr);
00473 ph.dip = (u_int32_t)(p->iph->ip_dst.s_addr);
00474 ph.zero = 0;
00475 ph.protocol = p->iph->ip_proto;
00476 ph.len = htons((u_short)ip_len);
00477 p->udph->uh_chk = in_chksum_udp((u_short *)&ph,
00478 (u_short *)(p->udph), ip_len);
00479 }
00480 else if (p->icmph)
00481 {
00482 p->icmph->csum = 0;
00483 ph.sip = (u_int32_t)(p->iph->ip_src.s_addr);
00484 ph.dip = (u_int32_t)(p->iph->ip_dst.s_addr);
00485 ph.zero = 0;
00486 ph.protocol = p->iph->ip_proto;
00487 ph.len = htons((u_short)ip_len);
00488 p->icmph->csum = in_chksum_icmp((u_int16_t *)(p->icmph), ip_len);
00489 }
00490 }
00491
00492 return 1;
00493 }
00494
00495 static inline int computeDepth(int dlen, PatternMatchData * pmd)
00496 {
00497
00498 if((pmd->depth + pmd->offset) > dlen)
00499 {
00500
00501 int sub_depth = dlen - pmd->offset;
00502
00503 if((sub_depth > 0) && (sub_depth >= (int)pmd->pattern_size))
00504 {
00505 return sub_depth;
00506 }
00507 else
00508 {
00509 DEBUG_WRAP(DebugMessage(DEBUG_PATTERN_MATCH,
00510 "Pattern Match failed -- sub_depth: %d < "
00511 "(int)pmd->pattern_size: %d!\n",
00512 sub_depth, (int)pmd->pattern_size););
00513
00514 return -1;
00515 }
00516 }
00517 else
00518 {
00519 if(pmd->depth && (dlen - pmd->offset > pmd->depth))
00520 {
00521 return pmd->depth;
00522 }
00523 else
00524 {
00525 return dlen - pmd->offset;
00526 }
00527 }
00528 }
00529
00530
00531
00532
00533
00534
00535
00536
00537
00538
00539
00540 static inline int computeWithin(int dlen, PatternMatchData *pmd)
00541 {
00542
00543 if(pmd->within > dlen)
00544 {
00545
00546
00547
00548
00549
00550 if(dlen >= (int)pmd->pattern_size)
00551 {
00552
00553 return dlen;
00554 }
00555 else
00556 {
00557
00558 return -1;
00559 }
00560 }
00561
00562
00563 return pmd->within;
00564 }
00565
00566
00567 static int uniSearchREG(char * data, int dlen, PatternMatchData * pmd)
00568 {
00569 int depth = computeDepth(dlen, pmd);
00570
00571
00572
00573 int success = 0;
00574
00575 if (depth < 0)
00576 return 0;
00577
00578
00579
00580
00581
00582
00583
00584 return success;
00585 }
00586
00587
00588
00589
00590
00591
00592
00593
00594
00595
00596
00597
00598 static int uniSearch(char *data, int dlen, PatternMatchData *pmd)
00599 {
00600 return uniSearchReal(data, dlen, pmd, 0);
00601 }
00602
00603
00604
00605
00606
00607
00608
00609
00610
00611 static int uniSearchCI(char *data, int dlen, PatternMatchData *pmd)
00612 {
00613 return uniSearchReal(data, dlen, pmd, 1);
00614 }
00615
00616
00617
00618
00619
00620
00621
00622
00623
00624
00625
00626 static int uniSearchReal(char *data, int dlen, PatternMatchData *pmd, int nocase)
00627 {
00628
00629
00630
00631
00632 int depth = dlen;
00633 int old_depth = dlen;
00634 int success = 0;
00635 char *start_ptr = data;
00636 char *end_ptr = data + dlen;
00637 char *base_ptr = start_ptr;
00638
00639 DEBUG_WRAP(char *hexbuf;);
00640
00641
00642 if(pmd->use_doe != 1)
00643 {
00644 DEBUG_WRAP(DebugMessage(DEBUG_PATTERN_MATCH,
00645 "NOT Using Doe Ptr\n"););
00646 doe_ptr = NULL;
00647 }
00648
00649
00650 if(doe_ptr)
00651 {
00652 DEBUG_WRAP(DebugMessage(DEBUG_PATTERN_MATCH,
00653 "Using Doe Ptr\n"););
00654
00655 base_ptr = doe_ptr;
00656 depth = dlen - ((char *) doe_ptr - data);
00657 }
00658 else
00659 {
00660 base_ptr = start_ptr;
00661 depth = dlen;
00662 }
00663
00664
00665 if(pmd->distance)
00666 {
00667
00668 base_ptr += pmd->distance;
00669 depth -= pmd->distance;
00670 }
00671 else
00672 {
00673 base_ptr += pmd->offset;
00674 depth -= pmd->offset;
00675 }
00676
00677 if(pmd->within != 0)
00678 {
00679
00680
00681
00682
00683
00684
00685
00686 old_depth = depth;
00687
00688 depth = computeWithin(depth, pmd);
00689
00690 DEBUG_WRAP(DebugMessage(DEBUG_PATTERN_MATCH, "Changing Depth from %d to %d\n", old_depth, depth););
00691 }
00692
00693
00694 if(!inBounds(start_ptr, end_ptr, base_ptr))
00695 {
00696
00697 DEBUG_WRAP(DebugMessage(DEBUG_PATTERN_MATCH,
00698 "returning because base_ptr"
00699 " is out of bounds start_ptr: %p end: %p base: %p\n",
00700 start_ptr, end_ptr, base_ptr););
00701 return 0;
00702 }
00703
00704 if(depth < 0)
00705 {
00706 DEBUG_WRAP(DebugMessage(DEBUG_PATTERN_MATCH,
00707 "returning because depth is negative (%d)\n",
00708 depth););
00709 return 0;
00710 }
00711
00712 if(depth > dlen)
00713 {
00714
00715
00716
00717 depth = dlen;
00718 }
00719
00720 if((pmd->depth > 0) && (depth > pmd->depth))
00721 {
00722 DEBUG_WRAP(DebugMessage(DEBUG_PATTERN_MATCH,
00723 "Setting new depth to %d from %d\n",
00724 pmd->depth, depth););
00725
00726 depth = pmd->depth;
00727 }
00728
00729
00730 if(!inBounds(start_ptr, end_ptr, base_ptr + depth - 1))
00731 {
00732 DEBUG_WRAP(DebugMessage(DEBUG_PATTERN_MATCH,
00733 "returning because base_ptr + depth - 1"
00734 " is out of bounds start_ptr: %p end: %p base: %p\n",
00735 start_ptr, end_ptr, base_ptr););
00736 return 0;
00737 }
00738
00739 #ifdef DEBUG
00740 assert(depth <= old_depth);
00741
00742 DebugMessage(DEBUG_PATTERN_MATCH, "uniSearchReal:\n ");
00743
00744 hexbuf = hex(pmd->pattern_buf, pmd->pattern_size);
00745 DebugMessage(DEBUG_PATTERN_MATCH, " p->data: %p\n doe_ptr: %p\n "
00746 "base_ptr: %p\n depth: %d\n searching for: %s\n",
00747 data, doe_ptr, base_ptr, depth, hexbuf);
00748 free(hexbuf);
00749 #endif
00750
00751 if(nocase)
00752 {
00753 success = mSearchCI(base_ptr, depth,
00754 pmd->pattern_buf,
00755 pmd->pattern_size,
00756 pmd->skip_stride,
00757 pmd->shift_stride);
00758 }
00759 else
00760 {
00761 success = mSearch(base_ptr, depth,
00762 pmd->pattern_buf,
00763 pmd->pattern_size,
00764 pmd->skip_stride,
00765 pmd->shift_stride);
00766 }
00767
00768
00769 #ifdef DEBUG
00770 if(success)
00771 {
00772 DebugMessage(DEBUG_PATTERN_MATCH, "matched, doe_ptr: %p (%d)\n",
00773 doe_ptr, ((char *)doe_ptr - data));
00774 }
00775 #endif
00776
00777 return success;
00778 }
00779
00780
00781 static void make_precomp(PatternMatchData * idx)
00782 {
00783 free(idx->skip_stride);
00784 free(idx->shift_stride);
00785
00786 idx->skip_stride = make_skip(idx->pattern_buf, idx->pattern_size);
00787
00788 idx->shift_stride = make_shift(idx->pattern_buf, idx->pattern_size);
00789 }
00790
00791 void PayloadSearchListInit(char *data, OptTreeNode * otn, int protocol)
00792 {
00793 char *sptr;
00794 char *eptr;
00795
00796 lastType = PLUGIN_PATTERN_MATCH_OR;
00797
00798 DEBUG_WRAP(DebugMessage(DEBUG_PATTERN_MATCH, "In PayloadSearchListInit()\n"););
00799
00800
00801 while(isspace((int) *data))
00802 data++;
00803
00804
00805 sptr = index(data, '"');
00806 eptr = strrchr(data, '"');
00807
00808 if(sptr != NULL && eptr != NULL)
00809 {
00810
00811 sptr++;
00812
00813
00814 *eptr = 0;
00815 }
00816 else
00817 {
00818 sptr = data;
00819 }
00820
00821
00822 ParseContentListFile(sptr, otn, protocol);
00823
00824
00825
00826 AddOptFuncToList(CheckORPatternMatch, otn);
00827
00828 return;
00829 }
00830
00831
00832 void PayloadSearchInit(char *data, OptTreeNode * otn, int protocol)
00833 {
00834 OptFpList *fpl;
00835 PatternMatchData *pmd;
00836
00837 lastType = PLUGIN_PATTERN_MATCH;
00838
00839 DEBUG_WRAP(DebugMessage(DEBUG_PATTERN_MATCH, "In PayloadSearchInit()\n"););
00840
00841
00842 pmd = NewNode(otn, PLUGIN_PATTERN_MATCH);
00843
00844
00845 ParsePattern(data, otn, PLUGIN_PATTERN_MATCH);
00846
00847
00848 fpl = AddOptFuncToList(CheckANDPatternMatch, otn);
00849
00850 fpl->context = pmd;
00851
00852 DEBUG_WRAP(DebugMessage(DEBUG_PATTERN_MATCH,
00853 "OTN function PatternMatch Added to rule!\n"););
00854 }
00855
00856
00857
00858 void PayloadSearchUri(char *data, OptTreeNode * otn, int protocol)
00859 {
00860 PatternMatchData * pmd;
00861 OptFpList *fpl;
00862
00863 lastType = PLUGIN_PATTERN_MATCH_URI;
00864 DEBUG_WRAP(DebugMessage(DEBUG_PATTERN_MATCH, "In PayloadSearchUri()\n"););
00865
00866
00867 pmd = NewNode(otn, PLUGIN_PATTERN_MATCH_URI);
00868
00869
00870 ParsePattern(data, otn, PLUGIN_PATTERN_MATCH_URI);
00871
00872 #ifdef PATTERN_FAST
00873 pmd->search = uniSearch;
00874 make_precomp(pmd);
00875 #endif
00876
00877
00878 fpl = AddOptFuncToList(CheckUriPatternMatch, otn);
00879
00880 fpl->context = pmd;
00881
00882 DEBUG_WRAP(DebugMessage(DEBUG_PATTERN_MATCH,
00883 "OTN function PatternMatch Added to rule!\n"););
00884 }
00885
00886
00887
00888
00889 void PayloadSearchOffset(char *data, OptTreeNode * otn, int protocol)
00890 {
00891 PatternMatchData *idx;
00892
00893 DEBUG_WRAP(DebugMessage(DEBUG_PATTERN_MATCH, "In PayloadSearch()\n"););
00894
00895 idx = otn->ds_list[lastType];
00896
00897 if(idx == NULL)
00898 {
00899 FatalError("%s(%d) => Please place \"content\" rules before "
00900 "depth, nocase or offset modifiers.\n", file_name, file_line);
00901 }
00902
00903 while(idx->next != NULL)
00904 idx = idx->next;
00905
00906 while(isspace((int) *data))
00907 data++;
00908
00909 errno = 0;
00910
00911 idx->offset = strtol(data, NULL, 10);
00912
00913 if(errno == ERANGE)
00914 {
00915 FatalError("ERROR %s Line %d => Range problem on offset value\n",
00916 file_name, file_line);
00917 }
00918
00919 if(idx->offset > 65535 || idx->offset < -65535)
00920 {
00921 FatalError("ERROR %s Line %d => Offset greater than max Ipv4 "
00922 "packet size\n", file_name, file_line);
00923 }
00924
00925 DEBUG_WRAP(DebugMessage(DEBUG_PARSER, "Pattern offset = %d\n",
00926 idx->offset););
00927
00928 return;
00929 }
00930
00931
00932
00933 void PayloadSearchDepth(char *data, OptTreeNode * otn, int protocol)
00934 {
00935 PatternMatchData *idx;
00936
00937 idx = (PatternMatchData *) otn->ds_list[lastType];
00938
00939 if(idx == NULL)
00940 {
00941 FatalError("ERROR %s Line %d => Please place \"content\" rules "
00942 "before depth, nocase or offset modifiers.\n",
00943 file_name, file_line);
00944 }
00945
00946 while(idx->next != NULL)
00947 idx = idx->next;
00948
00949 while(isspace((int) *data))
00950 data++;
00951
00952 errno = 0;
00953
00954 idx->depth = strtol(data, NULL, 10);
00955
00956 if(errno == ERANGE)
00957 {
00958 FatalError("ERROR %s Line %d => Range problem on depth value\n",
00959 file_name, file_line);
00960 }
00961
00962 if(idx->depth > 65535 || idx->depth < -65535)
00963 {
00964 FatalError("ERROR %s Line %d => Depth greater than max Ipv4 "
00965 "packet size\n", file_name, file_line);
00966 }
00967
00968
00969 if(idx->depth != 0 && idx->depth < (int)idx->pattern_size)
00970 {
00971 FatalError("%s(%d) => The depth(%d) is less than the size of the content(%u)!\n",
00972 file_name, file_line, idx->depth, idx->pattern_size);
00973 }
00974
00975
00976 DEBUG_WRAP(DebugMessage(DEBUG_PATTERN_MATCH, "Pattern depth = %d\n",
00977 idx->depth););
00978
00979 return;
00980 }
00981
00982 void PayloadSearchNocase(char *data, OptTreeNode * otn, int protocol)
00983 {
00984 PatternMatchData *idx;
00985 int i;
00986
00987 idx = (PatternMatchData *) otn->ds_list[lastType];
00988
00989 if(idx == NULL)
00990 {
00991 FatalError("(%s)%d => Please place \"content\" rules before"
00992 " depth, nocase or offset modifiers.\n", file_name, file_line);
00993 }
00994 while(idx->next != NULL)
00995 idx = idx->next;
00996
00997 i = idx->pattern_size;
00998
00999 while(--i >= 0)
01000 idx->pattern_buf[i] = toupper((unsigned char) idx->pattern_buf[i]);
01001
01002 idx->nocase = 1;
01003
01004 #ifdef PATTERN_FAST
01005 idx->search = setSearch;
01006 #else
01007 idx->search = uniSearchCI;
01008 make_precomp(idx);
01009 #endif
01010
01011
01012 return;
01013 }
01014
01015 void PayloadSearchRawbytes(char *data, OptTreeNode * otn, int protocol)
01016 {
01017 PatternMatchData *idx;
01018
01019 idx = (PatternMatchData *) otn->ds_list[lastType];
01020
01021 if(idx == NULL)
01022 {
01023 FatalError("ERROR Line %d => Please place \"content\" rules before"
01024 " rawbytes, depth, nocase or offset modifiers.\n", file_line);
01025 }
01026 while(idx->next != NULL)
01027 idx = idx->next;
01028
01029
01030
01031 idx->rawbytes = 1;
01032 return;
01033 }
01034
01035 void PayloadSearchDistance(char *data, OptTreeNode *otn, int protocol)
01036 {
01037 PatternMatchData *idx;
01038
01039 idx = (PatternMatchData *) otn->ds_list[lastType];
01040
01041 if(idx == NULL)
01042 {
01043 FatalError("Error %s(%d) => Distance without context, please place "
01044 "\"content\" keywords before distance modifiers\n", file_name,
01045 file_line);
01046 }
01047
01048 while(idx->next != NULL)
01049 idx = idx->next;
01050
01051 while(isspace((int) *data))
01052 data++;
01053
01054
01055 errno = 0;
01056
01057 idx->distance = strtol(data, NULL, 10);
01058
01059 if(errno == ERANGE)
01060 {
01061 FatalError("ERROR %s Line %d => Range problem on distance value\n",
01062 file_name, file_line);
01063 }
01064
01065 if(idx->distance > 65535 || idx->distance < -65535)
01066 {
01067 FatalError("ERROR %s Line %d => Distance greater than max Ipv4 "
01068 "packet size\n", file_name, file_line);
01069 }
01070
01071 DEBUG_WRAP(DebugMessage(DEBUG_PATTERN_MATCH, "Pattern distance = %d\n",
01072 idx->distance););
01073
01074
01075 if(!SetUseDoePtr(otn))
01076 {
01077 FatalError("%s Line %d => Unable to initialize doe_ptr\n",
01078 file_name, file_line);
01079 }
01080
01081 return;
01082 }
01083
01084
01085 void PayloadSearchWithin(char *data, OptTreeNode *otn, int protocol)
01086 {
01087 PatternMatchData *idx;
01088
01089 idx = (PatternMatchData *) otn->ds_list[lastType];
01090
01091 if(idx == NULL)
01092 {
01093 FatalError("Error %s(%d) => Distance without context, please place "
01094 "\"content\" keywords before distance modifiers\n", file_name,
01095 file_line);
01096 }
01097
01098 while(idx->next != NULL)
01099 idx = idx->next;
01100
01101 while(isspace((int) *data))
01102 data++;
01103
01104 errno = 0;
01105
01106 idx->within = strtol(data, NULL, 10);
01107
01108 if(errno == ERANGE)
01109 {
01110 FatalError("ERROR %s Line %d => Range problem on within value\n",
01111 file_name, file_line);
01112 }
01113
01114 if(idx->within > 65535 || idx->within < -65535)
01115 {
01116 FatalError("ERROR %s Line %d => Within greater than max Ipv4 "
01117 "packet size\n", file_name, file_line);
01118 }
01119
01120 DEBUG_WRAP(DebugMessage(DEBUG_PATTERN_MATCH, "Pattern within = %d\n",
01121 idx->within););
01122
01123
01124 if(!SetUseDoePtr(otn))
01125 {
01126 FatalError("%s Line %d => Unable to initialize doe_ptr\n",
01127 file_name, file_line);
01128 }
01129
01130 return;
01131 }
01132
01133
01134
01135 void PayloadSearchRegex(char *data, OptTreeNode * otn, int protocol)
01136 {
01137 PatternMatchData *idx;
01138 int i;
01139
01140 FatalError("%s(%d) => Sorry, regex isn't supported at this time. "
01141 "This isn't new.", file_name,file_line);
01142
01143 idx = (PatternMatchData *) otn->ds_list[lastType];
01144
01145 if(idx == NULL)
01146 {
01147 FatalError("%s(%d) => Please place \"content\" rules "
01148 "before regex modifiers.\n", file_name, file_line);
01149 }
01150
01151 while(idx->next != NULL)
01152 idx = idx->next;
01153
01154 idx->search = uniSearchREG;
01155
01156 i = idx->pattern_size;
01157
01158 make_precomp(idx);
01159
01160 return;
01161 }
01162
01163
01164
01165
01166 static PatternMatchData * NewNode(OptTreeNode * otn, int type)
01167 {
01168 PatternMatchData *idx;
01169
01170 idx = (PatternMatchData *) otn->ds_list[type];
01171
01172 if(idx == NULL)
01173 {
01174 if((otn->ds_list[type] =
01175 (PatternMatchData *) calloc(sizeof(PatternMatchData),
01176 sizeof(char))) == NULL)
01177 {
01178 FatalError("sp_pattern_match NewNode() calloc failed!\n");
01179 }
01180
01181 return otn->ds_list[type];
01182 }
01183 else
01184 {
01185 idx = otn->ds_list[type];
01186
01187 while(idx->next != NULL)
01188 idx = idx->next;
01189
01190 if((idx->next = (PatternMatchData *)
01191 calloc(sizeof(PatternMatchData), sizeof(char))) == NULL)
01192 {
01193 FatalError("sp_pattern_match NewNode() calloc failed!\n");
01194 }
01195
01196 return idx->next;
01197 }
01198 }
01199
01200
01201
01202
01203
01204
01205
01206 int SetUseDoePtr(OptTreeNode * otn)
01207 {
01208 PatternMatchData *idx;
01209
01210 idx = (PatternMatchData *) otn->ds_list[PLUGIN_PATTERN_MATCH];
01211
01212 if(idx == NULL)
01213 {
01214
01215
01216
01217 #ifdef WIN32
01218 #define __FUNCTION__ "SetUseDoePtr"
01219 #endif
01220 LogMessage("%s: No pattern match data found\n", __FUNCTION__);
01221 #ifdef WIN32
01222 #undef __FUNCTION__
01223 #endif
01224
01225 return 0;
01226 }
01227 else
01228 {
01229
01230 while(idx->next != NULL)
01231 {
01232 idx = idx->next;
01233 }
01234
01235 idx->use_doe = 1;
01236 return 1;
01237 }
01238 }
01239
01240
01241
01242
01243
01244
01245
01246
01247
01248
01249
01250
01251
01252
01253
01254 static unsigned int GetMaxJumpSize(char *data, int data_len)
01255 {
01256 int i, j;
01257
01258 j = 0;
01259 for ( i = 1; i < data_len; i++ )
01260 {
01261 if ( data[j] != data[i] )
01262 {
01263 j = 0;
01264 continue;
01265 }
01266 if ( i == (data_len - 1) )
01267 {
01268 return (data_len - j - 1);
01269 }
01270 j++;
01271 }
01272 return data_len;
01273 }
01274
01275
01276
01277
01278
01279
01280
01281
01282
01283
01284
01285
01286
01287
01288 static void ParsePattern(char *rule, OptTreeNode * otn, int type)
01289 {
01290 unsigned char tmp_buf[2048];
01291
01292
01293 char *start_ptr;
01294 char *end_ptr;
01295 char *idx;
01296 char *dummy_idx;
01297 char *dummy_end;
01298 char *tmp;
01299 char hex_buf[3];
01300 u_int dummy_size = 0;
01301 int size;
01302 int hexmode = 0;
01303 int hexsize = 0;
01304 int pending = 0;
01305 int cnt = 0;
01306 int literal = 0;
01307 int exception_flag = 0;
01308 PatternMatchData *ds_idx;
01309
01310
01311 bzero(tmp_buf, 2048);
01312
01313 if(rule == NULL)
01314 {
01315 FatalError("%s(%d) => ParsePattern Got Null "
01316 "enclosed in quotation marks (\")!\n",
01317 file_name, file_line);
01318 }
01319
01320 while(isspace((int)*rule))
01321 rule++;
01322
01323 if(*rule == '!')
01324 {
01325 exception_flag = 1;
01326 }
01327
01328
01329 start_ptr = index(rule, '"');
01330
01331 if(start_ptr == NULL)
01332 {
01333 FatalError("%s(%d) => Content data needs to be "
01334 "enclosed in quotation marks (\")!\n",
01335 file_name, file_line);
01336 }
01337
01338
01339 start_ptr++;
01340
01341
01342 end_ptr = strrchr(start_ptr, '"');
01343
01344 if(end_ptr == NULL)
01345 {
01346 FatalError("%s(%d) => Content data needs to be enclosed "
01347 "in quotation marks (\")!\n", file_name, file_line);
01348 }
01349
01350
01351 *end_ptr = '\0';
01352
01353
01354
01355 tmp = end_ptr + 1;
01356 while (*tmp != '\0' && isspace ((int)*tmp))
01357 tmp++;
01358
01359 if (strlen (tmp) > 0)
01360 {
01361 FatalError("%s(%d) => Bad data (possibly due to missing semicolon) "
01362 "after trailing double quote.",
01363 file_name, file_line, end_ptr + 1);
01364 }
01365
01366
01367 size = end_ptr - start_ptr;
01368
01369
01370 if(size <= 0)
01371 {
01372 FatalError("%s(%d) => Bad pattern length!\n",
01373 file_name, file_line);
01374 }
01375
01376 idx = start_ptr;
01377
01378
01379 dummy_idx = tmp_buf;
01380 dummy_end = (dummy_idx + size);
01381
01382
01383 bzero(hex_buf, 3);
01384 memset(hex_buf, '0', 2);
01385
01386
01387 while(idx < end_ptr)
01388 {
01389 DEBUG_WRAP(DebugMessage(DEBUG_PARSER, "processing char: %c\n", *idx););
01390 switch(*idx)
01391 {
01392 case '|':
01393 DEBUG_WRAP(DebugMessage(DEBUG_PARSER, "Got bar... "););
01394 if(!literal)
01395 {
01396 DEBUG_WRAP(DebugMessage(DEBUG_PARSER, "not in literal mode... "););
01397 if(!hexmode)
01398 {
01399 DEBUG_WRAP(DebugMessage(DEBUG_PARSER, "Entering hexmode\n"););
01400 hexmode = 1;
01401 }
01402 else
01403 {
01404 DEBUG_WRAP(DebugMessage(DEBUG_PARSER, "Exiting hexmode\n"););
01405
01406
01407
01408
01409 if(!hexsize || hexsize % 2)
01410 {
01411 FatalError("%s(%d) => Content hexmode argument has invalid "
01412 "number of hex digits. The argument '%s' must "
01413 "contain a full even byte string.\n",
01414 file_name, file_line, start_ptr);
01415 }
01416
01417 hexmode = 0;
01418 pending = 0;
01419 }
01420
01421 if(hexmode)
01422 hexsize = 0;
01423 }
01424 else
01425 {
01426 DEBUG_WRAP(DebugMessage(DEBUG_PARSER, "literal set, Clearing\n"););
01427 literal = 0;
01428 tmp_buf[dummy_size] = start_ptr[cnt];
01429 dummy_size++;
01430 }
01431
01432 break;
01433
01434 case '\\':
01435 DEBUG_WRAP(DebugMessage(DEBUG_PATTERN_MATCH, "Got literal char... "););
01436
01437 if(!literal)
01438 {
01439
01440
01441
01442 if (idx [1] != '\0' && strchr ("\\\":;", idx [1]) == NULL)
01443 {
01444 FatalError("%s(%d) => bad escape sequence starting "
01445 "with \"%s\". ", file_name, file_line, idx);
01446 }
01447
01448 DEBUG_WRAP(DebugMessage(DEBUG_PATTERN_MATCH, "Setting literal\n"););
01449
01450 literal = 1;
01451 }
01452 else
01453 {
01454 DEBUG_WRAP(DebugMessage(DEBUG_PATTERN_MATCH, "Clearing literal\n"););
01455 tmp_buf[dummy_size] = start_ptr[cnt];
01456 literal = 0;
01457 dummy_size++;
01458 }
01459
01460 break;
01461 case '"':
01462 if (!literal) {
01463 FatalError("%s(%d) => Non-escaped "
01464 " '\"' character!\n", file_name, file_line);
01465 }
01466
01467 default:
01468 if(hexmode)
01469 {
01470 if(isxdigit((int) *idx))
01471 {
01472 hexsize++;
01473
01474 if(!pending)
01475 {
01476 hex_buf[0] = *idx;
01477 pending++;
01478 }
01479 else
01480 {
01481 hex_buf[1] = *idx;
01482 pending--;
01483
01484 if(dummy_idx < dummy_end)
01485 {
01486 tmp_buf[dummy_size] = (u_char)
01487 strtol(hex_buf, (char **) NULL, 16)&0xFF;
01488
01489 dummy_size++;
01490 bzero(hex_buf, 3);
01491 memset(hex_buf, '0', 2);
01492 }
01493 else
01494 {
01495 FatalError("ParsePattern() dummy "
01496 "buffer overflow, make a smaller "
01497 "pattern please! (Max size = 2048)\n");
01498 }
01499 }
01500 }
01501 else
01502 {
01503 if(*idx != ' ')
01504 {
01505 FatalError("%s(%d) => What is this "
01506 "\"%c\"(0x%X) doing in your binary "
01507 "buffer? Valid hex values only please! "
01508 "(0x0 - 0xF) Position: %d\n",
01509 file_name,
01510 file_line, (char) *idx, (char) *idx, cnt);
01511 }
01512 }
01513 }
01514 else
01515 {
01516 if(*idx >= 0x1F && *idx <= 0x7e)
01517 {
01518 if(dummy_idx < dummy_end)
01519 {
01520 tmp_buf[dummy_size] = start_ptr[cnt];
01521 dummy_size++;
01522 }
01523 else
01524 {
01525 FatalError("%s(%d)=> ParsePattern() "
01526 "dummy buffer overflow!\n", file_name, file_line);
01527 }
01528
01529 if(literal)
01530 {
01531 literal = 0;
01532 }
01533 }
01534 else
01535 {
01536 if(literal)
01537 {
01538 tmp_buf[dummy_size] = start_ptr[cnt];
01539 dummy_size++;
01540 DEBUG_WRAP(DebugMessage(DEBUG_PARSER, "Clearing literal\n"););
01541 literal = 0;
01542 }
01543 else
01544 {
01545 FatalError("%s(%d)=> character value out "
01546 "of range, try a binary buffer\n",
01547 file_name, file_line);
01548 }
01549 }
01550 }
01551
01552 break;
01553 }
01554
01555 dummy_idx++;
01556 idx++;
01557 cnt++;
01558 }
01559
01560
01561
01562
01563 if (literal) {
01564 FatalError("%s(%d)=> backslash escape is not "
01565 "completed\n", file_name, file_line);
01566 }
01567 if (hexmode) {
01568 FatalError("%s(%d)=> hexmode is not "
01569 "completed\n", file_name, file_line);
01570 }
01571
01572 ds_idx = (PatternMatchData *) otn->ds_list[type];
01573
01574 while(ds_idx->next != NULL)
01575 ds_idx = ds_idx->next;
01576
01577 if((ds_idx->pattern_buf = (char *) calloc(dummy_size+1, sizeof(char)))
01578 == NULL)
01579 {
01580 FatalError("ParsePattern() pattern_buf malloc failed!\n");
01581 }
01582
01583 memcpy(ds_idx->pattern_buf, tmp_buf, dummy_size);
01584
01585 ds_idx->pattern_size = dummy_size;
01586 ds_idx->search = uniSearch;
01587
01588 make_precomp(ds_idx);
01589 ds_idx->exception_flag = exception_flag;
01590
01591 ds_idx->pattern_max_jump_size = GetMaxJumpSize(ds_idx->pattern_buf, ds_idx->pattern_size);
01592
01593 return;
01594 }
01595
01596 static int CheckORPatternMatch(Packet * p, struct _OptTreeNode * otn_idx,
01597 OptFpList * fp_list)
01598 {
01599 int found = 0;
01600 int dsize;
01601 char *dp;
01602
01603
01604 PatternMatchData *idx;
01605
01606 DEBUG_WRAP(DebugMessage(DEBUG_PATTERN_MATCH, "CheckPatternORMatch: "););
01607
01608 idx = otn_idx->ds_list[PLUGIN_PATTERN_MATCH_OR];
01609
01610 while(idx != NULL)
01611 {
01612
01613 if((p->packet_flags & PKT_ALT_DECODE) && (idx->rawbytes == 0))
01614 {
01615 dsize = p->alt_dsize;
01616 dp = (char *) DecodeBuffer;
01617 DEBUG_WRAP(DebugMessage(DEBUG_PATTERN_MATCH,
01618 "Using Alternative Decode buffer!\n"););
01619 }
01620 else
01621 {
01622 dsize = p->dsize;
01623 dp = (char *) p->data;
01624 }
01625
01626
01627 if(idx->offset > dsize)
01628 {
01629 DEBUG_WRAP(DebugMessage(DEBUG_PATTERN_MATCH,
01630 "Initial offset larger than payload!\n"););
01631
01632 goto sizetoosmall;
01633 }
01634 else
01635 {
01636 DEBUG_WRAP(DebugMessage(DEBUG_PATTERN_MATCH,
01637 "testing pattern: %s\n", idx->pattern_buf););
01638 found = idx->search(dp, dsize, idx);
01639
01640 if(!found)
01641 {
01642 DEBUG_WRAP(DebugMessage(DEBUG_PATTERN_MATCH,
01643 "Pattern Match failed!\n"););
01644 }
01645 }
01646
01647 DEBUG_WRAP(DebugMessage(DEBUG_PATTERN_MATCH,
01648 "Checking the results\n"););
01649
01650 if(found)
01651 {
01652 DEBUG_WRAP(DebugMessage(DEBUG_PATTERN_MATCH, "Pattern Match "
01653 "successful: %s!\n", idx->pattern_buf););
01654
01655 return fp_list->next->OptTestFunc(p, otn_idx, fp_list->next);
01656
01657 }
01658 else
01659 {
01660 DEBUG_WRAP(DebugMessage(DEBUG_PATTERN_MATCH,
01661 "Pattern match failed\n"););
01662 }
01663
01664 DEBUG_WRAP(DebugMessage(DEBUG_PATTERN_MATCH,
01665 "Stepping to next content keyword\n"););
01666
01667 sizetoosmall:
01668
01669 idx = idx->next;
01670 }
01671
01672 DEBUG_WRAP(DebugMessage(DEBUG_PATTERN_MATCH,
01673 "No more keywords, exiting... \n"););
01674
01675 return 0;
01676 }
01677
01678 static int CheckANDPatternMatch(Packet *p, struct _OptTreeNode *otn_idx,
01679 OptFpList *fp_list)
01680 {
01681 int found = 0;
01682 int next_found;
01683 int dsize;
01684 char *dp;
01685 int origUseDoe;
01686 char *tmp_doe, *orig_doe, *start_doe;
01687
01688 PatternMatchData *idx;
01689
01690 DEBUG_WRAP(DebugMessage(DEBUG_PATTERN_MATCH, "CheckPatternANDMatch: "););
01691
01692 idx = fp_list->context;
01693 origUseDoe = idx->use_doe;
01694
01695 if((p->packet_flags & PKT_ALT_DECODE) && (idx->rawbytes == 0))
01696 {
01697 dsize = p->alt_dsize;
01698 dp = (char *) DecodeBuffer;
01699 DEBUG_WRAP(DebugMessage(DEBUG_PATTERN_MATCH,
01700 "Using Alternative Decode buffer!\n"););
01701 }
01702 else
01703 {
01704 dsize = p->dsize;
01705 dp = (char *) p->data;
01706 }
01707
01708
01709
01710 orig_doe = doe_ptr;
01711 found = (idx->search(dp, dsize, idx) ^ idx->exception_flag);
01712
01713 if (InlineMode() && found && idx->replace_buf)
01714 {
01715
01716 PayloadReplace(p, otn_idx, fp_list, detect_depth);
01717 }
01718
01719 while (found)
01720 {
01721
01722 tmp_doe = doe_ptr;
01723
01724
01725 start_doe = doe_ptr - idx->pattern_size + idx->pattern_max_jump_size;
01726
01727 DEBUG_WRAP(DebugMessage(DEBUG_PATTERN_MATCH, "Pattern Match successful!\n"););
01728 DEBUG_WRAP(DebugMessage(DEBUG_PATTERN_MATCH, "Check next functions!\n"););
01729
01730
01731 next_found= fp_list->next->OptTestFunc(p, otn_idx, fp_list->next);
01732
01733 if(next_found != 0)
01734 {
01735 DEBUG_WRAP(DebugMessage(DEBUG_PATTERN_MATCH,
01736 "Next functions matched!\n"););
01737
01738
01739 return next_found;
01740 }
01741 else if(tmp_doe != NULL)
01742 {
01743 int new_dsize = dsize-(start_doe-dp);
01744
01745 if(new_dsize <= 0 || new_dsize > dsize)
01746 {
01747 DEBUG_WRAP(DebugMessage(DEBUG_PATTERN_MATCH,
01748 "The new dsize is less than <= 0 or > "
01749 "the the original dsize;returning "
01750 "false\n"););
01751 idx->use_doe = origUseDoe;
01752 return 0;
01753 }
01754
01755 if (orig_doe)
01756 {
01757
01758 if (((idx->distance != 0) && (start_doe - orig_doe > idx->distance)) ||
01759 ((idx->offset != 0) && (start_doe - orig_doe > idx->offset)) )
01760 {
01761 DEBUG_WRAP(DebugMessage(DEBUG_PATTERN_MATCH,
01762 "The next starting point to search "
01763 "from is beyond the original "
01764 "distance;returning false\n"););
01765 idx->use_doe = origUseDoe;
01766 return 0;
01767 }
01768
01769 if (((idx->within != 0) &&
01770 (start_doe - orig_doe + idx->pattern_size > (unsigned int)idx->within)) ||
01771 ((idx->depth != 0) &&
01772 (start_doe - orig_doe + idx->pattern_size > (unsigned int)idx->depth)) )
01773 {
01774 DEBUG_WRAP(DebugMessage(DEBUG_PATTERN_MATCH,
01775 "The next starting point to search "
01776 "from is beyond the original "
01777 "within;returning false\n"););
01778 idx->use_doe = origUseDoe;
01779 return 0;
01780 }
01781 }
01782 else
01783 {
01784
01785 if (((idx->distance != 0) && (start_doe - dp > idx->distance)) ||
01786 ((idx->offset != 0) && (start_doe - dp > idx->offset)) )
01787 {
01788 DEBUG_WRAP(DebugMessage(DEBUG_PATTERN_MATCH,
01789 "The next starting point to search "
01790 "from is beyond the original "
01791 "distance;returning false\n"););
01792 idx->use_doe = origUseDoe;
01793 return 0;
01794 }
01795
01796 if (((idx->within != 0) &&
01797 (start_doe - dp + idx->pattern_size > (unsigned int)idx->within)) ||
01798 ((idx->depth != 0) &&
01799 (start_doe - dp + idx->pattern_size > (unsigned int)idx->depth)) )
01800 {
01801 DEBUG_WRAP(DebugMessage(DEBUG_PATTERN_MATCH,
01802 "The next starting point to search "
01803 "from is beyond the original "
01804 "within;returning false\n"););
01805 idx->use_doe = origUseDoe;
01806 return 0;
01807 }
01808 }
01809
01810 DEBUG_WRAP(DebugMessage(DEBUG_PATTERN_MATCH,
01811 "At least ONE of the next functions does to match!\n"););
01812 DEBUG_WRAP(DebugMessage(DEBUG_PATTERN_MATCH,
01813 "Start search again from a next point!\n"););
01814
01815
01816 doe_ptr = start_doe;
01817 idx->use_doe = 1;
01818 found = (idx->search(start_doe, new_dsize,idx) ^ idx->exception_flag);
01819
01820
01821
01822
01823
01824
01825
01826 if(start_doe == (char *)doe_ptr)
01827 {
01828 idx->use_doe = origUseDoe;
01829 return 0;
01830 }
01831 }
01832 else
01833 {
01834 DEBUG_WRAP(DebugMessage(DEBUG_PATTERN_MATCH,
01835 "Returning 0 because tmp_doe is NULL\n"););
01836
01837 idx->use_doe = origUseDoe;
01838 return 0;
01839 }
01840
01841 }
01842
01843 idx->use_doe = origUseDoe;
01844 DEBUG_WRAP(DebugMessage(DEBUG_PLUGIN, "Pattern match failed\n"););
01845 return 0;
01846 }
01847
01848
01849
01850
01851
01852 static int CheckUriPatternMatch(Packet *p, struct _OptTreeNode *otn_idx,
01853 OptFpList *fp_list)
01854 {
01855 int found = 0;
01856 int i;
01857 PatternMatchData *idx;
01858
01859 if(p->uri_count <= 0)
01860 {
01861 DEBUG_WRAP(DebugMessage(DEBUG_HTTP_DECODE,
01862 "CheckUriPatternMatch: p->uri_count is %d. Returning",
01863 p->uri_count););
01864 return 0;
01865 }
01866
01867 DEBUG_WRAP(DebugMessage(DEBUG_PLUGIN, "CheckUriPatternMatch: "););
01868
01869 idx = fp_list->context;
01870
01871 for(i=0;i < p->uri_count; i++)
01872 {
01873
01874 #ifdef DEBUG
01875 int j;
01876
01877 DebugMessage(DEBUG_HTTP_DECODE,"Checking against URL: ");
01878 for(j=0; j<=UriBufs[i].length; j++)
01879 {
01880 DebugMessage(DEBUG_HTTP_DECODE, "%c", UriBufs[i].uri[j]);
01881 }
01882 DebugMessage(DEBUG_HTTP_DECODE,"\n");
01883
01884 #endif
01885
01886
01887
01888
01889 doe_ptr = NULL;
01890
01891
01892
01893 found = (idx->search(UriBufs[i].uri, UriBufs[i].length, idx) ^ idx->exception_flag);
01894
01895 if(found)
01896 {
01897 DEBUG_WRAP(DebugMessage(DEBUG_PATTERN_MATCH, "Pattern Match successful!\n"););
01898
01899 return fp_list->next->OptTestFunc(p, otn_idx, fp_list->next);
01900 }
01901 }
01902
01903 DEBUG_WRAP(DebugMessage(DEBUG_PLUGIN, "Pattern match failed\n"););
01904
01905 return 0;
01906 }
01907
01908
01909
01910
01911
01912
01913
01914
01915
01916
01917
01918
01919
01920
01921
01922
01923
01924 static void ParseContentListFile(char *file, OptTreeNode * otn, int protocol)
01925 {
01926 FILE *thefp;
01927 char buf[STD_BUF+1];
01928 char rule_buf[STD_BUF+1];
01929 int frazes_count;
01930
01931
01932 #ifdef DEBUG
01933 PatternMatchData *idx;
01934 DEBUG_WRAP(DebugMessage(DEBUG_PATTERN_MATCH, "Opening content_list file: %s\n", file););
01935 #endif
01936
01937 if((thefp = fopen(file, "r")) == NULL)
01938 {
01939 FatalError("Unable to open list file: %s\n", file);
01940 }
01941
01942 bzero((char *) buf, STD_BUF);
01943 bzero((char *) rule_buf, STD_BUF);
01944 frazes_count = 0;
01945
01946
01947 while((fgets(buf, STD_BUF-2, thefp)) != NULL)
01948 {
01949
01950 list_file_line++;
01951
01952 DEBUG_WRAP(DebugMessage(DEBUG_PATTERN_MATCH, "Got line %d: %s",
01953 list_file_line, buf););
01954
01955
01956 if((buf[0] != '#') && (buf[0] != 0x0a) && (buf[0] != ';'))
01957 {
01958 DEBUG_WRAP(DebugMessage(DEBUG_PATTERN_MATCH,
01959 "Adding content keyword: %s", buf););
01960
01961 frazes_count++;
01962 strip(buf);
01963
01964 NewNode(otn, PLUGIN_PATTERN_MATCH_OR);
01965
01966
01967 ParsePattern(buf, otn, PLUGIN_PATTERN_MATCH_OR);
01968
01969 DEBUG_WRAP(DebugMessage(DEBUG_PATTERN_MATCH,
01970 "Content keyword %s\" added!\n", buf););
01971 }
01972 }
01973 #ifdef DEBUG
01974 DEBUG_WRAP(DebugMessage(DEBUG_PATTERN_MATCH, "%d frazes read...\n", frazes_count););
01975 idx = (PatternMatchData *) otn->ds_list[PLUGIN_PATTERN_MATCH_OR];
01976
01977 if(idx == NULL)
01978 {
01979 DEBUG_WRAP(DebugMessage(DEBUG_PATTERN_MATCH, "No patterns loaded\n"););
01980 }
01981 else
01982 {
01983 while(idx != NULL)
01984 {
01985 DEBUG_WRAP(DebugMessage(DEBUG_PATTERN_MATCH, "Pattern = %s\n",
01986 idx->pattern_buf););
01987 idx = idx->next;
01988 }
01989 }
01990 #endif
01991
01992 fclose(thefp);
01993
01994 return;
01995 }