Prefilter signatures before fully scanning them.

remotes/origin/master-1.0.x
Victor Julien 15 years ago
parent 60668fd01d
commit 37442a8a84

@ -222,6 +222,22 @@ typedef struct PktVar_ {
/* forward declartion since Packet struct definition requires this */
struct PacketQueue_;
/* sizes of the members:
* src: 17 bytes
* dst: 17 bytes
* sp/type: 1 byte
* dp/code: 1 byte
* proto: 1 byte
* recurs: 1 byte
*
* sum of above: 38 bytes
*
* flow ptr: 4/8 bytes
* flags: 1 byte
* flowflags: 1 byte
*
* sum of above 44/48 bytes
*/
typedef struct Packet_
{
/* Addresses, Ports and protocol
@ -242,51 +258,35 @@ typedef struct Packet_
* has the exact same tuple as the lower levels */
uint8_t recursion_level;
struct timeval ts;
/*Pkt Flags*/
uint8_t flags;
/* flow */
uint8_t flowflags;
struct Flow_ *flow;
/* ready to set verdict counter, only set in root */
uint8_t rtv_cnt;
/* tunnel packet ref count */
uint8_t tpr_cnt;
SCMutex mutex_rtv_cnt;
/* tunnel stuff */
uint8_t tunnel_proto;
/* tunnel XXX convert to bitfield*/
char tunnel_pkt;
char tunnel_verdicted;
struct timeval ts;
/* nfq stuff */
union {
/* nfq stuff */
#ifdef NFQ
NFQPacketVars nfq_v;
NFQPacketVars nfq_v;
#endif /* NFQ */
/** libpcap vars: shared by Pcap Live mode and Pcap File mode */
PcapPacketVars pcap_v;
/** libpcap vars: shared by Pcap Live mode and Pcap File mode */
PcapPacketVars pcap_v;
};
/** data linktype in host order */
int datalink;
/* storage: maximum ip packet size + link header */
uint8_t pkt[IPV6_HEADER_LEN + 65536 + 28];
uint32_t pktlen;
/* flow */
struct Flow_ *flow;
uint8_t flowflags;
/*Pkt Flags*/
uint8_t flags;
/* IPS action to take */
uint8_t action;
/* pkt vars */
PktVar *pktvar;
/* header pointers */
EthernetHdr *ethh;
PPPHdr *ppph;
PPPOESessionHdr *pppoesh;
PPPOEDiscoveryHdr *pppoedh;
GREHdr *greh;
VLANHdr *vlanh;
IPV4Hdr *ip4h;
IPV4Vars ip4vars;
@ -297,6 +297,14 @@ typedef struct Packet_
IPV6Cache ip6c;
IPV6ExtHdrs ip6eh;
TCPHdr *tcph;
TCPVars tcpvars;
TCPCache tcpc;
UDPHdr *udph;
UDPVars udpvars;
UDPCache udpc;
ICMPV4Hdr *icmpv4h;
ICMPV4Cache icmpv4c;
ICMPV4Vars icmpv4vars;
@ -305,27 +313,28 @@ typedef struct Packet_
ICMPV6Cache icmpv6c;
ICMPV6Vars icmpv6vars;
TCPHdr *tcph;
TCPVars tcpvars;
TCPCache tcpc;
PPPHdr *ppph;
PPPOESessionHdr *pppoesh;
PPPOEDiscoveryHdr *pppoedh;
UDPHdr *udph;
UDPVars udpvars;
UDPCache udpc;
GREHdr *greh;
VLANHdr *vlanh;
/* ptr to the payload of the packet
* with it's length. */
uint8_t *payload;
uint16_t payload_len;
/* storage: maximum ip packet size + link header */
uint8_t pkt[IPV6_HEADER_LEN + 65536 + 28];
uint32_t pktlen;
/* decoder events: review how many events we have */
uint8_t events[(DECODE_EVENT_MAX / 8) + 1];
PacketAlerts alerts;
/* IPS action to take */
uint8_t action;
/** packet number in the pcap file, matches wireshark */
uint64_t pcap_cnt;
@ -333,6 +342,17 @@ typedef struct Packet_
struct Packet_ *next;
struct Packet_ *prev;
/* ready to set verdict counter, only set in root */
uint8_t rtv_cnt;
/* tunnel packet ref count */
uint8_t tpr_cnt;
SCMutex mutex_rtv_cnt;
/* tunnel stuff */
uint8_t tunnel_proto;
/* tunnel XXX convert to bitfield*/
char tunnel_pkt;
char tunnel_verdicted;
/* tunnel/encapsulation handling */
struct Packet_ *root; /* in case of tunnel this is a ptr
* to the 'real' packet, the one we

@ -30,9 +30,11 @@
#include "detect-uricontent.h"
#include "detect-engine-mpm.h"
#include "detect-engine.h"
#include "detect-engine-state.h"
#include "detect-parse.h"
#include "util-mpm.h"
#include "flow.h"
#include "flow-util.h"
#include "flow-var.h"
#include "detect-flow.h"
#include "app-layer.h"
@ -1743,10 +1745,16 @@ static int SigTest76TestBug134(void)
uint16_t buflen = strlen((char *)buf);
Packet *p = UTHBuildPacket( buf, buflen, IPPROTO_TCP);
int result = 0;
Flow f;
memset(&f, 0, sizeof(Flow));
FLOW_INITIALIZE(&f);
p->dp = 515;
p->flowflags |= FLOW_PKT_ESTABLISHED;
p->flowflags |= FLOW_PKT_TOSERVER;
p->flow = &f;
char sig[] = "alert tcp any any -> any 515 "
"(msg:\"detect IFS\"; flow:to_server,established; content:\"${IFS}\";"
" depth:50; offset:0; sid:900091; rev:1;)";
@ -1759,6 +1767,8 @@ static int SigTest76TestBug134(void)
end:
if (p != NULL)
UTHFreePacket(p);
FLOW_DESTROY(&f);
return result;
}

@ -278,8 +278,8 @@ int DetectDistanceTestPacket01 (void) {
if (p == NULL)
goto end;
char sig[] = "alert tcp any any -> any any (msg:\"suricata test\"; flow:"
"from_server,established; byte_jump:1,2; content:\"|00|\"; "
char sig[] = "alert tcp any any -> any any (msg:\"suricata test\"; "
"byte_jump:1,2; content:\"|00|\"; "
"within:1; distance:2; sid:98711212; rev:1;)";
p->flowflags = FLOW_PKT_ESTABLISHED | FLOW_PKT_TOCLIENT;

@ -29,15 +29,20 @@
#include "decode.h"
#include "detect.h"
#include "app-layer-parser.h"
#include "flow-util.h"
#include "flow-var.h"
#include "detect-engine-siggroup.h"
#include "detect-engine-state.h"
#include "util-cidr.h"
#include "util-byte.h"
#include "util-unittest.h"
#include "util-debug.h"
#include "detect-engine-siggroup.h"
/*Prototypes*/
void DetectProtoTests (void);
@ -349,9 +354,15 @@ static int DetectProtoTestSig01(void) {
ThreadVars th_v;
DetectEngineThreadCtx *det_ctx;
int result = 0;
Flow f;
memset(&f, 0, sizeof(Flow));
memset(&th_v, 0, sizeof(th_v));
memset(&p, 0, sizeof(p));
FLOW_INITIALIZE(&f);
p.flow = &f;
p.src.family = AF_INET;
p.dst.family = AF_INET;
p.proto = IPPROTO_TCP;
@ -400,6 +411,8 @@ static int DetectProtoTestSig01(void) {
result = 1;
cleanup:
FLOW_DESTROY(&f);
SigGroupCleanup(de_ctx);
SigCleanSignatures(de_ctx);

@ -65,18 +65,6 @@ static uint32_t detect_siggroup_matcharray_memory = 0;
static uint32_t detect_siggroup_matcharray_init_cnt = 0;
static uint32_t detect_siggroup_matcharray_free_cnt = 0;
static SigGroupHeadInitData *SigGroupHeadInitDataAlloc(uint32_t size) {
SigGroupHeadInitData *sghid = SCMalloc(sizeof(SigGroupHeadInitData));
if (sghid == NULL)
return NULL;
memset(sghid, 0x00, sizeof(SigGroupHeadInitData));
detect_siggroup_head_initdata_init_cnt++;
detect_siggroup_head_initdata_memory += sizeof(SigGroupHeadInitData);
return sghid;
}
void SigGroupHeadInitDataFree(SigGroupHeadInitData *sghid) {
if (sghid->content_array != NULL) {
SCFree(sghid->content_array);
@ -88,12 +76,59 @@ void SigGroupHeadInitDataFree(SigGroupHeadInitData *sghid) {
sghid->uri_content_array = NULL;
sghid->uri_content_size = 0;
}
if (sghid->sig_array != NULL) {
SCFree(sghid->sig_array);
sghid->sig_array = NULL;
detect_siggroup_sigarray_free_cnt++;
detect_siggroup_sigarray_memory -= sghid->sig_size;
}
SCFree(sghid);
detect_siggroup_head_initdata_free_cnt++;
detect_siggroup_head_initdata_memory -= sizeof(SigGroupHeadInitData);
}
static SigGroupHeadInitData *SigGroupHeadInitDataAlloc(uint32_t size) {
SigGroupHeadInitData *sghid = SCMalloc(sizeof(SigGroupHeadInitData));
if (sghid == NULL)
return NULL;
memset(sghid, 0x00, sizeof(SigGroupHeadInitData));
detect_siggroup_head_initdata_init_cnt++;
detect_siggroup_head_initdata_memory += sizeof(SigGroupHeadInitData);
/* initialize the signature bitarray */
sghid->sig_size = size;
if ( (sghid->sig_array = SCMalloc(sghid->sig_size)) == NULL)
goto error;
memset(sghid->sig_array, 0, sghid->sig_size);
detect_siggroup_sigarray_init_cnt++;
detect_siggroup_sigarray_memory += sghid->sig_size;
return sghid;
error:
SigGroupHeadInitDataFree(sghid);
return NULL;
}
void SigGroupHeadStore(DetectEngineCtx *de_ctx, SigGroupHead *sgh) {
//printf("de_ctx->sgh_array_cnt %u, de_ctx->sgh_array_size %u, de_ctx->sgh_array %p\n", de_ctx->sgh_array_cnt, de_ctx->sgh_array_size, de_ctx->sgh_array);
if (de_ctx->sgh_array_cnt < de_ctx->sgh_array_size) {
de_ctx->sgh_array[de_ctx->sgh_array_cnt] = sgh;
} else {
de_ctx->sgh_array = SCRealloc(de_ctx->sgh_array, sizeof(SigGroupHead *) * (16 + de_ctx->sgh_array_size));
if (de_ctx->sgh_array == NULL)
return;
de_ctx->sgh_array_size += 10;
de_ctx->sgh_array[de_ctx->sgh_array_cnt] = sgh;
}
de_ctx->sgh_array_cnt++;
}
/**
* \brief Alloc a SigGroupHead and its signature bit_array.
*
@ -103,7 +138,7 @@ void SigGroupHeadInitDataFree(SigGroupHeadInitData *sghid) {
* \retval sgh Pointer to the newly init SigGroupHead on success; or NULL in
* case of error.
*/
static SigGroupHead *SigGroupHeadAlloc(uint32_t size)
static SigGroupHead *SigGroupHeadAlloc(DetectEngineCtx *de_ctx, uint32_t size)
{
SigGroupHead *sgh = SCMalloc(sizeof(SigGroupHead));
if (sgh == NULL)
@ -117,15 +152,6 @@ static SigGroupHead *SigGroupHeadAlloc(uint32_t size)
detect_siggroup_head_init_cnt++;
detect_siggroup_head_memory += sizeof(SigGroupHead);
/* initialize the signature bitarray */
sgh->sig_size = size;
if ( (sgh->sig_array = SCMalloc(sgh->sig_size)) == NULL)
goto error;
memset(sgh->sig_array, 0, sgh->sig_size);
detect_siggroup_sigarray_init_cnt++;
detect_siggroup_sigarray_memory += sgh->sig_size;
return sgh;
error:
@ -148,14 +174,6 @@ void SigGroupHeadFree(SigGroupHead *sgh)
PatternMatchDestroyGroup(sgh);
if (sgh->sig_array != NULL) {
SCFree(sgh->sig_array);
sgh->sig_array = NULL;
detect_siggroup_sigarray_free_cnt++;
detect_siggroup_sigarray_memory -= sgh->sig_size;
}
if (sgh->match_array != NULL) {
detect_siggroup_matcharray_free_cnt++;
detect_siggroup_matcharray_memory -= (sgh->sig_cnt * sizeof(Signature *));
@ -575,11 +593,11 @@ uint32_t SigGroupHeadHashFunc(HashListTable *ht, void *data, uint16_t datalen)
SCLogDebug("hashing sgh %p (mpm_content_maxlen %u)", sgh, sgh->mpm_content_maxlen);
for (b = 0; b < sgh->sig_size; b++)
hash += sgh->sig_array[b];
for (b = 0; b < sgh->init->sig_size; b++)
hash += sgh->init->sig_array[b];
hash %= ht->array_size;
SCLogDebug("hash %"PRIu32" (sig_size %"PRIu32")", hash, sgh->sig_size);
SCLogDebug("hash %"PRIu32" (sig_size %"PRIu32")", hash, sgh->init->sig_size);
return hash;
}
@ -604,10 +622,10 @@ char SigGroupHeadCompareFunc(void *data1, uint16_t len1, void *data2,
if (data1 == NULL || data2 == NULL)
return 0;
if (sgh1->sig_size != sgh2->sig_size)
if (sgh1->init->sig_size != sgh2->init->sig_size)
return 0;
if (memcmp(sgh1->sig_array, sgh2->sig_array, sgh1->sig_size) != 0)
if (memcmp(sgh1->init->sig_array, sgh2->init->sig_array, sgh1->init->sig_size) != 0)
return 0;
return 1;
@ -866,16 +884,17 @@ static void SigGroupHeadFreeSigArraysHash2(DetectEngineCtx *de_ctx,
for (htb = HashListTableGetListHead(ht);
htb != NULL;
htb = HashListTableGetListNext(htb)) {
htb = HashListTableGetListNext(htb))
{
sgh = (SigGroupHead *)HashListTableGetListData(htb);
if (sgh->sig_array != NULL) {
if (sgh->init->sig_array != NULL) {
detect_siggroup_sigarray_free_cnt++;
detect_siggroup_sigarray_memory -= sgh->sig_size;
detect_siggroup_sigarray_memory -= sgh->init->sig_size;
SCFree(sgh->sig_array);
sgh->sig_array = NULL;
sgh->sig_size = 0;
SCFree(sgh->init->sig_array);
sgh->init->sig_array = NULL;
sgh->init->sig_size = 0;
}
if (sgh->init != NULL) {
@ -905,15 +924,6 @@ static void SigGroupHeadFreeSigArraysHash(DetectEngineCtx *de_ctx,
htb = HashListTableGetListNext(htb)) {
sgh = (SigGroupHead *)HashListTableGetListData(htb);
if (sgh->sig_array != NULL) {
detect_siggroup_sigarray_free_cnt++;
detect_siggroup_sigarray_memory -= sgh->sig_size;
SCFree(sgh->sig_array);
sgh->sig_array = NULL;
sgh->sig_size = 0;
}
if (sgh->init != NULL) {
SigGroupHeadInitDataFree(sgh->init);
sgh->init = NULL;
@ -987,13 +997,13 @@ int SigGroupHeadAppendSig(DetectEngineCtx *de_ctx, SigGroupHead **sgh,
/* see if we have a head already */
if (*sgh == NULL) {
*sgh = SigGroupHeadAlloc(DetectEngineGetMaxSigId(de_ctx) / 8 + 1);
*sgh = SigGroupHeadAlloc(de_ctx, DetectEngineGetMaxSigId(de_ctx) / 8 + 1);
if (*sgh == NULL)
goto error;
}
/* enable the sig in the bitarray */
(*sgh)->sig_array[s->num / 8] |= 1 << (s->num % 8);
(*sgh)->init->sig_array[s->num / 8] |= 1 << (s->num % 8);
/* update maxlen for mpm */
if (s->flags & SIG_FLAG_MPM) {
@ -1037,8 +1047,8 @@ int SigGroupHeadClearSigs(SigGroupHead *sgh)
if (sgh == NULL)
return 0;
if (sgh->sig_array != NULL)
memset(sgh->sig_array, 0, sgh->sig_size);
if (sgh->init->sig_array != NULL)
memset(sgh->init->sig_array, 0, sgh->init->sig_size);
sgh->sig_cnt = 0;
@ -1064,14 +1074,14 @@ int SigGroupHeadCopySigs(DetectEngineCtx *de_ctx, SigGroupHead *src, SigGroupHea
return 0;
if (*dst == NULL) {
*dst = SigGroupHeadAlloc(DetectEngineGetMaxSigId(de_ctx) / 8 + 1);
*dst = SigGroupHeadAlloc(de_ctx, DetectEngineGetMaxSigId(de_ctx) / 8 + 1);
if (*dst == NULL)
goto error;
}
/* do the copy */
for (idx = 0; idx < src->sig_size; idx++)
(*dst)->sig_array[idx] = (*dst)->sig_array[idx] | src->sig_array[idx];
for (idx = 0; idx < src->init->sig_size; idx++)
(*dst)->init->sig_array[idx] = (*dst)->init->sig_array[idx] | src->init->sig_array[idx];
if (src->mpm_content_maxlen != 0) {
if ((*dst)->mpm_content_maxlen == 0)
@ -1111,7 +1121,7 @@ void SigGroupHeadSetSigCnt(SigGroupHead *sgh, uint32_t max_idx)
sgh->sig_cnt = 0;
for (sig = 0; sig < max_idx + 1; sig++) {
if (sgh->sig_array[sig / 8] & (1 << (sig % 8)))
if (sgh->init->sig_array[sig / 8] & (1 << (sig % 8)))
sgh->sig_cnt++;
}
@ -1192,8 +1202,8 @@ void SigGroupHeadPrintSigs(DetectEngineCtx *de_ctx, SigGroupHead *sgh)
uint32_t u;
SCLogDebug("The Signatures present in this SigGroupHead are: ");
for (u = 0; u < (sgh->sig_size * 8); u++) {
if (sgh->sig_array[u / 8] & (1 << (u % 8))) {
for (u = 0; u < (sgh->init->sig_size * 8); u++) {
if (sgh->init->sig_array[u / 8] & (1 << (u % 8))) {
SCLogDebug("%" PRIu32, u);
printf("s->num %"PRIu16" ", u);
}
@ -1532,7 +1542,7 @@ int SigGroupHeadBuildMatchArray(DetectEngineCtx *de_ctx, SigGroupHead *sgh,
detect_siggroup_matcharray_memory += (sgh->sig_cnt * sizeof(Signature *));
for (sig = 0; sig < max_idx + 1; sig++) {
if (!(sgh->sig_array[(sig / 8)] & (1 << (sig % 8))) )
if (!(sgh->init->sig_array[(sig / 8)] & (1 << (sig % 8))) )
continue;
s = de_ctx->sig_array[sig];
@ -1546,6 +1556,49 @@ int SigGroupHeadBuildMatchArray(DetectEngineCtx *de_ctx, SigGroupHead *sgh,
return 0;
}
int SigGroupHeadBuildHeadArray(DetectEngineCtx *de_ctx, SigGroupHead *sgh)
{
Signature *s = NULL;
uint32_t idx = 0;
uint32_t sig = 0;
if (sgh == NULL)
return 0;
BUG_ON(sgh->head_array != NULL);
sgh->head_array = SCMalloc(sgh->sig_cnt * sizeof(SignatureHeader));
if (sgh->head_array == NULL)
return -1;
memset(sgh->head_array, 0, sgh->sig_cnt * sizeof(SignatureHeader));
detect_siggroup_matcharray_init_cnt++;
detect_siggroup_matcharray_memory += (sgh->sig_cnt * sizeof(SignatureHeader *));
for (sig = 0; sig < sgh->sig_cnt; sig++) {
s = sgh->match_array[sig];
if (s == NULL)
continue;
sgh->head_array[idx].flags = s->flags;
sgh->head_array[idx].mpm_pattern_id = s->mpm_pattern_id;
sgh->head_array[idx].alproto = s->alproto;
sgh->head_array[idx].num = s->num;
sgh->head_array[idx].full_sig = s;
BUG_ON(s->flags != sgh->head_array[idx].flags);
BUG_ON(s->alproto != sgh->head_array[idx].alproto);
BUG_ON(s->mpm_pattern_id != sgh->head_array[idx].mpm_pattern_id);
BUG_ON(s->num != sgh->head_array[idx].num);
BUG_ON(s != sgh->head_array[idx].full_sig);
idx++;
}
return 0;
}
/**
* \brief Check if a SigGroupHead contains a Signature, whose sid is sent as an
* argument.
@ -1572,12 +1625,12 @@ int SigGroupHeadContainsSigId(DetectEngineCtx *de_ctx, SigGroupHead *sgh,
}
for (sig = 0; sig < max_sid; sig++) {
if (sgh->sig_array == NULL) {
if (sgh->init->sig_array == NULL) {
SCReturnInt(0);
}
/* Check if the SigGroupHead has an entry for the sid */
if ( !(sgh->sig_array[sig / 8] & (1 << (sig % 8))) )
if ( !(sgh->init->sig_array[sig / 8] & (1 << (sig % 8))) )
continue;
/* If we have reached here, we have an entry for sid in the SigGrouHead.

@ -83,4 +83,6 @@ int SigGroupHeadContainsSigId (DetectEngineCtx *de_ctx, SigGroupHead *sgh,
void SigGroupHeadRegisterTests(void);
void SigGroupHeadPrintSigs(DetectEngineCtx *de_ctx, SigGroupHead *sgh);
void SigGroupHeadStore(DetectEngineCtx *, SigGroupHead *);
int SigGroupHeadBuildHeadArray(DetectEngineCtx *, SigGroupHead *);
#endif /* __DETECT_ENGINE_SIGGROUP_H__ */

@ -1089,6 +1089,13 @@ Signature *SigInit(DetectEngineCtx *de_ctx, char *sigstr) {
}
}
if (sig->umatch)
sig->flags |= SIG_FLAG_UMATCH;
if (sig->dmatch)
sig->flags |= SIG_FLAG_AMATCH;
if (sig->amatch)
sig->flags |= SIG_FLAG_AMATCH;
SCLogDebug("sig %"PRIu32" SIG_FLAG_APPLAYER: %s, SIG_FLAG_PACKET: %s",
sig->id, sig->flags & SIG_FLAG_APPLAYER ? "set" : "not set",
sig->flags & SIG_FLAG_PACKET ? "set" : "not set");
@ -1267,6 +1274,13 @@ Signature *SigInitReal(DetectEngineCtx *de_ctx, char *sigstr) {
}
}
if (sig->umatch)
sig->flags |= SIG_FLAG_UMATCH;
if (sig->dmatch)
sig->flags |= SIG_FLAG_AMATCH;
if (sig->amatch)
sig->flags |= SIG_FLAG_AMATCH;
SCLogDebug("sig %"PRIu32" SIG_FLAG_APPLAYER: %s, SIG_FLAG_PACKET: %s",
sig->id, sig->flags & SIG_FLAG_APPLAYER ? "set" : "not set",
sig->flags & SIG_FLAG_PACKET ? "set" : "not set");

@ -204,28 +204,6 @@ void DetectExitPrintStats(ThreadVars *tv, void *data) {
(float)(det_ctx->pkts_uri_searched/(float)(det_ctx->uris)*100));
}
int SghHasSig(DetectEngineCtx *de_ctx, SigGroupHead *sgh, uint32_t sid) {
if (sgh == NULL) {
return 0;
}
uint32_t sig;
for (sig = 0; sig < DetectEngineGetMaxSigId(de_ctx); sig++) {
if (!(sgh->sig_array[(sig/8)] & (1<<(sig%8))))
continue;
Signature *s = de_ctx->sig_array[sig];
if (s == NULL)
continue;
if (sid == s->id) {
return 1;
}
}
return 0;
}
/** \brief Create the path if default-rule-path was specified
* \param sig_file The name of the file
* \retval str Pointer to the string path + sig_file
@ -441,6 +419,12 @@ int SigLoadSignatures (DetectEngineCtx *de_ctx, char *sig_file)
* \param de_state_start flag to indicate if we're at the start of a stateful run
* \param p packet
* \param alproto application layer protocol
*
* Order of SignatureHeader access:
* 1. flags
* 2. alproto
* 3. mpm_pattern_id
* 4. num
*/
static void SigMatchSignaturesBuildMatchArray(DetectEngineCtx *de_ctx,
DetectEngineThreadCtx *det_ctx, char de_state_start, Packet *p,
@ -452,26 +436,10 @@ static void SigMatchSignaturesBuildMatchArray(DetectEngineCtx *de_ctx,
det_ctx->match_array_cnt = 0;
for (i = 0; i < det_ctx->sgh->sig_cnt; i++) {
Signature *s = det_ctx->sgh->match_array[i];
SignatureHeader *s = &det_ctx->sgh->head_array[i];
if (s->flags & SIG_FLAG_MPM) {
/* filter out sigs that want pattern matches, but
* have no matches */
if (!(det_ctx->pmq.pattern_id_bitarray[(s->mpm_pattern_id / 8)] & (1<<(s->mpm_pattern_id % 8))) &&
(s->flags & SIG_FLAG_MPM) && !(s->flags & SIG_FLAG_MPM_NEGCONTENT)) {
SCLogDebug("mpm sig without matches (pat id check in content).");
continue;
}
}
/* de_state check, filter out all signatures that already had a match before
* or just partially match */
if (de_state_start == FALSE) {
if (s->amatch != NULL || s->umatch != NULL || s->dmatch != NULL) {
if (det_ctx->de_state_sig_array[s->num] != DE_STATE_MATCH_NEW) {
continue;
}
}
if (s->flags & SIG_FLAG_FLOW && !p->flow) {
continue;
}
/* filter out the sigs that inspect the payload, if packet
@ -488,43 +456,29 @@ static void SigMatchSignaturesBuildMatchArray(DetectEngineCtx *de_ctx,
}
}
/* check the source & dst port in the sig */
if (p->proto == IPPROTO_TCP || p->proto == IPPROTO_UDP) {
if (!(s->flags & SIG_FLAG_DP_ANY)) {
DetectPort *dport = DetectPortLookupGroup(s->dp,p->dp);
if (dport == NULL) {
SCLogDebug("dport didn't match.");
continue;
}
}
if (!(s->flags & SIG_FLAG_SP_ANY)) {
DetectPort *sport = DetectPortLookupGroup(s->sp,p->sp);
if (sport == NULL) {
SCLogDebug("sport didn't match.");
continue;
}
if (s->flags & SIG_FLAG_MPM && !(s->flags & SIG_FLAG_MPM_NEGCONTENT)) {
/* filter out sigs that want pattern matches, but
* have no matches */
if (!(det_ctx->pmq.pattern_id_bitarray[(s->mpm_pattern_id / 8)] & (1<<(s->mpm_pattern_id % 8)))) {
SCLogDebug("mpm sig without matches (pat id %"PRIu32" check in content).", s->mpm_pattern_id);
continue;
}
}
/* check the destination address */
if (!(s->flags & SIG_FLAG_DST_ANY)) {
DetectAddress *daddr = DetectAddressLookupInHead(&s->dst,&p->dst);
if (daddr == NULL) {
SCLogDebug("dst addr didn't match.");
continue;
}
}
/* check the source address */
if (!(s->flags & SIG_FLAG_SRC_ANY)) {
DetectAddress *saddr = DetectAddressLookupInHead(&s->src,&p->src);
if (saddr == NULL) {
SCLogDebug("src addr didn't match.");
/* de_state check, filter out all signatures that already had a match before
* or just partially match */
if (s->flags & SIG_FLAG_AMATCH || s->flags & SIG_FLAG_UMATCH ||
s->flags & SIG_FLAG_DMATCH)
{
if (de_state_start == FALSE) {
if (det_ctx->de_state_sig_array[s->num] != DE_STATE_MATCH_NEW) {
continue;
}
}
}
/* okay, store it */
det_ctx->match_array[det_ctx->match_array_cnt] = s;
det_ctx->match_array[det_ctx->match_array_cnt] = s->full_sig;
det_ctx->match_array_cnt++;
}
}
@ -759,6 +713,41 @@ int SigMatchSignatures(ThreadVars *th_v, DetectEngineCtx *de_ctx, DetectEngineTh
s = det_ctx->match_array[idx];
SCLogDebug("inspecting signature id %"PRIu32"", s->id);
/* check the source & dst port in the sig */
if (p->proto == IPPROTO_TCP || p->proto == IPPROTO_UDP) {
if (!(s->flags & SIG_FLAG_DP_ANY)) {
DetectPort *dport = DetectPortLookupGroup(s->dp,p->dp);
if (dport == NULL) {
SCLogDebug("dport didn't match.");
continue;
}
}
if (!(s->flags & SIG_FLAG_SP_ANY)) {
DetectPort *sport = DetectPortLookupGroup(s->sp,p->sp);
if (sport == NULL) {
SCLogDebug("sport didn't match.");
continue;
}
}
}
/* check the destination address */
if (!(s->flags & SIG_FLAG_DST_ANY)) {
DetectAddress *daddr = DetectAddressLookupInHead(&s->dst,&p->dst);
if (daddr == NULL) {
SCLogDebug("dst addr didn't match.");
continue;
}
}
/* check the source address */
if (!(s->flags & SIG_FLAG_SRC_ANY)) {
DetectAddress *saddr = DetectAddressLookupInHead(&s->src,&p->src);
if (saddr == NULL) {
SCLogDebug("src addr didn't match.");
continue;
}
}
SCLogDebug("s->amatch %p, s->umatch %p", s->amatch, s->umatch);
if ((s->amatch != NULL || s->umatch != NULL || s->dmatch != NULL) && p->flow != NULL) {
if (de_state_start == TRUE) {
@ -1891,7 +1880,7 @@ int BuildDestinationAddressHeads(DetectEngineCtx *de_ctx, DetectAddressHead *hea
* and build the temporary destination address list for it */
uint32_t sig;
for (sig = 0; sig < de_ctx->sig_array_len; sig++) {
if (!(gr->sh->sig_array[(sig/8)] & (1<<(sig%8))))
if (!(gr->sh->init->sig_array[(sig/8)] & (1<<(sig%8))))
continue;
tmp_s = de_ctx->sig_array[sig];
@ -2033,6 +2022,7 @@ int BuildDestinationAddressHeads(DetectEngineCtx *de_ctx, DetectAddressHead *hea
}
SigGroupHeadHashAdd(de_ctx, sgr->sh);
SigGroupHeadStore(de_ctx, sgr->sh);
de_ctx->gh_unique++;
} else {
SCLogDebug("calling SigGroupHeadFree sgr %p, sgr->sh %p", sgr, sgr->sh);
@ -2083,7 +2073,7 @@ int BuildDestinationAddressHeadsWithBothPorts(DetectEngineCtx *de_ctx, DetectAdd
* and build the temporary destination address list for it */
uint32_t sig;
for (sig = 0; sig < de_ctx->sig_array_len; sig++) {
if (!(src_gr->sh->sig_array[(sig/8)] & (1<<(sig%8))))
if (!(src_gr->sh->init->sig_array[(sig/8)] & (1<<(sig%8))))
continue;
tmp_s = de_ctx->sig_array[sig];
@ -2145,7 +2135,7 @@ int BuildDestinationAddressHeadsWithBothPorts(DetectEngineCtx *de_ctx, DetectAdd
uint32_t sig2;
for (sig2 = 0; sig2 < max_idx+1; sig2++) {
if (!(dst_gr->sh->sig_array[(sig2/8)] & (1<<(sig2%8))))
if (!(dst_gr->sh->init->sig_array[(sig2/8)] & (1<<(sig2%8))))
continue;
Signature *s = de_ctx->sig_array[sig2];
@ -2201,7 +2191,7 @@ int BuildDestinationAddressHeadsWithBothPorts(DetectEngineCtx *de_ctx, DetectAdd
DetectPortDpHashReset(de_ctx);
uint32_t sig2;
for (sig2 = 0; sig2 < max_idx+1; sig2++) {
if (!(sp->sh->sig_array[(sig2/8)] & (1<<(sig2%8))))
if (!(sp->sh->init->sig_array[(sig2/8)] & (1<<(sig2%8))))
continue;
Signature *s = de_ctx->sig_array[sig2];
@ -2323,6 +2313,7 @@ int BuildDestinationAddressHeadsWithBothPorts(DetectEngineCtx *de_ctx, DetectAdd
}
SigGroupHeadDPortHashAdd(de_ctx, dp->sh);
SigGroupHeadStore(de_ctx, dp->sh);
de_ctx->gh_unique++;
} else {
SCLogDebug("dp %p dp->sh %p is a copy", dp, dp->sh);
@ -2537,14 +2528,14 @@ void DbgPrintSigs(DetectEngineCtx *de_ctx, SigGroupHead *sgh) {
}
void DbgPrintSigs2(DetectEngineCtx *de_ctx, SigGroupHead *sgh) {
if (sgh == NULL) {
if (sgh == NULL || sgh->init == NULL) {
printf("\n");
return;
}
uint32_t sig;
for (sig = 0; sig < DetectEngineGetMaxSigId(de_ctx); sig++) {
if (sgh->sig_array[(sig/8)] & (1<<(sig%8))) {
if (sgh->init->sig_array[(sig/8)] & (1<<(sig%8))) {
printf("%" PRIu32 " ", de_ctx->sig_array[sig]->id);
}
}
@ -2552,14 +2543,14 @@ void DbgPrintSigs2(DetectEngineCtx *de_ctx, SigGroupHead *sgh) {
}
void DbgSghContainsSig(DetectEngineCtx *de_ctx, SigGroupHead *sgh, uint32_t sid) {
if (sgh == NULL) {
if (sgh == NULL || sgh->init == NULL) {
printf("\n");
return;
}
uint32_t sig;
for (sig = 0; sig < DetectEngineGetMaxSigId(de_ctx); sig++) {
if (!(sgh->sig_array[(sig/8)] & (1<<(sig%8))))
if (!(sgh->init->sig_array[(sig/8)] & (1<<(sig%8))))
continue;
Signature *s = de_ctx->sig_array[sig];
@ -2573,6 +2564,29 @@ void DbgSghContainsSig(DetectEngineCtx *de_ctx, SigGroupHead *sgh, uint32_t sid)
printf("\n");
}
/** \brief finalize preparing sgh's */
int SigAddressPrepareStage4(DetectEngineCtx *de_ctx) {
SCEnter();
//SCLogInfo("sgh's %"PRIu32, de_ctx->sgh_array_cnt);
uint32_t idx = 0;
for (idx = 0; idx < de_ctx->sgh_array_cnt; idx++) {
SigGroupHead *sgh = de_ctx->sgh_array[idx];
if (sgh == NULL)
continue;
SigGroupHeadBuildHeadArray(de_ctx, sgh);
}
SCFree(de_ctx->sgh_array);
de_ctx->sgh_array_cnt = 0;
de_ctx->sgh_array_size = 0;
SCReturnInt(0);
}
/* shortcut for debugging. If enabled Stage5 will
* print sigid's for all groups */
#define PRINTSIGS
@ -2921,6 +2935,7 @@ int SigGroupBuild (DetectEngineCtx *de_ctx) {
#endif
SigAddressPrepareStage3(de_ctx);
SigAddressPrepareStage4(de_ctx);
#ifdef __SC_CUDA_SUPPORT__
unsigned int cuda_free_after_alloc = 0;

@ -55,7 +55,6 @@ struct SCSigSignatureWrapper_;
For TCP/UDP
Packet data size (dsize)
- Flow direction
-- Protocol
-=- Src address
@ -65,7 +64,6 @@ struct SCSigSignatureWrapper_;
For the other protocols
Packet data size (dsize)
- Flow direction
-- Protocol
-=- Src address
@ -200,6 +198,10 @@ typedef struct DetectPort_ {
#define SIG_FLAG_BIDIREC 0x00010000 /**< signature has bidirectional operator */
#define SIG_FLAG_PACKET 0x00020000 /**< signature has matches against a packet (as opposed to app layer) */
#define SIG_FLAG_UMATCH 0x00040000
#define SIG_FLAG_AMATCH 0x00080000
#define SIG_FLAG_DMATCH 0x00100000
/* Detection Engine flags */
#define DE_QUIET 0x01 /**< DE is quiet (esp for unittests) */
@ -219,33 +221,43 @@ typedef struct IPOnlyCIDRItem_ {
} IPOnlyCIDRItem;
/** \brief Signature container */
typedef struct Signature_ {
/** \brief Subset of the Signature for cache efficient prefiltering
*/
typedef struct SignatureHeader_ {
uint32_t flags;
uint8_t rev;
int prio;
/* app layer signature stuff */
uint16_t alproto;
/** pattern in the mpm matcher */
uint32_t mpm_pattern_id;
uint32_t gid; /**< generator id */
SigIntId num; /**< signature number, internal id */
uint32_t id; /**< sid, set by the 'sid' rule keyword */
uint8_t nchunk_groups; /**< Internal chunk grp id (for splitted patterns) */
char *msg;
/** classification id **/
uint8_t class;
/** pointer to the full signature */
struct Signature_ *full_sig;
} SignatureHeader;
/** classification message */
char *class_msg;
/** \brief Signature container */
typedef struct Signature_ {
uint32_t flags;
/** Reference */
Reference *references;
/* app layer signature stuff */
uint16_t alproto;
/** addresses, ports and proto this sig matches on */
/** pattern in the mpm matcher */
uint32_t mpm_pattern_id;
SigIntId num; /**< signature number, internal id */
/** address settings for this signature */
DetectAddressHead src, dst;
DetectProto proto;
/** port settings for this signature */
DetectPort *sp, *dp;
/** addresses, ports and proto this sig matches on */
DetectProto proto;
/** netblocks and hosts specified at the sid, in CIDR format */
IPOnlyCIDRItem *CidrSrc, *CidrDst;
@ -260,6 +272,7 @@ typedef struct Signature_ {
struct SigMatch_ *amatch_tail; /* general app layer matches, tail of the list */
struct SigMatch_ *dmatch; /* dce app layer matches */
struct SigMatch_ *dmatch_tail; /* dce app layer matches, tail of the list */
/** ptr to the next sig in the list */
struct Signature_ *next;
@ -270,18 +283,30 @@ typedef struct Signature_ {
uint16_t mpm_content_maxlen;
uint16_t mpm_uricontent_maxlen;
/* app layer signature stuff */
uint8_t alproto;
/** number of sigmatches in the match and pmatch list */
uint16_t sm_cnt;
SigIntId order_id;
/** pattern in the mpm matcher */
uint32_t mpm_pattern_id;
uint32_t mpm_uripattern_id;
uint8_t rev;
int prio;
uint32_t gid; /**< generator id */
uint32_t id; /**< sid, set by the 'sid' rule keyword */
char *msg;
/** classification id **/
uint8_t class;
/** classification message */
char *class_msg;
/** Reference */
Reference *references;
#ifdef PROFILING
uint16_t profiling_id;
#endif
@ -439,6 +464,12 @@ typedef struct DetectEngineCtx_ {
/** hash table for looking up patterns for
* id sharing and id tracking. */
MpmPatternIdStore *mpm_pattern_id_store;
/* array containing all sgh's in use so we can loop
* through it in Stage4. */
struct SigGroupHead_ **sgh_array;
uint32_t sgh_array_cnt;
uint32_t sgh_array_size;
} DetectEngineCtx;
/* Engine groups profiles (low, medium, high, custom) */
@ -588,29 +619,37 @@ typedef struct SigGroupHeadInitData_ {
uint8_t *stream_content_array;
uint32_t stream_content_size;
/* "Normal" detection uses these only at init, but ip-only
* uses it during runtime as well, thus not in init... */
uint8_t *sig_array; /**< bit array of sig nums (internal id's) */
uint32_t sig_size; /**< size in bytes */
/* port ptr */
struct DetectPort_ *port;
} SigGroupHeadInitData;
/** \brief head of the list of containers. */
/** \brief Container for matching data for a signature group */
typedef struct SigGroupHead_ {
uint8_t flags;
/* pattern matcher instance */
MpmCtx *mpm_ctx;
uint16_t mpm_content_maxlen;
MpmCtx *mpm_uri_ctx;
uint16_t mpm_uricontent_maxlen;
MpmCtx *mpm_stream_ctx;
uint16_t mpm_streamcontent_maxlen;
uint8_t pad0;
uint16_t pad1;
/* number of sigs in this head */
uint32_t sig_cnt;
/* "Normal" detection uses these only at init, but ip-only
* uses it during runtime as well, thus not in init... */
uint8_t *sig_array; /**< bit array of sig nums (internal id's) */
uint32_t sig_size; /**< size in bytes */
/** chunk of memory containing the "header" part of each
* signature ordered as an array. Used to pre-filter the
* signatures to be inspected in a cache efficient way. */
SignatureHeader *head_array;
/* pattern matcher instances */
MpmCtx *mpm_ctx;
MpmCtx *mpm_stream_ctx;
uint16_t mpm_content_maxlen;
uint16_t mpm_streamcontent_maxlen;
MpmCtx *mpm_uri_ctx;
uint16_t mpm_uricontent_maxlen;
/** Array with sig ptrs... size is sig_cnt * sizeof(Signature *) */
Signature **match_array;

@ -25,18 +25,21 @@
*/
#include "suricata-common.h"
#include "decode.h"
#include "flow-private.h"
#include "flow-util.h"
#include "detect.h"
#include "detect-parse.h"
#include "detect-engine.h"
#include "util-debug.h"
#include "util-time.h"
#include "util-error.h"
#include "util-unittest.h"
#include "util-unittest-helper.h"
#include <stdarg.h>
#include "detect-engine.h"
#include "flow-private.h"
#include "flow-util.h"
/**
* \brief UTHBuildPacketReal is a function that create tcp/udp packets for unittests
@ -586,7 +589,6 @@ int UTHPacketMatchSigMpm(Packet *p, char *sig, uint16_t mpm_type) {
int result = 0;
DecodeThreadVars dtv;
ThreadVars th_v;
DetectEngineThreadCtx *det_ctx = NULL;

Loading…
Cancel
Save