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 
51 static int DetectReplaceSetup(DetectEngineCtx *, Signature *, const char *);
52 #ifdef UNITTESTS
53 static void DetectReplaceRegisterTests(void);
54 #endif
55 static int DetectReplacePostMatch(DetectEngineThreadCtx *det_ctx,
56  Packet *p, const Signature *s, const SigMatchCtx *ctx);
57 
59 {
60  sigmatch_table[DETECT_REPLACE].name = "replace";
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 
71 static 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 
81 int 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;
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  goto error;
149  }
150  return 0;
151 
152 error:
153  SCFree(ud->replace);
154  ud->replace = NULL;
155  SCFree(content);
156  return -1;
157 }
158 
159 /* Add to the head of the replace-list.
160  *
161  * The first to add to the replace-list has the highest priority. So,
162  * adding the head of the list results in the newest modifications
163  * of content being applied first, so later changes can over ride
164  * earlier changes. Thus the highest priority modifications should be
165  * applied last.
166  */
168  DetectReplaceList *replist, uint8_t *found, const DetectContentData *cd)
169 {
170  if (cd->content_len != cd->replace_len)
171  return NULL;
172  SCLogDebug("replace: Adding match");
173 
174  DetectReplaceList *newlist = SCMalloc(sizeof(DetectReplaceList));
175  if (unlikely(newlist == NULL))
176  return replist;
177  newlist->found = found;
178  newlist->cd = cd;
179  /* Push new value onto the front of the list. */
180  newlist->next = replist;
181  return newlist;
182 }
183 
185 {
186  DetectReplaceList *tlist = NULL;
187 
188  SCLogDebug("replace: Executing match");
189  while (replist) {
190  memcpy(replist->found, replist->cd->replace, replist->cd->replace_len);
191  SCLogDebug("replace: replaced data");
194  tlist = replist;
195  replist = replist->next;
196  SCFree(tlist);
197  }
198 }
199 
200 
202 {
203  DetectReplaceList *tlist = NULL;
204  while (replist) {
205  SCLogDebug("replace: Freeing match");
206  tlist = replist;
207  replist = replist->next;
208  SCFree(tlist);
209  }
210 }
211 
212 #ifdef UNITTESTS /* UNITTESTS */
213 #include "detect-engine-alert.h"
214 #include "packet.h"
215 
216 /**
217  * \test Test packet Matches
218  * \param raw_eth_pkt pointer to the ethernet packet
219  * \param pktsize size of the packet
220  * \param sig pointer to the signature to test
221  * \param sid sid number of the signature
222  * \retval return 1 if match
223  * \retval return 0 if not
224  */
225 static
226 int DetectReplaceLongPatternMatchTest(uint8_t *raw_eth_pkt, uint16_t pktsize,
227  const char *sig, uint32_t sid, uint8_t *pp,
228  uint16_t *len)
229 {
230  int result = 0;
231 
232  Packet *p = NULL;
233  p = PacketGetFromAlloc();
234  if (unlikely(p == NULL))
235  return 0;
236 
238 
239  ThreadVars th_v;
240  DetectEngineThreadCtx *det_ctx = NULL;
241 
242  if (pp == NULL) {
243  SCLogDebug("replace: looks like a second run");
244  }
245 
246  PacketCopyData(p, raw_eth_pkt, pktsize);
247  memset(&dtv, 0, sizeof(DecodeThreadVars));
248  memset(&th_v, 0, sizeof(th_v));
250 
252  DecodeEthernet(&th_v, &dtv, p, GET_PKT_DATA(p), pktsize);
253 
255  if (de_ctx == NULL) {
256  goto end;
257  }
258  de_ctx->flags |= DE_QUIET;
259 
260  de_ctx->sig_list = SigInit(de_ctx, sig);
261  if (de_ctx->sig_list == NULL) {
262  goto end;
263  }
264  de_ctx->sig_list->next = NULL;
265 
269  ->ctx;
271  printf("relative next flag set on final match which is content: ");
272  goto end;
273  }
274  }
275 
278  DetectEngineThreadCtxInit(&th_v, NULL, (void *)&det_ctx);
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 
295  result = 1;
296 end:
297  if (dtv.app_tctx != NULL)
299  if (det_ctx != NULL)
300  DetectEngineThreadCtxDeinit(&th_v, (void *)det_ctx);
302  PacketRecycle(p);
303  FlowShutdown();
304  SCFree(p);
305 
306 
307  return result;
308 }
309 
310 
311 /**
312  * \brief Wrapper for DetectContentLongPatternMatchTest
313  */
314 static int DetectReplaceLongPatternMatchTestWrp(const char *sig, uint32_t sid, const char *sig_rep, uint32_t sid_rep)
315 {
316  int ret;
317  /** Real packet with the following tcp data:
318  * "Hi, this is a big test to check content matches of splitted"
319  * "patterns between multiple chunks!"
320  * (without quotes! :) )
321  */
322  uint8_t raw_eth_pkt[] = {
323  0xff,0xff,0xff,0xff,0xff,0xff,0x00,0x00,
324  0x00,0x00,0x00,0x00,0x08,0x00,0x45,0x00,
325  0x00,0x85,0x00,0x01,0x00,0x00,0x40,0x06,
326  0x7c,0x70,0x7f,0x00,0x00,0x01,0x7f,0x00,
327  0x00,0x01,0x00,0x14,0x00,0x50,0x00,0x00,
328  0x00,0x00,0x00,0x00,0x00,0x00,0x50,0x02,
329  0x20,0x00,0xc9,0xad,0x00,0x00,0x48,0x69,
330  0x2c,0x20,0x74,0x68,0x69,0x73,0x20,0x69,
331  0x73,0x20,0x61,0x20,0x62,0x69,0x67,0x20,
332  0x74,0x65,0x73,0x74,0x20,0x74,0x6f,0x20,
333  0x63,0x68,0x65,0x63,0x6b,0x20,0x63,0x6f,
334  0x6e,0x74,0x65,0x6e,0x74,0x20,0x6d,0x61,
335  0x74,0x63,0x68,0x65,0x73,0x20,0x6f,0x66,
336  0x20,0x73,0x70,0x6c,0x69,0x74,0x74,0x65,
337  0x64,0x20,0x70,0x61,0x74,0x74,0x65,0x72,
338  0x6e,0x73,0x20,0x62,0x65,0x74,0x77,0x65,
339  0x65,0x6e,0x20,0x6d,0x75,0x6c,0x74,0x69,
340  0x70,0x6c,0x65,0x20,0x63,0x68,0x75,0x6e,
341  0x6b,0x73,0x21 }; /* end raw_eth_pkt */
342  uint8_t p[sizeof(raw_eth_pkt)];
343  uint16_t psize = sizeof(raw_eth_pkt);
344 
345  /* would be unittest */
346  int run_mode_backup = SCRunmodeGet();
348  ret = DetectReplaceLongPatternMatchTest(raw_eth_pkt, (uint16_t)sizeof(raw_eth_pkt),
349  sig, sid, p, &psize);
350  if (ret == 1) {
351  SCLogDebug("replace: test1 phase1");
352  ret = DetectReplaceLongPatternMatchTest(p, psize, sig_rep, sid_rep, NULL, NULL);
353  }
354  SCRunmodeSet(run_mode_backup);
355  return ret;
356 }
357 
358 
359 /**
360  * \brief Wrapper for DetectContentLongPatternMatchTest
361  */
362 static int DetectReplaceLongPatternMatchTestUDPWrp(const char *sig, uint32_t sid, const char *sig_rep, uint32_t sid_rep)
363 {
364  int ret;
365  /** Real UDP DNS packet with a request A to a1.twimg.com
366  */
367  uint8_t raw_eth_pkt[] = {
368  0x8c, 0xa9, 0x82, 0x75, 0x5d, 0x62, 0xb4, 0x07,
369  0xf9, 0xf3, 0xc7, 0x0a, 0x08, 0x00, 0x45, 0x00,
370  0x00, 0x3a, 0x92, 0x4f, 0x40, 0x00, 0x40, 0x11,
371  0x31, 0x1a, 0xc0, 0xa8, 0x00, 0x02, 0xc1, 0xbd,
372  0xf4, 0xe1, 0x3b, 0x7e, 0x00, 0x35, 0x00, 0x26,
373  0xcb, 0x81, 0x37, 0x62, 0x01, 0x00, 0x00, 0x01,
374  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0x61,
375  0x31, 0x05, 0x74, 0x77, 0x69, 0x6d, 0x67, 0x03,
376  0x63, 0x6f, 0x6d, 0x00, 0x00, 0x01, 0x00, 0x01 };
377 
378  uint8_t p[sizeof(raw_eth_pkt)];
379  uint16_t psize = sizeof(raw_eth_pkt);
380 
381  int run_mode_backup = SCRunmodeGet();
383  ret = DetectReplaceLongPatternMatchTest(raw_eth_pkt, (uint16_t)sizeof(raw_eth_pkt),
384  sig, sid, p, &psize);
385  if (ret == 1) {
386  SCLogDebug("replace: test1 phase1 ok: %" PRIuMAX" vs %d",(uintmax_t)sizeof(raw_eth_pkt),psize);
387  ret = DetectReplaceLongPatternMatchTest(p, psize, sig_rep, sid_rep, NULL, NULL);
388  }
389  SCRunmodeSet(run_mode_backup);
390  return ret;
391 }
392 
393 /**
394  * \test Check if replace is working
395  */
396 static int DetectReplaceMatchTest01(void)
397 {
398  const char *sig = "alert tcp any any -> any any (msg:\"Nothing..\";"
399  " content:\"big\"; replace:\"pig\"; sid:1;)";
400  const char *sig_rep = "alert tcp any any -> any any (msg:\"replace worked\";"
401  " content:\"this is a pig test\"; sid:2;)";
402  FAIL_IF_NOT(DetectReplaceLongPatternMatchTestWrp(sig, 1, sig_rep, 2));
403  PASS;
404 }
405 
406 /**
407  * \test Check if replace is working with offset
408  */
409 static int DetectReplaceMatchTest02(void)
410 {
411  const char *sig = "alert tcp any any -> any any (msg:\"Nothing..\";"
412  " content:\"th\"; offset: 4; replace:\"TH\"; sid:1;)";
413  const char *sig_rep = "alert tcp any any -> any any (msg:\"replace worked\";"
414  " content:\"THis\"; offset:4; sid:2;)";
415  FAIL_IF_NOT(DetectReplaceLongPatternMatchTestWrp(sig, 1, sig_rep, 2));
416  PASS;
417 }
418 
419 /**
420  * \test Check if replace is working with offset and keyword inversion
421  */
422 static int DetectReplaceMatchTest03(void)
423 {
424  const char *sig = "alert tcp any any -> any any (msg:\"Nothing..\";"
425  " content:\"th\"; replace:\"TH\"; offset: 4; sid:1;)";
426  const char *sig_rep = "alert tcp any any -> any any (msg:\"replace worked\";"
427  " content:\"THis\"; offset:4; sid:2;)";
428  FAIL_IF_NOT(DetectReplaceLongPatternMatchTestWrp(sig, 1, sig_rep, 2));
429  PASS;
430 }
431 
432 /**
433  * \test Check if replace is working with second content
434  */
435 static int DetectReplaceMatchTest04(void)
436 {
437  const char *sig = "alert tcp any any -> any any (msg:\"Nothing..\";"
438  " content:\"th\"; replace:\"TH\"; content:\"patter\"; replace:\"matter\"; sid:1;)";
439  const char *sig_rep = "alert tcp any any -> any any (msg:\"replace worked\";"
440  " content:\"THis\"; content:\"matterns\"; sid:2;)";
441  FAIL_IF_NOT(DetectReplaceLongPatternMatchTestWrp(sig, 1, sig_rep, 2));
442  PASS;
443 }
444 
445 /**
446  * \test Check if replace is not done when second content don't match
447  */
448 static int DetectReplaceMatchTest05(void)
449 {
450  const char *sig = "alert tcp any any -> any any (msg:\"Nothing..\";"
451  " content:\"th\"; replace:\"TH\"; content:\"nutella\"; sid:1;)";
452  const char *sig_rep = "alert tcp any any -> any any (msg:\"replace worked\";"
453  " content:\"TH\"; sid:2;)";
454  FAIL_IF(DetectReplaceLongPatternMatchTestWrp(sig, 1, sig_rep, 2));
455  PASS;
456 }
457 
458 /**
459  * \test Check if replace is not done when second content match and not
460  * first
461  */
462 static int DetectReplaceMatchTest06(void)
463 {
464  const char *sig = "alert tcp any any -> any any (msg:\"Nothing..\";"
465  " content:\"nutella\"; replace:\"commode\"; content:\"this is\"; sid:1;)";
466  const char *sig_rep = "alert tcp any any -> any any (msg:\"replace worked\";"
467  " content:\"commode\"; sid:2;)";
468  FAIL_IF(DetectReplaceLongPatternMatchTestWrp(sig, 1, sig_rep, 2));
469  PASS;
470 }
471 
472 /**
473  * \test Check if replace is working when nocase used
474  */
475 static int DetectReplaceMatchTest07(void)
476 {
477  const char *sig = "alert tcp any any -> any any (msg:\"Nothing..\";"
478  " content:\"BiG\"; nocase; replace:\"pig\"; sid:1;)";
479  const char *sig_rep = "alert tcp any any -> any any (msg:\"replace worked\";"
480  " content:\"this is a pig test\"; sid:2;)";
481  FAIL_IF_NOT(DetectReplaceLongPatternMatchTestWrp(sig, 1, sig_rep, 2));
482  PASS;
483 }
484 
485 /**
486  * \test Check if replace is working when depth is used
487  */
488 static int DetectReplaceMatchTest08(void)
489 {
490  const char *sig = "alert tcp any any -> any any (msg:\"Nothing..\";"
491  " content:\"big\"; depth:17; replace:\"pig\"; sid:1;)";
492  const char *sig_rep = "alert tcp any any -> any any (msg:\"replace worked\";"
493  " content:\"this is a pig test\"; sid:2;)";
494  FAIL_IF_NOT(DetectReplaceLongPatternMatchTestWrp(sig, 1, sig_rep, 2));
495  PASS;
496 }
497 
498 /**
499  * \test Check if replace is working when depth block match used
500  */
501 static int DetectReplaceMatchTest09(void)
502 {
503  const char *sig = "alert tcp any any -> any any (msg:\"Nothing..\";"
504  " content:\"big\"; depth:16; replace:\"pig\"; sid:1;)";
505  const char *sig_rep = "alert tcp any any -> any any (msg:\"replace worked\";"
506  " content:\"this is a pig test\"; sid:2;)";
507  FAIL_IF(DetectReplaceLongPatternMatchTestWrp(sig, 1, sig_rep, 2));
508  PASS;
509 }
510 
511 /**
512  * \test Check if replace is working when depth block match used
513  */
514 static int DetectReplaceMatchTest10(void)
515 {
516  const char *sig = "alert tcp any any -> any any (msg:\"Nothing..\";"
517  " content:\"big\"; depth:17; replace:\"pig\"; offset: 14; sid:1;)";
518  const char *sig_rep = "alert tcp any any -> any any (msg:\"replace worked\";"
519  " content:\"pig\"; depth:17; offset:14; sid:2;)";
520  FAIL_IF_NOT(DetectReplaceLongPatternMatchTestWrp(sig, 1, sig_rep, 2));
521  PASS;
522 }
523 
524 /**
525  * \test Check if replace is working with within
526  */
527 static int DetectReplaceMatchTest11(void)
528 {
529  const char *sig = "alert tcp any any -> any any (msg:\"Nothing..\";"
530  " content:\"big\"; replace:\"pig\"; content:\"to\"; within: 11; sid:1;)";
531  const char *sig_rep = "alert tcp any any -> any any (msg:\"replace worked\";"
532  " content:\"pig\"; depth:17; offset:14; sid:2;)";
533 
534  FAIL_IF_NOT(DetectReplaceLongPatternMatchTestWrp(sig, 1, sig_rep, 2));
535  PASS;
536 }
537 
538 /**
539  * \test Check if replace is working with within
540  */
541 static int DetectReplaceMatchTest12(void)
542 {
543  const char *sig = "alert tcp any any -> any any (msg:\"Nothing..\";"
544  " content:\"big\"; replace:\"pig\"; content:\"to\"; within: 4; sid:1;)";
545  const char *sig_rep = "alert tcp any any -> any any (msg:\"replace worked\";"
546  " content:\"pig\"; depth:17; offset:14; sid:2;)";
547  FAIL_IF(DetectReplaceLongPatternMatchTestWrp(sig, 1, sig_rep, 2));
548  PASS;
549 }
550 
551 /**
552  * \test Check if replace is working with within
553  */
554 static int DetectReplaceMatchTest13(void)
555 {
556  const char *sig = "alert tcp any any -> any any (msg:\"Nothing..\";"
557  " content:\"big\"; replace:\"pig\"; content:\"test\"; distance: 1; sid:1;)";
558  const char *sig_rep = "alert tcp any any -> any any (msg:\"replace worked\";"
559  " content:\"pig\"; depth:17; offset:14; sid:2;)";
560  FAIL_IF_NOT(DetectReplaceLongPatternMatchTestWrp(sig, 1, sig_rep, 2));
561  PASS;
562 }
563 
564 /**
565  * \test Check if replace is working with within
566  */
567 static int DetectReplaceMatchTest14(void)
568 {
569  const char *sig = "alert tcp any any -> any any (msg:\"Nothing..\";"
570  " content:\"big\"; replace:\"pig\"; content:\"test\"; distance: 2; sid:1;)";
571  const char *sig_rep = "alert tcp any any -> any any (msg:\"replace worked\";"
572  " content:\"pig\"; depth:17; offset:14; sid:2;)";
573  FAIL_IF(DetectReplaceLongPatternMatchTestWrp(sig, 1, sig_rep, 2));
574  PASS;
575 }
576 
577 /**
578  * \test Check if replace is working with within
579  */
580 static int DetectReplaceMatchTest15(void)
581 {
582  const char *sig = "alert udp any any -> any any (msg:\"Nothing..\";"
583  " content:\"com\"; replace:\"org\"; sid:1;)";
584  const char *sig_rep = "alert udp any any -> any any (msg:\"replace worked\";"
585  " content:\"twimg|03|org\"; sid:2;)";
586  FAIL_IF_NOT(DetectReplaceLongPatternMatchTestUDPWrp(sig, 1, sig_rep, 2));
587  PASS;
588 }
589 
590 
591 /**
592  * \test Parsing test
593  */
594 static int DetectReplaceParseTest01(void)
595 {
596  int run_mode_backup = SCRunmodeGet();
598 
601 
602  de_ctx->flags |= DE_QUIET;
604  "alert udp any any -> any any "
605  "(msg:\"test\"; content:\"doh\"; replace:\"; sid:238012;)"));
606 
607  SCRunmodeSet(run_mode_backup);
609  PASS;
610 }
611 
612 /**
613  * \test Parsing test: non valid because of http protocol
614  */
615 static int DetectReplaceParseTest02(void)
616 {
617  int run_mode_backup = SCRunmodeGet();
619 
622 
623  de_ctx->flags |= DE_QUIET;
625  "alert http any any -> any any "
626  "(msg:\"test\"; content:\"doh\"; replace:\"bon\"; sid:238012;)"));
627 
628  SCRunmodeSet(run_mode_backup);
630  PASS;
631 }
632 
633 /**
634  * \test Parsing test: non valid because of http_header on same content
635  * as replace keyword
636  */
637 static int DetectReplaceParseTest03(void)
638 {
639  int run_mode_backup = SCRunmodeGet();
641 
643 
645 
646  de_ctx->flags |= DE_QUIET;
648  "alert tcp any any -> any any "
649  "(msg:\"test\"; content:\"doh\"; replace:\"don\"; http_header; sid:238012;)"));
650 
651  SCRunmodeSet(run_mode_backup);
653  PASS;
654 }
655 
656 /**
657  * \test Parsing test no content
658  */
659 static int DetectReplaceParseTest04(void)
660 {
661  int run_mode_backup = SCRunmodeGet();
663 
666 
667  de_ctx->flags |= DE_QUIET;
668  FAIL_IF_NOT_NULL(DetectEngineAppendSig(de_ctx, "alert tcp any any -> any any "
669  "(msg:\"test\"; replace:\"don\"; sid:238012;)"));
670 
671  SCRunmodeSet(run_mode_backup);
673  PASS;
674 }
675 
676 /**
677  * \test Parsing test content after replace
678  */
679 static int DetectReplaceParseTest05(void)
680 {
681  int run_mode_backup = SCRunmodeGet();
683 
686 
687  de_ctx->flags |= DE_QUIET;
689  "alert tcp any any -> any any "
690  "(msg:\"test\"; replace:\"don\"; content:\"doh\"; sid:238012;)"));
691 
692  SCRunmodeSet(run_mode_backup);
694  PASS;
695 }
696 
697 /**
698  * \test Parsing test content and replace length differ
699  */
700 static int DetectReplaceParseTest06(void)
701 {
702  int run_mode_backup = SCRunmodeGet();
704 
707 
708  de_ctx->flags |= DE_QUIET;
710  "alert tcp any any -> any any "
711  "(msg:\"test\"; content:\"don\"; replace:\"donut\"; sid:238012;)"));
712 
713  SCRunmodeSet(run_mode_backup);
715  PASS;
716 }
717 
718 /**
719  * \test Parsing test content and replace length differ
720  */
721 static int DetectReplaceParseTest07(void)
722 {
723  int run_mode_backup = SCRunmodeGet();
725 
728 
729  de_ctx->flags |= DE_QUIET;
731  DetectEngineAppendSig(de_ctx, "alert tcp any any -> any any "
732  "(msg:\"test\"; content:\"don\"; replace:\"dou\"; "
733  "content:\"jpg\"; http_header; sid:238012;)"));
734 
735  SCRunmodeSet(run_mode_backup);
737  PASS;
738 }
739 
740 /**
741  * \brief this function registers unit tests for DetectContent
742  */
743 void DetectReplaceRegisterTests(void)
744 {
745 /* matching */
746  UtRegisterTest("DetectReplaceMatchTest01", DetectReplaceMatchTest01);
747  UtRegisterTest("DetectReplaceMatchTest02", DetectReplaceMatchTest02);
748  UtRegisterTest("DetectReplaceMatchTest03", DetectReplaceMatchTest03);
749  UtRegisterTest("DetectReplaceMatchTest04", DetectReplaceMatchTest04);
750  UtRegisterTest("DetectReplaceMatchTest05", DetectReplaceMatchTest05);
751  UtRegisterTest("DetectReplaceMatchTest06", DetectReplaceMatchTest06);
752  UtRegisterTest("DetectReplaceMatchTest07", DetectReplaceMatchTest07);
753  UtRegisterTest("DetectReplaceMatchTest08", DetectReplaceMatchTest08);
754  UtRegisterTest("DetectReplaceMatchTest09", DetectReplaceMatchTest09);
755  UtRegisterTest("DetectReplaceMatchTest10", DetectReplaceMatchTest10);
756  UtRegisterTest("DetectReplaceMatchTest11", DetectReplaceMatchTest11);
757  UtRegisterTest("DetectReplaceMatchTest12", DetectReplaceMatchTest12);
758  UtRegisterTest("DetectReplaceMatchTest13", DetectReplaceMatchTest13);
759  UtRegisterTest("DetectReplaceMatchTest14", DetectReplaceMatchTest14);
760  UtRegisterTest("DetectReplaceMatchTest15", DetectReplaceMatchTest15);
761 /* parsing */
762  UtRegisterTest("DetectReplaceParseTest01", DetectReplaceParseTest01);
763  UtRegisterTest("DetectReplaceParseTest02", DetectReplaceParseTest02);
764  UtRegisterTest("DetectReplaceParseTest03", DetectReplaceParseTest03);
765  UtRegisterTest("DetectReplaceParseTest04", DetectReplaceParseTest04);
766  UtRegisterTest("DetectReplaceParseTest05", DetectReplaceParseTest05);
767  UtRegisterTest("DetectReplaceParseTest06", DetectReplaceParseTest06);
768  UtRegisterTest("DetectReplaceParseTest07", DetectReplaceParseTest07);
769 }
770 #endif /* UNITTESTS */
SigTableElmt_::url
const char * url
Definition: detect.h:1312
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:740
len
uint8_t len
Definition: app-layer-dnp3.h:2
detect-engine.h
DETECT_SM_LIST_PMATCH
@ DETECT_SM_LIST_PMATCH
Definition: detect.h:116
FAIL_IF_NULL
#define FAIL_IF_NULL(expr)
Fail a test if expression evaluates to NULL.
Definition: util-unittest.h:89
SCRunmodeGet
int SCRunmodeGet(void)
Get the current run mode.
Definition: suricata.c:260
SigTableElmt_::desc
const char * desc
Definition: detect.h:1311
sigmatch_table
SigTableElmt * sigmatch_table
Definition: detect-parse.c:128
Signature_::sig_str
char * sig_str
Definition: detect.h:670
PacketCopyData
int PacketCopyData(Packet *p, const uint8_t *pktdata, uint32_t pktlen)
Copy data to Packet payload and set packet length.
Definition: decode.c:351
SigTableElmt_::name
const char * name
Definition: detect.h:1309
SignatureInitData_::smlists_tail
struct SigMatch_ * smlists_tail[DETECT_SM_LIST_MAX]
Definition: detect.h:590
DetectEnginePruneFreeList
void DetectEnginePruneFreeList(void)
Definition: detect-engine.c:4713
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:103
DETECT_CONTENT
@ DETECT_CONTENT
Definition: detect-engine-register.h:72
PKT_STREAM_MODIFIED
#define PKT_STREAM_MODIFIED
Definition: decode.h:1273
SCLogDebug
#define SCLogDebug(...)
Definition: util-debug.h:269
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:141
Packet_::flags
uint32_t flags
Definition: decode.h:513
PacketRecycle
void PacketRecycle(Packet *p)
Definition: packet.c:143
DETECT_REPLACE
@ DETECT_REPLACE
Definition: detect-engine-register.h:81
DetectReplaceList_::found
uint8_t * found
Definition: detect.h:741
SCRunmodeSet
void SCRunmodeSet(int run_mode)
Set the current run mode.
Definition: suricata.c:265
SigTableElmt_::flags
uint16_t flags
Definition: detect.h:1303
ctx
struct Thresholds ctx
DetectEngineCtx_
main detection engine ctx
Definition: detect.h:843
DetectEngineCtxFree
void DetectEngineCtxFree(DetectEngineCtx *)
Free a DetectEngineCtx::
Definition: detect-engine.c:2623
DetectEngineAddToMaster
int DetectEngineAddToMaster(DetectEngineCtx *de_ctx)
Definition: detect-engine.c:4643
DE_QUIET
#define DE_QUIET
Definition: detect.h:323
DetectReplaceList_
Definition: detect.h:739
SigMatchSignatures
void SigMatchSignatures(ThreadVars *tv, DetectEngineCtx *de_ctx, DetectEngineThreadCtx *det_ctx, Packet *p)
wrapper for old tests
Definition: detect.c:1950
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:2591
SigTableElmt_::Setup
int(* Setup)(DetectEngineCtx *, Signature *, const char *)
Definition: detect.h:1294
util-unittest.h
FAIL_IF_NOT
#define FAIL_IF_NOT(expr)
Fail a test if expression evaluates to false.
Definition: util-unittest.h:82
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:701
DetectReplaceAddToList
DetectReplaceList * DetectReplaceAddToList(DetectReplaceList *replist, uint8_t *found, const DetectContentData *cd)
Definition: detect-replace.c:167
Signature_::next
struct Signature_ * next
Definition: detect.h:675
SIGMATCH_QUOTES_MANDATORY
#define SIGMATCH_QUOTES_MANDATORY
Definition: detect.h:1509
FlowInitConfig
void FlowInitConfig(bool quiet)
initialize the configuration
Definition: flow.c:533
DETECT_SM_LIST_POSTMATCH
@ DETECT_SM_LIST_POSTMATCH
Definition: detect.h:124
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:4703
PASS
#define PASS
Pass the test.
Definition: util-unittest.h:105
de_ctx
DetectEngineCtx * de_ctx
Definition: fuzz_siginit.c:17
DetectReplaceRegister
void DetectReplaceRegister(void)
Definition: detect-replace.c:58
DetectEngineThreadCtx_
Definition: detect.h:1098
DetectReplaceList_::next
struct DetectReplaceList_ * next
Definition: detect.h:742
GET_PKT_DATA
#define GET_PKT_DATA(p)
Definition: decode.h:205
detect-engine-mpm.h
detect.h
ThreadVars_
Per thread variable structure.
Definition: threadvars.h:58
DetectEngineThreadCtxInit
TmEcode DetectEngineThreadCtxInit(ThreadVars *tv, void *initdata, void **data)
initialize thread specific detection engine context
Definition: detect-engine.c:3365
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:249
SigInit
Signature * SigInit(DetectEngineCtx *de_ctx, const char *sigstr)
Parses a signature and adds it to the Detection Engine Context.
Definition: detect-parse.c:2289
SigMatch_::ctx
SigMatchCtx * ctx
Definition: detect.h:352
Signature_::flags
uint32_t flags
Definition: detect.h:604
Packet_
Definition: decode.h:476
detect-engine-build.h
GET_PKT_LEN
#define GET_PKT_LEN(p)
Definition: decode.h:204
DecodeThreadVars_::app_tctx
AppLayerThreadCtx * app_tctx
Definition: decode.h:934
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
SIGMATCH_HANDLE_NEGATION
#define SIGMATCH_HANDLE_NEGATION
Definition: detect.h:1513
Signature_::init_data
SignatureInitData * init_data
Definition: detect.h:672
AppLayerGetCtxThread
AppLayerThreadCtx * AppLayerGetCtxThread(void)
Creates a new app layer thread context.
Definition: app-layer.c:1060
SignatureInitData_::negated
bool negated
Definition: detect.h:547
SigTableElmt_::Match
int(* Match)(DetectEngineThreadCtx *, Packet *, const Signature *, const SigMatchCtx *)
Definition: detect.h:1277
detect-replace.h
DetectContentData_::replace
uint8_t * replace
Definition: detect-content.h:113
runmodes.h
SigGroupBuild
int SigGroupBuild(DetectEngineCtx *de_ctx)
Convert the signature list into the runtime match structure.
Definition: detect-engine-build.c:2145
dtv
DecodeThreadVars * dtv
Definition: fuzz_decodepcapfile.c:33
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:344
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:83
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:350
FlowShutdown
void FlowShutdown(void)
shutdown the flow engine
Definition: flow.c:680
packet.h
DetectEngineThreadCtxDeinit
TmEcode DetectEngineThreadCtxDeinit(ThreadVars *tv, void *data)
Definition: detect-engine.c:3592
DetectEngineCtx_::sig_list
Signature * sig_list
Definition: detect.h:851
PacketGetFromAlloc
Packet * PacketGetFromAlloc(void)
Get a malloced packet.
Definition: decode.c:232
RUNMODE_NFQ
@ RUNMODE_NFQ
Definition: runmodes.h:31
SCMalloc
#define SCMalloc(sz)
Definition: util-mem.h:47
SCLogError
#define SCLogError(...)
Macro used to log ERROR messages.
Definition: util-debug.h:261
SCFree
#define SCFree(p)
Definition: util-mem.h:61
DecodeThreadVars_
Structure to hold thread specific data for all decode modules.
Definition: decode.h:932
AppLayerDestroyCtxThread
void AppLayerDestroyCtxThread(AppLayerThreadCtx *app_tctx)
Destroys the context created by AppLayerGetCtxThread().
Definition: app-layer.c:1081
detect-parse.h
Signature_
Signature container.
Definition: detect.h:603
SigMatch_
a single match condition for a signature
Definition: detect.h:349
DetectEngineCtxInit
DetectEngineCtx * DetectEngineCtxInit(void)
Definition: detect-engine.c:2584
DetectReplaceFreeInternal
void DetectReplaceFreeInternal(DetectReplaceList *replist)
Definition: detect-replace.c:201
FLOW_QUIET
#define FLOW_QUIET
Definition: flow.h:43
DetectContentData_::content_len
uint16_t content_len
Definition: detect-content.h:95
SigMatchAppendSMToList
SigMatch * SigMatchAppendSMToList(DetectEngineCtx *de_ctx, Signature *s, uint16_t type, SigMatchCtx *ctx, const int list)
Append a SigMatch to the list type.
Definition: detect-parse.c:437
DetectEngineCtx_::flags
uint8_t flags
Definition: detect.h:845
DetectEngineThreadCtx_::replist
DetectReplaceList * replist
Definition: detect.h:1208
DETECT_CONTENT_REPLACE
#define DETECT_CONTENT_REPLACE
Definition: detect-content.h:51
DetectReplaceExecuteInternal
void DetectReplaceExecuteInternal(Packet *p, DetectReplaceList *replist)
Definition: detect-replace.c:184
DecodeEthernet
int DecodeEthernet(ThreadVars *tv, DecodeThreadVars *dtv, Packet *p, const uint8_t *pkt, uint32_t len)
Definition: decode-ethernet.c:42
RUNMODE_IPFW
@ RUNMODE_IPFW
Definition: runmodes.h:33
SigTableElmt_::RegisterTests
void(* RegisterTests)(void)
Definition: detect.h:1301
app-layer.h
SIG_FLAG_REQUIRE_PACKET
#define SIG_FLAG_REQUIRE_PACKET
Definition: detect.h:250