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  uint8_t ipproto_bitarray[256 / 8];
456  memset(ipproto_bitarray, 0, sizeof(ipproto_bitarray));
457  ipproto_bitarray[IPPROTO_TCP / 8] |= 1 << (IPPROTO_TCP % 8);
458 
459  DetectAppLayerEventData *aled = DetectAppLayerEventParse("smtp.event1",
460  &event_type);
461  FAIL_IF_NULL(aled);
462  FAIL_IF(DetectAppLayerEventParseAppP2(aled, ipproto_bitarray, &event_type) < 0);
463  FAIL_IF(aled->alproto != ALPROTO_SMTP);
465 
466  aled = DetectAppLayerEventParse("smtp.event4",
467  &event_type);
468  FAIL_IF_NULL(aled);
469  FAIL_IF(DetectAppLayerEventParseAppP2(aled, ipproto_bitarray, &event_type) < 0);
470  FAIL_IF(aled->alproto != ALPROTO_SMTP);
472 
473  aled = DetectAppLayerEventParse("http.event2",
474  &event_type);
475  FAIL_IF_NULL(aled);
476  FAIL_IF(DetectAppLayerEventParseAppP2(aled, ipproto_bitarray, &event_type) < 0);
477  FAIL_IF(aled->alproto != ALPROTO_HTTP);
479 
480  aled = DetectAppLayerEventParse("smb.event3",
481  &event_type);
482  FAIL_IF_NULL(aled);
483  FAIL_IF(DetectAppLayerEventParseAppP2(aled, ipproto_bitarray, &event_type) < 0);
484  FAIL_IF(aled->alproto != ALPROTO_SMB);
486 
487  aled = DetectAppLayerEventParse("ftp.event5",
488  &event_type);
489  FAIL_IF_NULL(aled);
490  FAIL_IF(DetectAppLayerEventParseAppP2(aled, ipproto_bitarray, &event_type) < 0);
491  FAIL_IF(aled->alproto != ALPROTO_FTP);
493 
495  DetectAppLayerEventFree(aled);
496  PASS;
497 }
498 
499 static int DetectAppLayerEventTest03(void)
500 {
501  ThreadVars tv;
502  TcpReassemblyThreadCtx *ra_ctx = NULL;
503  Packet *p = NULL;
504  Flow *f = NULL;
505  TcpSession ssn;
506  TcpStream stream_ts, stream_tc;
507  DetectEngineCtx *de_ctx = NULL;
508  DetectEngineThreadCtx *det_ctx = NULL;
509 
510  uint8_t buf_ts[] = "GET /index.html HTTP/1.1\r\n"
511  "Host: 127.0.0.1\r\n"
512  "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"
513  "Accept: text/html,application/xhtml+xml,application/xml;q=0.9,*/*;q=0.8\r\n"
514  "Accept-Language: en-us,en;q=0.5\r\n"
515  "Accept-Encoding: gzip,deflate\r\n"
516  "Accept-Charset: ISO-8859-1,utf-8;q=0.7,*;q=0.7\r\n"
517  "Keep-Alive: 115\r\n"
518  "Connection: keep-alive\r\n"
519  "\r\n";
520  uint8_t buf_tc[] = "HTTP/1.1 200 OK\r\n"
521  "Date: Fri, 22 Oct 2010 12:31:08 GMT\r\n"
522  "Server: Apache/2.2.15 (Unix) DAV/2\r\n"
523  "Last-Modified: Sat, 20 Nov 2004 20:16:24 GMT\r\n"
524  "ETag: \"ab8486-2c-3e9564c23b600\"\r\n"
525  "Accept-Ranges: bytes\r\n"
526  "Content-Length: 44\r\n"
527  "Keep-Alive: timeout=5, max=100\r\n"
528  "Connection: Keep-Alive\r\n"
529  "Content-Type: text/html\r\n"
530  "\r\n"
531  "<html><body><h1>It works!</h1></body></html>";
532 
533  memset(&tv, 0, sizeof (ThreadVars));
534  memset(&ssn, 0, sizeof(TcpSession));
535  memset(&stream_ts, 0, sizeof(TcpStream));
536  memset(&stream_tc, 0, sizeof(TcpStream));
537 
539 
540  de_ctx = DetectEngineCtxInit();
541  FAIL_IF(de_ctx == NULL);
542  de_ctx->flags |= DE_QUIET;
543  de_ctx->sig_list = SigInit(de_ctx, "alert tcp any any -> any any "
544  "(app-layer-event: applayer_mismatch_protocol_both_directions; "
545  "sid:1;)");
546  FAIL_IF(de_ctx->sig_list == NULL);
547  SigGroupBuild(de_ctx);
548  DetectEngineThreadCtxInit(&tv, (void *)de_ctx, (void *)&det_ctx);
549 
550  f = UTHBuildFlow(AF_INET, "1.2.3.4", "1.2.3.5", 200, 220);
551  FAIL_IF(f == NULL);
552  FLOW_INITIALIZE(f);
553  f->protoctx = &ssn;
554  f->proto = IPPROTO_TCP;
555  f->flags |= FLOW_IPV4;
556 
557  p = PacketGetFromAlloc();
558  FAIL_IF(unlikely(p == NULL));
559  p->flow = f;
560  p->src.family = AF_INET;
561  p->dst.family = AF_INET;
562  p->proto = IPPROTO_TCP;
563 
564  StreamTcpUTInit(&ra_ctx);
565 
567  FAIL_IF(AppLayerHandleTCPData(&tv, ra_ctx, p, f, &ssn, &stream_ts, buf_ts,
568  sizeof(buf_ts), STREAM_TOSERVER | STREAM_START) < 0);
569 
570  SigMatchSignatures(&tv, de_ctx, det_ctx, p);
571 
572  FAIL_IF (PacketAlertCheck(p, 1));
573 
575  FAIL_IF (AppLayerHandleTCPData(&tv, ra_ctx, p, f, &ssn, &stream_tc, buf_tc,
576  sizeof(buf_tc), STREAM_TOCLIENT | STREAM_START) < 0);
577 
578  SigMatchSignatures(&tv, de_ctx, det_ctx, p);
579 
580  FAIL_IF(PacketAlertCheck(p, 1));
581 
582  StreamTcpUTDeinit(ra_ctx);
583  PASS;
584 }
585 
586 static int DetectAppLayerEventTest04(void)
587 {
588  ThreadVars tv;
589  TcpReassemblyThreadCtx *ra_ctx = NULL;
590  Packet *p = NULL;
591  Flow *f = NULL;
592  TcpSession ssn;
593  TcpStream stream_ts, stream_tc;
594  DetectEngineCtx *de_ctx = NULL;
595  DetectEngineThreadCtx *det_ctx = NULL;
596 
597  uint8_t buf_ts[] = "GET /index.html HTTP/1.1\r\n"
598  "Host: 127.0.0.1\r\n"
599  "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"
600  "Accept: text/html,application/xhtml+xml,application/xml;q=0.9,*/*;q=0.8\r\n"
601  "Accept-Language: en-us,en;q=0.5\r\n"
602  "Accept-Encoding: gzip,deflate\r\n"
603  "Accept-Charset: ISO-8859-1,utf-8;q=0.7,*;q=0.7\r\n"
604  "Keep-Alive: 115\r\n"
605  "Connection: keep-alive\r\n"
606  "\r\n";
607  uint8_t buf_tc[] = "XTTP/1.1 200 OK\r\n"
608  "Date: Fri, 22 Oct 2010 12:31:08 GMT\r\n"
609  "Server: Apache/2.2.15 (Unix) DAV/2\r\n"
610  "Last-Modified: Sat, 20 Nov 2004 20:16:24 GMT\r\n"
611  "ETag: \"ab8486-2c-3e9564c23b600\"\r\n"
612  "Accept-Ranges: bytes\r\n"
613  "Content-Length: 44\r\n"
614  "Keep-Alive: timeout=5, max=100\r\n"
615  "Connection: Keep-Alive\r\n"
616  "Content-Type: text/html\r\n"
617  "\r\n"
618  "<html><body><h1>It works!</h1></body></html>";
619 
620  memset(&tv, 0, sizeof (ThreadVars));
621  memset(&ssn, 0, sizeof(TcpSession));
622  memset(&stream_ts, 0, sizeof(TcpStream));
623  memset(&stream_tc, 0, sizeof(TcpStream));
624 
626 
627  de_ctx = DetectEngineCtxInit();
628  FAIL_IF (de_ctx == NULL);
629  de_ctx->flags |= DE_QUIET;
630  de_ctx->sig_list = SigInit(de_ctx, "alert tcp any any -> any any "
631  "(app-layer-event: applayer_detect_protocol_only_one_direction; "
632  "sid:1;)");
633  FAIL_IF(de_ctx->sig_list == NULL);
634  SigGroupBuild(de_ctx);
635  DetectEngineThreadCtxInit(&tv, (void *)de_ctx, (void *)&det_ctx);
636 
637  f = UTHBuildFlow(AF_INET, "1.2.3.4", "1.2.3.5", 200, 220);
638  FAIL_IF (f == NULL);
639  FLOW_INITIALIZE(f);
640  f->protoctx = &ssn;
641  f->proto = IPPROTO_TCP;
642  f->flags |= FLOW_IPV4;
643 
644  p = PacketGetFromAlloc();
645  FAIL_IF(unlikely(p == NULL));
646  p->flow = f;
647  p->src.family = AF_INET;
648  p->dst.family = AF_INET;
649  p->proto = IPPROTO_TCP;
650 
651  StreamTcpUTInit(&ra_ctx);
652 
654  FAIL_IF(AppLayerHandleTCPData(&tv, ra_ctx, p, f, &ssn, &stream_ts, buf_ts,
655  sizeof(buf_ts), STREAM_TOSERVER | STREAM_START) < 0);
656  SigMatchSignatures(&tv, de_ctx, det_ctx, p);
657  FAIL_IF (PacketAlertCheck(p, 1));
658 
660  FAIL_IF (AppLayerHandleTCPData(&tv, ra_ctx, p, f, &ssn, &stream_tc, buf_tc,
661  sizeof(buf_tc), STREAM_TOCLIENT | STREAM_START) < 0);
662  SigMatchSignatures(&tv, de_ctx, det_ctx, p);
663  FAIL_IF (!PacketAlertCheck(p, 1));
664 
665  StreamTcpUTDeinit(ra_ctx);
666  PASS;
667 }
668 
669 static int DetectAppLayerEventTest05(void)
670 {
671  ThreadVars tv;
672  TcpReassemblyThreadCtx *ra_ctx = NULL;
673  Packet *p = NULL;
674  Flow *f = NULL;
675  TcpSession ssn;
676  TcpStream stream_ts, stream_tc;
677  DetectEngineCtx *de_ctx = NULL;
678  DetectEngineThreadCtx *det_ctx = NULL;
679 
680  uint8_t buf_ts[] = "GET /index.html HTTP/1.1\r\n"
681  "Host: 127.0.0.1\r\n"
682  "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"
683  "Accept: text/html,application/xhtml+xml,application/xml;q=0.9,*/*;q=0.8\r\n"
684  "Accept-Language: en-us,en;q=0.5\r\n"
685  "Accept-Encoding: gzip,deflate\r\n"
686  "Accept-Charset: ISO-8859-1,utf-8;q=0.7,*;q=0.7\r\n"
687  "Keep-Alive: 115\r\n"
688  "Connection: keep-alive\r\n"
689  "\r\n";
690  /* tls */
691  uint8_t buf_tc[] = {
692  0x16, 0x03, 0x01, 0x00, 0x86, 0x10, 0x00, 0x00,
693  0x82, 0x00, 0x80, 0xd3, 0x6f, 0x1f, 0x63, 0x82,
694  0x8d, 0x75, 0x77, 0x8c, 0x91, 0xbc, 0xa1, 0x3d,
695  0xbb, 0xe1, 0xb5, 0xd3, 0x31, 0x92, 0x59, 0x2b,
696  0x2c, 0x43, 0x96, 0xa3, 0xaa, 0x23, 0x92, 0xd0,
697  0x91, 0x2a, 0x5e, 0x10, 0x5b, 0xc8, 0xc1, 0xe2,
698  0xd3, 0x5c, 0x8b, 0x8c, 0x91, 0x9e, 0xc2, 0xf2,
699  0x9c, 0x3c, 0x4f, 0x37, 0x1e, 0x20, 0x5e, 0x33,
700  0xd5, 0xf0, 0xd6, 0xaf, 0x89, 0xf5, 0xcc, 0xb2,
701  0xcf, 0xc1, 0x60, 0x3a, 0x46, 0xd5, 0x4e, 0x2a,
702  0xb6, 0x6a, 0xb9, 0xfc, 0x32, 0x8b, 0xe0, 0x6e,
703  0xa0, 0xed, 0x25, 0xa0, 0xa4, 0x82, 0x81, 0x73,
704  0x90, 0xbf, 0xb5, 0xde, 0xeb, 0x51, 0x8d, 0xde,
705  0x5b, 0x6f, 0x94, 0xee, 0xba, 0xe5, 0x69, 0xfa,
706  0x1a, 0x80, 0x30, 0x54, 0xeb, 0x12, 0x01, 0xb9,
707  0xfe, 0xbf, 0x82, 0x95, 0x01, 0x7b, 0xb0, 0x97,
708  0x14, 0xc2, 0x06, 0x3c, 0x69, 0xfb, 0x1c, 0x66,
709  0x47, 0x17, 0xd9, 0x14, 0x03, 0x01, 0x00, 0x01,
710  0x01, 0x16, 0x03, 0x01, 0x00, 0x30, 0xf6, 0xbc,
711  0x0d, 0x6f, 0xe8, 0xbb, 0xaa, 0xbf, 0x14, 0xeb,
712  0x7b, 0xcc, 0x6c, 0x28, 0xb0, 0xfc, 0xa6, 0x01,
713  0x2a, 0x97, 0x96, 0x17, 0x5e, 0xe8, 0xb4, 0x4e,
714  0x78, 0xc9, 0x04, 0x65, 0x53, 0xb6, 0x93, 0x3d,
715  0xeb, 0x44, 0xee, 0x86, 0xf9, 0x80, 0x49, 0x45,
716  0x21, 0x34, 0xd1, 0xee, 0xc8, 0x9c,
717  };
718 
719  memset(&tv, 0, sizeof (ThreadVars));
720  memset(&ssn, 0, sizeof(TcpSession));
721  memset(&stream_ts, 0, sizeof(TcpStream));
722  memset(&stream_tc, 0, sizeof(TcpStream));
723 
725 
726  de_ctx = DetectEngineCtxInit();
727  FAIL_IF (de_ctx == NULL);
728  de_ctx->flags |= DE_QUIET;
729  de_ctx->sig_list = SigInit(de_ctx, "alert tcp any any -> any any "
730  "(app-layer-event: applayer_mismatch_protocol_both_directions; "
731  "sid:1;)");
732  FAIL_IF (de_ctx->sig_list == NULL);
733  SigGroupBuild(de_ctx);
734  DetectEngineThreadCtxInit(&tv, (void *)de_ctx, (void *)&det_ctx);
735 
736  f = UTHBuildFlow(AF_INET, "1.2.3.4", "1.2.3.5", 200, 220);
737  FAIL_IF (f == NULL);
738  FLOW_INITIALIZE(f);
739  f->protoctx = &ssn;
740  f->proto = IPPROTO_TCP;
741  f->flags |= FLOW_IPV4;
742 
743  p = PacketGetFromAlloc();
744  FAIL_IF (unlikely(p == NULL));
745  p->flow = f;
746  p->src.family = AF_INET;
747  p->dst.family = AF_INET;
748  p->proto = IPPROTO_TCP;
749 
750  StreamTcpUTInit(&ra_ctx);
751 
753  FAIL_IF (AppLayerHandleTCPData(&tv, ra_ctx, p, f, &ssn, &stream_ts, buf_ts,
754  sizeof(buf_ts), STREAM_TOSERVER | STREAM_START) < 0);
755  SigMatchSignatures(&tv, de_ctx, det_ctx, p);
756  FAIL_IF (PacketAlertCheck(p, 1));
757 
759  FAIL_IF (AppLayerHandleTCPData(&tv, ra_ctx, p, f, &ssn, &stream_tc, buf_tc,
760  sizeof(buf_tc), STREAM_TOCLIENT | STREAM_START) < 0);
761  SigMatchSignatures(&tv, de_ctx, det_ctx, p);
762  FAIL_IF (!PacketAlertCheck(p, 1));
763 
764  StreamTcpUTDeinit(ra_ctx);
765  PASS;
766 }
767 
768 static int DetectAppLayerEventTest06(void)
769 {
771  uint8_t ipproto_bitarray[256 / 8];
772  memset(ipproto_bitarray, 0, sizeof(ipproto_bitarray));
773  ipproto_bitarray[IPPROTO_TCP / 8] |= 1 << (IPPROTO_TCP % 8);
774 
775  DetectAppLayerEventData *aled = DetectAppLayerEventParse("file.test",
776  &event_type);
777 
778  FAIL_IF_NULL(aled);
779 
780  FAIL_IF(DetectAppLayerEventParseAppP2(aled, ipproto_bitarray, &event_type) < 0);
781 
782  FAIL_IF(aled->alproto != ALPROTO_UNKNOWN);
784 
785  DetectAppLayerEventFree(aled);
786  PASS;
787 }
788 #endif /* UNITTESTS */
789 
790 /**
791  * \brief This function registers unit tests for "app-layer-event" keyword.
792  */
793 void DetectAppLayerEventRegisterTests(void)
794 {
795 #ifdef UNITTESTS /* UNITTESTS */
796  UtRegisterTest("DetectAppLayerEventTest01", DetectAppLayerEventTest01);
797  UtRegisterTest("DetectAppLayerEventTest02", DetectAppLayerEventTest02);
798  UtRegisterTest("DetectAppLayerEventTest03", DetectAppLayerEventTest03);
799  UtRegisterTest("DetectAppLayerEventTest04", DetectAppLayerEventTest04);
800  UtRegisterTest("DetectAppLayerEventTest05", DetectAppLayerEventTest05);
801  UtRegisterTest("DetectAppLayerEventTest06", DetectAppLayerEventTest06);
802 #endif /* UNITTESTS */
803 
804  return;
805 }
enum AppLayerEventType_ AppLayerEventType
SigTableElmt sigmatch_table[DETECT_TBLSIZE]
Definition: detect.h:1409
DetectProto proto
Definition: detect.h:513
SignatureInitData * init_data
Definition: detect.h:564
uint16_t flags
int(* Setup)(DetectEngineCtx *, Signature *, const char *)
Definition: detect.h:1150
void StreamTcpUTInit(TcpReassemblyThreadCtx **ra_ctx)
int DetectSignatureSetAppProto(Signature *s, AppProto alproto)
struct Flow_ * flow
Definition: decode.h:443
#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:497
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:333
Signature * SigInit(DetectEngineCtx *, const char *)
Parses a signature and adds it to the Detection Engine Context.
struct SigMatch_ * prev
Definition: detect.h:327
Signature * sig_list
Definition: detect.h:730
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:551
#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:411
Data needed for Match()
Definition: detect.h:331
#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:1164
uint16_t AppProto
Signature container.
Definition: detect.h:496
AppProto AppLayerGetProtoByName(char *alproto_name)
Given a protocol string, returns the corresponding internal protocol id.
Definition: app-layer.c:742
void AppLayerParserBackupParserTable(void)
#define TRUE
Used to start a pointer to SigMatch context Should never be dereferenced without casting to something...
Definition: detect.h:317
#define SIG_FLAG_APPLAYER
Definition: detect.h:223
void * protoctx
Definition: flow.h:400
struct SigMatch_ * next
Definition: detect.h:326
main detection engine ctx
Definition: detect.h:724
void StreamTcpUTDeinit(TcpReassemblyThreadCtx *ra_ctx)
#define KEYWORD_PROFILING_START
SCEnumCharMap app_layer_event_test_map[]
#define DE_QUIET
Definition: detect.h:296
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:242
char family
Definition: decode.h:109
uint8_t proto
Definition: decode.h:428
uint8_t flags
Definition: detect.h:725
#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:1155
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:1742
#define SIG_FLAG_TOSERVER
Definition: detect.h:241
uint8_t flowflags
Definition: decode.h:437
#define STREAM_TOCLIENT
Definition: stream.h:32
#define FLOW_PKT_TOSERVER
Definition: flow.h:201
struct SigMatch_ ** smlists_tail
Definition: detect.h:492
int8_t data_first_seen_dir
uint8_t type
Definition: detect.h:323
#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)
struct SigMatch_ ** smlists
Definition: detect.h:490
SigMatchCtx * ctx
Definition: detect.h:325
#define DETECT_ENGINE_INSPECT_SIG_CANT_MATCH
#define SCMalloc(a)
Definition: util-mem.h:166
uint8_t type
Definition: detect.h:332
#define DETECT_ENGINE_INSPECT_SIG_NO_MATCH
#define SCFree(a)
Definition: util-mem.h:228
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
int(* Match)(ThreadVars *, DetectEngineThreadCtx *, Packet *, const Signature *, const SigMatchCtx *)
Definition: detect.h:1133
#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:212
#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:1156
a single match condition for a signature
Definition: detect.h:322
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:410
SigMatchCtx * ctx
Definition: detect.h:334
DetectEngineCtx * DetectEngineCtxInit(void)