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