suricata
detect-bytejump.c
Go to the documentation of this file.
1 /* Copyright (C) 2007-2020 Open Information Security Foundation
2  *
3  * You can copy, redistribute or modify this Program under the terms of
4  * the GNU General Public License version 2 as published by the Free
5  * Software Foundation.
6  *
7  * This program is distributed in the hope that it will be useful,
8  * but WITHOUT ANY WARRANTY; without even the implied warranty of
9  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
10  * GNU General Public License for more details.
11  *
12  * You should have received a copy of the GNU General Public License
13  * version 2 along with this program; if not, write to the Free Software
14  * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
15  * 02110-1301, USA.
16  */
17 
18 /**
19  * \file
20  *
21  * \author Brian Rectanus <brectanu@gmail.com>
22  *
23  * Implements byte_jump keyword.
24  */
25 
26 #include "suricata-common.h"
27 #include "decode.h"
28 #include "detect.h"
29 #include "detect-parse.h"
30 #include "detect-engine.h"
31 #include "detect-engine-buffer.h"
32 #include "app-layer.h"
33 
34 #include "detect-byte.h"
35 #include "detect-byte-extract.h"
36 #include "detect-bytejump.h"
37 #include "detect-content.h"
38 #include "detect-uricontent.h"
39 
40 #include "util-byte.h"
41 #include "util-debug.h"
42 #include "util-validate.h"
43 #include "detect-pcre.h"
44 #include "detect-engine-build.h"
45 
46 /**
47  * \brief Regex for parsing our options
48  */
49 #define PARSE_REGEX \
50  "^\\s*" \
51  "([^\\s,]+\\s*,\\s*[^\\s,]+)" \
52  "(?:\\s*,\\s*((?:multiplier|post_offset|bitmask)\\s+[^\\s,]+|[^\\s,]+))?" \
53  "(?:\\s*,\\s*((?:multiplier|post_offset|bitmask)\\s+[^\\s,]+|[^\\s,]+))?" \
54  "(?:\\s*,\\s*((?:multiplier|post_offset|bitmask)\\s+[^\\s,]+|[^\\s,]+))?" \
55  "(?:\\s*,\\s*((?:multiplier|post_offset|bitmask)\\s+[^\\s,]+|[^\\s,]+))?" \
56  "(?:\\s*,\\s*((?:multiplier|post_offset|bitmask)\\s+[^\\s,]+|[^\\s,]+))?" \
57  "(?:\\s*,\\s*((?:multiplier|post_offset|bitmask)\\s+[^\\s,]+|[^\\s,]+))?" \
58  "(?:\\s*,\\s*((?:multiplier|post_offset|bitmask)\\s+[^\\s,]+|[^\\s,]+))?" \
59  "(?:\\s*,\\s*((?:multiplier|post_offset|bitmask)\\s+[^\\s,]+|[^\\s,]+))?" \
60  "(?:\\s*,\\s*((?:multiplier|post_offset|bitmask)\\s+[^\\s,]+|[^\\s,]+))?" \
61  "(?:\\s*,\\s*((?:multiplier|post_offset|bitmask)\\s+[^\\s,]+|[^\\s,]+))?" \
62  "\\s*$"
63 
64 static DetectParseRegex parse_regex;
65 
66 static DetectBytejumpData *DetectBytejumpParse(
67  DetectEngineCtx *de_ctx, const char *optstr, char **nbytes, char **offset);
68 static int DetectBytejumpSetup(DetectEngineCtx *de_ctx, Signature *s, const char *optstr);
69 static void DetectBytejumpFree(DetectEngineCtx*, void *ptr);
70 #ifdef UNITTESTS
71 static void DetectBytejumpRegisterTests(void);
72 #endif
73 
75 {
76  sigmatch_table[DETECT_BYTEJUMP].name = "byte_jump";
77  sigmatch_table[DETECT_BYTEJUMP].desc = "allow the ability to select a <num of bytes> from an <offset> and move the detection pointer to that position";
78  sigmatch_table[DETECT_BYTEJUMP].url = "/rules/payload-keywords.html#byte-jump";
80  sigmatch_table[DETECT_BYTEJUMP].Setup = DetectBytejumpSetup;
81  sigmatch_table[DETECT_BYTEJUMP].Free = DetectBytejumpFree;
82 #ifdef UNITTESTS
83  sigmatch_table[DETECT_BYTEJUMP].RegisterTests = DetectBytejumpRegisterTests;
84 #endif
85  DetectSetupParseRegexes(PARSE_REGEX, &parse_regex);
86 }
87 
88 /* 23 - This is the largest string (octal, with a zero prefix) that
89  * will not overflow uint64_t. The only way this length
90  * could be over 23 and still not overflow is if it were zero
91  * prefixed and we only support 1 byte of zero prefix for octal.
92  *
93  * "01777777777777777777777" = 0xffffffffffffffff
94  *
95  * 8 - Without string, the maximum byte extract count is 8.
96  */
97 static inline bool DetectBytejumpValidateNbytesOnly(const DetectBytejumpData *data, int32_t nbytes)
98 {
99  return nbytes >= 0 && ((data->flags & DETECT_BYTEJUMP_STRING && nbytes <= 23) || (nbytes <= 8));
100 }
101 
102 static bool DetectBytejumpValidateNbytes(const DetectBytejumpData *data, int32_t nbytes)
103 {
104  if (!DetectBytejumpValidateNbytesOnly(data, nbytes)) {
105  if (data->flags & DETECT_BYTEJUMP_STRING) {
106  /* 23 - This is the largest string (octal, with a zero prefix) that
107  * will not overflow uint64_t. The only way this length
108  * could be over 23 and still not overflow is if it were zero
109  * prefixed and we only support 1 byte of zero prefix for octal.
110  *
111  * "01777777777777777777777" = 0xffffffffffffffff
112  */
113  if (nbytes > 23) {
114  SCLogError("Cannot test more than 23 bytes "
115  "with \"string\"");
116  }
117  } else {
118  if (nbytes > 8) {
119  SCLogError("Cannot test more than 8 bytes "
120  "without \"string\"");
121  }
122  }
123  return false;
124  }
125 
126  return true;
127 }
128 
129 /** \brief Byte jump match function
130  * \param det_ctx thread detect engine ctx
131  * \param s signature
132  * \param m byte jump sigmatch
133  * \param payload ptr to the payload
134  * \param payload_len length of the payload
135  * \retval true match
136  * \retval false no match
137  */
139  const SigMatchCtx *ctx, const uint8_t *payload, uint32_t payload_len, uint16_t flags,
140  int32_t nbytes, int32_t offset)
141 {
142  SCEnter();
143 
144  const DetectBytejumpData *data = (const DetectBytejumpData *)ctx;
145  const uint8_t *ptr = NULL;
146  int32_t len = 0;
147  uint64_t val = 0;
148  int extbytes;
149 
150  if (payload_len == 0) {
151  SCReturnBool(false);
152  }
153 
154  /* Validate the number of bytes we are testing
155  * If the validation is successful, we know that
156  * it contains a value <= 23. Thus, we can
157  * safely cast it when extracting bytes
158  */
159  if (data->flags & DETECT_BYTEJUMP_NBYTES_VAR) {
160  if (!DetectBytejumpValidateNbytesOnly(data, nbytes)) {
161  SCLogDebug("Invalid byte_jump nbytes "
162  "seen in byte_jump - %d",
163  nbytes);
164  SCReturnBool(false);
165  }
166  }
167 
168  /* Calculate the ptr value for the bytejump and length remaining in
169  * the packet from that point.
170  */
171  ptr = payload + offset;
172  len = payload_len - offset;
174  ptr += det_ctx->buffer_offset;
175  len -= det_ctx->buffer_offset;
176 
177  SCLogDebug("[relative] after: ptr %p [len %d]", ptr, len);
178 
179  /* No match if there is no relative base */
180  if (ptr == NULL || (nbytes && len <= 0)) {
181  SCReturnBool(false);
182  }
183  }
184 
185  /* Verify the to-be-extracted data is within the packet */
186  if (ptr < payload || nbytes > len) {
187  SCLogDebug("Data not within payload "
188  "pkt=%p, ptr=%p, len=%" PRIi32 ", nbytes=%" PRIi32,
189  payload, ptr, len, nbytes);
190  SCReturnBool(false);
191  }
192 
193  /* Extract the byte data */
195  extbytes = ByteExtractStringUint64(&val, data->base, nbytes, (const char *)ptr);
196  if(extbytes <= 0) {
197  SCLogDebug("error extracting %d bytes of string data: %d", nbytes, extbytes);
198  SCReturnBool(false);
199  }
200  }
201  else {
203  extbytes = ByteExtractUint64(&val, endianness, (uint16_t)nbytes, ptr);
204  if (extbytes != nbytes) {
205  SCLogDebug("error extracting %d bytes of numeric data: %d", nbytes, extbytes);
206  SCReturnBool(false);
207  }
208  }
209 
210  SCLogDebug("VAL: (%" PRIu64 " x %" PRIu32 ") + %" PRIi32 " + %" PRId32, val, data->multiplier,
211  extbytes, data->post_offset);
212 
213  /* Apply the bitmask value and bitmask shift count; note, the bitmask is applied
214  * before the multiplier per snort */
215  if (data->flags & DETECT_BYTEJUMP_BITMASK) {
216  SCLogDebug("[before bitmask] val: %" PRIi64 " bitmask_value: %" PRIx32, val,
217  data->bitmask_value);
218  val &= data->bitmask_value;
219  if (val && data->bitmask_shift_count) {
220  val = val >> data->bitmask_shift_count;
221  }
222  SCLogDebug("[after bitmask] val: %" PRIi64 " bitmask_value: %" PRIx32, val,
223  data->bitmask_value);
224  }
225 
226  /* Adjust the jump value based on flags */
227  val *= data->multiplier;
229  if ((val % 4) != 0) {
230  val += 4 - (val % 4);
231  }
232  }
233 
234  val += data->post_offset;
235  SCLogDebug("val: %" PRIi64 " post_offset: %" PRIi32, val, data->post_offset);
236 
237  const uint8_t *jumpptr;
238  /* Calculate the jump location */
240  jumpptr = payload + (int64_t)val;
241  SCLogDebug("NEWVAL: payload %p + %" PRIi64 " = %p", payload, (int64_t)val, jumpptr + val);
242  } else if (flags & DETECT_BYTEJUMP_END) {
243  jumpptr = payload + payload_len + (int64_t)val;
244  SCLogDebug(
245  "NEWVAL: payload %p + %" PRIu32 " + %" PRIi64, payload, payload_len, (int64_t)val);
246  } else {
247  jumpptr = ptr + (int64_t)val + extbytes;
248  SCLogDebug("NEWVAL: ptr %p + %" PRIi64 " = %p", ptr, val, jumpptr);
249  }
250 
251  /* Validate that the jump location is still in the packet
252  * \todo Should this validate it is still in the *payload*?
253  */
254  if (jumpptr < payload) {
255  jumpptr = payload;
256  SCLogDebug("jump location is before buffer start; resetting to buffer start");
257  } else if (jumpptr > (payload + payload_len)) {
258  SCLogDebug("Jump location (%" PRIu64 ") is not within payload (%" PRIu32 ")",
259  payload_len + val, payload_len);
260  SCReturnBool(false);
261  }
262 
263 #ifdef DEBUG
264  if (SCLogDebugEnabled()) {
265  const uint8_t *sptr = (flags & DETECT_BYTEJUMP_BEGIN) ? payload : ptr;
266  SCLogDebug("jumping %" PRId64 " bytes from %p (%08x)", val, sptr, (int)(sptr - payload));
267  }
268 #endif /* DEBUG */
269 
270  /* Adjust the detection context to the jump location. */
271  DEBUG_VALIDATE_BUG_ON(jumpptr < payload);
272  det_ctx->buffer_offset = (uint32_t)(jumpptr - payload);
273 
274  SCReturnBool(true);
275 }
276 
277 static DetectBytejumpData *DetectBytejumpParse(
278  DetectEngineCtx *de_ctx, const char *optstr, char **nbytes_str, char **offset)
279 {
280  DetectBytejumpData *data = NULL;
281  char args[11][64];
282  int res = 0;
283  size_t pcre2len;
284  int numargs = 0;
285  int i = 0;
286  uint32_t nbytes = 0;
287  char *str_ptr;
288  char *end_ptr;
289  pcre2_match_data *match = NULL;
290 
291  memset(args, 0x00, sizeof(args));
292 
293  /* Execute the regex and populate args with captures. */
294  int ret = DetectParsePcreExec(&parse_regex, &match, optstr, 0, 0);
295  if (ret < 2 || ret > 11) {
296  SCLogError("parse error, ret %" PRId32 ", string \"%s\"", ret, optstr);
297  goto error;
298  }
299 
300  /* The first two arguments are stashed in the first PCRE substring.
301  * This is because byte_jump can take 10 arguments, but PCRE only
302  * supports 9 substrings, sigh.
303  */
304  char str[512] = "";
305  pcre2len = sizeof(str);
306  res = pcre2_substring_copy_bynumber(match, 1, (PCRE2_UCHAR8 *)str, &pcre2len);
307  if (res < 0) {
308  SCLogError("pcre2_substring_copy_bynumber failed "
309  "for arg 1");
310  goto error;
311  }
312 
313  /* Break up first substring into two parameters
314  *
315  * NOTE: Because of this, we cannot free args[1] as it is part of args[0],
316  * and *yes* this *is* ugly.
317  */
318  end_ptr = str;
319  while (!(isspace((unsigned char)*end_ptr) || (*end_ptr == ','))) end_ptr++;
320  *(end_ptr++) = '\0';
321  strlcpy(args[0], str, sizeof(args[0]));
322  numargs++;
323 
324  str_ptr = end_ptr;
325  while (isspace((unsigned char)*str_ptr) || (*str_ptr == ',')) str_ptr++;
326  end_ptr = str_ptr;
327  while (!(isspace((unsigned char)*end_ptr) || (*end_ptr == ',')) && (*end_ptr != '\0'))
328  end_ptr++;
329  *(end_ptr++) = '\0';
330  strlcpy(args[1], str_ptr, sizeof(args[1]));
331  numargs++;
332 
333  /* The remaining args are directly from PCRE substrings */
334  for (i = 1; i < (ret - 1); i++) {
335  pcre2len = sizeof(args[0]);
336  res = pcre2_substring_copy_bynumber(match, i + 1, (PCRE2_UCHAR8 *)args[i + 1], &pcre2len);
337  if (res < 0) {
338  SCLogError("pcre2_substring_copy_bynumber failed for arg %d", i + 1);
339  goto error;
340  }
341  numargs++;
342  }
343 
344  /* Initialize the data */
345  data = SCMalloc(sizeof(DetectBytejumpData));
346  if (unlikely(data == NULL))
347  goto error;
349  data->flags = 0;
350  data->multiplier = 1;
351  data->post_offset = 0;
352 
353  /*
354  * The first two options are required and positional. The
355  * remaining arguments are flags and are not positional.
356  */
357 
358  /* Number of bytes */
359  if (args[0][0] != '-' && isalpha((unsigned char)args[0][0])) {
360  if (nbytes_str == NULL) {
361  SCLogError("byte_jump supplied with "
362  "var name for nbytes. \"value\" argument supplied to "
363  "this function has to be non-NULL");
364  goto error;
365  }
366  *nbytes_str = SCStrdup(args[0]);
367  if (*nbytes_str == NULL)
368  goto error;
370  } else {
371  if (StringParseUint32(&nbytes, 10, (uint16_t)strlen(args[0]), args[0]) <= 0) {
372  SCLogError("Malformed number of bytes: %s", optstr);
373  goto error;
374  }
375  }
376 
377  /* Offset */
378  if (args[1][0] != '-' && isalpha((unsigned char)args[1][0])) {
379  if (offset == NULL) {
380  SCLogError("byte_jump supplied with "
381  "var name for offset. \"value\" argument supplied to "
382  "this function has to be non-NULL");
383  goto error;
384  }
385  *offset = SCStrdup(args[1]);
386  if (*offset == NULL)
387  goto error;
388  } else {
390  &data->offset, 10, (uint16_t)strlen(args[1]), args[1], -65535, 65535) <= 0) {
391  SCLogError("Malformed offset: %s", optstr);
392  goto error;
393  }
394  }
395 
396  /* The remaining options are flags. */
397  /** \todo Error on dups? */
398  for (i = 2; i < numargs; i++) {
399  if (strcmp("relative", args[i]) == 0) {
401  } else if (strcasecmp("string", args[i]) == 0) {
402  data->flags |= DETECT_BYTEJUMP_STRING;
403  } else if (strcasecmp("dec", args[i]) == 0) {
405  } else if (strcasecmp("hex", args[i]) == 0) {
407  } else if (strcasecmp("oct", args[i]) == 0) {
409  } else if (strcasecmp("big", args[i]) == 0) {
410  if (data->flags & DETECT_BYTEJUMP_LITTLE) {
411  data->flags ^= DETECT_BYTEJUMP_LITTLE;
412  }
413  data->flags |= DETECT_BYTEJUMP_BIG;
414  } else if (strcasecmp("little", args[i]) == 0) {
415  data->flags |= DETECT_BYTEJUMP_LITTLE;
416  } else if (strcasecmp("from_beginning", args[i]) == 0) {
417  data->flags |= DETECT_BYTEJUMP_BEGIN;
418  } else if (strcasecmp("from_end", args[i]) == 0) {
419  data->flags |= DETECT_BYTEJUMP_END;
420  } else if (strcasecmp("align", args[i]) == 0) {
421  data->flags |= DETECT_BYTEJUMP_ALIGN;
422  } else if (strncasecmp("multiplier ", args[i], 11) == 0) {
423  if (StringParseU16RangeCheck(&data->multiplier, 10, (uint16_t)strlen(args[i]) - 11,
424  args[i] + 11, 1, 65535) <= 0) {
425  SCLogError("Malformed multiplier: %s", optstr);
426  goto error;
427  }
428  } else if (strncasecmp("post_offset ", args[i], 12) == 0) {
429  if (StringParseI32RangeCheck(&data->post_offset, 10, (uint16_t)strlen(args[i]) - 12,
430  args[i] + 12, -65535, 65535) <= 0) {
431  SCLogError("Malformed post_offset: %s", optstr);
432  goto error;
433  }
434  SCLogDebug("post_offset: %s [%d]", optstr, data->post_offset);
435  } else if (strncasecmp("bitmask ", args[i], 8) == 0) {
437  if (ByteExtractStringUint32(&data->bitmask_value, 0, 0, args[i] + strlen("bitmask ")) <=
438  0) {
439  SCLogError("Malformed bitmask: %s", optstr);
440  goto error;
441  }
442  if (data->bitmask_value == 0) {
443  SCLogError("Invalid bitmask value: %d", data->bitmask_value);
444  goto error;
445  }
446  } else if (strcasecmp("dce", args[i]) == 0) {
447  data->flags |= DETECT_BYTEJUMP_DCE;
448  } else {
449  SCLogError("Unknown option: \"%s\"", args[i]);
450  goto error;
451  }
452  }
453 
454  if ((data->flags & DETECT_BYTEJUMP_END) && (data->flags & DETECT_BYTEJUMP_BEGIN)) {
455  SCLogError("'from_end' and 'from_beginning' "
456  "cannot be used in the same byte_jump statement");
457  goto error;
458  }
459 
460  if (!(data->flags & DETECT_BYTEJUMP_NBYTES_VAR)) {
461  if (!DetectBytejumpValidateNbytes(data, nbytes)) {
462  goto error;
463  }
464 
465  /* This is max 23 so it will fit in a byte (see validation function) */
466  data->nbytes = (uint8_t)nbytes;
467  }
468  if (!(data->flags & DETECT_BYTEJUMP_STRING)) {
469  if (data->base != DETECT_BYTEJUMP_BASE_UNSET) {
470  SCLogError("Cannot use a base "
471  "without \"string\": %s",
472  optstr);
473  goto error;
474  }
475  }
476 
477  data->bitmask_shift_count = 0;
478  if (data->flags & DETECT_BYTEJUMP_BITMASK) {
479  uint32_t bmask = data->bitmask_value;
480  while (!(bmask & 0x1)) {
481  bmask = bmask >> 1;
482  data->bitmask_shift_count++;
483  }
484  SCLogDebug("bitmask value 0x%x -> shift value %d", data->bitmask_value,
485  data->bitmask_shift_count);
486  }
487 
488  pcre2_match_data_free(match);
489  return data;
490 
491 error:
492  if (offset != NULL && *offset != NULL) {
493  SCFree(*offset);
494  *offset = NULL;
495  }
496  if (nbytes_str != NULL && *nbytes_str != NULL) {
497  SCFree(*nbytes_str);
498  *nbytes_str = NULL;
499  }
500  if (data != NULL)
501  DetectBytejumpFree(de_ctx, data);
502  if (match) {
503  pcre2_match_data_free(match);
504  }
505  return NULL;
506 }
507 
508 static int DetectBytejumpSetup(DetectEngineCtx *de_ctx, Signature *s, const char *optstr)
509 {
510  SigMatch *prev_pm = NULL;
511  DetectBytejumpData *data = NULL;
512  char *offset = NULL;
513  char *nbytes = NULL;
514  int ret = -1;
515 
516  data = DetectBytejumpParse(de_ctx, optstr, &nbytes, &offset);
517  if (data == NULL)
518  goto error;
519 
520  int sm_list;
521  if (s->init_data->list != DETECT_SM_LIST_NOTSET) {
522  if (DetectBufferGetActiveList(de_ctx, s) == -1)
523  goto error;
524 
525  sm_list = s->init_data->list;
526 
527  if (data->flags & DETECT_BYTEJUMP_RELATIVE) {
529  }
530  } else if (data->flags & DETECT_BYTEJUMP_DCE) {
531  if (data->flags & DETECT_BYTEJUMP_RELATIVE) {
534  if (prev_pm == NULL) {
535  sm_list = DETECT_SM_LIST_PMATCH;
536  } else {
537  sm_list = SigMatchListSMBelongsTo(s, prev_pm);
538  if (sm_list < 0)
539  goto error;
540  }
541  } else {
542  sm_list = DETECT_SM_LIST_PMATCH;
543  }
544 
546  goto error;
547 
548  } else if (data->flags & DETECT_BYTEJUMP_RELATIVE) {
551  if (prev_pm == NULL) {
552  sm_list = DETECT_SM_LIST_PMATCH;
553  } else {
554  sm_list = SigMatchListSMBelongsTo(s, prev_pm);
555  if (sm_list < 0)
556  goto error;
557  }
558 
559  } else {
560  sm_list = DETECT_SM_LIST_PMATCH;
561  }
562 
563  if (data->flags & DETECT_BYTEJUMP_DCE) {
564  if ((data->flags & DETECT_BYTEJUMP_STRING) ||
565  (data->flags & DETECT_BYTEJUMP_LITTLE) ||
566  (data->flags & DETECT_BYTEJUMP_BIG) ||
567  (data->flags & DETECT_BYTEJUMP_BEGIN) ||
568  (data->flags & DETECT_BYTEJUMP_END) ||
569  (data->base == DETECT_BYTEJUMP_BASE_DEC) ||
570  (data->base == DETECT_BYTEJUMP_BASE_HEX) ||
571  (data->base == DETECT_BYTEJUMP_BASE_OCT) ) {
572  SCLogError("Invalid option. "
573  "A byte_jump keyword with dce holds other invalid modifiers.");
574  goto error;
575  }
576  }
577 
578  if (nbytes != NULL) {
579  DetectByteIndexType index;
580  if (!DetectByteRetrieveSMVar(nbytes, s, sm_list, &index)) {
581  SCLogError("Unknown byte_extract var "
582  "seen in byte_jump - %s",
583  nbytes);
584  goto error;
585  }
586  data->nbytes = index;
587  SCFree(nbytes);
588  nbytes = NULL;
589  }
590 
591  if (offset != NULL) {
592  DetectByteIndexType index;
593  if (!DetectByteRetrieveSMVar(offset, s, sm_list, &index)) {
594  SCLogError("Unknown byte_extract var "
595  "seen in byte_jump - %s",
596  offset);
597  goto error;
598  }
599  data->offset = index;
601  SCFree(offset);
602  offset = NULL;
603  }
604 
605  if (SCSigMatchAppendSMToList(de_ctx, s, DETECT_BYTEJUMP, (SigMatchCtx *)data, sm_list) ==
606  NULL) {
607  goto error;
608  }
609 
610  if (!(data->flags & DETECT_BYTEJUMP_RELATIVE))
611  goto okay;
612 
613  if (prev_pm == NULL)
614  goto okay;
615 
616  if (prev_pm->type == DETECT_CONTENT) {
617  DetectContentData *cd = (DetectContentData *)prev_pm->ctx;
619  } else if (prev_pm->type == DETECT_PCRE) {
620  DetectPcreData *pd = (DetectPcreData *)prev_pm->ctx;
622  }
623 
624  okay:
625  ret = 0;
626  return ret;
627 
628  error:
629  if (nbytes != NULL) {
630  SCFree(nbytes);
631  }
632  if (offset != NULL) {
633  SCFree(offset);
634  }
635  DetectBytejumpFree(de_ctx, data);
636  return ret;
637 }
638 
639 /**
640  * \brief this function will free memory associated with DetectBytejumpData
641  *
642  * \param data pointer to DetectBytejumpData
643  */
644 static void DetectBytejumpFree(DetectEngineCtx *de_ctx, void *ptr)
645 {
646  if (ptr == NULL)
647  return;
648 
649  DetectBytejumpData *data = (DetectBytejumpData *)ptr;
650  SCFree(data);
651 }
652 
653 
654 /* UNITTESTS */
655 #ifdef UNITTESTS
656 #include "util-unittest-helper.h"
657 static int g_file_data_buffer_id = 0;
658 static int g_dce_stub_data_buffer_id = 0;
659 
660 /**
661  * \test DetectBytejumpTestParse01 is a test to make sure that we return
662  * "something" when given valid bytejump opt
663  */
664 static int DetectBytejumpTestParse01(void)
665 {
666  DetectBytejumpData *data = NULL;
667  data = DetectBytejumpParse(NULL, "4,0", NULL, NULL);
668  FAIL_IF_NULL(data);
669 
670  DetectBytejumpFree(NULL, data);
671  PASS;
672 }
673 
674 /**
675  * \test DetectBytejumpTestParse02 is a test for setting the required opts
676  */
677 static int DetectBytejumpTestParse02(void)
678 {
679  DetectBytejumpData *data = NULL;
680  data = DetectBytejumpParse(NULL, "4, 0", NULL, NULL);
681  FAIL_IF_NULL(data);
682  FAIL_IF_NOT(data->nbytes == 4);
683  FAIL_IF_NOT(data->offset == 0);
684  FAIL_IF_NOT(data->multiplier == 1);
685  FAIL_IF_NOT(data->post_offset == 0);
686  FAIL_IF_NOT(data->flags == 0);
688 
689  DetectBytejumpFree(NULL, data);
690  PASS;
691 }
692 
693 /**
694  * \test DetectBytejumpTestParse03 is a test for setting the optional flags
695  */
696 static int DetectBytejumpTestParse03(void)
697 {
698  DetectBytejumpData *data = NULL;
699  data = DetectBytejumpParse(NULL,
700  " 4,0 , relative , little, string, "
701  "dec, align, from_beginning",
702  NULL, NULL);
703  FAIL_IF_NULL(data);
704  FAIL_IF_NOT(data->nbytes == 4);
705  FAIL_IF_NOT(data->offset == 0);
706  FAIL_IF_NOT(data->multiplier == 1);
707  FAIL_IF_NOT(data->post_offset == 0);
708  FAIL_IF_NOT(data->flags ==
712 
713  DetectBytejumpFree(NULL, data);
714  PASS;
715 }
716 
717 /**
718  * \test DetectBytejumpTestParse04 is a test for setting the optional flags
719  * with parameters
720  *
721  * \todo This fails because we can only have 9 captures and there are 10.
722  */
723 static int DetectBytejumpTestParse04(void)
724 {
725  DetectBytejumpData *data = NULL;
726  data = DetectBytejumpParse(NULL,
727  " 4,0 , relative , little, string, "
728  "dec, align, from_beginning , "
729  "multiplier 2 , post_offset -16 ",
730  NULL, NULL);
731  FAIL_IF_NULL(data);
732  FAIL_IF_NOT(data->nbytes == 4);
733  FAIL_IF_NOT(data->offset == 0);
734  FAIL_IF_NOT(data->multiplier == 2);
735  FAIL_IF_NOT(data->post_offset == -16);
736  FAIL_IF_NOT(data->flags ==
740 
741  DetectBytejumpFree(NULL, data);
742  PASS;
743 }
744 
745 /**
746  * \test DetectBytejumpTestParse05 is a test for setting base without string
747  */
748 static int DetectBytejumpTestParse05(void)
749 {
750  DetectBytejumpData *data = NULL;
751  data = DetectBytejumpParse(NULL,
752  " 4,0 , relative , little, dec, "
753  "align, from_beginning",
754  NULL, NULL);
755  FAIL_IF_NOT_NULL(data);
756 
757  PASS;
758 }
759 
760 /**
761  * \test DetectBytejumpTestParse06 is a test for too many bytes to extract
762  */
763 static int DetectBytejumpTestParse06(void)
764 {
765  DetectBytejumpData *data = NULL;
766  data = DetectBytejumpParse(NULL, "9, 0", NULL, NULL);
767  FAIL_IF_NOT_NULL(data);
768 
769  PASS;
770 }
771 
772 /**
773  * \test DetectBytejumpTestParse07 is a test for too many string bytes to extract
774  */
775 static int DetectBytejumpTestParse07(void)
776 {
777  DetectBytejumpData *data = NULL;
778  data = DetectBytejumpParse(NULL, "24, 0, string, dec", NULL, NULL);
779  FAIL_IF_NOT_NULL(data);
780 
781  PASS;
782 }
783 
784 /**
785  * \test DetectBytejumpTestParse08 is a test for offset too big
786  */
787 static int DetectBytejumpTestParse08(void)
788 {
789  DetectBytejumpData *data = NULL;
790  data = DetectBytejumpParse(NULL, "4, 0xffffffffffffffff", NULL, NULL);
791  FAIL_IF_NOT_NULL(data);
792 
793  PASS;
794 }
795 
796 /**
797  * \test Test dce option.
798  */
799 static int DetectBytejumpTestParse09(void)
800 {
801  Signature *s = SigAlloc();
802  FAIL_IF_NULL(s);
803 
805 
806  FAIL_IF_NOT(DetectBytejumpSetup(NULL, s,
807  "4,0, align, multiplier 2, "
808  "post_offset -16,dce") == 0);
809  FAIL_IF_NOT(DetectBytejumpSetup(NULL, s,
810  "4,0, multiplier 2, "
811  "post_offset -16,dce") == 0);
812  FAIL_IF_NOT(DetectBytejumpSetup(NULL, s, "4,0,post_offset -16,dce") == 0);
813  FAIL_IF_NOT(DetectBytejumpSetup(NULL, s, "4,0,dce") == 0);
814  FAIL_IF_NOT(DetectBytejumpSetup(NULL, s, "4,0,dce") == 0);
815  FAIL_IF_NOT(DetectBytejumpSetup(NULL, s, "4,0, string, dce") == -1);
816  FAIL_IF_NOT(DetectBytejumpSetup(NULL, s, "4,0, big, dce") == -1);
817  FAIL_IF_NOT(DetectBytejumpSetup(NULL, s, "4,0, little, dce") == -1);
818  FAIL_IF_NOT(DetectBytejumpSetup(NULL, s, "4,0, string, dec, dce") == -1);
819  FAIL_IF_NOT(DetectBytejumpSetup(NULL, s, "4,0, string, oct, dce") == -1);
820  FAIL_IF_NOT(DetectBytejumpSetup(NULL, s, "4,0, string, hex, dce") == -1);
821  FAIL_IF_NOT(DetectBytejumpSetup(NULL, s, "4,0, from_beginning, dce") == -1);
822 
824  SigMatch *sm = DetectBufferGetFirstSigMatch(s, g_dce_stub_data_buffer_id);
825  FAIL_IF_NOT_NULL(sm);
826 
827  SigFree(NULL, s);
828  PASS;
829 }
830 
831 /**
832  * \test Test dce option.
833  */
834 static int DetectBytejumpTestParse10(void)
835 {
838  de_ctx->flags |= DE_QUIET;
839 
840  Signature *s = DetectEngineAppendSig(de_ctx, "alert tcp any any -> any any "
841  "(msg:\"Testing bytejump_body\"; "
842  "dce_iface:3919286a-b10c-11d0-9ba8-00c04fd92ef5; "
843  "dce_stub_data; "
844  "content:\"one\"; distance:0; "
845  "byte_jump:4,0,align,multiplier 2, "
846  "post_offset -16,relative,dce; sid:1;)");
847  FAIL_IF_NULL(s);
848  SigMatch *sm = DetectBufferGetFirstSigMatch(s, g_dce_stub_data_buffer_id);
849  FAIL_IF_NULL(sm);
851  FAIL_IF_NULL(sm->next);
852  sm = sm->next;
854 
861 
862  s = DetectEngineAppendSig(de_ctx, "alert tcp any any -> any any "
863  "(msg:\"Testing bytejump_body\"; "
864  "dce_iface:3919286a-b10c-11d0-9ba8-00c04fd92ef5; "
865  "dce_stub_data; "
866  "content:\"one\"; distance:0; "
867  "byte_jump:4,0,align,multiplier 2, "
868  "post_offset -16,relative,dce; sid:2;)");
869  FAIL_IF_NULL(s);
870  sm = DetectBufferGetFirstSigMatch(s, g_dce_stub_data_buffer_id);
871  FAIL_IF_NULL(sm);
872 
874  FAIL_IF_NULL(sm->next);
875  sm = sm->next;
877 
878  bd = (DetectBytejumpData *)sm->ctx;
884 
885  s = DetectEngineAppendSig(de_ctx, "alert tcp any any -> any any "
886  "(msg:\"Testing bytejump_body\"; "
887  "dce_iface:3919286a-b10c-11d0-9ba8-00c04fd92ef5; "
888  "dce_stub_data; "
889  "content:\"one\"; distance:0; "
890  "byte_jump:4,0,align,multiplier 2, "
891  "post_offset -16,relative; sid:3;)");
892  FAIL_IF_NULL(s);
893  sm = DetectBufferGetFirstSigMatch(s, g_dce_stub_data_buffer_id);
894  FAIL_IF_NULL(sm);
895 
897  FAIL_IF_NULL(sm->next);
898  sm = sm->next;
900 
901  bd = (DetectBytejumpData *)sm->ctx;
907 
909  PASS;
910 }
911 
912 /**
913  * \test Test dce option.
914  */
915 static int DetectBytejumpTestParse11(void)
916 {
917  DetectEngineCtx *de_ctx = NULL;
918  Signature *s = NULL;
919 
922 
923  de_ctx->flags |= DE_QUIET;
924  s = SigInit(de_ctx, "alert tcp any any -> any any "
925  "(msg:\"Testing bytejump_body\"; "
926  "dce_iface:3919286a-b10c-11d0-9ba8-00c04fd92ef5; "
927  "dce_stub_data; "
928  "content:\"one\"; byte_jump:4,0,align,multiplier 2, "
929  "post_offset -16,string,dce; sid:1;)");
930  FAIL_IF_NOT_NULL(s);
931 
932  s = SigInit(de_ctx, "alert tcp any any -> any any "
933  "(msg:\"Testing bytejump_body\"; "
934  "dce_iface:3919286a-b10c-11d0-9ba8-00c04fd92ef5; "
935  "dce_sub_data; "
936  "content:\"one\"; byte_jump:4,0,align,multiplier 2, "
937  "post_offset -16,big,dce; sid:1;)");
938  FAIL_IF_NOT_NULL(s);
939 
940  s = SigInit(de_ctx, "alert tcp any any -> any any "
941  "(msg:\"Testing bytejump_body\"; "
942  "dce_iface:3919286a-b10c-11d0-9ba8-00c04fd92ef5; "
943  "dce_stub_data; "
944  "content:\"one\"; byte_jump:4,0,align,multiplier 2, "
945  "post_offset -16,little,dce; sid:1;)");
946  FAIL_IF_NOT_NULL(s);
947 
948  s = SigInit(de_ctx, "alert tcp any any -> any any "
949  "(msg:\"Testing bytejump_body\"; "
950  "dce_iface:3919286a-b10c-11d0-9ba8-00c04fd92ef5; "
951  "dce_stub_data; "
952  "content:\"one\"; byte_jump:4,0,align,multiplier 2, "
953  "post_offset -16,string,hex,dce; sid:1;)");
954  FAIL_IF_NOT_NULL(s);
955 
956  s = SigInit(de_ctx, "alert tcp any any -> any any "
957  "(msg:\"Testing bytejump_body\"; "
958  "dce_iface:3919286a-b10c-11d0-9ba8-00c04fd92ef5; "
959  "dce_stub_data; "
960  "content:\"one\"; byte_jump:4,0,align,multiplier 2, "
961  "post_offset -16,string,dec,dce; sid:1;)");
962  FAIL_IF_NOT_NULL(s);
963 
964  s = SigInit(de_ctx, "alert tcp any any -> any any "
965  "(msg:\"Testing bytejump_body\"; "
966  "dce_iface:3919286a-b10c-11d0-9ba8-00c04fd92ef5; "
967  "dce_stub_data; "
968  "content:\"one\"; byte_jump:4,0,align,multiplier 2, "
969  "post_offset -16,string,oct,dce; sid:1;)");
970  FAIL_IF_NOT_NULL(s);
971 
972  s = SigInit(de_ctx, "alert tcp any any -> any any "
973  "(msg:\"Testing bytejump_body\"; "
974  "dce_iface:3919286a-b10c-11d0-9ba8-00c04fd92ef5; "
975  "dce_stub_data; "
976  "content:\"one\"; byte_jump:4,0,align,multiplier 2, "
977  "post_offset -16,from_beginning,dce; sid:1;)");
978  FAIL_IF_NOT_NULL(s);
979 
983  PASS;
984 }
985 
986 /**
987  * \test Test file_data
988  */
989 static int DetectBytejumpTestParse12(void)
990 {
993  de_ctx->flags |= DE_QUIET;
994 
995  Signature *s = DetectEngineAppendSig(de_ctx, "alert tcp any any -> any any "
996  "(file_data; byte_jump:4,0,align,multiplier 2, "
997  "post_offset -16,relative; sid:1;)");
998  FAIL_IF_NULL(s);
999 
1000  SigMatch *sm = DetectBufferGetFirstSigMatch(s, g_file_data_buffer_id);
1001  FAIL_IF_NULL(sm);
1003 
1006  FAIL_IF((bd->flags &
1009 
1011  PASS;
1012 }
1013 
1014 static int DetectBytejumpTestParse13(void)
1015 {
1016  DetectBytejumpData *data = DetectBytejumpParse(NULL,
1017  " 4,0 , relative , little, string, dec, "
1018  "align, from_end",
1019  NULL, NULL);
1020  FAIL_IF_NULL(data);
1022 
1023  DetectBytejumpFree(NULL, data);
1024 
1025  PASS;
1026 }
1027 
1028 static int DetectBytejumpTestParse14(void)
1029 {
1030  DetectBytejumpData *data = DetectBytejumpParse(NULL,
1031  " 4,0 , relative , little, string, dec, "
1032  "align, from_beginning, from_end",
1033  NULL, NULL);
1034 
1035  FAIL_IF_NOT_NULL(data);
1036 
1037  PASS;
1038 }
1039 
1040 static int DetectBytejumpTestParse15(void)
1041 {
1044  de_ctx->flags |= DE_QUIET;
1045 
1046  Signature *s =
1047  DetectEngineAppendSig(de_ctx, "alert tcp any any -> any any "
1048  "(msg:\"Testing bytejump_body\"; "
1049  "dce_iface:3919286a-b10c-11d0-9ba8-00c04fd92ef5; "
1050  "dce_stub_data; "
1051  "content:\"one\"; distance:0; "
1052  "byte_jump:4,0,align,multiplier 2, "
1053  "post_offset -16,relative,bitmask 0x8f40,dce; sid:1;)");
1054  FAIL_IF_NULL(s);
1055  SigMatch *sm = DetectBufferGetFirstSigMatch(s, g_dce_stub_data_buffer_id);
1056  FAIL_IF_NULL(sm);
1058  FAIL_IF_NULL(sm->next);
1059  sm = sm->next;
1061 
1068 
1070  FAIL_IF_NOT(bd->bitmask_value == 0x8f40);
1071  FAIL_IF_NOT(bd->bitmask_shift_count == 6);
1072 
1074  PASS;
1075 }
1076 
1077 static int DetectBytejumpTestParse16(void)
1078 {
1081  de_ctx->flags |= DE_QUIET;
1082 
1083  Signature *s =
1084  DetectEngineAppendSig(de_ctx, "alert tcp any any -> any any "
1085  "(msg:\"Testing bytejump_body\"; "
1086  "dce_iface:3919286a-b10c-11d0-9ba8-00c04fd92ef5; "
1087  "dce_stub_data; "
1088  "content:\"one\"; distance:0; "
1089  "byte_jump:4,0,align,multiplier 2, "
1090  "post_offset -16,relative,bitmask 5304,dce; sid:1;)");
1091  FAIL_IF_NULL(s);
1092  SigMatch *sm = DetectBufferGetFirstSigMatch(s, g_dce_stub_data_buffer_id);
1093  FAIL_IF_NULL(sm);
1095  FAIL_IF_NULL(sm->next);
1096  sm = sm->next;
1098 
1105 
1107  FAIL_IF_NOT(bd->bitmask_value == 5304);
1108  FAIL_IF_NOT(bd->bitmask_shift_count == 3);
1109 
1111  PASS;
1112 }
1113 
1114 /**
1115  * \test DetectByteJumpTestPacket01 is a test to check matches of
1116  * byte_jump and byte_jump relative works if the previous keyword is pcre
1117  * (bug 142)
1118  */
1119 static int DetectByteJumpTestPacket01 (void)
1120 {
1121  uint8_t *buf = (uint8_t *)"GET /AllWorkAndNoPlayMakesWillADullBoy HTTP/1.0"
1122  "User-Agent: Wget/1.11.4"
1123  "Accept: */*"
1124  "Host: www.google.com"
1125  "Connection: Keep-Alive"
1126  "Date: Mon, 04 Jan 2010 17:29:39 GMT";
1127  uint16_t buflen = strlen((char *)buf);
1128  Packet *p;
1129  p = UTHBuildPacket((uint8_t *)buf, buflen, IPPROTO_TCP);
1130 
1131  FAIL_IF_NULL(p);
1132 
1133  char sig[] = "alert tcp any any -> any any (msg:\"pcre + byte_test + "
1134  "relative\"; pcre:\"/AllWorkAndNoPlayMakesWillADullBoy/\"; byte_jump:1,6,"
1135  "relative,string,dec; content:\"0\"; sid:134; rev:1;)";
1136 
1138 
1139  UTHFreePacket(p);
1140  PASS;
1141 }
1142 
1143 /**
1144  * \test DetectByteJumpTestPacket02 is a test to check matches of
1145  * byte_jump and byte_jump relative works if the previous keyword is byte_jump
1146  * (bug 165)
1147  */
1148 static int DetectByteJumpTestPacket02 (void)
1149 {
1150  uint8_t buf[] = { 0x00, 0x00, 0x00, 0x77, 0xff, 0x53,
1151  0x4d, 0x42, 0x2f, 0x00, 0x00, 0x00, 0x00, 0x18,
1152  0x01, 0x20, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
1153  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x08,
1154  0x92, 0xa4, 0x01, 0x08, 0x17, 0x5c, 0x0e, 0xff,
1155  0x00, 0x00, 0x00, 0x01, 0x40, 0x48, 0x00, 0x00,
1156  0x00, 0xff };
1157  uint16_t buflen = sizeof(buf);
1158  Packet *p;
1159  p = UTHBuildPacket((uint8_t *)buf, buflen, IPPROTO_TCP);
1160 
1161  FAIL_IF_NULL(p);
1162 
1163  char sig[] = "alert tcp any any -> any any (msg:\"byte_jump with byte_jump"
1164  " + relative\"; byte_jump:1,13; byte_jump:4,0,relative; "
1165  "content:\"|48 00 00|\"; within:3; sid:144; rev:1;)";
1166 
1168 
1169  UTHFreePacket(p);
1170  PASS;
1171 }
1172 
1173 static int DetectByteJumpTestPacket03(void)
1174 {
1175  uint8_t *buf = NULL;
1176  uint16_t buflen = 0;
1177  buf = SCMalloc(4);
1178  if (unlikely(buf == NULL)) {
1179  printf("malloc failed\n");
1180  exit(EXIT_FAILURE);
1181  }
1182  memcpy(buf, "boom", 4);
1183  buflen = 4;
1184 
1185  Packet *p;
1186  p = UTHBuildPacket((uint8_t *)buf, buflen, IPPROTO_TCP);
1187 
1188  FAIL_IF_NULL(p);
1189 
1190  char sig[] = "alert tcp any any -> any any (msg:\"byte_jump\"; "
1191  "byte_jump:1,214748364; sid:1; rev:1;)";
1192 
1193  FAIL_IF(UTHPacketMatchSig(p, sig));
1194 
1195  UTHFreePacket(p);
1196  FAIL_IF_NULL(buf);
1197 
1198  SCFree(buf);
1199  PASS;
1200 }
1201 
1202 /**
1203  * \test check matches of with from_beginning (bug 626/627)
1204  */
1205 static int DetectByteJumpTestPacket04 (void)
1206 {
1207  uint8_t *buf = (uint8_t *)"XYZ04abcdABCD";
1208  uint16_t buflen = strlen((char *)buf);
1209  Packet *p;
1210  p = UTHBuildPacket((uint8_t *)buf, buflen, IPPROTO_TCP);
1211 
1212  FAIL_IF_NULL(p);
1213 
1214  char sig[] = "alert tcp any any -> any any (content:\"XYZ\"; byte_jump:2,0,relative,string,dec; content:\"ABCD\"; distance:0; within:4; sid:1; rev:1;)";
1215 
1217 
1218  UTHFreePacket(p);
1219  PASS;
1220 }
1221 
1222 /**
1223  * \test check matches of with from_beginning (bug 626/627)
1224  */
1225 static int DetectByteJumpTestPacket05 (void)
1226 {
1227  uint8_t *buf = (uint8_t *)"XYZ04abcdABCD";
1228  uint16_t buflen = strlen((char *)buf);
1229  Packet *p;
1230  p = UTHBuildPacket((uint8_t *)buf, buflen, IPPROTO_TCP);
1231 
1232  FAIL_IF_NULL(p);
1233 
1234  char sig[] = "alert tcp any any -> any any (content:\"XYZ\"; byte_jump:2,0,relative,string,dec; content:\"cdABCD\"; within:6; sid:1; rev:1;)";
1235 
1236  FAIL_IF_NOT(UTHPacketMatchSig(p, sig) ? 0 : 1);
1237 
1238  UTHFreePacket(p);
1239  PASS;
1240 }
1241 
1242 /**
1243  * \test check matches of with from_beginning (bug 626/627)
1244  */
1245 static int DetectByteJumpTestPacket06 (void)
1246 {
1247  uint8_t *buf = (uint8_t *)"XX04abcdABCD";
1248  uint16_t buflen = strlen((char *)buf);
1249  Packet *p;
1250  p = UTHBuildPacket((uint8_t *)buf, buflen, IPPROTO_TCP);
1251 
1252  FAIL_IF_NULL(p);
1253 
1254  char sig[] = "alert tcp any any -> any any (content:\"XX\"; byte_jump:2,0,relative,string,dec,from_beginning; content:\"ABCD\"; distance:4; within:4; sid:1; rev:1;)";
1255 
1257 
1258  UTHFreePacket(p);
1259  PASS;
1260 }
1261 
1262 /**
1263  * \test check matches of with from_beginning (bug 626/627)
1264  */
1265 static int DetectByteJumpTestPacket07 (void)
1266 {
1267  uint8_t *buf = (uint8_t *)"XX04abcdABCD";
1268  uint16_t buflen = strlen((char *)buf);
1269  Packet *p;
1270  p = UTHBuildPacket((uint8_t *)buf, buflen, IPPROTO_TCP);
1271 
1272  FAIL_IF_NULL(p);
1273 
1274  char sig[] = "alert tcp any any -> any any (content:\"XX\"; byte_jump:2,0,relative,string,dec,from_beginning; content:\"abcdABCD\"; distance:0; within:8; sid:1; rev:1;)";
1275 
1276  FAIL_IF_NOT(UTHPacketMatchSig(p, sig) ? 1 : 0);
1277 
1278  UTHFreePacket(p);
1279  PASS;
1280 }
1281 
1282 /**
1283  * \test check matches of with from_end
1284  */
1285 static int DetectByteJumpTestPacket08 (void)
1286 {
1287  uint8_t *buf = (uint8_t *)"XX04abcdABCD";
1288  uint16_t buflen = strlen((char *)buf);
1289  Packet *p = UTHBuildPacket((uint8_t *)buf, buflen, IPPROTO_TCP);
1290 
1291  FAIL_IF_NULL(p);
1292 
1293  char sig[] = "alert tcp any any -> any any (content:\"XX\"; byte_jump:2,0,"
1294  "relative,string,dec,from_end, post_offset -8; content:\"ABCD\"; sid:1; rev:1;)";
1295 
1297 
1298  UTHFreePacket(p);
1299 
1300  PASS;
1301 }
1302 
1303 /**
1304  * \brief this function registers unit tests for DetectBytejump
1305  */
1306 static void DetectBytejumpRegisterTests(void)
1307 {
1308  g_file_data_buffer_id = DetectBufferTypeGetByName("file_data");
1309  g_dce_stub_data_buffer_id = DetectBufferTypeGetByName("dce_stub_data");
1310 
1311  UtRegisterTest("DetectBytejumpTestParse01", DetectBytejumpTestParse01);
1312  UtRegisterTest("DetectBytejumpTestParse02", DetectBytejumpTestParse02);
1313  UtRegisterTest("DetectBytejumpTestParse03", DetectBytejumpTestParse03);
1314  UtRegisterTest("DetectBytejumpTestParse04", DetectBytejumpTestParse04);
1315  UtRegisterTest("DetectBytejumpTestParse05", DetectBytejumpTestParse05);
1316  UtRegisterTest("DetectBytejumpTestParse06", DetectBytejumpTestParse06);
1317  UtRegisterTest("DetectBytejumpTestParse07", DetectBytejumpTestParse07);
1318  UtRegisterTest("DetectBytejumpTestParse08", DetectBytejumpTestParse08);
1319  UtRegisterTest("DetectBytejumpTestParse09", DetectBytejumpTestParse09);
1320  UtRegisterTest("DetectBytejumpTestParse10", DetectBytejumpTestParse10);
1321  UtRegisterTest("DetectBytejumpTestParse11", DetectBytejumpTestParse11);
1322  UtRegisterTest("DetectBytejumpTestParse12", DetectBytejumpTestParse12);
1323  UtRegisterTest("DetectBytejumpTestParse13", DetectBytejumpTestParse13);
1324  UtRegisterTest("DetectBytejumpTestParse14", DetectBytejumpTestParse14);
1325  UtRegisterTest("DetectBytejumpTestParse15", DetectBytejumpTestParse15);
1326  UtRegisterTest("DetectBytejumpTestParse16", DetectBytejumpTestParse16);
1327 
1328  UtRegisterTest("DetectByteJumpTestPacket01", DetectByteJumpTestPacket01);
1329  UtRegisterTest("DetectByteJumpTestPacket02", DetectByteJumpTestPacket02);
1330  UtRegisterTest("DetectByteJumpTestPacket03", DetectByteJumpTestPacket03);
1331  UtRegisterTest("DetectByteJumpTestPacket04", DetectByteJumpTestPacket04);
1332  UtRegisterTest("DetectByteJumpTestPacket05", DetectByteJumpTestPacket05);
1333  UtRegisterTest("DetectByteJumpTestPacket06", DetectByteJumpTestPacket06);
1334  UtRegisterTest("DetectByteJumpTestPacket07", DetectByteJumpTestPacket07);
1335  UtRegisterTest("DetectByteJumpTestPacket08", DetectByteJumpTestPacket08);
1336 }
1337 #endif /* UNITTESTS */
DetectBytejumpData_::post_offset
int32_t post_offset
Definition: detect-bytejump.h:52
util-byte.h
SigTableElmt_::url
const char * url
Definition: detect.h:1545
DETECT_CONTENT_RELATIVE_NEXT
#define DETECT_CONTENT_RELATIVE_NEXT
Definition: detect-content.h:66
detect-content.h
len
uint8_t len
Definition: app-layer-dnp3.h:2
DetectEngineThreadCtx_::buffer_offset
uint32_t buffer_offset
Definition: detect.h:1340
detect-engine.h
DETECT_SM_LIST_PMATCH
@ DETECT_SM_LIST_PMATCH
Definition: detect.h:120
FAIL_IF_NULL
#define FAIL_IF_NULL(expr)
Fail a test if expression evaluates to NULL.
Definition: util-unittest.h:89
SignatureInitData_::smlists
struct SigMatch_ * smlists[DETECT_SM_LIST_MAX]
Definition: detect.h:666
SigTableElmt_::desc
const char * desc
Definition: detect.h:1544
ByteExtractUint64
int ByteExtractUint64(uint64_t *res, int e, uint16_t len, const uint8_t *bytes)
Definition: util-byte.c:74
sigmatch_table
SigTableElmt * sigmatch_table
Definition: detect-parse.c:78
offset
uint64_t offset
Definition: util-streaming-buffer.h:0
ALPROTO_DCERPC
@ ALPROTO_DCERPC
Definition: app-layer-protos.h:44
SigTableElmt_::Free
void(* Free)(DetectEngineCtx *, void *)
Definition: detect.h:1529
PARSE_REGEX
#define PARSE_REGEX
Regex for parsing our options.
Definition: detect-bytejump.c:49
DetectBufferGetFirstSigMatch
SigMatch * DetectBufferGetFirstSigMatch(const Signature *s, const uint32_t buf_id)
Definition: detect-engine-buffer.c:157
DetectParseRegex
Definition: detect-parse.h:94
SigTableElmt_::name
const char * name
Definition: detect.h:1542
DETECT_BYTEJUMP
@ DETECT_BYTEJUMP
Definition: detect-engine-register.h:92
SigFree
void SigFree(DetectEngineCtx *, Signature *)
Definition: detect-parse.c:2383
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:101
DETECT_BYTEJUMP_LITTLE
#define DETECT_BYTEJUMP_LITTLE
Definition: detect-bytejump.h:35
DETECT_CONTENT
@ DETECT_CONTENT
Definition: detect-engine-register.h:78
SCLogDebug
#define SCLogDebug(...)
Definition: util-debug.h:282
DETECT_BYTEJUMP_NBYTES_VAR
#define DETECT_BYTEJUMP_NBYTES_VAR
Definition: detect-bytejump.h:43
SCDetectGetLastSMFromLists
SigMatch * SCDetectGetLastSMFromLists(const Signature *s,...)
Returns the sm with the largest index (added latest) from the lists passed to us.
Definition: detect-parse.c:600
ctx
struct Thresholds ctx
DETECT_BYTEJUMP_BASE_OCT
#define DETECT_BYTEJUMP_BASE_OCT
Definition: detect-bytejump.h:29
DetectEngineCtx_
main detection engine ctx
Definition: detect.h:995
DetectEngineCtxFree
void DetectEngineCtxFree(DetectEngineCtx *)
Free a DetectEngineCtx::
Definition: detect-engine.c:2912
DE_QUIET
#define DE_QUIET
Definition: detect.h:334
UTHPacketMatchSig
int UTHPacketMatchSig(Packet *p, const char *sig)
Definition: util-unittest-helper.c:833
DETECT_BYTEJUMP_DCE
#define DETECT_BYTEJUMP_DCE
Definition: detect-bytejump.h:40
UTHBuildPacket
Packet * UTHBuildPacket(uint8_t *payload, uint16_t payload_len, uint8_t ipproto)
UTHBuildPacket is a wrapper that build packets with default ip and port fields.
Definition: util-unittest-helper.c:241
ByteExtractStringUint32
int ByteExtractStringUint32(uint32_t *res, int base, size_t len, const char *str)
Definition: util-byte.c:194
p
Packet * p
Definition: fuzz_dataset.c:30
DetectParsePcreExec
int DetectParsePcreExec(DetectParseRegex *parse_regex, pcre2_match_data **match, const char *str, int start_offset, int options)
Definition: detect-parse.c:4025
DetectContentData_
Definition: detect-content.h:93
DetectPcreData_::flags
uint16_t flags
Definition: detect-pcre.h:52
SigCleanSignatures
void SigCleanSignatures(DetectEngineCtx *de_ctx)
Definition: detect-engine-build.c:56
SCDetectSignatureSetAppProto
int SCDetectSignatureSetAppProto(Signature *s, AppProto alproto)
Definition: detect-parse.c:2619
ByteExtractStringUint64
int ByteExtractStringUint64(uint64_t *res, int base, size_t len, const char *str)
Definition: util-byte.c:189
DetectEngineAppendSig
Signature * DetectEngineAppendSig(DetectEngineCtx *, const char *)
Parse and append a Signature into the Detection Engine Context signature list.
Definition: detect-parse.c:3971
DETECT_BYTEJUMP_BIG
#define DETECT_BYTEJUMP_BIG
Definition: detect-bytejump.h:36
DetectBytejumpData_::base
uint8_t base
Definition: detect-bytejump.h:49
SigTableElmt_::Setup
int(* Setup)(DetectEngineCtx *, Signature *, const char *)
Definition: detect.h:1524
detect-pcre.h
DetectBytejumpData_
Definition: detect-bytejump.h:47
DetectByteIndexType
uint8_t DetectByteIndexType
Definition: detect-byte.h:28
DetectBytejumpData_::offset
int32_t offset
Definition: detect-bytejump.h:51
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
DetectBytejumpData_::multiplier
uint16_t multiplier
Definition: detect-bytejump.h:55
DetectBufferTypeGetByName
int DetectBufferTypeGetByName(const char *name)
Definition: detect-engine.c:1452
strlcpy
size_t strlcpy(char *dst, const char *src, size_t siz)
Definition: util-strlcpyu.c:43
SCReturnBool
#define SCReturnBool(x)
Definition: util-debug.h:302
DetectBytejumpData_::bitmask_value
uint32_t bitmask_value
Definition: detect-bytejump.h:53
DetectBytejumpRegister
void DetectBytejumpRegister(void)
Definition: detect-bytejump.c:74
DETECT_BYTEJUMP_BITMASK
#define DETECT_BYTEJUMP_BITMASK
Definition: detect-bytejump.h:45
decode.h
FAIL_IF_NOT_NULL
#define FAIL_IF_NOT_NULL(expr)
Fail a test if expression evaluates to non-NULL.
Definition: util-unittest.h:96
util-debug.h
PASS
#define PASS
Pass the test.
Definition: util-unittest.h:105
de_ctx
DetectEngineCtx * de_ctx
Definition: fuzz_siginit.c:22
DetectEngineThreadCtx_
Definition: detect.h:1316
DETECT_BYTEJUMP_ALIGN
#define DETECT_BYTEJUMP_ALIGN
Definition: detect-bytejump.h:39
StringParseI32RangeCheck
int StringParseI32RangeCheck(int32_t *res, int base, size_t len, const char *str, int32_t min, int32_t max)
Definition: util-byte.c:680
DetectSetupParseRegexes
void DetectSetupParseRegexes(const char *parse_str, DetectParseRegex *detect_parse)
Definition: detect-parse.c:4151
DETECT_BYTEJUMP_END
#define DETECT_BYTEJUMP_END
Definition: detect-bytejump.h:42
SignatureInitData_::list
int list
Definition: detect.h:645
SCEnter
#define SCEnter(...)
Definition: util-debug.h:284
SCSigMatchAppendSMToList
SigMatch * SCSigMatchAppendSMToList(DetectEngineCtx *de_ctx, Signature *s, uint16_t type, SigMatchCtx *ctx, const int list)
Append a SigMatch to the list type.
Definition: detect-parse.c:424
detect.h
StringParseU16RangeCheck
int StringParseU16RangeCheck(uint16_t *res, int base, size_t len, const char *str, uint16_t min, uint16_t max)
Definition: util-byte.c:394
SigMatch_::next
struct SigMatch_ * next
Definition: detect.h:364
StringParseUint32
int StringParseUint32(uint32_t *res, int base, size_t len, const char *str)
Definition: util-byte.c:268
SigInit
Signature * SigInit(DetectEngineCtx *de_ctx, const char *sigstr)
Parses a signature and adds it to the Detection Engine Context.
Definition: detect-parse.c:3624
SigMatch_::ctx
SigMatchCtx * ctx
Definition: detect.h:363
BYTE_BIG_ENDIAN
#define BYTE_BIG_ENDIAN
Definition: util-byte.h:29
DetectBytejumpDoMatch
bool DetectBytejumpDoMatch(DetectEngineThreadCtx *det_ctx, const Signature *s, const SigMatchCtx *ctx, const uint8_t *payload, uint32_t payload_len, uint16_t flags, int32_t nbytes, int32_t offset)
Byte jump match function.
Definition: detect-bytejump.c:138
SigGroupCleanup
int SigGroupCleanup(DetectEngineCtx *de_ctx)
Definition: detect-engine-build.c:2371
Packet_
Definition: decode.h:516
detect-engine-build.h
detect-bytejump.h
DetectContentData_::flags
uint32_t flags
Definition: detect-content.h:104
DETECT_BYTEJUMP_BASE_UNSET
#define DETECT_BYTEJUMP_BASE_UNSET
Definition: detect-bytejump.h:28
Signature_::init_data
SignatureInitData * init_data
Definition: detect.h:775
SigTableElmt_::Match
int(* Match)(DetectEngineThreadCtx *, Packet *, const Signature *, const SigMatchCtx *)
Definition: detect.h:1504
detect-byte.h
DETECT_BYTEJUMP_BASE_HEX
#define DETECT_BYTEJUMP_BASE_HEX
Definition: detect-bytejump.h:31
DETECT_PCRE
@ DETECT_PCRE
Definition: detect-engine-register.h:80
DetectBytejumpData_::bitmask_shift_count
uint8_t bitmask_shift_count
Definition: detect-bytejump.h:56
SigMatchCtx_
Used to start a pointer to SigMatch context Should never be dereferenced without casting to something...
Definition: detect.h:355
DETECT_SM_LIST_NOTSET
#define DETECT_SM_LIST_NOTSET
Definition: detect.h:145
DETECT_BYTETEST
@ DETECT_BYTETEST
Definition: detect-engine-register.h:91
BYTE_LITTLE_ENDIAN
#define BYTE_LITTLE_ENDIAN
Definition: util-byte.h:30
FAIL_IF
#define FAIL_IF(expr)
Fail a test if expression evaluates to true.
Definition: util-unittest.h:71
flags
uint8_t flags
Definition: decode-gre.h:0
suricata-common.h
SigMatch_::type
uint16_t type
Definition: detect.h:361
detect-byte-extract.h
DetectBytejumpData_::nbytes
uint8_t nbytes
Definition: detect-bytejump.h:48
detect-engine-buffer.h
SCStrdup
#define SCStrdup(s)
Definition: util-mem.h:56
DETECT_BYTEJUMP_BASE_DEC
#define DETECT_BYTEJUMP_BASE_DEC
Definition: detect-bytejump.h:30
util-validate.h
SCMalloc
#define SCMalloc(sz)
Definition: util-mem.h:47
str
#define str(s)
Definition: suricata-common.h:313
SCLogError
#define SCLogError(...)
Macro used to log ERROR messages.
Definition: util-debug.h:274
SigMatchListSMBelongsTo
int SigMatchListSMBelongsTo(const Signature *s, const SigMatch *key_sm)
Definition: detect-parse.c:799
SCFree
#define SCFree(p)
Definition: util-mem.h:61
UTHFreePacket
void UTHFreePacket(Packet *p)
UTHFreePacket: function to release the allocated data from UTHBuildPacket and the packet itself.
Definition: util-unittest-helper.c:470
DETECT_BYTE_EXTRACT
@ DETECT_BYTE_EXTRACT
Definition: detect-engine-register.h:94
detect-parse.h
Signature_
Signature container.
Definition: detect.h:692
SigMatch_
a single match condition for a signature
Definition: detect.h:360
payload_len
uint16_t payload_len
Definition: stream-tcp-private.h:1
DETECT_ISDATAAT
@ DETECT_ISDATAAT
Definition: detect-engine-register.h:102
DetectEngineCtxInit
DetectEngineCtx * DetectEngineCtxInit(void)
Definition: detect-engine.c:2873
DETECT_PCRE_RELATIVE_NEXT
#define DETECT_PCRE_RELATIVE_NEXT
Definition: detect-pcre.h:34
DetectPcreData_
Definition: detect-pcre.h:48
DETECT_BYTEMATH
@ DETECT_BYTEMATH
Definition: detect-engine-register.h:93
DETECT_BYTEJUMP_STRING
#define DETECT_BYTEJUMP_STRING
Definition: detect-bytejump.h:37
detect-uricontent.h
DETECT_BYTEJUMP_BEGIN
#define DETECT_BYTEJUMP_BEGIN
Definition: detect-bytejump.h:34
DetectEngineCtx_::flags
uint8_t flags
Definition: detect.h:997
DetectByteRetrieveSMVar
bool DetectByteRetrieveSMVar(const char *arg, const Signature *s, int sm_list, DetectByteIndexType *index)
Used to retrieve args from BM.
Definition: detect-byte.c:41
SigAlloc
Signature * SigAlloc(void)
Definition: detect-parse.c:2263
DetectBufferGetActiveList
int DetectBufferGetActiveList(DetectEngineCtx *de_ctx, Signature *s)
Definition: detect-engine-buffer.c:109
SCLogDebugEnabled
int SCLogDebugEnabled(void)
Returns whether debug messages are enabled to be logged or not.
Definition: util-debug.c:767
DEBUG_VALIDATE_BUG_ON
#define DEBUG_VALIDATE_BUG_ON(exp)
Definition: util-validate.h:109
DETECT_BYTEJUMP_RELATIVE
#define DETECT_BYTEJUMP_RELATIVE
Definition: detect-bytejump.h:38
SigTableElmt_::RegisterTests
void(* RegisterTests)(void)
Definition: detect.h:1531
DETECT_BYTEJUMP_OFFSET_VAR
#define DETECT_BYTEJUMP_OFFSET_VAR
Definition: detect-bytejump.h:44
DetectBytejumpData_::flags
uint16_t flags
Definition: detect-bytejump.h:50
app-layer.h