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