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.
714 lines
24 KiB
C
714 lines
24 KiB
C
/* Copyright (C) 2007-2025 Open Information Security Foundation
|
|
*
|
|
* You can copy, redistribute or modify this Program under the terms of
|
|
* the GNU General Public License version 2 as published by the Free
|
|
* Software Foundation.
|
|
*
|
|
* This program is distributed in the hope that it will be useful,
|
|
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
|
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
|
* GNU General Public License for more details.
|
|
*
|
|
* You should have received a copy of the GNU General Public License
|
|
* version 2 along with this program; if not, write to the Free Software
|
|
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
|
|
* 02110-1301, USA.
|
|
*/
|
|
|
|
/**
|
|
* \file
|
|
*
|
|
* \author Anoop Saldanha <anoopsaldanha@gmail.com>
|
|
*/
|
|
|
|
#include "suricata-common.h"
|
|
#include "detect-engine.h"
|
|
#include "detect-engine-build.h"
|
|
#include "detect-engine-prefilter.h"
|
|
#include "detect-engine-prefilter-common.h"
|
|
#include "detect-parse.h"
|
|
#include "detect-app-layer-protocol.h"
|
|
#include "app-layer.h"
|
|
#include "app-layer-parser.h"
|
|
#include "util-debug.h"
|
|
#include "util-unittest.h"
|
|
#include "util-unittest-helper.h"
|
|
|
|
#ifdef UNITTESTS
|
|
static void DetectAppLayerProtocolRegisterTests(void);
|
|
#endif
|
|
|
|
enum {
|
|
DETECT_ALPROTO_DIRECTION = 0,
|
|
DETECT_ALPROTO_FINAL = 1,
|
|
DETECT_ALPROTO_EITHER = 2,
|
|
DETECT_ALPROTO_TOSERVER = 3,
|
|
DETECT_ALPROTO_TOCLIENT = 4,
|
|
DETECT_ALPROTO_ORIG = 5,
|
|
};
|
|
|
|
typedef struct DetectAppLayerProtocolData_ {
|
|
AppProto alproto;
|
|
uint8_t negated;
|
|
uint8_t mode;
|
|
} DetectAppLayerProtocolData;
|
|
|
|
static int DetectAppLayerProtocolPacketMatch(
|
|
DetectEngineThreadCtx *det_ctx,
|
|
Packet *p, const Signature *s, const SigMatchCtx *ctx)
|
|
{
|
|
SCEnter();
|
|
|
|
bool r = false;
|
|
const DetectAppLayerProtocolData *data = (const DetectAppLayerProtocolData *)ctx;
|
|
|
|
/* if the sig is PD-only we only match when PD packet flags are set */
|
|
if (s->type == SIG_TYPE_PDONLY &&
|
|
(p->flags & (PKT_PROTO_DETECT_TS_DONE | PKT_PROTO_DETECT_TC_DONE)) == 0) {
|
|
SCLogDebug("packet %"PRIu64": flags not set", p->pcap_cnt);
|
|
SCReturnInt(0);
|
|
}
|
|
|
|
const Flow *f = p->flow;
|
|
if (f == NULL) {
|
|
SCLogDebug("packet %"PRIu64": no flow", p->pcap_cnt);
|
|
SCReturnInt(0);
|
|
}
|
|
|
|
switch (data->mode) {
|
|
case DETECT_ALPROTO_DIRECTION:
|
|
if (data->negated) {
|
|
if (p->flowflags & FLOW_PKT_TOSERVER) {
|
|
if (f->alproto_ts == ALPROTO_UNKNOWN)
|
|
SCReturnInt(0);
|
|
r = AppProtoEquals(data->alproto, f->alproto_ts);
|
|
} else {
|
|
if (f->alproto_tc == ALPROTO_UNKNOWN)
|
|
SCReturnInt(0);
|
|
r = AppProtoEquals(data->alproto, f->alproto_tc);
|
|
}
|
|
} else {
|
|
if (p->flowflags & FLOW_PKT_TOSERVER) {
|
|
r = AppProtoEquals(data->alproto, f->alproto_ts);
|
|
} else {
|
|
r = AppProtoEquals(data->alproto, f->alproto_tc);
|
|
}
|
|
}
|
|
break;
|
|
case DETECT_ALPROTO_ORIG:
|
|
if (data->negated) {
|
|
if (f->alproto_orig == ALPROTO_UNKNOWN)
|
|
SCReturnInt(0);
|
|
r = AppProtoEquals(data->alproto, f->alproto_orig);
|
|
} else {
|
|
r = AppProtoEquals(data->alproto, f->alproto_orig);
|
|
}
|
|
break;
|
|
case DETECT_ALPROTO_FINAL:
|
|
if (data->negated) {
|
|
if (f->alproto == ALPROTO_UNKNOWN)
|
|
SCReturnInt(0);
|
|
r = AppProtoEquals(data->alproto, f->alproto);
|
|
} else {
|
|
r = AppProtoEquals(data->alproto, f->alproto);
|
|
}
|
|
break;
|
|
case DETECT_ALPROTO_TOSERVER:
|
|
if (data->negated) {
|
|
if (f->alproto_ts == ALPROTO_UNKNOWN)
|
|
SCReturnInt(0);
|
|
r = AppProtoEquals(data->alproto, f->alproto_ts);
|
|
} else {
|
|
r = AppProtoEquals(data->alproto, f->alproto_ts);
|
|
}
|
|
break;
|
|
case DETECT_ALPROTO_TOCLIENT:
|
|
if (data->negated) {
|
|
if (f->alproto_tc == ALPROTO_UNKNOWN)
|
|
SCReturnInt(0);
|
|
r = AppProtoEquals(data->alproto, f->alproto_tc);
|
|
} else {
|
|
r = AppProtoEquals(data->alproto, f->alproto_tc);
|
|
}
|
|
break;
|
|
case DETECT_ALPROTO_EITHER:
|
|
if (data->negated) {
|
|
if (f->alproto_ts == ALPROTO_UNKNOWN && f->alproto_tc == ALPROTO_UNKNOWN)
|
|
SCReturnInt(0);
|
|
r = AppProtoEquals(data->alproto, f->alproto_tc) ||
|
|
AppProtoEquals(data->alproto, f->alproto_ts);
|
|
} else {
|
|
r = AppProtoEquals(data->alproto, f->alproto_tc) ||
|
|
AppProtoEquals(data->alproto, f->alproto_ts);
|
|
}
|
|
break;
|
|
}
|
|
r = r ^ data->negated;
|
|
if (r) {
|
|
SCReturnInt(1);
|
|
}
|
|
SCReturnInt(0);
|
|
}
|
|
|
|
#define MAX_ALPROTO_NAME 50
|
|
static DetectAppLayerProtocolData *DetectAppLayerProtocolParse(const char *arg, bool negate)
|
|
{
|
|
DetectAppLayerProtocolData *data;
|
|
AppProto alproto = ALPROTO_UNKNOWN;
|
|
|
|
char alproto_copy[MAX_ALPROTO_NAME];
|
|
char *sep = strchr(arg, ',');
|
|
char *alproto_name;
|
|
if (sep && sep - arg < MAX_ALPROTO_NAME) {
|
|
strlcpy(alproto_copy, arg, sep - arg + 1);
|
|
alproto_name = alproto_copy;
|
|
} else {
|
|
alproto_name = (char *)arg;
|
|
}
|
|
if (strcmp(alproto_name, "failed") == 0) {
|
|
alproto = ALPROTO_FAILED;
|
|
} else if (strcmp(alproto_name, "unknown") == 0) {
|
|
if (negate) {
|
|
SCLogError("app-layer-protocol "
|
|
"keyword can't use negation with protocol 'unknown'");
|
|
return NULL;
|
|
}
|
|
alproto = ALPROTO_UNKNOWN;
|
|
} else {
|
|
alproto = AppLayerGetProtoByName(alproto_name);
|
|
if (alproto == ALPROTO_UNKNOWN) {
|
|
SCLogError("app-layer-protocol "
|
|
"keyword supplied with unknown protocol \"%s\"",
|
|
alproto_name);
|
|
return NULL;
|
|
}
|
|
}
|
|
uint8_t mode = DETECT_ALPROTO_DIRECTION;
|
|
if (sep) {
|
|
if (strcmp(sep + 1, "final") == 0) {
|
|
mode = DETECT_ALPROTO_FINAL;
|
|
} else if (strcmp(sep + 1, "original") == 0) {
|
|
mode = DETECT_ALPROTO_ORIG;
|
|
} else if (strcmp(sep + 1, "either") == 0) {
|
|
mode = DETECT_ALPROTO_EITHER;
|
|
} else if (strcmp(sep + 1, "to_server") == 0) {
|
|
mode = DETECT_ALPROTO_TOSERVER;
|
|
} else if (strcmp(sep + 1, "to_client") == 0) {
|
|
mode = DETECT_ALPROTO_TOCLIENT;
|
|
} else if (strcmp(sep + 1, "direction") == 0) {
|
|
mode = DETECT_ALPROTO_DIRECTION;
|
|
} else {
|
|
SCLogError("app-layer-protocol "
|
|
"keyword supplied with unknown mode \"%s\"",
|
|
sep + 1);
|
|
return NULL;
|
|
}
|
|
}
|
|
|
|
data = SCMalloc(sizeof(DetectAppLayerProtocolData));
|
|
if (unlikely(data == NULL))
|
|
return NULL;
|
|
data->alproto = alproto;
|
|
data->negated = negate;
|
|
data->mode = mode;
|
|
|
|
return data;
|
|
}
|
|
|
|
static bool HasConflicts(const DetectAppLayerProtocolData *us,
|
|
const DetectAppLayerProtocolData *them)
|
|
{
|
|
/* mixing negated and non negated is illegal */
|
|
if ((them->negated ^ us->negated) && them->mode == us->mode)
|
|
return true;
|
|
/* multiple non-negated is illegal */
|
|
if (!us->negated && them->mode == us->mode)
|
|
return true;
|
|
/* duplicate option */
|
|
if (us->alproto == them->alproto && them->mode == us->mode)
|
|
return true;
|
|
|
|
/* all good */
|
|
return false;
|
|
}
|
|
|
|
static int DetectAppLayerProtocolSetup(DetectEngineCtx *de_ctx,
|
|
Signature *s, const char *arg)
|
|
{
|
|
DetectAppLayerProtocolData *data = NULL;
|
|
|
|
if (s->alproto != ALPROTO_UNKNOWN) {
|
|
SCLogError("Either we already "
|
|
"have the rule match on an app layer protocol set through "
|
|
"other keywords that match on this protocol, or have "
|
|
"already seen a non-negated app-layer-protocol.");
|
|
goto error;
|
|
}
|
|
|
|
data = DetectAppLayerProtocolParse(arg, s->init_data->negated);
|
|
if (data == NULL)
|
|
goto error;
|
|
|
|
SigMatch *tsm = s->init_data->smlists[DETECT_SM_LIST_MATCH];
|
|
for ( ; tsm != NULL; tsm = tsm->next) {
|
|
if (tsm->type == DETECT_APP_LAYER_PROTOCOL) {
|
|
const DetectAppLayerProtocolData *them = (const DetectAppLayerProtocolData *)tsm->ctx;
|
|
|
|
if (HasConflicts(data, them)) {
|
|
SCLogError("can't mix "
|
|
"positive app-layer-protocol match with negated "
|
|
"match or match for 'failed'.");
|
|
goto error;
|
|
}
|
|
}
|
|
}
|
|
|
|
if (SigMatchAppendSMToList(de_ctx, s, DETECT_APP_LAYER_PROTOCOL, (SigMatchCtx *)data,
|
|
DETECT_SM_LIST_MATCH) == NULL) {
|
|
goto error;
|
|
}
|
|
return 0;
|
|
|
|
error:
|
|
if (data != NULL)
|
|
SCFree(data);
|
|
return -1;
|
|
}
|
|
|
|
static void DetectAppLayerProtocolFree(DetectEngineCtx *de_ctx, void *ptr)
|
|
{
|
|
SCFree(ptr);
|
|
}
|
|
|
|
/** \internal
|
|
* \brief prefilter function for protocol detect matching
|
|
*/
|
|
static void
|
|
PrefilterPacketAppProtoMatch(DetectEngineThreadCtx *det_ctx, Packet *p, const void *pectx)
|
|
{
|
|
const PrefilterPacketHeaderCtx *ctx = pectx;
|
|
|
|
if (!PrefilterPacketHeaderExtraMatch(ctx, p)) {
|
|
SCLogDebug("packet %"PRIu64": extra match failed", p->pcap_cnt);
|
|
SCReturn;
|
|
}
|
|
|
|
if (p->flow == NULL) {
|
|
SCLogDebug("packet %"PRIu64": no flow, no alproto", p->pcap_cnt);
|
|
SCReturn;
|
|
}
|
|
|
|
if ((p->flags & (PKT_PROTO_DETECT_TS_DONE|PKT_PROTO_DETECT_TC_DONE)) == 0) {
|
|
SCLogDebug("packet %"PRIu64": flags not set", p->pcap_cnt);
|
|
SCReturn;
|
|
}
|
|
|
|
Flow *f = p->flow;
|
|
AppProto alproto = ALPROTO_UNKNOWN;
|
|
bool negated = (bool)ctx->v1.u8[2];
|
|
switch (ctx->v1.u8[3]) {
|
|
case DETECT_ALPROTO_DIRECTION:
|
|
if (p->flowflags & FLOW_PKT_TOSERVER) {
|
|
alproto = f->alproto_ts;
|
|
} else {
|
|
alproto = f->alproto_tc;
|
|
}
|
|
break;
|
|
case DETECT_ALPROTO_ORIG:
|
|
alproto = f->alproto_orig;
|
|
break;
|
|
case DETECT_ALPROTO_FINAL:
|
|
alproto = f->alproto;
|
|
break;
|
|
case DETECT_ALPROTO_TOSERVER:
|
|
alproto = f->alproto_ts;
|
|
break;
|
|
case DETECT_ALPROTO_TOCLIENT:
|
|
alproto = f->alproto_tc;
|
|
break;
|
|
case DETECT_ALPROTO_EITHER:
|
|
// check if either protocol toclient or toserver matches
|
|
// the one in the signature ctx
|
|
if (negated) {
|
|
if (f->alproto_tc != ALPROTO_UNKNOWN &&
|
|
!AppProtoEquals(ctx->v1.u16[0], f->alproto_tc)) {
|
|
PrefilterAddSids(&det_ctx->pmq, ctx->sigs_array, ctx->sigs_cnt);
|
|
} else if (f->alproto_ts != ALPROTO_UNKNOWN &&
|
|
!AppProtoEquals(ctx->v1.u16[0], f->alproto_ts)) {
|
|
PrefilterAddSids(&det_ctx->pmq, ctx->sigs_array, ctx->sigs_cnt);
|
|
}
|
|
} else {
|
|
if (AppProtoEquals(ctx->v1.u16[0], f->alproto_tc) ||
|
|
AppProtoEquals(ctx->v1.u16[0], f->alproto_ts)) {
|
|
PrefilterAddSids(&det_ctx->pmq, ctx->sigs_array, ctx->sigs_cnt);
|
|
}
|
|
}
|
|
// We return right away to avoid calling PrefilterAddSids again
|
|
return;
|
|
}
|
|
|
|
if (negated) {
|
|
if (alproto != ALPROTO_UNKNOWN) {
|
|
if (!AppProtoEquals(ctx->v1.u16[0], alproto)) {
|
|
PrefilterAddSids(&det_ctx->pmq, ctx->sigs_array, ctx->sigs_cnt);
|
|
}
|
|
}
|
|
} else {
|
|
if (AppProtoEquals(ctx->v1.u16[0], alproto)) {
|
|
PrefilterAddSids(&det_ctx->pmq, ctx->sigs_array, ctx->sigs_cnt);
|
|
}
|
|
}
|
|
}
|
|
|
|
static void
|
|
PrefilterPacketAppProtoSet(PrefilterPacketHeaderValue *v, void *smctx)
|
|
{
|
|
const DetectAppLayerProtocolData *a = smctx;
|
|
v->u16[0] = a->alproto;
|
|
v->u8[2] = (uint8_t)a->negated;
|
|
v->u8[3] = a->mode;
|
|
}
|
|
|
|
static bool
|
|
PrefilterPacketAppProtoCompare(PrefilterPacketHeaderValue v, void *smctx)
|
|
{
|
|
const DetectAppLayerProtocolData *a = smctx;
|
|
if (v.u16[0] == a->alproto && v.u8[2] == (uint8_t)a->negated && v.u8[3] == a->mode)
|
|
return true;
|
|
return false;
|
|
}
|
|
|
|
static int PrefilterSetupAppProto(DetectEngineCtx *de_ctx, SigGroupHead *sgh)
|
|
{
|
|
return PrefilterSetupPacketHeader(de_ctx, sgh, DETECT_APP_LAYER_PROTOCOL, SIG_MASK_REQUIRE_FLOW,
|
|
PrefilterPacketAppProtoSet, PrefilterPacketAppProtoCompare,
|
|
PrefilterPacketAppProtoMatch);
|
|
}
|
|
|
|
static bool PrefilterAppProtoIsPrefilterable(const Signature *s)
|
|
{
|
|
if (s->type == SIG_TYPE_PDONLY) {
|
|
SCLogDebug("prefilter on PD %u", s->id);
|
|
return true;
|
|
}
|
|
return false;
|
|
}
|
|
|
|
void DetectAppLayerProtocolRegister(void)
|
|
{
|
|
sigmatch_table[DETECT_APP_LAYER_PROTOCOL].name = "app-layer-protocol";
|
|
sigmatch_table[DETECT_APP_LAYER_PROTOCOL].desc = "match on the detected app-layer protocol";
|
|
sigmatch_table[DETECT_APP_LAYER_PROTOCOL].url = "/rules/app-layer.html#app-layer-protocol";
|
|
sigmatch_table[DETECT_APP_LAYER_PROTOCOL].Match = DetectAppLayerProtocolPacketMatch;
|
|
sigmatch_table[DETECT_APP_LAYER_PROTOCOL].Setup = DetectAppLayerProtocolSetup;
|
|
sigmatch_table[DETECT_APP_LAYER_PROTOCOL].Free = DetectAppLayerProtocolFree;
|
|
#ifdef UNITTESTS
|
|
sigmatch_table[DETECT_APP_LAYER_PROTOCOL].RegisterTests = DetectAppLayerProtocolRegisterTests;
|
|
#endif
|
|
sigmatch_table[DETECT_APP_LAYER_PROTOCOL].flags =
|
|
(SIGMATCH_QUOTES_OPTIONAL | SIGMATCH_HANDLE_NEGATION | SIGMATCH_SUPPORT_FIREWALL);
|
|
|
|
sigmatch_table[DETECT_APP_LAYER_PROTOCOL].SetupPrefilter = PrefilterSetupAppProto;
|
|
sigmatch_table[DETECT_APP_LAYER_PROTOCOL].SupportsPrefilter = PrefilterAppProtoIsPrefilterable;
|
|
}
|
|
|
|
/**********************************Unittests***********************************/
|
|
|
|
#ifdef UNITTESTS
|
|
|
|
static int DetectAppLayerProtocolTest01(void)
|
|
{
|
|
DetectAppLayerProtocolData *data = DetectAppLayerProtocolParse("http", false);
|
|
FAIL_IF_NULL(data);
|
|
FAIL_IF(data->alproto != ALPROTO_HTTP);
|
|
FAIL_IF(data->negated != 0);
|
|
DetectAppLayerProtocolFree(NULL, data);
|
|
PASS;
|
|
}
|
|
|
|
static int DetectAppLayerProtocolTest02(void)
|
|
{
|
|
DetectAppLayerProtocolData *data = DetectAppLayerProtocolParse("http", true);
|
|
FAIL_IF_NULL(data);
|
|
FAIL_IF(data->alproto != ALPROTO_HTTP);
|
|
FAIL_IF(data->negated == 0);
|
|
DetectAppLayerProtocolFree(NULL, data);
|
|
PASS;
|
|
}
|
|
|
|
static int DetectAppLayerProtocolTest03(void)
|
|
{
|
|
Signature *s = NULL;
|
|
DetectAppLayerProtocolData *data = NULL;
|
|
DetectEngineCtx *de_ctx = DetectEngineCtxInit();
|
|
FAIL_IF_NULL(de_ctx);
|
|
de_ctx->flags |= DE_QUIET;
|
|
|
|
s = DetectEngineAppendSig(de_ctx, "alert tcp any any -> any any "
|
|
"(app-layer-protocol:http; sid:1;)");
|
|
FAIL_IF_NULL(s);
|
|
|
|
FAIL_IF(s->alproto != ALPROTO_UNKNOWN);
|
|
|
|
FAIL_IF_NULL(s->init_data->smlists[DETECT_SM_LIST_MATCH]);
|
|
FAIL_IF_NULL(s->init_data->smlists[DETECT_SM_LIST_MATCH]->ctx);
|
|
|
|
data = (DetectAppLayerProtocolData *)s->init_data->smlists[DETECT_SM_LIST_MATCH]->ctx;
|
|
FAIL_IF(data->alproto != ALPROTO_HTTP);
|
|
FAIL_IF(data->negated);
|
|
DetectEngineCtxFree(de_ctx);
|
|
PASS;
|
|
}
|
|
|
|
static int DetectAppLayerProtocolTest04(void)
|
|
{
|
|
Signature *s = NULL;
|
|
DetectAppLayerProtocolData *data = NULL;
|
|
DetectEngineCtx *de_ctx = DetectEngineCtxInit();
|
|
FAIL_IF_NULL(de_ctx);
|
|
de_ctx->flags |= DE_QUIET;
|
|
|
|
s = DetectEngineAppendSig(de_ctx, "alert tcp any any -> any any "
|
|
"(app-layer-protocol:!http; sid:1;)");
|
|
FAIL_IF_NULL(s);
|
|
FAIL_IF(s->alproto != ALPROTO_UNKNOWN);
|
|
FAIL_IF(s->flags & SIG_FLAG_APPLAYER);
|
|
|
|
FAIL_IF_NULL(s->init_data->smlists[DETECT_SM_LIST_MATCH]);
|
|
FAIL_IF_NULL(s->init_data->smlists[DETECT_SM_LIST_MATCH]->ctx);
|
|
|
|
data = (DetectAppLayerProtocolData *)s->init_data->smlists[DETECT_SM_LIST_MATCH]->ctx;
|
|
FAIL_IF_NULL(data);
|
|
FAIL_IF(data->alproto != ALPROTO_HTTP);
|
|
FAIL_IF(data->negated == 0);
|
|
|
|
DetectEngineCtxFree(de_ctx);
|
|
PASS;
|
|
}
|
|
|
|
static int DetectAppLayerProtocolTest05(void)
|
|
{
|
|
Signature *s = NULL;
|
|
DetectAppLayerProtocolData *data = NULL;
|
|
DetectEngineCtx *de_ctx = DetectEngineCtxInit();
|
|
FAIL_IF_NULL(de_ctx);
|
|
de_ctx->flags |= DE_QUIET;
|
|
|
|
s = DetectEngineAppendSig(de_ctx, "alert tcp any any -> any any "
|
|
"(app-layer-protocol:!http; app-layer-protocol:!smtp; sid:1;)");
|
|
FAIL_IF_NULL(s);
|
|
FAIL_IF(s->alproto != ALPROTO_UNKNOWN);
|
|
FAIL_IF(s->flags & SIG_FLAG_APPLAYER);
|
|
|
|
FAIL_IF_NULL(s->init_data->smlists[DETECT_SM_LIST_MATCH]);
|
|
FAIL_IF_NULL(s->init_data->smlists[DETECT_SM_LIST_MATCH]->ctx);
|
|
|
|
data = (DetectAppLayerProtocolData *)s->init_data->smlists[DETECT_SM_LIST_MATCH]->ctx;
|
|
FAIL_IF_NULL(data);
|
|
FAIL_IF(data->alproto != ALPROTO_HTTP);
|
|
FAIL_IF(data->negated == 0);
|
|
|
|
data = (DetectAppLayerProtocolData *)s->init_data->smlists[DETECT_SM_LIST_MATCH]->next->ctx;
|
|
FAIL_IF_NULL(data);
|
|
FAIL_IF(data->alproto != ALPROTO_SMTP);
|
|
FAIL_IF(data->negated == 0);
|
|
|
|
DetectEngineCtxFree(de_ctx);
|
|
PASS;
|
|
}
|
|
|
|
static int DetectAppLayerProtocolTest06(void)
|
|
{
|
|
Signature *s = NULL;
|
|
DetectEngineCtx *de_ctx = DetectEngineCtxInit();
|
|
FAIL_IF_NULL(de_ctx);
|
|
de_ctx->flags |= DE_QUIET;
|
|
|
|
s = DetectEngineAppendSig(de_ctx, "alert http any any -> any any "
|
|
"(app-layer-protocol:smtp; sid:1;)");
|
|
FAIL_IF_NOT_NULL(s);
|
|
DetectEngineCtxFree(de_ctx);
|
|
PASS;
|
|
}
|
|
|
|
static int DetectAppLayerProtocolTest07(void)
|
|
{
|
|
Signature *s = NULL;
|
|
DetectEngineCtx *de_ctx = DetectEngineCtxInit();
|
|
FAIL_IF_NULL(de_ctx);
|
|
de_ctx->flags |= DE_QUIET;
|
|
|
|
s = DetectEngineAppendSig(de_ctx, "alert http any any -> any any "
|
|
"(app-layer-protocol:!smtp; sid:1;)");
|
|
FAIL_IF_NOT_NULL(s);
|
|
DetectEngineCtxFree(de_ctx);
|
|
PASS;
|
|
}
|
|
|
|
static int DetectAppLayerProtocolTest08(void)
|
|
{
|
|
Signature *s = NULL;
|
|
DetectEngineCtx *de_ctx = DetectEngineCtxInit();
|
|
FAIL_IF_NULL(de_ctx);
|
|
de_ctx->flags |= DE_QUIET;
|
|
|
|
s = DetectEngineAppendSig(de_ctx, "alert tcp any any -> any any "
|
|
"(app-layer-protocol:!smtp; app-layer-protocol:http; sid:1;)");
|
|
FAIL_IF_NOT_NULL(s);
|
|
DetectEngineCtxFree(de_ctx);
|
|
PASS;
|
|
}
|
|
|
|
static int DetectAppLayerProtocolTest09(void)
|
|
{
|
|
Signature *s = NULL;
|
|
DetectEngineCtx *de_ctx = DetectEngineCtxInit();
|
|
FAIL_IF_NULL(de_ctx);
|
|
de_ctx->flags |= DE_QUIET;
|
|
|
|
s = DetectEngineAppendSig(de_ctx, "alert tcp any any -> any any "
|
|
"(app-layer-protocol:http; app-layer-protocol:!smtp; sid:1;)");
|
|
FAIL_IF_NOT_NULL(s);
|
|
DetectEngineCtxFree(de_ctx);
|
|
PASS;
|
|
}
|
|
|
|
static int DetectAppLayerProtocolTest10(void)
|
|
{
|
|
Signature *s = NULL;
|
|
DetectEngineCtx *de_ctx = DetectEngineCtxInit();
|
|
FAIL_IF_NULL(de_ctx);
|
|
de_ctx->flags |= DE_QUIET;
|
|
|
|
s = DetectEngineAppendSig(de_ctx, "alert tcp any any -> any any "
|
|
"(app-layer-protocol:smtp; app-layer-protocol:!http; sid:1;)");
|
|
FAIL_IF_NOT_NULL(s);
|
|
DetectEngineCtxFree(de_ctx);
|
|
PASS;
|
|
}
|
|
|
|
static int DetectAppLayerProtocolTest11(void)
|
|
{
|
|
DetectAppLayerProtocolData *data = DetectAppLayerProtocolParse("failed", false);
|
|
FAIL_IF_NULL(data);
|
|
FAIL_IF(data->alproto != ALPROTO_FAILED);
|
|
FAIL_IF(data->negated != 0);
|
|
DetectAppLayerProtocolFree(NULL, data);
|
|
PASS;
|
|
}
|
|
|
|
static int DetectAppLayerProtocolTest12(void)
|
|
{
|
|
DetectAppLayerProtocolData *data = DetectAppLayerProtocolParse("failed", true);
|
|
FAIL_IF_NULL(data);
|
|
FAIL_IF(data->alproto != ALPROTO_FAILED);
|
|
FAIL_IF(data->negated == 0);
|
|
DetectAppLayerProtocolFree(NULL, data);
|
|
PASS;
|
|
}
|
|
|
|
static int DetectAppLayerProtocolTest13(void)
|
|
{
|
|
Signature *s = NULL;
|
|
DetectAppLayerProtocolData *data = NULL;
|
|
DetectEngineCtx *de_ctx = DetectEngineCtxInit();
|
|
FAIL_IF_NULL(de_ctx);
|
|
de_ctx->flags |= DE_QUIET;
|
|
|
|
s = DetectEngineAppendSig(de_ctx, "alert tcp any any -> any any "
|
|
"(app-layer-protocol:failed; sid:1;)");
|
|
FAIL_IF_NULL(s);
|
|
|
|
FAIL_IF(s->alproto != ALPROTO_UNKNOWN);
|
|
|
|
FAIL_IF_NULL(s->init_data->smlists[DETECT_SM_LIST_MATCH]);
|
|
FAIL_IF_NULL(s->init_data->smlists[DETECT_SM_LIST_MATCH]->ctx);
|
|
|
|
data = (DetectAppLayerProtocolData *)s->init_data->smlists[DETECT_SM_LIST_MATCH]->ctx;
|
|
FAIL_IF(data->alproto != ALPROTO_FAILED);
|
|
FAIL_IF(data->negated);
|
|
DetectEngineCtxFree(de_ctx);
|
|
PASS;
|
|
}
|
|
|
|
static int DetectAppLayerProtocolTest14(void)
|
|
{
|
|
DetectAppLayerProtocolData *data = NULL;
|
|
DetectEngineCtx *de_ctx = DetectEngineCtxInit();
|
|
FAIL_IF_NULL(de_ctx);
|
|
de_ctx->flags |= DE_QUIET;
|
|
|
|
Signature *s1 = DetectEngineAppendSig(de_ctx, "alert tcp any any -> any any "
|
|
"(app-layer-protocol:http; flowbits:set,blah; sid:1;)");
|
|
FAIL_IF_NULL(s1);
|
|
FAIL_IF(s1->alproto != ALPROTO_UNKNOWN);
|
|
FAIL_IF_NULL(s1->init_data->smlists[DETECT_SM_LIST_MATCH]);
|
|
FAIL_IF_NULL(s1->init_data->smlists[DETECT_SM_LIST_MATCH]->ctx);
|
|
data = (DetectAppLayerProtocolData *)s1->init_data->smlists[DETECT_SM_LIST_MATCH]->ctx;
|
|
FAIL_IF(data->alproto != ALPROTO_HTTP);
|
|
FAIL_IF(data->negated);
|
|
|
|
Signature *s2 = DetectEngineAppendSig(de_ctx, "alert tcp any any -> any any "
|
|
"(app-layer-protocol:http; flow:to_client; sid:2;)");
|
|
FAIL_IF_NULL(s2);
|
|
FAIL_IF(s2->alproto != ALPROTO_UNKNOWN);
|
|
FAIL_IF_NULL(s2->init_data->smlists[DETECT_SM_LIST_MATCH]);
|
|
FAIL_IF_NULL(s2->init_data->smlists[DETECT_SM_LIST_MATCH]->ctx);
|
|
data = (DetectAppLayerProtocolData *)s2->init_data->smlists[DETECT_SM_LIST_MATCH]->ctx;
|
|
FAIL_IF(data->alproto != ALPROTO_HTTP);
|
|
FAIL_IF(data->negated);
|
|
|
|
/* flow:established and other options not supported for PD-only */
|
|
Signature *s3 = DetectEngineAppendSig(de_ctx, "alert tcp any any -> any any "
|
|
"(app-layer-protocol:http; flow:to_client,established; sid:3;)");
|
|
FAIL_IF_NULL(s3);
|
|
FAIL_IF(s3->alproto != ALPROTO_UNKNOWN);
|
|
FAIL_IF_NULL(s3->init_data->smlists[DETECT_SM_LIST_MATCH]);
|
|
FAIL_IF_NULL(s3->init_data->smlists[DETECT_SM_LIST_MATCH]->ctx);
|
|
data = (DetectAppLayerProtocolData *)s3->init_data->smlists[DETECT_SM_LIST_MATCH]->ctx;
|
|
FAIL_IF(data->alproto != ALPROTO_HTTP);
|
|
FAIL_IF(data->negated);
|
|
|
|
SigGroupBuild(de_ctx);
|
|
FAIL_IF_NOT(s1->type == SIG_TYPE_PDONLY);
|
|
FAIL_IF_NOT(s2->type == SIG_TYPE_PDONLY);
|
|
FAIL_IF(s3->type == SIG_TYPE_PDONLY); // failure now
|
|
|
|
DetectEngineCtxFree(de_ctx);
|
|
PASS;
|
|
}
|
|
|
|
|
|
static void DetectAppLayerProtocolRegisterTests(void)
|
|
{
|
|
UtRegisterTest("DetectAppLayerProtocolTest01",
|
|
DetectAppLayerProtocolTest01);
|
|
UtRegisterTest("DetectAppLayerProtocolTest02",
|
|
DetectAppLayerProtocolTest02);
|
|
UtRegisterTest("DetectAppLayerProtocolTest03",
|
|
DetectAppLayerProtocolTest03);
|
|
UtRegisterTest("DetectAppLayerProtocolTest04",
|
|
DetectAppLayerProtocolTest04);
|
|
UtRegisterTest("DetectAppLayerProtocolTest05",
|
|
DetectAppLayerProtocolTest05);
|
|
UtRegisterTest("DetectAppLayerProtocolTest06",
|
|
DetectAppLayerProtocolTest06);
|
|
UtRegisterTest("DetectAppLayerProtocolTest07",
|
|
DetectAppLayerProtocolTest07);
|
|
UtRegisterTest("DetectAppLayerProtocolTest08",
|
|
DetectAppLayerProtocolTest08);
|
|
UtRegisterTest("DetectAppLayerProtocolTest09",
|
|
DetectAppLayerProtocolTest09);
|
|
UtRegisterTest("DetectAppLayerProtocolTest10",
|
|
DetectAppLayerProtocolTest10);
|
|
UtRegisterTest("DetectAppLayerProtocolTest11",
|
|
DetectAppLayerProtocolTest11);
|
|
UtRegisterTest("DetectAppLayerProtocolTest12",
|
|
DetectAppLayerProtocolTest12);
|
|
UtRegisterTest("DetectAppLayerProtocolTest13",
|
|
DetectAppLayerProtocolTest13);
|
|
UtRegisterTest("DetectAppLayerProtocolTest14",
|
|
DetectAppLayerProtocolTest14);
|
|
}
|
|
#endif /* UNITTESTS */
|