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