suricata
detect-app-layer-event.c
Go to the documentation of this file.
1 /* Copyright (C) 2007-2012 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 Anoop Saldanha <anoopsaldanha@gmail.com>
22  */
23 
24 #include "suricata-common.h"
25 #include "threads.h"
26 #include "decode.h"
27 
28 #include "app-layer.h"
29 #include "app-layer-protos.h"
30 #include "app-layer-parser.h"
31 #include "app-layer-smtp.h"
32 #include "detect.h"
33 #include "detect-parse.h"
34 #include "detect-engine.h"
35 #include "detect-engine-state.h"
36 #include "detect-app-layer-event.h"
37 
38 #include "flow.h"
39 #include "flow-var.h"
40 #include "flow-util.h"
41 
42 #include "decode-events.h"
43 #include "util-byte.h"
44 #include "util-debug.h"
45 #include "util-unittest.h"
46 #include "util-unittest-helper.h"
47 #include "stream-tcp-util.h"
48 
49 #define MAX_ALPROTO_NAME 50
50 
51 static int DetectAppLayerEventPktMatch(DetectEngineThreadCtx *det_ctx,
52  Packet *p, const Signature *s, const SigMatchCtx *ctx);
53 static int DetectAppLayerEventSetupP1(DetectEngineCtx *, Signature *, const char *);
54 static void DetectAppLayerEventRegisterTests(void);
55 static void DetectAppLayerEventFree(void *);
56 static int DetectEngineAptEventInspect(ThreadVars *tv,
57  DetectEngineCtx *de_ctx, DetectEngineThreadCtx *det_ctx,
58  const Signature *s, const SigMatchData *smd,
59  Flow *f, uint8_t flags, void *alstate,
60  void *tx, uint64_t tx_id);
61 static int g_applayer_events_list_id = 0;
62 
63 /**
64  * \brief Registers the keyword handlers for the "app-layer-event" keyword.
65  */
67 {
68  sigmatch_table[DETECT_AL_APP_LAYER_EVENT].name = "app-layer-event";
69  sigmatch_table[DETECT_AL_APP_LAYER_EVENT].desc = "match on events generated by the App Layer Parsers and the protocol detection engine";
70  sigmatch_table[DETECT_AL_APP_LAYER_EVENT].url = DOC_URL DOC_VERSION "/rules/app-layer.html#app-layer-event";
72  DetectAppLayerEventPktMatch;
73  sigmatch_table[DETECT_AL_APP_LAYER_EVENT].Setup = DetectAppLayerEventSetupP1;
74  sigmatch_table[DETECT_AL_APP_LAYER_EVENT].Free = DetectAppLayerEventFree;
76  DetectAppLayerEventRegisterTests;
77 
78  DetectAppLayerInspectEngineRegister("app-layer-events",
80  DetectEngineAptEventInspect);
81  DetectAppLayerInspectEngineRegister("app-layer-events",
83  DetectEngineAptEventInspect);
84 
85  g_applayer_events_list_id = DetectBufferTypeGetByName("app-layer-events");
86 }
87 
88 static int DetectEngineAptEventInspect(ThreadVars *tv,
89  DetectEngineCtx *de_ctx, DetectEngineThreadCtx *det_ctx,
90  const Signature *s, const SigMatchData *smd,
91  Flow *f, uint8_t flags, void *alstate,
92  void *tx, uint64_t tx_id)
93 {
94  AppLayerDecoderEvents *decoder_events = NULL;
95  int r = 0;
96  AppProto alproto;
97  DetectAppLayerEventData *aled = NULL;
98 
99  alproto = f->alproto;
100  decoder_events = AppLayerParserGetEventsByTx(f->proto, alproto, tx);
101  if (decoder_events == NULL)
102  goto end;
103 
104  while (1) {
105  aled = (DetectAppLayerEventData *)smd->ctx;
107 
108  if (AppLayerDecoderEventsIsEventSet(decoder_events, aled->event_id)) {
109  KEYWORD_PROFILING_END(det_ctx, smd->type, 1);
110 
111  if (smd->is_last)
112  break;
113  smd++;
114  continue;
115  }
116 
117  KEYWORD_PROFILING_END(det_ctx, smd->type, 0);
118  goto end;
119  }
120 
121  r = 1;
122 
123  end:
124  if (r == 1) {
126  } else {
127  if (AppLayerParserGetStateProgress(f->proto, alproto, tx, flags) ==
129  {
131  } else {
133  }
134  }
135 }
136 
137 
138 static int DetectAppLayerEventPktMatch(DetectEngineThreadCtx *det_ctx,
139  Packet *p, const Signature *s, const SigMatchCtx *ctx)
140 {
141  const DetectAppLayerEventData *aled = (const DetectAppLayerEventData *)ctx;
142 
143  return AppLayerDecoderEventsIsEventSet(p->app_layer_events,
144  aled->event_id);
145 }
146 
147 static DetectAppLayerEventData *DetectAppLayerEventParsePkt(const char *arg,
149 {
151 
152  int event_id = 0;
153  int r = 0;
154 
155  r = AppLayerGetPktEventInfo(arg, &event_id);
156  if (r < 0) {
157  SCLogError(SC_ERR_INVALID_SIGNATURE, "app-layer-event keyword "
158  "supplied with packet based event - \"%s\" that isn't "
159  "supported yet.", arg);
160  return NULL;
161  }
162 
163  aled = SCMalloc(sizeof(DetectAppLayerEventData));
164  if (unlikely(aled == NULL))
165  return NULL;
166  memset(aled,0x00,sizeof(*aled));
167  aled->event_id = event_id;
168  *event_type = APP_LAYER_EVENT_TYPE_PACKET;
169 
170  return aled;
171 }
172 
173 static int DetectAppLayerEventParseAppP2(DetectAppLayerEventData *data,
174  uint8_t *ipproto_bitarray,
176 {
177  int event_id = 0;
178  const char *p_idx;
179  uint8_t ipproto;
180  char alproto_name[MAX_ALPROTO_NAME];
181  int r = 0;
182 
183  p_idx = strchr(data->arg, '.');
184  if (strlen(data->arg) > MAX_ALPROTO_NAME) {
185  SCLogError(SC_ERR_INVALID_SIGNATURE, "app-layer-event keyword is too long or malformed");
186  return -1;
187  }
188  strlcpy(alproto_name, data->arg, p_idx - data->arg + 1);
189 
190  if (ipproto_bitarray[IPPROTO_TCP / 8] & 1 << (IPPROTO_TCP % 8)) {
191  ipproto = IPPROTO_TCP;
192  } else if (ipproto_bitarray[IPPROTO_UDP / 8] & 1 << (IPPROTO_UDP % 8)) {
193  ipproto = IPPROTO_UDP;
194  } else {
195  SCLogError(SC_ERR_INVALID_SIGNATURE, "protocol %s is disabled", alproto_name);
196  return -1;
197  }
198 
199  if (!data->needs_detctx) {
200  r = AppLayerParserGetEventInfo(ipproto, data->alproto,
201  p_idx + 1, &event_id, event_type);
202  } else {
203  r = DetectEngineGetEventInfo(p_idx + 1, &event_id, event_type);
204  }
205 
206  if (r < 0) {
207  SCLogError(SC_ERR_INVALID_SIGNATURE, "app-layer-event keyword's "
208  "protocol \"%s\" doesn't have event \"%s\" registered",
209  alproto_name, p_idx + 1);
210  return -1;
211  }
212  data->event_id = event_id;
213 
214  return 0;
215 }
216 
217 static DetectAppLayerEventData *DetectAppLayerEventParseAppP1(const char *arg)
218 {
219  /* period index */
221  AppProto alproto;
222  const char *p_idx;
223  char alproto_name[MAX_ALPROTO_NAME];
224  int needs_detctx = FALSE;
225 
226  p_idx = strchr(arg, '.');
227  if (strlen(arg) > MAX_ALPROTO_NAME) {
228  SCLogError(SC_ERR_INVALID_SIGNATURE, "app-layer-event keyword is too long or malformed");
229  return NULL;
230  }
231  /* + 1 for trailing \0 */
232  strlcpy(alproto_name, arg, p_idx - arg + 1);
233 
234  alproto = AppLayerGetProtoByName(alproto_name);
235  if (alproto == ALPROTO_UNKNOWN) {
236  if (!strcmp(alproto_name, "file")) {
237  needs_detctx = TRUE;
238  } else {
239  SCLogError(SC_ERR_INVALID_SIGNATURE, "app-layer-event keyword "
240  "supplied with unknown protocol \"%s\"",
241  alproto_name);
242  return NULL;
243  }
244  }
245 
246  aled = SCMalloc(sizeof(*aled));
247  if (unlikely(aled == NULL))
248  return NULL;
249  memset(aled, 0x00, sizeof(*aled));
250  aled->alproto = alproto;
251  aled->arg = SCStrdup(arg);
252  aled->needs_detctx = needs_detctx;
253  if (aled->arg == NULL) {
254  SCFree(aled);
255  return NULL;
256  }
257 
258  return aled;
259 }
260 
261 static DetectAppLayerEventData *DetectAppLayerEventParse(const char *arg,
263 {
264  *event_type = 0;
265 
266  if (arg == NULL) {
267  SCLogError(SC_ERR_INVALID_SIGNATURE, "app-layer-event keyword supplied "
268  "with no arguments. This keyword needs an argument.");
269  return NULL;
270  }
271 
272  while (*arg != '\0' && isspace((unsigned char)*arg))
273  arg++;
274 
275  if (strchr(arg, '.') == NULL) {
276  return DetectAppLayerEventParsePkt(arg, event_type);
277  } else {
278  return DetectAppLayerEventParseAppP1(arg);
279  }
280 }
281 
282 static int DetectAppLayerEventSetupP2(Signature *s,
283  SigMatch *sm)
284 {
286 
287  if (DetectAppLayerEventParseAppP2((DetectAppLayerEventData *)sm->ctx, s->proto.proto,
288  &event_type) < 0) {
289  /* DetectAppLayerEventParseAppP2 prints errors */
290 
291  /* sm has been removed from lists by DetectAppLayerEventPrepare */
292  SigMatchFree(sm);
293  return -1;
294  }
295  SigMatchAppendSMToList(s, sm, g_applayer_events_list_id);
296  /* We should have set this flag already in SetupP1 */
297  s->flags |= SIG_FLAG_APPLAYER;
298 
299  return 0;
300 }
301 
302 static int DetectAppLayerEventSetupP1(DetectEngineCtx *de_ctx, Signature *s, const char *arg)
303 {
304  DetectAppLayerEventData *data = NULL;
305  SigMatch *sm = NULL;
307 
308  data = DetectAppLayerEventParse(arg, &event_type);
309  if (data == NULL)
310  goto error;
311 
312  sm = SigMatchAlloc();
313  if (sm == NULL)
314  goto error;
315 
317  sm->ctx = (SigMatchCtx *)data;
318 
319  if (event_type == APP_LAYER_EVENT_TYPE_PACKET) {
321  } else {
322  if (DetectSignatureSetAppProto(s, data->alproto) != 0)
323  goto error;
324 
325  SigMatchAppendSMToList(s, sm, g_applayer_events_list_id);
326  }
327 
328  return 0;
329 
330 error:
331  if (data)
332  SCFree(data);
333  if (sm) {
334  sm->ctx = NULL;
335  SigMatchFree(sm);
336  }
337  return -1;
338 }
339 
340 static void DetectAppLayerEventFree(void *ptr)
341 {
343  if (data->arg != NULL)
344  SCFree(data->arg);
345 
346  SCFree(ptr);
347 
348  return;
349 }
350 
352 {
353  SigMatch *sm = s->init_data->smlists[g_applayer_events_list_id];
354  SigMatch *smn;
355  s->init_data->smlists[g_applayer_events_list_id] = NULL;
356  s->init_data->smlists_tail[g_applayer_events_list_id] = NULL;
357 
358  while (sm != NULL) {
359  // save it for later use in loop
360  smn = sm->next;
361  /* these will be overwritten in SigMatchAppendSMToList
362  * called by DetectAppLayerEventSetupP2
363  */
364  sm->next = sm->prev = NULL;
365  if (DetectAppLayerEventSetupP2(s, sm) < 0) {
366  // current one was freed, let's free the next ones
367  sm = smn;
368  while(sm) {
369  smn = sm->next;
370  SigMatchFree(sm);
371  sm = smn;
372  }
373  return -1;
374  }
375  sm = smn;
376  }
377 
378  return 0;
379 }
380 
381 /**********************************Unittests***********************************/
382 
383 #ifdef UNITTESTS /* UNITTESTS */
384 #include "stream-tcp-private.h"
385 #include "stream-tcp-reassemble.h"
386 #include "stream-tcp.h"
387 
388 #define APP_LAYER_EVENT_TEST_MAP_EVENT1 0
389 #define APP_LAYER_EVENT_TEST_MAP_EVENT2 1
390 #define APP_LAYER_EVENT_TEST_MAP_EVENT3 2
391 #define APP_LAYER_EVENT_TEST_MAP_EVENT4 3
392 #define APP_LAYER_EVENT_TEST_MAP_EVENT5 4
393 #define APP_LAYER_EVENT_TEST_MAP_EVENT6 5
394 
396  { "event1", APP_LAYER_EVENT_TEST_MAP_EVENT1 },
397  { "event2", APP_LAYER_EVENT_TEST_MAP_EVENT2 },
398  { "event3", APP_LAYER_EVENT_TEST_MAP_EVENT3 },
399  { "event4", APP_LAYER_EVENT_TEST_MAP_EVENT4 },
400  { "event5", APP_LAYER_EVENT_TEST_MAP_EVENT5 },
401  { "event6", APP_LAYER_EVENT_TEST_MAP_EVENT6 },
402 };
403 
404 static int DetectAppLayerEventTestGetEventInfo(const char *event_name,
405  int *event_id,
407 {
408  *event_id = SCMapEnumNameToValue(event_name, app_layer_event_test_map);
409  if (*event_id == -1) {
410  SCLogError(SC_ERR_INVALID_ENUM_MAP, "event \"%s\" not present in "
411  "app-layer-event's test enum map table.", event_name);
412  /* this should be treated as fatal */
413  return -1;
414  }
415 
416  *event_type = APP_LAYER_EVENT_TYPE_TRANSACTION;
417 
418  return 0;
419 }
420 
421 
422 static int DetectAppLayerEventTest01(void)
423 {
426  DetectAppLayerEventTestGetEventInfo);
427 
429  int result = 0;
430  uint8_t ipproto_bitarray[256 / 8];
431  memset(ipproto_bitarray, 0, sizeof(ipproto_bitarray));
432  ipproto_bitarray[IPPROTO_TCP / 8] |= 1 << (IPPROTO_TCP % 8);
433 
434  DetectAppLayerEventData *aled = DetectAppLayerEventParse("smtp.event1",
435  &event_type);
436  if (aled == NULL)
437  goto end;
438  if (DetectAppLayerEventParseAppP2(aled, ipproto_bitarray, &event_type) < 0) {
439  printf("failure 1\n");
440  goto end;
441  }
442  if (aled->alproto != ALPROTO_SMTP ||
444  printf("test failure. Holding wrong state\n");
445  goto end;
446  }
447 
448  result = 1;
449 
450  end:
452  if (aled != NULL)
453  DetectAppLayerEventFree(aled);
454  return result;
455 }
456 
457 static int DetectAppLayerEventTest02(void)
458 {
460 
462  DetectAppLayerEventTestGetEventInfo);
464  DetectAppLayerEventTestGetEventInfo);
466  DetectAppLayerEventTestGetEventInfo);
468  DetectAppLayerEventTestGetEventInfo);
469 
471  uint8_t ipproto_bitarray[256 / 8];
472  memset(ipproto_bitarray, 0, sizeof(ipproto_bitarray));
473  ipproto_bitarray[IPPROTO_TCP / 8] |= 1 << (IPPROTO_TCP % 8);
474 
475  DetectAppLayerEventData *aled = DetectAppLayerEventParse("smtp.event1",
476  &event_type);
477  FAIL_IF_NULL(aled);
478  FAIL_IF(DetectAppLayerEventParseAppP2(aled, ipproto_bitarray, &event_type) < 0);
479  FAIL_IF(aled->alproto != ALPROTO_SMTP);
481 
482  aled = DetectAppLayerEventParse("smtp.event4",
483  &event_type);
484  FAIL_IF_NULL(aled);
485  FAIL_IF(DetectAppLayerEventParseAppP2(aled, ipproto_bitarray, &event_type) < 0);
486  FAIL_IF(aled->alproto != ALPROTO_SMTP);
488 
489  aled = DetectAppLayerEventParse("http.event2",
490  &event_type);
491  FAIL_IF_NULL(aled);
492  FAIL_IF(DetectAppLayerEventParseAppP2(aled, ipproto_bitarray, &event_type) < 0);
493  FAIL_IF(aled->alproto != ALPROTO_HTTP);
495 
496  aled = DetectAppLayerEventParse("smb.event3",
497  &event_type);
498  FAIL_IF_NULL(aled);
499  FAIL_IF(DetectAppLayerEventParseAppP2(aled, ipproto_bitarray, &event_type) < 0);
500  FAIL_IF(aled->alproto != ALPROTO_SMB);
502 
503  aled = DetectAppLayerEventParse("ftp.event5",
504  &event_type);
505  FAIL_IF_NULL(aled);
506  FAIL_IF(DetectAppLayerEventParseAppP2(aled, ipproto_bitarray, &event_type) < 0);
507  FAIL_IF(aled->alproto != ALPROTO_FTP);
509 
511  DetectAppLayerEventFree(aled);
512  PASS;
513 }
514 
515 static int DetectAppLayerEventTest03(void)
516 {
517  ThreadVars tv;
518  TcpReassemblyThreadCtx *ra_ctx = NULL;
519  Packet *p = NULL;
520  Flow *f = NULL;
521  TcpSession ssn;
522  TcpStream stream_ts, stream_tc;
523  DetectEngineCtx *de_ctx = NULL;
524  DetectEngineThreadCtx *det_ctx = NULL;
525 
526  uint8_t buf_ts[] = "GET /index.html HTTP/1.1\r\n"
527  "Host: 127.0.0.1\r\n"
528  "User-Agent: Mozilla/5.0 (X11; U; Linux x86_64; en-US; rv:1.9.2.3) Gecko/20100402 Firefox/3.6.3\r\n"
529  "Accept: text/html,application/xhtml+xml,application/xml;q=0.9,*/*;q=0.8\r\n"
530  "Accept-Language: en-us,en;q=0.5\r\n"
531  "Accept-Encoding: gzip,deflate\r\n"
532  "Accept-Charset: ISO-8859-1,utf-8;q=0.7,*;q=0.7\r\n"
533  "Keep-Alive: 115\r\n"
534  "Connection: keep-alive\r\n"
535  "\r\n";
536  uint8_t buf_tc[] = "HTTP/1.1 200 OK\r\n"
537  "Date: Fri, 22 Oct 2010 12:31:08 GMT\r\n"
538  "Server: Apache/2.2.15 (Unix) DAV/2\r\n"
539  "Last-Modified: Sat, 20 Nov 2004 20:16:24 GMT\r\n"
540  "ETag: \"ab8486-2c-3e9564c23b600\"\r\n"
541  "Accept-Ranges: bytes\r\n"
542  "Content-Length: 44\r\n"
543  "Keep-Alive: timeout=5, max=100\r\n"
544  "Connection: Keep-Alive\r\n"
545  "Content-Type: text/html\r\n"
546  "\r\n"
547  "<html><body><h1>It works!</h1></body></html>";
548 
549  memset(&tv, 0, sizeof (ThreadVars));
550  memset(&ssn, 0, sizeof(TcpSession));
551  memset(&stream_ts, 0, sizeof(TcpStream));
552  memset(&stream_tc, 0, sizeof(TcpStream));
553 
555 
556  de_ctx = DetectEngineCtxInit();
557  FAIL_IF(de_ctx == NULL);
558  de_ctx->flags |= DE_QUIET;
559  de_ctx->sig_list = SigInit(de_ctx, "alert tcp any any -> any any "
560  "(app-layer-event: applayer_mismatch_protocol_both_directions; "
561  "sid:1;)");
562  FAIL_IF(de_ctx->sig_list == NULL);
563  SigGroupBuild(de_ctx);
564  DetectEngineThreadCtxInit(&tv, (void *)de_ctx, (void *)&det_ctx);
565 
566  f = UTHBuildFlow(AF_INET, "1.2.3.4", "1.2.3.5", 200, 220);
567  FAIL_IF(f == NULL);
568  FLOW_INITIALIZE(f);
569  f->protoctx = &ssn;
570  f->proto = IPPROTO_TCP;
571  f->flags |= FLOW_IPV4;
572 
573  p = PacketGetFromAlloc();
574  FAIL_IF(unlikely(p == NULL));
575  p->flow = f;
576  p->src.family = AF_INET;
577  p->dst.family = AF_INET;
578  p->proto = IPPROTO_TCP;
579 
580  StreamTcpUTInit(&ra_ctx);
581 
583  TcpStream *stream = &stream_ts;
584  FAIL_IF(AppLayerHandleTCPData(&tv, ra_ctx, p, f, &ssn, &stream, buf_ts,
585  sizeof(buf_ts), STREAM_TOSERVER | STREAM_START) < 0);
586 
587  SigMatchSignatures(&tv, de_ctx, det_ctx, p);
588 
589  FAIL_IF (PacketAlertCheck(p, 1));
590 
592  stream = &stream_tc;
593  FAIL_IF (AppLayerHandleTCPData(&tv, ra_ctx, p, f, &ssn, &stream, buf_tc,
594  sizeof(buf_tc), STREAM_TOCLIENT | STREAM_START) < 0);
595 
596  SigMatchSignatures(&tv, de_ctx, det_ctx, p);
597 
598  FAIL_IF(PacketAlertCheck(p, 1));
599 
600  StreamTcpUTDeinit(ra_ctx);
601  PASS;
602 }
603 
604 static int DetectAppLayerEventTest04(void)
605 {
606  ThreadVars tv;
607  TcpReassemblyThreadCtx *ra_ctx = NULL;
608  Packet *p = NULL;
609  Flow *f = NULL;
610  TcpSession ssn;
611  TcpStream stream_ts, stream_tc;
612  DetectEngineCtx *de_ctx = NULL;
613  DetectEngineThreadCtx *det_ctx = NULL;
614 
615  uint8_t buf_ts[] = "GET /index.html HTTP/1.1\r\n"
616  "Host: 127.0.0.1\r\n"
617  "User-Agent: Mozilla/5.0 (X11; U; Linux x86_64; en-US; rv:1.9.2.3) Gecko/20100402 Firefox/3.6.3\r\n"
618  "Accept: text/html,application/xhtml+xml,application/xml;q=0.9,*/*;q=0.8\r\n"
619  "Accept-Language: en-us,en;q=0.5\r\n"
620  "Accept-Encoding: gzip,deflate\r\n"
621  "Accept-Charset: ISO-8859-1,utf-8;q=0.7,*;q=0.7\r\n"
622  "Keep-Alive: 115\r\n"
623  "Connection: keep-alive\r\n"
624  "\r\n";
625  uint8_t buf_tc[] = "XTTP/1.1 200 OK\r\n"
626  "Date: Fri, 22 Oct 2010 12:31:08 GMT\r\n"
627  "Server: Apache/2.2.15 (Unix) DAV/2\r\n"
628  "Last-Modified: Sat, 20 Nov 2004 20:16:24 GMT\r\n"
629  "ETag: \"ab8486-2c-3e9564c23b600\"\r\n"
630  "Accept-Ranges: bytes\r\n"
631  "Content-Length: 44\r\n"
632  "Keep-Alive: timeout=5, max=100\r\n"
633  "Connection: Keep-Alive\r\n"
634  "Content-Type: text/html\r\n"
635  "\r\n"
636  "<html><body><h1>It works!</h1></body></html>";
637 
638  memset(&tv, 0, sizeof (ThreadVars));
639  memset(&ssn, 0, sizeof(TcpSession));
640  memset(&stream_ts, 0, sizeof(TcpStream));
641  memset(&stream_tc, 0, sizeof(TcpStream));
642 
644 
645  de_ctx = DetectEngineCtxInit();
646  FAIL_IF (de_ctx == NULL);
647  de_ctx->flags |= DE_QUIET;
648  de_ctx->sig_list = SigInit(de_ctx, "alert tcp any any -> any any "
649  "(app-layer-event: applayer_detect_protocol_only_one_direction; "
650  "sid:1;)");
651  FAIL_IF(de_ctx->sig_list == NULL);
652  SigGroupBuild(de_ctx);
653  DetectEngineThreadCtxInit(&tv, (void *)de_ctx, (void *)&det_ctx);
654 
655  f = UTHBuildFlow(AF_INET, "1.2.3.4", "1.2.3.5", 200, 220);
656  FAIL_IF (f == NULL);
657  FLOW_INITIALIZE(f);
658  f->protoctx = &ssn;
659  f->proto = IPPROTO_TCP;
660  f->flags |= FLOW_IPV4;
661 
662  p = PacketGetFromAlloc();
663  FAIL_IF(unlikely(p == NULL));
664  p->flow = f;
665  p->src.family = AF_INET;
666  p->dst.family = AF_INET;
667  p->proto = IPPROTO_TCP;
668 
669  StreamTcpUTInit(&ra_ctx);
670 
672  TcpStream *stream = &stream_ts;
673  FAIL_IF(AppLayerHandleTCPData(&tv, ra_ctx, p, f, &ssn, &stream, buf_ts,
674  sizeof(buf_ts), STREAM_TOSERVER | STREAM_START) < 0);
675  SigMatchSignatures(&tv, de_ctx, det_ctx, p);
676  FAIL_IF (PacketAlertCheck(p, 1));
677 
679  stream = &stream_tc;
680  FAIL_IF (AppLayerHandleTCPData(&tv, ra_ctx, p, f, &ssn, &stream, buf_tc,
681  sizeof(buf_tc), STREAM_TOCLIENT | STREAM_START) < 0);
682  SigMatchSignatures(&tv, de_ctx, det_ctx, p);
683  FAIL_IF (!PacketAlertCheck(p, 1));
684 
685  StreamTcpUTDeinit(ra_ctx);
686  PASS;
687 }
688 
689 static int DetectAppLayerEventTest05(void)
690 {
691  ThreadVars tv;
692  TcpReassemblyThreadCtx *ra_ctx = NULL;
693  Packet *p = NULL;
694  Flow *f = NULL;
695  TcpSession ssn;
696  TcpStream stream_ts, stream_tc;
697  DetectEngineCtx *de_ctx = NULL;
698  DetectEngineThreadCtx *det_ctx = NULL;
699 
700  uint8_t buf_ts[] = "GET /index.html HTTP/1.1\r\n"
701  "Host: 127.0.0.1\r\n"
702  "User-Agent: Mozilla/5.0 (X11; U; Linux x86_64; en-US; rv:1.9.2.3) Gecko/20100402 Firefox/3.6.3\r\n"
703  "Accept: text/html,application/xhtml+xml,application/xml;q=0.9,*/*;q=0.8\r\n"
704  "Accept-Language: en-us,en;q=0.5\r\n"
705  "Accept-Encoding: gzip,deflate\r\n"
706  "Accept-Charset: ISO-8859-1,utf-8;q=0.7,*;q=0.7\r\n"
707  "Keep-Alive: 115\r\n"
708  "Connection: keep-alive\r\n"
709  "\r\n";
710  /* tls */
711  uint8_t buf_tc[] = {
712  0x16, 0x03, 0x01, 0x00, 0x86, 0x10, 0x00, 0x00,
713  0x82, 0x00, 0x80, 0xd3, 0x6f, 0x1f, 0x63, 0x82,
714  0x8d, 0x75, 0x77, 0x8c, 0x91, 0xbc, 0xa1, 0x3d,
715  0xbb, 0xe1, 0xb5, 0xd3, 0x31, 0x92, 0x59, 0x2b,
716  0x2c, 0x43, 0x96, 0xa3, 0xaa, 0x23, 0x92, 0xd0,
717  0x91, 0x2a, 0x5e, 0x10, 0x5b, 0xc8, 0xc1, 0xe2,
718  0xd3, 0x5c, 0x8b, 0x8c, 0x91, 0x9e, 0xc2, 0xf2,
719  0x9c, 0x3c, 0x4f, 0x37, 0x1e, 0x20, 0x5e, 0x33,
720  0xd5, 0xf0, 0xd6, 0xaf, 0x89, 0xf5, 0xcc, 0xb2,
721  0xcf, 0xc1, 0x60, 0x3a, 0x46, 0xd5, 0x4e, 0x2a,
722  0xb6, 0x6a, 0xb9, 0xfc, 0x32, 0x8b, 0xe0, 0x6e,
723  0xa0, 0xed, 0x25, 0xa0, 0xa4, 0x82, 0x81, 0x73,
724  0x90, 0xbf, 0xb5, 0xde, 0xeb, 0x51, 0x8d, 0xde,
725  0x5b, 0x6f, 0x94, 0xee, 0xba, 0xe5, 0x69, 0xfa,
726  0x1a, 0x80, 0x30, 0x54, 0xeb, 0x12, 0x01, 0xb9,
727  0xfe, 0xbf, 0x82, 0x95, 0x01, 0x7b, 0xb0, 0x97,
728  0x14, 0xc2, 0x06, 0x3c, 0x69, 0xfb, 0x1c, 0x66,
729  0x47, 0x17, 0xd9, 0x14, 0x03, 0x01, 0x00, 0x01,
730  0x01, 0x16, 0x03, 0x01, 0x00, 0x30, 0xf6, 0xbc,
731  0x0d, 0x6f, 0xe8, 0xbb, 0xaa, 0xbf, 0x14, 0xeb,
732  0x7b, 0xcc, 0x6c, 0x28, 0xb0, 0xfc, 0xa6, 0x01,
733  0x2a, 0x97, 0x96, 0x17, 0x5e, 0xe8, 0xb4, 0x4e,
734  0x78, 0xc9, 0x04, 0x65, 0x53, 0xb6, 0x93, 0x3d,
735  0xeb, 0x44, 0xee, 0x86, 0xf9, 0x80, 0x49, 0x45,
736  0x21, 0x34, 0xd1, 0xee, 0xc8, 0x9c,
737  };
738 
739  memset(&tv, 0, sizeof (ThreadVars));
740  memset(&ssn, 0, sizeof(TcpSession));
741  memset(&stream_ts, 0, sizeof(TcpStream));
742  memset(&stream_tc, 0, sizeof(TcpStream));
743 
745 
746  de_ctx = DetectEngineCtxInit();
747  FAIL_IF (de_ctx == NULL);
748  de_ctx->flags |= DE_QUIET;
749  de_ctx->sig_list = SigInit(de_ctx, "alert tcp any any -> any any "
750  "(app-layer-event: applayer_mismatch_protocol_both_directions; "
751  "sid:1;)");
752  FAIL_IF (de_ctx->sig_list == NULL);
753  SigGroupBuild(de_ctx);
754  DetectEngineThreadCtxInit(&tv, (void *)de_ctx, (void *)&det_ctx);
755 
756  f = UTHBuildFlow(AF_INET, "1.2.3.4", "1.2.3.5", 200, 220);
757  FAIL_IF (f == NULL);
758  FLOW_INITIALIZE(f);
759  f->protoctx = &ssn;
760  f->proto = IPPROTO_TCP;
761  f->flags |= FLOW_IPV4;
762 
763  p = PacketGetFromAlloc();
764  FAIL_IF (unlikely(p == NULL));
765  p->flow = f;
766  p->src.family = AF_INET;
767  p->dst.family = AF_INET;
768  p->proto = IPPROTO_TCP;
769 
770  StreamTcpUTInit(&ra_ctx);
771 
773  TcpStream *stream = &stream_ts;
774  FAIL_IF (AppLayerHandleTCPData(&tv, ra_ctx, p, f, &ssn, &stream, buf_ts,
775  sizeof(buf_ts), STREAM_TOSERVER | STREAM_START) < 0);
776  SigMatchSignatures(&tv, de_ctx, det_ctx, p);
777  FAIL_IF (PacketAlertCheck(p, 1));
778 
780  stream = &stream_tc;
781  FAIL_IF (AppLayerHandleTCPData(&tv, ra_ctx, p, f, &ssn, &stream, buf_tc,
782  sizeof(buf_tc), STREAM_TOCLIENT | STREAM_START) < 0);
783  SigMatchSignatures(&tv, de_ctx, det_ctx, p);
784  FAIL_IF (!PacketAlertCheck(p, 1));
785 
786  StreamTcpUTDeinit(ra_ctx);
787  PASS;
788 }
789 
790 static int DetectAppLayerEventTest06(void)
791 {
793  uint8_t ipproto_bitarray[256 / 8];
794  memset(ipproto_bitarray, 0, sizeof(ipproto_bitarray));
795  ipproto_bitarray[IPPROTO_TCP / 8] |= 1 << (IPPROTO_TCP % 8);
796 
797  DetectAppLayerEventData *aled = DetectAppLayerEventParse("file.test",
798  &event_type);
799 
800  FAIL_IF_NULL(aled);
801 
802  FAIL_IF(DetectAppLayerEventParseAppP2(aled, ipproto_bitarray, &event_type) < 0);
803 
804  FAIL_IF(aled->alproto != ALPROTO_UNKNOWN);
806 
807  DetectAppLayerEventFree(aled);
808  PASS;
809 }
810 #endif /* UNITTESTS */
811 
812 /**
813  * \brief This function registers unit tests for "app-layer-event" keyword.
814  */
815 void DetectAppLayerEventRegisterTests(void)
816 {
817 #ifdef UNITTESTS /* UNITTESTS */
818  UtRegisterTest("DetectAppLayerEventTest01", DetectAppLayerEventTest01);
819  UtRegisterTest("DetectAppLayerEventTest02", DetectAppLayerEventTest02);
820  UtRegisterTest("DetectAppLayerEventTest03", DetectAppLayerEventTest03);
821  UtRegisterTest("DetectAppLayerEventTest04", DetectAppLayerEventTest04);
822  UtRegisterTest("DetectAppLayerEventTest05", DetectAppLayerEventTest05);
823  UtRegisterTest("DetectAppLayerEventTest06", DetectAppLayerEventTest06);
824 #endif /* UNITTESTS */
825 
826  return;
827 }
enum AppLayerEventType_ AppLayerEventType
SigTableElmt sigmatch_table[DETECT_TBLSIZE]
Definition: detect.h:1448
DetectProto proto
Definition: detect.h:539
SignatureInitData * init_data
Definition: detect.h:591
uint16_t flags
int(* Setup)(DetectEngineCtx *, Signature *, const char *)
Definition: detect.h:1186
void StreamTcpUTInit(TcpReassemblyThreadCtx **ra_ctx)
int DetectSignatureSetAppProto(Signature *s, AppProto alproto)
struct Flow_ * flow
Definition: decode.h:445
#define KEYWORD_PROFILING_END(ctx, type, m)
AppLayerDecoderEvents * app_layer_events
Definition: decode.h:567
size_t strlcpy(char *dst, const char *src, size_t siz)
Definition: util-strlcpyu.c:43
#define APP_LAYER_EVENT_TEST_MAP_EVENT2
int PacketAlertCheck(Packet *p, uint32_t sid)
Check if a certain sid alerted, this is used in the test functions.
int DetectAppLayerEventPrepare(Signature *s)
uint32_t flags
Definition: detect.h:523
uint32_t event_type
uint8_t proto
Definition: flow.h:344
int AppLayerParserGetStateProgressCompletionStatus(AppProto alproto, uint8_t direction)
#define FALSE
int AppLayerParserGetStateProgress(uint8_t ipproto, AppProto alproto, void *alstate, uint8_t flags)
get the progress value for a tx/protocol
#define PASS
Pass the test.
#define unlikely(expr)
Definition: util-optimize.h:35
uint8_t is_last
Definition: detect.h:329
Signature * SigInit(DetectEngineCtx *, const char *)
Parses a signature and adds it to the Detection Engine Context.
struct SigMatch_ * prev
Definition: detect.h:323
Signature * sig_list
Definition: detect.h:767
#define FAIL_IF(expr)
Fail a test if expression evaluates to false.
Definition: util-unittest.h:71
uint8_t proto[256/8]
Address dst
Definition: decode.h:413
Data needed for Match()
Definition: detect.h:327
#define MAX_ALPROTO_NAME
AppLayerDecoderEvents * AppLayerParserGetEventsByTx(uint8_t ipproto, AppProto alproto, void *tx)
TmEcode DetectEngineThreadCtxInit(ThreadVars *, void *, void **)
initialize thread specific detection engine context
int SCMapEnumNameToValue(const char *enum_name, SCEnumCharMap *table)
Maps a string name to an enum value from the supplied table. Please specify the last element of any m...
Definition: util-enum.c:41
const char * name
Definition: detect.h:1200
uint16_t AppProto
Signature container.
Definition: detect.h:522
AppProto AppLayerGetProtoByName(char *alproto_name)
Given a protocol string, returns the corresponding internal protocol id.
Definition: app-layer.c:759
void AppLayerParserBackupParserTable(void)
#define TRUE
Used to start a pointer to SigMatch context Should never be dereferenced without casting to something...
Definition: detect.h:313
#define SIG_FLAG_APPLAYER
Definition: detect.h:218
void * protoctx
Definition: flow.h:400
struct SigMatch_ * next
Definition: detect.h:322
main detection engine ctx
Definition: detect.h:761
void StreamTcpUTDeinit(TcpReassemblyThreadCtx *ra_ctx)
#define KEYWORD_PROFILING_START
SCEnumCharMap app_layer_event_test_map[]
#define DE_QUIET
Definition: detect.h:292
Flow * UTHBuildFlow(int family, const char *src, const char *dst, Port sp, Port dp)
int DetectBufferTypeGetByName(const char *name)
Data structure to store app layer decoder events.
#define SIG_FLAG_TOCLIENT
Definition: detect.h:237
char family
Definition: decode.h:111
uint8_t proto
Definition: decode.h:430
uint8_t flags
Definition: detect.h:762
#define DETECT_ENGINE_INSPECT_SIG_MATCH
void AppLayerParserRestoreParserTable(void)
Data structures and function prototypes for keeping state for the detection engine.
void(* Free)(void *)
Definition: detect.h:1191
void AppLayerParserRegisterGetEventInfo(uint8_t ipproto, AppProto alproto, int(*StateGetEventInfo)(const char *event_name, int *event_id, AppLayerEventType *event_type))
#define SCLogError(err_code,...)
Macro used to log ERROR messages.
Definition: util-debug.h:294
int SigGroupBuild(DetectEngineCtx *de_ctx)
Convert the signature list into the runtime match structure.
void UtRegisterTest(const char *name, int(*TestFn)(void))
Register unit test.
void SigMatchSignatures(ThreadVars *th_v, DetectEngineCtx *de_ctx, DetectEngineThreadCtx *det_ctx, Packet *p)
wrapper for old tests
Definition: detect.c:1669
#define SIG_FLAG_TOSERVER
Definition: detect.h:236
uint8_t flowflags
Definition: decode.h:439
#define STREAM_TOCLIENT
Definition: stream.h:32
#define FLOW_PKT_TOSERVER
Definition: flow.h:201
struct SigMatch_ ** smlists_tail
Definition: detect.h:518
int(* Match)(DetectEngineThreadCtx *, Packet *, const Signature *, const SigMatchCtx *)
Definition: detect.h:1170
int8_t data_first_seen_dir
uint8_t type
Definition: detect.h:319
#define APP_LAYER_EVENT_TEST_MAP_EVENT6
#define APP_LAYER_EVENT_TEST_MAP_EVENT5
const char * desc
Definition: detect.h:1202
void SigMatchAppendSMToList(Signature *s, SigMatch *new, int list)
Append a SigMatch to the list type.
Definition: detect-parse.c:346
int DetectEngineGetEventInfo(const char *event_name, int *event_id, AppLayerEventType *event_type)
int AppLayerHandleTCPData(ThreadVars *tv, TcpReassemblyThreadCtx *ra_ctx, Packet *p, Flow *f, TcpSession *ssn, TcpStream **stream, uint8_t *data, uint32_t data_len, uint8_t flags)
handle TCP data for the app-layer.
Definition: app-layer.c:563
struct SigMatch_ ** smlists
Definition: detect.h:516
SigMatchCtx * ctx
Definition: detect.h:321
#define DETECT_ENGINE_INSPECT_SIG_CANT_MATCH
#define SCMalloc(a)
Definition: util-mem.h:222
uint8_t type
Definition: detect.h:328
#define DETECT_ENGINE_INSPECT_SIG_NO_MATCH
#define SCFree(a)
Definition: util-mem.h:322
uint16_t tx_id
void DetectAppLayerEventRegister(void)
Registers the keyword handlers for the "app-layer-event" keyword.
#define APP_LAYER_EVENT_TEST_MAP_EVENT3
void SigMatchFree(SigMatch *sm)
free a SigMatch
Definition: detect-parse.c:247
#define STREAM_START
Definition: stream.h:29
const char * url
Definition: detect.h:1203
#define FLOW_INITIALIZE(f)
Definition: flow-util.h:39
int AppLayerGetPktEventInfo(const char *event_name, int *event_id)
#define STREAM_TOSERVER
Definition: stream.h:31
#define SCStrdup(a)
Definition: util-mem.h:268
#define FAIL_IF_NULL(expr)
Fail a test if expression evaluates to NULL.
Definition: util-unittest.h:89
#define DOC_URL
Definition: suricata.h:86
SigMatch * SigMatchAlloc(void)
Definition: detect-parse.c:232
Per thread variable structure.
Definition: threadvars.h:57
#define APP_LAYER_EVENT_TEST_MAP_EVENT1
#define FLOW_PKT_TOCLIENT
Definition: flow.h:202
AppProto alproto
application level protocol
Definition: flow.h:409
#define DOC_VERSION
Definition: suricata.h:91
#define APP_LAYER_EVENT_TEST_MAP_EVENT4
Flow data structure.
Definition: flow.h:325
#define FLOW_IPV4
Definition: flow.h:94
uint32_t flags
Definition: flow.h:379
void DetectAppLayerInspectEngineRegister(const char *name, AppProto alproto, uint32_t dir, int progress, InspectEngineFuncPtr Callback)
register inspect engine at start up time
void(* RegisterTests)(void)
Definition: detect.h:1192
a single match condition for a signature
Definition: detect.h:318
int AppLayerParserGetEventInfo(uint8_t ipproto, AppProto alproto, const char *event_name, int *event_id, AppLayerEventType *event_type)
Packet * PacketGetFromAlloc(void)
Get a malloced packet.
Definition: decode.c:141
Address src
Definition: decode.h:412
SigMatchCtx * ctx
Definition: detect.h:330
DetectEngineCtx * DetectEngineCtxInit(void)