"Fossies" - the Fresh Open Source Software Archive 
Member "snort-2.9.17/src/detection-plugins/sp_byte_check.c" (16 Oct 2020, 27255 Bytes) of package /linux/misc/snort-2.9.17.tar.gz:
As a special service "Fossies" has tried to format the requested source page into HTML format using (guessed) C and C++ source code syntax highlighting (style:
standard) with prefixed line numbers and
code folding option.
Alternatively you can here
view or
download the uninterpreted source code file.
For more information about "sp_byte_check.c" see the
Fossies "Dox" file reference documentation and the latest
Fossies "Diffs" side-by-side code changes report:
2.9.16.1_vs_2.9.17.
1 /* $Id$ */
2 /*
3 ** Copyright (C) 2014-2020 Cisco and/or its affiliates. All rights reserved.
4 ** Copyright (C) 2002-2013 Sourcefire, Inc.
5 ** Author: Martin Roesch
6 **
7 ** This program is free software; you can redistribute it and/or modify
8 ** it under the terms of the GNU General Public License Version 2 as
9 ** published by the Free Software Foundation. You may not use, modify or
10 ** distribute this program under any other version of the GNU General
11 ** Public License.
12 **
13 ** This program is distributed in the hope that it will be useful,
14 ** but WITHOUT ANY WARRANTY; without even the implied warranty of
15 ** MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
16 ** GNU General Public License for more details.
17 **
18 ** You should have received a copy of the GNU General Public License
19 ** along with this program; if not, write to the Free Software
20 ** Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
21 */
22
23 /* sp_byte_check
24 *
25 * Purpose:
26 * Test a byte field against a specific value (with operator). Capable
27 * of testing binary values or converting represenative byte strings
28 * to their binary equivalent and testing them.
29 *
30 *
31 * Arguments:
32 * Required:
33 * <bytes_to_convert>: number of bytes to pick up from the packet
34 * <operator>: operation to perform to test the value (<,>,=,!)
35 * <value>: value to test the converted value against
36 * <offset>: number of bytes into the payload to start processing
37 * Optional:
38 * ["relative"]: offset relative to last pattern match
39 * ["big"]: process data as big endian (default)
40 * ["little"]: process data as little endian
41 * ["string"]: converted bytes represented as a string needing conversion
42 * ["hex"]: converted string data is represented in hexidecimal
43 * ["dec"]: converted string data is represented in decimal
44 * ["oct"]: converted string data is represented in octal
45 *
46 * sample rules:
47 * alert udp $EXTERNAL_NET any -> $HOME_NET any \
48 * (msg:"AMD procedure 7 plog overflow "; \
49 * content: "|00 04 93 F3|"; \
50 * content: "|00 00 00 07|"; distance: 4; within: 4; \
51 * byte_test: 4,>, 1000, 20, relative;)
52 *
53 * alert tcp $EXTERNAL_NET any -> $HOME_NET any \
54 * (msg:"AMD procedure 7 plog overflow "; \
55 * content: "|00 04 93 F3|"; \
56 * content: "|00 00 00 07|"; distance: 4; within: 4; \
57 * byte_test: 4, >,1000, 20, relative;)
58 *
59 * alert udp any any -> any 1234 \
60 * (byte_test: 4, =, 1234, 0, string, dec; \
61 * msg: "got 1234!";)
62 *
63 * alert udp any any -> any 1235 \
64 * (byte_test: 3, =, 123, 0, string, dec; \
65 * msg: "got 123!";)
66 *
67 * alert udp any any -> any 1236 \
68 * (byte_test: 2, =, 12, 0, string, dec; \
69 * msg: "got 12!";)
70 *
71 * alert udp any any -> any 1237 \
72 * (byte_test: 10, =, 1234567890, 0, string, dec; \
73 * msg: "got 1234567890!";)
74 *
75 * alert udp any any -> any 1238 \
76 * (byte_test: 8, =, 0xdeadbeef, 0, string, hex; \
77 * msg: "got DEADBEEF!";)
78 *
79 * Effect:
80 *
81 * Reads in the indicated bytes, converts them to an numeric
82 * representation and then performs the indicated operation/test on
83 * the data using the value field. Returns 1 if the operation is true,
84 * 0 if it is not.
85 *
86 * Comments:
87 *
88 * Any comments?
89 *
90 */
91
92 #ifdef HAVE_CONFIG_H
93 #include "config.h"
94 #endif
95
96 #include <sys/types.h>
97 #include <stdlib.h>
98 #include <ctype.h>
99 #ifdef HAVE_STRINGS_H
100 #include <strings.h>
101 #endif
102 #include <errno.h>
103
104 #include "sf_types.h"
105 #include "snort_bounds.h"
106 #include "byte_extract.h"
107 #include "rules.h"
108 #include "treenodes.h"
109 #include "decode.h"
110 #include "plugbase.h"
111 #include "parser.h"
112 #include "snort_debug.h"
113 #include "util.h"
114 #include "plugin_enum.h"
115 #include "mstring.h"
116 #include "sfhashfcn.h"
117 #include "sp_byte_check.h"
118 #include "sp_byte_extract.h"
119 #include "sp_byte_math.h"
120
121 #define PARSELEN 10
122 #define TEXTLEN (PARSELEN + 2)
123
124 #include "snort.h"
125 #include "profiler.h"
126 #include "sfhashfcn.h"
127 #include "detection_options.h"
128 #include "detection_util.h"
129
130 #ifdef PERF_PROFILING
131 PreprocStats byteTestPerfStats;
132 extern PreprocStats ruleOTNEvalPerfStats;
133 #endif
134
135
136 typedef struct _ByteTestOverrideData
137 {
138 char *keyword;
139 char *option;
140 union
141 {
142 RuleOptOverrideFunc fptr;
143 void *void_fptr;
144 } fptr;
145 struct _ByteTestOverrideData *next;
146
147 } ByteTestOverrideData;
148
149 ByteTestOverrideData *byteTestOverrideFuncs = NULL;
150
151 static void ByteTestOverride(char *keyword, char *option, RuleOptOverrideFunc roo_func);
152 static void ByteTestOverrideFuncsFree(void);
153 static void ByteTestInit(struct _SnortConfig *, char *, OptTreeNode *, int);
154 static ByteTestOverrideData * ByteTestParse(char *data, ByteTestData *idx, OptTreeNode *otn);
155 static void ByteTestOverrideCleanup(int, void *);
156
157 uint32_t ByteTestHash(void *d)
158 {
159 uint32_t a,b,c;
160 ByteTestData *data = (ByteTestData *)d;
161
162 a = data->bytes_to_compare;
163 b = data->cmp_value;
164 c = data->operator;
165
166 mix(a,b,c);
167
168 a += data->offset;
169 b += (data->not_flag << 24 |
170 data->relative_flag << 16 |
171 data->data_string_convert_flag << 8 |
172 data->endianess);
173 c += data->base;
174
175 mix(a,b,c);
176
177 a += data->bitmask_val;
178 b += RULE_OPTION_TYPE_BYTE_TEST;
179 c += (data->cmp_value_var << 8 |
180 data->offset_var );
181
182 mix(a,b,c);
183
184 #if (defined(__ia64) || defined(__amd64) || defined(_LP64))
185 {
186 /* Cleanup warning because of cast from 64bit ptr to 32bit int
187 * warning on 64bit OSs */
188 uint64_t ptr; /* Addresses are 64bits */
189
190 ptr = (uint64_t) data->byte_order_func;
191 a += (ptr >> 32);
192 b += (ptr & 0xFFFFFFFF);
193 }
194 #else
195 a += (uint32_t)data->byte_order_func;
196 #endif
197
198 final(a,b,c);
199
200 return c;
201 }
202
203 int ByteTestCompare(void *l, void *r)
204 {
205 ByteTestData *left = (ByteTestData *)l;
206 ByteTestData *right = (ByteTestData *)r;
207
208 if (!left || !right)
209 return DETECTION_OPTION_NOT_EQUAL;
210
211 if (( left->bytes_to_compare == right->bytes_to_compare) &&
212 ( left->cmp_value == right->cmp_value) &&
213 ( left->operator == right->operator) &&
214 ( left->offset == right->offset) &&
215 ( left->not_flag == right->not_flag) &&
216 ( left->relative_flag == right->relative_flag) &&
217 ( left->data_string_convert_flag == right->data_string_convert_flag) &&
218 ( left->endianess == right->endianess) &&
219 ( left->base == right->base) &&
220 ( left->cmp_value_var == right->cmp_value_var) &&
221 ( left->offset_var == right->offset_var) &&
222 ( left->byte_order_func == right->byte_order_func) &&
223 ( left->bitmask_val == right->bitmask_val))
224 {
225 return DETECTION_OPTION_EQUAL;
226 }
227
228 return DETECTION_OPTION_NOT_EQUAL;
229 }
230
231 static void ByteTestOverride(char *keyword, char *option, RuleOptOverrideFunc roo_func)
232 {
233 ByteTestOverrideData *new = SnortAlloc(sizeof(ByteTestOverrideData));
234
235 new->keyword = SnortStrdup(keyword);
236 new->option = SnortStrdup(option);
237 new->func = roo_func;
238
239 new->next = byteTestOverrideFuncs;
240 byteTestOverrideFuncs = new;
241 }
242
243 static void ByteTestOverrideFuncsFree(void)
244 {
245 ByteTestOverrideData *node = byteTestOverrideFuncs;
246
247 while (node != NULL)
248 {
249 ByteTestOverrideData *tmp = node;
250
251 node = node->next;
252
253 if (tmp->keyword != NULL)
254 free(tmp->keyword);
255
256 if (tmp->option != NULL)
257 free(tmp->option);
258
259 free(tmp);
260 }
261
262 byteTestOverrideFuncs = NULL;
263 }
264
265 /****************************************************************************
266 * Function: SetupByteTest()
267 *
268 * Purpose: Register byte_test name and initialization function
269 *
270 * Arguments: None.
271 *
272 * Returns: void function
273 *
274 ****************************************************************************/
275 void SetupByteTest(void)
276 {
277 /* map the keyword to an initialization/processing function */
278 RegisterRuleOption("byte_test", ByteTestInit, ByteTestOverride, OPT_TYPE_DETECTION, NULL);
279 AddFuncToCleanExitList(ByteTestOverrideCleanup, NULL);
280 AddFuncToRuleOptParseCleanupList(ByteTestOverrideFuncsFree);
281
282 #ifdef PERF_PROFILING
283 RegisterPreprocessorProfile("byte_test", &byteTestPerfStats, 3, &ruleOTNEvalPerfStats, NULL);
284 #endif
285 DEBUG_WRAP(DebugMessage(DEBUG_PLUGIN,"Plugin: ByteTest Setup\n"););
286 }
287
288
289 /****************************************************************************
290 *
291 * Function: ByteTestInit(char *, OptTreeNode *)
292 *
293 * Purpose: Generic rule configuration function. Handles parsing the rule
294 * information and attaching the associated detection function to
295 * the OTN.
296 *
297 * Arguments: data => rule arguments/data
298 * otn => pointer to the current rule option list node
299 * protocol => protocol the rule is on (we don't care in this case)
300 *
301 * Returns: void function
302 *
303 ****************************************************************************/
304 static void ByteTestInit(struct _SnortConfig *sc, char *data, OptTreeNode *otn, int protocol)
305 {
306 ByteTestData *idx;
307 OptFpList *fpl;
308 ByteTestOverrideData *override;
309 void *idx_dup;
310
311 /* allocate the data structure and attach it to the
312 rule's data struct list */
313 idx = (ByteTestData *) calloc(sizeof(ByteTestData), sizeof(char));
314
315 if(idx == NULL)
316 {
317 FatalError("%s(%d): Unable to allocate byte_test data node\n",
318 file_name, file_line);
319 }
320
321 /* this is where the keyword arguments are processed and placed into the
322 rule option's data structure */
323 override = ByteTestParse(data, idx, otn);
324 if (override)
325 {
326 /* There is an override function */
327 free(idx);
328 override->func(sc, override->keyword, override->option, data, otn, protocol);
329 return;
330 }
331
332 fpl = AddOptFuncToList(ByteTest, otn);
333 fpl->type = RULE_OPTION_TYPE_BYTE_TEST;
334
335 if (add_detection_option(sc, RULE_OPTION_TYPE_BYTE_TEST, (void *)idx, &idx_dup) == DETECTION_OPTION_EQUAL)
336 {
337 #ifdef DEBUG_RULE_OPTION_TREE
338 LogMessage("Duplicate ByteCheck:\n%d %d %d %d %c %c %c %c %d 0x%x\n"
339 "%d %d %d %d %c %c %c %c %d 0x%x\n\n",
340 idx->bytes_to_compare,
341 idx->cmp_value,
342 idx->operator,
343 idx->offset,
344 idx->not_flag, idx->relative_flag,
345 idx->data_string_convert_flag,
346 idx->endianess, idx->base,
347 idx->bitmask_val,
348 ((ByteTestData *)idx_dup)->bytes_to_compare,
349 ((ByteTestData *)idx_dup)->cmp_value,
350 ((ByteTestData *)idx_dup)->operator,
351 ((ByteTestData *)idx_dup)->offset,
352 ((ByteTestData *)idx_dup)->not_flag, ((ByteTestData *)idx_dup)->relative_flag,
353 ((ByteTestData *)idx_dup)->data_string_convert_flag,
354 ((ByteTestData *)idx_dup)->endianess, ((ByteTestData *)idx_dup)->base,
355 ((ByteTestData *)idx_dup)->bitmask_val);
356 #endif
357 free(idx);
358 idx = idx_dup;
359 }
360
361 /* attach it to the context node so that we can call each instance
362 * individually
363 */
364 fpl->context = (void *) idx;
365
366 if (idx->relative_flag == 1)
367 fpl->isRelative = 1;
368 }
369
370 /****************************************************************************
371 *
372 * Function: ByteTestParse(char *, ByteTestData *, OptTreeNode *)
373 *
374 * Purpose: This is the function that is used to process the option keyword's
375 * arguments and attach them to the rule's data structures.
376 *
377 * Arguments: data => argument data
378 * idx => pointer to the processed argument storage
379 * otn => pointer to the current rule's OTN
380 *
381 * Returns: void function
382 *
383 ****************************************************************************/
384 static ByteTestOverrideData * ByteTestParse(char *data, ByteTestData *idx, OptTreeNode *otn)
385 {
386 char **toks;
387 char *endp;
388 int num_toks;
389 char *cptr;
390 int i =0;
391 RuleOptByteOrderFunc tmp_byte_order_func;
392
393 toks = mSplit(data, ",", 13, &num_toks, 0);
394
395 if(num_toks < 4)
396 ParseError(" Bad arguments to byte_test: %s\n",data);
397
398 /* set how many bytes to process from the packet */
399 idx->bytes_to_compare = strtol(toks[0], &endp, 10);
400
401 if(toks[0] == endp)
402 {
403 ParseError(" Unable to parse as byte value %s\n",toks[0]);
404 }
405
406 if(*endp != '\0')
407 {
408 ParseError("byte_test option has bad value: %s.", toks[0]);
409 }
410
411 if(idx->bytes_to_compare > PARSELEN || idx->bytes_to_compare == 0)
412 {
413 ParseError(" byte_test can't process more than "
414 "10 bytes!\n");
415 }
416
417 cptr = toks[1];
418
419 while(isspace((int)*cptr)) {cptr++;}
420
421 if(*cptr == '!')
422 {
423 DEBUG_WRAP(DebugMessage(DEBUG_PATTERN_MATCH,
424 "enabling not flag\n"););
425 idx->not_flag = 1;
426 cptr++;
427 }
428
429 if (idx->not_flag && strlen(cptr) == 0)
430 {
431 idx->operator = BT_EQUALS;
432 }
433 else
434 {
435 /* set the operator */
436 switch(*cptr)
437 {
438 case '<': idx->operator = BT_LESS_THAN;
439 cptr++;
440 if (*cptr == '=')
441 idx->operator = BT_LESS_THAN_EQUAL;
442 else
443 cptr--;
444 break;
445
446 case '=': idx->operator = BT_EQUALS;
447 break;
448
449 case '>': idx->operator = BT_GREATER_THAN;
450 cptr++;
451 if (*cptr == '=')
452 idx->operator = BT_GREATER_THAN_EQUAL;
453 else
454 cptr--;
455 break;
456
457 case '&': idx->operator = BT_AND;
458 break;
459
460 case '^': idx->operator = BT_XOR;
461 break;
462
463 default: ParseError(" byte_test unknown "
464 "operator ('%c, %s')\n",
465 *cptr, toks[1]);
466 }
467 }
468
469
470 /* set the value to test against */
471 if (isdigit(toks[2][0]) || toks[2][0] == '-')
472 {
473 int64_t rval = SnortStrtoul(toks[2], &endp,0);
474 if (rval > MAX_RVAL)
475 {
476 ParseError("byte_test rule option has invalid rvalue."
477 "Valid rvalue range %u-%u.",
478 MIN_RVAL-1,MAX_RVAL);
479 }
480 idx->cmp_value=rval;
481 idx->cmp_value_var = -1;
482
483 if(toks[2] == endp)
484 {
485 ParseError(" Unable to parse as comparison value %s\n",
486 toks[2]);
487 }
488
489 if(*endp != '\0')
490 {
491 ParseError("byte_test option has bad comparison value: %s.", toks[2]);
492 }
493
494 if(errno == ERANGE)
495 {
496 ParseError("Bad range: %s\n", toks[2]);
497 }
498 }
499 else
500 {
501 idx->cmp_value_var = find_value(toks[2]);
502 if ( idx->cmp_value_var == BYTE_EXTRACT_NO_VAR)
503 {
504 ParseError(BYTE_TEST_INVALID_ERR_FMT, "byte_test : value", toks[2]);
505 }
506 }
507
508 if (isdigit(toks[3][0]) || toks[3][0] == '-')
509 {
510 /* set offset */
511 idx->offset = strtol(toks[3], &endp, 10);
512 idx->offset_var = -1;
513
514 if(toks[3] == endp)
515 {
516 ParseError(" Unable to parse as offset value %s\n",
517 toks[3]);
518 }
519
520 if(*endp != '\0')
521 {
522 ParseError("byte_test option has bad offset: %s.", toks[3]);
523 }
524 }
525 else
526 {
527 idx->offset_var = find_value(toks[3]);
528 if ( idx->offset_var == BYTE_EXTRACT_NO_VAR)
529 {
530 ParseError(BYTE_TEST_INVALID_ERR_FMT, "byte_test : offset", toks[3]);
531 }
532 }
533
534
535 i = 4;
536
537 /* is it a relative offset? */
538 if(num_toks > 4)
539 {
540 while(i < num_toks)
541 {
542 cptr = toks[i];
543
544 while(isspace((int)*cptr)) {cptr++;}
545
546 if(!strcasecmp(cptr, "relative"))
547 {
548 /* the offset is relative to the last pattern match */
549 idx->relative_flag = 1;
550 }
551 else if(!strcasecmp(cptr, "string"))
552 {
553 /* the data will be represented as a string that needs
554 * to be converted to an int, binary is assumed otherwise
555 */
556 idx->data_string_convert_flag = 1;
557 }
558 else if(!strcasecmp(cptr, "little"))
559 {
560 idx->endianess = LITTLE;
561 }
562 else if(!strcasecmp(cptr, "big"))
563 {
564 /* this is the default */
565 idx->endianess = BIG;
566 }
567 else if(!strcasecmp(cptr, "hex"))
568 {
569 idx->base = 16;
570 }
571 else if(!strcasecmp(cptr, "dec"))
572 {
573 idx->base = 10;
574 }
575 else if(!strcasecmp(cptr, "oct"))
576 {
577 idx->base = 8;
578 }
579 else if((tmp_byte_order_func = GetByteOrderFunc(cptr)) != NULL)
580 {
581 idx->byte_order_func = tmp_byte_order_func;
582 }
583 else if(strncasecmp(cptr,"bitmask ",8) == 0)
584 {
585 RuleOptionBitmaskParse(&(idx->bitmask_val), cptr, idx->bytes_to_compare, "BYTE_TEST");
586 }
587 else
588 {
589 ByteTestOverrideData *override = byteTestOverrideFuncs;
590
591 while (override != NULL)
592 {
593 if (!strcasecmp(cptr, override->option))
594 {
595 mSplitFree(&toks, num_toks);
596 return override;
597 }
598
599 override = override->next;
600 }
601
602 ParseError("unknown modifier \"%s\"\n",cptr);
603 }
604
605 i++;
606 }
607 }
608
609 if (idx->bytes_to_compare > MAX_BYTES_TO_GRAB && !idx->data_string_convert_flag)
610 {
611 ParseError("byte_test rule option cannot extract more than %d bytes without valid string prefix.",
612 MAX_BYTES_TO_GRAB);
613 }
614 /* idx->base is only set if the parameter is specified */
615 if(!idx->data_string_convert_flag && idx->base)
616 {
617 ParseError("hex, dec and oct modifiers must be used in conjunction \n"
618 " with the 'string' modifier\n");
619 }
620 if (idx->offset < MIN_BYTE_EXTRACT_OFFSET || idx->offset > MAX_BYTE_EXTRACT_OFFSET)
621 {
622 ParseError("byte_test rule option has invalid offset. "
623 "Valid offsets are between %d and %d.",
624 MIN_BYTE_EXTRACT_OFFSET, MAX_BYTE_EXTRACT_OFFSET);
625 }
626 mSplitFree(&toks, num_toks);
627 return NULL;
628 }
629
630
631 /****************************************************************************
632 *
633 * Function: ByteTest(char *, OptTreeNode *, OptFpList *)
634 *
635 * Purpose: Use this function to perform the particular detection routine
636 * that this rule keyword is supposed to encompass.
637 *
638 * Arguments: p => pointer to the decoded packet
639 * otn => pointer to the current rule's OTN
640 * fp_list => pointer to the function pointer list
641 *
642 * Returns: If the detection test fails, this function *must* return a zero!
643 * On success, it calls the next function in the detection list
644 *
645 ****************************************************************************/
646 int ByteTest(void *option_data, Packet *p)
647 {
648 ByteTestData *btd = (ByteTestData *)option_data;
649 int rval = DETECTION_OPTION_NO_MATCH;
650 uint32_t value = 0;
651 int success = 0;
652 int dsize;
653 const char *base_ptr, *end_ptr, *start_ptr;
654 int payload_bytes_grabbed;
655 int32_t offset;
656 uint32_t extract_offset, extract_cmp_value;
657 int search_start = 0;
658 PROFILE_VARS;
659
660 PREPROC_PROFILE_START(byteTestPerfStats);
661
662 if (Is_DetectFlag(FLAG_ALT_DETECT))
663 {
664 dsize = DetectBuffer.len;
665 start_ptr = (const char*)DetectBuffer.data;
666 DEBUG_WRAP(DebugMessage(DEBUG_PATTERN_MATCH,
667 "Using Alternative Detect buffer!\n"););
668 }
669 else if(Is_DetectFlag(FLAG_ALT_DECODE))
670 {
671 dsize = DecodeBuffer.len;
672 start_ptr = (char *)DecodeBuffer.data;
673 DEBUG_WRAP(DebugMessage(DEBUG_PATTERN_MATCH,
674 "Using Alternative Decode buffer!\n"););
675 }
676 else
677 {
678 if(IsLimitedDetect(p))
679 dsize = p->alt_dsize;
680 else
681 dsize = p->dsize;
682 start_ptr = (char *) p->data;
683 }
684
685 base_ptr = start_ptr;
686 end_ptr = start_ptr + dsize;
687
688 DEBUG_WRAP(DebugMessage(DEBUG_PATTERN_MATCH,
689 "[*] byte test firing...\npayload starts at %p\n", start_ptr););
690
691
692 /* Get values from byte_extract variables, if present. */
693 if (btd->cmp_value_var >= 0 )
694 {
695
696 if(btd->cmp_value_var == BYTE_MATH_VAR_INDEX )
697 {
698 btd->cmp_value = (int32_t) bytemath_variable;
699 }
700 else if(btd->cmp_value_var == COMMON_VAR_INDEX )
701 {
702 btd->cmp_value = (int32_t) common_var;
703 }
704 else if (btd->cmp_value_var < NUM_BYTE_EXTRACT_VARS)
705 {
706 GetByteExtractValue(&extract_cmp_value, btd->cmp_value_var);
707 btd->cmp_value = (int32_t) extract_cmp_value;
708 }
709
710 }
711 if (btd->offset_var >= 0 )
712 {
713 if(btd->offset_var == BYTE_MATH_VAR_INDEX )
714 {
715 btd->offset = (int32_t) bytemath_variable;
716 }
717 else if(btd->offset_var == COMMON_VAR_INDEX )
718 {
719 btd->offset = (int32_t) common_var;
720 }
721 else if (btd->offset_var < NUM_BYTE_EXTRACT_VARS)
722 {
723 GetByteExtractValue(&extract_offset, btd->offset_var);
724 btd->offset = (int32_t) extract_offset;
725 }
726
727 }
728
729
730 if(btd->relative_flag && doe_ptr)
731 {
732 DEBUG_WRAP(DebugMessage(DEBUG_PATTERN_MATCH,
733 "Checking relative offset!\n"););
734
735 /* @todo: possibly degrade to use the other buffer, seems non-intuitive
736 * Because doe_ptr can be "end" in the last match,
737 * use end + 1 for upper bound
738 * Bound checked also after offset is applied
739 * (see byte_extract() and string_extract())
740 */
741 if(!inBounds((const uint8_t *)start_ptr, (const uint8_t *)end_ptr + 1, doe_ptr))
742 {
743 DEBUG_WRAP(DebugMessage(DEBUG_PATTERN_MATCH,
744 "[*] byte test bounds check failed..\n"););
745 PREPROC_PROFILE_END(byteTestPerfStats);
746 return rval;
747 }
748
749 search_start = (doe_ptr - (const uint8_t *)start_ptr) + btd->offset;
750 base_ptr = (const char *)doe_ptr;
751 }
752 else
753 {
754 DEBUG_WRAP(DebugMessage(DEBUG_PATTERN_MATCH,
755 "checking absolute offset %d\n", btd->offset););
756 search_start = btd->offset;
757 base_ptr = start_ptr;
758 }
759
760 if( search_start < 0 )
761 {
762 DEBUG_WRAP(DebugMessage(DEBUG_PATTERN_MATCH,
763 "[*] byte test bounds check failed..\n"););
764 PREPROC_PROFILE_END(byteTestPerfStats);
765 return rval;
766 }
767
768 base_ptr = base_ptr + btd->offset;
769
770 /* Use byte_order_func to determine endianess, if present */
771 if (btd->byte_order_func)
772 {
773 offset = (int32_t) ((const uint8_t *)base_ptr - p->data);
774 btd->endianess = btd->byte_order_func(p, offset);
775 if (btd->endianess == -1)
776 {
777 PREPROC_PROFILE_END(byteTestPerfStats);
778 return DETECTION_OPTION_NO_MATCH;
779 }
780 }
781
782 /* both of these functions below perform their own bounds checking within
783 * byte_extract.c
784 */
785
786 if(!btd->data_string_convert_flag)
787 {
788 if(byte_extract(btd->endianess, btd->bytes_to_compare,
789 (const uint8_t *)base_ptr, (const uint8_t *)start_ptr, (const uint8_t *)end_ptr, &value))
790 {
791 DEBUG_WRAP(DebugMessage(DEBUG_PATTERN_MATCH,
792 "Byte Extraction Failed\n"););
793
794 PREPROC_PROFILE_END(byteTestPerfStats);
795 return rval;
796 }
797 payload_bytes_grabbed = (int)btd->bytes_to_compare;
798 }
799 else
800 {
801 payload_bytes_grabbed = string_extract(
802 btd->bytes_to_compare, btd->base,
803 (const uint8_t *)base_ptr, (const uint8_t *)start_ptr,
804 (const uint8_t *)end_ptr, &value);
805
806 if ( payload_bytes_grabbed < 0 )
807 {
808 DEBUG_WRAP(DebugMessage(DEBUG_PATTERN_MATCH,
809 "String Extraction Failed\n"););
810
811 PREPROC_PROFILE_END(byteTestPerfStats);
812 return rval;
813 }
814
815 }
816
817 if(btd->bitmask_val != 0 )
818 {
819 int num_tailing_zeros_bitmask = getNumberTailingZerosInBitmask(btd->bitmask_val);
820 value = value & btd->bitmask_val ;
821 if ( value && num_tailing_zeros_bitmask )
822 {
823 value = value >> num_tailing_zeros_bitmask;
824 }
825 }
826
827 DEBUG_WRAP(DebugMessage(DEBUG_PATTERN_MATCH,
828 "Grabbed %d bytes at offset %d cmp_value = 0x%08X(%u) value = 0x%08X(%u)\n",
829 payload_bytes_grabbed, btd->offset, btd->cmp_value,btd->cmp_value,value, value); );
830
831 switch(btd->operator)
832 {
833 case BT_LESS_THAN: if(value < btd->cmp_value)
834 success = 1;
835 break;
836
837 case BT_EQUALS: if(value == btd->cmp_value)
838 success = 1;
839 break;
840
841 case BT_GREATER_THAN: if(value > btd->cmp_value)
842 success = 1;
843 break;
844
845 case BT_AND: if ((value & btd->cmp_value) > 0)
846 success = 1;
847 break;
848
849 case BT_XOR: if ((value ^ btd->cmp_value) > 0)
850 success = 1;
851 break;
852
853 case BT_GREATER_THAN_EQUAL: if (value >= btd->cmp_value)
854 success = 1;
855 break;
856
857 case BT_LESS_THAN_EQUAL: if (value <= btd->cmp_value)
858 success = 1;
859 break;
860
861 case BT_CHECK_ALL: if ((value & btd->cmp_value) == btd->cmp_value)
862 success = 1;
863 break;
864
865 case BT_CHECK_ATLEASTONE: if ((value & btd->cmp_value) != 0)
866 success = 1;
867 break;
868
869 case BT_CHECK_NONE: if ((value & btd->cmp_value) == 0)
870 success = 1;
871 break;
872 }
873
874 if (btd->not_flag)
875 {
876 DEBUG_WRAP(DebugMessage(DEBUG_PATTERN_MATCH,
877 "checking for not success...flag\n"););
878 if (!success)
879 {
880 rval = DETECTION_OPTION_MATCH;
881 }
882 }
883 else if (success)
884 {
885 rval = DETECTION_OPTION_MATCH;
886 }
887
888 /* if the test isn't successful, this function *must* return 0 */
889 PREPROC_PROFILE_END(byteTestPerfStats);
890 return rval;
891 }
892
893 static void ByteTestOverrideCleanup(int signal, void *data)
894 {
895 if (byteTestOverrideFuncs != NULL)
896 ByteTestOverrideFuncsFree();
897 }
898