suricata
detect-engine-content-inspection.c
Go to the documentation of this file.
1 /* Copyright (C) 2007-2017 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 Anoop Saldanha <anoopsaldanha@gmail.com>
22  *
23  * Performs content inspection on any buffer supplied.
24  */
25 
26 #include "suricata-common.h"
27 #include "suricata.h"
28 
29 #include "decode.h"
30 
31 #include "detect.h"
32 #include "detect-engine.h"
33 #include "detect-parse.h"
34 #include "detect-content.h"
35 #include "detect-pcre.h"
36 #include "detect-isdataat.h"
37 #include "detect-bytetest.h"
38 #include "detect-bytemath.h"
39 #include "detect-bytejump.h"
40 #include "detect-byte-extract.h"
41 #include "detect-replace.h"
43 #include "detect-uricontent.h"
44 #include "detect-urilen.h"
45 #include "detect-bsize.h"
46 #include "detect-lua.h"
47 #include "detect-base64-decode.h"
48 #include "detect-base64-data.h"
49 #include "detect-dataset.h"
50 #include "detect-datarep.h"
51 
52 #include "util-spm.h"
53 #include "util-debug.h"
54 #include "util-print.h"
55 
56 #include "util-unittest.h"
57 #include "util-unittest-helper.h"
58 #include "util-profiling.h"
59 
60 #ifdef HAVE_LUA
61 #include "util-lua.h"
62 #endif
63 
64 /**
65  * \brief Run the actual payload match functions
66  *
67  * The following keywords are inspected:
68  * - content, including all the http and dce modified contents
69  * - isdaatat
70  * - pcre
71  * - bytejump
72  * - bytetest
73  * - byte_extract
74  * - urilen
75  * -
76  *
77  * All keywords are evaluated against the buffer with buffer_len.
78  *
79  * For accounting the last match in relative matching the
80  * det_ctx->buffer_offset int is used.
81  *
82  * \param de_ctx Detection engine context
83  * \param det_ctx Detection engine thread context
84  * \param s Signature to inspect
85  * \param sm SigMatch to inspect
86  * \param p Packet. Can be NULL.
87  * \param f Flow (for pcre flowvar storage)
88  * \param buffer Ptr to the buffer to inspect
89  * \param buffer_len Length of the payload
90  * \param stream_start_offset Indicates the start of the current buffer in
91  * the whole buffer stream inspected. This
92  * applies if the current buffer is inspected
93  * in chunks.
94  * \param inspection_mode Refers to the engine inspection mode we are currently
95  * inspecting. Can be payload, stream, one of the http
96  * buffer inspection modes or dce inspection mode.
97  * \param flags DETECT_CI_FLAG_*
98  *
99  * \retval 0 no match
100  * \retval 1 match
101  */
103  const Signature *s, const SigMatchData *smd,
104  Packet *p, Flow *f,
105  const uint8_t *buffer, uint32_t buffer_len,
106  uint32_t stream_start_offset, uint8_t flags,
107  uint8_t inspection_mode)
108 {
109  SCEnter();
111 
112  det_ctx->inspection_recursion_counter++;
113 
115  det_ctx->discontinue_matching = 1;
116  KEYWORD_PROFILING_END(det_ctx, smd->type, 0);
117  SCReturnInt(0);
118  }
119 
120  if (smd == NULL || buffer_len == 0) {
121  KEYWORD_PROFILING_END(det_ctx, smd->type, 0);
122  SCReturnInt(0);
123  }
124 
125  /* \todo unify this which is phase 2 of payload inspection unification */
126  if (smd->type == DETECT_CONTENT) {
127 
129  SCLogDebug("inspecting content %"PRIu32" buffer_len %"PRIu32, cd->id, buffer_len);
130 
131  /* we might have already have this content matched by the mpm.
132  * (if there is any other reason why we'd want to avoid checking
133  * it here, please fill it in) */
134  //if (cd->flags & DETECT_CONTENT_NO_DOUBLE_INSPECTION_REQUIRED) {
135  // goto match;
136  //}
137 
138  /* rule parsers should take care of this */
139 #ifdef DEBUG
140  BUG_ON(cd->depth != 0 && cd->depth <= cd->offset);
141 #endif
142 
143  /* search for our pattern, checking the matches recursively.
144  * if we match we look for the next SigMatch as well */
145  const uint8_t *found = NULL;
146  uint32_t offset = 0;
147  uint32_t depth = buffer_len;
148  uint32_t prev_offset = 0; /**< used in recursive searching */
149  uint32_t prev_buffer_offset = det_ctx->buffer_offset;
150 
151  do {
152  if ((cd->flags & DETECT_CONTENT_DISTANCE) ||
153  (cd->flags & DETECT_CONTENT_WITHIN)) {
154  SCLogDebug("det_ctx->buffer_offset %"PRIu32, det_ctx->buffer_offset);
155 
156  offset = prev_buffer_offset;
157  depth = buffer_len;
158 
159  int distance = cd->distance;
160  if (cd->flags & DETECT_CONTENT_DISTANCE) {
162  distance = det_ctx->byte_values[cd->distance];
163  }
164  if (distance < 0 && (uint32_t)(abs(distance)) > offset)
165  offset = 0;
166  else
167  offset += distance;
168 
169  SCLogDebug("cd->distance %"PRIi32", offset %"PRIu32", depth %"PRIu32,
170  distance, offset, depth);
171  }
172 
173  if (cd->flags & DETECT_CONTENT_WITHIN) {
174  if (cd->flags & DETECT_CONTENT_WITHIN_VAR) {
175  if ((int32_t)depth > (int32_t)(prev_buffer_offset + det_ctx->byte_values[cd->within] + distance)) {
176  depth = prev_buffer_offset + det_ctx->byte_values[cd->within] + distance;
177  }
178  } else {
179  if ((int32_t)depth > (int32_t)(prev_buffer_offset + cd->within + distance)) {
180  depth = prev_buffer_offset + cd->within + distance;
181  }
182 
183  SCLogDebug("cd->within %"PRIi32", det_ctx->buffer_offset %"PRIu32", depth %"PRIu32,
184  cd->within, prev_buffer_offset, depth);
185  }
186 
187  if (stream_start_offset != 0 && prev_buffer_offset == 0) {
188  if (depth <= stream_start_offset) {
189  goto no_match;
190  } else if (depth >= (stream_start_offset + buffer_len)) {
191  ;
192  } else {
193  depth = depth - stream_start_offset;
194  }
195  }
196  }
197 
198  if (cd->flags & DETECT_CONTENT_DEPTH_VAR) {
199  if ((det_ctx->byte_values[cd->depth] + prev_buffer_offset) < depth) {
200  depth = prev_buffer_offset + det_ctx->byte_values[cd->depth];
201  }
202  } else {
203  if (cd->depth != 0) {
204  if ((cd->depth + prev_buffer_offset) < depth) {
205  depth = prev_buffer_offset + cd->depth;
206  }
207 
208  SCLogDebug("cd->depth %"PRIu32", depth %"PRIu32, cd->depth, depth);
209  }
210  }
211 
212  if (cd->flags & DETECT_CONTENT_OFFSET_VAR) {
213  if (det_ctx->byte_values[cd->offset] > offset)
214  offset = det_ctx->byte_values[cd->offset];
215  } else {
216  if (cd->offset > offset) {
217  offset = cd->offset;
218  SCLogDebug("setting offset %"PRIu32, offset);
219  }
220  }
221  } else { /* implied no relative matches */
222  /* set depth */
223  if (cd->flags & DETECT_CONTENT_DEPTH_VAR) {
224  depth = det_ctx->byte_values[cd->depth];
225  } else {
226  if (cd->depth != 0) {
227  depth = cd->depth;
228  }
229  }
230 
231  if (stream_start_offset != 0 && cd->flags & DETECT_CONTENT_DEPTH) {
232  if (depth <= stream_start_offset) {
233  goto no_match;
234  } else if (depth >= (stream_start_offset + buffer_len)) {
235  ;
236  } else {
237  depth = depth - stream_start_offset;
238  }
239  }
240 
241  /* set offset */
243  offset = det_ctx->byte_values[cd->offset];
244  else
245  offset = cd->offset;
246  prev_buffer_offset = 0;
247  }
248 
249  /* If the value came from a variable, make sure to adjust the depth so it's relative
250  * to the offset value.
251  */
253  depth += offset;
254  }
255 
256  /* update offset with prev_offset if we're searching for
257  * matches after the first occurrence. */
258  SCLogDebug("offset %"PRIu32", prev_offset %"PRIu32, offset, prev_offset);
259  if (prev_offset != 0)
260  offset = prev_offset;
261 
262  SCLogDebug("offset %"PRIu32", depth %"PRIu32, offset, depth);
263 
264  if (depth > buffer_len)
265  depth = buffer_len;
266 
267  /* if offset is bigger than depth we can never match on a pattern.
268  * We can however, "match" on a negated pattern. */
269  if (offset > depth || depth == 0) {
270  if (cd->flags & DETECT_CONTENT_NEGATED) {
271  goto match;
272  } else {
273  goto no_match;
274  }
275  }
276 
277  const uint8_t *sbuffer = buffer + offset;
278  uint32_t sbuffer_len = depth - offset;
279  uint32_t match_offset = 0;
280  SCLogDebug("sbuffer_len %"PRIu32, sbuffer_len);
281 #ifdef DEBUG
282  BUG_ON(sbuffer_len > buffer_len);
283 #endif
284  if (cd->flags & DETECT_CONTENT_ENDS_WITH && depth < buffer_len) {
285  SCLogDebug("depth < buffer_len while DETECT_CONTENT_ENDS_WITH is set. Can't possibly match.");
286  found = NULL;
287  } else if (cd->content_len > sbuffer_len) {
288  found = NULL;
289  } else {
290  /* do the actual search */
291  found = SpmScan(cd->spm_ctx, det_ctx->spm_thread_ctx, sbuffer,
292  sbuffer_len);
293  }
294 
295  /* next we evaluate the result in combination with the
296  * negation flag. */
297  SCLogDebug("found %p cd negated %s", found, cd->flags & DETECT_CONTENT_NEGATED ? "true" : "false");
298 
299  if (found == NULL && !(cd->flags & DETECT_CONTENT_NEGATED)) {
301  /* independent match from previous matches, so failure is fatal */
302  det_ctx->discontinue_matching = 1;
303  }
304 
305  goto no_match;
306  } else if (found == NULL && (cd->flags & DETECT_CONTENT_NEGATED)) {
307  goto match;
308  } else if (found != NULL && (cd->flags & DETECT_CONTENT_NEGATED)) {
309  SCLogDebug("content %"PRIu32" matched at offset %"PRIu32", but negated so no match", cd->id, match_offset);
310  /* don't bother carrying recursive matches now, for preceding
311  * relative keywords */
312  if (DETECT_CONTENT_IS_SINGLE(cd))
313  det_ctx->discontinue_matching = 1;
314  goto no_match;
315  } else {
316  match_offset = (uint32_t)((found - buffer) + cd->content_len);
317  SCLogDebug("content %"PRIu32" matched at offset %"PRIu32"", cd->id, match_offset);
318  det_ctx->buffer_offset = match_offset;
319 
320  if ((cd->flags & DETECT_CONTENT_ENDS_WITH) == 0 || match_offset == buffer_len) {
321  /* Match branch, add replace to the list if needed */
322  if (cd->flags & DETECT_CONTENT_REPLACE) {
323  if (inspection_mode == DETECT_ENGINE_CONTENT_INSPECTION_MODE_PAYLOAD) {
324  /* we will need to replace content if match is confirmed
325  * cast to non-const as replace writes to it. */
326  det_ctx->replist = DetectReplaceAddToList(det_ctx->replist, (uint8_t *)found, cd);
327  } else {
328  SCLogWarning(SC_ERR_INVALID_VALUE, "Can't modify payload without packet");
329  }
330  }
331 
332  /* if this is the last match we're done */
333  if (smd->is_last) {
334  goto match;
335  }
336 
337  SCLogDebug("content %"PRIu32, cd->id);
338  KEYWORD_PROFILING_END(det_ctx, smd->type, 1);
339 
340  /* see if the next buffer keywords match. If not, we will
341  * search for another occurrence of this content and see
342  * if the others match then until we run out of matches */
343  int r = DetectEngineContentInspection(de_ctx, det_ctx, s, smd+1,
344  p, f, buffer, buffer_len, stream_start_offset, flags,
345  inspection_mode);
346  if (r == 1) {
347  SCReturnInt(1);
348  }
349  SCLogDebug("no match for 'next sm'");
350 
351  if (det_ctx->discontinue_matching) {
352  SCLogDebug("'next sm' said to discontinue this right now");
353  goto no_match;
354  }
355 
356  /* no match and no reason to look for another instance */
357  if ((cd->flags & DETECT_CONTENT_WITHIN_NEXT) == 0) {
358  SCLogDebug("'next sm' does not depend on me, so we can give up");
359  det_ctx->discontinue_matching = 1;
360  goto no_match;
361  }
362 
363  SCLogDebug("'next sm' depends on me %p, lets see what we can do (flags %u)", cd, cd->flags);
364  }
365  /* set the previous match offset to the start of this match + 1 */
366  prev_offset = (match_offset - (cd->content_len - 1));
367  SCLogDebug("trying to see if there is another match after prev_offset %"PRIu32, prev_offset);
368  }
369 
370  } while(1);
371 
372  } else if (smd->type == DETECT_ISDATAAT) {
373  SCLogDebug("inspecting isdataat");
374 
375  const DetectIsdataatData *id = (DetectIsdataatData *)smd->ctx;
376  uint32_t dataat = id->dataat;
377  if (id->flags & ISDATAAT_OFFSET_VAR) {
378  uint64_t be_value = det_ctx->byte_values[dataat];
379  if (be_value >= 100000000) {
380  if ((id->flags & ISDATAAT_NEGATED) == 0) {
381  SCLogDebug("extracted value %"PRIu64" very big: no match", be_value);
382  goto no_match;
383  }
384  SCLogDebug("extracted value way %"PRIu64" very big: match", be_value);
385  goto match;
386  }
387  dataat = (uint32_t)be_value;
388  SCLogDebug("isdataat: using value %u from byte_extract local_id %u", dataat, id->dataat);
389  }
390 
391  if (id->flags & ISDATAAT_RELATIVE) {
392  if (det_ctx->buffer_offset + dataat > buffer_len) {
393  SCLogDebug("det_ctx->buffer_offset + dataat %"PRIu32" > %"PRIu32, det_ctx->buffer_offset + dataat, buffer_len);
394  if (id->flags & ISDATAAT_NEGATED)
395  goto match;
396  goto no_match;
397  } else {
398  SCLogDebug("relative isdataat match");
399  if (id->flags & ISDATAAT_NEGATED)
400  goto no_match;
401  goto match;
402  }
403  } else {
404  if (dataat < buffer_len) {
405  SCLogDebug("absolute isdataat match");
406  if (id->flags & ISDATAAT_NEGATED)
407  goto no_match;
408  goto match;
409  } else {
410  SCLogDebug("absolute isdataat mismatch, id->isdataat %"PRIu32", buffer_len %"PRIu32"", dataat, buffer_len);
411  if (id->flags & ISDATAAT_NEGATED)
412  goto match;
413  goto no_match;
414  }
415  }
416 
417  } else if (smd->type == DETECT_PCRE) {
418  SCLogDebug("inspecting pcre");
419  DetectPcreData *pe = (DetectPcreData *)smd->ctx;
420  uint32_t prev_buffer_offset = det_ctx->buffer_offset;
421  uint32_t prev_offset = 0;
422  int r = 0;
423 
424  det_ctx->pcre_match_start_offset = 0;
425  do {
426  r = DetectPcrePayloadMatch(det_ctx, s, smd, p, f,
427  buffer, buffer_len);
428  if (r == 0) {
429  goto no_match;
430  }
431 
432  if (!(pe->flags & DETECT_PCRE_RELATIVE_NEXT)) {
433  SCLogDebug("no relative match coming up, so this is a match");
434  goto match;
435  }
436  KEYWORD_PROFILING_END(det_ctx, smd->type, 1);
437 
438  /* save it, in case we need to do a pcre match once again */
439  prev_offset = det_ctx->pcre_match_start_offset;
440 
441  /* see if the next payload keywords match. If not, we will
442  * search for another occurrence of this pcre and see
443  * if the others match, until we run out of matches */
444  r = DetectEngineContentInspection(de_ctx, det_ctx, s, smd+1,
445  p, f, buffer, buffer_len, stream_start_offset, flags,
446  inspection_mode);
447  if (r == 1) {
448  SCReturnInt(1);
449  }
450 
451  if (det_ctx->discontinue_matching)
452  goto no_match;
453 
454  det_ctx->buffer_offset = prev_buffer_offset;
455  det_ctx->pcre_match_start_offset = prev_offset;
456  } while (1);
457 
458  } else if (smd->type == DETECT_BYTETEST) {
459  DetectBytetestData *btd = (DetectBytetestData *)smd->ctx;
460  uint8_t btflags = btd->flags;
461  int32_t offset = btd->offset;
462  uint64_t value = btd->value;
463  if (btflags & DETECT_BYTETEST_OFFSET_VAR) {
464  offset = det_ctx->byte_values[offset];
465  }
466  if (btflags & DETECT_BYTETEST_VALUE_VAR) {
467  value = det_ctx->byte_values[value];
468  }
469 
470  /* if we have dce enabled we will have to use the endianness
471  * specified by the dce header */
472  if (btflags & DETECT_BYTETEST_DCE) {
473  /* enable the endianness flag temporarily. once we are done
474  * processing we reset the flags to the original value*/
475  btflags |= ((flags & DETECT_CI_FLAGS_DCE_LE) ?
477  }
478 
479  if (DetectBytetestDoMatch(det_ctx, s, smd->ctx, buffer, buffer_len, btflags,
480  offset, value) != 1) {
481  goto no_match;
482  }
483 
484  goto match;
485 
486  } else if (smd->type == DETECT_BYTEJUMP) {
487  DetectBytejumpData *bjd = (DetectBytejumpData *)smd->ctx;
488  uint16_t bjflags = bjd->flags;
489  int32_t offset = bjd->offset;
490 
491  if (bjflags & DETECT_CONTENT_OFFSET_VAR) {
492  offset = det_ctx->byte_values[offset];
493  }
494 
495  /* if we have dce enabled we will have to use the endianness
496  * specified by the dce header */
497  if (bjflags & DETECT_BYTEJUMP_DCE) {
498  /* enable the endianness flag temporarily. once we are done
499  * processing we reset the flags to the original value*/
500  bjflags |= ((flags & DETECT_CI_FLAGS_DCE_LE) ?
502  }
503 
504  if (DetectBytejumpDoMatch(det_ctx, s, smd->ctx, buffer, buffer_len,
505  bjflags, offset) != 1) {
506  goto no_match;
507  }
508 
509  goto match;
510 
511  } else if (smd->type == DETECT_BYTE_EXTRACT) {
512 
513  DetectByteExtractData *bed = (DetectByteExtractData *)smd->ctx;
514  uint8_t endian = bed->endian;
515 
516  /* if we have dce enabled we will have to use the endianness
517  * specified by the dce header */
518  if ((bed->flags & DETECT_BYTE_EXTRACT_FLAG_ENDIAN) &&
519  endian == DETECT_BYTE_EXTRACT_ENDIAN_DCE &&
521 
522  /* enable the endianness flag temporarily. once we are done
523  * processing we reset the flags to the original value*/
524  endian |= ((flags & DETECT_CI_FLAGS_DCE_LE) ?
526  }
527 
528  if (DetectByteExtractDoMatch(det_ctx, smd, s, buffer,
529  buffer_len,
530  &det_ctx->byte_values[bed->local_id],
531  endian) != 1) {
532  goto no_match;
533  }
534 
535  SCLogDebug("[BE] Fetched value for index %d: %"PRIu64,
536  bed->local_id, det_ctx->byte_values[bed->local_id]);
537  goto match;
538 
539  } else if (smd->type == DETECT_BYTEMATH) {
540 
541  DetectByteMathData *bmd = (DetectByteMathData *)smd->ctx;
542  uint8_t endian = bmd->endian;
543 
544  /* if we have dce enabled we will have to use the endianness
545  * specified by the dce header */
546  if ((bmd->flags & DETECT_BYTEMATH_FLAG_ENDIAN) &&
547  endian == DETECT_BYTEMATH_ENDIAN_DCE &&
549 
550  /* enable the endianness flag temporarily. once we are done
551  * processing we reset the flags to the original value*/
552  endian |= ((flags & DETECT_CI_FLAGS_DCE_LE) ?
554  }
555  uint64_t rvalue;
556  if (bmd->flags & DETECT_BYTEMATH_RVALUE_VAR) {
557  rvalue = det_ctx->byte_values[bmd->local_id];
558  } else {
559  rvalue = bmd->rvalue;
560  }
561 
562 
563  if (DetectByteMathDoMatch(det_ctx, smd, s, buffer,
564  buffer_len,
565  rvalue,
566  &det_ctx->byte_values[bmd->local_id],
567  endian) != 1) {
568  goto no_match;
569  }
570 
571  SCLogDebug("[BM] Fetched value for index %d: %"PRIu64,
572  bmd->local_id, det_ctx->byte_values[bmd->local_id]);
573  goto match;
574 
575  } else if (smd->type == DETECT_BSIZE) {
576 
577  bool eof = (flags & DETECT_CI_FLAGS_END);
578  const uint64_t data_size = buffer_len + stream_start_offset;
579  int r = DetectBsizeMatch(smd->ctx, data_size, eof);
580  if (r < 0) {
581  det_ctx->discontinue_matching = 1;
582  goto no_match;
583 
584  } else if (r == 0) {
585  goto no_match;
586  }
587  goto match;
588 
589  } else if (smd->type == DETECT_DATASET) {
590 
591  //PrintRawDataFp(stdout, buffer, buffer_len);
592  const DetectDatasetData *sd = (const DetectDatasetData *) smd->ctx;
593  int r = DetectDatasetBufferMatch(det_ctx, sd, buffer, buffer_len); //TODO buffer offset?
594  if (r == 1) {
595  goto match;
596  }
597  det_ctx->discontinue_matching = 1;
598  goto no_match;
599 
600  } else if (smd->type == DETECT_DATAREP) {
601 
602  //PrintRawDataFp(stdout, buffer, buffer_len);
603  const DetectDatarepData *sd = (const DetectDatarepData *) smd->ctx;
604  int r = DetectDatarepBufferMatch(det_ctx, sd, buffer, buffer_len); //TODO buffer offset?
605  if (r == 1) {
606  goto match;
607  }
608  det_ctx->discontinue_matching = 1;
609  goto no_match;
610 
611  } else if (smd->type == DETECT_AL_URILEN) {
612  SCLogDebug("inspecting uri len");
613 
614  int r = 0;
615  DetectUrilenData *urilend = (DetectUrilenData *) smd->ctx;
616 
617  switch (urilend->mode) {
618  case DETECT_URILEN_EQ:
619  if (buffer_len == urilend->urilen1)
620  r = 1;
621  break;
622  case DETECT_URILEN_LT:
623  if (buffer_len < urilend->urilen1)
624  r = 1;
625  break;
626  case DETECT_URILEN_GT:
627  if (buffer_len > urilend->urilen1)
628  r = 1;
629  break;
630  case DETECT_URILEN_RA:
631  if (buffer_len > urilend->urilen1 &&
632  buffer_len < urilend->urilen2) {
633  r = 1;
634  }
635  break;
636  }
637 
638  if (r == 1) {
639  goto match;
640  }
641 
642  det_ctx->discontinue_matching = 0;
643 
644  goto no_match;
645 #ifdef HAVE_LUA
646  }
647  else if (smd->type == DETECT_LUA) {
648  SCLogDebug("lua starting");
649 
650  if (DetectLuaMatchBuffer(det_ctx, s, smd, buffer, buffer_len,
651  det_ctx->buffer_offset, f) != 1)
652  {
653  SCLogDebug("lua no_match");
654  goto no_match;
655  }
656  SCLogDebug("lua match");
657  goto match;
658 #endif /* HAVE_LUA */
659  } else if (smd->type == DETECT_BASE64_DECODE) {
660  if (DetectBase64DecodeDoMatch(det_ctx, s, smd, buffer, buffer_len)) {
661  if (s->sm_arrays[DETECT_SM_LIST_BASE64_DATA] != NULL) {
662  KEYWORD_PROFILING_END(det_ctx, smd->type, 1);
663  if (DetectBase64DataDoMatch(de_ctx, det_ctx, s, f)) {
664  /* Base64 is a terminal list. */
665  goto final_match;
666  }
667  }
668  }
669  } else {
670  SCLogDebug("sm->type %u", smd->type);
671 #ifdef DEBUG
672  BUG_ON(1);
673 #endif
674  }
675 
676 no_match:
677  KEYWORD_PROFILING_END(det_ctx, smd->type, 0);
678  SCReturnInt(0);
679 
680 match:
681  /* this sigmatch matched, inspect the next one. If it was the last,
682  * the buffer portion of the signature matched. */
683  if (!smd->is_last) {
684  KEYWORD_PROFILING_END(det_ctx, smd->type, 1);
685  int r = DetectEngineContentInspection(de_ctx, det_ctx, s, smd+1,
686  p, f, buffer, buffer_len, stream_start_offset, flags,
687  inspection_mode);
688  SCReturnInt(r);
689  }
690 final_match:
691  KEYWORD_PROFILING_END(det_ctx, smd->type, 1);
692  SCReturnInt(1);
693 }
694 
695 #ifdef UNITTESTS
697 #endif
DetectEngineThreadCtx_::byte_values
uint64_t * byte_values
Definition: detect.h:1111
DETECT_BYTEMATH_ENDIAN_DCE
#define DETECT_BYTEMATH_ENDIAN_DCE
Definition: detect-bytemath.h:38
DetectContentData_::offset
uint16_t offset
Definition: detect-content.h:100
DetectDatasetData_
Definition: detect-dataset.h:36
DETECT_BYTETEST_VALUE_VAR
#define DETECT_BYTETEST_VALUE_VAR
Definition: detect-bytetest.h:49
detect-content.h
DETECT_BYTE_EXTRACT_ENDIAN_DCE
#define DETECT_BYTE_EXTRACT_ENDIAN_DCE
Definition: detect-byte-extract.h:38
DetectEngineThreadCtx_::buffer_offset
uint32_t buffer_offset
Definition: detect.h:1031
detect-engine.h
DetectByteMathData_
Holds data related to byte_math keyword.
Definition: detect-bytemath.h:51
offset
uint64_t offset
Definition: util-streaming-buffer.h:0
SC_ERR_INVALID_VALUE
@ SC_ERR_INVALID_VALUE
Definition: util-error.h:160
DETECT_CONTENT_DISTANCE_VAR
#define DETECT_CONTENT_DISTANCE_VAR
Definition: detect-content.h:47
DetectPcrePayloadMatch
int DetectPcrePayloadMatch(DetectEngineThreadCtx *det_ctx, const Signature *s, const SigMatchData *smd, Packet *p, Flow *f, const uint8_t *payload, uint32_t payload_len)
Match a regex on a single payload.
Definition: detect-pcre.c:177
DETECT_BYTEJUMP
@ DETECT_BYTEJUMP
Definition: detect-engine-register.h:74
ISDATAAT_OFFSET_VAR
#define ISDATAAT_OFFSET_VAR
Definition: detect-isdataat.h:30
DetectContentData_::within
int32_t within
Definition: detect-content.h:102
DetectBase64DecodeDoMatch
int DetectBase64DecodeDoMatch(DetectEngineThreadCtx *det_ctx, const Signature *s, const SigMatchData *smd, const uint8_t *payload, uint32_t payload_len)
Definition: detect-base64-decode.c:59
DetectIsdataatData_::flags
uint8_t flags
Definition: detect-isdataat.h:37
DETECT_BYTEJUMP_LITTLE
#define DETECT_BYTEJUMP_LITTLE
Definition: detect-bytejump.h:35
DetectByteExtractData_::local_id
uint8_t local_id
Definition: detect-byte-extract.h:45
DETECT_CONTENT
@ DETECT_CONTENT
Definition: detect-engine-register.h:60
SCLogDebug
#define SCLogDebug(...)
Definition: util-debug.h:298
detect-isdataat.h
DetectBytetestData_::flags
uint8_t flags
Definition: detect-bytetest.h:57
util-lua.h
DetectByteExtractData_
Holds data related to byte_extract keyword.
Definition: detect-byte-extract.h:43
DetectDatarepData_
Definition: detect-datarep.h:36
SigMatchData_::ctx
SigMatchCtx * ctx
Definition: detect.h:332
detect-bsize.h
Flow_
Flow data structure.
Definition: flow.h:353
DetectEngineCtx_::inspection_recursion_limit
int inspection_recursion_limit
Definition: detect.h:831
DetectEngineCtx_
main detection engine ctx
Definition: detect.h:758
DETECT_DATAREP
@ DETECT_DATAREP
Definition: detect-engine-register.h:100
DETECT_BYTEMATH_RVALUE_VAR
#define DETECT_BYTEMATH_RVALUE_VAR
Definition: detect-bytemath.h:32
DETECT_BYTETEST_DCE
#define DETECT_BYTETEST_DCE
Definition: detect-bytetest.h:47
DETECT_CONTENT_DEPTH_VAR
#define DETECT_CONTENT_DEPTH_VAR
Definition: detect-content.h:46
detect-lua.h
DetectUrilenData_::urilen1
uint16_t urilen1
Definition: detect-urilen.h:33
DETECT_ENGINE_CONTENT_INSPECTION_MODE_PAYLOAD
@ DETECT_ENGINE_CONTENT_INSPECTION_MODE_PAYLOAD
Definition: detect-engine-content-inspection.h:32
DETECT_BYTEJUMP_DCE
#define DETECT_BYTEJUMP_DCE
Definition: detect-bytejump.h:40
DetectEngineThreadCtx_::spm_thread_ctx
SpmThreadCtx * spm_thread_ctx
Definition: detect.h:1105
DetectIsdataatData_
Definition: detect-isdataat.h:35
DetectContentData_
Definition: detect-content.h:86
DetectPcreData_::flags
uint16_t flags
Definition: detect-pcre.h:44
DetectEngineContentInspection
int DetectEngineContentInspection(DetectEngineCtx *de_ctx, DetectEngineThreadCtx *det_ctx, const Signature *s, const SigMatchData *smd, Packet *p, Flow *f, const uint8_t *buffer, uint32_t buffer_len, uint32_t stream_start_offset, uint8_t flags, uint8_t inspection_mode)
Run the actual payload match functions.
Definition: detect-engine-content-inspection.c:102
DetectBytetestData_
Definition: detect-bytetest.h:52
DetectByteMathData_::endian
uint8_t endian
Definition: detect-bytemath.h:63
SigMatchData_
Data needed for Match()
Definition: detect.h:329
detect-pcre.h
KEYWORD_PROFILING_START
#define KEYWORD_PROFILING_START
Definition: util-profiling.h:69
DETECT_CI_FLAGS_DCE_BE
#define DETECT_CI_FLAGS_DCE_BE
Definition: detect-engine-content-inspection.h:42
DetectBytejumpData_
Definition: detect-bytejump.h:44
util-unittest.h
DetectBytejumpData_::offset
int32_t offset
Definition: detect-bytejump.h:49
util-unittest-helper.h
KEYWORD_PROFILING_END
#define KEYWORD_PROFILING_END(ctx, type, m)
Definition: util-profiling.h:83
detect-base64-data.h
DETECT_URILEN_GT
#define DETECT_URILEN_GT
Definition: detect-urilen.h:28
DetectLuaMatchBuffer
int DetectLuaMatchBuffer(DetectEngineThreadCtx *det_ctx, const Signature *s, const SigMatchData *smd, const uint8_t *buffer, uint32_t buffer_len, uint32_t offset, Flow *f)
decode.h
util-debug.h
DETECT_CONTENT_ENDS_WITH
#define DETECT_CONTENT_ENDS_WITH
Definition: detect-content.h:42
DETECT_CONTENT_DISTANCE
#define DETECT_CONTENT_DISTANCE
Definition: detect-content.h:30
de_ctx
DetectEngineCtx * de_ctx
Definition: fuzz_siginit.c:17
DetectBsizeMatch
int DetectBsizeMatch(const SigMatchCtx *ctx, const uint64_t buffer_size, bool eof)
bsize match function
Definition: detect-bsize.c:84
DetectEngineThreadCtx_
Definition: detect.h:1003
DETECT_BSIZE
@ DETECT_BSIZE
Definition: detect-engine-register.h:106
DETECT_SM_LIST_BASE64_DATA
@ DETECT_SM_LIST_BASE64_DATA
Definition: detect.h:95
DetectByteMathData_::local_id
uint8_t local_id
Definition: detect-bytemath.h:53
DETECT_URILEN_EQ
#define DETECT_URILEN_EQ
Definition: detect-urilen.h:30
DETECT_LUA
@ DETECT_LUA
Definition: detect-engine-register.h:211
DETECT_CONTENT_DEPTH
#define DETECT_CONTENT_DEPTH
Definition: detect-content.h:33
util-print.h
SCEnter
#define SCEnter(...)
Definition: util-debug.h:300
DETECT_BYTE_EXTRACT_ENDIAN_BIG
#define DETECT_BYTE_EXTRACT_ENDIAN_BIG
Definition: detect-byte-extract.h:36
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
SigMatchData_::type
uint8_t type
Definition: detect.h:330
DETECT_CONTENT_IS_SINGLE
#define DETECT_CONTENT_IS_SINGLE(c)
Definition: detect-content.h:66
DETECT_CONTENT_NEGATED
#define DETECT_CONTENT_NEGATED
Definition: detect-content.h:40
DetectBase64DataDoMatch
int DetectBase64DataDoMatch(DetectEngineCtx *de_ctx, DetectEngineThreadCtx *det_ctx, const Signature *s, Flow *f)
Definition: detect-base64-data.c:64
DetectContentData_::id
PatIntId id
Definition: detect-content.h:98
DetectByteExtractData_::endian
uint8_t endian
Definition: detect-byte-extract.h:52
BUG_ON
#define BUG_ON(x)
Definition: suricata-common.h:277
util-profiling.h
DETECT_BYTETEST_OFFSET_VAR
#define DETECT_BYTETEST_OFFSET_VAR
Definition: detect-bytetest.h:50
DetectContentData_::depth
uint16_t depth
Definition: detect-content.h:99
SpmScan
uint8_t * SpmScan(const SpmCtx *ctx, SpmThreadCtx *thread_ctx, const uint8_t *haystack, uint32_t haystack_len)
Definition: util-spm.c:194
Packet_
Definition: decode.h:414
ISDATAAT_RELATIVE
#define ISDATAAT_RELATIVE
Definition: detect-isdataat.h:27
detect-bytejump.h
DETECT_CI_FLAGS_END
#define DETECT_CI_FLAGS_END
Definition: detect-engine-content-inspection.h:39
DetectContentData_::flags
uint32_t flags
Definition: detect-content.h:97
DetectByteMathData_::rvalue
uint32_t rvalue
Definition: detect-bytemath.h:57
detect-replace.h
DetectReplaceAddToList
DetectReplaceList * DetectReplaceAddToList(DetectReplaceList *replist, uint8_t *found, DetectContentData *cd)
Definition: detect-replace.c:187
DetectByteMathData_::flags
uint8_t flags
Definition: detect-bytemath.h:62
DETECT_PCRE
@ DETECT_PCRE
Definition: detect-engine-register.h:62
DETECT_URILEN_RA
#define DETECT_URILEN_RA
Definition: detect-urilen.h:29
DETECT_BYTEMATH_FLAG_ENDIAN
#define DETECT_BYTEMATH_FLAG_ENDIAN
Definition: detect-bytemath.h:31
detect-engine-content-inspection.h
DetectEngineThreadCtx_::discontinue_matching
uint16_t discontinue_matching
Definition: detect.h:1066
DETECT_CONTENT_WITHIN_VAR
#define DETECT_CONTENT_WITHIN_VAR
Definition: detect-content.h:48
DetectDatasetBufferMatch
int DetectDatasetBufferMatch(DetectEngineThreadCtx *det_ctx, const DetectDatasetData *sd, const uint8_t *data, const uint32_t data_len)
Definition: detect-dataset.c:66
DETECT_URILEN_LT
#define DETECT_URILEN_LT
Definition: detect-urilen.h:27
DetectDatarepBufferMatch
int DetectDatarepBufferMatch(DetectEngineThreadCtx *det_ctx, const DetectDatarepData *sd, const uint8_t *data, const uint32_t data_len)
Definition: detect-datarep.c:67
DETECT_BYTETEST
@ DETECT_BYTETEST
Definition: detect-engine-register.h:73
DETECT_BYTEMATH_ENDIAN_LITTLE
#define DETECT_BYTEMATH_ENDIAN_LITTLE
Definition: detect-bytemath.h:37
flags
uint8_t flags
Definition: decode-gre.h:0
DETECT_BYTE_EXTRACT_ENDIAN_LITTLE
#define DETECT_BYTE_EXTRACT_ENDIAN_LITTLE
Definition: detect-byte-extract.h:37
SigMatchData_::is_last
uint8_t is_last
Definition: detect.h:331
suricata-common.h
detect-byte-extract.h
DetectContentData_::distance
int32_t distance
Definition: detect-content.h:101
DETECT_CONTENT_WITHIN_NEXT
#define DETECT_CONTENT_WITHIN_NEXT
Definition: detect-content.h:57
DetectEngineThreadCtx_::inspection_recursion_counter
int inspection_recursion_counter
Definition: detect.h:1078
DetectBytetestDoMatch
int DetectBytetestDoMatch(DetectEngineThreadCtx *det_ctx, const Signature *s, const SigMatchCtx *ctx, const uint8_t *payload, uint32_t payload_len, uint8_t flags, int32_t offset, uint64_t value)
Bytetest detection code.
Definition: detect-bytetest.c:105
util-spm.h
detect-dataset.h
detect-base64-decode.h
ISDATAAT_NEGATED
#define ISDATAAT_NEGATED
Definition: detect-isdataat.h:29
DetectContentData_::spm_ctx
SpmCtx * spm_ctx
Definition: detect-content.h:104
DetectEngineThreadCtx_::pcre_match_start_offset
uint32_t pcre_match_start_offset
Definition: detect.h:1033
SCLogWarning
#define SCLogWarning(err_code,...)
Macro used to log WARNING messages.
Definition: util-debug.h:244
detect-datarep.h
DETECT_BYTE_EXTRACT
@ DETECT_BYTE_EXTRACT
Definition: detect-engine-register.h:171
DetectByteExtractDoMatch
int DetectByteExtractDoMatch(DetectEngineThreadCtx *det_ctx, const SigMatchData *smd, const Signature *s, const uint8_t *payload, uint16_t payload_len, uint64_t *value, uint8_t endian)
Definition: detect-byte-extract.c:114
detect-parse.h
Signature_
Signature container.
Definition: detect.h:517
DETECT_ISDATAAT
@ DETECT_ISDATAAT
Definition: detect-engine-register.h:80
DetectByteExtractData_::flags
uint8_t flags
Definition: detect-byte-extract.h:51
DETECT_BYTE_EXTRACT_FLAG_ENDIAN
#define DETECT_BYTE_EXTRACT_FLAG_ENDIAN
Definition: detect-byte-extract.h:32
DetectBytetestData_::offset
int32_t offset
Definition: detect-bytetest.h:59
DetectIsdataatData_::dataat
uint16_t dataat
Definition: detect-isdataat.h:36
DetectByteMathDoMatch
int DetectByteMathDoMatch(DetectEngineThreadCtx *det_ctx, const SigMatchData *smd, const Signature *s, const uint8_t *payload, uint16_t payload_len, uint64_t rvalue, uint64_t *value, uint8_t endian)
Definition: detect-bytemath.c:137
DETECT_PCRE_RELATIVE_NEXT
#define DETECT_PCRE_RELATIVE_NEXT
Definition: detect-pcre.h:34
DetectUrilenData_::mode
uint8_t mode
Definition: detect-urilen.h:35
detect-urilen.h
suricata.h
DetectPcreData_
Definition: detect-pcre.h:39
DetectContentData_::content_len
uint16_t content_len
Definition: detect-content.h:88
DETECT_BYTEMATH
@ DETECT_BYTEMATH
Definition: detect-engine-register.h:75
DetectUrilenData_
Definition: detect-urilen.h:32
DETECT_BASE64_DECODE
@ DETECT_BASE64_DECODE
Definition: detect-engine-register.h:238
detect-uricontent.h
DETECT_BYTEMATH_ENDIAN_BIG
#define DETECT_BYTEMATH_ENDIAN_BIG
Definition: detect-bytemath.h:36
DetectEngineThreadCtx_::replist
DetectReplaceList * replist
Definition: detect.h:1114
DETECT_CONTENT_REPLACE
#define DETECT_CONTENT_REPLACE
Definition: detect-content.h:51
detect-engine-content-inspection.c
SCReturnInt
#define SCReturnInt(x)
Definition: util-debug.h:304
DETECT_BYTETEST_LITTLE
#define DETECT_BYTETEST_LITTLE
Definition: detect-bytetest.h:43
DETECT_AL_URILEN
@ DETECT_AL_URILEN
Definition: detect-engine-register.h:124
DETECT_DATASET
@ DETECT_DATASET
Definition: detect-engine-register.h:99
DetectBytetestData_::value
uint64_t value
Definition: detect-bytetest.h:61
DETECT_CONTENT_WITHIN
#define DETECT_CONTENT_WITHIN
Definition: detect-content.h:31
DETECT_CI_FLAGS_DCE_LE
#define DETECT_CI_FLAGS_DCE_LE
Definition: detect-engine-content-inspection.h:41
DetectBytejumpData_::flags
uint16_t flags
Definition: detect-bytejump.h:47
detect-bytemath.h
DETECT_CONTENT_OFFSET_VAR
#define DETECT_CONTENT_OFFSET_VAR
Definition: detect-content.h:45
detect-bytetest.h