suricata
detect-engine-event.c
Go to the documentation of this file.
1 /* Copyright (C) 2007-2021 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 Breno Silva <breno.silva@gmail.com>
22  *
23  * Implements the decode-event keyword
24  */
25 
26 #include "suricata-common.h"
27 #include "suricata.h"
28 #include "decode.h"
29 #include "detect.h"
30 #include "detect-parse.h"
31 
32 #include "flow-var.h"
33 #include "decode-events.h"
34 
35 #include "util-debug.h"
36 
37 #include "stream-tcp.h"
38 
39 
40 /* Need to get the DEvents[] array */
41 
42 #include "detect-engine-event.h"
43 #include "util-unittest.h"
44 
45 #define PARSE_REGEX "\\S[0-9A-z_]+[.][A-z0-9_+.]+$"
46 
47 static DetectParseRegex parse_regex;
48 
49 static int DetectEngineEventMatch (DetectEngineThreadCtx *,
50  Packet *, const Signature *, const SigMatchCtx *);
51 static int DetectEngineEventSetup (DetectEngineCtx *, Signature *, const char *);
52 static int DetectDecodeEventSetup (DetectEngineCtx *, Signature *, const char *);
53 static int DetectStreamEventSetup (DetectEngineCtx *, Signature *, const char *);
54 static void DetectEngineEventFree (DetectEngineCtx *, void *);
55 #ifdef UNITTESTS
56 void EngineEventRegisterTests(void);
57 #endif
58 
59 /**
60  * \brief Registration function for decode-event: keyword
61  */
63 {
64  sigmatch_table[DETECT_ENGINE_EVENT].name = "engine-event";
65  sigmatch_table[DETECT_ENGINE_EVENT].Match = DetectEngineEventMatch;
66  sigmatch_table[DETECT_ENGINE_EVENT].Setup = DetectEngineEventSetup;
67  sigmatch_table[DETECT_ENGINE_EVENT].Free = DetectEngineEventFree;
68 #ifdef UNITTESTS
70 #endif
71 
72  sigmatch_table[DETECT_DECODE_EVENT].name = "decode-event";
73  sigmatch_table[DETECT_DECODE_EVENT].Match = DetectEngineEventMatch;
74  sigmatch_table[DETECT_DECODE_EVENT].Setup = DetectDecodeEventSetup;
75  sigmatch_table[DETECT_DECODE_EVENT].Free = DetectEngineEventFree;
77 
78  sigmatch_table[DETECT_STREAM_EVENT].name = "stream-event";
79  sigmatch_table[DETECT_STREAM_EVENT].Match = DetectEngineEventMatch;
80  sigmatch_table[DETECT_STREAM_EVENT].Setup = DetectStreamEventSetup;
81  sigmatch_table[DETECT_STREAM_EVENT].Free = DetectEngineEventFree;
82 
83  DetectSetupParseRegexes(PARSE_REGEX, &parse_regex);
84 }
85 
86 /**
87  * \brief This function is used to match decoder event flags set on a packet with those passed via decode-event:
88  *
89  * \param t pointer to thread vars
90  * \param det_ctx pointer to the pattern matcher thread
91  * \param p pointer to the current packet
92  * \param s pointer to the Signature
93  * \param m pointer to the sigmatch
94  *
95  * \retval 0 no match
96  * \retval 1 match
97  */
98 static int DetectEngineEventMatch (DetectEngineThreadCtx *det_ctx,
99  Packet *p, const Signature *s, const SigMatchCtx *ctx)
100 {
101  SCEnter();
102 
103  const DetectEngineEventData *de = (const DetectEngineEventData *)ctx;
104 
105  if (ENGINE_ISSET_EVENT(p, de->event)) {
106  SCLogDebug("de->event matched %u", de->event);
107  SCReturnInt(1);
108  }
109 
110  SCReturnInt(0);
111 }
112 
113 static bool OutdatedEvent(const char *raw)
114 {
115  if (strcmp(raw, "decoder.udp.hlen_invalid") == 0) {
116  return true;
117  }
118  return false;
119 }
120 
121 /**
122  * \brief This function is used to parse decoder events options passed via decode-event: keyword
123  *
124  * \param rawstr Pointer to the user provided decode-event options
125  *
126  * \retval de pointer to DetectFlowData on success
127  * \retval NULL on failure
128  */
129 static DetectEngineEventData *DetectEngineEventParse (const char *rawstr)
130 {
131  int i;
132  DetectEngineEventData *de = NULL;
133  int res = 0, found = 0;
134  size_t pcre2len;
135  pcre2_match_data *match = NULL;
136 
137  int ret = DetectParsePcreExec(&parse_regex, &match, rawstr, 0, 0);
138  if (ret < 1) {
139  SCLogError("pcre_exec parse error, ret %" PRId32 ", string %s", ret, rawstr);
140  goto error;
141  }
142 
143  char copy_str[128] = "";
144  pcre2len = sizeof(copy_str);
145  res = pcre2_substring_copy_bynumber(match, 0, (PCRE2_UCHAR8 *)copy_str, &pcre2len);
146 
147  if (res < 0) {
148  SCLogError("pcre2_substring_copy_bynumber failed");
149  goto error;
150  }
151 
152  for (i = 0; DEvents[i].event_name != NULL; i++) {
153  if (strcasecmp(DEvents[i].event_name,copy_str) == 0) {
154  found = 1;
155  break;
156  }
157  }
158 
159  if (found == 0) {
160  SCLogError("unknown decode event \"%s\"", copy_str);
161  goto error;
162  }
163 
164  de = SCMalloc(sizeof(DetectEngineEventData));
165  if (unlikely(de == NULL))
166  goto error;
167 
168  de->event = DEvents[i].code;
169 
172  }
173 
174  if (OutdatedEvent(rawstr)) {
176  SCLogError("decode-event keyword no longer supports event \"%s\"", rawstr);
177  goto error;
178  } else {
179  SCLogWarning("decode-event keyword no longer supports event \"%s\"", rawstr);
180  }
181  }
182 
183  pcre2_match_data_free(match);
184  return de;
185 
186 error:
187  if (de)
188  SCFree(de);
189  if (match) {
190  pcre2_match_data_free(match);
191  }
192  return NULL;
193 }
194 
195 /**
196  * \brief this function is used to add the parsed decode-event into the current signature
197  *
198  * \param de_ctx pointer to the Detection Engine Context
199  * \param s pointer to the Current Signature
200  * \param rawstr pointer to the user provided decode-event options
201  *
202  * \retval 0 on Success
203  * \retval -1 on Failure
204  */
205 static int DetectEngineEventSetupDo(
206  DetectEngineCtx *de_ctx, Signature *s, const char *rawstr, uint16_t smtype)
207 {
208  DetectEngineEventData *de = DetectEngineEventParse(rawstr);
209  if (de == NULL)
210  return -1;
211 
212  SCLogDebug("rawstr %s %u", rawstr, de->event);
213 
214  SigMatch *sm = SigMatchAlloc();
215  if (sm == NULL) {
216  SCFree(de);
217  return -1;
218  }
219 
220  sm->type = smtype;
221  sm->ctx = (SigMatchCtx *)de;
222 
224  return 0;
225 }
226 
227 
228 static int DetectEngineEventSetup (DetectEngineCtx *de_ctx, Signature *s, const char *rawstr)
229 {
230  return DetectEngineEventSetupDo (de_ctx, s, rawstr, DETECT_ENGINE_EVENT);
231 }
232 
233 /**
234  * \brief this function will free memory associated with DetectEngineEventData
235  *
236  * \param de pointer to DetectEngineEventData
237  */
238 static void DetectEngineEventFree(DetectEngineCtx *de_ctx, void *ptr)
239 {
241  if (de)
242  SCFree(de);
243 }
244 
245 
246 /**
247  * \brief this function Setup the 'decode-event' keyword by setting the correct
248  * signature type
249 */
250 static int DetectDecodeEventSetup (DetectEngineCtx *de_ctx, Signature *s, const char *rawstr)
251 {
252  char drawstr[64] = "decoder.";
253 
254  /* decoder:$EVENT alias command develop as decode-event:decoder.$EVENT */
255  strlcat(drawstr, rawstr, sizeof(drawstr));
256 
257  return DetectEngineEventSetupDo(de_ctx, s, drawstr, DETECT_DECODE_EVENT);
258 }
259 
260 /**
261  * \brief this function Setup the 'stream-event' keyword by resolving the alias
262 */
263 static int DetectStreamEventSetup (DetectEngineCtx *de_ctx, Signature *s, const char *rawstr)
264 {
265  char srawstr[64] = "stream.";
266 
267  if (strcmp(rawstr, "est_synack_resend_with_different_ack") == 0) {
268  rawstr = "est_synack_resend_with_diff_ack";
269  } else if (strcmp(rawstr, "3whs_synack_resend_with_different_ack") == 0) {
270  rawstr = "3whs_synack_resend_with_diff_ack";
271  }
272 
273  /* stream:$EVENT alias command develop as decode-event:stream.$EVENT */
274  strlcat(srawstr, rawstr, sizeof(srawstr));
275 
276  return DetectEngineEventSetup(de_ctx, s, srawstr);
277 }
278 
279 /*
280  * ONLY TESTS BELOW THIS COMMENT
281  */
282 #ifdef UNITTESTS
283 
284 /**
285  * \test EngineEventTestParse01 is a test for a valid decode-event value
286  */
287 static int EngineEventTestParse01 (void)
288 {
289  DetectEngineEventData *de = DetectEngineEventParse("decoder.ipv4.pkt_too_small");
290 
291  FAIL_IF_NULL(de);
292 
293  DetectEngineEventFree(NULL, de);
294 
295  PASS;
296 }
297 
298 
299 /**
300  * \test EngineEventTestParse02 is a test for a valid upper + lower case decode-event value
301  */
302 static int EngineEventTestParse02 (void)
303 {
304  DetectEngineEventData *de = DetectEngineEventParse("decoder.PPP.pkt_too_small");
305 
306  FAIL_IF_NULL(de);
307 
308  DetectEngineEventFree(NULL, de);
309 
310  PASS;
311 }
312 
313 /**
314  * \test EngineEventTestParse03 is a test for a valid upper case decode-event value
315  */
316 static int EngineEventTestParse03 (void)
317 {
318  DetectEngineEventData *de = DetectEngineEventParse("decoder.IPV6.PKT_TOO_SMALL");
319 
320  FAIL_IF_NULL(de);
321 
322  DetectEngineEventFree(NULL, de);
323 
324  PASS;
325 }
326 
327 /**
328  * \test EngineEventTestParse04 is a test for an invalid upper case decode-event value
329  */
330 static int EngineEventTestParse04 (void)
331 {
332  DetectEngineEventData *de = DetectEngineEventParse("decoder.IPV6.INVALID_EVENT");
333 
335 
336  DetectEngineEventFree(NULL, de);
337 
338  PASS;
339 }
340 
341 /**
342  * \test EngineEventTestParse05 is a test for an invalid char into the decode-event value
343  */
344 static int EngineEventTestParse05 (void)
345 {
346  DetectEngineEventData *de = DetectEngineEventParse("decoder.IPV-6,INVALID_CHAR");
347 
349 
350  DetectEngineEventFree(NULL, de);
351 
352  PASS;
353 }
354 
355 /**
356  * \test EngineEventTestParse06 is a test for match function with valid decode-event value
357  */
358 static int EngineEventTestParse06 (void)
359 {
360  Packet *p = PacketGetFromAlloc();
361  FAIL_IF_NULL(p);
362 
363  ThreadVars tv;
364 
365  memset(&tv, 0, sizeof(ThreadVars));
366 
368 
369  DetectEngineEventData *de = DetectEngineEventParse("decoder.ppp.pkt_too_small");
370  FAIL_IF_NULL(de);
371 
372  de->event = PPP_PKT_TOO_SMALL;
373 
374  SigMatch *sm = SigMatchAlloc();
375  FAIL_IF_NULL(sm);
376 
378  sm->ctx = (SigMatchCtx *)de;
379 
380  FAIL_IF_NOT(DetectEngineEventMatch(NULL, p, NULL, sm->ctx));
381 
382  SCFree(p);
383  SCFree(de);
384  SCFree(sm);
385 
386  PASS;
387 }
388 
389 /**
390  * \brief this function registers unit tests for EngineEvent
391  */
393 {
394  UtRegisterTest("EngineEventTestParse01", EngineEventTestParse01);
395  UtRegisterTest("EngineEventTestParse02", EngineEventTestParse02);
396  UtRegisterTest("EngineEventTestParse03", EngineEventTestParse03);
397  UtRegisterTest("EngineEventTestParse04", EngineEventTestParse04);
398  UtRegisterTest("EngineEventTestParse05", EngineEventTestParse05);
399  UtRegisterTest("EngineEventTestParse06", EngineEventTestParse06);
400 }
401 #endif /* UNITTESTS */
ENGINE_SET_EVENT
#define ENGINE_SET_EVENT(p, e)
Definition: decode.h:884
EngineEventRegisterTests
void EngineEventRegisterTests(void)
this function registers unit tests for EngineEvent
Definition: detect-engine-event.c:392
FAIL_IF_NULL
#define FAIL_IF_NULL(expr)
Fail a test if expression evaluates to NULL.
Definition: util-unittest.h:89
SigMatchAppendSMToList
void SigMatchAppendSMToList(Signature *s, SigMatch *new, const int list)
Append a SigMatch to the list type.
Definition: detect-parse.c:437
SigTableElmt_::Free
void(* Free)(DetectEngineCtx *, void *)
Definition: detect.h:1274
DetectParseRegex
Definition: detect-parse.h:62
SigTableElmt_::name
const char * name
Definition: detect.h:1284
stream-tcp.h
detect-engine-event.h
unlikely
#define unlikely(expr)
Definition: util-optimize.h:35
UtRegisterTest
void UtRegisterTest(const char *name, int(*TestFn)(void))
Register unit test.
Definition: util-unittest.c:103
ENGINE_ISSET_EVENT
#define ENGINE_ISSET_EVENT(p, e)
Definition: decode.h:899
SCLogDebug
#define SCLogDebug(...)
Definition: util-debug.h:269
DETECT_DECODE_EVENT
@ DETECT_DECODE_EVENT
Definition: detect-engine-register.h:104
SigTableElmt_::flags
uint16_t flags
Definition: detect.h:1278
DetectEngineCtx_
main detection engine ctx
Definition: detect.h:826
StreamTcpReassembleConfigEnableOverlapCheck
void StreamTcpReassembleConfigEnableOverlapCheck(void)
Definition: stream-tcp-list.c:40
SIGMATCH_DEONLY_COMPAT
#define SIGMATCH_DEONLY_COMPAT
Definition: detect.h:1470
DetectParsePcreExec
int DetectParsePcreExec(DetectParseRegex *parse_regex, pcre2_match_data **match, const char *str, int start_offset, int options)
Definition: detect-parse.c:2623
SigTableElmt_::Setup
int(* Setup)(DetectEngineCtx *, Signature *, const char *)
Definition: detect.h:1269
util-unittest.h
FAIL_IF_NOT
#define FAIL_IF_NOT(expr)
Fail a test if expression evaluates to false.
Definition: util-unittest.h:82
PARSE_REGEX
#define PARSE_REGEX
Definition: detect-engine-event.c:45
PPP_PKT_TOO_SMALL
@ PPP_PKT_TOO_SMALL
Definition: decode-events.h:115
decode.h
FAIL_IF_NOT_NULL
#define FAIL_IF_NOT_NULL(expr)
Fail a test if expression evaluates to non-NULL.
Definition: util-unittest.h:96
util-debug.h
PASS
#define PASS
Pass the test.
Definition: util-unittest.h:105
de_ctx
DetectEngineCtx * de_ctx
Definition: fuzz_siginit.c:17
DetectEngineThreadCtx_
Definition: detect.h:1074
strlcat
size_t strlcat(char *, const char *src, size_t siz)
Definition: util-strlcatu.c:45
DEvents
const struct DecodeEvents_ DEvents[]
Definition: decode-events.c:29
de
uint8_t de
Definition: app-layer-htp.c:577
DetectSetupParseRegexes
void DetectSetupParseRegexes(const char *parse_str, DetectParseRegex *detect_parse)
Definition: detect-parse.c:2747
SCEnter
#define SCEnter(...)
Definition: util-debug.h:271
detect.h
ThreadVars_
Per thread variable structure.
Definition: threadvars.h:57
DETECT_ENGINE_EVENT
@ DETECT_ENGINE_EVENT
Definition: detect-engine-register.h:203
SigMatchStrictEnabled
bool SigMatchStrictEnabled(const enum DetectKeywordId id)
Definition: detect-parse.c:385
DETECT_SM_LIST_MATCH
@ DETECT_SM_LIST_MATCH
Definition: detect.h:108
SCLogWarning
#define SCLogWarning(...)
Macro used to log WARNING messages.
Definition: util-debug.h:249
SigMatch_::ctx
SigMatchCtx * ctx
Definition: detect.h:343
Packet_
Definition: decode.h:430
DecodeEvents_::code
uint8_t code
Definition: decode-events.h:311
SigTableElmt_::Match
int(* Match)(DetectEngineThreadCtx *, Packet *, const Signature *, const SigMatchCtx *)
Definition: detect.h:1252
SigMatchAlloc
SigMatch * SigMatchAlloc(void)
Definition: detect-parse.c:322
DecodeEvents_::event_name
const char * event_name
Definition: decode-events.h:310
decode-events.h
SigMatchCtx_
Used to start a pointer to SigMatch context Should never be dereferenced without casting to something...
Definition: detect.h:335
suricata-common.h
SigMatch_::type
uint16_t type
Definition: detect.h:341
sigmatch_table
SigTableElmt sigmatch_table[DETECT_TBLSIZE]
Definition: detect-parse.c:129
tv
ThreadVars * tv
Definition: fuzz_decodepcapfile.c:32
PacketGetFromAlloc
Packet * PacketGetFromAlloc(void)
Get a malloced packet.
Definition: decode.c:173
DetectEngineEventRegister
void DetectEngineEventRegister(void)
Registration function for decode-event: keyword.
Definition: detect-engine-event.c:62
SCMalloc
#define SCMalloc(sz)
Definition: util-mem.h:47
DETECT_STREAM_EVENT
@ DETECT_STREAM_EVENT
Definition: detect-engine-register.h:204
SCLogError
#define SCLogError(...)
Macro used to log ERROR messages.
Definition: util-debug.h:261
SCFree
#define SCFree(p)
Definition: util-mem.h:61
detect-parse.h
Signature_
Signature container.
Definition: detect.h:581
SigMatch_
a single match condition for a signature
Definition: detect.h:340
DetectEngineEventData_
Definition: detect-engine-event.h:28
suricata.h
STREAM_REASSEMBLY_OVERLAP_DIFFERENT_DATA
@ STREAM_REASSEMBLY_OVERLAP_DIFFERENT_DATA
Definition: decode-events.h:294
SCReturnInt
#define SCReturnInt(x)
Definition: util-debug.h:275
flow-var.h
SigTableElmt_::RegisterTests
void(* RegisterTests)(void)
Definition: detect.h:1276