|
|
|
@ -1,4 +1,4 @@
|
|
|
|
|
/* Copyright (C) 2007-2023 Open Information Security Foundation
|
|
|
|
|
/* Copyright (C) 2007-2024 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
|
|
|
|
@ -49,6 +49,7 @@
|
|
|
|
|
#include "app-layer-htp-mem.h"
|
|
|
|
|
#include "util-exception-policy.h"
|
|
|
|
|
|
|
|
|
|
extern bool g_stats_eps_per_app_proto_errors;
|
|
|
|
|
/**
|
|
|
|
|
* \brief This is for the app layer in general and it contains per thread
|
|
|
|
|
* context relevant to both the alpd and alp.
|
|
|
|
@ -80,6 +81,7 @@ typedef struct AppLayerCounterNames_ {
|
|
|
|
|
char parser_error[MAX_COUNTER_SIZE];
|
|
|
|
|
char internal_error[MAX_COUNTER_SIZE];
|
|
|
|
|
char alloc_error[MAX_COUNTER_SIZE];
|
|
|
|
|
char eps_name[EXCEPTION_POLICY_MAX][MAX_COUNTER_SIZE];
|
|
|
|
|
} AppLayerCounterNames;
|
|
|
|
|
|
|
|
|
|
typedef struct AppLayerCounters_ {
|
|
|
|
@ -89,12 +91,41 @@ typedef struct AppLayerCounters_ {
|
|
|
|
|
uint16_t parser_error_id;
|
|
|
|
|
uint16_t internal_error_id;
|
|
|
|
|
uint16_t alloc_error_id;
|
|
|
|
|
ExceptionPolicyCounters eps_error;
|
|
|
|
|
} AppLayerCounters;
|
|
|
|
|
|
|
|
|
|
/* counter names. Only used at init. */
|
|
|
|
|
AppLayerCounterNames applayer_counter_names[FLOW_PROTO_APPLAYER_MAX][ALPROTO_MAX];
|
|
|
|
|
/* counter id's. Used that runtime. */
|
|
|
|
|
AppLayerCounters applayer_counters[FLOW_PROTO_APPLAYER_MAX][ALPROTO_MAX];
|
|
|
|
|
/* Exception policy global counters ids */
|
|
|
|
|
ExceptionPolicyCounters eps_error_summary;
|
|
|
|
|
|
|
|
|
|
/* Settings order as in the enum */
|
|
|
|
|
// clang-format off
|
|
|
|
|
ExceptionPolicyStatsSetts app_layer_error_eps_stats = {
|
|
|
|
|
.valid_settings_ids = {
|
|
|
|
|
/* EXCEPTION_POLICY_NOT_SET */ false,
|
|
|
|
|
/* EXCEPTION_POLICY_AUTO */ false,
|
|
|
|
|
/* EXCEPTION_POLICY_PASS_PACKET */ true,
|
|
|
|
|
/* EXCEPTION_POLICY_PASS_FLOW */ true,
|
|
|
|
|
/* EXCEPTION_POLICY_BYPASS_FLOW */ true,
|
|
|
|
|
/* EXCEPTION_POLICY_DROP_PACKET */ false,
|
|
|
|
|
/* EXCEPTION_POLICY_DROP_FLOW */ false,
|
|
|
|
|
/* EXCEPTION_POLICY_REJECT */ true,
|
|
|
|
|
},
|
|
|
|
|
.valid_settings_ips = {
|
|
|
|
|
/* EXCEPTION_POLICY_NOT_SET */ false,
|
|
|
|
|
/* EXCEPTION_POLICY_AUTO */ false,
|
|
|
|
|
/* EXCEPTION_POLICY_PASS_PACKET */ true,
|
|
|
|
|
/* EXCEPTION_POLICY_PASS_FLOW */ true,
|
|
|
|
|
/* EXCEPTION_POLICY_BYPASS_FLOW */ true,
|
|
|
|
|
/* EXCEPTION_POLICY_DROP_PACKET */ true,
|
|
|
|
|
/* EXCEPTION_POLICY_DROP_FLOW */ true,
|
|
|
|
|
/* EXCEPTION_POLICY_REJECT */ true,
|
|
|
|
|
},
|
|
|
|
|
};
|
|
|
|
|
// clang-format on
|
|
|
|
|
|
|
|
|
|
void AppLayerSetupCounters(void);
|
|
|
|
|
void AppLayerDeSetupCounters(void);
|
|
|
|
@ -159,6 +190,25 @@ void AppLayerIncInternalErrorCounter(ThreadVars *tv, Flow *f)
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
static void AppLayerIncrErrorExcPolicyCounter(ThreadVars *tv, Flow *f, enum ExceptionPolicy policy)
|
|
|
|
|
{
|
|
|
|
|
#ifdef UNITTESTS
|
|
|
|
|
if (tv == NULL) {
|
|
|
|
|
return;
|
|
|
|
|
}
|
|
|
|
|
#endif
|
|
|
|
|
uint16_t id = applayer_counters[f->protomap][f->alproto].eps_error.eps_id[policy];
|
|
|
|
|
/* for the summary values */
|
|
|
|
|
uint16_t g_id = eps_error_summary.eps_id[policy];
|
|
|
|
|
|
|
|
|
|
if (likely(id > 0)) {
|
|
|
|
|
StatsIncr(tv, id);
|
|
|
|
|
}
|
|
|
|
|
if (likely(g_id > 0)) {
|
|
|
|
|
StatsIncr(tv, g_id);
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/* in IDS mode protocol detection is done in reverse order:
|
|
|
|
|
* when TCP data is ack'd. We want to flag the correct packet,
|
|
|
|
|
* so in this case we set a flag in the flow so that the first
|
|
|
|
@ -640,6 +690,7 @@ static int TCPProtoDetect(ThreadVars *tv, TcpReassemblyThreadCtx *ra_ctx,
|
|
|
|
|
SCReturnInt(0);
|
|
|
|
|
parser_error:
|
|
|
|
|
ExceptionPolicyApply(p, g_applayerparser_error_policy, PKT_DROP_REASON_APPLAYER_ERROR);
|
|
|
|
|
AppLayerIncrErrorExcPolicyCounter(tv, f, g_applayerparser_error_policy);
|
|
|
|
|
SCReturnInt(-1);
|
|
|
|
|
detect_error:
|
|
|
|
|
DisableAppLayer(tv, f, p);
|
|
|
|
@ -707,6 +758,7 @@ int AppLayerHandleTCPData(ThreadVars *tv, TcpReassemblyThreadCtx *ra_ctx, Packet
|
|
|
|
|
StreamTcpUpdateAppLayerProgress(ssn, direction, data_len);
|
|
|
|
|
if (r < 0) {
|
|
|
|
|
ExceptionPolicyApply(p, g_applayerparser_error_policy, PKT_DROP_REASON_APPLAYER_ERROR);
|
|
|
|
|
AppLayerIncrErrorExcPolicyCounter(tv, f, g_applayerparser_error_policy);
|
|
|
|
|
SCReturnInt(-1);
|
|
|
|
|
}
|
|
|
|
|
goto end;
|
|
|
|
@ -793,6 +845,7 @@ int AppLayerHandleTCPData(ThreadVars *tv, TcpReassemblyThreadCtx *ra_ctx, Packet
|
|
|
|
|
if (r < 0) {
|
|
|
|
|
ExceptionPolicyApply(
|
|
|
|
|
p, g_applayerparser_error_policy, PKT_DROP_REASON_APPLAYER_ERROR);
|
|
|
|
|
AppLayerIncrErrorExcPolicyCounter(tv, f, g_applayerparser_error_policy);
|
|
|
|
|
SCReturnInt(-1);
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
@ -933,6 +986,7 @@ int AppLayerHandleUdp(ThreadVars *tv, AppLayerThreadCtx *tctx, Packet *p, Flow *
|
|
|
|
|
}
|
|
|
|
|
if (r < 0) {
|
|
|
|
|
ExceptionPolicyApply(p, g_applayerparser_error_policy, PKT_DROP_REASON_APPLAYER_ERROR);
|
|
|
|
|
AppLayerIncrErrorExcPolicyCounter(tv, f, g_applayerparser_error_policy);
|
|
|
|
|
SCReturnInt(-1);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
@ -1062,6 +1116,30 @@ void AppLayerRegisterGlobalCounters(void)
|
|
|
|
|
StatsRegisterGlobalCounter("app_layer.expectations", ExpectationGetCounter);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
static bool IsAppLayerErrorExceptionPolicyStatsValid(enum ExceptionPolicy policy)
|
|
|
|
|
{
|
|
|
|
|
if (EngineModeIsIPS()) {
|
|
|
|
|
return app_layer_error_eps_stats.valid_settings_ips[policy];
|
|
|
|
|
}
|
|
|
|
|
return app_layer_error_eps_stats.valid_settings_ids[policy];
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
static void AppLayerSetupExceptionPolicyPerProtoCounters(
|
|
|
|
|
uint8_t ipproto_map, AppProto alproto, const char *alproto_str, const char *ipproto_suffix)
|
|
|
|
|
{
|
|
|
|
|
if (g_stats_eps_per_app_proto_errors &&
|
|
|
|
|
g_applayerparser_error_policy != EXCEPTION_POLICY_NOT_SET) {
|
|
|
|
|
for (enum ExceptionPolicy i = EXCEPTION_POLICY_NOT_SET + 1; i < EXCEPTION_POLICY_MAX; i++) {
|
|
|
|
|
if (IsAppLayerErrorExceptionPolicyStatsValid(i)) {
|
|
|
|
|
snprintf(applayer_counter_names[ipproto_map][alproto].eps_name[i],
|
|
|
|
|
sizeof(applayer_counter_names[ipproto_map][alproto].eps_name[i]),
|
|
|
|
|
"app_layer.error.%s%s.exception_policy.%s", alproto_str, ipproto_suffix,
|
|
|
|
|
ExceptionPolicyEnumToString(i, true));
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
#define IPPROTOS_MAX 2
|
|
|
|
|
void AppLayerSetupCounters(void)
|
|
|
|
|
{
|
|
|
|
@ -1070,6 +1148,19 @@ void AppLayerSetupCounters(void)
|
|
|
|
|
const char *str = "app_layer.flow.";
|
|
|
|
|
const char *estr = "app_layer.error.";
|
|
|
|
|
|
|
|
|
|
/* We don't log stats counters if exception policy is `ignore`/`not set` */
|
|
|
|
|
if (g_applayerparser_error_policy != EXCEPTION_POLICY_NOT_SET) {
|
|
|
|
|
/* Register global counters for app layer error exception policy summary */
|
|
|
|
|
const char *eps_default_str = "app_layer.error.exception_policy.";
|
|
|
|
|
for (enum ExceptionPolicy i = EXCEPTION_POLICY_NOT_SET + 1; i < EXCEPTION_POLICY_MAX; i++) {
|
|
|
|
|
if (IsAppLayerErrorExceptionPolicyStatsValid(i)) {
|
|
|
|
|
snprintf(app_layer_error_eps_stats.eps_name[i],
|
|
|
|
|
sizeof(app_layer_error_eps_stats.eps_name[i]), "%s%s", eps_default_str,
|
|
|
|
|
ExceptionPolicyEnumToString(i, true));
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
AppLayerProtoDetectSupportedAppProtocols(alprotos);
|
|
|
|
|
|
|
|
|
|
for (uint8_t p = 0; p < IPPROTOS_MAX; p++) {
|
|
|
|
@ -1108,6 +1199,9 @@ void AppLayerSetupCounters(void)
|
|
|
|
|
snprintf(applayer_counter_names[ipproto_map][alproto].internal_error,
|
|
|
|
|
sizeof(applayer_counter_names[ipproto_map][alproto].internal_error),
|
|
|
|
|
"%s%s%s.internal", estr, alproto_str, ipproto_suffix);
|
|
|
|
|
|
|
|
|
|
AppLayerSetupExceptionPolicyPerProtoCounters(
|
|
|
|
|
ipproto_map, alproto, alproto_str, ipproto_suffix);
|
|
|
|
|
} else {
|
|
|
|
|
snprintf(applayer_counter_names[ipproto_map][alproto].name,
|
|
|
|
|
sizeof(applayer_counter_names[ipproto_map][alproto].name),
|
|
|
|
@ -1130,6 +1224,8 @@ void AppLayerSetupCounters(void)
|
|
|
|
|
snprintf(applayer_counter_names[ipproto_map][alproto].internal_error,
|
|
|
|
|
sizeof(applayer_counter_names[ipproto_map][alproto].internal_error),
|
|
|
|
|
"%s%s.internal", estr, alproto_str);
|
|
|
|
|
AppLayerSetupExceptionPolicyPerProtoCounters(
|
|
|
|
|
ipproto_map, alproto, alproto_str, "");
|
|
|
|
|
}
|
|
|
|
|
} else if (alproto == ALPROTO_FAILED) {
|
|
|
|
|
snprintf(applayer_counter_names[ipproto_map][alproto].name,
|
|
|
|
@ -1151,6 +1247,17 @@ void AppLayerRegisterThreadCounters(ThreadVars *tv)
|
|
|
|
|
AppProto alprotos[ALPROTO_MAX];
|
|
|
|
|
AppLayerProtoDetectSupportedAppProtocols(alprotos);
|
|
|
|
|
|
|
|
|
|
/* We don't log stats counters if exception policy is `ignore`/`not set` */
|
|
|
|
|
if (g_applayerparser_error_policy != EXCEPTION_POLICY_NOT_SET) {
|
|
|
|
|
/* Register global counters for app layer error exception policy summary */
|
|
|
|
|
for (enum ExceptionPolicy i = EXCEPTION_POLICY_NOT_SET + 1; i < EXCEPTION_POLICY_MAX; i++) {
|
|
|
|
|
if (IsAppLayerErrorExceptionPolicyStatsValid(i)) {
|
|
|
|
|
eps_error_summary.eps_id[i] =
|
|
|
|
|
StatsRegisterCounter(app_layer_error_eps_stats.eps_name[i], tv);
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
for (uint8_t p = 0; p < IPPROTOS_MAX; p++) {
|
|
|
|
|
const uint8_t ipproto = ipprotos[p];
|
|
|
|
|
const uint8_t ipproto_map = FlowGetProtoMapping(ipproto);
|
|
|
|
@ -1173,6 +1280,18 @@ void AppLayerRegisterThreadCounters(ThreadVars *tv)
|
|
|
|
|
applayer_counter_names[ipproto_map][alproto].parser_error, tv);
|
|
|
|
|
applayer_counters[ipproto_map][alproto].internal_error_id = StatsRegisterCounter(
|
|
|
|
|
applayer_counter_names[ipproto_map][alproto].internal_error, tv);
|
|
|
|
|
/* We don't log stats counters if exception policy is `ignore`/`not set` */
|
|
|
|
|
if (g_stats_eps_per_app_proto_errors &&
|
|
|
|
|
g_applayerparser_error_policy != EXCEPTION_POLICY_NOT_SET) {
|
|
|
|
|
for (enum ExceptionPolicy i = EXCEPTION_POLICY_NOT_SET + 1;
|
|
|
|
|
i < EXCEPTION_POLICY_MAX; i++) {
|
|
|
|
|
if (IsAppLayerErrorExceptionPolicyStatsValid(i)) {
|
|
|
|
|
applayer_counters[ipproto_map][alproto]
|
|
|
|
|
.eps_error.eps_id[i] = StatsRegisterCounter(
|
|
|
|
|
applayer_counter_names[ipproto_map][alproto].eps_name[i], tv);
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
} else if (alproto == ALPROTO_FAILED) {
|
|
|
|
|
applayer_counters[ipproto_map][alproto].counter_id =
|
|
|
|
|
StatsRegisterCounter(applayer_counter_names[ipproto_map][alproto].name, tv);
|
|
|
|
|