]> git.ipfire.org Git - thirdparty/snort3.git/commitdiff
Pull request #3714: Event driven fw
authorRuss Combs (rucombs) <rucombs@cisco.com>
Thu, 12 Jan 2023 13:22:00 +0000 (13:22 +0000)
committerRuss Combs (rucombs) <rucombs@cisco.com>
Thu, 12 Jan 2023 13:22:00 +0000 (13:22 +0000)
Merge in SNORT/snort3 from ~RDEMPSTE/snort3:event_driven_fw to master

Squashed commit of the following:

commit 8c782e76e24166ec8f7fec99f7a532816c238fb3
Author: Ron Dempster (rdempste) <rdempste@cisco.com>
Date:   Fri Jan 6 15:28:48 2023 -0500

    stream: fix iss and irs and mid-stream sent post processing

commit e4b5df660ddb2422335e26b9aa8b4dd99574c8ad
Author: Ron Dempster (rdempste) <rdempste@cisco.com>
Date:   Tue Dec 13 19:19:05 2022 -0500

    stream: refactor tcp state machine to handle mid-stream flow and more established cases

commit 239472e8bf5924932871e9443581ef12eb23f471
Author: Ron Dempster (rdempste) <rdempste@cisco.com>
Date:   Tue Dec 13 19:17:49 2022 -0500

    flow: update flow creation to exclude non-syn packets with no payload

27 files changed:
src/flow/flow.cc
src/flow/flow.h
src/flow/flow_control.cc
src/network_inspectors/binder/bind_module.cc
src/protocols/packet.h
src/stream/tcp/CMakeLists.txt
src/stream/tcp/tcp_event_logger.cc
src/stream/tcp/tcp_ha.cc
src/stream/tcp/tcp_session.cc
src/stream/tcp/tcp_state_established.cc
src/stream/tcp/tcp_state_listen.cc
src/stream/tcp/tcp_state_listen.h
src/stream/tcp/tcp_state_machine.cc
src/stream/tcp/tcp_state_mid_stream_recv.cc [new file with mode: 0644]
src/stream/tcp/tcp_state_mid_stream_recv.h [new file with mode: 0644]
src/stream/tcp/tcp_state_mid_stream_sent.cc [new file with mode: 0644]
src/stream/tcp/tcp_state_mid_stream_sent.h [new file with mode: 0644]
src/stream/tcp/tcp_state_none.cc
src/stream/tcp/tcp_state_none.h
src/stream/tcp/tcp_state_syn_recv.cc
src/stream/tcp/tcp_state_syn_sent.cc
src/stream/tcp/tcp_state_syn_sent.h
src/stream/tcp/tcp_stream_session.cc
src/stream/tcp/tcp_stream_session.h
src/stream/tcp/tcp_stream_tracker.cc
src/stream/tcp/tcp_stream_tracker.h
src/stream/tcp/tcp_trace.cc

index f5e7a070bc8c4ea0d3c33ebd6729d3cb667611df..1353e708468609f7d49d1bac26e9389ca850b61b 100644 (file)
@@ -408,9 +408,9 @@ 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 )
+        if ( (ssn_state.session_flags & SSNFLAG_TCP_PSEUDO_EST) == SSNFLAG_TCP_PSEUDO_EST )
         {
-            p->packet_flags |= PKT_TCP_ONE_SIDED;
+            p->packet_flags |= PKT_TCP_PSEUDO_EST;
         }
     }
     else
index f1cf138085195e5270039e6280d7cde472225a09..eec2631208b293f924e4741857145ef6329c8de4 100644 (file)
@@ -66,7 +66,7 @@
 #define SSNFLAG_PRUNED              0x00002000
 #define SSNFLAG_RESET               0x00004000
 
-#define SSNFLAG_TCP_ONE_SIDED       0x00008000
+#define SSNFLAG_TCP_PSEUDO_EST      0x00008000
 
 #define SSNFLAG_DROP_CLIENT         0x00010000
 #define SSNFLAG_DROP_SERVER         0x00020000
 #define SSNFLAG_BLOCK (SSNFLAG_DROP_CLIENT|SSNFLAG_DROP_SERVER)
 
 #define STREAM_STATE_NONE              0x0000
-#define STREAM_STATE_SYN               0x0001
-#define STREAM_STATE_SYN_ACK           0x0002
-#define STREAM_STATE_ACK               0x0004
-#define STREAM_STATE_ESTABLISHED       0x0008
-#define STREAM_STATE_DROP_CLIENT       0x0010
-#define STREAM_STATE_DROP_SERVER       0x0020
-#define STREAM_STATE_MIDSTREAM         0x0040
-#define STREAM_STATE_TIMEDOUT          0x0080
-#define STREAM_STATE_UNREACH           0x0100
-#define STREAM_STATE_CLOSED            0x0200
-#define STREAM_STATE_BLOCK_PENDING     0x0400
-#define STREAM_STATE_RELEASING         0x0800
+#define STREAM_STATE_ESTABLISHED       0x0001
+#define STREAM_STATE_DROP_CLIENT       0x0002
+#define STREAM_STATE_DROP_SERVER       0x0004
+#define STREAM_STATE_MIDSTREAM         0x0008
+#define STREAM_STATE_TIMEDOUT          0x0010
+#define STREAM_STATE_UNREACH           0x0020
+#define STREAM_STATE_CLOSED            0x0040
+#define STREAM_STATE_BLOCK_PENDING     0x0080
+#define STREAM_STATE_RELEASING         0x0100
 
 class Continuation;
 class BitOp;
index 2945450397ee6e8bb3161cfee235772289201b12..41beb7d0d4fa85faeba419f6265210246694e4e0 100644 (file)
@@ -362,13 +362,17 @@ static bool want_flow(PktType type, Packet* p)
         // guessing direction based on ports is misleading
         return false;
 
-    if ( !p->ptrs.tcph->is_syn_only() or p->context->conf->track_on_syn() )
+    if ( p->ptrs.tcph->is_syn_ack() or p->dsize )
         return true;
 
-    const unsigned DECODE_TCP_HS = DECODE_TCP_MSS | DECODE_TCP_TS | DECODE_TCP_WS;
-
-    if ( (p->ptrs.decode_flags & DECODE_TCP_HS) or p->dsize )
-        return true;
+    if ( p->ptrs.tcph->is_syn_only() )
+    {
+        if ( p->context->conf->track_on_syn() )
+            return true;
+        const unsigned DECODE_TCP_HS = DECODE_TCP_MSS | DECODE_TCP_TS | DECODE_TCP_WS;
+        if ( p->ptrs.decode_flags & DECODE_TCP_HS )
+            return true;
+    }
 
     p->packet_flags |= PKT_FROM_CLIENT;
     return false;
index af79d59524cb570533c6cf9712c21de2242ae08e..3bbe42f57524db1e6ec750811dcd5458dcd7e6b7 100644 (file)
@@ -145,9 +145,6 @@ static const Parameter binder_use_params[] =
     { "file", Parameter::PT_STRING, nullptr, nullptr,
       "use configuration in given file" },
 
-    { "network_policy", Parameter::PT_STRING, nullptr, nullptr,
-      "use network policy from given file" },
-
     { "inspection_policy", Parameter::PT_STRING, nullptr, nullptr,
       "use inspection policy from given file" },
 
index 134ce4714cbe5d5c57f18061d125505637201077..d2bf1a2f42c7d250934d066d6903839a0440a5ec 100644 (file)
@@ -83,7 +83,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_TCP_ONE_SIDED         0x80000000 // A one-sided TCP session was detected
+#define PKT_TCP_PSEUDO_EST        0x80000000 // A one-sided or bidirectional without LWS TCP session was detected
 
 #define TS_PKT_OFFLOADED          0x01
 
