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