feature #727 - Add support for app-layer-protocol:<protocol> keyword

pull/567/head
Anoop Saldanha 12 years ago
parent 6f8cfd999f
commit 94e40907e2

@ -60,6 +60,7 @@ defrag-queue.c defrag-queue.h \
defrag-timeout.c defrag-timeout.h \
detect-ack.c detect-ack.h \
detect-app-layer-event.c detect-app-layer-event.h \
detect-app-layer-protocol.c detect-app-layer-protocol.h \
detect-asn1.c detect-asn1.h \
detect-byte-extract.c detect-byte-extract.h \
detect-bytejump.c detect-bytejump.h \

@ -0,0 +1,408 @@
/* 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
*
* \author Anoop Saldanha <anoopsaldanha@gmail.com>
*/
#include "suricata-common.h"
#include "detect-engine.h"
#include "detect-parse.h"
#include "detect-app-layer-protocol.h"
#include "app-layer-parser.h"
#include "util-debug.h"
#include "util-unittest.h"
#include "util-unittest-helper.h"
void DetectAppLayerProtocolRegisterTests(void);
int DetectAppLayerProtocolMatch(ThreadVars *t, DetectEngineThreadCtx *det_ctx,
Flow *f, uint8_t flags, void *state,
Signature *s, SigMatch *m)
{
int r = 0;
DetectAppLayerProtocolData *data = (DetectAppLayerProtocolData *)m->ctx;
FLOWLOCK_RDLOCK(f);
r = (data->negated) ? (f->alproto != data->alproto) :
(f->alproto == data->alproto);
FLOWLOCK_UNLOCK(f);
return r;
}
static DetectAppLayerProtocolData *DetectAppLayerProtocolParse(const char *arg)
{
DetectAppLayerProtocolData *data;
uint16_t alproto = ALPROTO_UNKNOWN;
uint8_t negated = 0;
if (arg == NULL) {
SCLogError(SC_ERR_INVALID_SIGNATURE, "app-layer-protocol keyword "
"supplied with no arguments. This keyword needs "
"an argument.");
return NULL;
}
while (*arg != '\0' && isspace((unsigned char)*arg))
arg++;
if (arg[0] == '!') {
negated = 1;
arg++;
}
while (*arg != '\0' && isspace((unsigned char)*arg))
arg++;
alproto = AppLayerGetProtoByName(arg);
if (alproto == ALPROTO_UNKNOWN) {
SCLogError(SC_ERR_INVALID_SIGNATURE, "app-layer-protocol "
"keyword supplied with unknown protocol \"%s\"", arg);
return NULL;
}
data = SCMalloc(sizeof(DetectAppLayerProtocolData));
if (unlikely(data == NULL))
return NULL;
data->alproto = alproto;
data->negated = negated;
return data;
}
int DetectAppLayerProtocolSetup(DetectEngineCtx *de_ctx, Signature *s,
char *arg)
{
DetectAppLayerProtocolData *data = NULL;
SigMatch *sm = NULL;
if (s->alproto != ALPROTO_UNKNOWN) {
SCLogError(SC_ERR_CONFLICTING_RULE_KEYWORDS, "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);
if (data == NULL)
goto error;
if (!data->negated)
s->alproto = data->alproto;
sm = SigMatchAlloc();
if (sm == NULL)
goto error;
sm->type = DETECT_AL_APP_LAYER_PROTOCOL;
sm->ctx = (void *)data;
SigMatchAppendSMToList(s, sm, DETECT_SM_LIST_AMATCH);
s->flags |= SIG_FLAG_APPLAYER;
return 0;
error:
if (data != NULL)
SCFree(data);
return -1;
}
void DetectAppLayerProtocolFree(void *ptr)
{
SCFree(ptr);
return;
}
void DetectAppLayerProtocolRegister(void)
{
sigmatch_table[DETECT_AL_APP_LAYER_PROTOCOL].name = "app-layer-protocol";
sigmatch_table[DETECT_AL_APP_LAYER_PROTOCOL].Match = NULL;
sigmatch_table[DETECT_AL_APP_LAYER_PROTOCOL].AppLayerMatch =
DetectAppLayerProtocolMatch;
sigmatch_table[DETECT_AL_APP_LAYER_PROTOCOL].Setup =
DetectAppLayerProtocolSetup;
sigmatch_table[DETECT_AL_APP_LAYER_PROTOCOL].Free =
DetectAppLayerProtocolFree;
sigmatch_table[DETECT_AL_APP_LAYER_PROTOCOL].RegisterTests =
DetectAppLayerProtocolRegisterTests;
return;
}
/**********************************Unittests***********************************/
#ifdef UNITTESTS
int DetectAppLayerProtocolTest01(void)
{
int result = 0;
DetectAppLayerProtocolData *data = DetectAppLayerProtocolParse("http");
if (data == NULL)
goto end;
if (data->alproto != ALPROTO_HTTP || data->negated) {
printf("test failure. Holding wrong state\n");
goto end;
}
result = 1;
end:
if (data != NULL)
DetectAppLayerProtocolFree(data);
return result;
}
int DetectAppLayerProtocolTest02(void)
{
int result = 0;
DetectAppLayerProtocolData *data = DetectAppLayerProtocolParse("!http");
if (data == NULL)
goto end;
if (data->alproto != ALPROTO_HTTP || !data->negated) {
printf("test failure. Holding wrong state\n");
goto end;
}
result = 1;
end:
if (data != NULL)
DetectAppLayerProtocolFree(data);
return result;
}
int DetectAppLayerProtocolTest03(void)
{
int result = 0;
Signature *s = NULL;
DetectAppLayerProtocolData *data = NULL;
DetectEngineCtx *de_ctx = DetectEngineCtxInit();
if (de_ctx == NULL)
goto end;
de_ctx->flags |= DE_QUIET;
s = SigInit(de_ctx, "alert tcp any any -> any any "
"(app-layer-protocol:http; sid:1;)");
if (s->alproto != ALPROTO_HTTP) {
printf("signature alproto should be http\n");
goto end;
}
data = s->sm_lists[DETECT_SM_LIST_AMATCH]->ctx;
if (data->alproto != ALPROTO_HTTP || data->negated) {
printf("if (data->alproto != ALPROTO_HTTP || data->negated)\n");
goto end;
}
result = 1;
end:
SigGroupCleanup(de_ctx);
SigCleanSignatures(de_ctx);
DetectEngineCtxFree(de_ctx);
return result;
}
int DetectAppLayerProtocolTest04(void)
{
int result = 0;
Signature *s = NULL;
DetectAppLayerProtocolData *data = NULL;
DetectEngineCtx *de_ctx = DetectEngineCtxInit();
if (de_ctx == NULL)
goto end;
de_ctx->flags |= DE_QUIET;
s = SigInit(de_ctx, "alert tcp any any -> any any "
"(app-layer-protocol:!http; sid:1;)");
if (s->alproto != ALPROTO_UNKNOWN) {
printf("signature alproto should be unknown\n");
goto end;
}
if (s->sm_lists[DETECT_SM_LIST_AMATCH] == NULL) {
printf("if (s->sm_lists[DETECT_SM_LIST_AMATCH] == NULL)\n");
goto end;
}
data = s->sm_lists[DETECT_SM_LIST_AMATCH]->ctx;
if (data == NULL) {
printf("if (data == NULL)\n");
goto end;
}
if (data->alproto != ALPROTO_HTTP || !data->negated) {
printf("if (data->alproto != ALPROTO_HTTP || !data->negated)\n");
goto end;
}
result = 1;
end:
SigGroupCleanup(de_ctx);
SigCleanSignatures(de_ctx);
DetectEngineCtxFree(de_ctx);
return result;
}
int DetectAppLayerProtocolTest05(void)
{
int result = 0;
Signature *s = NULL;
DetectEngineCtx *de_ctx = DetectEngineCtxInit();
if (de_ctx == NULL)
goto end;
de_ctx->flags |= DE_QUIET;
s = SigInit(de_ctx, "alert tcp any any -> any any "
"(app-layer-protocol:!http; app-layer-protocol:!smtp; sid:1;)");
if (s->alproto != ALPROTO_UNKNOWN) {
printf("signature alproto should be unknown\n");
goto end;
}
result = 1;
end:
SigGroupCleanup(de_ctx);
SigCleanSignatures(de_ctx);
DetectEngineCtxFree(de_ctx);
return result;
}
int DetectAppLayerProtocolTest06(void)
{
int result = 0;
Signature *s = NULL;
DetectEngineCtx *de_ctx = DetectEngineCtxInit();
if (de_ctx == NULL)
goto end;
de_ctx->flags |= DE_QUIET;
s = SigInit(de_ctx, "alert http any any -> any any "
"(app-layer-protocol:smtp; sid:1;)");
if (s != NULL) {
printf("if (s != NULL)\n");
goto end;
}
result = 1;
end:
SigGroupCleanup(de_ctx);
SigCleanSignatures(de_ctx);
DetectEngineCtxFree(de_ctx);
return result;
}
int DetectAppLayerProtocolTest07(void)
{
int result = 0;
Signature *s = NULL;
DetectEngineCtx *de_ctx = DetectEngineCtxInit();
if (de_ctx == NULL)
goto end;
de_ctx->flags |= DE_QUIET;
s = SigInit(de_ctx, "alert http any any -> any any "
"(app-layer-protocol:!smtp; sid:1;)");
if (s != NULL) {
printf("if (s != NULL)\n");
goto end;
}
result = 1;
end:
SigGroupCleanup(de_ctx);
SigCleanSignatures(de_ctx);
DetectEngineCtxFree(de_ctx);
return result;
}
int DetectAppLayerProtocolTest08(void)
{
int result = 0;
Signature *s = NULL;
DetectEngineCtx *de_ctx = DetectEngineCtxInit();
if (de_ctx == NULL)
goto end;
de_ctx->flags |= DE_QUIET;
s = SigInit(de_ctx, "alert tcp any any -> any any "
"(app-layer-protocol:!smtp; app-layer-protocol:http; sid:1;)");
if (s != NULL) {
printf("if (s != NULL)\n");
goto end;
}
result = 1;
end:
SigGroupCleanup(de_ctx);
SigCleanSignatures(de_ctx);
DetectEngineCtxFree(de_ctx);
return result;
}
int DetectAppLayerProtocolTest09(void)
{
int result = 0;
Signature *s = NULL;
DetectEngineCtx *de_ctx = DetectEngineCtxInit();
if (de_ctx == NULL)
goto end;
de_ctx->flags |= DE_QUIET;
s = SigInit(de_ctx, "alert tcp any any -> any any "
"(app-layer-protocol:http; app-layer-protocol:!smtp; sid:1;)");
if (s != NULL) {
printf("if (s != NULL)\n");
goto end;
}
result = 1;
end:
SigGroupCleanup(de_ctx);
SigCleanSignatures(de_ctx);
DetectEngineCtxFree(de_ctx);
return result;
}
#endif /* UNITTESTS */
void DetectAppLayerProtocolRegisterTests(void)
{
#ifdef UNITTESTS /* UNITTESTS */
UtRegisterTest("DetectAppLayerProtocolTest01", DetectAppLayerProtocolTest01, 1);
UtRegisterTest("DetectAppLayerProtocolTest02", DetectAppLayerProtocolTest02, 1);
UtRegisterTest("DetectAppLayerProtocolTest03", DetectAppLayerProtocolTest03, 1);
UtRegisterTest("DetectAppLayerProtocolTest04", DetectAppLayerProtocolTest04, 1);
UtRegisterTest("DetectAppLayerProtocolTest05", DetectAppLayerProtocolTest05, 1);
UtRegisterTest("DetectAppLayerProtocolTest06", DetectAppLayerProtocolTest06, 1);
UtRegisterTest("DetectAppLayerProtocolTest07", DetectAppLayerProtocolTest07, 1);
UtRegisterTest("DetectAppLayerProtocolTest08", DetectAppLayerProtocolTest08, 1);
UtRegisterTest("DetectAppLayerProtocolTest09", DetectAppLayerProtocolTest09, 1);
#endif /* UNITTESTS */
return;
}

@ -0,0 +1,34 @@
/* 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
*
* \author Anoop Saldanha <anoopsaldanha@gmail.com>
*/
#ifndef __DETECT_APP_LAYER_PROTOCOL__H__
#define __DETECT_APP_LAYER_PROTOCOL__H__
typedef struct DetectAppLayerProtocolData_ {
uint16_t alproto;
uint8_t negated;
} DetectAppLayerProtocolData;
void DetectAppLayerProtocolRegister(void);
#endif /* __DETECT_APP_LAYER_PROTOCOL__H__ */

@ -348,10 +348,9 @@ int DeStateDetectStartDetection(ThreadVars *tv, DetectEngineCtx *de_ctx,
}
sm = s->sm_lists[DETECT_SM_LIST_AMATCH];
for (; sm != NULL; sm = sm->next) {
if (sigmatch_table[sm->type].AppLayerMatch != NULL &&
(alproto == s->alproto || alproto == ALPROTO_SMB || alproto == ALPROTO_SMB2))
{
for (match = 0; sm != NULL; sm = sm->next) {
match = 0;
if (sigmatch_table[sm->type].AppLayerMatch != NULL) {
if (alproto == ALPROTO_SMB || alproto == ALPROTO_SMB2) {
smb_state = (SMBState *)alstate;
if (smb_state->dcerpc_present) {
@ -365,14 +364,16 @@ int DeStateDetectStartDetection(ThreadVars *tv, DetectEngineCtx *de_ctx,
if (match == 0)
break;
else if (match == 2)
if (match == 2) {
inspect_flags |= DE_STATE_FLAG_SIG_CANT_MATCH;
break;
}
}
}
if (s->sm_lists[DETECT_SM_LIST_AMATCH] != NULL) {
store_de_state = 1;
if (sm == NULL || inspect_flags & DE_STATE_FLAG_SIG_CANT_MATCH) {
if (sm == NULL)
if (match == 1)
alert_cnt = 1;
inspect_flags |= DE_STATE_FLAG_FULL_INSPECT;
}

@ -38,6 +38,7 @@
#include "detect-reference.h"
#include "detect-ipproto.h"
#include "detect-flow.h"
#include "detect-app-layer-protocol.h"
#include "pkt-var.h"
#include "host.h"
@ -1297,6 +1298,19 @@ int SigValidate(DetectEngineCtx *de_ctx, Signature *s) {
}
}
for (sm = s->sm_lists[DETECT_SM_LIST_AMATCH]; sm != NULL; sm = sm->next) {
if (sm->type != DETECT_AL_APP_LAYER_PROTOCOL)
continue;
if (((DetectAppLayerProtocolData *)sm->ctx)->negated)
break;
}
if (sm != NULL && s->alproto != ALPROTO_UNKNOWN) {
SCLogError(SC_ERR_CONFLICTING_RULE_KEYWORDS, "We can't have "
"the rule match on a fixed alproto and at the same time"
"have an app-layer-protocol keyword set.");
SCReturnInt(0);
}
/* TCP: pkt vs stream vs depth/offset */
if (s->proto.proto[IPPROTO_TCP / 8] & (1 << (IPPROTO_TCP % 8))) {
if (!(s->flags & (SIG_FLAG_REQUIRE_PACKET | SIG_FLAG_REQUIRE_STREAM))) {

@ -151,6 +151,7 @@
#include "detect-iprep.h"
#include "detect-geoip.h"
#include "detect-dns-query.h"
#include "detect-app-layer-protocol.h"
#include "util-rule-vars.h"
@ -4756,6 +4757,7 @@ void SigTableSetup(void) {
DetectLuajitRegister();
DetectIPRepRegister();
DetectDnsQueryRegister();
DetectAppLayerProtocolRegister();
}
void SigTableRegisterTests(void)

@ -1104,6 +1104,7 @@ enum {
DETECT_FILE_DATA,
DETECT_PKT_DATA,
DETECT_AL_APP_LAYER_EVENT,
DETECT_AL_APP_LAYER_PROTOCOL,
DETECT_DCE_IFACE,
DETECT_DCE_OPNUM,

Loading…
Cancel
Save