1 //--------------------------------------------------------------------------
2 // Copyright (C) 2015-2021 Cisco and/or its affiliates. All rights reserved.
3 //
4 // This program is free software; you can redistribute it and/or modify it
5 // under the terms of the GNU General Public License Version 2 as published
6 // by the Free Software Foundation. You may not use, modify or distribute
7 // this program under any other version of the GNU General Public License.
8 //
9 // This program is distributed in the hope that it will be useful, but
10 // WITHOUT ANY WARRANTY; without even the implied warranty of
11 // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
12 // General Public License for more details.
13 //
14 // You should have received a copy of the GNU General Public License along
15 // with this program; if not, write to the Free Software Foundation, Inc.,
16 // 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
17 //--------------------------------------------------------------------------
18
19 // tcp_state_fin_wait2.cc author davis mcpherson <davmcphe@cisco.com>
20 // Created on: Aug 5, 2015
21
22 #ifdef HAVE_CONFIG_H
23 #include "config.h"
24 #endif
25
26 #include "tcp_state_fin_wait2.h"
27
28 #include "tcp_normalizers.h"
29 #include "tcp_session.h"
30
31 using namespace snort;
32
TcpStateFinWait2(TcpStateMachine & tsm)33 TcpStateFinWait2::TcpStateFinWait2(TcpStateMachine& tsm) :
34 TcpStateHandler(TcpStreamTracker::TCP_FIN_WAIT2, tsm)
35 { }
36
syn_sent(TcpSegmentDescriptor & tsd,TcpStreamTracker & trk)37 bool TcpStateFinWait2::syn_sent(TcpSegmentDescriptor& tsd, TcpStreamTracker& trk)
38 {
39 trk.session->check_for_repeated_syn(tsd);
40 return true;
41 }
42
syn_recv(TcpSegmentDescriptor & tsd,TcpStreamTracker & trk)43 bool TcpStateFinWait2::syn_recv(TcpSegmentDescriptor& tsd, TcpStreamTracker& trk)
44 {
45 trk.normalizer.ecn_tracker(tsd.get_tcph(), trk.session->tcp_config->require_3whs());
46 if ( tsd.is_data_segment() )
47 trk.session->handle_data_on_syn(tsd);
48 return true;
49 }
50
syn_ack_recv(TcpSegmentDescriptor & tsd,TcpStreamTracker & trk)51 bool TcpStateFinWait2::syn_ack_recv(TcpSegmentDescriptor& tsd, TcpStreamTracker& trk)
52 {
53 if ( tsd.is_data_segment() )
54 trk.session->handle_data_on_syn(tsd);
55 return true;
56 }
57
ack_sent(TcpSegmentDescriptor & tsd,TcpStreamTracker & trk)58 bool TcpStateFinWait2::ack_sent(TcpSegmentDescriptor& tsd, TcpStreamTracker& trk)
59 {
60 trk.update_tracker_ack_sent(tsd);
61 return true;
62 }
63
ack_recv(TcpSegmentDescriptor & tsd,TcpStreamTracker & trk)64 bool TcpStateFinWait2::ack_recv(TcpSegmentDescriptor& tsd, TcpStreamTracker& trk)
65 {
66 if ( SEQ_GT(tsd.get_ack(), trk.get_snd_nxt() ) )
67 {
68 trk.session->tel.set_tcp_event(EVENT_BAD_ACK);
69 trk.normalizer.packet_dropper(tsd, NORM_TCP_BLOCK);
70 trk.session->set_pkt_action_flag(ACTION_BAD_PKT);
71 }
72 else
73 trk.update_tracker_ack_recv(tsd);
74
75 return true;
76 }
77
data_seg_sent(TcpSegmentDescriptor & tsd,TcpStreamTracker & trk)78 bool TcpStateFinWait2::data_seg_sent(TcpSegmentDescriptor& tsd, TcpStreamTracker& trk)
79 {
80 trk.update_tracker_ack_sent(tsd);
81 // data on a segment when we shouldn't be sending data any more alert!
82 trk.session->tel.set_tcp_event(EVENT_DATA_ON_CLOSED);
83 trk.session->mark_packet_for_drop(tsd);
84 return true;
85 }
86
data_seg_recv(TcpSegmentDescriptor & tsd,TcpStreamTracker & trk)87 bool TcpStateFinWait2::data_seg_recv(TcpSegmentDescriptor& tsd, TcpStreamTracker& trk)
88 {
89 if ( SEQ_GT(tsd.get_ack(), trk.get_snd_nxt() ) )
90 {
91 trk.session->tel.set_tcp_event(EVENT_BAD_ACK);
92 trk.normalizer.packet_dropper(tsd, NORM_TCP_BLOCK);
93 trk.session->set_pkt_action_flag(ACTION_BAD_PKT);
94 }
95 else
96 {
97 trk.update_tracker_ack_recv(tsd);
98 trk.session->handle_data_segment(tsd);
99 }
100
101 return true;
102 }
103
fin_recv(TcpSegmentDescriptor & tsd,TcpStreamTracker & trk)104 bool TcpStateFinWait2::fin_recv(TcpSegmentDescriptor& tsd, TcpStreamTracker& trk)
105 {
106 Flow* flow = tsd.get_flow();
107
108 trk.update_tracker_ack_recv(tsd);
109 if ( trk.update_on_fin_recv(tsd) )
110 {
111 trk.perform_fin_recv_flush(tsd);
112
113 if ( !flow->two_way_traffic() )
114 trk.set_tf_flags(TF_FORCE_FLUSH);
115
116 trk.set_tcp_state(TcpStreamTracker::TCP_TIME_WAIT);
117 }
118 return true;
119 }
120
rst_recv(TcpSegmentDescriptor & tsd,TcpStreamTracker & trk)121 bool TcpStateFinWait2::rst_recv(TcpSegmentDescriptor& tsd, TcpStreamTracker& trk)
122 {
123 if ( trk.update_on_rst_recv(tsd) )
124 {
125 trk.session->update_session_on_rst(tsd, true);
126 trk.session->update_perf_base_state(TcpStreamTracker::TCP_CLOSING);
127 trk.session->set_pkt_action_flag(ACTION_RST);
128 tsd.get_flow()->session_state |= STREAM_STATE_CLOSED;
129 }
130
131 return true;
132 }
133
do_pre_sm_packet_actions(TcpSegmentDescriptor & tsd,TcpStreamTracker & trk)134 bool TcpStateFinWait2::do_pre_sm_packet_actions(TcpSegmentDescriptor& tsd, TcpStreamTracker& trk)
135 {
136 return trk.session->validate_packet_established_session(tsd);
137 }
138
do_post_sm_packet_actions(TcpSegmentDescriptor & tsd,TcpStreamTracker & trk)139 bool TcpStateFinWait2::do_post_sm_packet_actions(TcpSegmentDescriptor& tsd, TcpStreamTracker& trk)
140 {
141 trk.session->update_paws_timestamps(tsd);
142 trk.session->check_for_window_slam(tsd);
143 return true;
144 }
145
146