suricata
detect-bytejump.c
Go to the documentation of this file.
1/* Copyright (C) 2007-2020 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 *
23 * Implements byte_jump keyword.
24 */
25
26#include "suricata-common.h"
27#include "decode.h"
28#include "detect.h"
29#include "detect-parse.h"
30#include "detect-engine.h"
32#include "app-layer.h"
33
34#include "detect-byte.h"
35#include "detect-byte-extract.h"
36#include "detect-bytejump.h"
37#include "detect-content.h"
38#include "detect-uricontent.h"
39
40#include "util-byte.h"
41#include "util-unittest.h"
42#include "util-debug.h"
43#include "util-validate.h"
44#include "detect-pcre.h"
45#include "detect-engine-build.h"
46
47/**
48 * \brief Regex for parsing our options
49 */
50#define PARSE_REGEX "^\\s*" \
51 "([^\\s,]+\\s*,\\s*[^\\s,]+)" \
52 "(?:\\s*,\\s*((?:multiplier|post_offset)\\s+[^\\s,]+|[^\\s,]+))?" \
53 "(?:\\s*,\\s*((?:multiplier|post_offset)\\s+[^\\s,]+|[^\\s,]+))?" \
54 "(?:\\s*,\\s*((?:multiplier|post_offset)\\s+[^\\s,]+|[^\\s,]+))?" \
55 "(?:\\s*,\\s*((?:multiplier|post_offset)\\s+[^\\s,]+|[^\\s,]+))?" \
56 "(?:\\s*,\\s*((?:multiplier|post_offset)\\s+[^\\s,]+|[^\\s,]+))?" \
57 "(?:\\s*,\\s*((?:multiplier|post_offset)\\s+[^\\s,]+|[^\\s,]+))?" \
58 "(?:\\s*,\\s*((?:multiplier|post_offset)\\s+[^\\s,]+|[^\\s,]+))?" \
59 "(?:\\s*,\\s*((?:multiplier|post_offset)\\s+[^\\s,]+|[^\\s,]+))?" \
60 "(?:\\s*,\\s*((?:multiplier|post_offset)\\s+[^\\s,]+|[^\\s,]+))?" \
61 "\\s*$"
62
63static DetectParseRegex parse_regex;
64
65static DetectBytejumpData *DetectBytejumpParse(
66 DetectEngineCtx *de_ctx, const char *optstr, char **nbytes, char **offset);
67static int DetectBytejumpSetup(DetectEngineCtx *de_ctx, Signature *s, const char *optstr);
68static void DetectBytejumpFree(DetectEngineCtx*, void *ptr);
69#ifdef UNITTESTS
70static void DetectBytejumpRegisterTests(void);
71#endif
72
74{
75 sigmatch_table[DETECT_BYTEJUMP].name = "byte_jump";
76 sigmatch_table[DETECT_BYTEJUMP].desc = "allow the ability to select a <num of bytes> from an <offset> and move the detection pointer to that position";
77 sigmatch_table[DETECT_BYTEJUMP].url = "/rules/payload-keywords.html#byte-jump";
79 sigmatch_table[DETECT_BYTEJUMP].Setup = DetectBytejumpSetup;
80 sigmatch_table[DETECT_BYTEJUMP].Free = DetectBytejumpFree;
81#ifdef UNITTESTS
82 sigmatch_table[DETECT_BYTEJUMP].RegisterTests = DetectBytejumpRegisterTests;
83#endif
85}
86
87/* 23 - This is the largest string (octal, with a zero prefix) that
88 * will not overflow uint64_t. The only way this length
89 * could be over 23 and still not overflow is if it were zero
90 * prefixed and we only support 1 byte of zero prefix for octal.
91 *
92 * "01777777777777777777777" = 0xffffffffffffffff
93 *
94 * 8 - Without string, the maximum byte extract count is 8.
95 */
96static inline bool DetectBytejumpValidateNbytesOnly(const DetectBytejumpData *data, int32_t nbytes)
97{
98 return (data->flags & DETECT_BYTEJUMP_STRING && nbytes <= 23) || (nbytes <= 8);
99}
100
101static bool DetectBytejumpValidateNbytes(const DetectBytejumpData *data, int32_t nbytes)
102{
103 if (!DetectBytejumpValidateNbytesOnly(data, nbytes)) {
104 if (data->flags & DETECT_BYTEJUMP_STRING) {
105 /* 23 - This is the largest string (octal, with a zero prefix) that
106 * will not overflow uint64_t. The only way this length
107 * could be over 23 and still not overflow is if it were zero
108 * prefixed and we only support 1 byte of zero prefix for octal.
109 *
110 * "01777777777777777777777" = 0xffffffffffffffff
111 */
112 if (nbytes > 23) {
113 SCLogError("Cannot test more than 23 bytes "
114 "with \"string\"");
115 }
116 } else {
117 if (nbytes > 8) {
118 SCLogError("Cannot test more than 8 bytes "
119 "without \"string\"");
120 }
121 }
122 return false;
123 }
124
125 return true;
126}
127
128/** \brief Byte jump match function
129 * \param det_ctx thread detect engine ctx
130 * \param s signature
131 * \param m byte jump sigmatch
132 * \param payload ptr to the payload
133 * \param payload_len length of the payload
134 * \retval true match
135 * \retval false no match
136 */
138 const SigMatchCtx *ctx, const uint8_t *payload, uint32_t payload_len, uint16_t flags,
139 int32_t nbytes, int32_t offset)
140{
141 SCEnter();
142
143 const DetectBytejumpData *data = (const DetectBytejumpData *)ctx;
144 const uint8_t *ptr = NULL;
145 int32_t len = 0;
146 uint64_t val = 0;
147 int extbytes;
148
149 if (payload_len == 0) {
150 SCReturnBool(false);
151 }
152
153 /* Validate the number of bytes we are testing
154 * If the validation is successful, we know that
155 * it contains a value <= 23. Thus, we can
156 * safely cast it when extracting bytes
157 */
158 if (data->flags & DETECT_BYTEJUMP_NBYTES_VAR) {
159 if (!DetectBytejumpValidateNbytesOnly(data, nbytes)) {
160 SCLogDebug("Invalid byte_jump nbytes "
161 "seen in byte_jump - %d",
162 nbytes);
163 SCReturnBool(false);
164 }
165 }
166
167 /* Calculate the ptr value for the bytejump and length remaining in
168 * the packet from that point.
169 */
170 ptr = payload + offset;
173 ptr += det_ctx->buffer_offset;
174 len -= det_ctx->buffer_offset;
175
176 SCLogDebug("[relative] after: ptr %p [len %d]", ptr, len);
177
178 /* No match if there is no relative base */
179 if (ptr == NULL || (nbytes && len <= 0)) {
180 SCReturnBool(false);
181 }
182 }
183
184 /* Verify the to-be-extracted data is within the packet */
185 if (ptr < payload || nbytes > len) {
186 SCLogDebug("Data not within payload "
187 "pkt=%p, ptr=%p, len=%" PRIi32 ", nbytes=%" PRIi32,
188 payload, ptr, len, nbytes);
189 SCReturnBool(false);
190 }
191
192 /* Extract the byte data */
194 extbytes = ByteExtractStringUint64(&val, data->base, nbytes, (const char *)ptr);
195 if(extbytes <= 0) {
196 SCLogDebug("error extracting %d bytes of string data: %d", nbytes, extbytes);
197 SCReturnBool(false);
198 }
199 }
200 else {
202 extbytes = ByteExtractUint64(&val, endianness, (uint16_t)nbytes, ptr);
203 if (extbytes != nbytes) {
204 SCLogDebug("error extracting %d bytes of numeric data: %d", nbytes, extbytes);
205 SCReturnBool(false);
206 }
207 }
208
209 SCLogDebug("VAL: (%" PRIu64 " x %" PRIu32 ") + %" PRIi32 " + %" PRId32, val, data->multiplier,
210 extbytes, data->post_offset);
211
212 /* Adjust the jump value based on flags */
213 val *= data->multiplier;
215 if ((val % 4) != 0) {
216 val += 4 - (val % 4);
217 }
218 }
219 val += data->post_offset;
220 SCLogDebug("val: %" PRIi64 " post_offset: %" PRIi32, val, data->post_offset);
221
222 const uint8_t *jumpptr;
223 /* Calculate the jump location */
225 jumpptr = payload + (int64_t)val;
226 SCLogDebug("NEWVAL: payload %p + %" PRIi64 " = %p", payload, (int64_t)val, jumpptr + val);
227 } else if (flags & DETECT_BYTEJUMP_END) {
228 jumpptr = payload + payload_len + (int64_t)val;
230 "NEWVAL: payload %p + %" PRIu32 " + %" PRIi64, payload, payload_len, (int64_t)val);
231 } else {
232 jumpptr = ptr + (int64_t)val + extbytes;
233 SCLogDebug("NEWVAL: ptr %p + %" PRIi64 " = %p", ptr, val, jumpptr);
234 }
235
236 /* Validate that the jump location is still in the packet
237 * \todo Should this validate it is still in the *payload*?
238 */
239 if (jumpptr < payload) {
240 jumpptr = payload;
241 SCLogDebug("jump location is before buffer start; resetting to buffer start");
242 } else if (jumpptr > (payload + payload_len)) {
243 SCLogDebug("Jump location (%" PRIu64 ") is not within payload (%" PRIu32 ")",
244 payload_len + val, payload_len);
245 SCReturnBool(false);
246 }
247
248#ifdef DEBUG
249 if (SCLogDebugEnabled()) {
250 const uint8_t *sptr = (flags & DETECT_BYTEJUMP_BEGIN) ? payload : ptr;
251 SCLogDebug("jumping %" PRId64 " bytes from %p (%08x)", val, sptr, (int)(sptr - payload));
252 }
253#endif /* DEBUG */
254
255 /* Adjust the detection context to the jump location. */
256 DEBUG_VALIDATE_BUG_ON(jumpptr < payload);
257 det_ctx->buffer_offset = (uint32_t)(jumpptr - payload);
258
259 SCReturnBool(true);
260}
261
262static DetectBytejumpData *DetectBytejumpParse(
263 DetectEngineCtx *de_ctx, const char *optstr, char **nbytes_str, char **offset)
264{
265 DetectBytejumpData *data = NULL;
266 char args[10][64];
267 int res = 0;
268 size_t pcre2len;
269 int numargs = 0;
270 int i = 0;
271 uint32_t nbytes = 0;
272 char *str_ptr;
273 char *end_ptr;
274 pcre2_match_data *match = NULL;
275
276 memset(args, 0x00, sizeof(args));
277
278 /* Execute the regex and populate args with captures. */
279 int ret = DetectParsePcreExec(&parse_regex, &match, optstr, 0, 0);
280 if (ret < 2 || ret > 10) {
281 SCLogError("parse error, ret %" PRId32 ", string \"%s\"", ret, optstr);
282 goto error;
283 }
284
285 /* The first two arguments are stashed in the first PCRE substring.
286 * This is because byte_jump can take 10 arguments, but PCRE only
287 * supports 9 substrings, sigh.
288 */
289 char str[512] = "";
290 pcre2len = sizeof(str);
291 res = pcre2_substring_copy_bynumber(match, 1, (PCRE2_UCHAR8 *)str, &pcre2len);
292 if (res < 0) {
293 SCLogError("pcre2_substring_copy_bynumber failed "
294 "for arg 1");
295 goto error;
296 }
297
298 /* Break up first substring into two parameters
299 *
300 * NOTE: Because of this, we cannot free args[1] as it is part of args[0],
301 * and *yes* this *is* ugly.
302 */
303 end_ptr = str;
304 while (!(isspace((unsigned char)*end_ptr) || (*end_ptr == ','))) end_ptr++;
305 *(end_ptr++) = '\0';
306 strlcpy(args[0], str, sizeof(args[0]));
307 numargs++;
308
309 str_ptr = end_ptr;
310 while (isspace((unsigned char)*str_ptr) || (*str_ptr == ',')) str_ptr++;
311 end_ptr = str_ptr;
312 while (!(isspace((unsigned char)*end_ptr) || (*end_ptr == ',')) && (*end_ptr != '\0'))
313 end_ptr++;
314 *(end_ptr++) = '\0';
315 strlcpy(args[1], str_ptr, sizeof(args[1]));
316 numargs++;
317
318 /* The remaining args are directly from PCRE substrings */
319 for (i = 1; i < (ret - 1); i++) {
320 pcre2len = sizeof(args[0]);
321 res = pcre2_substring_copy_bynumber(match, i + 1, (PCRE2_UCHAR8 *)args[i + 1], &pcre2len);
322 if (res < 0) {
323 SCLogError("pcre2_substring_copy_bynumber failed for arg %d", i + 1);
324 goto error;
325 }
326 numargs++;
327 }
328
329 /* Initialize the data */
330 data = SCMalloc(sizeof(DetectBytejumpData));
331 if (unlikely(data == NULL))
332 goto error;
334 data->flags = 0;
335 data->multiplier = 1;
336 data->post_offset = 0;
337
338 /*
339 * The first two options are required and positional. The
340 * remaining arguments are flags and are not positional.
341 */
342
343 /* Number of bytes */
344 if (args[0][0] != '-' && isalpha((unsigned char)args[0][0])) {
345 if (nbytes_str == NULL) {
346 SCLogError("byte_jump supplied with "
347 "var name for nbytes. \"value\" argument supplied to "
348 "this function has to be non-NULL");
349 goto error;
350 }
351 *nbytes_str = SCStrdup(args[0]);
352 if (*nbytes_str == NULL)
353 goto error;
355 } else {
356 if (StringParseUint32(&nbytes, 10, (uint16_t)strlen(args[0]), args[0]) <= 0) {
357 SCLogError("Malformed number of bytes: %s", optstr);
358 goto error;
359 }
360 }
361
362 /* Offset */
363 if (args[1][0] != '-' && isalpha((unsigned char)args[1][0])) {
364 if (offset == NULL) {
365 SCLogError("byte_jump supplied with "
366 "var name for offset. \"value\" argument supplied to "
367 "this function has to be non-NULL");
368 goto error;
369 }
370 *offset = SCStrdup(args[1]);
371 if (*offset == NULL)
372 goto error;
373 } else {
375 &data->offset, 10, (uint16_t)strlen(args[1]), args[1], -65535, 65535) <= 0) {
376 SCLogError("Malformed offset: %s", optstr);
377 goto error;
378 }
379 }
380
381 /* The remaining options are flags. */
382 /** \todo Error on dups? */
383 for (i = 2; i < numargs; i++) {
384 if (strcmp("relative", args[i]) == 0) {
386 } else if (strcasecmp("string", args[i]) == 0) {
388 } else if (strcasecmp("dec", args[i]) == 0) {
390 } else if (strcasecmp("hex", args[i]) == 0) {
392 } else if (strcasecmp("oct", args[i]) == 0) {
394 } else if (strcasecmp("big", args[i]) == 0) {
395 if (data->flags & DETECT_BYTEJUMP_LITTLE) {
397 }
398 data->flags |= DETECT_BYTEJUMP_BIG;
399 } else if (strcasecmp("little", args[i]) == 0) {
401 } else if (strcasecmp("from_beginning", args[i]) == 0) {
403 } else if (strcasecmp("from_end", args[i]) == 0) {
404 data->flags |= DETECT_BYTEJUMP_END;
405 } else if (strcasecmp("align", args[i]) == 0) {
407 } else if (strncasecmp("multiplier ", args[i], 11) == 0) {
408 if (StringParseU16RangeCheck(&data->multiplier, 10, (uint16_t)strlen(args[i]) - 11,
409 args[i] + 11, 1, 65535) <= 0) {
410 SCLogError("Malformed multiplier: %s", optstr);
411 goto error;
412 }
413 } else if (strncasecmp("post_offset ", args[i], 12) == 0) {
414 if (StringParseI32RangeCheck(&data->post_offset, 10, (uint16_t)strlen(args[i]) - 12,
415 args[i] + 12, -65535, 65535) <= 0) {
416 SCLogError("Malformed post_offset: %s", optstr);
417 goto error;
418 }
419 SCLogDebug("post_offset: %s [%d]", optstr, data->post_offset);
420 } else if (strcasecmp("dce", args[i]) == 0) {
421 data->flags |= DETECT_BYTEJUMP_DCE;
422 } else {
423 SCLogError("Unknown option: \"%s\"", args[i]);
424 goto error;
425 }
426 }
427
428 if ((data->flags & DETECT_BYTEJUMP_END) && (data->flags & DETECT_BYTEJUMP_BEGIN)) {
429 SCLogError("'from_end' and 'from_beginning' "
430 "cannot be used in the same byte_jump statement");
431 goto error;
432 }
433
434 if (!(data->flags & DETECT_BYTEJUMP_NBYTES_VAR)) {
435 if (!DetectBytejumpValidateNbytes(data, nbytes)) {
436 goto error;
437 }
438
439 /* This is max 23 so it will fit in a byte (see validation function) */
440 data->nbytes = (uint8_t)nbytes;
441 }
442 if (!(data->flags & DETECT_BYTEJUMP_STRING)) {
443 if (data->base != DETECT_BYTEJUMP_BASE_UNSET) {
444 SCLogError("Cannot use a base "
445 "without \"string\": %s",
446 optstr);
447 goto error;
448 }
449 }
450
451 pcre2_match_data_free(match);
452 return data;
453
454error:
455 if (offset != NULL && *offset != NULL) {
456 SCFree(*offset);
457 *offset = NULL;
458 }
459 if (nbytes_str != NULL && *nbytes_str != NULL) {
460 SCFree(*nbytes_str);
461 *nbytes_str = NULL;
462 }
463 if (data != NULL)
464 DetectBytejumpFree(de_ctx, data);
465 if (match) {
466 pcre2_match_data_free(match);
467 }
468 return NULL;
469}
470
471static int DetectBytejumpSetup(DetectEngineCtx *de_ctx, Signature *s, const char *optstr)
472{
473 SigMatch *prev_pm = NULL;
474 DetectBytejumpData *data = NULL;
475 char *offset = NULL;
476 char *nbytes = NULL;
477 int ret = -1;
478
479 data = DetectBytejumpParse(de_ctx, optstr, &nbytes, &offset);
480 if (data == NULL)
481 goto error;
482
483 int sm_list;
485 if (DetectBufferGetActiveList(de_ctx, s) == -1)
486 goto error;
487
488 sm_list = s->init_data->list;
489
490 if (data->flags & DETECT_BYTEJUMP_RELATIVE) {
492 }
493 } else if (data->flags & DETECT_BYTEJUMP_DCE) {
494 if (data->flags & DETECT_BYTEJUMP_RELATIVE) {
495 prev_pm = DetectGetLastSMFromLists(s,
499 if (prev_pm == NULL) {
500 sm_list = DETECT_SM_LIST_PMATCH;
501 } else {
502 sm_list = SigMatchListSMBelongsTo(s, prev_pm);
503 if (sm_list < 0)
504 goto error;
505 }
506 } else {
507 sm_list = DETECT_SM_LIST_PMATCH;
508 }
509
511 goto error;
512
513 } else if (data->flags & DETECT_BYTEJUMP_RELATIVE) {
514 prev_pm = DetectGetLastSMFromLists(s,
518 if (prev_pm == NULL) {
519 sm_list = DETECT_SM_LIST_PMATCH;
520 } else {
521 sm_list = SigMatchListSMBelongsTo(s, prev_pm);
522 if (sm_list < 0)
523 goto error;
524 }
525
526 } else {
527 sm_list = DETECT_SM_LIST_PMATCH;
528 }
529
530 if (data->flags & DETECT_BYTEJUMP_DCE) {
531 if ((data->flags & DETECT_BYTEJUMP_STRING) ||
532 (data->flags & DETECT_BYTEJUMP_LITTLE) ||
533 (data->flags & DETECT_BYTEJUMP_BIG) ||
534 (data->flags & DETECT_BYTEJUMP_BEGIN) ||
535 (data->flags & DETECT_BYTEJUMP_END) ||
536 (data->base == DETECT_BYTEJUMP_BASE_DEC) ||
537 (data->base == DETECT_BYTEJUMP_BASE_HEX) ||
538 (data->base == DETECT_BYTEJUMP_BASE_OCT) ) {
539 SCLogError("Invalid option. "
540 "A byte_jump keyword with dce holds other invalid modifiers.");
541 goto error;
542 }
543 }
544
545 if (nbytes != NULL) {
547 if (!DetectByteRetrieveSMVar(nbytes, s, sm_list, &index)) {
548 SCLogError("Unknown byte_extract var "
549 "seen in byte_jump - %s",
550 nbytes);
551 goto error;
552 }
553 data->nbytes = index;
554 SCFree(nbytes);
555 nbytes = NULL;
556 }
557
558 if (offset != NULL) {
560 if (!DetectByteRetrieveSMVar(offset, s, sm_list, &index)) {
561 SCLogError("Unknown byte_extract var "
562 "seen in byte_jump - %s",
563 offset);
564 goto error;
565 }
566 data->offset = index;
568 SCFree(offset);
569 offset = NULL;
570 }
571
572 if (SCSigMatchAppendSMToList(de_ctx, s, DETECT_BYTEJUMP, (SigMatchCtx *)data, sm_list) ==
573 NULL) {
574 goto error;
575 }
576
577 if (!(data->flags & DETECT_BYTEJUMP_RELATIVE))
578 goto okay;
579
580 if (prev_pm == NULL)
581 goto okay;
582
583 if (prev_pm->type == DETECT_CONTENT) {
584 DetectContentData *cd = (DetectContentData *)prev_pm->ctx;
585 cd->flags |= DETECT_CONTENT_RELATIVE_NEXT;
586 } else if (prev_pm->type == DETECT_PCRE) {
587 DetectPcreData *pd = (DetectPcreData *)prev_pm->ctx;
588 pd->flags |= DETECT_PCRE_RELATIVE_NEXT;
589 }
590
591 okay:
592 ret = 0;
593 return ret;
594
595 error:
596 if (nbytes != NULL) {
597 SCFree(nbytes);
598 }
599 if (offset != NULL) {
600 SCFree(offset);
601 }
602 DetectBytejumpFree(de_ctx, data);
603 return ret;
604}
605
606/**
607 * \brief this function will free memory associated with DetectBytejumpData
608 *
609 * \param data pointer to DetectBytejumpData
610 */
611static void DetectBytejumpFree(DetectEngineCtx *de_ctx, void *ptr)
612{
613 if (ptr == NULL)
614 return;
615
617 SCFree(data);
618}
619
620
621/* UNITTESTS */
622#ifdef UNITTESTS
623#include "util-unittest-helper.h"
624static int g_file_data_buffer_id = 0;
625static int g_dce_stub_data_buffer_id = 0;
626
627/**
628 * \test DetectBytejumpTestParse01 is a test to make sure that we return
629 * "something" when given valid bytejump opt
630 */
631static int DetectBytejumpTestParse01(void)
632{
633 DetectBytejumpData *data = NULL;
634 data = DetectBytejumpParse(NULL, "4,0", NULL, NULL);
635 FAIL_IF_NULL(data);
636
637 DetectBytejumpFree(NULL, data);
638 PASS;
639}
640
641/**
642 * \test DetectBytejumpTestParse02 is a test for setting the required opts
643 */
644static int DetectBytejumpTestParse02(void)
645{
646 DetectBytejumpData *data = NULL;
647 data = DetectBytejumpParse(NULL, "4, 0", NULL, NULL);
648 FAIL_IF_NULL(data);
649 FAIL_IF_NOT(data->nbytes == 4);
650 FAIL_IF_NOT(data->offset == 0);
651 FAIL_IF_NOT(data->multiplier == 1);
652 FAIL_IF_NOT(data->post_offset == 0);
653 FAIL_IF_NOT(data->flags == 0);
655
656 DetectBytejumpFree(NULL, data);
657 PASS;
658}
659
660/**
661 * \test DetectBytejumpTestParse03 is a test for setting the optional flags
662 */
663static int DetectBytejumpTestParse03(void)
664{
665 DetectBytejumpData *data = NULL;
666 data = DetectBytejumpParse(NULL,
667 " 4,0 , relative , little, string, "
668 "dec, align, from_beginning",
669 NULL, NULL);
670 FAIL_IF_NULL(data);
671 FAIL_IF_NOT(data->nbytes == 4);
672 FAIL_IF_NOT(data->offset == 0);
673 FAIL_IF_NOT(data->multiplier == 1);
674 FAIL_IF_NOT(data->post_offset == 0);
675 FAIL_IF_NOT(data->flags ==
679
680 DetectBytejumpFree(NULL, data);
681 PASS;
682}
683
684/**
685 * \test DetectBytejumpTestParse04 is a test for setting the optional flags
686 * with parameters
687 *
688 * \todo This fails because we can only have 9 captures and there are 10.
689 */
690static int DetectBytejumpTestParse04(void)
691{
692 DetectBytejumpData *data = NULL;
693 data = DetectBytejumpParse(NULL,
694 " 4,0 , relative , little, string, "
695 "dec, align, from_beginning , "
696 "multiplier 2 , post_offset -16 ",
697 NULL, NULL);
698 FAIL_IF_NULL(data);
699 FAIL_IF_NOT(data->nbytes == 4);
700 FAIL_IF_NOT(data->offset == 0);
701 FAIL_IF_NOT(data->multiplier == 2);
702 FAIL_IF_NOT(data->post_offset == -16);
703 FAIL_IF_NOT(data->flags ==
707
708 DetectBytejumpFree(NULL, data);
709 PASS;
710}
711
712/**
713 * \test DetectBytejumpTestParse05 is a test for setting base without string
714 */
715static int DetectBytejumpTestParse05(void)
716{
717 DetectBytejumpData *data = NULL;
718 data = DetectBytejumpParse(NULL,
719 " 4,0 , relative , little, dec, "
720 "align, from_beginning",
721 NULL, NULL);
722 FAIL_IF_NOT_NULL(data);
723
724 PASS;
725}
726
727/**
728 * \test DetectBytejumpTestParse06 is a test for too many bytes to extract
729 */
730static int DetectBytejumpTestParse06(void)
731{
732 DetectBytejumpData *data = NULL;
733 data = DetectBytejumpParse(NULL, "9, 0", NULL, NULL);
734 FAIL_IF_NOT_NULL(data);
735
736 PASS;
737}
738
739/**
740 * \test DetectBytejumpTestParse07 is a test for too many string bytes to extract
741 */
742static int DetectBytejumpTestParse07(void)
743{
744 DetectBytejumpData *data = NULL;
745 data = DetectBytejumpParse(NULL, "24, 0, string, dec", NULL, NULL);
746 FAIL_IF_NOT_NULL(data);
747
748 PASS;
749}
750
751/**
752 * \test DetectBytejumpTestParse08 is a test for offset too big
753 */
754static int DetectBytejumpTestParse08(void)
755{
756 DetectBytejumpData *data = NULL;
757 data = DetectBytejumpParse(NULL, "4, 0xffffffffffffffff", NULL, NULL);
758 FAIL_IF_NOT_NULL(data);
759
760 PASS;
761}
762
763/**
764 * \test Test dce option.
765 */
766static int DetectBytejumpTestParse09(void)
767{
768 Signature *s = SigAlloc();
769 FAIL_IF_NULL(s);
770
772
773 FAIL_IF_NOT(DetectBytejumpSetup(NULL, s,
774 "4,0, align, multiplier 2, "
775 "post_offset -16,dce") == 0);
776 FAIL_IF_NOT(DetectBytejumpSetup(NULL, s,
777 "4,0, multiplier 2, "
778 "post_offset -16,dce") == 0);
779 FAIL_IF_NOT(DetectBytejumpSetup(NULL, s, "4,0,post_offset -16,dce") == 0);
780 FAIL_IF_NOT(DetectBytejumpSetup(NULL, s, "4,0,dce") == 0);
781 FAIL_IF_NOT(DetectBytejumpSetup(NULL, s, "4,0,dce") == 0);
782 FAIL_IF_NOT(DetectBytejumpSetup(NULL, s, "4,0, string, dce") == -1);
783 FAIL_IF_NOT(DetectBytejumpSetup(NULL, s, "4,0, big, dce") == -1);
784 FAIL_IF_NOT(DetectBytejumpSetup(NULL, s, "4,0, little, dce") == -1);
785 FAIL_IF_NOT(DetectBytejumpSetup(NULL, s, "4,0, string, dec, dce") == -1);
786 FAIL_IF_NOT(DetectBytejumpSetup(NULL, s, "4,0, string, oct, dce") == -1);
787 FAIL_IF_NOT(DetectBytejumpSetup(NULL, s, "4,0, string, hex, dce") == -1);
788 FAIL_IF_NOT(DetectBytejumpSetup(NULL, s, "4,0, from_beginning, dce") == -1);
789
791 SigMatch *sm = DetectBufferGetFirstSigMatch(s, g_dce_stub_data_buffer_id);
793
794 SigFree(NULL, s);
795 PASS;
796}
797
798/**
799 * \test Test dce option.
800 */
801static int DetectBytejumpTestParse10(void)
802{
806
807 Signature *s = DetectEngineAppendSig(de_ctx, "alert tcp any any -> any any "
808 "(msg:\"Testing bytejump_body\"; "
809 "dce_iface:3919286a-b10c-11d0-9ba8-00c04fd92ef5; "
810 "dce_stub_data; "
811 "content:\"one\"; distance:0; "
812 "byte_jump:4,0,align,multiplier 2, "
813 "post_offset -16,relative,dce; sid:1;)");
814 FAIL_IF_NULL(s);
815 SigMatch *sm = DetectBufferGetFirstSigMatch(s, g_dce_stub_data_buffer_id);
816 FAIL_IF_NULL(sm);
818 FAIL_IF_NULL(sm->next);
819 sm = sm->next;
821
823 FAIL_IF_NOT(bd->flags & DETECT_BYTEJUMP_DCE);
825 FAIL_IF(bd->flags & DETECT_BYTEJUMP_STRING);
826 FAIL_IF(bd->flags & DETECT_BYTEJUMP_BIG);
827 FAIL_IF(bd->flags & DETECT_BYTEJUMP_LITTLE);
828
829 s = DetectEngineAppendSig(de_ctx, "alert tcp any any -> any any "
830 "(msg:\"Testing bytejump_body\"; "
831 "dce_iface:3919286a-b10c-11d0-9ba8-00c04fd92ef5; "
832 "dce_stub_data; "
833 "content:\"one\"; distance:0; "
834 "byte_jump:4,0,align,multiplier 2, "
835 "post_offset -16,relative,dce; sid:2;)");
836 FAIL_IF_NULL(s);
837 sm = DetectBufferGetFirstSigMatch(s, g_dce_stub_data_buffer_id);
838 FAIL_IF_NULL(sm);
839
840 FAIL_IF_NOT(sm->type == DETECT_CONTENT);
841 FAIL_IF_NULL(sm->next);
842 sm = sm->next;
843 FAIL_IF_NOT(sm->type == DETECT_BYTEJUMP);
844
845 bd = (DetectBytejumpData *)sm->ctx;
846 FAIL_IF_NOT(bd->flags & DETECT_BYTEJUMP_DCE);
848 FAIL_IF(bd->flags & DETECT_BYTEJUMP_STRING);
849 FAIL_IF(bd->flags & DETECT_BYTEJUMP_BIG);
850 FAIL_IF(bd->flags & DETECT_BYTEJUMP_LITTLE);
851
852 s = DetectEngineAppendSig(de_ctx, "alert tcp any any -> any any "
853 "(msg:\"Testing bytejump_body\"; "
854 "dce_iface:3919286a-b10c-11d0-9ba8-00c04fd92ef5; "
855 "dce_stub_data; "
856 "content:\"one\"; distance:0; "
857 "byte_jump:4,0,align,multiplier 2, "
858 "post_offset -16,relative; sid:3;)");
859 FAIL_IF_NULL(s);
860 sm = DetectBufferGetFirstSigMatch(s, g_dce_stub_data_buffer_id);
861 FAIL_IF_NULL(sm);
862
863 FAIL_IF_NOT(sm->type == DETECT_CONTENT);
864 FAIL_IF_NULL(sm->next);
865 sm = sm->next;
866 FAIL_IF_NOT(sm->type == DETECT_BYTEJUMP);
867
868 bd = (DetectBytejumpData *)sm->ctx;
869 FAIL_IF(bd->flags & DETECT_BYTEJUMP_DCE);
871 FAIL_IF(bd->flags & DETECT_BYTEJUMP_STRING);
872 FAIL_IF(bd->flags & DETECT_BYTEJUMP_BIG);
873 FAIL_IF(bd->flags & DETECT_BYTEJUMP_LITTLE);
874
876 PASS;
877}
878
879/**
880 * \test Test dce option.
881 */
882static int DetectBytejumpTestParse11(void)
883{
884 DetectEngineCtx *de_ctx = NULL;
885 Signature *s = NULL;
886
889
891 s = SigInit(de_ctx, "alert tcp any any -> any any "
892 "(msg:\"Testing bytejump_body\"; "
893 "dce_iface:3919286a-b10c-11d0-9ba8-00c04fd92ef5; "
894 "dce_stub_data; "
895 "content:\"one\"; byte_jump:4,0,align,multiplier 2, "
896 "post_offset -16,string,dce; sid:1;)");
898
899 s = SigInit(de_ctx, "alert tcp any any -> any any "
900 "(msg:\"Testing bytejump_body\"; "
901 "dce_iface:3919286a-b10c-11d0-9ba8-00c04fd92ef5; "
902 "dce_sub_data; "
903 "content:\"one\"; byte_jump:4,0,align,multiplier 2, "
904 "post_offset -16,big,dce; sid:1;)");
906
907 s = SigInit(de_ctx, "alert tcp any any -> any any "
908 "(msg:\"Testing bytejump_body\"; "
909 "dce_iface:3919286a-b10c-11d0-9ba8-00c04fd92ef5; "
910 "dce_stub_data; "
911 "content:\"one\"; byte_jump:4,0,align,multiplier 2, "
912 "post_offset -16,little,dce; sid:1;)");
914
915 s = SigInit(de_ctx, "alert tcp any any -> any any "
916 "(msg:\"Testing bytejump_body\"; "
917 "dce_iface:3919286a-b10c-11d0-9ba8-00c04fd92ef5; "
918 "dce_stub_data; "
919 "content:\"one\"; byte_jump:4,0,align,multiplier 2, "
920 "post_offset -16,string,hex,dce; sid:1;)");
922
923 s = SigInit(de_ctx, "alert tcp any any -> any any "
924 "(msg:\"Testing bytejump_body\"; "
925 "dce_iface:3919286a-b10c-11d0-9ba8-00c04fd92ef5; "
926 "dce_stub_data; "
927 "content:\"one\"; byte_jump:4,0,align,multiplier 2, "
928 "post_offset -16,string,dec,dce; sid:1;)");
930
931 s = SigInit(de_ctx, "alert tcp any any -> any any "
932 "(msg:\"Testing bytejump_body\"; "
933 "dce_iface:3919286a-b10c-11d0-9ba8-00c04fd92ef5; "
934 "dce_stub_data; "
935 "content:\"one\"; byte_jump:4,0,align,multiplier 2, "
936 "post_offset -16,string,oct,dce; sid:1;)");
938
939 s = SigInit(de_ctx, "alert tcp any any -> any any "
940 "(msg:\"Testing bytejump_body\"; "
941 "dce_iface:3919286a-b10c-11d0-9ba8-00c04fd92ef5; "
942 "dce_stub_data; "
943 "content:\"one\"; byte_jump:4,0,align,multiplier 2, "
944 "post_offset -16,from_beginning,dce; sid:1;)");
946
950 PASS;
951}
952
953/**
954 * \test Test file_data
955 */
956static int DetectBytejumpTestParse12(void)
957{
961
962 Signature *s = DetectEngineAppendSig(de_ctx, "alert tcp any any -> any any "
963 "(file_data; byte_jump:4,0,align,multiplier 2, "
964 "post_offset -16,relative; sid:1;)");
965 FAIL_IF_NULL(s);
966
967 SigMatch *sm = DetectBufferGetFirstSigMatch(s, g_file_data_buffer_id);
968 FAIL_IF_NULL(sm);
970
972 FAIL_IF(bd->flags & DETECT_BYTEJUMP_DCE);
973 FAIL_IF((bd->flags &
976
978 PASS;
979}
980
981static int DetectBytejumpTestParse13(void)
982{
983 DetectBytejumpData *data = DetectBytejumpParse(NULL,
984 " 4,0 , relative , little, string, dec, "
985 "align, from_end",
986 NULL, NULL);
987 FAIL_IF_NULL(data);
989
990 DetectBytejumpFree(NULL, data);
991
992 PASS;
993}
994
995static int DetectBytejumpTestParse14(void)
996{
997 DetectBytejumpData *data = DetectBytejumpParse(NULL,
998 " 4,0 , relative , little, string, dec, "
999 "align, from_beginning, from_end",
1000 NULL, NULL);
1001
1002 FAIL_IF_NOT_NULL(data);
1003
1004 PASS;
1005}
1006
1007/**
1008 * \test DetectByteJumpTestPacket01 is a test to check matches of
1009 * byte_jump and byte_jump relative works if the previous keyword is pcre
1010 * (bug 142)
1011 */
1012static int DetectByteJumpTestPacket01 (void)
1013{
1014 uint8_t *buf = (uint8_t *)"GET /AllWorkAndNoPlayMakesWillADullBoy HTTP/1.0"
1015 "User-Agent: Wget/1.11.4"
1016 "Accept: */*"
1017 "Host: www.google.com"
1018 "Connection: Keep-Alive"
1019 "Date: Mon, 04 Jan 2010 17:29:39 GMT";
1020 uint16_t buflen = strlen((char *)buf);
1021 Packet *p;
1022 p = UTHBuildPacket((uint8_t *)buf, buflen, IPPROTO_TCP);
1023
1024 FAIL_IF_NULL(p);
1025
1026 char sig[] = "alert tcp any any -> any any (msg:\"pcre + byte_test + "
1027 "relative\"; pcre:\"/AllWorkAndNoPlayMakesWillADullBoy/\"; byte_jump:1,6,"
1028 "relative,string,dec; content:\"0\"; sid:134; rev:1;)";
1029
1031
1032 UTHFreePacket(p);
1033 PASS;
1034}
1035
1036/**
1037 * \test DetectByteJumpTestPacket02 is a test to check matches of
1038 * byte_jump and byte_jump relative works if the previous keyword is byte_jump
1039 * (bug 165)
1040 */
1041static int DetectByteJumpTestPacket02 (void)
1042{
1043 uint8_t buf[] = { 0x00, 0x00, 0x00, 0x77, 0xff, 0x53,
1044 0x4d, 0x42, 0x2f, 0x00, 0x00, 0x00, 0x00, 0x18,
1045 0x01, 0x20, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
1046 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x08,
1047 0x92, 0xa4, 0x01, 0x08, 0x17, 0x5c, 0x0e, 0xff,
1048 0x00, 0x00, 0x00, 0x01, 0x40, 0x48, 0x00, 0x00,
1049 0x00, 0xff };
1050 uint16_t buflen = sizeof(buf);
1051 Packet *p;
1052 p = UTHBuildPacket((uint8_t *)buf, buflen, IPPROTO_TCP);
1053
1054 FAIL_IF_NULL(p);
1055
1056 char sig[] = "alert tcp any any -> any any (msg:\"byte_jump with byte_jump"
1057 " + relative\"; byte_jump:1,13; byte_jump:4,0,relative; "
1058 "content:\"|48 00 00|\"; within:3; sid:144; rev:1;)";
1059
1061
1062 UTHFreePacket(p);
1063 PASS;
1064}
1065
1066static int DetectByteJumpTestPacket03(void)
1067{
1068 uint8_t *buf = NULL;
1069 uint16_t buflen = 0;
1070 buf = SCMalloc(4);
1071 if (unlikely(buf == NULL)) {
1072 printf("malloc failed\n");
1073 exit(EXIT_FAILURE);
1074 }
1075 memcpy(buf, "boom", 4);
1076 buflen = 4;
1077
1078 Packet *p;
1079 p = UTHBuildPacket((uint8_t *)buf, buflen, IPPROTO_TCP);
1080
1081 FAIL_IF_NULL(p);
1082
1083 char sig[] = "alert tcp any any -> any any (msg:\"byte_jump\"; "
1084 "byte_jump:1,214748364; sid:1; rev:1;)";
1085
1086 FAIL_IF(UTHPacketMatchSig(p, sig));
1087
1088 UTHFreePacket(p);
1089 FAIL_IF_NULL(buf);
1090
1091 SCFree(buf);
1092 PASS;
1093}
1094
1095/**
1096 * \test check matches of with from_beginning (bug 626/627)
1097 */
1098static int DetectByteJumpTestPacket04 (void)
1099{
1100 uint8_t *buf = (uint8_t *)"XYZ04abcdABCD";
1101 uint16_t buflen = strlen((char *)buf);
1102 Packet *p;
1103 p = UTHBuildPacket((uint8_t *)buf, buflen, IPPROTO_TCP);
1104
1105 FAIL_IF_NULL(p);
1106
1107 char sig[] = "alert tcp any any -> any any (content:\"XYZ\"; byte_jump:2,0,relative,string,dec; content:\"ABCD\"; distance:0; within:4; sid:1; rev:1;)";
1108
1110
1111 UTHFreePacket(p);
1112 PASS;
1113}
1114
1115/**
1116 * \test check matches of with from_beginning (bug 626/627)
1117 */
1118static int DetectByteJumpTestPacket05 (void)
1119{
1120 uint8_t *buf = (uint8_t *)"XYZ04abcdABCD";
1121 uint16_t buflen = strlen((char *)buf);
1122 Packet *p;
1123 p = UTHBuildPacket((uint8_t *)buf, buflen, IPPROTO_TCP);
1124
1125 FAIL_IF_NULL(p);
1126
1127 char sig[] = "alert tcp any any -> any any (content:\"XYZ\"; byte_jump:2,0,relative,string,dec; content:\"cdABCD\"; within:6; sid:1; rev:1;)";
1128
1129 FAIL_IF_NOT(UTHPacketMatchSig(p, sig) ? 0 : 1);
1130
1131 UTHFreePacket(p);
1132 PASS;
1133}
1134
1135/**
1136 * \test check matches of with from_beginning (bug 626/627)
1137 */
1138static int DetectByteJumpTestPacket06 (void)
1139{
1140 uint8_t *buf = (uint8_t *)"XX04abcdABCD";
1141 uint16_t buflen = strlen((char *)buf);
1142 Packet *p;
1143 p = UTHBuildPacket((uint8_t *)buf, buflen, IPPROTO_TCP);
1144
1145 FAIL_IF_NULL(p);
1146
1147 char sig[] = "alert tcp any any -> any any (content:\"XX\"; byte_jump:2,0,relative,string,dec,from_beginning; content:\"ABCD\"; distance:4; within:4; sid:1; rev:1;)";
1148
1150
1151 UTHFreePacket(p);
1152 PASS;
1153}
1154
1155/**
1156 * \test check matches of with from_beginning (bug 626/627)
1157 */
1158static int DetectByteJumpTestPacket07 (void)
1159{
1160 uint8_t *buf = (uint8_t *)"XX04abcdABCD";
1161 uint16_t buflen = strlen((char *)buf);
1162 Packet *p;
1163 p = UTHBuildPacket((uint8_t *)buf, buflen, IPPROTO_TCP);
1164
1165 FAIL_IF_NULL(p);
1166
1167 char sig[] = "alert tcp any any -> any any (content:\"XX\"; byte_jump:2,0,relative,string,dec,from_beginning; content:\"abcdABCD\"; distance:0; within:8; sid:1; rev:1;)";
1168
1169 FAIL_IF_NOT(UTHPacketMatchSig(p, sig) ? 1 : 0);
1170
1171 UTHFreePacket(p);
1172 PASS;
1173}
1174
1175/**
1176 * \test check matches of with from_end
1177 */
1178static int DetectByteJumpTestPacket08 (void)
1179{
1180 uint8_t *buf = (uint8_t *)"XX04abcdABCD";
1181 uint16_t buflen = strlen((char *)buf);
1182 Packet *p = UTHBuildPacket((uint8_t *)buf, buflen, IPPROTO_TCP);
1183
1184 FAIL_IF_NULL(p);
1185
1186 char sig[] = "alert tcp any any -> any any (content:\"XX\"; byte_jump:2,0,"
1187 "relative,string,dec,from_end, post_offset -8; content:\"ABCD\"; sid:1; rev:1;)";
1188
1190
1191 UTHFreePacket(p);
1192
1193 PASS;
1194}
1195
1196/**
1197 * \brief this function registers unit tests for DetectBytejump
1198 */
1199static void DetectBytejumpRegisterTests(void)
1200{
1201 g_file_data_buffer_id = DetectBufferTypeGetByName("file_data");
1202 g_dce_stub_data_buffer_id = DetectBufferTypeGetByName("dce_stub_data");
1203
1204 UtRegisterTest("DetectBytejumpTestParse01", DetectBytejumpTestParse01);
1205 UtRegisterTest("DetectBytejumpTestParse02", DetectBytejumpTestParse02);
1206 UtRegisterTest("DetectBytejumpTestParse03", DetectBytejumpTestParse03);
1207 UtRegisterTest("DetectBytejumpTestParse04", DetectBytejumpTestParse04);
1208 UtRegisterTest("DetectBytejumpTestParse05", DetectBytejumpTestParse05);
1209 UtRegisterTest("DetectBytejumpTestParse06", DetectBytejumpTestParse06);
1210 UtRegisterTest("DetectBytejumpTestParse07", DetectBytejumpTestParse07);
1211 UtRegisterTest("DetectBytejumpTestParse08", DetectBytejumpTestParse08);
1212 UtRegisterTest("DetectBytejumpTestParse09", DetectBytejumpTestParse09);
1213 UtRegisterTest("DetectBytejumpTestParse10", DetectBytejumpTestParse10);
1214 UtRegisterTest("DetectBytejumpTestParse11", DetectBytejumpTestParse11);
1215 UtRegisterTest("DetectBytejumpTestParse12", DetectBytejumpTestParse12);
1216 UtRegisterTest("DetectBytejumpTestParse13", DetectBytejumpTestParse13);
1217 UtRegisterTest("DetectBytejumpTestParse14", DetectBytejumpTestParse14);
1218
1219 UtRegisterTest("DetectByteJumpTestPacket01", DetectByteJumpTestPacket01);
1220 UtRegisterTest("DetectByteJumpTestPacket02", DetectByteJumpTestPacket02);
1221 UtRegisterTest("DetectByteJumpTestPacket03", DetectByteJumpTestPacket03);
1222 UtRegisterTest("DetectByteJumpTestPacket04", DetectByteJumpTestPacket04);
1223 UtRegisterTest("DetectByteJumpTestPacket05", DetectByteJumpTestPacket05);
1224 UtRegisterTest("DetectByteJumpTestPacket06", DetectByteJumpTestPacket06);
1225 UtRegisterTest("DetectByteJumpTestPacket07", DetectByteJumpTestPacket07);
1226 UtRegisterTest("DetectByteJumpTestPacket08", DetectByteJumpTestPacket08);
1227}
1228#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
bool DetectBytejumpDoMatch(DetectEngineThreadCtx *det_ctx, const Signature *s, const SigMatchCtx *ctx, const uint8_t *payload, uint32_t payload_len, uint16_t flags, int32_t nbytes, int32_t offset)
Byte jump match function.
void DetectBytejumpRegister(void)
#define PARSE_REGEX
Regex for parsing our options.
#define DETECT_BYTEJUMP_ALIGN
#define DETECT_BYTEJUMP_DCE
#define DETECT_BYTEJUMP_LITTLE
#define DETECT_BYTEJUMP_OFFSET_VAR
#define DETECT_BYTEJUMP_BASE_DEC
#define DETECT_BYTEJUMP_BASE_UNSET
#define DETECT_BYTEJUMP_END
#define DETECT_BYTEJUMP_RELATIVE
#define DETECT_BYTEJUMP_BIG
#define DETECT_BYTEJUMP_STRING
#define DETECT_BYTEJUMP_NBYTES_VAR
#define DETECT_BYTEJUMP_BEGIN
#define DETECT_BYTEJUMP_BASE_OCT
#define DETECT_BYTEJUMP_BASE_HEX
#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::
Signature * DetectEngineAppendSig(DetectEngineCtx *, const char *)
Parse and append a Signature into the Detection Engine Context signature list.
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
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
int(* Match)(DetectEngineThreadCtx *, Packet *, const Signature *, const SigMatchCtx *)
Definition detect.h:1421
const char * name
Definition detect.h:1459
struct SigMatch_ * smlists[DETECT_SM_LIST_MAX]
Definition detect.h:642
Signature container.
Definition detect.h:668
SignatureInitData * init_data
Definition detect.h:747
#define str(s)
size_t strlcpy(char *dst, const char *src, size_t siz)
int StringParseU16RangeCheck(uint16_t *res, int base, size_t len, const char *str, uint16_t min, uint16_t max)
Definition util-byte.c:433
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 StringParseI32RangeCheck(int32_t *res, int base, size_t len, const char *str, int32_t min, int32_t max)
Definition util-byte.c:716
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
int SCLogDebugEnabled(void)
Returns whether debug messages are enabled to be logged or not.
Definition util-debug.c:767
#define SCReturnBool(x)
Definition util-debug.h:295
#define SCEnter(...)
Definition util-debug.h:277
#define SCLogDebug(...)
Definition util-debug.h:275
#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
int UTHPacketMatchSig(Packet *p, const char *sig)
Packet * UTHBuildPacket(uint8_t *payload, uint16_t payload_len, uint8_t ipproto)
UTHBuildPacket is a wrapper that build packets with default ip and port fields.
void UTHFreePacket(Packet *p)
UTHFreePacket: function to release the allocated data from UTHBuildPacket and the packet itself.
#define DEBUG_VALIDATE_BUG_ON(exp)