From: Steve Chew (stechew) Date: Tue, 3 Dec 2019 20:08:48 +0000 (+0000) Subject: Merge pull request #1863 in SNORT/snort3 from ~STECHEW/snort3:deferred_whitelist... X-Git-Tag: 3.0.0-266~4 X-Git-Url: http://git.ipfire.org/cgi-bin/gitweb.cgi?a=commitdiff_plain;h=af43b734555e86dbf2a198798002d9efbf481962;p=thirdparty%2Fsnort3.git Merge pull request #1863 in SNORT/snort3 from ~STECHEW/snort3:deferred_whitelist to master Squashed commit of the following: commit 5a3d0a1cd928695d52cf798cb92fb55186fe1593 Author: Steve Chew Date: Fri Nov 22 12:18:20 2019 -0500 flow: Add ability to defer whitelist verdict. --- diff --git a/src/flow/flow.h b/src/flow/flow.h index 218dfbb50..43548acd7 100644 --- a/src/flow/flow.h +++ b/src/flow/flow.h @@ -153,6 +153,13 @@ struct LwState char ignore_direction; }; +enum DeferredWhitelist { + WHITELIST_DEFER_OFF = 0, + WHITELIST_DEFER_ON, + WHITELIST_DEFER_STARTED, + WHITELIST_DEFER_DONE, +}; + // this struct is organized by member size for compactness class SO_PUBLIC Flow { @@ -340,6 +347,16 @@ public: bool is_hard_expiration() { return (ssn_state.session_flags & SSNFLAG_HARD_EXPIRATION) != 0; } + void set_deferred_whitelist(DeferredWhitelist defer_state) + { + deferred_whitelist = defer_state; + } + + DeferredWhitelist get_deferred_whitelist_state() + { + return deferred_whitelist; + } + public: // FIXIT-M privatize if possible // fields are organized by initialization and size to minimize // void space and allow for memset of tail end of struct @@ -399,6 +416,8 @@ public: // FIXIT-M privatize if possible bool disable_inspect; bool trigger_finalize_event; + DeferredWhitelist deferred_whitelist = WHITELIST_DEFER_OFF; + private: void clean(); }; diff --git a/src/main/analyzer.cc b/src/main/analyzer.cc index 91c6f4715..5d5eb2be4 100644 --- a/src/main/analyzer.cc +++ b/src/main/analyzer.cc @@ -208,6 +208,52 @@ static bool process_packet(Packet* p) return true; } +// If necessary, defer returning a WHITELIST until it's safe to do so. +// While deferring, keep inspection turned on. +static void handle_deferred_whitelist(Packet* pkt, DAQ_Verdict& verdict) +{ + if ( !pkt->flow or pkt->flow->deferred_whitelist == WHITELIST_DEFER_OFF ) + return; + + if (verdict == DAQ_VERDICT_BLOCK or verdict == DAQ_VERDICT_BLACKLIST ) + { + // A block/blacklist verdict overrides any earlier whitelist. + pkt->flow->deferred_whitelist = WHITELIST_DEFER_OFF; + return; + } + + if ( pkt->flow->deferred_whitelist == WHITELIST_DEFER_ON ) + { + if ( verdict == DAQ_VERDICT_WHITELIST ) + { + verdict = DAQ_VERDICT_PASS; + pkt->flow->deferred_whitelist = WHITELIST_DEFER_STARTED; + pkt->flow->set_state(Flow::FlowState::INSPECT); + pkt->flow->disable_inspect = false; + } + return; + } + + if ( pkt->flow->deferred_whitelist == WHITELIST_DEFER_STARTED) + { + verdict = DAQ_VERDICT_PASS; + pkt->flow->set_state(Flow::FlowState::INSPECT); + pkt->flow->disable_inspect = false; + return; + } + + if ( pkt->flow->deferred_whitelist == WHITELIST_DEFER_DONE ) + { + // Now that we're done deferring, return the WHITELIST that would + // have happened earlier. + verdict = DAQ_VERDICT_WHITELIST; + + // Turn inspection back off and allow the flow. + pkt->flow->set_state(Flow::FlowState::ALLOW); + pkt->flow->disable_inspect = true; + } +} + // Finalize DAQ message verdict static DAQ_Verdict distill_verdict(Packet* p) { @@ -273,6 +319,8 @@ static DAQ_Verdict distill_verdict(Packet* p) else verdict = DAQ_VERDICT_PASS; + handle_deferred_whitelist(p, verdict); + return verdict; }