firewall: accept:flow no longer implies pass:flow

Previously a `accept:flow` action would act as both a firewall "accept" and
a threat detection "pass" for the rest of the flow.

This patch changes that. The `accept:flow` action now only accepts the
rest of the packets for the firewall ruleset, but does still continue
threat detection rule evaluation.

Ticket: #8444.
(cherry picked from commit eaacb41aaf)
pull/15572/head
Victor Julien 4 months ago
parent a08d4d7df1
commit c17728c5e7

@ -650,6 +650,14 @@ static int SortHelper(const void *a, const void *b)
return sa->iid > sb->iid ? 1 : -1;
}
static inline bool SkipFwRules(const Packet *p)
{
if (p->flow != NULL) {
return (p->flow->flags & FLOW_ACTION_ACCEPT) != 0;
}
return false;
}
static inline uint8_t DetectRulePacketRules(ThreadVars *const tv,
const DetectEngineCtx *const de_ctx, DetectEngineThreadCtx *const det_ctx, Packet *const p,
Flow *const pflow, const DetectRunScratchpad *scratch)
@ -676,7 +684,7 @@ static inline uint8_t DetectRulePacketRules(ThreadVars *const tv,
RulesDumpMatchArray(det_ctx, scratch->sgh, p);
#endif
bool skip_fw = false;
bool skip_fw = SkipFwRules(p);
uint32_t sflags, next_sflags = 0;
if (match_cnt) {
next_s = *match_array++;
@ -863,12 +871,12 @@ static inline uint8_t DetectRulePacketRules(ThreadVars *const tv,
} else if (as == ACTION_SCOPE_PACKET) {
/* accept:packet: break loop, return accept */
action |= s->action;
break_out_of_packet_filter = true;
skip_fw = true;
} else if (as == ACTION_SCOPE_FLOW) {
/* accept:flow: break loop, return accept */
action |= s->action;
break_out_of_packet_filter = true;
skip_fw = true;
/* set immediately, as we're in hook "packet_filter" */
if (pflow) {
@ -887,7 +895,7 @@ next:
DetectReplaceFree(det_ctx);
RULE_PROFILING_END(det_ctx, s, smatch, p);
/* fw accept:packet or accept:flow means we're done here */
/* fw drop means we're done here */
if (break_out_of_packet_filter)
break;
@ -898,7 +906,7 @@ next:
* policy
*/
if (have_fw_rules && scratch->default_action == ACTION_DROP) {
if (!fw_verdict) {
if (!skip_fw && !fw_verdict) {
DEBUG_VALIDATE_BUG_ON(action & ACTION_DROP);
PacketDrop(p, ACTION_DROP, PKT_DROP_REASON_DEFAULT_PACKET_POLICY);
action |= ACTION_DROP;
@ -1571,6 +1579,15 @@ static enum DetectTxFirewallFlowControl DetectRunTxPreCheckFirewallPolicy(
DetectEngineThreadCtx *det_ctx, Packet *p, DetectTransaction *tx, const Signature *s,
const uint32_t can_idx, bool *tx_fw_verdict, const bool last_tx)
{
if (p->flow->flags & FLOW_ACTION_ACCEPT) {
if ((*tx_fw_verdict) == false) {
*tx_fw_verdict = true;
DetectRunAppendDefaultAccept(det_ctx, p);
}
if (s->flags & SIG_FLAG_FIREWALL) {
return DETECT_TX_FW_FC_SKIP;
}
}
/* skip fw rules if we're in accept:tx mode */
if (tx->tx_data_ptr->flags & APP_LAYER_TX_ACCEPT) {
/* append a blank accept:packet action for the APP_LAYER_TX_ACCEPT,
@ -1939,6 +1956,11 @@ static void DetectRunTx(ThreadVars *tv,
/* if there are no rules / rule candidates, handling invoking the default
* policy. */
if (have_fw_rules && array_idx == 0) {
if (f->flags & FLOW_ACTION_ACCEPT) {
fw_verdicted++;
DetectRunAppendDefaultAccept(det_ctx, p);
return;
}
if (tx.tx_data_ptr->flags & APP_LAYER_TX_ACCEPT) {
fw_verdicted++;
@ -1956,19 +1978,21 @@ static void DetectRunTx(ThreadVars *tv,
}
}
bool fw_skip_app_filter = false; /**< skip the rest of the app filter (fw) rules */
bool tx_fw_verdict = false;
/* run rules: inspect the match candidates */
for (uint32_t i = 0; i < array_idx; i++) {
RuleMatchCandidateTx *can = &det_ctx->tx_candidates[i];
const Signature *s = det_ctx->tx_candidates[i].s;
uint32_t *inspect_flags = det_ctx->tx_candidates[i].flags;
bool break_out_of_app_filter = false;
SCLogDebug("%" PRIu64 ": sid:%u: %s tx %u/%u/%u sig %u", p->pcap_cnt, s->id,
flow_flags & STREAM_TOSERVER ? "toserver" : "toclient", tx.tx_progress,
tx.detect_progress, tx.detect_progress_orig, s->app_progress_hook);
if (have_fw_rules) {
if ((s->flags & SIG_FLAG_FIREWALL) != 0 && fw_skip_app_filter)
continue;
const enum DetectTxFirewallFlowControl fw_r = DetectRunTxPreCheckFirewallPolicy(
det_ctx, p, &tx, s, i, &tx_fw_verdict, last_tx);
if (fw_r == DETECT_TX_FW_FC_SKIP)
@ -2003,13 +2027,11 @@ static void DetectRunTx(ThreadVars *tv,
if (have_fw_rules && (s->flags & SIG_FLAG_FIREWALL) &&
(s->action & ACTION_ACCEPT) && s->app_progress_hook == tx.tx_progress) {
const bool fw_accept_to_packet = ApplyAcceptToPacket(last_tx, &tx, s);
break_out_of_app_filter = ApplyAccept(p, flow_flags, s, &tx, tx_end_state,
fw_skip_app_filter = ApplyAccept(p, flow_flags, s, &tx, tx_end_state,
fw_next_progress_missing, &tx_fw_verdict, &skip_fw_hook,
&skip_before_progress);
if (fw_accept_to_packet)
DetectRunAppendDefaultAccept(det_ctx, p);
if (break_out_of_app_filter)
break;
}
continue;
}
@ -2051,7 +2073,7 @@ static void DetectRunTx(ThreadVars *tv,
"%p/%" PRIu64 " sig %u (%u) matched", tx.tx_ptr, tx.tx_id, s->id, s->iid);
if ((s->flags & SIG_FLAG_FIREWALL) && (s->action & ACTION_ACCEPT)) {
break_out_of_app_filter = ApplyAccept(p, flow_flags, s, &tx, tx_end_state,
fw_skip_app_filter = ApplyAccept(p, flow_flags, s, &tx, tx_end_state,
fw_next_progress_missing, &tx_fw_verdict, &skip_fw_hook,
&skip_before_progress);
/* see if we need to apply tx/hook accept to the packet. This can be needed when
@ -2075,7 +2097,7 @@ static void DetectRunTx(ThreadVars *tv,
/* if this rule was the last for our progress state, and it didn't match,
* we have to invoke the default drop policy. */
DetectFirewallApplyDefaultPolicy(p, s->alproto, s->app_progress_hook);
break_out_of_app_filter = true;
fw_skip_app_filter = true;
tx_fw_verdict = true;
}
}
@ -2113,9 +2135,6 @@ static void DetectRunTx(ThreadVars *tv,
det_ctx->post_rule_work_queue.len = 0;
PMQ_RESET(&det_ctx->pmq);
}
if (break_out_of_app_filter)
break;
}
if (tx_fw_verdict)
fw_verdicted++;
@ -2334,12 +2353,9 @@ static void DetectFlow(ThreadVars *tv,
}
/* in firewall mode, we still need to run the fw rulesets even for exception policy pass */
bool skip = false;
if (EngineModeIsFirewall()) {
skip = (f->flags & (FLOW_ACTION_ACCEPT));
} else {
skip = (p->flags & PKT_NOPACKET_INSPECTION || f->flags & (FLOW_ACTION_PASS));
bool skip = (p->flags & PKT_NOPACKET_INSPECTION || f->flags & (FLOW_ACTION_PASS));
if (EngineModeIsFirewall() && (f->flags & FLOW_ACTION_ACCEPT) == 0) {
skip = false;
}
if (skip) {
/* enfore prior accept:flow */

Loading…
Cancel
Save