suricata
detect-replace.c
Go to the documentation of this file.
1/* Copyright (C) 2011-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 Eric Leblond <eric@regit.org>
22 *
23 * Replace part of the detection engine.
24 *
25 * If previous filter is of content type, replace can be used to change
26 * the matched part to a new value.
27 */
28
29#include "suricata-common.h"
30
31#include "runmodes.h"
32
33#include "decode.h"
34
35#include "detect.h"
36#include "detect-parse.h"
37#include "detect-content.h"
38#include "detect-replace.h"
39#include "app-layer.h"
40
41#include "detect-engine-mpm.h"
42#include "detect-engine.h"
43#include "detect-engine-build.h"
44
45#include "util-checksum.h"
46
47#include "util-unittest.h"
48
49#include "util-debug.h"
50
51static int DetectReplaceSetup(DetectEngineCtx *, Signature *, const char *);
52#ifdef UNITTESTS
53static void DetectReplaceRegisterTests(void);
54#endif
55static int DetectReplacePostMatch(DetectEngineThreadCtx *det_ctx,
56 Packet *p, const Signature *s, const SigMatchCtx *ctx);
57
59{
61 sigmatch_table[DETECT_REPLACE].desc = "only to be used in IPS-mode. Change the following content into another";
62 sigmatch_table[DETECT_REPLACE].url = "/rules/payload-keywords.html#replace";
63 sigmatch_table[DETECT_REPLACE].Match = DetectReplacePostMatch;
64 sigmatch_table[DETECT_REPLACE].Setup = DetectReplaceSetup;
65#ifdef UNITTESTS
66 sigmatch_table[DETECT_REPLACE].RegisterTests = DetectReplaceRegisterTests;
67#endif
69}
70
71static int DetectReplacePostMatch(DetectEngineThreadCtx *det_ctx,
72 Packet *p, const Signature *s, const SigMatchCtx *ctx)
73{
74 if (det_ctx->replist) {
76 det_ctx->replist = NULL;
77 }
78 return 1;
79}
80
81int DetectReplaceSetup(DetectEngineCtx *de_ctx, Signature *s, const char *replacestr)
82{
83 uint8_t *content = NULL;
84 uint16_t len = 0;
85
86 if (s->init_data->negated) {
87 SCLogError("Can't negate replacement string: %s", replacestr);
88 return -1;
89 }
90
91 switch (SCRunmodeGet()) {
92 case RUNMODE_NFQ:
93 case RUNMODE_IPFW:
94 break;
95 default:
96 SCLogWarning("Can't use 'replace' keyword in non IPS mode: %s", s->sig_str);
97 /* this is a success, having the alert is interesting */
98 return 0;
99 }
100
101 int ret = DetectContentDataParse("replace", replacestr, &content, &len);
102 if (ret == -1)
103 return -1;
104
105 /* add to the latest "content" keyword from pmatch */
107 DETECT_CONTENT, -1);
108 if (pm == NULL) {
109 SCLogError("replace needs"
110 "preceding content option for raw sig");
111 SCFree(content);
112 return -1;
113 }
114
115 /* we can remove this switch now with the unified structure */
117 if (ud == NULL) {
118 SCLogError("invalid argument");
119 SCFree(content);
120 return -1;
121 }
122 if (ud->flags & DETECT_CONTENT_NEGATED) {
123 SCLogError("can't have a relative "
124 "negated keyword set along with a replacement");
125 goto error;
126 }
127 if (ud->content_len != len) {
128 SCLogError("can't have a content "
129 "length different from replace length");
130 goto error;
131 }
132
133 ud->replace = SCMalloc(len);
134 if (ud->replace == NULL) {
135 goto error;
136 }
137 memcpy(ud->replace, content, len);
138 ud->replace_len = len;
139 ud->flags |= DETECT_CONTENT_REPLACE;
140 /* want packet matching only won't be able to replace data with
141 * a flow.
142 */
144 SCFree(content);
145 content = NULL;
146
148 NULL) {
149 goto error;
150 }
151 return 0;
152
153error:
154 SCFree(ud->replace);
155 ud->replace = NULL;
156 SCFree(content);
157 return -1;
158}
159
160/* Add to the head of the replace-list.
161 *
162 * The first to add to the replace-list has the highest priority. So,
163 * adding the head of the list results in the newest modifications
164 * of content being applied first, so later changes can over ride
165 * earlier changes. Thus the highest priority modifications should be
166 * applied last.
167 */
169 DetectReplaceList *replist, uint8_t *found, const DetectContentData *cd)
170{
171 if (cd->content_len != cd->replace_len)
172 return NULL;
173 SCLogDebug("replace: Adding match");
174
175 DetectReplaceList *newlist = SCMalloc(sizeof(DetectReplaceList));
176 if (unlikely(newlist == NULL))
177 return replist;
178 newlist->found = found;
179 newlist->cd = cd;
180 /* Push new value onto the front of the list. */
181 newlist->next = replist;
182 return newlist;
183}
184
186{
187 DetectReplaceList *tlist = NULL;
188
189 SCLogDebug("replace: Executing match");
190 while (replist) {
191 memcpy(replist->found, replist->cd->replace, replist->cd->replace_len);
192 SCLogDebug("replace: replaced data");
195 tlist = replist;
196 replist = replist->next;
197 SCFree(tlist);
198 }
199}
200
201
203{
204 DetectReplaceList *tlist = NULL;
205 while (replist) {
206 SCLogDebug("replace: Freeing match");
207 tlist = replist;
208 replist = replist->next;
209 SCFree(tlist);
210 }
211}
212
213#ifdef UNITTESTS /* UNITTESTS */
214#include "detect-engine-alert.h"
215#include "packet.h"
216
217/**
218 * \test Test packet Matches
219 * \param raw_eth_pkt pointer to the ethernet packet
220 * \param pktsize size of the packet
221 * \param sig pointer to the signature to test
222 * \param sid sid number of the signature
223 * \retval return 1 if match
224 * \retval return 0 if not
225 */
226static
227int DetectReplaceLongPatternMatchTest(uint8_t *raw_eth_pkt, uint16_t pktsize,
228 const char *sig, uint32_t sid, uint8_t *pp,
229 uint16_t *len)
230{
231 int result = 0;
232
233 Packet *p = NULL;
234 p = PacketGetFromAlloc();
235 if (unlikely(p == NULL))
236 return 0;
237
239
240 ThreadVars th_v;
241 DetectEngineThreadCtx *det_ctx = NULL;
242
243 if (pp == NULL) {
244 SCLogDebug("replace: looks like a second run");
245 }
246
247 PacketCopyData(p, raw_eth_pkt, pktsize);
248 memset(&dtv, 0, sizeof(DecodeThreadVars));
249 memset(&th_v, 0, sizeof(th_v));
251
253 DecodeEthernet(&th_v, &dtv, p, GET_PKT_DATA(p), pktsize);
254
256 if (de_ctx == NULL) {
257 goto end;
258 }
260
261 de_ctx->sig_list = SigInit(de_ctx, sig);
262 if (de_ctx->sig_list == NULL) {
263 goto end;
264 }
265 de_ctx->sig_list->next = NULL;
266
270 ->ctx;
271 if (co->flags & DETECT_CONTENT_RELATIVE_NEXT) {
272 printf("relative next flag set on final match which is content: ");
273 goto end;
274 }
275 }
276
279 DetectEngineThreadCtxInit(&th_v, NULL, (void *)&det_ctx);
280
281 SigMatchSignatures(&th_v, de_ctx, det_ctx, p);
283
284 if (PacketAlertCheck(p, sid) != 1) {
285 SCLogDebug("replace: no alert on sig %d", sid);
286 goto end;
287 }
288
289 if (pp) {
290 memcpy(pp, GET_PKT_DATA(p), GET_PKT_LEN(p));
291 *len = pktsize;
292 SCLogDebug("replace: copying %d on %p", *len, pp);
293 }
294
295
296 result = 1;
297end:
298 if (dtv.app_tctx != NULL)
300 if (det_ctx != NULL)
301 DetectEngineThreadCtxDeinit(&th_v, (void *)det_ctx);
303 PacketRecycle(p);
304 FlowShutdown();
305 SCFree(p);
306
307
308 return result;
309}
310
311
312/**
313 * \brief Wrapper for DetectContentLongPatternMatchTest
314 */
315static int DetectReplaceLongPatternMatchTestWrp(const char *sig, uint32_t sid, const char *sig_rep, uint32_t sid_rep)
316{
317 int ret;
318 /** Real packet with the following tcp data:
319 * "Hi, this is a big test to check content matches of splitted"
320 * "patterns between multiple chunks!"
321 * (without quotes! :) )
322 */
323 uint8_t raw_eth_pkt[] = {
324 0xff,0xff,0xff,0xff,0xff,0xff,0x00,0x00,
325 0x00,0x00,0x00,0x00,0x08,0x00,0x45,0x00,
326 0x00,0x85,0x00,0x01,0x00,0x00,0x40,0x06,
327 0x7c,0x70,0x7f,0x00,0x00,0x01,0x7f,0x00,
328 0x00,0x01,0x00,0x14,0x00,0x50,0x00,0x00,
329 0x00,0x00,0x00,0x00,0x00,0x00,0x50,0x02,
330 0x20,0x00,0xc9,0xad,0x00,0x00,0x48,0x69,
331 0x2c,0x20,0x74,0x68,0x69,0x73,0x20,0x69,
332 0x73,0x20,0x61,0x20,0x62,0x69,0x67,0x20,
333 0x74,0x65,0x73,0x74,0x20,0x74,0x6f,0x20,
334 0x63,0x68,0x65,0x63,0x6b,0x20,0x63,0x6f,
335 0x6e,0x74,0x65,0x6e,0x74,0x20,0x6d,0x61,
336 0x74,0x63,0x68,0x65,0x73,0x20,0x6f,0x66,
337 0x20,0x73,0x70,0x6c,0x69,0x74,0x74,0x65,
338 0x64,0x20,0x70,0x61,0x74,0x74,0x65,0x72,
339 0x6e,0x73,0x20,0x62,0x65,0x74,0x77,0x65,
340 0x65,0x6e,0x20,0x6d,0x75,0x6c,0x74,0x69,
341 0x70,0x6c,0x65,0x20,0x63,0x68,0x75,0x6e,
342 0x6b,0x73,0x21 }; /* end raw_eth_pkt */
343 uint8_t p[sizeof(raw_eth_pkt)];
344 uint16_t psize = sizeof(raw_eth_pkt);
345
346 /* would be unittest */
347 int run_mode_backup = SCRunmodeGet();
349 ret = DetectReplaceLongPatternMatchTest(raw_eth_pkt, (uint16_t)sizeof(raw_eth_pkt),
350 sig, sid, p, &psize);
351 if (ret == 1) {
352 SCLogDebug("replace: test1 phase1");
353 ret = DetectReplaceLongPatternMatchTest(p, psize, sig_rep, sid_rep, NULL, NULL);
354 }
355 SCRunmodeSet(run_mode_backup);
356 return ret;
357}
358
359
360/**
361 * \brief Wrapper for DetectContentLongPatternMatchTest
362 */
363static int DetectReplaceLongPatternMatchTestUDPWrp(const char *sig, uint32_t sid, const char *sig_rep, uint32_t sid_rep)
364{
365 int ret;
366 /** Real UDP DNS packet with a request A to a1.twimg.com
367 */
368 uint8_t raw_eth_pkt[] = {
369 0x8c, 0xa9, 0x82, 0x75, 0x5d, 0x62, 0xb4, 0x07,
370 0xf9, 0xf3, 0xc7, 0x0a, 0x08, 0x00, 0x45, 0x00,
371 0x00, 0x3a, 0x92, 0x4f, 0x40, 0x00, 0x40, 0x11,
372 0x31, 0x1a, 0xc0, 0xa8, 0x00, 0x02, 0xc1, 0xbd,
373 0xf4, 0xe1, 0x3b, 0x7e, 0x00, 0x35, 0x00, 0x26,
374 0xcb, 0x81, 0x37, 0x62, 0x01, 0x00, 0x00, 0x01,
375 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0x61,
376 0x31, 0x05, 0x74, 0x77, 0x69, 0x6d, 0x67, 0x03,
377 0x63, 0x6f, 0x6d, 0x00, 0x00, 0x01, 0x00, 0x01 };
378
379 uint8_t p[sizeof(raw_eth_pkt)];
380 uint16_t psize = sizeof(raw_eth_pkt);
381
382 int run_mode_backup = SCRunmodeGet();
384 ret = DetectReplaceLongPatternMatchTest(raw_eth_pkt, (uint16_t)sizeof(raw_eth_pkt),
385 sig, sid, p, &psize);
386 if (ret == 1) {
387 SCLogDebug("replace: test1 phase1 ok: %" PRIuMAX" vs %d",(uintmax_t)sizeof(raw_eth_pkt),psize);
388 ret = DetectReplaceLongPatternMatchTest(p, psize, sig_rep, sid_rep, NULL, NULL);
389 }
390 SCRunmodeSet(run_mode_backup);
391 return ret;
392}
393
394/**
395 * \test Check if replace is working
396 */
397static int DetectReplaceMatchTest01(void)
398{
399 const char *sig = "alert tcp any any -> any any (msg:\"Nothing..\";"
400 " content:\"big\"; replace:\"pig\"; sid:1;)";
401 const char *sig_rep = "alert tcp any any -> any any (msg:\"replace worked\";"
402 " content:\"this is a pig test\"; sid:2;)";
403 FAIL_IF_NOT(DetectReplaceLongPatternMatchTestWrp(sig, 1, sig_rep, 2));
404 PASS;
405}
406
407/**
408 * \test Check if replace is working with offset
409 */
410static int DetectReplaceMatchTest02(void)
411{
412 const char *sig = "alert tcp any any -> any any (msg:\"Nothing..\";"
413 " content:\"th\"; offset: 4; replace:\"TH\"; sid:1;)";
414 const char *sig_rep = "alert tcp any any -> any any (msg:\"replace worked\";"
415 " content:\"THis\"; offset:4; sid:2;)";
416 FAIL_IF_NOT(DetectReplaceLongPatternMatchTestWrp(sig, 1, sig_rep, 2));
417 PASS;
418}
419
420/**
421 * \test Check if replace is working with offset and keyword inversion
422 */
423static int DetectReplaceMatchTest03(void)
424{
425 const char *sig = "alert tcp any any -> any any (msg:\"Nothing..\";"
426 " content:\"th\"; replace:\"TH\"; offset: 4; sid:1;)";
427 const char *sig_rep = "alert tcp any any -> any any (msg:\"replace worked\";"
428 " content:\"THis\"; offset:4; sid:2;)";
429 FAIL_IF_NOT(DetectReplaceLongPatternMatchTestWrp(sig, 1, sig_rep, 2));
430 PASS;
431}
432
433/**
434 * \test Check if replace is working with second content
435 */
436static int DetectReplaceMatchTest04(void)
437{
438 const char *sig = "alert tcp any any -> any any (msg:\"Nothing..\";"
439 " content:\"th\"; replace:\"TH\"; content:\"patter\"; replace:\"matter\"; sid:1;)";
440 const char *sig_rep = "alert tcp any any -> any any (msg:\"replace worked\";"
441 " content:\"THis\"; content:\"matterns\"; sid:2;)";
442 FAIL_IF_NOT(DetectReplaceLongPatternMatchTestWrp(sig, 1, sig_rep, 2));
443 PASS;
444}
445
446/**
447 * \test Check if replace is not done when second content don't match
448 */
449static int DetectReplaceMatchTest05(void)
450{
451 const char *sig = "alert tcp any any -> any any (msg:\"Nothing..\";"
452 " content:\"th\"; replace:\"TH\"; content:\"nutella\"; sid:1;)";
453 const char *sig_rep = "alert tcp any any -> any any (msg:\"replace worked\";"
454 " content:\"TH\"; sid:2;)";
455 FAIL_IF(DetectReplaceLongPatternMatchTestWrp(sig, 1, sig_rep, 2));
456 PASS;
457}
458
459/**
460 * \test Check if replace is not done when second content match and not
461 * first
462 */
463static int DetectReplaceMatchTest06(void)
464{
465 const char *sig = "alert tcp any any -> any any (msg:\"Nothing..\";"
466 " content:\"nutella\"; replace:\"commode\"; content:\"this is\"; sid:1;)";
467 const char *sig_rep = "alert tcp any any -> any any (msg:\"replace worked\";"
468 " content:\"commode\"; sid:2;)";
469 FAIL_IF(DetectReplaceLongPatternMatchTestWrp(sig, 1, sig_rep, 2));
470 PASS;
471}
472
473/**
474 * \test Check if replace is working when nocase used
475 */
476static int DetectReplaceMatchTest07(void)
477{
478 const char *sig = "alert tcp any any -> any any (msg:\"Nothing..\";"
479 " content:\"BiG\"; nocase; replace:\"pig\"; sid:1;)";
480 const char *sig_rep = "alert tcp any any -> any any (msg:\"replace worked\";"
481 " content:\"this is a pig test\"; sid:2;)";
482 FAIL_IF_NOT(DetectReplaceLongPatternMatchTestWrp(sig, 1, sig_rep, 2));
483 PASS;
484}
485
486/**
487 * \test Check if replace is working when depth is used
488 */
489static int DetectReplaceMatchTest08(void)
490{
491 const char *sig = "alert tcp any any -> any any (msg:\"Nothing..\";"
492 " content:\"big\"; depth:17; replace:\"pig\"; sid:1;)";
493 const char *sig_rep = "alert tcp any any -> any any (msg:\"replace worked\";"
494 " content:\"this is a pig test\"; sid:2;)";
495 FAIL_IF_NOT(DetectReplaceLongPatternMatchTestWrp(sig, 1, sig_rep, 2));
496 PASS;
497}
498
499/**
500 * \test Check if replace is working when depth block match used
501 */
502static int DetectReplaceMatchTest09(void)
503{
504 const char *sig = "alert tcp any any -> any any (msg:\"Nothing..\";"
505 " content:\"big\"; depth:16; replace:\"pig\"; sid:1;)";
506 const char *sig_rep = "alert tcp any any -> any any (msg:\"replace worked\";"
507 " content:\"this is a pig test\"; sid:2;)";
508 FAIL_IF(DetectReplaceLongPatternMatchTestWrp(sig, 1, sig_rep, 2));
509 PASS;
510}
511
512/**
513 * \test Check if replace is working when depth block match used
514 */
515static int DetectReplaceMatchTest10(void)
516{
517 const char *sig = "alert tcp any any -> any any (msg:\"Nothing..\";"
518 " content:\"big\"; depth:17; replace:\"pig\"; offset: 14; sid:1;)";
519 const char *sig_rep = "alert tcp any any -> any any (msg:\"replace worked\";"
520 " content:\"pig\"; depth:17; offset:14; sid:2;)";
521 FAIL_IF_NOT(DetectReplaceLongPatternMatchTestWrp(sig, 1, sig_rep, 2));
522 PASS;
523}
524
525/**
526 * \test Check if replace is working with within
527 */
528static int DetectReplaceMatchTest11(void)
529{
530 const char *sig = "alert tcp any any -> any any (msg:\"Nothing..\";"
531 " content:\"big\"; replace:\"pig\"; content:\"to\"; within: 11; sid:1;)";
532 const char *sig_rep = "alert tcp any any -> any any (msg:\"replace worked\";"
533 " content:\"pig\"; depth:17; offset:14; sid:2;)";
534
535 FAIL_IF_NOT(DetectReplaceLongPatternMatchTestWrp(sig, 1, sig_rep, 2));
536 PASS;
537}
538
539/**
540 * \test Check if replace is working with within
541 */
542static int DetectReplaceMatchTest12(void)
543{
544 const char *sig = "alert tcp any any -> any any (msg:\"Nothing..\";"
545 " content:\"big\"; replace:\"pig\"; content:\"to\"; within: 4; sid:1;)";
546 const char *sig_rep = "alert tcp any any -> any any (msg:\"replace worked\";"
547 " content:\"pig\"; depth:17; offset:14; sid:2;)";
548 FAIL_IF(DetectReplaceLongPatternMatchTestWrp(sig, 1, sig_rep, 2));
549 PASS;
550}
551
552/**
553 * \test Check if replace is working with within
554 */
555static int DetectReplaceMatchTest13(void)
556{
557 const char *sig = "alert tcp any any -> any any (msg:\"Nothing..\";"
558 " content:\"big\"; replace:\"pig\"; content:\"test\"; distance: 1; sid:1;)";
559 const char *sig_rep = "alert tcp any any -> any any (msg:\"replace worked\";"
560 " content:\"pig\"; depth:17; offset:14; sid:2;)";
561 FAIL_IF_NOT(DetectReplaceLongPatternMatchTestWrp(sig, 1, sig_rep, 2));
562 PASS;
563}
564
565/**
566 * \test Check if replace is working with within
567 */
568static int DetectReplaceMatchTest14(void)
569{
570 const char *sig = "alert tcp any any -> any any (msg:\"Nothing..\";"
571 " content:\"big\"; replace:\"pig\"; content:\"test\"; distance: 2; sid:1;)";
572 const char *sig_rep = "alert tcp any any -> any any (msg:\"replace worked\";"
573 " content:\"pig\"; depth:17; offset:14; sid:2;)";
574 FAIL_IF(DetectReplaceLongPatternMatchTestWrp(sig, 1, sig_rep, 2));
575 PASS;
576}
577
578/**
579 * \test Check if replace is working with within
580 */
581static int DetectReplaceMatchTest15(void)
582{
583 const char *sig = "alert udp any any -> any any (msg:\"Nothing..\";"
584 " content:\"com\"; replace:\"org\"; sid:1;)";
585 const char *sig_rep = "alert udp any any -> any any (msg:\"replace worked\";"
586 " content:\"twimg|03|org\"; sid:2;)";
587 FAIL_IF_NOT(DetectReplaceLongPatternMatchTestUDPWrp(sig, 1, sig_rep, 2));
588 PASS;
589}
590
591
592/**
593 * \test Parsing test
594 */
595static int DetectReplaceParseTest01(void)
596{
597 int run_mode_backup = SCRunmodeGet();
599
602
605 "alert udp any any -> any any "
606 "(msg:\"test\"; content:\"doh\"; replace:\"; sid:238012;)"));
607
608 SCRunmodeSet(run_mode_backup);
610 PASS;
611}
612
613/**
614 * \test Parsing test: non valid because of http protocol
615 */
616static int DetectReplaceParseTest02(void)
617{
618 int run_mode_backup = SCRunmodeGet();
620
623
626 "alert http any any -> any any "
627 "(msg:\"test\"; content:\"doh\"; replace:\"bon\"; sid:238012;)"));
628
629 SCRunmodeSet(run_mode_backup);
631 PASS;
632}
633
634/**
635 * \test Parsing test: non valid because of http_header on same content
636 * as replace keyword
637 */
638static int DetectReplaceParseTest03(void)
639{
640 int run_mode_backup = SCRunmodeGet();
642
644
646
649 "alert tcp any any -> any any "
650 "(msg:\"test\"; content:\"doh\"; replace:\"don\"; http_header; sid:238012;)"));
651
652 SCRunmodeSet(run_mode_backup);
654 PASS;
655}
656
657/**
658 * \test Parsing test no content
659 */
660static int DetectReplaceParseTest04(void)
661{
662 int run_mode_backup = SCRunmodeGet();
664
667
669 FAIL_IF_NOT_NULL(DetectEngineAppendSig(de_ctx, "alert tcp any any -> any any "
670 "(msg:\"test\"; replace:\"don\"; sid:238012;)"));
671
672 SCRunmodeSet(run_mode_backup);
674 PASS;
675}
676
677/**
678 * \test Parsing test content after replace
679 */
680static int DetectReplaceParseTest05(void)
681{
682 int run_mode_backup = SCRunmodeGet();
684
687
690 "alert tcp any any -> any any "
691 "(msg:\"test\"; replace:\"don\"; content:\"doh\"; sid:238012;)"));
692
693 SCRunmodeSet(run_mode_backup);
695 PASS;
696}
697
698/**
699 * \test Parsing test content and replace length differ
700 */
701static int DetectReplaceParseTest06(void)
702{
703 int run_mode_backup = SCRunmodeGet();
705
708
711 "alert tcp any any -> any any "
712 "(msg:\"test\"; content:\"don\"; replace:\"donut\"; sid:238012;)"));
713
714 SCRunmodeSet(run_mode_backup);
716 PASS;
717}
718
719/**
720 * \test Parsing test content and replace length differ
721 */
722static int DetectReplaceParseTest07(void)
723{
724 int run_mode_backup = SCRunmodeGet();
726
729
732 DetectEngineAppendSig(de_ctx, "alert tcp any any -> any any "
733 "(msg:\"test\"; content:\"don\"; replace:\"dou\"; "
734 "content:\"jpg\"; http_header; sid:238012;)"));
735
736 SCRunmodeSet(run_mode_backup);
738 PASS;
739}
740
741/**
742 * \brief this function registers unit tests for DetectContent
743 */
744void DetectReplaceRegisterTests(void)
745{
746/* matching */
747 UtRegisterTest("DetectReplaceMatchTest01", DetectReplaceMatchTest01);
748 UtRegisterTest("DetectReplaceMatchTest02", DetectReplaceMatchTest02);
749 UtRegisterTest("DetectReplaceMatchTest03", DetectReplaceMatchTest03);
750 UtRegisterTest("DetectReplaceMatchTest04", DetectReplaceMatchTest04);
751 UtRegisterTest("DetectReplaceMatchTest05", DetectReplaceMatchTest05);
752 UtRegisterTest("DetectReplaceMatchTest06", DetectReplaceMatchTest06);
753 UtRegisterTest("DetectReplaceMatchTest07", DetectReplaceMatchTest07);
754 UtRegisterTest("DetectReplaceMatchTest08", DetectReplaceMatchTest08);
755 UtRegisterTest("DetectReplaceMatchTest09", DetectReplaceMatchTest09);
756 UtRegisterTest("DetectReplaceMatchTest10", DetectReplaceMatchTest10);
757 UtRegisterTest("DetectReplaceMatchTest11", DetectReplaceMatchTest11);
758 UtRegisterTest("DetectReplaceMatchTest12", DetectReplaceMatchTest12);
759 UtRegisterTest("DetectReplaceMatchTest13", DetectReplaceMatchTest13);
760 UtRegisterTest("DetectReplaceMatchTest14", DetectReplaceMatchTest14);
761 UtRegisterTest("DetectReplaceMatchTest15", DetectReplaceMatchTest15);
762/* parsing */
763 UtRegisterTest("DetectReplaceParseTest01", DetectReplaceParseTest01);
764 UtRegisterTest("DetectReplaceParseTest02", DetectReplaceParseTest02);
765 UtRegisterTest("DetectReplaceParseTest03", DetectReplaceParseTest03);
766 UtRegisterTest("DetectReplaceParseTest04", DetectReplaceParseTest04);
767 UtRegisterTest("DetectReplaceParseTest05", DetectReplaceParseTest05);
768 UtRegisterTest("DetectReplaceParseTest06", DetectReplaceParseTest06);
769 UtRegisterTest("DetectReplaceParseTest07", DetectReplaceParseTest07);
770}
771#endif /* UNITTESTS */
uint8_t len
void AppLayerDestroyCtxThread(AppLayerThreadCtx *app_tctx)
Destroys the context created by AppLayerGetCtxThread().
Definition app-layer.c:1129
AppLayerThreadCtx * AppLayerGetCtxThread(void)
Creates a new app layer thread context.
Definition app-layer.c:1108
int DecodeEthernet(ThreadVars *tv, DecodeThreadVars *dtv, Packet *p, const uint8_t *pkt, uint32_t len)
#define GET_PKT_DATA(p)
Definition decode.h:209
#define PKT_STREAM_MODIFIED
Definition decode.h:1271
#define GET_PKT_LEN(p)
Definition decode.h:208
int DetectContentDataParse(const char *keyword, const char *contentstr, uint8_t **pstr, uint16_t *plen)
Parse a content string, ie "abc|DE|fgh".
#define DETECT_CONTENT_RELATIVE_NEXT
#define DETECT_CONTENT_NEGATED
#define DETECT_CONTENT_REPLACE
int PacketAlertCheck(Packet *p, uint32_t sid)
Check if a certain sid alerted, this is used in the test functions.
int SigGroupBuild(DetectEngineCtx *de_ctx)
Convert the signature list into the runtime match structure.
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 DetectEnginePruneFreeList(void)
int DetectEngineMoveToFreeList(DetectEngineCtx *de_ctx)
TmEcode DetectEngineThreadCtxInit(ThreadVars *tv, void *initdata, void **data)
initialize thread specific detection engine context
int DetectEngineAddToMaster(DetectEngineCtx *de_ctx)
TmEcode DetectEngineThreadCtxDeinit(ThreadVars *tv, void *data)
SigMatch * DetectGetLastSMByListId(const Signature *s, int list_id,...)
Returns the sm with the largest index (added last) from the list passed to us as an id.
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.
SigTableElmt * sigmatch_table
void DetectReplaceRegister(void)
void DetectReplaceExecuteInternal(Packet *p, DetectReplaceList *replist)
void DetectReplaceFreeInternal(DetectReplaceList *replist)
DetectReplaceList * DetectReplaceAddToList(DetectReplaceList *replist, uint8_t *found, const DetectContentData *cd)
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 SIG_FLAG_REQUIRE_PACKET
Definition detect.h:254
#define SIGMATCH_QUOTES_MANDATORY
Definition detect.h:1668
@ DETECT_SM_LIST_PMATCH
Definition detect.h:119
@ DETECT_SM_LIST_POSTMATCH
Definition detect.h:127
#define SIGMATCH_HANDLE_NEGATION
Definition detect.h:1672
void FlowInitConfig(bool quiet)
initialize the configuration
Definition flow.c:547
void FlowShutdown(void)
shutdown the flow engine
Definition flow.c:691
#define FLOW_QUIET
Definition flow.h:43
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
int PacketCopyData(Packet *p, const uint8_t *pktdata, uint32_t pktlen)
Copy data to Packet payload and set packet length.
Definition decode.c:377
struct Thresholds ctx
void PacketRecycle(Packet *p)
Definition packet.c:150
@ RUNMODE_NFQ
Definition runmodes.h:31
@ RUNMODE_IPFW
Definition runmodes.h:33
Structure to hold thread specific data for all decode modules.
Definition decode.h:963
AppLayerThreadCtx * app_tctx
Definition decode.h:965
main detection engine ctx
Definition detect.h:932
uint8_t flags
Definition detect.h:934
Signature * sig_list
Definition detect.h:941
DetectReplaceList * replist
Definition detect.h:1352
const struct DetectContentData_ * cd
Definition detect.h:816
uint8_t * found
Definition detect.h:817
struct DetectReplaceList_ * next
Definition detect.h:818
uint32_t flags
Definition decode.h:544
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
SigMatchCtx * ctx
Definition detect.h:359
const char * url
Definition detect.h:1462
int(* Setup)(DetectEngineCtx *, Signature *, const char *)
Definition detect.h:1441
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_tail[DETECT_SM_LIST_MAX]
Definition detect.h:644
Signature container.
Definition detect.h:668
uint32_t flags
Definition detect.h:669
SignatureInitData * init_data
Definition detect.h:747
char * sig_str
Definition detect.h:745
struct Signature_ * next
Definition detect.h:750
Per thread variable structure.
Definition threadvars.h:58
SCRunMode SCRunmodeGet(void)
Get the current run mode.
Definition suricata.c:279
void SCRunmodeSet(SCRunMode run_mode)
Set the current run mode.
Definition suricata.c:284
int ReCalculateChecksum(Packet *p)
#define SCLogDebug(...)
Definition util-debug.h:275
#define SCLogWarning(...)
Macro used to log WARNING messages.
Definition util-debug.h:255
#define SCLogError(...)
Macro used to log ERROR messages.
Definition util-debug.h:267
#define SCMalloc(sz)
Definition util-mem.h:47
#define SCFree(p)
Definition util-mem.h:61
#define unlikely(expr)