suricata
detect-content.c
Go to the documentation of this file.
1/* Copyright (C) 2007-2022 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 Victor Julien <victor@inliniac.net>
22 *
23 * Simple content match part of the detection engine.
24 */
25
26#include "suricata-common.h"
27#include "decode.h"
28#include "detect.h"
29#include "detect-content.h"
30#include "detect-uricontent.h"
31#include "detect-engine-mpm.h"
32#include "detect-engine.h"
34#include "detect-engine-build.h"
35#include "detect-engine-state.h"
36#include "detect-parse.h"
37#include "detect-pcre.h"
38#include "util-mpm.h"
39#include "flow.h"
40#include "flow-util.h"
41#include "flow-var.h"
42#include "detect-flow.h"
43#include "app-layer.h"
44#include "util-unittest.h"
45#include "util-print.h"
46#include "util-debug.h"
47#include "util-spm.h"
48#include "threads.h"
50#include "pkt-var.h"
51#include "host.h"
52#include "util-profiling.h"
53#include "detect-dsize.h"
54
55#ifdef UNITTESTS
56static void DetectContentRegisterTests(void);
57#endif
58
73
74/**
75 * \brief Parse a content string, ie "abc|DE|fgh"
76 *
77 * \param content_str null terminated string containing the content
78 * \param result result pointer to pass the fully parsed byte array
79 * \param result_len size of the resulted data
80 * \param flags flags to be set by this parsing function
81 *
82 * \retval -1 error
83 * \retval 0 ok
84 */
85int DetectContentDataParse(const char *keyword, const char *contentstr,
86 uint8_t **pstr, uint16_t *plen)
87{
88 char *str = NULL;
89 size_t slen = 0;
90
91 slen = strlen(contentstr);
92 if (slen == 0) {
93 return -1;
94 }
95 uint8_t buffer[slen + 1];
96 strlcpy((char *)&buffer, contentstr, slen + 1);
97 str = (char *)buffer;
98
99 SCLogDebug("\"%s\", len %" PRIuMAX, str, (uintmax_t)slen);
100
101 //SCLogDebug("DetectContentParse: \"%s\", len %" PRIu32 "", str, len);
102 char converted = 0;
103
104 {
105 size_t i, x;
106 uint8_t bin = 0;
107 uint8_t escape = 0;
108 uint8_t binstr[3] = "";
109 uint8_t binpos = 0;
110 uint16_t bin_count = 0;
111
112 for (i = 0, x = 0; i < slen; i++) {
113 // SCLogDebug("str[%02u]: %c", i, str[i]);
114 if (str[i] == '|') {
115 bin_count++;
116 if (bin) {
117 if (binpos > 0) {
118 SCLogError("Incomplete hex code in content - %s. Invalidating signature.",
119 contentstr);
120 goto error;
121 }
122 bin = 0;
123 } else {
124 bin = 1;
125 }
126 } else if(!escape && str[i] == '\\') {
127 escape = 1;
128 } else {
129 if (bin) {
130 if (isdigit((unsigned char)str[i]) ||
131 str[i] == 'A' || str[i] == 'a' ||
132 str[i] == 'B' || str[i] == 'b' ||
133 str[i] == 'C' || str[i] == 'c' ||
134 str[i] == 'D' || str[i] == 'd' ||
135 str[i] == 'E' || str[i] == 'e' ||
136 str[i] == 'F' || str[i] == 'f')
137 {
138 // SCLogDebug("part of binary: %c", str[i]);
139
140 binstr[binpos] = (char)str[i];
141 binpos++;
142
143 if (binpos == 2) {
144 uint8_t c = strtol((char *)binstr, (char **) NULL, 16) & 0xFF;
145 binpos = 0;
146 str[x] = c;
147 x++;
148 converted = 1;
149 }
150 } else if (str[i] == ' ') {
151 // SCLogDebug("space as part of binary string");
152 }
153 else if (str[i] != ',') {
154 SCLogError("Invalid hex code in "
155 "content - %s, hex %c. Invalidating signature.",
156 contentstr, str[i]);
157 goto error;
158 }
159 } else if (escape) {
160 if (str[i] == ':' ||
161 str[i] == ';' ||
162 str[i] == '\\' ||
163 str[i] == '\"')
164 {
165 str[x] = str[i];
166 x++;
167 } else {
168 SCLogError("'%c' has to be escaped", str[i - 1]);
169 goto error;
170 }
171 escape = 0;
172 converted = 1;
173 } else if (str[i] == '"') {
174 SCLogError("Invalid unescaped double quote within content section.");
175 goto error;
176 } else {
177 str[x] = str[i];
178 x++;
179 }
180 }
181 }
182
183 if (bin_count % 2 != 0) {
184 SCLogError("Invalid hex code assembly in "
185 "%s - %s. Invalidating signature.",
186 keyword, contentstr);
187 goto error;
188 }
189
190 if (converted) {
191 slen = x;
192 }
193 }
194
195 if (slen) {
196 uint8_t *ptr = SCCalloc(1, slen);
197 if (ptr == NULL) {
198 return -1;
199 }
200 memcpy(ptr, str, slen);
201
202 *plen = (uint16_t)slen;
203 *pstr = ptr;
204 return 0;
205 }
206error:
207 return -1;
208}
209/**
210 * \brief DetectContentParse
211 * \initonly
212 */
214 const char *contentstr)
215{
216 DetectContentData *cd = NULL;
217 uint8_t *content = NULL;
218 uint16_t len = 0;
219 int ret;
220
221 ret = DetectContentDataParse("content", contentstr, &content, &len);
222 if (ret == -1) {
223 return NULL;
224 }
225
226 cd = SCCalloc(1, sizeof(DetectContentData) + len);
227 if (unlikely(cd == NULL)) {
228 SCFree(content);
229 exit(EXIT_FAILURE);
230 }
231
232 cd->content = (uint8_t *)cd + sizeof(DetectContentData);
233 memcpy(cd->content, content, len);
234 cd->content_len = len;
235
236 /* Prepare SPM search context. */
237 cd->spm_ctx = SpmInitCtx(cd->content, cd->content_len, 0,
238 spm_global_thread_ctx);
239 if (cd->spm_ctx == NULL) {
240 SCFree(content);
241 SCFree(cd);
242 return NULL;
243 }
244
245 cd->depth = 0;
246 cd->offset = 0;
247 cd->within = 0;
248 cd->distance = 0;
249
250 SCFree(content);
251 return cd;
252
253}
254
256 const char *contentstr)
257{
258 return DetectContentParse(spm_global_thread_ctx, contentstr);
259}
260
261/**
262 * \brief Helper function to print a DetectContentData
263 */
265{
266 int i = 0;
267 if (cd == NULL) {
268 SCLogDebug("DetectContentData \"cd\" is NULL");
269 return;
270 }
271 char *tmpstr = SCMalloc(sizeof(char) * cd->content_len + 1);
272 if (tmpstr != NULL) {
273 for (i = 0; i < cd->content_len; i++) {
274 if (isprint(cd->content[i]))
275 tmpstr[i] = cd->content[i];
276 else
277 tmpstr[i] = '.';
278 }
279 tmpstr[i] = '\0';
280 SCLogDebug("Content: \"%s\"", tmpstr);
281 SCFree(tmpstr);
282 } else {
283 SCLogDebug("Content: ");
284 for (i = 0; i < cd->content_len; i++)
285 SCLogDebug("%c", cd->content[i]);
286 }
287
288 SCLogDebug("Content_id: %"PRIu32, cd->id);
289 SCLogDebug("Content_len: %"PRIu16, cd->content_len);
290 SCLogDebug("Depth: %"PRIu16, cd->depth);
291 SCLogDebug("Offset: %"PRIu16, cd->offset);
292 SCLogDebug("Within: %"PRIi32, cd->within);
293 SCLogDebug("Distance: %"PRIi32, cd->distance);
294 SCLogDebug("flags: %u ", cd->flags);
295 SCLogDebug("negated: %s ", cd->flags & DETECT_CONTENT_NEGATED ? "true" : "false");
296 SCLogDebug("relative match next: %s ", cd->flags & DETECT_CONTENT_RELATIVE_NEXT ? "true" : "false");
297
298 if (cd->replace && cd->replace_len) {
299 char *tmprstr = SCMalloc(sizeof(char) * cd->replace_len + 1);
300
301 if (tmprstr != NULL) {
302 for (i = 0; i < cd->replace_len; i++) {
303 if (isprint(cd->replace[i]))
304 tmprstr[i] = cd->replace[i];
305 else
306 tmprstr[i] = '.';
307 }
308 tmprstr[i] = '\0';
309 SCLogDebug("Replace: \"%s\"", tmprstr);
310 SCFree(tmprstr);
311 } else {
312 SCLogDebug("Replace: ");
313 for (i = 0; i < cd->replace_len; i++)
314 SCLogDebug("%c", cd->replace[i]);
315 }
316 }
317 SCLogDebug("-----------");
318}
319
320/**
321 * \brief Function to setup a content pattern.
322 *
323 * \param de_ctx pointer to the current detection_engine
324 * \param s pointer to the current Signature
325 * \param m pointer to the last parsed SigMatch
326 * \param contentstr pointer to the current keyword content string
327 * \retval -1 if error
328 * \retval 0 if all was ok
329 */
330int DetectContentSetup(DetectEngineCtx *de_ctx, Signature *s, const char *contentstr)
331{
333 if (cd == NULL)
334 goto error;
335 if (s->init_data->negated) {
337 }
338
340
341 if (DetectBufferGetActiveList(de_ctx, s) == -1)
342 goto error;
343
344 int sm_list = s->init_data->list;
345 if (sm_list == DETECT_SM_LIST_NOTSET) {
346 sm_list = DETECT_SM_LIST_PMATCH;
347 } else if (sm_list > DETECT_SM_LIST_MAX &&
348 0 == (cd->flags & DETECT_CONTENT_NEGATED)) {
349 /* Check transform compatibility */
350 const char *tstr;
352 de_ctx, sm_list, cd->content, cd->content_len, &tstr)) {
353 SCLogError("content string \"%s\" incompatible with %s transform", contentstr, tstr);
354 goto error;
355 }
356 }
357
358 if (SCSigMatchAppendSMToList(de_ctx, s, DETECT_CONTENT, (SigMatchCtx *)cd, sm_list) == NULL) {
359 goto error;
360 }
361
362 return 0;
363
364error:
366 return -1;
367}
368
369/**
370 * \brief this function will SCFree memory associated with DetectContentData
371 *
372 * \param cd pointer to DetectContentData
373 */
375{
376 SCEnter();
378
379 if (cd == NULL)
380 SCReturn;
381
383
384 SCFree(cd);
385 SCReturn;
386}
387
388/**
389 * \brief Determine the size needed to accommodate the content
390 * elements of a signature
391 * \param s signature to get dsize value from
392 * \param max_size Maximum buffer/data size allowed.
393 * \param list signature match list.
394 * \param len Maximum length required
395 * \param offset Maximum offset encountered
396 *
397 * Note that negated content does not contribute to the maximum
398 * required size value. However, each negated content's values
399 * must not exceed the size value.
400 *
401 * Values from negated content blocks are used to determine if the
402 * negated content block requires a value that exceeds "max_size". The
403 * distance and within values from negated content blocks are added to
404 * the running total of required content size to see if the max_size
405 * would be exceeded.
406 *
407 * - Non-negated content contributes to the required size (content length, distance)
408 * - Negated content values are checked but not accumulated for the required size.
409 */
411 const Signature *s, const uint64_t max_size, const SigMatch *sm, int *len, int *offset)
412{
413 int max_offset = 0, total_len = 0;
414 bool first = true;
415 for (; sm != NULL; sm = sm->next) {
416 if (sm->type != DETECT_CONTENT || sm->ctx == NULL) {
417 continue;
418 }
419
421 SCLogDebug("content_len %d; negated: %s; distance: %d, offset: %d, depth: %d",
422 cd->content_len, cd->flags & DETECT_CONTENT_NEGATED ? "yes" : "no", cd->distance,
423 cd->offset, cd->depth);
424
425 if (!first) {
426 /* only count content with relative modifiers */
428 continue;
429
430 if (cd->flags & DETECT_CONTENT_NEGATED) {
431 /* Check if distance/within cause max to be exceeded */
432 int check = total_len + cd->distance + cd->within;
433 if (max_size < (uint64_t)check) {
434 *len = check;
435 return;
436 }
437
438 continue;
439 }
440 }
441 SCLogDebug("content_len %d; distance: %d, offset: %d, depth: %d", cd->content_len,
442 cd->distance, cd->offset, cd->depth);
443 total_len += cd->content_len + cd->distance;
444 max_offset = MAX(max_offset, cd->offset);
445 first = false;
446 }
447
448 *len = total_len;
449 *offset = max_offset;
450}
451
452/**
453 * \retval true valid
454 * \retval false invalid
455 */
457{
458 if (!(s->flags & SIG_FLAG_DSIZE)) {
459 return true;
460 }
461
462 uint16_t max_right_edge_i;
463 if (SigParseGetMaxDsize(s, &max_right_edge_i) < 0) {
464 return true;
465 }
466 uint32_t max_right_edge = max_right_edge_i;
467
468 int min_dsize_required = SigParseMaxRequiredDsize(s);
469 if (min_dsize_required >= 0) {
470 SCLogDebug("min_dsize %d; max_right_edge %d", min_dsize_required, max_right_edge);
471 if ((uint32_t)min_dsize_required > max_right_edge) {
472 SCLogError("signature can't match as required content length %d exceeds dsize value %d",
473 min_dsize_required, max_right_edge);
474 return false;
475 }
476 }
477
478 return true;
479}
480
481/** \brief apply depth/offset and distance/within to content matches
482 *
483 * The idea is that any limitation we can set is a win, as the mpm
484 * can use this to reduce match candidates.
485 *
486 * E.g. if we have 'content:"1"; depth:1; content:"2"; distance:0; within:1;'
487 * we know that we can add 'offset:1; depth:2;' to the 2nd condition. This
488 * will then be used in mpm if the 2nd condition would be selected for mpm.
489 *
490 * Another example: 'content:"1"; depth:1; content:"2"; distance:0;'. Here we
491 * cannot set a depth, but we can set an offset of 'offset:1;'. This will
492 * make the mpm a bit more precise.
493 */
494static void PropagateLimits(Signature *s, SigMatch *sm_head)
495{
496#define VALIDATE(e) \
497 if (!(e)) { \
498 return; \
499 }
500 uint16_t offset = 0;
501 uint16_t offset_plus_pat = 0;
502 uint16_t depth = 0;
503 bool has_active_depth_chain = false;
504
505 bool has_depth = false;
506 bool has_ends_with = false;
507 uint16_t ends_with_depth = 0;
508
509 for (SigMatch *sm = sm_head; sm != NULL; sm = sm->next) {
510 switch (sm->type) {
511 case DETECT_CONTENT: {
512 DetectContentData *cd = (DetectContentData *)sm->ctx;
513 if ((cd->flags & (DETECT_CONTENT_DEPTH | DETECT_CONTENT_OFFSET |
515 offset = depth = 0;
516 offset_plus_pat = cd->content_len;
517 SCLogDebug("reset");
518 has_active_depth_chain = false;
519 continue;
520 }
521 if (sm->prev == NULL) {
522 if (cd->distance >= 0 && cd->distance <= (int32_t)USHRT_MAX &&
523 cd->within >= 0 && cd->within <= (int32_t)USHRT_MAX) {
524 if (cd->flags & DETECT_CONTENT_DISTANCE) {
525 if (cd->distance > 0)
526 cd->flags |= DETECT_CONTENT_OFFSET;
527 cd->flags &= ~DETECT_CONTENT_DISTANCE;
528 cd->offset = (uint16_t)cd->distance;
529 cd->distance = 0;
531 }
532 if (cd->flags & DETECT_CONTENT_WITHIN) {
533 cd->flags |= DETECT_CONTENT_DEPTH;
534 cd->flags &= ~DETECT_CONTENT_WITHIN;
535 cd->depth = (uint16_t)cd->within + cd->offset;
536 cd->within = 0;
537 cd->flags |= DETECT_CONTENT_WITHIN2DEPTH;
538 }
539 }
540 }
541
542 if (cd->flags & DETECT_CONTENT_NEGATED) {
543 offset = depth = 0;
544 offset_plus_pat = 0;
545 SCLogDebug("reset because of negation");
546 has_active_depth_chain = false;
547 continue;
548 }
549
550 if (cd->depth) {
551 has_depth = true;
552 has_active_depth_chain = true;
553 }
554
555 SCLogDebug("sm %p depth %u offset %u distance %d within %d", sm, cd->depth,
556 cd->offset, cd->distance, cd->within);
557 SCLogDebug("stored: offset %u depth %u offset_plus_pat %u", offset, depth,
558 offset_plus_pat);
559
560 if ((cd->flags & (DETECT_CONTENT_DEPTH | DETECT_CONTENT_WITHIN)) == 0) {
561 if (depth)
562 SCLogDebug("no within, reset depth");
563 depth = 0;
564 has_active_depth_chain = false;
565 }
566 if ((cd->flags & DETECT_CONTENT_DISTANCE) == 0) {
567 if (offset_plus_pat)
568 SCLogDebug("no distance, reset offset_plus_pat & offset");
569 offset_plus_pat = offset = 0;
570 }
571
572 SCLogDebug("stored: offset %u depth %u offset_plus_pat %u "
573 "has_active_depth_chain %s",
574 offset, depth, offset_plus_pat, has_active_depth_chain ? "true" : "false");
575 if (cd->flags & DETECT_CONTENT_DISTANCE) {
576 if (cd->distance >= 0) {
577 VALIDATE((uint32_t)offset_plus_pat + cd->distance <= UINT16_MAX);
578 offset = cd->offset = (uint16_t)(offset_plus_pat + cd->distance);
579 SCLogDebug("distance %d: updated content to have offset %u", cd->distance,
580 cd->offset);
581 } else {
582 if (abs(cd->distance) > offset_plus_pat)
583 offset = cd->offset = 0;
584 else
585 offset = cd->offset = (uint16_t)(offset_plus_pat + cd->distance);
586 offset_plus_pat = offset + cd->content_len;
587 SCLogDebug("distance %d: updated content to have offset %u", cd->distance,
588 cd->offset);
589 }
590 }
591 if (has_active_depth_chain) {
592 if (offset_plus_pat && cd->flags & DETECT_CONTENT_WITHIN && cd->within >= 0) {
593 if (depth && depth > offset_plus_pat) {
594 int32_t dist = 0;
595 if (cd->flags & DETECT_CONTENT_DISTANCE && cd->distance > 0) {
596 dist = cd->distance;
598 "distance to add: %u. depth + dist %u", dist, depth + dist);
599 }
600 SCLogDebug("depth %u + cd->within %u", depth, cd->within);
601 VALIDATE(depth + cd->within + dist >= 0 &&
602 depth + cd->within + dist <= UINT16_MAX);
603 depth = cd->depth = (uint16_t)(depth + cd->within + dist);
604 } else if ((cd->flags & DETECT_CONTENT_DISTANCE_VAR) == 0) {
605 // we cannot know the depth yet if it comes from a var
606 SCLogDebug("offset %u + cd->within %u", offset, cd->within);
607 VALIDATE(depth + cd->within >= 0 && depth + cd->within <= UINT16_MAX);
608 depth = cd->depth = (uint16_t)(offset + cd->within);
609 }
610 SCLogDebug("updated content to have depth %u", cd->depth);
611 } else {
612 if (cd->depth == 0 && depth != 0) {
613 if (cd->within > 0) {
614 SCLogDebug("within %d distance %d", cd->within, cd->distance);
615 if (cd->flags & DETECT_CONTENT_DISTANCE && cd->distance >= 0) {
616 VALIDATE(offset_plus_pat + cd->distance >= 0 &&
617 offset_plus_pat + cd->distance <= UINT16_MAX);
618 cd->offset = (uint16_t)(offset_plus_pat + cd->distance);
619 SCLogDebug("updated content to have offset %u", cd->offset);
620 }
621
622 VALIDATE(depth + cd->within >= 0 &&
623 depth + cd->within <= UINT16_MAX);
624 depth = cd->depth = (uint16_t)(cd->within + depth);
625 SCLogDebug("updated content to have depth %u", cd->depth);
626
627 if (cd->flags & DETECT_CONTENT_ENDS_WITH) {
628 has_ends_with = true;
629 if (ends_with_depth == 0)
630 ends_with_depth = depth;
631 ends_with_depth = MIN(ends_with_depth, depth);
632 }
633 }
634 }
635 }
636 }
637 if (cd->offset == 0) { // && offset != 0) {
638 if (cd->flags & DETECT_CONTENT_DISTANCE && cd->distance >= 0) {
639 cd->offset = offset_plus_pat;
640 SCLogDebug("update content to have offset %u", cd->offset);
641 }
642 }
643
644 if ((cd->flags & (DETECT_CONTENT_DEPTH | DETECT_CONTENT_OFFSET |
650 if (cd->distance >= 0) {
651 // only distance
652 VALIDATE((uint32_t)offset_plus_pat + cd->distance <= UINT16_MAX);
653 offset = cd->offset = (uint16_t)(offset_plus_pat + cd->distance);
654 offset_plus_pat = offset + cd->content_len;
655 SCLogDebug("offset %u offset_plus_pat %u", offset, offset_plus_pat);
656 }
657 }
658 if (cd->flags & DETECT_CONTENT_OFFSET) {
659 offset = cd->offset;
660 offset_plus_pat = offset + cd->content_len;
661 SCLogDebug("stored offset %u offset_plus_pat %u", offset, offset_plus_pat);
662 }
663 if (cd->depth) {
664 depth = cd->depth;
665 SCLogDebug("stored depth now %u", depth);
666 offset_plus_pat = offset + cd->content_len;
667 if (cd->flags & DETECT_CONTENT_ENDS_WITH) {
668 has_ends_with = true;
669 if (ends_with_depth == 0)
670 ends_with_depth = depth;
671 ends_with_depth = MIN(ends_with_depth, depth);
672 }
673 }
674 if ((cd->flags & (DETECT_CONTENT_WITHIN | DETECT_CONTENT_DEPTH)) == 0) {
675 has_active_depth_chain = false;
676 depth = 0;
677 }
678 break;
679 }
680 case DETECT_PCRE: {
681 // relative could leave offset_plus_pat set.
682 const DetectPcreData *pd = (const DetectPcreData *)sm->ctx;
683 if (pd->flags & DETECT_PCRE_RELATIVE) {
684 depth = 0;
685 } else {
686 SCLogDebug("non-anchored PCRE not supported, reset offset_plus_pat & offset");
687 offset_plus_pat = offset = depth = 0;
688 }
689 has_active_depth_chain = false;
690 break;
691 }
692 default:
693 SCLogDebug("keyword not supported, reset offset_plus_pat & offset");
694 offset_plus_pat = offset = depth = 0;
695 has_active_depth_chain = false;
696 break;
697 }
698 }
699 /* apply anchored 'ends with' as depth to all patterns */
700 if (has_depth && has_ends_with) {
701 for (SigMatch *sm = sm_head; sm != NULL; sm = sm->next) {
702 switch (sm->type) {
703 case DETECT_CONTENT: {
704 DetectContentData *cd = (DetectContentData *)sm->ctx;
705 if (cd->depth == 0)
706 cd->depth = ends_with_depth;
707 cd->depth = MIN(ends_with_depth, cd->depth);
708 if (cd->depth)
709 cd->flags |= DETECT_CONTENT_DEPTH;
710 break;
711 }
712 }
713 }
714 }
715#undef VALIDATE
716}
717
719{
720 PropagateLimits(s, s->init_data->smlists[DETECT_SM_LIST_PMATCH]);
721 for (uint32_t x = 0; x < s->init_data->buffer_index; x++) {
722 PropagateLimits(s, s->init_data->buffers[x].head);
723 }
724}
725
726static inline bool NeedsAsHex(uint8_t c)
727{
728 if (!isprint(c))
729 return true;
730
731 switch (c) {
732 case '/':
733 case ';':
734 case ':':
735 case '\\':
736 case ' ':
737 case '|':
738 case '"':
739 case '`':
740 case '\'':
741 return true;
742 }
743 return false;
744}
745
746void DetectContentPatternPrettyPrint(const DetectContentData *cd, char *str, size_t str_len)
747{
748 bool hex = false;
749 for (uint16_t i = 0; i < cd->content_len; i++) {
750 if (NeedsAsHex(cd->content[i])) {
751 char hex_str[4];
752 snprintf(hex_str, sizeof(hex_str), "%s%02X", !hex ? "|" : " ", cd->content[i]);
753 strlcat(str, hex_str, str_len);
754 hex = true;
755 } else {
756 char p_str[3];
757 snprintf(p_str, sizeof(p_str), "%s%c", hex ? "|" : "", cd->content[i]);
758 strlcat(str, p_str, str_len);
759 hex = false;
760 }
761 }
762 if (hex) {
763 strlcat(str, "|", str_len);
764 }
765}
766
768{
769 if (cd->flags & DETECT_CONTENT_NOCASE) {
770 SCLogError("can't use multiple nocase modifiers with the same content");
771 return -1;
772 }
773
774 /* for consistency in later use (e.g. by MPM construction and hashing),
775 * coerce the content string to lower-case. */
776 for (uint8_t *c = cd->content; c < cd->content + cd->content_len; c++) {
777 *c = u8_tolower(*c);
778 }
779
781 /* Recreate the context with nocase chars */
784 if (cd->spm_ctx == NULL) {
785 return -1;
786 }
787 return 0;
788}
789
790#ifdef UNITTESTS /* UNITTESTS */
791#include "detect-engine-alert.h"
792#include "packet.h"
793
794static bool TestLastContent(const Signature *s, uint16_t o, uint16_t d)
795{
797 if (!sm) {
798 SCLogDebug("no sm");
799 return false;
800 }
801 if (!(sm->type == DETECT_CONTENT)) {
802 SCLogDebug("not content");
803 return false;
804 }
805 const DetectContentData *cd = (const DetectContentData *)sm->ctx;
806 if (o != cd->offset) {
807 SCLogDebug("offset mismatch %u != %u", o, cd->offset);
808 return false;
809 }
810 if (d != cd->depth) {
811 SCLogDebug("depth mismatch %u != %u", d, cd->depth);
812 return false;
813 }
814 return true;
815}
816
817#define TEST_RUN(sig, o, d) \
818 { \
819 SCLogDebug("TEST_RUN start: '%s'", (sig)); \
820 DetectEngineCtx *de_ctx = DetectEngineCtxInit(); \
821 FAIL_IF_NULL(de_ctx); \
822 de_ctx->flags |= DE_QUIET; \
823 char rule[2048]; \
824 snprintf(rule, sizeof(rule), "alert tcp any any -> any any (%s sid:1; rev:1;)", (sig)); \
825 Signature *s = DetectEngineAppendSig(de_ctx, rule); \
826 FAIL_IF_NULL(s); \
827 SigPrepareStage1(de_ctx); \
828 bool res = TestLastContent(s, (o), (d)); \
829 FAIL_IF_NOT(res); \
830 DetectEngineCtxFree(de_ctx); \
831 }
832
833#define TEST_DONE \
834 PASS
835
836/** \test test propagation of depth/offset/distance/within */
837static int DetectContentDepthTest01(void)
838{
839 // straight depth/offset
840 TEST_RUN("content:\"abc\"; offset:1; depth:3;", 1, 4);
841 // dsize applied as depth
842 TEST_RUN("dsize:10; content:\"abc\";", 0, 10);
843 TEST_RUN("dsize:<10; content:\"abc\";", 0, 10);
844 TEST_RUN("dsize:5<>10; content:\"abc\";", 0, 10);
845
846 // relative match, directly following anchored content
847 TEST_RUN("content:\"abc\"; depth:3; content:\"xyz\"; distance:0; within:3; ", 3, 6);
848 // relative match, directly following anchored content
849 TEST_RUN("content:\"abc\"; offset:3; depth:3; content:\"xyz\"; distance:0; within:3; ", 6, 9);
850 TEST_RUN("content:\"abc\"; depth:6; content:\"xyz\"; distance:0; within:3; ", 3, 9);
851
852 // multiple relative matches after anchored content
853 TEST_RUN("content:\"abc\"; depth:3; content:\"klm\"; distance:0; within:3; content:\"xyz\"; distance:0; within:3; ", 6, 9);
854 // test 'reset' due to unanchored content
855 TEST_RUN("content:\"abc\"; depth:3; content:\"klm\"; content:\"xyz\"; distance:0; within:3; ", 3, 0);
856 // test 'reset' due to unanchored pcre
857 TEST_RUN("content:\"abc\"; depth:3; pcre:/\"klm\"/; content:\"xyz\"; distance:0; within:3; ", 0, 0);
858 // test relative pcre. We can use previous offset+pattern len
859 TEST_RUN("content:\"abc\"; depth:3; pcre:/\"klm\"/R; content:\"xyz\"; distance:0; within:3; ", 3, 0);
860 TEST_RUN("content:\"abc\"; offset:3; depth:3; pcre:/\"klm\"/R; content:\"xyz\"; distance:0; within:3; ", 6, 0);
861
862 TEST_RUN("content:\"abc\"; depth:3; content:\"klm\"; within:3; content:\"xyz\"; within:3; ", 0, 9);
863
864 TEST_RUN("content:\"abc\"; depth:3; content:\"klm\"; distance:0; content:\"xyz\"; distance:0; ", 6, 0);
865
866 // tests to see if anchored 'ends_with' is applied to other content as depth
867 TEST_RUN("content:\"abc\"; depth:6; isdataat:!1,relative; content:\"klm\";", 0, 6);
868 TEST_RUN("content:\"abc\"; depth:3; content:\"klm\"; within:3; content:\"xyz\"; within:3; isdataat:!1,relative; content:\"def\"; ", 0, 9);
869
870 TEST_RUN("content:\"|03|\"; depth:1; content:\"|e0|\"; distance:4; within:1;", 5, 6);
871 TEST_RUN("content:\"|03|\"; depth:1; content:\"|e0|\"; distance:4; within:1; content:\"Cookie|3a|\"; distance:5; within:7;", 11, 18);
872
873 TEST_RUN("content:\"this\"; content:\"is\"; within:6; content:\"big\"; within:8; content:\"string\"; within:8;", 0, 0);
874
875 TEST_RUN("dsize:<80; content:!\"|00 22 02 00|\"; depth: 4; content:\"|00 00 04|\"; distance:8; within:3; content:\"|00 00 00 00 00|\"; distance:6; within:5;", 17, 80);
876 TEST_RUN("content:!\"|00 22 02 00|\"; depth: 4; content:\"|00 00 04|\"; distance:8; within:3; content:\"|00 00 00 00 00|\"; distance:6; within:5;", 17, 0);
877
878 TEST_RUN("content:\"|0d 0a 0d 0a|\"; content:\"code=\"; distance:0;", 4, 0);
879 TEST_RUN("content:\"|0d 0a 0d 0a|\"; content:\"code=\"; distance:0; content:\"xploit.class\"; distance:2; within:18;", 11, 0);
880
881 TEST_RUN("content:\"|16 03|\"; depth:2; content:\"|55 04 0a|\"; distance:0;", 2, 0);
882 TEST_RUN("content:\"|16 03|\"; depth:2; content:\"|55 04 0a|\"; distance:0; content:\"|0d|LogMeIn, Inc.\"; distance:1; within:14;", 6, 0);
883 TEST_RUN("content:\"|16 03|\"; depth:2; content:\"|55 04 0a|\"; distance:0; content:\"|0d|LogMeIn, Inc.\"; distance:1; within:14; content:\".app\";", 0, 0);
884
885 TEST_RUN("content:\"=\"; offset:4; depth:9;", 4, 13);
886 // low end: offset 4 + patlen 1 = 5. So 5 + distance 55 = 60.
887 // hi end: depth '13' (4+9) + distance 55 = 68 + within 2 = 70
888 TEST_RUN("content:\"=\"; offset:4; depth:9; content:\"=&\"; distance:55; within:2;", 60, 70);
889
890 // distance value is too high so we bail and not set anything on this content
891 TEST_RUN("content:\"0123456789\"; content:\"abcdef\"; distance:1048576;", 0, 0);
892
893 // Bug #5162.
894 TEST_RUN("content:\"SMB\"; depth:8; content:\"|09 00|\"; distance:8; within:2;", 11, 18);
895 TEST_RUN("content:\"SMB\"; depth:8; content:\"|09 00|\"; distance:8; within:2; content:\"|05 "
896 "00 00|\"; distance:0;",
897 13, 0);
898 TEST_RUN("content:\"SMB\"; depth:8; content:\"|09 00|\"; distance:8; within:2; content:\"|05 "
899 "00 00|\"; distance:0; content:\"|0c 00|\"; distance:19; within:2;",
900 35, 0);
901 TEST_RUN("content:\"SMB\"; depth:8; content:\"|09 00|\"; distance:8; within:2; content:\"|05 "
902 "00 00|\"; distance:0; content:\"|0c 00|\"; distance:19; within:2; content:\"|15 00 "
903 "00 00|\"; distance:20; within:4;",
904 57, 0);
905
906 TEST_DONE;
907}
908
909/**
910 * \brief Print list of DETECT_CONTENT SigMatch's allocated in a
911 * SigMatch list, from the current sm to the end
912 * \param sm pointer to the current SigMatch to start printing from
913 */
914static void DetectContentPrintAll(SigMatch *sm)
915{
916#ifdef DEBUG
917 if (SCLogDebugEnabled()) {
918 int i = 0;
919
920 if (sm == NULL)
921 return;
922
923 SigMatch *first_sm = sm;
924
925 /* Print all of them */
926 for (; first_sm != NULL; first_sm = first_sm->next) {
927 if (first_sm->type == DETECT_CONTENT) {
928 SCLogDebug("Printing SigMatch DETECT_CONTENT %d", ++i);
930 }
931 }
932 }
933#endif /* DEBUG */
934}
935
936static int g_file_data_buffer_id = 0;
937static int g_dce_stub_data_buffer_id = 0;
938
939/**
940 * \test DetectContentParseTest01 this is a test to make sure we can deal with escaped colons
941 */
942static int DetectContentParseTest01 (void)
943{
944 int result = 1;
945 DetectContentData *cd = NULL;
946 const char *teststring = "abc\\:def";
947 const char *teststringparsed = "abc:def";
948
949 uint8_t spm_matcher = SinglePatternMatchDefaultMatcher();
950 SpmGlobalThreadCtx *spm_global_thread_ctx = SpmInitGlobalThreadCtx(spm_matcher);
951 FAIL_IF(spm_global_thread_ctx == NULL);
952
953 cd = DetectContentParse(spm_global_thread_ctx, teststring);
954 if (cd != NULL) {
955 if (memcmp(cd->content, teststringparsed, strlen(teststringparsed)) != 0) {
956 SCLogDebug("expected %s got ", teststringparsed);
957 PrintRawUriFp(stdout,cd->content,cd->content_len);
958 SCLogDebug(": ");
959 result = 0;
960 DetectContentFree(NULL, cd);
961 }
962 } else {
963 SCLogDebug("expected %s got NULL: ", teststringparsed);
964 result = 0;
965 }
966 SpmDestroyGlobalThreadCtx(spm_global_thread_ctx);
967 return result;
968}
969
970/**
971 * \test DetectContentParseTest02 this is a test to make sure we can deal with escaped semi-colons
972 */
973static int DetectContentParseTest02 (void)
974{
975 int result = 1;
976 DetectContentData *cd = NULL;
977 const char *teststring = "abc\\;def";
978 const char *teststringparsed = "abc;def";
979
980 uint8_t spm_matcher = SinglePatternMatchDefaultMatcher();
981 SpmGlobalThreadCtx *spm_global_thread_ctx = SpmInitGlobalThreadCtx(spm_matcher);
982 FAIL_IF(spm_global_thread_ctx == NULL);
983
984 cd = DetectContentParse(spm_global_thread_ctx, teststring);
985 if (cd != NULL) {
986 if (memcmp(cd->content, teststringparsed, strlen(teststringparsed)) != 0) {
987 SCLogDebug("expected %s got ", teststringparsed);
988 PrintRawUriFp(stdout,cd->content,cd->content_len);
989 SCLogDebug(": ");
990 result = 0;
991 DetectContentFree(NULL, cd);
992 }
993 } else {
994 SCLogDebug("expected %s got NULL: ", teststringparsed);
995 result = 0;
996 }
997 SpmDestroyGlobalThreadCtx(spm_global_thread_ctx);
998 return result;
999}
1000
1001/**
1002 * \test DetectContentParseTest03 this is a test to make sure we can deal with escaped double-quotes
1003 */
1004static int DetectContentParseTest03 (void)
1005{
1006 int result = 1;
1007 DetectContentData *cd = NULL;
1008 const char *teststring = "abc\\\"def";
1009 const char *teststringparsed = "abc\"def";
1010
1011 uint8_t spm_matcher = SinglePatternMatchDefaultMatcher();
1012 SpmGlobalThreadCtx *spm_global_thread_ctx = SpmInitGlobalThreadCtx(spm_matcher);
1013 FAIL_IF(spm_global_thread_ctx == NULL);
1014
1015 cd = DetectContentParse(spm_global_thread_ctx, teststring);
1016 if (cd != NULL) {
1017 if (memcmp(cd->content, teststringparsed, strlen(teststringparsed)) != 0) {
1018 SCLogDebug("expected %s got ", teststringparsed);
1019 PrintRawUriFp(stdout,cd->content,cd->content_len);
1020 SCLogDebug(": ");
1021 result = 0;
1022 DetectContentFree(NULL, cd);
1023 }
1024 } else {
1025 SCLogDebug("expected %s got NULL: ", teststringparsed);
1026 result = 0;
1027 }
1028 SpmDestroyGlobalThreadCtx(spm_global_thread_ctx);
1029 return result;
1030}
1031
1032/**
1033 * \test DetectContentParseTest04 this is a test to make sure we can deal with escaped backslashes
1034 */
1035static int DetectContentParseTest04 (void)
1036{
1037 int result = 1;
1038 DetectContentData *cd = NULL;
1039 const char *teststring = "abc\\\\def";
1040 const char *teststringparsed = "abc\\def";
1041
1042 uint8_t spm_matcher = SinglePatternMatchDefaultMatcher();
1043 SpmGlobalThreadCtx *spm_global_thread_ctx = SpmInitGlobalThreadCtx(spm_matcher);
1044 FAIL_IF(spm_global_thread_ctx == NULL);
1045
1046 cd = DetectContentParse(spm_global_thread_ctx, teststring);
1047 if (cd != NULL) {
1048 uint16_t len = (cd->content_len > strlen(teststringparsed));
1049 if (memcmp(cd->content, teststringparsed, len) != 0) {
1050 SCLogDebug("expected %s got ", teststringparsed);
1051 PrintRawUriFp(stdout,cd->content,cd->content_len);
1052 SCLogDebug(": ");
1053 result = 0;
1054 DetectContentFree(NULL, cd);
1055 }
1056 } else {
1057 SCLogDebug("expected %s got NULL: ", teststringparsed);
1058 result = 0;
1059 }
1060 SpmDestroyGlobalThreadCtx(spm_global_thread_ctx);
1061 return result;
1062}
1063
1064/**
1065 * \test DetectContentParseTest05 test illegal escape
1066 */
1067static int DetectContentParseTest05 (void)
1068{
1069 int result = 1;
1070 DetectContentData *cd = NULL;
1071 const char *teststring = "abc\\def";
1072
1073 uint8_t spm_matcher = SinglePatternMatchDefaultMatcher();
1074 SpmGlobalThreadCtx *spm_global_thread_ctx = SpmInitGlobalThreadCtx(spm_matcher);
1075 FAIL_IF(spm_global_thread_ctx == NULL);
1076
1077 cd = DetectContentParse(spm_global_thread_ctx, teststring);
1078 if (cd != NULL) {
1079 SCLogDebug("expected NULL got ");
1080 PrintRawUriFp(stdout,cd->content,cd->content_len);
1081 SCLogDebug(": ");
1082 result = 0;
1083 DetectContentFree(NULL, cd);
1084 }
1085 SpmDestroyGlobalThreadCtx(spm_global_thread_ctx);
1086 return result;
1087}
1088
1089/**
1090 * \test DetectContentParseTest06 test a binary content
1091 */
1092static int DetectContentParseTest06 (void)
1093{
1094 int result = 1;
1095 DetectContentData *cd = NULL;
1096 const char *teststring = "a|42|c|44|e|46|";
1097 const char *teststringparsed = "abcdef";
1098
1099 uint8_t spm_matcher = SinglePatternMatchDefaultMatcher();
1100 SpmGlobalThreadCtx *spm_global_thread_ctx = SpmInitGlobalThreadCtx(spm_matcher);
1101 FAIL_IF(spm_global_thread_ctx == NULL);
1102
1103 cd = DetectContentParse(spm_global_thread_ctx, teststring);
1104 if (cd != NULL) {
1105 uint16_t len = (cd->content_len > strlen(teststringparsed));
1106 if (memcmp(cd->content, teststringparsed, len) != 0) {
1107 SCLogDebug("expected %s got ", teststringparsed);
1108 PrintRawUriFp(stdout,cd->content,cd->content_len);
1109 SCLogDebug(": ");
1110 result = 0;
1111 DetectContentFree(NULL, cd);
1112 }
1113 } else {
1114 SCLogDebug("expected %s got NULL: ", teststringparsed);
1115 result = 0;
1116 }
1117 SpmDestroyGlobalThreadCtx(spm_global_thread_ctx);
1118 return result;
1119}
1120
1121/**
1122 * \test DetectContentParseTest07 test an empty content
1123 */
1124static int DetectContentParseTest07 (void)
1125{
1126 int result = 1;
1127 DetectContentData *cd = NULL;
1128 const char *teststring = "";
1129
1130 uint8_t spm_matcher = SinglePatternMatchDefaultMatcher();
1131 SpmGlobalThreadCtx *spm_global_thread_ctx = SpmInitGlobalThreadCtx(spm_matcher);
1132 FAIL_IF(spm_global_thread_ctx == NULL);
1133
1134 cd = DetectContentParse(spm_global_thread_ctx, teststring);
1135 if (cd != NULL) {
1136 SCLogDebug("expected NULL got %p: ", cd);
1137 result = 0;
1138 DetectContentFree(NULL, cd);
1139 }
1140 SpmDestroyGlobalThreadCtx(spm_global_thread_ctx);
1141 return result;
1142}
1143
1144/**
1145 * \test DetectContentParseTest08 test an empty content
1146 */
1147static int DetectContentParseTest08 (void)
1148{
1149 int result = 1;
1150 DetectContentData *cd = NULL;
1151 const char *teststring = "";
1152
1153 uint8_t spm_matcher = SinglePatternMatchDefaultMatcher();
1154 SpmGlobalThreadCtx *spm_global_thread_ctx = SpmInitGlobalThreadCtx(spm_matcher);
1155 FAIL_IF(spm_global_thread_ctx == NULL);
1156
1157 cd = DetectContentParse(spm_global_thread_ctx, teststring);
1158 if (cd != NULL) {
1159 SCLogDebug("expected NULL got %p: ", cd);
1160 result = 0;
1161 DetectContentFree(NULL, cd);
1162 }
1163 SpmDestroyGlobalThreadCtx(spm_global_thread_ctx);
1164 return result;
1165}
1166
1167/**
1168 * \test Test packet Matches
1169 * \param raw_eth_pkt pointer to the ethernet packet
1170 * \param pktsize size of the packet
1171 * \param sig pointer to the signature to test
1172 * \param sid sid number of the signature
1173 * \retval return 1 if match
1174 * \retval return 0 if not
1175 */
1176static int DetectContentLongPatternMatchTest(uint8_t *raw_eth_pkt, uint16_t pktsize, const char *sig,
1177 uint32_t sid)
1178{
1180 FAIL_IF_NULL(p);
1182
1183 ThreadVars th_v;
1184 DetectEngineThreadCtx *det_ctx = NULL;
1185 memset(&dtv, 0, sizeof(DecodeThreadVars));
1186 memset(&th_v, 0, sizeof(th_v));
1187
1189 DecodeEthernet(&th_v, &dtv, p, raw_eth_pkt, pktsize);
1190
1193 de_ctx->flags |= DE_QUIET;
1194
1196 FAIL_IF_NULL(s);
1197
1201 ->ctx;
1203 }
1204
1205 SCLogDebug("---DetectContentLongPatternMatchTest---");
1206 DetectContentPrintAll(de_ctx->sig_list->init_data->smlists[DETECT_SM_LIST_MATCH]);
1207
1209 DetectEngineThreadCtxInit(&th_v, (void *)de_ctx, (void *)&det_ctx);
1210
1211 SigMatchSignatures(&th_v, de_ctx, det_ctx, p);
1212 int result = PacketAlertCheck(p, sid);
1213
1214 DetectEngineThreadCtxDeinit(&th_v, (void *)det_ctx);
1216 PacketRecycle(p);
1217 FlowShutdown();
1218 SCFree(p);
1219 return result;
1220}
1221
1222/**
1223 * \brief Wrapper for DetectContentLongPatternMatchTest
1224 */
1225static int DetectContentLongPatternMatchTestWrp(const char *sig, uint32_t sid)
1226{
1227 /** Real packet with the following tcp data:
1228 * "Hi, this is a big test to check content matches of splitted"
1229 * "patterns between multiple chunks!"
1230 * (without quotes! :) )
1231 */
1232 uint8_t raw_eth_pkt[] = {
1233 0xff,0xff,0xff,0xff,0xff,0xff,0x00,0x00,
1234 0x00,0x00,0x00,0x00,0x08,0x00,0x45,0x00,
1235 0x00,0x85,0x00,0x01,0x00,0x00,0x40,0x06,
1236 0x7c,0x70,0x7f,0x00,0x00,0x01,0x7f,0x00,
1237 0x00,0x01,0x00,0x14,0x00,0x50,0x00,0x00,
1238 0x00,0x00,0x00,0x00,0x00,0x00,0x50,0x02,
1239 0x20,0x00,0xc9,0xad,0x00,0x00,0x48,0x69,
1240 0x2c,0x20,0x74,0x68,0x69,0x73,0x20,0x69,
1241 0x73,0x20,0x61,0x20,0x62,0x69,0x67,0x20,
1242 0x74,0x65,0x73,0x74,0x20,0x74,0x6f,0x20,
1243 0x63,0x68,0x65,0x63,0x6b,0x20,0x63,0x6f,
1244 0x6e,0x74,0x65,0x6e,0x74,0x20,0x6d,0x61,
1245 0x74,0x63,0x68,0x65,0x73,0x20,0x6f,0x66,
1246 0x20,0x73,0x70,0x6c,0x69,0x74,0x74,0x65,
1247 0x64,0x20,0x70,0x61,0x74,0x74,0x65,0x72,
1248 0x6e,0x73,0x20,0x62,0x65,0x74,0x77,0x65,
1249 0x65,0x6e,0x20,0x6d,0x75,0x6c,0x74,0x69,
1250 0x70,0x6c,0x65,0x20,0x63,0x68,0x75,0x6e,
1251 0x6b,0x73,0x21 }; /* end raw_eth_pkt */
1252
1253 return DetectContentLongPatternMatchTest(raw_eth_pkt, (uint16_t)sizeof(raw_eth_pkt),
1254 sig, sid);
1255}
1256
1257/**
1258 * \test Check if we match a normal pattern (not splitted)
1259 */
1260static int DetectContentLongPatternMatchTest01(void)
1261{
1262 const char *sig = "alert tcp any any -> any any (msg:\"Nothing..\";"
1263 " content:\"Hi, this is a big test\"; sid:1;)";
1264 return DetectContentLongPatternMatchTestWrp(sig, 1);
1265}
1266
1267/**
1268 * \test Check if we match a splitted pattern
1269 */
1270static int DetectContentLongPatternMatchTest02(void)
1271{
1272 const char *sig = "alert tcp any any -> any any (msg:\"Nothing..\";"
1273 " content:\"Hi, this is a big test to check content matches of"
1274 " splitted patterns between multiple chunks!\"; sid:1;)";
1275 return DetectContentLongPatternMatchTestWrp(sig, 1);
1276}
1277
1278/**
1279 * \test Check that we don't match the signature if one of the splitted
1280 * chunks doesn't match the packet
1281 */
1282static int DetectContentLongPatternMatchTest03(void)
1283{
1284 /** The last chunk of the content should not match */
1285 const char *sig = "alert tcp any any -> any any (msg:\"Nothing..\";"
1286 " content:\"Hi, this is a big test to check content matches of"
1287 " splitted patterns between multiple splitted chunks!\"; sid:1;)";
1288 return (DetectContentLongPatternMatchTestWrp(sig, 1) == 0) ? 1: 0;
1289}
1290
1291/**
1292 * \test Check if we match multiple content (not splitted)
1293 */
1294static int DetectContentLongPatternMatchTest04(void)
1295{
1296 const char *sig = "alert tcp any any -> any any (msg:\"Nothing..\"; "
1297 " content:\"Hi, this is\"; depth:15 ;content:\"a big test\"; "
1298 " within:15; content:\"to check content matches of\"; "
1299 " within:30; content:\"splitted patterns\"; distance:1; "
1300 " within:30; "
1301 " sid:1;)";
1302 return DetectContentLongPatternMatchTestWrp(sig, 1);
1303}
1304
1305/**
1306 * \test Check that we match packets with multiple chunks and not chunks
1307 * Here we should specify only contents that fit in 32 bytes
1308 * Each of them with their modifier values
1309 */
1310static int DetectContentLongPatternMatchTest05(void)
1311{
1312 const char *sig = "alert tcp any any -> any any (msg:\"Nothing..\"; "
1313 " content:\"Hi, this is a big\"; depth:17; "
1314 " isdataat:30, relative; "
1315 " content:\"test\"; within: 5; distance:1; "
1316 " isdataat:15, relative; "
1317 " content:\"of splitted\"; within:37; distance:15; "
1318 " isdataat:20,relative; "
1319 " content:\"patterns\"; within:9; distance:1; "
1320 " isdataat:10, relative; "
1321 " sid:1;)";
1322 return DetectContentLongPatternMatchTestWrp(sig, 1);
1323}
1324
1325/**
1326 * \test Check that we match packets with multiple chunks and not chunks
1327 * Here we should specify contents that fit and contents that must be splitted
1328 * Each of them with their modifier values
1329 */
1330static int DetectContentLongPatternMatchTest06(void)
1331{
1332 const char *sig = "alert tcp any any -> any any (msg:\"Nothing..\"; "
1333 " content:\"Hi, this is a big test to check cont\"; depth:36;"
1334 " content:\"ent matches\"; within:11; distance:0; "
1335 " content:\"of splitted patterns between multiple\"; "
1336 " within:38; distance:1; "
1337 " content:\"chunks!\"; within: 8; distance:1; "
1338 " sid:1;)";
1339 return DetectContentLongPatternMatchTestWrp(sig, 1);
1340}
1341
1342/**
1343 * \test Check if we match contents that are in the payload
1344 * but not in the same order as specified in the signature
1345 */
1346static int DetectContentLongPatternMatchTest07(void)
1347{
1348 const char *sig = "alert tcp any any -> any any (msg:\"Nothing..\"; "
1349 " content:\"chunks!\"; "
1350 " content:\"content matches\"; offset:32; depth:47; "
1351 " content:\"of splitted patterns between multiple\"; "
1352 " content:\"Hi, this is a big\"; offset:0; depth:17; "
1353 " sid:1;)";
1354 return DetectContentLongPatternMatchTestWrp(sig, 1);
1355}
1356
1357/**
1358 * \test Check if we match contents that are in the payload
1359 * but not in the same order as specified in the signature
1360 */
1361static int DetectContentLongPatternMatchTest08(void)
1362{
1363 const char *sig = "alert tcp any any -> any any (msg:\"Nothing..\"; "
1364 " content:\"ent matches\"; "
1365 " content:\"of splitted patterns between multiple\"; "
1366 " within:38; distance:1; "
1367 " content:\"chunks!\"; within: 8; distance:1; "
1368 " content:\"Hi, this is a big test to check cont\"; depth:36;"
1369 " sid:1;)";
1370 return DetectContentLongPatternMatchTestWrp(sig, 1);
1371}
1372
1373/**
1374 * \test Check if we match contents that are in the payload
1375 * but not in the same order as specified in the signature
1376 */
1377static int DetectContentLongPatternMatchTest09(void)
1378{
1379 const char *sig = "alert tcp any any -> any any (msg:\"Nothing..\"; "
1380 " content:\"ent matches\"; "
1381 " content:\"of splitted patterns between multiple\"; "
1382 " offset:47; depth:85; "
1383 " content:\"chunks!\"; within: 8; distance:1; "
1384 " content:\"Hi, this is a big test to chec\"; depth:36;"
1385 " content:\"k cont\"; distance:0; within:6;"
1386 " sid:1;)";
1387 return DetectContentLongPatternMatchTestWrp(sig, 1);
1388}
1389
1390/**
1391 * \test Check if we match two consecutive simple contents
1392 */
1393static int DetectContentLongPatternMatchTest10(void)
1394{
1395 const char *sig = "alert tcp any any -> any any (msg:\"Nothing..\"; "
1396 " content:\"Hi, this is a big test to check \"; "
1397 " content:\"con\"; "
1398 " sid:1;)";
1399 return DetectContentLongPatternMatchTestWrp(sig, 1);
1400}
1401
1402/**
1403 * \test Check if we match two contents of length 1
1404 */
1405static int DetectContentLongPatternMatchTest11(void)
1406{
1407 const char *sig = "alert tcp any any -> any any (msg:\"Nothing..\"; "
1408 " content:\"H\"; "
1409 " content:\"i\"; "
1410 " sid:1;)";
1411 return DetectContentLongPatternMatchTestWrp(sig, 1);
1412}
1413
1414static int DetectContentParseTest09(void)
1415{
1416 DetectContentData *cd = NULL;
1417 const char *teststring = "boo";
1418
1419 uint8_t spm_matcher = SinglePatternMatchDefaultMatcher();
1420 SpmGlobalThreadCtx *spm_global_thread_ctx = SpmInitGlobalThreadCtx(spm_matcher);
1421 FAIL_IF(spm_global_thread_ctx == NULL);
1422
1423 cd = DetectContentParse(spm_global_thread_ctx, teststring);
1424 FAIL_IF_NULL(cd);
1425 DetectContentFree(NULL, cd);
1426 SpmDestroyGlobalThreadCtx(spm_global_thread_ctx);
1427 PASS;
1428}
1429
1430/**
1431 * \test Test cases where if within specified is < content length we invalidate
1432 * the sig.
1433 */
1434static int DetectContentParseTest17(void)
1435{
1436 int result = 0;
1437 const char *sigstr = "alert tcp any any -> any any (msg:\"Dummy\"; "
1438 "content:\"one\"; content:\"two\"; within:2; sid:1;)";
1439
1441 if (de_ctx == NULL)
1442 goto end;
1443
1444 de_ctx->sig_list = SigInit(de_ctx, sigstr);
1445 if (de_ctx->sig_list != NULL)
1446 goto end;
1447
1448 result = 1;
1449
1450end:
1452 if (de_ctx != NULL)
1454 return result;
1455}
1456
1457/**
1458 * \test Test content for dce sig.
1459 */
1460static int DetectContentParseTest18(void)
1461{
1464
1465 Signature *s = SigAlloc();
1466 FAIL_IF_NULL(s);
1468 FAIL_IF_NOT(DetectContentSetup(de_ctx, s, "one") == 0);
1469 FAIL_IF(DetectBufferIsPresent(s, g_dce_stub_data_buffer_id));
1471 SigFree(de_ctx, s);
1472
1473 s = SigAlloc();
1474 FAIL_IF_NULL(s);
1475 FAIL_IF_NOT(DetectContentSetup(de_ctx, s, "one") == 0);
1476 FAIL_IF(DetectBufferIsPresent(s, g_dce_stub_data_buffer_id));
1478 SigFree(de_ctx, s);
1479
1481 PASS;
1482}
1483
1484/**
1485 * \test Test content for dce sig.
1486 */
1487
1488static int DetectContentParseTest19(void)
1489{
1490
1493 de_ctx->flags |= DE_QUIET;
1494
1495 Signature *s =
1496 DetectEngineAppendSig(de_ctx, "alert tcp any any -> any any "
1497 "(msg:\"Testing dce iface, stub_data with content\"; "
1498 "dce_iface:3919286a-b10c-11d0-9ba8-00c04fd92ef5; "
1499 "dce_stub_data; "
1500 "content:\"one\"; distance:0; sid:1;)");
1501 FAIL_IF_NULL(s);
1502
1503 SigMatch *sm = DetectBufferGetFirstSigMatch(s, g_dce_stub_data_buffer_id);
1504 FAIL_IF_NULL(sm);
1507
1510
1512 "alert tcp any any -> any any "
1513 "(msg:\"Testing dce iface, stub_data with contents & distance, within\"; "
1514 "dce_iface:3919286a-b10c-11d0-9ba8-00c04fd92ef5; "
1515 "dce_stub_data; "
1516 "content:\"one\"; distance:0; content:\"two\"; within:10; sid:2;)");
1517 FAIL_IF_NULL(s);
1518 sm = DetectBufferGetFirstSigMatch(s, g_dce_stub_data_buffer_id);
1519 FAIL_IF_NULL(sm);
1521 FAIL_IF_NULL(sm->next);
1522 sm = sm->next;
1525
1526 data = (DetectContentData *)sm->ctx;
1527 FAIL_IF_NOT(data->flags == DETECT_CONTENT_WITHIN);
1528 FAIL_IF_NOT(data->within == 10);
1529
1531 "alert tcp any any -> any any "
1532 "(msg:\"Testing dce iface, stub with contents, distance, within\"; "
1533 "dce_iface:3919286a-b10c-11d0-9ba8-00c04fd92ef5; "
1534 "dce_stub_data; "
1535 "content:\"one\"; distance:0; "
1536 "content:\"two\"; within:10; distance:2; sid:3;)");
1537 FAIL_IF_NULL(s);
1538 sm = DetectBufferGetFirstSigMatch(s, g_dce_stub_data_buffer_id);
1539 FAIL_IF_NULL(sm);
1541 FAIL_IF_NULL(sm->next);
1542 sm = sm->next;
1544 data = (DetectContentData *)sm->ctx;
1546 FAIL_IF_NOT(data->within == 10);
1547 FAIL_IF_NOT(data->distance == 2);
1549
1550 s = DetectEngineAppendSig(de_ctx, "alert tcp any any -> any any "
1551 "(msg:\"Testing content\"; "
1552 "content:\"one\"; sid:4;)");
1553 FAIL_IF_NULL(s);
1554 FAIL_IF(DetectBufferIsPresent(s, g_dce_stub_data_buffer_id));
1556
1558 PASS;
1559}
1560
1561/**
1562 * \test Test content for dce sig.
1563 */
1564static int DetectContentParseTest20(void)
1565{
1566 DetectEngineCtx *de_ctx = NULL;
1567 int result = 1;
1568
1570 if (de_ctx == NULL)
1571 goto end;
1572
1573 de_ctx->flags |= DE_QUIET;
1575 "alert udp any any -> any any "
1576 "(msg:\"test\"; content:\"\"; sid:238012;)");
1577 if (de_ctx->sig_list != NULL) {
1578 result = 0;
1579 goto end;
1580 }
1581
1582 end:
1586
1587 return result;
1588}
1589
1590/**
1591 * \test Parsing test
1592 */
1593static int DetectContentParseTest21(void)
1594{
1595 DetectEngineCtx *de_ctx = NULL;
1596 int result = 1;
1597
1599 if (de_ctx == NULL)
1600 goto end;
1601
1602 de_ctx->flags |= DE_QUIET;
1604 "alert udp any any -> any any "
1605 "(msg:\"test\"; content:\"; sid:238012;)");
1606 if (de_ctx->sig_list != NULL) {
1607 result = 0;
1608 goto end;
1609 }
1610
1611 end:
1615
1616 return result;
1617}
1618
1619/**
1620 * \test Parsing test
1621 */
1622static int DetectContentParseTest22(void)
1623{
1624 DetectEngineCtx *de_ctx = NULL;
1625 int result = 1;
1626
1628 if (de_ctx == NULL)
1629 goto end;
1630
1631 de_ctx->flags |= DE_QUIET;
1633 "alert udp any any -> any any "
1634 "(msg:\"test\"; content:\"boo; sid:238012;)");
1635 if (de_ctx->sig_list != NULL) {
1636 result = 0;
1637 goto end;
1638 }
1639
1640 end:
1644
1645 return result;
1646}
1647
1648/**
1649 * \test Parsing test
1650 */
1651static int DetectContentParseTest23(void)
1652{
1653 DetectEngineCtx *de_ctx = NULL;
1654 int result = 1;
1655
1657 if (de_ctx == NULL)
1658 goto end;
1659
1660 de_ctx->flags |= DE_QUIET;
1662 "alert udp any any -> any any "
1663 "(msg:\"test\"; content:boo\"; sid:238012;)");
1664 if (de_ctx->sig_list != NULL) {
1665 result = 0;
1666 goto end;
1667 }
1668
1669 end:
1673
1674 return result;
1675}
1676
1677/**
1678 * \test Parsing test
1679 */
1680static int DetectContentParseTest24(void)
1681{
1682 DetectEngineCtx *de_ctx = NULL;
1683 DetectContentData *cd = 0;
1684 Signature *s = NULL;
1685 int result = 1;
1686
1688 if (de_ctx == NULL)
1689 goto end;
1690
1691 de_ctx->flags |= DE_QUIET;
1693 "alert udp any any -> any any "
1694 "(msg:\"test\"; content: !\"boo\"; sid:238012;)");
1695 if (de_ctx->sig_list == NULL) {
1696 printf("de_ctx->sig_list == NULL: ");
1697 result = 0;
1698 goto end;
1699 }
1700
1701 if (s->init_data->smlists_tail[DETECT_SM_LIST_PMATCH] == NULL ||
1703 printf("de_ctx->pmatch_tail == NULL || de_ctx->pmatch_tail->ctx == NULL: ");
1704 result = 0;
1705 goto end;
1706 }
1707
1709 result = (strncmp("boo", (char *)cd->content, cd->content_len) == 0);
1710
1711end:
1715
1716 return result;
1717}
1718
1719/**
1720 * \test Parsing test
1721 */
1722static int DetectContentParseTest25(void)
1723{
1724 DetectEngineCtx *de_ctx = NULL;
1725 int result = 1;
1726
1728 if (de_ctx == NULL)
1729 goto end;
1730
1731 de_ctx->flags |= DE_QUIET;
1733 "alert udp any any -> any any "
1734 "(msg:\"test\"; content:\"|\"; sid:1;)");
1735 if (de_ctx->sig_list != NULL) {
1736 result = 0;
1737 goto end;
1738 }
1739
1740 end:
1744
1745 return result;
1746}
1747
1748/**
1749 * \test Parsing test
1750 */
1751static int DetectContentParseTest26(void)
1752{
1753 DetectEngineCtx *de_ctx = NULL;
1754 int result = 1;
1755
1757 if (de_ctx == NULL)
1758 goto end;
1759
1760 de_ctx->flags |= DE_QUIET;
1762 "alert udp any any -> any any "
1763 "(msg:\"test\"; content:\"|af\"; sid:1;)");
1764 if (de_ctx->sig_list != NULL) {
1765 result = 0;
1766 goto end;
1767 }
1768
1769 end:
1773
1774 return result;
1775}
1776
1777/**
1778 * \test Parsing test
1779 */
1780static int DetectContentParseTest27(void)
1781{
1782 DetectEngineCtx *de_ctx = NULL;
1783 int result = 1;
1784
1786 if (de_ctx == NULL)
1787 goto end;
1788
1789 de_ctx->flags |= DE_QUIET;
1791 "alert udp any any -> any any "
1792 "(msg:\"test\"; content:\"af|\"; sid:1;)");
1793 if (de_ctx->sig_list != NULL) {
1794 result = 0;
1795 goto end;
1796 }
1797
1798 end:
1802
1803 return result;
1804}
1805
1806/**
1807 * \test Parsing test
1808 */
1809static int DetectContentParseTest28(void)
1810{
1811 DetectEngineCtx *de_ctx = NULL;
1812 int result = 1;
1813
1815 if (de_ctx == NULL)
1816 goto end;
1817
1818 de_ctx->flags |= DE_QUIET;
1820 "alert udp any any -> any any "
1821 "(msg:\"test\"; content:\"|af|\"; sid:1;)");
1822 if (de_ctx->sig_list == NULL) {
1823 result = 0;
1824 goto end;
1825 }
1826
1827 end:
1831
1832 return result;
1833}
1834
1835/**
1836 * \test Parsing test
1837 */
1838static int DetectContentParseTest29(void)
1839{
1840 DetectEngineCtx *de_ctx = NULL;
1841 int result = 1;
1842
1844 if (de_ctx == NULL)
1845 goto end;
1846
1847 de_ctx->flags |= DE_QUIET;
1849 "alert udp any any -> any any "
1850 "(msg:\"test\"; content:\"aast|\"; sid:1;)");
1851 if (de_ctx->sig_list != NULL) {
1852 result = 0;
1853 goto end;
1854 }
1855
1856 end:
1860
1861 return result;
1862}
1863
1864/**
1865 * \test Parsing test
1866 */
1867static int DetectContentParseTest30(void)
1868{
1869 DetectEngineCtx *de_ctx = NULL;
1870 int result = 1;
1871
1873 if (de_ctx == NULL)
1874 goto end;
1875
1876 de_ctx->flags |= DE_QUIET;
1878 "alert udp any any -> any any "
1879 "(msg:\"test\"; content:\"aast|af\"; sid:1;)");
1880 if (de_ctx->sig_list != NULL) {
1881 result = 0;
1882 goto end;
1883 }
1884
1885 end:
1889
1890 return result;
1891}
1892
1893/**
1894 * \test Parsing test
1895 */
1896static int DetectContentParseTest31(void)
1897{
1898 DetectEngineCtx *de_ctx = NULL;
1899 int result = 1;
1900
1902 if (de_ctx == NULL)
1903 goto end;
1904
1905 de_ctx->flags |= DE_QUIET;
1907 "alert udp any any -> any any "
1908 "(msg:\"test\"; content:\"aast|af|\"; sid:1;)");
1909 if (de_ctx->sig_list == NULL) {
1910 result = 0;
1911 goto end;
1912 }
1913
1914 end:
1918
1919 return result;
1920}
1921
1922/**
1923 * \test Parsing test
1924 */
1925static int DetectContentParseTest32(void)
1926{
1927 DetectEngineCtx *de_ctx = NULL;
1928 int result = 1;
1929
1931 if (de_ctx == NULL)
1932 goto end;
1933
1934 de_ctx->flags |= DE_QUIET;
1936 "alert udp any any -> any any "
1937 "(msg:\"test\"; content:\"|af|asdf\"; sid:1;)");
1938 if (de_ctx->sig_list == NULL) {
1939 result = 0;
1940 goto end;
1941 }
1942
1943 end:
1947
1948 return result;
1949}
1950
1951/**
1952 * \test Parsing test
1953 */
1954static int DetectContentParseTest33(void)
1955{
1956 DetectEngineCtx *de_ctx = NULL;
1957 int result = 1;
1958
1960 if (de_ctx == NULL)
1961 goto end;
1962
1963 de_ctx->flags |= DE_QUIET;
1965 "alert udp any any -> any any "
1966 "(msg:\"test\"; content:\"|af|af|\"; sid:1;)");
1967 if (de_ctx->sig_list != NULL) {
1968 result = 0;
1969 goto end;
1970 }
1971
1972 end:
1976
1977 return result;
1978}
1979
1980/**
1981 * \test Parsing test
1982 */
1983static int DetectContentParseTest34(void)
1984{
1985 DetectEngineCtx *de_ctx = NULL;
1986 int result = 1;
1987
1989 if (de_ctx == NULL)
1990 goto end;
1991
1992 de_ctx->flags |= DE_QUIET;
1994 "alert udp any any -> any any "
1995 "(msg:\"test\"; content:\"|af|af|af\"; sid:1;)");
1996 if (de_ctx->sig_list != NULL) {
1997 result = 0;
1998 goto end;
1999 }
2000
2001 end:
2005
2006 return result;
2007}
2008
2009/**
2010 * \test Parsing test
2011 */
2012static int DetectContentParseTest35(void)
2013{
2014 DetectEngineCtx *de_ctx = NULL;
2015 int result = 1;
2016
2018 if (de_ctx == NULL)
2019 goto end;
2020
2021 de_ctx->flags |= DE_QUIET;
2023 "alert udp any any -> any any "
2024 "(msg:\"test\"; content:\"|af|af|af|\"; sid:1;)");
2025 if (de_ctx->sig_list == NULL) {
2026 result = 0;
2027 goto end;
2028 }
2029
2030 end:
2034
2035 return result;
2036}
2037
2038static int SigTestPositiveTestContent(const char *rule, uint8_t *buf)
2039{
2040 uint16_t buflen = strlen((char *)buf);
2041 ThreadVars th_v;
2042 DetectEngineThreadCtx *det_ctx = NULL;
2043
2044 memset(&th_v, 0, sizeof(th_v));
2045 Packet *p = UTHBuildPacket(buf, buflen, IPPROTO_TCP);
2046 FAIL_IF_NULL(p);
2047
2050 de_ctx->flags |= DE_QUIET;
2051
2052 de_ctx->sig_list = SigInit(de_ctx, rule);
2054
2056 DetectEngineThreadCtxInit(&th_v, (void *)de_ctx, (void *)&det_ctx);
2057 FAIL_IF_NULL(det_ctx);
2058
2059 SigMatchSignatures(&th_v, de_ctx, det_ctx, p);
2060
2061 FAIL_IF(PacketAlertCheck(p, 1) != 1);
2062
2063 DetectEngineThreadCtxDeinit(&th_v, (void *)det_ctx);
2065
2066 UTHFreePackets(&p, 1);
2067 PASS;
2068}
2069
2070static int DetectContentParseTest41(void)
2071{
2072 int result = 1;
2073 DetectContentData *cd = NULL;
2074 int patlen = 255;
2075 char *teststring = SCMalloc(sizeof(char) * (patlen + 1));
2076 if (unlikely(teststring == NULL))
2077 return 0;
2078 int idx = 0;
2079 for (int i = 0; i < patlen; idx++, i++) {
2080 teststring[idx] = 'a';
2081 }
2082 teststring[idx++] = '\0';
2083
2084 uint8_t spm_matcher = SinglePatternMatchDefaultMatcher();
2085 SpmGlobalThreadCtx *spm_global_thread_ctx = SpmInitGlobalThreadCtx(spm_matcher);
2086 FAIL_IF(spm_global_thread_ctx == NULL);
2087
2088 cd = DetectContentParse(spm_global_thread_ctx, teststring);
2089 if (cd == NULL) {
2090 SCLogDebug("expected not NULL");
2091 result = 0;
2092 }
2093
2094 SpmDestroyGlobalThreadCtx(spm_global_thread_ctx);
2095 SCFree(teststring);
2096 DetectContentFree(NULL, cd);
2097 return result;
2098}
2099
2100/**
2101 * Tests that content lengths > 255 are supported.
2102 */
2103static int DetectContentParseTest42(void)
2104{
2105 int result = 1;
2106 DetectContentData *cd = NULL;
2107 int patlen = 256;
2108 char *teststring = SCMalloc(sizeof(char) * (patlen + 1));
2109 if (unlikely(teststring == NULL))
2110 return 0;
2111 int idx = 0;
2112 for (int i = 0; i < patlen; idx++, i++) {
2113 teststring[idx] = 'a';
2114 }
2115 teststring[idx++] = '\0';
2116
2117 uint8_t spm_matcher = SinglePatternMatchDefaultMatcher();
2118 SpmGlobalThreadCtx *spm_global_thread_ctx = SpmInitGlobalThreadCtx(spm_matcher);
2119 FAIL_IF(spm_global_thread_ctx == NULL);
2120
2121 cd = DetectContentParse(spm_global_thread_ctx, teststring);
2122 if (cd == NULL) {
2123 SCLogDebug("expected not NULL");
2124 result = 0;
2125 }
2126
2127 SpmDestroyGlobalThreadCtx(spm_global_thread_ctx);
2128 SCFree(teststring);
2129 DetectContentFree(NULL, cd);
2130 return result;
2131}
2132
2133static int DetectContentParseTest43(void)
2134{
2135 int result = 1;
2136 DetectContentData *cd = NULL;
2137 int patlen = 258;
2138 char *teststring = SCMalloc(sizeof(char) * (patlen + 1));
2139 if (unlikely(teststring == NULL))
2140 return 0;
2141 int idx = 0;
2142 teststring[idx++] = '|';
2143 teststring[idx++] = '4';
2144 teststring[idx++] = '6';
2145 teststring[idx++] = '|';
2146 for (int i = 0; i < (patlen - 4); idx++, i++) {
2147 teststring[idx] = 'a';
2148 }
2149 teststring[idx++] = '\0';
2150
2151 uint8_t spm_matcher = SinglePatternMatchDefaultMatcher();
2152 SpmGlobalThreadCtx *spm_global_thread_ctx = SpmInitGlobalThreadCtx(spm_matcher);
2153 FAIL_IF(spm_global_thread_ctx == NULL);
2154
2155 cd = DetectContentParse(spm_global_thread_ctx, teststring);
2156 if (cd == NULL) {
2157 SCLogDebug("expected not NULL");
2158 result = 0;
2159 }
2160
2161 SpmDestroyGlobalThreadCtx(spm_global_thread_ctx);
2162 SCFree(teststring);
2163 DetectContentFree(NULL, cd);
2164 return result;
2165}
2166
2167/**
2168 * Tests that content lengths > 255 are supported.
2169 */
2170static int DetectContentParseTest44(void)
2171{
2172 int result = 1;
2173 DetectContentData *cd = NULL;
2174 int patlen = 259;
2175 char *teststring = SCMalloc(sizeof(char) * (patlen + 1));
2176 if (unlikely(teststring == NULL))
2177 return 0;
2178 int idx = 0;
2179 teststring[idx++] = '|';
2180 teststring[idx++] = '4';
2181 teststring[idx++] = '6';
2182 teststring[idx++] = '|';
2183 for (int i = 0; i < (patlen - 4); idx++, i++) {
2184 teststring[idx] = 'a';
2185 }
2186 teststring[idx++] = '\0';
2187
2188 uint8_t spm_matcher = SinglePatternMatchDefaultMatcher();
2189 SpmGlobalThreadCtx *spm_global_thread_ctx = SpmInitGlobalThreadCtx(spm_matcher);
2190 FAIL_IF(spm_global_thread_ctx == NULL);
2191
2192 cd = DetectContentParse(spm_global_thread_ctx, teststring);
2193 if (cd == NULL) {
2194 SCLogDebug("expected not NULL");
2195 result = 0;
2196 }
2197
2198 SpmDestroyGlobalThreadCtx(spm_global_thread_ctx);
2199 SCFree(teststring);
2200 DetectContentFree(NULL, cd);
2201 return result;
2202}
2203
2204/**
2205 * \test Parsing test to check for unescaped quote within content section
2206 */
2207static int DetectContentParseTest45(void)
2208{
2209 DetectEngineCtx *de_ctx = NULL;
2210
2213
2214 de_ctx->flags |= DE_QUIET;
2216 "alert tcp any any -> any any "
2217 "(msg:\"test\"; content:\"|ff|\" content:\"TEST\"; sid:1;)");
2219
2221
2222 PASS;
2223}
2224
2225static int SigTestNegativeTestContent(const char *rule, uint8_t *buf)
2226{
2227 uint16_t buflen = strlen((char *)buf);
2228 Packet *p = NULL;
2229 ThreadVars th_v;
2230 DetectEngineThreadCtx *det_ctx = NULL;
2231 int result = 0;
2232 memset(&th_v, 0, sizeof(th_v));
2233
2234 p = UTHBuildPacket(buf, buflen, IPPROTO_TCP);
2235
2237 if (de_ctx == NULL)
2238 goto end;
2239
2240 de_ctx->flags |= DE_QUIET;
2241
2242 de_ctx->sig_list = SigInit(de_ctx, rule);
2243 if (de_ctx->sig_list == NULL) {
2244 goto end;
2245 }
2246
2248 DetectEngineThreadCtxInit(&th_v, (void *)de_ctx, (void *)&det_ctx);
2249
2250 SigMatchSignatures(&th_v, de_ctx, det_ctx, p);
2251 if (PacketAlertCheck(p, 1) != 0) {
2252 goto end;
2253 }
2254
2255 result = 1;
2256end:
2257 if (det_ctx != NULL) {
2258 DetectEngineThreadCtxDeinit(&th_v, (void *)det_ctx);
2259 }
2260 if (de_ctx != NULL) {
2264 }
2265 UTHFreePackets(&p, 1);
2266 return result;
2267}
2268
2269/**
2270 * \test A positive test that checks that the content string doesn't contain
2271 * the negated content
2272 */
2273static int SigTest41TestNegatedContent(void)
2274{
2275 return SigTestPositiveTestContent("alert tcp any any -> any any "
2276 "(msg:\"HTTP URI cap\"; content:!\"GES\"; sid:1;)",
2277
2278 (uint8_t *)"GET /one/ HTTP/1.1\r\n Host: one.example.org\r\n\r\n\r\n"
2279 "GET /two/ HTTP/1.1\r\nHost: two.example.org\r\n\r\n\r\n");
2280}
2281
2282/**
2283 * \test crash condition: as packet has no direction, it defaults to toclient
2284 * in stream ctx inspection of packet. There a null ptr deref happens
2285 * We don't care about the match/nomatch here.
2286 */
2287static int SigTest41aTestNegatedContent(void)
2288{
2289 (void)SigTestPositiveTestContent("alert tcp any any -> any any (msg:\"HTTP URI cap\"; flow:to_server; content:\"GET\"; sid:1;)", (uint8_t *)"GET /one/ HTTP/1.1\r\n Host: one.example.org\r\n\r\n\r\nGET /two/ HTTP/1.1\r\nHost: two.example.org\r\n\r\n\r\n");
2290 return 1;
2291}
2292
2293
2294/**
2295 * \test A positive test that checks that the content string doesn't contain
2296 * the negated content within the specified depth
2297 */
2298static int SigTest42TestNegatedContent(void)
2299{
2300 return SigTestPositiveTestContent(
2301 "alert tcp any any -> any any (content:!\"eeeeeeeeeee\"; depth:22; offset:35; sid:1;)",
2302 (uint8_t *)"aaa bbbb cccc dddddddd eeeeeeeeeee ffffffffff gggggggg hhhhhhhh");
2303}
2304
2305/**
2306 * \test A negative test that checks that the content string doesn't contain
2307 * the negated content within the specified depth, and also after the
2308 * specified offset. Since the content is there, the match fails.
2309 *
2310 * Match is at offset:23, depth:34
2311 */
2312static int SigTest43TestNegatedContent(void)
2313{
2314 return SigTestNegativeTestContent(
2315 "alert tcp any any -> any any (content:!\"eeeeeeeeeee\"; depth:34; offset:23; sid:1;)",
2316 (uint8_t *)"aaa bbbb cccc dddddddd eeeeeeeeeee ffffffffff gggggggg hhhhhhhh");
2317}
2318
2319/**
2320 * \test A negative test that checks that the content string doesn't contain
2321 * the negated content after the specified offset and within the specified
2322 * depth.
2323 */
2324static int SigTest44TestNegatedContent(void)
2325{
2326 return SigTestPositiveTestContent(
2327 "alert tcp any any -> any any (content:!\"eeeeeeeeeee\"; offset:40; depth:35; sid:1;)",
2328 (uint8_t *)"aaa bbbb cccc dddddddd eeeeeeeeeee ffffffffff gggggggg hhhhhhhh");
2329}
2330
2331/**
2332 * \test A positive test that uses a combination of content string with negated
2333 * content string
2334 */
2335static int SigTest45TestNegatedContent(void)
2336{
2337 return SigTestPositiveTestContent("alert tcp any any -> any any (content:\"aaa\"; depth:5; "
2338 "content:!\"eeeeeeeeeee\"; depth:23; sid:1;)",
2339 (uint8_t *)"aaa bbbb cccc dddddddd eeeeeeeeeee ffffffffff gggggggg hhhhhhhh");
2340}
2341
2342/**
2343 * \test A negative test that uses a combination of content string with negated
2344 * content string, with we receiving a failure for 'onee' itself.
2345 */
2346static int SigTest46TestNegatedContent(void)
2347{
2348 return SigTestNegativeTestContent("alert tcp any any -> any any (content:\"aaaE\"; "
2349 "content:!\"eeeeeeeeeee\"; depth:23; sid:1;)",
2350 (uint8_t *)"aaa bbbb cccc dddddddd eeeeeeeeeee ffffffffff gggggggg hhhhhhhh");
2351}
2352
2353/**
2354 * \test A negative test that uses a combination of content string with negated
2355 * content string, with we receiving a failure of first content's offset
2356 * condition
2357 */
2358static int SigTest47TestNegatedContent(void)
2359{
2360 return SigTestNegativeTestContent("alert tcp any any -> any any (content:\"aaa\"; offset:5; "
2361 "content:!\"eeeeeeeeeee\"; depth:23; sid:1;)",
2362 (uint8_t *)"aaa bbbb cccc dddddddd eeeeeeeeeee ffffffffff gggggggg hhhhhhhh");
2363}
2364
2365/**
2366 * \test A positive test that checks that we don't have a negated content within
2367 * the specified length from the previous content match.
2368 */
2369static int SigTest48TestNegatedContent(void)
2370{
2371 return SigTestPositiveTestContent(
2372 "alert tcp any any -> any any (content:\"GET\"; content:!\"GES\"; within:26; sid:1;)",
2373 (uint8_t *)"GET /one/ HTTP/1.1\r\n Host: one.example.org\r\n\r\n\r\nGET /two/ "
2374 "HTTP/1.1\r\nHost: two.example.org\r\n\r\n\r\n");
2375}
2376
2377/**
2378 * \test A negative test that checks the combined use of content and negated
2379 * content with the use of within
2380 */
2381static int SigTest49TestNegatedContent(void)
2382{
2383 return SigTestNegativeTestContent(
2384 "alert tcp any any -> any any (content:\"GET\"; content:!\"Host\"; within:26; sid:1;)",
2385 (uint8_t *)"GET /one/ HTTP/1.1\r\n Host: one.example.org\r\n\r\n\r\nGET /two/ "
2386 "HTTP/1.1\r\nHost: two.example.org\r\n\r\n\r\n");
2387}
2388
2389/**
2390 * \test A positive test that checks the combined use of content and negated
2391 * content with the use of distance
2392 */
2393static int SigTest50TestNegatedContent(void)
2394{
2395 return SigTestPositiveTestContent(
2396 "alert tcp any any -> any any (content:\"GET\"; content:!\"GES\"; distance:25; sid:1;)",
2397 (uint8_t *)"GET /one/ HTTP/1.1\r\n Host: one.example.org\r\n\r\n\r\nGET /two/ "
2398 "HTTP/1.1\r\nHost: two.example.org\r\n\r\n\r\n");
2399}
2400
2401/**
2402 * \test A negative test that checks the combined use of content and negated
2403 * content with the use of distance
2404 *
2405 * First GET at offset 0
2406 * First Host at offset 21
2407 */
2408static int SigTest51TestNegatedContent(void)
2409{
2410 return SigTestNegativeTestContent("alert tcp any any -> any any (content:\"GET\"; content:!\"Host\"; distance:17; sid:1;)", (uint8_t *)"GET /one/ HTTP/1.1\r\nHost: one.example.org\r\n\r\n\r\nGET /two/ HTTP/1.1\r\nHost: two.example.org\r\n\r\n\r\n");
2411}
2412
2413/**
2414 * \test A negative test that checks the combined use of content and negated
2415 * content, with the content not being present
2416 */
2417static int SigTest52TestNegatedContent(void)
2418{
2419 return SigTestNegativeTestContent(
2420 "alert tcp any any -> any any (content:\"GES\"; content:!\"BOO\"; sid:1;)",
2421 (uint8_t *)"GET /one/ HTTP/1.1\r\n Host: one.example.org\r\n\r\n\r\nGET /two/ "
2422 "HTTP/1.1\r\nHost: two.example.org\r\n\r\n\r\n");
2423}
2424
2425/**
2426 * \test A negative test that checks the combined use of content and negated
2427 * content, in the presence of within
2428 */
2429static int SigTest53TestNegatedContent(void)
2430{
2431 return SigTestNegativeTestContent(
2432 "alert tcp any any -> any any (content:\"aaa\"; content:!\"Ggggg\"; within:56; sid:1;)",
2433 (uint8_t *)"aaa bbbb cccc dddddddd eeeeeeeeeee ffffffffff Ggggggggg hhhhhhhh");
2434}
2435
2436/**
2437 * \test A positive test that checks the combined use of content and negated
2438 * content, in the presence of within
2439 */
2440static int SigTest54TestNegatedContent(void)
2441{
2442 return SigTestPositiveTestContent("alert tcp any any -> any any (content:\"aaa\"; "
2443 "content:!\"gggggg\"; within:20; sid:1;)",
2444 (uint8_t *)"aaa bbbb cccc dddddddd eeeeeeeeeee ffffffffff ggggggggg hhhhhhhh");
2445}
2446
2447/**
2448 * \test A negative test that checks the use of negated content along with
2449 * the presence of depth
2450 */
2451static int SigTest55TestNegatedContent(void)
2452{
2453 return SigTestNegativeTestContent(
2454 "alert tcp any any -> any any (content:!\"aaa\"; depth:5; sid:1;)",
2455 (uint8_t *)"aaa bbbb cccc dddddddd eeeeeeeeeee ffffffffff gggggggg hhhhhhhh");
2456}
2457
2458/**
2459 * \test A positive test that checks the combined use of 2 contents in the
2460 * presence of within
2461 */
2462static int SigTest56TestNegatedContent(void)
2463{
2464 return SigTestPositiveTestContent(
2465 "alert tcp any any -> any any (content:\"aaa\"; content:\"Ggggg\"; within:56; sid:1;)",
2466 (uint8_t *)"aaa bbbb cccc dddddddd eeeeeeeeeee ffffffffff Gggggggg hhhhhhhh");
2467}
2468
2469/**
2470 * \test A negative test that checks the combined use of content and negated
2471 * content, in the presence of within
2472 */
2473static int SigTest57TestNegatedContent(void)
2474{
2475 return SigTestNegativeTestContent(
2476 "alert tcp any any -> any any (content:\"aaa\"; content:!\"Ggggg\"; within:56; sid:1;)",
2477 (uint8_t *)"aaa bbbb cccc dddddddd eeeeeeeeeee ffffffffff Ggggggggg hhhhhhhh");
2478}
2479
2480/**
2481 * \test A positive test that checks the combined use of content and negated
2482 * content, in the presence of distance
2483 */
2484static int SigTest58TestNegatedContent(void)
2485{
2486 return SigTestPositiveTestContent("alert tcp any any -> any any (content:\"aaa\"; "
2487 "content:!\"Ggggg\"; distance:57; sid:1;)",
2488 (uint8_t *)"aaa bbbb cccc dddddddd eeeeeeeeeee ffffffffff Ggggggggg hhhhhhhh");
2489}
2490
2491/**
2492 * \test A negative test that checks the combined use of content and negated
2493 * content, in the presence of distance
2494 */
2495static int SigTest59TestNegatedContent(void)
2496{
2497 return SigTestNegativeTestContent("alert tcp any any -> any any (content:\"aaa\"; "
2498 "content:!\"Gggg\"; distance:30; sid:1;)",
2499 (uint8_t *)"aaa bbbb cccc dddddddd eeeeeeeeeee ffffffffff Ggggggggg hhhhhhhh");
2500}
2501
2502static int SigTest60TestNegatedContent(void)
2503{
2504 return SigTestNegativeTestContent(
2505 "alert tcp any any -> any any (content:!\"aaa\"; content:\"Ggggg\"; sid:1;)",
2506 (uint8_t *)"aaa bbbb cccc dddddddd eeeeeeeeeee ffffffffff Ggggggggg hhhhhhhh");
2507}
2508
2509static int SigTest61TestNegatedContent(void)
2510{
2511 return SigTestPositiveTestContent("alert tcp any any -> any any (content:\"aaa\"; depth:10; "
2512 "content:!\"Ggggg\"; within:30; sid:1;)",
2513 (uint8_t *)"aaa bbbb cccc dddddddd eeeeeeeeeee ffffffffff Ggggggggg hhhhhhhh");
2514}
2515
2516/** \test Test negation in combination with within and depth
2517 *
2518 * Match of "aaa" at offset:0, depth:3
2519 * Match of "Gggggg" at offset:46, depth:52
2520 *
2521 * This signature should not match for the test to pass.
2522 */
2523static int SigTest62TestNegatedContent(void)
2524{
2525 return SigTestNegativeTestContent("alert tcp any any -> any any (content:\"aaa\"; depth:10; "
2526 "content:!\"Gggggg\"; within:49; sid:1;)",
2527 (uint8_t *)"aaa bbbb cccc dddddddd eeeeeeeeeee ffffffffff Ggggggggg hhhhhhhh");
2528}
2529
2530static int SigTest63TestNegatedContent(void)
2531{
2532 return SigTestNegativeTestContent("alert tcp any any -> any any (content:\"aaa\"; depth:10; "
2533 "content:!\"Gggggg\"; within:56; sid:1;)",
2534 (uint8_t *)"aaa bbbb cccc dddddddd eeeeeeeeeee ffffffffff Ggggggggg hhhhhhhh");
2535}
2536
2537static int SigTest64TestNegatedContent(void)
2538{
2539 return SigTestPositiveTestContent("alert tcp any any -> any any (content:\"aaa\"; depth:10; "
2540 "content:!\"Gggggg\"; within:30; sid:1;)",
2541 (uint8_t *)"aaa bbbb cccc dddddddd eeeeeeeeeee ffffffffff Ggggggggg hhhhhhhh");
2542}
2543
2544/** \test Test negation in combination with within and depth
2545 *
2546 * Match of "aaa" at offset:0, depth:3
2547 * Match of "gggggg" at offset:46, depth:52
2548 *
2549 * This signature should not match for the test to pass.
2550 */
2551static int SigTest65TestNegatedContent(void)
2552{
2553 return SigTestNegativeTestContent("alert tcp any any -> any any (content:\"aaa\"; depth:10; "
2554 "content:!\"Gggggg\"; distance:0; within:49; sid:1;)",
2555 (uint8_t *)"aaa bbbb cccc dddddddd eeeeeeeeeee ffffffffff Ggggggggg hhhhhhhh");
2556}
2557
2558static int SigTest66TestNegatedContent(void)
2559{
2560 return SigTestPositiveTestContent("alert tcp any any -> any any (content:\"aaa\"; depth:10; "
2561 "content:!\"Gggggg\"; within:30; sid:1;)",
2562 (uint8_t *)"aaa bbbb cccc dddddddd eeeeeeeeeee ffffffffff Ggggggggg hhhhhhhh");
2563}
2564
2565static int SigTest67TestNegatedContent(void)
2566{
2567 return SigTestNegativeTestContent("alert tcp any any -> any any (content:\"aaa\"; depth:10; "
2568 "content:!\"XXXX\"; within:56; sid:1;)",
2569 (uint8_t *)"aaa bbbb cccc XXXXdddd eeeeeeeeeee ffffffffff XXXXggggg hhhhhhhh");
2570}
2571
2572static int SigTest68TestNegatedContent(void)
2573{
2574 return SigTestPositiveTestContent(
2575 "alert tcp any any -> any any (content:\"aaa\"; depth:10; content:\"cccc\"; offset:8; "
2576 "content:!\"Gggggg\"; within:28; content:\"hhhhhhhh\"; sid:1;)",
2577 (uint8_t *)"aaa bbbb cccc dddddddd eeeeeeeeeee ffffffffff Ggggggggg hhhhhhhh");
2578}
2579
2580static int SigTest69TestNegatedContent(void)
2581{
2582 return SigTestNegativeTestContent(
2583 "alert tcp any any -> any any (content:\"aaa\"; depth:10; content:\"cccc\"; offset:8; "
2584 "content:!\"Gggggg\"; within:48; content:\"hhhhhhhh\"; sid:1;)",
2585 (uint8_t *)"aaa bbbb cccc dddddddd eeeeeeeeeee ffffffffff Ggggggggg hhhhhhhh");
2586}
2587
2588static int SigTest70TestNegatedContent(void)
2589{
2590 return SigTestNegativeTestContent("alert tcp any any -> any any (content:\"aaa\"; "
2591 "content:!\"Gggggg\"; within:52; sid:1;)",
2592 (uint8_t *)"aaa bbbb cccc dddddddd eeeeeeeeeee ffffffffff Ggggggggg hhhhhhhh");
2593}
2594
2595/** \test within and distance */
2596static int SigTest71TestNegatedContent(void)
2597{
2598 return SigTestNegativeTestContent("alert tcp any any -> any any (content:\"aaa\"; "
2599 "content:!\"Gggggg\"; within:40; distance:43; sid:1;)",
2600 (uint8_t *)"aaa bbbb cccc dddddddd eeeeeeeeeee ffffffffff Ggggggggg hhhhhhhh");
2601}
2602
2603static int SigTest72TestNegatedContent(void)
2604{
2605 return SigTestNegativeTestContent("alert tcp any any -> any any (content:\"aaa\"; "
2606 "content:!\"Gggggg\"; within:49; distance:43; sid:1;)",
2607 (uint8_t *)"aaa bbbb cccc dddddddd eeeeeeeeeee ffffffffff Ggggggggg hhhhhhhh");
2608}
2609
2610static int SigTest73TestNegatedContent(void)
2611{
2612 return SigTestNegativeTestContent("alert tcp any any -> any any (content:\"aaa\"; depth:5; "
2613 "content:!\"eeeeeeeeeee\"; depth:35; sid:1;)",
2614 (uint8_t *)"aaa bbbb cccc dddddddd eeeeeeeeeee ffffffffff ggggggggg hhhhhhhh");
2615}
2616
2617static int SigTest74TestNegatedContent(void)
2618{
2619 return SigTestPositiveTestContent("alert tcp any any -> any any (msg:\"HTTP URI cap\"; content:\"USER\"; content:!\"PASS\"; sid:1;)", (uint8_t *)"USER apple");
2620}
2621
2622static int SigTest75TestNegatedContent(void)
2623{
2624 return SigTestPositiveTestContent("alert tcp any any -> any any (msg:\"HTTP URI cap\"; content:\"USER\"; content:\"!PASS\"; sid:1;)", (uint8_t *)"USER !PASS");
2625}
2626
2627static int SigTest76TestBug134(void)
2628{
2629 uint8_t *buf = (uint8_t *)"test detect ${IFS} in traffic";
2630 uint16_t buflen = strlen((char *)buf);
2631 Packet *p = UTHBuildPacket( buf, buflen, IPPROTO_TCP);
2632 int result = 0;
2633 Flow f;
2634
2635 memset(&f, 0, sizeof(Flow));
2636 FLOW_INITIALIZE(&f);
2637
2638 p->dp = 515;
2641 p->flow = &f;
2642 p->flags |= PKT_HAS_FLOW;
2643
2644 char sig[] = "alert tcp any any -> any 515 "
2645 "(msg:\"detect IFS\"; flow:to_server,established; content:\"${IFS}\";"
2646 " depth:50; offset:0; sid:900091; rev:1;)";
2647 if (UTHPacketMatchSigMpm(p, sig, MPM_AC) == 0) {
2648 result = 0;
2649 goto end;
2650 }
2651
2652 result = 1;
2653end:
2654 if (p != NULL)
2655 UTHFreePacket(p);
2656
2657 FLOW_DESTROY(&f);
2658 return result;
2659}
2660
2661static int SigTest77TestBug139(void)
2662{
2663 uint8_t buf[] = {
2664 0x12, 0x23, 0x34, 0x35, 0x52, 0x52, 0x24, 0x42, 0x22, 0x24,
2665 0x52, 0x24, 0x82, 0x00, 0x00, 0x00, 0x00, 0x00, 0x24, 0x34 };
2666 uint16_t buflen = sizeof(buf);
2667 Packet *p = UTHBuildPacket( buf, buflen, IPPROTO_UDP);
2668 int result = 0;
2669
2670 p->dp = 53;
2671 char sig[] = "alert udp any any -> any 53 (msg:\"dns testing\";"
2672 " content:\"|00 00|\"; depth:5; offset:13; sid:9436601;"
2673 " rev:1;)";
2674 if (UTHPacketMatchSigMpm(p, sig, MPM_AC) == 0) {
2675 result = 0;
2676 goto end;
2677 }
2678
2679 result = 1;
2680end:
2681 if (p != NULL)
2682 UTHFreePacket(p);
2683 return result;
2684}
2685
2686static int DetectLongContentTestCommon(const char *sig, uint32_t sid)
2687{
2688 /* Packet with 512 A's in it for testing long content. */
2689 static uint8_t pkt[739] = {
2690 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
2691 0x00, 0x00, 0x00, 0x00, 0x08, 0x00, 0x45, 0x00,
2692 0x02, 0xd5, 0x4a, 0x18, 0x40, 0x00, 0x40, 0x06,
2693 0xd7, 0xd6, 0x0a, 0x10, 0x01, 0x0b, 0x0a, 0x10,
2694 0x01, 0x0a, 0xdb, 0x36, 0x00, 0x50, 0xca, 0xc5,
2695 0xcc, 0xd1, 0x95, 0x77, 0x0f, 0x7d, 0x80, 0x18,
2696 0x00, 0xe5, 0x77, 0x9d, 0x00, 0x00, 0x01, 0x01,
2697 0x08, 0x0a, 0x1d, 0xe0, 0x86, 0xc6, 0xfc, 0x73,
2698 0x49, 0xf3, 0x50, 0x4f, 0x53, 0x54, 0x20, 0x2f,
2699 0x20, 0x48, 0x54, 0x54, 0x50, 0x2f, 0x31, 0x2e,
2700 0x31, 0x0d, 0x0a, 0x55, 0x73, 0x65, 0x72, 0x2d,
2701 0x41, 0x67, 0x65, 0x6e, 0x74, 0x3a, 0x20, 0x63,
2702 0x75, 0x72, 0x6c, 0x2f, 0x37, 0x2e, 0x33, 0x37,
2703 0x2e, 0x30, 0x0d, 0x0a, 0x48, 0x6f, 0x73, 0x74,
2704 0x3a, 0x20, 0x31, 0x30, 0x2e, 0x31, 0x36, 0x2e,
2705 0x31, 0x2e, 0x31, 0x30, 0x0d, 0x0a, 0x41, 0x63,
2706 0x63, 0x65, 0x70, 0x74, 0x3a, 0x20, 0x2a, 0x2f,
2707 0x2a, 0x0d, 0x0a, 0x43, 0x6f, 0x6e, 0x74, 0x65,
2708 0x6e, 0x74, 0x2d, 0x4c, 0x65, 0x6e, 0x67, 0x74,
2709 0x68, 0x3a, 0x20, 0x35, 0x32, 0x38, 0x0d, 0x0a,
2710 0x43, 0x6f, 0x6e, 0x74, 0x65, 0x6e, 0x74, 0x2d,
2711 0x54, 0x79, 0x70, 0x65, 0x3a, 0x20, 0x61, 0x70,
2712 0x70, 0x6c, 0x69, 0x63, 0x61, 0x74, 0x69, 0x6f,
2713 0x6e, 0x2f, 0x78, 0x2d, 0x77, 0x77, 0x77, 0x2d,
2714 0x66, 0x6f, 0x72, 0x6d, 0x2d, 0x75, 0x72, 0x6c,
2715 0x65, 0x6e, 0x63, 0x6f, 0x64, 0x65, 0x64, 0x0d,
2716 0x0a, 0x0d, 0x0a, 0x58, 0x58, 0x58, 0x58, 0x58,
2717 0x58, 0x58, 0x58, 0x41, 0x41, 0x41, 0x41, 0x41,
2718 0x41, 0x41, 0x41, 0x41, 0x41, 0x41, 0x41, 0x41,
2719 0x41, 0x41, 0x41, 0x41, 0x41, 0x41, 0x41, 0x41,
2720 0x41, 0x41, 0x41, 0x41, 0x41, 0x41, 0x41, 0x41,
2721 0x41, 0x41, 0x41, 0x41, 0x41, 0x41, 0x41, 0x41,
2722 0x41, 0x41, 0x41, 0x41, 0x41, 0x41, 0x41, 0x41,
2723 0x41, 0x41, 0x41, 0x41, 0x41, 0x41, 0x41, 0x41,
2724 0x41, 0x41, 0x41, 0x41, 0x41, 0x41, 0x41, 0x41,
2725 0x41, 0x41, 0x41, 0x41, 0x41, 0x41, 0x41, 0x41,
2726 0x41, 0x41, 0x41, 0x41, 0x41, 0x41, 0x41, 0x41,
2727 0x41, 0x41, 0x41, 0x41, 0x41, 0x41, 0x41, 0x41,
2728 0x41, 0x41, 0x41, 0x41, 0x41, 0x41, 0x41, 0x41,
2729 0x41, 0x41, 0x41, 0x41, 0x41, 0x41, 0x41, 0x41,
2730 0x41, 0x41, 0x41, 0x41, 0x41, 0x41, 0x41, 0x41,
2731 0x41, 0x41, 0x41, 0x41, 0x41, 0x41, 0x41, 0x41,
2732 0x41, 0x41, 0x41, 0x41, 0x41, 0x41, 0x41, 0x41,
2733 0x41, 0x41, 0x41, 0x41, 0x41, 0x41, 0x41, 0x41,
2734 0x41, 0x41, 0x41, 0x41, 0x41, 0x41, 0x41, 0x41,
2735 0x41, 0x41, 0x41, 0x41, 0x41, 0x41, 0x41, 0x41,
2736 0x41, 0x41, 0x41, 0x41, 0x41, 0x41, 0x41, 0x41,
2737 0x41, 0x41, 0x41, 0x41, 0x41, 0x41, 0x41, 0x41,
2738 0x41, 0x41, 0x41, 0x41, 0x41, 0x41, 0x41, 0x41,
2739 0x41, 0x41, 0x41, 0x41, 0x41, 0x41, 0x41, 0x41,
2740 0x41, 0x41, 0x41, 0x41, 0x41, 0x41, 0x41, 0x41,
2741 0x41, 0x41, 0x41, 0x41, 0x41, 0x41, 0x41, 0x41,
2742 0x41, 0x41, 0x41, 0x41, 0x41, 0x41, 0x41, 0x41,
2743 0x41, 0x41, 0x41, 0x41, 0x41, 0x41, 0x41, 0x41,
2744 0x41, 0x41, 0x41, 0x41, 0x41, 0x41, 0x41, 0x41,
2745 0x41, 0x41, 0x41, 0x41, 0x41, 0x41, 0x41, 0x41,
2746 0x41, 0x41, 0x41, 0x41, 0x41, 0x41, 0x41, 0x41,
2747 0x41, 0x41, 0x41, 0x41, 0x41, 0x41, 0x41, 0x41,
2748 0x41, 0x41, 0x41, 0x41, 0x41, 0x41, 0x41, 0x41,
2749 0x41, 0x41, 0x41, 0x41, 0x41, 0x41, 0x41, 0x41,
2750 0x41, 0x41, 0x41, 0x41, 0x41, 0x41, 0x41, 0x41,
2751 0x41, 0x41, 0x41, 0x41, 0x41, 0x41, 0x41, 0x41,
2752 0x41, 0x41, 0x41, 0x41, 0x41, 0x41, 0x41, 0x41,
2753 0x41, 0x41, 0x41, 0x41, 0x41, 0x41, 0x41, 0x41,
2754 0x41, 0x41, 0x41, 0x41, 0x41, 0x41, 0x41, 0x41,
2755 0x41, 0x41, 0x41, 0x41, 0x41, 0x41, 0x41, 0x41,
2756 0x41, 0x41, 0x41, 0x41, 0x41, 0x41, 0x41, 0x41,
2757 0x41, 0x41, 0x41, 0x41, 0x41, 0x41, 0x41, 0x41,
2758 0x41, 0x41, 0x41, 0x41, 0x41, 0x41, 0x41, 0x41,
2759 0x41, 0x41, 0x41, 0x41, 0x41, 0x41, 0x41, 0x41,
2760 0x41, 0x41, 0x41, 0x41, 0x41, 0x41, 0x41, 0x41,
2761 0x41, 0x41, 0x41, 0x41, 0x41, 0x41, 0x41, 0x41,
2762 0x41, 0x41, 0x41, 0x41, 0x41, 0x41, 0x41, 0x41,
2763 0x41, 0x41, 0x41, 0x41, 0x41, 0x41, 0x41, 0x41,
2764 0x41, 0x41, 0x41, 0x41, 0x41, 0x41, 0x41, 0x41,
2765 0x41, 0x41, 0x41, 0x41, 0x41, 0x41, 0x41, 0x41,
2766 0x41, 0x41, 0x41, 0x41, 0x41, 0x41, 0x41, 0x41,
2767 0x41, 0x41, 0x41, 0x41, 0x41, 0x41, 0x41, 0x41,
2768 0x41, 0x41, 0x41, 0x41, 0x41, 0x41, 0x41, 0x41,
2769 0x41, 0x41, 0x41, 0x41, 0x41, 0x41, 0x41, 0x41,
2770 0x41, 0x41, 0x41, 0x41, 0x41, 0x41, 0x41, 0x41,
2771 0x41, 0x41, 0x41, 0x41, 0x41, 0x41, 0x41, 0x41,
2772 0x41, 0x41, 0x41, 0x41, 0x41, 0x41, 0x41, 0x41,
2773 0x41, 0x41, 0x41, 0x41, 0x41, 0x41, 0x41, 0x41,
2774 0x41, 0x41, 0x41, 0x41, 0x41, 0x41, 0x41, 0x41,
2775 0x41, 0x41, 0x41, 0x41, 0x41, 0x41, 0x41, 0x41,
2776 0x41, 0x41, 0x41, 0x41, 0x41, 0x41, 0x41, 0x41,
2777 0x41, 0x41, 0x41, 0x41, 0x41, 0x41, 0x41, 0x41,
2778 0x41, 0x41, 0x41, 0x41, 0x41, 0x41, 0x41, 0x41,
2779 0x41, 0x41, 0x41, 0x41, 0x41, 0x41, 0x41, 0x41,
2780 0x41, 0x41, 0x41, 0x41, 0x41, 0x41, 0x41, 0x41,
2781 0x41, 0x41, 0x41, 0x58, 0x58, 0x58, 0x58, 0x58,
2782 0x58, 0x58, 0x58
2783 };
2784
2785 return DetectContentLongPatternMatchTest(pkt, (uint16_t)sizeof(pkt), sig,
2786 sid);
2787}
2788
2789static int DetectLongContentTest1(void)
2790{
2791 /* Signature with 256 A's. */
2792 const char *sig = "alert tcp any any -> any any (msg:\"Test Rule\"; content:\"AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA\"; sid:1;)";
2793
2794 return DetectLongContentTestCommon(sig, 1);
2795}
2796
2797static int DetectLongContentTest2(void)
2798{
2799 /* Signature with 512 A's. */
2800 const char *sig = "alert tcp any any -> any any (msg:\"Test Rule\"; content:\"AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA\"; sid:1;)";
2801
2802 return DetectLongContentTestCommon(sig, 1);
2803}
2804
2805static int DetectLongContentTest3(void)
2806{
2807 /* Signature with 513 A's. */
2808 const char *sig = "alert tcp any any -> any any (msg:\"Test Rule\"; content:\"AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA\"; sid:1;)";
2809
2810 return !DetectLongContentTestCommon(sig, 1);
2811}
2812
2813static int DetectBadBinContent(void)
2814{
2815 DetectEngineCtx *de_ctx = NULL;
2818 de_ctx->flags |= DE_QUIET;
2820 de_ctx, "alert tcp any any -> any any (msg:\"test\"; content:\"|a|\"; sid:1;)"));
2822 de_ctx, "alert tcp any any -> any any (msg:\"test\"; content:\"|aa b|\"; sid:1;)"));
2824 de_ctx, "alert tcp any any -> any any (msg:\"test\"; content:\"|aa bz|\"; sid:1;)"));
2825 /* https://redmine.openinfosecfoundation.org/issues/5201 */
2827 de_ctx, "alert tcp any any -> any any (msg:\"test\"; content:\"|22 2 22|\"; sid:1;)"));
2829 PASS;
2830}
2831
2832/**
2833 * \brief this function registers unit tests for DetectContent
2834 */
2835static void DetectContentRegisterTests(void)
2836{
2837 g_file_data_buffer_id = DetectBufferTypeGetByName("file_data");
2838 g_dce_stub_data_buffer_id = DetectBufferTypeGetByName("dce_stub_data");
2839
2840 UtRegisterTest("DetectContentDepthTest01", DetectContentDepthTest01);
2841
2842 UtRegisterTest("DetectContentParseTest01", DetectContentParseTest01);
2843 UtRegisterTest("DetectContentParseTest02", DetectContentParseTest02);
2844 UtRegisterTest("DetectContentParseTest03", DetectContentParseTest03);
2845 UtRegisterTest("DetectContentParseTest04", DetectContentParseTest04);
2846 UtRegisterTest("DetectContentParseTest05", DetectContentParseTest05);
2847 UtRegisterTest("DetectContentParseTest06", DetectContentParseTest06);
2848 UtRegisterTest("DetectContentParseTest07", DetectContentParseTest07);
2849 UtRegisterTest("DetectContentParseTest08", DetectContentParseTest08);
2850 UtRegisterTest("DetectContentParseTest09", DetectContentParseTest09);
2851 UtRegisterTest("DetectContentParseTest17", DetectContentParseTest17);
2852 UtRegisterTest("DetectContentParseTest18", DetectContentParseTest18);
2853 UtRegisterTest("DetectContentParseTest19", DetectContentParseTest19);
2854 UtRegisterTest("DetectContentParseTest20", DetectContentParseTest20);
2855 UtRegisterTest("DetectContentParseTest21", DetectContentParseTest21);
2856 UtRegisterTest("DetectContentParseTest22", DetectContentParseTest22);
2857 UtRegisterTest("DetectContentParseTest23", DetectContentParseTest23);
2858 UtRegisterTest("DetectContentParseTest24", DetectContentParseTest24);
2859 UtRegisterTest("DetectContentParseTest25", DetectContentParseTest25);
2860 UtRegisterTest("DetectContentParseTest26", DetectContentParseTest26);
2861 UtRegisterTest("DetectContentParseTest27", DetectContentParseTest27);
2862 UtRegisterTest("DetectContentParseTest28", DetectContentParseTest28);
2863 UtRegisterTest("DetectContentParseTest29", DetectContentParseTest29);
2864 UtRegisterTest("DetectContentParseTest30", DetectContentParseTest30);
2865 UtRegisterTest("DetectContentParseTest31", DetectContentParseTest31);
2866 UtRegisterTest("DetectContentParseTest32", DetectContentParseTest32);
2867 UtRegisterTest("DetectContentParseTest33", DetectContentParseTest33);
2868 UtRegisterTest("DetectContentParseTest34", DetectContentParseTest34);
2869 UtRegisterTest("DetectContentParseTest35", DetectContentParseTest35);
2870 UtRegisterTest("DetectContentParseTest41", DetectContentParseTest41);
2871 UtRegisterTest("DetectContentParseTest42", DetectContentParseTest42);
2872 UtRegisterTest("DetectContentParseTest43", DetectContentParseTest43);
2873 UtRegisterTest("DetectContentParseTest44", DetectContentParseTest44);
2874 UtRegisterTest("DetectContentParseTest45", DetectContentParseTest45);
2875
2876 /* The reals */
2877 UtRegisterTest("DetectContentLongPatternMatchTest01",
2878 DetectContentLongPatternMatchTest01);
2879 UtRegisterTest("DetectContentLongPatternMatchTest02",
2880 DetectContentLongPatternMatchTest02);
2881 UtRegisterTest("DetectContentLongPatternMatchTest03",
2882 DetectContentLongPatternMatchTest03);
2883 UtRegisterTest("DetectContentLongPatternMatchTest04",
2884 DetectContentLongPatternMatchTest04);
2885 UtRegisterTest("DetectContentLongPatternMatchTest05",
2886 DetectContentLongPatternMatchTest05);
2887 UtRegisterTest("DetectContentLongPatternMatchTest06",
2888 DetectContentLongPatternMatchTest06);
2889 UtRegisterTest("DetectContentLongPatternMatchTest07",
2890 DetectContentLongPatternMatchTest07);
2891 UtRegisterTest("DetectContentLongPatternMatchTest08",
2892 DetectContentLongPatternMatchTest08);
2893 UtRegisterTest("DetectContentLongPatternMatchTest09",
2894 DetectContentLongPatternMatchTest09);
2895 UtRegisterTest("DetectContentLongPatternMatchTest10",
2896 DetectContentLongPatternMatchTest10);
2897 UtRegisterTest("DetectContentLongPatternMatchTest11",
2898 DetectContentLongPatternMatchTest11);
2899
2900 /* Negated content tests */
2901 UtRegisterTest("SigTest41TestNegatedContent", SigTest41TestNegatedContent);
2902 UtRegisterTest("SigTest41aTestNegatedContent",
2903 SigTest41aTestNegatedContent);
2904 UtRegisterTest("SigTest42TestNegatedContent", SigTest42TestNegatedContent);
2905 UtRegisterTest("SigTest43TestNegatedContent", SigTest43TestNegatedContent);
2906 UtRegisterTest("SigTest44TestNegatedContent", SigTest44TestNegatedContent);
2907 UtRegisterTest("SigTest45TestNegatedContent", SigTest45TestNegatedContent);
2908 UtRegisterTest("SigTest46TestNegatedContent", SigTest46TestNegatedContent);
2909 UtRegisterTest("SigTest47TestNegatedContent", SigTest47TestNegatedContent);
2910 UtRegisterTest("SigTest48TestNegatedContent", SigTest48TestNegatedContent);
2911 UtRegisterTest("SigTest49TestNegatedContent", SigTest49TestNegatedContent);
2912 UtRegisterTest("SigTest50TestNegatedContent", SigTest50TestNegatedContent);
2913 UtRegisterTest("SigTest51TestNegatedContent", SigTest51TestNegatedContent);
2914 UtRegisterTest("SigTest52TestNegatedContent", SigTest52TestNegatedContent);
2915 UtRegisterTest("SigTest53TestNegatedContent", SigTest53TestNegatedContent);
2916 UtRegisterTest("SigTest54TestNegatedContent", SigTest54TestNegatedContent);
2917 UtRegisterTest("SigTest55TestNegatedContent", SigTest55TestNegatedContent);
2918 UtRegisterTest("SigTest56TestNegatedContent", SigTest56TestNegatedContent);
2919 UtRegisterTest("SigTest57TestNegatedContent", SigTest57TestNegatedContent);
2920 UtRegisterTest("SigTest58TestNegatedContent", SigTest58TestNegatedContent);
2921 UtRegisterTest("SigTest59TestNegatedContent", SigTest59TestNegatedContent);
2922 UtRegisterTest("SigTest60TestNegatedContent", SigTest60TestNegatedContent);
2923 UtRegisterTest("SigTest61TestNegatedContent", SigTest61TestNegatedContent);
2924 UtRegisterTest("SigTest62TestNegatedContent", SigTest62TestNegatedContent);
2925 UtRegisterTest("SigTest63TestNegatedContent", SigTest63TestNegatedContent);
2926 UtRegisterTest("SigTest64TestNegatedContent", SigTest64TestNegatedContent);
2927 UtRegisterTest("SigTest65TestNegatedContent", SigTest65TestNegatedContent);
2928 UtRegisterTest("SigTest66TestNegatedContent", SigTest66TestNegatedContent);
2929 UtRegisterTest("SigTest67TestNegatedContent", SigTest67TestNegatedContent);
2930 UtRegisterTest("SigTest68TestNegatedContent", SigTest68TestNegatedContent);
2931 UtRegisterTest("SigTest69TestNegatedContent", SigTest69TestNegatedContent);
2932 UtRegisterTest("SigTest70TestNegatedContent", SigTest70TestNegatedContent);
2933 UtRegisterTest("SigTest71TestNegatedContent", SigTest71TestNegatedContent);
2934 UtRegisterTest("SigTest72TestNegatedContent", SigTest72TestNegatedContent);
2935 UtRegisterTest("SigTest73TestNegatedContent", SigTest73TestNegatedContent);
2936 UtRegisterTest("SigTest74TestNegatedContent", SigTest74TestNegatedContent);
2937 UtRegisterTest("SigTest75TestNegatedContent", SigTest75TestNegatedContent);
2938
2939 UtRegisterTest("SigTest76TestBug134", SigTest76TestBug134);
2940 UtRegisterTest("SigTest77TestBug139", SigTest77TestBug139);
2941
2942 UtRegisterTest("DetectLongContentTest1", DetectLongContentTest1);
2943 UtRegisterTest("DetectLongContentTest2", DetectLongContentTest2);
2944 UtRegisterTest("DetectLongContentTest3", DetectLongContentTest3);
2945
2946 UtRegisterTest("DetectBadBinContent", DetectBadBinContent);
2947}
2948#endif /* UNITTESTS */
uint8_t len
@ ALPROTO_DCERPC
int DecodeEthernet(ThreadVars *tv, DecodeThreadVars *dtv, Packet *p, const uint8_t *pkt, uint32_t len)
#define PKT_HAS_FLOW
Definition decode.h:1266
int DetectContentSetup(DetectEngineCtx *de_ctx, Signature *s, const char *contentstr)
Function to setup a content pattern.
int DetectContentConvertToNocase(DetectEngineCtx *de_ctx, DetectContentData *cd)
void DetectContentPropagateLimits(Signature *s)
DetectContentData * DetectContentParseEncloseQuotes(SpmGlobalThreadCtx *spm_global_thread_ctx, const char *contentstr)
DetectContentData * DetectContentParse(SpmGlobalThreadCtx *spm_global_thread_ctx, const char *contentstr)
DetectContentParse \initonly.
#define TEST_DONE
void SigParseRequiredContentSize(const Signature *s, const uint64_t max_size, const SigMatch *sm, int *len, int *offset)
Determine the size needed to accommodate the content elements of a signature.
bool DetectContentPMATCHValidateCallback(const Signature *s)
void DetectContentPatternPrettyPrint(const DetectContentData *cd, char *str, size_t str_len)
void DetectContentFree(DetectEngineCtx *de_ctx, void *ptr)
this function will SCFree memory associated with DetectContentData
#define VALIDATE(e)
void DetectContentPrint(DetectContentData *cd)
Helper function to print a DetectContentData.
int DetectContentDataParse(const char *keyword, const char *contentstr, uint8_t **pstr, uint16_t *plen)
Parse a content string, ie "abc|DE|fgh".
void DetectContentRegister(void)
#define TEST_RUN(sig, o, d)
#define DETECT_CONTENT_DEPTH
#define DETECT_CONTENT_RELATIVE_NEXT
#define DETECT_CONTENT_DISTANCE2OFFSET
#define DETECT_CONTENT_WITHIN
#define DETECT_CONTENT_ENDS_WITH
#define DETECT_CONTENT_WITHIN2DEPTH
#define DETECT_CONTENT_DISTANCE
#define DETECT_CONTENT_OFFSET
#define DETECT_CONTENT_NEGATED
#define DETECT_CONTENT_MPM
#define DETECT_CONTENT_DISTANCE_VAR
#define DETECT_CONTENT_NOCASE
int SigParseMaxRequiredDsize(const Signature *s)
Determine the required dsize for the signature.
int SigParseGetMaxDsize(const Signature *s, uint16_t *dsize)
get max dsize "depth"
int PacketAlertCheck(Packet *p, uint32_t sid)
Check if a certain sid alerted, this is used in the test functions.
SigMatch * DetectBufferGetFirstSigMatch(const Signature *s, const uint32_t buf_id)
int DetectBufferGetActiveList(DetectEngineCtx *de_ctx, Signature *s)
int SigGroupBuild(DetectEngineCtx *de_ctx)
Convert the signature list into the runtime match structure.
void SigCleanSignatures(DetectEngineCtx *de_ctx)
int SigGroupCleanup(DetectEngineCtx *de_ctx)
DetectEngineCtx * DetectEngineCtxInit(void)
void DetectEngineCtxFree(DetectEngineCtx *)
Free a DetectEngineCtx::
Signature * DetectEngineAppendSig(DetectEngineCtx *, const char *)
Parse and append a Signature into the Detection Engine Context signature list.
void SigFree(DetectEngineCtx *, Signature *)
Data structures and function prototypes for keeping state for the detection engine.
bool DetectBufferIsPresent(const Signature *s, const uint32_t buf_id)
bool DetectEngineBufferTypeValidateTransform(DetectEngineCtx *de_ctx, int sm_list, const uint8_t *content, uint16_t content_len, const char **namestr)
Check content byte array compatibility with transforms.
TmEcode DetectEngineThreadCtxInit(ThreadVars *tv, void *initdata, void **data)
initialize thread specific detection engine context
int DetectBufferTypeGetByName(const char *name)
TmEcode DetectEngineThreadCtxDeinit(ThreadVars *tv, void *data)
int SCDetectSignatureSetAppProto(Signature *s, AppProto alproto)
Signature * SigInit(DetectEngineCtx *de_ctx, const char *sigstr)
Parses a signature and adds it to the Detection Engine Context.
SigMatch * SCSigMatchAppendSMToList(DetectEngineCtx *de_ctx, Signature *s, uint16_t type, SigMatchCtx *ctx, const int list)
Append a SigMatch to the list type.
Signature * SigAlloc(void)
SigTableElmt * sigmatch_table
#define DETECT_PCRE_RELATIVE
Definition detect-pcre.h:29
void SigMatchSignatures(ThreadVars *tv, DetectEngineCtx *de_ctx, DetectEngineThreadCtx *det_ctx, Packet *p)
wrapper for old tests
Definition detect.c:2420
#define DE_QUIET
Definition detect.h:330
#define DETECT_SM_LIST_NOTSET
Definition detect.h:144
#define SIGMATCH_SUPPORT_FIREWALL
Definition detect.h:1682
#define SIGMATCH_QUOTES_MANDATORY
Definition detect.h:1668
#define SIG_FLAG_DSIZE
Definition detect.h:248
@ DETECT_SM_LIST_MATCH
Definition detect.h:117
@ DETECT_SM_LIST_PMATCH
Definition detect.h:119
@ DETECT_SM_LIST_MAX
Definition detect.h:135
#define SIGMATCH_HANDLE_NEGATION
Definition detect.h:1672
#define FLOW_INITIALIZE(f)
Definition flow-util.h:38
#define FLOW_DESTROY(f)
Definition flow-util.h:119
void FlowInitConfig(bool quiet)
initialize the configuration
Definition flow.c:547
void FlowShutdown(void)
shutdown the flow engine
Definition flow.c:691
#define FLOW_PKT_TOSERVER
Definition flow.h:233
#define FLOW_QUIET
Definition flow.h:43
#define FLOW_PKT_ESTABLISHED
Definition flow.h:235
DecodeThreadVars * dtv
DetectEngineCtx * de_ctx
#define FAIL_IF_NULL(expr)
Fail a test if expression evaluates to NULL.
void UtRegisterTest(const char *name, int(*TestFn)(void))
Register unit test.
#define FAIL_IF_NOT(expr)
Fail a test if expression evaluates to false.
#define PASS
Pass the test.
#define FAIL_IF(expr)
Fail a test if expression evaluates to true.
#define FAIL_IF_NOT_NULL(expr)
Fail a test if expression evaluates to non-NULL.
Packet * PacketGetFromAlloc(void)
Get a malloced packet.
Definition decode.c:258
void PacketRecycle(Packet *p)
Definition packet.c:150
Structure to hold thread specific data for all decode modules.
Definition decode.h:963
main detection engine ctx
Definition detect.h:932
SpmGlobalThreadCtx * spm_global_thread_ctx
Definition detect.h:986
uint8_t flags
Definition detect.h:934
Signature * sig_list
Definition detect.h:941
Flow data structure.
Definition flow.h:356
uint8_t flowflags
Definition decode.h:532
struct Flow_ * flow
Definition decode.h:546
uint32_t flags
Definition decode.h:544
Port dp
Definition decode.h:516
Used to start a pointer to SigMatch context Should never be dereferenced without casting to something...
Definition detect.h:351
a single match condition for a signature
Definition detect.h:356
uint16_t type
Definition detect.h:357
struct SigMatch_ * next
Definition detect.h:360
SigMatchCtx * ctx
Definition detect.h:359
const char * url
Definition detect.h:1462
int(* Setup)(DetectEngineCtx *, Signature *, const char *)
Definition detect.h:1441
void(* Free)(DetectEngineCtx *, void *)
Definition detect.h:1446
uint16_t flags
Definition detect.h:1450
const char * desc
Definition detect.h:1461
void(* RegisterTests)(void)
Definition detect.h:1448
int(* Match)(DetectEngineThreadCtx *, Packet *, const Signature *, const SigMatchCtx *)
Definition detect.h:1421
const char * name
Definition detect.h:1459
struct SigMatch_ * smlists[DETECT_SM_LIST_MAX]
Definition detect.h:642
struct SigMatch_ * smlists_tail[DETECT_SM_LIST_MAX]
Definition detect.h:644
SignatureInitDataBuffer * buffers
Definition detect.h:647
uint32_t buffer_index
Definition detect.h:648
Signature container.
Definition detect.h:668
uint32_t flags
Definition detect.h:669
SignatureInitData * init_data
Definition detect.h:747
Per thread variable structure.
Definition threadvars.h:58
#define u8_tolower(c)
#define MIN(x, y)
size_t strlcat(char *, const char *src, size_t siz)
#define MAX(x, y)
#define str(s)
size_t strlcpy(char *dst, const char *src, size_t siz)
int SCLogDebugEnabled(void)
Returns whether debug messages are enabled to be logged or not.
Definition util-debug.c:767
#define SCEnter(...)
Definition util-debug.h:277
#define SCLogDebug(...)
Definition util-debug.h:275
#define SCLogError(...)
Macro used to log ERROR messages.
Definition util-debug.h:267
#define SCReturn
Definition util-debug.h:279
#define SCMalloc(sz)
Definition util-mem.h:47
#define SCFree(p)
Definition util-mem.h:61
#define SCCalloc(nm, sz)
Definition util-mem.h:53
@ MPM_AC
Definition util-mpm.h:36
#define unlikely(expr)
void PrintRawUriFp(FILE *fp, const uint8_t *buf, uint32_t buflen)
Definition util-print.c:69
uint8_t SinglePatternMatchDefaultMatcher(void)
Returns the single pattern matcher algorithm to be used, based on the spm-algo setting in yaml.
Definition util-spm.c:68
void SpmDestroyGlobalThreadCtx(SpmGlobalThreadCtx *global_thread_ctx)
Definition util-spm.c:144
SpmGlobalThreadCtx * SpmInitGlobalThreadCtx(uint8_t matcher)
Definition util-spm.c:138
SpmCtx * SpmInitCtx(const uint8_t *needle, uint16_t needle_len, int nocase, SpmGlobalThreadCtx *global_thread_ctx)
Definition util-spm.c:173
void SpmDestroyCtx(SpmCtx *ctx)
Definition util-spm.c:183
uint64_t offset
void UTHFreePackets(Packet **p, int numpkts)
UTHFreePackets: function to release the allocated data from UTHBuildPacket and the packet itself.
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 UTHFreePacket(Packet *p)
UTHFreePacket: function to release the allocated data from UTHBuildPacket and the packet itself.
int UTHPacketMatchSigMpm(Packet *p, char *sig, uint16_t mpm_type)