]> git.ipfire.org Git - thirdparty/snort3.git/commitdiff
Pull request #3658: Established event
authorRon Dempster (rdempste) <rdempste@cisco.com>
Wed, 30 Nov 2022 16:32:12 +0000 (16:32 +0000)
committerRon Dempster (rdempste) <rdempste@cisco.com>
Wed, 30 Nov 2022 16:32:12 +0000 (16:32 +0000)
Merge in SNORT/snort3 from ~RDEMPSTE/snort3:established_event to master

Squashed commit of the following:

commit 38c51afab570fba0dff01bfe8f334b04632b74a1
Author: Ron Dempster (rdempste) <rdempste@cisco.com>
Date:   Thu Oct 13 10:52:10 2022 -0400

    flow, stream: added code to track and event for one-sided TCP sessions and generate an event for established or one-sided flows

13 files changed:
src/flow/flow.cc
src/flow/flow.h
src/framework/data_bus.h
src/managers/inspector_manager.cc
src/protocols/packet.h
src/stream/tcp/tcp_session.cc
src/stream/tcp/tcp_state_listen.cc
src/stream/tcp/tcp_state_listen.h
src/stream/tcp/tcp_state_syn_recv.cc
src/stream/tcp/tcp_state_syn_sent.cc
src/stream/tcp/tcp_stream_session.cc
src/stream/tcp/tcp_stream_session.h
src/stream/tcp/tcp_stream_tracker.cc

index 1e27dacb00d7b5c24e0ca4d03fe6adc197fe0e03..202770d80d2a89ee728ebe691d766b7e9543928c 100644 (file)
@@ -408,6 +408,10 @@ void Flow::markup_packet_flags(Packet* p)
         {
             p->packet_flags |= PKT_STREAM_UNEST_UNI;
         }
