suricata
detect-isdataat.c
Go to the documentation of this file.
1/* Copyright (C) 2007-2020 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 Pablo Rincon <pablo.rincon.crespo@gmail.com>
22 *
23 * Implements isdataat keyword
24 */
25
26#include "suricata-common.h"
27#include "decode.h"
28#include "detect.h"
29#include "detect-engine.h"
31#include "detect-parse.h"
32#include "app-layer.h"
33
34#include "util-unittest.h"
36
37#include "detect-isdataat.h"
38#include "detect-content.h"
39#include "detect-bytetest.h"
40#include "detect-uricontent.h"
41#include "detect-engine-build.h"
42
43#include "flow.h"
44#include "flow-var.h"
45
46#include "util-debug.h"
47#include "util-byte.h"
48#include "detect-pcre.h"
49#include "detect-byte.h"
50
51/**
52 * \brief Regex for parsing our isdataat options
53 */
54#define PARSE_REGEX "^\\s*!?([^\\s,]+)\\s*(,\\s*relative)?\\s*(,\\s*rawbytes\\s*)?\\s*$"
55
56static DetectParseRegex parse_regex;
57
58int DetectIsdataatSetup (DetectEngineCtx *, Signature *, const char *);
59#ifdef UNITTESTS
60static void DetectIsdataatRegisterTests(void);
61static void DetectAbsentRegisterTests(void);
62#endif
64
65static int DetectEndsWithSetup (DetectEngineCtx *de_ctx, Signature *s, const char *nullstr);
66
67static void DetectAbsentFree(DetectEngineCtx *de_ctx, void *ptr)
68{
69 SCFree(ptr);
70}
71
72static int DetectAbsentSetup(DetectEngineCtx *de_ctx, Signature *s, const char *optstr)
73{
75 SCLogError("no buffer for absent keyword");
76 return -1;
77 }
78
80 return -1;
81
82 bool or_else;
83 if (optstr == NULL) {
84 or_else = false;
85 } else if (strcmp(optstr, "or_else") == 0) {
86 or_else = true;
87 } else {
88 SCLogError("unhandled value for absent keyword: %s", optstr);
89 return -1;
90 }
91 if (s->init_data->curbuf == NULL || s->init_data->list != (int)s->init_data->curbuf->id) {
92 SCLogError("unspected buffer for absent keyword");
93 return -1;
94 }
96 if (!b || b->frame) {
97 SCLogError("absent does not work with frames");
98 return -1;
99 }
100 if (s->init_data->curbuf->tail != NULL) {
101 SCLogError("absent must come first right after buffer");
102 return -1;
103 }
105 if (unlikely(dad == NULL))
106 return -1;
107
108 dad->or_else = or_else;
109
111 de_ctx, s, DETECT_ABSENT, (SigMatchCtx *)dad, s->init_data->list) == NULL) {
112 DetectAbsentFree(de_ctx, dad);
113 return -1;
114 }
115 return 0;
116}
117
119{
120 bool has_other = false;
121 bool only_absent = false;
122 bool has_absent = false;
123 for (const SigMatch *sm = b->head; sm != NULL; sm = sm->next) {
124 if (sm->type == DETECT_ABSENT) {
125 has_absent = true;
126 const DetectAbsentData *dad = (const DetectAbsentData *)sm->ctx;
127 if (!dad->or_else) {
128 only_absent = true;
129 }
130 } else {
131 has_other = true;
132 if (sm->type == DETECT_CONTENT) {
133 const DetectContentData *cd = (DetectContentData *)sm->ctx;
134 if (has_absent && (cd->flags & DETECT_CONTENT_FAST_PATTERN)) {
135 SCLogError("signature can't have absent and fast_pattern on the same buffer");
136 return false;
137 }
138 }
139 }
140 }
141
142 if (only_absent && has_other) {
143 SCLogError("signature can't have a buffer tested absent and tested with other keywords "
144 "such as content");
145 return false;
146 } else if (has_absent && !only_absent && !has_other) {
148 "signature with absent: or_else expects other keywords to test on such as content");
149 return false;
150 }
151 return true;
152}
153
154/**
155 * \brief Registration function for isdataat: keyword
156 */
158{
159 sigmatch_table[DETECT_ISDATAAT].name = "isdataat";
160 sigmatch_table[DETECT_ISDATAAT].desc = "check if there is still data at a specific part of the payload";
161 sigmatch_table[DETECT_ISDATAAT].url = "/rules/payload-keywords.html#isdataat";
162 /* match is handled in DetectEngineContentInspection() */
166#ifdef UNITTESTS
167 sigmatch_table[DETECT_ISDATAAT].RegisterTests = DetectIsdataatRegisterTests;
168#endif
170 sigmatch_table[DETECT_ENDS_WITH].desc = "make sure the previous content matches exactly at the end of the buffer";
171 sigmatch_table[DETECT_ENDS_WITH].url = "/rules/payload-keywords.html#endswith";
172 sigmatch_table[DETECT_ENDS_WITH].Setup = DetectEndsWithSetup;
174
176 sigmatch_table[DETECT_ABSENT].desc = "test if the buffer is absent";
177 sigmatch_table[DETECT_ABSENT].url = "/rules/payload-keywords.html#absent";
178 sigmatch_table[DETECT_ABSENT].Setup = DetectAbsentSetup;
179 sigmatch_table[DETECT_ABSENT].Free = DetectAbsentFree;
181#ifdef UNITTESTS
182 sigmatch_table[DETECT_ABSENT].RegisterTests = DetectAbsentRegisterTests;
183#endif
184
186}
187
188/**
189 * \brief This function is used to parse isdataat options passed via isdataat: keyword
190 *
191 * \param de_ctx Pointer to the detection engine context
192 * \param isdataatstr Pointer to the user provided isdataat options
193 *
194 * \retval idad pointer to DetectIsdataatData on success
195 * \retval NULL on failure
196 */
197static DetectIsdataatData *DetectIsdataatParse (DetectEngineCtx *de_ctx, const char *isdataatstr, char **offset)
198{
199 DetectIsdataatData *idad = NULL;
200 char *args[3] = {NULL,NULL,NULL};
201 int res = 0;
202 size_t pcre2_len;
203 int i=0;
204
205 pcre2_match_data *match = NULL;
206 int ret = DetectParsePcreExec(&parse_regex, &match, isdataatstr, 0, 0);
207 if (ret < 1 || ret > 4) {
208 SCLogError("pcre_exec parse error, ret %" PRId32 ", string %s", ret, isdataatstr);
209 goto error;
210 }
211
212 if (ret > 1) {
213 const char *str_ptr;
214 res = pcre2_substring_get_bynumber(match, 1, (PCRE2_UCHAR8 **)&str_ptr, &pcre2_len);
215 if (res < 0) {
216 SCLogError("pcre2_substring_get_bynumber failed");
217 goto error;
218 }
219 args[0] = (char *)str_ptr;
220
221
222 if (ret > 2) {
223 res = pcre2_substring_get_bynumber(match, 2, (PCRE2_UCHAR8 **)&str_ptr, &pcre2_len);
224 if (res < 0) {
225 SCLogError("pcre2_substring_get_bynumber failed");
226 goto error;
227 }
228 args[1] = (char *)str_ptr;
229 }
230 if (ret > 3) {
231 res = pcre2_substring_get_bynumber(match, 3, (PCRE2_UCHAR8 **)&str_ptr, &pcre2_len);
232 if (res < 0) {
233 SCLogError("pcre2_substring_get_bynumber failed");
234 goto error;
235 }
236 args[2] = (char *)str_ptr;
237 }
238
239 idad = SCMalloc(sizeof(DetectIsdataatData));
240 if (unlikely(idad == NULL))
241 goto error;
242
243 idad->flags = 0;
244 idad->dataat = 0;
245
246 if (args[0][0] != '-' && isalpha((unsigned char)args[0][0])) {
247 if (offset == NULL) {
248 SCLogError("isdataat supplied with "
249 "var name for offset. \"offset\" argument supplied to "
250 "this function has to be non-NULL");
251 goto error;
252 }
253 *offset = SCStrdup(args[0]);
254 if (*offset == NULL)
255 goto error;
256 } else {
257 if (StringParseUint16(&idad->dataat, 10,
258 strlen(args[0]), args[0]) < 0 ) {
259 SCLogError("isdataat out of range");
260 SCFree(idad);
261 idad = NULL;
262 goto error;
263 }
264 }
265
266 if (args[1] !=NULL) {
267 idad->flags |= ISDATAAT_RELATIVE;
268
269 if(args[2] !=NULL)
270 idad->flags |= ISDATAAT_RAWBYTES;
271 }
272
273 if (isdataatstr[0] == '!') {
274 idad->flags |= ISDATAAT_NEGATED;
275 }
276
277 for (i = 0; i < (ret -1); i++) {
278 if (args[i] != NULL)
279 pcre2_substring_free((PCRE2_UCHAR8 *)args[i]);
280 }
281
282 pcre2_match_data_free(match);
283 return idad;
284
285 }
286
287error:
288 if (match) {
289 pcre2_match_data_free(match);
290 }
291 for (i = 0; i < (ret -1) && i < 3; i++){
292 if (args[i] != NULL)
293 pcre2_substring_free((PCRE2_UCHAR8 *)args[i]);
294 }
295
296 if (idad != NULL)
298 return NULL;
299
300}
301
302/**
303 * \brief This function is used to add the parsed isdataatdata into the current
304 * signature.
305 * \param de_ctx pointer to the Detection Engine Context
306 * \param s pointer to the Current Signature
307 * \param isdataatstr pointer to the user provided isdataat options
308 *
309 * \retval 0 on Success
310 * \retval -1 on Failure
311 */
312int DetectIsdataatSetup (DetectEngineCtx *de_ctx, Signature *s, const char *isdataatstr)
313{
314 SigMatch *prev_pm = NULL;
315 DetectIsdataatData *idad = NULL;
316 char *offset = NULL;
317 int ret = -1;
318
319 idad = DetectIsdataatParse(de_ctx, isdataatstr, &offset);
320 if (idad == NULL)
321 return -1;
322
323 int sm_list;
325 if (DetectBufferGetActiveList(de_ctx, s) == -1)
326 goto end;
327 sm_list = s->init_data->list;
328
329 if (idad->flags & ISDATAAT_RELATIVE) {
331 }
332 } else if (idad->flags & ISDATAAT_RELATIVE) {
333 prev_pm = DetectGetLastSMFromLists(s,
337 if (prev_pm == NULL)
338 sm_list = DETECT_SM_LIST_PMATCH;
339 else {
340 sm_list = SigMatchListSMBelongsTo(s, prev_pm);
341 if (sm_list < 0)
342 goto end;
343 }
344 } else {
345 sm_list = DETECT_SM_LIST_PMATCH;
346 }
347
348 if (offset != NULL) {
350 if (!DetectByteRetrieveSMVar(offset, s, -1, &index)) {
351 SCLogError("Unknown byte_extract var "
352 "seen in isdataat - %s\n",
353 offset);
354 goto end;
355 }
356 idad->dataat = index;
357 idad->flags |= ISDATAAT_OFFSET_VAR;
358 SCLogDebug("isdataat uses byte_extract with local id %u", idad->dataat);
359 SCFree(offset);
360 offset = NULL;
361 }
362
363 /* 'ends with' scenario */
364 if (prev_pm != NULL && prev_pm->type == DETECT_CONTENT &&
365 idad->dataat == 1 &&
367 {
369 DetectContentData *cd = (DetectContentData *)prev_pm->ctx;
371 ret = 0;
372 goto end;
373 }
374
375 if (SCSigMatchAppendSMToList(de_ctx, s, DETECT_ISDATAAT, (SigMatchCtx *)idad, sm_list) ==
376 NULL) {
377 goto end;
378 }
379
380 if (!(idad->flags & ISDATAAT_RELATIVE)) {
381 ret = 0;
382 goto end;
383 }
384
385 if (prev_pm == NULL) {
386 ret = 0;
387 goto end;
388 }
389
390 if (prev_pm->type == DETECT_CONTENT) {
391 DetectContentData *cd = (DetectContentData *)prev_pm->ctx;
393 } else if (prev_pm->type == DETECT_PCRE) {
394 DetectPcreData *pd = (DetectPcreData *)prev_pm->ctx;
396 }
397
398 ret = 0;
399
400end:
401 if (offset)
402 SCFree(offset);
403 if (ret != 0)
405 return ret;
406}
407
408/**
409 * \brief this function will free memory associated with DetectIsdataatData
410 *
411 * \param idad pointer to DetectIsdataatData
412 */
414{
416 SCFree(idad);
417}
418
419static int DetectEndsWithSetup (DetectEngineCtx *de_ctx, Signature *s, const char *nullstr)
420{
421 SigMatch *pm = NULL;
422 int ret = -1;
423
424 /* retrieve the sm to apply the depth against */
426 if (pm == NULL) {
427 SCLogError("endswith needs a "
428 "preceding content option");
429 goto end;
430 }
431
432 /* verify other conditions. */
434
435 cd->flags |= DETECT_CONTENT_ENDS_WITH;
436
437 ret = 0;
438 end:
439 return ret;
440}
441
442#ifdef UNITTESTS
443static int g_dce_stub_data_buffer_id = 0;
444
445/**
446 * \test DetectIsdataatTestParse01 is a test to make sure that we return a correct IsdataatData structure
447 * when given valid isdataat opt
448 */
449static int DetectIsdataatTestParse01 (void)
450{
451 int result = 0;
452 DetectIsdataatData *idad = NULL;
453 idad = DetectIsdataatParse(NULL, "30 ", NULL);
454 if (idad != NULL) {
455 DetectIsdataatFree(NULL, idad);
456 result = 1;
457 }
458
459 return result;
460}
461
462/**
463 * \test DetectIsdataatTestParse02 is a test to make sure that we return a correct IsdataatData structure
464 * when given valid isdataat opt
465 */
466static int DetectIsdataatTestParse02 (void)
467{
468 int result = 0;
469 DetectIsdataatData *idad = NULL;
470 idad = DetectIsdataatParse(NULL, "30 , relative", NULL);
471 if (idad != NULL && idad->flags & ISDATAAT_RELATIVE && !(idad->flags & ISDATAAT_RAWBYTES)) {
472 DetectIsdataatFree(NULL, idad);
473 result = 1;
474 }
475
476 return result;
477}
478
479/**
480 * \test DetectIsdataatTestParse03 is a test to make sure that we return a correct IsdataatData structure
481 * when given valid isdataat opt
482 */
483static int DetectIsdataatTestParse03 (void)
484{
485 int result = 0;
486 DetectIsdataatData *idad = NULL;
487 idad = DetectIsdataatParse(NULL, "30,relative, rawbytes ", NULL);
488 if (idad != NULL && idad->flags & ISDATAAT_RELATIVE && idad->flags & ISDATAAT_RAWBYTES) {
489 DetectIsdataatFree(NULL, idad);
490 result = 1;
491 }
492
493 return result;
494}
495
496/**
497 * \test Test isdataat option for dce sig.
498 */
499static int DetectIsdataatTestParse04(void)
500{
501 Signature *s = SigAlloc();
502 FAIL_IF_NULL(s);
503
505
506 FAIL_IF_NOT(DetectIsdataatSetup(NULL, s, "30") == 0);
507 SigMatch *sm = DetectBufferGetFirstSigMatch(s, g_dce_stub_data_buffer_id);
510 SigFree(NULL, s);
511
512 s = SigAlloc();
513 FAIL_IF_NULL(s);
515 /* relative w/o preceeding match defaults to "pmatch" */
516 FAIL_IF_NOT(DetectIsdataatSetup(NULL, s, "30,relative") == 0);
517 sm = DetectBufferGetFirstSigMatch(s, g_dce_stub_data_buffer_id);
520
521 SigFree(NULL, s);
522 PASS;
523}
524
525static int DetectIsdataatTestParse06(void)
526{
528 FAIL_IF(de_ctx == NULL);
530
531 Signature *s = DetectEngineAppendSig(de_ctx, "alert tcp any any -> any any "
532 "(msg:\"Testing bytejump_body\"; "
533 "content:\"one\"; "
534 "isdataat:!4,relative; sid:1;)");
535 FAIL_IF(s == NULL);
536
538
540 DetectIsdataatData *data =
542
543 FAIL_IF_NOT(data->flags & ISDATAAT_RELATIVE);
544 FAIL_IF(data->flags & ISDATAAT_RAWBYTES);
545 FAIL_IF_NOT(data->flags & ISDATAAT_NEGATED);
546
547 s = DetectEngineAppendSig(de_ctx, "alert tcp any any -> any any "
548 "(msg:\"Testing bytejump_body\"; "
549 "content:\"one\"; "
550 "isdataat: !4,relative; sid:2;)");
551 FAIL_IF(s == NULL);
552
554
557
558 FAIL_IF_NOT(data->flags & ISDATAAT_RELATIVE);
559 FAIL_IF(data->flags & ISDATAAT_RAWBYTES);
560 FAIL_IF_NOT(data->flags & ISDATAAT_NEGATED);
562
563 PASS;
564}
565
566/**
567 * \test DetectIsdataatTestPacket01 is a test to check matches of
568 * isdataat, and isdataat relative
569 */
570static int DetectIsdataatTestPacket01 (void)
571{
572 int result = 0;
573 uint8_t *buf = (uint8_t *)"Hi all!";
574 uint16_t buflen = strlen((char *)buf);
575 Packet *p[3];
576 p[0] = UTHBuildPacket((uint8_t *)buf, buflen, IPPROTO_TCP);
577 p[1] = UTHBuildPacket((uint8_t *)buf, buflen, IPPROTO_UDP);
578 p[2] = UTHBuildPacket((uint8_t *)buf, buflen, IPPROTO_ICMP);
579
580 if (p[0] == NULL || p[1] == NULL ||p[2] == NULL)
581 goto end;
582
583 const char *sigs[5];
584 sigs[0]= "alert ip any any -> any any (msg:\"Testing window 1\"; isdataat:6; sid:1;)";
585 sigs[1]= "alert ip any any -> any any (msg:\"Testing window 2\"; content:\"all\"; isdataat:1, relative; isdataat:6; sid:2;)";
586 sigs[2]= "alert ip any any -> any any (msg:\"Testing window 3\"; isdataat:8; sid:3;)";
587 sigs[3]= "alert ip any any -> any any (msg:\"Testing window 4\"; content:\"Hi\"; isdataat:5, relative; sid:4;)";
588 sigs[4]= "alert ip any any -> any any (msg:\"Testing window 4\"; content:\"Hi\"; isdataat:6, relative; sid:5;)";
589
590 uint32_t sid[5] = {1, 2, 3, 4, 5};
591
592 uint32_t results[3][5] = {
593 /* packet 0 match sid 1 but should not match sid 2 */
594 {1, 1, 0, 1, 0},
595 /* packet 1 should not match */
596 {1, 1, 0, 1, 0},
597 /* packet 2 should not match */
598 {1, 1, 0, 1, 0} };
599
600 result = UTHGenericTest(p, 3, sigs, sid, (uint32_t *) results, 5);
601
602 UTHFreePackets(p, 3);
603end:
604 return result;
605}
606
607/**
608 * \test DetectIsdataatTestPacket02 is a test to check matches of
609 * isdataat, and isdataat relative works if the previous keyword is pcre
610 * (bug 144)
611 */
612static int DetectIsdataatTestPacket02 (void)
613{
614 int result = 0;
615 uint8_t *buf = (uint8_t *)"GET /AllWorkAndNoPlayMakesWillADullBoy HTTP/1.0"
616 "User-Agent: Wget/1.11.4"
617 "Accept: */*"
618 "Host: www.google.com"
619 "Connection: Keep-Alive"
620 "Date: Mon, 04 Jan 2010 17:29:39 GMT";
621 uint16_t buflen = strlen((char *)buf);
622 Packet *p;
623 p = UTHBuildPacket((uint8_t *)buf, buflen, IPPROTO_TCP);
624
625 if (p == NULL)
626 goto end;
627
628 char sig[] = "alert tcp any any -> any any (msg:\"pcre with"
629 " isdataat + relative\"; pcre:\"/A(ll|pp)WorkAndNoPlayMakesWillA"
630 "DullBoy/\"; isdataat:96,relative; sid:1;)";
631
632 result = UTHPacketMatchSig(p, sig);
633
634 UTHFreePacket(p);
635end:
636 return result;
637}
638
639/**
640 * \test DetectIsdataatTestPacket03 is a test to check matches of
641 * isdataat, and isdataat relative works if the previous keyword is byte_jump
642 * (bug 146)
643 */
644static int DetectIsdataatTestPacket03 (void)
645{
646 int result = 0;
647 uint8_t *buf = (uint8_t *)"GET /AllWorkAndNoPlayMakesWillADullBoy HTTP/1.0"
648 "User-Agent: Wget/1.11.4"
649 "Accept: */*"
650 "Host: www.google.com"
651 "Connection: Keep-Alive"
652 "Date: Mon, 04 Jan 2010 17:29:39 GMT";
653 uint16_t buflen = strlen((char *)buf);
654 Packet *p;
655 p = UTHBuildPacket((uint8_t *)buf, buflen, IPPROTO_TCP);
656
657 if (p == NULL)
658 goto end;
659
660 char sig[] = "alert tcp any any -> any any (msg:\"byte_jump match = 0 "
661 "with distance content HTTP/1. relative against HTTP/1.0\"; byte_jump:1,"
662 "46,string,dec; isdataat:87,relative; sid:109; rev:1;)";
663
664 result = UTHPacketMatchSig(p, sig);
665
666 UTHFreePacket(p);
667end:
668 return result;
669}
670
671/**
672 * \brief this function registers unit tests for DetectIsdataat
673 */
674void DetectIsdataatRegisterTests(void)
675{
676 g_dce_stub_data_buffer_id = DetectBufferTypeGetByName("dce_stub_data");
677
678 UtRegisterTest("DetectIsdataatTestParse01", DetectIsdataatTestParse01);
679 UtRegisterTest("DetectIsdataatTestParse02", DetectIsdataatTestParse02);
680 UtRegisterTest("DetectIsdataatTestParse03", DetectIsdataatTestParse03);
681 UtRegisterTest("DetectIsdataatTestParse04", DetectIsdataatTestParse04);
682 UtRegisterTest("DetectIsdataatTestParse06", DetectIsdataatTestParse06);
683
684 UtRegisterTest("DetectIsdataatTestPacket01", DetectIsdataatTestPacket01);
685 UtRegisterTest("DetectIsdataatTestPacket02", DetectIsdataatTestPacket02);
686 UtRegisterTest("DetectIsdataatTestPacket03", DetectIsdataatTestPacket03);
687}
688
689static int DetectAbsentTestParse01(void)
690{
692 FAIL_IF(de_ctx == NULL);
694
696 "alert http any any -> any any "
697 "(msg:\"invalid absent only with negated content\"; http.user_agent; "
698 "absent; content:!\"one\"; sid:2;)");
699 FAIL_IF(s != NULL);
700 s = DetectEngineAppendSig(de_ctx, "alert http any any -> any any "
701 "(msg:\"invalid absent\"; http.user_agent; "
702 "content:!\"one\"; absent; sid:2;)");
703 FAIL_IF(s != NULL);
704 s = DetectEngineAppendSig(de_ctx, "alert http any any -> any any "
705 "(msg:\"invalid absent\"; http.user_agent; "
706 "content:\"one\"; absent: or_else; sid:2;)");
707 FAIL_IF(s != NULL);
708 s = DetectEngineAppendSig(de_ctx, "alert http any any -> any any "
709 "(msg:\"absent without sticky buffer\"; "
710 "content:!\"one\"; absent: or_else; sid:2;)");
711 FAIL_IF(s != NULL);
713 "alert websocket any any -> any any "
714 "(msg:\"absent with frame\"; "
715 "frame: websocket.pdu; absent: or_else; content:!\"one\"; sid:2;)");
716 FAIL_IF(s != NULL);
718 PASS;
719}
720
721void DetectAbsentRegisterTests(void)
722{
723 UtRegisterTest("DetectAbsentTestParse01", DetectAbsentTestParse01);
724}
725#endif
@ ALPROTO_DCERPC
bool DetectByteRetrieveSMVar(const char *arg, const Signature *s, int sm_list, DetectByteIndexType *index)
Used to retrieve args from BM.
Definition detect-byte.c:41
uint8_t DetectByteIndexType
Definition detect-byte.h:28
#define DETECT_CONTENT_RELATIVE_NEXT
#define DETECT_CONTENT_FAST_PATTERN
#define DETECT_CONTENT_ENDS_WITH
SigMatch * DetectBufferGetFirstSigMatch(const Signature *s, const uint32_t buf_id)
int DetectBufferGetActiveList(DetectEngineCtx *de_ctx, Signature *s)
@ DETECT_BYTE_EXTRACT
@ DETECT_BYTEMATH
@ DETECT_BYTETEST
@ DETECT_BYTEJUMP
@ DETECT_ENDS_WITH
@ DETECT_ISDATAAT
DetectEngineCtx * DetectEngineCtxInit(void)
void DetectEngineCtxFree(DetectEngineCtx *)
Free a DetectEngineCtx::
Signature * DetectEngineAppendSig(DetectEngineCtx *, const char *)
Parse and append a Signature into the Detection Engine Context signature list.
void SigFree(DetectEngineCtx *, Signature *)
const DetectBufferType * DetectEngineBufferTypeGetById(const DetectEngineCtx *de_ctx, const int id)
int DetectBufferTypeGetByName(const char *name)
bool DetectAbsentValidateContentCallback(const Signature *s, const SignatureInitDataBuffer *b)
void DetectIsdataatFree(DetectEngineCtx *, void *)
this function will free memory associated with DetectIsdataatData
void DetectIsdataatRegister(void)
Registration function for isdataat: keyword.
int DetectIsdataatSetup(DetectEngineCtx *, Signature *, const char *)
This function is used to add the parsed isdataatdata into the current signature.
#define PARSE_REGEX
Regex for parsing our isdataat options.
#define ISDATAAT_RELATIVE
#define ISDATAAT_NEGATED
#define ISDATAAT_RAWBYTES
#define ISDATAAT_OFFSET_VAR
void DetectSetupParseRegexes(const char *parse_str, DetectParseRegex *detect_parse)
int SCDetectSignatureSetAppProto(Signature *s, AppProto alproto)
int DetectParsePcreExec(DetectParseRegex *parse_regex, pcre2_match_data **match, const char *str, int start_offset, int options)
SigMatch * SCSigMatchAppendSMToList(DetectEngineCtx *de_ctx, Signature *s, uint16_t type, SigMatchCtx *ctx, const int list)
Append a SigMatch to the list type.
SigMatch * DetectGetLastSMFromLists(const Signature *s,...)
Returns the sm with the largest index (added latest) from the lists passed to us.
Signature * SigAlloc(void)
int SigMatchListSMBelongsTo(const Signature *s, const SigMatch *key_sm)
SigTableElmt * sigmatch_table
#define DETECT_PCRE_RELATIVE_NEXT
Definition detect-pcre.h:34
#define SIGMATCH_NOOPT
Definition detect.h:1651
#define DE_QUIET
Definition detect.h:330
#define DETECT_SM_LIST_NOTSET
Definition detect.h:144
#define SIGMATCH_OPTIONAL_OPT
Definition detect.h:1661
@ DETECT_SM_LIST_PMATCH
Definition detect.h:119
DetectEngineCtx * de_ctx
#define FAIL_IF_NULL(expr)
Fail a test if expression evaluates to NULL.
void UtRegisterTest(const char *name, int(*TestFn)(void))
Register unit test.
#define FAIL_IF_NOT(expr)
Fail a test if expression evaluates to false.
#define PASS
Pass the test.
#define FAIL_IF(expr)
Fail a test if expression evaluates to true.
#define FAIL_IF_NOT_NULL(expr)
Fail a test if expression evaluates to non-NULL.
main detection engine ctx
Definition detect.h:932
uint8_t flags
Definition detect.h:934
Used to start a pointer to SigMatch context Should never be dereferenced without casting to something...
Definition detect.h:351
a single match condition for a signature
Definition detect.h:356
uint16_t type
Definition detect.h:357
SigMatchCtx * ctx
Definition detect.h:359
const char * url
Definition detect.h:1462
int(* Setup)(DetectEngineCtx *, Signature *, const char *)
Definition detect.h:1441
void(* Free)(DetectEngineCtx *, void *)
Definition detect.h:1446
uint16_t flags
Definition detect.h:1450
const char * desc
Definition detect.h:1461
void(* RegisterTests)(void)
Definition detect.h:1448
int(* Match)(DetectEngineThreadCtx *, Packet *, const Signature *, const SigMatchCtx *)
Definition detect.h:1421
const char * name
Definition detect.h:1459
struct SigMatch_ * smlists[DETECT_SM_LIST_MAX]
Definition detect.h:642
struct SigMatch_ * smlists_tail[DETECT_SM_LIST_MAX]
Definition detect.h:644
SignatureInitDataBuffer * curbuf
Definition detect.h:650
Signature container.
Definition detect.h:668
SignatureInitData * init_data
Definition detect.h:747
int StringParseUint16(uint16_t *res, int base, size_t len, const char *str)
Definition util-byte.c:337
#define SCLogDebug(...)
Definition util-debug.h:275
#define SCLogError(...)
Macro used to log ERROR messages.
Definition util-debug.h:267
#define SCMalloc(sz)
Definition util-mem.h:47
#define SCFree(p)
Definition util-mem.h:61
#define SCStrdup(s)
Definition util-mem.h:56
#define unlikely(expr)
uint64_t offset
void UTHFreePackets(Packet **p, int numpkts)
UTHFreePackets: function to release the allocated data from UTHBuildPacket and the packet itself.
int UTHPacketMatchSig(Packet *p, const char *sig)
Packet * UTHBuildPacket(uint8_t *payload, uint16_t payload_len, uint8_t ipproto)
UTHBuildPacket is a wrapper that build packets with default ip and port fields.
int UTHGenericTest(Packet **pkt, int numpkts, const char *sigs[], uint32_t sids[], uint32_t *results, int numsigs)
UTHGenericTest: function that perform a generic check taking care of as maximum common unittest eleme...
void UTHFreePacket(Packet *p)
UTHFreePacket: function to release the allocated data from UTHBuildPacket and the packet itself.