From: Victor Julien Date: Thu, 23 Jan 2014 08:55:09 +0000 (+0100) Subject: app-layer-event: refactor X-Git-Tag: suricata-2.0rc1~161 X-Git-Url: http://git.ipfire.org/gitweb.cgi?a=commitdiff_plain;h=347c0df9c4e821f33938628855e3ceed115fd9d0;p=thirdparty%2Fsuricata.git app-layer-event: refactor Move app layer event handling into app-layer-event.[ch]. Convert 'Set' macro's to functions. Get rid of duplication in Set and SetRaw. Set now calls SetRaw. Fix potentential int overflow condition in the event storage. Update callers. --- diff --git a/src/Makefile.am b/src/Makefile.am index db6b108f70..39bc612ae0 100644 --- a/src/Makefile.am +++ b/src/Makefile.am @@ -20,6 +20,7 @@ app-layer-detect-proto.c app-layer-detect-proto.h \ app-layer-dns-common.c app-layer-dns-common.h \ app-layer-dns-tcp.c app-layer-dns-tcp.h \ app-layer-dns-udp.c app-layer-dns-udp.h \ +app-layer-events.c app-layer-events.h \ app-layer-ftp.c app-layer-ftp.h \ app-layer-htp-body.c app-layer-htp-body.h \ app-layer-htp.c app-layer-htp.h \ diff --git a/src/app-layer-dns-common.c b/src/app-layer-dns-common.c index 27e2846a95..57c96917fc 100644 --- a/src/app-layer-dns-common.c +++ b/src/app-layer-dns-common.c @@ -196,7 +196,7 @@ int DNSGetAlstateProgressCompletionStatus(uint8_t direction) { void DNSSetEvent(DNSState *s, uint8_t e) { if (s && s->curr) { SCLogDebug("s->curr->decoder_events %p", s->curr->decoder_events); - AppLayerDecoderEventsSetEventRaw(s->curr->decoder_events, e); + AppLayerDecoderEventsSetEventRaw(&s->curr->decoder_events, e); SCLogDebug("s->curr->decoder_events %p", s->curr->decoder_events); s->events++; } else { @@ -251,7 +251,7 @@ static void DNSTransactionFree(DNSTransaction *tx, DNSState *state) { SCFree(a); } - AppLayerDecoderEventsFreeEvents(tx->decoder_events); + AppLayerDecoderEventsFreeEvents(&tx->decoder_events); DNSDecrMemcap(sizeof(DNSTransaction), state); SCFree(tx); diff --git a/src/app-layer-events.c b/src/app-layer-events.c new file mode 100644 index 0000000000..cd00a4ee8b --- /dev/null +++ b/src/app-layer-events.c @@ -0,0 +1,137 @@ +/* Copyright (C) 2014 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 + * Software Foundation. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * version 2 along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA + * 02110-1301, USA. + */ + +/** + * \file + * + * \author Victor Julien + * \author Anoop Saldanha + */ + +#include "suricata-common.h" +#include "decode.h" +#include "flow.h" +#include "app-layer-events.h" +#include "app-layer-parser.h" +#include "util-enum.h" + +/* events raised during protocol detection are stored in the + * packets storage, not in the flow. */ +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 }, + { "APPLAYER_PROTO_DETECTION_SKIPPED", + APPLAYER_PROTO_DETECTION_SKIPPED }, + { 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; +} + +#define DECODER_EVENTS_BUFFER_STEPS 8 + +/** + * \brief Set an app layer decoder event. + * + * \param sevents Pointer to a AppLayerDecoderEvents pointer. If *sevents is NULL + * memory will be allocated. + * \param event The event to be stored. + */ +void AppLayerDecoderEventsSetEventRaw(AppLayerDecoderEvents **sevents, uint8_t event) +{ + if (*sevents == NULL) { + AppLayerDecoderEvents *new_devents = SCMalloc(sizeof(AppLayerDecoderEvents)); + if (new_devents == NULL) + return; + + memset(new_devents, 0, sizeof(AppLayerDecoderEvents)); + *sevents = new_devents; + + } + if ((*sevents)->cnt == UCHAR_MAX) { + /* we're full */ + return; + } + if ((*sevents)->cnt == (*sevents)->events_buffer_size) { + int steps = DECODER_EVENTS_BUFFER_STEPS; + if (UCHAR_MAX - (*sevents)->cnt < steps) + steps = UCHAR_MAX - (*sevents)->cnt < steps; + + void *ptr = SCRealloc((*sevents)->events, + ((*sevents)->cnt + steps) * sizeof(uint8_t)); + if (ptr == NULL) { + /* couldn't grow buffer, but no reason to free old + * so we keep the events that may already be here */ + return; + } + (*sevents)->events = ptr; + (*sevents)->events_buffer_size += steps; + } + + (*sevents)->events[(*sevents)->cnt++] = event; +} + +/** + * \brief Set an app layer decoder event. + * + * \param f Pointer to a flow containing DecoderEvents pointer head. If + * the head points to a DecoderEvents instance, a + * new instance would be created and the pointer head would + * would be updated with this new instance + * \param event The event to be stored. + */ +void AppLayerDecoderEventsSetEvent(Flow *f, uint8_t event) +{ + AppLayerDecoderEvents *events = AppLayerParserGetDecoderEvents(f->alparser); + AppLayerDecoderEvents *new = events; + AppLayerDecoderEventsSetEventRaw(&events, event); + if (events != new) + AppLayerParserSetDecoderEvents(f->alparser, events); +} + +void AppLayerDecoderEventsResetEvents(AppLayerDecoderEvents *events) +{ + if (events != NULL) + events->cnt = 0; +} + + +void AppLayerDecoderEventsFreeEvents(AppLayerDecoderEvents **events) +{ + if (events && *events != NULL) { + if ((*events)->events != NULL) + SCFree((*events)->events); + SCFree(*events); + *events = NULL; + } +} + diff --git a/src/app-layer-events.h b/src/app-layer-events.h new file mode 100644 index 0000000000..11dfb9e60d --- /dev/null +++ b/src/app-layer-events.h @@ -0,0 +1,83 @@ +/* Copyright (C) 2014 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 + * Software Foundation. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * version 2 along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA + * 02110-1301, USA. + */ + +/** + * \file + * + * \author Victor Julien + * \author Anoop Saldanha + */ + +#ifndef __APP_LAYER_EVENTS_H__ +#define __APP_LAYER_EVENTS_H__ + +/* contains fwd declaration of AppLayerDecoderEvents_ */ +#include "decode.h" + +/** + * \brief Data structure to store app layer decoder events. + */ +struct AppLayerDecoderEvents_ { + /* array of events */ + uint8_t *events; + /* number of events in the above buffer */ + uint8_t cnt; + /* current event buffer size */ + uint8_t events_buffer_size; +}; + +/* app layer pkt level events */ +enum { + APPLAYER_MISMATCH_PROTOCOL_BOTH_DIRECTIONS, + APPLAYER_WRONG_DIRECTION_FIRST_DATA, + APPLAYER_DETECT_PROTOCOL_ONLY_ONE_DIRECTION, + APPLAYER_PROTO_DETECTION_SKIPPED, +}; + +/* 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; + +int AppLayerGetPktEventInfo(const char *event_name, int *event_id); + +void AppLayerDecoderEventsSetEventRaw(AppLayerDecoderEvents **sevents, uint8_t event); +void AppLayerDecoderEventsSetEvent(Flow *f, uint8_t event); + +static inline int AppLayerDecoderEventsIsEventSet(AppLayerDecoderEvents *devents, + uint8_t event) +{ + if (devents == NULL) + return 0; + + int i; + int cnt = devents->cnt; + for (i = 0; i < cnt; i++) { + if (devents->events[i] == event) + return 1; + } + + return 0; +} + +void AppLayerDecoderEventsResetEvents(AppLayerDecoderEvents *events); +void AppLayerDecoderEventsFreeEvents(AppLayerDecoderEvents **events); + +#endif /* __APP_LAYER_EVENTS_H__ */ + diff --git a/src/app-layer-parser.c b/src/app-layer-parser.c index a56cdd421f..4d297c80b3 100644 --- a/src/app-layer-parser.c +++ b/src/app-layer-parser.c @@ -158,7 +158,7 @@ void AppLayerParserStateFree(AppLayerParserState *pstate) SCEnter(); if (pstate->decoder_events != NULL) - AppLayerDecoderEventsFreeEvents(pstate->decoder_events); + AppLayerDecoderEventsFreeEvents(&pstate->decoder_events); SCFree(pstate); SCReturn; diff --git a/src/app-layer-parser.h b/src/app-layer-parser.h index 69f94b62b6..cefd7287ad 100644 --- a/src/app-layer-parser.h +++ b/src/app-layer-parser.h @@ -25,7 +25,7 @@ #ifndef __APP_LAYER_PARSER_H__ #define __APP_LAYER_PARSER_H__ -#include "decode-events.h" +#include "app-layer-events.h" #include "util-file.h" #define APP_LAYER_PARSER_EOF 0x01 diff --git a/src/app-layer.c b/src/app-layer.c index 5bdf0da46f..1d699178ea 100644 --- a/src/app-layer.c +++ b/src/app-layer.c @@ -156,7 +156,7 @@ int AppLayerHandleTCPData(ThreadVars *tv, TcpReassemblyThreadCtx *ra_ctx, if (*alproto != ALPROTO_UNKNOWN) { if (*alproto_otherdir != ALPROTO_UNKNOWN && *alproto_otherdir != *alproto) { - AppLayerDecoderEventsSetEventRaw(p->app_layer_events, + AppLayerDecoderEventsSetEventRaw(&p->app_layer_events, APPLAYER_MISMATCH_PROTOCOL_BOTH_DIRECTIONS); /* it indicates some data has already been sent to the parser */ if (ssn->data_first_seen_dir == APP_LAYER_DATA_ALREADY_SENT_TO_APP_LAYER) { @@ -254,7 +254,7 @@ int AppLayerHandleTCPData(ThreadVars *tv, TcpReassemblyThreadCtx *ra_ctx, first_data_dir = AppLayerParserGetFirstDataDir(f->proto, *alproto); if (first_data_dir && !(first_data_dir & ssn->data_first_seen_dir)) { - AppLayerDecoderEventsSetEventRaw(p->app_layer_events, + AppLayerDecoderEventsSetEventRaw(&p->app_layer_events, APPLAYER_WRONG_DIRECTION_FIRST_DATA); FlowSetSessionNoApplayerInspectionFlag(f); StreamTcpSetStreamFlagAppProtoDetectionCompleted(&ssn->server); @@ -324,7 +324,7 @@ int AppLayerHandleTCPData(ThreadVars *tv, TcpReassemblyThreadCtx *ra_ctx, data + data_al_so_far, data_len - data_al_so_far); PACKET_PROFILING_APP_END(app_tctx, *alproto_otherdir); if (FLOW_IS_PM_DONE(f, flags) && FLOW_IS_PP_DONE(f, flags)) { - AppLayerDecoderEventsSetEventRaw(p->app_layer_events, + AppLayerDecoderEventsSetEventRaw(&p->app_layer_events, APPLAYER_DETECT_PROTOCOL_ONLY_ONE_DIRECTION); StreamTcpSetStreamFlagAppProtoDetectionCompleted(stream); f->data_al_so_far[dir] = 0; diff --git a/src/decode-events.c b/src/decode-events.c index 54d33796c0..cecf77c54d 100644 --- a/src/decode-events.c +++ b/src/decode-events.c @@ -22,30 +22,6 @@ */ #include "suricata-common.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 }, - { "APPLAYER_PROTO_DETECTION_SKIPPED", - APPLAYER_PROTO_DETECTION_SKIPPED }, - { NULL, - -1 }, -}; +/* code moved to app-layer-events */ -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 51aa99b46e..16aec8311a 100644 --- a/src/decode-events.h +++ b/src/decode-events.h @@ -224,141 +224,4 @@ 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, - APPLAYER_PROTO_DETECTION_SKIPPED, -}; - -#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; - -/** - * \brief Data structure to store app layer decoder events. - */ -typedef struct AppLayerDecoderEvents_ { - /* array of events */ - uint8_t *events; - /* number of events in the above buffer */ - uint8_t cnt; - /* current event buffer size */ - uint8_t events_buffer_size; -} AppLayerDecoderEvents; - -/** - * \brief Set an app layer decoder event. - * - * \param sevents Pointer to a DecoderEvents pointer head. If - * the head points to a DecoderEvents instance, a - * new instance would be created and the pointer head would - * would be updated with this new instance - * \param event The event to be stored. - */ -#define AppLayerDecoderEventsSetEventRaw(sevents, event) \ - do { \ - AppLayerDecoderEvents *devents = (sevents); \ - if (devents == NULL) { \ - AppLayerDecoderEvents *new_devents = \ - SCMalloc(sizeof(AppLayerDecoderEvents)); \ - if (new_devents == NULL) \ - break; \ - memset(new_devents, 0, sizeof(AppLayerDecoderEvents)); \ - (sevents) = devents = new_devents; \ - } \ - if (devents->cnt == devents->events_buffer_size) { \ - devents->events = SCRealloc(devents->events, \ - (devents->cnt + \ - DECODER_EVENTS_BUFFER_STEPS) * \ - sizeof(uint8_t)); \ - if (devents->events == NULL) { \ - devents->events_buffer_size = 0; \ - devents->cnt = 0; \ - (sevents) = NULL; \ - break; \ - } \ - devents->events_buffer_size += DECODER_EVENTS_BUFFER_STEPS; \ - } \ - devents->events[devents->cnt++] = (event); \ - } while (0) - -/** - * \brief Set an app layer decoder event. - * - * \param devents_head Pointer to a DecoderEvents pointer head. If - * the head points to a DecoderEvents instance, a - * new instance would be created and the pointer head would - * would be updated with this new instance - * \param event The event to be stored. - */ -#define AppLayerDecoderEventsSetEvent(f, event) \ - do { \ - AppLayerDecoderEvents *devents = \ - AppLayerParserGetDecoderEvents((f)->alparser); \ - if (devents == NULL) { \ - AppLayerDecoderEvents *new_devents = \ - SCMalloc(sizeof(AppLayerDecoderEvents)); \ - if (new_devents == NULL) \ - break; \ - memset(new_devents, 0, sizeof(AppLayerDecoderEvents)); \ - AppLayerParserSetDecoderEvents((f)->alparser, new_devents); \ - devents = new_devents; \ - } \ - if (devents->cnt == devents->events_buffer_size) { \ - devents->events = SCRealloc(devents->events, \ - (devents->cnt + \ - DECODER_EVENTS_BUFFER_STEPS) * \ - sizeof(uint8_t)); \ - if (devents->events == NULL) { \ - devents->events_buffer_size = 0; \ - devents->cnt = 0; \ - break; \ - } \ - devents->events_buffer_size += DECODER_EVENTS_BUFFER_STEPS; \ - } \ - devents->events[devents->cnt++] = (event); \ - SCLogDebug("setting app-layer-event %u", (event)); \ - } while (0) - -static inline int AppLayerDecoderEventsIsEventSet(AppLayerDecoderEvents *devents, - uint8_t event) -{ - if (devents == NULL) - return 0; - - int i; - int cnt = devents->cnt; - for (i = 0; i < cnt; i++) { - if (devents->events[i] == event) - return 1; - } - - return 0; -} - -#define AppLayerDecoderEventsResetEvents(devents) \ - do { \ - if ((devents) != NULL) { \ - (devents)->cnt = 0; \ - } \ - } while (0) - -#define AppLayerDecoderEventsFreeEvents(devents) \ - do { \ - if ((devents) != NULL) { \ - if ((devents)->events != NULL) \ - SCFree((devents)->events); \ - } \ - 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 790dac4ae3..49a1a69a06 100644 --- a/src/decode.h +++ b/src/decode.h @@ -83,10 +83,15 @@ enum PktSrcEnum { #include "app-layer-protos.h" +/* forward declarations */ +struct DetectionEngineThreadCtx_; typedef struct AppLayerThreadCtx_ AppLayerThreadCtx; -/* forward declaration */ -struct DetectionEngineThreadCtx_; +/* declare these here as they are called from the + * PACKET_RECYCLE and PACKET_CLEANUP macro's. */ +typedef struct AppLayerDecoderEvents_ AppLayerDecoderEvents; +void AppLayerDecoderEventsResetEvents(AppLayerDecoderEvents *events); +void AppLayerDecoderEventsFreeEvents(AppLayerDecoderEvents **events); /* Address */ typedef struct Address_ { @@ -712,7 +717,7 @@ typedef struct DecodeThreadVars_ PktVarFree((p)->pktvar); \ } \ SCMutexDestroy(&(p)->tunnel_mutex); \ - AppLayerDecoderEventsFreeEvents((p)->app_layer_events); \ + AppLayerDecoderEventsFreeEvents(&(p)->app_layer_events); \ } while (0) diff --git a/src/stream-tcp-reassemble.c b/src/stream-tcp-reassemble.c index 57f81b775a..7e763f51cf 100644 --- a/src/stream-tcp-reassemble.c +++ b/src/stream-tcp-reassemble.c @@ -55,6 +55,7 @@ #include "util-debug.h" #include "app-layer-protos.h" #include "app-layer.h" +#include "app-layer-events.h" #include "detect-engine-state.h" @@ -1720,7 +1721,7 @@ int StreamTcpReassembleHandleSegmentHandleData(ThreadVars *tv, TcpReassemblyThre if (stream->seg_list == NULL && stream->flags & STREAMTCP_STREAM_FLAG_APPPROTO_DETECTION_SKIPPED) { - AppLayerDecoderEventsSetEventRaw(p->app_layer_events, + AppLayerDecoderEventsSetEventRaw(&p->app_layer_events, APPLAYER_PROTO_DETECTION_SKIPPED); }