diff --git a/src/detect-engine-mpm.c b/src/detect-engine-mpm.c index ab53f653ef..24bc4fb2dd 100644 --- a/src/detect-engine-mpm.c +++ b/src/detect-engine-mpm.c @@ -86,78 +86,129 @@ const char *builtin_mpms[] = { typedef struct AppLayerMpms_ { const char *name; - int32_t sgh_mpm_context; /**< mpm factory id */ + int unused; int direction; /**< SIG_FLAG_TOSERVER or SIG_FLAG_TOCLIENT */ int sm_list; int (*PrefilterRegister)(SigGroupHead *sgh, MpmCtx *mpm_ctx); - int id; /**< index into this array and result arrays */ + int id; + } AppLayerMpms; AppLayerMpms app_mpms[] = { { "http_uri", 0, SIG_FLAG_TOSERVER, DETECT_SM_LIST_UMATCH, PrefilterTxUriRegister, 0 }, { "http_raw_uri", 0, SIG_FLAG_TOSERVER, DETECT_SM_LIST_HRUDMATCH, - PrefilterTxRawUriRegister, 1 }, + PrefilterTxRawUriRegister, 0 }, { "http_header", 0, SIG_FLAG_TOSERVER, DETECT_SM_LIST_HHDMATCH, - PrefilterTxHttpRequestHeadersRegister, 2}, + PrefilterTxHttpRequestHeadersRegister, 0}, { "http_header", 0, SIG_FLAG_TOCLIENT, DETECT_SM_LIST_HHDMATCH, - PrefilterTxHttpRequestHeadersRegister, 3}, + PrefilterTxHttpRequestHeadersRegister, 0}, { "http_user_agent", 0, SIG_FLAG_TOSERVER, DETECT_SM_LIST_HUADMATCH, - PrefilterTxUARegister, 4}, + PrefilterTxUARegister, 0}, { "http_raw_header", 0, SIG_FLAG_TOSERVER, DETECT_SM_LIST_HRHDMATCH, - PrefilterTxRequestHeadersRawRegister, 5}, + PrefilterTxRequestHeadersRawRegister, 0}, { "http_raw_header", 0, SIG_FLAG_TOCLIENT, DETECT_SM_LIST_HRHDMATCH, - PrefilterTxResponseHeadersRawRegister, 6}, + PrefilterTxResponseHeadersRawRegister, 0}, { "http_method", 0, SIG_FLAG_TOSERVER, DETECT_SM_LIST_HMDMATCH, - PrefilterTxMethodRegister, 7}, + PrefilterTxMethodRegister, 0}, { "file_data", 0, SIG_FLAG_TOSERVER, DETECT_SM_LIST_FILEDATA, - PrefilterTxSmtpFiledataRegister, 8}, /* smtp */ + PrefilterTxSmtpFiledataRegister, 0}, /* smtp */ { "file_data", 0, SIG_FLAG_TOCLIENT, DETECT_SM_LIST_FILEDATA, - PrefilterTxHttpResponseBodyRegister, 9}, /* http server body */ + PrefilterTxHttpResponseBodyRegister, 0}, /* http server body */ { "http_stat_msg", 0, SIG_FLAG_TOCLIENT, DETECT_SM_LIST_HSMDMATCH, - PrefilterTxHttpStatMsgRegister, 10}, + PrefilterTxHttpStatMsgRegister, 0}, { "http_stat_code", 0, SIG_FLAG_TOCLIENT, DETECT_SM_LIST_HSCDMATCH, - PrefilterTxHttpStatCodeRegister, 11}, + PrefilterTxHttpStatCodeRegister, 0}, { "http_client_body", 0, SIG_FLAG_TOSERVER, DETECT_SM_LIST_HCBDMATCH, - PrefilterTxHttpRequestBodyRegister, 12}, + PrefilterTxHttpRequestBodyRegister, 0}, { "http_host", 0, SIG_FLAG_TOSERVER, DETECT_SM_LIST_HHHDMATCH, - PrefilterTxHostnameRegister, 13}, + PrefilterTxHostnameRegister, 0}, { "http_raw_host", 0, SIG_FLAG_TOSERVER, DETECT_SM_LIST_HRHHDMATCH, - PrefilterTxHostnameRawRegister, 14}, + PrefilterTxHostnameRawRegister, 0}, { "http_cookie", 0, SIG_FLAG_TOSERVER, DETECT_SM_LIST_HCDMATCH, - PrefilterTxRequestCookieRegister, 15}, + PrefilterTxRequestCookieRegister, 0}, { "http_cookie", 0, SIG_FLAG_TOCLIENT, DETECT_SM_LIST_HCDMATCH, - PrefilterTxResponseCookieRegister, 16}, + PrefilterTxResponseCookieRegister, 0}, { "dns_query", 0, SIG_FLAG_TOSERVER, DETECT_SM_LIST_DNSQUERYNAME_MATCH, - PrefilterTxDnsQueryRegister, 17}, + PrefilterTxDnsQueryRegister, 0}, { "tls_sni", 0, SIG_FLAG_TOSERVER, DETECT_SM_LIST_TLSSNI_MATCH, - PrefilterTxTlsSniRegister, 18}, + PrefilterTxTlsSniRegister, 0}, { "tls_cert_issuer", 0, SIG_FLAG_TOCLIENT, DETECT_SM_LIST_TLSISSUER_MATCH, - PrefilterTxTlsIssuerRegister, 19}, + PrefilterTxTlsIssuerRegister, 0}, { "tls_cert_subject", 0, SIG_FLAG_TOCLIENT, DETECT_SM_LIST_TLSSUBJECT_MATCH, - PrefilterTxTlsSubjectRegister, 20}, + PrefilterTxTlsSubjectRegister, 0}, { NULL, 0, 0, 0, NULL, 0, } }; +/* Registery for mpm keywords + * + * Keywords are registered at engine start up + */ + +static DetectMpmAppLayerRegistery *g_app_mpms_list = NULL; +static int g_app_mpms_list_cnt = 0; + +void DetectMpmAppLayerRegister(const char *name, int direction, int sm_list, + int (*PrefilterRegister)(SigGroupHead *sgh, MpmCtx *mpm_ctx)) +{ + DetectMpmAppLayerRegistery *am = SCCalloc(1, sizeof(*am)); + BUG_ON(am == NULL); + am->name = name; + am->direction = direction; + am->sm_list = sm_list; + am->PrefilterRegister = PrefilterRegister; + + if (g_app_mpms_list == NULL) { + g_app_mpms_list = am; + } else { + DetectMpmAppLayerRegistery *t = g_app_mpms_list; + while (t->next != NULL) { + t = t->next; + } + + t->next = am; + am->id = t->id + 1; + } + g_app_mpms_list_cnt++; +} + +/* temporary table for turning the table app_mpms into the registery + * TODO to be removed */ +void RegisterAppMpmTable(void) +{ + AppLayerMpms *am = app_mpms; + while (am->name != NULL) { + DetectMpmAppLayerRegister(am->name, am->direction, + am->sm_list, am->PrefilterRegister); + am++; + } +} + void DetectMpmInitializeAppMpms(DetectEngineCtx *de_ctx) { - int i; - for (i = 0; i < APP_MPMS_MAX; i++) { - AppLayerMpms *am = &app_mpms[i]; + BUG_ON(g_app_mpms_list_cnt == 0); + + de_ctx->app_mpms = SCCalloc(g_app_mpms_list_cnt + 1, sizeof(DetectMpmAppLayerKeyword)); + BUG_ON(de_ctx->app_mpms == NULL); + + DetectMpmAppLayerRegistery *list = g_app_mpms_list; + while (list != NULL) { + DetectMpmAppLayerKeyword *am = &de_ctx->app_mpms[list->id]; + am->reg = list; /* default to whatever the global setting is */ int shared = (de_ctx->sgh_mpm_context == ENGINE_SGH_MPM_FACTORY_CONTEXT_SINGLE); @@ -165,24 +216,26 @@ void DetectMpmInitializeAppMpms(DetectEngineCtx *de_ctx) /* see if we use a unique or shared mpm ctx for this type */ int confshared = 0; char confstring[256] = "detect.mpm."; - strlcat(confstring, am->name, sizeof(confstring)); + strlcat(confstring, am->reg->name, sizeof(confstring)); strlcat(confstring, ".shared", sizeof(confstring)); if (ConfGetBool(confstring, &confshared) == 1) shared = confshared; if (shared == 0) { if (!(de_ctx->flags & DE_QUIET)) { - SCLogPerf("using unique mpm ctx' for %s", am->name); + SCLogPerf("using unique mpm ctx' for %s", am->reg->name); } am->sgh_mpm_context = MPM_CTX_FACTORY_UNIQUE_CONTEXT; } else { if (!(de_ctx->flags & DE_QUIET)) { - SCLogPerf("using shared mpm ctx' for %s", am->name); + SCLogPerf("using shared mpm ctx' for %s", am->reg->name); } - am->sgh_mpm_context = MpmFactoryRegisterMpmCtxProfile(de_ctx, am->name); + am->sgh_mpm_context = MpmFactoryRegisterMpmCtxProfile(de_ctx, am->reg->name); } - SCLogDebug("AppLayer MPM %s: %u", am->name, am->sgh_mpm_context); + SCLogDebug("AppLayer MPM %s: %u", am->reg->name, am->sgh_mpm_context); + + list = list->next; } } @@ -192,11 +245,9 @@ void DetectMpmInitializeAppMpms(DetectEngineCtx *de_ctx) */ void DetectMpmPrepareAppMpms(DetectEngineCtx *de_ctx) { - int i; - for (i = 0; i < APP_MPMS_MAX; i++) { - AppLayerMpms *am = &app_mpms[i]; - - int dir = (am->direction == SIG_FLAG_TOSERVER) ? 1 : 0; + DetectMpmAppLayerKeyword *am = de_ctx->app_mpms; + while (am->reg != NULL) { + int dir = (am->reg->direction == SIG_FLAG_TOSERVER) ? 1 : 0; if (am->sgh_mpm_context != MPM_CTX_FACTORY_UNIQUE_CONTEXT) { @@ -207,6 +258,7 @@ void DetectMpmPrepareAppMpms(DetectEngineCtx *de_ctx) } } } + am++; } } @@ -575,7 +627,7 @@ void RetrieveFPForSig(Signature *s) int count_n_sm_list = 0; int list_id; - /* inspect rule to see if we have the fast_pattern keyword to + /* inspect rule to see if we have the fast_pattern reg to * force using a sig, otherwise keep stats about the patterns */ for (list_id = 0; list_id < DETECT_SM_LIST_MAX; list_id++) { if (!FastPatternSupportEnabledForSigMatchList(list_id)) @@ -824,8 +876,15 @@ void MpmStoreReportStats(const DetectEngineCtx *de_ctx) { HashListTableBucket *htb = NULL; + int app_mpms_cnt = 0; + DetectMpmAppLayerKeyword *a = de_ctx->app_mpms; + while (a->reg != NULL) { + a++; + app_mpms_cnt++; + } uint32_t stats[MPMB_MAX] = {0}; - uint32_t appstats[APP_MPMS_MAX] = {0}; + uint32_t appstats[app_mpms_cnt]; + memset(&appstats, 0x00, sizeof(appstats)); for (htb = HashListTableGetListHead(de_ctx->mpm_hash_table); htb != NULL; @@ -838,34 +897,37 @@ void MpmStoreReportStats(const DetectEngineCtx *de_ctx) if (ms->buffer < MPMB_MAX) stats[ms->buffer]++; else if (ms->sm_list != DETECT_SM_LIST_PMATCH) { - int i; - for (i = 0; i < APP_MPMS_MAX; i++) { - AppLayerMpms *am = &app_mpms[i]; - if (ms->sm_list == am->sm_list && - ms->direction == am->direction) + int i = 0; + DetectMpmAppLayerKeyword *am = de_ctx->app_mpms; + while (am->reg != NULL) { + if (ms->sm_list == am->reg->sm_list && + ms->direction == am->reg->direction) { - SCLogDebug("%s %s: %u patterns. Min %u, Max %u. Ctx %p", am->name, - am->direction == SIG_FLAG_TOSERVER ? "toserver":"toclient", + SCLogDebug("%s %s: %u patterns. Min %u, Max %u. Ctx %p", + am->reg->name, + am->reg->direction == SIG_FLAG_TOSERVER ? "toserver":"toclient", ms->mpm_ctx->pattern_cnt, ms->mpm_ctx->minlen, ms->mpm_ctx->maxlen, ms->mpm_ctx); appstats[i]++; break; } + i++; + am++; } } } if (!(de_ctx->flags & DE_QUIET)) { - uint32_t x; + int x; for (x = 0; x < MPMB_MAX; x++) { SCLogPerf("Builtin MPM \"%s\": %u", builtin_mpms[x], stats[x]); } - for (x = 0; x < APP_MPMS_MAX; x++) { + for (x = 0; x < app_mpms_cnt; x++) { if (appstats[x] == 0) continue; - const char *name = app_mpms[x].name; - char *direction = app_mpms[x].direction == SIG_FLAG_TOSERVER ? "toserver" : "toclient"; + const char *name = de_ctx->app_mpms[x].reg->name; + char *direction = de_ctx->app_mpms[x].reg->direction == SIG_FLAG_TOSERVER ? "toserver" : "toclient"; SCLogPerf("AppLayer MPM \"%s %s\": %u", direction, name, appstats[x]); } } @@ -1119,7 +1181,8 @@ MpmStore *MpmStorePrepareBuffer(DetectEngineCtx *de_ctx, SigGroupHead *sgh, } } -MpmStore *MpmStorePrepareBuffer2(DetectEngineCtx *de_ctx, SigGroupHead *sgh, AppLayerMpms *am) +static MpmStore *MpmStorePrepareBufferAppLayer(DetectEngineCtx *de_ctx, + SigGroupHead *sgh, DetectMpmAppLayerKeyword *am) { const Signature *s = NULL; uint32_t sig; @@ -1128,8 +1191,9 @@ MpmStore *MpmStorePrepareBuffer2(DetectEngineCtx *de_ctx, SigGroupHead *sgh, App uint8_t sids_array[max_sid]; memset(sids_array, 0x00, max_sid); - SCLogDebug("handling %s direction %s for list %d", am->name, - am->direction == SIG_FLAG_TOSERVER ? "toserver" : "toclient", am->sm_list); + SCLogDebug("handling %s direction %s for list %d", am->reg->name, + am->reg->direction == SIG_FLAG_TOSERVER ? "toserver" : "toclient", + am->reg->sm_list); for (sig = 0; sig < sgh->sig_cnt; sig++) { s = sgh->match_array[sig]; @@ -1143,10 +1207,10 @@ MpmStore *MpmStorePrepareBuffer2(DetectEngineCtx *de_ctx, SigGroupHead *sgh, App if (list < 0) continue; - if ((s->flags & am->direction) == 0) + if ((s->flags & am->reg->direction) == 0) continue; - if (list != am->sm_list) + if (list != am->reg->sm_list) continue; sids_array[s->num / 8] |= 1 << (s->num % 8); @@ -1156,13 +1220,17 @@ MpmStore *MpmStorePrepareBuffer2(DetectEngineCtx *de_ctx, SigGroupHead *sgh, App if (cnt == 0) return NULL; - MpmStore lookup = { sids_array, max_sid, am->direction, MPMB_MAX, am->sm_list, 0, NULL}; - SCLogDebug("am->direction %d am->sm_list %d", am->direction, am->sm_list); + MpmStore lookup = { sids_array, max_sid, am->reg->direction, + MPMB_MAX, am->reg->sm_list, 0, NULL}; + SCLogDebug("am->direction %d am->sm_list %d", + am->reg->direction, am->reg->sm_list); MpmStore *result = MpmStoreLookup(de_ctx, &lookup); if (result == NULL) { SCLogDebug("new unique mpm for %s %s: %u patterns", - am->name, am->direction == SIG_FLAG_TOSERVER ? "toserver" : "toclient", cnt); + am->reg->name, + am->reg->direction == SIG_FLAG_TOSERVER ? "toserver" : "toclient", + cnt); MpmStore *copy = SCCalloc(1, sizeof(MpmStore)); if (copy == NULL) @@ -1177,8 +1245,8 @@ MpmStore *MpmStorePrepareBuffer2(DetectEngineCtx *de_ctx, SigGroupHead *sgh, App copy->sid_array = sids; copy->sid_array_size = max_sid; copy->buffer = MPMB_MAX; - copy->direction = am->direction; - copy->sm_list = am->sm_list; + copy->direction = am->reg->direction; + copy->sm_list = am->reg->sm_list; copy->sgh_mpm_context = am->sgh_mpm_context; MpmStoreSetup(de_ctx, copy); @@ -1240,19 +1308,28 @@ int PatternMatchPrepareGroup(DetectEngineCtx *de_ctx, SigGroupHead *sh) } } - AppLayerMpms *a = app_mpms; - while (a->name != NULL) { - if ((a->direction == SIG_FLAG_TOSERVER && SGH_DIRECTION_TS(sh)) || - (a->direction == SIG_FLAG_TOCLIENT && SGH_DIRECTION_TC(sh))) + int i = 0; + DetectMpmAppLayerKeyword *a = de_ctx->app_mpms; + while (a->reg != NULL) { + i++; + a++; + } + sh->init->app_mpms = SCCalloc(i, sizeof(MpmCtx *)); + BUG_ON(sh->init->app_mpms == NULL); + + a = de_ctx->app_mpms; + while (a->reg != NULL) { + if ((a->reg->direction == SIG_FLAG_TOSERVER && SGH_DIRECTION_TS(sh)) || + (a->reg->direction == SIG_FLAG_TOCLIENT && SGH_DIRECTION_TC(sh))) { - mpm_store = MpmStorePrepareBuffer2(de_ctx, sh, a); + mpm_store = MpmStorePrepareBufferAppLayer(de_ctx, sh, a); if (mpm_store != NULL) { - sh->init->app_mpms[a->id] = mpm_store->mpm_ctx; + sh->init->app_mpms[a->reg->id] = mpm_store->mpm_ctx; /* if we have just certain types of negated patterns, * mpm_ctx can be NULL */ - if (a->PrefilterRegister && mpm_store->mpm_ctx) { - BUG_ON(a->PrefilterRegister(sh, mpm_store->mpm_ctx) != 0); + if (a->reg->PrefilterRegister && mpm_store->mpm_ctx) { + BUG_ON(a->reg->PrefilterRegister(sh, mpm_store->mpm_ctx) != 0); } } } diff --git a/src/detect-engine-mpm.h b/src/detect-engine-mpm.h index bb73a6a303..6d4063243b 100644 --- a/src/detect-engine-mpm.h +++ b/src/detect-engine-mpm.h @@ -80,5 +80,19 @@ MpmStore *MpmStorePrepareBuffer(DetectEngineCtx *de_ctx, SigGroupHead *sgh, enum */ int DetectSetFastPatternAndItsId(DetectEngineCtx *de_ctx); +void RegisterAppMpmTable(void); + +/** \brief register an app layer keyword for mpm + * \param name keyword name + * \param direction SIG_FLAG_TOSERVER or SIG_FLAG_TOCLIENT + * \param sm_list list that contains the keyword's sigmatches + * \param PrefilterRegister Prefilter api registration function + * + * \note direction must be set to either toserver or toclient. + * If both are needed, register the keyword twice. + */ +void DetectMpmAppLayerRegister(const char *name, int direction, int sm_list, + int (*PrefilterRegister)(SigGroupHead *sgh, MpmCtx *mpm_ctx)); + #endif /* __DETECT_ENGINE_MPM_H__ */ diff --git a/src/detect-engine-siggroup.c b/src/detect-engine-siggroup.c index aab2fd4616..92d8dc66d4 100644 --- a/src/detect-engine-siggroup.c +++ b/src/detect-engine-siggroup.c @@ -61,6 +61,9 @@ void SigGroupHeadInitDataFree(SigGroupHeadInitData *sghid) SCFree(sghid->sig_array); sghid->sig_array = NULL; } + if (sghid->app_mpms != NULL) { + SCFree(sghid->app_mpms); + } SCFree(sghid); } diff --git a/src/detect-engine.c b/src/detect-engine.c index 6171e5e1fc..cc64d2b4fa 100644 --- a/src/detect-engine.c +++ b/src/detect-engine.c @@ -1017,6 +1017,8 @@ void DetectEngineCtxFree(DetectEngineCtx *de_ctx) SCSigSignatureOrderingModuleCleanup(de_ctx); ThresholdContextDestroy(de_ctx); SigCleanSignatures(de_ctx); + SCFree(de_ctx->app_mpms); + de_ctx->app_mpms = NULL; VariableNameFreeHash(de_ctx); if (de_ctx->sig_array) diff --git a/src/detect.c b/src/detect.c index 99860efd82..1f5a22d5ae 100644 --- a/src/detect.c +++ b/src/detect.c @@ -3987,6 +3987,8 @@ int SigGroupBuild(DetectEngineCtx *de_ctx) #ifdef PROFILING SCProfilingRuleInitCounters(de_ctx); #endif + SCFree(de_ctx->app_mpms); + de_ctx->app_mpms = NULL; return 0; } diff --git a/src/detect.h b/src/detect.h index a725e056cd..f0bae5ccb0 100644 --- a/src/detect.h +++ b/src/detect.h @@ -463,6 +463,25 @@ typedef struct Signature_ { struct Signature_ *next; } Signature; +/** \brief one time registration of keywords at start up */ +typedef struct DetectMpmAppLayerRegistery_ { + const char *name; + int direction; /**< SIG_FLAG_TOSERVER or SIG_FLAG_TOCLIENT */ + int sm_list; + + int (*PrefilterRegister)(struct SigGroupHead_ *sgh, MpmCtx *mpm_ctx); + + int id; /**< index into this array and result arrays */ + struct DetectMpmAppLayerRegistery_ *next; +} DetectMpmAppLayerRegistery; + +/** \brief structure for storing per detect engine mpm keyword settings + */ +typedef struct DetectMpmAppLayerKeyword_ { + const DetectMpmAppLayerRegistery *reg; + int32_t sgh_mpm_context; /**< mpm factory id */ +} DetectMpmAppLayerKeyword; + typedef struct DetectReplaceList_ { struct DetectContentData_ *cd; uint8_t *found; @@ -704,6 +723,10 @@ typedef struct DetectEngineCtx_ { /** table for storing the string representation with the parsers result */ HashListTable *address_table; + /** table with mpms and their registration function + * \todo we only need this at init, so perhaps this + * can move to a DetectEngineCtx 'init' struct */ + DetectMpmAppLayerKeyword *app_mpms; } DetectEngineCtx; /* Engine groups profiles (low, medium, high, custom) */ @@ -945,8 +968,6 @@ typedef struct SigTableElmt_ { #define SIG_GROUP_HEAD_HAVEFILESHA1 (1 << 23) #define SIG_GROUP_HEAD_HAVEFILESHA256 (1 << 24) -#define APP_MPMS_MAX 21 - enum MpmBuiltinBuffers { MPMB_TCP_PKT_TS, MPMB_TCP_PKT_TC, @@ -1010,7 +1031,7 @@ typedef struct SigGroupHeadInitData_ { uint32_t direction; /**< set to SIG_FLAG_TOSERVER, SIG_FLAG_TOCLIENT or both */ int whitelist; /**< try to make this group a unique one */ - MpmCtx *app_mpms[APP_MPMS_MAX]; + MpmCtx **app_mpms; /* port ptr */ struct DetectPort_ *port; diff --git a/src/suricata.c b/src/suricata.c index 1a395ce3b3..27c4cc5065 100644 --- a/src/suricata.c +++ b/src/suricata.c @@ -2400,6 +2400,8 @@ int main(int argc, char **argv) * are specified, IPS mode will overwrite this */ EngineModeSetIDS(); + /* TODO temporary */ + RegisterAppMpmTable(); #ifdef OS_WIN32 /* service initialization */