suricata
detect-engine-event.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 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 void EngineEventRegisterTests(void);
56 
57 
58 /**
59  * \brief Registration function for decode-event: keyword
60  */
62 {
63  sigmatch_table[DETECT_ENGINE_EVENT].name = "engine-event";
64  sigmatch_table[DETECT_ENGINE_EVENT].Match = DetectEngineEventMatch;
65  sigmatch_table[DETECT_ENGINE_EVENT].Setup = DetectEngineEventSetup;
66  sigmatch_table[DETECT_ENGINE_EVENT].Free = DetectEngineEventFree;
68 
69  sigmatch_table[DETECT_DECODE_EVENT].name = "decode-event";
70  sigmatch_table[DETECT_DECODE_EVENT].Match = DetectEngineEventMatch;
71  sigmatch_table[DETECT_DECODE_EVENT].Setup = DetectDecodeEventSetup;
72  sigmatch_table[DETECT_DECODE_EVENT].Free = DetectEngineEventFree;
74 
75  sigmatch_table[DETECT_STREAM_EVENT].name = "stream-event";
76  sigmatch_table[DETECT_STREAM_EVENT].Match = DetectEngineEventMatch;
77  sigmatch_table[DETECT_STREAM_EVENT].Setup = DetectStreamEventSetup;
78  sigmatch_table[DETECT_STREAM_EVENT].Free = DetectEngineEventFree;
79 
80  DetectSetupParseRegexes(PARSE_REGEX, &parse_regex);
81 }
82 
83 /**
84  * \brief This function is used to match decoder event flags set on a packet with those passed via decode-event:
85  *
86  * \param t pointer to thread vars
87  * \param det_ctx pointer to the pattern matcher thread
88  * \param p pointer to the current packet
89  * \param s pointer to the Signature
90  * \param m pointer to the sigmatch
91  *
92  * \retval 0 no match
93  * \retval 1 match
94  */
95 static int DetectEngineEventMatch (DetectEngineThreadCtx *det_ctx,
96  Packet *p, const Signature *s, const SigMatchCtx *ctx)
97 {
98  SCEnter();
99 
100  const DetectEngineEventData *de = (const DetectEngineEventData *)ctx;
101 
102  if (ENGINE_ISSET_EVENT(p, de->event)) {
103  SCLogDebug("de->event matched %u", de->event);
104  SCReturnInt(1);
105  }
106 
107  SCReturnInt(0);
108 }
109 
110 /**
111  * \brief This function is used to parse decoder events options passed via decode-event: keyword
112  *
113  * \param rawstr Pointer to the user provided decode-event options
114  *
115  * \retval de pointer to DetectFlowData on success
116  * \retval NULL on failure
117  */
118 static DetectEngineEventData *DetectEngineEventParse (const char *rawstr)
119 {
120  int i;
121  DetectEngineEventData *de = NULL;
122  int ret = 0, res = 0, found = 0;
123  int ov[MAX_SUBSTRINGS];
124 
125  ret = DetectParsePcreExec(&parse_regex, rawstr, 0, 0, ov, MAX_SUBSTRINGS);
126  if (ret < 1) {
127  SCLogError(SC_ERR_PCRE_MATCH, "pcre_exec parse error, ret %" PRId32
128  ", string %s", ret, rawstr);
129  goto error;
130  }
131 
132  char copy_str[128] = "";
133  res = pcre_copy_substring((char *)rawstr, ov, MAX_SUBSTRINGS, 0,
134  copy_str, sizeof(copy_str));
135 
136  if (res < 0) {
137  SCLogError(SC_ERR_PCRE_GET_SUBSTRING, "pcre_copy_substring failed");
138  goto error;
139  }
140 
141  for (i = 0; DEvents[i].event_name != NULL; i++) {
142  if (strcasecmp(DEvents[i].event_name,copy_str) == 0) {
143  found = 1;
144  break;
145  }
146  }
147 
148  if (found == 0) {
149  SCLogError(SC_ERR_UNKNOWN_DECODE_EVENT, "unknown decode event \"%s\"",
150  copy_str);
151  goto error;
152  }
153 
154  de = SCMalloc(sizeof(DetectEngineEventData));
155  if (unlikely(de == NULL))
156  goto error;
157 
158  de->event = DEvents[i].code;
159 
162  }
163  return de;
164 
165 error:
166  if (de)
167  SCFree(de);
168  return NULL;
169 }
170 
171 /**
172  * \brief this function is used to add the parsed decode-event into the current signature
173  *
174  * \param de_ctx pointer to the Detection Engine Context
175  * \param s pointer to the Current Signature
176  * \param rawstr pointer to the user provided decode-event options
177  *
178  * \retval 0 on Success
179  * \retval -1 on Failure
180  */
181 static int DetectEngineEventSetupDo (DetectEngineCtx *de_ctx, Signature *s,
182  const char *rawstr, int smtype)
183 {
184  DetectEngineEventData *de = DetectEngineEventParse(rawstr);
185  if (de == NULL)
186  return -1;
187 
188  SCLogDebug("rawstr %s %u", rawstr, de->event);
189 
190  SigMatch *sm = SigMatchAlloc();
191  if (sm == NULL) {
192  SCFree(de);
193  return -1;
194  }
195 
196  sm->type = smtype;
197  sm->ctx = (SigMatchCtx *)de;
198 
200  return 0;
201 }
202 
203 
204 static int DetectEngineEventSetup (DetectEngineCtx *de_ctx, Signature *s, const char *rawstr)
205 {
206  return DetectEngineEventSetupDo (de_ctx, s, rawstr, DETECT_ENGINE_EVENT);
207 }
208 
209 /**
210  * \brief this function will free memory associated with DetectEngineEventData
211  *
212  * \param de pointer to DetectEngineEventData
213  */
214 static void DetectEngineEventFree(DetectEngineCtx *de_ctx, void *ptr)
215 {
217  if (de)
218  SCFree(de);
219 }
220 
221 
222 /**
223  * \brief this function Setup the 'decode-event' keyword by setting the correct
224  * signature type
225 */
226 static int DetectDecodeEventSetup (DetectEngineCtx *de_ctx, Signature *s, const char *rawstr)
227 {
228  char drawstr[64] = "decoder.";
229 
230  /* decoder:$EVENT alias command develop as decode-event:decoder.$EVENT */
231  strlcat(drawstr, rawstr, sizeof(drawstr));
232 
233  return DetectEngineEventSetupDo(de_ctx, s, drawstr, DETECT_DECODE_EVENT);
234 }
235 
236 /**
237  * \brief this function Setup the 'stream-event' keyword by resolving the alias
238 */
239 static int DetectStreamEventSetup (DetectEngineCtx *de_ctx, Signature *s, const char *rawstr)
240 {
241  char srawstr[64] = "stream.";
242 
243  if (strcmp(rawstr, "est_synack_resend_with_different_ack") == 0) {
244  rawstr = "est_synack_resend_with_diff_ack";
245  } else if (strcmp(rawstr, "3whs_synack_resend_with_different_ack") == 0) {
246  rawstr = "3whs_synack_resend_with_diff_ack";
247  }
248 
249  /* stream:$EVENT alias command develop as decode-event:stream.$EVENT */
250  strlcat(srawstr, rawstr, sizeof(srawstr));
251 
252  return DetectEngineEventSetup(de_ctx, s, srawstr);
253 }
254 
255 /*
256  * ONLY TESTS BELOW THIS COMMENT
257  */
258 #ifdef UNITTESTS
259 
260 /**
261  * \test EngineEventTestParse01 is a test for a valid decode-event value
262  */
263 static int EngineEventTestParse01 (void)
264 {
265  DetectEngineEventData *de = NULL;
266  de = DetectEngineEventParse("decoder.ipv4.pkt_too_small");
267  if (de) {
268  DetectEngineEventFree(NULL, de);
269  return 1;
270  }
271 
272  return 0;
273 }
274 
275 
276 /**
277  * \test EngineEventTestParse02 is a test for a valid upper + lower case decode-event value
278  */
279 static int EngineEventTestParse02 (void)
280 {
281  DetectEngineEventData *de = NULL;
282  de = DetectEngineEventParse("decoder.PPP.pkt_too_small");
283  if (de) {
284  DetectEngineEventFree(NULL, de);
285  return 1;
286  }
287 
288  return 0;
289 }
290 
291 /**
292  * \test EngineEventTestParse03 is a test for a valid upper case decode-event value
293  */
294 static int EngineEventTestParse03 (void)
295 {
296  DetectEngineEventData *de = NULL;
297  de = DetectEngineEventParse("decoder.IPV6.PKT_TOO_SMALL");
298  if (de) {
299  DetectEngineEventFree(NULL, de);
300  return 1;
301  }
302 
303  return 0;
304 }
305 
306 /**
307  * \test EngineEventTestParse04 is a test for an invalid upper case decode-event value
308  */
309 static int EngineEventTestParse04 (void)
310 {
311  DetectEngineEventData *de = NULL;
312  de = DetectEngineEventParse("decoder.IPV6.INVALID_EVENT");
313  if (de) {
314  DetectEngineEventFree(NULL, de);
315  return 0;
316  }
317 
318  return 1;
319 }
320 
321 /**
322  * \test EngineEventTestParse05 is a test for an invalid char into the decode-event value
323  */
324 static int EngineEventTestParse05 (void)
325 {
326  DetectEngineEventData *de = NULL;
327  de = DetectEngineEventParse("decoder.IPV-6,INVALID_CHAR");
328  if (de) {
329  DetectEngineEventFree(NULL, de);
330  return 0;
331  }
332 
333  return 1;
334 }
335 
336 /**
337  * \test EngineEventTestParse06 is a test for match function with valid decode-event value
338  */
339 static int EngineEventTestParse06 (void)
340 {
342  if (unlikely(p == NULL))
343  return 0;
344  ThreadVars tv;
345  int ret = 0;
346  DetectEngineEventData *de = NULL;
347  SigMatch *sm = NULL;
348 
349 
350  memset(&tv, 0, sizeof(ThreadVars));
351  memset(p, 0, SIZE_OF_PACKET);
352 
354 
355  de = DetectEngineEventParse("decoder.ppp.pkt_too_small");
356  if (de == NULL)
357  goto error;
358 
359  de->event = PPP_PKT_TOO_SMALL;
360 
361  sm = SigMatchAlloc();
362  if (sm == NULL)
363  goto error;
364 
366  sm->ctx = (SigMatchCtx *)de;
367 
368  ret = DetectEngineEventMatch(NULL,p,NULL,sm->ctx);
369 
370  if(ret) {
371  SCFree(p);
372  return 1;
373  }
374 
375 error:
376  if (de) SCFree(de);
377  if (sm) SCFree(sm);
378  SCFree(p);
379  return 0;
380 }
381 #endif /* UNITTESTS */
382 
383 /**
384  * \brief this function registers unit tests for EngineEvent
385  */
387 {
388 #ifdef UNITTESTS
389  UtRegisterTest("EngineEventTestParse01", EngineEventTestParse01);
390  UtRegisterTest("EngineEventTestParse02", EngineEventTestParse02);
391  UtRegisterTest("EngineEventTestParse03", EngineEventTestParse03);
392  UtRegisterTest("EngineEventTestParse04", EngineEventTestParse04);
393  UtRegisterTest("EngineEventTestParse05", EngineEventTestParse05);
394  UtRegisterTest("EngineEventTestParse06", EngineEventTestParse06);
395 #endif /* UNITTESTS */
396 }
ENGINE_SET_EVENT
#define ENGINE_SET_EVENT(p, e)
Definition: decode.h:981
EngineEventRegisterTests
void EngineEventRegisterTests(void)
this function registers unit tests for EngineEvent
Definition: detect-engine-event.c:386
STREAM_REASSEMBLY_OVERLAP_DIFFERENT_DATA
@ STREAM_REASSEMBLY_OVERLAP_DIFFERENT_DATA
Definition: decode-events.h:262
SigTableElmt_::Free
void(* Free)(DetectEngineCtx *, void *)
Definition: detect.h:1192
SigTableElmt_::name
const char * name
Definition: detect.h:1201
stream-tcp.h
detect-engine-event.h
MAX_SUBSTRINGS
#define MAX_SUBSTRINGS
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:996
SCLogDebug
#define SCLogDebug(...)
Definition: util-debug.h:298
DETECT_DECODE_EVENT
@ DETECT_DECODE_EVENT
Definition: detect-engine-register.h:100
SigTableElmt_::flags
uint16_t flags
Definition: detect.h:1195
DetectEngineCtx_
main detection engine ctx
Definition: detect.h:761
StreamTcpReassembleConfigEnableOverlapCheck
void StreamTcpReassembleConfigEnableOverlapCheck(void)
Definition: stream-tcp-list.c:38
SIGMATCH_DEONLY_COMPAT
#define SIGMATCH_DEONLY_COMPAT
Definition: detect.h:1374
SC_ERR_PCRE_GET_SUBSTRING
@ SC_ERR_PCRE_GET_SUBSTRING
Definition: util-error.h:34
SigTableElmt_::Setup
int(* Setup)(DetectEngineCtx *, Signature *, const char *)
Definition: detect.h:1187
util-unittest.h
PARSE_REGEX
#define PARSE_REGEX
Definition: detect-engine-event.c:45
decode.h
util-debug.h
SC_ERR_PCRE_MATCH
@ SC_ERR_PCRE_MATCH
Definition: util-error.h:32
de_ctx
DetectEngineCtx * de_ctx
Definition: fuzz_siginit.c:17
SC_ERR_UNKNOWN_DECODE_EVENT
@ SC_ERR_UNKNOWN_DECODE_EVENT
Definition: util-error.h:218
DetectEngineThreadCtx_
Definition: detect.h:1004
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
res
PoolThreadReserved res
Definition: stream-tcp-private.h:0
DetectSetupParseRegexes
void DetectSetupParseRegexes(const char *parse_str, DetectParseRegex *detect_parse)
Definition: detect-parse.c:2446
SCEnter
#define SCEnter(...)
Definition: util-debug.h:300
detect.h
ThreadVars_
Per thread variable structure.
Definition: threadvars.h:58
de
int de
Definition: app-layer-htp.c:572
DETECT_ENGINE_EVENT
@ DETECT_ENGINE_EVENT
Definition: detect-engine-register.h:178
DETECT_SM_LIST_MATCH
@ DETECT_SM_LIST_MATCH
Definition: detect.h:89
SIZE_OF_PACKET
#define SIZE_OF_PACKET
Definition: decode.h:621
SigMatch_::ctx
SigMatchCtx * ctx
Definition: detect.h:321
DetectParsePcreExec
int DetectParsePcreExec(DetectParseRegex *parse_regex, const char *str, int start_offset, int options, int *ovector, int ovector_size)
Definition: detect-parse.c:2378
Packet_
Definition: decode.h:411
DecodeEvents_::code
uint8_t code
Definition: decode-events.h:275
SigTableElmt_::Match
int(* Match)(DetectEngineThreadCtx *, Packet *, const Signature *, const SigMatchCtx *)
Definition: detect.h:1171
SigMatchAlloc
SigMatch * SigMatchAlloc(void)
Definition: detect-parse.c:235
DecodeEvents_::event_name
const char * event_name
Definition: decode-events.h:274
decode-events.h
SigMatch_::type
uint8_t type
Definition: detect.h:319
SigMatchCtx_
Used to start a pointer to SigMatch context Should never be dereferenced without casting to something...
Definition: detect.h:313
suricata-common.h
sigmatch_table
SigTableElmt sigmatch_table[DETECT_TBLSIZE]
Definition: detect-parse.c:73
DetectParseRegex_
Definition: detect-parse.h:42
SCLogError
#define SCLogError(err_code,...)
Macro used to log ERROR messages.
Definition: util-debug.h:257
tv
ThreadVars * tv
Definition: fuzz_decodepcapfile.c:29
DetectEngineEventRegister
void DetectEngineEventRegister(void)
Registration function for decode-event: keyword.
Definition: detect-engine-event.c:61
SCMalloc
#define SCMalloc(sz)
Definition: util-mem.h:47
DETECT_STREAM_EVENT
@ DETECT_STREAM_EVENT
Definition: detect-engine-register.h:179
SCFree
#define SCFree(p)
Definition: util-mem.h:61
detect-parse.h
Signature_
Signature container.
Definition: detect.h:522
SigMatch_
a single match condition for a signature
Definition: detect.h:318
DetectEngineEventData_
Definition: detect-engine-event.h:29
suricata.h
PPP_PKT_TOO_SMALL
@ PPP_PKT_TOO_SMALL
Definition: decode-events.h:114
SCReturnInt
#define SCReturnInt(x)
Definition: util-debug.h:304
flow-var.h
SigMatchAppendSMToList
void SigMatchAppendSMToList(Signature *s, SigMatch *new, int list)
Append a SigMatch to the list type.
Definition: detect-parse.c:349
SigTableElmt_::RegisterTests
void(* RegisterTests)(void)
Definition: detect.h:1193