suricata
detect-bytetest.c
Go to the documentation of this file.
1/* Copyright (C) 2007-2022 Open Information Security Foundation
2 *
3 * You can copy, redistribute or modify this Program under the terms of
4 * the GNU General Public License version 2 as published by the Free
5 * Software Foundation.
6 *
7 * This program is distributed in the hope that it will be useful,
8 * but WITHOUT ANY WARRANTY; without even the implied warranty of
9 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
10 * GNU General Public License for more details.
11 *
12 * You should have received a copy of the GNU General Public License
13 * version 2 along with this program; if not, write to the Free Software
14 * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
15 * 02110-1301, USA.
16 */
17
18/**
19 * \file
20 *
21 * \author Brian Rectanus <brectanu@gmail.com>
22 * \author Jeff Lucovsky <jeff@lucovsky.org>
23 *
24 * Implements byte_test keyword.
25 */
26
27#include "suricata-common.h"
28#include "decode.h"
29#include "detect.h"
30#include "detect-engine.h"
32#include "detect-parse.h"
33#include "detect-engine-build.h"
34
35#include "detect-content.h"
36#include "detect-uricontent.h"
37#include "detect-byte.h"
38#include "detect-bytetest.h"
39#include "detect-bytejump.h"
40#include "detect-byte-extract.h"
41#include "app-layer.h"
42
43#include "util-byte.h"
44#include "util-unittest.h"
45#include "util-debug.h"
46#include "detect-pcre.h"
47
48
49/**
50 * \brief Regex for parsing our options
51 */
52/** \todo We probably just need a simple tokenizer here */
53
54/* PCRE supports 9 substrings so the 2nd and 3rd (negation, operator) and
55 * 4th and 5th (test value, offset) are combined
56 */
57#define VALID_KW "relative|big|little|string|oct|dec|hex|dce|bitmask"
58#define PARSE_REGEX "^\\s*" \
59 "([^\\s,]+)\\s*,\\s*" \
60 "(\\!?\\s*[^\\s,]*)" \
61 "\\s*,\\s*([^\\s,]+\\s*,\\s*[^\\s,]+)" \
62 "(?:\\s*,\\s*((?:"VALID_KW")\\s+[^\\s,]+|["VALID_KW"]+))?" \
63 "(?:\\s*,\\s*((?:"VALID_KW")\\s+[^\\s,]+|["VALID_KW"]+))?" \
64 "(?:\\s*,\\s*((?:"VALID_KW")\\s+[^\\s,]+|["VALID_KW"]+))?" \
65 "(?:\\s*,\\s*((?:"VALID_KW")\\s+[^\\s,]+|["VALID_KW"]+))?" \
66 "(?:\\s*,\\s*((?:"VALID_KW")\\s+[^\\s,]+|["VALID_KW"]+))?" \
67 "(?:\\s*,\\s*((?:"VALID_KW")\\s+[^\\s,]+|["VALID_KW"]+))?" \
68 "\\s*$"
69
70static DetectParseRegex parse_regex;
71
72static int DetectBytetestSetup(DetectEngineCtx *de_ctx, Signature *s, const char *optstr);
73static void DetectBytetestFree(DetectEngineCtx *, void *ptr);
74#ifdef UNITTESTS
75static void DetectBytetestRegisterTests(void);
76#endif
77
79{
80 sigmatch_table[DETECT_BYTETEST].name = "byte_test";
81 sigmatch_table[DETECT_BYTETEST].desc = "extract <num of bytes> and perform an operation selected with <operator> against the value in <test value> at a particular <offset>";
82 sigmatch_table[DETECT_BYTETEST].url = "/rules/payload-keywords.html#byte-test";
83 sigmatch_table[DETECT_BYTETEST].Setup = DetectBytetestSetup;
84 sigmatch_table[DETECT_BYTETEST].Free = DetectBytetestFree;
85#ifdef UNITTESTS
86 sigmatch_table[DETECT_BYTETEST].RegisterTests = DetectBytetestRegisterTests;
87#endif
89}
90
91/* 23 - This is the largest string (octal, with a zero prefix) that
92 * will not overflow uint64_t. The only way this length
93 * could be over 23 and still not overflow is if it were zero
94 * prefixed and we only support 1 byte of zero prefix for octal.
95 *
96 * "01777777777777777777777" = 0xffffffffffffffff
97 *
98 * 8 - Without string, the maximum byte extract count is 8.
99 */
100static inline bool DetectBytetestValidateNbytesOnly(const DetectBytetestData *data, int32_t nbytes)
101{
102 return ((data->flags & DETECT_BYTETEST_STRING) && nbytes <= 23) || (nbytes <= 8);
103}
104
105static bool DetectBytetestValidateNbytes(
106 const DetectBytetestData *data, int32_t nbytes, const char *optstr)
107{
108 if (!DetectBytetestValidateNbytesOnly(data, nbytes)) {
109 if (data->flags & DETECT_BYTETEST_STRING) {
110 /* 23 - This is the largest string (octal, with a zero prefix) that
111 * will not overflow uint64_t. The only way this length
112 * could be over 23 and still not overflow is if it were zero
113 * prefixed and we only support 1 byte of zero prefix for octal.
114 *
115 * "01777777777777777777777" = 0xffffffffffffffff
116 */
117 if (nbytes > 23) {
118 SCLogError("Cannot test more than 23 bytes with \"string\": %s", optstr);
119 }
120 } else {
121 if (nbytes > 8) {
122 SCLogError("Cannot test more than 8 bytes without \"string\": %s", optstr);
123 }
124 if (data->base != DETECT_BYTETEST_BASE_UNSET) {
125 SCLogError("Cannot use a base without \"string\": %s", optstr);
126 }
127 }
128 return false;
129 } else {
130 /*
131 * Even if the value is within the proper range, ensure
132 * that the base is unset unless string is used.
133 */
134 if (!(data->flags & DETECT_BYTETEST_STRING) && (data->base != DETECT_BYTETEST_BASE_UNSET)) {
135 SCLogError("Cannot use a base without \"string\": %s", optstr);
136 return false;
137 }
138 }
139
140 return true;
141}
142
143/** \brief Bytetest detection code
144 *
145 * Byte test works on the packet payload.
146 *
147 * \param det_ctx thread de ctx
148 * \param s signature
149 * \param m sigmatch for this bytetest
150 * \param payload ptr to the start of the buffer to inspect
151 * \param payload_len length of the payload
152 * \retval 1 match
153 * \retval 0 no match
154 */
156 const SigMatchCtx *ctx, const uint8_t *payload, uint32_t payload_len, uint16_t flags,
157 int32_t offset, int32_t nbytes, uint64_t value)
158{
159 SCEnter();
160
161 if (payload_len == 0) {
162 SCReturnInt(0);
163 }
164
165 const DetectBytetestData *data = (const DetectBytetestData *)ctx;
166 if (data->flags & DETECT_BYTETEST_NBYTES_VAR) {
167 if (!DetectBytetestValidateNbytesOnly(data, nbytes)) {
168 SCLogDebug("Invalid byte_test nbytes seen in byte_test - %d", nbytes);
169 SCReturnInt(0);
170 }
171 }
172
173 const uint8_t *ptr = NULL;
174 int32_t len = 0;
175 uint64_t val = 0;
176 int extbytes;
177 int neg;
178 int match;
179
180 /* Calculate the ptr value for the bytetest and length remaining in
181 * the packet from that point.
182 */
184 SCLogDebug("relative, working with det_ctx->buffer_offset %"PRIu32", "
185 "data->offset %"PRIi32"", det_ctx->buffer_offset, data->offset);
186
187 ptr = payload + det_ctx->buffer_offset;
188 len = payload_len - det_ctx->buffer_offset;
189
190 ptr += offset;
191 len -= offset;
192
193 /* No match if there is no relative base */
194 if (ptr == NULL || len <= 0) {
195 SCReturnInt(0);
196 }
197 }
198 else {
199 SCLogDebug("absolute, data->offset %"PRIi32"", data->offset);
200
201 ptr = payload + offset;
203 }
204
205 /* Validate that the to-be-extracted is within the packet
206 * \todo Should this validate it is in the *payload*?
207 */
208 if (ptr < payload || nbytes > len) {
209 SCLogDebug("Data not within payload pkt=%p, ptr=%p, len=%" PRIu32 ", nbytes=%d", payload,
210 ptr, len, nbytes);
211 SCReturnInt(0);
212 }
213
214 neg = data->neg_op;
215
216 /* Extract the byte data */
218 extbytes = ByteExtractStringUint64(&val, data->base, nbytes, (const char *)ptr);
219 if (extbytes <= 0) {
220 /* ByteExtractStringUint64() returns 0 if there is no numeric value in data string */
221 if (val == 0) {
222 SCLogDebug("No Numeric value");
223 SCReturnInt(0);
224 } else {
225 SCLogDebug("error extracting %d "
226 "bytes of string data: %d",
227 nbytes, extbytes);
228 SCReturnInt(-1);
229 }
230 }
231
232 SCLogDebug("comparing base %d string 0x%" PRIx64 " %s%u 0x%" PRIx64,
233 data->base, val, (neg ? "!" : ""), data->op, data->value);
234 }
235 else {
236 int endianness = (flags & DETECT_BYTETEST_LITTLE) ?
238 extbytes = ByteExtractUint64(&val, endianness, (uint16_t)nbytes, ptr);
239 if (extbytes != nbytes) {
240 SCLogDebug("error extracting %d bytes "
241 "of numeric data: %d",
242 nbytes, extbytes);
243 SCReturnInt(-1);
244 }
245
246 SCLogDebug("comparing numeric 0x%" PRIx64 " %s%u 0x%" PRIx64,
247 val, (neg ? "!" : ""), data->op, data->value);
248 }
249
250 /* apply bitmask, if any and then right-shift 1 bit for each trailing 0 in
251 * the bitmask. Note that it's one right shift for each trailing zero (not bit).
252 */
254 val &= data->bitmask;
255 if (val && data->bitmask_shift_count) {
256 val = val >> data->bitmask_shift_count;
257 }
258 }
259
260 /* Compare using the configured operator */
261 match = 0;
262 switch (data->op) {
264 if (val == value) {
265 match = 1;
266 }
267 break;
269 if (val < value) {
270 match = 1;
271 }
272 break;
274 if (val > value) {
275 match = 1;
276 }
277 break;
279 if (val & value) {
280 match = 1;
281 }
282 break;
284 if (val ^ value) {
285 match = 1;
286 }
287 break;
289 if (val >= value) {
290 match = 1;
291 }
292 break;
294 if (val <= value) {
295 match = 1;
296 }
297 break;
298 default:
299 /* Should never get here as we handle this in parsing. */
300 SCReturnInt(-1);
301 }
302
303 /* A successful match depends on negation */
304 if ((!neg && match) || (neg && !match)) {
305 SCLogDebug("MATCH [bt] extracted value is %"PRIu64, val);
306 SCReturnInt(1);
307 }
308
309 SCLogDebug("NO MATCH");
310 SCReturnInt(0);
311
312}
313
314static DetectBytetestData *DetectBytetestParse(
315 const char *optstr, char **value, char **offset, char **nbytes_str)
316{
317 DetectBytetestData *data = NULL;
318 char *args[9] = {
319 NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL,
320 NULL
321 };
322 char *test_value = NULL;
323 char *data_offset = NULL;
324 int res = 0;
325 size_t pcre2_len;
326 int i;
327 uint32_t nbytes = 0;
328 const char *str_ptr = NULL;
329 pcre2_match_data *match = NULL;
330
331 /* Execute the regex and populate args with captures. */
332 int ret = DetectParsePcreExec(&parse_regex, &match, optstr, 0, 0);
333 if (ret < 4 || ret > 9) {
334 SCLogError("parse error, ret %" PRId32 ", string %s", ret, optstr);
335 goto error;
336 }
337
338 /* Subtract two since two values are conjoined */
339 for (i = 0; i < (ret - 1); i++) {
340 res = pcre2_substring_get_bynumber(match, i + 1, (PCRE2_UCHAR8 **)&str_ptr, &pcre2_len);
341 if (res < 0) {
342 SCLogError("pcre2_substring_get_bynumber failed "
343 "for arg %d",
344 i + 1);
345 goto error;
346 }
347 /* args[2] is comma separated test value, offset */
348 if (i == 2) {
349 test_value = (char *) str_ptr;
350 data_offset = SCStrdup((char *) str_ptr);
351 if (data_offset == NULL) {
352 goto error;
353 }
354 } else {
355 args[i] = (char *)str_ptr;
356 }
357 }
358
359 /* Initialize the data */
360 data = SCMalloc(sizeof(DetectBytetestData));
361 if (unlikely(data == NULL))
362 goto error;
364 data->flags = 0;
365
366 /*
367 * The first four options are required and positional. The
368 * remaining arguments are flags and are not positional.
369 *
370 * The first four options have been collected into three
371 * arguments:
372 * - #1 -- byte count
373 * - #2 -- operator, including optional negation (!)
374 * - #3 -- test value and offset, comma separated
375 */
376
377 /* Number of bytes */
378 if (args[0][0] != '-' && isalpha((unsigned char)args[0][0])) {
379 if (nbytes_str == NULL) {
380 SCLogError("byte_test supplied with "
381 "var name for nbytes. \"value\" argument supplied to "
382 "this function has to be non-NULL");
383 goto error;
384 }
385 *nbytes_str = SCStrdup(args[0]);
386 if (*nbytes_str == NULL)
387 goto error;
389 } else {
390 if (StringParseUint32(&nbytes, 10, 0, args[0]) <= 0) {
391 SCLogError("Malformed number of bytes: %s", str_ptr);
392 goto error;
393 }
394 }
395
396 /* The operator is the next arg; it may contain a negation ! as the first char */
397 data->op = 0;
398 if (args[1] != NULL) {
399 int op_offset = 0;
400 char *op_ptr;
401 if (args[1][op_offset] == '!') {
402 data->neg_op = true;
403 op_ptr = &args[1][1];
404 while (isspace((char)*op_ptr) || (*op_ptr == ',')) op_ptr++;
405 op_offset = (uint32_t)(op_ptr - &args[1][0]);
406 } else {
407 data->neg_op = false;
408 }
409 op_ptr = args[1] + op_offset;
410 if ((strcmp("=", op_ptr) == 0) || (data->neg_op
411 && strcmp("", op_ptr) == 0)) {
412 data->op |= DETECT_BYTETEST_OP_EQ;
413 } else if (strcmp("<", op_ptr) == 0) {
414 data->op |= DETECT_BYTETEST_OP_LT;
415 } else if (strcmp(">", op_ptr) == 0) {
416 data->op |= DETECT_BYTETEST_OP_GT;
417 } else if (strcmp("&", op_ptr) == 0) {
418 data->op |= DETECT_BYTETEST_OP_AND;
419 } else if (strcmp("^", op_ptr) == 0) {
420 data->op |= DETECT_BYTETEST_OP_OR;
421 } else if (strcmp(">=", op_ptr) == 0) {
422 data->op |= DETECT_BYTETEST_OP_GE;
423 } else if (strcmp("<=", op_ptr) == 0) {
424 data->op |= DETECT_BYTETEST_OP_LE;
425 } else {
426 SCLogError("Invalid operator");
427 goto error;
428 }
429 }
430
431 if (test_value) {
432 /*
433 * test_value was created while fetching strings and contains the test value and offset,
434 * comma separated. The values was allocated by test_value (pcre2_substring_get_bynumber)
435 * and data_offset (SCStrdup), respectively; e.g., test_value,offset
436 */
437 char *end_ptr = test_value;
438 while (!(isspace((unsigned char)*end_ptr) || (*end_ptr == ','))) end_ptr++;
439 *end_ptr = '\0';
440
441 if (test_value[0] != '-' && isalpha((unsigned char)test_value[0])) {
442 if (value == NULL) {
443 SCLogError("byte_test supplied with "
444 "var name for value. \"value\" argument supplied to "
445 "this function has to be non-NULL");
446 goto error;
447 }
448 *value = SCStrdup(test_value);
449 if (*value == NULL)
450 goto error;
451 } else {
452 if (ByteExtractStringUint64(&data->value, 0, 0, test_value) <= 0) {
453 SCLogError("Malformed value: %s", test_value);
454 goto error;
455 }
456 }
457 }
458
459 /* Offset -- note that this *also* contains test_value, offset so parse accordingly */
460 if (data_offset) {
461 char *end_ptr = data_offset;
462 while (!(isspace((unsigned char)*end_ptr) || (*end_ptr == ','))) end_ptr++;
463 str_ptr = ++end_ptr;
464 while (isspace((unsigned char)*str_ptr) || (*str_ptr == ',')) str_ptr++;
465 end_ptr = (char *)str_ptr;
466 while (!(isspace((unsigned char)*end_ptr) || (*end_ptr == ',')) && (*end_ptr != '\0'))
467 end_ptr++;
468 memmove(data_offset, str_ptr, end_ptr - str_ptr);
469 data_offset[end_ptr-str_ptr] = '\0';
470 if (data_offset[0] != '-' && isalpha((unsigned char)data_offset[0])) {
471 *offset = SCStrdup(data_offset);
472 if (*offset == NULL)
473 goto error;
474 } else {
475 if (StringParseInt32(&data->offset, 0, 0, data_offset) <= 0) {
476 SCLogError("Malformed offset: %s", data_offset);
477 goto error;
478 }
479 }
480 }
481
482 /* The remaining options are flags. */
483 /** \todo Error on dups? */
484 int bitmask_index = -1;
485 for (i = 3; i < (ret - 1); i++) {
486 if (args[i] != NULL) {
487 if (strcmp("relative", args[i]) == 0) {
489 } else if (strcasecmp("string", args[i]) == 0) {
491 } else if (strcasecmp("dec", args[i]) == 0) {
493 } else if (strcasecmp("hex", args[i]) == 0) {
495 } else if (strcasecmp("oct", args[i]) == 0) {
497 } else if (strcasecmp("big", args[i]) == 0) {
498 if (data->flags & DETECT_BYTETEST_LITTLE) {
500 }
501 data->flags |= DETECT_BYTETEST_BIG;
502 } else if (strcasecmp("little", args[i]) == 0) {
504 } else if (strcasecmp("dce", args[i]) == 0) {
505 data->flags |= DETECT_BYTETEST_DCE;
506 } else if (strncasecmp("bitmask", args[i], strlen("bitmask")) == 0) {
508 bitmask_index = i;
509 } else {
510 SCLogError("Unknown value: \"%s\"", args[i]);
511 goto error;
512 }
513 }
514 }
515
516 if (!(data->flags & DETECT_BYTETEST_NBYTES_VAR)) {
517 if (!DetectBytetestValidateNbytes(data, nbytes, optstr)) {
518 goto error;
519 }
520
521 /* This is max 23 so it will fit in a byte (see above) */
522 data->nbytes = (uint8_t)nbytes;
523 }
524
525 if (bitmask_index != -1 && data->flags & DETECT_BYTETEST_BITMASK) {
526 if (ByteExtractStringUint32(&data->bitmask, 0, 0, args[bitmask_index]+strlen("bitmask")) <= 0) {
527 SCLogError("Malformed bitmask value: %s", args[bitmask_index] + strlen("bitmask"));
528 goto error;
529 }
530 /* determine how many trailing 0's are in the bitmask. This will be used
531 * to rshift the value after applying the bitmask
532 */
533 data->bitmask_shift_count = 0;
534 if (data->bitmask) {
535 uint32_t bmask = data->bitmask;
536 while (!(bmask & 0x1)){
537 bmask = bmask >> 1;
538 data->bitmask_shift_count++;
539 }
540 }
541 }
542
543 for (i = 0; i < (ret - 1); i++){
544 if (args[i] != NULL)
545 pcre2_substring_free((PCRE2_UCHAR8 *)args[i]);
546 }
547 if (data_offset) SCFree(data_offset);
548 if (test_value)
549 pcre2_substring_free((PCRE2_UCHAR8 *)test_value);
550 pcre2_match_data_free(match);
551 return data;
552
553error:
554 for (i = 0; i < (ret - 1); i++){
555 if (args[i] != NULL)
556 pcre2_substring_free((PCRE2_UCHAR8 *)args[i]);
557 }
558 if (data_offset) SCFree(data_offset);
559 if (test_value)
560 pcre2_substring_free((PCRE2_UCHAR8 *)test_value);
561 if (data) SCFree(data);
562 if (match) {
563 pcre2_match_data_free(match);
564 }
565 return NULL;
566}
567
568static int DetectBytetestSetup(DetectEngineCtx *de_ctx, Signature *s, const char *optstr)
569{
570 SigMatch *prev_pm = NULL;
571 char *value = NULL;
572 char *offset = NULL;
573 char *nbytes = NULL;
574 int ret = -1;
575
576 DetectBytetestData *data = DetectBytetestParse(optstr, &value, &offset, &nbytes);
577 if (data == NULL)
578 goto error;
579
580 int sm_list;
582 if (DetectBufferGetActiveList(de_ctx, s) == -1)
583 goto error;
584
585 sm_list = s->init_data->list;
586
587 if (data->flags & DETECT_BYTETEST_RELATIVE) {
589 }
590
591 } else if (data->flags & DETECT_BYTETEST_DCE) {
592 if (data->flags & DETECT_BYTETEST_RELATIVE) {
593 prev_pm = DetectGetLastSMFromLists(s,
597 if (prev_pm == NULL) {
598 sm_list = DETECT_SM_LIST_PMATCH;
599 } else {
600 sm_list = SigMatchListSMBelongsTo(s, prev_pm);
601 if (sm_list < 0)
602 goto error;
603 }
604 } else {
605 sm_list = DETECT_SM_LIST_PMATCH;
606 }
607
609 goto error;
610
611 } else if (data->flags & DETECT_BYTETEST_RELATIVE) {
612 prev_pm = DetectGetLastSMFromLists(s,
616 if (prev_pm == NULL) {
617 sm_list = DETECT_SM_LIST_PMATCH;
618 } else {
619 sm_list = SigMatchListSMBelongsTo(s, prev_pm);
620 if (sm_list < 0)
621 goto error;
622 }
623
624 } else {
625 sm_list = DETECT_SM_LIST_PMATCH;
626 }
627
628 if (data->flags & DETECT_BYTETEST_DCE) {
629 if ((data->flags & DETECT_BYTETEST_STRING) ||
630 (data->flags & DETECT_BYTETEST_LITTLE) ||
631 (data->flags & DETECT_BYTETEST_BIG) ||
632 (data->base == DETECT_BYTETEST_BASE_DEC) ||
633 (data->base == DETECT_BYTETEST_BASE_HEX) ||
634 (data->base == DETECT_BYTETEST_BASE_OCT) ) {
635 SCLogError("Invalid option. "
636 "A byte_test keyword with dce holds other invalid modifiers.");
637 goto error;
638 }
639 }
640
641 if (value != NULL) {
643 if (!DetectByteRetrieveSMVar(value, s, sm_list, &index)) {
644 SCLogError("Unknown byte_extract var "
645 "seen in byte_test - %s",
646 value);
647 goto error;
648 }
649 data->value = index;
651 SCFree(value);
652 value = NULL;
653 }
654
655 if (offset != NULL) {
657 if (!DetectByteRetrieveSMVar(offset, s, sm_list, &index)) {
658 SCLogError("Unknown byte_extract var "
659 "seen in byte_test - %s",
660 offset);
661 goto error;
662 }
663 data->offset = index;
665 SCFree(offset);
666 offset = NULL;
667 }
668
669 if (nbytes != NULL) {
671 if (!DetectByteRetrieveSMVar(nbytes, s, sm_list, &index)) {
672 SCLogError("Unknown byte_extract var "
673 "seen in byte_test - %s",
674 nbytes);
675 goto error;
676 }
677 data->nbytes = index;
679 SCFree(nbytes);
680 nbytes = NULL;
681 }
682
683 if (SCSigMatchAppendSMToList(de_ctx, s, DETECT_BYTETEST, (SigMatchCtx *)data, sm_list) ==
684 NULL) {
685 goto error;
686 }
687
688 if (!(data->flags & DETECT_BYTETEST_RELATIVE))
689 goto okay;
690
691 if (prev_pm == NULL)
692 goto okay;
693 if (prev_pm->type == DETECT_CONTENT) {
694 DetectContentData *cd = (DetectContentData *)prev_pm->ctx;
695 cd->flags |= DETECT_CONTENT_RELATIVE_NEXT;
696 } else if (prev_pm->type == DETECT_PCRE) {
697 DetectPcreData *pd = (DetectPcreData *)prev_pm->ctx;
698 pd->flags |= DETECT_PCRE_RELATIVE_NEXT;
699 }
700
701 okay:
702 ret = 0;
703 return ret;
704 error:
705 if (offset)
706 SCFree(offset);
707 if (value)
708 SCFree(value);
709 if (nbytes)
710 SCFree(nbytes);
711 DetectBytetestFree(de_ctx, data);
712 return ret;
713}
714
715/**
716 * \brief this function will free memory associated with DetectBytetestData
717 *
718 * \param data pointer to DetectBytetestData
719 */
720static void DetectBytetestFree(DetectEngineCtx *de_ctx, void *ptr)
721{
722 if (ptr == NULL)
723 return;
724
726 SCFree(data);
727}
728
729
730/* UNITTESTS */
731#ifdef UNITTESTS
732#include "util-unittest-helper.h"
733#include "app-layer-parser.h"
734#include "flow-util.h"
735static int g_file_data_buffer_id = 0;
736static int g_dce_stub_data_buffer_id = 0;
737
738/**
739 * \test DetectBytetestTestParse01 is a test to make sure that we return "something"
740 * when given valid bytetest opt
741 */
742static int DetectBytetestTestParse01(void)
743{
744 DetectBytetestData *data = NULL;
745 data = DetectBytetestParse("4, =, 1 , 0", NULL, NULL, NULL);
746 FAIL_IF_NULL(data);
747 DetectBytetestFree(NULL, data);
748 PASS;
749}
750
751/**
752 * \test DetectBytetestTestParse02 is a test for setting the required opts
753 */
754static int DetectBytetestTestParse02(void)
755{
756 DetectBytetestData *data = NULL;
757 data = DetectBytetestParse("4, !=, 1, 0", NULL, NULL, NULL);
758 FAIL_IF_NULL(data);
760 FAIL_IF_NOT(data->nbytes == 4);
761 FAIL_IF_NOT(data->value == 1);
762 FAIL_IF_NOT(data->offset == 0);
763 FAIL_IF_NOT(data->neg_op);
765
766 DetectBytetestFree(NULL, data);
767 PASS;
768}
769
770/**
771 * \test DetectBytetestTestParse03 is a test for setting the relative flag
772 */
773static int DetectBytetestTestParse03(void)
774{
775 DetectBytetestData *data = NULL;
776 data = DetectBytetestParse("4, !=, 1, 0, relative", NULL, NULL, NULL);
777 FAIL_IF_NULL(data);
779 FAIL_IF_NOT(data->nbytes == 4);
780 FAIL_IF_NOT(data->value == 1);
781 FAIL_IF_NOT(data->offset == 0);
782 FAIL_IF_NOT(data->neg_op);
785
786 DetectBytetestFree(NULL, data);
787 PASS;
788}
789
790/**
791 * \test DetectBytetestTestParse04 is a test for setting the string/oct flags
792 */
793static int DetectBytetestTestParse04(void)
794{
795 DetectBytetestData *data = NULL;
796 data = DetectBytetestParse("4, !=, 1, 0, string, oct", NULL, NULL, NULL);
797 FAIL_IF_NULL(data);
799 FAIL_IF_NOT(data->nbytes == 4);
800 FAIL_IF_NOT(data->value == 1);
801 FAIL_IF_NOT(data->offset == 0);
802 FAIL_IF_NOT(data->neg_op);
805 DetectBytetestFree(NULL, data);
806 PASS;
807}
808
809/**
810 * \test DetectBytetestTestParse05 is a test for setting the string/dec flags
811 */
812static int DetectBytetestTestParse05(void)
813{
814 DetectBytetestData *data = NULL;
815 data = DetectBytetestParse("4, =, 1, 0, string, dec", NULL, NULL, NULL);
816 FAIL_IF_NULL(data);
818 FAIL_IF_NOT(data->nbytes == 4);
819 FAIL_IF_NOT(data->value == 1);
820 FAIL_IF_NOT(data->offset == 0);
823 DetectBytetestFree(NULL, data);
824 PASS;
825}
826
827/**
828 * \test DetectBytetestTestParse06 is a test for setting the string/hex flags
829 */
830static int DetectBytetestTestParse06(void)
831{
832 DetectBytetestData *data = NULL;
833 data = DetectBytetestParse("4, >, 1, 0, string, hex", NULL, NULL, NULL);
834 FAIL_IF_NULL(data);
836 FAIL_IF_NOT(data->nbytes == 4);
837 FAIL_IF_NOT(data->value == 1);
838 FAIL_IF_NOT(data->offset == 0);
841 DetectBytetestFree(NULL, data);
842 PASS;
843}
844
845/**
846 * \test DetectBytetestTestParse07 is a test for setting the big flag
847 */
848static int DetectBytetestTestParse07(void)
849{
850 DetectBytetestData *data = NULL;
851 data = DetectBytetestParse("4, <, 5, 0, big", NULL, NULL, NULL);
852 FAIL_IF_NULL(data);
854 FAIL_IF_NOT(data->nbytes == 4);
855 FAIL_IF_NOT(data->value == 5);
856 FAIL_IF_NOT(data->offset == 0);
859 DetectBytetestFree(NULL, data);
860 PASS;
861}
862
863/**
864 * \test DetectBytetestTestParse08 is a test for setting the little flag
865 */
866static int DetectBytetestTestParse08(void)
867{
868 DetectBytetestData *data = NULL;
869 data = DetectBytetestParse("4, <, 5, 0, little", NULL, NULL, NULL);
870 FAIL_IF_NULL(data);
872 FAIL_IF_NOT(data->nbytes == 4);
873 FAIL_IF_NOT(data->value == 5);
874 FAIL_IF_NOT(data->offset == 0);
877
878 DetectBytetestFree(NULL, data);
879 PASS;
880}
881
882/**
883 * \test DetectBytetestTestParse09 is a test for neg operator only
884 */
885static int DetectBytetestTestParse09(void)
886{
887 DetectBytetestData *data = NULL;
888 data = DetectBytetestParse("4, !, 5, 0", NULL, NULL, NULL);
889 FAIL_IF_NULL(data);
891 FAIL_IF_NOT(data->nbytes == 4);
892 FAIL_IF_NOT(data->value == 5);
893 FAIL_IF_NOT(data->offset == 0);
894 FAIL_IF_NOT(data->neg_op);
896 DetectBytetestFree(NULL, data);
897 PASS;
898}
899
900/**
901 * \test DetectBytetestTestParse10 is a test for whitespace
902 */
903static int DetectBytetestTestParse10(void)
904{
905 DetectBytetestData *data = NULL;
906 data = DetectBytetestParse(" 4 , ! &, 5 , 0 , little ", NULL, NULL, NULL);
907 FAIL_IF_NULL(data);
909 FAIL_IF_NOT(data->nbytes == 4);
910 FAIL_IF_NOT(data->value == 5);
911 FAIL_IF_NOT(data->offset == 0);
912 FAIL_IF_NOT(data->neg_op);
915
916 DetectBytetestFree(NULL, data);
917 PASS;
918}
919
920/**
921 * \test DetectBytetestTestParse11 is a test for whitespace
922 */
923static int DetectBytetestTestParse11(void)
924{
925 DetectBytetestData *data = NULL;
926 data = DetectBytetestParse("4,!^,5,0,little,string,relative,hex", NULL, NULL, NULL);
927 FAIL_IF_NULL(data);
929 FAIL_IF_NOT(data->nbytes == 4);
930 FAIL_IF_NOT(data->value == 5);
931 FAIL_IF_NOT(data->offset == 0);
932 FAIL_IF_NOT(data->neg_op);
933 FAIL_IF_NOT(data->flags ==
936
937 DetectBytetestFree(NULL, data);
938 PASS;
939}
940
941/**
942 * \test DetectBytetestTestParse12 is a test for hex w/o string
943 */
944static int DetectBytetestTestParse12(void)
945{
946 DetectBytetestData *data = NULL;
947 data = DetectBytetestParse("4, =, 1, 0, hex", NULL, NULL, NULL);
948 FAIL_IF_NOT_NULL(data);
949
950 PASS;
951}
952
953/**
954 * \test DetectBytetestTestParse13 is a test for too many bytes to extract
955 */
956static int DetectBytetestTestParse13(void)
957{
958 DetectBytetestData *data = NULL;
959 data = DetectBytetestParse("9, =, 1, 0", NULL, NULL, NULL);
960 FAIL_IF_NOT_NULL(data);
961 PASS;
962}
963
964/**
965 * \test DetectBytetestTestParse14 is a test for large string extraction
966 */
967static int DetectBytetestTestParse14(void)
968{
969 DetectBytetestData *data = NULL;
970 data = DetectBytetestParse("23,=,0xffffffffffffffffULL,0,string,oct", NULL, NULL, NULL);
971 FAIL_IF_NULL(data);
973 FAIL_IF_NOT(data->nbytes == 23);
974 FAIL_IF_NOT(data->value == 0xffffffffffffffffULL);
975 FAIL_IF_NOT(data->offset == 0);
978
979 DetectBytetestFree(NULL, data);
980 PASS;
981}
982
983/**
984 * \test DetectBytetestTestParse15 is a test for too many bytes to extract (string)
985 */
986static int DetectBytetestTestParse15(void)
987{
988 DetectBytetestData *data = NULL;
989 data = DetectBytetestParse("24, =, 0xffffffffffffffffULL, 0, string", NULL, NULL, NULL);
990 FAIL_IF_NOT_NULL(data);
991
992 PASS;
993}
994
995/**
996 * \test DetectBytetestTestParse16 is a test for offset too big
997 */
998static int DetectBytetestTestParse16(void)
999{
1000 DetectBytetestData *data = NULL;
1001 data = DetectBytetestParse("4,=,0,0xffffffffffffffffULL", NULL, NULL, NULL);
1002 FAIL_IF_NOT_NULL(data);
1003
1004 PASS;
1005}
1006
1007/**
1008 * \test Test dce option.
1009 */
1010static int DetectBytetestTestParse17(void)
1011{
1012 DetectBytetestData *data = NULL;
1013 data = DetectBytetestParse("4, <, 5, 0, dce", NULL, NULL, NULL);
1014 FAIL_IF_NULL(data);
1016 FAIL_IF_NOT(data->nbytes == 4);
1017 FAIL_IF_NOT(data->value == 5);
1018 FAIL_IF_NOT(data->offset == 0);
1020
1021 DetectBytetestFree(NULL, data);
1022 PASS;
1023}
1024
1025/**
1026 * \test Test dce option.
1027 */
1028static int DetectBytetestTestParse18(void)
1029{
1030 DetectBytetestData *data = NULL;
1031 data = DetectBytetestParse("4, <, 5, 0", NULL, NULL, NULL);
1032 FAIL_IF_NULL(data);
1034 FAIL_IF_NOT(data->nbytes == 4);
1035 FAIL_IF_NOT(data->value == 5);
1036 FAIL_IF_NOT(data->offset == 0);
1038
1039 DetectBytetestFree(NULL, data);
1040 PASS;
1041}
1042
1043/**
1044 * \test Test dce option.
1045 */
1046static int DetectBytetestTestParse19(void)
1047{
1048 Signature *s = SigAlloc();
1049 FAIL_IF_NULL(s);
1050
1052
1053 FAIL_IF_NOT(DetectBytetestSetup(NULL, s, "1,=,1,6,dce") == 0);
1054 FAIL_IF_NOT(DetectBytetestSetup(NULL, s, "1,=,1,6,string,dce") == -1);
1055 FAIL_IF_NOT(DetectBytetestSetup(NULL, s, "1,=,1,6,big,dce") == -1);
1056 FAIL_IF_NOT(DetectBytetestSetup(NULL, s, "1,=,1,6,little,dce") == -1);
1057 FAIL_IF_NOT(DetectBytetestSetup(NULL, s, "1,=,1,6,hex,dce") == -1);
1058 FAIL_IF_NOT(DetectBytetestSetup(NULL, s, "1,=,1,6,oct,dce") == -1);
1059 FAIL_IF_NOT(DetectBytetestSetup(NULL, s, "1,=,1,6,dec,dce") == -1);
1060
1061 SigFree(NULL, s);
1062 PASS;
1063}
1064
1065/**
1066 * \test Test dce option.
1067 */
1068static int DetectBytetestTestParse20(void)
1069{
1070 DetectEngineCtx *de_ctx = NULL;
1071 Signature *s = NULL;
1072 DetectBytetestData *bd = NULL;
1073
1076
1077 de_ctx->flags |= DE_QUIET;
1078 de_ctx->sig_list = SigInit(de_ctx, "alert tcp any any -> any any "
1079 "(msg:\"Testing bytetest_body\"; "
1080 "dce_iface:3919286a-b10c-11d0-9ba8-00c04fd92ef5; "
1081 "dce_stub_data; "
1082 "content:\"one\"; distance:0; "
1083 "byte_test:1,=,1,6,relative,dce; sid:1;)");
1085
1086 s = de_ctx->sig_list;
1087
1088 SigMatch *sm = DetectBufferGetFirstSigMatch(s, g_dce_stub_data_buffer_id);
1089 FAIL_IF_NULL(sm);
1090 FAIL_IF_NULL(sm->next);
1091 sm = sm->next;
1093 bd = (DetectBytetestData *)sm->ctx;
1094 FAIL_IF_NOT(bd->flags & DETECT_BYTETEST_DCE);
1096 FAIL_IF(bd->flags & DETECT_BYTETEST_STRING);
1097 FAIL_IF(bd->flags & DETECT_BYTETEST_BIG);
1098 FAIL_IF(bd->flags & DETECT_BYTETEST_LITTLE);
1099 FAIL_IF(bd->neg_op);
1100
1101 s->next = SigInit(de_ctx, "alert tcp any any -> any any "
1102 "(msg:\"Testing bytetest_body\"; "
1103 "dce_iface:3919286a-b10c-11d0-9ba8-00c04fd92ef5; "
1104 "dce_stub_data; "
1105 "content:\"one\"; distance:0; "
1106 "byte_test:1,=,1,6,relative,dce; sid:1;)");
1107 FAIL_IF_NULL(s->next);
1108
1109 s = s->next;
1110
1111 sm = DetectBufferGetFirstSigMatch(s, g_dce_stub_data_buffer_id);
1112 FAIL_IF_NULL(sm);
1113 FAIL_IF_NULL(sm->next);
1114 sm = sm->next;
1115 bd = (DetectBytetestData *)sm->ctx;
1116 FAIL_IF_NOT(bd->flags & DETECT_BYTETEST_DCE);
1118 FAIL_IF(bd->flags & DETECT_BYTETEST_STRING);
1119 FAIL_IF(bd->flags & DETECT_BYTETEST_BIG);
1120 FAIL_IF(bd->flags & DETECT_BYTETEST_LITTLE);
1121 FAIL_IF(bd->neg_op);
1122
1123 s->next = SigInit(de_ctx, "alert tcp any any -> any any "
1124 "(msg:\"Testing bytetest_body\"; "
1125 "dce_iface:3919286a-b10c-11d0-9ba8-00c04fd92ef5; "
1126 "dce_stub_data; "
1127 "content:\"one\"; distance:0; "
1128 "byte_test:1,=,1,6,relative; sid:1;)");
1129 FAIL_IF_NULL(s->next);
1130
1131 s = s->next;
1132 sm = DetectBufferGetFirstSigMatch(s, g_dce_stub_data_buffer_id);
1133 FAIL_IF_NULL(sm);
1134 FAIL_IF_NULL(sm->next);
1135 sm = sm->next;
1136 bd = (DetectBytetestData *)sm->ctx;
1137 FAIL_IF(bd->flags & DETECT_BYTETEST_DCE);
1139 FAIL_IF(bd->flags & DETECT_BYTETEST_STRING);
1140 FAIL_IF(bd->flags & DETECT_BYTETEST_BIG);
1141 FAIL_IF(bd->flags & DETECT_BYTETEST_LITTLE);
1142 FAIL_IF(bd->neg_op);
1143
1147
1148 PASS;
1149}
1150
1151/**
1152 * \test Test dce option.
1153 */
1154static int DetectBytetestTestParse21(void)
1155{
1156 DetectEngineCtx *de_ctx = NULL;
1157 Signature *s = NULL;
1158
1161
1162 de_ctx->flags |= DE_QUIET;
1163 s = SigInit(de_ctx, "alert tcp any any -> any any "
1164 "(msg:\"Testing bytetest_body\"; "
1165 "dce_iface:3919286a-b10c-11d0-9ba8-00c04fd92ef5; "
1166 "content:\"one\"; byte_test:1,=,1,6,string,dce; sid:1;)");
1168
1169 s = SigInit(de_ctx, "alert tcp any any -> any any "
1170 "(msg:\"Testing bytetest_body\"; "
1171 "dce_iface:3919286a-b10c-11d0-9ba8-00c04fd92ef5; "
1172 "content:\"one\"; byte_test:1,=,1,6,big,dce; sid:1;)");
1174
1175 s = SigInit(de_ctx, "alert tcp any any -> any any "
1176 "(msg:\"Testing bytetest_body\"; "
1177 "dce_iface:3919286a-b10c-11d0-9ba8-00c04fd92ef5; "
1178 "content:\"one\"; byte_test:1,=,1,6,little,dce; sid:1;)");
1180
1181 s = SigInit(de_ctx, "alert tcp any any -> any any "
1182 "(msg:\"Testing bytetest_body\"; "
1183 "dce_iface:3919286a-b10c-11d0-9ba8-00c04fd92ef5; "
1184 "content:\"one\"; byte_test:1,=,1,6,hex,dce; sid:1;)");
1186
1187 s = SigInit(de_ctx, "alert tcp any any -> any any "
1188 "(msg:\"Testing bytetest_body\"; "
1189 "dce_iface:3919286a-b10c-11d0-9ba8-00c04fd92ef5; "
1190 "content:\"one\"; byte_test:1,=,1,6,dec,dce; sid:1;)");
1192
1193 s = SigInit(de_ctx, "alert tcp any any -> any any "
1194 "(msg:\"Testing bytetest_body\"; "
1195 "dce_iface:3919286a-b10c-11d0-9ba8-00c04fd92ef5; "
1196 "content:\"one\"; byte_test:1,=,1,6,oct,dce; sid:1;)");
1198
1199 s = SigInit(de_ctx, "alert tcp any any -> any any "
1200 "(msg:\"Testing bytetest_body\"; "
1201 "dce_iface:3919286a-b10c-11d0-9ba8-00c04fd92ef5; "
1202 "content:\"one\"; byte_test:1,=,1,6,string,hex,dce; sid:1;)");
1204
1205 s = SigInit(de_ctx, "alert tcp any any -> any any "
1206 "(msg:\"Testing bytetest_body\"; "
1207 "dce_iface:3919286a-b10c-11d0-9ba8-00c04fd92ef5; "
1208 "content:\"one\"; byte_test:1,=,1,6,big,string,hex,dce; sid:1;)");
1210
1211 s = SigInit(de_ctx, "alert tcp any any -> any any "
1212 "(msg:\"Testing bytetest_body\"; "
1213 "dce_iface:3919286a-b10c-11d0-9ba8-00c04fd92ef5; "
1214 "content:\"one\"; byte_test:1,=,1,6,big,string,oct,dce; sid:1;)");
1216
1217 s = SigInit(de_ctx, "alert tcp any any -> any any "
1218 "(msg:\"Testing bytetest_body\"; "
1219 "dce_iface:3919286a-b10c-11d0-9ba8-00c04fd92ef5; "
1220 "content:\"one\"; byte_test:1,=,1,6,little,string,hex,dce; sid:1;)");
1222
1223 s = SigInit(de_ctx, "alert tcp any any -> any any "
1224 "(msg:\"Testing bytetest_body\"; "
1225 "dce_iface:3919286a-b10c-11d0-9ba8-00c04fd92ef5; "
1226 "content:\"one\"; byte_test:1,=,1,6,big,string,dec,dce; sid:1;)");
1228
1232
1233 PASS;
1234}
1235
1236/**
1237 * \test Test file_data
1238 */
1239static int DetectBytetestTestParse22(void)
1240{
1241 DetectEngineCtx *de_ctx = NULL;
1242 Signature *s = NULL;
1243 DetectBytetestData *bd = NULL;
1244
1247
1248 de_ctx->flags |= DE_QUIET;
1249 de_ctx->sig_list = SigInit(de_ctx, "alert tcp any any -> any any "
1250 "(file_data; byte_test:1,=,1,6,relative; sid:1;)");
1252
1253 s = de_ctx->sig_list;
1254 SigMatch *sm = DetectBufferGetFirstSigMatch(s, g_file_data_buffer_id);
1255 FAIL_IF_NULL(sm);
1257 bd = (DetectBytetestData *)sm->ctx;
1258 FAIL_IF(bd->flags & DETECT_BYTETEST_DCE);
1260 FAIL_IF(bd->flags & DETECT_BYTETEST_STRING);
1261 FAIL_IF(bd->flags & DETECT_BYTETEST_BIG);
1262 FAIL_IF(bd->flags & DETECT_BYTETEST_LITTLE);
1263 FAIL_IF(bd->neg_op);
1264
1268
1269 PASS;
1270}
1271
1272/**
1273 * \test Test bitmask option.
1274 */
1275static int DetectBytetestTestParse23(void)
1276{
1277 DetectBytetestData *data;
1278 data = DetectBytetestParse("4, <, 5, 0, bitmask 0xf8", NULL, NULL, NULL);
1279
1280 FAIL_IF_NULL(data);
1282 FAIL_IF_NOT(data->nbytes == 4);
1283 FAIL_IF_NOT(data->value == 5);
1284 FAIL_IF_NOT(data->offset == 0);
1286 FAIL_IF_NOT(data->bitmask == 0xf8);
1287 FAIL_IF_NOT(data->bitmask_shift_count == 3);
1288
1289 DetectBytetestFree(NULL, data);
1290
1291 PASS;
1292}
1293
1294/**
1295 * \test Test all options
1296 */
1297static int DetectBytetestTestParse24(void)
1298{
1299 DetectBytetestData *data;
1300 data = DetectBytetestParse(
1301 "4, !<, 5, 0, relative,string,hex, big, bitmask 0xf8", NULL, NULL, NULL);
1302 FAIL_IF_NULL(data);
1304 FAIL_IF_NOT(data->nbytes == 4);
1305 FAIL_IF_NOT(data->value == 5);
1306 FAIL_IF_NOT(data->offset == 0);
1312 FAIL_IF_NOT(data->bitmask == 0xf8);
1313 FAIL_IF_NOT(data->bitmask_shift_count == 3);
1314
1315 DetectBytetestFree(NULL, data);
1316
1317 PASS;
1318}
1319
1320/**
1321 * \brief this function registers unit tests for DetectBytetest
1322 */
1323static void DetectBytetestRegisterTests(void)
1324{
1325 g_file_data_buffer_id = DetectBufferTypeGetByName("file_data");
1326 g_dce_stub_data_buffer_id = DetectBufferTypeGetByName("dce_stub_data");
1327
1328 UtRegisterTest("DetectBytetestTestParse01", DetectBytetestTestParse01);
1329 UtRegisterTest("DetectBytetestTestParse02", DetectBytetestTestParse02);
1330 UtRegisterTest("DetectBytetestTestParse03", DetectBytetestTestParse03);
1331 UtRegisterTest("DetectBytetestTestParse04", DetectBytetestTestParse04);
1332 UtRegisterTest("DetectBytetestTestParse05", DetectBytetestTestParse05);
1333 UtRegisterTest("DetectBytetestTestParse06", DetectBytetestTestParse06);
1334 UtRegisterTest("DetectBytetestTestParse07", DetectBytetestTestParse07);
1335 UtRegisterTest("DetectBytetestTestParse08", DetectBytetestTestParse08);
1336 UtRegisterTest("DetectBytetestTestParse09", DetectBytetestTestParse09);
1337 UtRegisterTest("DetectBytetestTestParse10", DetectBytetestTestParse10);
1338 UtRegisterTest("DetectBytetestTestParse11", DetectBytetestTestParse11);
1339 UtRegisterTest("DetectBytetestTestParse12", DetectBytetestTestParse12);
1340 UtRegisterTest("DetectBytetestTestParse13", DetectBytetestTestParse13);
1341 UtRegisterTest("DetectBytetestTestParse14", DetectBytetestTestParse14);
1342 UtRegisterTest("DetectBytetestTestParse15", DetectBytetestTestParse15);
1343 UtRegisterTest("DetectBytetestTestParse16", DetectBytetestTestParse16);
1344 UtRegisterTest("DetectBytetestTestParse17", DetectBytetestTestParse17);
1345 UtRegisterTest("DetectBytetestTestParse18", DetectBytetestTestParse18);
1346 UtRegisterTest("DetectBytetestTestParse19", DetectBytetestTestParse19);
1347 UtRegisterTest("DetectBytetestTestParse20", DetectBytetestTestParse20);
1348 UtRegisterTest("DetectBytetestTestParse21", DetectBytetestTestParse21);
1349 UtRegisterTest("DetectBytetestTestParse22", DetectBytetestTestParse22);
1350 UtRegisterTest("DetectBytetestTestParse23", DetectBytetestTestParse23);
1351 UtRegisterTest("DetectBytetestTestParse24", DetectBytetestTestParse24);
1352}
1353#endif /* UNITTESTS */
uint8_t len
@ ALPROTO_DCERPC
uint8_t flags
Definition decode-gre.h:0
bool DetectByteRetrieveSMVar(const char *arg, const Signature *s, int sm_list, DetectByteIndexType *index)
Used to retrieve args from BM.
Definition detect-byte.c:41
uint8_t DetectByteIndexType
Definition detect-byte.h:28
void DetectBytetestRegister(void)
#define PARSE_REGEX
int DetectBytetestDoMatch(DetectEngineThreadCtx *det_ctx, const Signature *s, const SigMatchCtx *ctx, const uint8_t *payload, uint32_t payload_len, uint16_t flags, int32_t offset, int32_t nbytes, uint64_t value)
Bytetest detection code.
#define DETECT_BYTETEST_DCE
#define DETECT_BYTETEST_OP_OR
#define DETECT_BYTETEST_OP_LE
#define DETECT_BYTETEST_OP_LT
#define DETECT_BYTETEST_RELATIVE
#define DETECT_BYTETEST_OFFSET_VAR
#define DETECT_BYTETEST_BIG
#define DETECT_BYTETEST_BASE_OCT
#define DETECT_BYTETEST_STRING
#define DETECT_BYTETEST_BASE_HEX
#define DETECT_BYTETEST_VALUE_VAR
#define DETECT_BYTETEST_OP_GT
#define DETECT_BYTETEST_LITTLE
#define DETECT_BYTETEST_BITMASK
#define DETECT_BYTETEST_BASE_DEC
#define DETECT_BYTETEST_OP_EQ
#define DETECT_BYTETEST_BASE_UNSET
#define DETECT_BYTETEST_OP_AND
#define DETECT_BYTETEST_OP_GE
#define DETECT_BYTETEST_NBYTES_VAR
#define DETECT_CONTENT_RELATIVE_NEXT
SigMatch * DetectBufferGetFirstSigMatch(const Signature *s, const uint32_t buf_id)
int DetectBufferGetActiveList(DetectEngineCtx *de_ctx, Signature *s)
void SigCleanSignatures(DetectEngineCtx *de_ctx)
int SigGroupCleanup(DetectEngineCtx *de_ctx)
@ DETECT_BYTE_EXTRACT
@ DETECT_BYTEMATH
@ DETECT_BYTETEST
@ DETECT_BYTEJUMP
@ DETECT_ISDATAAT
DetectEngineCtx * DetectEngineCtxInit(void)
void DetectEngineCtxFree(DetectEngineCtx *)
Free a DetectEngineCtx::
void SigFree(DetectEngineCtx *, Signature *)
int DetectBufferTypeGetByName(const char *name)
void DetectSetupParseRegexes(const char *parse_str, DetectParseRegex *detect_parse)
int SCDetectSignatureSetAppProto(Signature *s, AppProto alproto)
int DetectParsePcreExec(DetectParseRegex *parse_regex, pcre2_match_data **match, const char *str, int start_offset, int options)
Signature * SigInit(DetectEngineCtx *de_ctx, const char *sigstr)
Parses a signature and adds it to the Detection Engine Context.
SigMatch * SCSigMatchAppendSMToList(DetectEngineCtx *de_ctx, Signature *s, uint16_t type, SigMatchCtx *ctx, const int list)
Append a SigMatch to the list type.
SigMatch * DetectGetLastSMFromLists(const Signature *s,...)
Returns the sm with the largest index (added latest) from the lists passed to us.
Signature * SigAlloc(void)
int SigMatchListSMBelongsTo(const Signature *s, const SigMatch *key_sm)
SigTableElmt * sigmatch_table
#define DETECT_PCRE_RELATIVE_NEXT
Definition detect-pcre.h:34
#define DE_QUIET
Definition detect.h:330
#define DETECT_SM_LIST_NOTSET
Definition detect.h:144
@ DETECT_SM_LIST_PMATCH
Definition detect.h:119
DetectEngineCtx * de_ctx
#define FAIL_IF_NULL(expr)
Fail a test if expression evaluates to NULL.
void UtRegisterTest(const char *name, int(*TestFn)(void))
Register unit test.
#define FAIL_IF_NOT(expr)
Fail a test if expression evaluates to false.
#define PASS
Pass the test.
#define FAIL_IF(expr)
Fail a test if expression evaluates to true.
#define FAIL_IF_NOT_NULL(expr)
Fail a test if expression evaluates to non-NULL.
struct Thresholds ctx
uint16_t payload_len
main detection engine ctx
Definition detect.h:932
uint8_t flags
Definition detect.h:934
Signature * sig_list
Definition detect.h:941
Used to start a pointer to SigMatch context Should never be dereferenced without casting to something...
Definition detect.h:351
a single match condition for a signature
Definition detect.h:356
uint16_t type
Definition detect.h:357
struct SigMatch_ * next
Definition detect.h:360
SigMatchCtx * ctx
Definition detect.h:359
const char * url
Definition detect.h:1462
int(* Setup)(DetectEngineCtx *, Signature *, const char *)
Definition detect.h:1441
void(* Free)(DetectEngineCtx *, void *)
Definition detect.h:1446
const char * desc
Definition detect.h:1461
void(* RegisterTests)(void)
Definition detect.h:1448
const char * name
Definition detect.h:1459
Signature container.
Definition detect.h:668
SignatureInitData * init_data
Definition detect.h:747
struct Signature_ * next
Definition detect.h:750
int StringParseUint32(uint32_t *res, int base, size_t len, const char *str)
Definition util-byte.c:313
int ByteExtractUint64(uint64_t *res, int e, uint16_t len, const uint8_t *bytes)
Definition util-byte.c:122
int ByteExtractStringUint32(uint32_t *res, int base, size_t len, const char *str)
Definition util-byte.c:239
int StringParseInt32(int32_t *res, int base, size_t len, const char *str)
Definition util-byte.c:622
int ByteExtractStringUint64(uint64_t *res, int base, size_t len, const char *str)
Definition util-byte.c:234
#define BYTE_BIG_ENDIAN
Definition util-byte.h:29
#define BYTE_LITTLE_ENDIAN
Definition util-byte.h:30
#define SCEnter(...)
Definition util-debug.h:277
#define SCLogDebug(...)
Definition util-debug.h:275
#define SCReturnInt(x)
Definition util-debug.h:281
#define SCLogError(...)
Macro used to log ERROR messages.
Definition util-debug.h:267
#define SCMalloc(sz)
Definition util-mem.h:47
#define SCFree(p)
Definition util-mem.h:61
#define SCStrdup(s)
Definition util-mem.h:56
#define unlikely(expr)
uint64_t offset