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  NULL) {
149  goto error;
150  }
151  return 0;
152 
153 error:
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  */
226 static
227 int 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  }
259  de_ctx->flags |= DE_QUIET;
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;
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;
297 end:
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  */
315 static 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  */
363 static 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  */
397 static 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  */
410 static 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  */
423 static 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  */
436 static 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  */
449 static 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  */
463 static 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  */
476 static 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  */
489 static 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  */
502 static 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  */
515 static 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  */
528 static 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  */
542 static 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  */
555 static 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  */
568 static 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  */
581 static 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  */
595 static int DetectReplaceParseTest01(void)
596 {
597  int run_mode_backup = SCRunmodeGet();
599 
602 
603  de_ctx->flags |= DE_QUIET;
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  */
616 static int DetectReplaceParseTest02(void)
617 {
618  int run_mode_backup = SCRunmodeGet();
620 
623 
624  de_ctx->flags |= DE_QUIET;
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  */
638 static int DetectReplaceParseTest03(void)
639 {
640  int run_mode_backup = SCRunmodeGet();
642 
644 
646 
647  de_ctx->flags |= DE_QUIET;
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  */
660 static int DetectReplaceParseTest04(void)
661 {
662  int run_mode_backup = SCRunmodeGet();
664 
667 
668  de_ctx->flags |= DE_QUIET;
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  */
680 static int DetectReplaceParseTest05(void)
681 {
682  int run_mode_backup = SCRunmodeGet();
684 
687 
688  de_ctx->flags |= DE_QUIET;
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  */
701 static int DetectReplaceParseTest06(void)
702 {
703  int run_mode_backup = SCRunmodeGet();
705 
708 
709  de_ctx->flags |= DE_QUIET;
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  */
722 static int DetectReplaceParseTest07(void)
723 {
724  int run_mode_backup = SCRunmodeGet();
726 
729 
730  de_ctx->flags |= DE_QUIET;
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  */
744 void 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 */
SigTableElmt_::url
const char * url
Definition: detect.h:1422
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:805
len
uint8_t len
Definition: app-layer-dnp3.h:2
detect-engine.h
DETECT_SM_LIST_PMATCH
@ DETECT_SM_LIST_PMATCH
Definition: detect.h:119
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:1421
sigmatch_table
SigTableElmt * sigmatch_table
Definition: detect-parse.c:79
Signature_::sig_str
char * sig_str
Definition: detect.h:734
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:1419
SignatureInitData_::smlists_tail
struct SigMatch_ * smlists_tail[DETECT_SM_LIST_MAX]
Definition: detect.h:633
DetectEnginePruneFreeList
void DetectEnginePruneFreeList(void)
Definition: detect-engine.c:4698
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:69
PKT_STREAM_MODIFIED
#define PKT_STREAM_MODIFIED
Definition: decode.h:1258
SCLogDebug
#define SCLogDebug(...)
Definition: util-debug.h:270
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:535
PacketRecycle
void PacketRecycle(Packet *p)
Definition: packet.c:145
DETECT_REPLACE
@ DETECT_REPLACE
Definition: detect-engine-register.h:78
RUNMODE_NFQ
@ RUNMODE_NFQ
Definition: runmodes.h:31
DetectReplaceList_::found
uint8_t * found
Definition: detect.h:806
SigTableElmt_::flags
uint16_t flags
Definition: detect.h:1413
ctx
struct Thresholds ctx
DetectEngineCtx_
main detection engine ctx
Definition: detect.h:919
DetectEngineCtxFree
void DetectEngineCtxFree(DetectEngineCtx *)
Free a DetectEngineCtx::
Definition: detect-engine.c:2624
DetectEngineAddToMaster
int DetectEngineAddToMaster(DetectEngineCtx *de_ctx)
Definition: detect-engine.c:4628
DE_QUIET
#define DE_QUIET
Definition: detect.h:330
DetectReplaceList_
Definition: detect.h:804
SigMatchSignatures
void SigMatchSignatures(ThreadVars *tv, DetectEngineCtx *de_ctx, DetectEngineThreadCtx *det_ctx, Packet *p)
wrapper for old tests
Definition: detect.c:2349
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:3338
SigTableElmt_::Setup
int(* Setup)(DetectEngineCtx *, Signature *, const char *)
Definition: detect.h:1404
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:658
SCRunmodeSet
void SCRunmodeSet(SCRunMode run_mode)
Set the current run mode.
Definition: suricata.c:271
DetectReplaceAddToList
DetectReplaceList * DetectReplaceAddToList(DetectReplaceList *replist, uint8_t *found, const DetectContentData *cd)
Definition: detect-replace.c:168
Signature_::next
struct Signature_ * next
Definition: detect.h:739
SIGMATCH_QUOTES_MANDATORY
#define SIGMATCH_QUOTES_MANDATORY
Definition: detect.h:1628
FlowInitConfig
void FlowInitConfig(bool quiet)
initialize the configuration
Definition: flow.c:546
DETECT_SM_LIST_POSTMATCH
@ DETECT_SM_LIST_POSTMATCH
Definition: detect.h:127
SCRunmodeGet
SCRunMode SCRunmodeGet(void)
Get the current run mode.
Definition: suricata.c:266
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:4688
PASS
#define PASS
Pass the test.
Definition: util-unittest.h:105
de_ctx
DetectEngineCtx * de_ctx
Definition: fuzz_siginit.c:18
DetectReplaceRegister
void DetectReplaceRegister(void)
Definition: detect-replace.c:58
DetectEngineThreadCtx_
Definition: detect.h:1211
DetectReplaceList_::next
struct DetectReplaceList_ * next
Definition: detect.h:807
GET_PKT_DATA
#define GET_PKT_DATA(p)
Definition: decode.h:209
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:388
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:3350
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:250
SigInit
Signature * SigInit(DetectEngineCtx *de_ctx, const char *sigstr)
Parses a signature and adds it to the Detection Engine Context.
Definition: detect-parse.c:2996
SigMatch_::ctx
SigMatchCtx * ctx
Definition: detect.h:360
Signature_::flags
uint32_t flags
Definition: detect.h:658
Packet_
Definition: decode.h:492
detect-engine-build.h
GET_PKT_LEN
#define GET_PKT_LEN(p)
Definition: decode.h:208
DecodeThreadVars_::app_tctx
AppLayerThreadCtx * app_tctx
Definition: decode.h:956
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:1632
Signature_::init_data
SignatureInitData * init_data
Definition: detect.h:736
AppLayerGetCtxThread
AppLayerThreadCtx * AppLayerGetCtxThread(void)
Creates a new app layer thread context.
Definition: app-layer.c:1107
SignatureInitData_::negated
bool negated
Definition: detect.h:586
SigTableElmt_::Match
int(* Match)(DetectEngineThreadCtx *, Packet *, const Signature *, const SigMatchCtx *)
Definition: detect.h:1384
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:2130
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:352
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:85
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:358
FlowShutdown
void FlowShutdown(void)
shutdown the flow engine
Definition: flow.c:690
packet.h
DetectEngineThreadCtxDeinit
TmEcode DetectEngineThreadCtxDeinit(ThreadVars *tv, void *data)
Definition: detect-engine.c:3576
DetectEngineCtx_::sig_list
Signature * sig_list
Definition: detect.h:928
PacketGetFromAlloc
Packet * PacketGetFromAlloc(void)
Get a malloced packet.
Definition: decode.c:232
SCMalloc
#define SCMalloc(sz)
Definition: util-mem.h:47
SCLogError
#define SCLogError(...)
Macro used to log ERROR messages.
Definition: util-debug.h:262
SCFree
#define SCFree(p)
Definition: util-mem.h:61
DecodeThreadVars_
Structure to hold thread specific data for all decode modules.
Definition: decode.h:954
AppLayerDestroyCtxThread
void AppLayerDestroyCtxThread(AppLayerThreadCtx *app_tctx)
Destroys the context created by AppLayerGetCtxThread().
Definition: app-layer.c:1128
detect-parse.h
Signature_
Signature container.
Definition: detect.h:657
SigMatch_
a single match condition for a signature
Definition: detect.h:357
DetectEngineCtxInit
DetectEngineCtx * DetectEngineCtxInit(void)
Definition: detect-engine.c:2585
DetectReplaceFreeInternal
void DetectReplaceFreeInternal(DetectReplaceList *replist)
Definition: detect-replace.c:202
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:921
DetectEngineThreadCtx_::replist
DetectReplaceList * replist
Definition: detect.h:1315
DETECT_CONTENT_REPLACE
#define DETECT_CONTENT_REPLACE
Definition: detect-content.h:51
DetectReplaceExecuteInternal
void DetectReplaceExecuteInternal(Packet *p, DetectReplaceList *replist)
Definition: detect-replace.c:185
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:1411
app-layer.h
SIG_FLAG_REQUIRE_PACKET
#define SIG_FLAG_REQUIRE_PACKET
Definition: detect.h:254