aboutsummaryrefslogtreecommitdiffstats
path: root/framework/src/suricata/src/app-layer-parser.c
diff options
context:
space:
mode:
Diffstat (limited to 'framework/src/suricata/src/app-layer-parser.c')
-rw-r--r--framework/src/suricata/src/app-layer-parser.c1387
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