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