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