mirror of https://github.com/OISF/suricata
You cannot select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
1846 lines
54 KiB
C
1846 lines
54 KiB
C
/** Copyright (c) 2009 Open Information Security Foundation.
|
|
* \author Victor Julien <victor@inliniac.net>
|
|
*/
|
|
|
|
#include "suricata-common.h"
|
|
#include "decode.h"
|
|
#include "detect.h"
|
|
#include "flow-var.h"
|
|
|
|
#include "util-cidr.h"
|
|
#include "util-unittest.h"
|
|
|
|
#include "detect.h"
|
|
#include "detect-parse.h"
|
|
#include "detect-engine.h"
|
|
#include "detect-engine-address.h"
|
|
#include "detect-engine-mpm.h"
|
|
#include "detect-engine-siggroup.h"
|
|
|
|
#include "detect-content.h"
|
|
#include "detect-uricontent.h"
|
|
|
|
#include "util-hash.h"
|
|
#include "util-hashlist.h"
|
|
|
|
#include "util-error.h"
|
|
#include "util-debug.h"
|
|
|
|
/* prototypes */
|
|
int SigGroupHeadClearSigs(SigGroupHead *);
|
|
|
|
static uint32_t detect_siggroup_head_memory = 0;
|
|
static uint32_t detect_siggroup_head_init_cnt = 0;
|
|
static uint32_t detect_siggroup_head_free_cnt = 0;
|
|
static uint32_t detect_siggroup_head_initdata_memory = 0;
|
|
static uint32_t detect_siggroup_head_initdata_init_cnt = 0;
|
|
static uint32_t detect_siggroup_head_initdata_free_cnt = 0;
|
|
static uint32_t detect_siggroup_sigarray_memory = 0;
|
|
static uint32_t detect_siggroup_sigarray_init_cnt = 0;
|
|
static uint32_t detect_siggroup_sigarray_free_cnt = 0;
|
|
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 = malloc(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) {
|
|
free(sghid->content_array);
|
|
sghid->content_array = NULL;
|
|
sghid->content_size = 0;
|
|
}
|
|
if (sghid->uri_content_array != NULL) {
|
|
free(sghid->uri_content_array);
|
|
sghid->uri_content_array = NULL;
|
|
sghid->uri_content_size = 0;
|
|
}
|
|
free(sghid);
|
|
|
|
detect_siggroup_head_initdata_free_cnt++;
|
|
detect_siggroup_head_initdata_memory -= sizeof(SigGroupHeadInitData);
|
|
}
|
|
|
|
/**
|
|
* \brief Alloc a SigGroupHead and its signature bit_array.
|
|
*
|
|
* \param size Size of the sig_array that has to be created for this
|
|
* SigGroupHead.
|
|
*
|
|
* \retval sgh Pointer to the newly init SigGroupHead on success; or NULL in
|
|
* case of error.
|
|
*/
|
|
static SigGroupHead *SigGroupHeadAlloc(uint32_t size)
|
|
{
|
|
SigGroupHead *sgh = malloc(sizeof(SigGroupHead));
|
|
if (sgh == NULL) {
|
|
SCLogError(SC_ERR_MEM_ALLOC, "Error allocating memory");
|
|
return NULL;
|
|
}
|
|
memset(sgh, 0, sizeof(SigGroupHead));
|
|
|
|
sgh->init = SigGroupHeadInitDataAlloc(size);
|
|
if (sgh->init == NULL)
|
|
goto error;
|
|
|
|
detect_siggroup_head_init_cnt++;
|
|
detect_siggroup_head_memory += sizeof(SigGroupHead);
|
|
|
|
/* initialize the signature bitarray */
|
|
sgh->sig_size = size;
|
|
if ( (sgh->sig_array = malloc(sgh->sig_size)) == NULL) {
|
|
SCLogError(SC_ERR_MEM_ALLOC, "Error allocating memory");
|
|
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:
|
|
if (sgh != NULL)
|
|
SigGroupHeadFree(sgh);
|
|
return NULL;
|
|
}
|
|
|
|
/**
|
|
* \brief Free a SigGroupHead and its members.
|
|
*
|
|
* \param sgh Pointer to the SigGroupHead that has to be freed.
|
|
*/
|
|
void SigGroupHeadFree(SigGroupHead *sgh)
|
|
{
|
|
if (sgh == NULL)
|
|
return;
|
|
|
|
SCLogDebug("sgh %p", sgh);
|
|
|
|
PatternMatchDestroyGroup(sgh);
|
|
|
|
if (sgh->sig_array != NULL) {
|
|
free(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(SigIntId));
|
|
free(sgh->match_array);
|
|
sgh->match_array = NULL;
|
|
sgh->sig_cnt = 0;
|
|
}
|
|
|
|
if (sgh->init != NULL) {
|
|
SigGroupHeadInitDataFree(sgh->init);
|
|
}
|
|
|
|
free(sgh);
|
|
|
|
detect_siggroup_head_free_cnt++;
|
|
detect_siggroup_head_memory -= sizeof(SigGroupHead);
|
|
|
|
return;
|
|
}
|
|
|
|
/**
|
|
* \brief The hash function to be the used by the mpm SigGroupHead hash table -
|
|
* DetectEngineCtx->sgh_mpm_hash_table.
|
|
*
|
|
* \param ht Pointer to the hash table.
|
|
* \param data Pointer to the SigGroupHead.
|
|
* \param datalen Not used in our case.
|
|
*
|
|
* \retval hash The generated hash value.
|
|
*/
|
|
uint32_t SigGroupHeadMpmHashFunc(HashListTable *ht, void *data, uint16_t datalen)
|
|
{
|
|
SigGroupHead *sgh = (SigGroupHead *)data;
|
|
uint32_t hash = 0;
|
|
uint32_t b = 0;
|
|
|
|
for (b = 0; b < sgh->init->content_size; b++)
|
|
hash += sgh->init->content_array[b];
|
|
|
|
return hash % ht->array_size;
|
|
}
|
|
|
|
/**
|
|
* \brief The Compare function to be used by the mpm SigGroupHead hash table -
|
|
* DetectEngineCtx->sgh_mpm_hash_table.
|
|
*
|
|
* \param data1 Pointer to the first SigGroupHead.
|
|
* \param len1 Not used.
|
|
* \param data2 Pointer to the second SigGroupHead.
|
|
* \param len2 Not used.
|
|
*
|
|
* \retval 1 If the 2 SigGroupHeads sent as args match.
|
|
* \retval 0 If the 2 SigGroupHeads sent as args do not match.
|
|
*/
|
|
char SigGroupHeadMpmCompareFunc(void *data1, uint16_t len1, void *data2,
|
|
uint16_t len2)
|
|
{
|
|
SigGroupHead *sgh1 = (SigGroupHead *)data1;
|
|
SigGroupHead *sgh2 = (SigGroupHead *)data2;
|
|
|
|
if (sgh1->init->content_size != sgh2->init->content_size)
|
|
return 0;
|
|
|
|
if (memcmp(sgh1->init->content_array, sgh2->init->content_array,
|
|
sgh1->init->content_size) != 0) {
|
|
return 0;
|
|
}
|
|
|
|
return 1;
|
|
}
|
|
|
|
/**
|
|
* \brief Initializes the SigGroupHead mpm hash table to be used by the detection
|
|
* engine context.
|
|
*
|
|
* \param de_ctx Pointer to the detection engine context.
|
|
*
|
|
* \retval 0 On success.
|
|
* \retval -1 On failure.
|
|
*/
|
|
int SigGroupHeadMpmHashInit(DetectEngineCtx *de_ctx)
|
|
{
|
|
de_ctx->sgh_mpm_hash_table = HashListTableInit(4096, SigGroupHeadMpmHashFunc,
|
|
SigGroupHeadMpmCompareFunc,
|
|
NULL);
|
|
|
|
if (de_ctx->sgh_mpm_hash_table == NULL)
|
|
goto error;
|
|
|
|
return 0;
|
|
|
|
error:
|
|
return -1;
|
|
}
|
|
|
|
/**
|
|
* \brief Adds a SigGroupHead to the detection engine context SigGroupHead
|
|
* mpm hash table.
|
|
*
|
|
* \param de_ctx Pointer to the detection engine context.
|
|
* \param sgh Pointer to the SigGroupHead.
|
|
*
|
|
* \retval ret 0 on Successfully adding the argument sgh; -1 on failure.
|
|
*/
|
|
int SigGroupHeadMpmHashAdd(DetectEngineCtx *de_ctx, SigGroupHead *sgh)
|
|
{
|
|
int ret = HashListTableAdd(de_ctx->sgh_mpm_hash_table, (void *)sgh, 0);
|
|
|
|
return ret;
|
|
}
|
|
|
|
/**
|
|
* \brief Used to lookup a SigGroupHead from the detection engine context
|
|
* SigGroupHead mpm hash table.
|
|
*
|
|
* \param de_ctx Pointer to the detection engine context.
|
|
* \param sgh Pointer to the SigGroupHead.
|
|
*
|
|
* \retval rsgh On success a pointer to the SigGroupHead if the SigGroupHead is
|
|
* found in the hash table; NULL on failure.
|
|
*/
|
|
SigGroupHead *SigGroupHeadMpmHashLookup(DetectEngineCtx *de_ctx,
|
|
SigGroupHead *sgh)
|
|
{
|
|
SigGroupHead *rsgh = HashListTableLookup(de_ctx->sgh_mpm_hash_table,
|
|
(void *)sgh, 0);
|
|
|
|
return rsgh;
|
|
}
|
|
|
|
/**
|
|
* \brief Frees the hash table - DetectEngineCtx->sgh_mpm_hash_table, allocated by
|
|
* SigGroupHeadMpmHashInit() function.
|
|
*
|
|
* \param de_ctx Pointer to the detection engine context.
|
|
*/
|
|
void SigGroupHeadMpmHashFree(DetectEngineCtx *de_ctx)
|
|
{
|
|
if (de_ctx->sgh_mpm_hash_table == NULL)
|
|
return;
|
|
|
|
HashListTableFree(de_ctx->sgh_mpm_hash_table);
|
|
de_ctx->sgh_mpm_hash_table = NULL;
|
|
|
|
return;
|
|
}
|
|
|
|
/**
|
|
* \brief The hash function to be the used by the mpm uri SigGroupHead hash
|
|
* table - DetectEngineCtx->sgh_mpm_uri_hash_table.
|
|
*
|
|
* \param ht Pointer to the hash table.
|
|
* \param data Pointer to the SigGroupHead.
|
|
* \param datalen Not used in our case.
|
|
*
|
|
* \retval hash The generated hash value.
|
|
*/
|
|
uint32_t SigGroupHeadMpmUriHashFunc(HashListTable *ht, void *data, uint16_t datalen)
|
|
{
|
|
SigGroupHead *sgh = (SigGroupHead *)data;
|
|
uint32_t hash = 0;
|
|
uint32_t b = 0;
|
|
|
|
for (b = 0; b < sgh->init->uri_content_size; b++)
|
|
hash += sgh->init->uri_content_array[b];
|
|
|
|
return hash % ht->array_size;
|
|
}
|
|
|
|
/**
|
|
* \brief The Compare function to be used by the mpm uri SigGroupHead hash
|
|
* table - DetectEngineCtx->sgh_mpm_uri_hash_table.
|
|
*
|
|
* \param data1 Pointer to the first SigGroupHead.
|
|
* \param len1 Not used.
|
|
* \param data2 Pointer to the second SigGroupHead.
|
|
* \param len2 Not used.
|
|
*
|
|
* \retval 1 If the 2 SigGroupHeads sent as args match.
|
|
* \retval 0 If the 2 SigGroupHeads sent as args do not match.
|
|
*/
|
|
char SigGroupHeadMpmUriCompareFunc(void *data1, uint16_t len1, void *data2,
|
|
uint16_t len2)
|
|
{
|
|
SigGroupHead *sgh1 = (SigGroupHead *)data1;
|
|
SigGroupHead *sgh2 = (SigGroupHead *)data2;
|
|
|
|
if (sgh1->init->uri_content_size != sgh2->init->uri_content_size)
|
|
return 0;
|
|
|
|
if (memcmp(sgh1->init->uri_content_array, sgh2->init->uri_content_array,
|
|
sgh1->init->uri_content_size) != 0) {
|
|
return 0;
|
|
}
|
|
|
|
return 1;
|
|
}
|
|
|
|
/**
|
|
* \brief Initializes the mpm uri hash table to be used by the detection engine
|
|
* context.
|
|
*
|
|
* \param de_ctx Pointer to the detection engine context.
|
|
*
|
|
* \retval 0 On success.
|
|
* \retval -1 On failure.
|
|
*/
|
|
int SigGroupHeadMpmUriHashInit(DetectEngineCtx *de_ctx)
|
|
{
|
|
de_ctx->sgh_mpm_uri_hash_table = HashListTableInit(4096,
|
|
SigGroupHeadMpmUriHashFunc,
|
|
SigGroupHeadMpmUriCompareFunc,
|
|
NULL);
|
|
if (de_ctx->sgh_mpm_uri_hash_table == NULL)
|
|
goto error;
|
|
|
|
return 0;
|
|
|
|
error:
|
|
return -1;
|
|
}
|
|
|
|
/**
|
|
* \brief Adds a SigGroupHead to the detection engine context SigGroupHead
|
|
* mpm uri hash table.
|
|
*
|
|
* \param de_ctx Pointer to the detection engine context.
|
|
* \param sgh Pointer to the SigGroupHead.
|
|
*
|
|
* \retval ret 0 on Successfully adding the argument sgh and -1 on failure.
|
|
*/
|
|
int SigGroupHeadMpmUriHashAdd(DetectEngineCtx *de_ctx, SigGroupHead *sgh)
|
|
{
|
|
int ret = HashListTableAdd(de_ctx->sgh_mpm_uri_hash_table, (void *)sgh, 0);
|
|
|
|
return ret;
|
|
}
|
|
|
|
/**
|
|
* \brief Used to lookup a SigGroupHead from the detection engine context
|
|
* SigGroupHead mpm uri hash table.
|
|
*
|
|
* \param de_ctx Pointer to the detection engine context.
|
|
* \param sgh Pointer to the SigGroupHead.
|
|
*
|
|
* \retval rsgh On success a pointer to the SigGroupHead if the SigGroupHead is
|
|
* found in the hash table; NULL on failure.
|
|
*/
|
|
SigGroupHead *SigGroupHeadMpmUriHashLookup(DetectEngineCtx *de_ctx,
|
|
SigGroupHead *sgh)
|
|
{
|
|
SigGroupHead *rsgh = HashListTableLookup(de_ctx->sgh_mpm_uri_hash_table,
|
|
(void *)sgh, 0);
|
|
|
|
return rsgh;
|
|
}
|
|
|
|
/**
|
|
* \brief Frees the hash table - DetectEngineCtx->sgh_mpm_uri_hash_table,
|
|
* allocated by SigGroupHeadMpmUriHashInit() function.
|
|
*
|
|
* \param de_ctx Pointer to the detection engine context.
|
|
*/
|
|
void SigGroupHeadMpmUriHashFree(DetectEngineCtx *de_ctx)
|
|
{
|
|
if (de_ctx->sgh_mpm_uri_hash_table == NULL)
|
|
return;
|
|
|
|
HashListTableFree(de_ctx->sgh_mpm_uri_hash_table);
|
|
de_ctx->sgh_mpm_uri_hash_table = NULL;
|
|
|
|
return;
|
|
}
|
|
|
|
/**
|
|
* \brief The hash function to be the used by the hash table -
|
|
* DetectEngineCtx->sgh_hash_table.
|
|
*
|
|
* \param ht Pointer to the hash table.
|
|
* \param data Pointer to the SigGroupHead.
|
|
* \param datalen Not used in our case.
|
|
*
|
|
* \retval hash The generated hash value.
|
|
*/
|
|
uint32_t SigGroupHeadHashFunc(HashListTable *ht, void *data, uint16_t datalen)
|
|
{
|
|
SigGroupHead *sgh = (SigGroupHead *)data;
|
|
uint32_t hash = 0;
|
|
uint32_t b = 0;
|
|
|
|
SCLogDebug("hashing sgh %p", sgh);
|
|
|
|
for (b = 0; b < sgh->sig_size; b++)
|
|
hash += sgh->sig_array[b];
|
|
|
|
hash %= ht->array_size;
|
|
SCLogDebug("hash %"PRIu32" (sig_size %"PRIu32")", hash, sgh->sig_size);
|
|
return hash;
|
|
}
|
|
|
|
/**
|
|
* \brief The Compare function to be used by the SigGroupHead hash table -
|
|
* DetectEngineCtx->sgh_hash_table.
|
|
*
|
|
* \param data1 Pointer to the first SigGroupHead.
|
|
* \param len1 Not used.
|
|
* \param data2 Pointer to the second SigGroupHead.
|
|
* \param len2 Not used.
|
|
*
|
|
* \retval 1 If the 2 SigGroupHeads sent as args match.
|
|
* \retval 0 If the 2 SigGroupHeads sent as args do not match.
|
|
*/
|
|
char SigGroupHeadCompareFunc(void *data1, uint16_t len1, void *data2,
|
|
uint16_t len2)
|
|
{
|
|
SigGroupHead *sgh1 = (SigGroupHead *)data1;
|
|
SigGroupHead *sgh2 = (SigGroupHead *)data2;
|
|
|
|
if (data1 == NULL || data2 == NULL)
|
|
return 0;
|
|
|
|
if (sgh1->sig_size != sgh2->sig_size)
|
|
return 0;
|
|
|
|
if (memcmp(sgh1->sig_array, sgh2->sig_array, sgh1->sig_size) != 0)
|
|
return 0;
|
|
|
|
return 1;
|
|
}
|
|
|
|
/**
|
|
* \brief Initializes the hash table in the detection engine context to hold the
|
|
* SigGroupHeads.
|
|
*
|
|
* \param de_ctx Pointer to the detection engine context.
|
|
*
|
|
* \retval 0 On success.
|
|
* \retval -1 On failure.
|
|
*/
|
|
int SigGroupHeadHashInit(DetectEngineCtx *de_ctx)
|
|
{
|
|
de_ctx->sgh_hash_table = HashListTableInit(4096, SigGroupHeadHashFunc,
|
|
SigGroupHeadCompareFunc, NULL);
|
|
if (de_ctx->sgh_hash_table == NULL)
|
|
goto error;
|
|
|
|
return 0;
|
|
|
|
error:
|
|
return -1;
|
|
}
|
|
|
|
/**
|
|
* \brief Adds a SigGroupHead to the detection engine context SigGroupHead
|
|
* hash table.
|
|
*
|
|
* \param de_ctx Pointer to the detection engine context.
|
|
* \param sgh Pointer to the SigGroupHead.
|
|
*
|
|
* \retval ret 0 on Successfully adding the SigGroupHead; -1 on failure.
|
|
*/
|
|
int SigGroupHeadHashAdd(DetectEngineCtx *de_ctx, SigGroupHead *sgh)
|
|
{
|
|
int ret = HashListTableAdd(de_ctx->sgh_hash_table, (void *)sgh, 0);
|
|
|
|
return ret;
|
|
}
|
|
|
|
int SigGroupHeadHashRemove(DetectEngineCtx *de_ctx, SigGroupHead *sgh) {
|
|
return HashListTableRemove(de_ctx->sgh_hash_table, (void *)sgh, 0);
|
|
}
|
|
|
|
/**
|
|
* \brief Used to lookup a SigGroupHead hash from the detection engine context
|
|
* SigGroupHead hash table.
|
|
*
|
|
* \param de_ctx Pointer to the detection engine context.
|
|
* \param sgh Pointer to the SigGroupHead.
|
|
*
|
|
* \retval rsgh On success a pointer to the SigGroupHead if the SigGroupHead is
|
|
* found in the hash table; NULL on failure.
|
|
*/
|
|
SigGroupHead *SigGroupHeadHashLookup(DetectEngineCtx *de_ctx, SigGroupHead *sgh)
|
|
{
|
|
SigGroupHead *rsgh = HashListTableLookup(de_ctx->sgh_hash_table,
|
|
(void *)sgh, 0);
|
|
|
|
return rsgh;
|
|
}
|
|
|
|
/**
|
|
* \brief Frees the hash table - DetectEngineCtx->sgh_hash_table, allocated by
|
|
* SigGroupHeadHashInit() function.
|
|
*
|
|
* \param de_ctx Pointer to the detection engine context.
|
|
*/
|
|
void SigGroupHeadHashFree(DetectEngineCtx *de_ctx)
|
|
{
|
|
if (de_ctx->sgh_hash_table == NULL)
|
|
return;
|
|
|
|
HashListTableFree(de_ctx->sgh_hash_table);
|
|
de_ctx->sgh_hash_table = NULL;
|
|
|
|
return;
|
|
}
|
|
|
|
/**
|
|
* \brief Initializes the dport based SigGroupHead hash table to hold the
|
|
* SigGroupHeads. The hash table that would be initialized is
|
|
* DetectEngineCtx->sgh_dport_hash_table.
|
|
*
|
|
* \param de_ctx Pointer to the detection engine context.
|
|
*
|
|
* \retval 0 On success.
|
|
* \retval -1 On failure.
|
|
*/
|
|
int SigGroupHeadDPortHashInit(DetectEngineCtx *de_ctx)
|
|
{
|
|
de_ctx->sgh_dport_hash_table = HashListTableInit(4096, SigGroupHeadHashFunc,
|
|
SigGroupHeadCompareFunc,
|
|
NULL);
|
|
if (de_ctx->sgh_dport_hash_table == NULL)
|
|
goto error;
|
|
|
|
return 0;
|
|
|
|
error:
|
|
return -1;
|
|
}
|
|
|
|
/**
|
|
* \brief Adds a SigGroupHead to the detection engine context dport based
|
|
* SigGroupHead hash table(DetectEngineCtx->sgh_dport_hash_table).
|
|
*
|
|
* \param de_ctx Pointer to the detection engine context.
|
|
* \param sgh Pointer to the SigGroupHead.
|
|
*
|
|
* \retval ret 0 on Successfully adding the argument sgh and -1 on failure.
|
|
*/
|
|
int SigGroupHeadDPortHashAdd(DetectEngineCtx *de_ctx, SigGroupHead *sgh)
|
|
{
|
|
int ret = HashListTableAdd(de_ctx->sgh_dport_hash_table, (void *)sgh, 0);
|
|
|
|
return ret;
|
|
}
|
|
|
|
/**
|
|
* \brief Used to lookup a SigGroupHead hash from the detection engine ctx dport
|
|
* based SigGroupHead hash table(DetectEngineCtx->sgh_dport_hash_table).
|
|
*
|
|
* \param de_ctx Pointer to the detection engine context.
|
|
* \param sgh Pointer to the SigGroupHead.
|
|
*
|
|
* \retval rsgh On success a pointer to the SigGroupHead if the SigGroupHead is
|
|
* found in the hash table; NULL on failure.
|
|
*/
|
|
SigGroupHead *SigGroupHeadDPortHashLookup(DetectEngineCtx *de_ctx,
|
|
SigGroupHead *sgh)
|
|
{
|
|
SigGroupHead *rsgh = HashListTableLookup(de_ctx->sgh_dport_hash_table,
|
|
(void *)sgh, 0);
|
|
|
|
return rsgh;
|
|
}
|
|
|
|
/**
|
|
* \brief Frees the hash table - DetectEngineCtx->sgh_dport_hash_table,
|
|
* allocated by the SigGroupHeadDPortHashInit() function.
|
|
*
|
|
* \param de_ctx Pointer to the detection engine context.
|
|
*/
|
|
void SigGroupHeadDPortHashFree(DetectEngineCtx *de_ctx)
|
|
{
|
|
if (de_ctx->dport_hash_table == NULL)
|
|
return;
|
|
|
|
HashListTableFree(de_ctx->sgh_dport_hash_table);
|
|
de_ctx->sgh_dport_hash_table = NULL;
|
|
|
|
return;
|
|
}
|
|
|
|
/**
|
|
* \brief Initializes the sport based SigGroupHead hash table to hold the
|
|
* SigGroupHeads. The hash table that would be initialized is
|
|
* DetectEngineCtx->sgh_sport_hash_table.
|
|
*
|
|
* \param de_ctx Pointer to the detection engine context.
|
|
*
|
|
* \retval 0 On success.
|
|
* \retval -1 On failure.
|
|
*/
|
|
int SigGroupHeadSPortHashInit(DetectEngineCtx *de_ctx)
|
|
{
|
|
de_ctx->sgh_sport_hash_table = HashListTableInit(4096,
|
|
SigGroupHeadHashFunc,
|
|
SigGroupHeadCompareFunc,
|
|
NULL);
|
|
if (de_ctx->sgh_sport_hash_table == NULL)
|
|
goto error;
|
|
|
|
return 0;
|
|
|
|
error:
|
|
return -1;
|
|
}
|
|
|
|
/**
|
|
* \brief Adds a SigGroupHead to the detection engine context dport based
|
|
* SigGroupHead hash table(DetectEngineCtx->sgh_sport_hash_table).
|
|
*
|
|
* \param de_ctx Pointer to the detection engine context.
|
|
* \param sgh Pointer to the SigGroupHead.
|
|
*
|
|
* \retval ret 0 on Successfully adding the argument sgh and -1 on failure.
|
|
*/
|
|
int SigGroupHeadSPortHashAdd(DetectEngineCtx *de_ctx, SigGroupHead *sgh)
|
|
{
|
|
int ret = HashListTableAdd(de_ctx->sgh_sport_hash_table, (void *)sgh, 0);
|
|
|
|
return ret;
|
|
}
|
|
|
|
int SigGroupHeadSPortHashRemove(DetectEngineCtx *de_ctx, SigGroupHead *sgh) {
|
|
return HashListTableRemove(de_ctx->sgh_sport_hash_table, (void *)sgh, 0);
|
|
}
|
|
|
|
/**
|
|
* \brief Used to lookup a SigGroupHead hash from the detection engine ctx sport
|
|
* based SigGroupHead hash table(DetectEngineCtx->sgh_dport_hash_table).
|
|
*
|
|
* \param de_ctx Pointer to the detection engine context.
|
|
* \param sgh Pointer to the SigGroupHead.
|
|
*
|
|
* \retval rsgh On success a pointer to the SigGroupHead if the SigGroupHead is
|
|
* found in the hash table; NULL on failure.
|
|
*/
|
|
SigGroupHead *SigGroupHeadSPortHashLookup(DetectEngineCtx *de_ctx,
|
|
SigGroupHead *sgh)
|
|
{
|
|
SigGroupHead *rsgh = HashListTableLookup(de_ctx->sgh_sport_hash_table,
|
|
(void *)sgh, 0);
|
|
|
|
return rsgh;
|
|
}
|
|
|
|
/**
|
|
* \brief Frees the hash table - DetectEngineCtx->sgh_sport_hash_table,
|
|
* allocated by the SigGroupHeadSPortHashInit() function.
|
|
*
|
|
* \param de_ctx Pointer to the detection engine context.
|
|
*/
|
|
void SigGroupHeadSPortHashFree(DetectEngineCtx *de_ctx)
|
|
{
|
|
if (de_ctx->sport_hash_table == NULL)
|
|
return;
|
|
|
|
HashListTableFree(de_ctx->sgh_sport_hash_table);
|
|
de_ctx->sgh_sport_hash_table = NULL;
|
|
|
|
return;
|
|
}
|
|
|
|
/**
|
|
* \brief Used to free the signature array, content_array and uri_content_array
|
|
* members from the SigGroupHeads in the HashListTable.
|
|
*
|
|
* \param de_ctx Pointer to the detection engine context.
|
|
* \param ht Pointer to the HashListTable
|
|
*/
|
|
static void SigGroupHeadFreeSigArraysHash2(DetectEngineCtx *de_ctx,
|
|
HashListTable *ht)
|
|
{
|
|
HashListTableBucket *htb = NULL;
|
|
SigGroupHead *sgh = NULL;
|
|
|
|
for (htb = HashListTableGetListHead(ht);
|
|
htb != NULL;
|
|
htb = HashListTableGetListNext(htb)) {
|
|
sgh = (SigGroupHead *)HashListTableGetListData(htb);
|
|
|
|
if (sgh->sig_array != NULL) {
|
|
detect_siggroup_sigarray_free_cnt++;
|
|
detect_siggroup_sigarray_memory -= sgh->sig_size;
|
|
|
|
free(sgh->sig_array);
|
|
sgh->sig_array = NULL;
|
|
sgh->sig_size = 0;
|
|
}
|
|
|
|
if (sgh->init != NULL) {
|
|
SigGroupHeadInitDataFree(sgh->init);
|
|
sgh->init = NULL;
|
|
}
|
|
}
|
|
|
|
return;
|
|
}
|
|
|
|
/**
|
|
* \brief Used to free the sig_array member of the SigGroupHeads present
|
|
* in the HashListTable.
|
|
*
|
|
* \param de_ctx Pointer to the detection engine context.
|
|
* \param ht Pointer to the HashListTable
|
|
*/
|
|
static void SigGroupHeadFreeSigArraysHash(DetectEngineCtx *de_ctx,
|
|
HashListTable *ht)
|
|
{
|
|
HashListTableBucket *htb = NULL;
|
|
SigGroupHead *sgh = NULL;
|
|
|
|
for (htb = HashListTableGetListHead(ht);
|
|
htb != NULL;
|
|
htb = HashListTableGetListNext(htb)) {
|
|
sgh = (SigGroupHead *)HashListTableGetListData(htb);
|
|
|
|
if (sgh->sig_array != NULL) {
|
|
detect_siggroup_sigarray_free_cnt++;
|
|
detect_siggroup_sigarray_memory -= sgh->sig_size;
|
|
|
|
free(sgh->sig_array);
|
|
sgh->sig_array = NULL;
|
|
sgh->sig_size = 0;
|
|
}
|
|
|
|
if (sgh->init != NULL) {
|
|
SigGroupHeadInitDataFree(sgh->init);
|
|
sgh->init = NULL;
|
|
}
|
|
}
|
|
|
|
return;
|
|
}
|
|
|
|
/**
|
|
* \brief Free the sigarrays in the sgh's. Those are only used during the init
|
|
* stage.
|
|
*
|
|
* \param de_ctx Pointer to the detection engine context whose sigarrays have to
|
|
* be freed.
|
|
*/
|
|
void SigGroupHeadFreeSigArrays(DetectEngineCtx *de_ctx)
|
|
{
|
|
SigGroupHeadFreeSigArraysHash2(de_ctx, de_ctx->sgh_hash_table);
|
|
SigGroupHeadFreeSigArraysHash(de_ctx, de_ctx->sgh_dport_hash_table);
|
|
SigGroupHeadFreeSigArraysHash(de_ctx, de_ctx->sgh_sport_hash_table);
|
|
|
|
return;
|
|
}
|
|
|
|
/**
|
|
* \brief Free the mpm arrays that are only used during the init stage.
|
|
*
|
|
* \param de_ctx Pointer to the detection engine context.
|
|
*/
|
|
void SigGroupHeadFreeMpmArrays(DetectEngineCtx *de_ctx)
|
|
{
|
|
HashListTableBucket *htb = NULL;
|
|
SigGroupHead *sgh = NULL;
|
|
|
|
for (htb = HashListTableGetListHead(de_ctx->sgh_dport_hash_table); htb != NULL; htb = HashListTableGetListNext(htb)) {
|
|
sgh = (SigGroupHead *)HashListTableGetListData(htb);
|
|
if (sgh->init != NULL) {
|
|
SigGroupHeadInitDataFree(sgh->init);
|
|
sgh->init = NULL;
|
|
}
|
|
}
|
|
|
|
for (htb = HashListTableGetListHead(de_ctx->sgh_sport_hash_table); htb != NULL; htb = HashListTableGetListNext(htb)) {
|
|
sgh = (SigGroupHead *)HashListTableGetListData(htb);
|
|
if (sgh->init != NULL) {
|
|
SigGroupHeadInitDataFree(sgh->init);
|
|
sgh->init = NULL;
|
|
}
|
|
}
|
|
|
|
return;
|
|
}
|
|
|
|
/**
|
|
* \brief Add a Signature to a SigGroupHead.
|
|
*
|
|
* \param de_ctx Pointer to the detection engine context.
|
|
* \param sgh Pointer to a SigGroupHead. Can be NULL also.
|
|
* \param s Pointer to the Signature that has to be added to the
|
|
* SigGroupHead.
|
|
*
|
|
* \retval 0 On success.
|
|
* \retval -1 On failure.
|
|
*/
|
|
int SigGroupHeadAppendSig(DetectEngineCtx *de_ctx, SigGroupHead **sgh,
|
|
Signature *s)
|
|
{
|
|
if (de_ctx == NULL)
|
|
return 0;
|
|
|
|
/* see if we have a head already */
|
|
if (*sgh == NULL) {
|
|
*sgh = SigGroupHeadAlloc(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);
|
|
|
|
/* update maxlen for mpm */
|
|
if (s->flags & SIG_FLAG_MPM) {
|
|
/* check with the precalculated values from the sig */
|
|
if (s->mpm_content_maxlen > 0) {
|
|
if ((*sgh)->mpm_content_maxlen == 0)
|
|
(*sgh)->mpm_content_maxlen = s->mpm_content_maxlen;
|
|
|
|
if ((*sgh)->mpm_content_maxlen > s->mpm_content_maxlen)
|
|
(*sgh)->mpm_content_maxlen = s->mpm_content_maxlen;
|
|
}
|
|
if (s->mpm_uricontent_maxlen > 0) {
|
|
if ((*sgh)->mpm_uricontent_maxlen == 0)
|
|
(*sgh)->mpm_uricontent_maxlen = s->mpm_uricontent_maxlen;
|
|
|
|
if ((*sgh)->mpm_uricontent_maxlen > s->mpm_uricontent_maxlen)
|
|
(*sgh)->mpm_uricontent_maxlen = s->mpm_uricontent_maxlen;
|
|
}
|
|
}
|
|
return 0;
|
|
|
|
error:
|
|
return -1;
|
|
}
|
|
|
|
/**
|
|
* \brief Clears the bitarray holding the sids for this SigGroupHead.
|
|
*
|
|
* \param sgh Pointer to the SigGroupHead.
|
|
*
|
|
* \retval 0 Always.
|
|
*/
|
|
int SigGroupHeadClearSigs(SigGroupHead *sgh)
|
|
{
|
|
if (sgh == NULL)
|
|
return 0;
|
|
|
|
if (sgh->sig_array != NULL)
|
|
memset(sgh->sig_array, 0, sgh->sig_size);
|
|
|
|
sgh->sig_cnt = 0;
|
|
|
|
return 0;
|
|
}
|
|
|
|
/**
|
|
* \brief Copies the bitarray holding the sids from the source SigGroupHead to
|
|
* the destination SigGroupHead.
|
|
*
|
|
* \param de_ctx Pointer to the detection engine context.
|
|
* \param src Pointer to the source SigGroupHead.
|
|
* \param dst Pointer to the destination SigGroupHead.
|
|
*
|
|
* \retval 0 On success.
|
|
* \retval -1 On failure.
|
|
*/
|
|
int SigGroupHeadCopySigs(DetectEngineCtx *de_ctx, SigGroupHead *src, SigGroupHead **dst)
|
|
{
|
|
uint32_t idx = 0;
|
|
|
|
if (src == NULL || de_ctx == NULL)
|
|
return 0;
|
|
|
|
if (*dst == NULL) {
|
|
*dst = SigGroupHeadAlloc(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];
|
|
|
|
if (src->mpm_content_maxlen != 0) {
|
|
if ((*dst)->mpm_content_maxlen == 0)
|
|
(*dst)->mpm_content_maxlen = src->mpm_content_maxlen;
|
|
|
|
if ((*dst)->mpm_content_maxlen > src->mpm_content_maxlen)
|
|
(*dst)->mpm_content_maxlen = src->mpm_content_maxlen;
|
|
|
|
SCLogDebug("src (%p)->mpm_content_maxlen %u", src, src->mpm_content_maxlen);
|
|
SCLogDebug("dst (%p)->mpm_content_maxlen %u", (*dst), (*dst)->mpm_content_maxlen);
|
|
BUG_ON((*dst)->mpm_content_maxlen == 0);
|
|
}
|
|
if (src->mpm_uricontent_maxlen != 0) {
|
|
if ((*dst)->mpm_uricontent_maxlen == 0)
|
|
(*dst)->mpm_uricontent_maxlen = src->mpm_uricontent_maxlen;
|
|
|
|
if ((*dst)->mpm_uricontent_maxlen > src->mpm_uricontent_maxlen)
|
|
(*dst)->mpm_uricontent_maxlen = src->mpm_uricontent_maxlen;
|
|
}
|
|
return 0;
|
|
|
|
error:
|
|
return -1;
|
|
}
|
|
|
|
/**
|
|
* \brief Updates the SigGroupHead->sig_cnt with the total count of all the
|
|
* Signatures present in this SigGroupHead.
|
|
*
|
|
* \param sgh Pointer to the SigGroupHead.
|
|
* \param max_idx Maximum sid of the all the Signatures present in this
|
|
* SigGroupHead.
|
|
*/
|
|
void SigGroupHeadSetSigCnt(SigGroupHead *sgh, uint32_t max_idx)
|
|
{
|
|
uint32_t sig;
|
|
|
|
for (sig = 0; sig < max_idx + 1; sig++) {
|
|
if (sgh->sig_array[sig / 8] & (1 << (sig % 8)))
|
|
sgh->sig_cnt++;
|
|
}
|
|
|
|
return;
|
|
}
|
|
|
|
/**
|
|
* \brief Prints the memory statistics for the detect-engine-siggroup.[ch] module.
|
|
*/
|
|
void DetectSigGroupPrintMemory(void)
|
|
{
|
|
SCLogDebug(" * Sig group head memory stats (SigGroupHead %" PRIuMAX "):",
|
|
(uintmax_t)sizeof(SigGroupHead));
|
|
SCLogDebug(" - detect_siggroup_head_memory %" PRIu32,
|
|
detect_siggroup_head_memory);
|
|
SCLogDebug(" - detect_siggroup_head_init_cnt %" PRIu32,
|
|
detect_siggroup_head_init_cnt);
|
|
SCLogDebug(" - detect_siggroup_head_free_cnt %" PRIu32,
|
|
detect_siggroup_head_free_cnt);
|
|
SCLogDebug(" - outstanding sig group heads %" PRIu32,
|
|
detect_siggroup_head_init_cnt - detect_siggroup_head_free_cnt);
|
|
SCLogDebug(" * Sig group head memory stats done");
|
|
SCLogDebug(" * Sig group head initdata memory stats (SigGroupHeadInitData %" PRIuMAX "):",
|
|
(uintmax_t)sizeof(SigGroupHeadInitData));
|
|
SCLogDebug(" - detect_siggroup_head_initdata_memory %" PRIu32,
|
|
detect_siggroup_head_initdata_memory);
|
|
SCLogDebug(" - detect_siggroup_head_initdata_init_cnt %" PRIu32,
|
|
detect_siggroup_head_initdata_init_cnt);
|
|
SCLogDebug(" - detect_siggroup_head_initdata_free_cnt %" PRIu32,
|
|
detect_siggroup_head_initdata_free_cnt);
|
|
SCLogDebug(" - outstanding sig group head initdatas %" PRIu32,
|
|
detect_siggroup_head_initdata_init_cnt - detect_siggroup_head_initdata_free_cnt);
|
|
SCLogDebug(" * Sig group head memory initdata stats done");
|
|
SCLogDebug(" * Sig group sigarray memory stats:");
|
|
SCLogDebug(" - detect_siggroup_sigarray_memory %" PRIu32,
|
|
detect_siggroup_sigarray_memory);
|
|
SCLogDebug(" - detect_siggroup_sigarray_init_cnt %" PRIu32,
|
|
detect_siggroup_sigarray_init_cnt);
|
|
SCLogDebug(" - detect_siggroup_sigarray_free_cnt %" PRIu32,
|
|
detect_siggroup_sigarray_free_cnt);
|
|
SCLogDebug(" - outstanding sig group sigarrays %" PRIu32,
|
|
(detect_siggroup_sigarray_init_cnt -
|
|
detect_siggroup_sigarray_free_cnt));
|
|
SCLogDebug(" * Sig group sigarray memory stats done");
|
|
SCLogDebug(" * Sig group matcharray memory stats:");
|
|
SCLogDebug(" - detect_siggroup_matcharray_memory %" PRIu32,
|
|
detect_siggroup_matcharray_memory);
|
|
SCLogDebug(" - detect_siggroup_matcharray_init_cnt %" PRIu32,
|
|
detect_siggroup_matcharray_init_cnt);
|
|
SCLogDebug(" - detect_siggroup_matcharray_free_cnt %" PRIu32,
|
|
detect_siggroup_matcharray_free_cnt);
|
|
SCLogDebug(" - outstanding sig group matcharrays %" PRIu32,
|
|
(detect_siggroup_matcharray_init_cnt -
|
|
detect_siggroup_matcharray_free_cnt));
|
|
SCLogDebug(" * Sig group sigarray memory stats done");
|
|
SCLogDebug(" X Total %" PRIu32,
|
|
(detect_siggroup_head_memory + detect_siggroup_sigarray_memory +
|
|
detect_siggroup_matcharray_memory));
|
|
|
|
return;
|
|
}
|
|
|
|
/**
|
|
* \brief Helper function used to print the list of sids for the Signatures
|
|
* present in this SigGroupHead.
|
|
*
|
|
* \param de_ctx Pointer to the detection engine context.
|
|
* \param sgh Pointer to the SigGroupHead.
|
|
*/
|
|
void SigGroupHeadPrintSigs(DetectEngineCtx *de_ctx, SigGroupHead *sgh)
|
|
{
|
|
SCEnter();
|
|
|
|
uint32_t i;
|
|
|
|
SCLogDebug("The Signatures present in this SigGroupHead are: ");
|
|
for (i = 0; i < sgh->sig_size; i++) {
|
|
if (sgh->sig_array[i / 8] & (1 << (i % 8)))
|
|
SCLogDebug("%" PRIu32, i);
|
|
}
|
|
|
|
SCReturn;
|
|
}
|
|
|
|
/**
|
|
* \brief Helper function used to print the content ids of all the contents that
|
|
* have been added to the bitarray of this SigGroupHead.
|
|
*
|
|
* \param de_ctx Pointer to the detection engine context.
|
|
* \param sgh Pointer to the SigGroupHead.
|
|
*/
|
|
void SigGroupHeadPrintContent(DetectEngineCtx *de_ctx, SigGroupHead *sgh)
|
|
{
|
|
SCEnter();
|
|
|
|
uint32_t i = 0;
|
|
|
|
SCLogDebug("Contents with the following content ids are present in this "
|
|
"SigGroupHead - ");
|
|
for (i = 0; i < DetectContentMaxId(de_ctx); i++) {
|
|
if (sgh->init->content_array[i / 8] & (1 << (i % 8)))
|
|
SCLogDebug("%" PRIu32, i);
|
|
}
|
|
|
|
SCReturn;
|
|
}
|
|
|
|
/**
|
|
* \brief Helper function used to print the total no of contents that have
|
|
* been added to the bitarray for this SigGroupHead.
|
|
*
|
|
* \param de_ctx Pointer to the detection engine context.
|
|
* \param sgh Pointer to the SigGroupHead.
|
|
*/
|
|
void SigGroupHeadPrintContentCnt(DetectEngineCtx *de_ctx, SigGroupHead *sgh)
|
|
{
|
|
SCEnter();
|
|
|
|
uint32_t i = 0;
|
|
uint32_t cnt = 0;
|
|
|
|
for (i = 0; i < DetectContentMaxId(de_ctx); i++) {
|
|
if (sgh->init->content_array[i / 8] & (1 << (i % 8)))
|
|
cnt++;
|
|
}
|
|
|
|
SCLogDebug("Total contents added to the SigGroupHead content bitarray: "
|
|
"%" PRIu32, cnt);
|
|
|
|
SCReturn;
|
|
}
|
|
|
|
/**
|
|
* \brief Loads all the content ids from all the contents belonging to all the
|
|
* Signatures in this SigGroupHead, into a bitarray. A fast and an
|
|
* efficient way of comparing pattern sets.
|
|
*
|
|
* \param de_ctx Pointer to the detection engine context.
|
|
* \param sgh Pointer to the SigGroupHead.
|
|
*
|
|
* \retval 0 On success, i.e. on either the detection engine context being NULL
|
|
* or on succesfully allocating memory and updating it with relevant
|
|
* data.
|
|
* \retval -1 On failure.
|
|
*/
|
|
int SigGroupHeadLoadContent(DetectEngineCtx *de_ctx, SigGroupHead *sgh)
|
|
{
|
|
Signature *s = NULL;
|
|
SigMatch *sm = NULL;
|
|
uint32_t sig = 0;
|
|
SigIntId num = 0;
|
|
DetectContentData *co = NULL;
|
|
|
|
if (sgh == NULL)
|
|
return 0;
|
|
|
|
if (DetectContentMaxId(de_ctx) == 0)
|
|
return 0;
|
|
|
|
BUG_ON(sgh->init == NULL);
|
|
|
|
sgh->init->content_size = (DetectContentMaxId(de_ctx) / 8) + 1;
|
|
sgh->init->content_array = malloc(sgh->init->content_size);
|
|
if (sgh->init->content_array == NULL)
|
|
return -1;
|
|
|
|
memset(sgh->init->content_array,0, sgh->init->content_size);
|
|
|
|
for (sig = 0; sig < sgh->sig_cnt; sig++) {
|
|
num = sgh->match_array[sig];
|
|
|
|
s = de_ctx->sig_array[num];
|
|
if (s == NULL)
|
|
continue;
|
|
|
|
if (!(s->flags & SIG_FLAG_MPM))
|
|
continue;
|
|
|
|
sm = s->match;
|
|
if (sm == NULL)
|
|
continue;
|
|
|
|
for ( ;sm != NULL; sm = sm->next) {
|
|
if (sm->type == DETECT_CONTENT) {
|
|
co = (DetectContentData *)sm->ctx;
|
|
|
|
sgh->init->content_array[co->id / 8] |= 1 << (co->id % 8);
|
|
}
|
|
}
|
|
}
|
|
|
|
return 0;
|
|
}
|
|
|
|
/**
|
|
* \brief Clears the memory allocated by SigGroupHeadLoadContent() for the
|
|
* bitarray to hold the content ids for a SigGroupHead.
|
|
*
|
|
* \param Pointer to the SigGroupHead whose content_array would to be cleared.
|
|
*
|
|
* \ret 0 Always.
|
|
*/
|
|
int SigGroupHeadClearContent(SigGroupHead *sh)
|
|
{
|
|
if (sh == NULL)
|
|
return 0;
|
|
|
|
if (sh->init->content_array != NULL) {
|
|
free(sh->init->content_array);
|
|
sh->init->content_array = NULL;
|
|
sh->init->content_size = 0;
|
|
}
|
|
return 0;
|
|
}
|
|
|
|
/**
|
|
* \brief Loads all the uri content ids from all the uri contents belonging to
|
|
* all the Signatures in this SigGroupHead, into a bitarray. A fast and
|
|
* an efficient way of comparing pattern sets.
|
|
*
|
|
* \param de_ctx Pointer to the detection engine context.
|
|
* \param sgh Pointer to the SigGroupHead.
|
|
*
|
|
* \retval 0 On success, i.e. on either the detection engine context being NULL
|
|
* or on succesfully allocating memory and updating it with relevant
|
|
* data.
|
|
* \retval -1 On failure.
|
|
*/
|
|
int SigGroupHeadLoadUricontent(DetectEngineCtx *de_ctx, SigGroupHead *sgh)
|
|
{
|
|
Signature *s = NULL;
|
|
SigMatch *sm = NULL;
|
|
uint32_t sig = 0;
|
|
SigIntId num = 0;
|
|
DetectUricontentData *co = NULL;
|
|
|
|
if (sgh == NULL)
|
|
return 0;
|
|
|
|
if (DetectUricontentMaxId(de_ctx) == 0)
|
|
return 0;
|
|
|
|
BUG_ON(sgh->init == NULL);
|
|
|
|
sgh->init->uri_content_size = (DetectUricontentMaxId(de_ctx) / 8) + 1;
|
|
sgh->init->uri_content_array = malloc(sgh->init->uri_content_size);
|
|
if (sgh->init->uri_content_array == NULL)
|
|
return -1;
|
|
|
|
memset(sgh->init->uri_content_array, 0, sgh->init->uri_content_size);
|
|
|
|
for (sig = 0; sig < sgh->sig_cnt; sig++) {
|
|
num = sgh->match_array[sig];
|
|
|
|
s = de_ctx->sig_array[num];
|
|
if (s == NULL)
|
|
continue;
|
|
|
|
if (!(s->flags & SIG_FLAG_MPM))
|
|
continue;
|
|
|
|
sm = s->match;
|
|
if (sm == NULL)
|
|
continue;
|
|
|
|
for ( ;sm != NULL; sm = sm->next) {
|
|
if (sm->type == DETECT_URICONTENT) {
|
|
co = (DetectUricontentData *)sm->ctx;
|
|
|
|
sgh->init->uri_content_array[co->id / 8] |= 1 << (co->id % 8);
|
|
}
|
|
}
|
|
}
|
|
|
|
return 0;
|
|
}
|
|
|
|
/**
|
|
* \brief Clears the memory allocated by SigGroupHeadLoadUriContent() for the
|
|
* bitarray to hold the uri content ids for a SigGroupHead.
|
|
*
|
|
* \param Pointer to the SigGroupHead whose uri_content_array would to be
|
|
* cleared.
|
|
*
|
|
* \ret 0 Always.
|
|
*/
|
|
int SigGroupHeadClearUricontent(SigGroupHead *sh)
|
|
{
|
|
if (sh == NULL)
|
|
return 0;
|
|
|
|
if (sh->init->uri_content_array != NULL) {
|
|
free(sh->init->uri_content_array);
|
|
sh->init->uri_content_array = NULL;
|
|
sh->init->uri_content_size = 0;
|
|
}
|
|
|
|
return 0;
|
|
}
|
|
|
|
/**
|
|
* \brief Create an array with all the internal ids of the sigs that this
|
|
* sig group head will check for.
|
|
*
|
|
* \param de_ctx Pointer to the detection engine context.
|
|
* \param sgh Pointer to the SigGroupHead.
|
|
* \param max_idx The maximum value of the sid in the SigGroupHead arg.
|
|
*
|
|
* \retval 0 success
|
|
* \retval -1 error
|
|
*/
|
|
int SigGroupHeadBuildMatchArray(DetectEngineCtx *de_ctx, SigGroupHead *sgh,
|
|
uint32_t max_idx)
|
|
{
|
|
Signature *s = NULL;
|
|
uint32_t idx = 0;
|
|
uint32_t sig = 0;
|
|
|
|
if (sgh == NULL)
|
|
return 0;
|
|
|
|
BUG_ON(sgh->match_array != NULL);
|
|
|
|
sgh->match_array = malloc(sgh->sig_cnt * sizeof(SigIntId));
|
|
if (sgh->match_array == NULL)
|
|
return -1;
|
|
|
|
memset(sgh->match_array,0, sgh->sig_cnt * sizeof(SigIntId));
|
|
|
|
detect_siggroup_matcharray_init_cnt++;
|
|
detect_siggroup_matcharray_memory += (sgh->sig_cnt * sizeof(SigIntId));
|
|
|
|
for (sig = 0; sig < max_idx + 1; sig++) {
|
|
if ( !(sgh->sig_array[(sig / 8)] & (1 << (sig % 8))) )
|
|
continue;
|
|
|
|
s = de_ctx->sig_array[sig];
|
|
if (s == NULL)
|
|
continue;
|
|
|
|
sgh->match_array[idx] = s->num;
|
|
idx++;
|
|
}
|
|
|
|
return 0;
|
|
}
|
|
|
|
/**
|
|
* \brief Check if a SigGroupHead contains a Signature, whose sid is sent as an
|
|
* argument.
|
|
*
|
|
* \param de_ctx Pointer to the detection engine context.
|
|
* \param sgh Pointer to the SigGroupHead that has to be checked for the
|
|
* presence of a Signature.
|
|
* \param sid The Signature id(sid) that has to be checked in the SigGroupHead.
|
|
*
|
|
* \retval 1 On successfully finding the sid in the SigGroupHead.
|
|
* \retval 0 If the sid is not found in the SigGroupHead
|
|
*/
|
|
int SigGroupHeadContainsSigId(DetectEngineCtx *de_ctx, SigGroupHead *sgh,
|
|
uint32_t sid)
|
|
{
|
|
uint32_t sig = 0;
|
|
Signature *s = NULL;
|
|
uint32_t max_sid = DetectEngineGetMaxSigId(de_ctx);
|
|
|
|
if (sgh == NULL)
|
|
return 0;
|
|
|
|
for (sig = 0; sig < max_sid; sig++) {
|
|
if (sgh->sig_array == NULL)
|
|
return 0;
|
|
|
|
/* Check if the SigGroupHead has an entry for the sid */
|
|
if ( !(sgh->sig_array[sig / 8] & (1 << (sig % 8))) )
|
|
continue;
|
|
|
|
/* If we have reached here, we have an entry for sid in the SigGrouHead.
|
|
* Retrieve the Signature from the detection engine context */
|
|
s = de_ctx->sig_array[sig];
|
|
if (s == NULL)
|
|
continue;
|
|
|
|
/* If the retrieved Signature matches the sid arg, we have a match */
|
|
if (s->id == sid)
|
|
return 1;
|
|
}
|
|
|
|
return 0;
|
|
}
|
|
|
|
/*----------------------------------Unittests---------------------------------*/
|
|
|
|
#ifdef UNITTESTS
|
|
|
|
int SigAddressPrepareStage1(DetectEngineCtx *);
|
|
|
|
/**
|
|
* \test Check if a SigGroupHead mpm hash table is properly allocated and
|
|
* deallocated when calling SigGroupHeadMpmHashInit() and
|
|
* SigGroupHeadMpmHashFree() respectively.
|
|
*/
|
|
static int SigGroupHeadTest01(void)
|
|
{
|
|
int result = 1;
|
|
|
|
DetectEngineCtx *de_ctx = DetectEngineCtxInit();
|
|
|
|
SigGroupHeadMpmHashInit(de_ctx);
|
|
|
|
result &= (de_ctx->sgh_mpm_hash_table != NULL);
|
|
|
|
SigGroupHeadMpmHashFree(de_ctx);
|
|
|
|
result &= (de_ctx->sgh_mpm_hash_table == NULL);
|
|
|
|
DetectEngineCtxFree(de_ctx);
|
|
|
|
return result;
|
|
}
|
|
|
|
/**
|
|
* \test Check if a SigGroupHead mpm uri hash table is properly allocated and
|
|
* deallocated when calling SigGroupHeadMpmUriHashInit() and
|
|
* SigGroupHeadMpmUriHashFree() respectively.
|
|
*/
|
|
static int SigGroupHeadTest02(void)
|
|
{
|
|
int result = 1;
|
|
|
|
DetectEngineCtx *de_ctx = DetectEngineCtxInit();
|
|
|
|
SigGroupHeadMpmUriHashInit(de_ctx);
|
|
|
|
result &= (de_ctx->sgh_mpm_uri_hash_table != NULL);
|
|
|
|
SigGroupHeadMpmUriHashFree(de_ctx);
|
|
|
|
result &= (de_ctx->sgh_mpm_uri_hash_table == NULL);
|
|
|
|
DetectEngineCtxFree(de_ctx);
|
|
|
|
return result;
|
|
}
|
|
|
|
/**
|
|
* \test Check if a SigGroupHead hash table is properly allocated and
|
|
* deallocated when calling SigGroupHeadHashInit() and
|
|
* SigGroupHeadHashFree() respectively.
|
|
*/
|
|
static int SigGroupHeadTest03(void)
|
|
{
|
|
int result = 1;
|
|
|
|
DetectEngineCtx *de_ctx = DetectEngineCtxInit();
|
|
|
|
SigGroupHeadHashInit(de_ctx);
|
|
|
|
result &= (de_ctx->sgh_hash_table != NULL);
|
|
|
|
SigGroupHeadHashFree(de_ctx);
|
|
|
|
result &= (de_ctx->sgh_hash_table == NULL);
|
|
|
|
DetectEngineCtxFree(de_ctx);
|
|
|
|
return result;
|
|
}
|
|
|
|
/**
|
|
* \test Check if a SigGroupHead dport hash table is properly allocated and
|
|
* deallocated when calling SigGroupHeadDPortHashInit() and
|
|
* SigGroupHeadDportHashFree() respectively.
|
|
*/
|
|
static int SigGroupHeadTest04(void)
|
|
{
|
|
int result = 1;
|
|
|
|
DetectEngineCtx *de_ctx = DetectEngineCtxInit();
|
|
|
|
SigGroupHeadDPortHashInit(de_ctx);
|
|
|
|
result &= (de_ctx->sgh_dport_hash_table != NULL);
|
|
|
|
SigGroupHeadDPortHashFree(de_ctx);
|
|
|
|
result &= (de_ctx->sgh_dport_hash_table == NULL);
|
|
|
|
DetectEngineCtxFree(de_ctx);
|
|
|
|
return result;
|
|
}
|
|
|
|
/**
|
|
* \test Check if a SigGroupHead dport hash table is properly allocated and
|
|
* deallocated when calling SigGroupHeadSPortHashInit() and
|
|
* SigGroupHeadSportHashFree() respectively.
|
|
*/
|
|
static int SigGroupHeadTest05(void)
|
|
{
|
|
int result = 1;
|
|
|
|
DetectEngineCtx *de_ctx = DetectEngineCtxInit();
|
|
|
|
SigGroupHeadSPortHashInit(de_ctx);
|
|
|
|
result &= (de_ctx->sgh_sport_hash_table != NULL);
|
|
|
|
SigGroupHeadSPortHashFree(de_ctx);
|
|
|
|
result &= (de_ctx->sgh_sport_hash_table == NULL);
|
|
|
|
DetectEngineCtxFree(de_ctx);
|
|
|
|
return result;
|
|
}
|
|
|
|
/**
|
|
* \test Check if a SigGroupHeadAppendSig() correctly appends a sid to a
|
|
* SigGroupHead() and SigGroupHeadContainsSigId() correctly indicates
|
|
* the presence of a sid.
|
|
*/
|
|
static int SigGroupHeadTest06(void)
|
|
{
|
|
int result = 1;
|
|
SigGroupHead *sh = NULL;
|
|
DetectEngineCtx *de_ctx = DetectEngineCtxInit();
|
|
Signature *prev_sig = NULL;
|
|
|
|
if (de_ctx == NULL)
|
|
return 0;
|
|
|
|
de_ctx->sig_list = SigInit(de_ctx, "alert tcp any any -> any any "
|
|
"(msg:\"SigGroupHead tests\"; content:test1; "
|
|
"content:test2; content:test3; sid:0;)");
|
|
if (de_ctx->sig_list == NULL) {
|
|
result = 0;
|
|
goto end;
|
|
}
|
|
prev_sig = de_ctx->sig_list;
|
|
|
|
prev_sig->next = SigInit(de_ctx, "alert tcp any any -> any any "
|
|
"(msg:\"SigGroupHead tests\"; content:test1; "
|
|
"content:test2; content:test3; sid:1;)");
|
|
if (prev_sig->next == NULL) {
|
|
result = 0;
|
|
goto end;
|
|
}
|
|
prev_sig = prev_sig->next;
|
|
|
|
prev_sig->next = SigInit(de_ctx, "alert tcp any any -> any any "
|
|
"(msg:\"SigGroupHead tests\"; content:test1; "
|
|
"content:test2; content:test3; sid:2;)");
|
|
if (prev_sig->next == NULL) {
|
|
result = 0;
|
|
goto end;
|
|
}
|
|
prev_sig = prev_sig->next;
|
|
|
|
prev_sig->next = SigInit(de_ctx, "alert tcp any any -> any any "
|
|
"(msg:\"SigGroupHead tests\"; content:test1; "
|
|
"content:test2; content:test3; sid:3;)");
|
|
if (prev_sig->next == NULL) {
|
|
result = 0;
|
|
goto end;
|
|
}
|
|
prev_sig = prev_sig->next;
|
|
|
|
prev_sig->next = SigInit(de_ctx, "alert tcp any any -> any any "
|
|
"(msg:\"SigGroupHead tests\"; content:test1; "
|
|
"content:test2; content:test3; sid:4;)");
|
|
if (prev_sig->next == NULL) {
|
|
result = 0;
|
|
goto end;
|
|
}
|
|
prev_sig = prev_sig->next;
|
|
|
|
SigAddressPrepareStage1(de_ctx);
|
|
|
|
SigGroupHeadAppendSig(de_ctx, &sh, de_ctx->sig_list);
|
|
SigGroupHeadAppendSig(de_ctx, &sh, de_ctx->sig_list->next->next);
|
|
SigGroupHeadAppendSig(de_ctx, &sh, de_ctx->sig_list->next->next->next->next);
|
|
|
|
SigGroupHeadSetSigCnt(sh, 4);
|
|
|
|
result &= (sh->sig_cnt == 3);
|
|
result &= (SigGroupHeadContainsSigId(de_ctx, sh, 0) == 1);
|
|
result &= (SigGroupHeadContainsSigId(de_ctx, sh, 1) == 0);
|
|
result &= (SigGroupHeadContainsSigId(de_ctx, sh, 2) == 1);
|
|
result &= (SigGroupHeadContainsSigId(de_ctx, sh, 3) == 0);
|
|
result &= (SigGroupHeadContainsSigId(de_ctx, sh, 4) == 1);
|
|
|
|
SigGroupHeadFree(sh);
|
|
|
|
end:
|
|
SigCleanSignatures(de_ctx);
|
|
DetectEngineCtxFree(de_ctx);
|
|
return result;
|
|
}
|
|
|
|
/**
|
|
* \test Check if a SigGroupHeadAppendSig(), correctly appends a sid to a
|
|
* SigGroupHead() and SigGroupHeadContainsSigId(), correctly indicates
|
|
* the presence of a sid and SigGroupHeadClearSigs(), correctly clears
|
|
* the SigGroupHead->sig_array and SigGroupHead->sig_cnt.
|
|
*/
|
|
static int SigGroupHeadTest07(void)
|
|
{
|
|
int result = 1;
|
|
SigGroupHead *sh = NULL;
|
|
DetectEngineCtx *de_ctx = DetectEngineCtxInit();
|
|
Signature *prev_sig = NULL;
|
|
|
|
if (de_ctx == NULL)
|
|
return 0;
|
|
|
|
de_ctx->sig_list = SigInit(de_ctx, "alert tcp any any -> any any "
|
|
"(msg:\"SigGroupHead tests\"; content:test1; "
|
|
"content:test2; content:test3; sid:0;)");
|
|
if (de_ctx->sig_list == NULL) {
|
|
result = 0;
|
|
goto end;
|
|
}
|
|
prev_sig = de_ctx->sig_list;
|
|
|
|
prev_sig->next = SigInit(de_ctx, "alert tcp any any -> any any "
|
|
"(msg:\"SigGroupHead tests\"; content:test1; "
|
|
"content:test2; content:test3; sid:1;)");
|
|
if (prev_sig->next == NULL) {
|
|
result = 0;
|
|
goto end;
|
|
}
|
|
prev_sig = prev_sig->next;
|
|
|
|
prev_sig->next = SigInit(de_ctx, "alert tcp any any -> any any "
|
|
"(msg:\"SigGroupHead tests\"; content:test1; "
|
|
"content:test2; content:test3; sid:2;)");
|
|
if (prev_sig->next == NULL) {
|
|
result = 0;
|
|
goto end;
|
|
}
|
|
prev_sig = prev_sig->next;
|
|
|
|
prev_sig->next = SigInit(de_ctx, "alert tcp any any -> any any "
|
|
"(msg:\"SigGroupHead tests\"; content:test1; "
|
|
"content:test2; content:test3; sid:3;)");
|
|
if (prev_sig->next == NULL) {
|
|
result = 0;
|
|
goto end;
|
|
}
|
|
prev_sig = prev_sig->next;
|
|
|
|
prev_sig->next = SigInit(de_ctx, "alert tcp any any -> any any "
|
|
"(msg:\"SigGroupHead tests\"; content:test1; "
|
|
"content:test2; content:test3; sid:4;)");
|
|
if (prev_sig->next == NULL) {
|
|
result = 0;
|
|
goto end;
|
|
}
|
|
prev_sig = prev_sig->next;
|
|
|
|
SigAddressPrepareStage1(de_ctx);
|
|
|
|
SigGroupHeadAppendSig(de_ctx, &sh, de_ctx->sig_list);
|
|
SigGroupHeadAppendSig(de_ctx, &sh, de_ctx->sig_list->next->next);
|
|
SigGroupHeadAppendSig(de_ctx, &sh, de_ctx->sig_list->next->next->next->next);
|
|
|
|
SigGroupHeadSetSigCnt(sh, 4);
|
|
|
|
result &= (sh->sig_cnt == 3);
|
|
result &= (SigGroupHeadContainsSigId(de_ctx, sh, 0) == 1);
|
|
result &= (SigGroupHeadContainsSigId(de_ctx, sh, 1) == 0);
|
|
result &= (SigGroupHeadContainsSigId(de_ctx, sh, 2) == 1);
|
|
result &= (SigGroupHeadContainsSigId(de_ctx, sh, 3) == 0);
|
|
result &= (SigGroupHeadContainsSigId(de_ctx, sh, 4) == 1);
|
|
|
|
SigGroupHeadClearSigs(sh);
|
|
|
|
result &= (sh->sig_cnt == 0);
|
|
result &= (SigGroupHeadContainsSigId(de_ctx, sh, 0) == 0);
|
|
result &= (SigGroupHeadContainsSigId(de_ctx, sh, 1) == 0);
|
|
result &= (SigGroupHeadContainsSigId(de_ctx, sh, 2) == 0);
|
|
result &= (SigGroupHeadContainsSigId(de_ctx, sh, 3) == 0);
|
|
result &= (SigGroupHeadContainsSigId(de_ctx, sh, 4) == 0);
|
|
|
|
SigGroupHeadFree(sh);
|
|
|
|
end:
|
|
SigCleanSignatures(de_ctx);
|
|
DetectEngineCtxFree(de_ctx);
|
|
return result;
|
|
}
|
|
|
|
/**
|
|
* \test Check if SigGroupHeadCopySigs(), correctly copies the sig_array from
|
|
* the source to the destination SigGroupHead.
|
|
*/
|
|
static int SigGroupHeadTest08(void)
|
|
{
|
|
int result = 1;
|
|
SigGroupHead *src_sh = NULL;
|
|
SigGroupHead *dst_sh = NULL;
|
|
DetectEngineCtx *de_ctx = DetectEngineCtxInit();
|
|
Signature *prev_sig = NULL;
|
|
|
|
if (de_ctx == NULL)
|
|
return 0;
|
|
|
|
de_ctx->sig_list = SigInit(de_ctx, "alert tcp any any -> any any "
|
|
"(msg:\"SigGroupHead tests\"; content:test1; "
|
|
"content:test2; content:test3; sid:0;)");
|
|
if (de_ctx->sig_list == NULL) {
|
|
result = 0;
|
|
goto end;
|
|
}
|
|
prev_sig = de_ctx->sig_list;
|
|
|
|
prev_sig->next = SigInit(de_ctx, "alert tcp any any -> any any "
|
|
"(msg:\"SigGroupHead tests\"; content:test1; "
|
|
"content:test2; content:test3; sid:1;)");
|
|
if (prev_sig->next == NULL) {
|
|
result = 0;
|
|
goto end;
|
|
}
|
|
prev_sig = prev_sig->next;
|
|
|
|
prev_sig->next = SigInit(de_ctx, "alert tcp any any -> any any "
|
|
"(msg:\"SigGroupHead tests\"; content:test1; "
|
|
"content:test2; content:test3; sid:2;)");
|
|
if (prev_sig->next == NULL) {
|
|
result = 0;
|
|
goto end;
|
|
}
|
|
prev_sig = prev_sig->next;
|
|
|
|
prev_sig->next = SigInit(de_ctx, "alert tcp any any -> any any "
|
|
"(msg:\"SigGroupHead tests\"; content:test1; "
|
|
"content:test2; content:test3; sid:3;)");
|
|
if (prev_sig->next == NULL) {
|
|
result = 0;
|
|
goto end;
|
|
}
|
|
prev_sig = prev_sig->next;
|
|
|
|
prev_sig->next = SigInit(de_ctx, "alert tcp any any -> any any "
|
|
"(msg:\"SigGroupHead tests\"; content:test1; "
|
|
"content:test2; content:test3; sid:4;)");
|
|
if (prev_sig->next == NULL) {
|
|
result = 0;
|
|
goto end;
|
|
}
|
|
prev_sig = prev_sig->next;
|
|
|
|
SigAddressPrepareStage1(de_ctx);
|
|
|
|
SigGroupHeadAppendSig(de_ctx, &src_sh, de_ctx->sig_list);
|
|
SigGroupHeadAppendSig(de_ctx, &src_sh, de_ctx->sig_list->next->next);
|
|
SigGroupHeadAppendSig(de_ctx, &src_sh, de_ctx->sig_list->next->next->next->next);
|
|
|
|
SigGroupHeadSetSigCnt(src_sh, 4);
|
|
|
|
result &= (src_sh->sig_cnt == 3);
|
|
result &= (SigGroupHeadContainsSigId(de_ctx, src_sh, 0) == 1);
|
|
result &= (SigGroupHeadContainsSigId(de_ctx, src_sh, 1) == 0);
|
|
result &= (SigGroupHeadContainsSigId(de_ctx, src_sh, 2) == 1);
|
|
result &= (SigGroupHeadContainsSigId(de_ctx, src_sh, 3) == 0);
|
|
result &= (SigGroupHeadContainsSigId(de_ctx, src_sh, 4) == 1);
|
|
|
|
SigGroupHeadCopySigs(de_ctx, src_sh, &dst_sh);
|
|
|
|
SigGroupHeadSetSigCnt(dst_sh, 4);
|
|
|
|
result &= (dst_sh->sig_cnt == 3);
|
|
result &= (SigGroupHeadContainsSigId(de_ctx, dst_sh, 0) == 1);
|
|
result &= (SigGroupHeadContainsSigId(de_ctx, dst_sh, 1) == 0);
|
|
result &= (SigGroupHeadContainsSigId(de_ctx, dst_sh, 2) == 1);
|
|
result &= (SigGroupHeadContainsSigId(de_ctx, dst_sh, 3) == 0);
|
|
result &= (SigGroupHeadContainsSigId(de_ctx, dst_sh, 4) == 1);
|
|
|
|
SigGroupHeadFree(src_sh);
|
|
SigGroupHeadFree(dst_sh);
|
|
|
|
end:
|
|
SigCleanSignatures(de_ctx);
|
|
DetectEngineCtxFree(de_ctx);
|
|
return result;
|
|
}
|
|
|
|
/**
|
|
* \test Check if SigGroupHeadBuildMatchArray(), correctly updates the
|
|
* match array with the sids.
|
|
*/
|
|
static int SigGroupHeadTest09(void)
|
|
{
|
|
int result = 1;
|
|
SigGroupHead *sh = NULL;
|
|
DetectEngineCtx *de_ctx = DetectEngineCtxInit();
|
|
Signature *prev_sig = NULL;
|
|
|
|
if (de_ctx == NULL)
|
|
return 0;
|
|
|
|
de_ctx->sig_list = SigInit(de_ctx, "alert tcp any any -> any any "
|
|
"(msg:\"SigGroupHead tests\"; content:test1; "
|
|
"content:test2; content:test3; sid:0;)");
|
|
if (de_ctx->sig_list == NULL) {
|
|
result = 0;
|
|
goto end;
|
|
}
|
|
prev_sig = de_ctx->sig_list;
|
|
|
|
prev_sig->next = SigInit(de_ctx, "alert tcp any any -> any any "
|
|
"(msg:\"SigGroupHead tests\"; content:test1; "
|
|
"content:test2; content:test3; sid:1;)");
|
|
if (prev_sig->next == NULL) {
|
|
result = 0;
|
|
goto end;
|
|
}
|
|
prev_sig = prev_sig->next;
|
|
|
|
prev_sig->next = SigInit(de_ctx, "alert tcp any any -> any any "
|
|
"(msg:\"SigGroupHead tests\"; content:test1; "
|
|
"content:test2; content:test3; sid:2;)");
|
|
if (prev_sig->next == NULL) {
|
|
result = 0;
|
|
goto end;
|
|
}
|
|
prev_sig = prev_sig->next;
|
|
|
|
prev_sig->next = SigInit(de_ctx, "alert tcp any any -> any any "
|
|
"(msg:\"SigGroupHead tests\"; content:test1; "
|
|
"content:test2; content:test3; sid:3;)");
|
|
if (prev_sig->next == NULL) {
|
|
result = 0;
|
|
goto end;
|
|
}
|
|
prev_sig = prev_sig->next;
|
|
|
|
prev_sig->next = SigInit(de_ctx, "alert tcp any any -> any any "
|
|
"(msg:\"SigGroupHead tests\"; content:test1; "
|
|
"content:test2; content:test3; sid:4;)");
|
|
if (prev_sig->next == NULL) {
|
|
result = 0;
|
|
goto end;
|
|
}
|
|
prev_sig = prev_sig->next;
|
|
|
|
SigAddressPrepareStage1(de_ctx);
|
|
|
|
SigGroupHeadAppendSig(de_ctx, &sh, de_ctx->sig_list);
|
|
SigGroupHeadAppendSig(de_ctx, &sh, de_ctx->sig_list->next->next);
|
|
SigGroupHeadAppendSig(de_ctx, &sh, de_ctx->sig_list->next->next->next->next);
|
|
|
|
SigGroupHeadSetSigCnt(sh, 4);
|
|
SigGroupHeadBuildMatchArray(de_ctx, sh, 4);
|
|
|
|
result &= (sh->match_array[0] == 0);
|
|
result &= (sh->match_array[1] == 2);
|
|
result &= (sh->match_array[2] == 4);
|
|
|
|
SigGroupHeadFree(sh);
|
|
|
|
end:
|
|
SigCleanSignatures(de_ctx);
|
|
DetectEngineCtxFree(de_ctx);
|
|
return result;
|
|
}
|
|
|
|
#endif
|
|
|
|
void SigGroupHeadRegisterTests(void)
|
|
{
|
|
|
|
#ifdef UNITTESTS
|
|
|
|
UtRegisterTest("SigGroupHeadTest01", SigGroupHeadTest01, 1);
|
|
UtRegisterTest("SigGroupHeadTest02", SigGroupHeadTest02, 1);
|
|
UtRegisterTest("SigGroupHeadTest03", SigGroupHeadTest03, 1);
|
|
UtRegisterTest("SigGroupHeadTest04", SigGroupHeadTest04, 1);
|
|
UtRegisterTest("SigGroupHeadTest05", SigGroupHeadTest05, 1);
|
|
UtRegisterTest("SigGroupHeadTest06", SigGroupHeadTest06, 1);
|
|
UtRegisterTest("SigGroupHeadTest07", SigGroupHeadTest07, 1);
|
|
UtRegisterTest("SigGroupHeadTest08", SigGroupHeadTest08, 1);
|
|
UtRegisterTest("SigGroupHeadTest09", SigGroupHeadTest09, 1);
|
|
|
|
#endif
|
|
|
|
}
|