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.
1516 lines
51 KiB
C
1516 lines
51 KiB
C
/* Copyright (C) 2007-2013 Open Information Security Foundation
|
|
*
|
|
* You can copy, redistribute or modify this Program under the terms of
|
|
* the GNU General Public License version 2 as published by the Free
|
|
* Software Foundation.
|
|
*
|
|
* This program is distributed in the hope that it will be useful,
|
|
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
|
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
|
* GNU General Public License for more details.
|
|
*
|
|
* You should have received a copy of the GNU General Public License
|
|
* version 2 along with this program; if not, write to the Free Software
|
|
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
|
|
* 02110-1301, USA.
|
|
*/
|
|
|
|
/**
|
|
* \file detect-engine-tag.c
|
|
*
|
|
* \author Victor Julien <victor@inliniac.net>
|
|
* \author Pablo Rincon Crespo <pablo.rincon.crespo@gmail.com>
|
|
*
|
|
* Implements a global context to store data related to hosts flagged
|
|
* tag keyword
|
|
*/
|
|
|
|
#include "suricata-common.h"
|
|
#include "detect-engine.h"
|
|
#include "util-hash.h"
|
|
#include "util-atomic.h"
|
|
#include "util-time.h"
|
|
#include "util-hashlist.h"
|
|
#include "detect-engine-tag.h"
|
|
#include "detect-tag.h"
|
|
#include "host.h"
|
|
#include "host-storage.h"
|
|
#include "flow-storage.h"
|
|
|
|
#include "util-unittest.h"
|
|
#include "util-unittest-helper.h"
|
|
#include "flow-util.h"
|
|
#include "stream-tcp-private.h"
|
|
|
|
SC_ATOMIC_DECLARE(unsigned int, num_tags); /**< Atomic counter, to know if we
|
|
have tagged hosts/sessions,
|
|
to avoid locking */
|
|
static int host_tag_id = -1; /**< Host storage id for tags */
|
|
static int flow_tag_id = -1; /**< Flow storage id for tags */
|
|
|
|
void TagInitCtx(void)
|
|
{
|
|
SC_ATOMIC_INIT(num_tags);
|
|
|
|
host_tag_id = HostStorageRegister("tag", sizeof(void *), NULL, DetectTagDataListFree);
|
|
if (host_tag_id == -1) {
|
|
SCLogError(SC_ERR_HOST_INIT, "Can't initiate host storage for tag");
|
|
exit(EXIT_FAILURE);
|
|
}
|
|
flow_tag_id = FlowStorageRegister("tag", sizeof(void *), NULL, DetectTagDataListFree);
|
|
if (flow_tag_id == -1) {
|
|
SCLogError(SC_ERR_FLOW_INIT, "Can't initiate flow storage for tag");
|
|
exit(EXIT_FAILURE);
|
|
}
|
|
}
|
|
|
|
/**
|
|
* \brief Destroy tag context hash tables
|
|
*
|
|
* \param tag_ctx Tag Context
|
|
*
|
|
*/
|
|
void TagDestroyCtx(void)
|
|
{
|
|
#ifdef DEBUG
|
|
BUG_ON(SC_ATOMIC_GET(num_tags) != 0);
|
|
#endif
|
|
SC_ATOMIC_DESTROY(num_tags);
|
|
}
|
|
|
|
/** \brief Reset the tagging engine context
|
|
*/
|
|
void TagRestartCtx()
|
|
{
|
|
TagDestroyCtx();
|
|
TagInitCtx();
|
|
}
|
|
|
|
int TagHostHasTag(Host *host)
|
|
{
|
|
return HostGetStorageById(host, host_tag_id) ? 1 : 0;
|
|
}
|
|
|
|
static DetectTagDataEntry *DetectTagDataCopy(DetectTagDataEntry *dtd)
|
|
{
|
|
DetectTagDataEntry *tde = SCMalloc(sizeof(DetectTagDataEntry));
|
|
if (unlikely(tde == NULL)) {
|
|
return NULL;
|
|
}
|
|
memset(tde, 0, sizeof(DetectTagDataEntry));
|
|
|
|
tde->sid = dtd->sid;
|
|
tde->gid = dtd->gid;
|
|
tde->flags = dtd->flags;
|
|
tde->metric = dtd->metric;
|
|
tde->count = dtd->count;
|
|
|
|
tde->first_ts = dtd->first_ts;
|
|
tde->last_ts = dtd->last_ts;
|
|
return tde;
|
|
}
|
|
|
|
/**
|
|
* \brief This function is used to add a tag to a session (type session)
|
|
* or update it if it's already installed. The number of times to
|
|
* allow an update is limited by DETECT_TAG_MATCH_LIMIT. This way
|
|
* repetitive matches to the same rule are limited of setting tags,
|
|
* to avoid DOS attacks
|
|
*
|
|
* \param p pointer to the current packet
|
|
* \param tde pointer to the new DetectTagDataEntry
|
|
*
|
|
* \retval 0 if the tde was added succesfuly
|
|
* \retval 1 if an entry of this sid/gid already exist and was updated
|
|
*/
|
|
int TagFlowAdd(Packet *p, DetectTagDataEntry *tde)
|
|
{
|
|
uint8_t updated = 0;
|
|
uint16_t tag_cnt = 0;
|
|
DetectTagDataEntry *iter = NULL;
|
|
|
|
if (p->flow == NULL)
|
|
return 1;
|
|
|
|
iter = FlowGetStorageById(p->flow, flow_tag_id);
|
|
if (iter != NULL) {
|
|
/* First iterate installed entries searching a duplicated sid/gid */
|
|
for (; iter != NULL; iter = iter->next) {
|
|
tag_cnt++;
|
|
|
|
if (iter->sid == tde->sid && iter->gid == tde->gid) {
|
|
iter->cnt_match++;
|
|
|
|
/* If so, update data, unless the maximum MATCH limit is
|
|
* reached. This prevents possible DOS attacks */
|
|
if (iter->cnt_match < DETECT_TAG_MATCH_LIMIT) {
|
|
/* Reset time and counters */
|
|
iter->first_ts = iter->last_ts = tde->first_ts;
|
|
iter->packets = 0;
|
|
iter->bytes = 0;
|
|
}
|
|
updated = 1;
|
|
break;
|
|
}
|
|
}
|
|
}
|
|
|
|
/* If there was no entry of this rule, prepend the new tde */
|
|
if (updated == 0 && tag_cnt < DETECT_TAG_MAX_TAGS) {
|
|
DetectTagDataEntry *new_tde = DetectTagDataCopy(tde);
|
|
if (new_tde != NULL) {
|
|
new_tde->next = FlowGetStorageById(p->flow, flow_tag_id);
|
|
FlowSetStorageById(p->flow, flow_tag_id, new_tde);
|
|
SCLogDebug("adding tag with first_ts %u", new_tde->first_ts);
|
|
(void) SC_ATOMIC_ADD(num_tags, 1);
|
|
}
|
|
} else if (tag_cnt == DETECT_TAG_MAX_TAGS) {
|
|
SCLogDebug("Max tags for sessions reached (%"PRIu16")", tag_cnt);
|
|
}
|
|
|
|
return updated;
|
|
}
|
|
|
|
/**
|
|
* \brief Add a tag entry for a host. If it already exist, update it.
|
|
*
|
|
* \param tag_ctx Tag context for hosts
|
|
* \param tde Tag data
|
|
* \param p packet
|
|
*
|
|
* \retval 0 if it was added, 1 if it was updated
|
|
*/
|
|
int TagHashAddTag(DetectTagDataEntry *tde, Packet *p)
|
|
{
|
|
SCEnter();
|
|
|
|
uint8_t updated = 0;
|
|
uint16_t num_tags = 0;
|
|
Host *host = NULL;
|
|
|
|
/* Lookup host in the hash. If it doesn't exist yet it's
|
|
* created. */
|
|
if (tde->flags & TAG_ENTRY_FLAG_DIR_SRC) {
|
|
host = HostGetHostFromHash(&p->src);
|
|
} else if (tde->flags & TAG_ENTRY_FLAG_DIR_DST) {
|
|
host = HostGetHostFromHash(&p->dst);
|
|
}
|
|
/* no host for us */
|
|
if (host == NULL) {
|
|
SCLogDebug("host tag not added: no host");
|
|
return -1;
|
|
}
|
|
|
|
void *tag = HostGetStorageById(host, host_tag_id);
|
|
if (tag == NULL) {
|
|
/* get a new tde as the one we have is on the stack */
|
|
DetectTagDataEntry *new_tde = DetectTagDataCopy(tde);
|
|
if (new_tde != NULL) {
|
|
HostSetStorageById(host, host_tag_id, new_tde);
|
|
(void) SC_ATOMIC_ADD(num_tags, 1);
|
|
SCLogDebug("host tag added");
|
|
}
|
|
} else {
|
|
/* Append the tag to the list of this host */
|
|
SCLogDebug("updating existing host");
|
|
|
|
/* First iterate installed entries searching a duplicated sid/gid */
|
|
DetectTagDataEntry *iter = NULL;
|
|
|
|
for (iter = tag; iter != NULL; iter = iter->next) {
|
|
num_tags++;
|
|
if (iter->sid == tde->sid && iter->gid == tde->gid) {
|
|
iter->cnt_match++;
|
|
/* If so, update data, unless the maximum MATCH limit is
|
|
* reached. This prevents possible DOS attacks */
|
|
if (iter->cnt_match < DETECT_TAG_MATCH_LIMIT) {
|
|
/* Reset time and counters */
|
|
iter->first_ts = iter->last_ts = tde->first_ts;
|
|
iter->packets = 0;
|
|
iter->bytes = 0;
|
|
}
|
|
updated = 1;
|
|
break;
|
|
}
|
|
}
|
|
|
|
/* If there was no entry of this rule, append the new tde */
|
|
if (updated == 0 && num_tags < DETECT_TAG_MAX_TAGS) {
|
|
/* get a new tde as the one we have is on the stack */
|
|
DetectTagDataEntry *new_tde = DetectTagDataCopy(tde);
|
|
if (new_tde != NULL) {
|
|
(void) SC_ATOMIC_ADD(num_tags, 1);
|
|
|
|
new_tde->next = tag;
|
|
HostSetStorageById(host, host_tag_id, new_tde);
|
|
}
|
|
} else if (num_tags == DETECT_TAG_MAX_TAGS) {
|
|
SCLogDebug("Max tags for sessions reached (%"PRIu16")", num_tags);
|
|
}
|
|
}
|
|
|
|
HostRelease(host);
|
|
SCReturnInt(updated);
|
|
}
|
|
|
|
static void TagHandlePacketFlow(Flow *f, Packet *p)
|
|
{
|
|
if (FlowGetStorageById(f, flow_tag_id) == NULL)
|
|
return;
|
|
|
|
DetectTagDataEntry *tde = NULL;
|
|
DetectTagDataEntry *prev = NULL;
|
|
DetectTagDataEntry *iter = FlowGetStorageById(f, flow_tag_id);
|
|
uint8_t flag_added = 0;
|
|
|
|
while (iter != NULL) {
|
|
/* update counters */
|
|
iter->last_ts = p->ts.tv_sec;
|
|
switch (iter->metric) {
|
|
case DETECT_TAG_METRIC_PACKET:
|
|
iter->packets++;
|
|
break;
|
|
case DETECT_TAG_METRIC_BYTES:
|
|
iter->bytes += GET_PKT_LEN(p);
|
|
break;
|
|
}
|
|
|
|
/* If this packet triggered the rule with tag, we dont need
|
|
* to log it (the alert will log it) */
|
|
if (!(iter->flags & TAG_ENTRY_FLAG_SKIPPED_FIRST)) {
|
|
iter->flags |= TAG_ENTRY_FLAG_SKIPPED_FIRST;
|
|
} else {
|
|
/* Update metrics; remove if tag expired; and set alerts */
|
|
switch (iter->metric) {
|
|
case DETECT_TAG_METRIC_PACKET:
|
|
if (iter->packets > iter->count) {
|
|
SCLogDebug("flow tag expired: packets %u > %u",
|
|
iter->packets, iter->count);
|
|
/* tag expired */
|
|
if (prev != NULL) {
|
|
tde = iter;
|
|
prev->next = iter->next;
|
|
iter = iter->next;
|
|
SCFree(tde);
|
|
(void) SC_ATOMIC_SUB(num_tags, 1);
|
|
continue;
|
|
} else {
|
|
FlowSetStorageById(p->flow, flow_tag_id, iter->next);
|
|
tde = iter;
|
|
iter = iter->next;
|
|
SCFree(tde);
|
|
(void) SC_ATOMIC_SUB(num_tags, 1);
|
|
continue;
|
|
}
|
|
} else if (flag_added == 0) {
|
|
/* It's matching the tag. Add it to be logged and
|
|
* update "flag_added" to add the packet once. */
|
|
p->flags |= PKT_HAS_TAG;
|
|
flag_added++;
|
|
}
|
|
break;
|
|
case DETECT_TAG_METRIC_BYTES:
|
|
if (iter->bytes > iter->count) {
|
|
/* tag expired */
|
|
SCLogDebug("flow tag expired: bytes %u > %u",
|
|
iter->bytes, iter->count);
|
|
if (prev != NULL) {
|
|
tde = iter;
|
|
prev->next = iter->next;
|
|
iter = iter->next;
|
|
SCFree(tde);
|
|
(void) SC_ATOMIC_SUB(num_tags, 1);
|
|
continue;
|
|
} else {
|
|
FlowSetStorageById(p->flow, flow_tag_id, iter->next);
|
|
tde = iter;
|
|
iter = iter->next;
|
|
SCFree(tde);
|
|
(void) SC_ATOMIC_SUB(num_tags, 1);
|
|
continue;
|
|
}
|
|
} else if (flag_added == 0) {
|
|
/* It's matching the tag. Add it to be logged and
|
|
* update "flag_added" to add the packet once. */
|
|
p->flags |= PKT_HAS_TAG;
|
|
flag_added++;
|
|
}
|
|
break;
|
|
case DETECT_TAG_METRIC_SECONDS:
|
|
/* last_ts handles this metric, but also a generic time based
|
|
* expiration to prevent dead sessions/hosts */
|
|
if (iter->last_ts - iter->first_ts > iter->count) {
|
|
SCLogDebug("flow tag expired: %u - %u = %u > %u",
|
|
iter->last_ts, iter->first_ts,
|
|
(iter->last_ts - iter->first_ts), iter->count);
|
|
/* tag expired */
|
|
if (prev != NULL) {
|
|
tde = iter;
|
|
prev->next = iter->next;
|
|
iter = iter->next;
|
|
SCFree(tde);
|
|
(void) SC_ATOMIC_SUB(num_tags, 1);
|
|
continue;
|
|
} else {
|
|
FlowSetStorageById(p->flow, flow_tag_id, iter->next);
|
|
tde = iter;
|
|
iter = iter->next;
|
|
SCFree(tde);
|
|
(void) SC_ATOMIC_SUB(num_tags, 1);
|
|
continue;
|
|
}
|
|
} else if (flag_added == 0) {
|
|
/* It's matching the tag. Add it to be logged and
|
|
* update "flag_added" to add the packet once. */
|
|
p->flags |= PKT_HAS_TAG;
|
|
flag_added++;
|
|
}
|
|
break;
|
|
}
|
|
|
|
}
|
|
|
|
prev = iter;
|
|
iter = iter->next;
|
|
}
|
|
}
|
|
|
|
void TagHandlePacketHost(Host *host, Packet *p)
|
|
{
|
|
DetectTagDataEntry *tde = NULL;
|
|
DetectTagDataEntry *prev = NULL;
|
|
DetectTagDataEntry *iter;
|
|
uint8_t flag_added = 0;
|
|
|
|
iter = HostGetStorageById(host, host_tag_id);
|
|
prev = NULL;
|
|
while (iter != NULL) {
|
|
/* update counters */
|
|
iter->last_ts = p->ts.tv_sec;
|
|
switch (iter->metric) {
|
|
case DETECT_TAG_METRIC_PACKET:
|
|
iter->packets++;
|
|
break;
|
|
case DETECT_TAG_METRIC_BYTES:
|
|
iter->bytes += GET_PKT_LEN(p);
|
|
break;
|
|
}
|
|
|
|
/* If this packet triggered the rule with tag, we dont need
|
|
* to log it (the alert will log it) */
|
|
if (!(iter->flags & TAG_ENTRY_FLAG_SKIPPED_FIRST)) {
|
|
iter->flags |= TAG_ENTRY_FLAG_SKIPPED_FIRST;
|
|
} else {
|
|
/* Update metrics; remove if tag expired; and set alerts */
|
|
switch (iter->metric) {
|
|
case DETECT_TAG_METRIC_PACKET:
|
|
if (iter->packets > iter->count) {
|
|
SCLogDebug("host tag expired: packets %u > %u", iter->packets, iter->count);
|
|
/* tag expired */
|
|
if (prev != NULL) {
|
|
tde = iter;
|
|
prev->next = iter->next;
|
|
iter = iter->next;
|
|
SCFree(tde);
|
|
(void) SC_ATOMIC_SUB(num_tags, 1);
|
|
continue;
|
|
} else {
|
|
tde = iter;
|
|
iter = iter->next;
|
|
SCFree(tde);
|
|
(void) SC_ATOMIC_SUB(num_tags, 1);
|
|
HostSetStorageById(host, host_tag_id, iter);
|
|
continue;
|
|
}
|
|
} else if (flag_added == 0) {
|
|
/* It's matching the tag. Add it to be logged and
|
|
* update "flag_added" to add the packet once. */
|
|
p->flags |= PKT_HAS_TAG;
|
|
flag_added++;
|
|
}
|
|
break;
|
|
case DETECT_TAG_METRIC_BYTES:
|
|
if (iter->bytes > iter->count) {
|
|
SCLogDebug("host tag expired: bytes %u > %u", iter->bytes, iter->count);
|
|
/* tag expired */
|
|
if (prev != NULL) {
|
|
tde = iter;
|
|
prev->next = iter->next;
|
|
iter = iter->next;
|
|
SCFree(tde);
|
|
(void) SC_ATOMIC_SUB(num_tags, 1);
|
|
continue;
|
|
} else {
|
|
tde = iter;
|
|
iter = iter->next;
|
|
SCFree(tde);
|
|
(void) SC_ATOMIC_SUB(num_tags, 1);
|
|
HostSetStorageById(host, host_tag_id, iter);
|
|
continue;
|
|
}
|
|
} else if (flag_added == 0) {
|
|
/* It's matching the tag. Add it to be logged and
|
|
* update "flag_added" to add the packet once. */
|
|
p->flags |= PKT_HAS_TAG;
|
|
flag_added++;
|
|
}
|
|
break;
|
|
case DETECT_TAG_METRIC_SECONDS:
|
|
/* last_ts handles this metric, but also a generic time based
|
|
* expiration to prevent dead sessions/hosts */
|
|
if (iter->last_ts - iter->first_ts > iter->count) {
|
|
SCLogDebug("host tag expired: %u - %u = %u > %u",
|
|
iter->last_ts, iter->first_ts,
|
|
(iter->last_ts - iter->first_ts), iter->count);
|
|
/* tag expired */
|
|
if (prev != NULL) {
|
|
tde = iter;
|
|
prev->next = iter->next;
|
|
iter = iter->next;
|
|
SCFree(tde);
|
|
(void) SC_ATOMIC_SUB(num_tags, 1);
|
|
continue;
|
|
} else {
|
|
tde = iter;
|
|
iter = iter->next;
|
|
SCFree(tde);
|
|
(void) SC_ATOMIC_SUB(num_tags, 1);
|
|
HostSetStorageById(host, host_tag_id, iter);
|
|
continue;
|
|
}
|
|
} else if (flag_added == 0) {
|
|
/* It's matching the tag. Add it to be logged and
|
|
* update "flag_added" to add the packet once. */
|
|
p->flags |= PKT_HAS_TAG;
|
|
flag_added++;
|
|
}
|
|
break;
|
|
}
|
|
|
|
}
|
|
|
|
prev = iter;
|
|
iter = iter->next;
|
|
}
|
|
}
|
|
|
|
/**
|
|
* \brief Search tags for src and dst. Update entries of the tag, remove if necessary
|
|
*
|
|
* \param de_ctx Detect context
|
|
* \param det_ctx Detect thread context
|
|
* \param p packet
|
|
*
|
|
*/
|
|
void TagHandlePacket(DetectEngineCtx *de_ctx,
|
|
DetectEngineThreadCtx *det_ctx, Packet *p)
|
|
{
|
|
SCEnter();
|
|
|
|
/* If there's no tag, get out of here */
|
|
unsigned int current_tags = SC_ATOMIC_GET(num_tags);
|
|
if (current_tags == 0)
|
|
SCReturn;
|
|
|
|
/* First update and get session tags */
|
|
if (p->flow != NULL) {
|
|
TagHandlePacketFlow(p->flow, p);
|
|
}
|
|
|
|
Host *src = HostLookupHostFromHash(&p->src);
|
|
if (src) {
|
|
if (TagHostHasTag(src)) {
|
|
TagHandlePacketHost(src,p);
|
|
}
|
|
HostRelease(src);
|
|
}
|
|
Host *dst = HostLookupHostFromHash(&p->dst);
|
|
if (dst) {
|
|
if (TagHostHasTag(dst)) {
|
|
TagHandlePacketHost(dst,p);
|
|
}
|
|
HostRelease(dst);
|
|
}
|
|
SCReturn;
|
|
}
|
|
|
|
/**
|
|
* \brief Removes the entries exceding the max timeout value
|
|
*
|
|
* \param tag_ctx Tag context
|
|
* \param ts the current time
|
|
*
|
|
* \retval 1 no tags or tags removed -- host is free to go (from tag perspective)
|
|
* \retval 0 still active tags
|
|
*/
|
|
int TagTimeoutCheck(Host *host, struct timeval *tv)
|
|
{
|
|
DetectTagDataEntry *tde = NULL;
|
|
DetectTagDataEntry *tmp = NULL;
|
|
DetectTagDataEntry *prev = NULL;
|
|
int retval = 1;
|
|
|
|
tmp = HostGetStorageById(host, host_tag_id);
|
|
if (tmp == NULL)
|
|
return 1;
|
|
|
|
prev = NULL;
|
|
while (tmp != NULL) {
|
|
if ((tv->tv_sec - tmp->last_ts) <= TAG_MAX_LAST_TIME_SEEN) {
|
|
prev = tmp;
|
|
tmp = tmp->next;
|
|
retval = 0;
|
|
continue;
|
|
}
|
|
|
|
/* timed out */
|
|
|
|
if (prev != NULL) {
|
|
prev->next = tmp->next;
|
|
|
|
tde = tmp;
|
|
tmp = tde->next;
|
|
|
|
SCFree(tde);
|
|
(void) SC_ATOMIC_SUB(num_tags, 1);
|
|
} else {
|
|
HostSetStorageById(host, host_tag_id, tmp->next);
|
|
|
|
tde = tmp;
|
|
tmp = tde->next;
|
|
|
|
SCFree(tde);
|
|
(void) SC_ATOMIC_SUB(num_tags, 1);
|
|
}
|
|
}
|
|
return retval;
|
|
}
|
|
|
|
#ifdef UNITTESTS
|
|
|
|
/**
|
|
* \test host tagging: packets
|
|
*/
|
|
int DetectTagTestPacket01 (void)
|
|
{
|
|
int result = 0;
|
|
uint8_t *buf = (uint8_t *)"Hi all!";
|
|
uint8_t *buf2 = (uint8_t *)"lalala!";
|
|
uint16_t buf_len = strlen((char *)buf);
|
|
uint16_t buf_len2 = strlen((char *)buf2);
|
|
|
|
Packet *p[7];
|
|
p[0] = UTHBuildPacketReal(buf, buf_len, IPPROTO_TCP,
|
|
"192.168.1.5", "192.168.1.1",
|
|
41424, 80);
|
|
p[1] = UTHBuildPacketReal(buf2, buf_len2, IPPROTO_TCP,
|
|
"192.168.1.5", "192.168.1.1",
|
|
41424, 80);
|
|
p[2] = UTHBuildPacketReal(buf2, buf_len2, IPPROTO_TCP,
|
|
"192.168.1.5", "192.168.1.9",
|
|
41424, 80);
|
|
p[3] = UTHBuildPacketReal(buf2, buf_len2, IPPROTO_TCP,
|
|
"192.168.1.5", "192.168.1.9",
|
|
41424, 80);
|
|
p[4] = UTHBuildPacketReal(buf2, buf_len2, IPPROTO_TCP,
|
|
"192.168.1.1", "192.168.1.9",
|
|
41424, 80);
|
|
p[5] = UTHBuildPacketReal(buf2, buf_len2, IPPROTO_TCP,
|
|
"192.168.1.1", "192.168.1.11",
|
|
41424, 80);
|
|
p[6] = UTHBuildPacketReal(buf2, buf_len2, IPPROTO_TCP,
|
|
"192.168.1.5", "192.168.1.11",
|
|
41424, 80);
|
|
|
|
char *sigs[5];
|
|
sigs[0]= "alert tcp any any -> any any (msg:\"Testing tag 1\"; content:\"Hi all\"; tag:host,3,packets,src; sid:1;)";
|
|
sigs[1]= "alert tcp any any -> any any (msg:\"Testing tag 2\"; content:\"Hi all\"; tag:host,4,packets,dst; sid:2;)";
|
|
sigs[2]= "alert tcp any any -> any any (msg:\"Testing tag 2\"; content:\"no match\"; sid:3;)";
|
|
sigs[3]= "alert tcp any any -> any any (msg:\"Testing tag 2\"; content:\"no match\"; sid:4;)";
|
|
sigs[4]= "alert tcp any any -> any any (msg:\"Testing tag 2\"; content:\"no match\"; sid:5;)";
|
|
|
|
/* Please, Notice that tagged data goes with sig_id = 1 and tag sig generator = 2 */
|
|
uint32_t sid[5] = {1,2,3,4,5};
|
|
|
|
int32_t results[7][5] = {
|
|
{1, 1, 0, 0, 0},
|
|
{0, 0, 0, 0, 0},
|
|
{0, 0, 0, 0, 0},
|
|
{0, 0, 0, 0, 0},
|
|
{0, 0, 0, 0, 0},
|
|
{0, 0, 0, 0, 0},
|
|
{0, 0, 0, 0, 0}
|
|
};
|
|
StorageInit();
|
|
TagInitCtx();
|
|
StorageFinalize();
|
|
HostInitConfig(1);
|
|
|
|
SCLogDebug("running tests");
|
|
result = UTHGenericTest(p, 7, sigs, sid, (uint32_t *) results, 5);
|
|
SCLogDebug("running tests done");
|
|
|
|
Host *src = HostLookupHostFromHash(&p[1]->src);
|
|
if (src) {
|
|
void *tag = HostGetStorageById(src, host_tag_id);
|
|
if (tag != NULL) {
|
|
printf("tag should have been expired: ");
|
|
result = 0;
|
|
}
|
|
|
|
HostRelease(src);
|
|
}
|
|
Host *dst = HostLookupHostFromHash(&p[1]->dst);
|
|
if (dst) {
|
|
void *tag = HostGetStorageById(dst, host_tag_id);
|
|
BUG_ON(tag == NULL);
|
|
|
|
DetectTagDataEntry *iter = tag;
|
|
|
|
/* check internal state */
|
|
if (!(iter->gid == 1 && iter->sid == 2 && iter->packets == 4 && iter->count == 4)) {
|
|
printf("gid %u sid %u packets %u count %u: ", iter->gid, iter->sid, iter->packets, iter->count);
|
|
result = 0;
|
|
}
|
|
|
|
HostRelease(dst);
|
|
}
|
|
BUG_ON(src == NULL || dst == NULL);
|
|
|
|
UTHFreePackets(p, 7);
|
|
|
|
HostShutdown();
|
|
TagDestroyCtx();
|
|
StorageCleanup();
|
|
return result;
|
|
}
|
|
|
|
/**
|
|
* \test host tagging: seconds
|
|
*/
|
|
int DetectTagTestPacket02 (void)
|
|
{
|
|
int result = 0;
|
|
uint8_t *buf = (uint8_t *)"Hi all!";
|
|
uint8_t *buf2 = (uint8_t *)"lalala!";
|
|
uint16_t buf_len = strlen((char *)buf);
|
|
uint16_t buf_len2 = strlen((char *)buf2);
|
|
|
|
DecodeThreadVars dtv;
|
|
ThreadVars th_v;
|
|
DetectEngineThreadCtx *det_ctx = NULL;
|
|
memset(&dtv, 0, sizeof(DecodeThreadVars));
|
|
memset(&th_v, 0, sizeof(th_v));
|
|
|
|
StorageInit();
|
|
TagInitCtx();
|
|
StorageFinalize();
|
|
HostInitConfig(1);
|
|
|
|
DetectEngineCtx *de_ctx = DetectEngineCtxInit();
|
|
if (de_ctx == NULL) {
|
|
goto end;
|
|
}
|
|
de_ctx->flags |= DE_QUIET;
|
|
|
|
Packet *p[7];
|
|
p[0] = UTHBuildPacketReal(buf, buf_len, IPPROTO_TCP,
|
|
"192.168.1.5", "192.168.1.1",
|
|
41424, 80);
|
|
p[1] = UTHBuildPacketReal(buf2, buf_len2, IPPROTO_TCP,
|
|
"192.168.1.5", "192.168.1.1",
|
|
41424, 80);
|
|
p[2] = UTHBuildPacketReal(buf2, buf_len2, IPPROTO_TCP,
|
|
"192.168.1.5", "192.168.1.9",
|
|
41424, 80);
|
|
p[3] = UTHBuildPacketReal(buf2, buf_len2, IPPROTO_TCP,
|
|
"192.168.1.5", "192.168.1.9",
|
|
41424, 80);
|
|
p[4] = UTHBuildPacketReal(buf2, buf_len2, IPPROTO_TCP,
|
|
"192.168.1.1", "192.168.1.9",
|
|
41424, 80);
|
|
p[5] = UTHBuildPacketReal(buf2, buf_len2, IPPROTO_TCP,
|
|
"192.168.1.1", "192.168.1.11",
|
|
41424, 80);
|
|
p[6] = UTHBuildPacketReal(buf2, buf_len2, IPPROTO_TCP,
|
|
"192.168.1.5", "192.168.1.11",
|
|
41424, 80);
|
|
|
|
char *sigs[5];
|
|
sigs[0]= "alert tcp any any -> any any (msg:\"Testing tag 1\"; content:\"Hi all\"; tag:host,3,seconds,src; sid:1;)";
|
|
sigs[1]= "alert tcp any any -> any any (msg:\"Testing tag 2\"; content:\"Hi all\"; tag:host,8,seconds,dst; sid:2;)";
|
|
sigs[2]= "alert tcp any any -> any any (msg:\"Testing tag 2\"; content:\"no match\"; sid:3;)";
|
|
sigs[3]= "alert tcp any any -> any any (msg:\"Testing tag 2\"; content:\"no match\"; sid:4;)";
|
|
sigs[4]= "alert tcp any any -> any any (msg:\"Testing tag 2\"; content:\"no match\"; sid:5;)";
|
|
|
|
/* Please, Notice that tagged data goes with sig_id = 1 and tag sig generator = 2 */
|
|
uint32_t sid[5] = {1,2,3,4,5};
|
|
int numsigs = 5;
|
|
|
|
if (UTHAppendSigs(de_ctx, sigs, numsigs) == 0)
|
|
goto cleanup;
|
|
|
|
//de_ctx->flags |= DE_QUIET;
|
|
|
|
int32_t results[7][5] = {
|
|
{1, 1, 0, 0, 0},
|
|
{0, 0, 0, 0, 0},
|
|
{0, 0, 0, 0, 0},
|
|
{0, 0, 0, 0, 0},
|
|
{0, 0, 0, 0, 0},
|
|
{0, 0, 0, 0, 0},
|
|
{0, 0, 0, 0, 0}
|
|
};
|
|
|
|
int num_packets = 7;
|
|
SigGroupBuild(de_ctx);
|
|
DetectEngineThreadCtxInit(&th_v, (void *)de_ctx, (void *)&det_ctx);
|
|
|
|
int i = 0;
|
|
for (; i < num_packets; i++) {
|
|
SCLogDebug("packet %d", i);
|
|
TimeGet(&p[i]->ts);
|
|
SigMatchSignatures(&th_v, de_ctx, det_ctx, p[i]);
|
|
if (UTHCheckPacketMatchResults(p[i], sid, (uint32_t *)&results[i][0], numsigs) == 0)
|
|
goto cleanup;
|
|
|
|
TimeSetIncrementTime(2);
|
|
SCLogDebug("packet %d flag %s", i, p[i]->flags & PKT_HAS_TAG ? "true" : "false");
|
|
|
|
/* see if the PKT_HAS_TAG is set on the packet if needed */
|
|
int expect;
|
|
if (i == 0 || i == 2 || i == 3 || i == 5 || i == 6)
|
|
expect = FALSE;
|
|
else
|
|
expect = TRUE;
|
|
if (((p[i]->flags & PKT_HAS_TAG) ? TRUE : FALSE) != expect)
|
|
goto cleanup;
|
|
}
|
|
|
|
result = 1;
|
|
|
|
cleanup:
|
|
UTHFreePackets(p, 7);
|
|
if (det_ctx != NULL)
|
|
DetectEngineThreadCtxDeinit(&th_v, (void *)det_ctx);
|
|
|
|
if (de_ctx != NULL) {
|
|
SigGroupCleanup(de_ctx);
|
|
SigCleanSignatures(de_ctx);
|
|
DetectEngineCtxFree(de_ctx);
|
|
}
|
|
end:
|
|
HostShutdown();
|
|
TagDestroyCtx();
|
|
StorageCleanup();
|
|
return result;
|
|
}
|
|
|
|
/**
|
|
* \test host tagging: bytes
|
|
*/
|
|
static int DetectTagTestPacket03 (void)
|
|
{
|
|
int result = 0;
|
|
uint8_t *buf = (uint8_t *)"Hi all!";
|
|
uint8_t *buf2 = (uint8_t *)"lalala!";
|
|
uint16_t buf_len = strlen((char *)buf);
|
|
uint16_t buf_len2 = strlen((char *)buf2);
|
|
|
|
DecodeThreadVars dtv;
|
|
ThreadVars th_v;
|
|
DetectEngineThreadCtx *det_ctx = NULL;
|
|
memset(&dtv, 0, sizeof(DecodeThreadVars));
|
|
memset(&th_v, 0, sizeof(th_v));
|
|
|
|
StorageInit();
|
|
TagInitCtx();
|
|
StorageFinalize();
|
|
HostInitConfig(1);
|
|
|
|
DetectEngineCtx *de_ctx = DetectEngineCtxInit();
|
|
if (de_ctx == NULL) {
|
|
goto end;
|
|
}
|
|
de_ctx->flags |= DE_QUIET;
|
|
|
|
Packet *p[7];
|
|
p[0] = UTHBuildPacketReal(buf, buf_len, IPPROTO_TCP,
|
|
"192.168.1.5", "192.168.1.1",
|
|
41424, 80);
|
|
p[1] = UTHBuildPacketReal(buf2, buf_len2, IPPROTO_TCP,
|
|
"192.168.1.5", "192.168.1.1",
|
|
41424, 80);
|
|
p[2] = UTHBuildPacketReal(buf2, buf_len2, IPPROTO_TCP,
|
|
"192.168.1.5", "192.168.1.9",
|
|
41424, 80);
|
|
p[3] = UTHBuildPacketReal(buf2, buf_len2, IPPROTO_TCP,
|
|
"192.168.1.5", "192.168.1.9",
|
|
41424, 80);
|
|
p[4] = UTHBuildPacketReal(buf2, buf_len2, IPPROTO_TCP,
|
|
"192.168.1.1", "192.168.1.9",
|
|
41424, 80);
|
|
p[5] = UTHBuildPacketReal(buf2, buf_len2, IPPROTO_TCP,
|
|
"192.168.1.1", "192.168.1.11",
|
|
41424, 80);
|
|
p[6] = UTHBuildPacketReal(buf2, buf_len2, IPPROTO_TCP,
|
|
"192.168.1.5", "192.168.1.11",
|
|
41424, 80);
|
|
|
|
char *sigs[5];
|
|
sigs[0]= "alert tcp any any -> any any (msg:\"Testing tag 1\"; content:\"Hi all\"; tag:host, 150, bytes, src; sid:1;)";
|
|
sigs[1]= "alert tcp any any -> any any (msg:\"Testing tag 2\"; content:\"Hi all\"; tag:host, 150, bytes, dst; sid:2;)";
|
|
sigs[2]= "alert tcp any any -> any any (msg:\"Testing tag 2\"; content:\"no match\"; sid:3;)";
|
|
sigs[3]= "alert tcp any any -> any any (msg:\"Testing tag 2\"; content:\"no match\"; sid:4;)";
|
|
sigs[4]= "alert tcp any any -> any any (msg:\"Testing tag 2\"; content:\"no match\"; sid:5;)";
|
|
|
|
/* Please, Notice that tagged data goes with sig_id = 1 and tag sig generator = 2 */
|
|
uint32_t sid[5] = {1,2,3,4,5};
|
|
int numsigs = 5;
|
|
|
|
if (UTHAppendSigs(de_ctx, sigs, numsigs) == 0)
|
|
goto cleanup;
|
|
|
|
int32_t results[7][5] = {
|
|
{1, 1, 0, 0, 0},
|
|
{0, 0, 0, 0, 0},
|
|
{0, 0, 0, 0, 0},
|
|
{0, 0, 0, 0, 0},
|
|
{0, 0, 0, 0, 0},
|
|
{0, 0, 0, 0, 0},
|
|
{0, 0, 0, 0, 0}
|
|
};
|
|
|
|
int num_packets = 7;
|
|
SigGroupBuild(de_ctx);
|
|
DetectEngineThreadCtxInit(&th_v, (void *)de_ctx, (void *)&det_ctx);
|
|
|
|
int i = 0;
|
|
for (; i < num_packets; i++) {
|
|
SigMatchSignatures(&th_v, de_ctx, det_ctx, p[i]);
|
|
|
|
if (UTHCheckPacketMatchResults(p[i], sid, (uint32_t *)&results[i][0], numsigs) == 0)
|
|
goto cleanup;
|
|
|
|
SCLogDebug("packet %d flag %s", i, p[i]->flags & PKT_HAS_TAG ? "true" : "false");
|
|
|
|
/* see if the PKT_HAS_TAG is set on the packet if needed */
|
|
int expect;
|
|
if (i == 0 || i == 3 || i == 5 || i == 6)
|
|
expect = FALSE;
|
|
else
|
|
expect = TRUE;
|
|
if (((p[i]->flags & PKT_HAS_TAG) ? TRUE : FALSE) != expect)
|
|
goto cleanup;
|
|
}
|
|
|
|
result = 1;
|
|
|
|
cleanup:
|
|
UTHFreePackets(p, 7);
|
|
if (det_ctx != NULL)
|
|
DetectEngineThreadCtxDeinit(&th_v, (void *)det_ctx);
|
|
|
|
if (de_ctx != NULL) {
|
|
SigGroupCleanup(de_ctx);
|
|
SigCleanSignatures(de_ctx);
|
|
DetectEngineCtxFree(de_ctx);
|
|
}
|
|
end:
|
|
HostShutdown();
|
|
TagDestroyCtx();
|
|
StorageCleanup();
|
|
return result;
|
|
}
|
|
|
|
/**
|
|
* \test session tagging: packets
|
|
*/
|
|
static int DetectTagTestPacket04 (void)
|
|
{
|
|
int result = 0;
|
|
uint8_t *buf = (uint8_t *)"Hi all!";
|
|
uint8_t *buf2 = (uint8_t *)"lalala!";
|
|
uint16_t buf_len = strlen((char *)buf);
|
|
uint16_t buf_len2 = strlen((char *)buf2);
|
|
|
|
Flow *f = NULL;
|
|
TcpSession ssn;
|
|
|
|
memset(&f, 0, sizeof(f));
|
|
memset(&ssn, 0, sizeof(ssn));
|
|
|
|
StorageInit();
|
|
TagInitCtx();
|
|
StorageFinalize();
|
|
HostInitConfig(1);
|
|
FlowInitConfig(1);
|
|
|
|
f = FlowAlloc();
|
|
BUG_ON(f == NULL);
|
|
FLOW_INITIALIZE(f);
|
|
f->protoctx = (void *)&ssn;
|
|
f->flags |= FLOW_IPV4;
|
|
if (inet_pton(AF_INET, "192.168.1.5", f->src.addr_data32) != 1)
|
|
goto end;
|
|
if (inet_pton(AF_INET, "192.168.1.1", f->dst.addr_data32) != 1)
|
|
goto end;
|
|
|
|
DecodeThreadVars dtv;
|
|
ThreadVars th_v;
|
|
DetectEngineThreadCtx *det_ctx = NULL;
|
|
memset(&dtv, 0, sizeof(DecodeThreadVars));
|
|
memset(&th_v, 0, sizeof(th_v));
|
|
|
|
DetectEngineCtx *de_ctx = DetectEngineCtxInit();
|
|
if (de_ctx == NULL) {
|
|
goto end;
|
|
}
|
|
de_ctx->flags |= DE_QUIET;
|
|
|
|
Packet *p[7];
|
|
p[0] = UTHBuildPacketReal(buf, buf_len, IPPROTO_TCP,
|
|
"192.168.1.5", "192.168.1.1",
|
|
41424, 80);
|
|
p[1] = UTHBuildPacketReal(buf2, buf_len2, IPPROTO_TCP,
|
|
"192.168.1.5", "192.168.1.1",
|
|
41424, 80);
|
|
p[2] = UTHBuildPacketReal(buf2, buf_len2, IPPROTO_TCP,
|
|
"192.168.1.5", "192.168.1.1",
|
|
41424, 80);
|
|
p[3] = UTHBuildPacketReal(buf2, buf_len2, IPPROTO_TCP,
|
|
"192.168.1.5", "192.168.1.1",
|
|
41424, 80);
|
|
p[4] = UTHBuildPacketReal(buf2, buf_len2, IPPROTO_TCP,
|
|
"192.168.1.1", "192.168.1.5",
|
|
80, 41424);
|
|
p[5] = UTHBuildPacketReal(buf2, buf_len2, IPPROTO_TCP,
|
|
"192.168.1.1", "192.168.1.5",
|
|
80, 41424);
|
|
p[6] = UTHBuildPacketReal(buf2, buf_len2, IPPROTO_TCP,
|
|
"192.168.1.5", "192.168.1.1",
|
|
80, 41424);
|
|
|
|
char *sigs[5];
|
|
sigs[0]= "alert tcp any any -> any any (msg:\"Testing tag 1\"; content:\"Hi all\"; tag:session,4,packets; sid:1;)";
|
|
sigs[1]= "alert tcp any any -> any any (msg:\"Testing tag 2\"; content:\"blahblah\"; sid:2;)";
|
|
sigs[2]= "alert tcp any any -> any any (msg:\"Testing tag 2\"; content:\"no match\"; sid:3;)";
|
|
sigs[3]= "alert tcp any any -> any any (msg:\"Testing tag 2\"; content:\"no match\"; sid:4;)";
|
|
sigs[4]= "alert tcp any any -> any any (msg:\"Testing tag 2\"; content:\"no match\"; sid:5;)";
|
|
|
|
/* Please, Notice that tagged data goes with sig_id = 1 and tag sig generator = 2 */
|
|
uint32_t sid[5] = {1,2,3,4,5};
|
|
int numsigs = 5;
|
|
|
|
if (UTHAppendSigs(de_ctx, sigs, numsigs) == 0)
|
|
goto cleanup;
|
|
|
|
int32_t results[7][5] = {
|
|
{1, 0, 0, 0, 0},
|
|
{0, 0, 0, 0, 0},
|
|
{0, 0, 0, 0, 0},
|
|
{0, 0, 0, 0, 0},
|
|
{0, 0, 0, 0, 0},
|
|
{0, 0, 0, 0, 0},
|
|
{0, 0, 0, 0, 0}
|
|
};
|
|
|
|
int num_packets = 7;
|
|
SigGroupBuild(de_ctx);
|
|
DetectEngineThreadCtxInit(&th_v, (void *)de_ctx, (void *)&det_ctx);
|
|
|
|
int i = 0;
|
|
for (; i < num_packets; i++) {
|
|
p[i]->flow = f;
|
|
p[i]->flow->protoctx = &ssn;
|
|
SigMatchSignatures(&th_v, de_ctx, det_ctx, p[i]);
|
|
|
|
if (UTHCheckPacketMatchResults(p[i], sid, (uint32_t *)&results[i][0], numsigs) == 0)
|
|
goto cleanup;
|
|
|
|
SCLogDebug("packet %d flag %s", i, p[i]->flags & PKT_HAS_TAG ? "true" : "false");
|
|
/* see if the PKT_HAS_TAG is set on the packet if needed */
|
|
int expect;
|
|
if (i == 0 || i == 4 || i == 5 || i == 6)
|
|
expect = FALSE;
|
|
else
|
|
expect = TRUE;
|
|
if (((p[i]->flags & PKT_HAS_TAG) ? TRUE : FALSE) != expect)
|
|
goto cleanup;
|
|
}
|
|
|
|
result = 1;
|
|
|
|
cleanup:
|
|
UTHFreePackets(p, 7);
|
|
if (det_ctx != NULL)
|
|
DetectEngineThreadCtxDeinit(&th_v, (void *)det_ctx);
|
|
|
|
if (de_ctx != NULL) {
|
|
SigGroupCleanup(de_ctx);
|
|
SigCleanSignatures(de_ctx);
|
|
DetectEngineCtxFree(de_ctx);
|
|
}
|
|
|
|
/* clean up flow */
|
|
uint8_t proto_map = FlowGetProtoMapping(f->proto);
|
|
FlowClearMemory(f, proto_map);
|
|
FLOW_DESTROY(f);
|
|
end:
|
|
FlowShutdown();
|
|
HostShutdown();
|
|
TagDestroyCtx();
|
|
StorageCleanup();
|
|
return result;
|
|
}
|
|
|
|
/**
|
|
* \test session tagging: seconds
|
|
*/
|
|
static int DetectTagTestPacket05 (void)
|
|
{
|
|
int result = 0;
|
|
uint8_t *buf = (uint8_t *)"Hi all!";
|
|
uint8_t *buf2 = (uint8_t *)"lalala!";
|
|
uint16_t buf_len = strlen((char *)buf);
|
|
uint16_t buf_len2 = strlen((char *)buf2);
|
|
|
|
Flow *f = NULL;
|
|
TcpSession ssn;
|
|
|
|
memset(&f, 0, sizeof(f));
|
|
memset(&ssn, 0, sizeof(ssn));
|
|
|
|
StorageInit();
|
|
TagInitCtx();
|
|
StorageFinalize();
|
|
HostInitConfig(1);
|
|
FlowInitConfig(1);
|
|
|
|
f = FlowAlloc();
|
|
BUG_ON(f == NULL);
|
|
FLOW_INITIALIZE(f);
|
|
f->protoctx = (void *)&ssn;
|
|
f->flags |= FLOW_IPV4;
|
|
if (inet_pton(AF_INET, "192.168.1.5", f->src.addr_data32) != 1)
|
|
goto end;
|
|
if (inet_pton(AF_INET, "192.168.1.1", f->dst.addr_data32) != 1)
|
|
goto end;
|
|
|
|
DecodeThreadVars dtv;
|
|
ThreadVars th_v;
|
|
DetectEngineThreadCtx *det_ctx = NULL;
|
|
memset(&dtv, 0, sizeof(DecodeThreadVars));
|
|
memset(&th_v, 0, sizeof(th_v));
|
|
|
|
DetectEngineCtx *de_ctx = DetectEngineCtxInit();
|
|
if (de_ctx == NULL) {
|
|
goto end;
|
|
}
|
|
de_ctx->flags |= DE_QUIET;
|
|
|
|
Packet *p[7];
|
|
p[0] = UTHBuildPacketReal(buf, buf_len, IPPROTO_TCP,
|
|
"192.168.1.5", "192.168.1.1",
|
|
41424, 80);
|
|
p[1] = UTHBuildPacketReal(buf2, buf_len2, IPPROTO_TCP,
|
|
"192.168.1.5", "192.168.1.1",
|
|
41424, 80);
|
|
p[2] = UTHBuildPacketReal(buf2, buf_len2, IPPROTO_TCP,
|
|
"192.168.1.5", "192.168.1.1",
|
|
41424, 80);
|
|
p[3] = UTHBuildPacketReal(buf2, buf_len2, IPPROTO_TCP,
|
|
"192.168.1.5", "192.168.1.1",
|
|
41424, 80);
|
|
p[4] = UTHBuildPacketReal(buf2, buf_len2, IPPROTO_TCP,
|
|
"192.168.1.1", "192.168.1.5",
|
|
80, 41424);
|
|
p[5] = UTHBuildPacketReal(buf2, buf_len2, IPPROTO_TCP,
|
|
"192.168.1.1", "192.168.1.5",
|
|
80, 41424);
|
|
p[6] = UTHBuildPacketReal(buf2, buf_len2, IPPROTO_TCP,
|
|
"192.168.1.5", "192.168.1.1",
|
|
80, 41424);
|
|
|
|
char *sigs[5];
|
|
sigs[0]= "alert tcp any any -> any any (msg:\"Testing tag 1\"; content:\"Hi all\"; tag:session,8,seconds; sid:1;)";
|
|
sigs[1]= "alert tcp any any -> any any (msg:\"Testing tag 2\"; content:\"blahblah\"; sid:2;)";
|
|
sigs[2]= "alert tcp any any -> any any (msg:\"Testing tag 2\"; content:\"no match\"; sid:3;)";
|
|
sigs[3]= "alert tcp any any -> any any (msg:\"Testing tag 2\"; content:\"no match\"; sid:4;)";
|
|
sigs[4]= "alert tcp any any -> any any (msg:\"Testing tag 2\"; content:\"no match\"; sid:5;)";
|
|
|
|
/* Please, Notice that tagged data goes with sig_id = 1 and tag sig generator = 2 */
|
|
uint32_t sid[5] = {1,2,3,4,5};
|
|
int numsigs = 5;
|
|
|
|
if (UTHAppendSigs(de_ctx, sigs, numsigs) == 0)
|
|
goto cleanup;
|
|
|
|
int32_t results[7][5] = {
|
|
{1, 0, 0, 0, 0},
|
|
{0, 0, 0, 0, 0},
|
|
{0, 0, 0, 0, 0},
|
|
{0, 0, 0, 0, 0},
|
|
{0, 0, 0, 0, 0},
|
|
{0, 0, 0, 0, 0},
|
|
{0, 0, 0, 0, 0}
|
|
};
|
|
|
|
int num_packets = 7;
|
|
SigGroupBuild(de_ctx);
|
|
DetectEngineThreadCtxInit(&th_v, (void *)de_ctx, (void *)&det_ctx);
|
|
|
|
int i = 0;
|
|
for (; i < num_packets; i++) {
|
|
p[i]->flow = f;
|
|
p[i]->flow->protoctx = &ssn;
|
|
|
|
SCLogDebug("packet %d", i);
|
|
TimeGet(&p[i]->ts);
|
|
SigMatchSignatures(&th_v, de_ctx, det_ctx, p[i]);
|
|
|
|
if (UTHCheckPacketMatchResults(p[i], sid, (uint32_t *)&results[i][0], numsigs) == 0)
|
|
goto cleanup;
|
|
|
|
TimeSetIncrementTime(2);
|
|
|
|
SCLogDebug("packet %d flag %s", i, p[i]->flags & PKT_HAS_TAG ? "true" : "false");
|
|
/* see if the PKT_HAS_TAG is set on the packet if needed */
|
|
int expect;
|
|
if (i == 0 || i == 5 || i == 6)
|
|
expect = FALSE;
|
|
else
|
|
expect = TRUE;
|
|
if (((p[i]->flags & PKT_HAS_TAG) ? TRUE : FALSE) != expect)
|
|
goto cleanup;
|
|
}
|
|
|
|
result = 1;
|
|
|
|
cleanup:
|
|
UTHFreePackets(p, 7);
|
|
if (det_ctx != NULL)
|
|
DetectEngineThreadCtxDeinit(&th_v, (void *)det_ctx);
|
|
|
|
if (de_ctx != NULL) {
|
|
SigGroupCleanup(de_ctx);
|
|
SigCleanSignatures(de_ctx);
|
|
DetectEngineCtxFree(de_ctx);
|
|
}
|
|
|
|
/* clean up flow */
|
|
uint8_t proto_map = FlowGetProtoMapping(f->proto);
|
|
FlowClearMemory(f, proto_map);
|
|
FLOW_DESTROY(f);
|
|
end:
|
|
FlowShutdown();
|
|
HostShutdown();
|
|
TagDestroyCtx();
|
|
StorageCleanup();
|
|
return result;
|
|
}
|
|
|
|
/**
|
|
* \test session tagging: bytes
|
|
*/
|
|
static int DetectTagTestPacket06 (void)
|
|
{
|
|
int result = 0;
|
|
uint8_t *buf = (uint8_t *)"Hi all!";
|
|
uint8_t *buf2 = (uint8_t *)"lalala!";
|
|
uint16_t buf_len = strlen((char *)buf);
|
|
uint16_t buf_len2 = strlen((char *)buf2);
|
|
|
|
Flow *f = NULL;
|
|
TcpSession ssn;
|
|
|
|
memset(&f, 0, sizeof(f));
|
|
memset(&ssn, 0, sizeof(ssn));
|
|
|
|
StorageInit();
|
|
TagInitCtx();
|
|
StorageFinalize();
|
|
HostInitConfig(1);
|
|
FlowInitConfig(1);
|
|
|
|
f = FlowAlloc();
|
|
BUG_ON(f == NULL);
|
|
FLOW_INITIALIZE(f);
|
|
f->protoctx = (void *)&ssn;
|
|
f->flags |= FLOW_IPV4;
|
|
if (inet_pton(AF_INET, "192.168.1.5", f->src.addr_data32) != 1)
|
|
goto end;
|
|
if (inet_pton(AF_INET, "192.168.1.1", f->dst.addr_data32) != 1)
|
|
goto end;
|
|
|
|
DecodeThreadVars dtv;
|
|
ThreadVars th_v;
|
|
DetectEngineThreadCtx *det_ctx = NULL;
|
|
memset(&dtv, 0, sizeof(DecodeThreadVars));
|
|
memset(&th_v, 0, sizeof(th_v));
|
|
|
|
DetectEngineCtx *de_ctx = DetectEngineCtxInit();
|
|
if (de_ctx == NULL) {
|
|
goto end;
|
|
}
|
|
de_ctx->flags |= DE_QUIET;
|
|
|
|
Packet *p[7];
|
|
p[0] = UTHBuildPacketReal(buf, buf_len, IPPROTO_TCP,
|
|
"192.168.1.5", "192.168.1.1",
|
|
41424, 80);
|
|
p[1] = UTHBuildPacketReal(buf2, buf_len2, IPPROTO_TCP,
|
|
"192.168.1.5", "192.168.1.1",
|
|
41424, 80);
|
|
p[2] = UTHBuildPacketReal(buf2, buf_len2, IPPROTO_TCP,
|
|
"192.168.1.5", "192.168.1.1",
|
|
41424, 80);
|
|
p[3] = UTHBuildPacketReal(buf2, buf_len2, IPPROTO_TCP,
|
|
"192.168.1.5", "192.168.1.1",
|
|
41424, 80);
|
|
p[4] = UTHBuildPacketReal(buf2, buf_len2, IPPROTO_TCP,
|
|
"192.168.1.1", "192.168.1.5",
|
|
80, 41424);
|
|
p[5] = UTHBuildPacketReal(buf2, buf_len2, IPPROTO_TCP,
|
|
"192.168.1.1", "192.168.1.5",
|
|
80, 41424);
|
|
p[6] = UTHBuildPacketReal(buf2, buf_len2, IPPROTO_TCP,
|
|
"192.168.1.5", "192.168.1.1",
|
|
80, 41424);
|
|
|
|
char *sigs[5];
|
|
sigs[0]= "alert tcp any any -> any any (msg:\"Testing tag 1\"; content:\"Hi all\"; tag:session,150,bytes; sid:1;)";
|
|
sigs[1]= "alert tcp any any -> any any (msg:\"Testing tag 2\"; content:\"blahblah\"; sid:2;)";
|
|
sigs[2]= "alert tcp any any -> any any (msg:\"Testing tag 2\"; content:\"no match\"; sid:3;)";
|
|
sigs[3]= "alert tcp any any -> any any (msg:\"Testing tag 2\"; content:\"no match\"; sid:4;)";
|
|
sigs[4]= "alert tcp any any -> any any (msg:\"Testing tag 2\"; content:\"no match\"; sid:5;)";
|
|
|
|
/* Please, Notice that tagged data goes with sig_id = 1 and tag sig generator = 2 */
|
|
uint32_t sid[5] = {1,2,3,4,5};
|
|
int numsigs = 5;
|
|
|
|
if (UTHAppendSigs(de_ctx, sigs, numsigs) == 0)
|
|
goto cleanup;
|
|
|
|
int32_t results[7][5] = {
|
|
{1, 0, 0, 0, 0},
|
|
{0, 0, 0, 0, 0},
|
|
{0, 0, 0, 0, 0},
|
|
{0, 0, 0, 0, 0},
|
|
{0, 0, 0, 0, 0},
|
|
{0, 0, 0, 0, 0},
|
|
{0, 0, 0, 0, 0}
|
|
};
|
|
|
|
int num_packets = 7;
|
|
SigGroupBuild(de_ctx);
|
|
DetectEngineThreadCtxInit(&th_v, (void *)de_ctx, (void *)&det_ctx);
|
|
|
|
int i = 0;
|
|
for (; i < num_packets; i++) {
|
|
p[i]->flow = f;
|
|
p[i]->flow->protoctx = &ssn;
|
|
SigMatchSignatures(&th_v, de_ctx, det_ctx, p[i]);
|
|
|
|
if (UTHCheckPacketMatchResults(p[i], sid, (uint32_t *)&results[i][0], numsigs) == 0)
|
|
goto cleanup;
|
|
|
|
SCLogDebug("packet %d flag %s", i, p[i]->flags & PKT_HAS_TAG ? "true" : "false");
|
|
|
|
/* see if the PKT_HAS_TAG is set on the packet if needed */
|
|
int expect;
|
|
if (i == 0 || i == 3 || i == 4 || i == 5 || i == 6)
|
|
expect = FALSE;
|
|
else
|
|
expect = TRUE;
|
|
if (((p[i]->flags & PKT_HAS_TAG) ? TRUE : FALSE) != expect)
|
|
goto cleanup;
|
|
}
|
|
|
|
result = 1;
|
|
|
|
cleanup:
|
|
UTHFreePackets(p, 7);
|
|
if (det_ctx != NULL)
|
|
DetectEngineThreadCtxDeinit(&th_v, (void *)det_ctx);
|
|
|
|
if (de_ctx != NULL) {
|
|
SigGroupCleanup(de_ctx);
|
|
SigCleanSignatures(de_ctx);
|
|
DetectEngineCtxFree(de_ctx);
|
|
}
|
|
|
|
/* clean up flow */
|
|
uint8_t proto_map = FlowGetProtoMapping(f->proto);
|
|
FlowClearMemory(f, proto_map);
|
|
FLOW_DESTROY(f);
|
|
end:
|
|
FlowShutdown();
|
|
HostShutdown();
|
|
TagDestroyCtx();
|
|
StorageCleanup();
|
|
return result;
|
|
}
|
|
|
|
/**
|
|
* \test session tagging: bytes, where a 2nd match makes us tag more
|
|
*/
|
|
static int DetectTagTestPacket07 (void)
|
|
{
|
|
int result = 0;
|
|
uint8_t *buf = (uint8_t *)"Hi all!";
|
|
uint8_t *buf2 = (uint8_t *)"lalala!";
|
|
uint16_t buf_len = strlen((char *)buf);
|
|
uint16_t buf_len2 = strlen((char *)buf2);
|
|
|
|
Flow *f = NULL;
|
|
TcpSession ssn;
|
|
|
|
memset(&f, 0, sizeof(f));
|
|
memset(&ssn, 0, sizeof(ssn));
|
|
|
|
StorageInit();
|
|
TagInitCtx();
|
|
StorageFinalize();
|
|
HostInitConfig(1);
|
|
FlowInitConfig(1);
|
|
|
|
f = FlowAlloc();
|
|
BUG_ON(f == NULL);
|
|
FLOW_INITIALIZE(f);
|
|
f->protoctx = (void *)&ssn;
|
|
f->flags |= FLOW_IPV4;
|
|
if (inet_pton(AF_INET, "192.168.1.5", f->src.addr_data32) != 1)
|
|
goto end;
|
|
if (inet_pton(AF_INET, "192.168.1.1", f->dst.addr_data32) != 1)
|
|
goto end;
|
|
|
|
DecodeThreadVars dtv;
|
|
ThreadVars th_v;
|
|
DetectEngineThreadCtx *det_ctx = NULL;
|
|
memset(&dtv, 0, sizeof(DecodeThreadVars));
|
|
memset(&th_v, 0, sizeof(th_v));
|
|
|
|
DetectEngineCtx *de_ctx = DetectEngineCtxInit();
|
|
if (de_ctx == NULL) {
|
|
goto end;
|
|
}
|
|
de_ctx->flags |= DE_QUIET;
|
|
|
|
Packet *p[7];
|
|
p[0] = UTHBuildPacketReal(buf, buf_len, IPPROTO_TCP,
|
|
"192.168.1.5", "192.168.1.1",
|
|
41424, 80);
|
|
p[1] = UTHBuildPacketReal(buf2, buf_len2, IPPROTO_TCP,
|
|
"192.168.1.5", "192.168.1.1",
|
|
41424, 80);
|
|
p[2] = UTHBuildPacketReal(buf2, buf_len2, IPPROTO_TCP,
|
|
"192.168.1.5", "192.168.1.1",
|
|
41424, 80);
|
|
p[3] = UTHBuildPacketReal(buf, buf_len, IPPROTO_TCP,
|
|
"192.168.1.5", "192.168.1.1",
|
|
41424, 80);
|
|
p[4] = UTHBuildPacketReal(buf2, buf_len2, IPPROTO_TCP,
|
|
"192.168.1.1", "192.168.1.5",
|
|
80, 41424);
|
|
p[5] = UTHBuildPacketReal(buf2, buf_len2, IPPROTO_TCP,
|
|
"192.168.1.1", "192.168.1.5",
|
|
80, 41424);
|
|
p[6] = UTHBuildPacketReal(buf2, buf_len2, IPPROTO_TCP,
|
|
"192.168.1.5", "192.168.1.1",
|
|
80, 41424);
|
|
|
|
char *sigs[5];
|
|
sigs[0]= "alert tcp any any -> any any (msg:\"Testing tag 1\"; content:\"Hi all\"; tag:session,150,bytes; sid:1;)";
|
|
sigs[1]= "alert tcp any any -> any any (msg:\"Testing tag 2\"; content:\"blahblah\"; sid:2;)";
|
|
sigs[2]= "alert tcp any any -> any any (msg:\"Testing tag 2\"; content:\"no match\"; sid:3;)";
|
|
sigs[3]= "alert tcp any any -> any any (msg:\"Testing tag 2\"; content:\"no match\"; sid:4;)";
|
|
sigs[4]= "alert tcp any any -> any any (msg:\"Testing tag 2\"; content:\"no match\"; sid:5;)";
|
|
|
|
/* Please, Notice that tagged data goes with sig_id = 1 and tag sig generator = 2 */
|
|
uint32_t sid[5] = {1,2,3,4,5};
|
|
int numsigs = 5;
|
|
|
|
if (UTHAppendSigs(de_ctx, sigs, numsigs) == 0)
|
|
goto cleanup;
|
|
|
|
int32_t results[7][5] = {
|
|
{1, 0, 0, 0, 0},
|
|
{0, 0, 0, 0, 0},
|
|
{0, 0, 0, 0, 0},
|
|
{1, 0, 0, 0, 0},
|
|
{0, 0, 0, 0, 0},
|
|
{0, 0, 0, 0, 0},
|
|
{0, 0, 0, 0, 0}
|
|
};
|
|
|
|
int num_packets = 7;
|
|
SigGroupBuild(de_ctx);
|
|
DetectEngineThreadCtxInit(&th_v, (void *)de_ctx, (void *)&det_ctx);
|
|
|
|
int i = 0;
|
|
for (; i < num_packets; i++) {
|
|
p[i]->flow = f;
|
|
p[i]->flow->protoctx = &ssn;
|
|
SigMatchSignatures(&th_v, de_ctx, det_ctx, p[i]);
|
|
|
|
if (UTHCheckPacketMatchResults(p[i], sid, (uint32_t *)&results[i][0], numsigs) == 0)
|
|
goto cleanup;
|
|
|
|
SCLogDebug("packet %d flag %s", i, p[i]->flags & PKT_HAS_TAG ? "true" : "false");
|
|
#if 1
|
|
/* see if the PKT_HAS_TAG is set on the packet if needed */
|
|
int expect;
|
|
if (i == 0 || i == 6)
|
|
expect = FALSE;
|
|
else
|
|
expect = TRUE;
|
|
if (((p[i]->flags & PKT_HAS_TAG) ? TRUE : FALSE) != expect)
|
|
goto cleanup;
|
|
#endif
|
|
}
|
|
|
|
result = 1;
|
|
|
|
cleanup:
|
|
UTHFreePackets(p, 7);
|
|
if (det_ctx != NULL)
|
|
DetectEngineThreadCtxDeinit(&th_v, (void *)det_ctx);
|
|
|
|
if (de_ctx != NULL) {
|
|
SigGroupCleanup(de_ctx);
|
|
SigCleanSignatures(de_ctx);
|
|
DetectEngineCtxFree(de_ctx);
|
|
}
|
|
|
|
/* clean up flow */
|
|
uint8_t proto_map = FlowGetProtoMapping(f->proto);
|
|
FlowClearMemory(f, proto_map);
|
|
FLOW_DESTROY(f);
|
|
end:
|
|
FlowShutdown();
|
|
HostShutdown();
|
|
TagDestroyCtx();
|
|
StorageCleanup();
|
|
return result;
|
|
}
|
|
|
|
#endif /* UNITTESTS */
|
|
|
|
/**
|
|
* \brief this function registers unit tests for DetectTag
|
|
*/
|
|
void DetectEngineTagRegisterTests(void)
|
|
{
|
|
#ifdef UNITTESTS
|
|
UtRegisterTest("DetectTagTestPacket01", DetectTagTestPacket01);
|
|
UtRegisterTest("DetectTagTestPacket02", DetectTagTestPacket02);
|
|
UtRegisterTest("DetectTagTestPacket03", DetectTagTestPacket03);
|
|
UtRegisterTest("DetectTagTestPacket04", DetectTagTestPacket04);
|
|
UtRegisterTest("DetectTagTestPacket05", DetectTagTestPacket05);
|
|
UtRegisterTest("DetectTagTestPacket06", DetectTagTestPacket06);
|
|
UtRegisterTest("DetectTagTestPacket07", DetectTagTestPacket07);
|
|
#endif /* UNITTESTS */
|
|
}
|
|
|