detect/firewall: support substate in analyzer

pull/15846/head
Victor Julien 3 weeks ago
parent 2511070a58
commit e4176d2b9a

@ -2132,12 +2132,12 @@ void EngineAnalysisRules(const DetectEngineCtx *de_ctx,
#include "app-layer-parser.h"
static void AddPolicy(const DetectEngineCtx *de_ctx, RuleAnalyzer *ctx, const AppProto a,
const uint8_t state, const uint8_t direction)
const uint8_t sub_state, const uint8_t state, const uint8_t direction)
{
char policy_string[64] = "";
const struct DetectFirewallPolicies *fw_policies = de_ctx->fw_policies;
const struct DetectFirewallAppPolicy lookup = {
.alproto = a, .sub_state = 0, .progress = state, .direction = direction
.alproto = a, .sub_state = sub_state, .progress = state, .direction = direction
};
const struct DetectFirewallAppPolicy *ap =
HashTableLookup(fw_policies->app_policies, (void *)&lookup, 0);
@ -2175,12 +2175,12 @@ static void AddPolicy(const DetectEngineCtx *de_ctx, RuleAnalyzer *ctx, const Ap
}
static void FirewallAddRulesForState(const DetectEngineCtx *de_ctx, const AppProto a,
const uint8_t state, const uint8_t direction, RuleAnalyzer *ctx)
const uint8_t sub_state, const uint8_t state, const uint8_t direction, RuleAnalyzer *ctx)
{
uint32_t accept_rules = 0;
AddPolicy(de_ctx, ctx, a, state, direction);
AddPolicy(de_ctx, ctx, a, sub_state, state, direction);
SCJbOpenArray(ctx->js, "rules");
for (Signature *s = de_ctx->sig_list; s != NULL; s = s->next) {
for (const Signature *s = de_ctx->sig_list; s != NULL; s = s->next) {
if ((s->flags & SIG_FLAG_FIREWALL) == 0)
break;
if (s->type != SIG_TYPE_APP_TX)
@ -2198,6 +2198,25 @@ static void FirewallAddRulesForState(const DetectEngineCtx *de_ctx, const AppPro
}
}
/* sig has no sub_state field, so check the app inspect engines (if any).
* We assume that the only engines we have either:
* - are unknown/substate 0
* - matching the rule's substate */
if (s->app_inspect != NULL) {
bool skip_rule = false;
for (const DetectEngineAppInspectionEngine *engine = s->app_inspect; engine != NULL;
engine = engine->next) {
if (engine->alproto == ALPROTO_UNKNOWN) {
// skip engines targeting unknown, like stream or app-layer-event
} else if (engine->sub_state != sub_state) {
skip_rule = true;
break;
}
}
if (skip_rule) {
continue;
}
}
if ((s->flags & SIG_FLAG_FW_HOOK_LTE) && state < s->app_progress_hook) {
SCJbAppendString(ctx->js, s->sig_str);
accept_rules += ((s->action & ACTION_ACCEPT) != 0);
@ -2257,6 +2276,57 @@ int FirewallAnalyzer(const DetectEngineCtx *de_ctx)
if (!AppProtoIsValid(a))
continue;
if (AppLayerParserSupportsSubStates(a)) {
SCJbOpenObject(ctx.js, AppProtoToString(a));
const uint8_t max_sub_state = AppLayerParserGetMaxSubState(a);
for (uint8_t sub_state = 1; sub_state <= max_sub_state; sub_state++) {
const char *sub_state_name = AppLayerParserGetSubStateName(a, sub_state);
const uint8_t max_progress = AppLayerParserGetSubStateCompletion(a, sub_state);
for (uint8_t state = 0; state <= max_progress; state++) {
const char *name = AppLayerParserGetSubStateProgressName(
a, sub_state, state, STREAM_TOSERVER);
if (name == NULL)
continue;
char table_name[256];
snprintf(table_name, sizeof(table_name), "app:%s:%s:%s", AppProtoToString(a),
sub_state_name, name);
SCJbOpenObject(ctx.js, table_name);
FirewallAddRulesForState(de_ctx, a, sub_state, state, STREAM_TOSERVER, &ctx);
if (ctx.js_warnings) {
SCJbClose(ctx.js_warnings);
SCJbSetObject(ctx.js, "warnings", ctx.js_warnings);
SCJbFree(ctx.js_warnings);
ctx.js_warnings = NULL;
}
SCJbClose(ctx.js);
}
for (uint8_t state = 0; state <= max_progress; state++) {
const char *name = AppLayerParserGetSubStateProgressName(
a, sub_state, state, STREAM_TOCLIENT);
if (name == NULL)
continue;
char table_name[256];
snprintf(table_name, sizeof(table_name), "app:%s:%s:%s", AppProtoToString(a),
sub_state_name, name);
SCJbOpenObject(ctx.js, table_name);
FirewallAddRulesForState(de_ctx, a, sub_state, state, STREAM_TOCLIENT, &ctx);
if (ctx.js_warnings) {
SCJbClose(ctx.js_warnings);
SCJbSetObject(ctx.js, "warnings", ctx.js_warnings);
SCJbFree(ctx.js_warnings);
ctx.js_warnings = NULL;
}
SCJbClose(ctx.js);
}
}
SCJbClose(ctx.js); // app layer
continue;
}
/* no sub state follows */
const uint8_t complete_state_ts =
(const uint8_t)AppLayerParserGetStateProgressCompletionStatus(a, STREAM_TOSERVER);
SCJbOpenObject(ctx.js, AppProtoToString(a));
@ -2275,7 +2345,7 @@ int FirewallAnalyzer(const DetectEngineCtx *de_ctx)
char table_name[128];
snprintf(table_name, sizeof(table_name), "app:%s:%s", AppProtoToString(a), name);
SCJbOpenObject(ctx.js, table_name);
FirewallAddRulesForState(de_ctx, a, state, STREAM_TOSERVER, &ctx);
FirewallAddRulesForState(de_ctx, a, 0, state, STREAM_TOSERVER, &ctx);
if (ctx.js_warnings) {
SCJbClose(ctx.js_warnings);
SCJbSetObject(ctx.js, "warnings", ctx.js_warnings);
@ -2300,7 +2370,7 @@ int FirewallAnalyzer(const DetectEngineCtx *de_ctx)
char table_name[128];
snprintf(table_name, sizeof(table_name), "app:%s:%s", AppProtoToString(a), name);
SCJbOpenObject(ctx.js, table_name);
FirewallAddRulesForState(de_ctx, a, state, STREAM_TOCLIENT, &ctx);
FirewallAddRulesForState(de_ctx, a, 0, state, STREAM_TOCLIENT, &ctx);
if (ctx.js_warnings) {
SCJbClose(ctx.js_warnings);
SCJbSetObject(ctx.js, "warnings", ctx.js_warnings);

Loading…
Cancel
Save