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