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