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