+        if ( (ssn_state.session_flags & SSNFLAG_TCP_ONE_SIDED) == SSNFLAG_TCP_ONE_SIDED )
+        {
+            p->packet_flags |= PKT_TCP_ONE_SIDED;
+        }
     }
     else
     {
index 82e4edd3577422522dffcf0a9d50dde0548768a0..f1cf138085195e5270039e6280d7cde472225a09 100644 (file)
@@ -66,6 +66,8 @@
 #define SSNFLAG_PRUNED              0x00002000
 #define SSNFLAG_RESET               0x00004000
 
+#define SSNFLAG_TCP_ONE_SIDED       0x00008000
+
 #define SSNFLAG_DROP_CLIENT         0x00010000
 #define SSNFLAG_DROP_SERVER         0x00020000
 
index 9770aa5e9e19364471cf6ab36ba2e4d3f3a7b0d1..b53a0d14a5cfee2a744dfa3a72191ef08af527fa 100644 (file)
@@ -167,6 +167,7 @@ private:
 #define STREAM_TCP_SYN_EVENT "stream.tcp_syn"
 #define STREAM_TCP_SYN_ACK_EVENT "stream.tcp_syn_ack"
 #define STREAM_TCP_MIDSTREAM_EVENT "stream.tcp_midstream"
+#define STREAM_TCP_ESTABLISHED_EVENT "stream.tcp_established"
 
 // A new standby flow was generated by stream high availability
 #define STREAM_HA_NEW_FLOW_EVENT "stream.ha.new_flow"
index 4106a9ce09c95dec83549572c356679473146a01..1ed13806828919afb91014f882481220b74da537 100644 (file)
@@ -2145,7 +2145,10 @@ void InspectorManager::internal_execute(Packet* p)
     else
     {
         if ( !p->has_paf_payload() and p->flow->flow_state == Flow::FlowState::INSPECT )
-            p->flow->session->process(p);
+        {
+            Flow& flow = *p->flow;
+            flow.session->process(p);
+        }
 
         if ( p->flow->reload_id != reload_id )
         {
index 3b8ca361c6bcc5fe4d4a66bf9bb23f6193a6f316..530d18e9e5be559ce9d3f3cd8c7a9105616a5e5a 100644 (file)
@@ -86,7 +86,7 @@ class SFDAQInstance;
 #define PKT_MORE_TO_FLUSH         0x20000000 // when more data is available to StreamSplitter::scan
 #define PKT_FAST_PAT_EVAL         0x40000000 // temporary until IpsOption api updated
 
-#define PKT_UNUSED_FLAGS          0x80000000
+#define PKT_TCP_ONE_SIDED         0x80000000 // A one-sided TCP session was detected
 
 #define TS_PKT_OFFLOADED          0x01
 
index 7a7010ef849f6f3bb3d0b39195ccd084fcd41d5e..7a69e9752be898a87b16fd0bc1df32a38fe4c9d0 100644 (file)
@@ -102,6 +102,7 @@ bool TcpSession::setup(Packet*)
     cleaning = false;
     splitter_init = false;
 
+    initiator_watermark = 0;
     pkt_action_mask = ACTION_NOTHING;
     ecn = 0;
     ingress_index = egress_index = 0;
index 39ea68ff123f83e09473d6803a27d994462122fd..26d31700f233985154d52b86874e738b6d08548c 100644 (file)
@@ -213,3 +213,9 @@ bool TcpStateListen::rst_recv(TcpSegmentDescriptor& tsd, TcpStreamTracker& trk)
     return true;
 }
 
+bool TcpStateListen::do_post_sm_packet_actions(TcpSegmentDescriptor& tsd, TcpStreamTracker& trk)
+{
+    trk.session->check_for_one_sided_session(tsd.get_pkt());
+    return true;
+}
+
index 34b34422e13e39453b91d778e7ef6d14c32fd290..0575e8ff8bd89c80b4d8a23e6b9eb303ddd545c8 100644 (file)
@@ -40,6 +40,8 @@ public:
     bool fin_sent(TcpSegmentDescriptor&, TcpStreamTracker&) override;
     bool fin_recv(TcpSegmentDescriptor&, TcpStreamTracker&) override;
     bool rst_recv(TcpSegmentDescriptor&, TcpStreamTracker&) override;
+
+    bool do_post_sm_packet_actions(TcpSegmentDescriptor&, TcpStreamTracker&) override;
 };
 
 #endif
index 499882f042599989f9c10c61dd92405fe0ed741f..6b18e98e6f7459c73201aaf6522ee7917bb9f37c 100644 (file)
@@ -78,12 +78,9 @@ bool TcpStateSynRecv::syn_ack_recv(TcpSegmentDescriptor& tsd, TcpStreamTracker&
 {
     if ( trk.is_ack_valid(tsd.get_ack()) )
     {
-        Flow* flow = tsd.get_flow();
-
         trk.update_tracker_ack_recv(tsd);
         trk.normalizer.ecn_tracker(tsd.get_tcph(), trk.session->tcp_config->require_3whs());
-        flow->set_session_flags(SSNFLAG_ESTABLISHED);
-        flow->session_state |= ( STREAM_STATE_ACK | STREAM_STATE_ESTABLISHED );
+        trk.session->set_established(tsd.get_pkt(), STREAM_STATE_ACK);
         trk.session->update_perf_base_state(TcpStreamTracker::TCP_ESTABLISHED);
         trk.set_tcp_state(TcpStreamTracker::TCP_ESTABLISHED);
         if ( tsd.is_data_segment() )
@@ -105,13 +102,10 @@ bool TcpStateSynRecv::ack_recv(TcpSegmentDescriptor& tsd, TcpStreamTracker& trk)
 {
     if ( !tsd.is_meta_ack_packet() && trk.is_ack_valid(tsd.get_ack()) )
     {
-        Flow* flow = tsd.get_flow();
-
         trk.update_tracker_ack_recv(tsd);
         trk.session->set_pkt_action_flag(trk.normalizer.handle_paws(tsd));
         tsd.set_packet_flags(PKT_STREAM_TWH);
-        flow->set_session_flags(SSNFLAG_ESTABLISHED);
-        flow->session_state |= ( STREAM_STATE_ACK | STREAM_STATE_ESTABLISHED );
+        trk.session->set_established(tsd.get_pkt(), STREAM_STATE_ACK);
         trk.session->update_perf_base_state(TcpStreamTracker::TCP_ESTABLISHED);
         trk.set_tcp_state(TcpStreamTracker::TCP_ESTABLISHED);
         trk.session->check_for_window_slam(tsd);
index e2eacf9af2c097b0c36d4cac2264d7f6c73184b0..7a0ce1d75df181e56232a7cefbc3f0a4bb558515 100644 (file)
@@ -66,11 +66,8 @@ bool TcpStateSynSent::syn_ack_recv(TcpSegmentDescriptor& tsd, TcpStreamTracker&
 
 bool TcpStateSynSent::ack_sent(TcpSegmentDescriptor& tsd, TcpStreamTracker& trk)
 {
-    Flow* flow = tsd.get_flow();
-
     trk.update_tracker_ack_sent(tsd);
-    flow->set_session_flags(SSNFLAG_ESTABLISHED);
-    flow->session_state |= ( STREAM_STATE_ACK | STREAM_STATE_ESTABLISHED );
+    trk.session->set_established(tsd.get_pkt(), STREAM_STATE_ACK);
     trk.session->update_timestamp_tracking(tsd);
     trk.session->update_perf_base_state(TcpStreamTracker::TCP_ESTABLISHED);
     trk.set_tcp_state(TcpStreamTracker::TCP_ESTABLISHED);
@@ -86,11 +83,8 @@ bool TcpStateSynSent::ack_recv(TcpSegmentDescriptor& tsd, TcpStreamTracker& trk)
 
 bool TcpStateSynSent::data_seg_sent(TcpSegmentDescriptor& tsd, TcpStreamTracker& trk)
 {
-    Flow* flow = tsd.get_flow();
-
     trk.update_tracker_ack_sent(tsd);
-    flow->set_session_flags(SSNFLAG_ESTABLISHED);
-    flow->session_state |= ( STREAM_STATE_ACK | STREAM_STATE_ESTABLISHED );
+    trk.session->set_established(tsd.get_pkt(), STREAM_STATE_ACK);
     trk.session->update_timestamp_tracking(tsd);
     trk.session->update_perf_base_state(TcpStreamTracker::TCP_ESTABLISHED);
     trk.set_tcp_state(TcpStreamTracker::TCP_ESTABLISHED);
index 9a6f276cb860a75761c5541f9003be303fb0c419..7824bbf78b21c0d24f8587090dcd118eda5f356b 100644 (file)
@@ -25,6 +25,7 @@
 
 #include "tcp_stream_session.h"
 
+#include "framework/data_bus.h"
 #include "log/messages.h"
 #include "stream/tcp/tcp_ha.h"
 
@@ -98,8 +99,7 @@ void TcpStreamSession::update_session_on_server_packet(TcpSegmentDescriptor& tsd
         if ( flow->get_session_flags() & SSNFLAG_SEEN_CLIENT )
         {
             // should TCP state go to established too?
-            flow->session_state |= STREAM_STATE_ESTABLISHED;
-            flow->set_session_flags(SSNFLAG_ESTABLISHED);
+            set_established(tsd.get_pkt());
             update_perf_base_state(TcpStreamTracker::TCP_ESTABLISHED);
         }
     }
@@ -120,10 +120,7 @@ void TcpStreamSession::update_session_on_client_packet(TcpSegmentDescriptor& tsd
     {
         /* Midstream and seen server. */
         if ( flow->get_session_flags() & SSNFLAG_SEEN_SERVER )
-        {
-            flow->session_state |= STREAM_STATE_ESTABLISHED;
-            flow->set_session_flags(SSNFLAG_ESTABLISHED);
-        }
+            set_established(tsd.get_pkt());
     }
 
     if ( !flow->inner_client_ttl && !tsd.is_meta_ack_packet() )
@@ -393,3 +390,48 @@ StreamSplitter* TcpStreamSession::get_splitter(bool to_server)
 void TcpStreamSession::start_proxy()
 { tcp_config->policy = StreamPolicy::OS_PROXY; }
 
+void TcpStreamSession::set_established(Packet* p, uint32_t flags)
+{
+    flow->session_state |= STREAM_STATE_ESTABLISHED | flags;
+    if (SSNFLAG_ESTABLISHED != (SSNFLAG_ESTABLISHED & flow->get_session_flags()))
+    {
+        flow->set_session_flags(SSNFLAG_ESTABLISHED);
+        DataBus::publish(STREAM_TCP_ESTABLISHED_EVENT, p);
+    }
+}
+
+void TcpStreamSession::check_for_one_sided_session(Packet* p)
+{
+    Flow& flow = *p->flow;
+    if ( !( (SSNFLAG_ESTABLISHED | SSNFLAG_TCP_ONE_SIDED) & flow.ssn_state.session_flags )
+        && p->is_from_client_originally() )
+    {
+        uint64_t initiator_packets;
+        uint64_t responder_packets;
+        if (flow.flags.client_initiated)
+        {
+            initiator_packets = flow.flowstats.client_pkts;
+            responder_packets = flow.flowstats.server_pkts;
+        }
+        else
+        {
+            initiator_packets = flow.flowstats.server_pkts;
+            responder_packets = flow.flowstats.client_pkts;
+        }
+
+        if ( !responder_packets )
+        {
+            // handle case where traffic is only in one direction, but the sequence numbers
+            // are changing indicating an asynchronous session
+            uint32_t watermark = p->ptrs.tcph->seq() + p->ptrs.tcph->ack();
+            if ( 1 == initiator_packets )
+                initiator_watermark = watermark;
+            else if ( initiator_watermark != watermark )
+            {
+                flow.ssn_state.session_flags |= SSNFLAG_TCP_ONE_SIDED;
+                DataBus::publish(STREAM_TCP_ESTABLISHED_EVENT, p);
+            }
+        }
+    }
+}
+
index b6e43d2d4a6cee862db68f385e06e67c5df31e4b..8145f7b0d7bd6d6dd0e04ab5db2ddfe089cabc18 100644 (file)
@@ -99,6 +99,9 @@ public:
     void set_pkt_action_flag(uint32_t flag)
     { pkt_action_mask |= flag; }
 
+    void set_established(snort::Packet*, uint32_t flags = 0);
+    void check_for_one_sided_session(snort::Packet*);
+
     virtual void update_paws_timestamps(TcpSegmentDescriptor&) = 0;
     virtual void check_for_repeated_syn(TcpSegmentDescriptor&) = 0;
     virtual void check_for_session_hijack(TcpSegmentDescriptor&) = 0;
@@ -112,10 +115,10 @@ public:
     bool lws_init = false;
     bool tcp_init = false;
     uint32_t pkt_action_mask = ACTION_NOTHING;
-    uint8_t ecn = 0;
+    uint32_t initiator_watermark = 0;
     int32_t ingress_index = DAQ_PKTHDR_UNKNOWN;
-    int16_t ingress_group = DAQ_PKTHDR_UNKNOWN;
     int32_t egress_index = DAQ_PKTHDR_UNKNOWN;
+    int16_t ingress_group = DAQ_PKTHDR_UNKNOWN;
     int16_t egress_group = DAQ_PKTHDR_UNKNOWN;
     uint32_t daq_flags = 0;
     uint32_t address_space_id = 0;
@@ -124,6 +127,7 @@ public:
     TcpEventLogger tel;
     bool cleaning = false;
     uint8_t held_packet_dir = SSN_DIR_NONE;
+    uint8_t ecn = 0;
 
 private:
     bool no_ack = false;
index cfef5f3e11d0c2f92ce0057d835934df755810f7..0b6d314bc2d0287b1d8cdacff3503c5f5a0ab09f 100644 (file)
@@ -552,13 +552,10 @@ bool TcpStreamTracker::update_on_3whs_ack(TcpSegmentDescriptor& tsd)
 
     if ( good_ack )
     {
-        Flow* flow = tsd.get_flow();
-
         irs = tsd.get_seq();
         finish_client_init(tsd);
         update_tracker_ack_recv(tsd);
-        flow->set_session_flags(SSNFLAG_ESTABLISHED);
-        flow->session_state |= ( STREAM_STATE_ACK | STREAM_STATE_ESTABLISHED );
+        session->set_established(tsd.get_pkt(), STREAM_STATE_ACK);
         tcp_state = TcpStreamTracker::TCP_ESTABLISHED;
     }