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