get_proto_session[to_utype(type)] = get_ssn;
}
-// FIXIT-P apply more filtering logic here, eg require_3whs
-// delegate to stream inspectors but that requires binding
-// can't use session because goal is to avoid instantiation
static bool want_flow(PktType type, Packet* p)
{
if ( type != PktType::TCP )
// guessing direction based on ports is misleading
return false;
- if ( p->ptrs.tcph->is_syn_ack() or p->dsize )
- return true;
-
if ( p->ptrs.tcph->is_syn_only() )
{
+ if ( Stream::require_3whs() )
+ return true;
+
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 )
+
+ if ( p->ptrs.decode_flags & (DECODE_TCP_MSS | DECODE_TCP_TS | DECODE_TCP_WS) )
return true;
}
+ if ( p->ptrs.tcph->is_syn_ack() or p->dsize )
+ return Stream::midstream_allowed(p, true);
+
p->packet_flags |= PKT_FROM_CLIENT;
return false;
}
flow->set_direction(p);
// This call can reset the flow state to SETUP in lazy flow timeout cases
- if ( flow->flow_state != Flow::FlowState::ALLOW )
- flow->session->precheck(p);
+ if ( flow->flow_state == Flow::FlowState::INSPECT and !flow->session->precheck(p) )
+ {
+ // flow expired, must recheck eligibility
+ if ( !want_flow(flow->pkt_type, p) )
+ {
+ flow->session_state |= STREAM_STATE_CLOSED;
+ return 0; // flow will be deleted
+ }
+ // flow will restart using existing service
+ // FIXIT-M reuse direction or clear service and use wizard
+ }
}
if ( flow->flow_state != Flow::FlowState::SETUP )
virtual int process(snort::Packet*) { return 0; }
virtual void restart(snort::Packet*) { }
- virtual void precheck(snort::Packet*) { }
+ virtual bool precheck(snort::Packet*) { return false; }
virtual void clear() = 0;
virtual void cleanup(snort::Packet* = nullptr) { clear(); }
{
uint32_t IpApi::id() const { return 0; }
}
+bool Stream::midstream_allowed(Packet const*, bool)
+{ return false; }
}
ExpectCache::ExpectCache(uint32_t) { }
{
uint32_t IpApi::id() const { return 0; }
}
+bool Stream::midstream_allowed(Packet const*, bool)
+{ return false; }
}
bool FlowKey::init(
uint32_t checksum_eval = CHECKSUM_FLAG__ALL | CHECKSUM_FLAG__DEF;
uint32_t checksum_drop = CHECKSUM_FLAG__DEF;
uint32_t normal_mask = 0;
+
+ int hs_timeout = -1;
bool cloned = false;
private:
"use zero for production, non-zero for testing at given size (for TCP and user)" },
#endif
+ { "held_packet_timeout", Parameter::PT_INT, "1:max32", "1000",
+ "timeout in milliseconds for held packets" },
+
{ "ip_frags_only", Parameter::PT_BOOL, nullptr, "false",
"don't process non-frag flows" },
{ "pruning_timeout", Parameter::PT_INT, "1:max32", "30",
"minimum inactive time before being eligible for pruning" },
- { "held_packet_timeout", Parameter::PT_INT, "1:max32", "1000",
- "timeout in milliseconds for held packets" },
+ { "require_3whs", Parameter::PT_INT, "-1:max31", "-1",
+ "don't track midstream TCP sessions after given seconds from start up; -1 tracks all" },
FLOW_TYPE_TABLE("ip_cache", "ip", ip_params),
FLOW_TYPE_TABLE("icmp_cache", "icmp", icmp_params),
bool StreamModule::set(const char* fqn, Value& v, SnortConfig* c)
{
- PktType type = PktType::NONE;
-
#ifdef REG_TEST
if ( v.is("footprint") )
- {
config.footprint = v.get_uint32();
- return true;
- }
+ else
#endif
- if ( v.is("ip_frags_only") )
+ if ( v.is("held_packet_timeout") )
+ config.held_packet_timeout = v.get_uint32();
+
+ else if ( v.is("ip_frags_only") )
{
if ( v.get_bool() )
c->set_run_flags(RUN_FLAG__IP_FRAGS_ONLY);
- return true;
}
else if ( v.is("max_flows") )
- {
config.flow_cache_cfg.max_flows = v.get_uint32();
- return true;
- }
+
else if ( v.is("prune_flows") )
- {
config.flow_cache_cfg.prune_flows = v.get_uint32();
- return true;
- }
+
else if ( v.is("pruning_timeout") )
- {
config.flow_cache_cfg.pruning_timeout = v.get_uint32();
- return true;
- }
- else if ( v.is("held_packet_timeout") )
+
+ else if ( v.is("require_3whs") )
+ config.hs_timeout = v.get_int32();
+
+ else if ( !strcmp(fqn, "stream.file_cache.idle_timeout") )
+ config.flow_cache_cfg.proto[to_utype(PktType::FILE)].nominal_timeout = v.get_uint32();
+
+ else if ( !strcmp(fqn, "stream.ip_cache.idle_timeout") )
+ config.flow_cache_cfg.proto[to_utype(PktType::IP)].nominal_timeout = v.get_uint32();
+
+ else if ( !strcmp(fqn, "stream.icmp_cache.idle_timeout") )
+ config.flow_cache_cfg.proto[to_utype(PktType::ICMP)].nominal_timeout = v.get_uint32();
+
+ else if ( !strcmp(fqn, "stream.tcp_cache.idle_timeout") )
+ config.flow_cache_cfg.proto[to_utype(PktType::TCP)].nominal_timeout = v.get_uint32();
+
+ else if ( !strcmp(fqn, "stream.udp_cache.idle_timeout") )
+ config.flow_cache_cfg.proto[to_utype(PktType::UDP)].nominal_timeout = v.get_uint32();
+
+ else
{
- config.held_packet_timeout = v.get_uint32();
- return true;
+ assert(!strcmp(fqn, "stream.user_cache.idle_timeout"));
+ config.flow_cache_cfg.proto[to_utype(PktType::USER)].nominal_timeout = v.get_uint32();
}
- else if ( strstr(fqn, "ip_cache") )
- type = PktType::IP;
- else if ( strstr(fqn, "icmp_cache") )
- type = PktType::ICMP;
- else if ( strstr(fqn, "tcp_cache") )
- type = PktType::TCP;
- else if ( strstr(fqn, "udp_cache") )
- type = PktType::UDP;
- else if ( strstr(fqn, "user_cache") )
- type = PktType::USER;
- else if ( strstr(fqn, "file_cache") )
- type = PktType::FILE;
- else
- return false;
-
- if ( v.is("idle_timeout") )
- config.flow_cache_cfg.proto[to_utype(type)].nominal_timeout = v.get_uint32();
return true;
}
bool StreamModule::end(const char* fqn, int, SnortConfig* sc)
{
+ if ( config.hs_timeout != -1 ) // condition required until stream_tcp.require_3whs is removed
+ get_network_parse_policy()->hs_timeout = config.hs_timeout;
+
if ( Snort::is_reloading() && strcmp(fqn, MOD_NAME) == 0 )
{
StreamReloadResourceManager* reload_resource_manager = new StreamReloadResourceManager;
ConfigLogger::log_value("max_aux_ip", SnortConfig::get_conf()->max_aux_ip);
ConfigLogger::log_value("pruning_timeout", flow_cache_cfg.pruning_timeout);
ConfigLogger::log_value("prune_flows", flow_cache_cfg.prune_flows);
+ ConfigLogger::log_limit("require_3whs", hs_timeout, -1, hs_timeout < 0 ? hs_timeout : -1);
for (int i = to_utype(PktType::IP); i < to_utype(PktType::PDU); ++i)
{
#include "framework/module.h"
#include "main/analyzer.h"
#include "main/reload_tuner.h"
+#include "protocols/packet.h"
+#include "time/packet_time.h"
namespace snort
{
unsigned footprint = 0;
#endif
uint32_t held_packet_timeout = 1000; // in milliseconds
+ int hs_timeout = -1;
void show() const;
};
#include "trace/trace_api.h"
#include "utils/util.h"
+#include "tcp/tcp_module.h"
#include "tcp/tcp_session.h"
#include "tcp/tcp_stream_tracker.h"
// session status
//-------------------------------------------------------------------------
+bool Stream::midstream_allowed(const Packet* p, bool alert)
+{
+ int t = get_network_policy()->hs_timeout;
+
+ if ( (t < 0) or (p->pkth->ts.tv_sec - packet_first_time() < t) )
+ return true;
+
+ if ( alert )
+ DetectionEngine::queue_event(GID_STREAM_TCP, STREAM_TCP_NO_3WHS);
+
+ return false;
+}
+
void Stream::check_flow_closed(Packet* p)
{
Flow* flow = p->flow;
#include <daq_common.h>
#include "flow/flow.h"
+#include "main/policy.h"
+#include "protocols/packet.h"
+#include "time/packet_time.h"
class HostAttributesDescriptor;
typedef std::shared_ptr<HostAttributesDescriptor> HostAttributesEntry;
Flow*, Packet* p, uint32_t gid, uint32_t sid,
uint32_t eventId, uint32_t eventSecond);
-
static void disable_reassembly(Flow*);
// Returns true if stream data for the flow is in sequence, otherwise return false.
// Handle session block pending state
static void check_flow_closed(Packet*);
- static void populate_flow_key(const Packet*, FlowKey*);
+ static bool require_3whs()
+ { return get_network_policy()->hs_timeout >= 0; }
- static void set_snort_protocol_id_from_ha(Flow*, const SnortProtocolId);
+ static bool midstream_allowed(const Packet* p, bool alert = false);
static bool is_midstream(Flow* flow)
{ return ((flow->ssn_state.session_flags & SSNFLAG_MIDSTREAM) != 0); }
+ static void populate_flow_key(const Packet*, FlowKey*);
+
+ static void set_snort_protocol_id_from_ha(Flow*, const SnortProtocolId);
+
// Get the TTL value used at session setup
// Set outer=false to get inner ip ttl for ip in ip; else outer=true
static uint8_t get_flow_ttl(Flow*, char dir, bool outer);
"queue data for reassembly before traffic is seen in both directions" },
{ "require_3whs", Parameter::PT_INT, "-1:max31", "-1",
- "don't track midstream sessions after given seconds from start up; -1 tracks all" },
+ "deprecated: use stream.require_3whs instead" },
{ "show_rebuilt_packets", Parameter::PT_BOOL, nullptr, "false",
"enable cmg like output of reassembled packets" },
else if ( v.is("require_3whs") )
{
- config->hs_timeout = v.get_int32();
+ int t = v.get_int32();
+ if ( t != -1 )
+ get_network_parse_policy()->hs_timeout = v.get_int32();
}
-
else if ( v.is("show_rebuilt_packets") )
{
if ( v.get_bool() )
return true;
}
-bool StreamTcpModule::end(const char*, int, SnortConfig* sc)
-{
- if ( config->hs_timeout >= 0 )
- sc->set_run_flags(RUN_FLAG__TRACK_ON_SYN);
- return true;
-}
-
const PegInfo* StreamTcpModule::get_pegs() const
{ return tcp_pegs; }
bool set(const char*, snort::Value&, snort::SnortConfig*) override;
bool begin(const char*, int, snort::SnortConfig*) override;
- bool end(const char*, int, snort::SnortConfig*) override;
const snort::RuleMap* get_rules() const override;
}
void TcpNormalizer::ecn_tracker(
- TcpNormalizerState& tns, const tcp::TCPHdr* tcph, bool req3way)
+ TcpNormalizerState& tns, const tcp::TCPHdr* tcph)
{
- if ( tcph->is_syn_ack() )
- {
- if ( !req3way || tns.session->ecn )
- tns.session->ecn = ((tcph->th_flags & (TH_ECE | TH_CWR)) == TH_ECE);
- }
- else if ( tcph->is_syn() )
+ if ( tcph->is_syn_only() )
tns.session->ecn = tcph->are_flags_set(TH_ECE | TH_CWR);
+
+ else if ( tcph->is_syn_ack() )
+ tns.session->ecn = tns.session->ecn and ((tcph->th_flags & (TH_ECE | TH_CWR)) == TH_ECE);
}
void TcpNormalizer::ecn_stripper(
virtual void trim_win_payload(State&, TcpSegmentDescriptor&, uint32_t max = 0,
bool force = false);
virtual void trim_mss_payload(State&, TcpSegmentDescriptor&, uint32_t max = 0);
- virtual void ecn_tracker(State&, const snort::tcp::TCPHdr*, bool req3way);
+ virtual void ecn_tracker(State&, const snort::tcp::TCPHdr*);
virtual void ecn_stripper(State&, TcpSegmentDescriptor&);
virtual uint32_t get_zwp_seq(State&);
virtual uint32_t get_stream_window(State&, TcpSegmentDescriptor&);
void trim_mss_payload(TcpSegmentDescriptor& tsd, uint32_t max = 0)
{ norm->trim_mss_payload(tns, tsd, max); }
- void ecn_tracker(const snort::tcp::TCPHdr* tcph, bool req3way)
- { norm->ecn_tracker(tns, tcph, req3way); }
+ void ecn_tracker(const snort::tcp::TCPHdr* tcph)
+ { norm->ecn_tracker(tns, tcph); }
void ecn_stripper(TcpSegmentDescriptor& tsd)
{ norm->ecn_stripper(tns, tsd); }
client.init_tcp_state(this);
server.init_tcp_state(this);
tcp_init = false;
- generate_3whs_alert = true;
cleaning = false;
splitter_init = false;
flow->set_ttl(tsd.get_pkt(), true);
init_session_on_syn(tsd);
tcpStats.resyns++;
- listener->normalizer.ecn_tracker(tcph, tcp_config->require_3whs());
+ listener->normalizer.ecn_tracker(tcph);
flow->update_session_flags(SSNFLAG_SEEN_CLIENT);
}
else if ( tcph->is_syn_ack() )
{
- if ( tcp_config->midstream_allowed(tsd.get_pkt()) )
- {
- flow->ssn_state.direction = FROM_SERVER;
- flow->set_ttl(tsd.get_pkt(), false);
- init_session_on_synack(tsd);
- tcpStats.resyns++;
- }
+ flow->ssn_state.direction = FROM_SERVER;
+ flow->set_ttl(tsd.get_pkt(), false);
+ init_session_on_synack(tsd);
+ tcpStats.resyns++;
- listener->normalizer.ecn_tracker(tcph, tcp_config->require_3whs());
+ listener->normalizer.ecn_tracker(tcph);
flow->update_session_flags(SSNFLAG_SEEN_SERVER);
}
}
return false;
}
-void TcpSession::cleanup_session_if_expired(Packet* p)
+bool TcpSession::cleanup_session_if_expired(Packet* p)
{
// Check if the session is expired. Should be done before we do something with
// the packet...Insert a packet, or handle state change SYN, FIN, RST, etc.
tcpStats.timeouts++;
TcpHAManager::process_deletion(*flow);
+
+ return true;
}
+ return false;
}
-void TcpSession::precheck(Packet* p)
+bool TcpSession::precheck(Packet* p)
{
// Check if the session is expired. Should be done before we do something with
// the packet...Insert a packet, or handle state change SYN, FIN, RST, etc.
- cleanup_session_if_expired(p);
+ return !cleanup_session_if_expired(p);
}
void TcpSession::init_tcp_packet_analysis(TcpSegmentDescriptor& tsd)
{
- if ( !splitter_init and tsd.is_data_segment() and
- (tcp_init or is_midstream_allowed(tsd)) )
+ if ( !splitter_init and tsd.is_data_segment() )
{
if ( !(tcp_config->flags & STREAM_CONFIG_NO_REASSEMBLY) and
!(tsd.get_flow()->flags.disable_reassembly_by_ips) )
#include "flow/flow.h"
#include "flow/session.h"
#include "protocols/packet.h"
+#include "stream/stream.h"
#include "tcp_event_logger.h"
#include "tcp_state_machine.h"
bool setup(snort::Packet*) override;
void restart(snort::Packet* p) override;
- void precheck(snort::Packet* p) override;
+ bool precheck(snort::Packet* p) override;
int process(snort::Packet*) override;
void clear() override;
void handle_data_on_syn(TcpSegmentDescriptor&);
void update_ignored_session(TcpSegmentDescriptor&);
- bool is_midstream_allowed(const TcpSegmentDescriptor& tsd)
- { return tcp_config->midstream_allowed(tsd.get_pkt()); }
-
uint16_t get_mss(bool to_server) const;
uint8_t get_tcp_options_len(bool to_server) const;
bool set_no_ack(bool);
bool no_ack_mode_enabled() { return no_ack; }
- void generate_no_3whs_event()
- {
- if ( generate_3whs_alert && flow->two_way_traffic())
- {
- tel.set_tcp_event(EVENT_NO_3WHS);
- generate_3whs_alert = false;
- }
- }
-
void set_pkt_action_flag(uint32_t flag)
{ pkt_action_mask |= flag; }
int16_t egress_group = DAQ_PKTHDR_UNKNOWN;
uint32_t daq_flags = 0;
uint32_t address_space_id = 0;
- bool generate_3whs_alert = true;
bool cleaning = false;
uint8_t held_packet_dir = SSN_DIR_NONE;
uint8_t ecn = 0;
void init_session_on_synack(TcpSegmentDescriptor&);
void update_on_3whs_complete(TcpSegmentDescriptor&);
bool ignore_this_packet(snort::Packet*);
- void cleanup_session_if_expired(snort::Packet*);
+ bool cleanup_session_if_expired(snort::Packet*);
void init_tcp_packet_analysis(TcpSegmentDescriptor&);
void check_events_and_actions(const TcpSegmentDescriptor& tsd);
void flush_tracker(TcpStreamTracker&, snort::Packet*, uint32_t dir, bool final_flush);
bool TcpStateCloseWait::syn_recv(TcpSegmentDescriptor& tsd, TcpStreamTracker& trk)
{
- trk.normalizer.ecn_tracker(tsd.get_tcph(), trk.session->tcp_config->require_3whs() );
+ trk.normalizer.ecn_tracker(tsd.get_tcph());
if ( tsd.is_data_segment() )
trk.session->handle_data_on_syn(tsd);
bool TcpStateClosing::syn_recv(TcpSegmentDescriptor& tsd, TcpStreamTracker& trk)
{
- trk.normalizer.ecn_tracker(tsd.get_tcph(), trk.session->tcp_config->require_3whs());
+ trk.normalizer.ecn_tracker(tsd.get_tcph());
if ( tsd.is_data_segment() )
trk.session->handle_data_on_syn(tsd);
return true;
bool TcpStateEstablished::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.normalizer.ecn_tracker(tsd.get_tcph());
return true;
}
bool TcpStateEstablished::syn_ack_sent(TcpSegmentDescriptor& tsd, TcpStreamTracker& trk)
{
- if ( trk.session->tcp_config->midstream_allowed(tsd.get_pkt()) )
+ // FIXIT-M there may be an issue when syn/ack from server is seen
+ // after ack from client which causes some tracker state variables to
+ // not be initialized... update_tracker_ack_sent may fix that but needs
+ // more testing
+ //trk.update_tracker_ack_sent( tsd );
+ Flow* flow = tsd.get_flow();
+ if ( !(flow->session_state & STREAM_STATE_ESTABLISHED) )
{
- // FIXIT-M there may be an issue when syn/ack from server is seen
- // after ack from client which causes some tracker state variables to
- // not be initialized... update_tracker_ack_sent may fix that but needs
- // more testing
- //trk.update_tracker_ack_sent( tsd );
- 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);
- }
+ /* 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() )
- trk.normalizer.ecn_tracker(tsd.get_tcph(), trk.session->tcp_config->require_3whs() );
+ trk.normalizer.ecn_tracker(tsd.get_tcph());
return true;
}
bool TcpStateFinWait1::syn_recv(TcpSegmentDescriptor& tsd, TcpStreamTracker& trk)
{
- trk.normalizer.ecn_tracker(tsd.get_tcph(), trk.session->tcp_config->require_3whs());
+ trk.normalizer.ecn_tracker(tsd.get_tcph());
if ( tsd.is_data_segment() )
trk.session->handle_data_on_syn(tsd);
return true;
bool TcpStateFinWait2::syn_recv(TcpSegmentDescriptor& tsd, TcpStreamTracker& trk)
{
- trk.normalizer.ecn_tracker(tsd.get_tcph(), trk.session->tcp_config->require_3whs());
+ trk.normalizer.ecn_tracker(tsd.get_tcph());
if ( tsd.is_data_segment() )
trk.session->handle_data_on_syn(tsd);
return true;
bool TcpStateLastAck::syn_recv(TcpSegmentDescriptor& tsd, TcpStreamTracker& trk)
{
- trk.normalizer.ecn_tracker(tsd.get_tcph(), trk.session->tcp_config->require_3whs());
+ trk.normalizer.ecn_tracker(tsd.get_tcph());
if ( tsd.is_data_segment() )
trk.session->handle_data_on_syn(tsd);
return true;
bool TcpStateListen::syn_recv(TcpSegmentDescriptor& tsd, TcpStreamTracker& trk)
{
trk.init_on_syn_recv(tsd);
- trk.normalizer.ecn_tracker(tsd.get_tcph(), trk.session->tcp_config->require_3whs());
+ trk.normalizer.ecn_tracker(tsd.get_tcph());
trk.session->set_pkt_action_flag(trk.normalizer.handle_paws(tsd) );
if ( tsd.is_data_segment() )
trk.session->handle_data_on_syn(tsd);
bool TcpStateListen::syn_ack_sent(TcpSegmentDescriptor& tsd, TcpStreamTracker& trk)
{
- if ( trk.session->is_midstream_allowed(tsd) )
- {
- trk.init_on_synack_sent(tsd);
- trk.normalizer.ecn_tracker(tsd.get_tcph(), trk.session->tcp_config->require_3whs());
- trk.session->init_new_tcp_session(tsd);
- }
- else if ( trk.session->tcp_config->require_3whs() )
- {
- trk.session->generate_no_3whs_event();
- return false;
- }
- return true;
-}
-
-bool TcpStateListen::ack_sent(TcpSegmentDescriptor&, TcpStreamTracker& trk)
-{
- if ( trk.session->tcp_config->require_3whs() )
- {
- trk.session->generate_no_3whs_event();
- return false;
- }
+ trk.init_on_synack_sent(tsd);
+ trk.normalizer.ecn_tracker(tsd.get_tcph());
+ trk.session->init_new_tcp_session(tsd);
return true;
}
bool TcpStateListen::data_seg_sent(TcpSegmentDescriptor& tsd, TcpStreamTracker& trk)
{
- if ( trk.session->is_midstream_allowed(tsd) )
- {
- Flow* flow = tsd.get_flow();
- flow->session_state |= STREAM_STATE_MIDSTREAM;
-
- if ( !Stream::is_midstream(flow) )
- {
- TcpStreamTracker* listener = tsd.get_listener();
- TcpStreamTracker* talker = tsd.get_talker();
-
- trk.normalizer.init(StreamPolicy::MISSED_3WHS, trk.session, listener, talker);
- trk.normalizer.init(StreamPolicy::MISSED_3WHS, trk.session, talker, listener);
- flow->set_session_flags(SSNFLAG_MIDSTREAM);
+ Flow* flow = tsd.get_flow();
+ flow->session_state |= STREAM_STATE_MIDSTREAM;
- if ( PacketTracer::is_active() )
- PacketTracer::log("Stream TCP did not see the complete 3-Way Handshake. "
- "Not all normalizations will be in effect\n");
+ if ( !Stream::is_midstream(flow) )
+ {
+ TcpStreamTracker* listener = tsd.get_listener();
+ TcpStreamTracker* talker = tsd.get_talker();
- DataBus::publish(Stream::get_pub_id(), StreamEventIds::TCP_MIDSTREAM, tsd.get_pkt());
- }
+ trk.normalizer.init(StreamPolicy::MISSED_3WHS, trk.session, listener, talker);
+ trk.normalizer.init(StreamPolicy::MISSED_3WHS, trk.session, talker, listener);
+ flow->set_session_flags(SSNFLAG_MIDSTREAM);
- trk.init_on_data_seg_sent(tsd);
- trk.session->init_new_tcp_session(tsd);
- }
- else if ( trk.session->tcp_config->require_3whs() )
- {
- trk.session->generate_no_3whs_event();
- return false;
- }
- return true;
-}
+ if ( PacketTracer::is_active() )
+ PacketTracer::log("Stream TCP did not see the complete 3-Way Handshake. "
+ "Not all normalizations will be in effect\n");
-bool TcpStateListen::data_seg_recv(TcpSegmentDescriptor& tsd, TcpStreamTracker& trk)
-{
- if ( trk.session->is_midstream_allowed(tsd) )
- {
- Flow* flow = tsd.get_flow();
- flow->session_state |= STREAM_STATE_MIDSTREAM;
- 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, !trk.normalizer.is_tcp_ips_enabled());
+ DataBus::publish(Stream::get_pub_id(), StreamEventIds::TCP_MIDSTREAM, tsd.get_pkt());
}
- else if ( trk.session->tcp_config->require_3whs() )
- {
- trk.session->generate_no_3whs_event();
- return false;
- }
- return true;
-}
-bool TcpStateListen::fin_sent(TcpSegmentDescriptor& tsd, TcpStreamTracker& trk)
-{
- if ( !trk.session->is_midstream_allowed(tsd) && trk.session->tcp_config->require_3whs() )
- {
- // FIXIT-L listen gets fin triggers 129:20 ??
- trk.session->generate_no_3whs_event();
- return false;
- }
+ trk.init_on_data_seg_sent(tsd);
+ trk.session->init_new_tcp_session(tsd);
return true;
}
-bool TcpStateListen::fin_recv(TcpSegmentDescriptor& tsd, TcpStreamTracker& trk)
+bool TcpStateListen::data_seg_recv(TcpSegmentDescriptor& tsd, TcpStreamTracker& trk)
{
- if ( trk.session->is_midstream_allowed(tsd) )
- {
- // FIXIT-L handle FIN on midstream
- }
- else if ( trk.session->tcp_config->require_3whs() )
- {
- trk.session->generate_no_3whs_event();
- return false;
- }
+ Flow* flow = tsd.get_flow();
+ flow->session_state |= STREAM_STATE_MIDSTREAM;
+ trk.init_on_data_seg_recv(tsd);
+ trk.normalizer.ecn_tracker(tsd.get_tcph());
+ trk.session->handle_data_segment(tsd, !trk.normalizer.is_tcp_ips_enabled());
return true;
}
bool syn_recv(TcpSegmentDescriptor&, TcpStreamTracker&) override;
bool syn_ack_sent(TcpSegmentDescriptor&, TcpStreamTracker&) override;
- bool ack_sent(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;
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());
+ trk.normalizer.ecn_tracker(tsd.get_tcph());
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.normalizer.ecn_tracker(tsd.get_tcph());
trk.set_tcp_state(TcpStreamTracker::TCP_ESTABLISHED);
return true;
}
return true;
}
-bool TcpStateNone::syn_ack_sent(TcpSegmentDescriptor&, TcpStreamTracker& trk)
-{
- trk.session->generate_no_3whs_event();
- return false;
-}
-
bool TcpStateNone::syn_ack_recv(TcpSegmentDescriptor& tsd, TcpStreamTracker& trk)
{
- if ( trk.session->is_midstream_allowed(tsd) )
- {
- trk.init_on_synack_recv(tsd);
- trk.normalizer.ecn_tracker(tsd.get_tcph(), trk.session->tcp_config->require_3whs());
- if ( tsd.is_data_segment() )
- trk.session->handle_data_segment(tsd, !trk.normalizer.is_tcp_ips_enabled());
- }
- else if ( trk.session->tcp_config->require_3whs() )
- {
- trk.session->generate_no_3whs_event();
- return false;
- }
- return true;
-}
-
-bool TcpStateNone::ack_sent(TcpSegmentDescriptor&, TcpStreamTracker& trk)
-{
- if ( trk.session->tcp_config->require_3whs() )
- {
- trk.session->generate_no_3whs_event();
- return false;
- }
+ trk.init_on_synack_recv(tsd);
+ trk.normalizer.ecn_tracker(tsd.get_tcph());
+ if ( tsd.is_data_segment() )
+ trk.session->handle_data_segment(tsd, !trk.normalizer.is_tcp_ips_enabled());
return true;
}
bool TcpStateNone::data_seg_sent(TcpSegmentDescriptor& tsd, TcpStreamTracker& trk)
{
- if ( trk.session->is_midstream_allowed(tsd) )
- {
- Flow* flow = tsd.get_flow();
- flow->session_state |= STREAM_STATE_MIDSTREAM;
-
- if ( !Stream::is_midstream(flow) )
- {
- TcpStreamTracker* listener = tsd.get_listener();
- TcpStreamTracker* talker = tsd.get_talker();
-
- trk.normalizer.init(StreamPolicy::MISSED_3WHS, trk.session, listener, talker);
- trk.normalizer.init(StreamPolicy::MISSED_3WHS, trk.session, talker, listener);
- flow->set_session_flags(SSNFLAG_MIDSTREAM);
-
- if ( PacketTracer::is_active() )
- PacketTracer::log("Stream TCP did not see the complete 3-Way Handshake. "
- "Not all normalizations will be in effect\n");
-
- DataBus::publish(Stream::get_pub_id(), StreamEventIds::TCP_MIDSTREAM, tsd.get_pkt());
- }
+ Flow* flow = tsd.get_flow();
+ flow->session_state |= STREAM_STATE_MIDSTREAM;
- trk.init_on_data_seg_sent(tsd);
- trk.session->init_new_tcp_session(tsd);
- }
- else if ( trk.session->tcp_config->require_3whs() )
+ if ( !Stream::is_midstream(flow) )
{
- trk.session->generate_no_3whs_event();
- return false;
- }
- return true;
-}
+ TcpStreamTracker* listener = tsd.get_listener();
+ TcpStreamTracker* talker = tsd.get_talker();
-bool TcpStateNone::data_seg_recv(TcpSegmentDescriptor& tsd, TcpStreamTracker& trk)
-{
- if ( trk.session->is_midstream_allowed(tsd) )
- {
- Flow* flow = tsd.get_flow();
- flow->session_state |= STREAM_STATE_MIDSTREAM;
- 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, !trk.normalizer.is_tcp_ips_enabled());
- }
- else if ( trk.session->tcp_config->require_3whs() )
- {
- trk.session->generate_no_3whs_event();
- return false;
- }
- return true;
-}
+ trk.normalizer.init(StreamPolicy::MISSED_3WHS, trk.session, listener, talker);
+ trk.normalizer.init(StreamPolicy::MISSED_3WHS, trk.session, talker, listener);
+ flow->set_session_flags(SSNFLAG_MIDSTREAM);
-bool TcpStateNone::fin_sent(TcpSegmentDescriptor& tsd, TcpStreamTracker& trk)
-{
- if ( trk.session->is_midstream_allowed(tsd) )
- {
- // FIXIT-M handle FIN on midstream
- }
- else if ( trk.session->tcp_config->require_3whs() )
- {
- trk.session->generate_no_3whs_event();
- return false;
- }
- return true;
-}
+ if ( PacketTracer::is_active() )
+ PacketTracer::log("Stream TCP did not see the complete 3-Way Handshake. "
+ "Not all normalizations will be in effect\n");
-bool TcpStateNone::fin_recv(TcpSegmentDescriptor& tsd, TcpStreamTracker& trk)
-{
- if ( trk.session->is_midstream_allowed(tsd) )
- {
- // FIXIT-M handle FIN on midstream
- }
- else if ( trk.session->tcp_config->require_3whs() )
- {
- trk.session->generate_no_3whs_event();
- return false;
+ DataBus::publish(Stream::get_pub_id(), StreamEventIds::TCP_MIDSTREAM, tsd.get_pkt());
}
+
+ trk.init_on_data_seg_sent(tsd);
+ trk.session->init_new_tcp_session(tsd);
return true;
}
-bool TcpStateNone::rst_sent(TcpSegmentDescriptor& tsd, TcpStreamTracker& trk)
+bool TcpStateNone::data_seg_recv(TcpSegmentDescriptor& tsd, TcpStreamTracker& trk)
{
- if ( trk.session->is_midstream_allowed(tsd) )
- {
- // FIXIT-M handle RST on midstream
- }
+ Flow* flow = tsd.get_flow();
+ flow->session_state |= STREAM_STATE_MIDSTREAM;
+ trk.init_on_data_seg_recv(tsd);
+ trk.normalizer.ecn_tracker(tsd.get_tcph());
+ trk.session->handle_data_segment(tsd, !trk.normalizer.is_tcp_ips_enabled());
return true;
}
TcpStateNone(TcpStateMachine&);
bool syn_sent(TcpSegmentDescriptor&, TcpStreamTracker&) override;
- bool syn_ack_sent(TcpSegmentDescriptor&, TcpStreamTracker&) override;
bool syn_ack_recv(TcpSegmentDescriptor&, TcpStreamTracker&) override;
- bool ack_sent(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;
bool TcpStateSynRecv::syn_sent(TcpSegmentDescriptor& tsd, TcpStreamTracker& trk)
{
trk.finish_server_init(tsd);
- trk.normalizer.ecn_tracker(tsd.get_tcph(), trk.session->tcp_config->require_3whs());
+ trk.normalizer.ecn_tracker(tsd.get_tcph());
trk.session->update_timestamp_tracking(tsd);
Flow* flow = tsd.get_flow();
if ( tsd.get_tcph()->are_flags_set(TH_ECE) &&
bool TcpStateSynRecv::syn_ack_sent(TcpSegmentDescriptor& tsd, TcpStreamTracker& trk)
{
trk.finish_server_init(tsd);
- trk.normalizer.ecn_tracker(tsd.get_tcph(), trk.session->tcp_config->require_3whs());
+ trk.normalizer.ecn_tracker(tsd.get_tcph());
return true;
}
{
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.normalizer.ecn_tracker(tsd.get_tcph());
trk.set_tcp_state(TcpStreamTracker::TCP_ESTABLISHED);
if ( tsd.is_data_segment() )
trk.session->handle_data_on_syn(tsd);
bool TcpStateSynRecv::ack_sent(TcpSegmentDescriptor& tsd, TcpStreamTracker& trk)
{
- if ( trk.session->tcp_config->midstream_allowed(tsd.get_pkt()) && trk.session->flow->two_way_traffic() )
+ if ( trk.session->flow->two_way_traffic() )
{
TcpStreamTracker::TcpState listener_state = tsd.get_listener()->get_tcp_state();
// Does this ACK finish 4-way handshake
bool TcpStateSynRecv::data_seg_sent(TcpSegmentDescriptor& tsd, TcpStreamTracker& trk)
{
- 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() )
{
- 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 )
{
- 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);
- }
+ trk.session->set_established(tsd);
+ trk.set_tcp_state(TcpStreamTracker::TCP_ESTABLISHED);
}
}
return true;
bool TcpStateTimeWait::syn_recv(TcpSegmentDescriptor& tsd, TcpStreamTracker& trk)
{
- trk.normalizer.ecn_tracker(tsd.get_tcph(), trk.session->tcp_config->require_3whs());
+ trk.normalizer.ecn_tracker(tsd.get_tcph());
if ( tsd.is_data_segment() )
trk.session->handle_data_on_syn(tsd);
str += " }";
ConfigLogger::log_value("asymmetric_ids", str.c_str());
ConfigLogger::log_flag("reassemble_async", !(flags & STREAM_CONFIG_NO_ASYNC_REASSEMBLY));
- ConfigLogger::log_limit("require_3whs", hs_timeout, -1, hs_timeout < 0 ? hs_timeout : -1);
ConfigLogger::log_value("session_timeout", session_timeout);
str = "{ count = ";
public:
TcpStreamConfig();
- bool require_3whs()
- {
- return hs_timeout >= 0;
- }
-
- bool midstream_allowed(snort::Packet* p)
- {
- if ( ( hs_timeout < 0 ) || ( p->pkth->ts.tv_sec - packet_first_time() < hs_timeout ) )
- return true;
-
- return false;
- }
-
void show() const;
StreamPolicy policy = StreamPolicy::OS_DEFAULT;
uint32_t max_consec_small_seg_size = STREAM_DEFAULT_MAX_SMALL_SEG_SIZE;
uint32_t paf_max = 16384;
- int hs_timeout = -1;
bool no_ack = false;
uint32_t embryonic_timeout = STREAM_DEFAULT_SSN_TIMEOUT;
TcpEvent tcp_event = TCP_MAX_EVENTS;
bool client_tracker;
- bool require_3whs = false;
bool rst_pkt_sent = false;
bool midstream_initial_ack_flush = false;
TcpSession::TcpSession( Flow* ) : Session( flow ) { }
TcpSession::~TcpSession() = default;
bool TcpSession::setup(Packet*){ return true; }
-void TcpSession::update_direction(char, SfIp const*, unsigned short){ }
-int TcpSession::process(Packet*){ return 0; }
-void TcpSession::restart(Packet*){ }
-void TcpSession::precheck(Packet*){ }
+void TcpSession::update_direction(char, SfIp const*, unsigned short) { }
+int TcpSession::process(Packet*) { return 0; }
+void TcpSession::restart(Packet*) { }
+bool TcpSession::precheck(Packet*) { return false; }
void TcpSession::clear(){ }
void TcpSession::cleanup(Packet* = nullptr){ }
bool TcpSession::add_alert(Packet*, unsigned int, unsigned int){ return true; }