From: Anoop Saldanha Date: Fri, 16 Aug 2013 14:38:53 +0000 (+0530) Subject: Add app layer protocol packet event detection support. X-Git-Tag: suricata-2.0beta2~292 X-Git-Url: http://git.ipfire.org/gitweb.cgi?a=commitdiff_plain;h=b1dffdfbe0b28962d013cfdad4e52b86a9e0c906;p=thirdparty%2Fsuricata.git Add app layer protocol packet event detection support. --- diff --git a/src/app-layer-detect-proto.c b/src/app-layer-detect-proto.c index d9e1ed9c69..073d598043 100644 --- a/src/app-layer-detect-proto.c +++ b/src/app-layer-detect-proto.c @@ -578,7 +578,7 @@ uint16_t AppLayerDetectGetProto(AlpProtoDetectCtx *ctx, for (uint16_t i = 0; i < pm_matches; i++) { if (al_proto_table[pm_results[i]].pp_alproto_map[dir] != NULL) { if (pm_results[i] != al_proto_table[pm_results[i]].pp_alproto_map[dir](buf, buflen, NULL)) { - /* \todo set event */ + /* \todo set event - Needs some deliberation */ continue; } } diff --git a/src/app-layer.c b/src/app-layer.c index 6f950e2732..003242d9b1 100644 --- a/src/app-layer.c +++ b/src/app-layer.c @@ -36,6 +36,7 @@ #include "util-print.h" #include "util-profiling.h" #include "util-validate.h" +#include "decode-events.h" //#define PRINT extern uint8_t engine_mode; @@ -182,7 +183,8 @@ int AppLayerHandleTCPData(ThreadVars *tv, TcpReassemblyThreadCtx *ra_ctx, if (*alproto != ALPROTO_UNKNOWN) { if (*alproto_otherdir != ALPROTO_UNKNOWN && *alproto_otherdir != *alproto) { - /* \todo set event */ + AppLayerDecoderEventsSetEventRaw(p->app_layer_events, + APPLAYER_MISMATCH_PROTOCOL_BOTH_DIRECTIONS); f->alproto = f->alproto_ts = f->alproto_tc = ALPROTO_UNKNOWN; FlowSetSessionNoApplayerInspectionFlag(f); ssn->client.flags |= STREAMTCP_STREAM_FLAG_APPPROTO_DETECTION_COMPLETED; @@ -220,7 +222,8 @@ int AppLayerHandleTCPData(ThreadVars *tv, TcpReassemblyThreadCtx *ra_ctx, if (ssn->data_first_seen_dir != 0x01) { if (al_proto_table[*alproto].flags && !(al_proto_table[*alproto].flags & ssn->data_first_seen_dir)) { - /* \todo Set event */ + AppLayerDecoderEventsSetEventRaw(p->app_layer_events, + APPLAYER_WRONG_DIRECTION_FIRST_DATA); r = -1; f->alproto = f->alproto_ts = f->alproto_tc = ALPROTO_UNKNOWN; FlowSetSessionNoApplayerInspectionFlag(f); @@ -247,7 +250,8 @@ int AppLayerHandleTCPData(ThreadVars *tv, TcpReassemblyThreadCtx *ra_ctx, data + data_al_so_far, data_len - data_al_so_far); PACKET_PROFILING_APP_END(dp_ctx, *alproto_otherdir); if (FLOW_IS_PM_DONE(f, flags) && FLOW_IS_PP_DONE(f, flags)) { - /* \todo event. Unable to detect protocol for one direction */ + AppLayerDecoderEventsSetEventRaw(p->app_layer_events, + APPLAYER_DETECT_PROTOCOL_ONLY_ONE_DIRECTION); stream->flags |= STREAMTCP_STREAM_FLAG_APPPROTO_DETECTION_COMPLETED; f->data_al_so_far[dir] = 0; } else { diff --git a/src/decode-events.c b/src/decode-events.c index f050d7a9f7..c6a94fa79e 100644 --- a/src/decode-events.c +++ b/src/decode-events.c @@ -1,4 +1,4 @@ -/* Copyright (C) 2007-2011 Open Information Security Foundation +/* Copyright (C) 2007-2013 Open Information Security Foundation * * You can copy, redistribute or modify this Program under the terms of * the GNU General Public License version 2 as published by the Free @@ -22,7 +22,28 @@ */ #include "suricata-common.h" -#include "app-layer-parser.h" -#include "decode-events.h" -#include "flow.h" +#include "util-enum.h" +SCEnumCharMap app_layer_event_pkt_table[ ] = { + { "APPLAYER_MISMATCH_PROTOCOL_BOTH_DIRECTIONS", + APPLAYER_MISMATCH_PROTOCOL_BOTH_DIRECTIONS }, + { "APPLAYER_WRONG_DIRECTION_FIRST_DATA", + APPLAYER_WRONG_DIRECTION_FIRST_DATA }, + { "APPLAYER_DETECT_PROTOCOL_ONLY_ONE_DIRECTION", + APPLAYER_DETECT_PROTOCOL_ONLY_ONE_DIRECTION }, + { NULL, + -1 }, +}; + +int AppLayerGetPktEventInfo(const char *event_name, int *event_id) +{ + *event_id = SCMapEnumNameToValue(event_name, app_layer_event_pkt_table); + if (*event_id == -1) { + SCLogError(SC_ERR_INVALID_ENUM_MAP, "event \"%s\" not present in " + "app-layer-event's packet event table.", event_name); + /* this should be treated as fatal */ + return -1; + } + + return 0; +} diff --git a/src/decode-events.h b/src/decode-events.h index 3570a7f0c4..e25942a1bb 100644 --- a/src/decode-events.h +++ b/src/decode-events.h @@ -1,4 +1,4 @@ -/* Copyright (C) 2007-2010 Open Information Security Foundation +/* Copyright (C) 2007-2013 Open Information Security Foundation * * You can copy, redistribute or modify this Program under the terms of * the GNU General Public License version 2 as published by the Free @@ -25,8 +25,7 @@ #ifndef __DECODE_EVENTS_H__ #define __DECODE_EVENTS_H__ -/***** packet decoder events *****/ - +/* packet decoder events */ enum { /* IPV4 EVENTS */ IPV4_PKT_TOO_SMALL = 1, /**< ipv4 pkt smaller than minimum header size */ @@ -225,12 +224,20 @@ enum { DECODE_EVENT_MAX, }; +/* app layer pkt level events */ +enum { + APPLAYER_MISMATCH_PROTOCOL_BOTH_DIRECTIONS, + APPLAYER_WRONG_DIRECTION_FIRST_DATA, + APPLAYER_DETECT_PROTOCOL_ONLY_ONE_DIRECTION, +}; + #define DECODER_EVENTS_BUFFER_STEPS 5 /* the event types for app events */ typedef enum AppLayerEventType_ { APP_LAYER_EVENT_TYPE_GENERAL = 1, APP_LAYER_EVENT_TYPE_TRANSACTION, + APP_LAYER_EVENT_TYPE_PACKET, } AppLayerEventType; /** @@ -353,4 +360,6 @@ static inline int AppLayerDecoderEventsIsEventSet(AppLayerDecoderEvents *devents SCFree((devents)); \ } while (0) +int AppLayerGetPktEventInfo(const char *event_name, int *event_id); + #endif /* __DECODE_EVENTS_H__ */ diff --git a/src/decode.h b/src/decode.h index 9e4420c93f..ab8c782a88 100644 --- a/src/decode.h +++ b/src/decode.h @@ -29,6 +29,7 @@ #include "suricata-common.h" #include "threadvars.h" +#include "decode-events.h" #ifdef __SC_CUDA_SUPPORT__ #include "util-cuda-buffer.h" @@ -486,6 +487,8 @@ typedef struct Packet_ /* engine events */ PacketEngineEvents events; + AppLayerDecoderEvents *app_layer_events; + /* double linked list ptrs */ struct Packet_ *next; struct Packet_ *prev; @@ -701,6 +704,7 @@ typedef struct DecodeThreadVars_ SCMutexDestroy(&(p)->tunnel_mutex); \ SCMutexInit(&(p)->tunnel_mutex, NULL); \ (p)->events.cnt = 0; \ + AppLayerDecoderEventsResetEvents((p)->app_layer_events); \ (p)->next = NULL; \ (p)->prev = NULL; \ (p)->root = NULL; \ @@ -719,6 +723,7 @@ typedef struct DecodeThreadVars_ PktVarFree((p)->pktvar); \ } \ SCMutexDestroy(&(p)->tunnel_mutex); \ + AppLayerDecoderEventsFreeEvents((p)->app_layer_events); \ } while (0) diff --git a/src/detect-app-layer-event.c b/src/detect-app-layer-event.c index a59ca3b7f3..449e7540b5 100644 --- a/src/detect-app-layer-event.c +++ b/src/detect-app-layer-event.c @@ -45,8 +45,10 @@ #include "util-unittest-helper.h" -int DetectAppLayerEventMatch(ThreadVars *, DetectEngineThreadCtx *, Flow *, - uint8_t, void *, Signature *, SigMatch *); +int DetectAppLayerEventPktMatch(ThreadVars *t, DetectEngineThreadCtx *det_ctx, + Packet *p, Signature *s, SigMatch *m); +int DetectAppLayerEventAppMatch(ThreadVars *, DetectEngineThreadCtx *, Flow *, + uint8_t, void *, Signature *, SigMatch *); int DetectAppLayerEventSetup(DetectEngineCtx *, Signature *, char *); void DetectAppLayerEventRegisterTests(void); void DetectAppLayerEventFree(void *); @@ -57,9 +59,10 @@ void DetectAppLayerEventFree(void *); void DetectAppLayerEventRegister(void) { sigmatch_table[DETECT_AL_APP_LAYER_EVENT].name = "app-layer-event"; - sigmatch_table[DETECT_AL_APP_LAYER_EVENT].Match = NULL; + sigmatch_table[DETECT_AL_APP_LAYER_EVENT].Match = + DetectAppLayerEventPktMatch; sigmatch_table[DETECT_AL_APP_LAYER_EVENT].AppLayerMatch = - DetectAppLayerEventMatch; + DetectAppLayerEventAppMatch; sigmatch_table[DETECT_AL_APP_LAYER_EVENT].Setup = DetectAppLayerEventSetup; sigmatch_table[DETECT_AL_APP_LAYER_EVENT].Free = DetectAppLayerEventFree; sigmatch_table[DETECT_AL_APP_LAYER_EVENT].RegisterTests = @@ -68,9 +71,19 @@ void DetectAppLayerEventRegister(void) return; } -int DetectAppLayerEventMatch(ThreadVars *t, DetectEngineThreadCtx *det_ctx, - Flow *f, uint8_t flags, void *state, Signature *s, - SigMatch *m) + +int DetectAppLayerEventPktMatch(ThreadVars *t, DetectEngineThreadCtx *det_ctx, + Packet *p, Signature *s, SigMatch *m) +{ + DetectAppLayerEventData *aled = (DetectAppLayerEventData *)m->ctx; + + return AppLayerDecoderEventsIsEventSet(p->app_layer_events, + aled->event_id); +} + +int DetectAppLayerEventAppMatch(ThreadVars *t, DetectEngineThreadCtx *det_ctx, + Flow *f, uint8_t flags, void *state, Signature *s, + SigMatch *m) { SCEnter(); AppLayerDecoderEvents *decoder_events = NULL; @@ -87,7 +100,7 @@ int DetectAppLayerEventMatch(ThreadVars *t, DetectEngineThreadCtx *det_ctx, tx_id = AppLayerTransactionGetInspectId(f, flags); max_id = AppLayerGetTxCnt(f->alproto, f->alstate); - for ( ; tx_id < max_id; tx_id++) { + for (; tx_id < max_id; tx_id++) { decoder_events = AppLayerGetEventsFromFlowByTx(f, tx_id); if (decoder_events != NULL && AppLayerDecoderEventsIsEventSet(decoder_events, aled->event_id)) { @@ -109,54 +122,68 @@ int DetectAppLayerEventMatch(ThreadVars *t, DetectEngineThreadCtx *det_ctx, SCReturnInt(r); } -static DetectAppLayerEventData *DetectAppLayerEventParse(const char *arg) +static DetectAppLayerEventData *DetectAppLayerEventParsePkt(const char *arg, + AppLayerEventType *event_type) { - /* period index */ - const char *p_idx; - int r = 0; + DetectAppLayerEventData *aled; + int event_id = 0; - AppLayerEventType event_type = 0; - uint16_t alproto; + int r = 0; - if (arg == NULL) { - SCLogError(SC_ERR_INVALID_SIGNATURE, "app-layer-event keyword supplied " - "with no arguments. This keyword needs an argument."); + r = AppLayerGetPktEventInfo(arg, &event_id); + if (r < 0) { + SCLogError(SC_ERR_INVALID_SIGNATURE, "app-layer-event keyword " + "supplied with packet based event - \"%s\" that isn't " + "supported yet.", arg); return NULL; } - while (*arg != '\0' && isspace((unsigned char)*arg)) { - arg++; - } - - p_idx = strchr(arg, '.'); - if (p_idx == NULL) { - SCLogError(SC_ERR_INVALID_SIGNATURE, "app-layer-event keyword supplied " - "with an argument which is not in the right format. The " - "right format is \".\""); + aled = SCMalloc(sizeof(DetectAppLayerEventData)); + if (unlikely(aled == NULL)) return NULL; - } + aled->event_id = event_id; + *event_type = APP_LAYER_EVENT_TYPE_PACKET; + + return aled; +} + +static DetectAppLayerEventData *DetectAppLayerEventParseApp(const char *arg, + AppLayerEventType *event_type) +{ + /* period index */ + DetectAppLayerEventData *aled; + + uint16_t alproto; + int event_id = 0; - char buffer[50] = ""; - strlcpy(buffer, arg, p_idx - arg + 1); /* + 1 for trailing \0 */ + const char *p_idx; + char alproto_name[50]; + int r = 0; - /** XXX HACK to support "dns" we use this trick */ - if (strcasecmp(buffer, "dns") == 0) - strlcpy(buffer, "dnsudp", sizeof(buffer)); + p_idx = strchr(arg, '.'); + /* + 1 for trailing \0 */ + strlcpy(alproto_name, arg, p_idx - arg + 1); - alproto = AppLayerGetProtoByName(buffer); + /* XXX HACK to support "dns" we use this trick */ + if (strcasecmp(alproto_name, "dns") == 0) + strlcpy(alproto_name, "dnsudp", sizeof(alproto_name)); + + alproto = AppLayerGetProtoByName(alproto_name); if (alproto == ALPROTO_UNKNOWN) { - SCLogError(SC_ERR_INVALID_SIGNATURE, "app-layer-event keyword supplied " - "with unknown protocol \"%s\"", buffer); + SCLogError(SC_ERR_INVALID_SIGNATURE, "app-layer-event keyword " + "supplied with unknown protocol \"%s\"", + alproto_name); return NULL; } - r = AppLayerGetEventInfo(alproto, p_idx + 1, &event_id, &event_type); + r = AppLayerGetEventInfo(alproto, p_idx + 1, &event_id, event_type); if (r < 0) { - SCLogError(SC_ERR_INVALID_SIGNATURE, "app-layer-event keyword protocol " - "\"%s\" don't have event \"%s\" registered", buffer, p_idx + 1); + SCLogError(SC_ERR_INVALID_SIGNATURE, "app-layer-event keyword's " + "protocol \"%s\" doesn't have event \"%s\" registered", + alproto_name, p_idx + 1); return NULL; } - DetectAppLayerEventData *aled = SCMalloc(sizeof(DetectAppLayerEventData)); + aled = SCMalloc(sizeof(DetectAppLayerEventData)); if (unlikely(aled == NULL)) return NULL; aled->alproto = alproto; @@ -165,12 +192,32 @@ static DetectAppLayerEventData *DetectAppLayerEventParse(const char *arg) return aled; } +static DetectAppLayerEventData *DetectAppLayerEventParse(const char *arg, + AppLayerEventType *event_type) +{ + if (arg == NULL) { + SCLogError(SC_ERR_INVALID_SIGNATURE, "app-layer-event keyword supplied " + "with no arguments. This keyword needs an argument."); + return NULL; + } + + while (*arg != '\0' && isspace((unsigned char)*arg)) + arg++; + + if (strchr(arg, '.') == NULL) { + return DetectAppLayerEventParsePkt(arg, event_type); + } else { + return DetectAppLayerEventParseApp(arg, event_type); + } +} + int DetectAppLayerEventSetup(DetectEngineCtx *de_ctx, Signature *s, char *arg) { DetectAppLayerEventData *data = NULL; SigMatch *sm = NULL; + AppLayerEventType event_type; - data = DetectAppLayerEventParse(arg); + data = DetectAppLayerEventParse(arg, &event_type); if (data == NULL) goto error; @@ -195,8 +242,12 @@ int DetectAppLayerEventSetup(DetectEngineCtx *de_ctx, Signature *s, char *arg) s->alproto = data->alproto; } - SigMatchAppendSMToList(s, sm, DETECT_SM_LIST_AMATCH); - s->flags |= SIG_FLAG_APPLAYER; + if (event_type == APP_LAYER_EVENT_TYPE_PACKET) { + SigMatchAppendSMToList(s, sm, DETECT_SM_LIST_MATCH); + } else { + SigMatchAppendSMToList(s, sm, DETECT_SM_LIST_AMATCH); + s->flags |= SIG_FLAG_APPLAYER; + } return 0; @@ -221,6 +272,11 @@ void DetectAppLayerEventFree(void *ptr) #ifdef UNITTESTS /* UNITTESTS */ +#include "stream-tcp-private.h" +#include "stream-tcp-reassemble.h" +#include "stream-tcp.h" +#include "app-layer.h" + #define APP_LAYER_EVENT_TEST_MAP_EVENT1 0 #define APP_LAYER_EVENT_TEST_MAP_EVENT2 1 #define APP_LAYER_EVENT_TEST_MAP_EVENT3 2 @@ -261,9 +317,11 @@ int DetectAppLayerEventTest01(void) AppLayerRegisterGetEventInfo(ALPROTO_SMTP, DetectAppLayerEventTestGetEventInfo); + AppLayerEventType event_type; int result = 0; - DetectAppLayerEventData *aled = DetectAppLayerEventParse("smtp.event1"); + DetectAppLayerEventData *aled = DetectAppLayerEventParse("smtp.event1", + &event_type); if (aled == NULL) goto end; if (aled->alproto != ALPROTO_SMTP || @@ -294,9 +352,11 @@ int DetectAppLayerEventTest02(void) AppLayerRegisterGetEventInfo(ALPROTO_FTP, DetectAppLayerEventTestGetEventInfo); + AppLayerEventType event_type; int result = 0; - DetectAppLayerEventData *aled = DetectAppLayerEventParse("smtp.event1"); + DetectAppLayerEventData *aled = DetectAppLayerEventParse("smtp.event1", + &event_type); if (aled == NULL) goto end; if (aled->alproto != ALPROTO_SMTP || @@ -305,7 +365,8 @@ int DetectAppLayerEventTest02(void) goto end; } - aled = DetectAppLayerEventParse("smtp.event4"); + aled = DetectAppLayerEventParse("smtp.event4", + &event_type); if (aled == NULL) goto end; if (aled->alproto != ALPROTO_SMTP || @@ -314,7 +375,8 @@ int DetectAppLayerEventTest02(void) goto end; } - aled = DetectAppLayerEventParse("http.event2"); + aled = DetectAppLayerEventParse("http.event2", + &event_type); if (aled == NULL) goto end; if (aled->alproto != ALPROTO_HTTP || @@ -323,7 +385,8 @@ int DetectAppLayerEventTest02(void) goto end; } - aled = DetectAppLayerEventParse("smb.event3"); + aled = DetectAppLayerEventParse("smb.event3", + &event_type); if (aled == NULL) goto end; if (aled->alproto != ALPROTO_SMB || @@ -332,7 +395,8 @@ int DetectAppLayerEventTest02(void) goto end; } - aled = DetectAppLayerEventParse("ftp.event5"); + aled = DetectAppLayerEventParse("ftp.event5", + &event_type); if (aled == NULL) goto end; if (aled->alproto != ALPROTO_FTP || @@ -350,6 +414,331 @@ int DetectAppLayerEventTest02(void) return result; } +int DetectAppLayerEventTest03(void) +{ + int result = 0; + ThreadVars tv; + TcpReassemblyThreadCtx *ra_ctx = NULL; + Packet *p = NULL; + Flow *f = NULL; + TcpSession ssn; + TcpStream stream_ts, stream_tc; + DetectEngineCtx *de_ctx = NULL; + DetectEngineThreadCtx *det_ctx = NULL; + + uint8_t buf_ts[] = "GET /index.html HTTP/1.1\r\n" + "Host: 127.0.0.1\r\n" + "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" + "Accept: text/html,application/xhtml+xml,application/xml;q=0.9,*/*;q=0.8\r\n" + "Accept-Language: en-us,en;q=0.5\r\n" + "Accept-Encoding: gzip,deflate\r\n" + "Accept-Charset: ISO-8859-1,utf-8;q=0.7,*;q=0.7\r\n" + "Keep-Alive: 115\r\n" + "Connection: keep-alive\r\n" + "\r\n"; + uint8_t buf_tc[] = "HTTP/1.1 200 OK\r\n" + "Date: Fri, 22 Oct 2010 12:31:08 GMT\r\n" + "Server: Apache/2.2.15 (Unix) DAV/2\r\n" + "Last-Modified: Sat, 20 Nov 2004 20:16:24 GMT\r\n" + "ETag: \"ab8486-2c-3e9564c23b600\"\r\n" + "Accept-Ranges: bytes\r\n" + "Content-Length: 44\r\n" + "Keep-Alive: timeout=5, max=100\r\n" + "Connection: Keep-Alive\r\n" + "Content-Type: text/html\r\n" + "\r\n" + "