index 0380349e6ccc03fdd236eb5d9535c2bc1fa8602a..fe7dec693db65472892a544719be8bd010fc00ea 100644 (file)
@@ -52,6 +52,10 @@ add_library( stream_tcp OBJECT
     tcp_state_listen.h
     tcp_state_machine.cc
     tcp_state_machine.h
+    tcp_state_mid_stream_recv.cc
+    tcp_state_mid_stream_recv.h
+    tcp_state_mid_stream_sent.cc
+    tcp_state_mid_stream_sent.h
     tcp_state_none.cc
     tcp_state_none.h
     tcp_state_syn_recv.cc
index 506e842d7dc90c4374c6d5f330282dd5614f0d2c..203fdb3d0c83919e436bb84f5bcba17d5a5dd47d 100644 (file)
@@ -90,7 +90,8 @@ void TcpEventLogger::log_tcp_events()
         {
             DetectionEngine::queue_event(GID_STREAM_TCP, tcp_event_sids[idx].sid);
             if ( PacketTracer::is_active() )
-                PacketTracer::log("Stream: TCP normalization error in %s\n",
+                PacketTracer::log("Stream: TCP raised %u:%u %s\n",
+                    GID_STREAM_TCP, tcp_event_sids[idx].sid,
                     tcp_event_sids[idx].event_description);
             tcp_events ^= tcp_event_sids[idx].event_id;
             tcpStats.events++;
index 472d8e14be4d8415a4f5d4829b009a33917f8ee5..b6d27fd7b5d3c36e49d8e560fae8af639821f136 100644 (file)
@@ -53,8 +53,7 @@ void TcpHA::deactivate_session(Flow* flow)
         ((TcpSession*)(flow->session))->clear_session(true, false, false);
     }
 
-    flow->clear_session_state(STREAM_STATE_SYN | STREAM_STATE_SYN_ACK |
-        STREAM_STATE_ACK | STREAM_STATE_ESTABLISHED);
+    flow->clear_session_state(STREAM_STATE_ESTABLISHED);
 
     assert( flow->ha_state );
     flow->clear_session_flags( SSNFLAG_SEEN_CLIENT | SSNFLAG_SEEN_SERVER );
index 564874526f21e41b2442e277a25b6185dd6053c4..def8e0458c6a31559d66a074e5e52467484d7a7b 100644 (file)
@@ -608,7 +608,6 @@ bool TcpSession::handle_syn_on_reset_session(TcpSegmentDescriptor& tsd)
         else if ( tcph->is_syn_only() )
         {
             flow->ssn_state.direction = FROM_CLIENT;
-            flow->session_state = STREAM_STATE_SYN;
             flow->set_ttl(tsd.get_pkt(), true);
             init_session_on_syn(tsd);
             tcpStats.resyns++;
@@ -620,7 +619,6 @@ bool TcpSession::handle_syn_on_reset_session(TcpSegmentDescriptor& tsd)
             if ( tcp_config->midstream_allowed(tsd.get_pkt()) )
             {
                 flow->ssn_state.direction = FROM_SERVER;
-                flow->session_state = STREAM_STATE_SYN_ACK;
                 flow->set_ttl(tsd.get_pkt(), false);
                 init_session_on_synack(tsd);
                 tcpStats.resyns++;
index 3e952704a0971c4e5360b6d972a9fad33521ca96..0158abc5a615a9d5c05fe25fcca00e13e5570953 100644 (file)
@@ -28,6 +28,8 @@
 #include "tcp_normalizers.h"
 #include "tcp_session.h"
 
+using namespace snort;
+
 TcpStateEstablished::TcpStateEstablished(TcpStateMachine& tsm) :
     TcpStateHandler(TcpStreamTracker::TCP_ESTABLISHED, tsm)
 { }
@@ -54,7 +56,13 @@ bool TcpStateEstablished::syn_ack_sent(TcpSegmentDescriptor& tsd, TcpStreamTrack
         // not be initialized... update_tracker_ack_sent may fix that but needs
         // more testing
         //trk.update_tracker_ack_sent( tsd );
-        trk.session->update_session_on_syn_ack();
+        Flow* flow = tsd.get_flow();
+        if ( !(flow->session_state & STREAM_STATE_ESTABLISHED) )
+        {
+            /* SYN-ACK from server */
+            if (flow->session_state != STREAM_STATE_NONE)
+                trk.session->update_perf_base_state(TcpStreamTracker::TCP_ESTABLISHED);
+        }
     }
 
     if ( trk.is_server_tracker() )
index 49b047c80288319fe758311801248a06ef43919a..53d9e96507d8f5990907c5f549d3fceb3f92703f 100644 (file)
@@ -38,16 +38,6 @@ TcpStateListen::TcpStateListen(TcpStateMachine& tsm) :
 {
 }
 
-bool TcpStateListen::syn_sent(TcpSegmentDescriptor& tsd, TcpStreamTracker& trk)
-{
-    if ( trk.session->tcp_config->require_3whs() || tsd.has_wscale() || tsd.is_data_segment() )
-    {
-        if ( tsd.is_packet_from_server() )
-            trk.session->tel.set_tcp_event(EVENT_4WHS);
-    }
-    return true;
-}
-
 bool TcpStateListen::syn_recv(TcpSegmentDescriptor& tsd, TcpStreamTracker& trk)
 {
     trk.init_on_syn_recv(tsd);
@@ -60,9 +50,6 @@ bool TcpStateListen::syn_recv(TcpSegmentDescriptor& tsd, TcpStreamTracker& trk)
 
 bool TcpStateListen::syn_ack_sent(TcpSegmentDescriptor& tsd, TcpStreamTracker& trk)
 {
-    Flow* flow = tsd.get_flow();
-    flow->session_state |= ( STREAM_STATE_SYN | STREAM_STATE_SYN_ACK );
-
     if ( trk.session->is_midstream_allowed(tsd) )
     {
         trk.init_on_synack_sent(tsd);
@@ -77,56 +64,9 @@ bool TcpStateListen::syn_ack_sent(TcpSegmentDescriptor& tsd, TcpStreamTracker& t
     return true;
 }
 
-bool TcpStateListen::syn_ack_recv(TcpSegmentDescriptor& tsd, TcpStreamTracker& trk)
-{
-    if ( !trk.session->tcp_config->require_3whs() or trk.session->is_midstream_allowed(tsd) )
-    {
-        trk.init_on_synack_recv(tsd);
-        if ( tsd.is_data_segment() )
-            trk.session->handle_data_segment(tsd);
-    }
-    else if ( trk.session->tcp_config->require_3whs() )
-    {
-        trk.session->generate_no_3whs_event();
-        return false;
-    }
-    return true;
-}
-
-bool TcpStateListen::ack_sent(TcpSegmentDescriptor& tsd, TcpStreamTracker& trk)
-{
-    if ( trk.session->tcp_config->midstream_allowed(tsd.get_pkt()) && tsd.has_wscale() )
-    {
-        Flow* flow = tsd.get_flow();
-        flow->session_state |= ( STREAM_STATE_ACK | STREAM_STATE_SYN_ACK |
-            STREAM_STATE_ESTABLISHED );
-
-        trk.init_on_3whs_ack_sent(tsd);
-        trk.session->init_new_tcp_session(tsd);
-        trk.session->update_perf_base_state(TcpStreamTracker::TCP_ESTABLISHED);
-    }
-    else if ( trk.session->tcp_config->require_3whs() )
-    {
-        trk.session->generate_no_3whs_event();
-        return false;
-    }
-    return true;
-}
-
-bool TcpStateListen::ack_recv(TcpSegmentDescriptor& tsd, TcpStreamTracker& trk)
+bool TcpStateListen::ack_sent(TcpSegmentDescriptor&, TcpStreamTracker& trk)
 {
-    if ( trk.session->is_midstream_allowed(tsd) && tsd.has_wscale() )
-    {
-        Flow* flow = tsd.get_flow();
-
-        if ( !tsd.get_tcph()->is_rst() && ( flow->session_state & STREAM_STATE_SYN_ACK) )
-        {
-            trk.init_on_3whs_ack_recv(tsd);
-            trk.normalizer.ecn_tracker(
-                tsd.get_tcph(), trk.session->tcp_config->require_3whs());
-        }
-    }
-    else if ( trk.session->tcp_config->require_3whs() )
+    if ( trk.session->tcp_config->require_3whs() )
     {
         trk.session->generate_no_3whs_event();
         return false;
@@ -149,9 +89,6 @@ bool TcpStateListen::data_seg_sent(TcpSegmentDescriptor& tsd, TcpStreamTracker&
 
         trk.init_on_data_seg_sent(tsd);
         trk.session->init_new_tcp_session(tsd);
-
-        if ( flow->session_state & STREAM_STATE_ESTABLISHED )
-            trk.session->update_perf_base_state(TcpStreamTracker::TCP_ESTABLISHED);
     }
     else if ( trk.session->tcp_config->require_3whs() )
     {
@@ -166,13 +103,7 @@ bool TcpStateListen::data_seg_recv(TcpSegmentDescriptor& tsd, TcpStreamTracker&
     if ( trk.session->is_midstream_allowed(tsd) )
     {
         Flow* flow = tsd.get_flow();
-
         flow->session_state |= STREAM_STATE_MIDSTREAM;
-        if ( !Stream::is_midstream(flow) )
-        {
-            flow->set_session_flags(SSNFLAG_MIDSTREAM);
-            DataBus::publish(Stream::get_pub_id(), StreamEventIds::TCP_MIDSTREAM, tsd.get_pkt());
-        }
         trk.init_on_data_seg_recv(tsd);
         trk.normalizer.ecn_tracker(tsd.get_tcph(), trk.session->tcp_config->require_3whs());
         trk.session->handle_data_segment(tsd);
index 0575e8ff8bd89c80b4d8a23e6b9eb303ddd545c8..f9883bb267da72efd91729227ff9e5b3e855aa7f 100644 (file)
@@ -29,12 +29,9 @@ class TcpStateListen : public TcpStateHandler
 public:
     TcpStateListen(TcpStateMachine&);
 
-    bool syn_sent(TcpSegmentDescriptor&, TcpStreamTracker&) override;
     bool syn_recv(TcpSegmentDescriptor&, TcpStreamTracker&) override;
     bool syn_ack_sent(TcpSegmentDescriptor&, TcpStreamTracker&) override;
-    bool syn_ack_recv(TcpSegmentDescriptor&, TcpStreamTracker&) override;
     bool ack_sent(TcpSegmentDescriptor&, TcpStreamTracker&) override;
-    bool ack_recv(TcpSegmentDescriptor&, TcpStreamTracker&) override;
     bool data_seg_sent(TcpSegmentDescriptor&, TcpStreamTracker&) override;
     bool data_seg_recv(TcpSegmentDescriptor&, TcpStreamTracker&) override;
     bool fin_sent(TcpSegmentDescriptor&, TcpStreamTracker&) override;
index a7432e5a69ab37bf0c27e6d02f157889be7389b2..936a801acf8766cfcaee13900aa184a841418820 100644 (file)
 
 #include "tcp_state_machine.h"
 
+#include "tcp_session.h"
 #include "tcp_state_none.h"
 #include "tcp_state_closed.h"
 #include "tcp_state_listen.h"
 #include "tcp_state_syn_sent.h"
 #include "tcp_state_syn_recv.h"
+#include "tcp_state_mid_stream_sent.h"
+#include "tcp_state_mid_stream_recv.h"
 #include "tcp_state_established.h"
 #include "tcp_state_close_wait.h"
 #include "tcp_state_closing.h"
@@ -64,6 +67,8 @@ TcpStateMachine::TcpStateMachine()
     new TcpStateListen(*this);
     new TcpStateSynSent(*this);
     new TcpStateSynRecv(*this);
+    new TcpStateMidStreamSent(*this);
+    new TcpStateMidStreamRecv(*this);
     new TcpStateEstablished(*this);
     new TcpStateFinWait1(*this);
     new TcpStateFinWait2(*this);
@@ -103,6 +108,8 @@ bool TcpStateMachine::eval(TcpSegmentDescriptor& tsd)
             tcp_state_handlers[ listener_state ]->do_post_sm_packet_actions(tsd, *listener);
             return true;
         }
+        else
+            talker->session->check_for_pseudo_established(tsd.get_pkt());
 
         return false;
     }
diff --git a/src/stream/tcp/tcp_state_mid_stream_recv.cc b/src/stream/tcp/tcp_state_mid_stream_recv.cc
new file mode 100644 (file)
index 0000000..8871338
--- /dev/null
@@ -0,0 +1,140 @@
+//--------------------------------------------------------------------------
+// Copyright (C) 2022-2022 Cisco and/or its affiliates. All rights reserved.
+//
+// This program is free software; you can redistribute it and/or modify it
+// under the terms of the GNU General Public License Version 2 as published
+// by the Free Software Foundation.  You may not use, modify or distribute
+// this program under any other version of the GNU General Public License.
+//
+// This program is distributed in the hope that it will be useful, but
+// WITHOUT ANY WARRANTY; without even the implied warranty of
+// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+// General Public License for more details.
+//
+// You should have received a copy of the GNU General Public License along
+// with this program; if not, write to the Free Software Foundation, Inc.,
+// 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA.
+//--------------------------------------------------------------------------
+
+// tcp_state_mid_stream_recv.cc author Ron Dempster <rdempste@cisco.com>
+// Created on: Dec 7, 2022
+
+#ifdef HAVE_CONFIG_H
+#include "config.h"
+#endif
+
+#include "tcp_state_mid_stream_recv.h"
+
+#include "tcp_normalizers.h"
+#include "tcp_session.h"
+
+using namespace snort;
+
+TcpStateMidStreamRecv::TcpStateMidStreamRecv(TcpStateMachine& tsm) :
+    TcpStateHandler(TcpStreamTracker::TCP_MID_STREAM_RECV, tsm)
+{
+}
+
+bool TcpStateMidStreamRecv::syn_sent(TcpSegmentDescriptor& tsd, TcpStreamTracker& trk)
+{
+    trk.session->check_for_repeated_syn(tsd);
+    trk.set_tcp_state(TcpStreamTracker::TCP_ESTABLISHED);
+    return true;
+}
+
+bool TcpStateMidStreamRecv::syn_recv(TcpSegmentDescriptor& tsd, TcpStreamTracker& trk)
+{
+    trk.session->check_for_repeated_syn(tsd);
+    trk.normalizer.ecn_tracker(tsd.get_tcph(), trk.session->tcp_config->require_3whs());
+    return true;
+}
+
+bool TcpStateMidStreamRecv::syn_ack_sent(TcpSegmentDescriptor& tsd, TcpStreamTracker& trk)
+{
+    trk.session->check_for_repeated_syn(tsd);
+    trk.set_tcp_state(TcpStreamTracker::TCP_ESTABLISHED);
+    return true;
+}
+
+bool TcpStateMidStreamRecv::ack_sent(TcpSegmentDescriptor& tsd, TcpStreamTracker& trk)
+{
+    trk.update_tracker_ack_sent(tsd);
+    trk.set_tcp_state(TcpStreamTracker::TCP_ESTABLISHED);
+    return true;
+}
+
+bool TcpStateMidStreamRecv::ack_recv(TcpSegmentDescriptor& tsd, TcpStreamTracker& trk)
+{
+    trk.update_tracker_ack_recv(tsd);
+    return true;
+}
+
+bool TcpStateMidStreamRecv::data_seg_sent(TcpSegmentDescriptor& tsd, TcpStreamTracker& trk)
+{
+    trk.update_tracker_ack_sent(tsd);
+    trk.set_tcp_state(TcpStreamTracker::TCP_ESTABLISHED);
+    if ( trk.session->no_ack_mode_enabled() )
+        trk.update_tracker_no_ack_recv(tsd);
+    return true;
+}
+
+bool TcpStateMidStreamRecv::data_seg_recv(TcpSegmentDescriptor& tsd, TcpStreamTracker& trk)
+{
+    trk.update_tracker_ack_recv(tsd);
+    trk.session->handle_data_segment(tsd);
+    return true;
+}
+
+bool TcpStateMidStreamRecv::fin_sent(TcpSegmentDescriptor& tsd, TcpStreamTracker& trk)
+{
+    trk.update_on_fin_sent(tsd);
+    trk.session->flow->call_handlers(tsd.get_pkt(), true);
+    TcpStreamTracker::TcpState listener_state = tsd.get_listener()->get_tcp_state();
+    // If one sided has sent a FIN
+    if ( TcpStreamTracker::TCP_FIN_WAIT1 == listener_state )
+        trk.set_tcp_state(TcpStreamTracker::TCP_LAST_ACK);
+    else
+        trk.set_tcp_state(TcpStreamTracker::TCP_FIN_WAIT1);
+    return true;
+}
+
+bool TcpStateMidStreamRecv::fin_recv(TcpSegmentDescriptor& tsd, TcpStreamTracker& trk)
+{
+    trk.set_fin_seq_status_seen(tsd);
+    trk.update_tracker_ack_recv(tsd);
+    trk.perform_fin_recv_flush(tsd);
+
+    if ( trk.update_on_fin_recv(tsd) )
+    {
+        trk.session->update_perf_base_state(TcpStreamTracker::TCP_CLOSING);
+        trk.set_tcp_state(TcpStreamTracker::TCP_CLOSE_WAIT);
+    }
+
+    return true;
+}
+
+bool TcpStateMidStreamRecv::rst_recv(TcpSegmentDescriptor& tsd, TcpStreamTracker& trk)
+{
+    if ( trk.update_on_rst_recv(tsd) )
+    {
+        trk.session->update_session_on_rst(tsd, false);
+        trk.session->update_perf_base_state(TcpStreamTracker::TCP_CLOSING);
+        trk.session->set_pkt_action_flag(ACTION_RST);
+    }
+
+    // FIXIT-L might be good to create alert specific to RST with data
+    if ( tsd.is_data_segment() )
+        trk.session->tel.set_tcp_event(EVENT_DATA_AFTER_RST_RCVD);
+
+    return true;
+}
+
+bool TcpStateMidStreamRecv::do_post_sm_packet_actions(TcpSegmentDescriptor& tsd, TcpStreamTracker& trk)
+{
+    // Always need to check for one sided
+    bool one_sided = trk.session->check_for_one_sided_session(tsd.get_pkt());
+    if ( one_sided && TcpStreamTracker::TCP_MID_STREAM_RECV == trk.get_tcp_state() )
+        trk.set_tcp_state(TcpStreamTracker::TCP_ESTABLISHED);
+    return true;
+}
+
diff --git a/src/stream/tcp/tcp_state_mid_stream_recv.h b/src/stream/tcp/tcp_state_mid_stream_recv.h
new file mode 100644 (file)
index 0000000..995f73b
--- /dev/null
@@ -0,0 +1,47 @@
+//--------------------------------------------------------------------------
+// Copyright (C) 2022-2022 Cisco and/or its affiliates. All rights reserved.
+//
+// This program is free software; you can redistribute it and/or modify it
+// under the terms of the GNU General Public License Version 2 as published
+// by the Free Software Foundation.  You may not use, modify or distribute
+// this program under any other version of the GNU General Public License.
+//
+// This program is distributed in the hope that it will be useful, but
+// WITHOUT ANY WARRANTY; without even the implied warranty of
+// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+// General Public License for more details.
+//
+// You should have received a copy of the GNU General Public License along
+// with this program; if not, write to the Free Software Foundation, Inc.,
+// 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA.
+//--------------------------------------------------------------------------
+
+// tcp_state_mid_stream_recv.h author Ron Dempster <rdempste@cisco.com>
+// Created on: Dec 7, 2022
+
+#ifndef TCP_STATE_MID_STREAM_RECV_H
+#define TCP_STATE_MID_STREAM_RECV_H
+
+#include "tcp_state_handler.h"
+
+class TcpStateMidStreamRecv : public TcpStateHandler
+{
+public:
+    TcpStateMidStreamRecv(TcpStateMachine&);
+
+    bool syn_sent(TcpSegmentDescriptor&, TcpStreamTracker&) override;
+    bool syn_recv(TcpSegmentDescriptor&, TcpStreamTracker&) override;
+    bool syn_ack_sent(TcpSegmentDescriptor&, TcpStreamTracker&) override;
+    bool ack_sent(TcpSegmentDescriptor&, TcpStreamTracker&) override;
+    bool ack_recv(TcpSegmentDescriptor&, TcpStreamTracker&) override;
+    bool data_seg_sent(TcpSegmentDescriptor&, TcpStreamTracker&) override;
+    bool data_seg_recv(TcpSegmentDescriptor&, TcpStreamTracker&) override;
+    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
+
diff --git a/src/stream/tcp/tcp_state_mid_stream_sent.cc b/src/stream/tcp/tcp_state_mid_stream_sent.cc
new file mode 100644 (file)
index 0000000..9e9209e
--- /dev/null
@@ -0,0 +1,174 @@
+//--------------------------------------------------------------------------
+// Copyright (C) 2022-2022 Cisco and/or its affiliates. All rights reserved.
+//
+// This program is free software; you can redistribute it and/or modify it
+// under the terms of the GNU General Public License Version 2 as published
+// by the Free Software Foundation.  You may not use, modify or distribute
+// this program under any other version of the GNU General Public License.
+//
+// This program is distributed in the hope that it will be useful, but
+// WITHOUT ANY WARRANTY; without even the implied warranty of
+// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+// General Public License for more details.
+//
+// You should have received a copy of the GNU General Public License along
+// with this program; if not, write to the Free Software Foundation, Inc.,
+// 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA.
+//--------------------------------------------------------------------------
+
+// tcp_state_mid_stream_sent.cc author Ron Dempster <rdempste@cisco.com>
+// Created on: Dec 7, 2022
+
+#ifdef HAVE_CONFIG_H
+#include "config.h"
+#endif
+
+#include "tcp_state_mid_stream_sent.h"
+
+#include "tcp_normalizers.h"
+#include "tcp_session.h"
+
+using namespace snort;
+
+TcpStateMidStreamSent::TcpStateMidStreamSent(TcpStateMachine& tsm) :
+    TcpStateHandler(TcpStreamTracker::TCP_MID_STREAM_SENT, tsm)
+{ }
+
+bool TcpStateMidStreamSent::syn_sent(TcpSegmentDescriptor& tsd, TcpStreamTracker& trk)
+{
+    trk.session->check_for_repeated_syn(tsd);
+    return true;
+}
+
+bool TcpStateMidStreamSent::syn_recv(TcpSegmentDescriptor& tsd, TcpStreamTracker& trk)
+{
+    trk.session->check_for_repeated_syn(tsd);
+    trk.normalizer.ecn_tracker(tsd.get_tcph(), trk.session->tcp_config->require_3whs());
+    trk.set_tcp_state(TcpStreamTracker::TCP_ESTABLISHED);
+    return true;
+}
+
+bool TcpStateMidStreamSent::syn_ack_sent(TcpSegmentDescriptor& tsd, TcpStreamTracker& trk)
+{
+    trk.session->check_for_repeated_syn(tsd);
+    return true;
+}
+
+bool TcpStateMidStreamSent::syn_ack_recv(TcpSegmentDescriptor&, TcpStreamTracker& trk)
+{
+    trk.set_tcp_state(TcpStreamTracker::TCP_ESTABLISHED);
+    return true;
+}
+
+bool TcpStateMidStreamSent::ack_sent(TcpSegmentDescriptor& tsd, TcpStreamTracker& trk)
+{
+    trk.update_tracker_ack_sent(tsd);
+    return true;
+}
+
+bool TcpStateMidStreamSent::ack_recv(TcpSegmentDescriptor& tsd, TcpStreamTracker& trk)
+{
+    trk.update_tracker_ack_recv(tsd);
+    trk.session->set_established(tsd);
+    trk.set_tcp_state(TcpStreamTracker::TCP_ESTABLISHED);
+    return true;
+}
+
+bool TcpStateMidStreamSent::data_seg_sent(TcpSegmentDescriptor& tsd, TcpStreamTracker& trk)
+{
+    trk.update_tracker_ack_sent(tsd);
+    return true;
+}
+
+bool TcpStateMidStreamSent::data_seg_recv(TcpSegmentDescriptor& tsd, TcpStreamTracker& trk)
+{
+    trk.update_tracker_ack_recv(tsd);
+    trk.session->set_established(tsd);
+    trk.set_tcp_state(TcpStreamTracker::TCP_ESTABLISHED);
+    trk.session->handle_data_segment(tsd);
+    return true;
+ }
+
+bool TcpStateMidStreamSent::fin_sent(TcpSegmentDescriptor& tsd, TcpStreamTracker& trk)
+{
+    trk.update_on_fin_sent(tsd);
+    return true;
+}
+
+bool TcpStateMidStreamSent::fin_recv(TcpSegmentDescriptor& tsd, TcpStreamTracker& trk)
+{
+    TcpStreamTracker::TcpState talker_state = tsd.get_talker()->get_tcp_state();
+    if ( TcpStreamTracker::TCP_LAST_ACK == talker_state )
+    {
+        trk.set_fin_seq_status_seen(tsd);
+        trk.update_tracker_ack_recv(tsd);
+        bool is_ack_valid = false;
+        if ( SEQ_GEQ(tsd.get_end_seq(), trk.r_win_base) and check_for_window_slam(tsd, trk, is_ack_valid) )
+        {
+            trk.perform_fin_recv_flush(tsd);
+            trk.update_on_fin_recv(tsd);
+
+            if ( is_ack_valid )
+                trk.set_tcp_state(TcpStreamTracker::TCP_TIME_WAIT);
+            else
+                trk.set_tcp_state(TcpStreamTracker::TCP_CLOSING);
+        }
+    }
+    else if ( trk.update_on_fin_recv(tsd) )
+    {
+        trk.set_fin_seq_status_seen(tsd);
+        trk.update_tracker_ack_recv(tsd);
+        trk.session->set_established(tsd);
+        trk.set_tcp_state(TcpStreamTracker::TCP_ESTABLISHED);
+        trk.perform_fin_recv_flush(tsd);
+
+        trk.session->update_perf_base_state(TcpStreamTracker::TCP_CLOSING);
+        trk.set_tcp_state(TcpStreamTracker::TCP_CLOSE_WAIT);
+    }
+    return true;
+}
+
+bool TcpStateMidStreamSent::rst_recv(TcpSegmentDescriptor& tsd, TcpStreamTracker& trk)
+{
+    if ( trk.update_on_rst_recv(tsd) )
+    {
+        trk.session->update_session_on_rst(tsd, false);
+        trk.session->update_perf_base_state(TcpStreamTracker::TCP_CLOSING);
+        trk.session->set_pkt_action_flag(ACTION_RST);
+    }
+
+    // FIXIT-L might be good to create alert specific to RST with data
+    if ( tsd.is_data_segment() )
+        trk.session->tel.set_tcp_event(EVENT_DATA_AFTER_RST_RCVD);
+
+    return true;
+}
+
+bool TcpStateMidStreamSent::do_post_sm_packet_actions(TcpSegmentDescriptor& tsd, TcpStreamTracker& trk)
+{
+    trk.session->check_for_pseudo_established(tsd.get_pkt());
+    trk.session->update_paws_timestamps(tsd);
+    trk.session->check_for_window_slam(tsd);
+    return true;
+}
+
+bool TcpStateMidStreamSent::check_for_window_slam(TcpSegmentDescriptor& tsd, TcpStreamTracker& trk, bool& is_ack_valid)
+{
+    if ( SEQ_EQ(tsd.get_ack(), trk.get_snd_nxt() ) )
+    {
+        if ( (trk.normalizer.get_os_policy() == StreamPolicy::OS_WINDOWS)
+            && (tsd.get_wnd() == 0))
+        {
+            trk.session->tel.set_tcp_event(EVENT_WINDOW_SLAM);
+            trk.normalizer.packet_dropper(tsd, NORM_TCP_BLOCK);
+            trk.session->set_pkt_action_flag(ACTION_BAD_PKT);
+            return false;
+        }
+
+        trk.set_tcp_state(TcpStreamTracker::TCP_FIN_WAIT2);
+        is_ack_valid = true;
+    }
+
+    return true;
+}
+
diff --git a/src/stream/tcp/tcp_state_mid_stream_sent.h b/src/stream/tcp/tcp_state_mid_stream_sent.h
new file mode 100644 (file)
index 0000000..46d690c
--- /dev/null
@@ -0,0 +1,51 @@
+//--------------------------------------------------------------------------
+// Copyright (C) 2022-2022 Cisco and/or its affiliates. All rights reserved.
+//
+// This program is free software; you can redistribute it and/or modify it
+// under the terms of the GNU General Public License Version 2 as published
+// by the Free Software Foundation.  You may not use, modify or distribute
+// this program under any other version of the GNU General Public License.
+//
+// This program is distributed in the hope that it will be useful, but
+// WITHOUT ANY WARRANTY; without even the implied warranty of
+// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+// General Public License for more details.
+//
+// You should have received a copy of the GNU General Public License along
+// with this program; if not, write to the Free Software Foundation, Inc.,
+// 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA.
+//--------------------------------------------------------------------------
+
+// tcp_state_mid_stream_sent.h author Ron Dempster <rdempste@cisco.com>
+// Created on: Dec 7, 2022
+
+#ifndef TCP_STATE_MID_STREAM_SENT_H
+#define TCP_STATE_MID_STREAM_SENT_H
+
+#include "tcp_state_handler.h"
+
+class TcpStateMidStreamSent : public TcpStateHandler
+{
+public:
+    TcpStateMidStreamSent(TcpStateMachine&);
+
+    bool syn_sent(TcpSegmentDescriptor&, TcpStreamTracker&) override;
+    bool syn_recv(TcpSegmentDescriptor&, TcpStreamTracker&) override;
+    bool syn_ack_sent(TcpSegmentDescriptor&, TcpStreamTracker&) override;
+    bool syn_ack_recv(TcpSegmentDescriptor&, TcpStreamTracker&) override;
+    bool ack_sent(TcpSegmentDescriptor&, TcpStreamTracker&) override;
+    bool ack_recv(TcpSegmentDescriptor&, TcpStreamTracker&) override;
+    bool data_seg_sent(TcpSegmentDescriptor&, TcpStreamTracker&) override;
+    bool data_seg_recv(TcpSegmentDescriptor&, TcpStreamTracker&) override;
+    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;
+
+private:
+    bool check_for_window_slam(TcpSegmentDescriptor&, TcpStreamTracker&, bool& is_ack_valid);
+};
+
+#endif
+
index 4cc945f151f0e09b6ca146f8da56b744b4f367a6..55f5ba35c5d2a0b01b68c37c133bc622ddea74ff 100644 (file)
@@ -41,35 +41,16 @@ bool TcpStateNone::syn_sent(TcpSegmentDescriptor& tsd, TcpStreamTracker& trk)
 {
     Flow* flow = tsd.get_flow();
     flow->ssn_state.direction = FROM_CLIENT;
-    flow->session_state |= STREAM_STATE_SYN;
 
     trk.init_on_syn_sent(tsd);
     trk.session->init_new_tcp_session(tsd);
     return true;
 }
 
-bool TcpStateNone::syn_recv(TcpSegmentDescriptor&, TcpStreamTracker&)
+bool TcpStateNone::syn_ack_sent(TcpSegmentDescriptor&, TcpStreamTracker& trk)
 {
-    return true;
-}
-
-bool TcpStateNone::syn_ack_sent(TcpSegmentDescriptor& tsd, TcpStreamTracker& trk)
-{
-    Flow* flow = tsd.get_flow();
-
-    if ( !trk.session->tcp_config->require_3whs() or trk.session->is_midstream_allowed(tsd) )
-    {
-        flow->session_state |= ( STREAM_STATE_SYN | STREAM_STATE_SYN_ACK );
-        trk.init_on_synack_sent(tsd);
-        trk.session->init_new_tcp_session(tsd);
-        trk.normalizer.ecn_tracker(tsd.get_tcph(), trk.session->tcp_config->require_3whs());
-    }
-    else if ( trk.session->tcp_config->require_3whs() )
-    {
-        trk.session->generate_no_3whs_event();
-        return false;
-    }
-    return true;
+    trk.session->generate_no_3whs_event();
+    return false;
 }
 
 bool TcpStateNone::syn_ack_recv(TcpSegmentDescriptor& tsd, TcpStreamTracker& trk)
@@ -89,40 +70,9 @@ bool TcpStateNone::syn_ack_recv(TcpSegmentDescriptor& tsd, TcpStreamTracker& trk
     return true;
 }
 
-bool TcpStateNone::ack_sent(TcpSegmentDescriptor& tsd, TcpStreamTracker& trk)
-{
-    if ( trk.session->is_midstream_allowed(tsd) && tsd.has_wscale() )
-    {
-        Flow* flow = tsd.get_flow();
-
-        flow->session_state |= ( STREAM_STATE_ACK | STREAM_STATE_SYN_ACK |
-            STREAM_STATE_ESTABLISHED );
-        trk.init_on_3whs_ack_sent(tsd);
-        trk.session->init_new_tcp_session(tsd);
-        trk.session->update_perf_base_state(TcpStreamTracker::TCP_ESTABLISHED);
-    }
-    else if ( trk.session->tcp_config->require_3whs() )
-    {
-        trk.session->generate_no_3whs_event();
-        return false;
-    }
-    return true;
-}
-
-bool TcpStateNone::ack_recv(TcpSegmentDescriptor& tsd, TcpStreamTracker& trk)
+bool TcpStateNone::ack_sent(TcpSegmentDescriptor&, TcpStreamTracker& trk)
 {
-    if ( trk.session->is_midstream_allowed(tsd) && tsd.has_wscale() )
-    {
-        Flow* flow = tsd.get_flow();
-
-        if ( !tsd.get_tcph()->is_rst() && ( flow->session_state & STREAM_STATE_SYN_ACK ) )
-        {
-            trk.init_on_3whs_ack_recv(tsd);
-            trk.normalizer.ecn_tracker(
-                tsd.get_tcph(), trk.session->tcp_config->require_3whs());
-        }
-    }
-    else if ( trk.session->tcp_config->require_3whs() )
+    if ( trk.session->tcp_config->require_3whs() )
     {
         trk.session->generate_no_3whs_event();
         return false;
@@ -135,7 +85,6 @@ bool TcpStateNone::data_seg_sent(TcpSegmentDescriptor& tsd, TcpStreamTracker& tr
     if ( trk.session->is_midstream_allowed(tsd) )
     {
         Flow* flow = tsd.get_flow();
-
         flow->session_state |= STREAM_STATE_MIDSTREAM;
         if ( !Stream::is_midstream(flow) )
         {
@@ -145,9 +94,6 @@ bool TcpStateNone::data_seg_sent(TcpSegmentDescriptor& tsd, TcpStreamTracker& tr
 
         trk.init_on_data_seg_sent(tsd);
         trk.session->init_new_tcp_session(tsd);
-
-        if ( flow->session_state & STREAM_STATE_ESTABLISHED )
-            trk.session->update_perf_base_state(TcpStreamTracker::TCP_ESTABLISHED);
     }
     else if ( trk.session->tcp_config->require_3whs() )
     {
@@ -162,14 +108,7 @@ bool TcpStateNone::data_seg_recv(TcpSegmentDescriptor& tsd, TcpStreamTracker& tr
     if ( trk.session->is_midstream_allowed(tsd) )
     {
         Flow* flow = tsd.get_flow();
-
         flow->session_state |= STREAM_STATE_MIDSTREAM;
-        if ( !Stream::is_midstream(flow) )
-        {
-            flow->set_session_flags(SSNFLAG_MIDSTREAM);
-            DataBus::publish(Stream::get_pub_id(), StreamEventIds::TCP_MIDSTREAM, tsd.get_pkt());
-        }
-
         trk.init_on_data_seg_recv(tsd);
         trk.normalizer.ecn_tracker(tsd.get_tcph(), trk.session->tcp_config->require_3whs());
         trk.session->handle_data_segment(tsd);
@@ -231,3 +170,9 @@ bool TcpStateNone::rst_recv(TcpSegmentDescriptor& tsd, TcpStreamTracker& trk)
     return true;
 }
 
+bool TcpStateNone::do_post_sm_packet_actions(TcpSegmentDescriptor& tsd, TcpStreamTracker& trk)
+{
+    trk.session->check_for_one_sided_session(tsd.get_pkt());
+    return true;
+}
+
index 92605f3d9497ca70a5569665353dc0de804b4e8a..4d4c09102baf69bcc378b0de287737e5970a5e17 100644 (file)
@@ -30,17 +30,17 @@ public:
     TcpStateNone(TcpStateMachine&);
 
     bool syn_sent(TcpSegmentDescriptor&, TcpStreamTracker&) override;
-    bool syn_recv(TcpSegmentDescriptor&, TcpStreamTracker&) override;
     bool syn_ack_sent(TcpSegmentDescriptor&, TcpStreamTracker&) override;
     bool syn_ack_recv(TcpSegmentDescriptor&, TcpStreamTracker&) override;
     bool ack_sent(TcpSegmentDescriptor&, TcpStreamTracker&) override;
-    bool ack_recv(TcpSegmentDescriptor&, TcpStreamTracker&) override;
     bool data_seg_sent(TcpSegmentDescriptor&, TcpStreamTracker&) override;
     bool data_seg_recv(TcpSegmentDescriptor&, TcpStreamTracker&) override;
     bool fin_sent(TcpSegmentDescriptor&, TcpStreamTracker&) override;
     bool fin_recv(TcpSegmentDescriptor&, TcpStreamTracker&) override;
     bool rst_sent(TcpSegmentDescriptor&, TcpStreamTracker&) override;
     bool rst_recv(TcpSegmentDescriptor&, TcpStreamTracker&) override;
+
+    bool do_post_sm_packet_actions(TcpSegmentDescriptor&, TcpStreamTracker&) override;
 };
 
 #endif
index 6b18e98e6f7459c73201aaf6522ee7917bb9f37c..6c7f7969595ea060913d3d1cb000ad2001d247d4 100644 (file)
@@ -37,11 +37,10 @@ TcpStateSynRecv::TcpStateSynRecv(TcpStateMachine& tsm) :
 
 bool TcpStateSynRecv::syn_sent(TcpSegmentDescriptor& tsd, TcpStreamTracker& trk)
 {
-    Flow* flow = tsd.get_flow();
-
     trk.finish_server_init(tsd);
     trk.normalizer.ecn_tracker(tsd.get_tcph(), trk.session->tcp_config->require_3whs());
     trk.session->update_timestamp_tracking(tsd);
+    Flow* flow = tsd.get_flow();
     if ( tsd.get_tcph()->are_flags_set(TH_ECE) &&
         ( flow->get_session_flags() & SSNFLAG_ECN_CLIENT_QUERY ) )
         flow->set_session_flags(SSNFLAG_ECN_SERVER_REPLY);
@@ -65,11 +64,8 @@ bool TcpStateSynRecv::syn_recv(TcpSegmentDescriptor& tsd, TcpStreamTracker& trk)
 
 bool TcpStateSynRecv::syn_ack_sent(TcpSegmentDescriptor& tsd, TcpStreamTracker& trk)
 {
-    Flow* flow = tsd.get_flow();
-
     trk.finish_server_init(tsd);
     trk.normalizer.ecn_tracker(tsd.get_tcph(), trk.session->tcp_config->require_3whs());
-    flow->session_state |= STREAM_STATE_SYN_ACK;
 
     return true;
 }
@@ -78,10 +74,9 @@ bool TcpStateSynRecv::syn_ack_recv(TcpSegmentDescriptor& tsd, TcpStreamTracker&
 {
     if ( trk.is_ack_valid(tsd.get_ack()) )
     {
+        trk.irs = tsd.get_seq();
         trk.update_tracker_ack_recv(tsd);
         trk.normalizer.ecn_tracker(tsd.get_tcph(), trk.session->tcp_config->require_3whs());
-        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() )
             trk.session->handle_data_on_syn(tsd);
@@ -92,9 +87,16 @@ bool TcpStateSynRecv::syn_ack_recv(TcpSegmentDescriptor& tsd, TcpStreamTracker&
 
 bool TcpStateSynRecv::ack_sent(TcpSegmentDescriptor& tsd, TcpStreamTracker& trk)
 {
-    if ( trk.session->tcp_config->midstream_allowed(tsd.get_pkt()) )
-        trk.session->update_session_on_ack();
-
+    if ( trk.session->tcp_config->midstream_allowed(tsd.get_pkt()) && trk.session->flow->two_way_traffic() )
+    {
+        TcpStreamTracker::TcpState listener_state = tsd.get_listener()->get_tcp_state();
+        // Does this ACK finish 4-way handshake
+        if ( TcpStreamTracker::TCP_ESTABLISHED == listener_state )
+        {
+            trk.session->set_established(tsd);
+            trk.set_tcp_state(TcpStreamTracker::TCP_ESTABLISHED);
+        }
+    }
     return true;
 }
 
@@ -105,37 +107,41 @@ bool TcpStateSynRecv::ack_recv(TcpSegmentDescriptor& tsd, TcpStreamTracker& trk)
         trk.update_tracker_ack_recv(tsd);
         trk.session->set_pkt_action_flag(trk.normalizer.handle_paws(tsd));
         tsd.set_packet_flags(PKT_STREAM_TWH);
-        trk.session->set_established(tsd.get_pkt(), STREAM_STATE_ACK);
-        trk.session->update_perf_base_state(TcpStreamTracker::TCP_ESTABLISHED);
+        TcpStreamTracker::TcpState talker_state = tsd.get_talker()->get_tcp_state();
+        // Does this ACK finish the 3-way or 4-way handshake
+        if ( TcpStreamTracker::TCP_ESTABLISHED == talker_state || !trk.session->flow->two_way_traffic() )
+            trk.session->set_established(tsd);
         trk.set_tcp_state(TcpStreamTracker::TCP_ESTABLISHED);
         trk.session->check_for_window_slam(tsd);
     }
-
     return true;
 }
 
 bool TcpStateSynRecv::data_seg_sent(TcpSegmentDescriptor& tsd, TcpStreamTracker& trk)
 {
-    trk.update_tracker_ack_sent(tsd);
-    if ( trk.session->no_ack_mode_enabled() )
-        trk.update_tracker_no_ack_recv(tsd);
-
+    if ( trk.session->tcp_config->midstream_allowed(tsd.get_pkt()) )
+    {
+        trk.update_tracker_ack_sent(tsd);
+        if ( trk.session->no_ack_mode_enabled() )
+            trk.update_tracker_no_ack_recv(tsd);
+        if ( trk.session->flow->two_way_traffic() )
+        {
+            TcpStreamTracker::TcpState listener_state = tsd.get_listener()->get_tcp_state();
+            // Does this ACK finish 4-way handshake
+            if ( TcpStreamTracker::TCP_ESTABLISHED == listener_state )
+            {
+                trk.session->set_established(tsd);
+                trk.set_tcp_state(TcpStreamTracker::TCP_ESTABLISHED);
+            }
+        }
+    }
     return true;
 }
 
 bool TcpStateSynRecv::data_seg_recv(TcpSegmentDescriptor& tsd, TcpStreamTracker& trk)
 {
-    if ( trk.is_ack_valid(tsd.get_ack()) )
-    {
-        trk.update_tracker_ack_recv(tsd);
-        tsd.set_packet_flags(PKT_STREAM_TWH);
-        trk.session->set_pkt_action_flag(trk.normalizer.handle_paws(tsd));
-        trk.session->update_perf_base_state(TcpStreamTracker::TCP_ESTABLISHED);
-        trk.set_tcp_state(TcpStreamTracker::TCP_ESTABLISHED);
-    }
-
+    ack_recv(tsd, trk);
     trk.session->handle_data_segment(tsd);
-
     return true;
 }
 
@@ -143,12 +149,16 @@ bool TcpStateSynRecv::fin_recv(TcpSegmentDescriptor& tsd, TcpStreamTracker& trk)
 {
     if ( tsd.get_tcph()->is_ack() )
     {
-        Flow* flow = tsd.get_flow();
-
         trk.set_fin_seq_status_seen(tsd);
         trk.update_tracker_ack_recv(tsd);
         trk.session->set_pkt_action_flag(trk.normalizer.handle_paws(tsd));
-        flow->session_state |= STREAM_STATE_ACK;
+
+        TcpStreamTracker::TcpState talker_state = tsd.get_talker()->get_tcp_state();
+        // Does this ACK finish the 3-way
+        if ( TcpStreamTracker::TCP_ESTABLISHED == talker_state
+            || TcpStreamTracker::TCP_FIN_WAIT1 == talker_state )
+            trk.session->set_established(tsd);
+
         trk.perform_fin_recv_flush(tsd);
 
         if ( trk.update_on_fin_recv(tsd) )
@@ -168,6 +178,8 @@ bool TcpStateSynRecv::rst_recv(TcpSegmentDescriptor& tsd, TcpStreamTracker& trk)
     {
         Flow* flow = tsd.get_flow();
         flow->set_session_flags(SSNFLAG_RESET);
+        if ( !((SSNFLAG_TCP_PSEUDO_EST | SSNFLAG_ESTABLISHED) & flow->get_session_flags()) )
+            trk.session->set_pseudo_established(tsd.get_pkt());
     }
     else
     {
index 7a0ce1d75df181e56232a7cefbc3f0a4bb558515..497fb59a115c27cac7e59595675ed348b90a1fec 100644 (file)
@@ -36,30 +36,44 @@ TcpStateSynSent::TcpStateSynSent(TcpStateMachine& tsm) :
 bool TcpStateSynSent::syn_sent(TcpSegmentDescriptor& tsd, TcpStreamTracker& trk)
 {
     trk.session->check_for_repeated_syn(tsd);
-
     return true;
 }
 
 bool TcpStateSynSent::syn_recv(TcpSegmentDescriptor& tsd, TcpStreamTracker& trk)
 {
+    trk.irs = tsd.get_seq();
     trk.finish_client_init(tsd);
     if ( tsd.is_data_segment() )
         trk.session->handle_data_on_syn(tsd);
     trk.set_tcp_state(TcpStreamTracker::TCP_SYN_RECV);
+    return true;
+}
 
+bool TcpStateSynSent::syn_ack_sent(TcpSegmentDescriptor& tsd, TcpStreamTracker& trk)
+{
+    if ( trk.session->flow->two_way_traffic() )
+    {
+        trk.session->check_for_repeated_syn(tsd);
+        trk.update_tracker_ack_sent(tsd);
+        trk.iss = tsd.get_seq();
+        trk.session->update_timestamp_tracking(tsd);
+    }
     return true;
 }
 
 bool TcpStateSynSent::syn_ack_recv(TcpSegmentDescriptor& tsd, TcpStreamTracker& trk)
 {
-    if ( trk.update_on_3whs_ack(tsd) )
+    if ( trk.session->flow->two_way_traffic() )
     {
-        trk.session->update_timestamp_tracking(tsd);
-        if ( tsd.is_data_segment() )
-            trk.session->handle_data_on_syn(tsd);
+        if ( trk.update_on_3whs_ack(tsd) )
+        {
+            trk.session->update_timestamp_tracking(tsd);
+            if ( tsd.is_data_segment() )
+                trk.session->handle_data_on_syn(tsd);
+        }
+        else
+            trk.session->set_pkt_action_flag(ACTION_BAD_PKT);
     }
-    else
-        trk.session->set_pkt_action_flag(ACTION_BAD_PKT);
 
     return true;
 }
@@ -67,42 +81,89 @@ bool TcpStateSynSent::syn_ack_recv(TcpSegmentDescriptor& tsd, TcpStreamTracker&
 bool TcpStateSynSent::ack_sent(TcpSegmentDescriptor& tsd, TcpStreamTracker& trk)
 {
     trk.update_tracker_ack_sent(tsd);
-    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);
-
+    if ( trk.session->flow->two_way_traffic() )
+    {
+        TcpStreamTracker::TcpState listener_state = tsd.get_listener()->get_tcp_state();
+        // Weird case with c2s syn, c2s syn seq + 1, s2c syn-ack to 2nd syn, c2s ack
+        if ( TcpStreamTracker::TCP_SYN_RECV == listener_state )
+        {
+            trk.session->set_established(tsd);
+            trk.set_tcp_state(TcpStreamTracker::TCP_ESTABLISHED);
+        }
+    }
     return true;
 }
 
 bool TcpStateSynSent::ack_recv(TcpSegmentDescriptor& tsd, TcpStreamTracker& trk)
 {
-    trk.update_on_3whs_ack(tsd);
+    // Finish handshake
+    if ( trk.session->flow->two_way_traffic() )
+        trk.update_on_3whs_ack(tsd);
+    else
+    {
+        trk.update_tracker_ack_recv(tsd);
+        trk.session->set_established(tsd);
+        trk.set_tcp_state(TcpStreamTracker::TCP_ESTABLISHED);
+    }
     return true;
 }
 
 bool TcpStateSynSent::data_seg_sent(TcpSegmentDescriptor& tsd, TcpStreamTracker& trk)
 {
     trk.update_tracker_ack_sent(tsd);
-    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);
-
+    if ( trk.session->flow->two_way_traffic() )
+    {
+        TcpStreamTracker::TcpState listener_state = tsd.get_listener()->get_tcp_state();
+        // Weird case with c2s syn, c2s syn seq + 1, s2c syn-ack to 2nd syn, c2s ack
+        if ( TcpStreamTracker::TCP_SYN_RECV == listener_state )
+        {
+            trk.session->set_established(tsd);
+            trk.set_tcp_state(TcpStreamTracker::TCP_ESTABLISHED);
+        }
+    }
     return true;
 }
 
 bool TcpStateSynSent::data_seg_recv(TcpSegmentDescriptor& tsd, TcpStreamTracker& trk)
 {
-    if ( trk.update_on_3whs_ack(tsd) )
-        trk.session->handle_data_segment(tsd);
+    ack_recv(tsd, trk);
+    trk.session->handle_data_segment(tsd);
+    return true;
+}
 
+bool TcpStateSynSent::fin_sent(TcpSegmentDescriptor& tsd, TcpStreamTracker& trk)
+{
+    trk.update_on_fin_sent(tsd);
+    trk.session->flow->call_handlers(tsd.get_pkt(), true);
+    trk.session->update_timestamp_tracking(tsd);
+    if ( trk.session->flow->two_way_traffic() )
+    {
+        TcpStreamTracker::TcpState listener_state = tsd.get_listener()->get_tcp_state();
+        // Weird case with c2s syn, c2s syn seq + 1, s2c syn-ack to 2nd syn, c2s ack
+        if ( TcpStreamTracker::TCP_SYN_RECV == listener_state )
+        {
+            trk.session->set_established(tsd);
+            trk.set_tcp_state(TcpStreamTracker::TCP_ESTABLISHED);
+        }
+        trk.set_tcp_state(TcpStreamTracker::TCP_FIN_WAIT1);
+    }
     return true;
 }
 
 bool TcpStateSynSent::fin_recv(TcpSegmentDescriptor& tsd, TcpStreamTracker& trk)
 {
     trk.set_fin_seq_status_seen(tsd);
+    ack_recv(tsd, trk);
+    if ( trk.session->flow->two_way_traffic() )
+    {
+        if ( trk.update_on_fin_recv(tsd) )
+        {
+            trk.session->update_perf_base_state(TcpStreamTracker::TCP_CLOSING);
+            trk.set_tcp_state(TcpStreamTracker::TCP_CLOSE_WAIT);
+        }
+    }
     trk.perform_fin_recv_flush(tsd);
     return true;
 }
@@ -125,3 +186,10 @@ bool TcpStateSynSent::rst_recv(TcpSegmentDescriptor& tsd, TcpStreamTracker& trk)
     return true;
 }
 
+bool TcpStateSynSent::do_post_sm_packet_actions(TcpSegmentDescriptor& tsd, TcpStreamTracker& trk)
+{
+    trk.session->check_for_window_slam(tsd);
+
+    return true;
+}
+
index c5b302c632110263784e0aa1b66e24af531d4f46..16743a33d8e2fd021e95accb9e5519d801046220 100644 (file)
@@ -31,13 +31,17 @@ public:
 
     bool syn_sent(TcpSegmentDescriptor&, TcpStreamTracker&) override;
     bool syn_recv(TcpSegmentDescriptor&, TcpStreamTracker&) override;
+    bool syn_ack_sent(TcpSegmentDescriptor&, TcpStreamTracker&) override;
     bool syn_ack_recv(TcpSegmentDescriptor&, TcpStreamTracker&) override;
     bool ack_sent(TcpSegmentDescriptor&, TcpStreamTracker&) override;
     bool ack_recv(TcpSegmentDescriptor&, TcpStreamTracker&) override;
     bool data_seg_sent(TcpSegmentDescriptor&, TcpStreamTracker&) override;
     bool data_seg_recv(TcpSegmentDescriptor&, TcpStreamTracker&) override;
+    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 b00dbd74777ee3d0ff9aa147e186ccf18f494a09..8067a637da4664a415a77d7af21c277a8200170a 100644 (file)
@@ -26,7 +26,6 @@
 #include "tcp_stream_session.h"
 
 #include "framework/data_bus.h"
-#include "log/messages.h"
 #include "pub_sub/stream_event_ids.h"
 #include "stream/stream.h"
 #include "stream/tcp/tcp_ha.h"
@@ -57,55 +56,12 @@ void TcpStreamSession::init_new_tcp_session(TcpSegmentDescriptor& tsd)
     lws_init = true;
 }
 
-void TcpStreamSession::update_session_on_syn_ack()
-{
-    /* If session is already marked as established */
-    if ( !(flow->session_state & STREAM_STATE_ESTABLISHED) )
-    {
-        /* SYN-ACK from server */
-        if (flow->session_state != STREAM_STATE_NONE)
-        {
-            flow->session_state |= STREAM_STATE_SYN_ACK;
-            update_perf_base_state(TcpStreamTracker::TCP_ESTABLISHED);
-        }
-    }
-}
-
-void TcpStreamSession::update_session_on_ack()
-{
-    /* If session is already marked as established */
-    if ( !(flow->session_state & STREAM_STATE_ESTABLISHED) )
-    {
-        if ( flow->session_state & STREAM_STATE_SYN_ACK )
-        {
-            flow->session_state |= STREAM_STATE_ACK | STREAM_STATE_ESTABLISHED;
-            update_perf_base_state(TcpStreamTracker::TCP_ESTABLISHED);
-        }
-    }
-}
-
 void TcpStreamSession::update_session_on_server_packet(TcpSegmentDescriptor& tsd)
 {
     flow->set_session_flags(SSNFLAG_SEEN_SERVER);
     tsd.set_talker(server);
     tsd.set_listener(client);
 
-    /* If we picked this guy up midstream, finish the initialization */
-    if ( !(flow->session_state & STREAM_STATE_ESTABLISHED)
-        && (flow->session_state & STREAM_STATE_MIDSTREAM) )
-    {
-        if ( tsd.get_tcph()->are_flags_set(TH_ECE)
-             && (flow->get_session_flags() & SSNFLAG_ECN_CLIENT_QUERY) )
-            flow->set_session_flags(SSNFLAG_ECN_SERVER_REPLY);
-
-        if ( flow->get_session_flags() & SSNFLAG_SEEN_CLIENT )
-        {
-            // should TCP state go to established too?
-            set_established(tsd.get_pkt());
-            update_perf_base_state(TcpStreamTracker::TCP_ESTABLISHED);
-        }
-    }
-
     if ( !flow->inner_server_ttl && !tsd.is_meta_ack_packet() )
         flow->set_ttl(tsd.get_pkt(), false);
 }
@@ -117,14 +73,6 @@ void TcpStreamSession::update_session_on_client_packet(TcpSegmentDescriptor& tsd
     tsd.set_talker(client);
     tsd.set_listener(server);
 
-    if ( !( flow->session_state & STREAM_STATE_ESTABLISHED )
-        && ( flow->session_state & STREAM_STATE_MIDSTREAM ) )
-    {
-        /* Midstream and seen server. */
-        if ( flow->get_session_flags() & SSNFLAG_SEEN_SERVER )
-            set_established(tsd.get_pkt());
-    }
-
     if ( !flow->inner_client_ttl && !tsd.is_meta_ack_packet() )
         flow->set_ttl(tsd.get_pkt(), true);
 }
@@ -392,20 +340,29 @@ 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)
+void TcpStreamSession::set_established(const TcpSegmentDescriptor& tsd)
 {
-    flow->session_state |= STREAM_STATE_ESTABLISHED | flags;
+    update_perf_base_state(TcpStreamTracker::TCP_ESTABLISHED);
+    flow->session_state |= STREAM_STATE_ESTABLISHED;
     if (SSNFLAG_ESTABLISHED != (SSNFLAG_ESTABLISHED & flow->get_session_flags()))
     {
         flow->set_session_flags(SSNFLAG_ESTABLISHED);
-        DataBus::publish(Stream::get_pub_id(), StreamEventIds::TCP_ESTABLISHED, p);
+        // Only send 1 event
+        if (SSNFLAG_TCP_PSEUDO_EST != (SSNFLAG_TCP_PSEUDO_EST & flow->get_session_flags()))
+            DataBus::publish(Stream::get_pub_id(), StreamEventIds::TCP_ESTABLISHED, tsd.get_pkt());
     }
 }
 
-void TcpStreamSession::check_for_one_sided_session(Packet* p)
+void TcpStreamSession::set_pseudo_established(Packet* p)
+{
+    p->flow->ssn_state.session_flags |= SSNFLAG_TCP_PSEUDO_EST;
+    DataBus::publish(Stream::get_pub_id(), StreamEventIds::TCP_ESTABLISHED, p);
+}
+
+bool TcpStreamSession::check_for_one_sided_session(Packet* p)
 {
     Flow& flow = *p->flow;
-    if ( !( (SSNFLAG_ESTABLISHED | SSNFLAG_TCP_ONE_SIDED) & flow.ssn_state.session_flags )
+    if ( 0 == ( (SSNFLAG_ESTABLISHED | SSNFLAG_TCP_PSEUDO_EST) & flow.ssn_state.session_flags )
         && p->is_from_client_originally() )
     {
         uint64_t initiator_packets;
@@ -430,10 +387,23 @@ void TcpStreamSession::check_for_one_sided_session(Packet* p)
                 initiator_watermark = watermark;
             else if ( initiator_watermark != watermark )
             {
-                flow.ssn_state.session_flags |= SSNFLAG_TCP_ONE_SIDED;
-                DataBus::publish(Stream::get_pub_id(), StreamEventIds::TCP_ESTABLISHED, p);
+                set_pseudo_established(p);
+                return true;
             }
         }
     }
+    return false;
+}
+
+void TcpStreamSession::check_for_pseudo_established(Packet* p)
+{
+    Flow& flow = *p->flow;
+    if ( 0 == ( (SSNFLAG_ESTABLISHED | SSNFLAG_TCP_PSEUDO_EST) & flow.ssn_state.session_flags ) )
+    {
+        if ( check_for_one_sided_session(p) )
+            return;
+        if ( 0 < flow.flowstats.client_pkts && 0 < flow.flowstats.server_pkts )
+            set_pseudo_established(p);
+    }
 }
 
index 8145f7b0d7bd6d6dd0e04ab5db2ddfe089cabc18..6e0fa1559ce6642b2347b7c63a6c171534d69533 100644 (file)
@@ -79,8 +79,6 @@ public:
 
     virtual void init_new_tcp_session(TcpSegmentDescriptor&);
     virtual void update_timestamp_tracking(TcpSegmentDescriptor&) = 0;
-    virtual void update_session_on_syn_ack();
-    virtual void update_session_on_ack();
     virtual void update_session_on_server_packet(TcpSegmentDescriptor&);
     virtual void update_session_on_client_packet(TcpSegmentDescriptor&);
     virtual void update_session_on_rst(TcpSegmentDescriptor&, bool) = 0;
@@ -99,8 +97,10 @@ 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*);
+    void set_established(const TcpSegmentDescriptor&);
+    void set_pseudo_established(snort::Packet*);
+    bool check_for_one_sided_session(snort::Packet*);
+    void check_for_pseudo_established(snort::Packet*);
 
     virtual void update_paws_timestamps(TcpSegmentDescriptor&) = 0;
     virtual void check_for_repeated_syn(TcpSegmentDescriptor&) = 0;
index 9d8fb205cc0ec4981225a5ee3d533a2cef72d4fd..9a64fbf776cff828b8f075a7f796dac844018c39 100644 (file)
@@ -27,7 +27,6 @@
 
 #include <daq.h>
 
-#include "log/messages.h"
 #include "main/analyzer.h"
 #include "main/snort.h"
 #include "packet_io/active.h"
@@ -89,9 +88,27 @@ TcpStreamTracker::TcpEvent TcpStreamTracker::set_tcp_event(const TcpSegmentDescr
     {
         // talker events
         if ( tcph->is_syn_only() )
+        {
             tcp_event = TCP_SYN_SENT_EVENT;
+            if ( tcp_state == TcpStreamTracker::TCP_STATE_NONE )
+                DataBus::publish(Stream::get_pub_id(), StreamEventIds::TCP_SYN, tsd.get_pkt());
+        }
         else if ( tcph->is_syn_ack() )
+        {
             tcp_event = TCP_SYN_ACK_SENT_EVENT;
+            if ( tcp_state == TcpStreamTracker::TCP_LISTEN )
+                DataBus::publish(Stream::get_pub_id(), StreamEventIds::TCP_SYN_ACK, tsd.get_pkt());
+            else if ( tcp_state == TcpStreamTracker::TCP_SYN_RECV )
+            {
+                Flow* flow = tsd.get_flow();
+                if ( flow->get_session_flags() & SSNFLAG_SEEN_CLIENT )
+                {
+                    TcpStreamTracker::TcpState listener_state = tsd.get_listener()->get_tcp_state();
+                    if ( listener_state == TcpStreamTracker::TCP_SYN_SENT )
+                        DataBus::publish(Stream::get_pub_id(), StreamEventIds::TCP_SYN_ACK, tsd.get_pkt());
+                }
+            }
+        }
         else if ( tcph->is_rst() )
             tcp_event = TCP_RST_SENT_EVENT;
         else if ( tcph->is_fin( ) )
@@ -117,18 +134,11 @@ TcpStreamTracker::TcpEvent TcpStreamTracker::set_tcp_event(const TcpSegmentDescr
         {
             tcp_event = TCP_SYN_RECV_EVENT;
             tcpStats.syns++;
-            if ( tcp_state == TcpStreamTracker::TCP_LISTEN )
-                DataBus::publish(Stream::get_pub_id(), StreamEventIds::TCP_SYN, tsd.get_pkt());
         }
         else if ( tcph->is_syn_ack() )
         {
             tcp_event = TCP_SYN_ACK_RECV_EVENT;
             tcpStats.syn_acks++;
-            if ( tcp_state == TcpStreamTracker::TCP_SYN_SENT or
-                (!Stream::is_midstream(tsd.get_flow()) and
-                (tcp_state == TcpStreamTracker::TCP_LISTEN or
-                tcp_state == TcpStreamTracker::TCP_STATE_NONE)) )
-                DataBus::publish(Stream::get_pub_id(), StreamEventIds::TCP_SYN_ACK, tsd.get_pkt());
         }
         else if ( tcph->is_rst() )
         {
@@ -371,49 +381,10 @@ void TcpStreamTracker::init_on_synack_recv(TcpSegmentDescriptor& tsd)
     reassembler.set_seglist_base_seq(tsd.get_seq() + 1);
 
     cache_mac_address(tsd, FROM_SERVER);
-    tcp_state = TcpStreamTracker::TCP_ESTABLISHED;
-}
-
-void TcpStreamTracker::init_on_3whs_ack_sent(TcpSegmentDescriptor& tsd)
-{
-    tsd.get_flow()->set_session_flags(SSNFLAG_SEEN_CLIENT);
-
-    if ( tsd.get_tcph()->are_flags_set(TH_CWR | TH_ECE) )
-        tsd.get_flow()->set_session_flags(SSNFLAG_ECN_CLIENT_QUERY);
-
-    iss = tsd.get_seq();
-    snd_una = tsd.get_seq();
-    snd_nxt = snd_una;
-    snd_wnd = tsd.get_wnd();
-
-    r_win_base = tsd.get_ack();
-    rcv_nxt = tsd.get_ack();
-
-    ts_last_packet = tsd.get_packet_timestamp();
-    tf_flags |= normalizer.get_tcp_timestamp(tsd, false);
-    ts_last = tsd.get_timestamp();
-    if (ts_last == 0)
-        tf_flags |= TF_TSTAMP_ZERO;
-    tf_flags |= tsd.init_wscale(&wscale);
-
-    cache_mac_address(tsd, FROM_CLIENT);
-    tcp_state = TcpStreamTracker::TCP_ESTABLISHED;
-}
-
-void TcpStreamTracker::init_on_3whs_ack_recv(TcpSegmentDescriptor& tsd)
-{
-    iss = tsd.get_ack() - 1;
-    irs = tsd.get_seq();
-    snd_una = tsd.get_ack();
-    snd_nxt = snd_una;
-
-    rcv_nxt = tsd.get_seq();
-    r_win_base = tsd.get_seq();
-    reassembler.set_seglist_base_seq(tsd.get_seq() + 1);
-
-    cache_mac_address(tsd, FROM_CLIENT);
-    tcp_state = TcpStreamTracker::TCP_ESTABLISHED;
-    tcpStats.sessions_on_3way++;
+    if ( TcpStreamTracker::TCP_SYN_SENT == tcp_state )
+        tcp_state = TcpStreamTracker::TCP_ESTABLISHED;
+    else
+        tcp_state = TcpStreamTracker::TCP_SYN_SENT;
 }
 
 void TcpStreamTracker::init_on_data_seg_sent(TcpSegmentDescriptor& tsd)
@@ -425,8 +396,8 @@ void TcpStreamTracker::init_on_data_seg_sent(TcpSegmentDescriptor& tsd)
     else
         flow->set_session_flags(SSNFLAG_SEEN_SERVER);
 
-    iss = tsd.get_seq();
-    irs = tsd.get_ack();
+    iss = tsd.get_seq() - 1;
+    irs = tsd.get_ack() - 1;
     snd_una = tsd.get_seq();
     snd_nxt = snd_una + tsd.get_len();
     snd_wnd = tsd.get_wnd();
@@ -444,13 +415,16 @@ void TcpStreamTracker::init_on_data_seg_sent(TcpSegmentDescriptor& tsd)
     tf_flags |= tsd.init_wscale(&wscale);
 
     cache_mac_address(tsd, tsd.get_direction() );
-    tcp_state = TcpStreamTracker::TCP_ESTABLISHED;
+    if ( TcpStreamTracker::TCP_LISTEN == tcp_state || TcpStreamTracker::TCP_STATE_NONE == tcp_state)
+        tcp_state = TcpStreamTracker::TCP_MID_STREAM_SENT;
+    else
+        tcp_state = TcpStreamTracker::TCP_ESTABLISHED;
 }
 
 void TcpStreamTracker::init_on_data_seg_recv(TcpSegmentDescriptor& tsd)
 {
-    iss = tsd.get_ack();
-    irs = tsd.get_seq();
+    iss = tsd.get_ack() - 1;
+    irs = tsd.get_seq() - 1;
     snd_una = tsd.get_ack();
     snd_nxt = snd_una;
     snd_wnd = 0; /* reset later */
@@ -460,7 +434,10 @@ void TcpStreamTracker::init_on_data_seg_recv(TcpSegmentDescriptor& tsd)
     reassembler.set_seglist_base_seq(tsd.get_seq());
 
     cache_mac_address(tsd, tsd.get_direction() );
-    tcp_state = TcpStreamTracker::TCP_ESTABLISHED;
+    if ( TcpStreamTracker::TCP_LISTEN == tcp_state || TcpStreamTracker::TCP_STATE_NONE == tcp_state )
+        tcp_state = TcpStreamTracker::TCP_MID_STREAM_RECV;
+    else
+        tcp_state = TcpStreamTracker::TCP_ESTABLISHED;
     tcpStats.sessions_on_data++;
 }
 
@@ -553,10 +530,13 @@ bool TcpStreamTracker::update_on_3whs_ack(TcpSegmentDescriptor& tsd)
 
     if ( good_ack )
     {
-        irs = tsd.get_seq();
+        if (!irs)
+            irs = tsd.get_seq();
         finish_client_init(tsd);
         update_tracker_ack_recv(tsd);
-        session->set_established(tsd.get_pkt(), STREAM_STATE_ACK);
+        TcpStreamTracker::TcpState talker_state = tsd.get_talker()->get_tcp_state();
+        if ( TcpStreamTracker::TCP_ESTABLISHED == talker_state )
+            session->set_established(tsd);
         tcp_state = TcpStreamTracker::TCP_ESTABLISHED;
     }
 
@@ -593,17 +573,22 @@ void TcpStreamTracker::update_on_rst_sent()
 
 bool TcpStreamTracker::update_on_fin_recv(TcpSegmentDescriptor& tsd)
 {
-    if ( SEQ_LT(tsd.get_end_seq(), r_win_base) )
-        return false;
+    if ( session->flow->two_way_traffic() )
+    {
+        if ( SEQ_LT(tsd.get_end_seq(), r_win_base) )
+            return false;
 
-    //--------------------------------------------------
-    // FIXIT-L don't bump rcv_nxt unless FIN is in seq
-    // because it causes bogus 129:5 cases
-    // but doing so causes extra gaps
-    if ( SEQ_EQ(tsd.get_end_seq(), rcv_nxt) )
-        rcv_nxt++;
+        //--------------------------------------------------
+        // FIXIT-L don't bump rcv_nxt unless FIN is in seq
+        // because it causes bogus 129:5 cases
+        // but doing so causes extra gaps
+        if ( SEQ_EQ(tsd.get_end_seq(), rcv_nxt) )
+            rcv_nxt++;
+        else
+            fin_seq_adjust = 1;
+    }
     else
-        fin_seq_adjust = 1;
+        rcv_nxt++;
 
     return true;
 }
index 309fdef2c6e51c224dd556f372a87036a1cb063f..08208f3193668a774a8e98ad2f68db877783e9b6 100644 (file)
@@ -54,6 +54,8 @@ public:
         TCP_SYN_SENT,
         TCP_SYN_RECV,
         TCP_ESTABLISHED,
+        TCP_MID_STREAM_SENT,
+        TCP_MID_STREAM_RECV,
         TCP_FIN_WAIT1,
         TCP_FIN_WAIT2,
         TCP_CLOSE_WAIT,
@@ -276,8 +278,6 @@ public:
     virtual void init_on_syn_recv(TcpSegmentDescriptor&);
     virtual void init_on_synack_sent(TcpSegmentDescriptor&);
     virtual void init_on_synack_recv(TcpSegmentDescriptor&);
-    virtual void init_on_3whs_ack_sent(TcpSegmentDescriptor&);
-    virtual void init_on_3whs_ack_recv(TcpSegmentDescriptor&);
     virtual void init_on_data_seg_sent(TcpSegmentDescriptor&);
     virtual void init_on_data_seg_recv(TcpSegmentDescriptor&);
     virtual void finish_server_init(TcpSegmentDescriptor&);
index e3b882bdeedaca06308177dd4fb693be38805c7b..5ef7f4c3a9e81f3bdf481096f01fec01702aa0e4 100644 (file)
@@ -40,7 +40,7 @@ void S5TraceTCP(const TcpSegmentDescriptor&, const snort::Packet*) { }
 
 static const char* const statext[] =
 {
-    "LST", "SYS", "SYR", "EST", "FW1", "FW2", "CLW",
+    "LST", "SYS", "SYR", "EST", "MDS", "MDR", "FW1", "FW2", "CLW",
     "CLG", "LAK", "TWT", "CLD", "NON"
 };