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