It works!

"; + + memset(&tv, 0, sizeof (ThreadVars)); + memset(&ssn, 0, sizeof(TcpSession)); + memset(&stream_ts, 0, sizeof(TcpStream)); + memset(&stream_tc, 0, sizeof(TcpStream)); + + ssn.data_first_seen_dir = STREAM_TOSERVER; + + de_ctx = DetectEngineCtxInit(); + if (de_ctx == NULL) + goto end; + de_ctx->flags |= DE_QUIET; + de_ctx->sig_list = SigInit(de_ctx, "alert tcp any any -> any any " + "(app-layer-event: applayer_mismatch_protocol_both_directions; " + "sid:1;)"); + if (de_ctx->sig_list == NULL) + goto end; + SigGroupBuild(de_ctx); + DetectEngineThreadCtxInit(&tv, (void *)de_ctx, (void *)&det_ctx); + + f = UTHBuildFlow(AF_INET, "1.2.3.4", "1.2.3.5", 200, 220); + if (f == NULL) + goto end; + FLOW_INITIALIZE(f); + f->protoctx = &ssn; + f->flags |= FLOW_IPV4; + + p = PacketGetFromAlloc(); + if (unlikely(p == NULL)) + goto end; + p->flow = f; + p->src.family = AF_INET; + p->dst.family = AF_INET; + p->proto = IPPROTO_TCP; + + ra_ctx = StreamTcpReassembleInitThreadCtx(); + if (ra_ctx == NULL) + goto end; + StreamTcpInitConfig(TRUE); + + p->flowflags = FLOW_PKT_TOSERVER; + if (AppLayerHandleTCPData(&tv, ra_ctx, f, &ssn, &stream_ts, buf_ts, + sizeof(buf_ts), p, STREAM_TOSERVER | STREAM_START) < 0) { + printf("AppLayerHandleTCPData failure\n"); + goto end; + } + SigMatchSignatures(&tv, de_ctx, det_ctx, p); + if (PacketAlertCheck(p, 1)) { + printf("sid 1 matched but shouldn't have\n"); + goto end; + } + + p->flowflags = FLOW_PKT_TOCLIENT; + if (AppLayerHandleTCPData(&tv, ra_ctx, f, &ssn, &stream_tc, buf_tc, + sizeof(buf_tc), p, STREAM_TOCLIENT | STREAM_START) < 0) { + printf("AppLayerHandleTCPData failure\n"); + goto end; + } + SigMatchSignatures(&tv, de_ctx, det_ctx, p); + if (PacketAlertCheck(p, 1)) { + printf("sid 1 matched but shouldn't have\n"); + goto end; + } + + result = 1; + end: + return result; +} + +int DetectAppLayerEventTest04(void) +{ + int result = 0; + ThreadVars tv; + TcpReassemblyThreadCtx *ra_ctx = NULL; + Packet *p = NULL; + Flow *f = NULL; + TcpSession ssn; + TcpStream stream_ts, stream_tc; + DetectEngineCtx *de_ctx = NULL; + DetectEngineThreadCtx *det_ctx = NULL; + + uint8_t buf_ts[] = "GET /index.html HTTP/1.1\r\n" + "Host: 127.0.0.1\r\n" + "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" + "Accept: text/html,application/xhtml+xml,application/xml;q=0.9,*/*;q=0.8\r\n" + "Accept-Language: en-us,en;q=0.5\r\n" + "Accept-Encoding: gzip,deflate\r\n" + "Accept-Charset: ISO-8859-1,utf-8;q=0.7,*;q=0.7\r\n" + "Keep-Alive: 115\r\n" + "Connection: keep-alive\r\n" + "\r\n"; + uint8_t buf_tc[] = "XTTP/1.1 200 OK\r\n" + "Date: Fri, 22 Oct 2010 12:31:08 GMT\r\n" + "Server: Apache/2.2.15 (Unix) DAV/2\r\n" + "Last-Modified: Sat, 20 Nov 2004 20:16:24 GMT\r\n" + "ETag: \"ab8486-2c-3e9564c23b600\"\r\n" + "Accept-Ranges: bytes\r\n" + "Content-Length: 44\r\n" + "Keep-Alive: timeout=5, max=100\r\n" + "Connection: Keep-Alive\r\n" + "Content-Type: text/html\r\n" + "\r\n" + "

It works!

"; + + memset(&tv, 0, sizeof (ThreadVars)); + memset(&ssn, 0, sizeof(TcpSession)); + memset(&stream_ts, 0, sizeof(TcpStream)); + memset(&stream_tc, 0, sizeof(TcpStream)); + + ssn.data_first_seen_dir = STREAM_TOSERVER; + + de_ctx = DetectEngineCtxInit(); + if (de_ctx == NULL) + goto end; + de_ctx->flags |= DE_QUIET; + de_ctx->sig_list = SigInit(de_ctx, "alert tcp any any -> any any " + "(app-layer-event: applayer_detect_protocol_only_one_direction; " + "sid:1;)"); + if (de_ctx->sig_list == NULL) + goto end; + SigGroupBuild(de_ctx); + DetectEngineThreadCtxInit(&tv, (void *)de_ctx, (void *)&det_ctx); + + f = UTHBuildFlow(AF_INET, "1.2.3.4", "1.2.3.5", 200, 220); + if (f == NULL) + goto end; + FLOW_INITIALIZE(f); + f->protoctx = &ssn; + f->flags |= FLOW_IPV4; + + p = PacketGetFromAlloc(); + if (unlikely(p == NULL)) + goto end; + p->flow = f; + p->src.family = AF_INET; + p->dst.family = AF_INET; + p->proto = IPPROTO_TCP; + + ra_ctx = StreamTcpReassembleInitThreadCtx(); + if (ra_ctx == NULL) + goto end; + StreamTcpInitConfig(TRUE); + + p->flowflags = FLOW_PKT_TOSERVER; + if (AppLayerHandleTCPData(&tv, ra_ctx, f, &ssn, &stream_ts, buf_ts, + sizeof(buf_ts), p, STREAM_TOSERVER | STREAM_START) < 0) { + printf("AppLayerHandleTCPData failure\n"); + goto end; + } + SigMatchSignatures(&tv, de_ctx, det_ctx, p); + if (PacketAlertCheck(p, 1)) { + printf("sid 1 matched but shouldn't have\n"); + goto end; + } + + p->flowflags = FLOW_PKT_TOCLIENT; + if (AppLayerHandleTCPData(&tv, ra_ctx, f, &ssn, &stream_tc, buf_tc, + sizeof(buf_tc), p, STREAM_TOCLIENT | STREAM_START) < 0) { + printf("AppLayerHandleTCPData failure\n"); + goto end; + } + SigMatchSignatures(&tv, de_ctx, det_ctx, p); + if (!PacketAlertCheck(p, 1)) { + printf("sid 1 didn't match but should have\n"); + goto end; + } + + result = 1; + end: + return result; +} + +int DetectAppLayerEventTest05(void) +{ + int result = 0; + ThreadVars tv; + TcpReassemblyThreadCtx *ra_ctx = NULL; + Packet *p = NULL; + Flow *f = NULL; + TcpSession ssn; + TcpStream stream_ts, stream_tc; + DetectEngineCtx *de_ctx = NULL; + DetectEngineThreadCtx *det_ctx = NULL; + + uint8_t buf_ts[] = "GET /index.html HTTP/1.1\r\n" + "Host: 127.0.0.1\r\n" + "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" + "Accept: text/html,application/xhtml+xml,application/xml;q=0.9,*/*;q=0.8\r\n" + "Accept-Language: en-us,en;q=0.5\r\n" + "Accept-Encoding: gzip,deflate\r\n" + "Accept-Charset: ISO-8859-1,utf-8;q=0.7,*;q=0.7\r\n" + "Keep-Alive: 115\r\n" + "Connection: keep-alive\r\n" + "\r\n"; + /* tls */ + uint8_t buf_tc[] = { + 0x16, 0x03, 0x01, 0x00, 0x86, 0x10, 0x00, 0x00, + 0x82, 0x00, 0x80, 0xd3, 0x6f, 0x1f, 0x63, 0x82, + 0x8d, 0x75, 0x77, 0x8c, 0x91, 0xbc, 0xa1, 0x3d, + 0xbb, 0xe1, 0xb5, 0xd3, 0x31, 0x92, 0x59, 0x2b, + 0x2c, 0x43, 0x96, 0xa3, 0xaa, 0x23, 0x92, 0xd0, + 0x91, 0x2a, 0x5e, 0x10, 0x5b, 0xc8, 0xc1, 0xe2, + 0xd3, 0x5c, 0x8b, 0x8c, 0x91, 0x9e, 0xc2, 0xf2, + 0x9c, 0x3c, 0x4f, 0x37, 0x1e, 0x20, 0x5e, 0x33, + 0xd5, 0xf0, 0xd6, 0xaf, 0x89, 0xf5, 0xcc, 0xb2, + 0xcf, 0xc1, 0x60, 0x3a, 0x46, 0xd5, 0x4e, 0x2a, + 0xb6, 0x6a, 0xb9, 0xfc, 0x32, 0x8b, 0xe0, 0x6e, + 0xa0, 0xed, 0x25, 0xa0, 0xa4, 0x82, 0x81, 0x73, + 0x90, 0xbf, 0xb5, 0xde, 0xeb, 0x51, 0x8d, 0xde, + 0x5b, 0x6f, 0x94, 0xee, 0xba, 0xe5, 0x69, 0xfa, + 0x1a, 0x80, 0x30, 0x54, 0xeb, 0x12, 0x01, 0xb9, + 0xfe, 0xbf, 0x82, 0x95, 0x01, 0x7b, 0xb0, 0x97, + 0x14, 0xc2, 0x06, 0x3c, 0x69, 0xfb, 0x1c, 0x66, + 0x47, 0x17, 0xd9, 0x14, 0x03, 0x01, 0x00, 0x01, + 0x01, 0x16, 0x03, 0x01, 0x00, 0x30, 0xf6, 0xbc, + 0x0d, 0x6f, 0xe8, 0xbb, 0xaa, 0xbf, 0x14, 0xeb, + 0x7b, 0xcc, 0x6c, 0x28, 0xb0, 0xfc, 0xa6, 0x01, + 0x2a, 0x97, 0x96, 0x17, 0x5e, 0xe8, 0xb4, 0x4e, + 0x78, 0xc9, 0x04, 0x65, 0x53, 0xb6, 0x93, 0x3d, + 0xeb, 0x44, 0xee, 0x86, 0xf9, 0x80, 0x49, 0x45, + 0x21, 0x34, 0xd1, 0xee, 0xc8, 0x9c, + }; + + memset(&tv, 0, sizeof (ThreadVars)); + memset(&ssn, 0, sizeof(TcpSession)); + memset(&stream_ts, 0, sizeof(TcpStream)); + memset(&stream_tc, 0, sizeof(TcpStream)); + + ssn.data_first_seen_dir = STREAM_TOSERVER; + + de_ctx = DetectEngineCtxInit(); + if (de_ctx == NULL) + goto end; + de_ctx->flags |= DE_QUIET; + de_ctx->sig_list = SigInit(de_ctx, "alert tcp any any -> any any " + "(app-layer-event: applayer_mismatch_protocol_both_directions; " + "sid:1;)"); + if (de_ctx->sig_list == NULL) + goto end; + SigGroupBuild(de_ctx); + DetectEngineThreadCtxInit(&tv, (void *)de_ctx, (void *)&det_ctx); + + f = UTHBuildFlow(AF_INET, "1.2.3.4", "1.2.3.5", 200, 220); + if (f == NULL) + goto end; + FLOW_INITIALIZE(f); + f->protoctx = &ssn; + f->flags |= FLOW_IPV4; + + p = PacketGetFromAlloc(); + if (unlikely(p == NULL)) + goto end; + p->flow = f; + p->src.family = AF_INET; + p->dst.family = AF_INET; + p->proto = IPPROTO_TCP; + + ra_ctx = StreamTcpReassembleInitThreadCtx(); + if (ra_ctx == NULL) + goto end; + StreamTcpInitConfig(TRUE); + + p->flowflags = FLOW_PKT_TOSERVER; + if (AppLayerHandleTCPData(&tv, ra_ctx, f, &ssn, &stream_ts, buf_ts, + sizeof(buf_ts), p, STREAM_TOSERVER | STREAM_START) < 0) { + printf("AppLayerHandleTCPData failure\n"); + goto end; + } + SigMatchSignatures(&tv, de_ctx, det_ctx, p); + if (PacketAlertCheck(p, 1)) { + printf("sid 1 matched but shouldn't have\n"); + goto end; + } + + p->flowflags = FLOW_PKT_TOCLIENT; + if (AppLayerHandleTCPData(&tv, ra_ctx, f, &ssn, &stream_tc, buf_tc, + sizeof(buf_tc), p, STREAM_TOCLIENT | STREAM_START) < 0) { + printf("AppLayerHandleTCPData failure\n"); + goto end; + } + SigMatchSignatures(&tv, de_ctx, det_ctx, p); + if (!PacketAlertCheck(p, 1)) { + printf("sid 1 didn't match but should have\n"); + goto end; + } + + result = 1; + end: + return result; +} + #endif /* UNITTESTS */ /** @@ -360,6 +749,9 @@ void DetectAppLayerEventRegisterTests(void) #ifdef UNITTESTS /* UNITTESTS */ UtRegisterTest("DetectAppLayerEventTest01", DetectAppLayerEventTest01, 1); UtRegisterTest("DetectAppLayerEventTest02", DetectAppLayerEventTest02, 1); + UtRegisterTest("DetectAppLayerEventTest03", DetectAppLayerEventTest03, 1); + UtRegisterTest("DetectAppLayerEventTest04", DetectAppLayerEventTest04, 1); + UtRegisterTest("DetectAppLayerEventTest05", DetectAppLayerEventTest05, 1); #endif /* UNITTESTS */ return; diff --git a/src/detect-byte-extract.c b/src/detect-byte-extract.c index a7225f31f8..948a996623 100644 --- a/src/detect-byte-extract.c +++ b/src/detect-byte-extract.c @@ -677,6 +677,8 @@ int DetectByteExtractSetup(DetectEngineCtx *de_ctx, Signature *s, char *arg) sm_list = DETECT_SM_LIST_PMATCH; } else { sm_list = SigMatchListSMBelongsTo(s, prev_pm); + if (sm_list != DETECT_SM_LIST_PMATCH) + s->flags |= SIG_FLAG_APPLAYER; } } else { diff --git a/src/detect-ftpbounce.c b/src/detect-ftpbounce.c index 6f36f66b0d..1840ae9b07 100644 --- a/src/detect-ftpbounce.c +++ b/src/detect-ftpbounce.c @@ -269,14 +269,15 @@ int DetectFtpbounceSetup(DetectEngineCtx *de_ctx, Signature *s, char *ftpbounces */ sm->ctx = NULL; - SigMatchAppendSMToList(s, sm, DETECT_SM_LIST_AMATCH); - if (s->alproto != ALPROTO_UNKNOWN && s->alproto != ALPROTO_FTP) { SCLogError(SC_ERR_CONFLICTING_RULE_KEYWORDS, "rule contains conflicting keywords."); goto error; } + SigMatchAppendSMToList(s, sm, DETECT_SM_LIST_AMATCH); + s->alproto = ALPROTO_FTP; + s->flags |= SIG_FLAG_APPLAYER; SCReturnInt(0); error: diff --git a/src/detect-parse.c b/src/detect-parse.c index 93780c236f..269ece987e 100644 --- a/src/detect-parse.c +++ b/src/detect-parse.c @@ -1427,8 +1427,6 @@ static Signature *SigInitHelper(DetectEngineCtx *de_ctx, char *sigstr, if (sig->sm_lists[DETECT_SM_LIST_MATCH] != NULL) { SigMatch *sm = sig->sm_lists[DETECT_SM_LIST_MATCH]; for ( ; sm != NULL; sm = sm->next) { - if (sigmatch_table[sm->type].AppLayerMatch != NULL) - sig->flags |= SIG_FLAG_APPLAYER; if (sigmatch_table[sm->type].Match != NULL) sig->init_flags |= SIG_FLAG_INIT_PACKET; } @@ -1437,6 +1435,9 @@ static Signature *SigInitHelper(DetectEngineCtx *de_ctx, char *sigstr, } } + if (sig->sm_lists[DETECT_SM_LIST_AMATCH] != NULL) + sig->flags |= SIG_FLAG_APPLAYER; + if (sig->sm_lists[DETECT_SM_LIST_UMATCH]) sig->flags |= SIG_FLAG_STATE_MATCH; if (sig->sm_lists[DETECT_SM_LIST_DMATCH]) diff --git a/src/detect-ssh-proto-version.c b/src/detect-ssh-proto-version.c index 41201a76f8..e66be0f902 100644 --- a/src/detect-ssh-proto-version.c +++ b/src/detect-ssh-proto-version.c @@ -244,16 +244,17 @@ static int DetectSshVersionSetup (DetectEngineCtx *de_ctx, Signature *s, char *s if (sm == NULL) goto error; - sm->type = DETECT_AL_SSH_PROTOVERSION; - sm->ctx = (void *)ssh; - - SigMatchAppendSMToList(s, sm, DETECT_SM_LIST_AMATCH); - if (s->alproto != ALPROTO_UNKNOWN && s->alproto != ALPROTO_SSH) { SCLogError(SC_ERR_CONFLICTING_RULE_KEYWORDS, "rule contains conflicting keywords."); goto error; } + sm->type = DETECT_AL_SSH_PROTOVERSION; + sm->ctx = (void *)ssh; + + SigMatchAppendSMToList(s, sm, DETECT_SM_LIST_AMATCH); + + s->flags |= SIG_FLAG_APPLAYER; s->alproto = ALPROTO_SSH; return 0; diff --git a/src/detect-ssh-software-version.c b/src/detect-ssh-software-version.c index 0d5b132a48..bcde214b87 100644 --- a/src/detect-ssh-software-version.c +++ b/src/detect-ssh-software-version.c @@ -225,17 +225,19 @@ static int DetectSshSoftwareVersionSetup (DetectEngineCtx *de_ctx, Signature *s, if (sm == NULL) goto error; - sm->type = DETECT_AL_SSH_SOFTWAREVERSION; - sm->ctx = (void *)ssh; - - SigMatchAppendSMToList(s, sm, DETECT_SM_LIST_AMATCH); - if (s->alproto != ALPROTO_UNKNOWN && s->alproto != ALPROTO_SSH) { SCLogError(SC_ERR_CONFLICTING_RULE_KEYWORDS, "rule contains conflicting keywords."); goto error; } + sm->type = DETECT_AL_SSH_SOFTWAREVERSION; + sm->ctx = (void *)ssh; + + s->flags |= SIG_FLAG_APPLAYER; s->alproto = ALPROTO_SSH; + + SigMatchAppendSMToList(s, sm, DETECT_SM_LIST_AMATCH); + return 0; error: diff --git a/src/detect-tls.c b/src/detect-tls.c index e8e813d65a..746fd58f23 100644 --- a/src/detect-tls.c +++ b/src/detect-tls.c @@ -344,17 +344,19 @@ static int DetectTlsSubjectSetup (DetectEngineCtx *de_ctx, Signature *s, char *s if (sm == NULL) goto error; - sm->type = DETECT_AL_TLS_SUBJECT; - sm->ctx = (void *)tls; - - SigMatchAppendSMToList(s, sm, DETECT_SM_LIST_AMATCH); - if (s->alproto != ALPROTO_UNKNOWN && s->alproto != ALPROTO_TLS) { SCLogError(SC_ERR_CONFLICTING_RULE_KEYWORDS, "rule contains conflicting keywords."); goto error; } + sm->type = DETECT_AL_TLS_SUBJECT; + sm->ctx = (void *)tls; + + s->flags |= SIG_FLAG_APPLAYER; s->alproto = ALPROTO_TLS; + + SigMatchAppendSMToList(s, sm, DETECT_SM_LIST_AMATCH); + return 0; error: @@ -544,17 +546,19 @@ static int DetectTlsIssuerDNSetup (DetectEngineCtx *de_ctx, Signature *s, char * if (sm == NULL) goto error; - sm->type = DETECT_AL_TLS_ISSUERDN; - sm->ctx = (void *)tls; - - SigMatchAppendSMToList(s, sm, DETECT_SM_LIST_AMATCH); - if (s->alproto != ALPROTO_UNKNOWN && s->alproto != ALPROTO_TLS) { SCLogError(SC_ERR_CONFLICTING_RULE_KEYWORDS, "rule contains conflicting keywords."); goto error; } + sm->type = DETECT_AL_TLS_ISSUERDN; + sm->ctx = (void *)tls; + + s->flags |= SIG_FLAG_APPLAYER; s->alproto = ALPROTO_TLS; + + SigMatchAppendSMToList(s, sm, DETECT_SM_LIST_AMATCH); + return 0; error: @@ -733,17 +737,19 @@ static int DetectTlsFingerprintSetup (DetectEngineCtx *de_ctx, Signature *s, cha if (sm == NULL) goto error; - sm->type = DETECT_AL_TLS_FINGERPRINT; - sm->ctx = (void *)tls; - - SigMatchAppendSMToList(s, sm, DETECT_SM_LIST_AMATCH); - if (s->alproto != ALPROTO_UNKNOWN && s->alproto != ALPROTO_TLS) { SCLogError(SC_ERR_CONFLICTING_RULE_KEYWORDS, "rule contains conflicting keywords."); goto error; } + sm->type = DETECT_AL_TLS_FINGERPRINT; + sm->ctx = (void *)tls; + + s->flags |= SIG_FLAG_APPLAYER; s->alproto = ALPROTO_TLS; + + SigMatchAppendSMToList(s, sm, DETECT_SM_LIST_AMATCH); + return 0; error: @@ -788,15 +794,17 @@ static int DetectTlsStoreSetup (DetectEngineCtx *de_ctx, Signature *s, char *str if (sm == NULL) goto error; - sm->type = DETECT_AL_TLS_STORE; - SigMatchAppendSMToList(s, sm, DETECT_SM_LIST_AMATCH); - if (s->alproto != ALPROTO_UNKNOWN && s->alproto != ALPROTO_TLS) { SCLogError(SC_ERR_CONFLICTING_RULE_KEYWORDS, "rule contains conflicting keywords."); goto error; } + sm->type = DETECT_AL_TLS_STORE; + s->flags |= SIG_FLAG_APPLAYER; s->alproto = ALPROTO_TLS; + + SigMatchAppendSMToList(s, sm, DETECT_SM_LIST_AMATCH); + return 0; error: diff --git a/src/detect.c b/src/detect.c index 0341de593e..d84d485676 100644 --- a/src/detect.c +++ b/src/detect.c @@ -2043,7 +2043,7 @@ PacketCreateMask(Packet *p, SignatureMask *mask, uint16_t alproto, void *alstate (*mask) |= SIG_MASK_REQUIRE_NO_PAYLOAD; } - if (p->events.cnt > 0 || app_decoder_events != 0) { + if (p->events.cnt > 0 || app_decoder_events != 0 || p->app_layer_events != NULL) { SCLogDebug("packet/flow has events set"); (*mask) |= SIG_MASK_REQUIRE_ENGINE_EVENT; } @@ -2251,6 +2251,9 @@ static int SignatureCreateMask(Signature *s) { } break; } + case DETECT_AL_APP_LAYER_EVENT: + s->mask |= SIG_MASK_REQUIRE_ENGINE_EVENT; + break; case DETECT_ENGINE_EVENT: s->mask |= SIG_MASK_REQUIRE_ENGINE_EVENT; break;