detect-engine: improved inspect engines

Inspect engines are called per signature per sigmatch list. Most
wrap around DetectEngineContentInspection, but it's more generic.

Until now, the inspect engines were setup in a large per ipproto,
per alproto, per direction table. For stateful inspection each
engine needed a global flag.

This approach had a number of issues:
1. inefficient: each inspection round walked the table and then
   checked if the inspect engine was even needed for the current
   rule.
2. clumsy registration with global flag registration.
3. global flag space was approaching the need for 64 bits
4. duplicate registration for alprotos supporting both TCP and
   TCP (DNS).

This patch introduces a new approach.

First, it does away with the per ipproto engines. This wasn't used.

Second, it adds a per signature list of inspect engine containing
only those engines that actually apply to the rule.

Third, it gets rid of the global flags and replaces it with flags
assigned per rule per engine.
pull/2310/head
Victor Julien 10 years ago
parent bac37fc9ae
commit 5f994756e6

@ -523,13 +523,13 @@ int DeStateDetectStartDetection(ThreadVars *tv, DetectEngineCtx *de_ctx,
det_ctx->tx_id = tx_id;
det_ctx->tx_id_set = 1;
DetectEngineAppInspectionEngine *engine = app_inspection_engine[f->protomap][alproto][direction];
DetectEngineAppInspectionEngine *engine = s->app_inspect;
SCLogDebug("engine %p", engine);
inspect_flags = 0;
while (engine != NULL) {
SCLogDebug("engine %p", engine);
SCLogDebug("inspect_flags %x", inspect_flags);
if (s->sm_lists[engine->sm_list] != NULL) {
if (direction == engine->dir) {
KEYWORD_PROFILING_SET_LIST(det_ctx, engine->sm_list);
int match = engine->Callback(tv, de_ctx, det_ctx, s, f,
flags, alstate,
@ -843,7 +843,8 @@ static int DoInspectItem(ThreadVars *tv,
det_ctx->tx_id_set = 1;
SCLogDebug("inspecting: tx %u packet %u", (uint)inspect_tx_id, (uint)p->pcap_cnt);
DetectEngineAppInspectionEngine *engine = app_inspection_engine[f->protomap][alproto][(flags & STREAM_TOSERVER) ? 0 : 1];
uint8_t direction = (flags & STREAM_TOSERVER) ? 0 : 1;
DetectEngineAppInspectionEngine *engine = s->app_inspect;
void *inspect_tx = AppLayerParserGetTx(f->proto, alproto, alstate, inspect_tx_id);
if (inspect_tx == NULL) {
RULE_PROFILING_END(det_ctx, s, 0, p);
@ -852,7 +853,7 @@ static int DoInspectItem(ThreadVars *tv,
while (engine != NULL) {
if (!(item->flags & engine->inspect_flags) &&
s->sm_lists[engine->sm_list] != NULL)
direction == engine->dir)
{
SCLogDebug("inspect_flags %x", inspect_flags);
KEYWORD_PROFILING_SET_LIST(det_ctx, engine->sm_list);
@ -1341,13 +1342,8 @@ end:
static int DeStateTest03(void)
{
int result = 0;
DetectEngineState *state = DetectEngineStateAlloc();
if (state == NULL) {
printf("d == NULL: ");
goto end;
}
FAIL_IF_NULL(state);
Signature s;
memset(&s, 0x00, sizeof(s));
@ -1357,34 +1353,20 @@ static int DeStateTest03(void)
s.num = 11;
DeStateSignatureAppend(state, &s, 0, direction);
s.num = 22;
DeStateSignatureAppend(state, &s, DE_STATE_FLAG_URI_INSPECT, direction);
DeStateSignatureAppend(state, &s, BIT_U32(DE_STATE_FLAG_BASE), direction);
if (state->dir_state[direction & STREAM_TOSERVER ? 0 : 1].head == NULL) {
goto end;
}
FAIL_IF(state->dir_state[direction & STREAM_TOSERVER ? 0 : 1].head == NULL);
if (state->dir_state[direction & STREAM_TOSERVER ? 0 : 1].head->store[0].sid != 11) {
goto end;
}
FAIL_IF(state->dir_state[direction & STREAM_TOSERVER ? 0 : 1].head->store[0].sid != 11);
if (state->dir_state[direction & STREAM_TOSERVER ? 0 : 1].head->store[0].flags & DE_STATE_FLAG_URI_INSPECT) {
goto end;
}
FAIL_IF(state->dir_state[direction & STREAM_TOSERVER ? 0 : 1].head->store[0].flags & BIT_U32(DE_STATE_FLAG_BASE));
if (state->dir_state[direction & STREAM_TOSERVER ? 0 : 1].head->store[1].sid != 22) {
goto end;
}
FAIL_IF(state->dir_state[direction & STREAM_TOSERVER ? 0 : 1].head->store[1].sid != 22);
if (!(state->dir_state[direction & STREAM_TOSERVER ? 0 : 1].head->store[1].flags & DE_STATE_FLAG_URI_INSPECT)) {
goto end;
}
FAIL_IF(!(state->dir_state[direction & STREAM_TOSERVER ? 0 : 1].head->store[1].flags & BIT_U32(DE_STATE_FLAG_BASE)));
result = 1;
end:
if (state != NULL) {
DetectEngineStateFree(state);
}
return result;
DetectEngineStateFree(state);
PASS;
}
static int DeStateSigTest01(void)
@ -1535,7 +1517,6 @@ end:
/** \test multiple pipelined http transactions */
static int DeStateSigTest02(void)
{
int result = 0;
Signature *s = NULL;
DetectEngineThreadCtx *det_ctx = NULL;
ThreadVars th_v;
@ -1578,22 +1559,14 @@ static int DeStateSigTest02(void)
StreamTcpInitConfig(TRUE);
DetectEngineCtx *de_ctx = DetectEngineCtxInit();
if (de_ctx == NULL) {
goto end;
}
FAIL_IF_NULL(de_ctx);
de_ctx->flags |= DE_QUIET;
s = DetectEngineAppendSig(de_ctx, "alert tcp any any -> any any (content:\"POST\"; http_method; content:\"/\"; http_uri; content:\"Mozilla\"; http_header; content:\"dummy\"; http_cookie; content:\"body\"; nocase; http_client_body; sid:1; rev:1;)");
if (s == NULL) {
printf("sig parse failed: ");
goto end;
}
FAIL_IF_NULL(s);
s = DetectEngineAppendSig(de_ctx, "alert tcp any any -> any any (content:\"GET\"; http_method; content:\"Firefox\"; http_header; content:\"dummy2\"; http_cookie; sid:2; rev:1;)");
if (s == NULL) {
printf("sig2 parse failed: ");
goto end;
}
FAIL_IF_NULL(s);
SigGroupBuild(de_ctx);
DetectEngineThreadCtxInit(&th_v, (void *)de_ctx, (void *)&det_ctx);
@ -1601,116 +1574,74 @@ static int DeStateSigTest02(void)
FLOWLOCK_WRLOCK(&f);
int r = AppLayerParserParse(NULL, alp_tctx, &f, ALPROTO_HTTP,
STREAM_TOSERVER, httpbuf1, httplen1);
if (r != 0) {
printf("toserver chunk 1 returned %" PRId32 ", expected 0: ", r);
FLOWLOCK_UNLOCK(&f);
goto end;
}
FLOWLOCK_UNLOCK(&f);
FAIL_IF(r != 0);
/* do detect */
SigMatchSignatures(&th_v, de_ctx, det_ctx, p);
if (PacketAlertCheck(p, 1)) {
printf("sig 1 alerted: ");
goto end;
}
FAIL_IF(PacketAlertCheck(p, 1));
p->alerts.cnt = 0;
FLOWLOCK_WRLOCK(&f);
r = AppLayerParserParse(NULL, alp_tctx, &f, ALPROTO_HTTP,
STREAM_TOSERVER, httpbuf2, httplen2);
if (r != 0) {
printf("toserver chunk 2 returned %" PRId32 ", expected 0: ", r);
FLOWLOCK_UNLOCK(&f);
goto end;
}
FLOWLOCK_UNLOCK(&f);
FAIL_IF(r != 0);
/* do detect */
SigMatchSignatures(&th_v, de_ctx, det_ctx, p);
if (PacketAlertCheck(p, 1)) {
printf("sig 1 alerted (2): ");
goto end;
}
FAIL_IF(PacketAlertCheck(p, 1));
p->alerts.cnt = 0;
FLOWLOCK_WRLOCK(&f);
r = AppLayerParserParse(NULL, alp_tctx, &f, ALPROTO_HTTP,
STREAM_TOSERVER, httpbuf3, httplen3);
if (r != 0) {
printf("toserver chunk 3 returned %" PRId32 ", expected 0: ", r);
FLOWLOCK_UNLOCK(&f);
goto end;
}
FLOWLOCK_UNLOCK(&f);
FAIL_IF(r != 0);
/* do detect */
SigMatchSignatures(&th_v, de_ctx, det_ctx, p);
if (PacketAlertCheck(p, 1)) {
printf("sig 1 alerted too early: ");
goto end;
}
FAIL_IF(PacketAlertCheck(p, 1));
p->alerts.cnt = 0;
void *tx = AppLayerParserGetTx(IPPROTO_TCP, ALPROTO_HTTP, f.alstate, 0);
if (tx == NULL) {
printf("no http tx: ");
goto end;
}
FAIL_IF_NULL(tx);
DetectEngineState *tx_de_state = AppLayerParserGetTxDetectState(IPPROTO_TCP, ALPROTO_HTTP, tx);
if (tx_de_state == NULL || tx_de_state->dir_state[0].cnt != 1 ||
tx_de_state->dir_state[0].head->store[0].flags != 0x00000001) {
printf("de_state not present or has unexpected content: ");
goto end;
}
FAIL_IF_NULL(tx_de_state);
FAIL_IF(tx_de_state->dir_state[0].cnt != 1);
FAIL_IF(tx_de_state->dir_state[0].head->store[0].flags != BIT_U32(DE_STATE_FLAG_BASE));
FLOWLOCK_WRLOCK(&f);
r = AppLayerParserParse(NULL, alp_tctx, &f, ALPROTO_HTTP,
STREAM_TOSERVER, httpbuf4, httplen4);
if (r != 0) {
printf("toserver chunk 4 returned %" PRId32 ", expected 0: ", r);
result = 0;
FLOWLOCK_UNLOCK(&f);
goto end;
}
FLOWLOCK_UNLOCK(&f);
FAIL_IF(r != 0);
/* do detect */
SigMatchSignatures(&th_v, de_ctx, det_ctx, p);
if (!(PacketAlertCheck(p, 1))) {
printf("sig 1 didn't match: ");
goto end;
}
p->alerts.cnt = 0;
FAIL_IF(!(PacketAlertCheck(p, 1)));
FLOWLOCK_WRLOCK(&f);
r = AppLayerParserParse(NULL, alp_tctx, &f, ALPROTO_HTTP,
STREAM_TOSERVER, httpbuf5, httplen5);
if (r != 0) {
printf("toserver chunk 5 returned %" PRId32 ", expected 0: ", r);
FLOWLOCK_UNLOCK(&f);
goto end;
}
FLOWLOCK_UNLOCK(&f);
FAIL_IF(r != 0);
/* do detect */
SigMatchSignatures(&th_v, de_ctx, det_ctx, p);
if (PacketAlertCheck(p, 1)) {
printf("sig 1 alerted (5): ");
goto end;
}
FAIL_IF(PacketAlertCheck(p, 1));
p->alerts.cnt = 0;
FLOWLOCK_WRLOCK(&f);
r = AppLayerParserParse(NULL, alp_tctx, &f, ALPROTO_HTTP,
STREAM_TOSERVER, httpbuf6, httplen6);
if (r != 0) {
printf("toserver chunk 6 returned %" PRId32 ", expected 0: ", r);
FLOWLOCK_UNLOCK(&f);
goto end;
}
FLOWLOCK_UNLOCK(&f);
FAIL_IF(r != 0);
/* do detect */
SigMatchSignatures(&th_v, de_ctx, det_ctx, p);
if ((PacketAlertCheck(p, 1)) || (PacketAlertCheck(p, 2))) {
printf("sig 1 alerted (request 2, chunk 6): ");
goto end;
}
FAIL_IF((PacketAlertCheck(p, 1)) || (PacketAlertCheck(p, 2)));
p->alerts.cnt = 0;
SCLogDebug("sending data chunk 7");
@ -1718,36 +1649,21 @@ static int DeStateSigTest02(void)
FLOWLOCK_WRLOCK(&f);
r = AppLayerParserParse(NULL, alp_tctx, &f, ALPROTO_HTTP,
STREAM_TOSERVER, httpbuf7, httplen7);
if (r != 0) {
printf("toserver chunk 7 returned %" PRId32 ", expected 0: ", r);
FLOWLOCK_UNLOCK(&f);
goto end;
}
FLOWLOCK_UNLOCK(&f);
FAIL_IF(r != 0);
/* do detect */
SigMatchSignatures(&th_v, de_ctx, det_ctx, p);
if (!(PacketAlertCheck(p, 2))) {
printf("signature 2 didn't match, but should have: ");
goto end;
}
FAIL_IF(!(PacketAlertCheck(p, 2)));
p->alerts.cnt = 0;
result = 1;
end:
if (alp_tctx != NULL)
AppLayerParserThreadCtxFree(alp_tctx);
if (det_ctx != NULL) {
DetectEngineThreadCtxDeinit(&th_v, (void *)det_ctx);
}
if (de_ctx != NULL) {
SigGroupCleanup(de_ctx);
DetectEngineCtxFree(de_ctx);
}
AppLayerParserThreadCtxFree(alp_tctx);
DetectEngineThreadCtxDeinit(&th_v, (void *)det_ctx);
DetectEngineCtxFree(de_ctx);
StreamTcpFreeConfig(TRUE);
FLOW_DESTROY(&f);
UTHFreePacket(p);
return result;
PASS;
}
static int DeStateSigTest03(void)
@ -1766,7 +1682,6 @@ static int DeStateSigTest03(void)
uint32_t httplen1 = sizeof(httpbuf1) - 1; /* minus the \0 */
ThreadVars th_v;
TcpSession ssn;
int result = 0;
Flow *f = NULL;
Packet *p = NULL;
HtpState *http_state = NULL;
@ -1777,31 +1692,24 @@ static int DeStateSigTest03(void)
DetectEngineThreadCtx *det_ctx = NULL;
DetectEngineCtx *de_ctx = DetectEngineCtxInit();
if (de_ctx == NULL) {
goto end;
}
FAIL_IF_NULL(de_ctx);
de_ctx->flags |= DE_QUIET;
Signature *s = DetectEngineAppendSig(de_ctx, "alert http any any -> any any (content:\"POST\"; http_method; content:\"upload.cgi\"; http_uri; filestore; sid:1; rev:1;)");
if (s == NULL) {
printf("sig parse failed: ");
goto end;
}
FAIL_IF_NULL(s);
SigGroupBuild(de_ctx);
DetectEngineThreadCtxInit(&th_v, (void *)de_ctx, (void *)&det_ctx);
f = UTHBuildFlow(AF_INET, "1.2.3.4", "1.2.3.5", 1024, 80);
if (f == NULL)
goto end;
FAIL_IF_NULL(f);
f->protoctx = &ssn;
f->proto = IPPROTO_TCP;
f->alproto = ALPROTO_HTTP;
p = UTHBuildPacket(NULL, 0, IPPROTO_TCP);
if (p == NULL)
goto end;
FAIL_IF_NULL(p);
p->flow = f;
p->flags |= PKT_HAS_FLOW|PKT_STREAM_EST;
@ -1815,69 +1723,36 @@ static int DeStateSigTest03(void)
STREAM_TOSERVER | STREAM_START | STREAM_EOF,
httpbuf1,
httplen1);
if (r != 0) {
printf("toserver chunk 1 returned %" PRId32 ", expected 0: ", r);
result = 0;
FLOWLOCK_UNLOCK(f);
goto end;
}
FLOWLOCK_UNLOCK(f);
/* do detect */
SigMatchSignatures(&th_v, de_ctx, det_ctx, p);
if (!(PacketAlertCheck(p, 1))) {
printf("sig 1 didn't alert: ");
goto end;
}
FAIL_IF(r != 0);
http_state = f->alstate;
if (http_state == NULL) {
printf("no http state: ");
result = 0;
goto end;
}
FAIL_IF_NULL(http_state);
FAIL_IF_NULL(http_state->files_ts);
if (http_state->files_ts == NULL) {
printf("no files in state: ");
goto end;
}
/* do detect */
SigMatchSignatures(&th_v, de_ctx, det_ctx, p);
FAIL_IF(!(PacketAlertCheck(p, 1)));
FLOWLOCK_WRLOCK(f);
FileContainer *files = AppLayerParserGetFiles(p->flow->proto, p->flow->alproto,
p->flow->alstate, STREAM_TOSERVER);
if (files == NULL) {
printf("no stored files: ");
FLOWLOCK_UNLOCK(f);
goto end;
}
FLOWLOCK_UNLOCK(f);
FAIL_IF_NULL(files);
File *file = files->head;
if (file == NULL) {
printf("no file: ");
goto end;
}
FAIL_IF_NULL(file);
if (!(file->flags & FILE_STORE)) {
printf("file is set to store, but sig didn't match: ");
goto end;
}
FAIL_IF(!(file->flags & FILE_STORE));
result = 1;
end:
if (alp_tctx != NULL)
AppLayerParserThreadCtxFree(alp_tctx);
AppLayerParserThreadCtxFree(alp_tctx);
UTHFreeFlow(f);
if (det_ctx != NULL) {
DetectEngineThreadCtxDeinit(&th_v, (void *)det_ctx);
}
if (de_ctx != NULL) {
SigGroupCleanup(de_ctx);
DetectEngineCtxFree(de_ctx);
}
DetectEngineThreadCtxDeinit(&th_v, (void *)det_ctx);
DetectEngineCtxFree(de_ctx);
StreamTcpFreeConfig(TRUE);
return result;
PASS;
}
static int DeStateSigTest04(void)

@ -66,35 +66,12 @@
#define DE_STATE_FLAG_FULL_INSPECT BIT_U32(0)
#define DE_STATE_FLAG_SIG_CANT_MATCH BIT_U32(1)
#define DE_STATE_FLAG_URI_INSPECT BIT_U32(2)
#define DE_STATE_FLAG_HRUD_INSPECT BIT_U32(3)
#define DE_STATE_FLAG_HCBD_INSPECT BIT_U32(4)
#define DE_STATE_FLAG_HSBD_INSPECT BIT_U32(5)
#define DE_STATE_FLAG_HHD_INSPECT BIT_U32(6)
#define DE_STATE_FLAG_HRHD_INSPECT BIT_U32(7)
#define DE_STATE_FLAG_HHHD_INSPECT BIT_U32(8)
#define DE_STATE_FLAG_HRHHD_INSPECT BIT_U32(9)
#define DE_STATE_FLAG_HUAD_INSPECT BIT_U32(10)
#define DE_STATE_FLAG_HMD_INSPECT BIT_U32(11)
#define DE_STATE_FLAG_HCD_INSPECT BIT_U32(12)
#define DE_STATE_FLAG_HSMD_INSPECT BIT_U32(13)
#define DE_STATE_FLAG_HSCD_INSPECT BIT_U32(14)
#define DE_STATE_FLAG_FILE_TC_INSPECT BIT_U32(15)
#define DE_STATE_FLAG_FILE_TS_INSPECT BIT_U32(16)
#define DE_STATE_FLAG_DNSQUERYNAME_INSPECT BIT_U32(17)
#define DE_STATE_FLAG_APP_EVENT_INSPECT BIT_U32(18)
#define DE_STATE_FLAG_MODBUS_INSPECT BIT_U32(19)
#define DE_STATE_FLAG_HTTP_REQLINE_INSPECT BIT_U32(20)
#define DE_STATE_FLAG_FD_SMTP_INSPECT BIT_U32(21)
#define DE_STATE_FLAG_DNSREQUEST_INSPECT BIT_U32(22)
#define DE_STATE_FLAG_DNSRESPONSE_INSPECT BIT_U32(23)
#define DE_STATE_FLAG_TLSSNI_INSPECT BIT_U32(24)
#define DE_STATE_FLAG_TLSISSUER_INSPECT BIT_U32(25)
#define DE_STATE_FLAG_TLSSUBJECT_INSPECT BIT_U32(26)
#define DE_STATE_FLAG_TLSVALIDITY_INSPECT BIT_U32(27)
#define DE_STATE_FLAG_DCE_PAYLOAD_INSPECT BIT_U32(28)
#define DE_STATE_FLAG_TEMPLATE_BUFFER_INSPECT BIT_U32(29)
#define DE_STATE_FLAG_HTTP_RESLINE_INSPECT BIT_U32(30)
#define DE_STATE_FLAG_DCE_PAYLOAD_INSPECT BIT_U32(2)
#define DE_STATE_FLAG_FILE_TC_INSPECT BIT_U32(3)
#define DE_STATE_FLAG_FILE_TS_INSPECT BIT_U32(4)
/* first bit position after the built-ins */
#define DE_STATE_FLAG_BASE 5UL
/* state flags */
#define DETECT_ENGINE_STATE_FLAG_FILE_STORE_DISABLED 0x0001

@ -118,48 +118,11 @@ static void TenantIdFree(void *d);
static uint32_t DetectEngineTentantGetIdFromVlanId(const void *ctx, const Packet *p);
static uint32_t DetectEngineTentantGetIdFromPcap(const void *ctx, const Packet *p);
/* 2 - for each direction */
DetectEngineAppInspectionEngine *app_inspection_engine[FLOW_PROTO_DEFAULT][ALPROTO_MAX][2];
#if 0
static void DetectEnginePrintAppInspectionEngines(DetectEngineAppInspectionEngine *list[][ALPROTO_MAX][2])
{
printf("\n");
AppProto alproto = ALPROTO_UNKNOWN + 1;
for ( ; alproto < ALPROTO_MAX; alproto++) {
printf("alproto - %d\n", alproto);
int dir = 0;
for ( ; dir < 2; dir++) {
printf(" direction - %d\n", dir);
DetectEngineAppInspectionEngine *engine = list[alproto][dir];
while (engine != NULL) {
printf(" engine->alproto - %"PRIu16"\n", engine->alproto);
printf(" engine->dir - %"PRIu16"\n", engine->dir);
printf(" engine->sm_list - %d\n", engine->sm_list);
printf(" engine->inspect_flags - %"PRIu32"\n", engine->inspect_flags);
printf(" engine->match_flags - %"PRIu32"\n", engine->match_flags);
printf("\n");
engine = engine->next;
}
} /* for ( ; dir < 2; dir++) */
} /* for ( ; alproto < ALPROTO_MAX; alproto++) */
return;
}
#endif
void DetectEngineRegisterAppInspectionEngines(void)
{
struct tmp_t {
uint8_t ipproto;
AppProto alproto;
int32_t sm_list;
uint32_t inspect_flags;
uint16_t dir;
int (*Callback)(ThreadVars *tv,
DetectEngineCtx *de_ctx,
DetectEngineThreadCtx *det_ctx,
@ -170,317 +133,150 @@ void DetectEngineRegisterAppInspectionEngines(void)
};
struct tmp_t data_toserver[] = {
{ IPPROTO_TCP,
ALPROTO_HTTP,
{ ALPROTO_HTTP,
DETECT_SM_LIST_UMATCH,
DE_STATE_FLAG_URI_INSPECT,
0,
DetectEngineInspectPacketUris },
{ IPPROTO_TCP,
ALPROTO_HTTP,
{ ALPROTO_HTTP,
DETECT_SM_LIST_HTTP_REQLINEMATCH,
DE_STATE_FLAG_HTTP_REQLINE_INSPECT,
0,
DetectEngineInspectHttpRequestLine },
{ IPPROTO_TCP,
ALPROTO_HTTP,
{ ALPROTO_HTTP,
DETECT_SM_LIST_HCBDMATCH,
DE_STATE_FLAG_HCBD_INSPECT,
0,
DetectEngineInspectHttpClientBody },
{ IPPROTO_TCP,
ALPROTO_HTTP,
{ ALPROTO_HTTP,
DETECT_SM_LIST_HHDMATCH,
DE_STATE_FLAG_HHD_INSPECT,
0,
DetectEngineInspectHttpHeader },
{ IPPROTO_TCP,
ALPROTO_HTTP,
{ ALPROTO_HTTP,
DETECT_SM_LIST_HRHDMATCH,
DE_STATE_FLAG_HRHD_INSPECT,
0,
DetectEngineInspectHttpRawHeader },
{ IPPROTO_TCP,
ALPROTO_HTTP,
{ ALPROTO_HTTP,
DETECT_SM_LIST_HMDMATCH,
DE_STATE_FLAG_HMD_INSPECT,
0,
DetectEngineInspectHttpMethod },
{ IPPROTO_TCP,
ALPROTO_HTTP,
{ ALPROTO_HTTP,
DETECT_SM_LIST_HCDMATCH,
DE_STATE_FLAG_HCD_INSPECT,
0,
DetectEngineInspectHttpCookie },
{ IPPROTO_TCP,
ALPROTO_HTTP,
{ ALPROTO_HTTP,
DETECT_SM_LIST_HRUDMATCH,
DE_STATE_FLAG_HRUD_INSPECT,
0,
DetectEngineInspectHttpRawUri },
{ IPPROTO_TCP,
ALPROTO_HTTP,
{ ALPROTO_HTTP,
DETECT_SM_LIST_FILEMATCH,
DE_STATE_FLAG_FILE_TS_INSPECT,
0,
DetectFileInspectHttp },
{ IPPROTO_TCP,
ALPROTO_HTTP,
{ ALPROTO_HTTP,
DETECT_SM_LIST_HUADMATCH,
DE_STATE_FLAG_HUAD_INSPECT,
0,
DetectEngineInspectHttpUA },
{ IPPROTO_TCP,
ALPROTO_HTTP,
{ ALPROTO_HTTP,
DETECT_SM_LIST_HHHDMATCH,
DE_STATE_FLAG_HHHD_INSPECT,
0,
DetectEngineInspectHttpHH },
{ IPPROTO_TCP,
ALPROTO_HTTP,
{ ALPROTO_HTTP,
DETECT_SM_LIST_HRHHDMATCH,
DE_STATE_FLAG_HRHHD_INSPECT,
0,
DetectEngineInspectHttpHRH },
/* DNS */
{ IPPROTO_TCP,
ALPROTO_DNS,
DETECT_SM_LIST_DNSQUERYNAME_MATCH,
DE_STATE_FLAG_DNSQUERYNAME_INSPECT,
0,
DetectEngineInspectDnsQueryName },
/* specifically for UDP, register again
* allows us to use the alproto w/o translation
* in the detection engine */
{ IPPROTO_UDP,
ALPROTO_DNS,
{ ALPROTO_DNS,
DETECT_SM_LIST_DNSQUERYNAME_MATCH,
DE_STATE_FLAG_DNSQUERYNAME_INSPECT,
0,
DetectEngineInspectDnsQueryName },
{ IPPROTO_TCP,
ALPROTO_DNS,
{ ALPROTO_DNS,
DETECT_SM_LIST_DNSREQUEST_MATCH,
DE_STATE_FLAG_DNSREQUEST_INSPECT,
0,
DetectEngineInspectDnsRequest },
/* specifically for UDP, register again
* allows us to use the alproto w/o translation
* in the detection engine */
{ IPPROTO_UDP,
ALPROTO_DNS,
DETECT_SM_LIST_DNSREQUEST_MATCH,
DE_STATE_FLAG_DNSREQUEST_INSPECT,
0,
DetectEngineInspectDnsRequest },
/* TLS */
{ IPPROTO_TCP,
ALPROTO_TLS,
{ ALPROTO_TLS,
DETECT_SM_LIST_TLSSNI_MATCH,
DE_STATE_FLAG_TLSSNI_INSPECT,
0,
DetectEngineInspectTlsSni },
/* SMTP */
{ IPPROTO_TCP,
ALPROTO_SMTP,
{ ALPROTO_SMTP,
DETECT_SM_LIST_FILEMATCH,
DE_STATE_FLAG_FILE_TS_INSPECT,
0,
DetectFileInspectSmtp },
/* Modbus */
{ IPPROTO_TCP,
ALPROTO_MODBUS,
{ ALPROTO_MODBUS,
DETECT_SM_LIST_MODBUS_MATCH,
DE_STATE_FLAG_MODBUS_INSPECT,
0,
DetectEngineInspectModbus },
/* file_data smtp */
{ IPPROTO_TCP,
ALPROTO_SMTP,
{ ALPROTO_SMTP,
DETECT_SM_LIST_FILEDATA,
DE_STATE_FLAG_FD_SMTP_INSPECT,
0,
DetectEngineInspectSMTPFiledata },
/* Template. */
{ IPPROTO_TCP,
ALPROTO_TEMPLATE,
{ ALPROTO_TEMPLATE,
DETECT_SM_LIST_TEMPLATE_BUFFER_MATCH,
DE_STATE_FLAG_TEMPLATE_BUFFER_INSPECT,
0,
DetectEngineInspectTemplateBuffer },
};
struct tmp_t data_toclient[] = {
{ IPPROTO_TCP,
ALPROTO_HTTP,
{ ALPROTO_HTTP,
DETECT_SM_LIST_FILEDATA,
DE_STATE_FLAG_HSBD_INSPECT,
1,
DetectEngineInspectHttpServerBody },
{ IPPROTO_TCP,
ALPROTO_HTTP,
{ ALPROTO_HTTP,
DETECT_SM_LIST_HHDMATCH,
DE_STATE_FLAG_HHD_INSPECT,
1,
DetectEngineInspectHttpHeader },
{ IPPROTO_TCP,
ALPROTO_HTTP,
{ ALPROTO_HTTP,
DETECT_SM_LIST_HRHDMATCH,
DE_STATE_FLAG_HRHD_INSPECT,
1,
DetectEngineInspectHttpRawHeader },
{ IPPROTO_TCP,
ALPROTO_HTTP,
{ ALPROTO_HTTP,
DETECT_SM_LIST_HCDMATCH,
DE_STATE_FLAG_HCD_INSPECT,
1,
DetectEngineInspectHttpCookie },
{ IPPROTO_TCP,
ALPROTO_HTTP,
{ ALPROTO_HTTP,
DETECT_SM_LIST_FILEMATCH,
DE_STATE_FLAG_FILE_TC_INSPECT,
1,
DetectFileInspectHttp },
{ IPPROTO_TCP,
ALPROTO_HTTP,
{ ALPROTO_HTTP,
DETECT_SM_LIST_HSMDMATCH,
DE_STATE_FLAG_HSMD_INSPECT,
1,
DetectEngineInspectHttpStatMsg },
{ IPPROTO_TCP,
ALPROTO_HTTP,
{ ALPROTO_HTTP,
DETECT_SM_LIST_HSCDMATCH,
DE_STATE_FLAG_HSCD_INSPECT,
1,
DetectEngineInspectHttpStatCode },
{ IPPROTO_TCP,
ALPROTO_HTTP,
{ ALPROTO_HTTP,
DETECT_SM_LIST_HTTP_RESLINEMATCH,
DE_STATE_FLAG_HTTP_RESLINE_INSPECT,
1,
DetectEngineInspectHttpResponseLine },
/* Modbus */
{ IPPROTO_TCP,
ALPROTO_MODBUS,
{ ALPROTO_MODBUS,
DETECT_SM_LIST_MODBUS_MATCH,
DE_STATE_FLAG_MODBUS_INSPECT,
0,
DetectEngineInspectModbus },
{ IPPROTO_TCP,
ALPROTO_DNS,
{ ALPROTO_DNS,
DETECT_SM_LIST_DNSRESPONSE_MATCH,
DE_STATE_FLAG_DNSRESPONSE_INSPECT,
1,
DetectEngineInspectDnsResponse },
/* TLS */
{ IPPROTO_TCP,
ALPROTO_TLS,
{ ALPROTO_TLS,
DETECT_SM_LIST_TLSISSUER_MATCH,
DE_STATE_FLAG_TLSISSUER_INSPECT,
1,
DetectEngineInspectTlsIssuer },
{ IPPROTO_TCP,
ALPROTO_TLS,
{ ALPROTO_TLS,
DETECT_SM_LIST_TLSSUBJECT_MATCH,
DE_STATE_FLAG_TLSSUBJECT_INSPECT,
1,
DetectEngineInspectTlsSubject },
{ IPPROTO_TCP,
ALPROTO_TLS,
{ ALPROTO_TLS,
DETECT_SM_LIST_TLSVALIDITY_MATCH,
DE_STATE_FLAG_TLSVALIDITY_INSPECT,
1,
DetectEngineInspectTlsValidity },
/* specifically for UDP, register again
* allows us to use the alproto w/o translation
* in the detection engine */
{ IPPROTO_UDP,
ALPROTO_DNS,
DETECT_SM_LIST_DNSRESPONSE_MATCH,
DE_STATE_FLAG_DNSRESPONSE_INSPECT,
1,
DetectEngineInspectDnsResponse },
/* Template. */
{ IPPROTO_TCP,
ALPROTO_TEMPLATE,
{ ALPROTO_TEMPLATE,
DETECT_SM_LIST_TEMPLATE_BUFFER_MATCH,
DE_STATE_FLAG_TEMPLATE_BUFFER_INSPECT,
1,
DetectEngineInspectTemplateBuffer },
};
size_t i;
for (i = 0 ; i < sizeof(data_toserver) / sizeof(struct tmp_t); i++) {
DetectEngineRegisterAppInspectionEngine(data_toserver[i].ipproto,
data_toserver[i].alproto,
data_toserver[i].dir,
DetectEngineRegisterAppInspectionEngine(data_toserver[i].alproto,
0,
data_toserver[i].sm_list,
data_toserver[i].inspect_flags,
data_toserver[i].Callback,
app_inspection_engine);
data_toserver[i].Callback);
}
for (i = 0 ; i < sizeof(data_toclient) / sizeof(struct tmp_t); i++) {
DetectEngineRegisterAppInspectionEngine(data_toclient[i].ipproto,
data_toclient[i].alproto,
data_toclient[i].dir,
DetectEngineRegisterAppInspectionEngine(data_toclient[i].alproto,
1,
data_toclient[i].sm_list,
data_toclient[i].inspect_flags,
data_toclient[i].Callback,
app_inspection_engine);
data_toclient[i].Callback);
}
#if 0
DetectEnginePrintAppInspectionEngines(app_inspection_engine);
#endif
return;
}
static void AppendAppInspectionEngine(DetectEngineAppInspectionEngine *engine,
DetectEngineAppInspectionEngine *list[][ALPROTO_MAX][2])
{
/* append to the list */
DetectEngineAppInspectionEngine *tmp = list[FlowGetProtoMapping(engine->ipproto)][engine->alproto][engine->dir];
DetectEngineAppInspectionEngine *insert = NULL;
while (tmp != NULL) {
if (tmp->dir == engine->dir &&
(tmp->sm_list == engine->sm_list ||
tmp->inspect_flags == engine->inspect_flags
)) {
SCLogError(SC_ERR_DETECT_PREPARE, "App Inspection Engine already "
"registered for this direction(%"PRIu16") ||"
"sm_list(%d) || "
"[inspect(%"PRIu32")]_flags",
tmp->dir, tmp->sm_list, tmp->inspect_flags);
exit(EXIT_FAILURE);
}
insert = tmp;
tmp = tmp->next;
}
if (insert == NULL)
list[FlowGetProtoMapping(engine->ipproto)][engine->alproto][engine->dir] = engine;
else
insert->next = engine;
static DetectEngineAppInspectionEngine *g_app_inspect_engines = NULL;
return;
}
void DetectEngineRegisterAppInspectionEngine(uint8_t ipproto,
AppProto alproto,
void DetectEngineRegisterAppInspectionEngine(AppProto alproto,
uint16_t dir,
int32_t sm_list,
uint32_t inspect_flags,
int (*Callback)(ThreadVars *tv,
DetectEngineCtx *de_ctx,
DetectEngineThreadCtx *det_ctx,
Signature *sig, Flow *f,
uint8_t flags, void *alstate,
void *tx, uint64_t tx_id),
DetectEngineAppInspectionEngine *list[][ALPROTO_MAX][2])
void *tx, uint64_t tx_id))
{
if ((list == NULL) ||
(alproto <= ALPROTO_UNKNOWN || alproto >= ALPROTO_FAILED) ||
if ((alproto <= ALPROTO_UNKNOWN || alproto >= ALPROTO_FAILED) ||
(dir > 1) ||
(sm_list < DETECT_SM_LIST_MATCH || sm_list >= DETECT_SM_LIST_MAX) ||
(Callback == NULL))
@ -489,31 +285,76 @@ void DetectEngineRegisterAppInspectionEngine(uint8_t ipproto,
exit(EXIT_FAILURE);
}
DetectEngineAppInspectionEngine *tmp = list[FlowGetProtoMapping(ipproto)][alproto][dir];
while (tmp != NULL) {
if (tmp->sm_list == sm_list && tmp->Callback == Callback) {
return;
}
tmp = tmp->next;
}
DetectEngineAppInspectionEngine *new_engine = SCMalloc(sizeof(DetectEngineAppInspectionEngine));
if (unlikely(new_engine == NULL)) {
exit(EXIT_FAILURE);
}
memset(new_engine, 0, sizeof(*new_engine));
new_engine->ipproto = ipproto;
new_engine->alproto = alproto;
new_engine->dir = dir;
new_engine->sm_list = sm_list;
new_engine->inspect_flags = inspect_flags;
new_engine->Callback = Callback;
AppendAppInspectionEngine(new_engine, list);
if (g_app_inspect_engines == NULL) {
g_app_inspect_engines = new_engine;
} else {
DetectEngineAppInspectionEngine *t = g_app_inspect_engines;
while (t->next != NULL) {
t = t->next;
}
t->next = new_engine;
}
return;
}
int DetectEngineAppInspectionEngine2Signature(Signature *s)
{
DetectEngineAppInspectionEngine *t = g_app_inspect_engines;
while (t != NULL) {
if (s->sm_lists[t->sm_list] == NULL)
goto next;
if (s->alproto != ALPROTO_UNKNOWN && s->alproto != t->alproto)
goto next;
if (s->flags & SIG_FLAG_TOSERVER && !(s->flags & SIG_FLAG_TOCLIENT)) {
if (t->dir == 1)
goto next;
} else if (s->flags & SIG_FLAG_TOCLIENT && !(s->flags & SIG_FLAG_TOSERVER)) {
if (t->dir == 0)
goto next;
}
DetectEngineAppInspectionEngine *new_engine = SCCalloc(1, sizeof(DetectEngineAppInspectionEngine));
if (unlikely(new_engine == NULL)) {
exit(EXIT_FAILURE);
}
new_engine->alproto = t->alproto;
new_engine->dir = t->dir;
new_engine->sm_list = t->sm_list;
new_engine->Callback = t->Callback;
if (s->app_inspect == NULL) {
s->app_inspect = new_engine;
new_engine->inspect_flags = BIT_U32(DE_STATE_FLAG_BASE); // start beyond the built-ins
} else {
DetectEngineAppInspectionEngine *t = s->app_inspect;
while (t->next != NULL) {
t = t->next;
}
t->next = new_engine;
new_engine->id = t->id + 1;
new_engine->inspect_flags = BIT_U32(new_engine->id + DE_STATE_FLAG_BASE);
}
SCLogDebug("sid %u: engine %p/%u added", s->id, new_engine, new_engine->id);
next:
t = t->next;
}
return 0;
}
/* code to control the main thread to do a reload */
enum DetectEngineSyncState {
@ -3044,300 +2885,6 @@ static int DetectEngineTest04(void)
return result;
}
int DummyTestAppInspectionEngine01(ThreadVars *tv,
DetectEngineCtx *de_ctx,
DetectEngineThreadCtx *det_ctx,
Signature *sig,
Flow *f,
uint8_t flags,
void *alstate,
void *tx, uint64_t tx_id)
{
return 0;
}
int DummyTestAppInspectionEngine02(ThreadVars *tv,
DetectEngineCtx *de_ctx,
DetectEngineThreadCtx *det_ctx,
Signature *sig,
Flow *f,
uint8_t flags,
void *alstate,
void *tx, uint64_t tx_id)
{
return 0;
}
int DetectEngineTest05(void)
{
int result = 0;
int ip = 0;
DetectEngineAppInspectionEngine *engine_list[FLOW_PROTO_DEFAULT][ALPROTO_MAX][2];
memset(engine_list, 0, sizeof(engine_list));
DetectEngineRegisterAppInspectionEngine(IPPROTO_TCP,
ALPROTO_HTTP,
0 /* STREAM_TOSERVER */,
DETECT_SM_LIST_UMATCH,
DE_STATE_FLAG_URI_INSPECT,
DummyTestAppInspectionEngine01,
engine_list);
int alproto = ALPROTO_UNKNOWN + 1;
for (ip = 0; ip < FLOW_PROTO_DEFAULT; ip++) {
for ( ; alproto < ALPROTO_FAILED; alproto++) {
int dir = 0;
for ( ; dir < 2; dir++) {
if (alproto == ALPROTO_HTTP && dir == 0) {
if (engine_list[ip][alproto][dir]->next != NULL) {
printf("more than one entry found\n");
goto end;
}
DetectEngineAppInspectionEngine *engine = engine_list[ip][alproto][dir];
if (engine->alproto != alproto ||
engine->dir != dir ||
engine->sm_list != DETECT_SM_LIST_UMATCH ||
engine->inspect_flags != DE_STATE_FLAG_URI_INSPECT ||
engine->Callback != DummyTestAppInspectionEngine01) {
printf("failed for http and dir(0-toserver)\n");
goto end;
}
} /* if (alproto == ALPROTO_HTTP && dir == 0) */
if (alproto == ALPROTO_HTTP && dir == 1) {
if (engine_list[ip][alproto][dir] != NULL) {
printf("failed for http and dir(1-toclient)\n");
goto end;
}
}
if (alproto != ALPROTO_HTTP &&
engine_list[ip][alproto][0] != NULL &&
engine_list[ip][alproto][1] != NULL) {
printf("failed for protocol %d\n", alproto);
goto end;
}
} /* for ( ; dir < 2 ..)*/
} /* for ( ; alproto < ALPROTO_FAILED; ..) */
}
result = 1;
end:
return result;
}
int DetectEngineTest06(void)
{
int result = 0;
int ip = 0;
DetectEngineAppInspectionEngine *engine_list[FLOW_PROTO_DEFAULT][ALPROTO_MAX][2];
memset(engine_list, 0, sizeof(engine_list));
DetectEngineRegisterAppInspectionEngine(IPPROTO_TCP,
ALPROTO_HTTP,
0 /* STREAM_TOSERVER */,
DETECT_SM_LIST_UMATCH,
DE_STATE_FLAG_URI_INSPECT,
DummyTestAppInspectionEngine01,
engine_list);
DetectEngineRegisterAppInspectionEngine(IPPROTO_TCP,
ALPROTO_HTTP,
1 /* STREAM_TOCLIENT */,
DETECT_SM_LIST_UMATCH,
DE_STATE_FLAG_URI_INSPECT,
DummyTestAppInspectionEngine02,
engine_list);
int alproto = ALPROTO_UNKNOWN + 1;
for (ip = 0; ip < FLOW_PROTO_DEFAULT; ip++) {
for ( ; alproto < ALPROTO_FAILED; alproto++) {
int dir = 0;
for ( ; dir < 2; dir++) {
if (alproto == ALPROTO_HTTP && dir == 0) {
if (engine_list[ip][alproto][dir]->next != NULL) {
printf("more than one entry found\n");
goto end;
}
DetectEngineAppInspectionEngine *engine = engine_list[ip][alproto][dir];
if (engine->alproto != alproto ||
engine->dir != dir ||
engine->sm_list != DETECT_SM_LIST_UMATCH ||
engine->inspect_flags != DE_STATE_FLAG_URI_INSPECT ||
engine->Callback != DummyTestAppInspectionEngine01) {
printf("failed for http and dir(0-toserver)\n");
goto end;
}
} /* if (alproto == ALPROTO_HTTP && dir == 0) */
if (alproto == ALPROTO_HTTP && dir == 1) {
if (engine_list[ip][alproto][dir]->next != NULL) {
printf("more than one entry found\n");
goto end;
}
DetectEngineAppInspectionEngine *engine = engine_list[ip][alproto][dir];
if (engine->alproto != alproto ||
engine->dir != dir ||
engine->sm_list != DETECT_SM_LIST_UMATCH ||
engine->inspect_flags != DE_STATE_FLAG_URI_INSPECT ||
engine->Callback != DummyTestAppInspectionEngine02) {
printf("failed for http and dir(0-toclient)\n");
goto end;
}
} /* if (alproto == ALPROTO_HTTP && dir == 1) */
if (alproto != ALPROTO_HTTP &&
engine_list[ip][alproto][0] != NULL &&
engine_list[ip][alproto][1] != NULL) {
printf("failed for protocol %d\n", alproto);
goto end;
}
} /* for ( ; dir < 2 ..)*/
} /* for ( ; alproto < ALPROTO_FAILED; ..) */
}
result = 1;
end:
return result;
}
int DetectEngineTest07(void)
{
int result = 0;
int ip = 0;
DetectEngineAppInspectionEngine *engine_list[FLOW_PROTO_DEFAULT][ALPROTO_MAX][2];
memset(engine_list, 0, sizeof(engine_list));
struct test_data_t {
int32_t sm_list;
uint32_t inspect_flags;
uint16_t dir;
int (*Callback)(ThreadVars *tv,
DetectEngineCtx *de_ctx,
DetectEngineThreadCtx *det_ctx,
Signature *sig, Flow *f,
uint8_t flags, void *alstate,
void *tx, uint64_t tx_id);
};
struct test_data_t data[] = {
{ DETECT_SM_LIST_UMATCH,
DE_STATE_FLAG_URI_INSPECT,
0,
DummyTestAppInspectionEngine01 },
{ DETECT_SM_LIST_HCBDMATCH,
DE_STATE_FLAG_HCBD_INSPECT,
0,
DummyTestAppInspectionEngine02 },
{ DETECT_SM_LIST_FILEDATA,
DE_STATE_FLAG_HSBD_INSPECT,
1,
DummyTestAppInspectionEngine02 },
{ DETECT_SM_LIST_HHDMATCH,
DE_STATE_FLAG_HHD_INSPECT,
0,
DummyTestAppInspectionEngine01 },
{ DETECT_SM_LIST_HRHDMATCH,
DE_STATE_FLAG_HRHD_INSPECT,
0,
DummyTestAppInspectionEngine01 },
{ DETECT_SM_LIST_HMDMATCH,
DE_STATE_FLAG_HMD_INSPECT,
0,
DummyTestAppInspectionEngine02 },
{ DETECT_SM_LIST_HCDMATCH,
DE_STATE_FLAG_HCD_INSPECT,
0,
DummyTestAppInspectionEngine01 },
{ DETECT_SM_LIST_HRUDMATCH,
DE_STATE_FLAG_HRUD_INSPECT,
0,
DummyTestAppInspectionEngine01 },
{ DETECT_SM_LIST_FILEMATCH,
DE_STATE_FLAG_FILE_TS_INSPECT,
0,
DummyTestAppInspectionEngine02 },
{ DETECT_SM_LIST_FILEMATCH,
DE_STATE_FLAG_FILE_TC_INSPECT,
1,
DummyTestAppInspectionEngine02 },
{ DETECT_SM_LIST_HSMDMATCH,
DE_STATE_FLAG_HSMD_INSPECT,
0,
DummyTestAppInspectionEngine01 },
{ DETECT_SM_LIST_HSCDMATCH,
DE_STATE_FLAG_HSCD_INSPECT,
0,
DummyTestAppInspectionEngine01 },
{ DETECT_SM_LIST_HUADMATCH,
DE_STATE_FLAG_HUAD_INSPECT,
0,
DummyTestAppInspectionEngine02 },
};
size_t i = 0;
for ( ; i < sizeof(data) / sizeof(struct test_data_t); i++) {
DetectEngineRegisterAppInspectionEngine(IPPROTO_TCP,
ALPROTO_HTTP,
data[i].dir /* STREAM_TOCLIENT */,
data[i].sm_list,
data[i].inspect_flags,
data[i].Callback,
engine_list);
}
#if 0
DetectEnginePrintAppInspectionEngines(engine_list);
#endif
int alproto = ALPROTO_UNKNOWN + 1;
for (ip = 0; ip < FLOW_PROTO_DEFAULT; ip++) {
for ( ; alproto < ALPROTO_FAILED; alproto++) {
int dir = 0;
for ( ; dir < 2; dir++) {
if (alproto == ALPROTO_HTTP) {
DetectEngineAppInspectionEngine *engine = engine_list[ip][alproto][dir];
size_t i = 0;
for ( ; i < (sizeof(data) / sizeof(struct test_data_t)); i++) {
if (data[i].dir != dir)
continue;
if (engine->alproto != ALPROTO_HTTP ||
engine->dir != data[i].dir ||
engine->sm_list != data[i].sm_list ||
engine->inspect_flags != data[i].inspect_flags ||
engine->Callback != data[i].Callback) {
printf("failed for http\n");
goto end;
}
engine = engine->next;
}
} else {
if (engine_list[ip][alproto][0] != NULL &&
engine_list[ip][alproto][1] != NULL) {
printf("failed for protocol %d\n", alproto);
goto end;
}
} /* else */
} /* for ( ; dir < 2; dir++) */
} /* for ( ; alproto < ALPROTO_FAILED; ..) */
}
result = 1;
end:
return result;
}
static int DetectEngineTest08(void)
{
char *conf =
@ -3416,9 +2963,6 @@ void DetectEngineRegisterTests()
UtRegisterTest("DetectEngineTest02", DetectEngineTest02);
UtRegisterTest("DetectEngineTest03", DetectEngineTest03);
UtRegisterTest("DetectEngineTest04", DetectEngineTest04);
UtRegisterTest("DetectEngineTest05", DetectEngineTest05);
UtRegisterTest("DetectEngineTest06", DetectEngineTest06);
UtRegisterTest("DetectEngineTest07", DetectEngineTest07);
UtRegisterTest("DetectEngineTest08", DetectEngineTest08);
UtRegisterTest("DetectEngineTest09", DetectEngineTest09);
#endif

@ -28,30 +28,6 @@
#include "tm-threads.h"
#include "flow-private.h"
typedef struct DetectEngineAppInspectionEngine_ {
uint8_t ipproto;
AppProto alproto;
uint16_t dir;
int32_t sm_list;
uint32_t inspect_flags;
/* \retval 0 No match. Don't discontinue matching yet. We need more data.
* 1 Match.
* 2 Sig can't match.
* 3 Special value used by filestore sigs to indicate disabling
* filestore for the tx.
*/
int (*Callback)(ThreadVars *tv,
DetectEngineCtx *de_ctx, DetectEngineThreadCtx *det_ctx,
Signature *sig, Flow *f, uint8_t flags, void *alstate,
void *tx, uint64_t tx_id);
struct DetectEngineAppInspectionEngine_ *next;
} DetectEngineAppInspectionEngine;
extern DetectEngineAppInspectionEngine *app_inspection_engine[FLOW_PROTO_DEFAULT][ALPROTO_MAX][2];
/* prototypes */
void DetectEngineRegisterAppInspectionEngines(void);
DetectEngineCtx *DetectEngineCtxInitWithPrefix(const char *prefix);
@ -111,16 +87,16 @@ int DetectEngineInspectGenericList(ThreadVars *, const DetectEngineCtx *,
* the inpsect_flags.
* \param Callback The engine callback.
*/
void DetectEngineRegisterAppInspectionEngine(uint8_t ipproto,
AppProto alproto,
uint16_t direction,
void DetectEngineRegisterAppInspectionEngine(AppProto alproto,
uint16_t dir,
int32_t sm_list,
uint32_t inspect_flags,
int (*Callback)(ThreadVars *tv,
DetectEngineCtx *de_ctx,
DetectEngineThreadCtx *det_ctx,
Signature *sig, Flow *f,
uint8_t flags, void *alstate,
void *tx, uint64_t tx_id),
DetectEngineAppInspectionEngine *list[][ALPROTO_MAX][2]);
void *tx, uint64_t tx_id));
int DetectEngineAppInspectionEngine2Signature(Signature *s);
#endif /* __DETECT_ENGINE_H__ */

@ -1096,6 +1096,13 @@ void SigFree(Signature *s)
SigRefFree(s);
DetectEngineAppInspectionEngine *ie = s->app_inspect;
while (ie) {
DetectEngineAppInspectionEngine *next = ie->next;
SCFree(ie);
ie = next;
}
SCFree(s);
}
@ -1636,44 +1643,20 @@ static Signature *SigInitHelper(DetectEngineCtx *de_ctx, char *sigstr,
SigBuildAddressMatchArray(sig);
if (sig->sm_lists[DETECT_SM_LIST_APP_EVENT] != NULL) {
if (AppLayerParserProtocolIsTxEventAware(IPPROTO_TCP, sig->alproto)) {
if (sig->flags & SIG_FLAG_TOSERVER) {
DetectEngineRegisterAppInspectionEngine(IPPROTO_TCP,
sig->alproto,
0,
DETECT_SM_LIST_APP_EVENT,
DE_STATE_FLAG_APP_EVENT_INSPECT,
DetectEngineAptEventInspect,
app_inspection_engine);
}
if (sig->flags & SIG_FLAG_TOCLIENT) {
DetectEngineRegisterAppInspectionEngine(IPPROTO_TCP,
sig->alproto,
1,
DETECT_SM_LIST_APP_EVENT,
DE_STATE_FLAG_APP_EVENT_INSPECT,
DetectEngineAptEventInspect,
app_inspection_engine);
}
}
if (AppLayerParserProtocolIsTxEventAware(IPPROTO_UDP, sig->alproto)) {
if (AppLayerParserProtocolIsTxEventAware(IPPROTO_TCP, sig->alproto) ||
AppLayerParserProtocolIsTxEventAware(IPPROTO_UDP, sig->alproto))
{
if (sig->flags & SIG_FLAG_TOSERVER) {
DetectEngineRegisterAppInspectionEngine(IPPROTO_UDP,
sig->alproto,
DetectEngineRegisterAppInspectionEngine(sig->alproto,
0,
DETECT_SM_LIST_APP_EVENT,
DE_STATE_FLAG_APP_EVENT_INSPECT,
DetectEngineAptEventInspect,
app_inspection_engine);
DetectEngineAptEventInspect);
}
if (sig->flags & SIG_FLAG_TOCLIENT) {
DetectEngineRegisterAppInspectionEngine(IPPROTO_UDP,
sig->alproto,
DetectEngineRegisterAppInspectionEngine(sig->alproto,
1,
DETECT_SM_LIST_APP_EVENT,
DE_STATE_FLAG_APP_EVENT_INSPECT,
DetectEngineAptEventInspect,
app_inspection_engine);
DetectEngineAptEventInspect);
}
}
}

@ -3891,8 +3891,10 @@ static int SigMatchPrepare(DetectEngineCtx *de_ctx)
}
}
}
DetectEngineAppInspectionEngine2Signature(s);
}
SCReturnInt(0);
}

@ -364,6 +364,29 @@ typedef struct SigMatchData_ {
SigMatchCtx *ctx; /**< plugin specific data */
} SigMatchData;
struct DetectEngineThreadCtx_;// DetectEngineThreadCtx;
typedef struct DetectEngineAppInspectionEngine_ {
AppProto alproto;
uint8_t dir;
uint8_t id;
int sm_list;
uint32_t inspect_flags;
/* \retval 0 No match. Don't discontinue matching yet. We need more data.
* 1 Match.
* 2 Sig can't match.
* 3 Special value used by filestore sigs to indicate disabling
* filestore for the tx.
*/
int (*Callback)(ThreadVars *tv,
struct DetectEngineCtx_ *de_ctx, struct DetectEngineThreadCtx_ *det_ctx,
struct Signature_ *sig, Flow *f, uint8_t flags, void *alstate,
void *tx, uint64_t tx_id);
struct DetectEngineAppInspectionEngine_ *next;
} DetectEngineAppInspectionEngine;
/** \brief Signature container */
typedef struct Signature_ {
@ -420,6 +443,8 @@ typedef struct Signature_ {
/** netblocks and hosts specified at the sid, in CIDR format */
IPOnlyCIDRItem *CidrSrc, *CidrDst;
DetectEngineAppInspectionEngine *app_inspect;
/* Hold copies of the sm lists for Match() */
SigMatchData *sm_arrays[DETECT_SM_LIST_MAX];

Loading…
Cancel
Save