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