|
|
|
/* Copyright (C) 2007-2010 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>
|
|
|
|
*/
|
|
|
|
|
|
|
|
#ifndef __APP_LAYER_PARSER_H__
|
|
|
|
#define __APP_LAYER_PARSER_H__
|
|
|
|
|
|
|
|
#include "decode-events.h"
|
|
|
|
|
|
|
|
#include "util-file.h"
|
|
|
|
|
|
|
|
/** Mapping between local parser id's (e.g. HTTP_FIELD_REQUEST_URI) and
|
|
|
|
* the dynamically assigned (at registration) global parser id. */
|
|
|
|
typedef struct AppLayerLocalMap_ {
|
|
|
|
uint16_t parser_id;
|
|
|
|
} AppLayerLocalMap;
|
|
|
|
|
|
|
|
/** \brief Mapping between ALPROTO_* and L7Parsers
|
|
|
|
*
|
|
|
|
* Map the proto to the parsers for the to_client and to_server directions.
|
|
|
|
*/
|
|
|
|
typedef struct AppLayerProto_ {
|
|
|
|
char *name; /**< name of the registered proto */
|
|
|
|
|
|
|
|
uint16_t to_server;
|
|
|
|
uint16_t to_client;
|
|
|
|
uint16_t map_size;
|
|
|
|
char logger; /**< does this proto have a logger enabled? */
|
|
|
|
|
|
|
|
AppLayerLocalMap **map;
|
|
|
|
|
|
|
|
void *(*StateAlloc)(void);
|
|
|
|
void (*StateFree)(void *);
|
|
|
|
void (*StateUpdateTransactionId)(void *, uint16_t *);
|
|
|
|
void (*StateTransactionFree)(void *, uint16_t);
|
|
|
|
void *(*LocalStorageAlloc)(void);
|
|
|
|
void (*LocalStorageFree)(void *);
|
|
|
|
|
|
|
|
/** truncate state after a gap/depth event */
|
|
|
|
void (*Truncate)(void *, uint8_t);
|
|
|
|
FileContainer *(*StateGetFiles)(void *, uint8_t);
|
|
|
|
|
|
|
|
int (*StateGetAlstateProgress)(void *alstate, uint8_t direction);
|
|
|
|
uint64_t (*StateGetTxCnt)(void *alstate);
|
|
|
|
void *(*StateGetTx)(void *alstate, uint64_t tx_id);
|
|
|
|
int (*StateGetAlstateProgressCompletionStatus)(uint8_t direction);
|
|
|
|
} AppLayerProto;
|
|
|
|
|
|
|
|
/** flags for the result elmts */
|
|
|
|
#define ALP_RESULT_ELMT_ALLOC 0x01
|
|
|
|
|
|
|
|
/** \brief Result elements for the parser */
|
|
|
|
typedef struct AppLayerParserResultElmt_ {
|
|
|
|
uint16_t flags; /* flags. E.g. local alloc */
|
|
|
|
uint16_t name_idx; /* idx for names like "http.request_line.uri" */
|
|
|
|
|
|
|
|
uint32_t data_len; /* length of the data from the ptr */
|
|
|
|
uint8_t *data_ptr; /* point to the position in the "input" data
|
|
|
|
* or ptr to new mem if local alloc flag set */
|
|
|
|
struct AppLayerParserResultElmt_ *next;
|
|
|
|
} AppLayerParserResultElmt;
|
|
|
|
|
|
|
|
/** \brief List head for parser result elmts */
|
|
|
|
typedef struct AppLayerParserResult_ {
|
|
|
|
AppLayerParserResultElmt *head;
|
|
|
|
AppLayerParserResultElmt *tail;
|
|
|
|
uint32_t cnt;
|
|
|
|
} AppLayerParserResult;
|
|
|
|
|
|
|
|
#define APP_LAYER_PARSER_USE 0x01
|
|
|
|
#define APP_LAYER_PARSER_EOF 0x02
|
|
|
|
#define APP_LAYER_PARSER_DONE 0x04 /**< parser is done, ignore more
|
|
|
|
msgs */
|
|
|
|
#define APP_LAYER_PARSER_NO_INSPECTION 0x08 /**< Flag to indicate no more
|
|
|
|
packets payload inspection */
|
|
|
|
#define APP_LAYER_PARSER_NO_REASSEMBLY 0x10 /**< Flag to indicate no more
|
|
|
|
packets reassembly for this
|
|
|
|
session */
|
|
|
|
|
|
|
|
#define APP_LAYER_TRANSACTION_EOF 0x01 /**< Session done, last transaction
|
|
|
|
as well */
|
|
|
|
#define APP_LAYER_TRANSACTION_TOSERVER 0x02 /**< transaction has been inspected
|
|
|
|
in to server direction. */
|
|
|
|
#define APP_LAYER_TRANSACTION_TOCLIENT 0x04 /**< transaction has been inspected
|
|
|
|
in to server direction. */
|
|
|
|
|
|
|
|
typedef struct AppLayerParserState_ {
|
|
|
|
uint8_t flags;
|
|
|
|
uint16_t cur_parser; /**< idx of currently active parser */
|
|
|
|
uint8_t *store;
|
|
|
|
uint32_t store_len;
|
|
|
|
uint16_t parse_field;
|
|
|
|
} AppLayerParserState;
|
|
|
|
|
|
|
|
typedef struct AppLayerParserStateStore_ {
|
|
|
|
AppLayerParserState to_client;
|
|
|
|
AppLayerParserState to_server;
|
|
|
|
|
|
|
|
/** flags related to the id's */
|
|
|
|
uint8_t id_flags;
|
|
|
|
|
|
|
|
/* Indicates the current transaction that is being indicated. 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;
|
|
|
|
uint16_t version; /**< state version, incremented for each update,
|
|
|
|
* can wrap around */
|
|
|
|
|
|
|
|
/* Used to store decoder events */
|
|
|
|
AppLayerDecoderEvents *decoder_events;
|
|
|
|
} AppLayerParserStateStore;
|
|
|
|
|
|
|
|
typedef struct AppLayerParserTableElement_ {
|
|
|
|
int (*AppLayerParser)(Flow *f, void *protocol_state, AppLayerParserState
|
|
|
|
*parser_state, uint8_t *input, uint32_t input_len,
|
|
|
|
void *local_storage, AppLayerParserResult *output);
|
|
|
|
|
|
|
|
char *name;
|
|
|
|
|
|
|
|
uint16_t proto;
|
|
|
|
uint16_t parser_local_id; /**< local id of the parser in the parser itself. */
|
|
|
|
} AppLayerParserTableElement;
|
|
|
|
|
|
|
|
typedef struct AppLayerProbingParserElement_ {
|
|
|
|
const char *al_proto_name;
|
|
|
|
uint16_t al_proto;
|
|
|
|
uint16_t port;
|
|
|
|
uint16_t ip_proto;
|
|
|
|
uint8_t priority;
|
|
|
|
uint8_t top;
|
|
|
|
uint32_t al_proto_mask;
|
|
|
|
/* the min length of data that has to be supplied to invoke the parser */
|
|
|
|
uint32_t min_depth;
|
|
|
|
/* the max length of data after which this parser won't be invoked */
|
|
|
|
uint32_t max_depth;
|
|
|
|
/* the probing parser function */
|
|
|
|
uint16_t (*ProbingParser)(uint8_t *input, uint32_t input_len);
|
|
|
|
|
|
|
|
struct AppLayerProbingParserElement_ *next;
|
|
|
|
} AppLayerProbingParserElement;
|
|
|
|
|
|
|
|
typedef struct AppLayerProbingParser_ {
|
|
|
|
/* the port no for which probing parser(s) are invoked */
|
|
|
|
uint16_t port;
|
|
|
|
uint32_t toserver_al_proto_mask;
|
|
|
|
uint32_t toclient_al_proto_mask;
|
|
|
|
/* the max depth for all the probing parsers registered for this port */
|
|
|
|
uint16_t toserver_max_depth;
|
|
|
|
uint16_t toclient_max_depth;
|
|
|
|
|
|
|
|
AppLayerProbingParserElement *toserver;
|
|
|
|
AppLayerProbingParserElement *toclient;
|
|
|
|
|
|
|
|
struct AppLayerProbingParser_ *next;
|
|
|
|
} AppLayerProbingParser;
|
|
|
|
|
|
|
|
typedef struct AppLayerProbingParserInfo_ {
|
|
|
|
const char *al_proto_name;
|
|
|
|
uint16_t ip_proto;
|
|
|
|
uint16_t al_proto;
|
|
|
|
uint16_t (*ProbingParser)(uint8_t *input, uint32_t input_len);
|
|
|
|
struct AppLayerProbingParserInfo_ *next;
|
|
|
|
} AppLayerProbingParserInfo;
|
|
|
|
|
|
|
|
#define APP_LAYER_PROBING_PARSER_PRIORITY_HIGH 1
|
|
|
|
#define APP_LAYER_PROBING_PARSER_PRIORITY_MEDIUM 2
|
|
|
|
#define APP_LAYER_PROBING_PARSER_PRIORITY_LOW 3
|
|
|
|
|
|
|
|
extern AppLayerProto al_proto_table[];
|
|
|
|
|
|
|
|
static inline
|
|
|
|
AppLayerProbingParser *AppLayerGetProbingParsers(AppLayerProbingParser *probing_parsers,
|
|
|
|
uint16_t ip_proto,
|
|
|
|
uint16_t port)
|
|
|
|
{
|
|
|
|
if (probing_parsers == NULL)
|
|
|
|
return NULL;
|
|
|
|
|
|
|
|
AppLayerProbingParser *pp = probing_parsers;
|
|
|
|
while (pp != NULL) {
|
|
|
|
if (pp->port == port || pp->port == 0) {
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
pp = pp->next;
|
|
|
|
}
|
|
|
|
|
|
|
|
return pp;
|
|
|
|
}
|
|
|
|
|
|
|
|
static inline
|
|
|
|
AppLayerProbingParserInfo *AppLayerGetProbingParserInfo(AppLayerProbingParserInfo *ppi,
|
|
|
|
const char *al_proto_name)
|
|
|
|
{
|
|
|
|
while (ppi != NULL) {
|
|
|
|
if (strcmp(ppi->al_proto_name, al_proto_name) == 0)
|
|
|
|
return ppi;
|
|
|
|
ppi = ppi->next;
|
|
|
|
}
|
|
|
|
|
|
|
|
return NULL;
|
|
|
|
}
|
|
|
|
struct AlpProtoDetectCtx_;
|
|
|
|
|
|
|
|
/* prototypes */
|
|
|
|
void AppLayerParsersInitPostProcess(void);
|
|
|
|
void RegisterAppLayerParsers(void);
|
|
|
|
void AppLayerParserRegisterTests(void);
|
|
|
|
|
|
|
|
/* registration */
|
|
|
|
int AppLayerRegisterProto(char *name, uint8_t proto, uint8_t flags,
|
|
|
|
int (*AppLayerParser)(Flow *f, void *protocol_state,
|
|
|
|
AppLayerParserState *parser_state,
|
|
|
|
uint8_t *input, uint32_t input_len,
|
|
|
|
void *local_data,
|
|
|
|
AppLayerParserResult *output));
|
|
|
|
int AppLayerRegisterParser(char *name, uint16_t proto, uint16_t parser_id,
|
|
|
|
int (*AppLayerParser)(Flow *f, void *protocol_state,
|
|
|
|
AppLayerParserState *parser_state,
|
|
|
|
uint8_t *input, uint32_t input_len,
|
|
|
|
void *local_data,
|
|
|
|
AppLayerParserResult *output),
|
|
|
|
char *dependency);
|
|
|
|
void AppLayerRegisterProbingParser(struct AlpProtoDetectCtx_ *, uint16_t, uint16_t,
|
|
|
|
const char *, uint16_t,
|
|
|
|
uint16_t, uint16_t, uint8_t, uint8_t,
|
|
|
|
uint8_t,
|
|
|
|
uint16_t (*ProbingParser)(uint8_t *, uint32_t));
|
|
|
|
void AppLayerRegisterStateFuncs(uint16_t proto, void *(*StateAlloc)(void),
|
|
|
|
void (*StateFree)(void *));
|
|
|
|
void AppLayerRegisterTransactionIdFuncs(uint16_t proto,
|
|
|
|
void (*StateTransactionId)(void *, uint16_t *),
|
|
|
|
void (*StateTransactionFree)(void *, uint16_t id));
|
|
|
|
void AppLayerRegisterLocalStorageFunc(uint16_t proto,
|
|
|
|
void *(*LocalStorageAlloc)(void),
|
|
|
|
void (*LocalStorageFree)(void *));
|
|
|
|
void *AppLayerGetProtocolParserLocalStorage(uint16_t);
|
|
|
|
void AppLayerRegisterGetFilesFunc(uint16_t proto,
|
|
|
|
FileContainer *(*StateGetFile)(void *, uint8_t));
|
|
|
|
void AppLayerRegisterLogger(uint16_t proto);
|
|
|
|
uint16_t AppLayerGetProtoByName(const char *);
|
|
|
|
const char *AppLayerGetProtoString(int proto);
|
|
|
|
void AppLayerRegisterTruncateFunc(uint16_t proto, void (*Truncate)(void *, uint8_t));
|
|
|
|
void AppLayerRegisterGetAlstateProgressFunc(uint16_t alproto,
|
|
|
|
int (*StateGetAlstateProgress)(void *alstate, uint8_t direction));
|
|
|
|
void AppLayerRegisterGetTxCnt(uint16_t alproto,
|
|
|
|
uint64_t (*StateGetTxCnt)(void *alstate));
|
|
|
|
void AppLayerRegisterGetTx(uint16_t alproto,
|
|
|
|
void *(*StateGetTx)(void *alstate, uint64_t tx_id));
|
|
|
|
void AppLayerRegisterGetAlstateProgressCompletionStatus(uint16_t alproto,
|
|
|
|
int (*StateProgressCompletionStatus)(uint8_t direction));
|
|
|
|
|
|
|
|
int AppLayerParse(void *, Flow *, uint8_t,
|
|
|
|
uint8_t, uint8_t *, uint32_t);
|
|
|
|
|
|
|
|
int AlpParseFieldBySize(AppLayerParserResult *, AppLayerParserState *, uint16_t,
|
|
|
|
uint32_t, uint8_t *, uint32_t, uint32_t *);
|
|
|
|
int AlpParseFieldByEOF(AppLayerParserResult *, AppLayerParserState *, uint16_t,
|
|
|
|
uint8_t *, uint32_t);
|
|
|
|
int AlpParseFieldByDelimiter(AppLayerParserResult *, AppLayerParserState *,
|
|
|
|
uint16_t, const uint8_t *, uint8_t, uint8_t *,
|
|
|
|
uint32_t, uint32_t *);
|
|
|
|
|
|
|
|
|
|
|
|
/***** transaction handling *****/
|
|
|
|
|
|
|
|
/**
|
|
|
|
* \brief Update the current log id. Does one step increments currently.
|
|
|
|
*
|
|
|
|
* \param f Flow.
|
|
|
|
*/
|
|
|
|
void AppLayerTransactionUpdateLogId(Flow *f);
|
|
|
|
|
|
|
|
/**
|
|
|
|
* \brief Get the current log id.
|
|
|
|
*
|
|
|
|
* \param f Flow.
|
|
|
|
*/
|
|
|
|
uint64_t AppLayerTransactionGetLogId(Flow *f);
|
|
|
|
|
|
|
|
/**
|
|
|
|
* \brief Updates the inspection id for the alstate.
|
|
|
|
*
|
|
|
|
* \param f Pointer to the flow(LOCKED).
|
|
|
|
* \param direction Direction. 0 - toserver, 1 - toclient.
|
|
|
|
*/
|
|
|
|
void AppLayerTransactionUpdateInspectId(Flow *f, uint8_t direction);
|
|
|
|
|
|
|
|
/**
|
|
|
|
* \brief Get the current tx id to be inspected.
|
|
|
|
*
|
|
|
|
* \param f Flow.
|
|
|
|
* \param flags Flags.
|
|
|
|
*
|
|
|
|
* \retval A positive integer value.
|
|
|
|
*/
|
|
|
|
uint64_t AppLayerTransactionGetInspectId(Flow *f, uint8_t flags);
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
void AppLayerSetEOF(Flow *);
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
/***** cleanup *****/
|
|
|
|
|
|
|
|
void AppLayerParserCleanupState(Flow *);
|
|
|
|
void AppLayerFreeProbingParsers(AppLayerProbingParser *);
|
|
|
|
void AppLayerFreeProbingParsersInfo(AppLayerProbingParserInfo *);
|
|
|
|
void AppLayerPrintProbingParsers(AppLayerProbingParser *);
|
|
|
|
|
|
|
|
void AppLayerListSupportedProtocols(void);
|
|
|
|
AppLayerDecoderEvents *AppLayerGetDecoderEventsForFlow(Flow *);
|
|
|
|
|
|
|
|
/***** Alproto param retrieval ******/
|
|
|
|
|
|
|
|
/**
|
|
|
|
* \brief get the version of the state in a direction
|
|
|
|
*
|
|
|
|
* \param f Flow(LOCKED).
|
|
|
|
* \param direction STREAM_TOSERVER or STREAM_TOCLIENT
|
|
|
|
*/
|
|
|
|
uint16_t AppLayerGetStateVersion(Flow *f);
|
|
|
|
|
|
|
|
FileContainer *AppLayerGetFilesFromFlow(Flow *, uint8_t);
|
|
|
|
|
|
|
|
/**
|
|
|
|
* \brief Get the state progress.
|
|
|
|
*
|
|
|
|
* This is a generic wrapper to each ALPROTO. The value returned
|
|
|
|
* needs to be interpreted by the caller, based on the ALPROTO_*
|
|
|
|
* the caller supplies.
|
|
|
|
*
|
|
|
|
* The state can be anything based on what the ALPROTO handler
|
|
|
|
* expects. We have given a return value of int, although a range
|
|
|
|
* of -128 to 127 (int8_t) should be more than sufficient.
|
|
|
|
*
|
|
|
|
* \param alproto The app protocol.
|
|
|
|
* \param state App state.
|
|
|
|
* \param dir Directin. 0 - ts, 1 - tc.
|
|
|
|
*
|
|
|
|
* \retval An integer value indicating the current progress of "state".
|
|
|
|
*/
|
|
|
|
int AppLayerGetAlstateProgress(uint16_t alproto, void *state, uint8_t direction);
|
|
|
|
|
|
|
|
/**
|
|
|
|
* \brief Get the no of txs.
|
|
|
|
*
|
|
|
|
* \param alproto The app protocol.
|
|
|
|
* \param alstate App state.
|
|
|
|
*
|
|
|
|
* \retval A positive integer value indicating the no of txs.
|
|
|
|
*/
|
|
|
|
uint64_t AppLayerGetTxCnt(uint16_t alproto, void *alstate);
|
|
|
|
|
|
|
|
/**
|
|
|
|
* \brief Get a tx referenced by the id.
|
|
|
|
*
|
|
|
|
* \param alproto The app protocol
|
|
|
|
* \param alstate App state.
|
|
|
|
* \param tx_id The transaction id.
|
|
|
|
*
|
|
|
|
* \retval Tx instance.
|
|
|
|
*/
|
|
|
|
void *AppLayerGetTx(uint16_t alproto, void *alstate, uint64_t tx_id);
|
|
|
|
|
|
|
|
/**
|
|
|
|
* \brief Get the state value for the following alproto, that corresponds to
|
|
|
|
* COMPLETE or DONE.
|
|
|
|
*
|
|
|
|
* \param alproto The app protocol.
|
|
|
|
* \param direction The direction. 0 - ts, 1 - tc.
|
|
|
|
*
|
|
|
|
* \retval An integer value indicating the state value.
|
|
|
|
*/
|
|
|
|
int AppLayerGetAlstateProgressCompletionStatus(uint16_t alproto, uint8_t direction);
|
|
|
|
|
|
|
|
/**
|
|
|
|
* \brief Informs if the alproto supports transactions or not.
|
|
|
|
*
|
|
|
|
* \param alproto The app protocol.
|
|
|
|
* \param direction The direction. 0 - ts, 1 - tc.
|
|
|
|
*
|
|
|
|
* \retval 1 If true; 0 If false.
|
|
|
|
*/
|
|
|
|
int AppLayerAlprotoSupportsTxs(uint16_t alproto);
|
|
|
|
|
|
|
|
void AppLayerTriggerRawStreamReassembly(Flow *);
|
|
|
|
|
|
|
|
#endif /* __APP_LAYER_PARSER_H__ */
|