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";
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, tx);
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(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  SigMatch *smn;
353  s->init_data->smlists[g_applayer_events_list_id] = NULL;
354  s->init_data->smlists_tail[g_applayer_events_list_id] = NULL;
355 
356  while (sm != NULL) {
357  // save it for later use in loop
358  smn = sm->next;
359  /* these will be overwritten in SigMatchAppendSMToList
360  * called by DetectAppLayerEventSetupP2
361  */
362  sm->next = sm->prev = NULL;
363  if (DetectAppLayerEventSetupP2(s, sm) < 0) {
364  // current one was freed, let's free the next ones
365  sm = smn;
366  while(sm) {
367  smn = sm->next;
368  SigMatchFree(sm);
369  sm = smn;
370  }
371  return -1;
372  }
373  sm = smn;
374  }
375 
376  return 0;
377 }
378 
379 /**********************************Unittests***********************************/
380 
381 #ifdef UNITTESTS /* UNITTESTS */
382 #include "stream-tcp-private.h"
383 #include "stream-tcp-reassemble.h"
384 #include "stream-tcp.h"
385 
386 #define APP_LAYER_EVENT_TEST_MAP_EVENT1 0
387 #define APP_LAYER_EVENT_TEST_MAP_EVENT2 1
388 #define APP_LAYER_EVENT_TEST_MAP_EVENT3 2
389 #define APP_LAYER_EVENT_TEST_MAP_EVENT4 3
390 #define APP_LAYER_EVENT_TEST_MAP_EVENT5 4
391 #define APP_LAYER_EVENT_TEST_MAP_EVENT6 5
392 
394  { "event1", APP_LAYER_EVENT_TEST_MAP_EVENT1 },
395  { "event2", APP_LAYER_EVENT_TEST_MAP_EVENT2 },
396  { "event3", APP_LAYER_EVENT_TEST_MAP_EVENT3 },
397  { "event4", APP_LAYER_EVENT_TEST_MAP_EVENT4 },
398  { "event5", APP_LAYER_EVENT_TEST_MAP_EVENT5 },
399  { "event6", APP_LAYER_EVENT_TEST_MAP_EVENT6 },
400 };
401 
402 static int DetectAppLayerEventTestGetEventInfo(const char *event_name,
403  int *event_id,
405 {
406  *event_id = SCMapEnumNameToValue(event_name, app_layer_event_test_map);
407  if (*event_id == -1) {
408  SCLogError(SC_ERR_INVALID_ENUM_MAP, "event \"%s\" not present in "
409  "app-layer-event's test enum map table.", event_name);
410  /* this should be treated as fatal */
411  return -1;
412  }
413 
414  *event_type = APP_LAYER_EVENT_TYPE_TRANSACTION;
415 
416  return 0;
417 }
418 
419 
420 static int DetectAppLayerEventTest01(void)
421 {
424  DetectAppLayerEventTestGetEventInfo);
425 
427  int result = 0;
428  uint8_t ipproto_bitarray[256 / 8];
429  memset(ipproto_bitarray, 0, sizeof(ipproto_bitarray));
430  ipproto_bitarray[IPPROTO_TCP / 8] |= 1 << (IPPROTO_TCP % 8);
431 
432  DetectAppLayerEventData *aled = DetectAppLayerEventParse("smtp.event1",
433  &event_type);
434  if (aled == NULL)
435  goto end;
436  if (DetectAppLayerEventParseAppP2(aled, ipproto_bitarray, &event_type) < 0) {
437  printf("failure 1\n");
438  goto end;
439  }
440  if (aled->alproto != ALPROTO_SMTP ||
442  printf("test failure. Holding wrong state\n");
443  goto end;
444  }
445 
446  result = 1;
447 
448  end:
450  if (aled != NULL)
451  DetectAppLayerEventFree(aled);
452  return result;
453 }
454 
455 static int DetectAppLayerEventTest02(void)
456 {
458 
460  DetectAppLayerEventTestGetEventInfo);
462  DetectAppLayerEventTestGetEventInfo);
464  DetectAppLayerEventTestGetEventInfo);
466  DetectAppLayerEventTestGetEventInfo);
467 
469  uint8_t ipproto_bitarray[256 / 8];
470  memset(ipproto_bitarray, 0, sizeof(ipproto_bitarray));
471  ipproto_bitarray[IPPROTO_TCP / 8] |= 1 << (IPPROTO_TCP % 8);
472 
473  DetectAppLayerEventData *aled = DetectAppLayerEventParse("smtp.event1",
474  &event_type);
475  FAIL_IF_NULL(aled);
476  FAIL_IF(DetectAppLayerEventParseAppP2(aled, ipproto_bitarray, &event_type) < 0);
477  FAIL_IF(aled->alproto != ALPROTO_SMTP);
479 
480  aled = DetectAppLayerEventParse("smtp.event4",
481  &event_type);
482  FAIL_IF_NULL(aled);
483  FAIL_IF(DetectAppLayerEventParseAppP2(aled, ipproto_bitarray, &event_type) < 0);
484  FAIL_IF(aled->alproto != ALPROTO_SMTP);
486 
487  aled = DetectAppLayerEventParse("http.event2",
488  &event_type);
489  FAIL_IF_NULL(aled);
490  FAIL_IF(DetectAppLayerEventParseAppP2(aled, ipproto_bitarray, &event_type) < 0);
491  FAIL_IF(aled->alproto != ALPROTO_HTTP);
493 
494  aled = DetectAppLayerEventParse("smb.event3",
495  &event_type);
496  FAIL_IF_NULL(aled);
497  FAIL_IF(DetectAppLayerEventParseAppP2(aled, ipproto_bitarray, &event_type) < 0);
498  FAIL_IF(aled->alproto != ALPROTO_SMB);
500 
501  aled = DetectAppLayerEventParse("ftp.event5",
502  &event_type);
503  FAIL_IF_NULL(aled);
504  FAIL_IF(DetectAppLayerEventParseAppP2(aled, ipproto_bitarray, &event_type) < 0);
505  FAIL_IF(aled->alproto != ALPROTO_FTP);
507 
509  DetectAppLayerEventFree(aled);
510  PASS;
511 }
512 
513 static int DetectAppLayerEventTest03(void)
514 {
515  ThreadVars tv;
516  TcpReassemblyThreadCtx *ra_ctx = NULL;
517  Packet *p = NULL;
518  Flow *f = NULL;
519  TcpSession ssn;
520  TcpStream stream_ts, stream_tc;
521  DetectEngineCtx *de_ctx = NULL;
522  DetectEngineThreadCtx *det_ctx = NULL;
523 
524  uint8_t buf_ts[] = "GET /index.html HTTP/1.1\r\n"
525  "Host: 127.0.0.1\r\n"
526  "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"
527  "Accept: text/html,application/xhtml+xml,application/xml;q=0.9,*/*;q=0.8\r\n"
528  "Accept-Language: en-us,en;q=0.5\r\n"
529  "Accept-Encoding: gzip,deflate\r\n"
530  "Accept-Charset: ISO-8859-1,utf-8;q=0.7,*;q=0.7\r\n"
531  "Keep-Alive: 115\r\n"
532  "Connection: keep-alive\r\n"
533  "\r\n";
534  uint8_t buf_tc[] = "HTTP/1.1 200 OK\r\n"
535  "Date: Fri, 22 Oct 2010 12:31:08 GMT\r\n"
536  "Server: Apache/2.2.15 (Unix) DAV/2\r\n"
537  "Last-Modified: Sat, 20 Nov 2004 20:16:24 GMT\r\n"
538  "ETag: \"ab8486-2c-3e9564c23b600\"\r\n"
539  "Accept-Ranges: bytes\r\n"
540  "Content-Length: 44\r\n"
541  "Keep-Alive: timeout=5, max=100\r\n"
542  "Connection: Keep-Alive\r\n"
543  "Content-Type: text/html\r\n"
544  "\r\n"
545  "<html><body><h1>It works!</h1></body></html>";
546 
547  memset(&tv, 0, sizeof (ThreadVars));
548  memset(&ssn, 0, sizeof(TcpSession));
549  memset(&stream_ts, 0, sizeof(TcpStream));
550  memset(&stream_tc, 0, sizeof(TcpStream));
551 
553 
554  de_ctx = DetectEngineCtxInit();
555  FAIL_IF(de_ctx == NULL);
556  de_ctx->flags |= DE_QUIET;
557  de_ctx->sig_list = SigInit(de_ctx, "alert tcp any any -> any any "
558  "(app-layer-event: applayer_mismatch_protocol_both_directions; "
559  "sid:1;)");
560  FAIL_IF(de_ctx->sig_list == NULL);
561  SigGroupBuild(de_ctx);
562  DetectEngineThreadCtxInit(&tv, (void *)de_ctx, (void *)&det_ctx);
563 
564  f = UTHBuildFlow(AF_INET, "1.2.3.4", "1.2.3.5", 200, 220);
565  FAIL_IF(f == NULL);
566  FLOW_INITIALIZE(f);
567  f->protoctx = &ssn;
568  f->proto = IPPROTO_TCP;
569  f->flags |= FLOW_IPV4;
570 
571  p = PacketGetFromAlloc();
572  FAIL_IF(unlikely(p == NULL));
573  p->flow = f;
574  p->src.family = AF_INET;
575  p->dst.family = AF_INET;
576  p->proto = IPPROTO_TCP;
577 
578  StreamTcpUTInit(&ra_ctx);
579 
581  TcpStream *stream = &stream_ts;
582  FAIL_IF(AppLayerHandleTCPData(&tv, ra_ctx, p, f, &ssn, &stream, buf_ts,
583  sizeof(buf_ts), STREAM_TOSERVER | STREAM_START) < 0);
584 
585  SigMatchSignatures(&tv, de_ctx, det_ctx, p);
586 
587  FAIL_IF (PacketAlertCheck(p, 1));
588 
590  stream = &stream_tc;
591  FAIL_IF (AppLayerHandleTCPData(&tv, ra_ctx, p, f, &ssn, &stream, buf_tc,
592  sizeof(buf_tc), STREAM_TOCLIENT | STREAM_START) < 0);
593 
594  SigMatchSignatures(&tv, de_ctx, det_ctx, p);
595 
596  FAIL_IF(PacketAlertCheck(p, 1));
597 
598  StreamTcpUTDeinit(ra_ctx);
599  PASS;
600 }
601 
602 static int DetectAppLayerEventTest04(void)
603 {
604  ThreadVars tv;
605  TcpReassemblyThreadCtx *ra_ctx = NULL;
606  Packet *p = NULL;
607  Flow *f = NULL;
608  TcpSession ssn;
609  TcpStream stream_ts, stream_tc;
610  DetectEngineCtx *de_ctx = NULL;
611  DetectEngineThreadCtx *det_ctx = NULL;
612 
613  uint8_t buf_ts[] = "GET /index.html HTTP/1.1\r\n"
614  "Host: 127.0.0.1\r\n"
615  "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"
616  "Accept: text/html,application/xhtml+xml,application/xml;q=0.9,*/*;q=0.8\r\n"
617  "Accept-Language: en-us,en;q=0.5\r\n"
618  "Accept-Encoding: gzip,deflate\r\n"
619  "Accept-Charset: ISO-8859-1,utf-8;q=0.7,*;q=0.7\r\n"
620  "Keep-Alive: 115\r\n"
621  "Connection: keep-alive\r\n"
622  "\r\n";
623  uint8_t buf_tc[] = "XTTP/1.1 200 OK\r\n"
624  "Date: Fri, 22 Oct 2010 12:31:08 GMT\r\n"
625  "Server: Apache/2.2.15 (Unix) DAV/2\r\n"
626  "Last-Modified: Sat, 20 Nov 2004 20:16:24 GMT\r\n"
627  "ETag: \"ab8486-2c-3e9564c23b600\"\r\n"
628  "Accept-Ranges: bytes\r\n"
629  "Content-Length: 44\r\n"
630  "Keep-Alive: timeout=5, max=100\r\n"
631  "Connection: Keep-Alive\r\n"
632  "Content-Type: text/html\r\n"
633  "\r\n"
634  "<html><body><h1>It works!</h1></body></html>";
635 
636  memset(&tv, 0, sizeof (ThreadVars));
637  memset(&ssn, 0, sizeof(TcpSession));
638  memset(&stream_ts, 0, sizeof(TcpStream));
639  memset(&stream_tc, 0, sizeof(TcpStream));
640 
642 
643  de_ctx = DetectEngineCtxInit();
644  FAIL_IF (de_ctx == NULL);
645  de_ctx->flags |= DE_QUIET;
646  de_ctx->sig_list = SigInit(de_ctx, "alert tcp any any -> any any "
647  "(app-layer-event: applayer_detect_protocol_only_one_direction; "
648  "sid:1;)");
649  FAIL_IF(de_ctx->sig_list == NULL);
650  SigGroupBuild(de_ctx);
651  DetectEngineThreadCtxInit(&tv, (void *)de_ctx, (void *)&det_ctx);
652 
653  f = UTHBuildFlow(AF_INET, "1.2.3.4", "1.2.3.5", 200, 220);
654  FAIL_IF (f == NULL);
655  FLOW_INITIALIZE(f);
656  f->protoctx = &ssn;
657  f->proto = IPPROTO_TCP;
658  f->flags |= FLOW_IPV4;
659 
660  p = PacketGetFromAlloc();
661  FAIL_IF(unlikely(p == NULL));
662  p->flow = f;
663  p->src.family = AF_INET;
664  p->dst.family = AF_INET;
665  p->proto = IPPROTO_TCP;
666 
667  StreamTcpUTInit(&ra_ctx);
668 
670  TcpStream *stream = &stream_ts;
671  FAIL_IF(AppLayerHandleTCPData(&tv, ra_ctx, p, f, &ssn, &stream, buf_ts,
672  sizeof(buf_ts), STREAM_TOSERVER | STREAM_START) < 0);
673  SigMatchSignatures(&tv, de_ctx, det_ctx, p);
674  FAIL_IF (PacketAlertCheck(p, 1));
675 
677  stream = &stream_tc;
678  FAIL_IF (AppLayerHandleTCPData(&tv, ra_ctx, p, f, &ssn, &stream, buf_tc,
679  sizeof(buf_tc), STREAM_TOCLIENT | STREAM_START) < 0);
680  SigMatchSignatures(&tv, de_ctx, det_ctx, p);
681  FAIL_IF (!PacketAlertCheck(p, 1));
682 
683  StreamTcpUTDeinit(ra_ctx);
684  PASS;
685 }
686 
687 static int DetectAppLayerEventTest05(void)
688 {
689  ThreadVars tv;
690  TcpReassemblyThreadCtx *ra_ctx = NULL;
691  Packet *p = NULL;
692  Flow *f = NULL;
693  TcpSession ssn;
694  TcpStream stream_ts, stream_tc;
695  DetectEngineCtx *de_ctx = NULL;
696  DetectEngineThreadCtx *det_ctx = NULL;
697 
698  uint8_t buf_ts[] = "GET /index.html HTTP/1.1\r\n"
699  "Host: 127.0.0.1\r\n"
700  "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"
701  "Accept: text/html,application/xhtml+xml,application/xml;q=0.9,*/*;q=0.8\r\n"
702  "Accept-Language: en-us,en;q=0.5\r\n"
703  "Accept-Encoding: gzip,deflate\r\n"
704  "Accept-Charset: ISO-8859-1,utf-8;q=0.7,*;q=0.7\r\n"
705  "Keep-Alive: 115\r\n"
706  "Connection: keep-alive\r\n"
707  "\r\n";
708  /* tls */
709  uint8_t buf_tc[] = {
710  0x16, 0x03, 0x01, 0x00, 0x86, 0x10, 0x00, 0x00,
711  0x82, 0x00, 0x80, 0xd3, 0x6f, 0x1f, 0x63, 0x82,
712  0x8d, 0x75, 0x77, 0x8c, 0x91, 0xbc, 0xa1, 0x3d,
713  0xbb, 0xe1, 0xb5, 0xd3, 0x31, 0x92, 0x59, 0x2b,
714  0x2c, 0x43, 0x96, 0xa3, 0xaa, 0x23, 0x92, 0xd0,
715  0x91, 0x2a, 0x5e, 0x10, 0x5b, 0xc8, 0xc1, 0xe2,
716  0xd3, 0x5c, 0x8b, 0x8c, 0x91, 0x9e, 0xc2, 0xf2,
717  0x9c, 0x3c, 0x4f, 0x37, 0x1e, 0x20, 0x5e, 0x33,
718  0xd5, 0xf0, 0xd6, 0xaf, 0x89, 0xf5, 0xcc, 0xb2,
719  0xcf, 0xc1, 0x60, 0x3a, 0x46, 0xd5, 0x4e, 0x2a,
720  0xb6, 0x6a, 0xb9, 0xfc, 0x32, 0x8b, 0xe0, 0x6e,
721  0xa0, 0xed, 0x25, 0xa0, 0xa4, 0x82, 0x81, 0x73,
722  0x90, 0xbf, 0xb5, 0xde, 0xeb, 0x51, 0x8d, 0xde,
723  0x5b, 0x6f, 0x94, 0xee, 0xba, 0xe5, 0x69, 0xfa,
724  0x1a, 0x80, 0x30, 0x54, 0xeb, 0x12, 0x01, 0xb9,
725  0xfe, 0xbf, 0x82, 0x95, 0x01, 0x7b, 0xb0, 0x97,
726  0x14, 0xc2, 0x06, 0x3c, 0x69, 0xfb, 0x1c, 0x66,
727  0x47, 0x17, 0xd9, 0x14, 0x03, 0x01, 0x00, 0x01,
728  0x01, 0x16, 0x03, 0x01, 0x00, 0x30, 0xf6, 0xbc,
729  0x0d, 0x6f, 0xe8, 0xbb, 0xaa, 0xbf, 0x14, 0xeb,
730  0x7b, 0xcc, 0x6c, 0x28, 0xb0, 0xfc, 0xa6, 0x01,
731  0x2a, 0x97, 0x96, 0x17, 0x5e, 0xe8, 0xb4, 0x4e,
732  0x78, 0xc9, 0x04, 0x65, 0x53, 0xb6, 0x93, 0x3d,
733  0xeb, 0x44, 0xee, 0x86, 0xf9, 0x80, 0x49, 0x45,
734  0x21, 0x34, 0xd1, 0xee, 0xc8, 0x9c,
735  };
736 
737  memset(&tv, 0, sizeof (ThreadVars));
738  memset(&ssn, 0, sizeof(TcpSession));
739  memset(&stream_ts, 0, sizeof(TcpStream));
740  memset(&stream_tc, 0, sizeof(TcpStream));
741 
743 
744  de_ctx = DetectEngineCtxInit();
745  FAIL_IF (de_ctx == NULL);
746  de_ctx->flags |= DE_QUIET;
747  de_ctx->sig_list = SigInit(de_ctx, "alert tcp any any -> any any "
748  "(app-layer-event: applayer_mismatch_protocol_both_directions; "
749  "sid:1;)");
750  FAIL_IF (de_ctx->sig_list == NULL);
751  SigGroupBuild(de_ctx);
752  DetectEngineThreadCtxInit(&tv, (void *)de_ctx, (void *)&det_ctx);
753 
754  f = UTHBuildFlow(AF_INET, "1.2.3.4", "1.2.3.5", 200, 220);
755  FAIL_IF (f == NULL);
756  FLOW_INITIALIZE(f);
757  f->protoctx = &ssn;
758  f->proto = IPPROTO_TCP;
759  f->flags |= FLOW_IPV4;
760 
761  p = PacketGetFromAlloc();
762  FAIL_IF (unlikely(p == NULL));
763  p->flow = f;
764  p->src.family = AF_INET;
765  p->dst.family = AF_INET;
766  p->proto = IPPROTO_TCP;
767 
768  StreamTcpUTInit(&ra_ctx);
769 
771  TcpStream *stream = &stream_ts;
772  FAIL_IF (AppLayerHandleTCPData(&tv, ra_ctx, p, f, &ssn, &stream, buf_ts,
773  sizeof(buf_ts), STREAM_TOSERVER | STREAM_START) < 0);
774  SigMatchSignatures(&tv, de_ctx, det_ctx, p);
775  FAIL_IF (PacketAlertCheck(p, 1));
776 
778  stream = &stream_tc;
779  FAIL_IF (AppLayerHandleTCPData(&tv, ra_ctx, p, f, &ssn, &stream, buf_tc,
780  sizeof(buf_tc), STREAM_TOCLIENT | STREAM_START) < 0);
781  SigMatchSignatures(&tv, de_ctx, det_ctx, p);
782  FAIL_IF (!PacketAlertCheck(p, 1));
783 
784  StreamTcpUTDeinit(ra_ctx);
785  PASS;
786 }
787 
788 static int DetectAppLayerEventTest06(void)
789 {
791  uint8_t ipproto_bitarray[256 / 8];
792  memset(ipproto_bitarray, 0, sizeof(ipproto_bitarray));
793  ipproto_bitarray[IPPROTO_TCP / 8] |= 1 << (IPPROTO_TCP % 8);
794 
795  DetectAppLayerEventData *aled = DetectAppLayerEventParse("file.test",
796  &event_type);
797 
798  FAIL_IF_NULL(aled);
799 
800  FAIL_IF(DetectAppLayerEventParseAppP2(aled, ipproto_bitarray, &event_type) < 0);
801 
802  FAIL_IF(aled->alproto != ALPROTO_UNKNOWN);
804 
805  DetectAppLayerEventFree(aled);
806  PASS;
807 }
808 #endif /* UNITTESTS */
809 
810 /**
811  * \brief This function registers unit tests for "app-layer-event" keyword.
812  */
813 void DetectAppLayerEventRegisterTests(void)
814 {
815 #ifdef UNITTESTS /* UNITTESTS */
816  UtRegisterTest("DetectAppLayerEventTest01", DetectAppLayerEventTest01);
817  UtRegisterTest("DetectAppLayerEventTest02", DetectAppLayerEventTest02);
818  UtRegisterTest("DetectAppLayerEventTest03", DetectAppLayerEventTest03);
819  UtRegisterTest("DetectAppLayerEventTest04", DetectAppLayerEventTest04);
820  UtRegisterTest("DetectAppLayerEventTest05", DetectAppLayerEventTest05);
821  UtRegisterTest("DetectAppLayerEventTest06", DetectAppLayerEventTest06);
822 #endif /* UNITTESTS */
823 
824  return;
825 }
enum AppLayerEventType_ AppLayerEventType
SigTableElmt sigmatch_table[DETECT_TBLSIZE]
Definition: detect.h:1439
DetectProto proto
Definition: detect.h:534
SignatureInitData * init_data
Definition: detect.h:586
uint16_t flags
int(* Setup)(DetectEngineCtx *, Signature *, const char *)
Definition: detect.h:1179
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:518
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:324
Signature * SigInit(DetectEngineCtx *, const char *)
Parses a signature and adds it to the Detection Engine Context.
struct SigMatch_ * prev
Definition: detect.h:318
Signature * sig_list
Definition: detect.h:762
#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:322
#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:1193
uint16_t AppProto
Signature container.
Definition: detect.h:517
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:308
#define SIG_FLAG_APPLAYER
Definition: detect.h:214
void * protoctx
Definition: flow.h:400
struct SigMatch_ * next
Definition: detect.h:317
main detection engine ctx
Definition: detect.h:756
void StreamTcpUTDeinit(TcpReassemblyThreadCtx *ra_ctx)
#define KEYWORD_PROFILING_START
SCEnumCharMap app_layer_event_test_map[]
#define DE_QUIET
Definition: detect.h:287
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:233
char family
Definition: decode.h:111
uint8_t proto
Definition: decode.h:430
uint8_t flags
Definition: detect.h:757
#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:1184
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:1670
#define SIG_FLAG_TOSERVER
Definition: detect.h:232
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:513
int(* Match)(DetectEngineThreadCtx *, Packet *, const Signature *, const SigMatchCtx *)
Definition: detect.h:1163
int8_t data_first_seen_dir
uint8_t type
Definition: detect.h:314
#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:288
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:511
SigMatchCtx * ctx
Definition: detect.h:316
#define DETECT_ENGINE_INSPECT_SIG_CANT_MATCH
#define SCMalloc(a)
Definition: util-mem.h:222
uint8_t type
Definition: detect.h:323
#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
#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
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 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:1185
a single match condition for a signature
Definition: detect.h:313
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:325
DetectEngineCtx * DetectEngineCtxInit(void)