1 //--------------------------------------------------------------------------
2 // Copyright (C) 2014-2021 Cisco and/or its affiliates. All rights reserved.
3 // Copyright (C) 2005-2013 Sourcefire, Inc.
4 //
5 // This program is free software; you can redistribute it and/or modify it
6 // under the terms of the GNU General Public License Version 2 as published
7 // by the Free Software Foundation.  You may not use, modify or distribute
8 // this program under any other version of the GNU General Public License.
9 //
10 // This program is distributed in the hope that it will be useful, but
11 // WITHOUT ANY WARRANTY; without even the implied warranty of
12 // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
13 // General Public License for more details.
14 //
15 // You should have received a copy of the GNU General Public License along
16 // with this program; if not, write to the Free Software Foundation, Inc.,
17 // 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA.
18 //--------------------------------------------------------------------------
19 
20 /*
21  * stream_tcp.c authors:
22  *     Martin Roesch <roesch@sourcefire.com>
23  *     Steven Sturges <ssturges@sourcefire.com>
24  *     Russ Combs <rcombs@sourcefire.com>
25  */
26 
27 /*
28  * FIXITs:
29  * - midstream ssn pickup (done, SAS 10/14/2005)
30  * - syn flood protection (done, SAS 9/27/2005)
31  *
32  * - review policy anomaly detection
33  *   + URG pointer (TODO)
34  *   + data on SYN (done, SAS 10/12/2005)
35  *   + data on FIN (done, SAS 10/12/2005)
36  *   + data after FIN (done, SAS 10/13/2005)
37  *   + window scaling/window size max (done, SAS 10/13/2005)
38  *   + PAWS, TCP Timestamps (done, SAS 10/12/2005)
39  *
40  * - session shutdown/Reset handling (done, SAS)
41  * - flush policy for Window/Consumed
42  * - limit on number of overlapping packets (done, SAS)
43  */
44 
45 #ifdef HAVE_CONFIG_H
46 #include "config.h"
47 #endif
48 
49 #include "tcp_session.h"
50 
51 #include "detection/detection_engine.h"
52 #include "detection/rules.h"
53 #include "log/log.h"
54 #include "memory/memory_cap.h"
55 #include "profiler/profiler.h"
56 #include "protocols/eth.h"
57 
58 #include "stream_tcp.h"
59 #include "tcp_ha.h"
60 #include "tcp_module.h"
61 #include "tcp_normalizers.h"
62 #include "tcp_reassemblers.h"
63 #include "tcp_segment_node.h"
64 #include "tcp_state_machine.h"
65 #include "tcp_trace.h"
66 
67 using namespace snort;
68 
sinit()69 void TcpSession::sinit()
70 {
71     TcpSegmentDescriptor::setup();
72     TcpSegmentNode::setup();
73 }
74 
sterm()75 void TcpSession::sterm()
76 {
77     TcpSegmentDescriptor::clear();
78     TcpSegmentNode::clear();
79 }
80 
TcpSession(Flow * f)81 TcpSession::TcpSession(Flow* f) : TcpStreamSession(f)
82 {
83     tsm = TcpStateMachine::get_instance();
84     splitter_init = false;
85 
86     client.session = this;
87     server.session = this;
88     tcpStats.instantiated++;
89 }
90 
~TcpSession()91 TcpSession::~TcpSession()
92 {
93     clear_session(true, false, false);
94 }
95 
setup(Packet *)96 bool TcpSession::setup(Packet*)
97 {
98     client.init_tcp_state();
99     server.init_tcp_state();
100     lws_init = tcp_init = false;
101     generate_3whs_alert = true;
102     cleaning = false;
103     splitter_init = false;
104 
105     pkt_action_mask = ACTION_NOTHING;
106     ecn = 0;
107     ingress_index = egress_index = 0;
108     ingress_group = egress_group = 0;
109     daq_flags = address_space_id = 0;
110 
111     tcp_config = get_tcp_cfg(flow->ssn_server);
112     flow->set_default_session_timeout(tcp_config->session_timeout, false);
113     set_os_policy();
114 
115     SESSION_STATS_ADD(tcpStats)
116     tcpStats.setups++;
117     return true;
118 }
119 
120 // FIXIT-M once TcpReassembler interface is abstract class move this to base class
restart(Packet * p)121 void TcpSession::restart(Packet* p)
122 {
123     // sanity check since this is called externally
124     assert(p);
125     assert(p->ptrs.tcph);
126     assert(p->flow == flow);
127 
128     DetectionEngine::onload(flow);
129     TcpStreamTracker* talker;
130     TcpStreamTracker* listener;
131 
132     if (p->is_from_server())
133     {
134         talker = &server;
135         listener = &client;
136     }
137     else
138     {
139         talker = &client;
140         listener = &server;
141     }
142 
143     if (p->dsize > 0)
144         listener->reassembler.flush_on_data_policy(p);
145 
146     if (p->ptrs.tcph->is_ack())
147         talker->reassembler.flush_on_ack_policy(p);
148 
149     tcpStats.restarts++;
150 }
151 
152 // if the flush_segments parameter is true and clear_session is being called while not in
153 // the context of a wire packet then the caller must create a packet context by calling
154 // DetectionEngine::set_next_packet() before calling clear_session
clear_session(bool free_flow_data,bool flush_segments,bool restart,Packet * p)155 void TcpSession::clear_session(bool free_flow_data, bool flush_segments, bool restart, Packet* p)
156 {
157     assert(!p or p->flow == flow);
158     if ( !tcp_init )
159     {
160         if ( lws_init )
161             tcpStats.no_pickups++;
162         return;
163     }
164 
165     lws_init = false;
166     tcp_init = false;
167     tcpStats.released++;
168 
169     if ( flush_segments )
170     {
171         client.reassembler.flush_queued_segments(flow, true, p);
172         server.reassembler.flush_queued_segments(flow, true, p);
173     }
174 
175     if ( p )
176     {
177         client.finalize_held_packet(p);
178         server.finalize_held_packet(p);
179     }
180     else
181     {
182         client.finalize_held_packet(flow);
183         server.finalize_held_packet(flow);
184     }
185 
186     client.reassembler.purge_segment_list();
187     server.reassembler.purge_segment_list();
188 
189     update_perf_base_state(TcpStreamTracker::TCP_CLOSED);
190 
191     if ( restart )
192     {
193         flow->restart(free_flow_data);
194         client.reassembler.reset_paf();
195         server.reassembler.reset_paf();
196     }
197     else
198     {
199         flow->clear(free_flow_data);
200         client.reassembler.clear_paf();
201         server.reassembler.clear_paf();
202     }
203 
204     set_splitter(true, nullptr);
205     set_splitter(false, nullptr);
206 
207     tel.log_internal_event(SESSION_EVENT_CLEAR);
208 }
209 
update_perf_base_state(char newState)210 void TcpSession::update_perf_base_state(char newState)
211 {
212     uint32_t session_flags = flow->get_session_flags();
213     bool fire_event = false;
214 
215     switch ( newState )
216     {
217     case TcpStreamTracker::TCP_SYN_SENT:
218         if ( !( session_flags & SSNFLAG_COUNTED_INITIALIZE ) )
219         {
220             tcpStats.sessions_initializing++;
221             session_flags |= SSNFLAG_COUNTED_INITIALIZE;
222         }
223         break;
224 
225     case TcpStreamTracker::TCP_ESTABLISHED:
226         if ( !( session_flags & SSNFLAG_COUNTED_ESTABLISH ) )
227         {
228             tcpStats.sessions_established++;
229             session_flags |= SSNFLAG_COUNTED_ESTABLISH;
230             fire_event = true;
231 
232             tel.log_internal_event(SESSION_EVENT_SETUP);
233             if ( ( session_flags & SSNFLAG_COUNTED_INITIALIZE )
234                 && !( session_flags & SSNFLAG_COUNTED_CLOSING ) )
235             {
236                 assert(tcpStats.sessions_initializing);
237                 tcpStats.sessions_initializing--;
238             }
239         }
240         break;
241 
242     case TcpStreamTracker::TCP_CLOSING:
243         if ( !( session_flags & SSNFLAG_COUNTED_CLOSING ) )
244         {
245             tcpStats.sessions_closing++;
246             session_flags |= SSNFLAG_COUNTED_CLOSING;
247 
248             if ( session_flags & SSNFLAG_COUNTED_ESTABLISH )
249             {
250                 assert(tcpStats.sessions_established);
251                 tcpStats.sessions_established--;
252             }
253             else if ( session_flags & SSNFLAG_COUNTED_INITIALIZE )
254             {
255                 assert(tcpStats.sessions_initializing);
256                 tcpStats.sessions_initializing--;
257             }
258         }
259         break;
260 
261     case TcpStreamTracker::TCP_CLOSED:
262         if ( !( session_flags & SSNFLAG_COUNTED_CLOSED ) )
263         {
264             session_flags |= SSNFLAG_COUNTED_CLOSED;
265             fire_event = true;
266 
267             if ( session_flags & SSNFLAG_COUNTED_CLOSING )
268             {
269                 assert(tcpStats.sessions_closing);
270                 tcpStats.sessions_closing--;
271             }
272             else if ( session_flags & SSNFLAG_COUNTED_ESTABLISH )
273             {
274                 assert(tcpStats.sessions_established);
275                 tcpStats.sessions_established--;
276             }
277             else if ( session_flags & SSNFLAG_COUNTED_INITIALIZE )
278             {
279                 assert(tcpStats.sessions_initializing);
280                 tcpStats.sessions_initializing--;
281             }
282         }
283         break;
284 
285     default:
286         break;
287     }
288 
289     flow->update_session_flags(session_flags);
290 
291     if ( fire_event )
292         DataBus::publish(FLOW_STATE_EVENT, nullptr, flow);
293 }
294 
flow_exceeds_config_thresholds(TcpSegmentDescriptor & tsd)295 bool TcpSession::flow_exceeds_config_thresholds(TcpSegmentDescriptor& tsd)
296 {
297     TcpStreamTracker* listener = tsd.get_listener();
298 
299     if ( listener->get_flush_policy() == STREAM_FLPOLICY_IGNORE )
300         return true;
301 
302     // FIXIT-M any discards must be counted and in many cases alerted as well
303     // (count all but alert at most once per flow)
304     // three cases in this function; look for others
305     if ( ( tcp_config->flags & STREAM_CONFIG_NO_ASYNC_REASSEMBLY ) && !flow->two_way_traffic() )
306         return true;
307 
308     if ( tcp_config->max_consec_small_segs )
309     {
310         if ( tsd.get_len() >= tcp_config->max_consec_small_seg_size )
311             listener->small_seg_count = 0;
312 
313         else if ( ++listener->small_seg_count == tcp_config->max_consec_small_segs )
314             tel.set_tcp_event(EVENT_MAX_SMALL_SEGS_EXCEEDED);
315     }
316 
317     if ( tcp_config->max_queued_bytes )
318     {
319         int32_t space_left =
320             tcp_config->max_queued_bytes - listener->reassembler.get_seg_bytes_total();
321 
322         if ( space_left < (int32_t)tsd.get_len() )
323         {
324             tcpStats.exceeded_max_bytes++;
325             bool inline_mode = tsd.is_policy_inline();
326             bool ret_val = true;
327 
328             if ( space_left > 0 )
329                 ret_val = !inline_mode; // For partial trim, reassemble only if we can force an inject
330             else
331                 space_left = 0;
332 
333             if ( inline_mode )
334             {
335                 if ( listener->max_queue_exceeded == MQ_NONE )
336                 {
337                     listener->max_queue_seq_nxt = tsd.get_seq() + space_left;
338                     listener->max_queue_exceeded = MQ_BYTES;
339                 }
340                 else
341                     (const_cast<tcp::TCPHdr*>(tsd.get_pkt()->ptrs.tcph))->set_seq(listener->max_queue_seq_nxt);
342             }
343             listener->normalizer.trim_win_payload(tsd, space_left, inline_mode);
344             return ret_val;
345         }
346         else if ( listener->max_queue_exceeded == MQ_BYTES )
347             listener->max_queue_exceeded = MQ_NONE;
348     }
349 
350     if ( tcp_config->max_queued_segs )
351     {
352         if ( listener->reassembler.get_seg_count() + 1 > tcp_config->max_queued_segs )
353         {
354             tcpStats.exceeded_max_segs++;
355             bool inline_mode = tsd.is_policy_inline();
356 
357             if ( inline_mode )
358             {
359                 if ( listener->max_queue_exceeded == MQ_NONE )
360                 {
361                     listener->max_queue_seq_nxt = tsd.get_seq();
362                     listener->max_queue_exceeded = MQ_SEGS;
363                 }
364                 else
365                     (const_cast<tcp::TCPHdr*>(tsd.get_pkt()->ptrs.tcph))->set_seq(listener->max_queue_seq_nxt);
366             }
367             listener->normalizer.trim_win_payload(tsd, 0, inline_mode);
368             return true;
369         }
370         else if ( listener->max_queue_exceeded == MQ_SEGS )
371             listener->max_queue_exceeded = MQ_NONE;
372     }
373 
374     return false;
375 }
376 
process_tcp_stream(TcpSegmentDescriptor & tsd)377 void TcpSession::process_tcp_stream(TcpSegmentDescriptor& tsd)
378 {
379     if ( tsd.are_packet_flags_set(PKT_IGNORE) )
380         return;
381 
382     set_packet_header_foo(tsd);
383 
384     if ( flow_exceeds_config_thresholds(tsd) )
385         return;
386 
387     TcpStreamTracker* listener = tsd.get_listener();
388 
389     listener->reassembler.queue_packet_for_reassembly(tsd);
390 
391     // Alert if overlap limit exceeded
392     if ( (tcp_config->overlap_limit)
393         && (listener->reassembler.get_overlap_count() > tcp_config->overlap_limit) )
394     {
395         tel.set_tcp_event(EVENT_EXCESSIVE_OVERLAP);
396         listener->reassembler.set_overlap_count(0);
397     }
398 }
399 
update_stream_order(const TcpSegmentDescriptor & tsd,bool aligned)400 void TcpSession::update_stream_order(const TcpSegmentDescriptor& tsd, bool aligned)
401 {
402     TcpStreamTracker* listener = tsd.get_listener();
403 
404     switch ( listener->order )
405     {
406     case 0:
407         if ( aligned )
408             tsd.set_packet_flags(PKT_STREAM_ORDER_OK);
409         else
410             listener->order = 1;
411         break;
412 
413     case 1:
414         if ( aligned )
415         {
416             tsd.set_packet_flags(PKT_STREAM_ORDER_OK);
417             listener->order = 2;
418         }
419         break;
420 
421     default:
422         if ( aligned )
423             tsd.set_packet_flags(PKT_STREAM_ORDER_OK);
424 
425         else
426         {
427             if ( !(flow->get_session_flags() & SSNFLAG_STREAM_ORDER_BAD) )
428                 flow->set_session_flags(SSNFLAG_STREAM_ORDER_BAD);
429             tsd.set_packet_flags(PKT_STREAM_ORDER_BAD);
430          }
431     }
432 }
433 
process_tcp_data(TcpSegmentDescriptor & tsd)434 int TcpSession::process_tcp_data(TcpSegmentDescriptor& tsd)
435 {
436     TcpStreamTracker* listener = tsd.get_listener();
437     const tcp::TCPHdr* tcph = tsd.get_tcph();
438     uint32_t seq = tsd.get_seq();
439 
440     if ( tcph->is_syn() )
441         seq++;
442 
443     /* we're aligned, so that's nice anyway */
444     if (seq == listener->rcv_nxt)
445     {
446         /* check if we're in the window */
447         if ( tcp_config->policy != StreamPolicy::OS_PROXY
448             and listener->normalizer.get_stream_window(tsd) == 0 )
449         {
450             listener->normalizer.trim_win_payload(tsd);
451             return STREAM_UNALIGNED;
452         }
453 
454         /* move the ack boundary up, this is the only way we'll accept data */
455         // FIXIT-L for ips, must move all the way to first hole or right end
456         listener->rcv_nxt = tsd.get_end_seq();
457 
458         if ( tsd.is_data_segment() )
459         {
460             update_stream_order(tsd, true);
461             process_tcp_stream(tsd);
462             return STREAM_ALIGNED;
463         }
464     }
465     else
466     {
467         // pkt is out of order, do some target-based shizzle here...
468         // NO, we don't want to simply bail.  Some platforms favor unack'd dup data over the
469         // original data.  Let the reassembly policy decide how to handle the overlapping data.
470         // See HP, Solaris, et al. for those that favor duplicate data over the original in
471         // some cases.
472 
473         /* check if we're in the window */
474         if ( tcp_config->policy != StreamPolicy::OS_PROXY
475             and listener->normalizer.get_stream_window(tsd) == 0 )
476         {
477             listener->normalizer.trim_win_payload(tsd);
478             return STREAM_UNALIGNED;
479         }
480         if ( tsd.is_data_segment() )
481         {
482             update_stream_order(tsd, false);
483             process_tcp_stream(tsd);
484         }
485     }
486 
487     return STREAM_UNALIGNED;
488 }
489 
set_os_policy()490 void TcpSession::set_os_policy()
491 {
492     StreamPolicy client_os_policy = flow->ssn_policy ?
493         static_cast<StreamPolicy>( flow->ssn_policy ) : tcp_config->policy;
494 
495     StreamPolicy server_os_policy = flow->ssn_policy ?
496         static_cast<StreamPolicy>( flow->ssn_policy ) : tcp_config->policy;
497 
498     client.normalizer.init(client_os_policy, this, &client, &server);
499     server.normalizer.init(server_os_policy, this, &server, &client);
500 
501     client.reassembler.init(this, &client, client_os_policy, false);
502     server.reassembler.init(this, &server, server_os_policy, true);
503 }
504 
505 // FIXIT-M this is no longer called (but should be)
506 #if 0
507 void TcpSession::swap_trackers()
508 {
509     uint32_t session_flags = flow->get_session_flags( );
510     if ( ( session_flags & SSNFLAG_CLIENT_SWAP ) && !( session_flags & SSNFLAG_CLIENT_SWAPPED ) )
511     {
512         TcpStreamTracker& trk = client;
513         client = server;
514         server = trk;
515 
516         SfIp ip = flow->client_ip;
517         flow->client_ip = flow->server_ip;
518         flow->server_ip = ip;
519 
520         uint16_t port = flow->client_port;
521         flow->client_port = flow->server_port;
522         flow->server_port = port;
523 
524         if ( !flow->two_way_traffic() )
525         {
526             if ( session_flags & SSNFLAG_SEEN_CLIENT )
527             {
528                 session_flags ^= SSNFLAG_SEEN_CLIENT;
529                 session_flags |= SSNFLAG_SEEN_SERVER;
530             }
531             else if ( session_flags & SSNFLAG_SEEN_SERVER )
532             {
533                 session_flags ^= SSNFLAG_SEEN_SERVER;
534                 session_flags |= SSNFLAG_SEEN_CLIENT;
535             }
536         }
537 
538         session_flags |= SSNFLAG_CLIENT_SWAPPED;
539         flow->update_session_flags(session_flags);
540     }
541 }
542 #endif
543 
init_session_on_syn(TcpSegmentDescriptor & tsd)544 void TcpSession::init_session_on_syn(TcpSegmentDescriptor& tsd)
545 {
546     server.init_on_syn_recv(tsd);
547     client.init_on_syn_sent(tsd);
548     init_new_tcp_session(tsd);
549     tcpStats.sessions_on_syn++;
550 }
551 
init_session_on_synack(TcpSegmentDescriptor & tsd)552 void TcpSession::init_session_on_synack(TcpSegmentDescriptor& tsd)
553 {
554     server.init_on_synack_sent(tsd);
555     client.init_on_synack_recv(tsd);
556     init_new_tcp_session(tsd);
557     tcpStats.sessions_on_syn_ack++;
558 }
559 
update_timestamp_tracking(TcpSegmentDescriptor & tsd)560 void TcpSession::update_timestamp_tracking(TcpSegmentDescriptor& tsd)
561 {
562     TcpStreamTracker* listener = tsd.get_listener();
563     TcpStreamTracker* talker = tsd.get_talker();
564 
565     talker->set_tf_flags(listener->normalizer.get_timestamp_flags());
566     if (listener->normalizer.handling_timestamps()
567         && SEQ_EQ(listener->rcv_nxt, tsd.get_seq()))
568     {
569         talker->set_ts_last_packet(tsd.get_packet_timestamp());
570         talker->set_ts_last(tsd.get_timestamp());
571     }
572 }
573 
handle_syn_on_reset_session(TcpSegmentDescriptor & tsd)574 bool TcpSession::handle_syn_on_reset_session(TcpSegmentDescriptor& tsd)
575 {
576     TcpStreamTracker* listener = tsd.get_listener();
577     TcpStreamTracker* talker = tsd.get_talker();
578     const tcp::TCPHdr* tcph = tsd.get_tcph();
579 
580     if ( (listener->get_tcp_state() == TcpStreamTracker::TCP_CLOSED)
581          || (talker->get_tcp_state() == TcpStreamTracker::TCP_CLOSED) )
582     {
583         // Listener previously issued a reset Talker is re-SYN-ing
584 
585         // FIXIT-M this leads to bogus 129:20
586         clear_session( true, true, true, tsd.get_pkt() );
587 
588         if ( tcph->is_rst() )
589         {
590             // FIXIT-M  In inline mode, only one of the normalizations can
591             // occur.  If the first normalization fires, there is nothing
592             // for the second normalization to do.  However, in inline-test
593             // mode, since nothing is actually normalized, both of the
594             // following functions report that they 'would' normalize.
595             // i.e., both functions increment their count even though only
596             // one function can ever perform a normalization.
597 
598             /* Got SYN/RST.  We're done. */
599             listener->normalizer.trim_syn_payload(tsd);
600             listener->normalizer.trim_rst_payload(tsd);
601             set_pkt_action_flag(ACTION_RST);
602             return false;
603         }
604         else if ( tcph->is_syn_only() )
605         {
606             flow->ssn_state.direction = FROM_CLIENT;
607             flow->session_state = STREAM_STATE_SYN;
608             flow->set_ttl(tsd.get_pkt(), true);
609             init_session_on_syn(tsd);
610             tcpStats.resyns++;
611             listener->normalizer.ecn_tracker(tcph, tcp_config->require_3whs());
612             flow->update_session_flags(SSNFLAG_SEEN_CLIENT);
613         }
614         else if ( tcph->is_syn_ack() )
615         {
616             if ( tcp_config->midstream_allowed(tsd.get_pkt()) )
617             {
618                 flow->ssn_state.direction = FROM_SERVER;
619                 flow->session_state = STREAM_STATE_SYN_ACK;
620                 flow->set_ttl(tsd.get_pkt(), false);
621                 init_session_on_synack(tsd);
622                 tcpStats.resyns++;
623             }
624 
625             listener->normalizer.ecn_tracker(tcph, tcp_config->require_3whs());
626             flow->update_session_flags(SSNFLAG_SEEN_SERVER);
627         }
628     }
629 
630     return true;
631 }
632 
update_ignored_session(TcpSegmentDescriptor & tsd)633 void TcpSession::update_ignored_session(TcpSegmentDescriptor& tsd)
634 {
635     if ( tsd.is_meta_ack_packet() )
636         return;
637 
638     Packet* p = tsd.get_pkt();
639     // FIXIT-L why flush here instead of just purge?
640     // s5_ignored_session() may be disabling detection too soon if we really want to flush
641     if ( Stream::ignored_flow(flow, p) )
642     {
643         TcpStreamTracker* listener = tsd.get_listener();
644         TcpStreamTracker* talker = tsd.get_talker();
645 
646         if ( talker && ( talker->get_tf_flags() & TF_FORCE_FLUSH ) )
647         {
648             flush_talker(p);
649             talker->clear_tf_flags(TF_FORCE_FLUSH);
650         }
651 
652         if ( listener && ( listener->get_tf_flags() & TF_FORCE_FLUSH ) )
653         {
654             flush_listener(p);
655             listener->clear_tf_flags(TF_FORCE_FLUSH);
656         }
657 
658         tsd.set_packet_flags(PKT_IGNORE);
659         set_pkt_action_flag(ACTION_DISABLE_INSPECTION);
660         tcpStats.ignored++;
661     }
662 }
663 
handle_data_on_syn(TcpSegmentDescriptor & tsd)664 void TcpSession::handle_data_on_syn(TcpSegmentDescriptor& tsd)
665 {
666     TcpStreamTracker* listener = tsd.get_listener();
667 
668     if ( !listener->normalizer.trim_syn_payload(tsd) )
669     {
670         handle_data_segment(tsd);
671         tel.set_tcp_event(EVENT_DATA_ON_SYN);
672     }
673 }
674 
update_session_on_rst(TcpSegmentDescriptor & tsd,bool flush)675 void TcpSession::update_session_on_rst(TcpSegmentDescriptor& tsd, bool flush)
676 {
677     Packet* p = tsd.get_pkt();
678 
679     if ( flush )
680     {
681         flush_listener(p, true);
682         flush_talker(p, true);
683         set_splitter(true, nullptr);
684         set_splitter(false, nullptr);
685     }
686 
687     tsd.get_talker()->update_on_rst_sent();
688 }
689 
update_paws_timestamps(TcpSegmentDescriptor & tsd)690 void TcpSession::update_paws_timestamps(TcpSegmentDescriptor& tsd)
691 {
692     TcpStreamTracker* listener = tsd.get_listener();
693     TcpStreamTracker* talker = tsd.get_talker();
694 
695     if ( listener->normalizer.handling_timestamps()
696         && SEQ_EQ(listener->r_win_base, tsd.get_seq()) )
697     {
698         if ( ((int32_t)(tsd.get_timestamp() - talker->get_ts_last()) >= 0  )
699             || (tsd.get_packet_timestamp() >= talker->get_ts_last_packet() + PAWS_24DAYS) )
700         {
701             talker->set_ts_last(tsd.get_timestamp());
702             talker->set_ts_last_packet(tsd.get_packet_timestamp());
703         }
704     }
705 }
706 
check_for_session_hijack(TcpSegmentDescriptor & tsd)707 void TcpSession::check_for_session_hijack(TcpSegmentDescriptor& tsd)
708 {
709     TcpStreamTracker* listener = tsd.get_listener();
710     TcpStreamTracker* talker = tsd.get_talker();
711 
712     Packet* p = tsd.get_pkt();
713     if ( !(p->pkth->flags & DAQ_PKT_FLAG_PRE_ROUTING) )
714     {
715         if ( p->is_eth() )
716         {
717             const eth::EtherHdr* eh = layer::get_eth_layer(p);
718             bool t_hijack = !talker->compare_mac_addresses(eh->ether_src);
719             bool l_hijack = !listener->compare_mac_addresses(eh->ether_dst);
720 
721             // if both seem hijacked then swap src/dst check, it that matches probably a tap
722             if ( (t_hijack & l_hijack) && (talker->compare_mac_addresses(eh->ether_dst) &&
723                  listener->compare_mac_addresses(eh->ether_src)) )
724                 return;
725 
726             uint32_t event_code = 0;
727 
728             if ( t_hijack )
729             {
730                 if ( p->is_from_client() )
731                     event_code |= EVENT_SESSION_HIJACK_CLIENT;
732                 else
733                     event_code |= EVENT_SESSION_HIJACK_SERVER;
734             }
735 
736             if ( l_hijack )
737             {
738                 if ( p->is_from_client() )
739                     event_code |= EVENT_SESSION_HIJACK_SERVER;
740                 else
741                     event_code |= EVENT_SESSION_HIJACK_CLIENT;
742             }
743 
744             if ( event_code )
745                 tel.set_tcp_event(event_code);
746         }
747     }
748 }
749 
check_for_window_slam(TcpSegmentDescriptor & tsd)750 bool TcpSession::check_for_window_slam(TcpSegmentDescriptor& tsd)
751 {
752     TcpStreamTracker* listener = tsd.get_listener();
753 
754     if ( tcp_config->max_window && (tsd.get_wnd() > tcp_config->max_window) )
755     {
756         /* got a window too large, alert! */
757         tel.set_tcp_event(EVENT_WINDOW_TOO_LARGE);
758         listener->normalizer.packet_dropper(tsd, NORM_TCP_BLOCK);
759         set_pkt_action_flag(ACTION_BAD_PKT);
760         return true;
761     }
762     else if ( tsd.is_packet_from_client() && (tsd.get_wnd() <= SLAM_MAX)
763         && (tsd.get_ack() == listener->get_iss() + 1)
764         && !(tsd.get_tcph()->is_fin() || tsd.get_tcph()->is_rst())
765         && !(flow->get_session_flags() & SSNFLAG_MIDSTREAM))
766     {
767         /* got a window slam alert! */
768         tel.set_tcp_event(EVENT_WINDOW_SLAM);
769         listener->normalizer.packet_dropper(tsd, NORM_TCP_BLOCK);
770         set_pkt_action_flag(ACTION_BAD_PKT);
771         return true;
772     }
773 
774     return false;
775 }
776 
mark_packet_for_drop(TcpSegmentDescriptor & tsd)777 void TcpSession::mark_packet_for_drop(TcpSegmentDescriptor& tsd)
778 {
779 
780     tsd.get_listener()->normalizer.packet_dropper(tsd, NORM_TCP_BLOCK);
781     set_pkt_action_flag(ACTION_BAD_PKT);
782 }
783 
handle_data_segment(TcpSegmentDescriptor & tsd)784 void TcpSession::handle_data_segment(TcpSegmentDescriptor& tsd)
785 {
786     TcpStreamTracker* listener = tsd.get_listener();
787     TcpStreamTracker* talker = tsd.get_talker();
788 
789     // if this session started midstream we may need to init the listener's base seq #
790     if ( listener->reinit_seg_base )
791     {
792         listener->reassembler.set_seglist_base_seq(tsd.get_seq());
793         listener->reinit_seg_base = false;
794     }
795 
796     if ( TcpStreamTracker::TCP_CLOSED != talker->get_tcp_state() )
797     {
798         uint8_t tcp_options_len = tsd.get_tcph()->options_len();
799         if ( tsd.is_packet_from_client() )
800             client.set_tcp_options_len(tcp_options_len);
801         else
802             server.set_tcp_options_len(tcp_options_len);
803 
804         // FIXIT-M move this to normalizer base class, handle OS_PROXY in derived class
805         if ( tcp_config->policy != StreamPolicy::OS_PROXY )
806         {
807             // drop packet if sequence num is invalid
808             if ( !listener->is_segment_seq_valid(tsd) )
809             {
810                 tcpStats.invalid_seq_num++;
811                 listener->normalizer.trim_win_payload(tsd);
812                 return;
813             }
814 
815             // these normalizations can't be done if we missed setup. and
816             // window is zero in one direction until we've seen both sides.
817             if ( !(flow->get_session_flags() & SSNFLAG_MIDSTREAM) && flow->two_way_traffic() )
818             {
819                 // trim to fit in listener's window and mss
820                 listener->normalizer.trim_win_payload
821                     (tsd, (listener->r_win_base + listener->get_snd_wnd() - listener->rcv_nxt));
822 
823                 if ( listener->get_mss() )
824                     listener->normalizer.trim_mss_payload(tsd, listener->get_mss());
825 
826                 listener->normalizer.ecn_stripper(tsd);
827             }
828         }
829 
830         process_tcp_data(tsd);
831     }
832 
833     listener->reassembler.flush_on_data_policy(tsd.get_pkt());
834 }
835 
get_talker_state(TcpSegmentDescriptor & tsd)836 TcpStreamTracker::TcpState TcpSession::get_talker_state(TcpSegmentDescriptor& tsd)
837 {
838     return tsd.get_talker()->get_tcp_state();
839 }
840 
get_listener_state(TcpSegmentDescriptor & tsd)841 TcpStreamTracker::TcpState TcpSession::get_listener_state(TcpSegmentDescriptor& tsd)
842 {
843     return tsd.get_listener()->get_tcp_state();
844 }
845 
check_for_repeated_syn(TcpSegmentDescriptor & tsd)846 void TcpSession::check_for_repeated_syn(TcpSegmentDescriptor& tsd)
847 {
848     TcpStreamTracker* listener = tsd.get_listener();
849     TcpStreamTracker* talker = tsd.get_talker();
850     uint32_t action = ACTION_NOTHING;
851 
852     if ( !SEQ_EQ(tsd.get_seq(), talker->get_iss()) and
853         listener->normalizer.packet_dropper(tsd, NORM_TCP_BLOCK) )
854     {
855         set_pkt_action_flag(ACTION_BAD_PKT);
856     }
857     else if ( talker->get_tcp_state() >= TcpStreamTracker::TCP_ESTABLISHED and
858         talker->get_tcp_state() < TcpStreamTracker::TCP_CLOSED )
859     {
860         action = listener->normalizer.handle_repeated_syn(tsd);
861     }
862 
863     if (action != ACTION_NOTHING)
864     {
865         tel.set_tcp_event(EVENT_SYN_ON_EST);
866         pkt_action_mask |= action;
867     }
868 }
869 
flush_server(Packet * p)870 void TcpSession::flush_server(Packet* p)
871 {
872     if ( !tcp_init )
873         return;
874 
875     server.set_tf_flags(TF_FORCE_FLUSH);
876 
877     // don't flush if rebuilt packet, that would overwrite the packet being processed.
878     if ( p->packet_flags & PKT_REBUILT_STREAM )
879         return; // We'll check & clear the TF_FORCE_FLUSH next time through
880 
881     // Need to convert the addresses to network order
882     if ( server.reassembler.flush_stream(p, PKT_FROM_SERVER) )
883         server.reassembler.purge_flushed_ackd();
884 
885     server.clear_tf_flags(TF_FORCE_FLUSH);
886 }
887 
flush_client(Packet * p)888 void TcpSession::flush_client(Packet* p)
889 {
890     if ( !tcp_init )
891         return;
892 
893     client.set_tf_flags(TF_FORCE_FLUSH);
894 
895     // If rebuilt packet, don't flush now because we'll overwrite the packet being processed.
896     if ( p->packet_flags & PKT_REBUILT_STREAM )
897         return;         // TF_FORCE_FLUSH checked & cleared next time through
898 
899     if ( client.reassembler.flush_stream(p, PKT_FROM_CLIENT) )
900         client.reassembler.purge_flushed_ackd();
901 
902     client.clear_tf_flags(TF_FORCE_FLUSH);
903 }
904 
flush_tracker(TcpStreamTracker & tracker,Packet * p,uint32_t dir,bool final_flush)905 void TcpSession::flush_tracker(
906     TcpStreamTracker& tracker, Packet* p, uint32_t dir, bool final_flush)
907 {
908     if ( final_flush && (!tracker.get_splitter() || !tracker.get_splitter()->finish(flow)) )
909          return;
910 
911      tracker.set_tf_flags(TF_FORCE_FLUSH);
912      if ( tracker.reassembler.flush_stream(p, dir, final_flush) )
913          tracker.reassembler.purge_flushed_ackd();
914 
915      tracker.clear_tf_flags(TF_FORCE_FLUSH);
916 }
917 
flush_listener(Packet * p,bool final_flush)918 void TcpSession::flush_listener(Packet* p, bool final_flush)
919 {
920     // direction of flush is the data from the opposite side
921     if ( p->is_from_server() )
922         flush_tracker( client, p, PKT_FROM_SERVER, final_flush);
923     else if ( p->is_from_client() )
924         flush_tracker( server, p, PKT_FROM_CLIENT, final_flush);
925 }
926 
flush_talker(Packet * p,bool final_flush)927 void TcpSession::flush_talker(Packet* p, bool final_flush)
928 {
929     // direction of flush is the data from the opposite side
930     if ( p->is_from_server() )
931         flush_tracker( server, p, PKT_FROM_CLIENT, final_flush);
932     else if ( p->is_from_client() )
933         flush_tracker( client, p, PKT_FROM_SERVER, final_flush);
934 }
935 
936 // if not in the context of a wire packet the caller must create a packet context
937 // by calling DetectionEngine::set_next_packet() before calling TcpSession::flush()
flush()938 void TcpSession::flush()
939 {
940     if ( !tcp_init )
941         return;
942 
943     //FIXIT-L Cleanup tcp_init and lws_init as they have some side effect in TcpSession::clear_session
944     lws_init = false;
945     tcp_init = false;
946 
947     client.reassembler.flush_queued_segments(flow, true);
948     server.reassembler.flush_queued_segments(flow, true);
949 
950     lws_init = true;
951     tcp_init = true;
952 }
953 
set_extra_data(Packet * p,uint32_t xid)954 void TcpSession::set_extra_data(Packet* p, uint32_t xid)
955 {
956     TcpStreamTracker& st = p->ptrs.ip_api.get_src()->equals(flow->client_ip) ? server : client;
957     st.reassembler.set_xtradata_mask(st.reassembler.get_xtradata_mask() | BIT(xid));
958 }
959 
set_window_scale(TcpSegmentDescriptor & tsd)960 static inline void set_window_scale(TcpSegmentDescriptor& tsd)
961 {
962     // scale the window.  Only if BOTH client and server specified wscale option as part
963     // of 3-way handshake.  This is per RFC 1323.
964     if ( (tsd.get_talker()->get_tf_flags() & TF_WSCALE)
965          && (tsd.get_listener()->get_tf_flags() & TF_WSCALE) )
966     {
967         tsd.scale_wnd(tsd.get_talker()->get_wscale());
968     }
969 }
970 
check_events_and_actions(const TcpSegmentDescriptor & tsd)971 void TcpSession::check_events_and_actions(const TcpSegmentDescriptor& tsd)
972 {
973     tel.log_tcp_events();
974 
975     if ( tsd.is_meta_ack_packet() )
976         return;
977 
978     Packet* p = tsd.get_pkt();
979     if ( !(pkt_action_mask & ACTION_LWSSN_CLOSED) )
980     {
981         flow->markup_packet_flags(p);
982         flow->set_expire(p, flow->default_session_timeout);
983     }
984     else
985         TcpHAManager::process_deletion(*flow);
986 
987     if ( pkt_action_mask & ACTION_DISABLE_INSPECTION )
988         DetectionEngine::disable_all(p);
989 }
990 
ignore_this_packet(Packet * p)991 bool TcpSession::ignore_this_packet(Packet* p)
992 {
993     if ( no_ack_mode_enabled() and p->is_retry() )
994     {
995         // Don't need to process a retry packet through stream again,
996         // just make sure the retransmit handler is called so that
997         // we do things like update file inspection.
998         flow->call_handlers(p, false);
999         return true;
1000     }
1001 
1002     if ( Stream::blocked_flow(p) )
1003         return true;
1004 
1005     if ( flow->ssn_state.ignore_direction != SSN_DIR_NONE )
1006     {
1007         server.set_flush_policy(STREAM_FLPOLICY_IGNORE);
1008         client.set_flush_policy(STREAM_FLPOLICY_IGNORE);
1009         return true;
1010     }
1011 
1012     return false;
1013 }
1014 
cleanup_session_if_expired(Packet * p)1015 void TcpSession::cleanup_session_if_expired(Packet* p)
1016 {
1017     // Check if the session is expired. Should be done before we do something with
1018     // the packet...Insert a packet, or handle state change SYN, FIN, RST, etc.
1019     if ( Stream::expired_flow(flow, p) )
1020     {
1021         /* Session is timed out, if also reset then restart, otherwise clear */
1022         if ( flow->get_session_flags() & SSNFLAG_RESET )
1023             clear_session(true, true, true, p);
1024         else
1025             clear_session(true, true, false, p);
1026 
1027         tcpStats.timeouts++;
1028         TcpHAManager::process_deletion(*flow);
1029     }
1030 }
1031 
precheck(Packet * p)1032 void TcpSession::precheck(Packet* p)
1033 {
1034     // Check if the session is expired. Should be done before we do something with
1035     // the packet...Insert a packet, or handle state change SYN, FIN, RST, etc.
1036     cleanup_session_if_expired(p);
1037 }
1038 
init_tcp_packet_analysis(TcpSegmentDescriptor & tsd)1039 void TcpSession::init_tcp_packet_analysis(TcpSegmentDescriptor& tsd)
1040 {
1041     if ( !splitter_init and tsd.is_data_segment() )
1042     {
1043         if ( !(tcp_config->flags & STREAM_CONFIG_NO_REASSEMBLY) )
1044         {
1045             client.set_splitter(tsd.get_flow());
1046             server.set_splitter(tsd.get_flow());
1047 
1048             client.init_flush_policy();
1049             server.init_flush_policy();
1050 
1051             set_no_ack(tcp_config->no_ack);
1052         }
1053 
1054         splitter_init = true;
1055     }
1056 
1057     pkt_action_mask = ACTION_NOTHING;
1058     tel.clear_tcp_events();
1059     // process thru state machine...talker first
1060     // When in no-ack mode, don't trust ACK numbers. Set the ACK value
1061     // as if the last packet in the other direction was ACK'd.
1062     // FIXIT-M: The snd_nxt and snd_una checks are only needed because
1063     // the snd_nxt value isn't valid for SYN/ACK packet. Can remove those
1064     // checks if that is fixed.
1065     if ( tsd.is_packet_from_client() )
1066     {
1067         update_session_on_client_packet(tsd);
1068 
1069         if ( no_ack_mode_enabled() and (server.get_snd_nxt() or server.get_snd_una()) )
1070             tsd.set_ack(server.get_snd_nxt());
1071     }
1072     else
1073     {
1074         update_session_on_server_packet(tsd);
1075 
1076         if ( no_ack_mode_enabled() and (client.get_snd_nxt() or client.get_snd_una()) )
1077             tsd.set_ack(client.get_snd_nxt());
1078     }
1079 
1080     update_ignored_session(tsd);
1081     set_window_scale(tsd);
1082 }
1083 
validate_packet_established_session(TcpSegmentDescriptor & tsd)1084 bool TcpSession::validate_packet_established_session(TcpSegmentDescriptor& tsd)
1085 {
1086     TcpStreamTracker* listener = tsd.get_listener();
1087 
1088     if ( tsd.is_policy_inline() )
1089        if ( tsd.get_tcph()->is_ack() && !listener->is_ack_valid(tsd.get_ack()) )
1090        {
1091            listener->normalizer.packet_dropper(tsd, NORM_TCP_BLOCK);
1092            set_pkt_action_flag(ACTION_BAD_PKT);
1093        }
1094 
1095     if ( !tsd.is_meta_ack_packet() )
1096         set_pkt_action_flag(listener->normalizer.handle_paws(tsd));
1097 
1098     return ( pkt_action_mask & ACTION_BAD_PKT ) ? false : true;
1099 }
1100 
process_tcp_packet(TcpSegmentDescriptor & tsd,const Packet * p)1101 int TcpSession::process_tcp_packet(TcpSegmentDescriptor& tsd, const Packet* p)
1102 {
1103     tsm->eval(tsd);
1104     check_events_and_actions(tsd);
1105 
1106     S5TraceTCP(tsd, p);
1107 
1108     return ACTION_NOTHING;
1109 }
1110 
process(Packet * p)1111 int TcpSession::process(Packet* p)
1112 {
1113     Profile profile(s5TcpPerfStats);
1114     assert(flow->ssn_server && flow->pkt_type == PktType::TCP);
1115 
1116     if ( ignore_this_packet(p) )
1117         return ACTION_NOTHING;
1118 
1119     TcpSegmentDescriptor tsd(flow, p, tel);
1120     init_tcp_packet_analysis(tsd);
1121 
1122     // check for and process meta-ack info first if present, the current listener is the
1123     // talker for the meta-ack...
1124     DAQ_PktTcpAckData_t* tcp_mack = (DAQ_PktTcpAckData_t*)p->daq_msg->meta[DAQ_PKT_META_TCP_ACK_DATA];
1125     if ( tcp_mack )
1126     {
1127         TcpSegmentDescriptor ma_tsd(flow, p, tcp_mack->tcp_ack_seq_num, tcp_mack->tcp_window_size);
1128         init_tcp_packet_analysis(ma_tsd);
1129         process_tcp_packet(ma_tsd, p);
1130         tcpStats.meta_acks++;
1131     }
1132 
1133     if ( p->context->conf->is_address_anomaly_check_enabled() )
1134         check_for_session_hijack(tsd);
1135 
1136     if ( ( flow->get_session_flags() & SSNFLAG_RESET ) && tsd.get_tcph()->is_syn()
1137             && !handle_syn_on_reset_session(tsd) )
1138         return ACTION_NOTHING;
1139 
1140     return process_tcp_packet(tsd, p);
1141 }
1142