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