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