First iteration of doing app layer detection.

remotes/origin/master-1.0.x
Victor Julien 16 years ago
parent f31d8e0444
commit f1f7df0766

@ -125,12 +125,14 @@ stream-tcp-reassemble.c stream-tcp-reassemble.h \
respond-reject.c respond-reject.h \
respond-reject-libnet11.h respond-reject-libnet11.c \
counters.c counter.h \
app-layer.c app-layer.h \
app-layer-detect-proto.c app-layer-detect-proto.h \
app-layer-parser.c app-layer-parser.h \
app-layer-http.c app-layer-http.h \
app-layer-tls.c app-layer-tls.h \
app-layer-smb.c app-layer-smb.h \
app-layer-dcerpc.c app-layer-dcerpc.h \
app-layer-tls-detect-version.c app-layer-tls-detect-version.h \
app-layer-protos.h \
conf.c conf.h \
conf-yaml-loader.c conf-yaml-loader.h \

@ -0,0 +1,24 @@
#include "eidps-common.h"
#include "app-layer-detect.h"
/** \brief alloc a app layer detection ctx
* \retval alde_ctx ptr or NULL in case of error
*/
AlDetectEngineCtx *AlDetectEngineCtxAlloc(void) {
AlDetectEngineCtx *alde_ctx = malloc(sizeof(AlDetectEngineCtx));
if (alde_ctx == NULL) {
SCLogError(SC_ERR_MEM_ALLOC, "malloc failed: %s", strerror(errno));
return NULL;
}
memset(alde_ctx, 0x00, sizeof(AlDetectEngineCtx));
return alde_ctx;
}
/** \brief free a app layer detection ctx
* \param alde_ctx ptr to app layer detection ctx
*/
void AlDetectEngineCtxAllocFree(AlDetectEngineCtx *alde_ctx) {
free(alde_ctx);
}

@ -0,0 +1,33 @@
#include "eidps-common.h"
#include "detect.h"
#include "app-layer-protos.h"
/** detection engine will be grouped:
* - app layer protocol
* - flow direction
* - phase
* - src ip/dst ip
* - ports? (maybe unnecessary as proto detection is in place)
*/
#define AL_DETECT_FLOW_PHASES 4
typedef struct AlDetectProto_ {
DetectAddressGroupsHead *src[AL_DETECT_FLOW_PHASES];
DetectAddressGroupsHead *tmp[AL_DETECT_FLOW_PHASES];
} AlDetectProto;
/** 2 flow states: to_client, to_server */
#define AL_DETECT_FLOW_STATES 2
typedef struct AlDetectFlow_ {
AlDetectProto *proto[ALPROTO_MAX];
} AlDetectFlow;
typedef struct AlDetectEngineCtx_ {
/* flow direction */
AlDetectFlow *flow[AL_DETECT_FLOW_STATES];
} AlDetectEngineCtx;

