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 = PacketGetFromAlloc();
234  if (unlikely(p == NULL))
235  return 0;
236 
238  ThreadVars th_v;
239  memset(&dtv, 0, sizeof(DecodeThreadVars));
240  memset(&th_v, 0, sizeof(th_v));
241  StatsThreadInit(&th_v.stats);
242  DetectEngineThreadCtx *det_ctx = NULL;
243 
244  if (pp == NULL) {
245  SCLogDebug("replace: looks like a second run");
246  }
247 
248  PacketCopyData(p, raw_eth_pkt, pktsize);
251  DecodeEthernet(&th_v, &dtv, p, GET_PKT_DATA(p), pktsize);
252 
254  if (de_ctx == NULL) {
255  goto end;
256  }
257  de_ctx->flags |= DE_QUIET;
258 
260  if (s == NULL) {
261  goto end;
262  }
263 
265  DetectContentData *co =
268  printf("relative next flag set on final match which is content: ");
269  goto end;
270  }
271  }
272 
275  DetectEngineThreadCtxInit(&th_v, (void *)de_ctx, (void *)&det_ctx);
276  BUG_ON(det_ctx == NULL);
277 
278  SigMatchSignatures(&th_v, de_ctx, det_ctx, p);
280 
281  if (PacketAlertCheck(p, sid) != 1) {
282  SCLogDebug("replace: no alert on sig %d", sid);
283  goto end;
284  }
285 
286  if (pp) {
287  memcpy(pp, GET_PKT_DATA(p), GET_PKT_LEN(p));
288  *len = pktsize;
289  SCLogDebug("replace: copying %d on %p", *len, pp);
290  }
291 
292  result = 1;
293 end:
294  if (dtv.app_tctx != NULL)
296  if (det_ctx != NULL)
297  DetectEngineThreadCtxDeinit(&th_v, (void *)det_ctx);
299  PacketFree(p);
300  FlowShutdown();
301  StatsThreadCleanup(&th_v.stats);
302  return result;
303 }
304 
305 
306 /**
307  * \brief Wrapper for DetectContentLongPatternMatchTest
308  */
309 static int DetectReplaceLongPatternMatchTestWrp(const char *sig, uint32_t sid, const char *sig_rep, uint32_t sid_rep)
310 {
311  int ret;
312  /** Real packet with the following tcp data:
313  * "Hi, this is a big test to check content matches of splitted"
314  * "patterns between multiple chunks!"
315  * (without quotes! :) )
316  */
317  uint8_t raw_eth_pkt[] = {
318  0xff,0xff,0xff,0xff,0xff,0xff,0x00,0x00,
319  0x00,0x00,0x00,0x00,0x08,0x00,0x45,0x00,
320  0x00,0x85,0x00,0x01,0x00,0x00,0x40,0x06,
321  0x7c,0x70,0x7f,0x00,0x00,0x01,0x7f,0x00,
322  0x00,0x01,0x00,0x14,0x00,0x50,0x00,0x00,
323  0x00,0x00,0x00,0x00,0x00,0x00,0x50,0x02,
324  0x20,0x00,0xc9,0xad,0x00,0x00,0x48,0x69,
325  0x2c,0x20,0x74,0x68,0x69,0x73,0x20,0x69,
326  0x73,0x20,0x61,0x20,0x62,0x69,0x67,0x20,
327  0x74,0x65,0x73,0x74,0x20,0x74,0x6f,0x20,
328  0x63,0x68,0x65,0x63,0x6b,0x20,0x63,0x6f,
329  0x6e,0x74,0x65,0x6e,0x74,0x20,0x6d,0x61,
330  0x74,0x63,0x68,0x65,0x73,0x20,0x6f,0x66,
331  0x20,0x73,0x70,0x6c,0x69,0x74,0x74,0x65,
332  0x64,0x20,0x70,0x61,0x74,0x74,0x65,0x72,
333  0x6e,0x73,0x20,0x62,0x65,0x74,0x77,0x65,
334  0x65,0x6e,0x20,0x6d,0x75,0x6c,0x74,0x69,
335  0x70,0x6c,0x65,0x20,0x63,0x68,0x75,0x6e,
336  0x6b,0x73,0x21 }; /* end raw_eth_pkt */
337  uint8_t p[sizeof(raw_eth_pkt)];
338  uint16_t psize = sizeof(raw_eth_pkt);
339 
340  /* would be unittest */
341  int run_mode_backup = SCRunmodeGet();
343  ret = DetectReplaceLongPatternMatchTest(raw_eth_pkt, (uint16_t)sizeof(raw_eth_pkt),
344  sig, sid, p, &psize);
345  if (ret == 1) {
346  SCLogDebug("replace: test1 phase1");
347  ret = DetectReplaceLongPatternMatchTest(p, psize, sig_rep, sid_rep, NULL, NULL);
348  }
349  SCRunmodeSet(run_mode_backup);
350  return ret;
351 }
352 
353 
354 /**
355  * \brief Wrapper for DetectContentLongPatternMatchTest
356  */
357 static int DetectReplaceLongPatternMatchTestUDPWrp(const char *sig, uint32_t sid, const char *sig_rep, uint32_t sid_rep)
358 {
359  int ret;
360  /** Real UDP DNS packet with a request A to a1.twimg.com
361  */
362  uint8_t raw_eth_pkt[] = {
363  0x8c, 0xa9, 0x82, 0x75, 0x5d, 0x62, 0xb4, 0x07,
364  0xf9, 0xf3, 0xc7, 0x0a, 0x08, 0x00, 0x45, 0x00,
365  0x00, 0x3a, 0x92, 0x4f, 0x40, 0x00, 0x40, 0x11,
366  0x31, 0x1a, 0xc0, 0xa8, 0x00, 0x02, 0xc1, 0xbd,
367  0xf4, 0xe1, 0x3b, 0x7e, 0x00, 0x35, 0x00, 0x26,
368  0xcb, 0x81, 0x37, 0x62, 0x01, 0x00, 0x00, 0x01,
369  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0x61,
370  0x31, 0x05, 0x74, 0x77, 0x69, 0x6d, 0x67, 0x03,
371  0x63, 0x6f, 0x6d, 0x00, 0x00, 0x01, 0x00, 0x01 };
372 
373  uint8_t p[sizeof(raw_eth_pkt)];
374  uint16_t psize = sizeof(raw_eth_pkt);
375 
376  int run_mode_backup = SCRunmodeGet();
378  ret = DetectReplaceLongPatternMatchTest(raw_eth_pkt, (uint16_t)sizeof(raw_eth_pkt),
379  sig, sid, p, &psize);
380  if (ret == 1) {
381  SCLogDebug("replace: test1 phase1 ok: %" PRIuMAX" vs %d",(uintmax_t)sizeof(raw_eth_pkt),psize);
382  ret = DetectReplaceLongPatternMatchTest(p, psize, sig_rep, sid_rep, NULL, NULL);
383  }
384  SCRunmodeSet(run_mode_backup);
385  return ret;
386 }
387 
388 /**
389  * \test Check if replace is working
390  */
391 static int DetectReplaceMatchTest01(void)
392 {
393  const char *sig = "alert tcp any any -> any any (msg:\"Nothing..\";"
394  " content:\"big\"; replace:\"pig\"; sid:1;)";
395  const char *sig_rep = "alert tcp any any -> any any (msg:\"replace worked\";"
396  " content:\"this is a pig test\"; sid:2;)";
397  FAIL_IF_NOT(DetectReplaceLongPatternMatchTestWrp(sig, 1, sig_rep, 2));
398  PASS;
399 }
400 
401 /**
402  * \test Check if replace is working with offset
403  */
404 static int DetectReplaceMatchTest02(void)
405 {
406  const char *sig = "alert tcp any any -> any any (msg:\"Nothing..\";"
407  " content:\"th\"; offset: 4; replace:\"TH\"; sid:1;)";
408  const char *sig_rep = "alert tcp any any -> any any (msg:\"replace worked\";"
409  " content:\"THis\"; offset:4; sid:2;)";
410  FAIL_IF_NOT(DetectReplaceLongPatternMatchTestWrp(sig, 1, sig_rep, 2));
411  PASS;
412 }
413 
414 /**
415  * \test Check if replace is working with offset and keyword inversion
416  */
417 static int DetectReplaceMatchTest03(void)
418 {
419  const char *sig = "alert tcp any any -> any any (msg:\"Nothing..\";"
420  " content:\"th\"; replace:\"TH\"; offset: 4; sid:1;)";
421  const char *sig_rep = "alert tcp any any -> any any (msg:\"replace worked\";"
422  " content:\"THis\"; offset:4; sid:2;)";
423  FAIL_IF_NOT(DetectReplaceLongPatternMatchTestWrp(sig, 1, sig_rep, 2));
424  PASS;
425 }
426 
427 /**
428  * \test Check if replace is working with second content
429  */
430 static int DetectReplaceMatchTest04(void)
431 {
432  const char *sig = "alert tcp any any -> any any (msg:\"Nothing..\";"
433  " content:\"th\"; replace:\"TH\"; content:\"patter\"; replace:\"matter\"; sid:1;)";
434  const char *sig_rep = "alert tcp any any -> any any (msg:\"replace worked\";"
435  " content:\"THis\"; content:\"matterns\"; sid:2;)";
436  FAIL_IF_NOT(DetectReplaceLongPatternMatchTestWrp(sig, 1, sig_rep, 2));
437  PASS;
438 }
439 
440 /**
441  * \test Check if replace is not done when second content don't match
442  */
443 static int DetectReplaceMatchTest05(void)
444 {
445  const char *sig = "alert tcp any any -> any any (msg:\"Nothing..\";"
446  " content:\"th\"; replace:\"TH\"; content:\"nutella\"; sid:1;)";
447  const char *sig_rep = "alert tcp any any -> any any (msg:\"replace worked\";"
448  " content:\"TH\"; sid:2;)";
449  FAIL_IF(DetectReplaceLongPatternMatchTestWrp(sig, 1, sig_rep, 2));
450  PASS;
451 }
452 
453 /**
454  * \test Check if replace is not done when second content match and not
455  * first
456  */
457 static int DetectReplaceMatchTest06(void)
458 {
459  const char *sig = "alert tcp any any -> any any (msg:\"Nothing..\";"
460  " content:\"nutella\"; replace:\"commode\"; content:\"this is\"; sid:1;)";
461  const char *sig_rep = "alert tcp any any -> any any (msg:\"replace worked\";"
462  " content:\"commode\"; sid:2;)";
463  FAIL_IF(DetectReplaceLongPatternMatchTestWrp(sig, 1, sig_rep, 2));
464  PASS;
465 }
466 
467 /**
468  * \test Check if replace is working when nocase used
469  */
470 static int DetectReplaceMatchTest07(void)
471 {
472  const char *sig = "alert tcp any any -> any any (msg:\"Nothing..\";"
473  " content:\"BiG\"; nocase; replace:\"pig\"; sid:1;)";
474  const char *sig_rep = "alert tcp any any -> any any (msg:\"replace worked\";"
475  " content:\"this is a pig test\"; sid:2;)";
476  FAIL_IF_NOT(DetectReplaceLongPatternMatchTestWrp(sig, 1, sig_rep, 2));
477  PASS;
478 }
479 
480 /**
481  * \test Check if replace is working when depth is used
482  */
483 static int DetectReplaceMatchTest08(void)
484 {
485  const char *sig = "alert tcp any any -> any any (msg:\"Nothing..\";"
486  " content:\"big\"; depth:17; replace:\"pig\"; sid:1;)";
487  const char *sig_rep = "alert tcp any any -> any any (msg:\"replace worked\";"
488  " content:\"this is a pig test\"; sid:2;)";
489  FAIL_IF_NOT(DetectReplaceLongPatternMatchTestWrp(sig, 1, sig_rep, 2));
490  PASS;
491 }
492 
493 /**
494  * \test Check if replace is working when depth block match used
495  */
496 static int DetectReplaceMatchTest09(void)
497 {
498  const char *sig = "alert tcp any any -> any any (msg:\"Nothing..\";"
499  " content:\"big\"; depth:16; replace:\"pig\"; sid:1;)";
500  const char *sig_rep = "alert tcp any any -> any any (msg:\"replace worked\";"
501  " content:\"this is a pig test\"; sid:2;)";
502  FAIL_IF(DetectReplaceLongPatternMatchTestWrp(sig, 1, sig_rep, 2));
503  PASS;
504 }
505 
506 /**
507  * \test Check if replace is working when depth block match used
508  */
509 static int DetectReplaceMatchTest10(void)
510 {
511  const char *sig = "alert tcp any any -> any any (msg:\"Nothing..\";"
512  " content:\"big\"; depth:17; replace:\"pig\"; offset: 14; sid:1;)";
513  const char *sig_rep = "alert tcp any any -> any any (msg:\"replace worked\";"
514  " content:\"pig\"; depth:17; offset:14; sid:2;)";
515  FAIL_IF_NOT(DetectReplaceLongPatternMatchTestWrp(sig, 1, sig_rep, 2));
516  PASS;
517 }
518 
519 /**
520  * \test Check if replace is working with within
521  */
522 static int DetectReplaceMatchTest11(void)
523 {
524  const char *sig = "alert tcp any any -> any any (msg:\"Nothing..\";"
525  " content:\"big\"; replace:\"pig\"; content:\"to\"; within: 11; sid:1;)";
526  const char *sig_rep = "alert tcp any any -> any any (msg:\"replace worked\";"
527  " content:\"pig\"; depth:17; offset:14; sid:2;)";
528 
529  FAIL_IF_NOT(DetectReplaceLongPatternMatchTestWrp(sig, 1, sig_rep, 2));
530  PASS;
531 }
532 
533 /**
534  * \test Check if replace is working with within
535  */
536 static int DetectReplaceMatchTest12(void)
537 {
538  const char *sig = "alert tcp any any -> any any (msg:\"Nothing..\";"
539  " content:\"big\"; replace:\"pig\"; content:\"to\"; within: 4; sid:1;)";
540  const char *sig_rep = "alert tcp any any -> any any (msg:\"replace worked\";"
541  " content:\"pig\"; depth:17; offset:14; sid:2;)";
542  FAIL_IF(DetectReplaceLongPatternMatchTestWrp(sig, 1, sig_rep, 2));
543  PASS;
544 }
545 
546 /**
547  * \test Check if replace is working with within
548  */
549 static int DetectReplaceMatchTest13(void)
550 {
551  const char *sig = "alert tcp any any -> any any (msg:\"Nothing..\";"
552  " content:\"big\"; replace:\"pig\"; content:\"test\"; distance: 1; sid:1;)";
553  const char *sig_rep = "alert tcp any any -> any any (msg:\"replace worked\";"
554  " content:\"pig\"; depth:17; offset:14; sid:2;)";
555  FAIL_IF_NOT(DetectReplaceLongPatternMatchTestWrp(sig, 1, sig_rep, 2));
556  PASS;
557 }
558 
559 /**
560  * \test Check if replace is working with within
561  */
562 static int DetectReplaceMatchTest14(void)
563 {
564  const char *sig = "alert tcp any any -> any any (msg:\"Nothing..\";"
565  " content:\"big\"; replace:\"pig\"; content:\"test\"; distance: 2; sid:1;)";
566  const char *sig_rep = "alert tcp any any -> any any (msg:\"replace worked\";"
567  " content:\"pig\"; depth:17; offset:14; sid:2;)";
568  FAIL_IF(DetectReplaceLongPatternMatchTestWrp(sig, 1, sig_rep, 2));
569  PASS;
570 }
571 
572 /**
573  * \test Check if replace is working with within
574  */
575 static int DetectReplaceMatchTest15(void)
576 {
577  const char *sig = "alert udp any any -> any any (msg:\"Nothing..\";"
578  " content:\"com\"; replace:\"org\"; sid:1;)";
579  const char *sig_rep = "alert udp any any -> any any (msg:\"replace worked\";"
580  " content:\"twimg|03|org\"; sid:2;)";
581  FAIL_IF_NOT(DetectReplaceLongPatternMatchTestUDPWrp(sig, 1, sig_rep, 2));
582  PASS;
583 }
584 
585 
586 /**
587  * \test Parsing test
588  */
589 static int DetectReplaceParseTest01(void)
590 {
591  int run_mode_backup = SCRunmodeGet();
593 
596 
597  de_ctx->flags |= DE_QUIET;
599  "alert udp any any -> any any "
600  "(msg:\"test\"; content:\"doh\"; replace:\"; sid:238012;)"));
601 
602  SCRunmodeSet(run_mode_backup);
604  PASS;
605 }
606 
607 /**
608  * \test Parsing test: non valid because of http protocol
609  */
610 static int DetectReplaceParseTest02(void)
611 {
612  int run_mode_backup = SCRunmodeGet();
614 
617 
618  de_ctx->flags |= DE_QUIET;
620  "alert http any any -> any any "
621  "(msg:\"test\"; content:\"doh\"; replace:\"bon\"; sid:238012;)"));
622 
623  SCRunmodeSet(run_mode_backup);
625  PASS;
626 }
627 
628 /**
629  * \test Parsing test: non valid because of http_header on same content
630  * as replace keyword
631  */
632 static int DetectReplaceParseTest03(void)
633 {
634  int run_mode_backup = SCRunmodeGet();
636 
638 
640 
641  de_ctx->flags |= DE_QUIET;
643  "alert tcp any any -> any any "
644  "(msg:\"test\"; content:\"doh\"; replace:\"don\"; http_header; sid:238012;)"));
645 
646  SCRunmodeSet(run_mode_backup);
648  PASS;
649 }
650 
651 /**
652  * \test Parsing test no content
653  */
654 static int DetectReplaceParseTest04(void)
655 {
656  int run_mode_backup = SCRunmodeGet();
658 
661 
662  de_ctx->flags |= DE_QUIET;
663  FAIL_IF_NOT_NULL(DetectEngineAppendSig(de_ctx, "alert tcp any any -> any any "
664  "(msg:\"test\"; replace:\"don\"; sid:238012;)"));
665 
666  SCRunmodeSet(run_mode_backup);
668  PASS;
669 }
670 
671 /**
672  * \test Parsing test content after replace
673  */
674 static int DetectReplaceParseTest05(void)
675 {
676  int run_mode_backup = SCRunmodeGet();
678 
681 
682  de_ctx->flags |= DE_QUIET;
684  "alert tcp any any -> any any "
685  "(msg:\"test\"; replace:\"don\"; content:\"doh\"; sid:238012;)"));
686 
687  SCRunmodeSet(run_mode_backup);
689  PASS;
690 }
691 
692 /**
693  * \test Parsing test content and replace length differ
694  */
695 static int DetectReplaceParseTest06(void)
696 {
697  int run_mode_backup = SCRunmodeGet();
699 
702 
703  de_ctx->flags |= DE_QUIET;
705  "alert tcp any any -> any any "
706  "(msg:\"test\"; content:\"don\"; replace:\"donut\"; sid:238012;)"));
707 
708  SCRunmodeSet(run_mode_backup);
710  PASS;
711 }
712 
713 /**
714  * \test Parsing test content and replace length differ
715  */
716 static int DetectReplaceParseTest07(void)
717 {
718  int run_mode_backup = SCRunmodeGet();
720 
723 
724  de_ctx->flags |= DE_QUIET;
726  DetectEngineAppendSig(de_ctx, "alert tcp any any -> any any "
727  "(msg:\"test\"; content:\"don\"; replace:\"dou\"; "
728  "content:\"jpg\"; http_header; sid:238012;)"));
729 
730  SCRunmodeSet(run_mode_backup);
732  PASS;
733 }
734 
735 /**
736  * \brief this function registers unit tests for DetectContent
737  */
738 void DetectReplaceRegisterTests(void)
739 {
740 /* matching */
741  UtRegisterTest("DetectReplaceMatchTest01", DetectReplaceMatchTest01);
742  UtRegisterTest("DetectReplaceMatchTest02", DetectReplaceMatchTest02);
743  UtRegisterTest("DetectReplaceMatchTest03", DetectReplaceMatchTest03);
744  UtRegisterTest("DetectReplaceMatchTest04", DetectReplaceMatchTest04);
745  UtRegisterTest("DetectReplaceMatchTest05", DetectReplaceMatchTest05);
746  UtRegisterTest("DetectReplaceMatchTest06", DetectReplaceMatchTest06);
747  UtRegisterTest("DetectReplaceMatchTest07", DetectReplaceMatchTest07);
748  UtRegisterTest("DetectReplaceMatchTest08", DetectReplaceMatchTest08);
749  UtRegisterTest("DetectReplaceMatchTest09", DetectReplaceMatchTest09);
750  UtRegisterTest("DetectReplaceMatchTest10", DetectReplaceMatchTest10);
751  UtRegisterTest("DetectReplaceMatchTest11", DetectReplaceMatchTest11);
752  UtRegisterTest("DetectReplaceMatchTest12", DetectReplaceMatchTest12);
753  UtRegisterTest("DetectReplaceMatchTest13", DetectReplaceMatchTest13);
754  UtRegisterTest("DetectReplaceMatchTest14", DetectReplaceMatchTest14);
755  UtRegisterTest("DetectReplaceMatchTest15", DetectReplaceMatchTest15);
756 /* parsing */
757  UtRegisterTest("DetectReplaceParseTest01", DetectReplaceParseTest01);
758  UtRegisterTest("DetectReplaceParseTest02", DetectReplaceParseTest02);
759  UtRegisterTest("DetectReplaceParseTest03", DetectReplaceParseTest03);
760  UtRegisterTest("DetectReplaceParseTest04", DetectReplaceParseTest04);
761  UtRegisterTest("DetectReplaceParseTest05", DetectReplaceParseTest05);
762  UtRegisterTest("DetectReplaceParseTest06", DetectReplaceParseTest06);
763  UtRegisterTest("DetectReplaceParseTest07", DetectReplaceParseTest07);
764 }
765 #endif /* UNITTESTS */
SigTableElmt_::url
const char * url
Definition: detect.h:1461
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:817
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:1460
sigmatch_table
SigTableElmt * sigmatch_table
Definition: detect-parse.c:79
Signature_::sig_str
char * sig_str
Definition: detect.h:745
PacketCopyData
int PacketCopyData(Packet *p, const uint8_t *pktdata, uint32_t pktlen)
Copy data to Packet payload and set packet length.
Definition: decode.c:381
SigTableElmt_::name
const char * name
Definition: detect.h:1458
SignatureInitData_::smlists_tail
struct SigMatch_ * smlists_tail[DETECT_SM_LIST_MAX]
Definition: detect.h:644
DetectEnginePruneFreeList
void DetectEnginePruneFreeList(void)
Definition: detect-engine.c:4734
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
SigTableElmt_::flags
uint32_t flags
Definition: detect.h:1449
PKT_STREAM_MODIFIED
#define PKT_STREAM_MODIFIED
Definition: decode.h:1273
SCLogDebug
#define SCLogDebug(...)
Definition: util-debug.h:279
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:142
Packet_::flags
uint32_t flags
Definition: decode.h:544
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:818
ctx
struct Thresholds ctx
DetectEngineCtx_
main detection engine ctx
Definition: detect.h:933
DetectEngineCtxFree
void DetectEngineCtxFree(DetectEngineCtx *)
Free a DetectEngineCtx::
Definition: detect-engine.c:2634
DetectEngineAddToMaster
int DetectEngineAddToMaster(DetectEngineCtx *de_ctx)
Definition: detect-engine.c:4664
DE_QUIET
#define DE_QUIET
Definition: detect.h:330
DetectReplaceList_
Definition: detect.h:816
SigMatchSignatures
void SigMatchSignatures(ThreadVars *tv, DetectEngineCtx *de_ctx, DetectEngineThreadCtx *det_ctx, Packet *p)
wrapper for old tests
Definition: detect.c:2418
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:3447
SigTableElmt_::Setup
int(* Setup)(DetectEngineCtx *, Signature *, const char *)
Definition: detect.h:1440
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:287
DetectReplaceAddToList
DetectReplaceList * DetectReplaceAddToList(DetectReplaceList *replist, uint8_t *found, const DetectContentData *cd)
Definition: detect-replace.c:168
SIGMATCH_QUOTES_MANDATORY
#define SIGMATCH_QUOTES_MANDATORY
Definition: detect.h:1667
FlowInitConfig
void FlowInitConfig(bool quiet)
initialize the configuration
Definition: flow.c:549
DETECT_SM_LIST_POSTMATCH
@ DETECT_SM_LIST_POSTMATCH
Definition: detect.h:127
SCRunmodeGet
SCRunMode SCRunmodeGet(void)
Get the current run mode.
Definition: suricata.c:282
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:4724
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:1245
DetectReplaceList_::next
struct DetectReplaceList_ * next
Definition: detect.h:819
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:3364
PacketFree
void PacketFree(Packet *p)
Return a malloced packet.
Definition: decode.c:223
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:259
SigMatch_::ctx
SigMatchCtx * ctx
Definition: detect.h:359
BUG_ON
#define BUG_ON(x)
Definition: suricata-common.h:317
Signature_::flags
uint32_t flags
Definition: detect.h:669
Packet_
Definition: decode.h:501
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:965
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:1671
Signature_::init_data
SignatureInitData * init_data
Definition: detect.h:747
AppLayerGetCtxThread
AppLayerThreadCtx * AppLayerGetCtxThread(void)
Creates a new app layer thread context.
Definition: app-layer.c:1104
SignatureInitData_::negated
bool negated
Definition: detect.h:597
SigTableElmt_::Match
int(* Match)(DetectEngineThreadCtx *, Packet *, const Signature *, const SigMatchCtx *)
Definition: detect.h:1420
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:2194
dtv
DecodeThreadVars * dtv
Definition: fuzz_decodepcapfile.c:33
StatsThreadInit
void StatsThreadInit(StatsThreadContext *stats)
Definition: counters.c:1258
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:693
packet.h
DetectEngineThreadCtxDeinit
TmEcode DetectEngineThreadCtxDeinit(ThreadVars *tv, void *data)
Definition: detect-engine.c:3601
PacketGetFromAlloc
Packet * PacketGetFromAlloc(void)
Get a malloced packet.
Definition: decode.c:262
SCMalloc
#define SCMalloc(sz)
Definition: util-mem.h:47
SCLogError
#define SCLogError(...)
Macro used to log ERROR messages.
Definition: util-debug.h:271
SCFree
#define SCFree(p)
Definition: util-mem.h:61
DecodeThreadVars_
Structure to hold thread specific data for all decode modules.
Definition: decode.h:963
AppLayerDestroyCtxThread
void AppLayerDestroyCtxThread(AppLayerThreadCtx *app_tctx)
Destroys the context created by AppLayerGetCtxThread().
Definition: app-layer.c:1125
detect-parse.h
Signature_
Signature container.
Definition: detect.h:668
SigMatch_
a single match condition for a signature
Definition: detect.h:356
DetectEngineCtxInit
DetectEngineCtx * DetectEngineCtxInit(void)
Definition: detect-engine.c:2595
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:935
DetectEngineThreadCtx_::replist
DetectReplaceList * replist
Definition: detect.h:1351
DETECT_CONTENT_REPLACE
#define DETECT_CONTENT_REPLACE
Definition: detect-content.h:51
DetectReplaceExecuteInternal
void DetectReplaceExecuteInternal(Packet *p, DetectReplaceList *replist)
Definition: detect-replace.c:185
ThreadVars_::stats
StatsThreadContext stats
Definition: threadvars.h:121
StatsThreadCleanup
void StatsThreadCleanup(StatsThreadContext *stats)
Definition: counters.c:1354
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:1447
app-layer.h
SIG_FLAG_REQUIRE_PACKET
#define SIG_FLAG_REQUIRE_PACKET
Definition: detect.h:254