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