suricata
detect-replace.c
Go to the documentation of this file.
1 /* Copyright (C) 2011-2014 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 extern int run_mode;
34 
35 #include "decode.h"
36 
37 #include "detect.h"
38 #include "detect-parse.h"
39 #include "detect-content.h"
40 #include "detect-uricontent.h"
41 #include "detect-byte-extract.h"
42 #include "detect-replace.h"
43 #include "app-layer.h"
44 
45 #include "detect-engine-mpm.h"
46 #include "detect-engine.h"
47 #include "detect-engine-state.h"
48 
49 #include "util-checksum.h"
50 
51 #include "util-unittest.h"
52 #include "util-unittest-helper.h"
53 
54 #include "flow-var.h"
55 
56 #include "util-debug.h"
57 
58 #include "pkt-var.h"
59 #include "host.h"
60 #include "util-profiling.h"
61 
62 static int DetectReplaceSetup(DetectEngineCtx *, Signature *, const char *);
64 
66 {
67  sigmatch_table[DETECT_REPLACE].name = "replace";
69  sigmatch_table[DETECT_REPLACE].Setup = DetectReplaceSetup;
73 }
74 
75 int DetectReplaceSetup(DetectEngineCtx *de_ctx, Signature *s, const char *replacestr)
76 {
77  uint8_t *content = NULL;
78  uint16_t len = 0;
79 
80  if (s->init_data->negated) {
81  SCLogError(SC_ERR_INVALID_VALUE, "Can't negate replacement string: %s",
82  replacestr);
83  return -1;
84  }
85 
86  switch (run_mode) {
87  case RUNMODE_NFQ:
88  case RUNMODE_IPFW:
89  break;
90  default:
92  "Can't use 'replace' keyword in non IPS mode: %s",
93  s->sig_str);
94  /* this is a success, having the alert is interesting */
95  return 0;
96  }
97 
98  int ret = DetectContentDataParse("replace", replacestr, &content, &len);
99  if (ret == -1)
100  return -1;
101 
102  /* add to the latest "content" keyword from pmatch */
104  DETECT_CONTENT, -1);
105  if (pm == NULL) {
107  "preceding content option for raw sig");
108  SCFree(content);
109  return -1;
110  }
111 
112  /* we can remove this switch now with the unified structure */
114  if (ud == NULL) {
115  SCLogError(SC_ERR_INVALID_ARGUMENT, "invalid argument");
116  SCFree(content);
117  return -1;
118  }
119  if (ud->flags & DETECT_CONTENT_NEGATED) {
120  SCLogError(SC_ERR_INVALID_SIGNATURE, "can't have a relative "
121  "negated keyword set along with a replacement");
122  goto error;
123  }
124  if (ud->content_len != len) {
125  SCLogError(SC_ERR_INVALID_SIGNATURE, "can't have a content "
126  "length different from replace length");
127  goto error;
128  }
129 
130  ud->replace = SCMalloc(len);
131  if (ud->replace == NULL) {
132  goto error;
133  }
134  memcpy(ud->replace, content, len);
135  ud->replace_len = len;
137  /* want packet matching only won't be able to replace data with
138  * a flow.
139  */
141  SCFree(content);
142 
143  return 0;
144 
145 error:
146  SCFree(ud->replace);
147  ud->replace = NULL;
148  SCFree(content);
149  return -1;
150 }
151 
152 /* Add to the head of the replace-list.
153  *
154  * The first to add to the replace-list has the highest priority. So,
155  * adding the the head of the list results in the newest modifications
156  * of content being applied first, so later changes can over ride
157  * earlier changes. Thus the highest priority modifications should be
158  * applied last.
159  */
161  uint8_t *found,
162  DetectContentData *cd)
163 {
164  DetectReplaceList *newlist;
165 
166  if (cd->content_len != cd->replace_len)
167  return NULL;
168  SCLogDebug("replace: Adding match");
169 
170  newlist = SCMalloc(sizeof(DetectReplaceList));
171  if (unlikely(newlist == NULL))
172  return replist;
173  newlist->found = found;
174  newlist->cd = cd;
175  /* Push new value onto the front of the list. */
176  newlist->next = replist;
177 
178  return newlist;
179 }
180 
181 
183 {
184  DetectReplaceList *tlist = NULL;
185 
186  SCLogDebug("replace: Executing match");
187  while (replist) {
188  memcpy(replist->found, replist->cd->replace, replist->cd->replace_len);
189  SCLogDebug("replace: injecting '%s'", replist->cd->replace);
192  tlist = replist;
193  replist = replist->next;
194  SCFree(tlist);
195  }
196 }
197 
198 
200 {
201  DetectReplaceList *tlist = NULL;
202  while (replist) {
203  SCLogDebug("replace: Freeing match");
204  tlist = replist;
205  replist = replist->next;
206  SCFree(tlist);
207  }
208 }
209 
210 #ifdef UNITTESTS /* UNITTESTS */
211 
212 /**
213  * \test Test packet Matches
214  * \param raw_eth_pkt pointer to the ethernet packet
215  * \param pktsize size of the packet
216  * \param sig pointer to the signature to test
217  * \param sid sid number of the signature
218  * \retval return 1 if match
219  * \retval return 0 if not
220  */
221 static
222 int DetectReplaceLongPatternMatchTest(uint8_t *raw_eth_pkt, uint16_t pktsize,
223  const char *sig, uint32_t sid, uint8_t *pp,
224  uint16_t *len)
225 {
226  int result = 0;
227 
228  Packet *p = NULL;
229  p = PacketGetFromAlloc();
230  if (unlikely(p == NULL))
231  return 0;
232 
233  DecodeThreadVars dtv;
234 
235  ThreadVars th_v;
236  DetectEngineThreadCtx *det_ctx = NULL;
237 
238  if (pp == NULL) {
239  SCLogDebug("replace: looks like a second run");
240  }
241 
242  PacketCopyData(p, raw_eth_pkt, pktsize);
243  memset(&dtv, 0, sizeof(DecodeThreadVars));
244  memset(&th_v, 0, sizeof(th_v));
245  dtv.app_tctx = AppLayerGetCtxThread(&th_v);
246 
248  DecodeEthernet(&th_v, &dtv, p, GET_PKT_DATA(p), pktsize, NULL);
249 
251  if (de_ctx == NULL) {
252  goto end;
253  }
254  de_ctx->flags |= DE_QUIET;
255 
256  de_ctx->sig_list = SigInit(de_ctx, sig);
257  if (de_ctx->sig_list == NULL) {
258  goto end;
259  }
260  de_ctx->sig_list->next = NULL;
261 
262  if (de_ctx->sig_list->sm_lists_tail[DETECT_SM_LIST_PMATCH]->type == DETECT_CONTENT) {
263  DetectContentData *co = (DetectContentData *)de_ctx->sig_list->sm_lists_tail[DETECT_SM_LIST_PMATCH]->ctx;
265  printf("relative next flag set on final match which is content: ");
266  goto end;
267  }
268  }
269 
270  SigGroupBuild(de_ctx);
271  DetectEngineAddToMaster(de_ctx);
272  DetectEngineThreadCtxInit(&th_v, NULL, (void *)&det_ctx);
273 
274  SigMatchSignatures(&th_v, de_ctx, det_ctx, p);
276 
277  if (PacketAlertCheck(p, sid) != 1) {
278  SCLogDebug("replace: no alert on sig %d", sid);
279  goto end;
280  }
281 
282  if (pp) {
283  memcpy(pp, GET_PKT_DATA(p), GET_PKT_LEN(p));
284  *len = pktsize;
285  SCLogDebug("replace: copying %d on %p", *len, pp);
286  }
287 
288 
289  result = 1;
290 end:
291  if (dtv.app_tctx != NULL)
293  if (det_ctx != NULL)
294  DetectEngineThreadCtxDeinit(&th_v, (void *)det_ctx);
296  PACKET_RECYCLE(p);
297  FlowShutdown();
298  SCFree(p);
299 
300 
301  return result;
302 }
303 
304 
305 /**
306  * \brief Wrapper for DetectContentLongPatternMatchTest
307  */
308 static int DetectReplaceLongPatternMatchTestWrp(const char *sig, uint32_t sid, const char *sig_rep, uint32_t sid_rep)
309 {
310  int ret;
311  /** Real packet with the following tcp data:
312  * "Hi, this is a big test to check content matches of splitted"
313  * "patterns between multiple chunks!"
314  * (without quotes! :) )
315  */
316  uint8_t raw_eth_pkt[] = {
317  0xff,0xff,0xff,0xff,0xff,0xff,0x00,0x00,
318  0x00,0x00,0x00,0x00,0x08,0x00,0x45,0x00,
319  0x00,0x85,0x00,0x01,0x00,0x00,0x40,0x06,
320  0x7c,0x70,0x7f,0x00,0x00,0x01,0x7f,0x00,
321  0x00,0x01,0x00,0x14,0x00,0x50,0x00,0x00,
322  0x00,0x00,0x00,0x00,0x00,0x00,0x50,0x02,
323  0x20,0x00,0xc9,0xad,0x00,0x00,0x48,0x69,
324  0x2c,0x20,0x74,0x68,0x69,0x73,0x20,0x69,
325  0x73,0x20,0x61,0x20,0x62,0x69,0x67,0x20,
326  0x74,0x65,0x73,0x74,0x20,0x74,0x6f,0x20,
327  0x63,0x68,0x65,0x63,0x6b,0x20,0x63,0x6f,
328  0x6e,0x74,0x65,0x6e,0x74,0x20,0x6d,0x61,
329  0x74,0x63,0x68,0x65,0x73,0x20,0x6f,0x66,
330  0x20,0x73,0x70,0x6c,0x69,0x74,0x74,0x65,
331  0x64,0x20,0x70,0x61,0x74,0x74,0x65,0x72,
332  0x6e,0x73,0x20,0x62,0x65,0x74,0x77,0x65,
333  0x65,0x6e,0x20,0x6d,0x75,0x6c,0x74,0x69,
334  0x70,0x6c,0x65,0x20,0x63,0x68,0x75,0x6e,
335  0x6b,0x73,0x21 }; /* end raw_eth_pkt */
336  uint8_t p[sizeof(raw_eth_pkt)];
337  uint16_t psize = sizeof(raw_eth_pkt);
338 
339  /* would be unittest */
340  int run_mode_backup = run_mode;
342  ret = DetectReplaceLongPatternMatchTest(raw_eth_pkt, (uint16_t)sizeof(raw_eth_pkt),
343  sig, sid, p, &psize);
344  if (ret == 1) {
345  SCLogDebug("replace: test1 phase1");
346  ret = DetectReplaceLongPatternMatchTest(p, psize, sig_rep, sid_rep, NULL, NULL);
347  }
348  run_mode = run_mode_backup;
349  return ret;
350 }
351 
352 
353 /**
354  * \brief Wrapper for DetectContentLongPatternMatchTest
355  */
356 static int DetectReplaceLongPatternMatchTestUDPWrp(const char *sig, uint32_t sid, const char *sig_rep, uint32_t sid_rep)
357 {
358  int ret;
359  /** Real UDP DNS packet with a request A to a1.twimg.com
360  */
361  uint8_t raw_eth_pkt[] = {
362  0x8c, 0xa9, 0x82, 0x75, 0x5d, 0x62, 0xb4, 0x07,
363  0xf9, 0xf3, 0xc7, 0x0a, 0x08, 0x00, 0x45, 0x00,
364  0x00, 0x3a, 0x92, 0x4f, 0x40, 0x00, 0x40, 0x11,
365  0x31, 0x1a, 0xc0, 0xa8, 0x00, 0x02, 0xc1, 0xbd,
366  0xf4, 0xe1, 0x3b, 0x7e, 0x00, 0x35, 0x00, 0x26,
367  0xcb, 0x81, 0x37, 0x62, 0x01, 0x00, 0x00, 0x01,
368  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0x61,
369  0x31, 0x05, 0x74, 0x77, 0x69, 0x6d, 0x67, 0x03,
370  0x63, 0x6f, 0x6d, 0x00, 0x00, 0x01, 0x00, 0x01 };
371 
372  uint8_t p[sizeof(raw_eth_pkt)];
373  uint16_t psize = sizeof(raw_eth_pkt);
374 
375  int run_mode_backup = run_mode;
377  ret = DetectReplaceLongPatternMatchTest(raw_eth_pkt, (uint16_t)sizeof(raw_eth_pkt),
378  sig, sid, p, &psize);
379  if (ret == 1) {
380  SCLogDebug("replace: test1 phase1 ok: %" PRIuMAX" vs %d",(uintmax_t)sizeof(raw_eth_pkt),psize);
381  ret = DetectReplaceLongPatternMatchTest(p, psize, sig_rep, sid_rep, NULL, NULL);
382  }
383  run_mode = run_mode_backup;
384  return ret;
385 }
386 
387 /**
388  * \test Check if replace is working
389  */
390 static int DetectReplaceMatchTest01(void)
391 {
392  const char *sig = "alert tcp any any -> any any (msg:\"Nothing..\";"
393  " content:\"big\"; replace:\"pig\"; sid:1;)";
394  const char *sig_rep = "alert tcp any any -> any any (msg:\"replace worked\";"
395  " content:\"this is a pig test\"; sid:2;)";
396  return DetectReplaceLongPatternMatchTestWrp(sig, 1, sig_rep, 2);
397 }
398 
399 /**
400  * \test Check if replace is working with offset
401  */
402 static int DetectReplaceMatchTest02(void)
403 {
404  const char *sig = "alert tcp any any -> any any (msg:\"Nothing..\";"
405  " content:\"th\"; offset: 4; replace:\"TH\"; sid:1;)";
406  const char *sig_rep = "alert tcp any any -> any any (msg:\"replace worked\";"
407  " content:\"THis\"; offset:4; sid:2;)";
408  return DetectReplaceLongPatternMatchTestWrp(sig, 1, sig_rep, 2);
409 }
410 
411 /**
412  * \test Check if replace is working with offset and keyword inversion
413  */
414 static int DetectReplaceMatchTest03(void)
415 {
416  const char *sig = "alert tcp any any -> any any (msg:\"Nothing..\";"
417  " content:\"th\"; replace:\"TH\"; offset: 4; sid:1;)";
418  const char *sig_rep = "alert tcp any any -> any any (msg:\"replace worked\";"
419  " content:\"THis\"; offset:4; sid:2;)";
420  return DetectReplaceLongPatternMatchTestWrp(sig, 1, sig_rep, 2);
421 }
422 
423 /**
424  * \test Check if replace is working with second content
425  */
426 static int DetectReplaceMatchTest04(void)
427 {
428  const char *sig = "alert tcp any any -> any any (msg:\"Nothing..\";"
429  " content:\"th\"; replace:\"TH\"; content:\"patter\"; replace:\"matter\"; sid:1;)";
430  const char *sig_rep = "alert tcp any any -> any any (msg:\"replace worked\";"
431  " content:\"THis\"; content:\"matterns\"; sid:2;)";
432  return DetectReplaceLongPatternMatchTestWrp(sig, 1, sig_rep, 2);
433 }
434 
435 /**
436  * \test Check if replace is not done when second content don't match
437  */
438 static int DetectReplaceMatchTest05(void)
439 {
440  const char *sig = "alert tcp any any -> any any (msg:\"Nothing..\";"
441  " content:\"th\"; replace:\"TH\"; content:\"nutella\"; sid:1;)";
442  const char *sig_rep = "alert tcp any any -> any any (msg:\"replace worked\";"
443  " content:\"TH\"; sid:2;)";
444  return !DetectReplaceLongPatternMatchTestWrp(sig, 1, sig_rep, 2);
445 }
446 
447 /**
448  * \test Check if replace is not done when second content match and not
449  * first
450  */
451 static int DetectReplaceMatchTest06(void)
452 {
453  const char *sig = "alert tcp any any -> any any (msg:\"Nothing..\";"
454  " content:\"nutella\"; replace:\"commode\"; content:\"this is\"; sid:1;)";
455  const char *sig_rep = "alert tcp any any -> any any (msg:\"replace worked\";"
456  " content:\"commode\"; sid:2;)";
457  return !DetectReplaceLongPatternMatchTestWrp(sig, 1, sig_rep, 2);
458 }
459 
460 /**
461  * \test Check if replace is working when nocase used
462  */
463 static int DetectReplaceMatchTest07(void)
464 {
465  const char *sig = "alert tcp any any -> any any (msg:\"Nothing..\";"
466  " content:\"BiG\"; nocase; replace:\"pig\"; sid:1;)";
467  const char *sig_rep = "alert tcp any any -> any any (msg:\"replace worked\";"
468  " content:\"this is a pig test\"; sid:2;)";
469  return DetectReplaceLongPatternMatchTestWrp(sig, 1, sig_rep, 2);
470 }
471 
472 /**
473  * \test Check if replace is working when depth is used
474  */
475 static int DetectReplaceMatchTest08(void)
476 {
477  const char *sig = "alert tcp any any -> any any (msg:\"Nothing..\";"
478  " content:\"big\"; depth:17; replace:\"pig\"; sid:1;)";
479  const char *sig_rep = "alert tcp any any -> any any (msg:\"replace worked\";"
480  " content:\"this is a pig test\"; sid:2;)";
481  return DetectReplaceLongPatternMatchTestWrp(sig, 1, sig_rep, 2);
482 }
483 
484 /**
485  * \test Check if replace is working when depth block match used
486  */
487 static int DetectReplaceMatchTest09(void)
488 {
489  const char *sig = "alert tcp any any -> any any (msg:\"Nothing..\";"
490  " content:\"big\"; depth:16; replace:\"pig\"; sid:1;)";
491  const char *sig_rep = "alert tcp any any -> any any (msg:\"replace worked\";"
492  " content:\"this is a pig test\"; sid:2;)";
493  return !DetectReplaceLongPatternMatchTestWrp(sig, 1, sig_rep, 2);
494 }
495 
496 /**
497  * \test Check if replace is working when depth block match used
498  */
499 static int DetectReplaceMatchTest10(void)
500 {
501  const char *sig = "alert tcp any any -> any any (msg:\"Nothing..\";"
502  " content:\"big\"; depth:17; replace:\"pig\"; offset: 14; sid:1;)";
503  const char *sig_rep = "alert tcp any any -> any any (msg:\"replace worked\";"
504  " content:\"pig\"; depth:17; offset:14; sid:2;)";
505  return DetectReplaceLongPatternMatchTestWrp(sig, 1, sig_rep, 2);
506 }
507 
508 /**
509  * \test Check if replace is working with within
510  */
511 static int DetectReplaceMatchTest11(void)
512 {
513  const char *sig = "alert tcp any any -> any any (msg:\"Nothing..\";"
514  " content:\"big\"; replace:\"pig\"; content:\"to\"; within: 11; sid:1;)";
515  const char *sig_rep = "alert tcp any any -> any any (msg:\"replace worked\";"
516  " content:\"pig\"; depth:17; offset:14; sid:2;)";
517  return DetectReplaceLongPatternMatchTestWrp(sig, 1, sig_rep, 2);
518 }
519 
520 /**
521  * \test Check if replace is working with within
522  */
523 static int DetectReplaceMatchTest12(void)
524 {
525  const char *sig = "alert tcp any any -> any any (msg:\"Nothing..\";"
526  " content:\"big\"; replace:\"pig\"; content:\"to\"; within: 4; sid:1;)";
527  const char *sig_rep = "alert tcp any any -> any any (msg:\"replace worked\";"
528  " content:\"pig\"; depth:17; offset:14; sid:2;)";
529  return !DetectReplaceLongPatternMatchTestWrp(sig, 1, sig_rep, 2);
530 }
531 
532 /**
533  * \test Check if replace is working with within
534  */
535 static int DetectReplaceMatchTest13(void)
536 {
537  const char *sig = "alert tcp any any -> any any (msg:\"Nothing..\";"
538  " content:\"big\"; replace:\"pig\"; content:\"test\"; distance: 1; sid:1;)";
539  const char *sig_rep = "alert tcp any any -> any any (msg:\"replace worked\";"
540  " content:\"pig\"; depth:17; offset:14; sid:2;)";
541  return DetectReplaceLongPatternMatchTestWrp(sig, 1, sig_rep, 2);
542 }
543 
544 /**
545  * \test Check if replace is working with within
546  */
547 static int DetectReplaceMatchTest14(void)
548 {
549  const char *sig = "alert tcp any any -> any any (msg:\"Nothing..\";"
550  " content:\"big\"; replace:\"pig\"; content:\"test\"; distance: 2; sid:1;)";
551  const char *sig_rep = "alert tcp any any -> any any (msg:\"replace worked\";"
552  " content:\"pig\"; depth:17; offset:14; sid:2;)";
553  return !DetectReplaceLongPatternMatchTestWrp(sig, 1, sig_rep, 2);
554 }
555 
556 /**
557  * \test Check if replace is working with within
558  */
559 static int DetectReplaceMatchTest15(void)
560 {
561  const char *sig = "alert udp any any -> any any (msg:\"Nothing..\";"
562  " content:\"com\"; replace:\"org\"; sid:1;)";
563  const char *sig_rep = "alert udp any any -> any any (msg:\"replace worked\";"
564  " content:\"twimg|03|org\"; sid:2;)";
565  return DetectReplaceLongPatternMatchTestUDPWrp(sig, 1, sig_rep, 2);
566 }
567 
568 
569 /**
570  * \test Parsing test
571  */
572 static int DetectReplaceParseTest01(void)
573 {
574  int run_mode_backup = run_mode;
576 
577  DetectEngineCtx *de_ctx = NULL;
578  int result = 1;
579 
580  de_ctx = DetectEngineCtxInit();
581  if (de_ctx == NULL)
582  goto end;
583 
584  de_ctx->flags |= DE_QUIET;
585  de_ctx->sig_list = SigInit(de_ctx,
586  "alert udp any any -> any any "
587  "(msg:\"test\"; content:\"doh\"; replace:\"; sid:238012;)");
588  if (de_ctx->sig_list != NULL) {
589  result = 0;
590  goto end;
591  }
592 
593  end:
594  run_mode = run_mode_backup;
595 
596  SigGroupCleanup(de_ctx);
597  SigCleanSignatures(de_ctx);
598  DetectEngineCtxFree(de_ctx);
599 
600  return result;
601 }
602 
603 /**
604  * \test Parsing test: non valid because of http protocol
605  */
606 static int DetectReplaceParseTest02(void)
607 {
608  int run_mode_backup = run_mode;
610 
611  DetectEngineCtx *de_ctx = NULL;
612  int result = 1;
613 
614  de_ctx = DetectEngineCtxInit();
615  if (de_ctx == NULL)
616  goto end;
617 
618  de_ctx->flags |= DE_QUIET;
619  de_ctx->sig_list = SigInit(de_ctx,
620  "alert http any any -> any any "
621  "(msg:\"test\"; content:\"doh\"; replace:\"bon\"; sid:238012;)");
622  if (de_ctx->sig_list == NULL) {
623  result = 0;
624  goto end;
625  }
626 
627  end:
628  run_mode = run_mode_backup;
629 
630  SigGroupCleanup(de_ctx);
631  SigCleanSignatures(de_ctx);
632  DetectEngineCtxFree(de_ctx);
633 
634  return result;
635 }
636 
637 /**
638  * \test Parsing test: non valid because of http_header on same content
639  * as replace keyword
640  */
641 static int DetectReplaceParseTest03(void)
642 {
643  int run_mode_backup = run_mode;
645 
646  DetectEngineCtx *de_ctx = NULL;
647  int result = 1;
648 
649  de_ctx = DetectEngineCtxInit();
650  if (de_ctx == NULL)
651  goto end;
652 
653  de_ctx->flags |= DE_QUIET;
654  de_ctx->sig_list = SigInit(de_ctx,
655  "alert tcp any any -> any any "
656  "(msg:\"test\"; content:\"doh\"; replace:\"don\"; http_header; sid:238012;)");
657  if (de_ctx->sig_list != NULL) {
658  result = 0;
659  goto end;
660  }
661 
662  end:
663  run_mode = run_mode_backup;
664 
665  SigGroupCleanup(de_ctx);
666  SigCleanSignatures(de_ctx);
667  DetectEngineCtxFree(de_ctx);
668 
669  return result;
670 }
671 
672 /**
673  * \test Parsing test no content
674  */
675 static int DetectReplaceParseTest04(void)
676 {
677  int run_mode_backup = run_mode;
679 
680  DetectEngineCtx *de_ctx = NULL;
681  int result = 1;
682 
683  de_ctx = DetectEngineCtxInit();
684  if (de_ctx == NULL)
685  goto end;
686 
687  de_ctx->flags |= DE_QUIET;
688  de_ctx->sig_list = SigInit(de_ctx,
689  "alert tcp any any -> any any "
690  "(msg:\"test\"; replace:\"don\"; sid:238012;)");
691  if (de_ctx->sig_list != NULL) {
692  result = 0;
693  goto end;
694  }
695 
696  end:
697  run_mode = run_mode_backup;
698 
699  SigGroupCleanup(de_ctx);
700  SigCleanSignatures(de_ctx);
701  DetectEngineCtxFree(de_ctx);
702 
703  return result;
704 }
705 
706 /**
707  * \test Parsing test content after replace
708  */
709 static int DetectReplaceParseTest05(void)
710 {
711  int run_mode_backup = run_mode;
713 
714  DetectEngineCtx *de_ctx = NULL;
715  int result = 1;
716 
717  de_ctx = DetectEngineCtxInit();
718  if (de_ctx == NULL)
719  goto end;
720 
721  de_ctx->flags |= DE_QUIET;
722  de_ctx->sig_list = SigInit(de_ctx,
723  "alert tcp any any -> any any "
724  "(msg:\"test\"; replace:\"don\"; content:\"doh\"; sid:238012;)");
725  if (de_ctx->sig_list != NULL) {
726  result = 0;
727  goto end;
728  }
729 
730  end:
731  run_mode = run_mode_backup;
732 
733  SigGroupCleanup(de_ctx);
734  SigCleanSignatures(de_ctx);
735  DetectEngineCtxFree(de_ctx);
736 
737  return result;
738 }
739 
740 /**
741  * \test Parsing test content and replace length differ
742  */
743 static int DetectReplaceParseTest06(void)
744 {
745  int run_mode_backup = run_mode;
747 
748  DetectEngineCtx *de_ctx = NULL;
749  int result = 1;
750 
751  de_ctx = DetectEngineCtxInit();
752  if (de_ctx == NULL)
753  goto end;
754 
755  de_ctx->flags |= DE_QUIET;
756  de_ctx->sig_list = SigInit(de_ctx,
757  "alert tcp any any -> any any "
758  "(msg:\"test\"; content:\"don\"; replace:\"donut\"; sid:238012;)");
759  if (de_ctx->sig_list != NULL) {
760  result = 0;
761  goto end;
762  }
763 
764  end:
765  run_mode = run_mode_backup;
766 
767  SigGroupCleanup(de_ctx);
768  SigCleanSignatures(de_ctx);
769  DetectEngineCtxFree(de_ctx);
770 
771  return result;
772 }
773 
774 /**
775  * \test Parsing test content and replace length differ
776  */
777 static int DetectReplaceParseTest07(void)
778 {
779  int run_mode_backup = run_mode;
781 
782  DetectEngineCtx *de_ctx = NULL;
783  int result = 1;
784 
785  de_ctx = DetectEngineCtxInit();
786  if (de_ctx == NULL)
787  goto end;
788 
789  de_ctx->flags |= DE_QUIET;
790  de_ctx->sig_list = SigInit(de_ctx,
791  "alert tcp any any -> any any "
792  "(msg:\"test\"; content:\"don\"; replace:\"dou\"; content:\"jpg\"; http_header; sid:238012;)");
793  if (de_ctx->sig_list != NULL) {
794  result = 0;
795  goto end;
796  }
797 
798  end:
799  run_mode = run_mode_backup;
800 
801  SigGroupCleanup(de_ctx);
802  SigCleanSignatures(de_ctx);
803  DetectEngineCtxFree(de_ctx);
804 
805  return result;
806 }
807 
808 
809 
810 #endif /* UNITTESTS */
811 
812 /**
813  * \brief this function registers unit tests for DetectContent
814  */
816 {
817 #ifdef UNITTESTS /* UNITTESTS */
818 /* matching */
819  UtRegisterTest("DetectReplaceMatchTest01", DetectReplaceMatchTest01);
820  UtRegisterTest("DetectReplaceMatchTest02", DetectReplaceMatchTest02);
821  UtRegisterTest("DetectReplaceMatchTest03", DetectReplaceMatchTest03);
822  UtRegisterTest("DetectReplaceMatchTest04", DetectReplaceMatchTest04);
823  UtRegisterTest("DetectReplaceMatchTest05", DetectReplaceMatchTest05);
824  UtRegisterTest("DetectReplaceMatchTest06", DetectReplaceMatchTest06);
825  UtRegisterTest("DetectReplaceMatchTest07", DetectReplaceMatchTest07);
826  UtRegisterTest("DetectReplaceMatchTest08", DetectReplaceMatchTest08);
827  UtRegisterTest("DetectReplaceMatchTest09", DetectReplaceMatchTest09);
828  UtRegisterTest("DetectReplaceMatchTest10", DetectReplaceMatchTest10);
829  UtRegisterTest("DetectReplaceMatchTest11", DetectReplaceMatchTest11);
830  UtRegisterTest("DetectReplaceMatchTest12", DetectReplaceMatchTest12);
831  UtRegisterTest("DetectReplaceMatchTest13", DetectReplaceMatchTest13);
832  UtRegisterTest("DetectReplaceMatchTest14", DetectReplaceMatchTest14);
833  UtRegisterTest("DetectReplaceMatchTest15", DetectReplaceMatchTest15);
834 /* parsing */
835  UtRegisterTest("DetectReplaceParseTest01", DetectReplaceParseTest01);
836  UtRegisterTest("DetectReplaceParseTest02", DetectReplaceParseTest02);
837  UtRegisterTest("DetectReplaceParseTest03", DetectReplaceParseTest03);
838  UtRegisterTest("DetectReplaceParseTest04", DetectReplaceParseTest04);
839  UtRegisterTest("DetectReplaceParseTest05", DetectReplaceParseTest05);
840  UtRegisterTest("DetectReplaceParseTest06", DetectReplaceParseTest06);
841  UtRegisterTest("DetectReplaceParseTest07", DetectReplaceParseTest07);
842 #endif /* UNITTESTS */
843 }
SigTableElmt sigmatch_table[DETECT_TBLSIZE]
Definition: detect.h:1403
SignatureInitData * init_data
Definition: detect.h:560
int(* Setup)(DetectEngineCtx *, Signature *, const char *)
Definition: detect.h:1146
#define SCLogDebug(...)
Definition: util-debug.h:335
void DetectEnginePruneFreeList(void)
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:473
int PacketAlertCheck(Packet *p, uint32_t sid)
Check if a certain sid alerted, this is used in the test functions.
uint32_t flags
Definition: detect.h:493
void DetectReplaceFreeInternal(DetectReplaceList *replist)
#define unlikely(expr)
Definition: util-optimize.h:35
Signature * SigInit(DetectEngineCtx *, const char *)
Parses a signature and adds it to the Detection Engine Context.
Signature * sig_list
Definition: detect.h:726
int DetectContentDataParse(const char *keyword, const char *contentstr, uint8_t **pstr, uint16_t *plen)
Parse a content string, ie "abc|DE|fgh".
#define FLOW_QUIET
Definition: flow.h:37
void SigCleanSignatures(DetectEngineCtx *de_ctx)
#define PACKET_RECYCLE(p)
Definition: decode.h:827
#define SIG_FLAG_REQUIRE_PACKET
Definition: detect.h:230
TmEcode DetectEngineThreadCtxInit(ThreadVars *, void *, void **)
initialize thread specific detection engine context
const char * name
Definition: detect.h:1160
int DetectEngineAddToMaster(DetectEngineCtx *de_ctx)
Signature container.
Definition: detect.h:492
DetectReplaceList * DetectReplaceAddToList(DetectReplaceList *replist, uint8_t *found, DetectContentData *cd)
main detection engine ctx
Definition: detect.h:720
TmEcode DetectEngineThreadCtxDeinit(ThreadVars *, void *)
#define DE_QUIET
Definition: detect.h:298
void DetectReplaceRegisterTests(void)
this function registers unit tests for DetectContent
AppLayerThreadCtx * AppLayerGetCtxThread(ThreadVars *tv)
Creates a new app layer thread context.
Definition: app-layer.c:783
uint8_t flags
Definition: detect.h:721
Data structures and function prototypes for keeping state for the detection engine.
void(* Free)(void *)
Definition: detect.h:1151
int DecodeEthernet(ThreadVars *tv, DecodeThreadVars *dtv, Packet *p, uint8_t *pkt, uint32_t len, PacketQueue *pq)
int DetectEngineMoveToFreeList(DetectEngineCtx *de_ctx)
#define SCLogError(err_code,...)
Macro used to log ERROR messages.
Definition: util-debug.h:294
AppLayerThreadCtx * app_tctx
Definition: decode.h:645
int SigGroupBuild(DetectEngineCtx *de_ctx)
Convert the signature list into the runtime match structure.
void UtRegisterTest(const char *name, int(*TestFn)(void))
Register unit test.
#define PKT_STREAM_MODIFIED
Definition: decode.h:1103
Structure to hold thread specific data for all decode modules.
Definition: decode.h:642
void SigMatchSignatures(ThreadVars *th_v, DetectEngineCtx *de_ctx, DetectEngineThreadCtx *det_ctx, Packet *p)
wrapper for old tests
Definition: detect.c:1752
#define SIGMATCH_QUOTES_MANDATORY
Definition: detect.h:1344
void DetectReplaceExecuteInternal(Packet *p, DetectReplaceList *replist)
uint8_t * found
Definition: detect.h:602
int ReCalculateChecksum(Packet *p)
Definition: util-checksum.c:30
int SigGroupCleanup(DetectEngineCtx *de_ctx)
void DetectReplaceRegister(void)
struct Signature_ * next
Definition: detect.h:563
#define SCLogWarning(err_code,...)
Macro used to log WARNING messages.
Definition: util-debug.h:281
SigMatchCtx * ctx
Definition: detect.h:327
#define SCMalloc(a)
Definition: util-mem.h:174
#define DETECT_CONTENT_NEGATED
char * sig_str
Definition: detect.h:558
#define SCFree(a)
Definition: util-mem.h:236
#define DETECT_CONTENT_REPLACE
void AppLayerDestroyCtxThread(AppLayerThreadCtx *app_tctx)
Destroys the context created by AppLayeGetCtxThread().
Definition: app-layer.c:805
void FlowShutdown(void)
shutdown the flow engine
Definition: flow.c:599
int(* Match)(ThreadVars *, DetectEngineThreadCtx *, Packet *, const Signature *, const SigMatchCtx *)
Definition: detect.h:1129
struct DetectContentData_ * cd
Definition: detect.h:601
#define GET_PKT_DATA(p)
Definition: decode.h:224
int run_mode
Definition: suricata.c:204
#define DETECT_CONTENT_RELATIVE_NEXT
uint8_t len
Per thread variable structure.
Definition: threadvars.h:57
#define GET_PKT_LEN(p)
Definition: decode.h:223
uint32_t flags
Definition: decode.h:442
#define SIGMATCH_HANDLE_NEGATION
Definition: detect.h:1348
struct DetectReplaceList_ * next
Definition: detect.h:603
uint16_t flags
Definition: detect.h:1154
void DetectEngineCtxFree(DetectEngineCtx *)
Free a DetectEngineCtx::
int PacketCopyData(Packet *p, uint8_t *pktdata, uint32_t pktlen)
Copy data to Packet payload and set packet length.
Definition: decode.c:258
void(* RegisterTests)(void)
Definition: detect.h:1152
a single match condition for a signature
Definition: detect.h:324
Packet * PacketGetFromAlloc(void)
Get a malloced packet.
Definition: decode.c:140
DetectEngineCtx * DetectEngineCtxInit(void)
void FlowInitConfig(char quiet)
initialize the configuration
Definition: flow.c:444