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