@ -343,6 +343,26 @@ uint16_t AppLayerParserGetStorageId(void) {
return app_layer_sid;
}
uint16_t AppLayerGetProtoByName(const char *name) {
uint8_t u = 1;
SCLogDebug("looking for name %s", name);
for ( ; u < ALPROTO_MAX; u++) {
if (al_proto_table[u].name == NULL)
continue;
SCLogDebug("name %s proto %"PRIu16"",
al_proto_table[u].name, u);
if (strcasecmp(name,al_proto_table[u].name) == 0) {
SCLogDebug("match, returning %"PRIu16"", u);
return u;
}
}
return ALPROTO_UNKNOWN;
}
/** \brief Description: register a parser.
*
* \param name full parser name, e.g. "http.request_line"
@ -393,6 +413,8 @@ int AppLayerRegisterProto(char *name, uint8_t proto, uint8_t flags, int (*AppLay
al_parser_table[al_max_parsers].name = name;
al_parser_table[al_max_parsers].AppLayerParser = AppLayerParser;
al_proto_table[proto].name = name;
/* create proto, direction -- parser mapping */
if (flags & STREAM_TOSERVER) {
al_proto_table[proto].to_server = al_max_parsers;

@ -12,6 +12,8 @@ typedef struct AppLayerLocalMap_ {
* Map the proto to the parsers for the to_client and to_server directions.
*/
typedef struct AppLayerProto_ {
char *name; /**< name of the registered proto */
uint16_t to_server;
uint16_t to_client;
uint8_t storage_id;
@ -93,6 +95,8 @@ int AlpParseFieldByEOF(AppLayerParserResult *, AppLayerParserState *, uint16_t,
int AlpParseFieldByDelimiter(AppLayerParserResult *, AppLayerParserState *, uint16_t, const uint8_t *, uint8_t, uint8_t *, uint32_t, uint32_t *);
uint16_t AlpGetStateIdx(uint16_t);
uint16_t AppLayerGetProtoByName(const char *);
#include "stream-tcp-private.h"
void AppLayerParserCleanupState(TcpSession *);

@ -0,0 +1,396 @@
/**
* Copyright (c) 2009 Open Information Security Foundation
*
* \file
* \author Victor Julien <victor@inliniac.net>
*/
#include "eidps-common.h"
#include "threads.h"
#include "debug.h"
#include "decode.h"
#include "detect.h"
#include "detect-parse.h"
#include "detect-engine.h"
#include "detect-engine-mpm.h"
#include "flow.h"
#include "flow-var.h"
#include "util-debug.h"
#include "util-unittest.h"
#include "app-layer.h"
#include "app-layer-tls.h"
#include "app-layer-tls-detect-version.h"
/**
* \brief Regex for parsing "id" option, matching number or "number"
*/
#define PARSE_REGEX "^\\s*([A-z0-9\\.]+|\"[A-z0-9\\.]+\")\\s*$"
static pcre *parse_regex;
static pcre_extra *parse_regex_study;
int AppLayerTlsDetectVersionMatch (ThreadVars *, DetectEngineThreadCtx *, Flow *, uint8_t, void *, Signature *, SigMatch *);
int AppLayerTlsDetectVersionSetup (DetectEngineCtx *, Signature *, SigMatch *, char *);
void AppLayerTlsDetectVersionRegisterTests(void);
void AppLayerTlsDetectVersionFree(void *);
/**
* \brief Registration function for keyword: tls.version
*/
void AppLayerTlsDetectVersionRegister (void) {
sigmatch_table[DETECT_AL_TLS_VERSION].name = "tls.version";
sigmatch_table[DETECT_AL_TLS_VERSION].Match = NULL;
sigmatch_table[DETECT_AL_TLS_VERSION].AppLayerMatch = AppLayerTlsDetectVersionMatch;
sigmatch_table[DETECT_AL_TLS_VERSION].Setup = AppLayerTlsDetectVersionSetup;
sigmatch_table[DETECT_AL_TLS_VERSION].Free = AppLayerTlsDetectVersionFree;
sigmatch_table[DETECT_AL_TLS_VERSION].RegisterTests = AppLayerTlsDetectVersionRegisterTests;
const char *eb;
int eo;
int opts = 0;
SCLogDebug("registering tls.version rule option\n");
parse_regex = pcre_compile(PARSE_REGEX, opts, &eb, &eo, NULL);
if (parse_regex == NULL) {
SCLogDebug("Compile of \"%s\" failed at offset %" PRId32 ": %s\n",
PARSE_REGEX, eo, eb);
goto error;
}
parse_regex_study = pcre_study(parse_regex, 0, &eb);
if (eb != NULL) {
SCLogDebug("pcre study failed: %s\n", eb);
goto error;
}
return;
error:
return;
}
/**
* \brief match the specified version on a tls session
*
* \param t pointer to thread vars
* \param det_ctx pointer to the pattern matcher thread
* \param p pointer to the current packet
* \param m pointer to the sigmatch that we will cast into AppLayerTlsDetectVersionData
*
* \retval 0 no match
* \retval 1 match
*/
int AppLayerTlsDetectVersionMatch (ThreadVars *t, DetectEngineThreadCtx *det_ctx, Flow *f, uint8_t flags, void *state, Signature *s, SigMatch *m)
{
AppLayerTlsDetectVersionData *tls_data = (AppLayerTlsDetectVersionData *)m->ctx;
TlsState *tls_state = (TlsState *)state;
if (tls_state == NULL)
return 0;
int ret = 0;
mutex_lock(&f->m);
if (flags & STREAM_TOCLIENT) {
if (tls_data->ver == tls_state->client_version)
ret = 1;
} else if (flags & STREAM_TOSERVER) {
if (tls_data->ver == tls_state->server_version)
ret = 1;
}
mutex_unlock(&f->m);
return ret;
}
/**
* \brief This function is used to parse IPV4 ip_id passed via keyword: "id"
*
* \param idstr Pointer to the user provided id option
*
* \retval id_d pointer to AppLayerTlsDetectVersionData on success
* \retval NULL on failure
*/
AppLayerTlsDetectVersionData *AppLayerTlsDetectVersionParse (char *str)
{
uint8_t temp;
AppLayerTlsDetectVersionData *tls = NULL;
#define MAX_SUBSTRINGS 30
int ret = 0, res = 0;
int ov[MAX_SUBSTRINGS];
ret = pcre_exec(parse_regex, parse_regex_study, str, strlen(str), 0, 0,
ov, MAX_SUBSTRINGS);
if (ret < 1 || ret > 3) {
SCLogDebug("invalid tls.version option");
goto error;
}
if (ret > 1) {
const char *str_ptr;
char *orig;
char *tmp_str;
res = pcre_get_substring((char *)str, ov, MAX_SUBSTRINGS, 1, &str_ptr);
if (res < 0) {
SCLogDebug("AppLayerTlsDetectVersionParse: pcre_get_substring failed\n");
goto error;
}
/* We have a correct id option */
tls = malloc(sizeof(AppLayerTlsDetectVersionData));
if (tls == NULL) {
SCLogDebug("AppLayerTlsDetectVersionParse malloc failed\n");
goto error;
}
orig = strdup((char*)str_ptr);
tmp_str=orig;
/* Let's see if we need to scape "'s */
if (tmp_str[0] == '"')
{
tmp_str[strlen(tmp_str) - 1] = '\0';
tmp_str += 1;
}
if (strcmp("1.0", tmp_str) == 0) {
temp = TLS_VERSION_10;
} else if (strcmp("1.1", tmp_str) == 0) {
temp = TLS_VERSION_11;
} else if (strcmp("1.2", tmp_str) == 0) {
temp = TLS_VERSION_12;
} else {
goto error;
}
tls->ver = temp;
free(orig);
SCLogDebug("will look for tls %"PRIu8"\n", tls->ver);
}
return tls;
error:
if (tls != NULL)
AppLayerTlsDetectVersionFree(tls);
return NULL;
}
/**
* \brief this function is used to add the parsed "id" option
* \brief into the current signature
*
* \param de_ctx pointer to the Detection Engine Context
* \param s pointer to the Current Signature
* \param m pointer to the Current SigMatch
* \param idstr pointer to the user provided "id" option
*
* \retval 0 on Success
* \retval -1 on Failure
*/
int AppLayerTlsDetectVersionSetup (DetectEngineCtx *de_ctx, Signature *s, SigMatch *m, char *str)
{
AppLayerTlsDetectVersionData *tls = NULL;
SigMatch *sm = NULL;
tls = AppLayerTlsDetectVersionParse(str);
if (tls == NULL) goto error;
/* Okay so far so good, lets get this into a SigMatch
* and put it in the Signature. */
sm = SigMatchAlloc();
if (sm == NULL)
goto error;
sm->type = DETECT_AL_TLS_VERSION;
sm->ctx = (void *)tls;
SigMatchAppend(s,m,sm);
return 0;
error:
if (tls != NULL) AppLayerTlsDetectVersionFree(tls);
if (sm != NULL) free(sm);
return -1;
}
/**
* \brief this function will free memory associated with AppLayerTlsDetectVersionData
*
* \param id_d pointer to AppLayerTlsDetectVersionData
*/
void AppLayerTlsDetectVersionFree(void *ptr) {
AppLayerTlsDetectVersionData *id_d = (AppLayerTlsDetectVersionData *)ptr;
free(id_d);
}
#ifdef UNITTESTS /* UNITTESTS */
/**
* \test AppLayerTlsDetectVersionTestParse01 is a test to make sure that we parse the "id"
* option correctly when given valid id option
*/
int AppLayerTlsDetectVersionTestParse01 (void) {
AppLayerTlsDetectVersionData *tls = NULL;
tls = AppLayerTlsDetectVersionParse("1.0");
if (tls != NULL && tls->ver == TLS_VERSION_10) {
AppLayerTlsDetectVersionFree(tls);
return 1;
}
return 0;
}
/**
* \test AppLayerTlsDetectVersionTestParse02 is a test to make sure that we parse the "id"
* option correctly when given an invalid id option
* it should return id_d = NULL
*/
int AppLayerTlsDetectVersionTestParse02 (void) {
AppLayerTlsDetectVersionData *tls = NULL;
tls = AppLayerTlsDetectVersionParse("2.5");
if (tls == NULL) {
AppLayerTlsDetectVersionFree(tls);
return 1;
}
return 0;
}
#include "stream-tcp-reassemble.h"
/** \test Send a get request in three chunks + more data. */
static int AppLayerTlsDetectVersionTestDetect01(void) {
int result = 1;
Flow f;
uint8_t tlsbuf1[] = { 0x16 };
uint32_t tlslen1 = sizeof(tlsbuf1);
uint8_t tlsbuf2[] = { 0x03 };
uint32_t tlslen2 = sizeof(tlsbuf2);
uint8_t tlsbuf3[] = { 0x01 };
uint32_t tlslen3 = sizeof(tlsbuf3);
uint8_t tlsbuf4[] = { 0x01, 0x00, 0x00, 0xad, 0x03, 0x01 };
uint32_t tlslen4 = sizeof(tlsbuf4);
TcpSession ssn;
Packet p;
Signature *s = NULL;
ThreadVars th_v;
DetectEngineThreadCtx *det_ctx;
memset(&th_v, 0, sizeof(th_v));
memset(&p, 0, sizeof(p));
memset(&f, 0, sizeof(f));
memset(&ssn, 0, sizeof(ssn));
p.src.family = AF_INET;
p.dst.family = AF_INET;
p.payload = NULL;
p.payload_len = 0;
p.proto = IPPROTO_TCP;
StreamL7DataPtrInit(&ssn,StreamL7GetStorageSize());
f.protoctx = (void *)&ssn;
p.flow = &f;
DetectEngineCtx *de_ctx = DetectEngineCtxInit();
if (de_ctx == NULL) {
goto end;
}
//de_ctx->flags |= DE_QUIET;
s = de_ctx->sig_list = SigInit(de_ctx,"alert tls any any -> any any (msg:\"TLS\"; tls.version:1.0; sid:1;)");
if (s == NULL) {
goto end;
}
SigGroupBuild(de_ctx);
PatternMatchPrepare(mpm_ctx, MPM_B2G);
DetectEngineThreadCtxInit(&th_v, (void *)de_ctx, (void *)&det_ctx);
int r = AppLayerParse(&f, ALPROTO_TLS, STREAM_TOSERVER, tlsbuf1, tlslen1, FALSE);
if (r != 0) {
printf("toserver chunk 1 returned %" PRId32 ", expected 0: ", r);
result = 0;
goto end;
}
r = AppLayerParse(&f, ALPROTO_TLS, STREAM_TOSERVER, tlsbuf2, tlslen2, FALSE);
if (r != 0) {
printf("toserver chunk 2 returned %" PRId32 ", expected 0: ", r);
result = 0;
goto end;
}
r = AppLayerParse(&f, ALPROTO_TLS, STREAM_TOSERVER, tlsbuf3, tlslen3, FALSE);
if (r != 0) {
printf("toserver chunk 3 returned %" PRId32 ", expected 0: ", r);
result = 0;
goto end;
}
r = AppLayerParse(&f, ALPROTO_TLS, STREAM_TOSERVER, tlsbuf4, tlslen4, FALSE);
if (r != 0) {
printf("toserver chunk 4 returned %" PRId32 ", expected 0: ", r);
result = 0;
goto end;
}
TlsState *tls_state = ssn.aldata[AlpGetStateIdx(ALPROTO_TLS)];
if (tls_state == NULL) {
printf("no tls state: ");
result = 0;
goto end;
}
if (tls_state->client_content_type != 0x16) {
printf("expected content_type %" PRIu8 ", got %" PRIu8 ": ", 0x16, tls_state->client_content_type);
result = 0;
goto end;
}
if (tls_state->client_version != TLS_VERSION_10) {
printf("expected version %04" PRIu16 ", got %04" PRIu16 ": ", TLS_VERSION_10, tls_state->client_version);
result = 0;
goto end;
}
/* do detect */
SigMatchSignatures(&th_v, de_ctx, det_ctx, &p);
if (!(PacketAlertCheck(&p, 1))) {
goto end;
}
result = 1;
end:
SigGroupCleanup(de_ctx);
SigCleanSignatures(de_ctx);
DetectEngineThreadCtxDeinit(&th_v, (void *)det_ctx);
PatternMatchDestroy(mpm_ctx);
DetectEngineCtxFree(de_ctx);
return result;
}
#endif /* UNITTESTS */
/**
* \brief this function registers unit tests for AppLayerTlsDetectVersion
*/
void AppLayerTlsDetectVersionRegisterTests(void) {
#ifdef UNITTESTS /* UNITTESTS */
UtRegisterTest("AppLayerTlsDetectVersionTestParse01", AppLayerTlsDetectVersionTestParse01, 1);
UtRegisterTest("AppLayerTlsDetectVersionTestParse02", AppLayerTlsDetectVersionTestParse02, 1);
UtRegisterTest("AppLayerTlsDetectVersionTestDetect01", AppLayerTlsDetectVersionTestDetect01, 1);
#endif /* UNITTESTS */
}

@ -0,0 +1,12 @@
#ifndef __APP_LAYER_TLS_DETECT_VERSION_H__
#define __APP_LAYER_TLS_DETECT_VERSION_H__
typedef struct AppLayerTlsDetectVersionData_ {
uint8_t ver; /** tls version to match */
} AppLayerTlsDetectVersionData;
/* prototypes */
void AppLayerTlsDetectVersionRegister (void);
#endif /* __APP_LAYER_TLS_DETECT_VERSION_H__ */

@ -18,6 +18,8 @@
#include "conf.h"
#include "app-layer-tls.h"
#include "util-binsearch.h"
#include "util-unittest.h"
#include "util-debug.h"
@ -111,7 +113,17 @@ static int TLSParseClientVersion(void *tls_state, AppLayerParserState *pstate,
} *u16conv;
u16conv = (struct u16conv_ *)input;
state->client_version = ntohs(u16conv->u);
switch (ntohs(u16conv->u)) {
case 0x0301:
state->client_version = TLS_VERSION_10;
break;
case 0x0302:
state->client_version = TLS_VERSION_11;
break;
case 0x0303:
state->client_version = TLS_VERSION_12;
break;
}
SCLogDebug("version %04"PRIx16"", state->client_version);
return 1;
@ -517,9 +529,8 @@ static int TLSParserTest01(void) {
goto end;
}
if (tls_state->client_version != 0x0301) {
printf("expected version %04" PRIu16 ", got %04" PRIu16 ": ", 0x0301,
tls_state->client_version);
if (tls_state->client_version != TLS_VERSION_10) {
printf("expected version %04" PRIu16 ", got %04" PRIu16 ": ", TLS_VERSION_10, tls_state->client_version);
result = 0;
goto end;
}
@ -571,9 +582,8 @@ static int TLSParserTest02(void) {
goto end;
}
if (tls_state->client_version != 0x0301) {
printf("expected version %04" PRIu16 ", got %04" PRIu16 ": ", 0x0301,
tls_state->client_version);
if (tls_state->client_version != TLS_VERSION_10) {
printf("expected version %04" PRIu16 ", got %04" PRIu16 ": ", TLS_VERSION_10, tls_state->client_version);
result = 0;
goto end;
}
@ -634,9 +644,8 @@ static int TLSParserTest03(void) {
goto end;
}
if (tls_state->client_version != 0x0301) {
printf("expected version %04" PRIu16 ", got %04" PRIu16 ": ", 0x0301,
tls_state->client_version);
if (tls_state->client_version != TLS_VERSION_10) {
printf("expected version %04" PRIu16 ", got %04" PRIu16 ": ", TLS_VERSION_10, tls_state->client_version);
result = 0;
goto end;
}
@ -1005,9 +1014,8 @@ static int TLSParserMultimsgTest01(void) {
goto end;
}
if (tls_state->client_version != 0x0301) {
printf("expected version %04" PRIu16 ", got %04" PRIu16 ": ", 0x0301,
tls_state->client_version);
if (tls_state->client_version != TLS_VERSION_10) {
printf("expected version %04" PRIu16 ", got %04" PRIu16 ": ", TLS_VERSION_10, tls_state->client_version);
result = 0;
goto end;
}

@ -34,6 +34,14 @@ typedef struct TlsState_ {
uint8_t records; /**< no of records */
} TlsState;
enum {
TLS_VERSION_INVALID = 0,
TLS_VERSION_VALID,
TLS_VERSION_10,
TLS_VERSION_11,
TLS_VERSION_12,
};
void RegisterTLSParsers(void);
void TLSParserRegisterTests(void);

@ -0,0 +1,30 @@
#include "eidps-common.h"
#include "app-layer.h"
#include "stream-tcp-private.h"
/** \brief Get the active app layer state from the packet */
void *AppLayerGetProtoStateFromPacket(Packet *p) {
if (p == NULL || p->flow == NULL)
return NULL;
TcpSession *ssn = (TcpSession *)p->flow->protoctx;
if (ssn == NULL || ssn->aldata == NULL)
return NULL;
void *alstate = ssn->aldata[ssn->alproto];
return alstate;
}
/** \brief Get the active app layer state from the flow */
void *AppLayerGetProtoStateFromFlow(Flow *f) {
if (f == NULL)
return NULL;
TcpSession *ssn = (TcpSession *)f->protoctx;
if (ssn == NULL || ssn->aldata == NULL)
return NULL;
void *alstate = ssn->aldata[ssn->alproto];
return alstate;
}

@ -0,0 +1,15 @@
#ifndef __APP_LAYER_H__
#define __APP_LAYER_H__
#include "flow.h"
#include "decode.h"
#include "app-layer-protos.h"
#include "app-layer-parser.h"
#include "stream.h"
void *AppLayerGetProtoStateFromPacket(Packet *);
void *AppLayerGetProtoStateFromFlow(Flow *);
#endif /* __APP_LAYER_H__ */

@ -95,6 +95,10 @@ int DetectProtoParse(DetectProto *dp, char *str)
memset(dp->proto, 0xff, sizeof(dp->proto));
SCLogDebug("DetectProtoParse: IP protocol detected");
} else {
goto error;
/** \todo are numeric protocols even valid? */
#if 0
uint8_t proto_u8; /* Used to avoid sign extension */
/* Extract out a 0-256 value with validation checks */
@ -111,8 +115,8 @@ int DetectProtoParse(DetectProto *dp, char *str)
} else {
dp->proto[proto / 8] |= 1<<(proto % 8);
}
#endif
}
return 0;
error:

@ -16,6 +16,10 @@
#include "util-rule-vars.h"
#include "conf.h"
#include "conf-yaml-loader.h"
#include "app-layer-protos.h"
#include "app-layer-parser.h"
#include "util-unittest.h"
#include "util-debug.h"
@ -44,7 +48,7 @@ static uint32_t dbg_dstportany_cnt = 0;
// action protocol src sp dir dst dp options
#define CONFIG_PCRE "^([A-z]+)\\s+([A-z0-9]+)\\s+([\\[\\]A-z0-9\\.\\:_\\$\\!\\-,\\/]+)\\s+([\\:A-z0-9_\\$\\!,]+)\\s+(-\\>|\\<\\>)\\s+([\\[\\]A-z0-9\\.\\:_\\$\\!\\-,/]+)\\s+([\\:A-z0-9_\\$\\!,]+)(?:\\s+\\((.*)?(?:\\s*)\\))?(?:(?:\\s*)\\n)?$"
#define OPTION_PARTS 3
#define OPTION_PCRE "^\\s*([A-z_0-9-]+)(?:\\s*\\:\\s*(.*)(?<!\\\\))?\\s*;\\s*(?:\\s*(.*))?\\s*$"
#define OPTION_PCRE "^\\s*([A-z_0-9-\\.]+)(?:\\s*\\:\\s*(.*)(?<!\\\\))?\\s*;\\s*(?:\\s*(.*))?\\s*$"
uint32_t DbgGetSrcPortAnyCnt(void) {
return dbg_srcportany_cnt;
@ -308,8 +312,16 @@ error:
*/
int SigParseProto(Signature *s, const char *protostr) {
int r = DetectProtoParse(&s->proto, (char *)protostr);
if (r < 0)
if (r < 0) {
s->alproto = AppLayerGetProtoByName(protostr);
if (s->alproto != ALPROTO_UNKNOWN) {
/* indicate that the signature is app-layer */
s->flags |= SIG_FLAG_APPLAYER;
return 0;
}
return -1;
}
return 0;
}
@ -854,6 +866,7 @@ end:
DetectEngineCtxFree(de_ctx);
return result;
}
/**
* \test check that we don't allow invalid negation options
*/
@ -960,6 +973,100 @@ end:
return result;
}
/**
* \test test tls (app layer) rule
*/
static int SigParseTestAppLayerTLS01(void) {
int result = 0;
DetectEngineCtx *de_ctx;
Signature *s=NULL;
de_ctx = DetectEngineCtxInit();
if (de_ctx == NULL)
goto end;
de_ctx->flags |= DE_QUIET;
s = SigInit(de_ctx,"alert tls any any -> any any (msg:\"SigParseTestAppLayerTLS01 \"; classtype:misc-activity; sid:410006; rev:1;)");
if (s == NULL) {
printf("parsing sig failed: ");
goto end;
}
if (s->alproto == 0) {
printf("alproto not set: ");
goto end;
}
result = 1;
end:
if (s->alproto == 0) {
printf("alproto not set: ");
if (s != NULL)
SigFree(s);
if (de_ctx != NULL)
DetectEngineCtxFree(de_ctx);
return result;
}
/**
* \test test tls (app layer) rule
*/
static int SigParseTestAppLayerTLS02(void) {
int result = 0;
DetectEngineCtx *de_ctx;
Signature *s=NULL;
de_ctx = DetectEngineCtxInit();
if (de_ctx == NULL)
goto end;
de_ctx->flags |= DE_QUIET;
s = SigInit(de_ctx,"alert tls any any -> any any (msg:\"SigParseTestAppLayerTLS02 \"; tls.version:1.0; classtype:misc-activity; sid:410006; rev:1;)");
if (s == NULL) {
printf("parsing sig failed: ");
goto end;
}
if (s->alproto == 0) {
printf("alproto not set: ");
goto end;
}
result = 1;
end:
if (s != NULL)
SigFree(s);
if (de_ctx != NULL)
DetectEngineCtxFree(de_ctx);
return result;
}
/**
* \test test tls (app layer) rule
*/
static int SigParseTestAppLayerTLS03(void) {
int result = 0;
DetectEngineCtx *de_ctx;
Signature *s=NULL;
de_ctx = DetectEngineCtxInit();
if (de_ctx == NULL)
goto end;
de_ctx->flags |= DE_QUIET;
s = SigInit(de_ctx,"alert tls any any -> any any (msg:\"SigParseTestAppLayerTLS03 \"; tls.version:2.5; classtype:misc-activity; sid:410006; rev:1;)");
if (s != NULL) {
SigFree(s);
goto end;
}
result = 1;
end:
if (de_ctx != NULL)
DetectEngineCtxFree(de_ctx);
return result;
}
#endif /* UNITTESTS */
void SigParseRegisterTests(void) {
@ -978,5 +1085,8 @@ void SigParseRegisterTests(void) {
UtRegisterTest("SigParseTestNegation07", SigParseTestNegation07, 1);
UtRegisterTest("SigParseTestMpm01", SigParseTestMpm01, 1);
UtRegisterTest("SigParseTestMpm02", SigParseTestMpm02, 1);
UtRegisterTest("SigParseTestAppLayerTLS01", SigParseTestAppLayerTLS01, 1);
UtRegisterTest("SigParseTestAppLayerTLS02", SigParseTestAppLayerTLS02, 1);
UtRegisterTest("SigParseTestAppLayerTLS03", SigParseTestAppLayerTLS03, 1);
#endif /* UNITTESTS */
}

@ -62,6 +62,10 @@
#include "detect-fast-pattern.h"
#include "util-rule-vars.h"
#include "app-layer.h"
#include "app-layer-tls-detect-version.h"
#include "action-globals.h"
#include "tm-modules.h"
@ -344,6 +348,102 @@ inline SigGroupHead *SigMatchSignaturesGetSgh(ThreadVars *th_v, DetectEngineCtx
return sgh;
}
static int SigMatchSignaturesAppLayer(ThreadVars *th_v, DetectEngineCtx *de_ctx, DetectEngineThreadCtx *det_ctx, SigGroupHead *sgh, Packet *p)
{
int match = 0, fmatch = 0;
Signature *s = NULL;
SigMatch *sm = NULL;
uint32_t idx,sig;
void *alstate = AppLayerGetProtoStateFromPacket(p);
if (alstate == NULL)
return 0;
uint8_t flags = 0;
/* if we didn't get a sig group head, we
* have nothing to do.... */
if (sgh == NULL) {
return 0;
}
/* inspect the sigs against the packet */
for (idx = 0; idx < sgh->sig_cnt; idx++) {
sig = sgh->match_array[idx];
s = de_ctx->sig_array[sig];
/* only inspect app layer sigs here */
if (!(s->flags & SIG_FLAG_APPLAYER))
continue;
/* filter out the sigs that inspects the payload, if packet
no payload inspection flag is set*/
if ((p->flags & PKT_NOPAYLOAD_INSPECTION) && (s->flags & SIG_FLAG_PAYLOAD))
continue;
/* check the source & dst port in the sig */
if (p->proto == IPPROTO_TCP || p->proto == IPPROTO_UDP) {
if (!(s->flags & SIG_FLAG_DP_ANY)) {
DetectPort *dport = DetectPortLookupGroup(s->dp,p->dp);
if (dport == NULL)
continue;
}
if (!(s->flags & SIG_FLAG_SP_ANY)) {
DetectPort *sport = DetectPortLookupGroup(s->sp,p->sp);
if (sport == NULL)
continue;
}
}
/* check the source address */
if (!(s->flags & SIG_FLAG_SRC_ANY)) {
DetectAddressGroup *saddr = DetectAddressLookupGroup(&s->src,&p->src);
if (saddr == NULL)
continue;
}
/* check the destination address */
if (!(s->flags & SIG_FLAG_DST_ANY)) {
DetectAddressGroup *daddr = DetectAddressLookupGroup(&s->dst,&p->dst);
if (daddr == NULL)
continue;
}
/* reset pkt ptr and offset */
det_ctx->pkt_ptr = NULL;
det_ctx->pkt_off = 0;
sm = s->match;
while (sm) {
if (sigmatch_table[sm->type].AppLayerMatch == NULL)
continue;
match = sigmatch_table[sm->type].AppLayerMatch(th_v, det_ctx, p->flow, flags, alstate, s, sm);
if (match) {
/* okay, try the next match */
sm = sm->next;
/* only if the last matched as well, we have a hit */
if (sm == NULL) {
fmatch = 1;
//printf("DE : sig %" PRIu32 " matched\n", s->id);
if (!(s->flags & SIG_FLAG_NOALERT)) {
PacketAlertAppend(p, 1, s->id, s->rev, s->prio, s->msg);
/* set verdict on packet */
p->action = s->action;
}
}
} else {
/* done with this sig */
sm = NULL;
}
}
}
return fmatch;
}
int SigMatchSignatures(ThreadVars *th_v, DetectEngineCtx *de_ctx, DetectEngineThreadCtx *det_ctx, Packet *p)
{
int match = 0, fmatch = 0;
@ -427,6 +527,10 @@ int SigMatchSignatures(ThreadVars *th_v, DetectEngineCtx *de_ctx, DetectEngineTh
continue;
}
/* don't inspect app layer sigs here */
if (s->flags & SIG_FLAG_APPLAYER)
continue;
/* filter out sigs that want pattern matches, but
* have no matches */
if (!(det_ctx->pmq.sig_bitarray[(sig / 8)] & (1<<(sig % 8))) &&
@ -499,6 +603,9 @@ int SigMatchSignatures(ThreadVars *th_v, DetectEngineCtx *de_ctx, DetectEngineTh
do {
sm = s->match;
while (sm) {
if (sigmatch_table[sm->type].Match == NULL)
continue;
match = sigmatch_table[sm->type].Match(th_v, det_ctx, p, s, sm);
if (match) {
/* okay, try the next match */
@ -534,6 +641,9 @@ int SigMatchSignatures(ThreadVars *th_v, DetectEngineCtx *de_ctx, DetectEngineTh
SCLogDebug("running match functions, sm %p", sm);
while (sm) {
if (sigmatch_table[sm->type].Match == NULL)
continue;
match = sigmatch_table[sm->type].Match(th_v, det_ctx, p, s, sm);
if (match) {
/* okay, try the next match */
@ -560,6 +670,12 @@ int SigMatchSignatures(ThreadVars *th_v, DetectEngineCtx *de_ctx, DetectEngineTh
/* cleanup pkt specific part of the patternmatcher */
PacketPatternCleanup(th_v, det_ctx);
match = SigMatchSignaturesAppLayer(th_v, de_ctx, det_ctx, det_ctx->sgh, p);
if (match > 0) {
fmatch = 1;
}
SCReturnInt(fmatch);
}
@ -629,6 +745,13 @@ void SigCleanSignatures(DetectEngineCtx *de_ctx)
de_ctx->sig_list = NULL;
}
int SignatureIsAppLayer(DetectEngineCtx *de_ctx, Signature *s) {
if (s->alproto != 0)
return 1;
return 0;
}
/** \brief Test is a initialized signature is IP only
* \param de_ctx detection engine ctx
* \param s the signature
@ -2184,7 +2307,7 @@ int SigAddressPrepareStage3(DetectEngineCtx *de_ctx) {
SCLogInfo("MPM max patcnt %" PRIu32 ", avg %" PRIu32 "", de_ctx->mpm_max_patcnt, de_ctx->mpm_unique?de_ctx->mpm_tot_patcnt/de_ctx->mpm_unique:0);
if (de_ctx->mpm_uri_tot_patcnt && de_ctx->mpm_uri_unique)
SCLogInfo("MPM (URI) max patcnt %" PRIu32 ", avg %" PRIu32 " (%" PRIu32 "/%" PRIu32 ")", de_ctx->mpm_uri_max_patcnt, de_ctx->mpm_uri_tot_patcnt/de_ctx->mpm_uri_unique, de_ctx->mpm_uri_tot_patcnt, de_ctx->mpm_uri_unique);
SCLogInfo("port maxgroups: %" PRIu32 ", avg %" PRIu32 ", tot %" PRIu32 "", g_groupportlist_maxgroups, g_groupportlist_totgroups/g_groupportlist_groupscnt, g_groupportlist_totgroups);
SCLogInfo("port maxgroups: %" PRIu32 ", avg %" PRIu32 ", tot %" PRIu32 "", g_groupportlist_maxgroups, g_groupportlist_groupscnt ? g_groupportlist_totgroups/g_groupportlist_groupscnt : 0, g_groupportlist_totgroups);
SCLogInfo("building signature grouping structure, stage 3: building destination address lists... done");
}
return 0;
@ -2625,6 +2748,8 @@ void SigTableSetup(void) {
DetectTtlRegister();
DetectFastPatternRegister();
AppLayerTlsDetectVersionRegister();
uint8_t i = 0;
for (i = 0; i < DETECT_TBLSIZE; i++) {
if (sigmatch_table[i].RegisterTests == NULL) {

@ -3,6 +3,8 @@
#include <stdint.h>
#include "flow.h"
#include "detect-engine-proto.h"
#include "packet-queue.h"
@ -127,6 +129,7 @@ typedef struct DetectPort_ {
#define SIG_FLAG_DSIZE 0x0400 /**< signature has a dsize setting */
#define SIG_FLAG_FLOW 0x0800 /**< signature has a flow setting */
#define SIG_FLAG_MPM_NEGCONTENT 0x1000 /**< sig has negative mpm portion(!content) */
#define SIG_FLAG_APPLAYER 0x2000 /**< signature applies to app layer instead of packets */
/* Detection Engine flags */
#define DE_QUIET 0x01 /**< DE is quiet (esp for unittests) */
@ -166,6 +169,9 @@ typedef struct Signature_ {
/* helper for init phase */
uint16_t mpm_content_maxlen;
uint16_t mpm_uricontent_maxlen;
/* app layer signature stuff */
uint8_t alproto;
} Signature;
/** \brief IP only rules matching ctx.
@ -332,7 +338,11 @@ typedef struct SigMatch_ {
/** \brief element in sigmatch type table. */
typedef struct SigTableElmt_ {
/** Packet match function */
int (*Match)(ThreadVars *, DetectEngineThreadCtx *, Packet *, Signature *, SigMatch *);
/** AppLayer match function */
int (*AppLayerMatch)(ThreadVars *, DetectEngineThreadCtx *, Flow *, uint8_t flags, void *alstate, Signature *, SigMatch *);
int (*Setup)(DetectEngineCtx *, Signature *, SigMatch *, char *);
void (*Free)(void *);
void (*RegisterTests)(void);
@ -453,6 +463,8 @@ enum {
DETECT_FRAGBITS,
DETECT_GID,
DETECT_AL_TLS_VERSION,
/* make sure this stays last */
DETECT_TBLSIZE,
};

Loading…
Cancel
Save