diff options
Diffstat (limited to 'framework/src/suricata/src/app-layer-parser.c')
-rw-r--r-- | framework/src/suricata/src/app-layer-parser.c | 1387 |
1 files changed, 0 insertions, 1387 deletions
diff --git a/framework/src/suricata/src/app-layer-parser.c b/framework/src/suricata/src/app-layer-parser.c deleted file mode 100644 index 2650863e..00000000 --- a/framework/src/suricata/src/app-layer-parser.c +++ /dev/null @@ -1,1387 +0,0 @@ -/* 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 - * 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 <victor@inliniac.net> - * - * Generic App-layer parsing functions. - */ - -#include "suricata-common.h" -#include "debug.h" -#include "util-unittest.h" -#include "decode.h" -#include "threads.h" - -#include "util-print.h" -#include "util-pool.h" - -#include "flow-util.h" -#include "flow-private.h" - -#include "detect-engine-state.h" -#include "detect-engine-port.h" - -#include "stream-tcp.h" -#include "stream-tcp-private.h" -#include "stream.h" -#include "stream-tcp-reassemble.h" - -#include "app-layer.h" -#include "app-layer-protos.h" -#include "app-layer-parser.h" -#include "app-layer-smb.h" -#include "app-layer-smb2.h" -#include "app-layer-dcerpc.h" -#include "app-layer-dcerpc-udp.h" -#include "app-layer-htp.h" -#include "app-layer-ftp.h" -#include "app-layer-ssl.h" -#include "app-layer-ssh.h" -#include "app-layer-smtp.h" -#include "app-layer-dns-udp.h" -#include "app-layer-dns-tcp.h" -#include "app-layer-modbus.h" -#include "app-layer-template.h" - -#include "conf.h" -#include "util-spm.h" - -#include "util-debug.h" -#include "decode-events.h" -#include "util-unittest-helper.h" -#include "util-validate.h" - -#include "runmodes.h" - -static GetActiveTxIdFunc AppLayerGetActiveTxIdFuncPtr = NULL; - -struct AppLayerParserThreadCtx_ { - void *alproto_local_storage[FLOW_PROTO_MAX][ALPROTO_MAX]; -}; - - -/** - * \brief App layer protocol parser context. - */ -typedef struct AppLayerParserProtoCtx_ -{ - /* 0 - to_server, 1 - to_client. */ - int (*Parser[2])(Flow *f, void *protocol_state, - AppLayerParserState *pstate, - uint8_t *input, uint32_t input_len, - void *local_storage); - char logger; - - void *(*StateAlloc)(void); - void (*StateFree)(void *); - void (*StateTransactionFree)(void *, uint64_t); - void *(*LocalStorageAlloc)(void); - void (*LocalStorageFree)(void *); - - void (*Truncate)(void *, uint8_t); - FileContainer *(*StateGetFiles)(void *, uint8_t); - AppLayerDecoderEvents *(*StateGetEvents)(void *, uint64_t); - int (*StateHasEvents)(void *); - - int (*StateGetProgress)(void *alstate, uint8_t direction); - uint64_t (*StateGetTxCnt)(void *alstate); - void *(*StateGetTx)(void *alstate, uint64_t tx_id); - int (*StateGetProgressCompletionStatus)(uint8_t direction); - int (*StateGetEventInfo)(const char *event_name, - int *event_id, AppLayerEventType *event_type); - - int (*StateHasTxDetectState)(void *alstate); - DetectEngineState *(*GetTxDetectState)(void *tx); - int (*SetTxDetectState)(void *alstate, void *tx, DetectEngineState *); - - /* Indicates the direction the parser is ready to see the data - * the first time for a flow. Values accepted - - * STREAM_TOSERVER, STREAM_TOCLIENT */ - uint8_t first_data_dir; - -#ifdef UNITTESTS - void (*RegisterUnittests)(void); -#endif -} AppLayerParserProtoCtx; - -typedef struct AppLayerParserCtx_ { - AppLayerParserProtoCtx ctxs[FLOW_PROTO_MAX][ALPROTO_MAX]; -} AppLayerParserCtx; - -struct AppLayerParserState_ { - uint8_t flags; - - /* State version, incremented for each update. Can wrap around. */ - uint8_t version; - /* Indicates the current transaction that is being inspected. - * We have a var per direction. */ - uint64_t inspect_id[2]; - /* Indicates the current transaction being logged. Unlike inspect_id, - * we don't need a var per direction since we don't log a transaction - * unless we have the entire transaction. */ - uint64_t log_id; - - /* Used to store decoder events. */ - AppLayerDecoderEvents *decoder_events; -}; - -/* Static global version of the parser context. - * Post 2.0 let's look at changing this to move it out to app-layer.c. */ -static AppLayerParserCtx alp_ctx; - -AppLayerParserState *AppLayerParserStateAlloc(void) -{ - SCEnter(); - - AppLayerParserState *pstate = (AppLayerParserState *)SCMalloc(sizeof(*pstate)); - if (pstate == NULL) - goto end; - memset(pstate, 0, sizeof(*pstate)); - - end: - SCReturnPtr(pstate, "AppLayerParserState"); -} - -void AppLayerParserStateFree(AppLayerParserState *pstate) -{ - SCEnter(); - - if (pstate->decoder_events != NULL) - AppLayerDecoderEventsFreeEvents(&pstate->decoder_events); - SCFree(pstate); - - SCReturn; -} - -int AppLayerParserSetup(void) -{ - SCEnter(); - - memset(&alp_ctx, 0, sizeof(alp_ctx)); - - /* set the default tx handler if none was set explicitly */ - if (AppLayerGetActiveTxIdFuncPtr == NULL) { - RegisterAppLayerGetActiveTxIdFunc(AppLayerTransactionGetActiveDetectLog); - } - - SCReturnInt(0); -} - -int AppLayerParserDeSetup(void) -{ - SCEnter(); - - SCReturnInt(0); -} - -AppLayerParserThreadCtx *AppLayerParserThreadCtxAlloc(void) -{ - SCEnter(); - - AppProto alproto = 0; - int flow_proto = 0; - AppLayerParserThreadCtx *tctx; - - tctx = SCMalloc(sizeof(*tctx)); - if (tctx == NULL) - goto end; - memset(tctx, 0, sizeof(*tctx)); - - for (flow_proto = 0; flow_proto < FLOW_PROTO_DEFAULT; flow_proto++) { - for (alproto = 0; alproto < ALPROTO_MAX; alproto++) { - uint8_t ipproto = FlowGetReverseProtoMapping(flow_proto); - - tctx->alproto_local_storage[flow_proto][alproto] = - AppLayerParserGetProtocolParserLocalStorage(ipproto, alproto); - } - } - - end: - SCReturnPtr(tctx, "void *"); -} - -void AppLayerParserThreadCtxFree(AppLayerParserThreadCtx *tctx) -{ - SCEnter(); - - AppProto alproto = 0; - int flow_proto = 0; - - for (flow_proto = 0; flow_proto < FLOW_PROTO_DEFAULT; flow_proto++) { - for (alproto = 0; alproto < ALPROTO_MAX; alproto++) { - uint8_t ipproto = FlowGetReverseProtoMapping(flow_proto); - - AppLayerParserDestroyProtocolParserLocalStorage(ipproto, alproto, - tctx->alproto_local_storage[flow_proto][alproto]); - } - } - - SCFree(tctx); - SCReturn; -} - -int AppLayerParserConfParserEnabled(const char *ipproto, - const char *alproto_name) -{ - SCEnter(); - - int enabled = 1; - char param[100]; - ConfNode *node; - int r; - - if (RunmodeIsUnittests()) - goto enabled; - - r = snprintf(param, sizeof(param), "%s%s%s", "app-layer.protocols.", - alproto_name, ".enabled"); - if (r < 0) { - SCLogError(SC_ERR_FATAL, "snprintf failure."); - exit(EXIT_FAILURE); - } else if (r > (int)sizeof(param)) { - SCLogError(SC_ERR_FATAL, "buffer not big enough to write param."); - exit(EXIT_FAILURE); - } - - node = ConfGetNode(param); - if (node == NULL) { - SCLogDebug("Entry for %s not found.", param); - r = snprintf(param, sizeof(param), "%s%s%s%s%s", "app-layer.protocols.", - alproto_name, ".", ipproto, ".enabled"); - if (r < 0) { - SCLogError(SC_ERR_FATAL, "snprintf failure."); - exit(EXIT_FAILURE); - } else if (r > (int)sizeof(param)) { - SCLogError(SC_ERR_FATAL, "buffer not big enough to write param."); - exit(EXIT_FAILURE); - } - - node = ConfGetNode(param); - if (node == NULL) { - SCLogDebug("Entry for %s not found.", param); - goto enabled; - } - } - - if (strcasecmp(node->val, "yes") == 0) { - goto enabled; - } else if (strcasecmp(node->val, "no") == 0) { - goto disabled; - } else if (strcasecmp(node->val, "detection-only") == 0) { - goto disabled; - } else { - SCLogError(SC_ERR_FATAL, "Invalid value found for %s.", param); - exit(EXIT_FAILURE); - } - - disabled: - enabled = 0; - enabled: - SCReturnInt(enabled); -} - -/***** Parser related registration *****/ - -int AppLayerParserRegisterParser(uint8_t ipproto, AppProto alproto, - uint8_t direction, - int (*Parser)(Flow *f, void *protocol_state, - AppLayerParserState *pstate, - uint8_t *buf, uint32_t buf_len, - void *local_storage)) -{ - SCEnter(); - - alp_ctx.ctxs[FlowGetProtoMapping(ipproto)][alproto]. - Parser[(direction & STREAM_TOSERVER) ? 0 : 1] = Parser; - - SCReturnInt(0); -} - -void AppLayerParserRegisterParserAcceptableDataDirection(uint8_t ipproto, AppProto alproto, - uint8_t direction) -{ - SCEnter(); - - alp_ctx.ctxs[FlowGetProtoMapping(ipproto)][alproto].first_data_dir |= - (direction & (STREAM_TOSERVER | STREAM_TOCLIENT)); - - SCReturn; -} - -void AppLayerParserRegisterStateFuncs(uint8_t ipproto, AppProto alproto, - void *(*StateAlloc)(void), - void (*StateFree)(void *)) -{ - SCEnter(); - - alp_ctx.ctxs[FlowGetProtoMapping(ipproto)][alproto].StateAlloc = - StateAlloc; - alp_ctx.ctxs[FlowGetProtoMapping(ipproto)][alproto].StateFree = - StateFree; - - SCReturn; -} - -void AppLayerParserRegisterLocalStorageFunc(uint8_t ipproto, AppProto alproto, - void *(*LocalStorageAlloc)(void), - void (*LocalStorageFree)(void *)) -{ - SCEnter(); - - alp_ctx.ctxs[FlowGetProtoMapping(ipproto)][alproto].LocalStorageAlloc = - LocalStorageAlloc; - alp_ctx.ctxs[FlowGetProtoMapping(ipproto)][alproto].LocalStorageFree = - LocalStorageFree; - - SCReturn; -} - -void AppLayerParserRegisterGetFilesFunc(uint8_t ipproto, AppProto alproto, - FileContainer *(*StateGetFiles)(void *, uint8_t)) -{ - SCEnter(); - - alp_ctx.ctxs[FlowGetProtoMapping(ipproto)][alproto].StateGetFiles = - StateGetFiles; - - SCReturn; -} - -void AppLayerParserRegisterGetEventsFunc(uint8_t ipproto, AppProto alproto, - AppLayerDecoderEvents *(*StateGetEvents)(void *, uint64_t)) -{ - SCEnter(); - - alp_ctx.ctxs[FlowGetProtoMapping(ipproto)][alproto].StateGetEvents = - StateGetEvents; - - SCReturn; -} - -void AppLayerParserRegisterHasEventsFunc(uint8_t ipproto, AppProto alproto, - int (*StateHasEvents)(void *)) -{ - SCEnter(); - - alp_ctx.ctxs[FlowGetProtoMapping(ipproto)][alproto].StateHasEvents = - StateHasEvents; - - SCReturn; -} - -void AppLayerParserRegisterLogger(uint8_t ipproto, AppProto alproto) -{ - SCEnter(); - - alp_ctx.ctxs[FlowGetProtoMapping(ipproto)][alproto].logger = TRUE; - - SCReturn; -} - -void AppLayerParserRegisterTruncateFunc(uint8_t ipproto, AppProto alproto, - void (*Truncate)(void *, uint8_t)) -{ - SCEnter(); - - alp_ctx.ctxs[FlowGetProtoMapping(ipproto)][alproto].Truncate = Truncate; - - SCReturn; -} - -void AppLayerParserRegisterGetStateProgressFunc(uint8_t ipproto, AppProto alproto, - int (*StateGetProgress)(void *alstate, uint8_t direction)) -{ - SCEnter(); - - alp_ctx.ctxs[FlowGetProtoMapping(ipproto)][alproto]. - StateGetProgress = StateGetProgress; - - SCReturn; -} - -void AppLayerParserRegisterTxFreeFunc(uint8_t ipproto, AppProto alproto, - void (*StateTransactionFree)(void *, uint64_t)) -{ - SCEnter(); - - alp_ctx.ctxs[FlowGetProtoMapping(ipproto)][alproto]. - StateTransactionFree = StateTransactionFree; - - SCReturn; -} - -void AppLayerParserRegisterGetTxCnt(uint8_t ipproto, AppProto alproto, - uint64_t (*StateGetTxCnt)(void *alstate)) -{ - SCEnter(); - - alp_ctx.ctxs[FlowGetProtoMapping(ipproto)][alproto]. - StateGetTxCnt = StateGetTxCnt; - - SCReturn; -} - -void AppLayerParserRegisterGetTx(uint8_t ipproto, AppProto alproto, - void *(StateGetTx)(void *alstate, uint64_t tx_id)) -{ - SCEnter(); - - alp_ctx.ctxs[FlowGetProtoMapping(ipproto)][alproto]. - StateGetTx = StateGetTx; - - SCReturn; -} - -void AppLayerParserRegisterGetStateProgressCompletionStatus(uint8_t ipproto, - AppProto alproto, - int (*StateGetProgressCompletionStatus)(uint8_t direction)) -{ - SCEnter(); - - alp_ctx.ctxs[FlowGetProtoMapping(ipproto)][alproto]. - StateGetProgressCompletionStatus = StateGetProgressCompletionStatus; - - SCReturn; -} - -void AppLayerParserRegisterGetEventInfo(uint8_t ipproto, AppProto alproto, - int (*StateGetEventInfo)(const char *event_name, int *event_id, - AppLayerEventType *event_type)) -{ - SCEnter(); - - alp_ctx.ctxs[FlowGetProtoMapping(ipproto)][alproto]. - StateGetEventInfo = StateGetEventInfo; - - SCReturn; -} - -void AppLayerParserRegisterDetectStateFuncs(uint8_t ipproto, AppProto alproto, - int (*StateHasTxDetectState)(void *alstate), - DetectEngineState *(*GetTxDetectState)(void *tx), - int (*SetTxDetectState)(void *alstate, void *tx, DetectEngineState *)) -{ - SCEnter(); - - alp_ctx.ctxs[FlowGetProtoMapping(ipproto)][alproto].StateHasTxDetectState = StateHasTxDetectState; - alp_ctx.ctxs[FlowGetProtoMapping(ipproto)][alproto].GetTxDetectState = GetTxDetectState; - alp_ctx.ctxs[FlowGetProtoMapping(ipproto)][alproto].SetTxDetectState = SetTxDetectState; - - SCReturn; -} - -/***** Get and transaction functions *****/ - -void *AppLayerParserGetProtocolParserLocalStorage(uint8_t ipproto, AppProto alproto) -{ - SCEnter(); - void * r = NULL; - - if (alp_ctx.ctxs[FlowGetProtoMapping(ipproto)][alproto]. - LocalStorageAlloc != NULL) - { - r = alp_ctx.ctxs[FlowGetProtoMapping(ipproto)][alproto]. - LocalStorageAlloc(); - } - - SCReturnPtr(r, "void *"); -} - -void AppLayerParserDestroyProtocolParserLocalStorage(uint8_t ipproto, AppProto alproto, - void *local_data) -{ - SCEnter(); - - if (alp_ctx.ctxs[FlowGetProtoMapping(ipproto)][alproto]. - LocalStorageFree != NULL) - { - alp_ctx.ctxs[FlowGetProtoMapping(ipproto)][alproto]. - LocalStorageFree(local_data); - } - - SCReturn; -} - -uint64_t AppLayerParserGetTransactionLogId(AppLayerParserState *pstate) -{ - SCEnter(); - - SCReturnCT((pstate == NULL) ? 0 : pstate->log_id, "uint64_t"); -} - -void AppLayerParserSetTransactionLogId(AppLayerParserState *pstate) -{ - SCEnter(); - - if (pstate != NULL) - pstate->log_id++; - - SCReturn; -} - -uint64_t AppLayerParserGetTransactionInspectId(AppLayerParserState *pstate, uint8_t direction) -{ - SCEnter(); - - if (pstate == NULL) - SCReturnCT(0ULL, "uint64_t"); - - SCReturnCT(pstate->inspect_id[direction & STREAM_TOSERVER ? 0 : 1], "uint64_t"); -} - -void AppLayerParserSetTransactionInspectId(AppLayerParserState *pstate, - const uint8_t ipproto, const AppProto alproto, - void *alstate, const uint8_t flags) -{ - SCEnter(); - - int direction = (flags & STREAM_TOSERVER) ? 0 : 1; - uint64_t total_txs = AppLayerParserGetTxCnt(ipproto, alproto, alstate); - uint64_t idx = AppLayerParserGetTransactionInspectId(pstate, flags); - int state_done_progress = AppLayerParserGetStateProgressCompletionStatus(ipproto, alproto, flags); - void *tx; - int state_progress; - - for (; idx < total_txs; idx++) { - tx = AppLayerParserGetTx(ipproto, alproto, alstate, idx); - if (tx == NULL) - continue; - state_progress = AppLayerParserGetStateProgress(ipproto, alproto, tx, flags); - if (state_progress >= state_done_progress) - continue; - else - break; - } - pstate->inspect_id[direction] = idx; - - SCReturn; -} - -AppLayerDecoderEvents *AppLayerParserGetDecoderEvents(AppLayerParserState *pstate) -{ - SCEnter(); - - SCReturnPtr(pstate->decoder_events, - "AppLayerDecoderEvents *"); -} - -void AppLayerParserSetDecoderEvents(AppLayerParserState *pstate, AppLayerDecoderEvents *devents) -{ - pstate->decoder_events = devents; -} - -AppLayerDecoderEvents *AppLayerParserGetEventsByTx(uint8_t ipproto, AppProto alproto, - void *alstate, uint64_t tx_id) -{ - SCEnter(); - - AppLayerDecoderEvents *ptr = NULL; - - if (alp_ctx.ctxs[FlowGetProtoMapping(ipproto)][alproto]. - StateGetEvents != NULL) - { - ptr = alp_ctx.ctxs[FlowGetProtoMapping(ipproto)][alproto]. - StateGetEvents(alstate, tx_id); - } - - SCReturnPtr(ptr, "AppLayerDecoderEvents *"); -} - -uint16_t AppLayerParserGetStateVersion(AppLayerParserState *pstate) -{ - SCEnter(); - SCReturnCT((pstate == NULL) ? 0 : pstate->version, "uint8_t"); -} - -FileContainer *AppLayerParserGetFiles(uint8_t ipproto, AppProto alproto, - void *alstate, uint8_t direction) -{ - SCEnter(); - - FileContainer *ptr = NULL; - - if (alp_ctx.ctxs[FlowGetProtoMapping(ipproto)][alproto]. - StateGetFiles != NULL) - { - ptr = alp_ctx.ctxs[FlowGetProtoMapping(ipproto)][alproto]. - StateGetFiles(alstate, direction); - } - - SCReturnPtr(ptr, "FileContainer *"); -} - -/** \brief active TX retrieval for normal ops: so with detection and logging - * - * \retval tx_id lowest tx_id that still needs work */ -uint64_t AppLayerTransactionGetActiveDetectLog(Flow *f, uint8_t flags) -{ - AppLayerParserProtoCtx *p = &alp_ctx.ctxs[FlowGetProtoMapping(f->proto)][f->alproto]; - uint64_t log_id = f->alparser->log_id; - uint64_t inspect_id = f->alparser->inspect_id[flags & STREAM_TOSERVER ? 0 : 1]; - if (p->logger == TRUE) { - return (log_id < inspect_id) ? log_id : inspect_id; - } else { - return inspect_id; - } -} - -/** \brief active TX retrieval for logging only: so NO detection - * - * If the logger is enabled, we simply return the log_id here. - * - * Otherwise, we go look for the tx id. There probably is no point - * in running this function in that case though. With no detection - * and no logging, why run a parser in the first place? - **/ -uint64_t AppLayerTransactionGetActiveLogOnly(Flow *f, uint8_t flags) -{ - AppLayerParserProtoCtx *p = &alp_ctx.ctxs[f->protomap][f->alproto]; - - if (p->logger == TRUE) { - uint64_t log_id = f->alparser->log_id; - SCLogDebug("returning %"PRIu64, log_id); - return log_id; - } - - /* logger is disabled, return highest 'complete' tx id */ - uint64_t total_txs = AppLayerParserGetTxCnt(f->proto, f->alproto, f->alstate); - uint64_t idx = AppLayerParserGetTransactionInspectId(f->alparser, flags); - int state_done_progress = AppLayerParserGetStateProgressCompletionStatus(f->proto, f->alproto, flags); - void *tx; - int state_progress; - - for (; idx < total_txs; idx++) { - tx = AppLayerParserGetTx(f->proto, f->alproto, f->alstate, idx); - if (tx == NULL) - continue; - state_progress = AppLayerParserGetStateProgress(f->proto, f->alproto, tx, flags); - if (state_progress >= state_done_progress) - continue; - else - break; - } - SCLogDebug("returning %"PRIu64, idx); - return idx; -} - -void RegisterAppLayerGetActiveTxIdFunc(GetActiveTxIdFunc FuncPtr) -{ - //BUG_ON(AppLayerGetActiveTxIdFuncPtr != NULL); - AppLayerGetActiveTxIdFuncPtr = FuncPtr; - SCLogDebug("AppLayerGetActiveTxIdFuncPtr is now %p", AppLayerGetActiveTxIdFuncPtr); -} - -/** - * \brief Get 'active' tx id, meaning the lowest id that still need work. - * - * \retval id tx id - */ -static uint64_t AppLayerTransactionGetActive(Flow *f, uint8_t flags) -{ - BUG_ON(AppLayerGetActiveTxIdFuncPtr == NULL); - - return AppLayerGetActiveTxIdFuncPtr(f, flags); -} - -#ifndef MIN -#define MIN(a, b) (((a) < (b)) ? (a) : (b)) -#endif - -/** - * \brief remove obsolete (inspected and logged) transactions - */ -static void AppLayerParserTransactionsCleanup(Flow *f) -{ - DEBUG_ASSERT_FLOW_LOCKED(f); - - AppLayerParserProtoCtx *p = &alp_ctx.ctxs[FlowGetProtoMapping(f->proto)][f->alproto]; - if (p->StateTransactionFree == NULL) - return; - - uint64_t tx_id_ts = AppLayerTransactionGetActive(f, STREAM_TOSERVER); - uint64_t tx_id_tc = AppLayerTransactionGetActive(f, STREAM_TOCLIENT); - - uint64_t min = MIN(tx_id_ts, tx_id_tc); - if (min > 0) { - SCLogDebug("freeing %"PRIu64" %p", min - 1, p->StateTransactionFree); - p->StateTransactionFree(f->alstate, min - 1); - } -} - -#define IS_DISRUPTED(flags) \ - ((flags) & (STREAM_DEPTH|STREAM_GAP)) - -/** - * \brief get the progress value for a tx/protocol - * - * If the stream is disrupted, we return the 'completion' value. - */ -int AppLayerParserGetStateProgress(uint8_t ipproto, AppProto alproto, - void *alstate, uint8_t flags) -{ - SCEnter(); - int r = 0; - if (unlikely(IS_DISRUPTED(flags))) { - r = alp_ctx.ctxs[FlowGetProtoMapping(ipproto)][alproto]. - StateGetProgressCompletionStatus(flags); - } else { - r = alp_ctx.ctxs[FlowGetProtoMapping(ipproto)][alproto]. - StateGetProgress(alstate, flags); - } - SCReturnInt(r); -} - -uint64_t AppLayerParserGetTxCnt(uint8_t ipproto, AppProto alproto, void *alstate) -{ - SCEnter(); - uint64_t r = 0; - r = alp_ctx.ctxs[FlowGetProtoMapping(ipproto)][alproto]. - StateGetTxCnt(alstate); - SCReturnCT(r, "uint64_t"); -} - -void *AppLayerParserGetTx(uint8_t ipproto, AppProto alproto, void *alstate, uint64_t tx_id) -{ - SCEnter(); - void * r = NULL; - r = alp_ctx.ctxs[FlowGetProtoMapping(ipproto)][alproto]. - StateGetTx(alstate, tx_id); - SCReturnPtr(r, "void *"); -} - -int AppLayerParserGetStateProgressCompletionStatus(uint8_t ipproto, AppProto alproto, - uint8_t direction) -{ - SCEnter(); - int r = 0; - r = alp_ctx.ctxs[FlowGetProtoMapping(ipproto)][alproto]. - StateGetProgressCompletionStatus(direction); - SCReturnInt(r); -} - -int AppLayerParserGetEventInfo(uint8_t ipproto, AppProto alproto, const char *event_name, - int *event_id, AppLayerEventType *event_type) -{ - SCEnter(); - int ipproto_map = FlowGetProtoMapping(ipproto); - int r = (alp_ctx.ctxs[ipproto_map][alproto].StateGetEventInfo == NULL) ? - -1 : alp_ctx.ctxs[ipproto_map][alproto].StateGetEventInfo(event_name, event_id, event_type); - SCReturnInt(r); -} - -uint8_t AppLayerParserGetFirstDataDir(uint8_t ipproto, AppProto alproto) -{ - SCEnter(); - uint8_t r = 0; - r = alp_ctx.ctxs[FlowGetProtoMapping(ipproto)][alproto]. - first_data_dir; - SCReturnCT(r, "uint8_t"); -} - -uint64_t AppLayerParserGetTransactionActive(uint8_t ipproto, AppProto alproto, - AppLayerParserState *pstate, uint8_t direction) -{ - SCEnter(); - - uint64_t active_id; - - uint64_t log_id = pstate->log_id; - uint64_t inspect_id = pstate->inspect_id[direction & STREAM_TOSERVER ? 0 : 1]; - if (alp_ctx.ctxs[FlowGetProtoMapping(ipproto)][alproto].logger == TRUE) { - active_id = (log_id < inspect_id) ? log_id : inspect_id; - } else { - active_id = inspect_id; - } - - SCReturnCT(active_id, "uint64_t"); -} - -int AppLayerParserSupportsTxDetectState(uint8_t ipproto, AppProto alproto) -{ - if (alp_ctx.ctxs[FlowGetProtoMapping(ipproto)][alproto].GetTxDetectState != NULL) - return TRUE; - return FALSE; -} - -int AppLayerParserHasTxDetectState(uint8_t ipproto, AppProto alproto, void *alstate) -{ - int r; - SCEnter(); - if (alp_ctx.ctxs[FlowGetProtoMapping(ipproto)][alproto].StateHasTxDetectState == NULL) - return -ENOSYS; - r = alp_ctx.ctxs[FlowGetProtoMapping(ipproto)][alproto].StateHasTxDetectState(alstate); - SCReturnInt(r); -} - -DetectEngineState *AppLayerParserGetTxDetectState(uint8_t ipproto, AppProto alproto, void *tx) -{ - SCEnter(); - DetectEngineState *s; - s = alp_ctx.ctxs[FlowGetProtoMapping(ipproto)][alproto].GetTxDetectState(tx); - SCReturnPtr(s, "DetectEngineState"); -} - -int AppLayerParserSetTxDetectState(uint8_t ipproto, AppProto alproto, - void *alstate, void *tx, DetectEngineState *s) -{ - int r; - SCEnter(); - if ((alp_ctx.ctxs[FlowGetProtoMapping(ipproto)][alproto].GetTxDetectState(tx) != NULL)) - SCReturnInt(-EBUSY); - r = alp_ctx.ctxs[FlowGetProtoMapping(ipproto)][alproto].SetTxDetectState(alstate, tx, s); - SCReturnInt(r); -} - -/***** General *****/ - -int AppLayerParserParse(AppLayerParserThreadCtx *alp_tctx, Flow *f, AppProto alproto, - uint8_t flags, uint8_t *input, uint32_t input_len) -{ - SCEnter(); -#ifdef DEBUG_VALIDATION - BUG_ON(f->protomap != FlowGetProtoMapping(f->proto)); -#endif - AppLayerParserState *pstate = NULL; - AppLayerParserProtoCtx *p = &alp_ctx.ctxs[f->protomap][alproto]; - void *alstate = NULL; - - /* we don't have the parser registered for this protocol */ - if (p->StateAlloc == NULL) - goto end; - - /* Do this check before calling AppLayerParse */ - if (flags & STREAM_GAP) { - SCLogDebug("stream gap detected (missing packets), " - "this is not yet supported."); - - if (f->alstate != NULL) - AppLayerParserStreamTruncated(f->proto, alproto, f->alstate, flags); - goto error; - } - - /* Get the parser state (if any) */ - pstate = f->alparser; - if (pstate == NULL) { - f->alparser = pstate = AppLayerParserStateAlloc(); - if (pstate == NULL) - goto error; - } - pstate->version++; - SCLogDebug("app layer parser state version incremented to %"PRIu8, - pstate->version); - - if (flags & STREAM_EOF) - AppLayerParserStateSetFlag(pstate, APP_LAYER_PARSER_EOF); - - alstate = f->alstate; - if (alstate == NULL) { - f->alstate = alstate = p->StateAlloc(); - if (alstate == NULL) - goto error; - SCLogDebug("alloced new app layer state %p (name %s)", - alstate, AppLayerGetProtoName(f->alproto)); - } else { - SCLogDebug("using existing app layer state %p (name %s))", - alstate, AppLayerGetProtoName(f->alproto)); - } - - /* invoke the recursive parser, but only on data. We may get empty msgs on EOF */ - if (input_len > 0 || (flags & STREAM_EOF)) { - /* invoke the parser */ - if (p->Parser[(flags & STREAM_TOSERVER) ? 0 : 1](f, alstate, pstate, - input, input_len, - alp_tctx->alproto_local_storage[f->protomap][alproto]) < 0) - { - goto error; - } - } - - /* set the packets to no inspection and reassembly if required */ - if (pstate->flags & APP_LAYER_PARSER_NO_INSPECTION) { - AppLayerParserSetEOF(pstate); - FlowSetNoPayloadInspectionFlag(f); - - if (f->proto == IPPROTO_TCP) { - StreamTcpDisableAppLayer(f); - - /* Set the no reassembly flag for both the stream in this TcpSession */ - if (pstate->flags & APP_LAYER_PARSER_NO_REASSEMBLY) { - /* Used only if it's TCP */ - TcpSession *ssn = f->protoctx; - if (ssn != NULL) { - StreamTcpSetSessionNoReassemblyFlag(ssn, - flags & STREAM_TOCLIENT ? 1 : 0); - StreamTcpSetSessionNoReassemblyFlag(ssn, - flags & STREAM_TOSERVER ? 1 : 0); - } - } - } - } - - /* In cases like HeartBleed for TLS we need to inspect AppLayer but not Payload */ - if (!(f->flags & FLOW_NOPAYLOAD_INSPECTION) && pstate->flags & APP_LAYER_PARSER_NO_INSPECTION_PAYLOAD) { - FlowSetNoPayloadInspectionFlag(f); - /* Set the no reassembly flag for both the stream in this TcpSession */ - if (f->proto == IPPROTO_TCP) { - /* Used only if it's TCP */ - TcpSession *ssn = f->protoctx; - if (ssn != NULL) { - StreamTcpSetDisableRawReassemblyFlag(ssn, 0); - StreamTcpSetDisableRawReassemblyFlag(ssn, 1); - } - } - } - - /* next, see if we can get rid of transactions now */ - AppLayerParserTransactionsCleanup(f); - - /* stream truncated, inform app layer */ - if (flags & STREAM_DEPTH) - AppLayerParserStreamTruncated(f->proto, alproto, alstate, flags); - - end: - SCReturnInt(0); - error: - /* Set the no app layer inspection flag for both - * the stream in this Flow */ - if (f->proto == IPPROTO_TCP) { - StreamTcpDisableAppLayer(f); - } - AppLayerParserSetEOF(pstate); - SCReturnInt(-1); -} - -void AppLayerParserSetEOF(AppLayerParserState *pstate) -{ - SCEnter(); - - if (pstate == NULL) - goto end; - - AppLayerParserStateSetFlag(pstate, APP_LAYER_PARSER_EOF); - /* increase version so we will inspect it one more time - * with the EOF flags now set */ - pstate->version++; - - end: - SCReturn; -} - -int AppLayerParserHasDecoderEvents(uint8_t ipproto, AppProto alproto, - void *alstate, AppLayerParserState *pstate, - uint8_t flags) -{ - SCEnter(); - - if (alstate == NULL || pstate == NULL) - goto not_present; - - AppLayerDecoderEvents *decoder_events; - uint64_t tx_id; - uint64_t max_id; - - if (AppLayerParserProtocolIsTxEventAware(ipproto, alproto)) { - /* fast path if supported by alproto */ - if (alp_ctx.ctxs[FlowGetProtoMapping(ipproto)][alproto].StateHasEvents != NULL) { - if (alp_ctx.ctxs[FlowGetProtoMapping(ipproto)][alproto]. - StateHasEvents(alstate) == 1) - { - goto present; - } - } else { - /* check each tx */ - tx_id = AppLayerParserGetTransactionInspectId(pstate, flags); - max_id = AppLayerParserGetTxCnt(ipproto, alproto, alstate); - for ( ; tx_id < max_id; tx_id++) { - decoder_events = AppLayerParserGetEventsByTx(ipproto, alproto, alstate, tx_id); - if (decoder_events && decoder_events->cnt) - goto present; - } - } - } - - decoder_events = AppLayerParserGetDecoderEvents(pstate); - if (decoder_events && decoder_events->cnt) - goto present; - - /* if we have reached here, we don't have events */ - not_present: - SCReturnInt(0); - present: - SCReturnInt(1); -} - -int AppLayerParserProtocolIsTxAware(uint8_t ipproto, AppProto alproto) -{ - SCEnter(); - int ipproto_map = FlowGetProtoMapping(ipproto); - int r = (alp_ctx.ctxs[ipproto_map][alproto].StateGetTx == NULL) ? 0 : 1; - SCReturnInt(r); -} - -int AppLayerParserProtocolIsTxEventAware(uint8_t ipproto, AppProto alproto) -{ - SCEnter(); - int ipproto_map = FlowGetProtoMapping(ipproto); - int r = (alp_ctx.ctxs[ipproto_map][alproto].StateGetEvents == NULL) ? 0 : 1; - SCReturnInt(r); -} - -int AppLayerParserProtocolSupportsTxs(uint8_t ipproto, AppProto alproto) -{ - SCEnter(); - int ipproto_map = FlowGetProtoMapping(ipproto); - int r = (alp_ctx.ctxs[ipproto_map][alproto].StateTransactionFree == NULL) ? 0 : 1; - SCReturnInt(r); -} - -int AppLayerParserProtocolHasLogger(uint8_t ipproto, AppProto alproto) -{ - SCEnter(); - int ipproto_map = FlowGetProtoMapping(ipproto); - int r = (alp_ctx.ctxs[ipproto_map][alproto].logger == 0) ? 0 : 1; - SCReturnInt(r); -} - -void AppLayerParserTriggerRawStreamReassembly(Flow *f) -{ - SCEnter(); - - if (f != NULL && f->protoctx != NULL) - StreamTcpReassembleTriggerRawReassembly(f->protoctx); - - SCReturn; -} - -/***** Cleanup *****/ - -void AppLayerParserStateCleanup(uint8_t ipproto, AppProto alproto, void *alstate, - AppLayerParserState *pstate) -{ - SCEnter(); - - AppLayerParserProtoCtx *ctx = &alp_ctx.ctxs[FlowGetProtoMapping(ipproto)][alproto]; - - if (ctx->StateFree != NULL && alstate != NULL) - ctx->StateFree(alstate); - - /* free the app layer parser api state */ - if (pstate != NULL) - AppLayerParserStateFree(pstate); - - SCReturn; -} - - -void AppLayerParserRegisterProtocolParsers(void) -{ - SCEnter(); - - RegisterHTPParsers(); - RegisterSSLParsers(); - RegisterSMBParsers(); - /** \todo bug 719 */ - //RegisterSMB2Parsers(); - RegisterDCERPCParsers(); - RegisterDCERPCUDPParsers(); - RegisterFTPParsers(); - RegisterSSHParsers(); - RegisterSMTPParsers(); - RegisterDNSUDPParsers(); - RegisterDNSTCPParsers(); - RegisterModbusParsers(); - RegisterTemplateParsers(); - - /** IMAP */ - AppLayerProtoDetectRegisterProtocol(ALPROTO_IMAP, "imap"); - if (AppLayerProtoDetectConfProtoDetectionEnabled("tcp", "imap")) { - if (AppLayerProtoDetectPMRegisterPatternCS(IPPROTO_TCP, ALPROTO_IMAP, - "1|20|capability", 12, 0, STREAM_TOSERVER) < 0) - { - SCLogInfo("imap proto registration failure\n"); - exit(EXIT_FAILURE); - } - } else { - SCLogInfo("Protocol detection and parser disabled for %s protocol.", - "imap"); - } - - /** MSN Messenger */ - AppLayerProtoDetectRegisterProtocol(ALPROTO_MSN, "msn"); - if (AppLayerProtoDetectConfProtoDetectionEnabled("tcp", "msn")) { - if (AppLayerProtoDetectPMRegisterPatternCS(IPPROTO_TCP, ALPROTO_MSN, - "msn", 10, 6, STREAM_TOSERVER) < 0) - { - SCLogInfo("msn proto registration failure\n"); - exit(EXIT_FAILURE); - } - } else { - SCLogInfo("Protocol detection and parser disabled for %s protocol.", - "msn"); - } - - return; -} - - -void AppLayerParserStateSetFlag(AppLayerParserState *pstate, uint8_t flag) -{ - SCEnter(); - pstate->flags |= flag; - SCReturn; -} - -int AppLayerParserStateIssetFlag(AppLayerParserState *pstate, uint8_t flag) -{ - SCEnter(); - SCReturnInt(pstate->flags & flag); -} - - -void AppLayerParserStreamTruncated(uint8_t ipproto, AppProto alproto, void *alstate, - uint8_t direction) -{ - SCEnter(); - - - if (alp_ctx.ctxs[FlowGetProtoMapping(ipproto)][alproto].Truncate != NULL) - alp_ctx.ctxs[FlowGetProtoMapping(ipproto)][alproto].Truncate(alstate, direction); - - SCReturn; -} - -#ifdef DEBUG -void AppLayerParserStatePrintDetails(AppLayerParserState *pstate) -{ - SCEnter(); - - if (pstate == NULL) - SCReturn; - - AppLayerParserState *p = pstate; - SCLogDebug("AppLayerParser parser state information for parser state p(%p). " - "p->inspect_id[0](%"PRIu64"), " - "p->inspect_id[1](%"PRIu64"), " - "p->log_id(%"PRIu64"), " - "p->version(%"PRIu8"), " - "p->decoder_events(%p).", - pstate, p->inspect_id[0], p->inspect_id[1], p->log_id, - p->version, p->decoder_events); - - SCReturn; -} -#endif - - -/***** Unittests *****/ - -#ifdef UNITTESTS - -static AppLayerParserCtx alp_ctx_backup_unittest; - -typedef struct TestState_ { - uint8_t test; -} TestState; - -/** - * \brief Test parser function to test the memory deallocation of app layer - * parser of occurence of an error. - */ -static int TestProtocolParser(Flow *f, void *test_state, AppLayerParserState *pstate, - uint8_t *input, uint32_t input_len, - void *local_data) -{ - SCEnter(); - SCReturnInt(-1); -} - -/** \brief Function to allocates the Test protocol state memory - */ -static void *TestProtocolStateAlloc(void) -{ - SCEnter(); - void *s = SCMalloc(sizeof(TestState)); - if (unlikely(s == NULL)) - goto end; - memset(s, 0, sizeof(TestState)); - end: - SCReturnPtr(s, "TestState"); -} - -/** \brief Function to free the Test Protocol state memory - */ -static void TestProtocolStateFree(void *s) -{ - SCFree(s); -} - -void AppLayerParserRegisterProtocolUnittests(uint8_t ipproto, AppProto alproto, - void (*RegisterUnittests)(void)) -{ - SCEnter(); - alp_ctx.ctxs[FlowGetProtoMapping(ipproto)][alproto]. - RegisterUnittests = RegisterUnittests; - SCReturn; -} - -void AppLayerParserBackupParserTable(void) -{ - SCEnter(); - alp_ctx_backup_unittest = alp_ctx; - memset(&alp_ctx, 0, sizeof(alp_ctx)); - SCReturn; -} - -void AppLayerParserRestoreParserTable(void) -{ - SCEnter(); - alp_ctx = alp_ctx_backup_unittest; - memset(&alp_ctx_backup_unittest, 0, sizeof(alp_ctx_backup_unittest)); - SCReturn; -} - -/** - * \test Test the deallocation of app layer parser memory on occurance of - * error in the parsing process. - */ -static int AppLayerParserTest01(void) -{ - AppLayerParserBackupParserTable(); - - int result = 0; - Flow *f = NULL; - uint8_t testbuf[] = { 0x11 }; - uint32_t testlen = sizeof(testbuf); - TcpSession ssn; - AppLayerParserThreadCtx *alp_tctx = AppLayerParserThreadCtxAlloc(); - - memset(&ssn, 0, sizeof(ssn)); - - /* Register the Test protocol state and parser functions */ - AppLayerParserRegisterParser(IPPROTO_TCP, ALPROTO_TEST, STREAM_TOSERVER, - TestProtocolParser); - AppLayerParserRegisterStateFuncs(IPPROTO_TCP, ALPROTO_TEST, - TestProtocolStateAlloc, TestProtocolStateFree); - - f = UTHBuildFlow(AF_INET, "1.2.3.4", "4.3.2.1", 20, 40); - if (f == NULL) - goto end; - f->protoctx = &ssn; - f->alproto = ALPROTO_TEST; - f->proto = IPPROTO_TCP; - - StreamTcpInitConfig(TRUE); - - SCMutexLock(&f->m); - int r = AppLayerParserParse(alp_tctx, f, ALPROTO_TEST, STREAM_TOSERVER|STREAM_EOF, - testbuf, testlen); - if (r != -1) { - printf("returned %" PRId32 ", expected -1: ", r); - SCMutexUnlock(&f->m); - goto end; - } - SCMutexUnlock(&f->m); - - if (!(ssn.flags & STREAMTCP_FLAG_APP_LAYER_DISABLED)) { - printf("flag should have been set, but is not: "); - goto end; - } - - result = 1; - end: - AppLayerParserRestoreParserTable(); - StreamTcpFreeConfig(TRUE); - - UTHFreeFlow(f); - return result; -} - -/** - * \test Test the deallocation of app layer parser memory on occurance of - * error in the parsing process for UDP. - */ -static int AppLayerParserTest02(void) -{ - AppLayerParserBackupParserTable(); - - int result = 1; - Flow *f = NULL; - uint8_t testbuf[] = { 0x11 }; - uint32_t testlen = sizeof(testbuf); - AppLayerParserThreadCtx *alp_tctx = AppLayerParserThreadCtxAlloc(); - - /* Register the Test protocol state and parser functions */ - AppLayerParserRegisterParser(IPPROTO_UDP, ALPROTO_TEST, STREAM_TOSERVER, - TestProtocolParser); - AppLayerParserRegisterStateFuncs(IPPROTO_UDP, ALPROTO_TEST, - TestProtocolStateAlloc, TestProtocolStateFree); - - f = UTHBuildFlow(AF_INET, "1.2.3.4", "4.3.2.1", 20, 40); - if (f == NULL) - goto end; - f->alproto = ALPROTO_TEST; - f->proto = IPPROTO_UDP; - f->protomap = FlowGetProtoMapping(f->proto); - - StreamTcpInitConfig(TRUE); - - SCMutexLock(&f->m); - int r = AppLayerParserParse(alp_tctx, f, ALPROTO_TEST, STREAM_TOSERVER|STREAM_EOF, testbuf, - testlen); - if (r != -1) { - printf("returned %" PRId32 ", expected -1: \n", r); - result = 0; - SCMutexUnlock(&f->m); - goto end; - } - SCMutexUnlock(&f->m); - - end: - AppLayerParserRestoreParserTable(); - StreamTcpFreeConfig(TRUE); - UTHFreeFlow(f); - return result; -} - - -void AppLayerParserRegisterUnittests(void) -{ - SCEnter(); - - int ip; - AppProto alproto; - AppLayerParserProtoCtx *ctx; - - for (ip = 0; ip < FLOW_PROTO_DEFAULT; ip++) { - for (alproto = 0; alproto < ALPROTO_MAX; alproto++) { - ctx = &alp_ctx.ctxs[ip][alproto]; - if (ctx->RegisterUnittests == NULL) - continue; - ctx->RegisterUnittests(); - } - } - - UtRegisterTest("AppLayerParserTest01", AppLayerParserTest01, 1); - UtRegisterTest("AppLayerParserTest02", AppLayerParserTest02, 1); - - SCReturn; -} - -#endif |