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