|
|
|
#ifndef __DETECT_H__
|
|
|
|
#define __DETECT_H__
|
|
|
|
|
|
|
|
#include "detect-engine-proto.h"
|
|
|
|
|
|
|
|
#include "packet-queue.h"
|
|
|
|
#include "util-mpm.h"
|
|
|
|
#include "util-hash.h"
|
|
|
|
#include "util-hashlist.h"
|
|
|
|
|
|
|
|
#define COUNTER_DETECT_ALERTS 1
|
|
|
|
|
|
|
|
/*
|
|
|
|
* DETECT ADDRESS
|
|
|
|
*/
|
|
|
|
|
|
|
|
/* a is ... than b */
|
|
|
|
enum {
|
|
|
|
ADDRESS_ER = -1, /* error e.g. compare ipv4 and ipv6 */
|
|
|
|
ADDRESS_LT, /* smaller [aaa] [bbb] */
|
|
|
|
ADDRESS_LE, /* smaller with overlap [aa[bab]bb] */
|
|
|
|
ADDRESS_EQ, /* exactly equal [abababab] */
|
|
|
|
ADDRESS_ES, /* within [bb[aaa]bb] and [[abab]bbb] and [bbb[abab]] */
|
|
|
|
ADDRESS_EB, /* completely overlaps [aa[bbb]aa] and [[baba]aaa] and [aaa[baba]] */
|
|
|
|
ADDRESS_GE, /* bigger with overlap [bb[aba]aa] */
|
|
|
|
ADDRESS_GT, /* bigger [bbb] [aaa] */
|
|
|
|
};
|
|
|
|
|
|
|
|
#define ADDRESS_FLAG_ANY 0x1
|
|
|
|
#define ADDRESS_FLAG_NOT 0x2
|
|
|
|
|
|
|
|
#define ADDRESS_GROUP_SIGGROUPHEAD_COPY 0x01
|
|
|
|
#define ADDRESS_GROUP_PORTS_COPY 0x02
|
|
|
|
#define ADDRESS_GROUP_PORTS_NOTUNIQ 0x04
|
|
|
|
#define ADDRESS_GROUP_HAVEPORT 0x08
|
|
|
|
|
|
|
|
typedef struct DetectAddressData_ {
|
|
|
|
/* XXX convert to use a Address datatype to replace family, ip,ip2*/
|
|
|
|
uint8_t family;
|
|
|
|
uint32_t ip[4];
|
|
|
|
uint32_t ip2[4];
|
|
|
|
uint8_t flags;
|
|
|
|
} DetectAddressData;
|
|
|
|
|
|
|
|
typedef struct DetectAddressGroup_ {
|
|
|
|
/* address data for this group */
|
|
|
|
DetectAddressData *ad;
|
|
|
|
|
|
|
|
/* XXX ptr to rules, or PortGroup or whatever */
|
|
|
|
union {
|
|
|
|
struct DetectAddressGroupsHead_ *dst_gh;
|
|
|
|
struct DetectPort_ *port;
|
|
|
|
};
|
|
|
|
/* signatures that belong in this group */
|
|
|
|
struct SigGroupHead_ *sh;
|
|
|
|
uint8_t flags;
|
|
|
|
|
|
|
|
/* double linked list */
|
|
|
|
struct DetectAddressGroup_ *prev;
|
|
|
|
struct DetectAddressGroup_ *next;
|
|
|
|
|
|
|
|
uint32_t cnt;
|
|
|
|
} DetectAddressGroup;
|
|
|
|
|
|
|
|
/** Signature grouping head. Here 'any', ipv4 and ipv6 are split out */
|
|
|
|
typedef struct DetectAddressGroupsHead_ {
|
|
|
|
DetectAddressGroup *any_head;
|
|
|
|
DetectAddressGroup *ipv4_head;
|
|
|
|
DetectAddressGroup *ipv6_head;
|
|
|
|
} DetectAddressGroupsHead;
|
|
|
|
|
|
|
|
/*
|
|
|
|
* DETECT PORT
|
|
|
|
*/
|
|
|
|
|
|
|
|
/* a is ... than b */
|
|
|
|
enum {
|
|
|
|
PORT_ER = -1, /* error e.g. compare ipv4 and ipv6 */
|
|
|
|
PORT_LT, /* smaller [aaa] [bbb] */
|
|
|
|
PORT_LE, /* smaller with overlap [aa[bab]bb] */
|
|
|
|
PORT_EQ, /* exactly equal [abababab] */
|
|
|
|
PORT_ES, /* within [bb[aaa]bb] and [[abab]bbb] and [bbb[abab]] */
|
|
|
|
PORT_EB, /* completely overlaps [aa[bbb]aa] and [[baba]aaa] and [aaa[baba]] */
|
|
|
|
PORT_GE, /* bigger with overlap [bb[aba]aa] */
|
|
|
|
PORT_GT, /* bigger [bbb] [aaa] */
|
|
|
|
};
|
|
|
|
|
|
|
|
#define PORT_FLAG_ANY 0x01 /**< 'any' special port */
|
|
|
|
#define PORT_FLAG_NOT 0x02 /**< negated port */
|
|
|
|
#define PORT_SIGGROUPHEAD_COPY 0x04 /**< sgh is a ptr copy */
|
|
|
|
#define PORT_GROUP_PORTS_COPY 0x08 /**< dst_ph is a ptr copy */
|
|
|
|
|
|
|
|
/** \brief Port structure for detection engine */
|
|
|
|
typedef struct DetectPort_ {
|
|
|
|
uint16_t port;
|
|
|
|
uint16_t port2;
|
|
|
|
|
|
|
|
/* signatures that belong in this group */
|
|
|
|
struct SigGroupHead_ *sh;
|
|
|
|
|
|
|
|
struct DetectPort_ *dst_ph;
|
|
|
|
|
|
|
|
/* double linked list */
|
|
|
|
union {
|
|
|
|
struct DetectPort_ *prev;
|
|
|
|
struct DetectPort_ *hnext; /* hash next */
|
|
|
|
};
|
|
|
|
struct DetectPort_ *next;
|
|
|
|
|
|
|
|
uint32_t cnt;
|
|
|
|
uint8_t flags; /**< flags for this port */
|
|
|
|
} DetectPort;
|
|
|
|
|
|
|
|
/* Signature flags */
|
|
|
|
#define SIG_FLAG_RECURSIVE 0x0001 /**< recurive capturing enabled */
|
|
|
|
#define SIG_FLAG_SRC_ANY 0x0002 /**< source is any */
|
|
|
|
#define SIG_FLAG_DST_ANY 0x0004 /**< destination is any */
|
|
|
|
#define SIG_FLAG_SP_ANY 0x0008 /**< source port is any */
|
|
|
|
#define SIG_FLAG_DP_ANY 0x0010 /**< destination port is any */
|
|
|
|
#define SIG_FLAG_NOALERT 0x0020 /**< no alert flag is set */
|
|
|
|
#define SIG_FLAG_IPONLY 0x0040 /**< ip only signature */
|
|
|
|
#define SIG_FLAG_MPM 0x0080 /**< sig has mpm portion (content, uricontent, etc) */
|
|
|
|
#define SIG_FLAG_DEONLY 0x0100 /**< decode event only signature */
|
|
|
|
|
|
|
|
/* Detection Engine flags */
|
|
|
|
#define DE_QUIET 0x01 /**< DE is quiet (esp for unittests) */
|
|
|
|
|
|
|
|
typedef struct DetectEngineIPOnlyThreadCtx_ {
|
|
|
|
DetectAddressGroup *src, *dst;
|
|
|
|
uint8_t *sig_match_array; /* bit array of sig nums */
|
|
|
|
uint32_t sig_match_size; /* size in bytes of the array */
|
|
|
|
} DetectEngineIPOnlyThreadCtx;
|
|
|
|
|
|
|
|
/** \brief Signature container */
|
|
|
|
typedef struct Signature_ {
|
|
|
|
uint16_t flags;
|
|
|
|
|
|
|
|
uint8_t rev;
|
|
|
|
uint8_t prio;
|
|
|
|
|
|
|
|
uint32_t num; /**< signature number, internal id */
|
|
|
|
uint32_t id; /**< sid, set by the 'sid' rule keyword */
|
|
|
|
char *msg;
|
|
|
|
|
|
|
|
/** addresses, ports and proto this sig matches on */
|
|
|
|
DetectAddressGroupsHead src, dst;
|
|
|
|
DetectProto proto;
|
|
|
|
DetectPort *sp, *dp;
|
|
|
|
|
|
|
|
/** ptr to the SigMatch list */
|
|
|
|
struct SigMatch_ *match;
|
|
|
|
/** ptr to the next sig in the list */
|
|
|
|
struct Signature_ *next;
|
|
|
|
|
|
|
|
/** inline -- action */
|
|
|
|
uint8_t action;
|
|
|
|
} Signature;
|
|
|
|
|
|
|
|
/** \brief IP only rules matching ctx.
|
|
|
|
* \todo a radix tree would be great here */
|
|
|
|
typedef struct DetectEngineIPOnlyCtx_ {
|
|
|
|
/* lookup hashes */
|
|
|
|
HashListTable *ht16_src, *ht16_dst;
|
|
|
|
HashListTable *ht24_src, *ht24_dst;
|
|
|
|
|
|
|
|
/* counters */
|
|
|
|
uint32_t a_src_uniq16, a_src_total16;
|
|
|
|
uint32_t a_dst_uniq16, a_dst_total16;
|
|
|
|
uint32_t a_src_uniq24, a_src_total24;
|
|
|
|
uint32_t a_dst_uniq24, a_dst_total24;
|
|
|
|
|
|
|
|
uint32_t max_idx;
|
|
|
|
|
|
|
|
uint8_t *sig_init_array; /* bit array of sig nums */
|
|
|
|
uint32_t sig_init_size; /* size in bytes of the array */
|
|
|
|
|
|
|
|
/* number of sigs in this head */
|
|
|
|
uint32_t sig_cnt;
|
|
|
|
uint32_t *match_array;
|
|
|
|
} DetectEngineIPOnlyCtx;
|
|
|
|
|
|
|
|
typedef struct DetectEngineLookupFlow_ {
|
|
|
|
DetectAddressGroupsHead *src_gh[256]; /* a head for each protocol */
|
|
|
|
DetectAddressGroupsHead *tmp_gh[256];
|
|
|
|
} DetectEngineLookupFlow;
|
|
|
|
|
|
|
|
/* Flow status
|
|
|
|
*
|
|
|
|
* to server
|
|
|
|
* to client
|
|
|
|
*/
|
|
|
|
#define FLOW_STATES 2
|
|
|
|
typedef struct DetectEngineLookupDsize_ {
|
|
|
|
DetectEngineLookupFlow flow_gh[FLOW_STATES];
|
|
|
|
} DetectEngineLookupDsize;
|
|
|
|
|
|
|
|
/* Dsize states
|
|
|
|
* <= 100
|
|
|
|
* >100
|
|
|
|
*/
|
|
|
|
#define DSIZE_STATES 2
|
|
|
|
|
|
|
|
/** \brief main detection engine ctx */
|
|
|
|
typedef struct DetectEngineCtx_ {
|
|
|
|
uint8_t flags;
|
|
|
|
|
|
|
|
Signature *sig_list;
|
|
|
|
uint32_t sig_cnt;
|
|
|
|
|
|
|
|
Signature **sig_array;
|
|
|
|
uint32_t sig_array_size; /* size in bytes */
|
|
|
|
uint32_t sig_array_len; /* size in array members */
|
|
|
|
|
|
|
|
uint32_t signum;
|
|
|
|
|
|
|
|
/* main sigs */
|
|
|
|
DetectEngineLookupDsize dsize_gh[DSIZE_STATES];
|
|
|
|
|
|
|
|
uint32_t mpm_unique, mpm_reuse, mpm_none,
|
|
|
|
mpm_uri_unique, mpm_uri_reuse, mpm_uri_none;
|
|
|
|
uint32_t gh_unique, gh_reuse;
|
|
|
|
|
|
|
|
uint32_t mpm_max_patcnt, mpm_min_patcnt, mpm_tot_patcnt,
|
|
|
|
mpm_uri_max_patcnt, mpm_uri_min_patcnt, mpm_uri_tot_patcnt;
|
|
|
|
|
|
|
|
/* content and uricontent vars */
|
|
|
|
uint32_t content_max_id;
|
|
|
|
uint32_t uricontent_max_id;
|
|
|
|
|
|
|
|
/* init phase vars */
|
|
|
|
HashListTable *sgh_hash_table;
|
|
|
|
|
|
|
|
HashListTable *sgh_mpm_hash_table;
|
|
|
|
HashListTable *sgh_mpm_uri_hash_table;
|
|
|
|
|
|
|
|
HashListTable *sgh_sport_hash_table;
|
|
|
|
HashListTable *sgh_dport_hash_table;
|
|
|
|
|
|
|
|
HashListTable *sport_hash_table;
|
|
|
|
HashListTable *dport_hash_table;
|
|
|
|
|
|
|
|
HashListTable *variable_names;
|
|
|
|
uint16_t variable_names_idx;
|
|
|
|
|
|
|
|
/* memory counters */
|
|
|
|
uint32_t mpm_memory_size;
|
|
|
|
|
|
|
|
DetectEngineIPOnlyCtx io_ctx;
|
|
|
|
} DetectEngineCtx;
|
|
|
|
|
|
|
|
/**
|
|
|
|
* Detection engine thread data.
|
|
|
|
*/
|
|
|
|
typedef struct DetectionEngineThreadCtx_ {
|
|
|
|
/* detection engine variables */
|
|
|
|
uint8_t *pkt_ptr; /* ptr to the current position in the pkt */
|
|
|
|
uint16_t pkt_off;
|
|
|
|
uint8_t pkt_cnt;
|
|
|
|
|
|
|
|
char de_checking_distancewithin;
|
|
|
|
|
|
|
|
/* http_uri stuff for uricontent */
|
|
|
|
char de_have_httpuri;
|
|
|
|
|
|
|
|
/** pointer to the current mpm ctx that is stored
|
|
|
|
* in a rule group head -- can be either a content
|
|
|
|
* or uricontent ctx. */
|
|
|
|
MpmThreadCtx mtc; /**< thread ctx for the mpm */
|
|
|
|
MpmThreadCtx mtcu;
|
|
|
|
struct SigGroupHead_ *sgh;
|
|
|
|
PatternMatcherQueue pmq;
|
|
|
|
|
|
|
|
/* counters */
|
|
|
|
uint32_t pkts;
|
|
|
|
uint32_t pkts_scanned;
|
|
|
|
uint32_t pkts_searched;
|
|
|
|
uint32_t pkts_scanned1;
|
|
|
|
uint32_t pkts_searched1;
|
|
|
|
uint32_t pkts_scanned2;
|
|
|
|
uint32_t pkts_searched2;
|
|
|
|
uint32_t pkts_scanned3;
|
|
|
|
uint32_t pkts_searched3;
|
|
|
|
uint32_t pkts_scanned4;
|
|
|
|
uint32_t pkts_searched4;
|
|
|
|
|
|
|
|
uint32_t uris;
|
|
|
|
uint32_t pkts_uri_scanned;
|
|
|
|
uint32_t pkts_uri_searched;
|
|
|
|
uint32_t pkts_uri_scanned1;
|
|
|
|
uint32_t pkts_uri_searched1;
|
|
|
|
uint32_t pkts_uri_scanned2;
|
|
|
|
uint32_t pkts_uri_searched2;
|
|
|
|
uint32_t pkts_uri_scanned3;
|
|
|
|
uint32_t pkts_uri_searched3;
|
|
|
|
uint32_t pkts_uri_scanned4;
|
|
|
|
uint32_t pkts_uri_searched4;
|
|
|
|
|
|
|
|
/** id for alert counter */
|
|
|
|
uint16_t counter_alerts;
|
|
|
|
|
|
|
|
/** ip only rules ctx */
|
|
|
|
DetectEngineIPOnlyThreadCtx io_ctx;
|
|
|
|
|
|
|
|
DetectEngineCtx *de_ctx;
|
|
|
|
} DetectEngineThreadCtx;
|
|
|
|
|
|
|
|
/** \brief a single match condition for a signature */
|
|
|
|
typedef struct SigMatch_ {
|
|
|
|
uint8_t type; /**< match type */
|
|
|
|
void *ctx; /**< plugin specific data */
|
|
|
|
struct SigMatch_ *next;
|
|
|
|
struct SigMatch_ *prev;
|
|
|
|
} SigMatch;
|
|
|
|
|
|
|
|
/** \brief element in sigmatch type table. */
|
|
|
|
typedef struct SigTableElmt_ {
|
|
|
|
int (*Match)(ThreadVars *, DetectEngineThreadCtx *, Packet *, Signature *, SigMatch *);
|
|
|
|
int (*Setup)(DetectEngineCtx *, Signature *, SigMatch *, char *);
|
|
|
|
void (*Free)(void *);
|
|
|
|
void (*RegisterTests)(void);
|
|
|
|
|
|
|
|
uint8_t flags;
|
|
|
|
char *name;
|
|
|
|
} SigTableElmt;
|
|
|
|
|
|
|
|
#define SIG_GROUP_HAVECONTENT 0x01
|
|
|
|
#define SIG_GROUP_HAVEURICONTENT 0x02
|
|
|
|
#define SIG_GROUP_HEAD_MPM_COPY 0x04
|
|
|
|
#define SIG_GROUP_HEAD_MPM_URI_COPY 0x08
|
|
|
|
#define SIG_GROUP_HEAD_FREE 0x10
|
|
|
|
#define SIG_GROUP_HEAD_MPM_NOSCAN 0x20
|
|
|
|
#define SIG_GROUP_HEAD_MPM_URI_NOSCAN 0x40
|
|
|
|
|
|
|
|
/** \brief head of the list of containers. */
|
|
|
|
typedef struct SigGroupHead_ {
|
|
|
|
uint8_t flags;
|
|
|
|
|
|
|
|
/* pattern matcher instance */
|
|
|
|
MpmCtx *mpm_ctx; /* search */
|
|
|
|
uint16_t mpm_content_maxlen;
|
|
|
|
MpmCtx *mpm_uri_ctx;
|
|
|
|
uint16_t mpm_uricontent_maxlen;
|
|
|
|
|
|
|
|
/* number of sigs in this head */
|
|
|
|
uint32_t sig_cnt;
|
|
|
|
|
|
|
|
uint8_t *sig_array; /* bit array of sig nums */
|
|
|
|
uint32_t sig_size; /* size in bytes */
|
|
|
|
|
|
|
|
/* array with sig nums... size is sig_cnt * sizeof(uint32_t) */
|
|
|
|
uint32_t *match_array;
|
|
|
|
|
|
|
|
/* list of content containers
|
|
|
|
* XXX move into a separate data struct
|
|
|
|
* with only a ptr to it. Saves some memory
|
|
|
|
* after initialization
|
|
|
|
*/
|
|
|
|
uint32_t *content_array;
|
|
|
|
uint32_t content_size;
|
|
|
|
uint32_t *uri_content_array;
|
|
|
|
uint32_t uri_content_size;
|
|
|
|
|
|
|
|
/* port ptr */
|
|
|
|
struct DetectPort_ *port;
|
|
|
|
|
|
|
|
uint16_t mpm_len1;
|
|
|
|
uint16_t mpm_len2;
|
|
|
|
uint16_t mpm_len3;
|
|
|
|
uint16_t mpm_len4; /* 4+ */
|
|
|
|
} SigGroupHead;
|
|
|
|
|
|
|
|
/** sigmatch has no options, so the parser shouldn't expect any */
|
|
|
|
#define SIGMATCH_NOOPT 0x01
|
|
|
|
/** sigmatch is compatible with a ip only rule */
|
|
|
|
#define SIGMATCH_IPONLY_COMPAT 0x02
|
|
|
|
/** sigmatch is compatible with a decode event only rule */
|
|
|
|
#define SIGMATCH_DEONLY_COMPAT 0x04
|
|
|
|
|
|
|
|
enum {
|
|
|
|
DETECT_SID,
|
|
|
|
DETECT_PRIORITY,
|
|
|
|
DETECT_REV,
|
|
|
|
DETECT_CLASSTYPE,
|
|
|
|
DETECT_THRESHOLD,
|
|
|
|
DETECT_METADATA,
|
|
|
|
DETECT_REFERENCE,
|
|
|
|
DETECT_MSG,
|
|
|
|
DETECT_CONTENT, /* 8 */
|
|
|
|
DETECT_URICONTENT, /* 9 */
|
|
|
|
DETECT_PCRE, /* 10 */
|
|
|
|
DETECT_DEPTH,
|
|
|
|
DETECT_DISTANCE,
|
|
|
|
DETECT_WITHIN,
|
|
|
|
DETECT_OFFSET,
|
|
|
|
DETECT_NOCASE,
|
|
|
|
DETECT_RECURSIVE,
|
|
|
|
DETECT_RAWBYTES,
|
|
|
|
DETECT_FLOW,
|
|
|
|
DETECT_DSIZE,
|
|
|
|
DETECT_FLOWVAR,
|
|
|
|
DETECT_PKTVAR,
|
|
|
|
DETECT_NOALERT,
|
|
|
|
DETECT_FLOWBITS,
|
|
|
|
|
|
|
|
DETECT_ADDRESS,
|
|
|
|
DETECT_PROTO,
|
|
|
|
DETECT_PORT,
|
|
|
|
DETECT_DECODE_EVENT,
|
|
|
|
|
|
|
|
/* make sure this stays last */
|
|
|
|
DETECT_TBLSIZE,
|
|
|
|
};
|
|
|
|
|
|
|
|
/* Table with all SigMatch registrations */
|
|
|
|
SigTableElmt sigmatch_table[DETECT_TBLSIZE];
|
|
|
|
|
|
|
|
/* detection api */
|
|
|
|
SigMatch *SigMatchAlloc(void);
|
|
|
|
void SigMatchAppend(Signature *, SigMatch *, SigMatch *);
|
|
|
|
void SigCleanSignatures(DetectEngineCtx *);
|
|
|
|
|
|
|
|
void SigTableRegisterTests(void);
|
|
|
|
void SigRegisterTests(void);
|
|
|
|
void TmModuleDetectRegister (void);
|
|
|
|
|
|
|
|
int SigGroupBuild(DetectEngineCtx *);
|
|
|
|
int SigGroupCleanup();
|
|
|
|
|
|
|
|
int PacketAlertAppend(Packet *, uint8_t, uint32_t, uint8_t, uint8_t, char *);
|
|
|
|
|
|
|
|
void SigLoadSignatures (DetectEngineCtx *, char *);
|
|
|
|
void SigTableSetup(void);
|
|
|
|
|
|
|
|
#endif /* __DETECT_H__ */
|
|
|
|
|