1 /* $Id$ */
2 /****************************************************************************
3  *
4  * Copyright (C) 2014-2021 Cisco and/or its affiliates. All rights reserved.
5  * Copyright (C) 2005-2013 Sourcefire, Inc.
6  *
7  * This program is free software; you can redistribute it and/or modify
8  * it under the terms of the GNU General Public License Version 2 as
9  * published by the Free Software Foundation.  You may not use, modify or
10  * distribute this program under any other version of the GNU General
11  * Public License.
12  *
13  * This program is distributed in the hope that it will be useful,
14  * but WITHOUT ANY WARRANTY; without even the implied warranty of
15  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
16  * GNU General Public License for more details.
17  *
18  * You should have received a copy of the GNU General Public License
19  * along with this program; if not, write to the Free Software
20  * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA.
21  *
22  ****************************************************************************/
23 
24 /**
25  * @file    snort_stream_tcp.c
26  * @author  Martin Roesch <roesch@sourcefire.com>
27  * @author  Steven Sturges <ssturges@sourcefire.com>
28  *
29  */
30 
31 /*
32  * TODOs:
33  * - midstream ssn pickup (done, SAS 10/14/2005)
34  * - syn flood protection (done, SAS 9/27/2005)
35  *
36  * - review policy anomaly detection
37  *   + URG pointer (TODO)
38  *   + data on SYN (done, SAS 10/12/2005)
39  *   + data on FIN (done, SAS 10/12/2005)
40  *   + data after FIN (done, SAS 10/13/2005)
41  *   + window scaling/window size max (done, SAS 10/13/2005)
42  *   + PAWS, TCP Timestamps (done, SAS 10/12/2005)
43  *
44  * - session shutdown/Reset handling (done, SAS)
45  * - flush policy for Window/Consumed
46  * - limit on number of overlapping packets (done, SAS)
47  */
48 
49 #include <errno.h>
50 #include <assert.h>
51 
52 #ifdef HAVE_CONFIG_H
53 #include "config.h"
54 #endif
55 
56 #include "perf.h"
57 #include "sf_types.h"
58 #include "snort_debug.h"
59 #include "detect.h"
60 #include "plugbase.h"
61 #include "mstring.h"
62 #include "sfxhash.h"
63 #include "util.h"
64 #include "sflsq.h"
65 #include "snort_bounds.h"
66 #include "generators.h"
67 #include "event_queue.h"
68 #include "snort.h"
69 #include "memory_stats.h"
70 #include "parser/IpAddrSet.h"
71 
72 #include "decode.h"
73 #include "encode.h"
74 #include "log.h"
75 #include "active.h"
76 #include "spp_normalize.h"
77 
78 #include "sf_sdlist.h"
79 
80 #include "spp_session.h"
81 #include "session_api.h"
82 #include "snort_session.h"
83 
84 #include "stream_common.h"
85 #include "snort_stream_tcp.h"
86 #include "stream_api.h"
87 #include "session_expect.h"
88 #include "stream_paf.h"
89 #include "stream5_ha.h"
90 
91 #ifdef TARGET_BASED
92 #include "sftarget_protocol_reference.h"
93 #include "sftarget_hostentry.h"
94 #endif
95 
96 #include "profiler.h"
97 
98 #include "ipv6_port.h"
99 #include "sf_iph.h"
100 
101 #include "sp_preprocopt.h"
102 #include "sfPolicy.h"
103 #include "sfActionQueue.h"
104 #include "detection_util.h"
105 #include "file_api.h"
106 
107 #ifdef REG_TEST
108 #include "reg_test.h"
109 #include <stdio.h>
110 #endif
111 
112 // port reassembly registration utils
113 static void StreamCreateReassemblyPortList( void );
114 static void StreamDestoryReassemblyPortList( void );
115 
116 #ifdef PERF_PROFILING
117 PreprocStats s5TcpPerfStats;
118 PreprocStats s5TcpNewSessPerfStats;
119 PreprocStats s5TcpStatePerfStats;
120 PreprocStats s5TcpDataPerfStats;
121 PreprocStats s5TcpInsertPerfStats;
122 PreprocStats s5TcpPAFPerfStats;
123 PreprocStats s5TcpFlushPerfStats;
124 PreprocStats s5TcpBuildPacketPerfStats;
125 PreprocStats s5TcpProcessRebuiltPerfStats;
126 
127 PreprocStats streamSizePerfStats;
128 PreprocStats streamReassembleRuleOptionPerfStats;
129 extern PreprocStats preprocRuleOptionPerfStats;
130 
131 #endif
132 
133 /*  M A C R O S  **************************************************/
134 
135 /* TCP flags */
136 #define TH_FIN  0x01
137 #define TH_SYN  0x02
138 #define TH_RST  0x04
139 #define TH_PUSH 0x08
140 #define TH_ACK  0x10
141 #define TH_URG  0x20
142 #define TH_ECE  0x40
143 #define TH_CWR  0x80
144 #define TH_NORESERVED (TH_FIN|TH_SYN|TH_RST|TH_PUSH|TH_ACK|TH_URG)
145 
146 /* TCP states */
147 #define TCP_STATE_NONE         0
148 #define TCP_STATE_LISTEN       1
149 #define TCP_STATE_SYN_RCVD     2
150 #define TCP_STATE_SYN_SENT     3
151 #define TCP_STATE_ESTABLISHED  4
152 #define TCP_STATE_CLOSE_WAIT   5
153 #define TCP_STATE_LAST_ACK     6
154 #define TCP_STATE_FIN_WAIT_1   7
155 #define TCP_STATE_CLOSING      8
156 #define TCP_STATE_FIN_WAIT_2   9
157 #define TCP_STATE_TIME_WAIT   10
158 #define TCP_STATE_CLOSED      11
159 
160 #ifndef MIN
161 # define MIN(a,b)  (((a)<(b)) ? (a):(b))
162 #endif
163 #ifndef MAX
164 # define MAX(a,b)  (((a)>(b)) ? (a):(b))
165 #endif
166 
167 #define PAWS_WINDOW         60
168 #define PAWS_24DAYS         2147483647  /*  2^ 31 -1 - approx 24 days in milli secs*/
169 
170 /* for state transition queuing */
171 #define CHK_SEQ         0
172 #define NO_CHK_SEQ      1
173 
174 #define STREAM_UNALIGNED       0
175 #define STREAM_ALIGNED         1
176 
177 /* actions */
178 #define ACTION_NOTHING                  0x00000000
179 #define ACTION_FLUSH_SENDER_STREAM      0x00000001
180 #define ACTION_FLUSH_RECEIVER_STREAM    0x00000002
181 #define ACTION_DROP_SESSION             0x00000004
182 #define ACTION_ACK_SENDER_DATA          0x00000008
183 #define ACTION_ACK_RECEIVER_DATA        0x00000010
184 #define ACTION_SET_SSN                  0x00000040
185 #define ACTION_COMPLETE_TWH             0x00000080
186 #define ACTION_RST                      0x00000100
187 #define ACTION_BAD_SEQ                  0x00000200
188 #define ACTION_BAD_PKT                  0x00000400
189 #define ACTION_LWSSN_CLOSED             0x00000800
190 #define ACTION_DISABLE_INSPECTION       0x00001000
191 
192 /* events */
193 #define EVENT_SYN_ON_EST                0x00000001
194 #define EVENT_DATA_ON_SYN               0x00000002
195 #define EVENT_DATA_ON_CLOSED            0x00000004
196 #define EVENT_BAD_TIMESTAMP             0x00000008
197 #define EVENT_BAD_SEGMENT               0x00000010
198 #define EVENT_WINDOW_TOO_LARGE          0x00000020
199 #define EVENT_EXCESSIVE_TCP_OVERLAPS    0x00000040
200 #define EVENT_DATA_AFTER_RESET          0x00000080
201 #define EVENT_SESSION_HIJACK_CLIENT     0x00000100
202 #define EVENT_SESSION_HIJACK_SERVER     0x00000200
203 #define EVENT_DATA_WITHOUT_FLAGS        0x00000400
204 #define EVENT_4WHS                      0x00000800
205 #define EVENT_NO_TIMESTAMP              0x00001000
206 #define EVENT_BAD_RST                   0x00002000
207 #define EVENT_BAD_FIN                   0x00004000
208 #define EVENT_BAD_ACK                   0x00008000
209 #define EVENT_DATA_AFTER_RST_RCVD       0x00010000
210 #define EVENT_WINDOW_SLAM               0x00020000
211 
212 #define TF_NONE                     0x0000
213 #define TF_WSCALE                   0x0001
214 #define TF_TSTAMP                   0x0002
215 #define TF_TSTAMP_ZERO              0x0004
216 #define TF_MSS                      0x0008
217 #define TF_FORCE_FLUSH              0x0010
218 #define TF_PKT_MISSED               0x0020  // sticky
219 #define TF_MISSING_PKT              0x0040  // used internally
220 #define TF_MISSING_PREV_PKT         0x0080  // reset for each reassembled
221 #define TF_FIRST_PKT_MISSING        0x0100
222 #define TF_ALL                      0xFFFF
223 
224 #define STREAM_INSERT_OK            0
225 #define STREAM_INSERT_ANOMALY       1
226 #define STREAM_INSERT_TIMEOUT       2
227 #define STREAM_INSERT_FAILED        3
228 
229 #define STREAM_DEFAULT_TCP_PACKET_MEMCAP  8388608  /* 8MB */
230 #define STREAM_MIN_OVERLAP_LIMIT 0
231 #define STREAM_MAX_OVERLAP_LIMIT 255
232 #define STREAM_MAX_FLUSH_FACTOR 2048
233 
234 #define REASSEMBLY_POLICY_FIRST     1
235 #define REASSEMBLY_POLICY_LINUX     2
236 #define REASSEMBLY_POLICY_BSD       3
237 #define REASSEMBLY_POLICY_OLD_LINUX 4
238 #define REASSEMBLY_POLICY_LAST      5
239 #define REASSEMBLY_POLICY_WINDOWS   6
240 #define REASSEMBLY_POLICY_SOLARIS   7
241 #define REASSEMBLY_POLICY_HPUX11    8
242 #define REASSEMBLY_POLICY_IRIX      9
243 #define REASSEMBLY_POLICY_MACOS     10
244 #define REASSEMBLY_POLICY_HPUX10    11
245 #define REASSEMBLY_POLICY_VISTA     12
246 #define REASSEMBLY_POLICY_WINDOWS2K3 13
247 #define REASSEMBLY_POLICY_NOACK      14
248 #define REASSEMBLY_POLICY_DEFAULT   REASSEMBLY_POLICY_BSD
249 
250 #define SUB_SYN_SENT  0x01
251 #define SUB_ACK_SENT  0x02
252 #define SUB_SETUP_OK  0x03
253 #define SUB_RST_SENT  0x04
254 #define SUB_FIN_SENT  0x08
255 
256 // flush types
257 #define STREAM_FT_INTERNAL  0  // normal s5 "footprint"
258 #define STREAM_FT_EXTERNAL  1  // set by other preprocessor
259 #define STREAM_FT_PAF_MAX   2  // paf_max + footprint fp
260 
261 #define SLAM_MAX 4
262 
263 /* Only track a maximum number of alerts per session */
264 #define MAX_SESSION_ALERTS 8
265 
266 //#define STREAM_DEBUG_ENABLED
267 #ifdef STREAM_DEBUG_ENABLED
268 #define STREAM_DEBUG_WRAP(x) DEBUG_WRAP(x)
269 #else
270 #define STREAM_DEBUG_WRAP(x)
271 #endif
272 
273 /* client/server ip/port dereference */
274 #define tcp_client_ip scb->client_ip
275 #define tcp_client_port scb->client_port
276 #define tcp_server_ip scb->server_ip
277 #define tcp_server_port scb->server_port
278 
279 static uint32_t pkt_snaplen = 0;
280 #define PKT_SNAPLEN 1514
281 
282 /*  D A T A  S T R U C T U R E S  ***********************************/
283 typedef struct _TcpDataBlock
284 {
285     uint32_t   seq;
286     uint32_t   ack;
287     uint32_t   win;
288     uint32_t   end_seq;
289     uint32_t   ts;
290 } TcpDataBlock;
291 
292 typedef struct _StateMgr
293 {
294     uint8_t    state;
295     uint8_t    sub_state;
296     uint8_t    state_queue;
297     uint8_t    expected_flags;
298     uint32_t   transition_seq;
299     uint32_t   stq_get_seq;
300 } StateMgr;
301 
302 #define RAND_FLUSH_POINTS 64
303 
304 //-------------------------------------------------------------------------
305 // extra, extra - read all about it!
306 // -- u2 is the only output plugin that currently supports extra data
307 // -- extra data may be captured before or after alerts
308 // -- extra data may be per packet or persistent (saved on session)
309 //
310 // -- per packet extra data is logged iff we alert on the packet
311 //    containing the extra data - u2 drives this
312 // -- an extra data mask is added to Packet to indicate when per packet
313 //    extra data is available
314 //
315 // -- persistent extra data must be logged exactly once for each alert
316 //    regardless of capture/alert ordering - s5 purge_alerts drives this
317 // -- an extra data mask is added to the session trackers to indicate that
318 //    persistent extra data is available
319 //
320 // -- event id and second are added to the session alert trackers so that
321 //    the extra data can be correlated with events
322 // -- event id and second are not available when StreamAddSessionAlertTcp
323 //    is called; u2 calls StreamUpdateSessionAlertTcp as events are logged
324 //    to set these fields
325 //-------------------------------------------------------------------------
326 
327 typedef struct _StreamAlertInfo
328 {
329     /* For storing alerts that have already been seen on the session */
330     uint32_t sid;
331     uint32_t gid;
332     uint32_t seq;
333     // if we log extra data, event_* is used to correlate with alert
334     uint32_t event_id;
335     uint32_t event_second;
336 } StreamAlertInfo;
337 
338 //-----------------------------------------------------------------
339 // we make a lot of StreamSegments, StreamTrackers, and TcpSessions
340 // so they are organized by member size/alignment requirements to
341 // minimize unused space in the structs.
342 // ... however, use of padding below is critical, adjust if needed
343 //-----------------------------------------------------------------
344 
345 typedef struct _StreamSegment
346 {
347     uint8_t    *data;
348     uint8_t    *payload;
349 
350     struct _StreamSegment *prev;
351     struct _StreamSegment *next;
352 
353 #ifdef DEBUG
354     int ordinal;
355 #endif
356     struct timeval tv;
357     uint32_t caplen;
358     uint32_t pktlen;
359 
360     uint32_t   ts;
361     uint32_t   seq;
362 
363     uint16_t   orig_dsize;
364     uint16_t   size;
365 
366     uint16_t   urg_offset;
367 
368     uint8_t    buffered;
369 
370     // this sequence ensures 4-byte alignment of iph in pkt
371     // (only significant if we call the grinder)
372     uint8_t    pad1;
373     uint16_t   pad2;
374     uint8_t    pkt[1];  // variable length
375 
376 } StreamSegment;
377 
378 typedef struct _StreamTracker
379 {
380     StateMgr  s_mgr;        /* state tracking goodies */
381     FlushMgr  flush_mgr;    /* please flush twice, it's a long way to
382                              * the bitbucket... */
383 
384     // this is intended to be private to s5_paf but is included
385     // directly to avoid the need for allocation; do not directly
386     // manipulate within this module.
387     PAF_State paf_state;    // for tracking protocol aware flushing
388 
389     StreamAlertInfo alerts[MAX_SESSION_ALERTS]; /* history of alerts */
390 
391     StreamTcpPolicy *tcp_policy;
392     StreamSegment *seglist;       /* first queued segment */
393     StreamSegment *seglist_tail;  /* last queued segment */
394 
395     // TBD move out of here since only used per packet?
396     StreamSegment* seglist_next;  /* next queued segment to flush */
397 
398     StreamSegment *held_segment;  /* blocked segment of http connection */
399 #ifdef DEBUG
400     int segment_ordinal;
401 #endif
402     /* Local in the context of these variables means the local part
403      * of the connection.  For example, if this particular StreamTracker
404      * was tracking the client side of a connection, the l_unackd value
405      * would represent the client side of the connection's last unacked
406      * sequence number
407      */
408     uint32_t l_unackd;     /* local unack'd seq number */
409     uint32_t l_nxt_seq;    /* local next expected sequence */
410     uint32_t l_window;     /* local receive window */
411 
412     uint32_t r_nxt_ack;    /* next expected ack from remote side */
413     uint32_t r_win_base;   /* remote side window base sequence number
414                             * (i.e. the last ack we got) */
415     uint32_t isn;          /* initial sequence number */
416     uint32_t ts_last;      /* last timestamp (for PAWS) */
417     uint32_t ts_last_pkt;  /* last packet timestamp we got */
418 
419     uint32_t seglist_base_seq;   /* seq of first queued segment */
420     uint32_t seg_count;          /* number of current queued segments */
421     uint32_t seg_bytes_total;    /* total bytes currently queued */
422     uint32_t seg_bytes_logical;  /* logical bytes queued (total - overlaps) */
423     uint32_t total_bytes_queued; /* total bytes queued (life of session) */
424     uint32_t total_segs_queued;  /* number of segments queued (life) */
425     uint32_t overlap_count;      /* overlaps encountered */
426     uint32_t small_seg_count;
427     uint32_t flush_count;        /* number of flushed queued segments */
428     uint32_t xtradata_mask;      /* extra data available to log */
429 
430     uint16_t os_policy;
431     uint16_t reassembly_policy;
432 
433     uint16_t wscale;       /* window scale setting */
434     uint16_t mss;          /* max segment size */
435     uint16_t  flags;        /* bitmap flags (TF_xxx) */
436 
437     uint8_t  mac_addr[6];
438 
439     uint8_t  alert_count;  /* number alerts stored (up to MAX_SESSION_ALERTS) */
440 
441 } StreamTracker;
442 
443 typedef struct _TcpSession
444 {
445     StreamTracker client;
446     StreamTracker server;
447     SessionControlBlock *scb;
448 
449 #ifdef DEBUG
450     struct timeval ssn_time;
451 #endif
452 
453 #ifdef HAVE_DAQ_ADDRESS_SPACE_ID
454     int32_t ingress_index;  /* Index of the inbound interface. */
455     int32_t egress_index;   /* Index of the outbound interface. */
456     int32_t ingress_group;  /* Index of the inbound group. */
457     int32_t egress_group;   /* Index of the outbound group. */
458     uint32_t daq_flags;     /* Flags for the packet (DAQ_PKT_FLAG_*) */
459     void *priv_ptr;         /* private data pointer. used in pinhole */
460 #if !defined(SFLINUX) && defined(DAQ_CAPA_VRF)
461     uint16_t address_space_id_src;
462     uint16_t address_space_id_dst;
463 #else
464     uint16_t address_space_id;
465 #endif
466 #ifdef HAVE_DAQ_FLOW_ID
467     uint32_t daq_flow_id;
468 #endif
469 #endif
470     uint8_t ecn;
471     bool session_decrypted;
472     uint8_t pp_flags;
473 } TcpSession;
474 
475 #define SL_BUF_FLUSHED 1
476 
SetupOK(const StreamTracker * st)477 static inline int SetupOK (const StreamTracker* st)
478 {
479     return ( (st->s_mgr.sub_state & SUB_SETUP_OK) == SUB_SETUP_OK );
480 }
481 
Stream_NormGetMode(uint16_t reassembly_policy,const SnortConfig * sc,NormFlags nf)482 static inline int Stream_NormGetMode(uint16_t reassembly_policy, const SnortConfig* sc, NormFlags nf)
483 {
484     if ( reassembly_policy == REASSEMBLY_POLICY_NOACK )
485         return NORM_MODE_OFF;
486     return Normalize_GetMode(sc, nf);
487 }
488 
SegsToFlush(const StreamTracker * st,unsigned max)489 static inline uint32_t SegsToFlush (const StreamTracker* st, unsigned max)
490 {
491     uint32_t n = st->seg_count - st->flush_count;
492     StreamSegment* s;
493 
494     if ( !n || max == 1 )
495         return n;
496 
497     n = 0;
498     s = st->seglist;
499 
500     while ( s )
501     {
502         if ( !s->buffered && SEQ_LT(s->seq, st->r_win_base) )
503             n++;
504 
505         if ( max && n == max )
506             return n;
507 
508         s = s->next;
509     }
510     return n;
511 }
512 
DataToFlush(const StreamTracker * st)513 static inline bool DataToFlush (const StreamTracker* st)
514 {
515     if ( (st->flush_mgr.flush_policy == STREAM_FLPOLICY_PROTOCOL)
516 #ifdef NORMALIZER
517             || (st->flush_mgr.flush_policy == STREAM_FLPOLICY_PROTOCOL_IPS)
518 #endif
519             || st->flush_mgr.flush_policy == STREAM_FLPOLICY_PROTOCOL_NOACK
520             || st->flush_mgr.flush_policy == STREAM_FLPOLICY_FOOTPRINT_NOACK
521        )
522         return ( SegsToFlush(st, 1) > 0 );
523 
524 #ifdef NORMALIZER
525     if ((st->flush_mgr.flush_policy == STREAM_FLPOLICY_FOOTPRINT_IPS) || (st->flush_mgr.flush_policy == STREAM_FLPOLICY_FOOTPRINT_IPS_FTP))
526         return ( SegsToFlush(st, 1) > 1 );
527 #endif
528 
529     return ( SegsToFlush(st, 2) > 1 );
530 }
531 
532 #ifdef REG_TEST
533 int default_ports[] =
534 {
535     21, 23, 25, 42, 53, 80, 110, 111, 135, 136, 137, 139, 143, 445,
536     513, 514, 1433, 1521, 2401, 3306
537 };
538 #define DEFAULT_PORTS_SIZE (int)(sizeof(default_ports)/sizeof(int))
539 #else
540 int *default_ports = 0;
541 #define DEFAULT_PORTS_SIZE 0
542 #endif
543 
544 #ifdef TARGET_BASED
545 char *default_protocols[] =
546 {
547     "ftp", "telnet", "smtp", "nameserver", "dns", "http", "pop3", "sunrpc",
548     "dcerpc", "netbios-ssn", "imap", "login", "shell", "mssql", "oracle", "cvs",
549     "mysql"
550 };
551 #endif
552 
553 FlushConfig ignore_flush_policy[MAX_PORTS];
554 #ifdef TARGET_BASED
555 FlushConfig ignore_flush_policy_protocol[MAX_PROTOCOL_ORDINAL];
556 #endif
557 
558 /*  P R O T O T Y P E S  ********************************************/
559 static void StreamParseTcpArgs(struct _SnortConfig *, StreamTcpConfig *, char *, StreamTcpPolicy *);
560 static void StreamPrintTcpConfig(StreamTcpPolicy *);
561 
562 static void StreamInitPacket();
563 static inline void SetupTcpDataBlock(TcpDataBlock *, Packet *);
564 static int ProcessTcp(SessionControlBlock *, Packet *, TcpDataBlock *,
565         StreamTcpPolicy *, SFXHASH_NODE *);
566 #if OLD_CODE_NOLONGER_USED_DEPENDS_ON_CURRENT_STATE
567 static inline void QueueState(uint8_t, StreamTracker*, uint8_t,
568         uint32_t, uint8_t);
569 static inline int EvalStateQueue(StreamTracker *, uint8_t, uint32_t);
570 #endif
571 static inline int CheckFlushPolicyOnData(
572         StreamTcpConfig *config, TcpSession *, StreamTracker *,
573         StreamTracker *, TcpDataBlock *, Packet *);
574 static inline int CheckFlushPolicyOnAck(
575         StreamTcpConfig *config, TcpSession *, StreamTracker *,
576         StreamTracker *, TcpDataBlock *, Packet *);
577 static void StreamSeglistAddNode(StreamTracker *, StreamSegment *,
578         StreamSegment *);
579 static int StreamSeglistDeleteNode(StreamTracker *, StreamSegment *);
580 static int StreamSeglistDeleteNodeTrim(StreamTracker*, StreamSegment*, uint32_t flush_seq);
581 static int AddStreamNode(StreamTracker *st, Packet *p,
582         TcpDataBlock*,
583         TcpSession *tcpssn,
584         uint16_t len,
585         uint32_t slide,
586         uint32_t trunc,
587         uint32_t seq,
588         StreamSegment *left,
589         StreamSegment **retSeg);
590 static int DupStreamNode(
591         Packet*,
592         StreamTracker*,
593         StreamSegment* left,
594         StreamSegment** retSeg);
595 
596 static uint32_t StreamGetWscale(Packet *, uint16_t *);
597 static uint32_t StreamPacketHasWscale(Packet *);
598 static uint32_t StreamGetMss(Packet *, uint16_t *);
599 static uint32_t StreamGetTcpTimestamp(Packet *, uint32_t *, int strip);
600 static int FlushStream(
601         Packet*, StreamTracker *st, uint32_t toSeq, uint8_t *flushbuf,
602         const uint8_t *flushbuf_end);
603 static void TcpSessionCleanup(SessionControlBlock *ssn, int freeApplicationData);
604 static void TcpSessionCleanupWithFreeApplicationData(void *ssn);
605 static void FlushQueuedSegs(SessionControlBlock *ssn, TcpSession *tcpssn);
606 
607 int s5TcpStreamSizeInit(struct _SnortConfig *sc, char *name, char *parameters, void **dataPtr);
608 int s5TcpStreamSizeEval(void *p, const uint8_t **cursor, void *dataPtr);
609 void s5TcpStreamSizeCleanup(void *dataPtr);
610 int s5TcpStreamReassembleRuleOptionInit(struct _SnortConfig *sc, char *name, char *parameters, void **dataPtr);
611 int s5TcpStreamReassembleRuleOptionEval(void *p, const uint8_t **cursor, void *dataPtr);
612 void s5TcpStreamReassembleRuleOptionCleanup(void *dataPtr);
613 static inline void ResetFlushMgrs(void);
614 static void targetPolicyIterate(void (*callback)(int));
615 static void policyDecoderFlagsSaveNClear(int policyId);
616 static void policyDecoderFlagsRestore(int policyId);
617 static void policyChecksumFlagsSaveNClear(int policyId);
618 static void policyChecksumFlagsRestore(int policyId);
619 static inline uint16_t GetTcpReassemblyPolicy(int os_policy);
620 
621 /*  G L O B A L S  **************************************************/
622 static SessionCache* tcp_lws_cache = NULL;
623 static Packet *s5_pkt = NULL;
624 static Packet *tcp_cleanup_pkt = NULL;
625 static const uint8_t *s5_pkt_end = NULL;
626 static char midstream_allowed = 0;
627 static Packet *wire_packet = NULL;
628 static uint8_t flush_policy_for_dir = 0;
629 
630 /* enum for policy names */
631 static char *reassembly_policy_names[] = {
632     "no policy!",
633     "FIRST",
634     "LINUX",
635     "BSD",
636     "OLD LINUX",
637     "LAST",
638     "WINDOWS",
639     "SOLARIS",
640     "HPUX11",
641     "IRIX",
642     "MACOS",
643     "HPUX10",
644     "WINDOWS VISTA",
645     "WINDOWS 2003"
646         "IPS"
647 };
648 
649 #ifdef STREAM_DEBUG_ENABLED
650 static char *state_names[] = {
651     "NONE",
652     "LISTEN",
653     "SYN_RCVD",
654     "SYN_SENT",
655     "ESTABLISHED",
656     "CLOSE_WAIT",
657     "LAST_ACK",
658     "FIN_WAIT_1",
659     "CLOSING",
660     "FIN_WAIT_2",
661     "TIME_WAIT",
662     "CLOSED"
663 };
664 #endif
665 
666 static char *flush_policy_names[] = {
667     "None",
668     "Footprint",
669     "Logical",
670     "Response",
671     "Sliding Window",
672 #if 0
673     "Consumed",
674 #endif
675     "Ignore",
676     "Protocol",
677     "Footprint-IPS",
678     "Protocol-IPS",
679     "Footprint-NOACK",
680     "Protocol-NOACK",
681     "Footprint-IPS-FTP",
682     "Disabled"
683 };
684 
685 static int s5_tcp_cleanup = 0;
686 
687 static uint32_t g_static_points[RAND_FLUSH_POINTS] =
688 { 128, 217, 189, 130, 240, 221, 134, 129,
689     250, 232, 141, 131, 144, 177, 201, 130,
690     230, 190, 177, 142, 130, 200, 173, 129,
691     250, 244, 174, 151, 201, 190, 180, 198,
692     220, 201, 142, 185, 219, 129, 194, 140,
693     145, 191, 197, 183, 199, 220, 231, 245,
694     233, 135, 143, 158, 174, 194, 200, 180,
695     201, 142, 153, 187, 173, 199, 143, 201 };
696 
697 /*  F U N C T I O N S  **********************************************/
GenerateFlushPoint(FlushPointList * flush_point_list)698 static inline uint32_t GenerateFlushPoint(FlushPointList *flush_point_list)
699 {
700     return (rand() % flush_point_list->flush_range) + flush_point_list->flush_base;
701 }
702 
InitFlushPointList(FlushPointList * flush_point_list,uint32_t value,uint32_t range,int use_static)703 static inline void InitFlushPointList(FlushPointList *flush_point_list, uint32_t value, uint32_t range, int use_static)
704 {
705     uint32_t i;
706     uint32_t flush_range = range;
707     uint32_t flush_base = value - range/2;
708 
709     if (!flush_point_list)
710         return;
711 
712     if (!flush_point_list->initialized)
713     {
714 #ifdef REG_TEST
715         const char* sfp = getenv("S5_FPT");
716         // no error checking required - atoi() is sufficient
717         uint32_t cfp = sfp ? atoi(sfp) : 0;
718         if ( cfp < 128 || cfp > 255 ) cfp = 192;
719 #else
720         const uint32_t cfp = 192;
721 #endif
722 
723         flush_point_list->flush_range = flush_range;
724         flush_point_list->flush_base = flush_base;
725 #ifndef DYNAMIC_RANDOM_FLUSH_POINTS
726         flush_point_list->current = 0;
727 
728         flush_point_list->flush_points = SnortPreprocAlloc(RAND_FLUSH_POINTS, sizeof(uint32_t),
729                                                  PP_STREAM, PP_MEM_CATEGORY_CONFIG);
730         for (i=0;i<RAND_FLUSH_POINTS;i++)
731         {
732             if (snort_conf->run_flags & RUN_FLAG__STATIC_HASH)
733             {
734                 if ( i == 0 )
735                     LogMessage("WARNING:  using constant flush point = %u!\n", cfp);
736                 flush_point_list->flush_points[i] = cfp;
737 
738             }
739             else if (use_static)
740             {
741                 if ( i == 0 )
742                     LogMessage("WARNING: using static flush points.\n");
743                 flush_point_list->flush_points[i] = g_static_points[i];
744             }
745             else
746             {
747                 flush_point_list->flush_points[i] = GenerateFlushPoint(flush_point_list);
748             }
749         }
750 #endif
751         flush_point_list->initialized = 1;
752     }
753 }
754 
UpdateFlushMgr(SnortConfig * sc,FlushMgr * mgr,FlushPointList * flush_point_list,uint32_t flags)755 static inline void UpdateFlushMgr( SnortConfig *sc,
756         FlushMgr *mgr, FlushPointList *flush_point_list, uint32_t flags)
757 {
758     if ( mgr->flush_type == STREAM_FT_EXTERNAL )
759         return;
760 
761     switch (mgr->flush_policy)
762     {
763         case STREAM_FLPOLICY_FOOTPRINT:
764         case STREAM_FLPOLICY_LOGICAL:
765             break;
766 
767         case STREAM_FLPOLICY_PROTOCOL:
768             if ( flags & TF_PKT_MISSED )
769             {
770                 mgr->flush_policy = STREAM_FLPOLICY_FOOTPRINT;
771                 mgr->flush_type = STREAM_FT_PAF_MAX;
772             }
773             break;
774 
775 #ifdef NORMALIZER
776         case STREAM_FLPOLICY_FOOTPRINT_IPS:
777         case STREAM_FLPOLICY_FOOTPRINT_IPS_FTP:
778             break;
779 
780         case STREAM_FLPOLICY_PROTOCOL_IPS:
781             if ( flags & TF_PKT_MISSED )
782             {
783                 mgr->flush_policy = STREAM_FLPOLICY_FOOTPRINT_IPS;
784                 mgr->flush_type = STREAM_FT_PAF_MAX;
785             }
786             break;
787 #endif
788         case STREAM_FLPOLICY_FOOTPRINT_NOACK:
789             break;
790         case STREAM_FLPOLICY_PROTOCOL_NOACK:
791             if ( flags & TF_PKT_MISSED )
792             {
793                 mgr->flush_policy = STREAM_FLPOLICY_FOOTPRINT_NOACK;
794                 mgr->flush_type = STREAM_FT_PAF_MAX;
795             }
796             break;
797         default:
798             return;
799     }
800     /* Ideally, we would call rand() each time, but that
801      * is a performance headache waiting to happen. */
802 #ifdef DYNAMIC_RANDOM_FLUSH_POINTS
803     mgr->flush_pt = GenerateFlushPoint();
804 #else
805     if (flush_point_list)
806     {
807         /* Handle case where it wasn't initialized... */
808         if (flush_point_list->initialized == 0)
809         {
810             InitFlushPointList(flush_point_list, 192, 128, 0);
811         }
812         mgr->flush_pt = flush_point_list->flush_points[flush_point_list->current];
813         flush_point_list->current = (flush_point_list->current+1) % RAND_FLUSH_POINTS;
814     }
815 #endif
816     //Do not reset the last_size for FTP flush policy
817     if(mgr->flush_policy != STREAM_FLPOLICY_FOOTPRINT_IPS_FTP)
818     {
819         mgr->last_size = 0;
820         mgr->last_count = 0;
821     }
822 
823     if ( mgr->flush_type == STREAM_FT_PAF_MAX )
824         mgr->flush_pt += ScPafMaxNewConf(sc);
825 }
826 
InitFlushMgr(SnortConfig * sc,FlushMgr * mgr,FlushPointList * flush_point_list,uint8_t policy,uint8_t auto_disable)827 static inline void InitFlushMgr( SnortConfig *sc, FlushMgr *mgr, FlushPointList *flush_point_list,
828         uint8_t policy, uint8_t auto_disable)
829 {
830     // if policy is to disable reassembly just set policy in flush manager and
831     // return
832     if( policy == STREAM_FLPOLICY_DISABLED )
833     {
834         mgr->flush_policy = policy;
835         return;
836     }
837     else if ( mgr->flush_policy == STREAM_FLPOLICY_DISABLED )
838     {
839         WarningMessage( "Stream policy has disabled reassembly on this port." );
840         return;
841     }
842 
843     mgr->flush_policy = policy;
844     mgr->flush_type = STREAM_FT_INTERNAL;
845     mgr->auto_disable = auto_disable;
846 
847     UpdateFlushMgr(sc, mgr, flush_point_list, 0);
848 
849 #ifdef NORMALIZER
850     if ( Normalize_GetMode(sc, NORM_TCP_IPS) == NORM_MODE_ON)
851     {
852         if ( policy == STREAM_FLPOLICY_FOOTPRINT )
853             mgr->flush_policy = STREAM_FLPOLICY_FOOTPRINT_IPS;
854 
855         else if ( policy == STREAM_FLPOLICY_PROTOCOL )
856             mgr->flush_policy = STREAM_FLPOLICY_PROTOCOL_IPS;
857     }
858 #endif
859 }
860 
InitFlushMgrByPort(SessionControlBlock * scb,StreamTracker * pst,uint16_t port,bool c2s,uint8_t flush_policy,bool all_services)861 static inline void InitFlushMgrByPort (
862         SessionControlBlock* scb, StreamTracker* pst,
863         uint16_t port, bool c2s, uint8_t flush_policy, bool all_services)
864 {
865     uint16_t registration, auto_disable = 0;
866     bool flush = (flush_policy != STREAM_FLPOLICY_IGNORE);
867 
868 #if 0
869     // this check required if PAF doesn't abort
870     if ( scb->session_state & STREAM_STATE_MIDSTREAM )
871         registration = 0;
872     else
873 #endif
874         if(all_services)
875         {
876             registration = s5_paf_port_registration_all(
877                     ( ( StreamConfig * ) scb->stream_config )->tcp_config->paf_config, port, c2s, flush);
878         }
879         else
880         {
881             registration = s5_paf_port_registration(
882                     ( ( StreamConfig * ) scb->stream_config )->tcp_config->paf_config, port, c2s, flush);
883         }
884 
885     if ( registration )
886     {
887         if( flush_policy == STREAM_FLPOLICY_FOOTPRINT_NOACK )
888             flush_policy = STREAM_FLPOLICY_PROTOCOL_NOACK;
889         else
890             flush_policy = STREAM_FLPOLICY_PROTOCOL;
891         s5_paf_setup(&pst->paf_state, registration);
892         auto_disable = !flush;
893     }
894     InitFlushMgr(snort_conf, &pst->flush_mgr,
895             &pst->tcp_policy->flush_point_list, flush_policy, auto_disable);
896 }
897 
InitFlushMgrByService(SessionControlBlock * scb,StreamTracker * pst,int16_t service,bool c2s,uint8_t flush_policy)898 static inline void InitFlushMgrByService (
899         SessionControlBlock* scb, StreamTracker* pst,
900         int16_t service, bool c2s, uint8_t flush_policy)
901 {
902     uint16_t registration, auto_disable = 0;
903     bool flush = (flush_policy != STREAM_FLPOLICY_IGNORE);
904 
905 #if 0
906     // this check required if PAF doesn't abort
907     if ( scb->session_state & STREAM_STATE_MIDSTREAM )
908         registration = 0;
909     else
910 #endif
911         registration = s5_paf_service_registration(
912                 ( ( StreamConfig * ) scb->stream_config )->tcp_config->paf_config, service, c2s, flush);
913 
914     if ( registration )
915     {
916         if( flush_policy == STREAM_FLPOLICY_FOOTPRINT_NOACK )
917             flush_policy = STREAM_FLPOLICY_PROTOCOL_NOACK;
918         else
919             flush_policy = STREAM_FLPOLICY_PROTOCOL;
920         s5_paf_setup(&pst->paf_state, registration);
921         auto_disable = !flush;
922     }
923     InitFlushMgr(snort_conf, &pst->flush_mgr,
924             &pst->tcp_policy->flush_point_list, flush_policy, auto_disable);
925 }
926 
ResetFlushMgrsPolicy(tSfPolicyUserContextId config,tSfPolicyId policyId,void * pData)927 static int ResetFlushMgrsPolicy(
928         tSfPolicyUserContextId config,
929         tSfPolicyId policyId,
930         void* pData
931         )
932 {
933     int i;
934     StreamConfig *pPolicyConfig = (StreamConfig *)pData;
935 
936     //do any housekeeping before freeing StreamConfig
937     if (pPolicyConfig->tcp_config == NULL)
938         return 0;
939 
940     for (i = 0; i < pPolicyConfig->tcp_config->num_policies; i++)
941     {
942         int j;
943         StreamTcpPolicy *policy = pPolicyConfig->tcp_config->policy_list[i];
944         FlushPointList *fpl = &policy->flush_point_list;
945         FlushMgr *client, *server;
946         uint8_t flush_policy;
947 
948         fpl->current = 0;
949 
950         for (j = 0; j < MAX_PORTS; j++)
951         {
952             client = &policy->flush_config[j].client;
953             flush_policy = policy->flush_config[j].client.flush_policy;
954             InitFlushMgr(snort_conf, client, fpl, flush_policy, 0);
955 
956             server = &policy->flush_config[j].server;
957             flush_policy = policy->flush_config[j].server.flush_policy;
958             InitFlushMgr(snort_conf, server, fpl, flush_policy, 0);
959         }
960 #ifdef TARGET_BASED
961         /* protocol 0 is the unknown case. skip it */
962         for (j = 1; j < MAX_PROTOCOL_ORDINAL; j++)
963         {
964             client = &policy->flush_config_protocol[j].client;
965             flush_policy = policy->flush_config_protocol[j].client.flush_policy;
966             InitFlushMgr(snort_conf, client, fpl, flush_policy, 0);
967 
968             server = &policy->flush_config_protocol[j].server;
969             flush_policy = policy->flush_config_protocol[j].server.flush_policy;
970             InitFlushMgr(snort_conf, server, fpl, flush_policy, 0);
971         }
972 #endif
973     }
974 
975     return 0;
976 }
977 
ResetFlushMgrs(void)978 static inline void ResetFlushMgrs( void )
979 {
980     if( stream_online_config == NULL )
981         return;
982 
983     sfPolicyUserDataFreeIterate( stream_online_config, ResetFlushMgrsPolicy );
984 }
985 
StreamGetPAFUserDataTcp(SessionControlBlock * scb,bool to_server,uint8_t id)986 void **StreamGetPAFUserDataTcp( SessionControlBlock* scb, bool to_server, uint8_t id )
987 {
988     TcpSession* tcpssn;
989     PAF_State *ps;
990     int8_t i;
991 
992     if(!id)
993        return NULL;
994 
995     if( !scb->proto_specific_data )
996         return NULL;
997 
998     tcpssn = ( TcpSession * ) scb->proto_specific_data->data;
999 
1000     if ( !tcpssn )
1001         return NULL;
1002 
1003     ps = ( to_server ) ? &tcpssn->server.paf_state
1004        :
1005        &tcpssn->client.paf_state;
1006 
1007     i = s5_paf_get_user_data_index( ps, id );
1008 
1009     if( i >= 0 )
1010        return &ps->user[i];
1011     else
1012        return NULL;
1013 }
1014 
StreamIsPafActiveTcp(SessionControlBlock * scb,bool to_server)1015 bool StreamIsPafActiveTcp( SessionControlBlock *scb, bool to_server )
1016 {
1017     TcpSession *tcpssn;
1018     FlushMgr *fm;
1019 
1020     if( !scb->proto_specific_data )
1021         return false;
1022 
1023     tcpssn = ( TcpSession * ) scb->proto_specific_data->data;
1024 
1025     if( !tcpssn )
1026         return false;
1027 
1028     fm = ( to_server ) ? &tcpssn->server.flush_mgr : &tcpssn->client.flush_mgr;
1029 
1030     return ( ( fm->flush_policy == STREAM_FLPOLICY_PROTOCOL )
1031 #ifdef NORMALIZER
1032             || ( fm->flush_policy == STREAM_FLPOLICY_PROTOCOL_IPS )
1033 #endif
1034             || (fm->flush_policy == STREAM_FLPOLICY_PROTOCOL_NOACK)
1035            );
1036 }
1037 
StreamActivatePafTcp(SessionControlBlock * scb,int dir,int16_t service_port,uint8_t type)1038 bool StreamActivatePafTcp (SessionControlBlock *scb, int dir, int16_t service_port, uint8_t type)
1039 {
1040     TcpSession *tcpssn;
1041     StreamTracker *trk;
1042     FlushMgr *fm;
1043     uint8_t flush_policy;
1044 
1045     if( !scb->proto_specific_data )
1046         return false;
1047 
1048     tcpssn = ( TcpSession * ) scb->proto_specific_data->data;
1049 
1050     if( !tcpssn || !ScPafEnabled() )
1051         return false;
1052 
1053     // must have valid stream config for this session, may need to reset after a reload
1054     if( scb->stream_config == NULL )
1055     {
1056         WarningMessage("Stream Configuration NULL For In Progress Session, Reinitializing.\n");
1057         scb->stream_config = sfPolicyUserDataGet( stream_online_config, getNapRuntimePolicy() );
1058         if( scb->stream_config == NULL )
1059         {
1060             ErrorMessage("No Valid Stream Configurations, Stream Processing Terminated For This Packet.\n");
1061             return false;
1062         }
1063     }
1064 
1065     switch ( dir )
1066     {
1067         case SSN_DIR_TO_CLIENT:
1068             {
1069                 trk = &tcpssn->client;
1070                 fm = &tcpssn->client.flush_mgr;
1071                 flush_policy = fm->flush_policy;
1072                 if ( flush_policy == STREAM_FLPOLICY_IGNORE )
1073                     flush_policy = STREAM_FLPOLICY_PROTOCOL;
1074 
1075                 if ( type == PAF_TYPE_SERVICE )
1076                 {
1077                     InitFlushMgrByService(scb, trk, service_port, false, flush_policy);
1078                 }
1079                 else
1080                 {
1081                     InitFlushMgrByPort(scb, trk, service_port, false, flush_policy, true);
1082                 }
1083             }
1084             break;
1085         case SSN_DIR_TO_SERVER:
1086             {
1087                 trk = &tcpssn->server;
1088                 fm = &tcpssn->server.flush_mgr;
1089                 flush_policy = fm->flush_policy;
1090                 if ( flush_policy == STREAM_FLPOLICY_IGNORE )
1091                     flush_policy = STREAM_FLPOLICY_PROTOCOL;
1092 
1093                 if ( type == PAF_TYPE_SERVICE )
1094                 {
1095                     InitFlushMgrByService(scb, trk, service_port, true, flush_policy);
1096                 }
1097                 else
1098                 {
1099                     InitFlushMgrByPort(scb, trk, service_port, true, flush_policy, true );
1100                 }
1101             }
1102             break;
1103         case SSN_DIR_BOTH:
1104             {
1105                 trk = &tcpssn->server;
1106                 fm = &tcpssn->server.flush_mgr;
1107                 flush_policy = fm->flush_policy;
1108                 if ( flush_policy == STREAM_FLPOLICY_IGNORE )
1109                     flush_policy = STREAM_FLPOLICY_PROTOCOL;
1110 
1111                 if ( type == PAF_TYPE_SERVICE )
1112                 {
1113                     InitFlushMgrByService(scb, trk, service_port, true, flush_policy);
1114                 }
1115                 else
1116                 {
1117                     InitFlushMgrByPort(scb, trk, service_port, true, flush_policy, true );
1118                 }
1119             }
1120             {
1121                 trk = &tcpssn->client;
1122                 fm = &tcpssn->client.flush_mgr;
1123                 flush_policy = fm->flush_policy;
1124                 if ( flush_policy == STREAM_FLPOLICY_IGNORE )
1125                     flush_policy = STREAM_FLPOLICY_PROTOCOL;
1126 
1127                 if ( type == PAF_TYPE_SERVICE )
1128                 {
1129                     InitFlushMgrByService(scb, trk, service_port, false, flush_policy);
1130                 }
1131                 else
1132                 {
1133                     InitFlushMgrByPort(scb, trk, service_port, false, flush_policy, true);
1134                 }
1135             }
1136             break;
1137 
1138         default:
1139             return false;
1140     }
1141 
1142     return true;
1143 }
1144 
StreamResetPolicyPerTrk(StreamTracker * trk,uint16_t policy,uint16_t mss)1145 static inline void StreamResetPolicyPerTrk( StreamTracker* trk, uint16_t policy, uint16_t mss )
1146 {
1147     trk->tcp_policy->policy = trk->os_policy = policy;
1148     trk->reassembly_policy = GetTcpReassemblyPolicy( policy );
1149     trk->mss = mss;
1150 }
1151 
StreamResetPolicyTcp(SessionControlBlock * scb,int dir,uint16_t policy,uint16_t mss)1152 void StreamResetPolicyTcp ( SessionControlBlock *scb, int dir, uint16_t policy, uint16_t mss)
1153 {
1154     TcpSession *tcpssn;
1155 
1156     if( !scb->proto_specific_data )
1157         return;
1158 
1159     tcpssn = ( TcpSession * ) scb->proto_specific_data->data;
1160 
1161     if( !tcpssn )
1162         return;
1163 
1164     switch( dir )
1165     {
1166         case SSN_DIR_TO_CLIENT:
1167             StreamResetPolicyPerTrk( &tcpssn->client, policy, mss );
1168             break;
1169 
1170         case SSN_DIR_TO_SERVER:
1171             StreamResetPolicyPerTrk( &tcpssn->server, policy, mss );
1172             break;
1173 
1174         case SSN_DIR_BOTH:
1175             StreamResetPolicyPerTrk( &tcpssn->server, policy, mss );
1176             StreamResetPolicyPerTrk( &tcpssn->client, policy, mss );
1177             break;
1178 
1179         default:
1180             break;
1181     }
1182 }
1183 
StreamSetSessionDecryptedTcp(SessionControlBlock * scb,bool enable)1184 void StreamSetSessionDecryptedTcp( SessionControlBlock *scb, bool enable )
1185 {
1186     TcpSession *tcpssn;
1187 
1188     if( !scb->proto_specific_data )
1189         return;
1190 
1191     tcpssn = ( TcpSession * ) scb->proto_specific_data->data;
1192 
1193     if ( !tcpssn )
1194         return;
1195 
1196     if((SegsToFlush(&tcpssn->server, 1) > 0) || (SegsToFlush(&tcpssn->client, 1) > 0))
1197     {
1198         FlushQueuedSegs(scb, tcpssn);
1199         Active_Reset();
1200     }
1201 
1202     tcpssn->session_decrypted = enable;
1203 }
1204 
StreamIsSessionDecryptedTcp(SessionControlBlock * scb)1205 bool StreamIsSessionDecryptedTcp( SessionControlBlock *scb )
1206 {
1207     TcpSession *tcpssn;
1208 
1209     if( !scb->proto_specific_data )
1210         return false;
1211 
1212     tcpssn = ( TcpSession * ) scb->proto_specific_data->data;
1213 
1214     if ( !tcpssn )
1215         return false;
1216 
1217     return ( tcpssn->session_decrypted == true );
1218 }
1219 
StreamGetPreprocFlagsTcp(SessionControlBlock * scb)1220 uint32_t StreamGetPreprocFlagsTcp(SessionControlBlock *scb)
1221 {
1222     TcpSession *tcpssn;
1223 
1224     if( !scb->proto_specific_data )
1225         return 0;
1226 
1227     tcpssn = ( TcpSession * ) scb->proto_specific_data->data;
1228 
1229     if ( !tcpssn )
1230         return 0;
1231 
1232     return tcpssn->pp_flags;
1233 }
1234 
1235 //-------------------------------------------------------------------------
1236 // tcp ha stuff
1237 
1238 #ifdef ENABLE_HA
StreamTCPCreateSession(const SessionKey * key)1239 static SessionControlBlock *StreamTCPCreateSession( const SessionKey *key )
1240 {
1241     setNapRuntimePolicy( getDefaultPolicy() );
1242 
1243     /* TODO: Set the TCP policy to something here? */
1244     return session_api->create_session( tcp_lws_cache, NULL, key );
1245 }
1246 
StreamTCPDeactivateSession(SessionControlBlock * scb)1247 static void StreamTCPDeactivateSession( SessionControlBlock *scb )
1248 {
1249     if( scb->proto_specific_data )
1250     {
1251         STREAM_DEBUG_WRAP(DebugMessage(DEBUG_STREAM_STATE,
1252                     "Cleaning up the TCP session associated with the session being put into standby.\n"););
1253         TcpSessionCleanup( scb, 0 );
1254     }
1255 
1256     scb->session_state &= ~( STREAM_STATE_SYN | STREAM_STATE_SYN_ACK |
1257             STREAM_STATE_ACK | STREAM_STATE_ESTABLISHED );
1258     scb->ha_state.session_flags &= ~( SSNFLAG_SEEN_CLIENT | SSNFLAG_SEEN_SERVER );
1259 }
1260 
StreamTCPDeleteSession(const SessionKey * key)1261 static int StreamTCPDeleteSession( const SessionKey *key )
1262 {
1263     SessionControlBlock *scb = session_api->get_session_by_key( tcp_lws_cache, key );
1264 
1265     if( scb != NULL )
1266     {
1267         if( StreamSetRuntimeConfiguration( scb, scb->protocol ) == 0 )
1268         {
1269             if (!session_api->delete_session( tcp_lws_cache, scb, "ha sync", false ))
1270                s5stats.active_tcp_sessions--;
1271         }
1272         else
1273             WarningMessage(" WARNING: Attempt to delete a TCP Session when no valid runtime configuration.\n" );
1274     }
1275 
1276     return 0;
1277 }
1278 #endif
1279 
GetLWTcpSession(const SessionKey * key)1280 SessionControlBlock *GetLWTcpSession( const SessionKey *key )
1281 {
1282     return session_api->get_session_by_key( tcp_lws_cache, key );
1283 }
1284 
1285 #ifdef ENABLE_HA
1286 
1287 static HA_Api ha_tcp_api = {
1288     /*.get_lws = */ GetLWTcpSession,
1289 
1290     /*.create_session = */ StreamTCPCreateSession,
1291     /*.deactivate_session = */ StreamTCPDeactivateSession,
1292     /*.delete_session = */ StreamTCPDeleteSession,
1293 };
1294 
1295 #endif
1296 
setTcpDirectionAndPorts(Packet * p,SessionControlBlock * scb)1297 void setTcpDirectionAndPorts( Packet *p, SessionControlBlock *scb )
1298 {
1299     if( TCP_ISFLAGSET( p->tcph, TH_SYN ) && !TCP_ISFLAGSET( p->tcph, TH_ACK ) )
1300     {
1301         STREAM_DEBUG_WRAP( DebugMessage(DEBUG_STREAM_STATE,
1302                     "Stream SYN PACKET, establishing lightweight session direction.\n"););
1303         /* SYN packet from client */
1304         scb->ha_state.direction = FROM_CLIENT;
1305         IP_COPY_VALUE( scb->client_ip, GET_SRC_IP( p ) );
1306         scb->client_port = p->tcph->th_sport;
1307         IP_COPY_VALUE( scb->server_ip, GET_DST_IP( p ) );
1308         scb->server_port = p->tcph->th_dport;
1309     }
1310     else if( TCP_ISFLAGSET( p->tcph, ( TH_SYN | TH_ACK ) ) )
1311     {
1312         scb->ha_state.direction = FROM_SERVER;
1313         IP_COPY_VALUE( scb->client_ip, GET_DST_IP( p ) );
1314         scb->client_port = p->tcph->th_dport;
1315         IP_COPY_VALUE( scb->server_ip, GET_SRC_IP( p ) );
1316         scb->server_port = p->tcph->th_sport;
1317     }
1318     else
1319     {
1320         /* Assume from client, can update later */
1321         if( p->sp > p->dp )
1322         {
1323             scb->ha_state.direction = FROM_CLIENT;
1324             IP_COPY_VALUE( scb->client_ip, GET_SRC_IP( p ) );
1325             scb->client_port = p->tcph->th_sport;
1326             IP_COPY_VALUE( scb->server_ip, GET_DST_IP( p ) );
1327             scb->server_port = p->tcph->th_dport;
1328         }
1329         else
1330         {
1331             scb->ha_state.direction = FROM_SERVER;
1332             IP_COPY_VALUE( scb->client_ip, GET_DST_IP( p ) );
1333             scb->client_port = p->tcph->th_dport;
1334             IP_COPY_VALUE( scb->server_ip, GET_SRC_IP( p ) );
1335             scb->server_port = p->tcph->th_sport;
1336         }
1337     }
1338 }
StreamInitTcp(void)1339 void StreamInitTcp( void )
1340 {
1341     if( tcp_lws_cache == NULL )
1342     {
1343         tcp_lws_cache = session_api->init_session_cache( SESSION_PROTO_TCP,
1344                 sizeof( TcpSession ),
1345                 &TcpSessionCleanupWithFreeApplicationData );
1346         StreamTcpRegisterPreprocProfiles();
1347     }
1348 #ifdef ENABLE_HA
1349     ha_set_api( IPPROTO_TCP, &ha_tcp_api );
1350 #endif
1351 
1352     pkt_snaplen = (snort_conf->pkt_snaplen > 0) ? snort_conf->pkt_snaplen : PKT_SNAPLEN;
1353 }
1354 
StreamTcpRegisterPreprocProfiles(void)1355 void StreamTcpRegisterPreprocProfiles( void )
1356 {
1357 #ifdef PERF_PROFILING
1358     RegisterPreprocessorProfile( "s5TcpNewSess", &s5TcpNewSessPerfStats, 2, &s5TcpPerfStats , NULL);
1359     RegisterPreprocessorProfile( "s5TcpState", &s5TcpStatePerfStats, 2, &s5TcpPerfStats , NULL);
1360     RegisterPreprocessorProfile( "s5TcpData", &s5TcpDataPerfStats, 3, &s5TcpStatePerfStats , NULL);
1361     RegisterPreprocessorProfile( "s5TcpPktInsert", &s5TcpInsertPerfStats, 4, &s5TcpDataPerfStats , NULL);
1362     RegisterPreprocessorProfile( "s5TcpPAF", &s5TcpPAFPerfStats, 3, &s5TcpStatePerfStats , NULL);
1363     RegisterPreprocessorProfile( "s5TcpFlush", &s5TcpFlushPerfStats, 3, &s5TcpStatePerfStats , NULL);
1364     RegisterPreprocessorProfile( "s5TcpBuildPacket", &s5TcpBuildPacketPerfStats, 4, &s5TcpFlushPerfStats , NULL);
1365     RegisterPreprocessorProfile( "s5TcpProcessRebuilt", &s5TcpProcessRebuiltPerfStats,
1366             4, &s5TcpFlushPerfStats, NULL );
1367 #endif
1368 }
1369 
StreamTcpRegisterRuleOptions(struct _SnortConfig * sc)1370 void StreamTcpRegisterRuleOptions( struct _SnortConfig *sc )
1371 {
1372     /* Register the 'stream_size' rule option */
1373     RegisterPreprocessorRuleOption( sc, "stream_size", &s5TcpStreamSizeInit,
1374             &s5TcpStreamSizeEval, &s5TcpStreamSizeCleanup,
1375             NULL, NULL, NULL, NULL );
1376 
1377     RegisterPreprocessorRuleOption( sc, "stream_reassemble", &s5TcpStreamReassembleRuleOptionInit,
1378             &s5TcpStreamReassembleRuleOptionEval,
1379             &s5TcpStreamReassembleRuleOptionCleanup,
1380             NULL, NULL, NULL, NULL );
1381 #ifdef PERF_PROFILING
1382     RegisterPreprocessorProfile( "stream_size", &streamSizePerfStats, 4, &preprocRuleOptionPerfStats , NULL);
1383     RegisterPreprocessorProfile( "reassemble", &streamReassembleRuleOptionPerfStats,
1384             4, &preprocRuleOptionPerfStats, NULL);
1385 #endif
1386 }
1387 
StreamTcpInitFlushPoints(void)1388 void StreamTcpInitFlushPoints( void )
1389 {
1390     int i;
1391 
1392     /* Seed the flushpoint random generator */
1393     srand( ( unsigned int ) sizeof( default_ports ) + ( unsigned int ) time( NULL ) );
1394 
1395     /* Default is to ignore, for all ports */
1396     for( i = 0; i < MAX_PORTS; i++ )
1397     {
1398         ignore_flush_policy[i].client.flush_policy = STREAM_FLPOLICY_IGNORE;
1399         ignore_flush_policy[i].server.flush_policy = STREAM_FLPOLICY_IGNORE;
1400     }
1401 #ifdef TARGET_BASED
1402     for( i = 0; i < MAX_PROTOCOL_ORDINAL; i++)
1403     {
1404         ignore_flush_policy_protocol[i].client.flush_policy = STREAM_FLPOLICY_IGNORE;
1405         ignore_flush_policy_protocol[i].server.flush_policy = STREAM_FLPOLICY_IGNORE;
1406     }
1407 #endif
1408 }
1409 
addStreamTcpPolicyToList(StreamTcpConfig * config,StreamTcpPolicy * policy)1410 static void addStreamTcpPolicyToList( StreamTcpConfig *config, StreamTcpPolicy *policy )
1411 {
1412     config->num_policies++;
1413 
1414     /* Now add this context to the internal list */
1415     if( config->policy_list == NULL )
1416     {
1417         config->policy_list = ( StreamTcpPolicy ** ) SnortPreprocAlloc(1,
1418                              sizeof( StreamTcpPolicy * ), PP_STREAM,
1419                              PP_MEM_CATEGORY_CONFIG);
1420     }
1421     else
1422     {
1423         uint32_t policyListSize = sizeof( StreamTcpPolicy * ) * ( config->num_policies );
1424         StreamTcpPolicy **tmpPolicyList = ( StreamTcpPolicy ** ) SnortPreprocAlloc(1,
1425                                               policyListSize, PP_STREAM,
1426                                               PP_MEM_CATEGORY_CONFIG);
1427 
1428         // copy the existing policies to new list, free old list and point to new...
1429         memcpy( tmpPolicyList, config->policy_list, policyListSize - sizeof( StreamTcpPolicy * ) );
1430         SnortPreprocFree( config->policy_list, sizeof( StreamTcpPolicy * ), PP_STREAM,
1431                          PP_MEM_CATEGORY_CONFIG );
1432         config->policy_list = tmpPolicyList;
1433     }
1434 
1435     // add new policy to end of the list
1436     config->policy_list[config->num_policies - 1] = policy;
1437 }
1438 
initTcpPolicyInstance(void)1439 StreamTcpPolicy *initTcpPolicyInstance( void )
1440 {
1441     StreamTcpPolicy *tcp_policy = (StreamTcpPolicy *) SnortPreprocAlloc(1,
1442                                           sizeof(StreamTcpPolicy), PP_STREAM,
1443                                           PP_MEM_CATEGORY_CONFIG);
1444 
1445     /* Initialize flush policy to Ignore */
1446     memcpy(&tcp_policy->flush_config, ignore_flush_policy,
1447             sizeof(FlushConfig) * MAX_PORTS);
1448 #ifdef TARGET_BASED
1449     memcpy(&tcp_policy->flush_config_protocol, ignore_flush_policy_protocol,
1450             sizeof(FlushConfig) * MAX_PROTOCOL_ORDINAL);
1451 #endif
1452 
1453     return tcp_policy;
1454 }
1455 
StreamTcpPolicyClone(StreamTcpPolicy * master,StreamConfig * config)1456 StreamTcpPolicy *StreamTcpPolicyClone( StreamTcpPolicy *master, StreamConfig *config )
1457 {
1458     StreamTcpPolicy *clone = initTcpPolicyInstance( );
1459 
1460     clone->policy = master->policy;
1461     clone->reassembly_policy = master->reassembly_policy;
1462     clone->flags = master->flags;
1463     clone->flush_factor = master->flush_factor;
1464     clone->session_timeout = master->session_timeout;
1465     clone->max_window = master->max_window;
1466     clone->overlap_limit = master->overlap_limit;
1467     clone->hs_timeout = master->hs_timeout;
1468     clone->max_queued_bytes = master->max_queued_bytes;
1469     clone->max_queued_segs = master->max_queued_segs;
1470     clone->max_consec_small_segs = master->max_consec_small_segs;
1471     clone->max_consec_small_seg_size = master->max_consec_small_seg_size;
1472     memcpy(clone->small_seg_ignore, master->small_seg_ignore, sizeof(master->small_seg_ignore));
1473 
1474     addStreamTcpPolicyToList( config->tcp_config, clone );
1475 
1476     return clone;
1477 }
1478 
StreamTcpPolicyInit(struct _SnortConfig * sc,StreamTcpConfig * config,char * args)1479 void StreamTcpPolicyInit(struct _SnortConfig *sc, StreamTcpConfig *config, char *args)
1480 {
1481     StreamTcpPolicy *s5TcpPolicy;
1482 
1483     if (config == NULL)
1484         return;
1485 
1486     // create list for caching port reassembly requests...
1487     StreamCreateReassemblyPortList( );
1488 
1489     s5TcpPolicy = initTcpPolicyInstance( );
1490     StreamParseTcpArgs(sc, config, args, s5TcpPolicy);
1491     addStreamTcpPolicyToList( config, s5TcpPolicy );
1492 
1493     if ( ScPafEnabledNewConf(sc) && !config->paf_config )
1494         config->paf_config = s5_paf_new();
1495 
1496     // register callback with Session that determines direction and client/server ports
1497     registerDirectionPortCallback( SESSION_PROTO_TCP, setTcpDirectionAndPorts );
1498 
1499     StreamPrintTcpConfig(s5TcpPolicy);
1500 
1501 #ifdef REG_TEST
1502     LogMessage("    TCP Session Size: %lu\n", (long unsigned int)sizeof(TcpSession));
1503 #endif
1504 }
1505 
StreamPolicyIdFromName(char * name)1506 static inline uint16_t StreamPolicyIdFromName(char *name)
1507 {
1508     if (!name)
1509     {
1510         return STREAM_POLICY_DEFAULT;
1511     }
1512 
1513     if(!strcasecmp(name, "bsd"))
1514     {
1515         return STREAM_POLICY_BSD;
1516     }
1517     else if(!strcasecmp(name, "old-linux"))
1518     {
1519         return STREAM_POLICY_OLD_LINUX;
1520     }
1521     else if(!strcasecmp(name, "linux"))
1522     {
1523         return STREAM_POLICY_LINUX;
1524     }
1525     else if(!strcasecmp(name, "first"))
1526     {
1527         return STREAM_POLICY_FIRST;
1528     }
1529     else if(!strcasecmp(name, "noack"))
1530     {
1531         return STREAM_POLICY_NOACK;
1532     }
1533     else if(!strcasecmp(name, "last"))
1534     {
1535         return STREAM_POLICY_LAST;
1536     }
1537     else if(!strcasecmp(name, "windows"))
1538     {
1539         return STREAM_POLICY_WINDOWS;
1540     }
1541     else if(!strcasecmp(name, "solaris"))
1542     {
1543         return STREAM_POLICY_SOLARIS;
1544     }
1545     else if(!strcasecmp(name, "win2003") ||
1546             !strcasecmp(name, "win2k3"))
1547     {
1548         return STREAM_POLICY_WINDOWS2K3;
1549     }
1550     else if(!strcasecmp(name, "vista"))
1551     {
1552         return STREAM_POLICY_VISTA;
1553     }
1554     else if(!strcasecmp(name, "hpux") ||
1555             !strcasecmp(name, "hpux11"))
1556     {
1557         return STREAM_POLICY_HPUX11;
1558     }
1559     else if(!strcasecmp(name, "hpux10"))
1560     {
1561         return STREAM_POLICY_HPUX10;
1562     }
1563     else if(!strcasecmp(name, "irix"))
1564     {
1565         return STREAM_POLICY_IRIX;
1566     }
1567     else if(!strcasecmp(name, "macos") ||
1568             !strcasecmp(name, "grannysmith"))
1569     {
1570         return STREAM_POLICY_MACOS;
1571     }
1572     return STREAM_POLICY_DEFAULT; /* BSD is the default */
1573 }
1574 
GetTcpReassemblyPolicy(int os_policy)1575 static inline uint16_t GetTcpReassemblyPolicy(int os_policy)
1576 {
1577     switch (os_policy)
1578     {
1579         case STREAM_POLICY_FIRST:
1580             return REASSEMBLY_POLICY_FIRST;
1581         case STREAM_POLICY_LINUX:
1582             return REASSEMBLY_POLICY_LINUX;
1583         case STREAM_POLICY_BSD:
1584             return REASSEMBLY_POLICY_BSD;
1585         case STREAM_POLICY_OLD_LINUX:
1586             return REASSEMBLY_POLICY_OLD_LINUX;
1587         case STREAM_POLICY_LAST:
1588             return REASSEMBLY_POLICY_LAST;
1589         case STREAM_POLICY_WINDOWS:
1590             return REASSEMBLY_POLICY_WINDOWS;
1591         case STREAM_POLICY_SOLARIS:
1592             return REASSEMBLY_POLICY_SOLARIS;
1593         case STREAM_POLICY_WINDOWS2K3:
1594             return REASSEMBLY_POLICY_WINDOWS2K3;
1595         case STREAM_POLICY_VISTA:
1596             return REASSEMBLY_POLICY_VISTA;
1597         case STREAM_POLICY_HPUX11:
1598             return REASSEMBLY_POLICY_HPUX11;
1599         case STREAM_POLICY_HPUX10:
1600             return REASSEMBLY_POLICY_HPUX10;
1601         case STREAM_POLICY_IRIX:
1602             return REASSEMBLY_POLICY_IRIX;
1603         case STREAM_POLICY_MACOS:
1604             return REASSEMBLY_POLICY_MACOS;
1605         case STREAM_POLICY_NOACK:
1606             return REASSEMBLY_POLICY_NOACK;
1607         default:
1608             return REASSEMBLY_POLICY_DEFAULT;
1609     }
1610 }
1611 
1612 #define STATIC_FP ((s5TcpPolicy->flags & STREAM_CONFIG_STATIC_FLUSHPOINTS)?1:0)
1613 
StreamParseTcpArgs(struct _SnortConfig * sc,StreamTcpConfig * config,char * args,StreamTcpPolicy * s5TcpPolicy)1614 static void StreamParseTcpArgs(struct _SnortConfig *sc, StreamTcpConfig *config, char *args, StreamTcpPolicy *s5TcpPolicy)
1615 {
1616     char **toks;
1617     int num_toks;
1618     int i;
1619     char **stoks = NULL;
1620     int s_toks;
1621     char *endPtr = NULL;
1622     char set_flush_policy = 0;
1623 #ifdef TARGET_BASED
1624     char set_target_flush_policy = 0;
1625 #endif
1626     int reassembly_direction = SSN_DIR_FROM_CLIENT;
1627     int32_t long_val = 0;
1628 
1629     s5TcpPolicy->policy = STREAM_POLICY_DEFAULT;
1630     s5TcpPolicy->reassembly_policy = REASSEMBLY_POLICY_DEFAULT;
1631     s5TcpPolicy->session_timeout = STREAM_DEFAULT_SSN_TIMEOUT;
1632     s5TcpPolicy->max_window = 0;
1633     s5TcpPolicy->flags = 0;
1634     s5TcpPolicy->max_queued_bytes = STREAM_DEFAULT_MAX_QUEUED_BYTES;
1635     s5TcpPolicy->max_queued_segs = STREAM_DEFAULT_MAX_QUEUED_SEGS;
1636 
1637     s5TcpPolicy->max_consec_small_segs = STREAM_DEFAULT_CONSEC_SMALL_SEGS;
1638     s5TcpPolicy->max_consec_small_seg_size = STREAM_DEFAULT_MAX_SMALL_SEG_SIZE;
1639     s5TcpPolicy->log_asymmetric_traffic = false;
1640 
1641     if(args != NULL && strlen(args) != 0)
1642     {
1643         toks = mSplit(args, ",", 0, &num_toks, 0);
1644 
1645         for (i = 0; i < num_toks; i++)
1646         {
1647             if(!strcasecmp(toks[i], "use_static_footprint_sizes"))
1648                 s5TcpPolicy->flags |= STREAM_CONFIG_STATIC_FLUSHPOINTS;
1649         }
1650 
1651         for (i = 0; i < num_toks; i++)
1652         {
1653             int max_s_toks = 1;  // set to 0 to disable check
1654             stoks = mSplit(toks[i], " ", 3, &s_toks, 0);
1655 
1656             if (s_toks == 0)
1657             {
1658                 FatalError("%s(%d) => Missing parameter in Stream TCP config.\n",
1659                         file_name, file_line);
1660             }
1661 
1662             if(!strcasecmp(stoks[0], "timeout"))
1663             {
1664                 if(stoks[1])
1665                 {
1666                     s5TcpPolicy->session_timeout = strtoul(stoks[1], &endPtr, 10);
1667                 }
1668 
1669                 if (!stoks[1] || (endPtr == &stoks[1][0]) || *endPtr)
1670                 {
1671                     FatalError("%s(%d) => Invalid timeout in config file.  "
1672                             "Integer parameter required.\n",
1673                             file_name, file_line);
1674                 }
1675 
1676                 if ((s5TcpPolicy->session_timeout > STREAM_MAX_SSN_TIMEOUT) ||
1677                         (s5TcpPolicy->session_timeout < STREAM_MIN_SSN_TIMEOUT))
1678                 {
1679                     FatalError("%s(%d) => Invalid timeout in config file.  "
1680                             "Must be between %d and %d\n",
1681                             file_name, file_line,
1682                             STREAM_MIN_SSN_TIMEOUT, STREAM_MAX_SSN_TIMEOUT);
1683                 }
1684                 max_s_toks = 2;
1685             }
1686             else if(!strcasecmp(stoks[0], "log_asymmetric_traffic"))
1687             {
1688                 if(stoks[1])
1689                 {
1690                     if(!strcasecmp(stoks[1], "no"))
1691                            s5TcpPolicy->log_asymmetric_traffic = false;
1692                     else if(!strcasecmp(stoks[1], "yes"))
1693                            s5TcpPolicy->log_asymmetric_traffic = true;
1694                     else
1695                            FatalError("%s(%d) => invalid: value must be 'yes' or 'no'\n", file_name, file_line);
1696                 }
1697                 else
1698                 {
1699                     FatalError("%s(%d) => 'log_asymmetric_traffic' missing option\n", file_name, file_line);
1700                 }
1701                 max_s_toks = 2;
1702             }
1703             else if(!strcasecmp(stoks[0], "overlap_limit"))
1704             {
1705                 if(stoks[1])
1706                 {
1707                     long_val = SnortStrtol(stoks[1], &endPtr, 10);
1708                     if (errno == ERANGE)
1709                     {
1710                         errno = 0;
1711                         long_val = -1;
1712                     }
1713                     s5TcpPolicy->overlap_limit = (uint8_t)long_val;
1714                 }
1715 
1716                 if (!stoks[1] || (endPtr == &stoks[1][0]))
1717                 {
1718                     FatalError("%s(%d) => Invalid overlap limit in config file."
1719                             "Integer parameter required\n",
1720                             file_name, file_line);
1721                 }
1722 
1723                 if ((long_val > STREAM_MAX_OVERLAP_LIMIT) ||
1724                         (long_val < STREAM_MIN_OVERLAP_LIMIT))
1725                 {
1726                     FatalError("%s(%d) => Invalid overlap limit in config file."
1727                             "  Must be between %d and %d\n",
1728                             file_name, file_line,
1729                             STREAM_MIN_OVERLAP_LIMIT, STREAM_MAX_OVERLAP_LIMIT);
1730                 }
1731                 max_s_toks = 2;
1732             }
1733             else if(!strcasecmp(stoks[0], "detect_anomalies"))
1734             {
1735                 s5TcpPolicy->flags |=  STREAM_CONFIG_ENABLE_ALERTS;
1736             }
1737             else if(!strcasecmp(stoks[0], "policy"))
1738             {
1739                 if(s_toks != 2)
1740                     ParseError("Invalid Stream TCP policy option");
1741                 s5TcpPolicy->policy = StreamPolicyIdFromName(stoks[1]);
1742 
1743                 if ((s5TcpPolicy->policy == STREAM_POLICY_DEFAULT) &&
1744                         (strcasecmp(stoks[1], "bsd")))
1745                 {
1746                     /* Default is BSD.  If we don't have "bsd", its
1747                      * the default and invalid.
1748                      */
1749                     FatalError("%s(%d) => Bad policy name \"%s\"\n",
1750                             file_name, file_line, stoks[1]);
1751                 }
1752                 s5TcpPolicy->reassembly_policy =
1753                     GetTcpReassemblyPolicy(s5TcpPolicy->policy);
1754 
1755                 max_s_toks = 2;
1756             }
1757             else if(!strcasecmp(stoks[0], "require_3whs"))
1758             {
1759                 s5TcpPolicy->flags |= STREAM_CONFIG_REQUIRE_3WHS;
1760 
1761                 if (s_toks > 1)
1762                 {
1763                     s5TcpPolicy->hs_timeout = SnortStrtoul(stoks[1], &endPtr, 10);
1764 
1765                     if ((endPtr == &stoks[1][0]) || (*endPtr != '\0') || (errno == ERANGE))
1766                     {
1767                         FatalError("%s(%d) => Invalid 3Way Handshake allowable.  Integer parameter required.\n",
1768                                 file_name, file_line);
1769                     }
1770 
1771                     if (s5TcpPolicy->hs_timeout > STREAM_MAX_SSN_TIMEOUT)
1772                     {
1773                         FatalError("%s(%d) => Invalid handshake timeout in "
1774                                 "config file.  Must be between %d and %d\n",
1775                                 file_name, file_line,
1776                                 STREAM_MIN_ALT_HS_TIMEOUT, STREAM_MAX_SSN_TIMEOUT);
1777                     }
1778                 }
1779 
1780                 max_s_toks = 2;
1781             }
1782             else if(!strcasecmp(stoks[0], "bind_to"))
1783             {
1784                 if (s_toks < 2)
1785                 {
1786                     FatalError("%s(%d) => Invalid Stream TCP Policy option - "
1787                             "\"bind_to\" option requires an argument.\n",
1788                             file_name, file_line);
1789                 }
1790 
1791                 if(strstr(stoks[1], "["))
1792                 {
1793                     FatalError("%s(%d) => Invalid Stream TCP Policy option.  IP lists are not allowed.\n",
1794                             file_name, file_line);
1795                 }
1796 
1797                 s5TcpPolicy->bound_addrs = IpAddrSetParse(sc, stoks[1]);
1798                 max_s_toks = 2;
1799             }
1800             else if(!strcasecmp(stoks[0], "max_window"))
1801             {
1802                 if(stoks[1])
1803                 {
1804                     long_val = SnortStrtol(stoks[1], &endPtr, 10);
1805                     if (errno == ERANGE)
1806                     {
1807                         errno = 0;
1808                         FatalError("%s(%d) => Invalid Max Window size.  Integer parameter required.\n",
1809                                 file_name, file_line);
1810                     }
1811                     s5TcpPolicy->max_window = (uint32_t)long_val;
1812                 }
1813 
1814                 if (!stoks[1] || (endPtr == &stoks[1][0]))
1815                 {
1816                     FatalError("%s(%d) => Invalid Max Window size.  Integer parameter required.\n",
1817                             file_name, file_line);
1818                 }
1819 
1820                 if ((long_val > STREAM_MAX_MAX_WINDOW) ||
1821                         (long_val < STREAM_MIN_MAX_WINDOW))
1822                 {
1823                     FatalError("%s(%d) => Invalid Max Window size."
1824                             "  Must be between %d and %d\n",
1825                             file_name, file_line,
1826                             STREAM_MIN_MAX_WINDOW, STREAM_MAX_MAX_WINDOW);
1827                 }
1828                 max_s_toks = 2;
1829             }
1830             else if(!strcasecmp(stoks[0], "use_static_footprint_sizes"))
1831             {
1832                 // we already handled this one above
1833             }
1834             else if(!strcasecmp(stoks[0], "flush_factor"))
1835             {
1836                 if (stoks[1])
1837                 {
1838                     s5TcpPolicy->flush_factor = (uint16_t)SnortStrtoulRange(
1839                             stoks[1], &endPtr, 10, 0, STREAM_MAX_FLUSH_FACTOR);
1840                 }
1841                 if (
1842                         (!stoks[1] || (endPtr == &stoks[1][0])) ||
1843                         (s5TcpPolicy->flush_factor > STREAM_MAX_FLUSH_FACTOR))
1844                 {
1845                     FatalError("%s(%d) => 'flush_factor %d' invalid: "
1846                             "value must be between 0 and %d segments.\n",
1847                             file_name, file_line, s5TcpPolicy->flush_factor,
1848                             STREAM_MAX_FLUSH_FACTOR);
1849                 }
1850                 max_s_toks = 2;
1851             }
1852             else if(!strcasecmp(stoks[0], "dont_store_large_packets"))
1853             {
1854                 s5TcpPolicy->flags |= STREAM_CONFIG_PERFORMANCE;
1855             }
1856             else if(!strcasecmp(stoks[0], "check_session_hijacking"))
1857             {
1858                 s5TcpPolicy->flags |= STREAM_CONFIG_CHECK_SESSION_HIJACKING;
1859             }
1860             else if(!strcasecmp(stoks[0], "ignore_any_rules"))
1861             {
1862                 s5TcpPolicy->flags |= STREAM_CONFIG_IGNORE_ANY;
1863             }
1864             else if(!strcasecmp(stoks[0], "dont_reassemble_async"))
1865             {
1866                 s5TcpPolicy->flags |= STREAM_CONFIG_NO_ASYNC_REASSEMBLY;
1867             }
1868             else if(!strcasecmp(stoks[0], "max_queued_bytes"))
1869             {
1870                 if(stoks[1])
1871                 {
1872                     long_val = SnortStrtol(stoks[1], &endPtr, 10);
1873                     if (errno == ERANGE)
1874                     {
1875                         errno = 0;
1876                         FatalError("%s(%d) => Invalid Max Queued Bytes.  Integer parameter required.\n",
1877                                 file_name, file_line);
1878                     }
1879                     s5TcpPolicy->max_queued_bytes = (uint32_t)long_val;
1880                 }
1881 
1882                 if (!stoks[1] || (endPtr == &stoks[1][0]))
1883                 {
1884                     FatalError("%s(%d) => Invalid Max Queued Bytes.  Integer parameter required.\n",
1885                             file_name, file_line);
1886                 }
1887                 if (((long_val > STREAM_MAX_MAX_QUEUED_BYTES) ||
1888                             (long_val < STREAM_MIN_MAX_QUEUED_BYTES)) &&
1889                         (long_val != 0))
1890                 {
1891                     FatalError("%s(%d) => Invalid Max Queued Bytes."
1892                             "  Must be 0 (disabled) or between %d and %d\n",
1893                             file_name, file_line,
1894                             STREAM_MIN_MAX_QUEUED_BYTES, STREAM_MAX_MAX_QUEUED_BYTES);
1895                 }
1896                 max_s_toks = 2;
1897             }
1898             else if(!strcasecmp(stoks[0], "max_queued_segs"))
1899             {
1900                 if(stoks[1])
1901                 {
1902                     long_val = SnortStrtol(stoks[1], &endPtr, 10);
1903                     if (errno == ERANGE)
1904                     {
1905                         errno = 0;
1906                         FatalError("%s(%d) => Invalid Max Queued Bytes.  Integer parameter required.\n",
1907                                 file_name, file_line);
1908                     }
1909                     s5TcpPolicy->max_queued_segs = (uint32_t)long_val;
1910                 }
1911 
1912                 if (!stoks[1] || (endPtr == &stoks[1][0]))
1913                 {
1914                     FatalError("%s(%d) => Invalid Max Queued Bytes.  Integer parameter required.\n",
1915                             file_name, file_line);
1916                 }
1917 
1918                 if (((long_val > STREAM_MAX_MAX_QUEUED_SEGS) ||
1919                             (long_val < STREAM_MIN_MAX_QUEUED_SEGS)) &&
1920                         (long_val != 0))
1921                 {
1922                     FatalError("%s(%d) => Invalid Max Queued Bytes."
1923                             "  Must be 0 (disabled) or between %d and %d\n",
1924                             file_name, file_line,
1925                             STREAM_MIN_MAX_QUEUED_SEGS, STREAM_MAX_MAX_QUEUED_SEGS);
1926                 }
1927                 max_s_toks = 2;
1928             }
1929             else if (!strcasecmp(stoks[0], "small_segments"))
1930             {
1931                 char **ptoks;
1932                 int num_ptoks;
1933 
1934                 /* Small segments takes at least 3 parameters... */
1935                 if (s_toks < 3)
1936                 {
1937                     FatalError("%s(%d) => Insufficient parameters to small "
1938                             "segments configuration.  Syntax is: "
1939                             "<number> bytes <number> ignore_ports p1 p2, "
1940                             "with ignore_ports being an optional parameter\n",
1941                             file_name, file_line);
1942                 }
1943 
1944                 /* first the number of consecutive segments */
1945                 long_val = SnortStrtol(stoks[1], &endPtr, 10);
1946                 if (errno == ERANGE)
1947                 {
1948                     errno = 0;
1949                     FatalError("%s(%d) => Invalid Small Segment number.  Integer parameter required.\n",
1950                             file_name, file_line);
1951                 }
1952                 s5TcpPolicy->max_consec_small_segs = (uint32_t)long_val;
1953 
1954                 if ((long_val > STREAM_MAX_CONSEC_SMALL_SEGS) ||
1955                         (long_val < STREAM_MIN_CONSEC_SMALL_SEGS))
1956                 {
1957                     FatalError("%s(%d) => Invalid Small Segments."
1958                             "  Must be integer between %d and %d, inclusive\n",
1959                             file_name, file_line,
1960                             STREAM_MIN_CONSEC_SMALL_SEGS, STREAM_MAX_CONSEC_SMALL_SEGS);
1961                 }
1962 
1963                 ptoks = mSplit(stoks[2], " ", MAX_PORTS + 3, &num_ptoks, 0);
1964 
1965                 /* the bytes keyword */
1966                 if (strcasecmp(ptoks[0], "bytes") || (num_ptoks < 2))
1967                 {
1968                     FatalError("%s(%d) => Insufficient parameters to small "
1969                             "segments configuration.  Syntax is: "
1970                             "<number> bytes <number> ignore_ports p1 p2, "
1971                             "with ignore_ports being an optional parameter\n",
1972                             file_name, file_line);
1973                 }
1974 
1975                 /* the minimum bytes for a segment to be considered "small" */
1976                 long_val = SnortStrtol(ptoks[1], &endPtr, 10);
1977                 if (errno == ERANGE)
1978                 {
1979                     errno = 0;
1980                     FatalError("%s(%d) => Invalid Small Segment bytes.  Integer parameter required.\n",
1981                             file_name, file_line);
1982                 }
1983                 s5TcpPolicy->max_consec_small_seg_size = (uint32_t)long_val;
1984 
1985                 if ((long_val > STREAM_MAX_MAX_SMALL_SEG_SIZE) ||
1986                         (long_val < STREAM_MIN_MAX_SMALL_SEG_SIZE))
1987                 {
1988                     FatalError("%s(%d) => Invalid Small Segments bytes."
1989                             "  Must be integer between %d and %d, inclusive\n",
1990                             file_name, file_line,
1991                             STREAM_MIN_MAX_SMALL_SEG_SIZE, STREAM_MAX_MAX_SMALL_SEG_SIZE);
1992                 }
1993 
1994                 /* and the optional ignore_ports */
1995                 if (num_ptoks > 2)
1996                 {
1997                     int j;
1998                     unsigned short port = 0;
1999                     long long_port = 0;
2000                     if (strcasecmp(ptoks[2], "ignore_ports") || (num_ptoks < 4))
2001                     {
2002                         FatalError("%s(%d) => Insufficient parameters to small "
2003                                 "segments configuration.  Syntax is: "
2004                                 "<number> bytes <number> ignore_ports p1 p2, "
2005                                 "with ignore_ports being an optional parameter\n",
2006                                 file_name, file_line);
2007                     }
2008 
2009                     for (j=3; j<num_ptoks;j++)
2010                     {
2011                         if (ptoks[j])
2012                         {
2013                             long_port = strtol(ptoks[j], &endPtr, 10);
2014                         }
2015                         if (!ptoks[j] || (endPtr == &ptoks[j][0]))
2016                         {
2017                             FatalError("%s(%d) => Invalid Port for small segments ignore_ports parameter.  Integer parameter required.\n",
2018                                     file_name, file_line);
2019                         }
2020 
2021                         if ((long_port < 0) || (long_port > MAX_PORTS-1))
2022                         {
2023                             FatalError(
2024                                     "%s(%d) => Invalid port %ld for small segments ignore_ports "
2025                                     "parameter, must be between 0 and %d, inclusive\n",
2026                                     file_name, file_line, long_port, MAX_PORTS-1);
2027                         }
2028                         port = (unsigned short)long_port;
2029 
2030                         s5TcpPolicy->small_seg_ignore[port/8] |= (1 << (port %8));
2031                     }
2032                 }
2033                 max_s_toks = 0; // we already checked all tokens
2034                 mSplitFree(&ptoks, num_ptoks);
2035             }
2036             else if (!strcasecmp(stoks[0], "ports"))
2037             {
2038                 if (s_toks > 1)
2039                 {
2040                     if(!strcasecmp(stoks[1], "client"))
2041                     {
2042                         reassembly_direction = SSN_DIR_FROM_CLIENT;
2043                     }
2044                     else if(!strcasecmp(stoks[1], "server"))
2045                     {
2046                         reassembly_direction = SSN_DIR_FROM_SERVER;
2047                     }
2048                     else if(!strcasecmp(stoks[1], "both"))
2049                     {
2050                         reassembly_direction = SSN_DIR_BOTH;
2051                     }
2052                     else
2053                     {
2054                         FatalError(
2055                                 "%s(%d) => Invalid direction for reassembly "
2056                                 "configuration \"%s\".  Valid values are 'client', "
2057                                 "'server', or 'both'.\n",
2058                                 file_name, file_line, stoks[1]);
2059                     }
2060                 }
2061 
2062                 if (s_toks > 2)
2063                 {
2064                     char **ptoks;
2065                     int num_ptoks;
2066                     int j;
2067                     unsigned short port = 0;
2068                     long long_port = 0;
2069 
2070                     /* Initialize it if not already... */
2071                     InitFlushPointList(&s5TcpPolicy->flush_point_list, 192, 128, STATIC_FP);
2072 
2073                     if (!strcasecmp(stoks[2], "all"))
2074                     {
2075                         for (j=0; j<MAX_PORTS; j++)
2076                         {
2077                             if (reassembly_direction & SSN_DIR_FROM_CLIENT)
2078                             {
2079                                 FlushMgr *flush_mgr = &s5TcpPolicy->flush_config[j].client;
2080                                 FlushPointList *flush_point_list = &s5TcpPolicy->flush_point_list;
2081                                 InitFlushMgr(sc, flush_mgr, flush_point_list, STREAM_FLPOLICY_FOOTPRINT, 0);
2082                             }
2083                             if (reassembly_direction & SSN_DIR_FROM_SERVER)
2084                             {
2085                                 FlushMgr *flush_mgr = &s5TcpPolicy->flush_config[j].server;
2086                                 FlushPointList *flush_point_list = &s5TcpPolicy->flush_point_list;
2087                                 InitFlushMgr(sc, flush_mgr, flush_point_list, STREAM_FLPOLICY_FOOTPRINT, 0);
2088                             }
2089                         }
2090                     }
2091                     else if (!strcasecmp(stoks[2], "none"))
2092                     {
2093                         for (j=0; j<MAX_PORTS; j++)
2094                         {
2095                             if (reassembly_direction & SSN_DIR_FROM_CLIENT)
2096                             {
2097                                 FlushMgr *flush_mgr = &s5TcpPolicy->flush_config[j].client;
2098                                 flush_mgr->flush_policy = STREAM_FLPOLICY_IGNORE;
2099                             }
2100                             if (reassembly_direction & SSN_DIR_FROM_SERVER)
2101                             {
2102                                 FlushMgr *flush_mgr = &s5TcpPolicy->flush_config[j].server;
2103                                 flush_mgr->flush_policy = STREAM_FLPOLICY_IGNORE;
2104                             }
2105                         }
2106                     }
2107                     else
2108                     {
2109                         ptoks = mSplit(stoks[2], " ", MAX_PORTS, &num_ptoks, 0);
2110 
2111                         for (j=0; j < num_ptoks; j++)
2112                         {
2113                             FlushPolicy flush_policy = STREAM_FLPOLICY_FOOTPRINT;
2114 
2115                             if (ptoks[j])
2116                             {
2117                                 // check for '!' not port syntax used to disable reassembly on a port
2118                                 // even if requested later by a preproc...
2119                                 if ( ptoks[j][0] == '!' )
2120                                 {
2121                                     flush_policy = STREAM_FLPOLICY_DISABLED;
2122                                     long_port = strtol(&ptoks[j][1], &endPtr, 10);
2123                                 }
2124                                 else
2125                                 {
2126                                     long_port = strtol(ptoks[j], &endPtr, 10);
2127                                 }
2128                             }
2129 
2130                             if (!ptoks[j] || (endPtr == &ptoks[j][0]))
2131                             {
2132                                 FatalError("%s(%d) => Invalid Port list.  Integer parameter required.\n",
2133                                         file_name, file_line);
2134                             }
2135 
2136                             if ((long_port < 0) || (long_port > MAX_PORTS-1))
2137                             {
2138                                 FatalError(
2139                                         "%s(%d) => Invalid port %ld, must be between 0 and %d, "
2140                                         "inclusive\n",
2141                                         file_name, file_line, long_port, MAX_PORTS-1);
2142                             }
2143                             port = (unsigned short)long_port;
2144 
2145                             if (reassembly_direction & SSN_DIR_FROM_CLIENT)
2146                             {
2147                                 FlushMgr *flush_mgr = &s5TcpPolicy->flush_config[port].client;
2148                                 FlushPointList *flush_point_list = &s5TcpPolicy->flush_point_list;
2149                                 InitFlushMgr(sc, flush_mgr, flush_point_list, flush_policy, 0);
2150                             }
2151                             if (reassembly_direction & SSN_DIR_FROM_SERVER)
2152                             {
2153                                 FlushMgr *flush_mgr = &s5TcpPolicy->flush_config[port].server;
2154                                 FlushPointList *flush_point_list = &s5TcpPolicy->flush_point_list;
2155                                 InitFlushMgr(sc, flush_mgr, flush_point_list, flush_policy, 0);
2156                             }
2157                         }
2158                         mSplitFree(&ptoks, num_ptoks);
2159                     }
2160                     set_flush_policy = 1;
2161                 }
2162                 max_s_toks = 0;  // we already checked all tokens
2163             }
2164 #ifdef TARGET_BASED
2165             else if (!strcasecmp(stoks[0], "protocol"))
2166             {
2167                 if (s_toks > 1)
2168                 {
2169                     if(!strcasecmp(stoks[1], "client"))
2170                     {
2171                         reassembly_direction = SSN_DIR_FROM_CLIENT;
2172                     }
2173                     else if(!strcasecmp(stoks[1], "server"))
2174                     {
2175                         reassembly_direction = SSN_DIR_FROM_SERVER;
2176                     }
2177                     else if(!strcasecmp(stoks[1], "both"))
2178                     {
2179                         reassembly_direction = SSN_DIR_BOTH;
2180                     }
2181                     else
2182                     {
2183                         FatalError(
2184                                 "%s(%d) => Invalid direction for reassembly "
2185                                 "configuration \"%s\".  Valid values are 'client', "
2186                                 "'server', or 'both'.\n",
2187                                 file_name, file_line, stoks[1]);
2188                     }
2189                 }
2190 
2191                 if (s_toks > 2)
2192                 {
2193                     char **ptoks;
2194                     int num_ptoks;
2195                     int j;
2196 
2197                     /* Initialize it if not already... */
2198                     InitFlushPointList(&s5TcpPolicy->flush_point_list, 192, 128, STATIC_FP);
2199 
2200                     if (!strcasecmp(stoks[2], "all"))
2201                     {
2202                         for (j=1; j<MAX_PROTOCOL_ORDINAL; j++)
2203                         {
2204                             if (reassembly_direction & SSN_DIR_FROM_CLIENT)
2205                             {
2206                                 FlushMgr *flush_mgr = &s5TcpPolicy->flush_config_protocol[j].client;
2207                                 FlushPointList *flush_point_list = &s5TcpPolicy->flush_point_list;
2208                                 InitFlushMgr(sc, flush_mgr, flush_point_list, STREAM_FLPOLICY_FOOTPRINT, 0);
2209                             }
2210                             if (reassembly_direction & SSN_DIR_FROM_SERVER)
2211                             {
2212                                 FlushMgr *flush_mgr = &s5TcpPolicy->flush_config_protocol[j].server;
2213                                 FlushPointList *flush_point_list = &s5TcpPolicy->flush_point_list;
2214                                 InitFlushMgr(sc, flush_mgr, flush_point_list, STREAM_FLPOLICY_FOOTPRINT, 0);
2215                             }
2216                             s5TcpPolicy->flush_config_protocol[j].configured = 1;
2217                         }
2218                     }
2219                     else if (!strcasecmp(stoks[2], "none"))
2220                     {
2221                         for (j=1; j<MAX_PROTOCOL_ORDINAL; j++)
2222                         {
2223                             if (reassembly_direction & SSN_DIR_FROM_CLIENT)
2224                             {
2225                                 FlushMgr *flush_mgr = &s5TcpPolicy->flush_config_protocol[j].client;
2226                                 flush_mgr->flush_policy = STREAM_FLPOLICY_IGNORE;
2227                             }
2228                             if (reassembly_direction & SSN_DIR_FROM_SERVER)
2229                             {
2230                                 FlushMgr *flush_mgr = &s5TcpPolicy->flush_config_protocol[j].server;
2231                                 flush_mgr->flush_policy = STREAM_FLPOLICY_IGNORE;
2232                             }
2233                             s5TcpPolicy->flush_config_protocol[j].configured = 1;
2234                         }
2235                     }
2236                     else
2237                     {
2238                         ptoks = mSplit(stoks[2], " ", MAX_PROTOCOL_ORDINAL, &num_ptoks, 0);
2239 
2240                         for (j=0;j<num_ptoks;j++)
2241                         {
2242                             int16_t proto_ordinal;
2243                             if (!ptoks[j])
2244                             {
2245                                 FatalError("%s(%d) => Invalid Protocol Name.  Protocol name must be specified.\n",
2246                                         file_name, file_line);
2247                             }
2248                             /* First look it up */
2249                             proto_ordinal = FindProtocolReference(ptoks[j]);
2250                             if (proto_ordinal == SFTARGET_UNKNOWN_PROTOCOL)
2251                             {
2252                                 /* Not known -- add it */
2253                                 proto_ordinal = AddProtocolReference(ptoks[j]);
2254                                 if (proto_ordinal == SFTARGET_UNKNOWN_PROTOCOL)
2255                                 {
2256                                     FatalError("%s(%d) => Failed to find protocol reference for '%s'\n",
2257                                             file_name, file_line, ptoks[j]);
2258                                 }
2259                             }
2260 
2261                             if (reassembly_direction & SSN_DIR_FROM_CLIENT)
2262                             {
2263                                 FlushMgr *flush_mgr = &s5TcpPolicy->flush_config_protocol[proto_ordinal].client;
2264                                 FlushPointList *flush_point_list = &s5TcpPolicy->flush_point_list;
2265                                 InitFlushMgr(sc, flush_mgr, flush_point_list, STREAM_FLPOLICY_FOOTPRINT, 0);
2266                             }
2267                             if (reassembly_direction & SSN_DIR_FROM_SERVER)
2268                             {
2269                                 FlushMgr *flush_mgr = &s5TcpPolicy->flush_config_protocol[proto_ordinal].server;
2270                                 FlushPointList *flush_point_list = &s5TcpPolicy->flush_point_list;
2271                                 InitFlushMgr(sc, flush_mgr, flush_point_list, STREAM_FLPOLICY_FOOTPRINT, 0);
2272                             }
2273                             s5TcpPolicy->flush_config_protocol[proto_ordinal].configured = 1;
2274                         }
2275                         mSplitFree(&ptoks, num_ptoks);
2276                     }
2277                     set_target_flush_policy = 1;
2278                 }
2279                 max_s_toks = 0;  // we already checked all tokens
2280             }
2281 #endif
2282             else
2283             {
2284                 FatalError("%s(%d) => Invalid Stream TCP policy option\n",
2285                         file_name, file_line);
2286             }
2287 
2288             if ( max_s_toks && (s_toks > max_s_toks) )
2289             {
2290                 FatalError("%s(%d) => Invalid Stream TCP Policy option.  Missing comma?\n",
2291                         file_name, file_line);
2292             }
2293             mSplitFree(&stoks, s_toks);
2294         }
2295 
2296         mSplitFree(&toks, num_toks);
2297     }
2298 
2299     if (s5TcpPolicy->bound_addrs == NULL)
2300     {
2301         if (config->default_policy != NULL)
2302         {
2303             FatalError("%s(%d) => Default Stream TCP Policy already set. "
2304                     "This policy must be bound to a specific host or "
2305                     "network.\n", file_name, file_line);
2306         }
2307 
2308         config->default_policy = s5TcpPolicy;
2309     }
2310     else
2311     {
2312         if (s5TcpPolicy->flags & STREAM_CONFIG_IGNORE_ANY)
2313         {
2314             FatalError("%s(%d) => \"ignore_any_rules\" option can be used only"
2315                     " with Default Stream TCP Policy\n", file_name, file_line);
2316         }
2317     }
2318 
2319     if (!set_flush_policy)
2320     {
2321         /* Initialize it if not already... */
2322         InitFlushPointList(&s5TcpPolicy->flush_point_list, 192, 128, STATIC_FP);
2323         for (i=0; i<DEFAULT_PORTS_SIZE; i++)
2324         {
2325             if (reassembly_direction & SSN_DIR_FROM_CLIENT)
2326             {
2327                 FlushMgr *flush_mgr = &s5TcpPolicy->flush_config[default_ports[i]].client;
2328                 FlushPointList *flush_point_list = &s5TcpPolicy->flush_point_list;
2329                 InitFlushMgr(sc, flush_mgr, flush_point_list, STREAM_FLPOLICY_FOOTPRINT, 0);
2330             }
2331             if (reassembly_direction & SSN_DIR_FROM_SERVER)
2332             {
2333                 FlushMgr *flush_mgr = &s5TcpPolicy->flush_config[default_ports[i]].server;
2334                 FlushPointList *flush_point_list = &s5TcpPolicy->flush_point_list;
2335                 InitFlushMgr(sc, flush_mgr, flush_point_list, STREAM_FLPOLICY_FOOTPRINT, 0);
2336             }
2337         }
2338     }
2339 
2340 #ifdef TARGET_BASED
2341     if (!set_target_flush_policy)
2342     {
2343         int app_id;
2344         /* Initialize it if not already... */
2345         InitFlushPointList(&s5TcpPolicy->flush_point_list, 192, 128, STATIC_FP);
2346         for (i=0; i<(int)(sizeof(default_protocols)/sizeof(char *)); i++)
2347         {
2348             /* Look up the protocol by name. Add it if it doesn't exist. */
2349             app_id = FindProtocolReference(default_protocols[i]);
2350             if (app_id == SFTARGET_UNKNOWN_PROTOCOL)
2351             {
2352                 app_id = AddProtocolReference(default_protocols[i]);
2353             }
2354 
2355             /* While this should never happen, I don't feel guilty adding this
2356              * logic as it executes at parse time. */
2357             if (app_id == SFTARGET_UNKNOWN_PROTOCOL)
2358                 continue;
2359 
2360             /* Set flush managers. */
2361             if (reassembly_direction & SSN_DIR_FROM_CLIENT)
2362             {
2363                 FlushMgr *flush_mgr = &s5TcpPolicy->flush_config_protocol[app_id].client;
2364                 FlushPointList *flush_point_list = &s5TcpPolicy->flush_point_list;
2365                 InitFlushMgr(sc, flush_mgr, flush_point_list, STREAM_FLPOLICY_FOOTPRINT, 0);
2366             }
2367             if (reassembly_direction & SSN_DIR_FROM_SERVER)
2368             {
2369                 FlushMgr *flush_mgr = &s5TcpPolicy->flush_config_protocol[app_id].server;
2370                 FlushPointList *flush_point_list = &s5TcpPolicy->flush_point_list;
2371                 InitFlushMgr(sc, flush_mgr, flush_point_list, STREAM_FLPOLICY_FOOTPRINT, 0);
2372             }
2373             s5TcpPolicy->flush_config_protocol[app_id].configured = 1;
2374         }
2375     }
2376 #endif
2377 }
2378 
StreamPrintTcpConfig(StreamTcpPolicy * s5TcpPolicy)2379 static void StreamPrintTcpConfig(StreamTcpPolicy *s5TcpPolicy)
2380 {
2381     int i=0, j=0;
2382     LogMessage("Stream TCP Policy config:\n");
2383     if (s5TcpPolicy->bound_addrs != NULL)
2384     {
2385         IpAddrSetPrint("    Bound Addresses: ", s5TcpPolicy->bound_addrs);
2386     }
2387     else
2388     {
2389         LogMessage("    Bound Address: default\n");
2390     }
2391     LogMessage("    Reassembly Policy: %s\n",
2392             reassembly_policy_names[s5TcpPolicy->reassembly_policy]);
2393     LogMessage("    Timeout: %d seconds\n", s5TcpPolicy->session_timeout);
2394     if (s5TcpPolicy->max_window != 0)
2395         LogMessage("    Max TCP Window: %u\n", s5TcpPolicy->max_window);
2396     if (s5TcpPolicy->overlap_limit)
2397         LogMessage("    Limit on TCP Overlaps: %d\n", s5TcpPolicy->overlap_limit);
2398     if (s5TcpPolicy->max_queued_bytes != 0)
2399     {
2400         LogMessage("    Maximum number of bytes to queue per session: %d\n",
2401                 s5TcpPolicy->max_queued_bytes);
2402     }
2403     if (s5TcpPolicy->max_queued_segs != 0)
2404     {
2405         LogMessage("    Maximum number of segs to queue per session: %d\n",
2406                 s5TcpPolicy->max_queued_segs);
2407     }
2408     if (s5TcpPolicy->flags)
2409     {
2410         LogMessage("    Options:\n");
2411         if (s5TcpPolicy->flags & STREAM_CONFIG_REQUIRE_3WHS)
2412         {
2413             LogMessage("        Require 3-Way Handshake: YES\n");
2414             if (s5TcpPolicy->hs_timeout != 0)
2415             {
2416                 LogMessage("        3-Way Handshake Timeout: %d\n",
2417                         s5TcpPolicy->hs_timeout);
2418             }
2419         }
2420         if (s5TcpPolicy->flags & STREAM_CONFIG_ENABLE_ALERTS)
2421         {
2422             LogMessage("        Detect Anomalies: YES\n");
2423         }
2424         if (s5TcpPolicy->flags & STREAM_CONFIG_STATIC_FLUSHPOINTS)
2425         {
2426             LogMessage("        Static Flushpoint Sizes: YES\n");
2427         }
2428         if (s5TcpPolicy->flags & STREAM_CONFIG_PERFORMANCE)
2429         {
2430             LogMessage("        Don't Queue Large Packets for Reassembly: YES\n");
2431         }
2432         if (s5TcpPolicy->flags & STREAM_CONFIG_CHECK_SESSION_HIJACKING)
2433         {
2434             LogMessage("        Check for TCP Session Hijacking: YES\n");
2435         }
2436         if (s5TcpPolicy->flags & STREAM_CONFIG_IGNORE_ANY)
2437         {
2438             LogMessage("        Ignore Any -> Any Rules: YES\n");
2439         }
2440         if (s5TcpPolicy->flags & STREAM_CONFIG_NO_ASYNC_REASSEMBLY)
2441         {
2442             LogMessage("        Don't queue packets on one-sided sessions: YES\n");
2443         }
2444     }
2445     LogMessage("    Reassembly Ports:\n");
2446     for (i=0; i<MAX_PORTS; i++)
2447     {
2448         int direction = 0;
2449         int client_flushpolicy = s5TcpPolicy->flush_config[i].client.flush_policy;
2450         int server_flushpolicy = s5TcpPolicy->flush_config[i].server.flush_policy;
2451         char client_policy_str[STD_BUF];
2452         char server_policy_str[STD_BUF];
2453         client_policy_str[0] = server_policy_str[0] = '\0';
2454 
2455         if (client_flushpolicy != STREAM_FLPOLICY_IGNORE)
2456         {
2457             direction |= SSN_DIR_FROM_CLIENT;
2458 
2459             if (client_flushpolicy < STREAM_FLPOLICY_MAX)
2460                 SnortSnprintf(client_policy_str, STD_BUF, "client (%s)",
2461                         flush_policy_names[client_flushpolicy]);
2462         }
2463         if (server_flushpolicy != STREAM_FLPOLICY_IGNORE)
2464         {
2465             direction |= SSN_DIR_FROM_SERVER;
2466 
2467             if (server_flushpolicy < STREAM_FLPOLICY_MAX)
2468                 SnortSnprintf(server_policy_str, STD_BUF, "server (%s)",
2469                         flush_policy_names[server_flushpolicy]);
2470         }
2471         if (direction)
2472         {
2473             if (j<MAX_PORTS_TO_PRINT)
2474             {
2475                 LogMessage("      %d %s %s\n", i,
2476                         client_policy_str, server_policy_str);
2477             }
2478             j++;
2479         }
2480     }
2481 
2482     if (j > MAX_PORTS_TO_PRINT)
2483     {
2484         LogMessage("      additional ports configured but not printed.\n");
2485     }
2486 }
2487 
2488 #ifdef TARGET_BASED
StreamPolicyIdFromHostAttributeEntry(HostAttributeEntry * host_entry)2489 int StreamPolicyIdFromHostAttributeEntry(HostAttributeEntry *host_entry)
2490 {
2491     if (!host_entry)
2492         return 0;
2493 
2494     host_entry->hostInfo.streamPolicy = StreamPolicyIdFromName(host_entry->hostInfo.streamPolicyName);
2495     host_entry->hostInfo.streamPolicySet = 1;
2496 
2497     STREAM_DEBUG_WRAP(
2498             DebugMessage(DEBUG_STREAM_STATE,
2499                 "STREAM INIT: %s(%d) for Entry %s\n",
2500                 reassembly_policy_names[host_entry->hostInfo.streamPolicy],
2501                 host_entry->hostInfo.streamPolicy,
2502                 host_entry->hostInfo.streamPolicyName););
2503     return 0;
2504 }
2505 #endif
2506 
StreamPostConfigTcp(struct _SnortConfig * sc,void * pv)2507 void StreamPostConfigTcp (struct _SnortConfig *sc, void* pv)
2508 {
2509     // enable all ports registered by preprocessors for reassembly
2510     enableRegisteredPortsForReassembly( sc );
2511 }
2512 
2513 void s5TcpPrintPortFilter();
2514 
2515 /**
2516  * StreamVerifyTcpConfig is is called after all preprocs (static & dynamic)
2517  * are inited.
2518  */
StreamVerifyTcpConfig(struct _SnortConfig * sc,StreamTcpConfig * config,tSfPolicyId policy_id)2519 int StreamVerifyTcpConfig(struct _SnortConfig *sc, StreamTcpConfig *config, tSfPolicyId policy_id)
2520 {
2521     if (config == NULL)
2522         return -1;
2523 
2524     if (!tcp_lws_cache)
2525     {
2526         LogMessage("WARNING: Stream TCP Session Cache not initialized.\n");
2527         return -1;
2528     }
2529 
2530     if (config->num_policies == 0)
2531     {
2532         LogMessage("WARNING: Stream TCP no policies specified in configuration.\n");
2533         return -1;
2534     }
2535 
2536     if (config->default_policy == NULL)
2537     {
2538         LogMessage("WARNING: Stream TCP default policy not specified in configuration.\n");
2539         return -1;
2540     }
2541 
2542     /* Do this now
2543      * verify config is called after all preprocs (static & dynamic)
2544      * are inited.  Gives us the correct number of bits for
2545      * p->preprocessor_bits
2546      */
2547     if (!s5_pkt)
2548         StreamInitPacket();
2549 
2550 #ifdef TARGET_BASED
2551     SFAT_SetPolicyIds(StreamPolicyIdFromHostAttributeEntry, policy_id);
2552 #endif
2553 
2554     /* Post-process TCP rules to establish TCP ports to inspect. */
2555     setPortFilterList(sc, config->port_filter, IPPROTO_TCP,
2556             (config->default_policy->flags & STREAM_CONFIG_IGNORE_ANY), policy_id);
2557 
2558     //printf ("TCP Ports with Inspection/Monitoring\n");
2559     //s5PrintPortFilter(config->tcpPortFilter);
2560     return 0;
2561 }
2562 
2563 
StreamGetTcpPrunes(void)2564 uint32_t StreamGetTcpPrunes(void)
2565 {
2566     if( tcp_lws_cache )
2567         return session_api->get_session_prune_count( SESSION_PROTO_TCP );
2568     else
2569         return s5stats.tcp_prunes;
2570 }
2571 
StreamResetTcpPrunes(void)2572 void StreamResetTcpPrunes(void)
2573 {
2574     session_api->reset_session_prune_count( SESSION_PROTO_TCP );
2575 }
2576 
StreamResetTcp(void)2577 void StreamResetTcp(void)
2578 {
2579     if (snort_conf == NULL)
2580     {
2581         ErrorMessage("Snort configuration is NULL.\n");
2582         return;
2583     }
2584 
2585     /* Unset decoder flags for the purge */
2586     targetPolicyIterate(policyDecoderFlagsSaveNClear);
2587 
2588     s5_tcp_cleanup = 1;
2589     session_api->purge_session_cache(tcp_lws_cache);
2590     s5_tcp_cleanup = 0;
2591     session_api->clean_protocol_session_pool( SESSION_PROTO_TCP );
2592 
2593     /* Set decoder flags back to original */
2594     targetPolicyIterate(policyDecoderFlagsRestore);
2595 
2596     ResetFlushMgrs();
2597 }
2598 
2599 
StreamCleanTcp(void)2600 void StreamCleanTcp(void)
2601 {
2602     if (snort_conf == NULL)
2603     {
2604         ErrorMessage("Snort configuration is NULL.\n");
2605         return;
2606     }
2607 
2608     s5stats.tcp_prunes = session_api->get_session_prune_count( SESSION_PROTO_TCP );
2609 
2610     /* Turn off decoder alerts since we're decoding stored
2611      * packets that we already alerted on. */
2612     targetPolicyIterate(policyDecoderFlagsSaveNClear);
2613 
2614     /* Set s5_tcp_cleanup to force a flush of all queued data */
2615     s5_tcp_cleanup = 1;
2616     /* Clean up session cache */
2617     session_api->delete_session_cache( SESSION_PROTO_TCP );
2618     tcp_lws_cache = NULL;
2619 
2620     /* Cleanup the rebuilt packet */
2621     if (s5_pkt)
2622     {
2623         Encode_Delete(s5_pkt);
2624         s5_pkt = NULL;
2625     }
2626 
2627     /* Cleanup TCP session cleanup packet */
2628     if (tcp_cleanup_pkt)
2629     {
2630         DeleteGrinderPkt(tcp_cleanup_pkt);
2631         tcp_cleanup_pkt = NULL;
2632     }
2633 
2634     /* cleanup is over... */
2635     s5_tcp_cleanup = 0;
2636 
2637     /* And turn decoder alerts back on (or whatever they were set to) */
2638     targetPolicyIterate(policyDecoderFlagsRestore);
2639 }
2640 
StreamTcpConfigFree(StreamTcpConfig * config)2641 void StreamTcpConfigFree(StreamTcpConfig *config)
2642 {
2643     int i;
2644 
2645     if (config == NULL)
2646         return;
2647 
2648     /* Cleanup TCP Policies and the list */
2649     for (i = 0; i < config->num_policies; i++)
2650     {
2651         StreamTcpPolicy *policy = config->policy_list[i];
2652 
2653         SnortPreprocFree(policy->flush_point_list.flush_points,
2654                  sizeof(uint32_t) * RAND_FLUSH_POINTS, PP_STREAM,
2655                  PP_MEM_CATEGORY_CONFIG);
2656 
2657         if (policy->bound_addrs != NULL)
2658             sfvar_free(policy->bound_addrs);
2659         SnortPreprocFree(policy, sizeof( StreamTcpPolicy * ), PP_STREAM,
2660               PP_MEM_CATEGORY_CONFIG);
2661     }
2662 
2663     if ( config->paf_config )
2664         s5_paf_delete(config->paf_config);
2665 
2666     SnortPreprocFree(config->policy_list,
2667            sizeof(StreamTcpPolicy *) * (config->num_policies), PP_STREAM,
2668            PP_MEM_CATEGORY_CONFIG);
2669     SnortPreprocFree(config, sizeof(StreamTcpConfig), PP_STREAM, PP_MEM_CATEGORY_CONFIG);
2670 }
2671 
2672 #ifdef STREAM_DEBUG_ENABLED
PrintStateMgr(StateMgr * s)2673 static void PrintStateMgr(StateMgr *s)
2674 {
2675     LogMessage("StateMgr:\n");
2676     LogMessage("    state:          %s\n", state_names[s->state]);
2677     LogMessage("    state_queue:    %s\n", state_names[s->state_queue]);
2678     LogMessage("    expected_flags: 0x%X\n", s->expected_flags);
2679     LogMessage("    transition_seq: 0x%X\n", s->transition_seq);
2680     LogMessage("    stq_get_seq:    %d\n", s->stq_get_seq);
2681 }
2682 
PrintStreamTracker(StreamTracker * s)2683 static void PrintStreamTracker(StreamTracker *s)
2684 {
2685     LogMessage(" + StreamTracker +\n");
2686     LogMessage("    isn:                0x%X\n", s->isn);
2687     LogMessage("    ts_last:            %u\n", s->ts_last);
2688     LogMessage("    wscale:             %u\n", s->wscale);
2689     LogMessage("    mss:                0x%08X\n", s->mss);
2690     LogMessage("    l_unackd:           %X\n", s->l_unackd);
2691     LogMessage("    l_nxt_seq:          %X\n", s->l_nxt_seq);
2692     LogMessage("    l_window:           %u\n", s->l_window);
2693     LogMessage("    r_nxt_ack:          %X\n", s->r_nxt_ack);
2694     LogMessage("    r_win_base:         %X\n", s->r_win_base);
2695     LogMessage("    seglist_base_seq:   %X\n", s->seglist_base_seq);
2696     LogMessage("    seglist:            %p\n", (void*)s->seglist);
2697     LogMessage("    seglist_tail:       %p\n", (void*)s->seglist_tail);
2698     LogMessage("    seg_count:          %d\n", s->seg_count);
2699     LogMessage("    seg_bytes_total:    %d\n", s->seg_bytes_total);
2700     LogMessage("    seg_bytes_logical:  %d\n", s->seg_bytes_logical);
2701 
2702     PrintStateMgr(&s->s_mgr);
2703 }
2704 
PrintTcpSession(TcpSession * ts)2705 static void PrintTcpSession(TcpSession *ts)
2706 {
2707     char buf[64];
2708 
2709     LogMessage("TcpSession:\n");
2710 #ifdef DEBUG
2711     LogMessage("    ssn_time:           %lu\n", ts->ssn_time.tv_sec);
2712 #endif
2713     sfip_ntop(&ts->tcp_server_ip, buf, sizeof(buf));
2714     LogMessage("    server IP:          %s\n", buf);
2715     sfip_ntop(&ts->tcp_client_ip, buf, sizeof(buf));
2716     LogMessage("    client IP:          %s\n", buf);
2717 
2718     LogMessage("    server port:        %d\n", ts->tcp_server_port);
2719     LogMessage("    client port:        %d\n", ts->tcp_client_port);
2720 
2721     LogMessage("    flags:              0x%X\n", ts->scb->ha_state.session_flags);
2722 
2723     LogMessage("Client Tracker:\n");
2724     PrintStreamTracker(&ts->client);
2725     LogMessage("Server Tracker:\n");
2726     PrintStreamTracker(&ts->server);
2727 }
2728 
PrintTcpDataBlock(TcpDataBlock * tdb)2729 static void PrintTcpDataBlock(TcpDataBlock *tdb)
2730 {
2731     LogMessage("TcpDataBlock:\n");
2732     LogMessage("    seq:    0x%08X\n", tdb->seq);
2733     LogMessage("    ack:    0x%08X\n", tdb->ack);
2734     LogMessage("    win:    %d\n", tdb->win);
2735     LogMessage("    end:    0x%08X\n", tdb->end_seq);
2736 }
2737 
2738 #ifdef STREAM_DEBUG_ENABLED
PrintFlushMgr(FlushMgr * fm)2739 static void PrintFlushMgr(FlushMgr *fm)
2740 {
2741     if(fm == NULL)
2742         return;
2743 
2744     switch(fm->flush_policy)
2745     {
2746         case STREAM_FLPOLICY_NONE:
2747             STREAM_DEBUG_WRAP(DebugMessage(DEBUG_STREAM_STATE,
2748                         "    NONE\n"););
2749             break;
2750         case STREAM_FLPOLICY_FOOTPRINT:
2751             STREAM_DEBUG_WRAP(DebugMessage(DEBUG_STREAM_STATE,
2752                         "    FOOTPRINT %d\n", fm->flush_pt););
2753             break;
2754         case STREAM_FLPOLICY_LOGICAL:
2755             STREAM_DEBUG_WRAP(DebugMessage(DEBUG_STREAM_STATE,
2756                         "    LOGICAL %d\n", fm->flush_pt););
2757             break;
2758         case STREAM_FLPOLICY_RESPONSE:
2759             STREAM_DEBUG_WRAP(DebugMessage(DEBUG_STREAM_STATE,
2760                         "    RESPONSE\n"););
2761             break;
2762         case STREAM_FLPOLICY_SLIDING_WINDOW:
2763             STREAM_DEBUG_WRAP(DebugMessage(DEBUG_STREAM_STATE,
2764                         "    SLIDING_WINDOW %d\n", fm->flush_pt););
2765             break;
2766 #if 0
2767         case STREAM_FLPOLICY_CONSUMED:
2768             STREAM_DEBUG_WRAP(DebugMessage(DEBUG_STREAM_STATE,
2769                         "          CONSUMED %d\n", fm->flush_pt););
2770             break;
2771 #endif
2772         case STREAM_FLPOLICY_IGNORE:
2773             STREAM_DEBUG_WRAP(DebugMessage(DEBUG_STREAM_STATE,
2774                         "    IGNORE\n"););
2775             break;
2776 
2777         case STREAM_FLPOLICY_PROTOCOL:
2778             STREAM_DEBUG_WRAP(DebugMessage(DEBUG_STREAM_STATE,
2779                         "    PROTOCOL\n"););
2780             break;
2781     }
2782 }
2783 #endif  // DEBUG
2784 #endif  // STREAM_DEBUG_ENABLED
2785 
Discard()2786 static inline void Discard ()
2787 {
2788     s5stats.tcp_discards++;
2789 }
EventSynOnEst(StreamTcpPolicy * s5TcpPolicy)2790 static inline void EventSynOnEst(StreamTcpPolicy *s5TcpPolicy)
2791 {
2792     if(!(s5TcpPolicy->flags & STREAM_CONFIG_ENABLE_ALERTS))
2793         return;
2794 
2795     s5stats.events++;
2796 
2797     SnortEventqAdd(GENERATOR_SPP_STREAM,       /* GID */
2798             STREAM_SYN_ON_EST,                 /* SID */
2799             1,                                  /* rev */
2800             0,                                  /* class */
2801             3,                                  /* priority */
2802             STREAM_SYN_ON_EST_STR,             /* event msg */
2803             NULL);                              /* rule info ptr */
2804 }
2805 
EventExcessiveOverlap(StreamTcpPolicy * s5TcpPolicy)2806 static inline void EventExcessiveOverlap(StreamTcpPolicy *s5TcpPolicy)
2807 {
2808     if(!(s5TcpPolicy->flags & STREAM_CONFIG_ENABLE_ALERTS))
2809         return;
2810 
2811     s5stats.events++;
2812 
2813     SnortEventqAdd(GENERATOR_SPP_STREAM,       /* GID */
2814             STREAM_EXCESSIVE_TCP_OVERLAPS,     /* SID */
2815             1,                                  /* rev */
2816             0,                                  /* class */
2817             3,                                  /* priority */
2818             STREAM_EXCESSIVE_TCP_OVERLAPS_STR, /* event msg */
2819             NULL);                              /* rule info ptr */
2820 }
2821 
EventBadTimestamp(StreamTcpPolicy * s5TcpPolicy)2822 static inline void EventBadTimestamp(StreamTcpPolicy *s5TcpPolicy)
2823 {
2824     if(!(s5TcpPolicy->flags & STREAM_CONFIG_ENABLE_ALERTS))
2825         return;
2826 
2827     s5stats.events++;
2828 
2829     SnortEventqAdd(GENERATOR_SPP_STREAM,       /* GID */
2830             STREAM_BAD_TIMESTAMP,              /* SID */
2831             1,                                  /* rev */
2832             0,                                  /* class */
2833             3,                                  /* priority */
2834             STREAM_BAD_TIMESTAMP_STR,          /* event msg */
2835             NULL);                              /* rule info ptr */
2836 }
2837 
EventWindowTooLarge(StreamTcpPolicy * s5TcpPolicy)2838 static inline void EventWindowTooLarge(StreamTcpPolicy *s5TcpPolicy)
2839 {
2840     if(!(s5TcpPolicy->flags & STREAM_CONFIG_ENABLE_ALERTS))
2841         return;
2842 
2843     s5stats.events++;
2844 
2845     SnortEventqAdd(GENERATOR_SPP_STREAM,       /* GID */
2846             STREAM_WINDOW_TOO_LARGE,           /* SID */
2847             1,                                  /* rev */
2848             0,                                  /* class */
2849             3,                                  /* priority */
2850             STREAM_WINDOW_TOO_LARGE_STR,       /* event msg */
2851             NULL);                              /* rule info ptr */
2852 }
2853 
EventDataOnSyn(StreamTcpPolicy * s5TcpPolicy)2854 static inline void EventDataOnSyn(StreamTcpPolicy *s5TcpPolicy)
2855 {
2856     if(!(s5TcpPolicy->flags & STREAM_CONFIG_ENABLE_ALERTS))
2857         return;
2858 
2859     s5stats.events++;
2860 
2861     SnortEventqAdd(GENERATOR_SPP_STREAM,       /* GID */
2862             STREAM_DATA_ON_SYN,                /* SID */
2863             1,                                  /* rev */
2864             0,                                  /* class */
2865             3,                                  /* priority */
2866             STREAM_DATA_ON_SYN_STR,            /* event msg */
2867             NULL);                              /* rule info ptr */
2868 }
2869 
EventDataOnClosed(StreamTcpPolicy * s5TcpPolicy)2870 static inline void EventDataOnClosed(StreamTcpPolicy *s5TcpPolicy)
2871 {
2872     if(!(s5TcpPolicy->flags & STREAM_CONFIG_ENABLE_ALERTS))
2873         return;
2874 
2875     s5stats.events++;
2876 
2877     SnortEventqAdd(GENERATOR_SPP_STREAM,       /* GID */
2878             STREAM_DATA_ON_CLOSED,             /* SID */
2879             1,                                  /* rev */
2880             0,                                  /* class */
2881             3,                                  /* priority */
2882             STREAM_DATA_ON_CLOSED_STR,         /* event msg */
2883             NULL);                              /* rule info ptr */
2884 }
2885 
EventDataAfterReset(StreamTcpPolicy * s5TcpPolicy)2886 static inline void EventDataAfterReset(StreamTcpPolicy *s5TcpPolicy)
2887 {
2888     if(!(s5TcpPolicy->flags & STREAM_CONFIG_ENABLE_ALERTS))
2889         return;
2890 
2891     s5stats.events++;
2892 
2893     SnortEventqAdd(GENERATOR_SPP_STREAM,       /* GID */
2894             STREAM_DATA_AFTER_RESET,           /* SID */
2895             1,                                  /* rev */
2896             0,                                  /* class */
2897             3,                                  /* priority */
2898             STREAM_DATA_AFTER_RESET_STR,       /* event msg */
2899             NULL);                              /* rule info ptr */
2900 }
2901 
EventBadSegment(StreamTcpPolicy * s5TcpPolicy)2902 static inline void EventBadSegment(StreamTcpPolicy *s5TcpPolicy)
2903 {
2904     if(!(s5TcpPolicy->flags & STREAM_CONFIG_ENABLE_ALERTS))
2905         return;
2906 
2907     s5stats.events++;
2908 
2909     SnortEventqAdd(GENERATOR_SPP_STREAM,       /* GID */
2910             STREAM_BAD_SEGMENT,                /* SID */
2911             1,                                  /* rev */
2912             0,                                  /* class */
2913             3,                                  /* priority */
2914             STREAM_BAD_SEGMENT_STR,            /* event msg */
2915             NULL);                              /* rule info ptr */
2916 }
2917 
EventSessionHijackedClient(StreamTcpPolicy * s5TcpPolicy)2918 static inline void EventSessionHijackedClient(StreamTcpPolicy *s5TcpPolicy)
2919 {
2920     if(!(s5TcpPolicy->flags & STREAM_CONFIG_ENABLE_ALERTS))
2921         return;
2922 
2923     s5stats.events++;
2924 
2925     SnortEventqAdd(GENERATOR_SPP_STREAM,       /* GID */
2926             STREAM_SESSION_HIJACKED_CLIENT,    /* SID */
2927             1,                                  /* rev */
2928             0,                                  /* class */
2929             3,                                  /* priority */
2930             STREAM_SESSION_HIJACKED_CLIENT_STR, /* event msg */
2931             NULL);                              /* rule info ptr */
2932 }
EventSessionHijackedServer(StreamTcpPolicy * s5TcpPolicy)2933 static inline void EventSessionHijackedServer(StreamTcpPolicy *s5TcpPolicy)
2934 {
2935     if(!(s5TcpPolicy->flags & STREAM_CONFIG_ENABLE_ALERTS))
2936         return;
2937 
2938     s5stats.events++;
2939 
2940     SnortEventqAdd(GENERATOR_SPP_STREAM,       /* GID */
2941             STREAM_SESSION_HIJACKED_SERVER,    /* SID */
2942             1,                                  /* rev */
2943             0,                                  /* class */
2944             3,                                  /* priority */
2945             STREAM_SESSION_HIJACKED_SERVER_STR, /* event msg */
2946             NULL);                              /* rule info ptr */
2947 }
2948 
EventDataWithoutFlags(StreamTcpPolicy * s5TcpPolicy)2949 static inline void EventDataWithoutFlags(StreamTcpPolicy *s5TcpPolicy)
2950 {
2951     if(!(s5TcpPolicy->flags & STREAM_CONFIG_ENABLE_ALERTS))
2952         return;
2953 
2954     s5stats.events++;
2955 
2956     SnortEventqAdd(GENERATOR_SPP_STREAM,       /* GID */
2957             STREAM_DATA_WITHOUT_FLAGS,         /* SID */
2958             1,                                  /* rev */
2959             0,                                  /* class */
2960             3,                                  /* priority */
2961             STREAM_DATA_WITHOUT_FLAGS_STR,     /* event msg */
2962             NULL);                              /* rule info ptr */
2963 }
2964 
EventMaxSmallSegsExceeded(StreamTcpPolicy * s5TcpPolicy)2965 static inline void EventMaxSmallSegsExceeded(StreamTcpPolicy *s5TcpPolicy)
2966 {
2967     if(!(s5TcpPolicy->flags & STREAM_CONFIG_ENABLE_ALERTS))
2968         return;
2969 
2970     s5stats.events++;
2971 
2972     SnortEventqAdd(GENERATOR_SPP_STREAM,       /* GID */
2973             STREAM_SMALL_SEGMENT,              /* SID */
2974             1,                                  /* rev */
2975             0,                                  /* class */
2976             3,                                  /* priority */
2977             STREAM_SMALL_SEGMENT_STR,          /* event msg */
2978             NULL);                              /* rule info ptr */
2979 }
2980 
Event4whs(StreamTcpPolicy * s5TcpPolicy)2981 static inline void Event4whs(StreamTcpPolicy *s5TcpPolicy)
2982 {
2983     if(!(s5TcpPolicy->flags & STREAM_CONFIG_ENABLE_ALERTS))
2984         return;
2985 
2986     s5stats.events++;
2987 
2988     SnortEventqAdd(GENERATOR_SPP_STREAM,       /* GID */
2989             STREAM_4WAY_HANDSHAKE,             /* SID */
2990             1,                                  /* rev */
2991             0,                                  /* class */
2992             3,                                  /* priority */
2993             STREAM_4WAY_HANDSHAKE_STR,         /* event msg */
2994             NULL);                              /* rule info ptr */
2995 }
2996 
EventNoTimestamp(StreamTcpPolicy * s5TcpPolicy)2997 static inline void EventNoTimestamp(StreamTcpPolicy *s5TcpPolicy)
2998 {
2999     if(!(s5TcpPolicy->flags & STREAM_CONFIG_ENABLE_ALERTS))
3000         return;
3001 
3002     s5stats.events++;
3003 
3004     SnortEventqAdd(GENERATOR_SPP_STREAM,       /* GID */
3005             STREAM_NO_TIMESTAMP,               /* SID */
3006             1,                                  /* rev */
3007             0,                                  /* class */
3008             3,                                  /* priority */
3009             STREAM_NO_TIMESTAMP_STR,           /* event msg */
3010             NULL);                              /* rule info ptr */
3011 }
3012 
EventBadReset(StreamTcpPolicy * s5TcpPolicy)3013 static inline void EventBadReset(StreamTcpPolicy *s5TcpPolicy)
3014 {
3015     if(!(s5TcpPolicy->flags & STREAM_CONFIG_ENABLE_ALERTS))
3016         return;
3017 
3018     s5stats.events++;
3019 
3020     SnortEventqAdd(GENERATOR_SPP_STREAM,       /* GID */
3021             STREAM_BAD_RST,                    /* SID */
3022             1,                                  /* rev */
3023             0,                                  /* class */
3024             3,                                  /* priority */
3025             STREAM_BAD_RST_STR,                /* event msg */
3026             NULL);                              /* rule info ptr */
3027 }
3028 
EventBadFin(StreamTcpPolicy * s5TcpPolicy)3029 static inline void EventBadFin(StreamTcpPolicy *s5TcpPolicy)
3030 {
3031     if(!(s5TcpPolicy->flags & STREAM_CONFIG_ENABLE_ALERTS))
3032         return;
3033 
3034     s5stats.events++;
3035 
3036     SnortEventqAdd(GENERATOR_SPP_STREAM,       /* GID */
3037             STREAM_BAD_FIN,                    /* SID */
3038             1,                                  /* rev */
3039             0,                                  /* class */
3040             3,                                  /* priority */
3041             STREAM_BAD_FIN_STR,                /* event msg */
3042             NULL);                              /* rule info ptr */
3043 }
3044 
EventBadAck(StreamTcpPolicy * s5TcpPolicy)3045 static inline void EventBadAck(StreamTcpPolicy *s5TcpPolicy)
3046 {
3047     if(!(s5TcpPolicy->flags & STREAM_CONFIG_ENABLE_ALERTS))
3048         return;
3049 
3050     s5stats.events++;
3051 
3052     SnortEventqAdd(GENERATOR_SPP_STREAM,       /* GID */
3053             STREAM_BAD_ACK,                    /* SID */
3054             1,                                  /* rev */
3055             0,                                  /* class */
3056             3,                                  /* priority */
3057             STREAM_BAD_ACK_STR,                /* event msg */
3058             NULL);                              /* rule info ptr */
3059 }
3060 
EventDataAfterRstRcvd(StreamTcpPolicy * s5TcpPolicy)3061 static inline void EventDataAfterRstRcvd(StreamTcpPolicy *s5TcpPolicy)
3062 {
3063     if(!(s5TcpPolicy->flags & STREAM_CONFIG_ENABLE_ALERTS))
3064         return;
3065 
3066     s5stats.events++;
3067 
3068     SnortEventqAdd(GENERATOR_SPP_STREAM,       /* GID */
3069             STREAM_DATA_AFTER_RST_RCVD,        /* SID */
3070             1,                                  /* rev */
3071             0,                                  /* class */
3072             3,                                  /* priority */
3073             STREAM_DATA_AFTER_RST_RCVD_STR,    /* event msg */
3074             NULL);                              /* rule info ptr */
3075 }
3076 
EventInternal(uint32_t eventSid)3077 static inline void EventInternal (uint32_t eventSid)
3078 {
3079     if ( !InternalEventIsEnabled(snort_conf->rate_filter_config, eventSid) )
3080         return;
3081 
3082     s5stats.internalEvents++;
3083 
3084     STREAM_DEBUG_WRAP(DebugMessage(DEBUG_STREAM_STATE,
3085                 "Stream raised internal event %d\n", eventSid););
3086 
3087     SnortEventqAdd(
3088         GENERATOR_INTERNAL,             /* GID */
3089         eventSid,                       /* SID */
3090         1,                              /* rev */
3091         0,                              /* class */
3092         3,                              /* priority */
3093         STREAM_INTERNAL_EVENT_STR,      /* event msg*/
3094         NULL                            /* rule info ptr */
3095         );
3096 }
3097 
EventWindowSlam(StreamTcpPolicy * s5TcpPolicy)3098 static inline void EventWindowSlam (StreamTcpPolicy *s5TcpPolicy)
3099 {
3100     if(!(s5TcpPolicy->flags & STREAM_CONFIG_ENABLE_ALERTS))
3101         return;
3102 
3103     s5stats.events++;
3104 
3105     SnortEventqAdd(GENERATOR_SPP_STREAM,       /* GID */
3106             STREAM_WINDOW_SLAM,                /* SID */
3107             1,                                  /* rev */
3108             0,                                  /* class */
3109             3,                                  /* priority */
3110             STREAM_WINDOW_SLAM_STR,            /* event msg */
3111             NULL);                              /* rule info ptr */
3112 }
3113 
EventNo3whs(StreamTcpPolicy * s5TcpPolicy)3114 static inline void EventNo3whs (StreamTcpPolicy *s5TcpPolicy)
3115 {
3116     if(!(s5TcpPolicy->flags & STREAM_CONFIG_ENABLE_ALERTS))
3117         return;
3118 
3119     s5stats.events++;
3120 
3121     SnortEventqAdd(GENERATOR_SPP_STREAM,       /* GID */
3122             STREAM_NO_3WHS,                    /* SID */
3123             1,                                  /* rev */
3124             0,                                  /* class */
3125             3,                                  /* priority */
3126             STREAM_NO_3WHS_STR,                /* event msg */
3127             NULL);                              /* rule info ptr */
3128 }
3129 
3130 /*
3131  *  Utility functions for TCP stuff
3132  */
3133 #ifdef NORMALIZER
3134 typedef enum {
3135     PC_TCP_ECN_SSN,
3136     PC_TCP_TS_NOP,
3137     PC_TCP_IPS_DATA,
3138     PC_TCP_BLOCK,
3139     PC_TCP_TRIM_SYN,
3140     PC_TCP_TRIM_RST,
3141     PC_TCP_TRIM_WIN,
3142     PC_TCP_TRIM_MSS,
3143     PC_MAX
3144 } PegCounts;
3145 
3146 static uint64_t normStats[PC_MAX][NORM_MODE_MAX];
3147 
3148 static const char* pegName[PC_MAX] = {
3149     "tcp::ecn_ssn",
3150     "tcp::ts_nop",
3151     "tcp::ips_data",
3152     "tcp::block",
3153     "tcp::trim_syn",
3154     "tcp::trim_rst",
3155     "tcp::trim_win",
3156     "tcp::trim_mss",
3157 };
3158 
Stream_PrintNormalizationStats(void)3159 void Stream_PrintNormalizationStats (void)
3160 {
3161     int i;
3162     // header output by normalizer
3163 
3164     for ( i = 0; i < PC_MAX; i++ )
3165     {
3166         // same alignment as in Norm_PrintStats()
3167         LogMessage("%23s: " STDu64 "\n", pegName[i], normStats[i][NORM_MODE_ON]);
3168         LogMessage("Would %17s: " STDu64 "\n", pegName[i], normStats[i][NORM_MODE_WOULDA]);
3169     }
3170 }
3171 
Stream_ResetNormalizationStats(void)3172 void Stream_ResetNormalizationStats (void)
3173 {
3174     memset(normStats, 0, sizeof(normStats));
3175 }
3176 
3177 //-----------------------------------------------------------------------
3178 // instead of centralizing all these normalizations so that
3179 // Normalize_GetMode() is called only once, the checks and
3180 // normalizations are localized.  this should lead to many
3181 // fewer total checks.  however, it is best to minimize
3182 // configuration checks on a per packet basis so there is
3183 // still room for improvement.
3184 
NormalDropPacket(Packet * p)3185 static inline bool NormalDropPacket (Packet* p)
3186 {
3187     NormMode mode = Normalize_GetMode(snort_conf, NORM_TCP_BLOCK);
3188     if ( mode != NORM_MODE_OFF )
3189     {
3190             normStats[PC_TCP_BLOCK][mode]++;
3191             sfBase.iPegs[PERF_COUNT_TCP_BLOCK][mode]++;
3192             if ( mode == NORM_MODE_ON )
3193             {
3194                 Active_NapDropPacket(p);
3195                 if (pkt_trace_enabled)
3196                 {
3197                     addPktTraceData(VERDICT_REASON_STREAM, snprintf(trace_line, MAX_TRACE_LINE,
3198                        "Stream: TCP normalization error in timestamp, window, seq, ack, fin, flags, or unexpected data, %s\n",
3199                        getPktTraceActMsg()));
3200                 }
3201                 else addPktTraceData(VERDICT_REASON_STREAM, 0);
3202                 return true;
3203             }
3204     }
3205     return false;
3206 }
3207 
NormalStripTimeStamp(Packet * p,int i)3208 static inline bool NormalStripTimeStamp (Packet* p, int i)
3209 {
3210     uint8_t* opt;
3211     NormMode mode =  Normalize_GetMode(snort_conf, NORM_TCP_OPT);
3212 
3213     if ( mode != NORM_MODE_OFF )
3214     {
3215         if ( i < 0 )
3216         {
3217             for ( i = 0; i < p->tcp_option_count; i++ )
3218                 if ( p->tcp_options[i].code == TCPOPT_TIMESTAMP )
3219                     break;
3220             if ( i == p->tcp_option_count )
3221                 return false;
3222         }
3223 
3224         normStats[PC_TCP_TS_NOP][mode]++;
3225         sfBase.iPegs[PERF_COUNT_TCP_TS_NOP][mode]++;
3226         if ( mode == NORM_MODE_ON )
3227         {
3228             // first set raw option bytes to nops
3229             opt = (uint8_t*)p->tcp_options[i].data - 2;
3230             memset(opt, TCPOPT_NOP, TCPOLEN_TIMESTAMP);
3231 
3232             // then nop decoded option code only
3233             p->tcp_options[i].code = TCPOPT_NOP;
3234 
3235             p->packet_flags |= PKT_MODIFIED;
3236             return true;
3237         }
3238     }
3239     return false;
3240 }
3241 
NormalTrimPayload(Packet * p,uint32_t max,TcpDataBlock * tdb)3242 static inline void NormalTrimPayload (Packet* p, uint32_t max, TcpDataBlock* tdb)
3243 {
3244     uint16_t fat = p->dsize - max;
3245     p->dsize = max;
3246     p->packet_flags |= (PKT_MODIFIED|PKT_RESIZED);
3247     tdb->end_seq -= fat;
3248 }
3249 
NormalTrimPayloadIfSyn(Packet * p,uint32_t max,TcpDataBlock * tdb)3250 static inline bool NormalTrimPayloadIfSyn ( Packet *p, uint32_t max, TcpDataBlock *tdb )
3251 {
3252     NormMode mode = Normalize_GetMode(snort_conf, NORM_TCP_TRIM_SYN);
3253     if ( mode != NORM_MODE_OFF && p->dsize > max )
3254     {
3255         normStats[PC_TCP_TRIM_SYN][mode]++;
3256         sfBase.iPegs[PERF_COUNT_TCP_TRIM_SYN][mode]++;
3257         if( mode == NORM_MODE_ON )
3258         {
3259             NormalTrimPayload(p, max, tdb);
3260             return true;
3261         }
3262     }
3263     return false;
3264 }
3265 
NormalTrimPayloadIfRst(Packet * p,uint32_t max,TcpDataBlock * tdb)3266 static inline bool NormalTrimPayloadIfRst ( Packet *p, uint32_t max, TcpDataBlock *tdb )
3267 {
3268     NormMode mode = Normalize_GetMode(snort_conf, NORM_TCP_TRIM_RST);
3269     if ( mode != NORM_MODE_OFF && p->dsize > max )
3270     {
3271         normStats[PC_TCP_TRIM_RST][mode]++;
3272         sfBase.iPegs[PERF_COUNT_TCP_TRIM_RST][mode]++;
3273         if( mode == NORM_MODE_ON )
3274         {
3275             NormalTrimPayload(p, max, tdb);
3276             return true;
3277         }
3278     }
3279     return false;
3280 }
3281 
NormalTrimPayloadIfWin(Packet * p,uint32_t max,TcpDataBlock * tdb)3282 static inline bool NormalTrimPayloadIfWin ( Packet *p, uint32_t max, TcpDataBlock *tdb )
3283 {
3284     NormMode mode = Normalize_GetMode(snort_conf, NORM_TCP_TRIM_WIN);
3285     if ( mode != NORM_MODE_OFF && p->dsize > max )
3286     {
3287         normStats[PC_TCP_TRIM_WIN][mode]++;
3288         sfBase.iPegs[PERF_COUNT_TCP_TRIM_WIN][mode]++;
3289         if( mode == NORM_MODE_ON )
3290         {
3291             NormalTrimPayload(p, max, tdb);
3292             return true;
3293         }
3294     }
3295     return false;
3296 }
3297 
NormalTrimPayloadIfMss(Packet * p,uint32_t max,TcpDataBlock * tdb)3298 static inline bool NormalTrimPayloadIfMss ( Packet *p, uint32_t max, TcpDataBlock *tdb )
3299 {
3300     NormMode mode = Normalize_GetMode(snort_conf, NORM_TCP_TRIM_MSS);
3301     if ( mode != NORM_MODE_OFF && p->dsize > max )
3302     {
3303         normStats[PC_TCP_TRIM_MSS][mode]++;
3304         sfBase.iPegs[PERF_COUNT_TCP_TRIM_MSS][mode]++;
3305         if( mode == NORM_MODE_ON )
3306         {
3307             NormalTrimPayload(p, max, tdb);
3308             return true;
3309         }
3310     }
3311     return false;
3312 }
3313 
NormalTrackECN(TcpSession * s,const TCPHdr * tcph,int req3way)3314 static inline void NormalTrackECN (TcpSession* s, const TCPHdr* tcph, int req3way)
3315 {
3316     if ( !s )
3317         return;
3318 
3319     if ( TCP_ISFLAGSET(tcph, TH_SYN|TH_ACK) )
3320     {
3321         if ( !req3way || s->ecn )
3322             s->ecn = ((tcph->th_flags & (TH_ECE|TH_CWR)) == TH_ECE);
3323     }
3324     else if ( TCP_ISFLAGSET(tcph, TH_SYN) )
3325         s->ecn = TCP_ISFLAGSET(tcph, (TH_ECE|TH_CWR));
3326 }
3327 
NormalCheckECN(TcpSession * s,Packet * p)3328 static inline void NormalCheckECN (TcpSession* s, Packet* p)
3329 {
3330     NormMode mode = Normalize_GetMode(snort_conf, NORM_TCP_ECN_STR);
3331     if ( mode != NORM_MODE_OFF )
3332     {
3333         if ( !s->ecn && (p->tcph->th_flags & (TH_ECE|TH_CWR)) )
3334         {
3335             normStats[PC_TCP_ECN_SSN][mode]++;
3336             sfBase.iPegs[PERF_COUNT_TCP_ECN_SSN][mode]++;
3337             if ( mode == NORM_MODE_ON )
3338             {
3339                 ((TCPHdr*)p->tcph)->th_flags &= ~(TH_ECE|TH_CWR);
3340                 p->packet_flags |= PKT_MODIFIED;
3341             }
3342         }
3343     }
3344 }
3345 #else
3346 #define NormalDropPacket(p)
3347 #define NormalTrackECN(s, h, r)
3348 #endif
3349 
StreamUpdatePerfBaseState(SFBASE * sf_base,SessionControlBlock * scb,char newState)3350 void StreamUpdatePerfBaseState(SFBASE *sf_base,
3351         SessionControlBlock *scb,
3352         char newState)
3353 {
3354     if (!scb)
3355     {
3356         return;
3357     }
3358 
3359     switch (newState)
3360     {
3361         case TCP_STATE_SYN_SENT:
3362             if (!(scb->ha_state.session_flags & SSNFLAG_COUNTED_INITIALIZE))
3363             {
3364                 sf_base->iSessionsInitializing++;
3365                 scb->ha_state.session_flags |= SSNFLAG_COUNTED_INITIALIZE;
3366             }
3367             break;
3368         case TCP_STATE_ESTABLISHED:
3369             if (!(scb->ha_state.session_flags & SSNFLAG_COUNTED_ESTABLISH))
3370             {
3371                 sf_base->iSessionsEstablished++;
3372                 EventInternal(INTERNAL_EVENT_SESSION_ADD);
3373 
3374                 if (perfmon_config && (perfmon_config->perf_flags & SFPERF_FLOWIP))
3375                     UpdateFlowIPState(&sfFlow, IP_ARG(scb->client_ip), IP_ARG(scb->server_ip), SFS_STATE_TCP_ESTABLISHED);
3376 
3377                 scb->ha_state.session_flags |= SSNFLAG_COUNTED_ESTABLISH;
3378 
3379                 if ((scb->ha_state.session_flags & SSNFLAG_COUNTED_INITIALIZE) &&
3380                         !(scb->ha_state.session_flags & SSNFLAG_COUNTED_CLOSING))
3381                 {
3382                     assert(sf_base->iSessionsInitializing);
3383                     sf_base->iSessionsInitializing--;
3384                 }
3385             }
3386             break;
3387         case TCP_STATE_CLOSING:
3388             if (!(scb->ha_state.session_flags & SSNFLAG_COUNTED_CLOSING))
3389             {
3390                 sf_base->iSessionsClosing++;
3391                 scb->ha_state.session_flags |= SSNFLAG_COUNTED_CLOSING;
3392                 if (scb->ha_state.session_flags & SSNFLAG_COUNTED_ESTABLISH)
3393                 {
3394                     assert(sf_base->iSessionsEstablished);
3395                     sf_base->iSessionsEstablished--;
3396 
3397                     if (perfmon_config && (perfmon_config->perf_flags & SFPERF_FLOWIP))
3398                         UpdateFlowIPState(&sfFlow, IP_ARG(scb->client_ip), IP_ARG(scb->server_ip), SFS_STATE_TCP_CLOSED);
3399                 }
3400                 else if (scb->ha_state.session_flags & SSNFLAG_COUNTED_INITIALIZE)
3401                 {
3402                     assert(sf_base->iSessionsInitializing);
3403                     sf_base->iSessionsInitializing--;
3404                 }
3405             }
3406             break;
3407         case TCP_STATE_CLOSED:
3408             if (scb->ha_state.session_flags & SSNFLAG_COUNTED_CLOSING)
3409             {
3410                 assert(sf_base->iSessionsClosing);
3411                 sf_base->iSessionsClosing--;
3412             }
3413             else if (scb->ha_state.session_flags & SSNFLAG_COUNTED_ESTABLISH)
3414             {
3415                 assert(sf_base->iSessionsEstablished);
3416                 sf_base->iSessionsEstablished--;
3417 
3418                 if (perfmon_config && (perfmon_config->perf_flags & SFPERF_FLOWIP))
3419                     UpdateFlowIPState(&sfFlow, IP_ARG(scb->client_ip), IP_ARG(scb->server_ip), SFS_STATE_TCP_CLOSED);
3420             }
3421             else if (scb->ha_state.session_flags & SSNFLAG_COUNTED_INITIALIZE)
3422             {
3423                 assert(sf_base->iSessionsInitializing);
3424                 sf_base->iSessionsInitializing--;
3425             }
3426             break;
3427         default:
3428             break;
3429     }
3430     sf_base->stream5_mem_in_use = session_mem_in_use;
3431 }
3432 
3433 //-------------------------------------------------------------------------
3434 // ssn ingress is client; ssn egress is server
3435 
3436 #ifdef HAVE_DAQ_ADDRESS_SPACE_ID
SetPacketHeaderFoo(TcpSession * tcpssn,const Packet * p)3437 static inline void SetPacketHeaderFoo (TcpSession* tcpssn, const Packet* p)
3438 {
3439     if ( ( p->packet_flags & PKT_FROM_CLIENT ) || p->pkth->egress_index == DAQ_PKTHDR_UNKNOWN )
3440     {
3441         tcpssn->ingress_index = p->pkth->ingress_index;
3442         tcpssn->ingress_group = p->pkth->ingress_group;
3443         // ssn egress may be unknown, but will be correct
3444         tcpssn->egress_index = p->pkth->egress_index;
3445         tcpssn->egress_group = p->pkth->egress_group;
3446     }
3447     else
3448     {
3449         if ( p->pkth->egress_index != DAQ_PKTHDR_FLOOD )
3450         {
3451             tcpssn->ingress_index = p->pkth->egress_index;
3452             tcpssn->ingress_group = p->pkth->egress_group;
3453         }
3454         tcpssn->egress_index = p->pkth->ingress_index;
3455         tcpssn->egress_group = p->pkth->ingress_group;
3456     }
3457 #ifdef HAVE_DAQ_FLOW_ID
3458     tcpssn->daq_flow_id = p->pkth->flow_id;
3459 #endif
3460     tcpssn->daq_flags = p->pkth->flags;
3461 #if !defined(SFLINUX) && defined(DAQ_CAPA_VRF)
3462     tcpssn->address_space_id_dst = p->pkth->address_space_id_dst;
3463     tcpssn->address_space_id_src = p->pkth->address_space_id_src;
3464 #else
3465     tcpssn->address_space_id = p->pkth->address_space_id;
3466 #endif
3467 }
3468 
GetPacketHeaderFoo(const TcpSession * tcpssn,const DAQ_PktHdr_t * phdr,EncodeFlags fwd,DAQ_PktHdr_t * pkth,uint32_t dir)3469 static inline void GetPacketHeaderFoo (
3470         const TcpSession* tcpssn, const DAQ_PktHdr_t* phdr, EncodeFlags fwd,
3471         DAQ_PktHdr_t* pkth, uint32_t dir)
3472 {
3473     if ( (dir & PKT_FROM_CLIENT) || tcpssn->egress_index == DAQ_PKTHDR_UNKNOWN )
3474     {
3475         pkth->ingress_index = tcpssn->ingress_index;
3476         pkth->ingress_group = tcpssn->ingress_group;
3477         pkth->egress_index = tcpssn->egress_index;
3478         pkth->egress_group = tcpssn->egress_group;
3479     }
3480     else
3481     {
3482         pkth->ingress_index = tcpssn->egress_index;
3483         pkth->ingress_group = tcpssn->egress_group;
3484         pkth->egress_index = tcpssn->ingress_index;
3485         pkth->egress_group = tcpssn->ingress_group;
3486     }
3487 #ifdef HAVE_DAQ_FLOW_ID
3488     pkth->flow_id = tcpssn->daq_flow_id;
3489 #endif
3490     pkth->flags = tcpssn->daq_flags;
3491     pkth->priv_ptr = tcpssn->priv_ptr;
3492 #if !defined(SFLINUX) && defined(DAQ_CAPA_VRF)
3493     pkth->address_space_id_dst = tcpssn->address_space_id_dst;
3494     pkth->address_space_id_src = tcpssn->address_space_id_src;
3495 #else
3496     pkth->address_space_id = tcpssn->address_space_id;
3497 #endif
3498 #if defined(DAQ_VERSION) && DAQ_VERSION > 8
3499     pkth->proto = phdr->proto;
3500 #endif
3501 
3502 #if !defined(SFLINUX) && defined(DAQ_CAPA_CARRIER_ID) && defined(DAQ_VERSION) && DAQ_VERSION > 10
3503     pkth->carrier_id = phdr->carrier_id;
3504 #endif
3505 
3506 #ifdef HAVE_DAQ_REAL_ADDRESSES
3507     if (phdr->flags & DAQ_PKT_FLAG_REAL_ADDRESSES)
3508     {
3509         pkth->flags &= ~(DAQ_PKT_FLAG_REAL_SIP_V6 | DAQ_PKT_FLAG_REAL_DIP_V6);
3510         if (fwd)
3511         {
3512             pkth->flags |= phdr->flags & (DAQ_PKT_FLAG_REAL_SIP_V6 | DAQ_PKT_FLAG_REAL_DIP_V6);
3513             pkth->n_real_sPort = phdr->n_real_sPort;
3514             pkth->n_real_dPort = phdr->n_real_dPort;
3515             pkth->real_sIP = phdr->real_sIP;
3516             pkth->real_dIP = phdr->real_dIP;
3517         }
3518         else
3519         {
3520             if (phdr->flags & DAQ_PKT_FLAG_REAL_SIP_V6)
3521                 pkth->flags |= DAQ_PKT_FLAG_REAL_DIP_V6;
3522             if (phdr->flags & DAQ_PKT_FLAG_REAL_DIP_V6)
3523                 pkth->flags |= DAQ_PKT_FLAG_REAL_SIP_V6;
3524             pkth->n_real_sPort = phdr->n_real_dPort;
3525             pkth->n_real_dPort = phdr->n_real_sPort;
3526             pkth->real_sIP = phdr->real_dIP;
3527             pkth->real_dIP = phdr->real_sIP;
3528         }
3529     }
3530 #endif
3531 }
3532 
SwapPacketHeaderFoo(TcpSession * tcpssn)3533 static inline void SwapPacketHeaderFoo (TcpSession* tcpssn)
3534 {
3535     if ( tcpssn->egress_index != DAQ_PKTHDR_UNKNOWN )
3536     {
3537         int32_t ingress_index;
3538         int32_t ingress_group;
3539 
3540         ingress_index = tcpssn->ingress_index;
3541         ingress_group = tcpssn->ingress_group;
3542         tcpssn->ingress_index = tcpssn->egress_index;
3543         tcpssn->ingress_group = tcpssn->egress_group;
3544         tcpssn->egress_index = ingress_index;
3545         tcpssn->egress_group = ingress_group;
3546     }
3547 }
3548 #endif
3549 
3550 
3551 //-------------------------------------------------------------------------
3552 
IsBetween(uint32_t low,uint32_t high,uint32_t cur)3553 static inline int IsBetween(uint32_t low, uint32_t high, uint32_t cur)
3554 {
3555     STREAM_DEBUG_WRAP(DebugMessage(DEBUG_STREAM_STATE,
3556                 "(%X, %X, %X) = (low, high, cur)\n", low,high,cur););
3557 
3558     /* If we haven't seen anything, ie, low & high are 0, return true */
3559     if ((low == 0) && (low == high))
3560         return 1;
3561 
3562     return (SEQ_GEQ(cur, low) && SEQ_LEQ(cur, high));
3563 }
3564 
TwoWayTraffic(SessionControlBlock * scb)3565 static inline bool TwoWayTraffic (SessionControlBlock *scb)
3566 {
3567     return ( (scb->ha_state.session_flags & SSNFLAG_SEEN_BOTH) == SSNFLAG_SEEN_BOTH );
3568 }
3569 
StreamGetWindow(SessionControlBlock * scb,StreamTracker * st,TcpDataBlock * tdb)3570 static inline uint32_t StreamGetWindow(
3571         SessionControlBlock *scb, StreamTracker* st, TcpDataBlock* tdb)
3572 {
3573     int32_t window;
3574 
3575     if ( st->l_window )
3576     {
3577         // don't use the window if we may have missed scaling
3578         if ( !(scb->session_state & STREAM_STATE_MIDSTREAM) )
3579             return st->l_window;
3580     }
3581     // one way zero window is unitialized
3582     // two way zero window is actually closed (regardless of scaling)
3583     else if ( TwoWayTraffic(scb) )
3584         return st->l_window;
3585 
3586     // ensure the data is in the window
3587     window = tdb->end_seq - st->r_win_base;
3588 
3589     if(window <  0)
3590         window = 0;
3591 
3592     return (uint32_t) window;
3593 }
3594 
3595 // ack number must ack syn
ValidRstSynSent(StreamTracker * st,TcpDataBlock * tdb)3596 static inline int ValidRstSynSent(StreamTracker *st, TcpDataBlock *tdb)
3597 {
3598     return tdb->ack == st->l_unackd;
3599 }
3600 
3601 // per rfc 793 a rst is valid if the seq number is in window
3602 // for all states but syn-sent (handled above).  however, we
3603 // validate here based on how various implementations actually
3604 // handle a rst.
ValidRst(SessionControlBlock * scb,StreamTracker * st,TcpDataBlock * tdb)3605 static inline int ValidRst(
3606         SessionControlBlock *scb, StreamTracker *st, TcpDataBlock *tdb)
3607 {
3608     STREAM_DEBUG_WRAP(DebugMessage(DEBUG_STREAM_STATE,
3609                 "Checking end_seq (%X) > r_win_base (%X) && "
3610                 "seq (%X) < r_nxt_ack(%X)\n",
3611                 tdb->end_seq, st->r_win_base, tdb->seq,
3612                 st->r_nxt_ack+StreamGetWindow(scb, st, tdb)););
3613 
3614     switch (st->os_policy)
3615     {
3616         case STREAM_POLICY_HPUX11:
3617             if (SEQ_GEQ(tdb->seq, st->r_nxt_ack))
3618             {
3619                 STREAM_DEBUG_WRAP(DebugMessage(DEBUG_STREAM_STATE,
3620                             "rst is valid seq (>= next seq)!\n"););
3621                 return 1;
3622             }
3623             STREAM_DEBUG_WRAP(DebugMessage(DEBUG_STREAM_STATE,
3624                         "rst is not valid seq (>= next seq)!\n"););
3625             return 0;
3626             break;
3627         case STREAM_POLICY_FIRST:
3628         case STREAM_POLICY_NOACK:
3629         case STREAM_POLICY_LAST:
3630         case STREAM_POLICY_MACOS:
3631         case STREAM_POLICY_WINDOWS:
3632         case STREAM_POLICY_VISTA:
3633         case STREAM_POLICY_WINDOWS2K3:
3634         case STREAM_POLICY_HPUX10:
3635         case STREAM_POLICY_IRIX:
3636             if (SEQ_EQ(tdb->seq, st->r_nxt_ack))
3637             {
3638                 STREAM_DEBUG_WRAP(DebugMessage(DEBUG_STREAM_STATE,
3639                             "rst is valid seq (next seq)!\n"););
3640                 return 1;
3641             }
3642             STREAM_DEBUG_WRAP(DebugMessage(DEBUG_STREAM_STATE,
3643                         "rst is not valid seq (next seq)!\n"););
3644             return 0;
3645             break;
3646         case STREAM_POLICY_BSD:
3647         case STREAM_POLICY_LINUX:
3648         case STREAM_POLICY_OLD_LINUX:
3649         case STREAM_POLICY_SOLARIS:
3650             if(SEQ_GEQ(tdb->end_seq, st->r_win_base))
3651             {
3652                 // reset must be admitted when window closed
3653                 if ( SEQ_LEQ(tdb->seq, st->r_win_base+StreamGetWindow(scb, st, tdb)) )
3654                 {
3655                     STREAM_DEBUG_WRAP(DebugMessage(DEBUG_STREAM_STATE,
3656                                 "rst is valid seq (within window)!\n"););
3657                     return 1;
3658                 }
3659             }
3660 
3661             STREAM_DEBUG_WRAP(DebugMessage(DEBUG_STREAM_STATE,
3662                         "rst is not valid seq (within window)!\n"););
3663             return 0;
3664             break;
3665     }
3666 
3667     STREAM_DEBUG_WRAP(DebugMessage(DEBUG_STREAM_STATE,
3668                 "rst is not valid!\n"););
3669     return 0;
3670 }
3671 
ValidTimestamp(StreamTracker * talker,StreamTracker * listener,TcpDataBlock * tdb,Packet * p,int * eventcode,int * got_ts)3672 static inline int ValidTimestamp(StreamTracker *talker, StreamTracker *listener, TcpDataBlock *tdb,
3673         Packet *p, int *eventcode, int *got_ts)
3674 {
3675     if((p->tcph->th_flags & TH_RST) || (listener->tcp_policy->policy == STREAM_POLICY_NOACK))
3676         return ACTION_NOTHING;
3677 
3678 #ifdef NORMALIZER
3679 #if 0
3680     if ( p->tcph->th_flags & TH_ACK &&
3681             Normalize_GetMode(snort_conf, NORM_TCP_OPT) != NORM_MODE_OFF)
3682     {
3683         // FIXTHIS validate tsecr here (check that it was previously sent)
3684         // checking for the most recent ts is easy enough must check if
3685         // ts are up to date in retransmitted packets
3686     }
3687 #endif
3688 #endif
3689     /*
3690      * check PAWS
3691      */
3692     if((talker->flags & TF_TSTAMP) && (listener->flags & TF_TSTAMP))
3693     {
3694         char validate_timestamp = 1;
3695         STREAM_DEBUG_WRAP(DebugMessage(DEBUG_STREAM_STATE,
3696                     "Checking timestamps for PAWS\n"););
3697 
3698         *got_ts = StreamGetTcpTimestamp(p, &tdb->ts, 0);
3699 
3700         if (*got_ts)
3701         {
3702             if (listener->tcp_policy->policy == STREAM_POLICY_HPUX11)
3703             {
3704                 /* HPUX 11 ignores timestamps for out of order segments */
3705                 if ((listener->flags & TF_PKT_MISSED) ||
3706                         !SEQ_EQ(listener->r_nxt_ack, tdb->seq))
3707                 {
3708                     validate_timestamp = 0;
3709                 }
3710             }
3711 
3712             if (talker->flags & TF_TSTAMP_ZERO)
3713             {
3714                 /* Handle the case where the 3whs used a 0 timestamp.  Next packet
3715                  * from that endpoint should have a valid timestamp... */
3716                 if ((listener->tcp_policy->policy == STREAM_POLICY_LINUX) ||
3717                         (listener->tcp_policy->policy == STREAM_POLICY_WINDOWS2K3))
3718                 {
3719                     /* Linux, Win2k3 et al.  do not support timestamps if
3720                      * the 3whs used a 0 timestamp. */
3721                     talker->flags &= ~TF_TSTAMP;
3722                     listener->flags &= ~TF_TSTAMP;
3723                     validate_timestamp = 0;
3724                 }
3725                 else if ((listener->tcp_policy->policy == STREAM_POLICY_OLD_LINUX) ||
3726                         (listener->tcp_policy->policy == STREAM_POLICY_WINDOWS) ||
3727                         (listener->tcp_policy->policy == STREAM_POLICY_VISTA))
3728                 {
3729                     /* Older Linux (2.2 kernel & earlier), Win32 (non 2K3)
3730                      * allow the 3whs to use a 0 timestamp. */
3731                     talker->flags &= ~TF_TSTAMP_ZERO;
3732                     if(SEQ_EQ(listener->r_nxt_ack, tdb->seq))
3733                     {
3734                         talker->ts_last = tdb->ts;
3735                         validate_timestamp = 0; /* Ignore the timestamp for this
3736                                                  * first packet, next one will
3737                                                  * checked. */
3738                     }
3739                 }
3740             }
3741 
3742             if (validate_timestamp)
3743             {
3744                 int result = 0;
3745                 if (listener->tcp_policy->policy == STREAM_POLICY_LINUX)
3746                 {
3747                     /* Linux 2.6 accepts timestamp values that are off
3748                      * by one. */
3749                     result = (int)((tdb->ts - talker->ts_last) + 1);
3750                 }
3751                 else
3752                 {
3753                     result = (int)(tdb->ts - talker->ts_last);
3754                 }
3755 
3756 #ifdef DAQ_PKT_FLAG_RETRY_PACKET
3757                 if(result < 0 && (p->pkth->flags & DAQ_PKT_FLAG_RETRY_PACKET))
3758                 {
3759                     //  Retry packets can legitimately have old timestamps
3760                     //  in TCP options (if a re-transmit comes in before
3761                     //  the retry) so don't consider it an error.
3762                     STREAM_DEBUG_WRAP(DebugMessage(DEBUG_STREAM_STATE,
3763                                 "Retry packet had old timestamp.  Reseting to last timestamp seen.\n"););
3764                     tdb->ts = talker->ts_last;
3765                 }
3766                 else
3767 #endif
3768                 if( (talker->ts_last != 0) && result < 0)
3769                 {
3770                     STREAM_DEBUG_WRAP(DebugMessage(DEBUG_STREAM_STATE,
3771                                 "Packet outside PAWS window, dropping\n"););
3772                     /* bail, we've got a packet outside the PAWS window! */
3773                     //Discard();
3774                     *eventcode |= EVENT_BAD_TIMESTAMP;
3775                     NormalDropPacket(p);
3776                     return ACTION_BAD_PKT;
3777                 }
3778                 else if ((talker->ts_last != 0) &&
3779                         ((uint32_t)p->pkth->ts.tv_sec > talker->ts_last_pkt+PAWS_24DAYS))
3780                 {
3781                     /* this packet is from way too far into the future */
3782                     STREAM_DEBUG_WRAP(DebugMessage(DEBUG_STREAM_STATE,
3783                                 "packet PAWS timestamp way too far ahead of"
3784                                 "last packet %d %d...\n", p->pkth->ts.tv_sec,
3785                                 talker->ts_last_pkt););
3786                     //Discard();
3787                     *eventcode |= EVENT_BAD_TIMESTAMP;
3788                     NormalDropPacket(p);
3789                     return ACTION_BAD_PKT;
3790                 }
3791                 else
3792                 {
3793                     STREAM_DEBUG_WRAP(DebugMessage(DEBUG_STREAM_STATE,
3794                                 "packet PAWS ok...\n"););
3795                 }
3796             }
3797         }
3798         else
3799         {
3800             /* we've got a packet with no timestamp, but 3whs indicated talker
3801              * was doing timestamps.  This breaks protocol, however, some servers
3802              * still ack the packet with the missing timestamp.  Log an alert,
3803              * but continue to process the packet
3804              */
3805             *eventcode |= EVENT_NO_TIMESTAMP;
3806             STREAM_DEBUG_WRAP(DebugMessage(DEBUG_STREAM_STATE,
3807                         "packet no timestamp, had one earlier from this side...ok for now...\n"););
3808 
3809             if (listener->tcp_policy->policy == STREAM_POLICY_SOLARIS)
3810             {
3811                 /* Solaris stops using timestamps if it receives a packet
3812                  * without a timestamp and there were timestamps in use.
3813                  */
3814                 listener->flags &= ~TF_TSTAMP;
3815             }
3816             NormalDropPacket(p);
3817         }
3818     }
3819     else if ( TCP_ISFLAGSET(p->tcph, TH_SYN) &&
3820             !TCP_ISFLAGSET(p->tcph, TH_ACK) )
3821     {
3822         *got_ts = StreamGetTcpTimestamp(p, &tdb->ts, 0);
3823         if ( *got_ts ) {
3824             talker->flags |= TF_TSTAMP;
3825             // In case of SYN, there is no ts_last is 0
3826             // set it to the current value, so that computation of
3827             // ts_last is correct for subsequent packets.
3828             talker->ts_last = tdb->ts;
3829             talker->ts_last_pkt = p->pkth->ts.tv_sec;
3830         }
3831     }
3832     else
3833     {
3834 #ifdef NORMALIZER
3835         // if we are not handling timestamps, and this isn't a syn
3836         // (only), and we have seen a valid 3way setup, then we strip
3837         // (nop) the timestamp option.  this includes the cases where
3838         // we disable timestamp handling.
3839         int strip = ( SetupOK(talker) && SetupOK(listener) );
3840 #else
3841         int strip = 0;
3842 #endif
3843         STREAM_DEBUG_WRAP(DebugMessage(DEBUG_STREAM_STATE,
3844                     "listener not doing timestamps...\n"););
3845         *got_ts = StreamGetTcpTimestamp(p, &tdb->ts, strip);
3846 
3847         if (*got_ts)
3848         {
3849             if (!(talker->flags & TF_TSTAMP))
3850             {
3851                 /* Since we skipped the SYN, may have missed the talker's
3852                  * timestamp there, so set it now.
3853                  */
3854                 talker->flags |= TF_TSTAMP;
3855                 if (tdb->ts == 0)
3856                 {
3857                     talker->flags |= TF_TSTAMP_ZERO;
3858                 }
3859             }
3860 
3861             /* Only valid to test this if listener is using timestamps.
3862              * Otherwise, timestamp in this packet is not used, regardless
3863              * of its value. */
3864             if ((tdb->ts == 0) && (listener->flags & TF_TSTAMP))
3865             {
3866                 switch (listener->os_policy)
3867                 {
3868                     case STREAM_POLICY_WINDOWS:
3869                     case STREAM_POLICY_VISTA:
3870                     case STREAM_POLICY_WINDOWS2K3:
3871                     case STREAM_POLICY_OLD_LINUX:
3872                     case STREAM_POLICY_SOLARIS:
3873                         /* Old Linux & Windows allows a 0 timestamp value. */
3874                         break;
3875                     default:
3876                         STREAM_DEBUG_WRAP(DebugMessage(DEBUG_STREAM_STATE,
3877                                     "Packet with 0 timestamp, dropping\n"););
3878                         //Discard();
3879                         /* bail */
3880                         *eventcode |= EVENT_BAD_TIMESTAMP;
3881                         return ACTION_BAD_PKT;
3882                 }
3883             }
3884         }
3885     }
3886     return ACTION_NOTHING;
3887 }
3888 
3889 #ifdef S5_PEDANTIC
3890 // From RFC 793:
3891 //
3892 //    Segment Receive  Test
3893 //    Length  Window
3894 //    ------- -------  -------------------------------------------
3895 //
3896 //       0       0     SEG.SEQ = RCV.NXT
3897 //
3898 //       0      >0     RCV.NXT =< SEG.SEQ < RCV.NXT+RCV.WND
3899 //
3900 //      >0       0     not acceptable
3901 //
3902 //      >0      >0     RCV.NXT =< SEG.SEQ < RCV.NXT+RCV.WND
3903 //                     or RCV.NXT =< SEG.SEQ+SEG.LEN-1 < RCV.NXT+RCV.WND
3904 //
ValidSeq(const Packet * p,SessionControlBlock * scb,StreamTracker * st,TcpDataBlock * tdb,bool * before_win_base)3905 static inline int ValidSeq(
3906         const Packet* p, SessionControlBlock *scb, StreamTracker *st, TcpDataBlock *tdb, bool *before_win_base)
3907 {
3908     uint32_t win = StreamGetWindow(scb, st, tdb);
3909 
3910     if ( !p->dsize )
3911     {
3912         if ( !win )
3913         {
3914             return ( tdb->seq == st->r_win_base );
3915         }
3916         return SEQ_LEQ(st->r_win_base, tdb->seq) &&
3917             SEQ_LT(tdb->seq, st->r_win_base+win);
3918     }
3919     if ( !win )
3920         return 0;
3921 
3922     if ( SEQ_LEQ(st->r_win_base, tdb->seq) &&
3923             SEQ_LT(tdb->seq, st->r_win_base+win) )
3924         return 1;
3925 
3926     return SEQ_LEQ(st->r_win_base, tdb->end_seq) &&
3927         SEQ_LT(tdb->end_seq, st->r_win_base+win);
3928 }
3929 #else
ValidSeq(const Packet * p,SessionControlBlock * scb,StreamTracker * st,TcpDataBlock * tdb,bool * before_win_base)3930 static inline int ValidSeq(
3931         const Packet* p, SessionControlBlock *scb, StreamTracker *st, TcpDataBlock *tdb, bool *before_win_base)
3932 {
3933     int right_ok;
3934     uint32_t left_seq;
3935 
3936     STREAM_DEBUG_WRAP(DebugMessage(DEBUG_STREAM_STATE,
3937                 "Checking end_seq (%X) > r_win_base (%X) && "
3938                 "seq (%X) < r_nxt_ack(%X)\n",
3939                 tdb->end_seq, st->r_win_base, tdb->seq,
3940                 st->r_nxt_ack+StreamGetWindow(scb, st, tdb)););
3941 
3942     if ( SEQ_LT(st->r_nxt_ack, st->r_win_base) )
3943         left_seq = st->r_nxt_ack;
3944     else
3945         left_seq = st->r_win_base;
3946 
3947     if ( p->dsize )
3948         right_ok = SEQ_GT(tdb->end_seq, left_seq);
3949     else
3950         right_ok = SEQ_GEQ(tdb->end_seq, left_seq);
3951 
3952     if ( right_ok )
3953     {
3954         uint32_t win = StreamGetWindow(scb, st, tdb);
3955 
3956         if( SEQ_LEQ(tdb->seq, st->r_win_base+win) )
3957         {
3958             STREAM_DEBUG_WRAP(DebugMessage(DEBUG_STREAM_STATE,
3959                         "seq is within window!\n"););
3960             return 1;
3961         }
3962         else
3963         {
3964             STREAM_DEBUG_WRAP(DebugMessage(DEBUG_STREAM_STATE,
3965                         "seq is past the end of the window!\n"););
3966         }
3967     }
3968     else
3969     {
3970         STREAM_DEBUG_WRAP(DebugMessage(DEBUG_STREAM_STATE,
3971                     "end_seq is before win_base\n"););
3972         *before_win_base = true;
3973     }
3974     return 0;
3975 }
3976 #endif
3977 
UpdateSsn(Packet * p,StreamTracker * rcv,StreamTracker * snd,TcpDataBlock * tdb)3978 static inline void UpdateSsn(Packet* p, StreamTracker *rcv, StreamTracker *snd, TcpDataBlock *tdb)
3979 {
3980 #if 0
3981 #ifdef NORMALIZER
3982     if (
3983             // FIXTHIS these checks are a hack to avoid off by one normalization
3984             // due to FIN ... if last segment filled a hole, r_nxt_ack is not at
3985             // end of data, FIN is ignored so sequence isn't bumped, and this
3986             // forces seq-- on ACK of FIN.  :(
3987         rcv->s_mgr.state == TCP_STATE_ESTABLISHED &&
3988             rcv->s_mgr.state_queue == TCP_STATE_NONE &&
3989             Normalize_GetMode(snort_conf, NORM_TCP_IPS) )
3990             {
3991             // walk the seglist until a gap or tdb->ack whichever is first
3992             // if a gap exists prior to ack, move ack back to start of gap
3993             StreamSegment* seg = snd->seglist;
3994 
3995             // FIXTHIS must check ack oob with empty seglist
3996             // FIXTHIS add lower gap bound to tracker for efficiency?
3997             while ( seg )
3998             {
3999             uint32_t seq = seg->seq + seg->size;
4000             if ( SEQ_LEQ(tdb->ack, seq) )
4001             break;
4002 
4003             seg = seg->next;
4004 
4005             if ( !seg || seg->seq > seq )
4006             {
4007                 // normalize here
4008                 tdb->ack = seq;
4009                 ((TCPHdr*)p->tcph)->th_ack = htonl(seq);
4010                 p->packet_flags |= PKT_MODIFIED;
4011                 break;
4012             }
4013             }
4014             }
4015 #endif
4016 #endif
4017     // ** if we don't see a segment, we can't track seq at ** below
4018     // so we update the seq by the ack if it is beyond next expected
4019     if(SEQ_GT(tdb->ack, rcv->l_unackd))
4020         rcv->l_unackd = tdb->ack;
4021 
4022     // ** this is how we track the last seq number sent
4023     // as is l_unackd is the "last left" seq recvd
4024     snd->l_unackd = tdb->seq;
4025 
4026     if (SEQ_GT(tdb->end_seq, snd->l_nxt_seq))
4027         snd->l_nxt_seq = tdb->end_seq;
4028 
4029 #ifdef S5_PEDANTIC
4030     if ( SEQ_GT(tdb->ack, snd->r_win_base) &&
4031             SEQ_LEQ(tdb->ack, snd->r_nxt_ack) )
4032 #else
4033         if ( SEQ_GT(tdb->ack, snd->r_win_base) )
4034 #endif
4035             snd->r_win_base = tdb->ack;
4036 
4037     snd->l_window = tdb->win;
4038 }
4039 
StreamInitPacket(void)4040 static void StreamInitPacket(void)
4041 {
4042     s5_pkt = Encode_New();
4043 }
4044 
SetupTcpDataBlock(TcpDataBlock * tdb,Packet * p)4045 static inline void SetupTcpDataBlock(TcpDataBlock *tdb, Packet *p)
4046 {
4047     tdb->seq = ntohl(p->tcph->th_seq);
4048     tdb->ack = ntohl(p->tcph->th_ack);
4049     tdb->win = ntohs(p->tcph->th_win);
4050     tdb->end_seq = tdb->seq + (uint32_t) p->dsize;
4051     tdb->ts = 0;
4052 
4053     if(p->tcph->th_flags & TH_SYN)
4054     {
4055         tdb->end_seq++;
4056     }
4057     // don't bump end_seq for fin here
4058     // we will bump if/when fin is processed
4059 
4060     return;
4061 }
4062 
SegmentFree(StreamSegment * seg)4063 static void SegmentFree (StreamSegment *seg)
4064 {
4065     unsigned dropped = sizeof(StreamSegment);
4066 
4067     STREAM_DEBUG_WRAP( DebugMessage(DEBUG_STREAM_STATE,
4068                 "Dumping segment at seq %X, size %d, caplen %d\n",
4069                 seg->seq, seg->size, seg->caplen););
4070 
4071     if ( seg->caplen > 0 )
4072         dropped += seg->caplen - 1;  // seg contains 1st byte
4073 
4074     session_mem_in_use -= dropped;
4075     SnortPreprocFree(seg, dropped, PP_STREAM, PP_MEM_CATEGORY_SESSION);
4076     s5stats.tcp_streamsegs_released++;
4077 
4078     STREAM_DEBUG_WRAP( DebugMessage(DEBUG_STREAM_STATE,
4079                 "SegmentFree dropped %d bytes\n", dropped););
4080 }
4081 
DeleteSeglist(StreamSegment * listhead)4082 static void DeleteSeglist(StreamSegment *listhead)
4083 {
4084     StreamSegment *idx = listhead;
4085     StreamSegment *dump_me;
4086     int i = 0;
4087 
4088     STREAM_DEBUG_WRAP( DebugMessage(DEBUG_STREAM_STATE,
4089                 "In DeleteSeglist\n"););
4090     while(idx)
4091     {
4092         i++;
4093         dump_me = idx;
4094         idx = idx->next;
4095         SegmentFree(dump_me);
4096     }
4097 
4098     STREAM_DEBUG_WRAP( DebugMessage(DEBUG_STREAM_STATE,
4099                 "Dropped %d segments\n", i););
4100 }
4101 
purge_alerts(StreamTracker * st,uint32_t flush_seq,void * ssnptr)4102 static inline int purge_alerts(StreamTracker *st, uint32_t flush_seq, void *ssnptr)
4103 {
4104     int i;
4105     int new_count = 0;
4106 
4107     for (i=0;i<st->alert_count;i++)
4108     {
4109         StreamAlertInfo* ai = st->alerts + i;
4110 
4111         if (SEQ_LT(ai->seq, flush_seq) )
4112         {
4113             if(st->xtradata_mask && extra_data_log)
4114             {
4115                 extra_data_log(
4116                         ssnptr, extra_data_config, xtradata_map,
4117                         xtradata_func_count, st->xtradata_mask,
4118                         ai->event_id, ai->event_second);
4119             }
4120             memset(ai, 0, sizeof(*ai));
4121         }
4122         else
4123         {
4124             if (new_count != i)
4125             {
4126                 st->alerts[new_count] = st->alerts[i];
4127             }
4128             new_count++;
4129         }
4130     }
4131     st->alert_count = new_count;
4132 
4133     return new_count;
4134 }
4135 
purge_to_seq(TcpSession * tcpssn,StreamTracker * st,uint32_t flush_seq)4136 static inline int purge_to_seq(TcpSession *tcpssn, StreamTracker *st, uint32_t flush_seq)
4137 {
4138     StreamSegment *ss = NULL;
4139     StreamSegment *dump_me = NULL;
4140     int purged_bytes = 0;
4141     uint32_t last_ts = 0;
4142 
4143     if(st->seglist == NULL)
4144     {
4145         if ( SEQ_LT(st->seglist_base_seq, flush_seq) )
4146         {
4147             STREAM_DEBUG_WRAP(DebugMessage(DEBUG_STREAM_STATE,
4148                         "setting st->seglist_base_seq to 0x%X\n", flush_seq););
4149             st->seglist_base_seq = flush_seq;
4150         }
4151         return 0;
4152     }
4153 
4154     ss = st->seglist;
4155 
4156     STREAM_DEBUG_WRAP(DebugMessage(DEBUG_STREAM_STATE,
4157                 "In purge_to_seq, start seq = 0x%X end seq = 0x%X delta %d\n",
4158                 ss->seq, flush_seq, flush_seq-ss->seq););
4159     while(ss)
4160     {
4161         STREAM_DEBUG_WRAP(DebugMessage(DEBUG_STREAM_STATE,
4162                     "s: %X  sz: %d\n", ss->seq, ss->size););
4163         dump_me = ss;
4164 
4165         ss = ss->next;
4166         if(SEQ_LT(dump_me->seq, flush_seq))
4167         {
4168             if (dump_me->ts > last_ts)
4169             {
4170                 last_ts = dump_me->ts;
4171             }
4172             purged_bytes += StreamSeglistDeleteNodeTrim(st, dump_me, flush_seq);
4173         }
4174         else
4175             break;
4176     }
4177 
4178     if ( SEQ_LT(st->seglist_base_seq, flush_seq) )
4179     {
4180         STREAM_DEBUG_WRAP(DebugMessage(DEBUG_STREAM_STATE,
4181                     "setting st->seglist_base_seq to 0x%X\n", flush_seq););
4182         st->seglist_base_seq = flush_seq;
4183     }
4184     if ( SEQ_LT(st->r_nxt_ack, flush_seq) )
4185         st->r_nxt_ack = flush_seq;
4186 
4187     purge_alerts(st, flush_seq, (void *)tcpssn->scb);
4188 
4189     if (st->seglist == NULL)
4190     {
4191         st->seglist_tail = NULL;
4192     }
4193 
4194     /* Update the "last" time stamp seen from the other side
4195      * to be the most recent timestamp (largest) that was removed
4196      * from the queue.  This will ensure that as we go forward,
4197      * last timestamp is the highest one that we had stored and
4198      * purged and handle the case when packets arrive out of order,
4199      * such as:
4200      * P1: seq 10, length 10, timestamp 10
4201      * P3: seq 30, length 10, timestamp 30
4202      * P2: seq 20, length 10, timestamp 20
4203      *
4204      * Without doing it this way, the timestamp would be 20.  With
4205      * the next packet to arrive (P4, seq 40), the ts_last value
4206      * wouldn't be updated for the talker in ProcessTcp() since that
4207      * code specificially looks for the NEXT sequence number.
4208      */
4209     if ( !last_ts )
4210         return purged_bytes;
4211 
4212     if (st == &tcpssn->client)
4213     {
4214         int32_t delta = last_ts - tcpssn->server.ts_last;
4215         if (delta > 0)
4216             tcpssn->server.ts_last = last_ts;
4217     }
4218     else if (st == &tcpssn->server)
4219     {
4220         int32_t delta = last_ts - tcpssn->client.ts_last;
4221         if (delta > 0)
4222             tcpssn->client.ts_last = last_ts;
4223     }
4224 
4225     return purged_bytes;
4226 }
4227 
purge_all(StreamTracker * st)4228 static inline void purge_all (StreamTracker *st)
4229 {
4230     DeleteSeglist(st->seglist);
4231     st->seglist = st->seglist_tail = st->seglist_next = NULL;
4232     st->seg_count = st->flush_count = 0;
4233     st->seg_bytes_total = st->seg_bytes_logical = 0;
4234 }
4235 
4236 // purge_flushed_ackd():
4237 // * must only purge flushed and acked bytes
4238 // * we may flush partial segments
4239 // * must adjust seq->seq and seg->size when a flush gets only the
4240 //   initial part of a segment
4241 // * FIXTHIS need flag to mark any reassembled packets that have a gap
4242 //   (if we reassemble such)
purge_flushed_ackd(TcpSession * tcpssn,StreamTracker * st)4243 static inline int purge_flushed_ackd (TcpSession *tcpssn, StreamTracker *st)
4244 {
4245     StreamSegment* seg = st->seglist;
4246     uint32_t seq;
4247 
4248     if ( !st->seglist )
4249         return 0;
4250 
4251     seq = st->seglist->seq;
4252 
4253     while ( seg && seg->buffered )
4254     {
4255         uint32_t end = seg->seq + seg->size;
4256 
4257         if ( SEQ_GT(end, st->r_win_base) )
4258         {
4259             seq = st->r_win_base;
4260             break;
4261         }
4262         seq = end;
4263         seg = seg->next;
4264     }
4265     if ( seq != st->seglist->seq )
4266         return purge_to_seq(tcpssn, st, seq);
4267 
4268     return 0;
4269 }
4270 
ShowRebuiltPacket(Packet * p)4271 static void ShowRebuiltPacket (Packet* p)
4272 {
4273     if(stream_session_config->flags & STREAM_CONFIG_SHOW_PACKETS)
4274     {
4275         //ClearDumpBuf();
4276         printf("+++++++++++++++++++Stream Packet+++++++++++++++++++++\n");
4277         PrintIPPkt(stdout, IPPROTO_TCP, p);
4278         printf("+++++++++++++++++++++++++++++++++++++++++++++++++++++\n");
4279         //ClearDumpBuf();
4280     }
4281 }
4282 
_flush_to_seq_noack(TcpSession * tcpssn,StreamTracker * st,uint32_t bytes,Packet * p,sfaddr_t * sip,sfaddr_t * dip,uint16_t sp,uint16_t dp,uint32_t dir)4283 static inline int _flush_to_seq_noack( TcpSession *tcpssn, StreamTracker *st, uint32_t bytes,
4284         Packet *p, sfaddr_t* sip, sfaddr_t* dip, uint16_t sp, uint16_t dp, uint32_t dir )
4285 {
4286     uint32_t stop_seq;
4287     uint32_t footprint = 0;
4288     uint32_t bytes_processed = 0;
4289     PROFILE_VARS;
4290 
4291     PREPROC_PROFILE_START(s5TcpFlushPerfStats);
4292 
4293     if(p->dsize == 0)
4294         return bytes_processed;
4295 
4296     // if not specified, set bytes to flush to what was acked
4297     if ( !bytes && SEQ_GT(st->r_win_base, st->seglist_base_seq) )
4298         bytes = st->r_win_base - st->seglist_base_seq;
4299 
4300     stop_seq = st->seglist_base_seq + bytes;
4301 
4302     {
4303         footprint = stop_seq - st->seglist_base_seq;
4304 
4305         if(footprint == 0)
4306         {
4307             STREAM_DEBUG_WRAP(DebugMessage(DEBUG_STREAM_STATE,
4308                         "Negative footprint, bailing %d (0x%X - 0x%X)\n",
4309                         footprint, stop_seq, st->seglist_base_seq););
4310             PREPROC_PROFILE_END(s5TcpFlushPerfStats);
4311 
4312             return bytes_processed;
4313         }
4314 
4315 #if 0
4316         //Might not need this as we are not buffering the packets??
4317 #ifdef DEBUG_STREAM
4318         if(footprint < st->seg_bytes_logical)
4319         {
4320             STREAM5_DEBUG_WRAP(DebugMessage(DEBUG_STREAM_STATE,
4321                         "Footprint less than queued bytes, "
4322                         "win_base: 0x%X base_seq: 0x%X\n",
4323                         stop_seq, st->seglist_base_seq););
4324         }
4325 #endif
4326 #endif
4327 
4328 #if 0
4329         //Won't need this as we are not buffering the packets
4330         if(footprint > p->max_dsize)
4331         {
4332             /* this is as much as we can pack into a stream buffer */
4333             footprint = p->max_dsize;
4334             stop_seq = st->seglist_base_seq + footprint;
4335         }
4336 #endif
4337 
4338         STREAM_DEBUG_WRAP(DebugMessage(DEBUG_STREAM_STATE,
4339                     "Attempting to flush %lu bytes\n", footprint););
4340 
4341         st->seglist_base_seq = stop_seq;
4342         st->seglist_next->buffered = SL_BUF_FLUSHED;
4343         st->flush_count++;
4344         p->packet_flags &= ~PKT_STREAM_INSERT;
4345         p->packet_flags |= (PKT_REBUILT_STREAM|PKT_STREAM_EST);
4346         bytes_processed = p->dsize;
4347 
4348         sfBase.iStreamFlushes++;
4349         ShowRebuiltPacket(p);
4350         s5stats.tcp_rebuilt_packets++;
4351         UpdateStreamReassStats(&sfBase, bytes_processed);
4352 
4353     }
4354 
4355     if ( st->tcp_policy )
4356         UpdateFlushMgr(snort_conf, &st->flush_mgr, &st->tcp_policy->flush_point_list, st->flags);
4357 
4358     /* tell them how many bytes we processed */
4359     PREPROC_PROFILE_END(s5TcpFlushPerfStats);
4360     return bytes_processed;
4361 }
4362 
getSegmentFlushSize(StreamTracker * st,StreamSegment * ss,uint32_t to_seq,unsigned int flushBufSize)4363 static inline unsigned int getSegmentFlushSize(
4364         StreamTracker* st,
4365         StreamSegment *ss,
4366         uint32_t to_seq,
4367         unsigned int flushBufSize
4368         )
4369 {
4370     unsigned int flushSize = ss->size;
4371 
4372     //copy only till flush buffer gets full
4373     if ( flushSize > flushBufSize )
4374         flushSize = flushBufSize;
4375 
4376     // copy only to flush point
4377     if ( s5_paf_active(&st->paf_state) && SEQ_GT(ss->seq + flushSize, to_seq) )
4378         flushSize = to_seq - ss->seq;
4379 
4380     return flushSize;
4381 }
4382 
PseudoFlushStream(Packet * p,StreamTracker * st,uint32_t toSeq,uint8_t * flushbuf,const uint8_t * flushbuf_end)4383 static int PseudoFlushStream(
4384    Packet* p, StreamTracker *st, uint32_t toSeq,
4385    uint8_t *flushbuf, const uint8_t *flushbuf_end)
4386 {
4387     StreamSegment *ss = NULL, *seglist;
4388     uint16_t bytes_flushed = 0;
4389     uint32_t flushbuf_size, bytes_to_copy;
4390     int ret;
4391     PROFILE_VARS;
4392 
4393     if ( st->seglist == NULL || st->seglist_tail == NULL )
4394         return -1;
4395 
4396     PREPROC_PROFILE_START(s5TcpBuildPacketPerfStats);
4397 
4398     // skip over previously pseudo flushed segments
4399     seglist = st->seglist_next;
4400 
4401     for(ss = seglist; ss && SEQ_LT(ss->seq,  toSeq); ss = ss->next)
4402     {
4403         flushbuf_size = flushbuf_end - flushbuf;
4404         bytes_to_copy = getSegmentFlushSize(st, ss, toSeq, flushbuf_size);
4405 
4406         STREAM_DEBUG_WRAP(DebugMessage(DEBUG_STREAM_STATE,
4407                    "Copying %u bytes for pseudo flushing from %X\n",
4408                    bytes_to_copy, ss->seq););
4409 
4410         ret = SafeMemcpy(flushbuf, ss->payload,
4411                     bytes_to_copy, flushbuf, flushbuf_end);
4412 
4413         if (ret == SAFEMEM_ERROR)
4414         {
4415             STREAM_DEBUG_WRAP(DebugMessage(DEBUG_STREAM_STATE,
4416                             "ERROR writing flushbuf while pseudo flushing."
4417                             "Attempting to write flushbuf out of range!\n"););
4418         }
4419         else
4420         {
4421             flushbuf += bytes_to_copy;
4422         }
4423 
4424         bytes_flushed += bytes_to_copy;
4425         if (ss->next)
4426         {
4427             st->seglist_next = ss->next;
4428         }
4429 
4430         if ( flushbuf >= flushbuf_end )
4431             break;
4432 
4433         if ( SEQ_EQ(ss->seq + bytes_to_copy,  toSeq) )
4434             break;
4435 
4436     }
4437 
4438     PREPROC_PROFILE_END(s5TcpBuildPacketPerfStats);
4439     return bytes_flushed;
4440 }
4441 
pseudo_flush(TcpSession * tcpssn,StreamTracker * st,uint32_t bytes,Packet * p,sfaddr_t * sip,sfaddr_t * dip,uint16_t sp,uint16_t dp,uint32_t dir)4442 static inline void pseudo_flush(
4443 TcpSession *tcpssn, StreamTracker *st, uint32_t bytes, Packet *p,
4444         sfaddr_t* sip, sfaddr_t* dip, uint16_t sp, uint16_t dp, uint32_t dir)
4445 {
4446     uint32_t start_seq;
4447     uint32_t stop_seq;
4448     uint32_t footprint = 0;
4449     uint32_t bytes_processed = 0;
4450     int32_t flushed_bytes;
4451     StreamSegment *ss = NULL;
4452 
4453 #ifdef HAVE_DAQ_ADDRESS_SPACE_ID
4454     DAQ_PktHdr_t pkth;
4455 #endif
4456     EncodeFlags enc_flags = 0;
4457     PROFILE_VARS;
4458 
4459     if (!bytes)
4460     {
4461         STREAM_DEBUG_WRAP(DebugMessage(DEBUG_STREAM_STATE,
4462                "No bytes to pseudo flush\n"););
4463         return;
4464     }
4465     PREPROC_PROFILE_START(s5TcpFlushPerfStats);
4466 
4467     if ( !p->packet_flags || (dir & p->packet_flags) )
4468         enc_flags = ENC_FLAG_FWD;
4469 
4470 #ifdef HAVE_DAQ_ADDRESS_SPACE_ID
4471     GetPacketHeaderFoo(tcpssn, p->pkth, enc_flags, &pkth, dir);
4472     Encode_Format_With_DAQ_Info(enc_flags, p, s5_pkt, PSEUDO_PKT_TCP, &pkth, 0);
4473 #elif defined(HAVE_DAQ_ACQUIRE_WITH_META)
4474     Encode_Format_With_DAQ_Info(enc_flags, p, s5_pkt, PSEUDO_PKT_TCP, 0);
4475 #else
4476     Encode_Format(enc_flags, p, s5_pkt, PSEUDO_PKT_TCP);
4477 #endif
4478 
4479     s5_pkt_end = s5_pkt->data + s5_pkt->max_dsize;
4480 
4481     ss = st->seglist_next;
4482     stop_seq = st->seglist_next->seq + bytes;
4483     do
4484     {
4485         footprint = bytes;
4486         if(footprint > s5_pkt->max_dsize)
4487         {
4488             /* this is as much as we can pack into a stream buffer */
4489             footprint = s5_pkt->max_dsize;
4490             stop_seq = st->seglist_next->seq + footprint;
4491         }
4492 
4493         STREAM_DEBUG_WRAP(DebugMessage(DEBUG_STREAM_STATE,
4494                     "Attempting to pseudo flush %lu bytes\n", footprint););
4495         /* Capture the seq of the first octet before flush changes the sequence numbers */
4496         start_seq = htonl(st->seglist_next->seq);
4497 
4498         /* setup the pseudopacket payload */
4499         flushed_bytes = PseudoFlushStream(p, st, stop_seq, (uint8_t *)s5_pkt->data, s5_pkt_end);
4500 
4501         if(flushed_bytes == -1)
4502         {
4503             STREAM_DEBUG_WRAP(DebugMessage(DEBUG_STREAM_STATE,
4504                     "Failed to pseudo flush the stream\n"););
4505             return;
4506         }
4507         if (flushed_bytes == 0)
4508         {
4509             /* No more ACK'd data... bail */
4510             break;
4511         }
4512 
4513         bytes_processed += flushed_bytes;
4514 
4515         ((TCPHdr *)s5_pkt->tcph)->th_seq = start_seq;
4516         s5_pkt->packet_flags |= (PKT_REBUILT_STREAM|PKT_STREAM_EST);
4517         s5_pkt->dsize = (uint16_t)flushed_bytes;
4518 
4519         s5_pkt->packet_flags |= PKT_PDU_TAIL;
4520         s5_pkt->packet_flags |= PKT_PSEUDO_FLUSH;
4521 
4522         Encode_Update(s5_pkt);
4523 
4524         if(IS_IP4(s5_pkt))
4525         {
4526             s5_pkt->inner_ip4h.ip_len = s5_pkt->iph->ip_len;
4527         }
4528         else
4529         {
4530             IP6RawHdr* ip6h = (IP6RawHdr*)s5_pkt->raw_ip6h;
4531             if ( ip6h ) s5_pkt->inner_ip6h.len = ip6h->ip6plen;
4532         }
4533 
4534         ((DAQ_PktHdr_t*)s5_pkt->pkth)->ts.tv_sec = st->seglist_next->tv.tv_sec;
4535         ((DAQ_PktHdr_t*)s5_pkt->pkth)->ts.tv_usec = st->seglist_next->tv.tv_usec;
4536 
4537         s5_pkt->packet_flags |= dir;
4538         s5_pkt->ssnptr = (void *) tcpssn->scb;
4539 #ifdef TARGET_BASED
4540         s5_pkt->application_protocol_ordinal = p->application_protocol_ordinal;
4541 #endif
4542         PREPROC_PROFILE_TMPEND(s5TcpFlushPerfStats);
4543         {
4544             int tmp_do_detect, tmp_do_detect_content;
4545             PROFILE_VARS;
4546 
4547             PREPROC_PROFILE_START(s5TcpProcessRebuiltPerfStats);
4548             tmp_do_detect = do_detect;
4549             tmp_do_detect_content = do_detect_content;
4550 
4551             SnortEventqPush();
4552             Preprocess(s5_pkt);
4553             SnortEventqPop();
4554             DetectReset(s5_pkt->data, s5_pkt->dsize);
4555 
4556             do_detect = tmp_do_detect;
4557             do_detect_content = tmp_do_detect_content;
4558             PREPROC_PROFILE_END(s5TcpProcessRebuiltPerfStats);
4559         }
4560         PREPROC_PROFILE_TMPSTART(s5TcpFlushPerfStats);
4561     } while(bytes_processed < bytes);
4562 
4563     st->seglist_next = ss;
4564     PREPROC_PROFILE_END(s5TcpFlushPerfStats);
4565 }
4566 
_flush_to_seq(TcpSession * tcpssn,StreamTracker * st,uint32_t bytes,Packet * p,sfaddr_t * sip,sfaddr_t * dip,uint16_t sp,uint16_t dp,uint32_t dir)4567 static inline int _flush_to_seq (
4568 
4569         TcpSession *tcpssn, StreamTracker *st, uint32_t bytes, Packet *p,
4570         sfaddr_t* sip, sfaddr_t* dip, uint16_t sp, uint16_t dp, uint32_t dir)
4571 {
4572     uint32_t start_seq;
4573     uint32_t stop_seq;
4574     uint32_t footprint = 0;
4575     uint32_t bytes_processed = 0;
4576     int32_t flushed_bytes;
4577 
4578 #ifdef HAVE_DAQ_ADDRESS_SPACE_ID
4579     DAQ_PktHdr_t pkth;
4580 #endif
4581     EncodeFlags enc_flags = 0;
4582     PROFILE_VARS;
4583 
4584     PREPROC_PROFILE_START(s5TcpFlushPerfStats);
4585 
4586     if(st->paf_state.fpt_eoh)
4587         tcpssn->pp_flags |= PP_HTTPINSPECT_PAF_FLUSH_POST_HDR;
4588     else
4589         tcpssn->pp_flags &= ~PP_HTTPINSPECT_PAF_FLUSH_POST_HDR;
4590 
4591     if ( !p->packet_flags || (dir & p->packet_flags) )
4592         enc_flags = ENC_FLAG_FWD;
4593 
4594 #ifdef HAVE_DAQ_ADDRESS_SPACE_ID
4595     GetPacketHeaderFoo(tcpssn, p->pkth, enc_flags, &pkth, dir);
4596     Encode_Format_With_DAQ_Info(enc_flags, p, s5_pkt, PSEUDO_PKT_TCP, &pkth, 0);
4597 #elif defined(HAVE_DAQ_ACQUIRE_WITH_META)
4598     Encode_Format_With_DAQ_Info(enc_flags, p, s5_pkt, PSEUDO_PKT_TCP, 0);
4599 #else
4600     Encode_Format(enc_flags, p, s5_pkt, PSEUDO_PKT_TCP);
4601 #endif
4602 
4603     s5_pkt_end = s5_pkt->data + s5_pkt->max_dsize;
4604 
4605     // TBD in ips mode, these should be coming from current packet (tdb)
4606     ((TCPHdr *)s5_pkt->tcph)->th_ack = htonl(st->l_unackd);
4607     ((TCPHdr *)s5_pkt->tcph)->th_win = htons((uint16_t)st->l_window);
4608 
4609     // if not specified, set bytes to flush to what was acked
4610     if ( !bytes && SEQ_GT(st->r_win_base, st->seglist_base_seq) )
4611         bytes = st->r_win_base - st->seglist_base_seq;
4612 
4613     stop_seq = st->seglist_base_seq + bytes;
4614 
4615     do
4616     {
4617         footprint = stop_seq - st->seglist_base_seq;
4618 
4619         if(footprint == 0)
4620         {
4621             STREAM_DEBUG_WRAP(DebugMessage(DEBUG_STREAM_STATE,
4622                         "Negative footprint, bailing %d (0x%X - 0x%X)\n",
4623                         footprint, stop_seq, st->seglist_base_seq););
4624             PREPROC_PROFILE_END(s5TcpFlushPerfStats);
4625 
4626             return bytes_processed;
4627         }
4628 
4629 #ifdef STREAM_DEBUG_ENABLED
4630         if(footprint < st->seg_bytes_logical)
4631         {
4632             STREAM_DEBUG_WRAP(DebugMessage(DEBUG_STREAM_STATE,
4633                         "Footprint less than queued bytes, "
4634                         "win_base: 0x%X base_seq: 0x%X\n",
4635                         stop_seq, st->seglist_base_seq););
4636         }
4637 #endif
4638 
4639         if(footprint > s5_pkt->max_dsize)
4640         {
4641             /* this is as much as we can pack into a stream buffer */
4642             footprint = s5_pkt->max_dsize;
4643             stop_seq = st->seglist_base_seq + footprint;
4644         }
4645 
4646         STREAM_DEBUG_WRAP(DebugMessage(DEBUG_STREAM_STATE,
4647                     "Attempting to flush %lu bytes\n", footprint););
4648 
4649         /* Capture the seq of the first octet before flush changes the sequence numbers */
4650         start_seq = htonl(st->seglist_next->seq);
4651 
4652         /* setup the pseudopacket payload */
4653         flushed_bytes = FlushStream(p, st, stop_seq, (uint8_t *)s5_pkt->data, s5_pkt_end);
4654 
4655         if(flushed_bytes == -1)
4656         {
4657             /* couldn't put a stream together for whatever reason
4658              * should probably clean the seglist and bail...
4659              */
4660             if(st->seglist)
4661             {
4662                 STREAM_DEBUG_WRAP(DebugMessage(DEBUG_STREAM_STATE,
4663                             "dumping entire seglist!\n"););
4664                 purge_all(st);
4665             }
4666 
4667             STREAM_DEBUG_WRAP(DebugMessage(DEBUG_STREAM_STATE,
4668                         "setting st->seglist_base_seq to 0x%X\n", stop_seq););
4669             st->seglist_base_seq = stop_seq;
4670 
4671             PREPROC_PROFILE_END(s5TcpFlushPerfStats);
4672             return bytes_processed;
4673         }
4674 
4675         if (flushed_bytes == 0)
4676         {
4677             /* No more ACK'd data... bail */
4678             break;
4679         }
4680 
4681         ((TCPHdr *)s5_pkt->tcph)->th_seq = start_seq;
4682         s5_pkt->packet_flags |= (PKT_REBUILT_STREAM|PKT_STREAM_EST);
4683         s5_pkt->dsize = (uint16_t)flushed_bytes;
4684 
4685         if ((p->packet_flags & PKT_PDU_TAIL))
4686             s5_pkt->packet_flags |= PKT_PDU_TAIL;
4687 
4688         /* Rebuilt packet with only and complete http-post header is set with PKT_EVAL_DROP,
4689          * it will be used to evalute drop/allow packet by preprocs
4690          */
4691         if (tcpssn->pp_flags & PP_HTTPINSPECT_PAF_FLUSH_POST_HDR)
4692             s5_pkt->packet_flags |= PKT_EVAL_DROP;
4693 
4694         Encode_Update(s5_pkt);
4695 
4696         if(IS_IP4(s5_pkt))
4697         {
4698             s5_pkt->inner_ip4h.ip_len = s5_pkt->iph->ip_len;
4699         }
4700         else
4701         {
4702             IP6RawHdr* ip6h = (IP6RawHdr*)s5_pkt->raw_ip6h;
4703             if ( ip6h ) s5_pkt->inner_ip6h.len = ip6h->ip6plen;
4704         }
4705 
4706         ((DAQ_PktHdr_t*)s5_pkt->pkth)->ts.tv_sec = st->seglist_next->tv.tv_sec;
4707         ((DAQ_PktHdr_t*)s5_pkt->pkth)->ts.tv_usec = st->seglist_next->tv.tv_usec;
4708 
4709         sfBase.iStreamFlushes++;
4710         bytes_processed += s5_pkt->dsize;
4711 
4712         s5_pkt->packet_flags |= dir;
4713         s5_pkt->ssnptr = (void *) tcpssn->scb;
4714 #ifdef TARGET_BASED
4715         s5_pkt->application_protocol_ordinal = p->application_protocol_ordinal;
4716 #endif
4717         ShowRebuiltPacket(s5_pkt);
4718         s5stats.tcp_rebuilt_packets++;
4719         UpdateStreamReassStats(&sfBase, flushed_bytes);
4720 
4721         PREPROC_PROFILE_TMPEND(s5TcpFlushPerfStats);
4722         {
4723             int tmp_do_detect, tmp_do_detect_content;
4724             PROFILE_VARS;
4725 
4726             PREPROC_PROFILE_START(s5TcpProcessRebuiltPerfStats);
4727             tmp_do_detect = do_detect;
4728             tmp_do_detect_content = do_detect_content;
4729 
4730             SnortEventqPush();
4731             Preprocess(s5_pkt);
4732             SnortEventqPop();
4733             DetectReset(s5_pkt->data, s5_pkt->dsize);
4734 
4735             do_detect = tmp_do_detect;
4736             do_detect_content = tmp_do_detect_content;
4737             PREPROC_PROFILE_END(s5TcpProcessRebuiltPerfStats);
4738         }
4739         PREPROC_PROFILE_TMPSTART(s5TcpFlushPerfStats);
4740 
4741         // TBD abort should be by PAF callback only since
4742         // recovery may be possible in some cases
4743         if ( st->flags & TF_MISSING_PKT )
4744         {
4745             st->flags |= TF_MISSING_PREV_PKT;
4746             st->flags |= TF_PKT_MISSED;
4747             st->flags &= ~TF_MISSING_PKT;
4748             s5stats.tcp_gaps++;
4749         }
4750         else
4751         {
4752             st->flags &= ~TF_MISSING_PREV_PKT;
4753         }
4754     } while ( DataToFlush(st) );
4755 
4756     if ( st->tcp_policy )
4757         UpdateFlushMgr(snort_conf, &st->flush_mgr, &st->tcp_policy->flush_point_list, st->flags);
4758 
4759     /* tell them how many bytes we processed */
4760     PREPROC_PROFILE_END(s5TcpFlushPerfStats);
4761     return bytes_processed;
4762 }
4763 
flush_to_seq_noack(TcpSession * tcpssn,StreamTracker * st,uint32_t bytes,Packet * p,sfaddr_t * sip,sfaddr_t * dip,uint16_t sp,uint16_t dp,uint32_t dir)4764 static inline int flush_to_seq_noack( TcpSession *tcpssn, StreamTracker *st, uint32_t bytes,
4765         Packet *p, sfaddr_t* sip, sfaddr_t* dip, uint16_t sp, uint16_t dp, uint32_t dir )
4766 {
4767     STREAM_DEBUG_WRAP(DebugMessage(DEBUG_STREAM_STATE,
4768                 "In flush_to_seq_noack()\n"););
4769 
4770     if ( !bytes )
4771     {
4772         STREAM_DEBUG_WRAP(DebugMessage(DEBUG_STREAM_STATE,
4773                     "bailing, no data\n"););
4774         return 0;
4775     }
4776 
4777     if ( !st->seglist_next )
4778     {
4779         STREAM_DEBUG_WRAP(DebugMessage(DEBUG_STREAM_STATE,
4780                     "bailing, bad seglist ptr\n"););
4781         return 0;
4782     }
4783 
4784 #if 0
4785     //Might not need this. Check with Russ.
4786     if (!DataToFlush(st) && !(st->flags & TF_FORCE_FLUSH))
4787     {
4788         STREAM5_DEBUG_WRAP(DebugMessage(DEBUG_STREAM_STATE,
4789                     "only 1 packet in seglist no need to flush\n"););
4790         return 0;
4791     }
4792 #endif
4793 
4794     st->flags &= ~TF_MISSING_PKT;
4795     st->flags &= ~TF_MISSING_PREV_PKT;
4796 
4797     /* This will set this flag on the first reassembly
4798      * if reassembly for this direction was set midstream */
4799     if ( SEQ_LT(st->seglist_base_seq, st->seglist_next->seq) )
4800     {
4801         uint32_t missed = st->seglist_next->seq - st->seglist_base_seq;
4802 
4803         if ( missed <= bytes )
4804             bytes -= missed;
4805 
4806         st->flags |= TF_MISSING_PREV_PKT;
4807         st->flags |= TF_PKT_MISSED;
4808         s5stats.tcp_gaps++;
4809         st->seglist_base_seq = st->seglist_next->seq;
4810 
4811         if ( !bytes )
4812             return 0;
4813     }
4814 
4815     return _flush_to_seq_noack(tcpssn, st, bytes, p, sip, dip, sp, dp, dir);
4816 
4817 }
4818 /*
4819  * flush a seglist up to the given point, generate a pseudopacket,
4820  * and fire it thru the system.
4821  */
flush_to_seq(TcpSession * tcpssn,StreamTracker * st,uint32_t bytes,Packet * p,sfaddr_t * sip,sfaddr_t * dip,uint16_t sp,uint16_t dp,uint32_t dir)4822 static inline int flush_to_seq(
4823         TcpSession *tcpssn, StreamTracker *st, uint32_t bytes, Packet *p,
4824         sfaddr_t* sip, sfaddr_t* dip, uint16_t sp, uint16_t dp, uint32_t dir)
4825 {
4826     STREAM_DEBUG_WRAP(DebugMessage(DEBUG_STREAM_STATE,
4827                 "In flush_to_seq()\n"););
4828 
4829     if ( !bytes )
4830     {
4831         STREAM_DEBUG_WRAP(DebugMessage(DEBUG_STREAM_STATE,
4832                     "bailing, no data\n"););
4833         return 0;
4834     }
4835 
4836     if ( !st->seglist_next )
4837     {
4838         STREAM_DEBUG_WRAP(DebugMessage(DEBUG_STREAM_STATE,
4839                     "bailing, bad seglist ptr\n"););
4840         return 0;
4841     }
4842 
4843     if (!DataToFlush(st) && !(st->flags & TF_FORCE_FLUSH))
4844     {
4845         STREAM_DEBUG_WRAP(DebugMessage(DEBUG_STREAM_STATE,
4846                     "only 1 packet in seglist no need to flush\n"););
4847         return 0;
4848     }
4849 
4850     st->flags &= ~TF_MISSING_PREV_PKT;
4851 
4852     /* This will set this flag on the first reassembly
4853      * if reassembly for this direction was set midstream */
4854     if ( SEQ_LT(st->seglist_base_seq, st->seglist_next->seq) &&
4855             !(st->flags & TF_FIRST_PKT_MISSING) )
4856     {
4857         uint32_t missed = st->seglist_next->seq - st->seglist_base_seq;
4858 
4859         if ( missed <= bytes )
4860             bytes -= missed;
4861 
4862         st->flags |= TF_MISSING_PREV_PKT;
4863         st->flags |= TF_PKT_MISSED;
4864         s5stats.tcp_gaps++;
4865         st->seglist_base_seq = st->seglist_next->seq;
4866 
4867         if ( !bytes )
4868             return 0;
4869     }
4870     st->flags &= ~TF_FIRST_PKT_MISSING;
4871 
4872     if (p->packet_flags & PKT_PSEUDO_FLUSH)
4873     {
4874          pseudo_flush(tcpssn, st, bytes, p, sip, dip, sp, dp, dir);
4875          return 0;
4876     }
4877 
4878     return _flush_to_seq(tcpssn, st, bytes, p, sip, dip, sp, dp, dir);
4879 
4880 }
4881 
4882 /*
4883  * get the footprint for the current seglist, the difference
4884  * between our base sequence and the last ack'd sequence we
4885  * received
4886  */
get_q_footprint(StreamTracker * st)4887 static inline uint32_t get_q_footprint(StreamTracker *st)
4888 {
4889     uint32_t fp;
4890 
4891     if (st == NULL)
4892     {
4893         return 0;
4894     }
4895 
4896     fp = st->r_win_base - st->seglist_base_seq;
4897 
4898     if(fp <= 0)
4899         return 0;
4900 
4901     st->seglist_next = st->seglist;
4902     return fp;
4903 }
4904 
4905 static bool two_way_traffic=true;
4906 // FIXTHIS get_q_sequenced() performance could possibly be
4907 // boosted by tracking sequenced bytes as seglist is updated
4908 // to avoid the while loop, etc. below.
get_q_sequenced(StreamTracker * st)4909 static inline uint32_t get_q_sequenced(StreamTracker *st)
4910 {
4911     uint32_t len;
4912     StreamSegment* seg = st ? st->seglist : NULL;
4913     StreamSegment* base = NULL;
4914 
4915     if ( !seg )
4916         return 0;
4917 
4918     if ( two_way_traffic && SEQ_LT(st->r_win_base, seg->seq) )
4919         return 0;
4920 
4921     while ( seg->next && (seg->next->seq == seg->seq + seg->size) )
4922     {
4923         if ( !seg->buffered && !base )
4924             base = seg;
4925         seg = seg->next;
4926     }
4927     if ( !seg->buffered && !base )
4928         base = seg;
4929 
4930     if ( !base )
4931         return 0;
4932 
4933     st->seglist_next = base;
4934     st->seglist_base_seq = base->seq;
4935     len = seg->seq + seg->size - base->seq;
4936 
4937     return ( len > 0 ) ? len : 0;
4938 }
4939 
flush_ackd(TcpSession * tcpssn,StreamTracker * st,Packet * p,sfaddr_t * sip,sfaddr_t * dip,uint16_t sp,uint16_t dp,uint32_t dir)4940 static inline int flush_ackd(
4941         TcpSession *tcpssn, StreamTracker *st, Packet *p,
4942         sfaddr_t* sip, sfaddr_t* dip, uint16_t sp, uint16_t dp, uint32_t dir)
4943 {
4944     uint32_t bytes = get_q_footprint(st);
4945     return flush_to_seq(tcpssn, st, bytes, p, sip, dip, sp, dp, dir);
4946 }
4947 
4948 // FIXTHIS flush_stream() calls should be replaced with calls to
4949 // CheckFlushPolicyOn*() with the exception that for the *OnAck() case,
4950 // any available ackd data must be flushed in both directions.
flush_stream(TcpSession * tcpssn,StreamTracker * st,Packet * p,sfaddr_t * sip,sfaddr_t * dip,uint16_t sp,uint16_t dp,uint32_t dir)4951 static inline int flush_stream(
4952         TcpSession *tcpssn, StreamTracker *st, Packet *p,
4953         sfaddr_t* sip, sfaddr_t* dip, uint16_t sp, uint16_t dp, uint32_t dir)
4954 {
4955     FlushMgr* fm;
4956 #ifdef NORMALIZER
4957     if ( Stream_NormGetMode(st->reassembly_policy, snort_conf, NORM_TCP_IPS) == NORM_MODE_ON )
4958     {
4959         uint32_t bytes = get_q_sequenced(st);
4960         return flush_to_seq(tcpssn, st, bytes, p, sip, dip, sp, dp, dir);
4961     }
4962 #endif
4963     fm = &tcpssn->server.flush_mgr;
4964     if(fm->flush_policy == STREAM_FLPOLICY_PROTOCOL_NOACK)
4965     {
4966         uint32_t bytes = get_q_sequenced(st);
4967         return flush_to_seq(tcpssn, st, bytes, p, sip, dip, sp, dp, dir);
4968     }
4969     else if (fm->flush_policy == STREAM_FLPOLICY_FOOTPRINT_NOACK)
4970     {
4971         uint32_t bytes = get_q_sequenced(st);
4972         return flush_to_seq_noack(tcpssn, st, bytes, p, sip, dip, sp, dp, dir);
4973     }
4974     return flush_ackd(tcpssn, st, p, sip, dip, sp, dp, dir);
4975 }
4976 
FlushStream(Packet * p,StreamTracker * st,uint32_t toSeq,uint8_t * flushbuf,const uint8_t * flushbuf_end)4977 static int FlushStream(
4978         Packet* p, StreamTracker *st, uint32_t toSeq, uint8_t *flushbuf,
4979         const uint8_t *flushbuf_end)
4980 {
4981     StreamSegment *ss = NULL, *seglist, *sr;
4982     uint16_t bytes_flushed = 0;
4983     uint16_t bytes_skipped = 0;
4984     uint32_t bytes_queued = st->seg_bytes_logical;
4985     uint32_t segs = 0;
4986     int ret;
4987     PROFILE_VARS;
4988 
4989     if ( st->seglist == NULL || st->seglist_tail == NULL )
4990         return -1;
4991 
4992     PREPROC_PROFILE_START(s5TcpBuildPacketPerfStats);
4993 
4994     // skip over previously flushed segments
4995     seglist = st->seglist_next;
4996 
4997     for(ss = seglist; ss && SEQ_LT(ss->seq,  toSeq); ss = ss->next)
4998     {
4999         unsigned int flushbuf_size = flushbuf_end - flushbuf;
5000         unsigned int bytes_to_copy = getSegmentFlushSize(st, ss, toSeq, flushbuf_size);
5001 
5002         STREAM_DEBUG_WRAP(DebugMessage(DEBUG_STREAM_STATE,
5003                     "Flushing %u bytes from %X\n", bytes_to_copy, ss->seq));
5004 
5005         if(ss->urg_offset >= 1)
5006         {
5007             /* if urg_offset is set, seq + urg_offset is seq # of octet
5008              * in stream following the last urgent octet.  all preceding
5009              * octets in segment are considered urgent.  this code will
5010              * skip over the urgent data when flushing.
5011              */
5012 
5013             unsigned int non_urgent_bytes =
5014                 ss->urg_offset < bytes_to_copy ? (bytes_to_copy - ss->urg_offset) : 0;
5015 
5016             if ( non_urgent_bytes )
5017             {
5018                 ret = SafeMemcpy(flushbuf, ss->payload+ss->urg_offset,
5019                         non_urgent_bytes, flushbuf, flushbuf_end);
5020 
5021                 if (ret == SAFEMEM_ERROR)
5022                 {
5023                     STREAM_DEBUG_WRAP(DebugMessage(DEBUG_STREAM_STATE,
5024                                 "ERROR writing flushbuf attempting to "
5025                                 "write flushbuf out of range!\n"););
5026                 }
5027                 else
5028                     flushbuf += non_urgent_bytes;
5029 
5030                 bytes_skipped += ss->urg_offset;
5031             }
5032             else
5033             {
5034                 ss->urg_offset = 0;
5035             }
5036         }
5037         else
5038         {
5039             ret = SafeMemcpy(flushbuf, ss->payload,
5040                     bytes_to_copy, flushbuf, flushbuf_end);
5041 
5042             if (ret == SAFEMEM_ERROR)
5043             {
5044                 STREAM_DEBUG_WRAP(DebugMessage(DEBUG_STREAM_STATE,
5045                             "ERROR writing flushbuf attempting to "
5046                             "write flushbuf out of range!\n"););
5047             }
5048             else
5049                 flushbuf += bytes_to_copy;
5050         }
5051 
5052         if ( !st->paf_state.fpt_eoh &&
5053                 bytes_to_copy < ss->size &&
5054                 DupStreamNode(NULL, st, ss, &sr) == STREAM_INSERT_OK )
5055         {
5056             ss->size = bytes_to_copy;
5057             sr->seq += bytes_to_copy;
5058             sr->size -= bytes_to_copy;
5059             sr->payload += bytes_to_copy + (ss->payload - ss->data);
5060         }
5061 
5062         bytes_flushed += bytes_to_copy;
5063         if(!st->paf_state.fpt_eoh){
5064             ss->buffered = SL_BUF_FLUSHED;
5065             st->flush_count++;
5066             segs++;
5067         }
5068 
5069         if ( flushbuf >= flushbuf_end )
5070             break;
5071 
5072         if ( SEQ_EQ(ss->seq + bytes_to_copy,  toSeq) )
5073             break;
5074 
5075         /* Check for a gap/missing packet */
5076         // FIXTHIS PAF should account for missing data and resume
5077         // scanning at the start of next PDU instead of aborting.
5078         // FIXTHIS FIN may be in toSeq causing bogus gap counts.
5079         if ( ((ss->next && (ss->seq + ss->size != ss->next->seq)) ||
5080                     (!ss->next && (ss->seq + ss->size < toSeq))) &&
5081                 !(st->flags & TF_FIRST_PKT_MISSING) )
5082         {
5083             if ( ss->next )
5084             {
5085                 toSeq = ss->next->seq;
5086                 st->seglist_next = ss->next;
5087             }
5088             st->flags |= TF_MISSING_PKT;
5089             break;
5090         }
5091     }
5092 
5093     st->seglist_base_seq = toSeq;
5094 
5095     STREAM_DEBUG_WRAP(DebugMessage(DEBUG_STREAM_STATE,
5096                 "setting st->seglist_base_seq to 0x%X\n", st->seglist_base_seq););
5097 
5098     bytes_queued -= bytes_flushed;
5099 
5100     STREAM_DEBUG_WRAP(DebugMessage(DEBUG_STREAM_STATE,
5101                 "flushed %d bytes / %d segs on stream, "
5102                 "skipped %d bytes, %d still queued\n",
5103                 bytes_flushed, segs, bytes_skipped, bytes_queued););
5104 
5105     PREPROC_PROFILE_END(s5TcpBuildPacketPerfStats);
5106     return bytes_flushed - bytes_skipped;
5107 }
5108 
StreamFlushServer(Packet * p,SessionControlBlock * scb)5109 int StreamFlushServer(Packet *p, SessionControlBlock *scb)
5110 {
5111     int flushed;
5112     TcpSession *tcpssn = NULL;
5113     StreamTracker *flushTracker = NULL;
5114 
5115     if (scb->proto_specific_data)
5116         tcpssn = (TcpSession *)scb->proto_specific_data->data;
5117 
5118     if (!tcpssn)
5119         return 0;
5120 
5121     flushTracker = &tcpssn->server;
5122 
5123     flushTracker->flags |= TF_FORCE_FLUSH;
5124 
5125     /* If this is a rebuilt packet, don't flush now because we'll
5126      * overwrite the packet being processed.
5127      */
5128     if (p->packet_flags & PKT_REBUILT_STREAM)
5129     {
5130         /* We'll check & clear the TF_FORCE_FLUSH next time through */
5131         return 0;
5132     }
5133 
5134     /* Need to convert the addresses to network order */
5135     flushed = flush_stream(tcpssn, flushTracker, p,
5136             &tcpssn->tcp_server_ip,
5137             &tcpssn->tcp_client_ip,
5138             tcpssn->tcp_server_port,
5139             tcpssn->tcp_client_port,
5140             PKT_FROM_SERVER);
5141     if (flushed)
5142         purge_flushed_ackd(tcpssn, flushTracker);
5143 
5144     flushTracker->flags &= ~TF_FORCE_FLUSH;
5145 
5146     return flushed;
5147 }
5148 
StreamFlushClient(Packet * p,SessionControlBlock * scb)5149 int StreamFlushClient(Packet *p, SessionControlBlock *scb)
5150 {
5151     int flushed;
5152     TcpSession *tcpssn = NULL;
5153     StreamTracker *flushTracker = NULL;
5154 
5155     if (scb->proto_specific_data)
5156         tcpssn = (TcpSession *)scb->proto_specific_data->data;
5157 
5158     if (!tcpssn)
5159         return 0;
5160 
5161     flushTracker = &tcpssn->client;
5162 
5163     flushTracker->flags |= TF_FORCE_FLUSH;
5164 
5165     /* If this is a rebuilt packet, don't flush now because we'll
5166      * overwrite the packet being processed.
5167      */
5168     if (p->packet_flags & PKT_REBUILT_STREAM)
5169     {
5170         /* We'll check & clear the TF_FORCE_FLUSH next time through */
5171         return 0;
5172     }
5173 
5174     /* Need to convert the addresses to network order */
5175     flushed = flush_stream(tcpssn, flushTracker, p,
5176             &tcpssn->tcp_client_ip,
5177             &tcpssn->tcp_server_ip,
5178             tcpssn->tcp_client_port,
5179             tcpssn->tcp_server_port,
5180             PKT_FROM_CLIENT);
5181     if (flushed)
5182         purge_flushed_ackd(tcpssn, flushTracker);
5183 
5184     flushTracker->flags &= ~TF_FORCE_FLUSH;
5185 
5186     return flushed;
5187 }
5188 
StreamFlushListener(Packet * p,SessionControlBlock * scb)5189 int StreamFlushListener(Packet *p, SessionControlBlock *scb)
5190 {
5191     TcpSession *tcpssn = NULL;
5192     StreamTracker *listener = NULL;
5193     int dir = 0;
5194     int flushed = 0;
5195 
5196     if (scb->proto_specific_data)
5197         tcpssn = (TcpSession *)scb->proto_specific_data->data;
5198 
5199     if (!tcpssn)
5200         return 0;
5201 
5202     /* figure out direction of this packet -- we should've already
5203      * looked at it, so the packet_flags are already set. */
5204     if(p->packet_flags & PKT_FROM_SERVER)
5205     {
5206         STREAM_DEBUG_WRAP(DebugMessage(DEBUG_STREAM_STATE,
5207                     "Flushing listener on packet from server\n"););
5208         listener = &tcpssn->client;
5209         /* dir of flush is the data from the opposite side */
5210         dir = PKT_FROM_SERVER;
5211     }
5212     else if (p->packet_flags & PKT_FROM_CLIENT)
5213     {
5214         STREAM_DEBUG_WRAP(DebugMessage(DEBUG_STREAM_STATE,
5215                     "Flushing listener on packet from client\n"););
5216         listener = &tcpssn->server;
5217         /* dir of flush is the data from the opposite side */
5218         dir = PKT_FROM_CLIENT;
5219     }
5220 
5221     if (dir != 0)
5222     {
5223         listener->flags |= TF_FORCE_FLUSH;
5224         flushed = flush_stream(tcpssn, listener, p,
5225                 GET_SRC_IP(p), GET_DST_IP(p),
5226                 p->tcph->th_sport, p->tcph->th_dport, dir);
5227         if (flushed)
5228             purge_flushed_ackd(tcpssn, listener);
5229 
5230         listener->flags &= ~TF_FORCE_FLUSH;
5231     }
5232 
5233     return flushed;
5234 }
5235 
StreamFlushTalker(Packet * p,SessionControlBlock * scb)5236 int StreamFlushTalker(Packet *p, SessionControlBlock *scb)
5237 {
5238     TcpSession *tcpssn = NULL;
5239     StreamTracker *talker = NULL;
5240     int dir = 0;
5241     int flushed = 0;
5242 
5243     if (scb->proto_specific_data)
5244         tcpssn = (TcpSession *)scb->proto_specific_data->data;
5245 
5246     if (!tcpssn)
5247     {
5248         return 0;
5249     }
5250 
5251     /* figure out direction of this packet -- we should've already
5252      * looked at it, so the packet_flags are already set. */
5253     if(p->packet_flags & PKT_FROM_SERVER)
5254     {
5255         STREAM_DEBUG_WRAP(DebugMessage(DEBUG_STREAM_STATE,
5256                     "Flushing talker on packet from server\n"););
5257         talker = &tcpssn->server;
5258         /* dir of flush is the data from the opposite side */
5259         dir = PKT_FROM_CLIENT;
5260     }
5261     else if (p->packet_flags & PKT_FROM_CLIENT)
5262     {
5263         STREAM_DEBUG_WRAP(DebugMessage(DEBUG_STREAM_STATE,
5264                     "Flushing talker on packet from client\n"););
5265         talker = &tcpssn->client;
5266         /* dir of flush is the data from the opposite side */
5267         dir = PKT_FROM_SERVER;
5268     }
5269 
5270     if (dir != 0)
5271     {
5272         talker->flags |= TF_FORCE_FLUSH;
5273         flushed = flush_stream(tcpssn, talker, p,
5274                 GET_DST_IP(p), GET_SRC_IP(p),
5275                 p->tcph->th_dport, p->tcph->th_sport, dir);
5276         if (flushed)
5277             purge_flushed_ackd(tcpssn, talker);
5278 
5279         talker->flags &= ~TF_FORCE_FLUSH;
5280     }
5281 
5282     return flushed;
5283 }
5284 
TcpSessionClear(SessionControlBlock * scb,TcpSession * tcpssn,int freeApplicationData)5285 static void TcpSessionClear (SessionControlBlock* scb, TcpSession* tcpssn, int freeApplicationData)
5286 {
5287     STREAM_DEBUG_WRAP( DebugMessage(DEBUG_STREAM_STATE,
5288                 "In TcpSessionClear, %lu bytes in use\n", session_mem_in_use););
5289     STREAM_DEBUG_WRAP( DebugMessage(DEBUG_STREAM_STATE,
5290                 "client has %d segs queued\n", tcpssn->client.seg_count););
5291     STREAM_DEBUG_WRAP( DebugMessage(DEBUG_STREAM_STATE,
5292                 "server has %d segs queued\n", tcpssn->server.seg_count););
5293 
5294     // update stats
5295     s5stats.tcp_streamtrackers_released++;
5296     if (s5stats.active_tcp_sessions > 0 )
5297         s5stats.active_tcp_sessions--;
5298     StreamUpdatePerfBaseState(&sfBase, tcpssn->scb, TCP_STATE_CLOSED);
5299     RemoveStreamSession(&sfBase);
5300 
5301     if (scb->ha_state.session_flags & SSNFLAG_PRUNED)
5302         CloseStreamSession(&sfBase, SESSION_CLOSED_PRUNED);
5303     else if (scb->ha_state.session_flags & SSNFLAG_TIMEDOUT)
5304         CloseStreamSession(&sfBase, SESSION_CLOSED_PRUNED | SESSION_CLOSED_TIMEDOUT);
5305     else
5306         CloseStreamSession(&sfBase, SESSION_CLOSED_NORMALLY);
5307 
5308 
5309     // release external state
5310     if (freeApplicationData)
5311         session_api->free_application_data(scb);
5312     StreamResetFlowBits(scb);
5313 
5314     // release internal protocol specific state
5315     purge_all(&tcpssn->client);
5316     purge_all(&tcpssn->server);
5317 
5318     s5_paf_clear(&tcpssn->client.paf_state);
5319     s5_paf_clear(&tcpssn->server.paf_state);
5320 
5321     session_api->free_protocol_session_pool( SESSION_PROTO_TCP, scb );
5322     scb->proto_specific_data = NULL;
5323 
5324     // update light-weight state
5325     scb->ha_state.session_flags = SSNFLAG_NONE;
5326     scb->session_state = STREAM_STATE_NONE;
5327     scb->expire_time = 0;
5328     scb->ha_state.ignore_direction = 0;
5329 
5330     // generate event for rate filtering
5331     EventInternal(INTERNAL_EVENT_SESSION_DEL);
5332 
5333     STREAM_DEBUG_WRAP( DebugMessage(DEBUG_STREAM_STATE,
5334                 "After cleaning, %lu bytes in use\n", session_mem_in_use););
5335 }
StreamSearchTcpConfigForBoundPolicy(StreamTcpConfig * tcp_config,sfaddr_t * ip)5336 static StreamTcpPolicy *StreamSearchTcpConfigForBoundPolicy(StreamTcpConfig *tcp_config, sfaddr_t *ip)
5337 {
5338     int policyIndex;
5339     StreamTcpPolicy *policy = NULL;
5340 
5341     for (policyIndex = 0; policyIndex < tcp_config->num_policies; policyIndex++)
5342     {
5343         policy = tcp_config->policy_list[policyIndex];
5344 
5345         if (policy->bound_addrs == NULL)
5346             continue;
5347 
5348         /*
5349          * Does this policy handle packets to this IP address?
5350          */
5351         if(sfvar_ip_in(policy->bound_addrs, ip))
5352         {
5353             STREAM_DEBUG_WRAP(DebugMessage(DEBUG_STREAM,
5354                         "[Stream] Found tcp policy in IpAddrSet\n"););
5355             break;
5356         }
5357     }
5358 
5359     if (policyIndex == tcp_config->num_policies)
5360         policy = tcp_config->default_policy;
5361 
5362     return policy;
5363 }
5364 
StreamPolicyLookup(SessionControlBlock * scb,sfaddr_t * ip)5365 static inline StreamTcpPolicy *StreamPolicyLookup( SessionControlBlock *scb, sfaddr_t *ip)
5366 {
5367     StreamTcpConfig *tcp_config = ( ( StreamConfig * ) scb->stream_config )->tcp_config;
5368 
5369     if( tcp_config != NULL )
5370         return StreamSearchTcpConfigForBoundPolicy( tcp_config, ip );
5371     else
5372         return NULL;
5373 }
5374 
FlushQueuedSegs(SessionControlBlock * scb,TcpSession * tcpssn)5375 static void FlushQueuedSegs(SessionControlBlock *scb, TcpSession *tcpssn)
5376 {
5377     DAQ_PktHdr_t tmp_pcap_hdr;
5378 
5379 #ifdef REG_TEST
5380     if (getRegTestFlags() & REG_TEST_FLAG_STREAM_DECODE)
5381         printf("\nFlushQueuedSegs | ");
5382 #endif
5383 
5384     /* Flush ack'd data on both sides as necessary */
5385     {
5386         Packet *p = NewGrinderPkt(tcp_cleanup_pkt, NULL, NULL);
5387 
5388         int flushed;
5389 
5390         tcp_cleanup_pkt = p;
5391 
5392         if (!s5_tcp_cleanup)
5393         {
5394             /* Turn off decoder alerts since we're decoding stored
5395              * packets that we already alerted on. */
5396             policyDecoderFlagsSaveNClear(scb->napPolicyId);
5397         }
5398         policyChecksumFlagsSaveNClear(scb->napPolicyId);
5399 
5400         /* Flush the client */
5401         if (tcpssn->client.seglist && !(scb->ha_state.ignore_direction & SSN_DIR_FROM_SERVER) )
5402         {
5403             pc.s5tcp1++;
5404             /* Do each field individually because of size differences on 64bit OS */
5405             memset(&tmp_pcap_hdr, 0, sizeof(tmp_pcap_hdr));
5406             tmp_pcap_hdr.ts.tv_sec = tcpssn->client.seglist->tv.tv_sec;
5407             tmp_pcap_hdr.ts.tv_usec = tcpssn->client.seglist->tv.tv_usec;
5408             tmp_pcap_hdr.caplen = tcpssn->client.seglist->caplen;
5409             tmp_pcap_hdr.pktlen = tcpssn->client.seglist->pktlen;
5410 
5411             SnortEventqPush();
5412             (*grinder)(p, &tmp_pcap_hdr, tcpssn->client.seglist->pkt);
5413 
5414             p->ssnptr = scb;
5415 
5416             //set policy id for this packet
5417             {
5418 #ifdef HAVE_DAQ_REAL_ADDRESSES
5419                 sfaddr_t* srcIp = (p->iph)? GET_SRC_IP((p)) : NULL;
5420                 sfaddr_t* dstIp = (p->iph)? GET_DST_IP((p)) : NULL;
5421 
5422                 if (srcIp && dstIp)
5423                 {
5424                     if (srcIp->family == AF_INET6)
5425                     {
5426                         memcpy(&((((DAQ_PktHdr_t*)p->pkth)->real_sIP).s6_addr), &(srcIp)->ia32, sizeof(struct in6_addr));
5427                         memcpy(&((((DAQ_PktHdr_t*)p->pkth)->real_dIP).s6_addr), &(dstIp)->ia32, sizeof(struct in6_addr));
5428                         ((DAQ_PktHdr_t*)p->pkth)->flags |= (DAQ_PKT_FLAG_REAL_SIP_V6 | DAQ_PKT_FLAG_REAL_DIP_V6);
5429                     }
5430                     else
5431                     {
5432                         memcpy(&((((DAQ_PktHdr_t*)p->pkth)->real_sIP).s6_addr), &(srcIp)->ia32[3], sizeof(uint32_t));
5433                         memcpy(&((((DAQ_PktHdr_t*)p->pkth)->real_dIP).s6_addr), &(dstIp)->ia32[3], sizeof(uint32_t));
5434                     }
5435                     ((DAQ_PktHdr_t*)p->pkth)->flags |= DAQ_PKT_FLAG_REAL_ADDRESSES;
5436 
5437                     if( tcpssn->daq_flags & DAQ_PKT_FLAG_IGNORE_VLAN )
5438                         ((DAQ_PktHdr_t*)p->pkth)->flags |= DAQ_PKT_FLAG_IGNORE_VLAN;
5439                 }
5440 #endif
5441 
5442                 if( scb->session_config != session_configuration )
5443                 {
5444                     getSessionPlugins()->select_session_nap(p, true );
5445                     scb->napPolicyId = getNapRuntimePolicy();
5446                     scb->ipsPolicyId = getDefaultPolicy();
5447                     p->configPolicyId = snort_conf->targeted_policies[scb->ipsPolicyId]->configPolicyId;
5448                     scb->stream_config = sfPolicyUserDataGet( stream_online_config, scb->napPolicyId );
5449                     tcpssn->client.tcp_policy = StreamPolicyLookup(scb, GET_DST_IP(p));
5450                     tcpssn->server.tcp_policy = StreamPolicyLookup(scb, GET_SRC_IP(p));
5451                 }
5452                 else
5453                 {
5454                      setNapRuntimePolicy(scb->napPolicyId);
5455                      setIpsRuntimePolicy(scb->ipsPolicyId);
5456                      p->configPolicyId = snort_conf->targeted_policies[scb->ipsPolicyId]->configPolicyId;
5457                      scb->stream_config = sfPolicyUserDataGet( stream_online_config, scb->napPolicyId );
5458                 }
5459 
5460                 //actions are queued only for IDS case
5461                 sfActionQueueExecAll(decoderActionQ);
5462             }
5463             SnortEventqPop();
5464             tcpssn->client.flags |= TF_FORCE_FLUSH;
5465 
5466             if ( !p->tcph )
5467             {
5468                 flushed = 0;
5469             }
5470             else
5471             {
5472                 flushed = flush_stream(tcpssn, &tcpssn->client, p,
5473                         p->iph_api->iph_ret_src(p), p->iph_api->iph_ret_dst(p),
5474                         p->tcph->th_sport, p->tcph->th_dport,
5475                         PKT_FROM_SERVER);
5476             }
5477             if (flushed)
5478                 purge_flushed_ackd(tcpssn, &tcpssn->client);
5479             else
5480             {
5481                 SnortEventqPush();
5482                 SnortEventqLog(snort_conf->event_queue, p);
5483                 SnortEventqReset();
5484                 SnortEventqPop();
5485             }
5486             tcpssn->client.flags &= ~TF_FORCE_FLUSH;
5487         }
5488 
5489         /* Flush the server */
5490         if (tcpssn->server.seglist && !(scb->ha_state.ignore_direction & SSN_DIR_FROM_CLIENT) )
5491         {
5492             pc.s5tcp2++;
5493             /* Do each field individually because of size differences on 64bit OS */
5494             memset(&tmp_pcap_hdr, 0, sizeof(tmp_pcap_hdr));
5495             tmp_pcap_hdr.ts.tv_sec = tcpssn->server.seglist->tv.tv_sec;
5496             tmp_pcap_hdr.ts.tv_usec = tcpssn->server.seglist->tv.tv_usec;
5497             tmp_pcap_hdr.caplen = tcpssn->server.seglist->caplen;
5498             tmp_pcap_hdr.pktlen = tcpssn->server.seglist->pktlen;
5499 
5500             SnortEventqPush();
5501             (*grinder)(p, &tmp_pcap_hdr, tcpssn->server.seglist->pkt);
5502 
5503             p->ssnptr = scb;
5504 
5505             //set policy id for this packet
5506             {
5507 #ifdef HAVE_DAQ_REAL_ADDRESSES
5508                 sfaddr_t* srcIp = (p->iph)? GET_SRC_IP((p)) : NULL;
5509                 sfaddr_t* dstIp = (p->iph)? GET_DST_IP((p)) : NULL;
5510 
5511                 if (srcIp && dstIp)
5512                 {
5513                     if (srcIp->family == AF_INET6)
5514                     {
5515                         memcpy(&((((DAQ_PktHdr_t*)p->pkth)->real_sIP).s6_addr), &(srcIp)->ia32, sizeof(struct in6_addr));
5516                         memcpy(&((((DAQ_PktHdr_t*)p->pkth)->real_dIP).s6_addr), &(dstIp)->ia32, sizeof(struct in6_addr));
5517                         ((DAQ_PktHdr_t*)p->pkth)->flags |= (DAQ_PKT_FLAG_REAL_SIP_V6 | DAQ_PKT_FLAG_REAL_DIP_V6);
5518                     }
5519                     else
5520                     {
5521                         memcpy(&((((DAQ_PktHdr_t*)p->pkth)->real_sIP).s6_addr), &(srcIp)->ia32[3], sizeof(uint32_t));
5522                         memcpy(&((((DAQ_PktHdr_t*)p->pkth)->real_dIP).s6_addr), &(dstIp)->ia32[3], sizeof(uint32_t));
5523                     }
5524                     ((DAQ_PktHdr_t*)p->pkth)->flags |= DAQ_PKT_FLAG_REAL_ADDRESSES;
5525 
5526                     if( tcpssn->daq_flags & DAQ_PKT_FLAG_IGNORE_VLAN )
5527                         ((DAQ_PktHdr_t*)p->pkth)->flags |= DAQ_PKT_FLAG_IGNORE_VLAN;
5528                 }
5529 #endif
5530 
5531                 if( scb->session_config != session_configuration )
5532                 {
5533                     getSessionPlugins()->select_session_nap(p, false );
5534                     scb->ipsPolicyId = getDefaultPolicy();
5535                     scb->napPolicyId = getNapRuntimePolicy();
5536                     p->configPolicyId = snort_conf->targeted_policies[scb->ipsPolicyId]->configPolicyId;
5537                     scb->stream_config = sfPolicyUserDataGet( stream_online_config, scb->napPolicyId );
5538                     tcpssn->client.tcp_policy = StreamPolicyLookup(scb, GET_SRC_IP(p));
5539                     tcpssn->server.tcp_policy = StreamPolicyLookup(scb, GET_DST_IP(p));
5540                 }
5541                 else
5542                 {
5543                      setNapRuntimePolicy(scb->napPolicyId);
5544                      setIpsRuntimePolicy(scb->ipsPolicyId);
5545                      p->configPolicyId = snort_conf->targeted_policies[scb->ipsPolicyId]->configPolicyId;
5546                      scb->stream_config = sfPolicyUserDataGet( stream_online_config, scb->napPolicyId );
5547                 }
5548 
5549 		//actions are queued only for IDS case
5550                 sfActionQueueExecAll(decoderActionQ);
5551             }
5552             SnortEventqPop();
5553             tcpssn->server.flags |= TF_FORCE_FLUSH;
5554 
5555             if ( !p->tcph )
5556             {
5557                 flushed = 0;
5558             }
5559             else
5560             {
5561                 flushed = flush_stream(tcpssn, &tcpssn->server, p,
5562                         p->iph_api->iph_ret_src(p), p->iph_api->iph_ret_dst(p),
5563                         p->tcph->th_sport, p->tcph->th_dport,
5564                         PKT_FROM_CLIENT);
5565             }
5566             if (flushed)
5567                 purge_flushed_ackd(tcpssn, &tcpssn->server);
5568             else
5569             {
5570                 SnortEventqPush();
5571                 SnortEventqLog(snort_conf->event_queue, p);
5572                 SnortEventqReset();
5573                 SnortEventqPop();
5574             }
5575             tcpssn->server.flags &= ~TF_FORCE_FLUSH;
5576         }
5577 
5578         if (!s5_tcp_cleanup)
5579         {
5580             /* And turn decoder alerts back on (or whatever they were set to) */
5581             policyDecoderFlagsRestore(scb->napPolicyId);
5582         }
5583         policyChecksumFlagsRestore(scb->napPolicyId);
5584 
5585     }
5586 
5587 }
5588 
TcpSessionCleanup(SessionControlBlock * scb,int freeApplicationData)5589 static void TcpSessionCleanup(SessionControlBlock *scb, int freeApplicationData)
5590 {
5591     TcpSession *tcpssn = NULL;
5592 
5593     if (scb->proto_specific_data)
5594         tcpssn = (TcpSession *)scb->proto_specific_data->data;
5595 
5596     if (!tcpssn)
5597     {
5598         /* Huh? */
5599         StreamUpdatePerfBaseState(&sfBase, scb, TCP_STATE_CLOSED);
5600         return;
5601     }
5602 
5603     stream_session_config = scb->session_config;
5604 
5605     FlushQueuedSegs(scb, tcpssn);
5606 
5607     TcpSessionClear(scb, tcpssn, freeApplicationData);
5608 }
5609 
TcpSessionCleanupWithFreeApplicationData(void * scb)5610 static void TcpSessionCleanupWithFreeApplicationData(void *scb)
5611 {
5612     TcpSessionCleanup( ( SessionControlBlock * ) scb, 1);
5613 }
5614 
5615 struct session_state_cleanup_cache
5616 {
5617     uint32_t old_mem_in_use;
5618     sfaddr_t client_ip;
5619     sfaddr_t server_ip;
5620 
5621     uint16_t client_port;
5622     uint16_t server_port;
5623     uint16_t lw_session_state;
5624     uint32_t lw_session_flags;
5625     int16_t app_proto_id;
5626 };
5627 
cleanup_cache_session_state(SessionControlBlock * scb,struct session_state_cleanup_cache * sscc)5628 static inline void cleanup_cache_session_state( SessionControlBlock *scb, struct session_state_cleanup_cache *sscc )
5629 {
5630     sscc->old_mem_in_use = session_mem_in_use;
5631 
5632     sscc->client_port = scb->client_port;
5633     sscc->server_port = scb->server_port;
5634     sscc->lw_session_state = scb->session_state;
5635     sscc->lw_session_flags = scb->ha_state.session_flags;
5636 
5637 #ifdef TARGET_BASED
5638     sscc->app_proto_id = scb->ha_state.application_protocol;
5639 #else
5640     sscc->app_proto_id = 0;
5641 #endif
5642 
5643     sfip_set_ip(&sscc->client_ip, &scb->client_ip);
5644     sfip_set_ip(&sscc->server_ip, &scb->server_ip);
5645 }
5646 
cleanup_log_session_state(char * delete_reason,struct session_state_cleanup_cache * sscc)5647 static inline void cleanup_log_session_state( char *delete_reason, struct session_state_cleanup_cache *sscc )
5648 {
5649     if (stream_session_config->prune_log_max &&
5650             (sscc->old_mem_in_use - session_mem_in_use) > stream_session_config->prune_log_max)
5651     {
5652         char *client_ip_str, *server_ip_str;
5653         client_ip_str = SnortStrdup(inet_ntoa(&sscc->client_ip));
5654         server_ip_str = SnortStrdup(inet_ntoa(&sscc->server_ip));
5655 
5656         LogMessage("S5: Pruned session from cache that was "
5657                 "using %d bytes (%s). %s %d --> %s %d (%d) : "
5658                 "LWstate 0x%x LWFlags 0x%x\n",
5659                 sscc->old_mem_in_use - session_mem_in_use,
5660                 delete_reason,
5661                 client_ip_str, sscc->client_port,
5662                 server_ip_str, sscc->server_port,
5663                 sscc->app_proto_id, sscc->lw_session_state, sscc->lw_session_flags);
5664 
5665         free(client_ip_str);
5666         free(server_ip_str);
5667     }
5668 
5669 }
5670 
5671 
5672 #ifdef SEG_TEST
CheckSegments(const StreamTracker * a)5673 static void CheckSegments (const StreamTracker* a)
5674 {
5675     StreamSegment* ss = a->seglist;
5676     uint32_t sx = ss ? ss->seq : 0;
5677 
5678     while ( ss )
5679     {
5680         if ( SEQ_GT(sx, ss->seq) )
5681         {
5682             const int SEGBORK = 0;
5683             assert(SEGBORK);
5684         }
5685         sx = ss->seq + ss->size;
5686         ss = ss->next;
5687     }
5688 }
5689 #endif
5690 
5691 #ifdef REG_TEST
5692 #define LCL(p, x)    (p->x - p->isn)
5693 #define RMT(p, x, q) (p->x - (q ? q->isn : 0))
5694 
5695 static int s5_trace_enabled = -1;
5696 
TraceEvent(const Packet * p,TcpDataBlock * tdb,uint32_t txd,uint32_t rxd)5697 static void TraceEvent (
5698         const Packet* p, TcpDataBlock* tdb, uint32_t txd, uint32_t rxd
5699         ) {
5700     int i;
5701     char flags[7] = "UAPRSF";
5702     const TCPHdr* h = p->tcph;
5703     const char* order = "";
5704 
5705     if ( !h )
5706         return;
5707 
5708     for ( i = 0; i < 6; i++)
5709         if ( !((1<<(5-i)) & h->th_flags) ) flags[i] = '-';
5710 
5711     // force relative ack to zero if not conveyed
5712     if ( flags[1] != 'A' ) rxd = ntohl(h->th_ack);
5713 
5714     if ( p->packet_flags & PKT_STREAM_ORDER_OK )
5715         order = " (ins)";
5716 
5717     else if ( p->packet_flags & PKT_STREAM_ORDER_BAD )
5718         order = " (oos)";
5719 
5720     fprintf(stdout,
5721             "\n" FMTu64("-3") " %s=0x%02x Seq=%-4u Ack=%-4u Win=%-4u Len=%-4u%s\n",
5722             //"\n" FMTu64("-3") " %s=0x%02x Seq=%-4u Ack=%-4u Win=%-4u Len=%-4u End=%-4u%s\n",
5723             pc.total_from_daq, flags, h->th_flags,
5724             ntohl(h->th_seq)-txd, ntohl(h->th_ack)-rxd,
5725             ntohs(h->th_win), p->dsize, order
5726             //ntohs(h->th_win), p->dsize,  tdb->end_seq-txd, order
5727            );
5728 }
5729 
TraceSession(const SessionControlBlock * lws)5730 static void TraceSession (const SessionControlBlock* lws)
5731 {
5732     fprintf(stdout, "    LWS: ST=0x%x SF=0x%x CP=%u SP=%u\n",
5733             (unsigned)lws->session_state, lws->ha_state.session_flags,
5734             (unsigned)ntohs(lws->client_port), (unsigned)ntohs(lws->server_port));
5735 }
5736 
5737 static const char* statext[] = {
5738     "NON", "LST", "SYR", "SYS", "EST", "CLW",
5739     "LAK", "FW1", "CLG", "FW2", "TWT", "CLD"
5740 };
5741 
5742 static const char* flushxt[] = {
5743     "NON", "FPR", "LOG", "RSP", "SLW",
5744 #if 0
5745     "CON",
5746 #endif
5747     "IGN", "PRO",
5748 #ifdef NORMALIZER
5749     "PRE", "PAF"
5750 #endif
5751 };
5752 
TraceSegments(const StreamTracker * a)5753 static void TraceSegments (const StreamTracker* a)
5754 {
5755     StreamSegment* ss = a->seglist;
5756     uint32_t sx = a->r_win_base;
5757     unsigned segs = 0, bytes = 0;
5758 
5759     while ( ss )
5760     {
5761         if ( SEQ_LT(sx, ss->seq) )
5762             fprintf(stdout, " +%u", ss->seq-sx);
5763         else if ( SEQ_GT(sx, ss->seq) )
5764             fprintf(stdout, " -%u", sx-ss->seq);
5765 
5766         fprintf(stdout, " %u", ss->size);
5767 
5768         segs++;
5769         bytes += ss->size;
5770 
5771         sx = ss->seq + ss->size;
5772         ss = ss->next;
5773     }
5774     assert(a->seg_count == segs);
5775     assert(a->seg_bytes_logical == bytes);
5776 }
5777 
TraceState(const StreamTracker * a,const StreamTracker * b,const char * s)5778 static void TraceState (const StreamTracker* a, const StreamTracker* b, const char* s)
5779 {
5780     uint32_t why = a->l_nxt_seq ? LCL(a, l_nxt_seq) : 0;
5781 
5782     fprintf(stdout,
5783             "    %s ST=%s:%02x   UA=%-4u NS=%-4u LW=%-5u RN=%-4u RW=%-4u ",
5784             s, statext[a->s_mgr.state], a->s_mgr.sub_state,
5785             LCL(a, l_unackd), why, a->l_window,
5786             RMT(a, r_nxt_ack, b), RMT(a, r_win_base, b)
5787            );
5788     if ( a->s_mgr.state_queue )
5789         fprintf(stdout,
5790                 "QS=%s QC=0x%02x QA=%-4u",
5791                 statext[a->s_mgr.state_queue], a->s_mgr.expected_flags,
5792                 RMT(a, s_mgr.transition_seq, b)
5793                );
5794     fprintf(stdout, "\n");
5795     fprintf(stdout,
5796             "         FP=%s:%-4u SC=%-4u FL=%-4u SL=%-5u BS=%-4u",
5797             flushxt[a->flush_mgr.flush_policy], a->flush_mgr.flush_pt,
5798             a->seg_count, a->flush_count, a->seg_bytes_logical,
5799             a->seglist_base_seq - b->isn
5800            );
5801     if ( s5_trace_enabled == 2 )
5802         TraceSegments(a);
5803 
5804     fprintf(stdout, "\n");
5805 }
5806 
TraceTCP(const Packet * p,const SessionControlBlock * lws,TcpDataBlock * tdb,int event)5807 static void TraceTCP (
5808         const Packet* p, const SessionControlBlock* lws, TcpDataBlock* tdb, int event
5809         ) {
5810     const TcpSession* ssn = (lws && lws->proto_specific_data) ?
5811         (TcpSession*)lws->proto_specific_data->data : NULL;
5812     const StreamTracker* srv = ssn ? &ssn->server : NULL;
5813     const StreamTracker* cli = ssn ? &ssn->client : NULL;
5814 
5815     const char* cdir = "?", *sdir = "?";
5816     uint32_t txd = 0, rxd = 0;
5817 
5818     if ( p->packet_flags & PKT_FROM_SERVER )
5819     {
5820         sdir = "SRV>";
5821         cdir = "CLI<";
5822         if ( srv ) txd = srv->isn;
5823         if ( cli ) rxd = cli->isn;
5824     }
5825     else if ( p->packet_flags & PKT_FROM_CLIENT )
5826     {
5827         sdir = "SRV<";
5828         cdir = "CLI>";
5829         if ( cli ) txd = cli->isn;
5830         if ( srv ) rxd = srv->isn;
5831     }
5832     TraceEvent(p, tdb, txd, rxd);
5833 
5834     if ( lws && lws->session_established ) TraceSession(lws);
5835 
5836     if ( !event )
5837     {
5838         if ( cli ) TraceState(cli, srv, cdir);
5839         if ( srv ) TraceState(srv, cli, sdir);
5840     }
5841 }
5842 
S5TraceTCP(const Packet * p,const SessionControlBlock * lws,TcpDataBlock * tdb,int event)5843 static inline void S5TraceTCP (
5844         const Packet* p, const SessionControlBlock* lws, TcpDataBlock* tdb, int event
5845         ) {
5846     if ( !s5_trace_enabled )
5847         return;
5848 
5849     if ( s5_trace_enabled < 0 )
5850     {
5851         const char* s5t = getenv("S5_TRACE");
5852 
5853         if ( !s5t ) {
5854             s5_trace_enabled = 0;
5855             return;
5856         }
5857         // no error checking required - atoi() is sufficient
5858         s5_trace_enabled = atoi(s5t);
5859     }
5860     TraceTCP(p, lws, tdb, event);
5861 }
5862 #endif  // REG_TEST
5863 
5864 /*
5865  * Main entry point for TCP
5866  */
StreamProcessTcp(Packet * p,SessionControlBlock * scb,StreamTcpPolicy * s5TcpPolicy,SessionKey * skey)5867 int StreamProcessTcp(Packet *p, SessionControlBlock *scb, StreamTcpPolicy *s5TcpPolicy, SessionKey *skey)
5868 {
5869     TcpDataBlock tdb;
5870     SFXHASH_NODE *hash_node = NULL;
5871     int rc, status;
5872     PROFILE_VARS;
5873 #if defined(DAQ_CAPA_CST_TIMEOUT)
5874     uint64_t timeout;
5875 #endif
5876 
5877     STREAM_DEBUG_WRAP(
5878             char flagbuf[9];
5879             CreateTCPFlagString(p, flagbuf);
5880             DebugMessage((DEBUG_STREAM|DEBUG_STREAM_STATE),
5881                 "Got TCP Packet 0x%X:%d ->  0x%X:%d %s\nseq: 0x%X   ack:0x%X  "
5882                 "dsize: %u\n"
5883                 "active sessions: %u\n",
5884                 GET_SRC_IP(p),
5885                 p->sp,
5886                 GET_DST_IP(p),
5887                 p->dp,
5888                 flagbuf,
5889                 ntohl(p->tcph->th_seq), ntohl(p->tcph->th_ack), p->dsize,
5890                 sfxhash_count(tcp_lws_cache->hashTable));
5891             );
5892 
5893     PREPROC_PROFILE_START(s5TcpPerfStats);
5894 
5895     if( scb->ha_state.session_flags & ( SSNFLAG_DROP_CLIENT | SSNFLAG_DROP_SERVER ) )
5896     {
5897         /* Got a packet on a session that was dropped (by a rule). */
5898         session_api->set_packet_direction_flag(p, scb);
5899 
5900         /* Drop this packet */
5901         if( ( ( p->packet_flags & PKT_FROM_SERVER) &&
5902               ( scb->ha_state.session_flags & SSNFLAG_DROP_SERVER ) )
5903               ||
5904               ( ( p->packet_flags & PKT_FROM_CLIENT ) &&
5905                 ( scb->ha_state.session_flags & SSNFLAG_DROP_CLIENT ) ) )
5906         {
5907             DEBUG_WRAP(DebugMessage(DEBUG_STREAM_STATE,
5908                         "Blocking %s packet as session was blocked\n",
5909                         p->packet_flags & PKT_FROM_SERVER ?
5910                         "server" : "client"););
5911             DisableAllDetect( p );
5912 
5913             if( scb->ha_state.session_flags & SSNFLAG_FORCE_BLOCK )
5914                 Active_ForceDropSessionWithoutReset();
5915             else
5916                 Active_DropSessionWithoutReset(p);
5917 
5918 #ifdef ACTIVE_RESPONSE
5919             StreamActiveResponse(p, scb);
5920 #endif
5921             if (pkt_trace_enabled)
5922                 addPktTraceData(VERDICT_REASON_STREAM, snprintf(trace_line, MAX_TRACE_LINE,
5923                     "Stream: TCP session was already blocked, %s\n", getPktTraceActMsg()));
5924             else addPktTraceData(VERDICT_REASON_STREAM, 0);
5925 
5926             PREPROC_PROFILE_END(s5TcpPerfStats);
5927             return ACTION_NOTHING;
5928         }
5929     }
5930 
5931     if( s5TcpPolicy == NULL )
5932     {
5933         /* Find an Tcp policy for this packet */
5934         s5TcpPolicy = StreamPolicyLookup( scb, GET_DST_IP( p ) );
5935         if( !s5TcpPolicy )
5936         {
5937             STREAM_DEBUG_WRAP( DebugMessage( DEBUG_STREAM,
5938                                "[Stream] Could not find Tcp Policy context "
5939                                "for IP %s\n", inet_ntoa( GET_DST_ADDR( p ) ) ); );
5940             PREPROC_PROFILE_END( s5TcpPerfStats );
5941             return 0;
5942         }
5943 #if defined(DAQ_CAPA_CST_TIMEOUT)
5944         if (Daq_Capa_Timeout)
5945         {
5946            GetTimeout(p,&timeout);
5947            s5TcpPolicy->session_timeout = timeout + STREAM_DELAY_TIMEOUT_AFTER_CONNECTION_ENDED;
5948         }
5949 #endif
5950     }
5951 
5952     rc = isPacketFilterDiscard( p,
5953             ( ( ( StreamConfig * ) scb->stream_config )->tcp_config->default_policy->flags & STREAM_CONFIG_IGNORE_ANY ) );
5954     if( rc == PORT_MONITOR_PACKET_DISCARD )
5955     {
5956         //ignore the packet
5957         STREAM_DEBUG_WRAP(DebugMessage(DEBUG_STREAM,
5958                     "[Stream] %s:%d -> %s:%d Packet discarded due to port filtering\n",
5959                     inet_ntoa(GET_SRC_ADDR(p)),p->sp,inet_ntoa(GET_DST_ADDR(p)),p->dp););
5960 
5961         UpdateFilteredPacketStats(&sfBase, IPPROTO_TCP);
5962         PREPROC_PROFILE_END(s5TcpPerfStats);
5963         return 0;
5964     }
5965 
5966     SetupTcpDataBlock( &tdb, p );
5967 
5968 #ifdef STREAM_DEBUG_ENABLED
5969     PrintTcpDataBlock( &tdb );
5970 #endif
5971 
5972     if( !scb->session_established )
5973     {
5974         if( s5TcpPolicy->flags & STREAM_CONFIG_REQUIRE_3WHS )
5975         {
5976             /* if require 3WHS, set session state to SYN rx'ed if we got one */
5977             if( TCP_ISFLAGSET( p->tcph, TH_SYN ) && !TCP_ISFLAGSET( p->tcph, TH_ACK ) )
5978             {
5979                 /* SYN only */
5980                 scb->session_state = STREAM_STATE_SYN;
5981                 scb->session_established = true;
5982                 scb->proto_policy = s5TcpPolicy;
5983                 s5stats.total_tcp_sessions++;
5984                 s5stats.active_tcp_sessions++;
5985             }
5986             else
5987             {
5988                 /* If we're within the "startup" window, try to handle
5989                  * this packet as midstream pickup -- allows for
5990                  * connections that already existed before snort started.
5991                  */
5992                 if (p->pkth->ts.tv_sec - firstPacketTime < s5TcpPolicy->hs_timeout)
5993                 {
5994                     midstream_allowed = 1;
5995                     goto midstream_pickup_allowed;
5996                 }
5997                 /*
5998                  * Do nothing with this packet since we require a 3-way.
5999                  * Wow that just sounds cool... Require a 3-way.  Hehe.
6000                  */
6001                 DEBUG_WRAP(
6002                         DebugMessage(DEBUG_STREAM_STATE, "Stream: Requiring 3-way "
6003                             "Handshake, but failed to retrieve session object "
6004                             "for non SYN packet.\n"););
6005 
6006                 midstream_allowed = 0;
6007                 EventNo3whs(s5TcpPolicy);
6008                 PREPROC_PROFILE_END(s5TcpPerfStats);
6009 #ifdef REG_TEST
6010                 S5TraceTCP(p, scb, &tdb, 1);
6011 #endif
6012                 return 0;
6013             }
6014         }
6015         else
6016         {
6017 midstream_pickup_allowed:
6018             if (TCP_ISFLAGSET(p->tcph, (TH_SYN|TH_ACK)))
6019             {
6020                 /* If we have a SYN/ACK */
6021                 scb->session_established = true;
6022                 scb->proto_policy = s5TcpPolicy;
6023                 s5stats.total_tcp_sessions++;
6024                 s5stats.active_tcp_sessions++;
6025             }
6026             else if (p->dsize > 0)
6027             {
6028                 /* If we have data -- missed the SYN/ACK
6029                  * somehow -- maybe just an incomplete PCAP.
6030                  * This handles data on SYN situations
6031                  */
6032                 scb->session_established = true;
6033                 scb->proto_policy = s5TcpPolicy;
6034                 s5stats.total_tcp_sessions++;
6035                 s5stats.active_tcp_sessions++;
6036             }
6037             else if( ( ( ( ( StreamConfig * ) scb->stream_config )->tcp_config->session_on_syn ||
6038                         ( StreamPacketHasWscale(p) & TF_WSCALE ) )
6039                     && TCP_ISFLAGSET(p->tcph, TH_SYN) ) || StreamExpectIsExpected( p, &hash_node ) )
6040             {
6041                 /* If we have a wscale option or this is an expected connection, need to save the
6042                  * option if its the first SYN from client or continue to get the expected session
6043                  * data. */
6044                 scb->session_state = STREAM_STATE_SYN;
6045                 scb->session_established = true;
6046                 scb->proto_policy = s5TcpPolicy;
6047                 s5stats.total_tcp_sessions++;
6048                 s5stats.active_tcp_sessions++;
6049             }
6050             else
6051             {
6052                 /* No data, no need to create session yet */
6053                 /* This is done to handle SYN flood DoS attacks */
6054 #ifdef STREAM_DEBUG_ENABLED
6055                 if (TCP_ISFLAGSET(p->tcph, TH_SYN))
6056                 {
6057                     STREAM_DEBUG_WRAP(DebugMessage(DEBUG_STREAM_STATE,
6058                                 "Stream: no data in packet (SYN only), no need to"
6059                                 "create lightweight session.\n"););
6060                 }
6061                 else
6062                 {
6063                     STREAM_DEBUG_WRAP(DebugMessage(DEBUG_STREAM_STATE,
6064                                 "Stream: no data in packet (non SYN/keep alive "
6065                                 "ACK?), no need to create lightweight session.\n"););
6066                 }
6067 #endif
6068 
6069                 if(TCP_ISFLAGSET(p->tcph, TH_SYN))
6070                     scb->session_state |= STREAM_STATE_SYN;
6071                 PREPROC_PROFILE_END(s5TcpPerfStats);
6072 #ifdef REG_TEST
6073                 S5TraceTCP(p, scb, &tdb, 1);
6074 #endif
6075                 return 0;
6076             }
6077         }
6078     }
6079 
6080     p->ssnptr = scb;
6081 
6082     /*
6083      * Check if the session is expired.
6084      * Should be done before we do something with the packet...
6085      * ie, Insert a packet, or handle state change SYN, FIN, RST, etc.
6086      */
6087     if( ( scb->session_state & STREAM_STATE_TIMEDOUT) || StreamExpire( p, scb ) )
6088     {
6089         scb->ha_state.session_flags |= SSNFLAG_TIMEDOUT;
6090 
6091 #ifdef ENABLE_HA
6092         /* Notify the HA peer of the session cleanup/reset by way of a deletion notification. */
6093         PREPROC_PROFILE_TMPEND(s5TcpPerfStats);
6094         SessionHANotifyDeletion(scb);
6095         PREPROC_PROFILE_TMPSTART(s5TcpPerfStats);
6096         scb->ha_flags = HA_FLAG_NEW | HA_FLAG_MODIFIED;
6097 #endif
6098 
6099         /* If this one has been reset, delete the TCP portion, and start a new. */
6100         if( scb->ha_state.session_flags & SSNFLAG_RESET )
6101         {
6102             struct session_state_cleanup_cache sscc;
6103 
6104             cleanup_cache_session_state( scb, &sscc );
6105             TcpSessionCleanupWithFreeApplicationData(scb);
6106             cleanup_log_session_state( "new data/reset", &sscc );
6107             status = ProcessTcp( scb, p, &tdb, s5TcpPolicy, hash_node );
6108 
6109             STREAM_DEBUG_WRAP(DebugMessage(DEBUG_STREAM_STATE,
6110                         "Finished Stream TCP cleanly!\n"
6111                         "---------------------------------------------------\n"););
6112         }
6113         else
6114         {
6115             /* Not reset, simply time'd out.  Clean it up */
6116             struct session_state_cleanup_cache sscc;
6117 
6118             STREAM_DEBUG_WRAP(DebugMessage(DEBUG_STREAM_STATE, "Stream TCP session timedout!\n"););
6119 
6120             cleanup_cache_session_state( scb, &sscc );
6121             TcpSessionCleanupWithFreeApplicationData( scb );
6122             cleanup_log_session_state( "new data/timedout", &sscc );
6123             status = ProcessTcp(scb, p, &tdb, s5TcpPolicy, hash_node);
6124         }
6125     }
6126     else
6127     {
6128         status = ProcessTcp( scb, p, &tdb, s5TcpPolicy, hash_node );
6129         STREAM_DEBUG_WRAP(DebugMessage(DEBUG_STREAM_STATE,
6130                     "Finished Stream TCP cleanly!\n"
6131                     "---------------------------------------------------\n"););
6132     }
6133 
6134     if( !( status & ACTION_LWSSN_CLOSED ) )
6135     {
6136         MarkupPacketFlags( p, scb );
6137         /* Receiving valid RST for a ongoing/hanged tcp session,
6138          * override configured session timeout to non-configurable
6139          * lower timeout of 180 seconds to clean up the session.
6140          */
6141         if((status & ACTION_RST) &&
6142             (scb->expire_time - (((uint64_t)p->pkth->ts.tv_sec ) * TCP_HZ)) > (STREAM_SSN_RST_TIMEOUT * TCP_HZ))
6143         {
6144             session_api->set_expire_timer(p, scb, STREAM_SSN_RST_TIMEOUT);
6145         }
6146         else
6147         {
6148             session_api->set_expire_timer( p, scb, s5TcpPolicy->session_timeout );
6149         }
6150     }
6151 #ifdef ENABLE_HA
6152     else
6153     {
6154         /* TCP Session closed, so send an HA deletion event for the session. */
6155         SessionHANotifyDeletion( scb );
6156     }
6157 #endif
6158     if( status & ACTION_DISABLE_INSPECTION )
6159     {
6160         session_api->disable_inspection( scb, p );
6161 
6162         STREAM_DEBUG_WRAP(DebugMessage(DEBUG_STREAM_STATE,
6163                     "Stream Ignoring packet from %d. Session marked as ignore\n",
6164                     p->packet_flags & PKT_FROM_SERVER? "server" : "client"););
6165     }
6166 
6167     PREPROC_PROFILE_END(s5TcpPerfStats);
6168 #ifdef REG_TEST
6169     S5TraceTCP( p, scb, &tdb, 0 );
6170 #endif
6171     return 0;
6172 }
6173 
StreamGetTcpTimestamp(Packet * p,uint32_t * ts,int strip)6174 static uint32_t StreamGetTcpTimestamp( Packet *p, uint32_t *ts, int strip )
6175 {
6176     unsigned int i = 0;
6177 
6178     STREAM_DEBUG_WRAP(DebugMessage(DEBUG_STREAM_STATE,
6179                 "Getting timestamp...\n"););
6180     while(i < p->tcp_option_count && i < TCP_OPTLENMAX)
6181     {
6182         if(p->tcp_options[i].code == TCPOPT_TIMESTAMP)
6183         {
6184 #ifdef NORMALIZER
6185             if ( strip && Normalize_GetMode(snort_conf, NORM_TCP_OPT) == NORM_MODE_ON )
6186             {
6187                 NormalStripTimeStamp(p, i);
6188             }
6189             else
6190             if ( !strip || !NormalStripTimeStamp(p, i) )
6191 #endif
6192             {
6193                 *ts = EXTRACT_32BITS(p->tcp_options[i].data);
6194                 STREAM_DEBUG_WRAP(DebugMessage(DEBUG_STREAM_STATE,
6195                             "Found timestamp %lu\n", *ts););
6196 
6197                 return TF_TSTAMP;
6198             }
6199         }
6200         i++;
6201     }
6202     *ts = 0;
6203 
6204     STREAM_DEBUG_WRAP(DebugMessage(DEBUG_STREAM_STATE,
6205                 "No timestamp...\n"););
6206 
6207     return TF_NONE;
6208 }
6209 
StreamGetMss(Packet * p,uint16_t * value)6210 static uint32_t StreamGetMss(Packet *p, uint16_t *value)
6211 {
6212     unsigned int i = 0;
6213 
6214     STREAM_DEBUG_WRAP(DebugMessage(DEBUG_STREAM_STATE,
6215                 "Getting MSS...\n"););
6216     while(i < p->tcp_option_count && i < TCP_OPTLENMAX)
6217     {
6218         if(p->tcp_options[i].code == TCPOPT_MAXSEG)
6219         {
6220             *value = EXTRACT_16BITS(p->tcp_options[i].data);
6221             STREAM_DEBUG_WRAP(DebugMessage(DEBUG_STREAM_STATE,
6222                         "Found MSS %u\n", *value););
6223             return TF_MSS;
6224         }
6225 
6226         i++;
6227     }
6228 
6229     *value = 0;
6230 
6231     STREAM_DEBUG_WRAP(DebugMessage(DEBUG_STREAM_STATE,
6232                 "No MSS...\n"););
6233     return TF_NONE;
6234 }
6235 
StreamGetWscale(Packet * p,uint16_t * value)6236 static uint32_t StreamGetWscale(Packet *p, uint16_t *value)
6237 {
6238     unsigned int i = 0;
6239 
6240     STREAM_DEBUG_WRAP(DebugMessage(DEBUG_STREAM_STATE,
6241                 "Getting wscale...\n"););
6242     while(i < p->tcp_option_count && i < TCP_OPTLENMAX)
6243     {
6244         if(p->tcp_options[i].code == TCPOPT_WSCALE)
6245         {
6246             *value = (uint16_t) p->tcp_options[i].data[0];
6247             STREAM_DEBUG_WRAP(DebugMessage(DEBUG_STREAM_STATE,
6248                         "Found wscale %d\n", *value););
6249 
6250             /* If scale specified in option is larger than 14,
6251              * use 14 because of limitation in the math of
6252              * shifting a 32bit value (max scaled window is 2^30th).
6253              *
6254              * See RFC 1323 for details.
6255              */
6256             if (*value > 14)
6257             {
6258                 *value = 14;
6259             }
6260 
6261             return TF_WSCALE;
6262         }
6263 
6264         i++;
6265     }
6266 
6267     *value = 0;
6268     STREAM_DEBUG_WRAP(DebugMessage(DEBUG_STREAM_STATE,
6269                 "No wscale...\n"););
6270     return TF_NONE;
6271 }
6272 
StreamPacketHasWscale(Packet * p)6273 static uint32_t StreamPacketHasWscale(Packet *p)
6274 {
6275     uint16_t wscale;
6276 
6277     STREAM_DEBUG_WRAP(DebugMessage(DEBUG_STREAM_STATE,
6278                 "Checking for wscale...\n"););
6279     return StreamGetWscale(p, &wscale);
6280 }
6281 
IsWellFormed(Packet * p,StreamTracker * ts)6282 static inline int IsWellFormed(Packet *p, StreamTracker *ts)
6283 {
6284     return ( !ts->mss || (p->dsize <= ts->mss) );
6285 }
6286 
FinishServerInit(Packet * p,TcpDataBlock * tdb,TcpSession * ssn)6287 static void FinishServerInit(Packet *p, TcpDataBlock *tdb, TcpSession *ssn)
6288 {
6289     StreamTracker *server;
6290     StreamTracker *client;
6291 
6292     if (!ssn)
6293     {
6294         return;
6295     }
6296 
6297     server = &ssn->server;
6298     client = &ssn->client;
6299 
6300     server->l_window = tdb->win;              /* set initial server window */
6301     server->l_unackd = tdb->end_seq;
6302     server->l_nxt_seq = server->l_unackd;
6303     server->isn = tdb->seq;
6304 
6305     client->r_nxt_ack = tdb->seq + 1;
6306 
6307     if ( p->tcph->th_flags & TH_FIN )
6308         server->l_nxt_seq--;
6309 
6310     STREAM_DEBUG_WRAP(DebugMessage(DEBUG_STREAM_STATE,
6311                 "seglist_base_seq = %X\n", client->seglist_base_seq););
6312 
6313     if (!(ssn->scb->session_state & STREAM_STATE_MIDSTREAM))
6314     {
6315         server->s_mgr.state = TCP_STATE_SYN_RCVD;
6316         client->seglist_base_seq = server->l_unackd;
6317 
6318         if ( tdb->seq == tdb->end_seq )
6319             client->r_win_base = tdb->end_seq;
6320         else
6321             client->r_win_base = tdb->seq + 1;
6322     }
6323     else
6324     {
6325         client->seglist_base_seq = tdb->seq;
6326         client->r_win_base = tdb->seq;
6327     }
6328     server->flags |= StreamGetTcpTimestamp(p, &server->ts_last, 0);
6329     if (server->ts_last == 0)
6330         server->flags |= TF_TSTAMP_ZERO;
6331     else
6332         server->ts_last_pkt = p->pkth->ts.tv_sec;
6333     server->flags |= StreamGetMss(p, &server->mss);
6334     server->flags |= StreamGetWscale(p, &server->wscale);
6335 
6336 #ifdef STREAM_DEBUG_ENABLED
6337     PrintTcpSession(ssn);
6338 #endif
6339 }
6340 
6341 #ifdef OLD_CODE_NOLONGER_USED_DEPENDS_ON_CURRENT_STATE
QueueState(uint8_t transition,StreamTracker * st,uint8_t expected_flags,uint32_t seq_num,uint8_t get_seq)6342 static inline void QueueState(uint8_t transition, StreamTracker *st,
6343         uint8_t expected_flags, uint32_t seq_num, uint8_t get_seq)
6344 {
6345     StateMgr *smgr = &st->s_mgr;
6346 
6347     STREAM_DEBUG_WRAP(DebugMessage(DEBUG_STREAM_STATE,
6348                 "[^^] Queing transition to %s, flag 0x%X, seq: 0x%X\n",
6349                 state_names[transition], expected_flags, seq_num););
6350 
6351     smgr->state_queue = transition;
6352     smgr->expected_flags = expected_flags;
6353     smgr->stq_get_seq = get_seq;
6354     smgr->transition_seq = seq_num;
6355 
6356 #ifdef STREAM_DEBUG_ENABLED
6357     PrintStateMgr(smgr);
6358 #endif
6359     return;
6360 }
6361 
EvalStateQueue(StreamTracker * sptr,uint8_t flags,uint32_t ack)6362 static inline int EvalStateQueue(StreamTracker *sptr, uint8_t flags,
6363         uint32_t ack)
6364 {
6365     StateMgr *smgr = &sptr->s_mgr;
6366 
6367     STREAM_DEBUG_WRAP(DebugMessage(DEBUG_STREAM_STATE,
6368                 "Evaluating state queue!\n"););
6369     STREAM_DEBUG_WRAP(DebugMessage(DEBUG_STREAM_STATE,
6370                 "StreamTracker %p, flags 0x%X ack: 0x%X\n", sptr, flags, ack);
6371             PrintStateMgr(smgr););
6372 
6373     if(smgr->expected_flags != 0)
6374     {
6375         if((flags & smgr->expected_flags) != 0)
6376         {
6377             if(smgr->stq_get_seq && (SEQ_GEQ(ack, smgr->transition_seq)))
6378             {
6379 
6380                 STREAM_DEBUG_WRAP(DebugMessage(DEBUG_STREAM_STATE,
6381                             "[^^] Accepting %s state transition\n",
6382                             state_names[smgr->state_queue]););
6383                 smgr->state = smgr->state_queue;
6384                 smgr->expected_flags = 0;
6385                 smgr->transition_seq = 0;
6386                 return 1;
6387             }
6388             else if(!smgr->stq_get_seq)
6389             {
6390                 STREAM_DEBUG_WRAP(DebugMessage(DEBUG_STREAM_STATE,
6391                             "[^^] Accepting %s state transition\n",
6392                             state_names[smgr->state_queue]););
6393                 smgr->state = smgr->state_queue;
6394                 smgr->expected_flags = 0;
6395                 smgr->transition_seq = 0;
6396                 return 1;
6397 
6398             }
6399             else
6400             {
6401                 STREAM_DEBUG_WRAP(DebugMessage(DEBUG_STREAM_STATE,
6402                             "[!!] sptr->stq_get_seq: %d  "
6403                             "[ack: 0x%X expected: 0x%X]\n", smgr->stq_get_seq,
6404                             ack, smgr->transition_seq););
6405             }
6406         }
6407         else
6408         {
6409             STREAM_DEBUG_WRAP(DebugMessage(DEBUG_STREAM_STATE,
6410                         "[!!] flags: 0x%X  expected: 0x%X, bitwise: 0x%X\n",
6411                         flags, smgr->expected_flags,
6412                         (flags & smgr->expected_flags)););
6413         }
6414     }
6415     else
6416     {
6417         STREAM_DEBUG_WRAP(DebugMessage(DEBUG_STREAM_STATE,
6418                     "No transition queued, returning\n"););
6419     }
6420 
6421     return 0;
6422 }
6423 #endif
6424 
IgnoreLargePkt(StreamTracker * st,Packet * p,TcpDataBlock * tdb)6425 static inline int IgnoreLargePkt(StreamTracker *st, Packet *p, TcpDataBlock *tdb)
6426 {
6427     if((st->flush_mgr.flush_policy == STREAM_FLPOLICY_FOOTPRINT) &&
6428             (st->tcp_policy->flags & STREAM_CONFIG_PERFORMANCE))
6429     {
6430         if ((p->dsize > st->flush_mgr.flush_pt * 2) &&
6431                 (st->seg_count == 0))
6432         {
6433             STREAM_DEBUG_WRAP(DebugMessage(DEBUG_STREAM_STATE,
6434                         "WARNING: Data larger than twice flushpoint.  Not "
6435                         "inserting for reassembly: seq: %d, size %d!\n"
6436                         "This is a tradeoff of performance versus the remote "
6437                         "possibility of catching an exploit that spans two or "
6438                         "more consecuvitve large packets.\n",
6439                         tdb->seq, p->dsize););
6440             return 1;
6441         }
6442     }
6443     return 0;
6444 }
6445 
NewQueue(StreamTracker * st,Packet * p,TcpDataBlock * tdb,TcpSession * tcpssn)6446 static void NewQueue(StreamTracker *st, Packet *p, TcpDataBlock *tdb, TcpSession *tcpssn)
6447 {
6448     StreamSegment *ss = NULL;
6449     uint32_t overlap = 0;
6450     PROFILE_VARS;
6451 
6452     STREAM_DEBUG_WRAP(DebugMessage(DEBUG_STREAM_STATE,
6453                 "In NewQueue\n"););
6454 
6455     PREPROC_PROFILE_START(s5TcpInsertPerfStats);
6456 
6457     if(st->flush_mgr.flush_policy != STREAM_FLPOLICY_IGNORE)
6458     {
6459         uint32_t seq = tdb->seq;
6460 
6461         /* Check if we should not insert a large packet */
6462         if (IgnoreLargePkt(st, p, tdb))
6463         {
6464             return;
6465         }
6466 
6467         if ( p->tcph->th_flags & TH_SYN )
6468             seq++;
6469 
6470         /* new packet seq is below the last ack... */
6471         if ( SEQ_GT(st->r_win_base, seq) )
6472         {
6473             STREAM_DEBUG_WRAP(DebugMessage(DEBUG_STREAM_STATE,
6474                         "segment overlaps ack'd data...\n"););
6475             overlap = st->r_win_base - tdb->seq;
6476             if (overlap >= p->dsize)
6477             {
6478                 STREAM_DEBUG_WRAP(DebugMessage(DEBUG_STREAM_STATE,
6479                             "full overlap on ack'd data, dropping segment\n"););
6480                 PREPROC_PROFILE_END(s5TcpInsertPerfStats);
6481                 return;
6482             }
6483         }
6484 
6485         AddStreamNode(st, p, tdb, tcpssn, p->dsize, overlap, 0, tdb->seq+overlap, NULL, &ss);
6486 
6487         STREAM_DEBUG_WRAP(DebugMessage(DEBUG_STREAM_STATE,
6488                     "Attached new queue to seglist, %d bytes queued, "
6489                     "base_seq 0x%X\n",
6490                     ss->size, st->seglist_base_seq););
6491     }
6492 
6493     PREPROC_PROFILE_END(s5TcpInsertPerfStats);
6494     return;
6495 }
6496 
6497 #if 0
6498 static inline StreamSegment *FindSegment(StreamTracker *st, uint32_t pkt_seq)
6499 {
6500     int32_t dist_head;
6501     int32_t dist_tail;
6502     StreamSegment *ss;
6503 
6504     if (!st->seglist)
6505         return NULL;
6506 
6507     dist_head = pkt_seq - st->seglist->seq;
6508     dist_tail = pkt_seq - st->seglist_tail->seq;
6509 
6510     if (dist_head <= dist_tail)
6511     {
6512         /* Start iterating at the head (left) */
6513         for (ss = st->seglist; ss; ss = ss->next)
6514         {
6515             if (SEQ_EQ(ss->seq, pkt_seq))
6516                 return ss;
6517 
6518             if (SEQ_GEQ(ss->seq, pkt_seq))
6519                 break;
6520         }
6521     }
6522     else
6523     {
6524         /* Start iterating at the tail (right) */
6525         for (ss = st->seglist_tail; ss; ss = ss->prev)
6526         {
6527             if (SEQ_EQ(ss->seq, pkt_seq))
6528                 return ss;
6529 
6530             if (SEQ_LT(ss->seq, pkt_seq))
6531                 break;
6532         }
6533     }
6534     return NULL;
6535 }
6536 #endif
6537 
StreamTcpSessionClear(Packet * p)6538 void StreamTcpSessionClear(Packet *p)
6539 {
6540     SessionControlBlock *scb;
6541     TcpSession *ssn;
6542 
6543     if ((!p) || (!p->ssnptr))
6544         return;
6545 
6546     scb = (SessionControlBlock *)p->ssnptr;
6547 
6548     if (!scb->proto_specific_data)
6549         return;
6550 
6551     ssn = (TcpSession *)scb->proto_specific_data->data;
6552 
6553     if (!ssn)
6554         return;
6555 
6556     TcpSessionClear(scb, ssn, 1);
6557 }
6558 
SegmentFastTrack(StreamSegment * tail,TcpDataBlock * tdb)6559 static inline int SegmentFastTrack(StreamSegment *tail, TcpDataBlock *tdb)
6560 {
6561     STREAM_DEBUG_WRAP(DebugMessage(DEBUG_STREAM_STATE,
6562                 "Checking seq for fast track: %X > %X\n", tdb->seq,
6563                 tail->seq + tail->size););
6564 
6565     if(SEQ_EQ(tdb->seq, tail->seq + tail->size))
6566         return 1;
6567 
6568     return 0;
6569 }
6570 
SegmentAlloc(Packet * p,const struct timeval * tv,uint32_t caplen,uint32_t pktlen,const uint8_t * pkt)6571 static inline StreamSegment* SegmentAlloc (
6572         Packet* p, const struct timeval* tv, uint32_t caplen, uint32_t pktlen, const uint8_t* pkt)
6573 {
6574     StreamSegment* ss;
6575     unsigned size = sizeof(*ss);
6576 
6577     if ( caplen > 0 )
6578         size += caplen - 1;  // ss contains 1st byte
6579 
6580     session_mem_in_use += size;
6581 
6582     if (session_mem_in_use > stream_session_config->memcap)
6583     {
6584         pc.str_mem_faults++;
6585         sfBase.iStreamFaults++;
6586 
6587         if ( !p )
6588         {
6589             session_mem_in_use -= size;
6590             return NULL;
6591         }
6592 
6593         /* Smack the older time'd out sessions */
6594         if ( !session_api->prune_session_cache( tcp_lws_cache, p->pkth->ts.tv_sec,
6595                     ( SessionControlBlock * ) p->ssnptr, 0 ) )
6596         {
6597             /* Try the memcap - last parameter (1) specifies check
6598              * based on memory cap. */
6599             session_api->prune_session_cache(tcp_lws_cache, 0, (SessionControlBlock*) p->ssnptr, 1);
6600         }
6601     }
6602     if (session_mem_in_use > stream_session_config->memcap)
6603     {
6604         session_mem_in_use -= size;
6605         return NULL;
6606     }
6607 
6608     ss = SnortPreprocAlloc(1, size, PP_STREAM, PP_MEM_CATEGORY_SESSION);
6609 
6610     ss->tv.tv_sec = tv->tv_sec;
6611     ss->tv.tv_usec = tv->tv_usec;
6612     ss->caplen = caplen;
6613     ss->pktlen = pktlen;
6614 
6615     memcpy(ss->pkt, pkt, caplen);
6616 
6617     return ss;
6618 }
6619 
AddStreamNode(StreamTracker * st,Packet * p,TcpDataBlock * tdb,TcpSession * tcpssn,uint16_t len,uint32_t slide,uint32_t trunc,uint32_t seq,StreamSegment * left,StreamSegment ** retSeg)6620 static int AddStreamNode(StreamTracker *st, Packet *p,
6621         TcpDataBlock* tdb,
6622         TcpSession *tcpssn,
6623         uint16_t len,
6624         uint32_t slide,
6625         uint32_t trunc,
6626         uint32_t seq,
6627         StreamSegment *left,
6628         StreamSegment **retSeg)
6629 {
6630     StreamSegment *ss = NULL;
6631     uint16_t reassembly_policy;
6632     int32_t newSize = len - slide - trunc;
6633     reassembly_policy = st->reassembly_policy;
6634 
6635     if(st->s_mgr.state_queue == TCP_STATE_CLOSE_WAIT)
6636     {
6637         //If FIN is already queued, when adding a segment, take target-based approach
6638         switch(reassembly_policy)
6639         {
6640             case REASSEMBLY_POLICY_LAST:
6641                 st->s_mgr.state_queue = TCP_STATE_NONE;
6642                 break;
6643             case REASSEMBLY_POLICY_FIRST:
6644             default:
6645                 if(SEQ_GT(seq + newSize, st->s_mgr.transition_seq - 1))
6646                 {
6647                     uint32_t delta = seq + newSize - (st->s_mgr.transition_seq - 1);
6648                     newSize = newSize - delta;
6649                 }
6650                 break;
6651         }
6652     }
6653 
6654     if (newSize <= 0)
6655     {
6656         /*
6657          * zero size data because of trimming.  Don't
6658          * insert it
6659          */
6660         STREAM_DEBUG_WRAP(DebugMessage(DEBUG_STREAM_STATE,
6661                     "zero size TCP data after left & right trimming "
6662                     "(len: %d slide: %d trunc: %d)\n",
6663                     len, slide, trunc););
6664         Discard();
6665         NormalTrimPayloadIfWin(p, 0, tdb);
6666 
6667 #ifdef STREAM_DEBUG_ENABLED
6668         {
6669             StreamSegment *idx = st->seglist;
6670             unsigned long i = 0;
6671             STREAM_DEBUG_WRAP(DebugMessage(DEBUG_STREAM_STATE,
6672                         "Dumping seglist, %d segments\n", st->seg_count););
6673             while (idx)
6674             {
6675                 i++;
6676                 STREAM_DEBUG_WRAP(DebugMessage(DEBUG_STREAM_STATE,
6677                             "%d  ptr: %p  seq: 0x%X  size: %d nxt: %p prv: %p\n",
6678                             i, idx, idx->seq, idx->size, idx->next, idx->prev););
6679 
6680                 if(st->seg_count < i)
6681                     FatalError("Circular list, WTF?\n");
6682 
6683                 idx = idx->next;
6684             }
6685         }
6686 #endif
6687         return STREAM_INSERT_ANOMALY;
6688     }
6689 
6690     ss = SegmentAlloc(p, &p->pkth->ts, p->pkth->caplen, p->pkth->pktlen, p->pkt);
6691     if (!ss)
6692       return STREAM_INSERT_ANOMALY;
6693 
6694     ss->data = ss->pkt + (p->data - p->pkt);
6695     ss->orig_dsize = p->dsize;
6696 
6697     ss->payload = ss->data + slide;
6698     ss->size = (uint16_t)newSize;
6699     ss->seq = seq;
6700     ss->ts = tdb->ts;
6701 
6702     /* handle the urg ptr */
6703     if(p->tcph->th_flags & TH_URG)
6704     {
6705         if(ntohs(p->tcph->th_urp) < p->dsize)
6706         {
6707             switch(st->os_policy)
6708             {
6709                 case STREAM_POLICY_LINUX:
6710                 case STREAM_POLICY_OLD_LINUX:
6711                     /* Linux, Old linux discard data from urgent pointer */
6712                     /* If urg pointer is 0, it's treated as a 1 */
6713                     ss->urg_offset = ntohs(p->tcph->th_urp);
6714                     if (ss->urg_offset == 0)
6715                     {
6716                         ss->urg_offset = 1;
6717                     }
6718                     break;
6719                 case STREAM_POLICY_FIRST:
6720                 case STREAM_POLICY_NOACK:
6721                 case STREAM_POLICY_LAST:
6722                 case STREAM_POLICY_BSD:
6723                 case STREAM_POLICY_MACOS:
6724                 case STREAM_POLICY_SOLARIS:
6725                 case STREAM_POLICY_WINDOWS:
6726                 case STREAM_POLICY_WINDOWS2K3:
6727                 case STREAM_POLICY_VISTA:
6728                 case STREAM_POLICY_HPUX11:
6729                 case STREAM_POLICY_HPUX10:
6730                 case STREAM_POLICY_IRIX:
6731                     /* Others discard data from urgent pointer */
6732                     /* If urg pointer is beyond this packet, it's treated as a 0 */
6733                     ss->urg_offset = ntohs(p->tcph->th_urp);
6734                     if (ss->urg_offset > p->dsize)
6735                     {
6736                         ss->urg_offset = 0;
6737                     }
6738                     break;
6739             }
6740         }
6741     }
6742 
6743     StreamSeglistAddNode(st, left, ss);
6744     st->seg_bytes_logical += ss->size;
6745     st->seg_bytes_total += ss->caplen;  /* Includes protocol headers and payload */
6746     st->total_segs_queued++;
6747     st->total_bytes_queued += ss->size;
6748 
6749     p->packet_flags |= PKT_STREAM_INSERT;
6750 
6751     STREAM_DEBUG_WRAP(DebugMessage(DEBUG_STREAM_STATE,
6752                 "added %d bytes on segment list @ seq: 0x%X, total %lu, "
6753                 "%d segments queued\n", ss->size, ss->seq,
6754                 st->seg_bytes_logical, SegsToFlush(st, 0)););
6755 
6756     *retSeg = ss;
6757 #ifdef SEG_TEST
6758     CheckSegments(st);
6759 #endif
6760     return STREAM_INSERT_OK;
6761 }
6762 
DupStreamNode(Packet * p,StreamTracker * st,StreamSegment * left,StreamSegment ** retSeg)6763 static int DupStreamNode(Packet *p,
6764         StreamTracker *st,
6765         StreamSegment *left,
6766         StreamSegment **retSeg)
6767 {
6768     StreamSegment* ss = SegmentAlloc(p, &left->tv, left->caplen, left->pktlen, left->pkt);
6769 
6770     if ( !ss )
6771         return STREAM_INSERT_FAILED;
6772 
6773     ss->data = ss->pkt + (left->data - left->pkt);
6774     ss->orig_dsize = left->orig_dsize;
6775 
6776     /* twiddle the values for overlaps */
6777     ss->payload = ss->data;
6778     ss->size = left->size;
6779     ss->seq = left->seq;
6780 
6781     StreamSeglistAddNode(st, left, ss);
6782     st->seg_bytes_total += ss->caplen;
6783     st->total_segs_queued++;
6784     //st->total_bytes_queued += ss->size;
6785 
6786     STREAM_DEBUG_WRAP(DebugMessage(DEBUG_STREAM_STATE,
6787                 "added %d bytes on segment list @ seq: 0x%X, total %lu, "
6788                 "%d segments queued\n", ss->size, ss->seq,
6789                 st->seg_bytes_logical, SegsToFlush(st, 0)););
6790 
6791     *retSeg = ss;
6792     return STREAM_INSERT_OK;
6793 
6794 }
6795 
IsRetransmit(StreamSegment * seg,const uint8_t * rdata,uint16_t rsize,uint32_t rseq,bool check_frt,bool * full_retransmit)6796 static inline bool IsRetransmit(StreamSegment *seg, const uint8_t *rdata,
6797         uint16_t rsize, uint32_t rseq, bool check_frt, bool *full_retransmit)
6798 {
6799     // If seg->orig_size == seg->size, then it's sequence number wasn't adjusted
6800     // so can just do a straight compare of the sequence numbers.
6801     // Don't want to count as a retransmit if segment's size/sequence number
6802     // has been adjusted.
6803     *full_retransmit = false;
6804     if (SEQ_EQ(seg->seq, rseq) && (seg->orig_dsize == seg->size))
6805     {
6806         if (((seg->size <= rsize) && (memcmp(seg->data, rdata, seg->size) == 0))
6807                 || ((seg->size > rsize) && (memcmp(seg->data, rdata, rsize) == 0)))
6808             return true;
6809     }
6810     //Checking for a possible split of segment in which case
6811     //we compare complete data of the segment to find a retransmission
6812     else if(check_frt && SEQ_EQ(seg->seq, rseq) && seg->orig_dsize == rsize )
6813     {
6814         if(memcmp(seg->data, rdata, rsize) == 0)
6815         {
6816             *full_retransmit = true;
6817             return true;
6818         }
6819     }
6820     return false;
6821 }
6822 
RetransmitProcess(Packet * p,TcpSession * tcpssn)6823 static inline void RetransmitProcess(Packet *p, TcpSession *tcpssn)
6824 {
6825     // Data has already been analyzed so don't bother looking at it again.
6826     DisableDetect( p );
6827 
6828     DEBUG_WRAP(DebugMessage(DEBUG_STREAM, "Allowing retransmitted data "
6829                 "-- not blocked previously\n"););
6830 }
6831 
RetransmitHandle(Packet * p,TcpSession * tcpssn)6832 static inline void RetransmitHandle(Packet *p, TcpSession *tcpssn)
6833 {
6834 
6835     DEBUG_WRAP(DebugMessage(DEBUG_STREAM, "Calling SE_REXMIT Handler\n"););
6836 
6837     if ( tcpssn->scb->handler[SE_REXMIT] )
6838         StreamCallHandler(p, tcpssn->scb->handler[SE_REXMIT]);
6839 }
6840 
EndOfFileHandle(Packet * p,TcpSession * tcpssn)6841 static inline void EndOfFileHandle(Packet *p, TcpSession *tcpssn)
6842 {
6843     DEBUG_WRAP(DebugMessage(DEBUG_STREAM, "Calling SE_EOF Handler\n"););
6844 
6845     if ( tcpssn->scb->handler[SE_EOF] )
6846         StreamCallHandler(p, tcpssn->scb->handler[SE_EOF]);
6847 }
6848 
IsRetransmitOfHeldSegment(Packet * p,TcpDataBlock * tdb,StreamTracker * listener)6849 static inline bool IsRetransmitOfHeldSegment(Packet *p, TcpDataBlock *tdb,
6850       StreamTracker *listener)
6851 {
6852     StreamSegment *held_seg = listener->held_segment;
6853 
6854     if (held_seg == NULL)
6855         return FALSE;
6856 
6857     if (held_seg->seq == tdb->seq)
6858         return TRUE;
6859 
6860     return FALSE;
6861 }
6862 
IsTCPFastOpenPkt(Packet * p)6863 static bool IsTCPFastOpenPkt (Packet *p)
6864 {
6865     uint8_t opt_count = 0;
6866 
6867     while (opt_count < p->tcp_option_count)
6868     {
6869         if (p->tcp_options[opt_count].code == TCPOPT_TFO)
6870         {
6871             return TRUE;
6872         }
6873         opt_count++;
6874     }
6875     return FALSE;
6876 }
6877 
StreamQueue(StreamTracker * st,Packet * p,TcpDataBlock * tdb,TcpSession * tcpssn)6878 static int StreamQueue(StreamTracker *st, Packet *p, TcpDataBlock *tdb,
6879         TcpSession *tcpssn)
6880 {
6881     StreamSegment *ss = NULL;
6882     StreamSegment *left = NULL;
6883     StreamSegment *right = NULL;
6884     StreamSegment *dump_me = NULL;
6885     uint32_t seq = tdb->seq;
6886     uint32_t seq_end = tdb->end_seq;
6887     uint16_t len = p->dsize;
6888     int trunc = 0;
6889     int overlap = 0;
6890     int slide = 0;
6891     int ret = STREAM_INSERT_OK;
6892     char done = 0;
6893     char addthis = 1;
6894     int32_t dist_head;
6895     int32_t dist_tail;
6896     uint16_t reassembly_policy;
6897 #ifdef NORMALIZER
6898     NormMode ips_data;
6899 #endif
6900     // To check for retransmitted data
6901     const uint8_t *rdata = p->data;
6902     uint16_t rsize = p->dsize;
6903     uint32_t rseq = tdb->seq;
6904     PROFILE_VARS;
6905     STREAM_DEBUG_WRAP(
6906             StreamSegment *lastptr = NULL;
6907             uint32_t base_seq = st->seglist_base_seq;
6908             int last = 0;
6909             );
6910 
6911 #ifdef NORMALIZER
6912     ips_data = Stream_NormGetMode(st->reassembly_policy, snort_conf, NORM_TCP_IPS);
6913     if ( ips_data == NORM_MODE_ON )
6914         reassembly_policy = REASSEMBLY_POLICY_FIRST;
6915     else
6916 #endif
6917         reassembly_policy = st->reassembly_policy;
6918 
6919     STREAM_DEBUG_WRAP(DebugMessage(DEBUG_STREAM_STATE,
6920                 "Queuing %d bytes on stream!\n"
6921                 "base_seq: %X seq: %X  seq_end: %X\n",
6922                 seq_end - seq, base_seq, seq, seq_end););
6923 
6924     STREAM_DEBUG_WRAP(DebugMessage(DEBUG_STREAM_STATE,
6925                 "%d segments on seglist\n", SegsToFlush(st, 0)););
6926     STREAM_DEBUG_WRAP(DebugMessage(DEBUG_STREAM_STATE,
6927                 "!+!+!+!+!+!+!+!+!+!+!+!+!+!+!+!+!+!+!+!+!+!+!+!+!+!+!+\n"););
6928     STREAM_DEBUG_WRAP(DebugMessage(DEBUG_STREAM_STATE,
6929                 "!+!+!+!+!+!+!+!+!+!+!+!+!+!+!+!+!+!+!+!+!+!+!+!+!+!+!+\n"););
6930 
6931     PREPROC_PROFILE_START(s5TcpInsertPerfStats);
6932 
6933     /* Check if we should not insert a large packet */
6934     if (IgnoreLargePkt(st, p, tdb))
6935     {
6936         // NORM should ignore large pkt be disabled for stream normalization?
6937         // if not, how to normalize ignored large packets?
6938         return ret;
6939     }
6940 
6941     // NORM fast tracks are in sequence - no norms
6942     if(st->seglist_tail && SegmentFastTrack(st->seglist_tail, tdb))
6943     {
6944         /* segment fit cleanly at the end of the segment list */
6945         left = st->seglist_tail;
6946         right = NULL;
6947 
6948         STREAM_DEBUG_WRAP(DebugMessage(DEBUG_STREAM_STATE,
6949                     "Fast tracking segment! (tail_seq %X size %d)\n",
6950                     st->seglist_tail->seq, st->seglist_tail->size););
6951 
6952         ret = AddStreamNode(st, p, tdb, tcpssn, len,
6953                 slide /* 0 */, trunc /* 0 */, seq, left /* tail */,
6954                 &ss);
6955 
6956         PREPROC_PROFILE_END(s5TcpInsertPerfStats);
6957         return ret;
6958     }
6959 
6960     if (st->seglist && st->seglist_tail)
6961     {
6962         if (SEQ_GT(tdb->seq, st->seglist->seq))
6963         {
6964             dist_head = tdb->seq - st->seglist->seq;
6965         }
6966         else
6967         {
6968             dist_head = st->seglist->seq - tdb->seq;
6969         }
6970 
6971         if (SEQ_GT(tdb->seq, st->seglist_tail->seq))
6972         {
6973             dist_tail = tdb->seq - st->seglist_tail->seq;
6974         }
6975         else
6976         {
6977             dist_tail = st->seglist_tail->seq - tdb->seq;
6978         }
6979     }
6980     else
6981     {
6982         dist_head = dist_tail = 0;
6983     }
6984 
6985     if (SEQ_LEQ(dist_head, dist_tail))
6986     {
6987         /* Start iterating at the head (left) */
6988         for(ss = st->seglist; ss; ss = ss->next)
6989         {
6990             STREAM_DEBUG_WRAP(
6991                     DebugMessage(DEBUG_STREAM_STATE,
6992                         "ss: %p  seq: 0x%X  size: %lu delta: %d\n",
6993                         ss, ss->seq, ss->size, (ss->seq-base_seq) - last);
6994                     last = ss->seq-base_seq;
6995                     lastptr = ss;
6996 
6997                     DebugMessage(DEBUG_STREAM_STATE,
6998                         "   lastptr: %p ss->next: %p ss->prev: %p\n",
6999                         lastptr, ss->next, ss->prev);
7000                     );
7001 
7002             right = ss;
7003 
7004             if(SEQ_GEQ(right->seq, seq))
7005                 break;
7006 
7007             left = right;
7008         }
7009 
7010         if(ss == NULL)
7011             right = NULL;
7012     }
7013     else
7014     {
7015         /* Start iterating at the tail (right) */
7016         for(ss = st->seglist_tail; ss; ss = ss->prev)
7017         {
7018             STREAM_DEBUG_WRAP(
7019                     DebugMessage(DEBUG_STREAM_STATE,
7020                         "ss: %p  seq: 0x%X  size: %lu delta: %d\n",
7021                         ss, ss->seq, ss->size, (ss->seq-base_seq) - last);
7022                     last = ss->seq-base_seq;
7023                     lastptr = ss;
7024 
7025                     DebugMessage(DEBUG_STREAM_STATE,
7026                         "   lastptr: %p ss->next: %p ss->prev: %p\n",
7027                         lastptr, ss->next, ss->prev);
7028                     );
7029 
7030             left = ss;
7031 
7032             if(SEQ_LT(left->seq, seq))
7033                 break;
7034 
7035             right = left;
7036         }
7037 
7038         if(ss == NULL)
7039             left = NULL;
7040     }
7041 
7042     STREAM_DEBUG_WRAP(DebugMessage(DEBUG_STREAM_STATE,
7043                 "!+!+!+!+!+!+!+!+!+!+!+!+!+!+!+!+!+!+!+!+!+!+!+!+!+!+!+\n"););
7044     STREAM_DEBUG_WRAP(DebugMessage(DEBUG_STREAM_STATE,
7045                 "!+!+!+!+!+!+!+!+!+!+!+!+!+!+!+!+!+!+!+!+!+!+!+!+!+!+!+\n"););
7046 
7047     STREAM_DEBUG_WRAP(DebugMessage(DEBUG_STREAM_STATE,
7048                 "left: %p:0x%X  right: %p:0x%X\n", left,
7049                 left?left->seq:0, right, right?right->seq:0););
7050 
7051     /*
7052      * handle left overlaps
7053      */
7054     if(left)
7055     {
7056         // NOTE that left->seq is always less than seq, otherwise it would
7057         // be a right based on the above determination of left and right
7058 
7059         /* check if the new segment overlaps on the left side */
7060         overlap = left->seq + left->size - seq;
7061 
7062         STREAM_DEBUG_WRAP(DebugMessage(DEBUG_STREAM_STATE,
7063                     "left overlap %d\n", overlap););
7064 
7065         if(overlap > 0)
7066         {
7067             // NOTE that overlap will always be less than left->size since
7068             // seq is always greater than left->seq
7069             s5stats.tcp_overlaps++;
7070             st->overlap_count++;
7071 
7072             switch(reassembly_policy)
7073             {
7074                 case REASSEMBLY_POLICY_FIRST:
7075                 case REASSEMBLY_POLICY_NOACK:
7076                 case REASSEMBLY_POLICY_LINUX:
7077                 case REASSEMBLY_POLICY_BSD:
7078                 case REASSEMBLY_POLICY_WINDOWS:
7079                 case REASSEMBLY_POLICY_WINDOWS2K3:
7080                 case REASSEMBLY_POLICY_VISTA:
7081                 case REASSEMBLY_POLICY_HPUX10:
7082                 case REASSEMBLY_POLICY_IRIX:
7083                 case REASSEMBLY_POLICY_OLD_LINUX:
7084                 case REASSEMBLY_POLICY_MACOS:
7085                     STREAM_DEBUG_WRAP(DebugMessage(DEBUG_STREAM_STATE,
7086                                 "left overlap, honoring old data\n"););
7087 #ifdef NORMALIZER
7088                     if ( ips_data != NORM_MODE_OFF )
7089                     {
7090                         if (SEQ_LT(left->seq,tdb->seq) && SEQ_GT(left->seq + left->size, tdb->seq + p->dsize))
7091                         {
7092                             if ( ips_data == NORM_MODE_ON )
7093                             {
7094                                 unsigned offset = tdb->seq - left->seq;
7095                                 memcpy((uint8_t*)p->data, left->payload+offset, p->dsize);
7096                                 p->packet_flags |= PKT_MODIFIED;
7097                             }
7098                             normStats[PC_TCP_IPS_DATA][ips_data]++;
7099                             sfBase.iPegs[PERF_COUNT_TCP_IPS_DATA][ips_data]++;
7100                         }
7101                         else if (SEQ_LT(left->seq, tdb->seq))
7102                         {
7103                             if ( ips_data == NORM_MODE_ON )
7104                             {
7105                                 unsigned offset = tdb->seq - left->seq;
7106                                 unsigned length = left->seq + left->size - tdb->seq;
7107                                 memcpy((uint8_t*)p->data, left->payload+offset, length);
7108                                 p->packet_flags |= PKT_MODIFIED;
7109                             }
7110                             normStats[PC_TCP_IPS_DATA][ips_data]++;
7111                             sfBase.iPegs[PERF_COUNT_TCP_IPS_DATA][ips_data]++;
7112                         }
7113                     }
7114 #endif
7115                     seq += overlap;
7116                     slide = overlap;
7117                     if(SEQ_LEQ(seq_end, seq))
7118                     {
7119                         /*
7120                          * houston, we have a problem
7121                          */
7122                         /* flag an anomaly */
7123                         EventBadSegment(st->tcp_policy);
7124                         Discard();
7125                         PREPROC_PROFILE_END(s5TcpInsertPerfStats);
7126                         return STREAM_INSERT_ANOMALY;
7127                     }
7128                     break;
7129 
7130                 case REASSEMBLY_POLICY_SOLARIS:
7131                 case REASSEMBLY_POLICY_HPUX11:
7132                     if (SEQ_LT(left->seq, seq) && SEQ_GEQ(left->seq + left->size, seq + len))
7133                     {
7134                         /* New packet is entirely overlapped by an
7135                          * existing packet on both sides.  Drop the
7136                          * new data. */
7137                         STREAM_DEBUG_WRAP(DebugMessage(DEBUG_STREAM_STATE,
7138                                     "left overlap, honoring old data\n"););
7139                         seq += overlap;
7140                         slide = overlap;
7141                         if(SEQ_LEQ(seq_end, seq))
7142                         {
7143                             /*
7144                              * houston, we have a problem
7145                              */
7146                             /* flag an anomaly */
7147                             EventBadSegment(st->tcp_policy);
7148                             Discard();
7149                             PREPROC_PROFILE_END(s5TcpInsertPerfStats);
7150                             return STREAM_INSERT_ANOMALY;
7151                         }
7152                     }
7153 
7154                     /* Otherwise, trim the old data accordingly */
7155                     left->size -= (int16_t)overlap;
7156                     st->seg_bytes_logical -= overlap;
7157                     STREAM_DEBUG_WRAP(DebugMessage(DEBUG_STREAM_STATE,
7158                                 "left overlap, honoring new data\n"););
7159                     break;
7160                 case REASSEMBLY_POLICY_LAST:
7161                     /* True "Last" policy" */
7162                     if (SEQ_LT(left->seq, seq) && SEQ_GT(left->seq + left->size, seq + len))
7163                     {
7164                         /* New data is overlapped on both sides by
7165                          * existing data.  Existing data needs to be
7166                          * split and the new data inserted in the
7167                          * middle.
7168                          *
7169                          * Need to duplicate left.  Adjust that
7170                          * seq by + (seq + len) and
7171                          * size by - (seq + len - left->seq).
7172                          */
7173                         ret = DupStreamNode(p, st, left, &right);
7174                         if (ret != STREAM_INSERT_OK)
7175                         {
7176                             /* No warning,
7177                              * its done in StreamSeglistAddNode */
7178                             PREPROC_PROFILE_END(s5TcpInsertPerfStats);
7179                             return ret;
7180                         }
7181                         left->size -= (int16_t)overlap;
7182                         st->seg_bytes_logical -= overlap;
7183 
7184                         right->seq = seq + len;
7185                         right->size -= (int16_t)(seq + len - left->seq);
7186                         right->payload += (seq + len - left->seq);
7187                         st->seg_bytes_logical -= (seq + len - left->seq);
7188                     }
7189                     else
7190                     {
7191                         left->size -= (int16_t)overlap;
7192                         st->seg_bytes_logical -= overlap;
7193                     }
7194 
7195                     STREAM_DEBUG_WRAP(DebugMessage(DEBUG_STREAM_STATE,
7196                                 "left overlap, honoring new data\n"););
7197                     break;
7198             }
7199 
7200             if(SEQ_LEQ(seq_end, seq))
7201             {
7202                 STREAM_DEBUG_WRAP(DebugMessage(DEBUG_STREAM_STATE,
7203                             "seq_end < seq"););
7204                 /*
7205                  * houston, we have a problem
7206                  */
7207                 /* flag an anomaly */
7208                 EventBadSegment(st->tcp_policy);
7209                 Discard();
7210                 PREPROC_PROFILE_END(s5TcpInsertPerfStats);
7211                 return STREAM_INSERT_ANOMALY;
7212             }
7213         }
7214         else
7215         {
7216             STREAM_DEBUG_WRAP(DebugMessage(DEBUG_STREAM_STATE,
7217                         "No left overlap\n"););
7218         }
7219     }
7220 
7221     //(seq_end > right->seq) && (seq_end <= (right->seq+right->size))))
7222     while(right && !done && SEQ_LT(right->seq, seq_end))
7223     {
7224         bool full_retransmit = false;
7225         trunc = 0;
7226         overlap = (int)(seq_end - right->seq);
7227         //overlap = right->size - (right->seq - seq);
7228         //right->seq + right->size - seq_end;
7229 
7230         STREAM_DEBUG_WRAP(DebugMessage(DEBUG_STREAM_STATE,
7231                     "right overlap(%d): len: %d right->seq: 0x%X seq: 0x%X\n",
7232                     overlap, len, right->seq, seq););
7233         /* Treat sequence number overlap as a retransmission
7234          * Only check right side since left side happens rarely
7235          */
7236         if((st->flush_mgr.flush_policy == STREAM_FLPOLICY_FOOTPRINT_IPS_FTP) && (overlap == right->size) && right->next && (right->next->size > 0))
7237         {
7238             STREAM_DEBUG_WRAP(DebugMessage(DEBUG_STREAM_STATE,
7239                         "ftp-data daq retry or rexmit, do not call RetransmitHandle as \
7240                         data beyond this packet is already received\n"););
7241         }
7242         else
7243         {
7244             RetransmitHandle(p, tcpssn);
7245         }
7246 
7247         if(overlap < right->size)
7248         {
7249             if (IsRetransmit(right, rdata, rsize, rseq, false, &full_retransmit))
7250             {
7251 #ifdef DAQ_PKT_FLAG_RETRY_PACKET
7252 		 /* If packet is identified as re-transmitted
7253 		  * and it is set as retry already then block the packet  */
7254 		if (!(p->pkth->flags & DAQ_PKT_FLAG_RETRY_PACKET))
7255 			p->packet_flags |= PKT_RETRANSMIT;
7256 #endif
7257                 // All data was retransmitted
7258                 if (IsRetransmitOfHeldSegment(p, tdb, st))
7259                 {
7260                     st->held_segment = NULL;
7261                     p->packet_flags |= PKT_PSEUDO_FLUSH;
7262                 }
7263                 else
7264                 {
7265                     RetransmitProcess(p, tcpssn);
7266                 }
7267                 addthis = 0;
7268                 break;
7269             }
7270             s5stats.tcp_overlaps++;
7271             st->overlap_count++;
7272 
7273             STREAM_DEBUG_WRAP(DebugMessage(DEBUG_STREAM_STATE,
7274                         "Got partial right overlap\n"););
7275 
7276             switch(reassembly_policy)
7277             {
7278                 /* truncate existing data */
7279                 case REASSEMBLY_POLICY_LAST:
7280                 case REASSEMBLY_POLICY_LINUX:
7281                 case REASSEMBLY_POLICY_OLD_LINUX:
7282                 case REASSEMBLY_POLICY_BSD:
7283                 case REASSEMBLY_POLICY_WINDOWS:
7284                 case REASSEMBLY_POLICY_WINDOWS2K3:
7285                 case REASSEMBLY_POLICY_IRIX:
7286                 case REASSEMBLY_POLICY_HPUX10:
7287                 case REASSEMBLY_POLICY_MACOS:
7288                     if (SEQ_EQ(right->seq, seq) &&
7289                             (reassembly_policy != REASSEMBLY_POLICY_LAST))
7290                     {
7291                         slide = (right->seq + right->size - seq);
7292                         seq += slide;
7293                     }
7294                     else
7295                     {
7296                         /* partial overlap */
7297                         right->seq += overlap;
7298                         right->payload += overlap;
7299                         right->size -= (int16_t)overlap;
7300                         st->seg_bytes_logical -= overlap;
7301                         st->total_bytes_queued -= overlap;
7302                     }
7303 
7304                     // right->size always > 0 since overlap < right->size
7305 
7306                     break;
7307 
7308                 case REASSEMBLY_POLICY_FIRST:
7309                 case REASSEMBLY_POLICY_VISTA:
7310                 case REASSEMBLY_POLICY_SOLARIS:
7311                 case REASSEMBLY_POLICY_HPUX11:
7312 #ifdef NORMALIZER
7313                     if ( ips_data == NORM_MODE_ON )
7314                     {
7315                         unsigned offset = right->seq - tdb->seq;
7316                         unsigned length = tdb->seq + p->dsize - right->seq;
7317                         memcpy((uint8_t*)p->data+offset, right->payload, length);
7318                         p->packet_flags |= PKT_MODIFIED;
7319                     }
7320                     if ( ips_data != NORM_MODE_OFF )
7321                     {
7322                         normStats[PC_TCP_IPS_DATA][ips_data]++;
7323                         sfBase.iPegs[PERF_COUNT_TCP_IPS_DATA][ips_data]++;
7324                     }
7325 #endif
7326                     trunc = overlap;
7327                     break;
7328 
7329                 case REASSEMBLY_POLICY_NOACK:
7330                     // Don't normalize
7331                     trunc = overlap;
7332                     break;
7333             }
7334 
7335             /* all done, keep me out of the loop */
7336             done = 1;
7337         }
7338         else  // Full overlap
7339         {
7340             // Don't want to count retransmits as overlaps or do anything
7341             // else with them.  Account for retransmits of multiple PDUs
7342             // in one segment.
7343             if (IsRetransmit(right, rdata, rsize, rseq, (rseq == tdb->seq), &full_retransmit))
7344             {
7345                 if( !full_retransmit )
7346                 {
7347                     rdata += right->size;
7348                     rsize -= right->size;
7349                     rseq += right->size;
7350 
7351                     seq += right->size;
7352                     left = right;
7353                     right = right->next;
7354                 }
7355                 else
7356                 {
7357                     rsize = 0;
7358                     done = 1;
7359                 }
7360 
7361                 if (rsize == 0)
7362                 {
7363 #ifdef DAQ_PKT_FLAG_RETRY_PACKET
7364                 /* If packet is identified as re-transmitted
7365 		 * and it is set as retry already then block the packet  */
7366 		    if (!(p->pkth->flags & DAQ_PKT_FLAG_RETRY_PACKET))
7367 			    p->packet_flags |= PKT_RETRANSMIT;
7368 #endif
7369                     // All data was retransmitted
7370                     if (IsRetransmitOfHeldSegment(p, tdb, st))
7371                     {
7372                         st->held_segment = NULL;
7373                         p->packet_flags |= PKT_PSEUDO_FLUSH;
7374                     }
7375                     else
7376                     {
7377                         RetransmitProcess(p, tcpssn);
7378                     }
7379 
7380                     addthis = 0;
7381                 }
7382                 continue;
7383             }
7384 
7385             STREAM_DEBUG_WRAP(DebugMessage(DEBUG_STREAM_STATE,
7386                         "Got full right overlap\n"););
7387 
7388             s5stats.tcp_overlaps++;
7389             st->overlap_count++;
7390 
7391             switch(reassembly_policy)
7392             {
7393                 case REASSEMBLY_POLICY_BSD:
7394                 case REASSEMBLY_POLICY_LINUX:
7395                 case REASSEMBLY_POLICY_WINDOWS:
7396                 case REASSEMBLY_POLICY_WINDOWS2K3:
7397                 case REASSEMBLY_POLICY_HPUX10:
7398                 case REASSEMBLY_POLICY_IRIX:
7399                 case REASSEMBLY_POLICY_MACOS:
7400                     if (SEQ_GEQ(seq_end, right->seq + right->size) &&
7401                             SEQ_LT(seq, right->seq))
7402                     {
7403                         dump_me = right;
7404 
7405                         STREAM_DEBUG_WRAP(DebugMessage(DEBUG_STREAM_STATE,
7406                                     "retrans, dropping old data at seq %d, size %d\n",
7407                                     right->seq, right->size););
7408                         right = right->next;
7409                         StreamSeglistDeleteNode(st, dump_me);
7410                         if (left == dump_me)
7411                             left = NULL;
7412                         break;
7413                     }
7414                     else
7415                     {
7416                         switch (reassembly_policy)
7417                         {
7418                             case REASSEMBLY_POLICY_WINDOWS:
7419                             case REASSEMBLY_POLICY_WINDOWS2K3:
7420                             case REASSEMBLY_POLICY_BSD:
7421                             case REASSEMBLY_POLICY_MACOS:
7422                                 /* BSD/MacOS & Windows follow a FIRST policy in the
7423                                  * case below... */
7424                                 break;
7425                             default:
7426                                 /* All others follow a LAST policy */
7427                                 if (SEQ_GT(seq_end, right->seq + right->size) &&
7428                                         SEQ_EQ(seq, right->seq))
7429                                 {
7430                                     /* When existing data is fully overlapped by new
7431                                      * and sequence numbers are the same, most OSs
7432                                      * follow a LAST policy.
7433                                      */
7434                                     goto right_overlap_last;
7435                                 }
7436                                 break;
7437                         }
7438                     }
7439                     /* Fall through */
7440                 case REASSEMBLY_POLICY_FIRST:
7441                 case REASSEMBLY_POLICY_VISTA:
7442                     STREAM_DEBUG_WRAP(DebugMessage(DEBUG_STREAM_STATE,
7443                                 "Got full right overlap, truncating new\n"););
7444 #ifdef NORMALIZER
7445                     if ( ips_data == NORM_MODE_ON )
7446                     {
7447                         unsigned offset = right->seq - tdb->seq;
7448                         memcpy((uint8_t*)p->data+offset, right->payload, right->size);
7449                         p->packet_flags |= PKT_MODIFIED;
7450                     }
7451                     if ( ips_data != NORM_MODE_OFF )
7452                     {
7453                         normStats[PC_TCP_IPS_DATA][ips_data]++;
7454                         sfBase.iPegs[PERF_COUNT_TCP_IPS_DATA][ips_data]++;
7455                     }
7456 #endif
7457                     if (SEQ_EQ(right->seq, seq))
7458                     {
7459                         /* Overlap is greater than or equal to right->size
7460                          * slide gets set before insertion */
7461                         seq += right->size;
7462                         left = right;
7463                         right = right->next;
7464 
7465                         /* Adjusted seq is fully overlapped */
7466                         if (SEQ_EQ(seq, seq_end))
7467                         {
7468                             STREAM_DEBUG_WRAP(DebugMessage(DEBUG_STREAM_STATE,
7469                                         "StreamQueue got full right overlap with "
7470                                         "resulting seq too high, bad segment "
7471                                         "(seq: %X  seq_end: %X overlap: %lu\n",
7472                                         seq, seq_end, overlap););
7473                             EventBadSegment(st->tcp_policy);
7474                             Discard();
7475                             PREPROC_PROFILE_END(s5TcpInsertPerfStats);
7476                             return STREAM_INSERT_ANOMALY;
7477                         }
7478 
7479                         /* No data to add on the left of right, so continue
7480                          * since some of the other non-first targets may have
7481                          * fallen into this case */
7482                         continue;
7483                     }
7484 
7485                     /* seq is less than right->seq */
7486 
7487                     /* trunc is reset to 0 at beginning of loop */
7488                     trunc = overlap;
7489 
7490                     /* insert this one, and see if we need to chunk it up */
7491                     /* Adjust slide so that is correct relative to orig seq */
7492                     slide = seq - tdb->seq;
7493                     ret = AddStreamNode(st, p, tdb, tcpssn, len, slide, trunc, seq, left, &ss);
7494                     if (ret != STREAM_INSERT_OK)
7495                     {
7496                         /* no warning, already done above */
7497                         PREPROC_PROFILE_END(s5TcpInsertPerfStats);
7498                         return ret;
7499                     }
7500 
7501                     /* Set seq to end of right since overlap was greater than
7502                      * or equal to right->size and inserted seq has been
7503                      * truncated to beginning of right
7504                      * And reset trunc to 0 since we may fall out of loop if
7505                      * next right is NULL */
7506                     seq = right->seq + right->size;
7507                     left = right;
7508                     right = right->next;
7509                     trunc = 0;
7510 
7511                     /* Keep looping since in IPS we may need to copy old
7512                      * data into packet */
7513 
7514                     break;
7515 
7516                 case REASSEMBLY_POLICY_NOACK:
7517                     STREAM_DEBUG_WRAP(DebugMessage(DEBUG_STREAM_STATE,
7518                                 "Got full right overlap, truncating new\n"););
7519                     if (SEQ_EQ(right->seq, seq))
7520                     {
7521                         /* Overlap is greater than or equal to right->size
7522                          * slide gets set before insertion */
7523                         seq += right->size;
7524                         left = right;
7525                         right = right->next;
7526 
7527                         /* Adjusted seq is fully overlapped */
7528                         if (SEQ_EQ(seq, seq_end))
7529                         {
7530                             STREAM_DEBUG_WRAP(DebugMessage(DEBUG_STREAM_STATE,
7531                                         "StreamQueue got full right overlap with "
7532                                         "resulting seq too high, bad segment "
7533                                         "(seq: %X  seq_end: %X overlap: %lu\n",
7534                                         seq, seq_end, overlap););
7535                             EventBadSegment(st->tcp_policy);
7536                             s5stats.tcp_discards++;
7537                             PREPROC_PROFILE_END(s5TcpInsertPerfStats);
7538                             return STREAM_INSERT_ANOMALY;
7539                         }
7540 
7541                         /* No data to add on the left of right, so continue
7542                          * since some of the other non-first targets may have
7543                          * fallen into this case */
7544                         continue;
7545                     }
7546 
7547                     /* seq is less than right->seq */
7548 
7549                     /* trunc is reset to 0 at beginning of loop */
7550                     trunc = overlap;
7551 
7552                     /* insert this one, and see if we need to chunk it up */
7553                     /* Adjust slide so that is correct relative to orig seq */
7554                     slide = seq - tdb->seq;
7555                     ret = AddStreamNode(st, p, tdb, tcpssn, len, slide, trunc, seq, left, &ss);
7556                     if (ret != STREAM_INSERT_OK)
7557                     {
7558                         /* no warning, already done above */
7559                         PREPROC_PROFILE_END(s5TcpInsertPerfStats);
7560                         return ret;
7561                     }
7562 
7563                     /* Set seq to end of right since overlap was greater than
7564                      * or equal to right->size and inserted seq has been
7565                      * truncated to beginning of right
7566                      * And reset trunc to 0 since we may fall out of loop if
7567                      * next right is NULL */
7568                     seq = right->seq + right->size;
7569                     left = right;
7570                     right = right->next;
7571                     trunc = 0;
7572 
7573                     /* Keep looping since in IPS we may need to copy old
7574                      * data into packet */
7575 
7576                     break;
7577 
7578                 case REASSEMBLY_POLICY_HPUX11:
7579                 case REASSEMBLY_POLICY_SOLARIS:
7580                     /* If this packet is wholly overlapping and the same size
7581                      * as a previous one and we have not received the one
7582                      * immediately preceeding, we take the FIRST. */
7583                     if (SEQ_EQ(right->seq, seq) && (right->size == len) &&
7584                             (left && !SEQ_EQ(left->seq + left->size, seq)))
7585                     {
7586                         trunc += overlap;
7587                         if(SEQ_LEQ((int)(seq_end - trunc), seq))
7588                         {
7589                             STREAM_DEBUG_WRAP(DebugMessage(DEBUG_STREAM_STATE,
7590                                         "StreamQueue got full right overlap with "
7591                                         "resulting seq too high, bad segment "
7592                                         "(seq: %X  seq_end: %X overlap: %lu\n",
7593                                         seq, seq_end, overlap););
7594                             EventBadSegment(st->tcp_policy);
7595                             Discard();
7596                             PREPROC_PROFILE_END(s5TcpInsertPerfStats);
7597                             return STREAM_INSERT_ANOMALY;
7598                         }
7599                         break;
7600                     }
7601                     /* Fall through */
7602                 case REASSEMBLY_POLICY_OLD_LINUX:
7603                 case REASSEMBLY_POLICY_LAST:
7604 right_overlap_last:
7605                     STREAM_DEBUG_WRAP(DebugMessage(DEBUG_STREAM_STATE,
7606                                 "Got full right overlap of old, dropping old\n"););
7607                     dump_me = right;
7608                     right = right->next;
7609                     StreamSeglistDeleteNode(st, dump_me);
7610                     if (left == dump_me)
7611                         left = NULL;
7612                     break;
7613             }
7614         }
7615     }
7616 
7617     if (addthis)
7618     {
7619         /* Adjust slide so that is correct relative to orig seq */
7620         slide = seq - tdb->seq;
7621         ret = AddStreamNode(st, p, tdb, tcpssn, len,
7622                 slide, trunc, seq, left, &ss);
7623     }
7624     else
7625     {
7626         STREAM_DEBUG_WRAP(DebugMessage(DEBUG_STREAM_STATE,
7627                     "Fully truncated right overlap\n"););
7628     }
7629 
7630     STREAM_DEBUG_WRAP(DebugMessage(DEBUG_STREAM_STATE,
7631                 "StreamQueue returning normally\n"););
7632 
7633     PREPROC_PROFILE_END(s5TcpInsertPerfStats);
7634     return ret;
7635 }
7636 
7637 
ProcessTcpStream(StreamTracker * rcv,TcpSession * tcpssn,Packet * p,TcpDataBlock * tdb,StreamTcpPolicy * s5TcpPolicy)7638 static void ProcessTcpStream(StreamTracker *rcv, TcpSession *tcpssn,
7639         Packet *p, TcpDataBlock *tdb,
7640         StreamTcpPolicy *s5TcpPolicy)
7641 {
7642 
7643     STREAM_DEBUG_WRAP(DebugMessage(DEBUG_STREAM_STATE,
7644                 "In ProcessTcpStream(), %d bytes to queue\n", p->dsize););
7645 
7646     if ( p->packet_flags & PKT_IGNORE )
7647         return;
7648 
7649 #ifdef HAVE_DAQ_ADDRESS_SPACE_ID
7650     SetPacketHeaderFoo(tcpssn, p);
7651 #endif
7652 
7653     if ((s5TcpPolicy->flags & STREAM_CONFIG_NO_ASYNC_REASSEMBLY) &&
7654             !TwoWayTraffic(tcpssn->scb))
7655     {
7656         return;
7657     }
7658 
7659     if ((s5TcpPolicy->max_consec_small_segs) &&
7660         /* check ignore_ports */
7661         !(s5TcpPolicy->small_seg_ignore[p->dp/8] & (1 << (p->dp %8))))
7662     {
7663         if (p->dsize >= s5TcpPolicy->max_consec_small_seg_size)
7664         {
7665             rcv->small_seg_count = 0;
7666         }
7667         else
7668         {
7669             if (++rcv->small_seg_count == s5TcpPolicy->max_consec_small_segs)
7670             {
7671                 /* Above threshold, log it... requires detect_anomalies be
7672                  * on in this TCP policy, action controlled by preprocessor
7673                  * rule. */
7674                 EventMaxSmallSegsExceeded(s5TcpPolicy);
7675             }
7676         }
7677     }
7678 
7679     if (s5TcpPolicy->max_queued_bytes &&
7680             (rcv->seg_bytes_total > s5TcpPolicy->max_queued_bytes))
7681     {
7682         if (stream_session_config->prune_log_max && (TwoWayTraffic(tcpssn->scb) || s5TcpPolicy->log_asymmetric_traffic) && !(tcpssn->scb->ha_state.session_flags & SSNFLAG_LOGGED_QUEUE_FULL))
7683         {
7684             char bufc[INET6_ADDRSTRLEN], bufs[INET6_ADDRSTRLEN];
7685             sfip_ntop(&tcpssn->scb->client_ip, bufc, sizeof(bufc));
7686             sfip_ntop(&tcpssn->scb->server_ip, bufs, sizeof(bufs));
7687 
7688             LogMessage("S5: Session exceeded configured max bytes to queue %d "
7689                     "using %d bytes (%s). %s %d --> %s %d "
7690 #ifdef TARGET_BASED
7691                     "(%d) "
7692 #endif
7693                     ": LWstate 0x%x LWFlags 0x%x\n",
7694                     s5TcpPolicy->max_queued_bytes, rcv->seg_bytes_total,
7695                     (rcv == &tcpssn->client) ? "client queue" : "server queue",
7696                     bufc,
7697                     ntohs(tcpssn->scb->client_port),
7698                     bufs,
7699                     ntohs(tcpssn->scb->server_port),
7700 #ifdef TARGET_BASED
7701                     tcpssn->scb->ha_state.application_protocol,
7702 #endif
7703                     tcpssn->scb->session_state,
7704                     tcpssn->scb->ha_state.session_flags);
7705 
7706             /* only log this one per session */
7707             tcpssn->scb->ha_state.session_flags |= SSNFLAG_LOGGED_QUEUE_FULL;
7708         }
7709         STREAM_DEBUG_WRAP(DebugMessage(DEBUG_STREAM_STATE,
7710                     "Ignoring segment due to too many bytes queued\n"););
7711         return;
7712     }
7713 
7714     if (s5TcpPolicy->max_queued_segs &&
7715             (rcv->seg_count+1 > s5TcpPolicy->max_queued_segs))
7716     {
7717         if (stream_session_config->prune_log_max && (TwoWayTraffic(tcpssn->scb) || s5TcpPolicy->log_asymmetric_traffic) && !(tcpssn->scb->ha_state.session_flags & SSNFLAG_LOGGED_QUEUE_FULL))
7718         {
7719             char bufc[INET6_ADDRSTRLEN], bufs[INET6_ADDRSTRLEN];
7720             sfip_ntop(&tcpssn->scb->client_ip, bufc, sizeof(bufc));
7721             sfip_ntop(&tcpssn->scb->server_ip, bufs, sizeof(bufs));
7722 
7723             LogMessage("S5: Session exceeded configured max segs to queue %d "
7724                     "using %d segs (%s). %s %d --> %s %d "
7725 #ifdef TARGET_BASED
7726                     "(%d) "
7727 #endif
7728                     ": LWstate 0x%x LWFlags 0x%x\n",
7729                     s5TcpPolicy->max_queued_segs, rcv->seg_count,
7730                     (rcv == &tcpssn->client) ? "client queue" : "server queue",
7731                     bufc,
7732                     ntohs(tcpssn->scb->client_port),
7733                     bufs,
7734                     ntohs(tcpssn->scb->server_port),
7735 #ifdef TARGET_BASED
7736                     tcpssn->scb->ha_state.application_protocol,
7737 #endif
7738                     tcpssn->scb->session_state, tcpssn->scb->ha_state.session_flags);
7739 
7740             /* only log this one per session */
7741             tcpssn->scb->ha_state.session_flags |= SSNFLAG_LOGGED_QUEUE_FULL;
7742         }
7743         STREAM_DEBUG_WRAP(DebugMessage(DEBUG_STREAM_STATE,
7744                     "Ignoring segment due to too many bytes queued\n"););
7745         return;
7746     }
7747 
7748     if(rcv->seg_count != 0)
7749     {
7750         if(rcv->flush_mgr.flush_policy == STREAM_FLPOLICY_IGNORE)
7751         {
7752             STREAM_DEBUG_WRAP(DebugMessage(DEBUG_STREAM_STATE,
7753                         "Ignoring segment due to IGNORE flush_policy\n"););
7754             return;
7755         }
7756         else
7757         {
7758             STREAM_DEBUG_WRAP(DebugMessage(DEBUG_STREAM_STATE,
7759                         "queuing segment\n"););
7760 
7761             if ( SEQ_GT(rcv->r_win_base, tdb->seq) )
7762             {
7763                 uint32_t offset = rcv->r_win_base - tdb->seq;
7764 
7765                 if ( offset < p->dsize )
7766                 {
7767                     tdb->seq += offset;
7768                     p->data += offset;
7769                     p->dsize -= (uint16_t)offset;
7770 
7771                     StreamQueue(rcv, p, tdb, tcpssn);
7772 
7773                     p->dsize += (uint16_t)offset;
7774                     p->data -= offset;
7775                     tdb->seq -= offset;
7776                 }
7777             }
7778             else
7779                 StreamQueue(rcv, p, tdb, tcpssn);
7780 
7781             if ((rcv->tcp_policy->overlap_limit) &&
7782                     (rcv->overlap_count > rcv->tcp_policy->overlap_limit))
7783             {
7784                 STREAM_DEBUG_WRAP(DebugMessage(DEBUG_STREAM_STATE,
7785                             "Reached the overlap limit.  Flush the data "
7786                             "and kill the session if configured\n"););
7787                 if (p->packet_flags & PKT_FROM_CLIENT)
7788                 {
7789                     STREAM_DEBUG_WRAP(DebugMessage(DEBUG_STREAM_STATE,
7790                                 "Flushing data on packet from the client\n"););
7791                     flush_stream(tcpssn, rcv, p,
7792                             GET_SRC_IP(p), GET_DST_IP(p),
7793                             p->tcph->th_sport, p->tcph->th_dport,
7794                             PKT_FROM_CLIENT);
7795 
7796                     flush_stream(tcpssn, &tcpssn->server, p,
7797                             GET_DST_IP(p), GET_SRC_IP(p),
7798                             p->tcph->th_dport, p->tcph->th_sport,
7799                             PKT_FROM_SERVER);
7800                 }
7801                 else
7802                 {
7803                     STREAM_DEBUG_WRAP(DebugMessage(DEBUG_STREAM_STATE,
7804                                 "Flushing data on packet from the server\n"););
7805                     flush_stream(tcpssn, rcv, p,
7806                             GET_SRC_IP(p), GET_DST_IP(p),
7807                             p->tcph->th_sport, p->tcph->th_dport,
7808                             PKT_FROM_SERVER);
7809 
7810                     flush_stream(tcpssn, &tcpssn->client, p,
7811                             GET_DST_IP(p), GET_SRC_IP(p),
7812                             p->tcph->th_dport, p->tcph->th_sport,
7813                             PKT_FROM_CLIENT);
7814                 }
7815                 purge_all(&tcpssn->client);
7816                 purge_all(&tcpssn->server);
7817 
7818                 /* Alert on overlap limit and reset counter */
7819                 EventExcessiveOverlap(rcv->tcp_policy);
7820                 rcv->overlap_count = 0;
7821             }
7822         }
7823     }
7824     else
7825     {
7826         if(rcv->flush_mgr.flush_policy == STREAM_FLPOLICY_IGNORE)
7827         {
7828             STREAM_DEBUG_WRAP(DebugMessage(DEBUG_STREAM_STATE,
7829                         "Ignoring segment due to IGNORE flush_policy\n"););
7830             return;
7831         }
7832         else
7833         {
7834             STREAM_DEBUG_WRAP(DebugMessage(DEBUG_STREAM_STATE,
7835                         "queuing segment\n"););
7836             NewQueue(rcv, p, tdb, tcpssn);
7837         }
7838     }
7839 
7840     return;
7841 }
7842 
ProcessTcpData(Packet * p,StreamTracker * listener,TcpSession * tcpssn,TcpDataBlock * tdb,StreamTcpPolicy * s5TcpPolicy)7843 static int ProcessTcpData(Packet *p, StreamTracker *listener, TcpSession *tcpssn,
7844         TcpDataBlock *tdb, StreamTcpPolicy *s5TcpPolicy)
7845 {
7846     PROFILE_VARS;
7847 
7848     STREAM_DEBUG_WRAP(DebugMessage(DEBUG_STREAM_STATE,
7849                 "In ProcessTcpData()\n"););
7850 
7851     PREPROC_PROFILE_START(s5TcpDataPerfStats);
7852     if (!IsTCPFastOpenPkt(p) && (p->tcph->th_flags & TH_SYN) && (listener->os_policy != STREAM_POLICY_MACOS))
7853     {
7854         STREAM_DEBUG_WRAP(DebugMessage(DEBUG_STREAM_STATE,
7855                     "Bailing, data on SYN, not MAC Policy!\n"););
7856         NormalTrimPayloadIfSyn(p, 0, tdb);
7857         PREPROC_PROFILE_END(s5TcpDataPerfStats);
7858         return STREAM_UNALIGNED;
7859     }
7860 
7861     /* we're aligned, so that's nice anyway */
7862     if((tdb->seq == listener->r_nxt_ack) || (p->tcph->th_flags & TH_SYN))
7863     {
7864         if ( p->tcph->th_flags & TH_SYN )
7865             ++tdb->seq;
7866 
7867         /* check if we're in the window */
7868         if( s5TcpPolicy->policy != STREAM_POLICY_NOACK )
7869         {
7870             if(StreamGetWindow(tcpssn->scb, listener, tdb) == 0)
7871             {
7872                 STREAM_DEBUG_WRAP(DebugMessage(DEBUG_STREAM_STATE,
7873                             "Bailing, we're out of the window!\n"););
7874                 NormalTrimPayloadIfWin(p, 0, tdb);
7875                 PREPROC_PROFILE_END(s5TcpDataPerfStats);
7876                 return STREAM_UNALIGNED;
7877             }
7878         }
7879 
7880         /* move the ack boundry up, this is the only way we'll accept data */
7881         // update r_nxt_ack for IGNORE Flush policy here. Else update in StreamSeglistAddNode
7882         if((listener->s_mgr.state_queue == TCP_STATE_NONE) &&
7883                 (listener->flush_mgr.flush_policy == STREAM_FLPOLICY_IGNORE))
7884             listener->r_nxt_ack = tdb->end_seq;
7885 
7886         //For IPS mode trim packet if it overwrites OOO FIN in state_queue
7887         if((listener->s_mgr.state_queue == TCP_STATE_CLOSE_WAIT) &&
7888                 (Stream_NormGetMode(listener->reassembly_policy, snort_conf, NORM_TCP_IPS) == NORM_MODE_ON))
7889         {
7890             if(SEQ_GT(tdb->end_seq, listener->s_mgr.transition_seq - 1))
7891             {
7892                 uint32_t delta = tdb->end_seq - (listener->s_mgr.transition_seq - 1);
7893                 if (p->dsize > delta)
7894                     NormalTrimPayload(p, delta, tdb);
7895             }
7896         }
7897 
7898         if(p->dsize != 0)
7899         {
7900             if (listener->flags &  TF_MISSING_PKT)
7901                 tcpssn->scb->ha_state.session_flags |= SSNFLAG_STREAM_ORDER_BAD;
7902 
7903             if (tcpssn->scb->ha_state.session_flags & SSNFLAG_STREAM_ORDER_BAD)
7904                 p->packet_flags |= PKT_STREAM_ORDER_BAD;
7905             else
7906                 p->packet_flags |= PKT_STREAM_ORDER_OK;
7907 
7908             ProcessTcpStream(listener, tcpssn, p, tdb, s5TcpPolicy);
7909 
7910             if (SEQ_GT(listener->r_nxt_ack,tdb->end_seq))
7911             {
7912                 tcpssn->scb->ha_state.session_flags |= SSNFLAG_STREAM_ORDER_BAD;
7913             }
7914 
7915             PREPROC_PROFILE_END(s5TcpDataPerfStats);
7916             return STREAM_ALIGNED;
7917         }
7918     }
7919     else
7920     {
7921         /* pkt is out of order, do some target-based shizzle here */
7922 
7923         /* NO, we don't want to simply bail.  Some platforms
7924          * favor unack'd dup data over the original data.
7925          * Let the reassembly policy decide how to handle
7926          * the overlapping data.
7927          *
7928          * See HP, Solaris, et al. for those that favor
7929          * duplicate data over the original in some cases.
7930          */
7931         STREAM_DEBUG_WRAP(DebugMessage(DEBUG_STREAM_STATE,
7932                     "out of order segment (tdb->seq: 0x%X "
7933                     "l->r_nxt_ack: 0x%X!\n", tdb->seq, listener->r_nxt_ack););
7934 
7935         if (listener->s_mgr.state_queue == TCP_STATE_NONE)
7936         {
7937             /* check if we're in the window */
7938             if( s5TcpPolicy->policy != STREAM_POLICY_NOACK )
7939             {
7940                 if(StreamGetWindow(tcpssn->scb, listener, tdb) == 0)
7941                 {
7942                     STREAM_DEBUG_WRAP(DebugMessage(DEBUG_STREAM_STATE,
7943                                 "Bailing, we're out of the window!\n"););
7944                     NormalTrimPayloadIfWin(p, 0, tdb);
7945                     PREPROC_PROFILE_END(s5TcpDataPerfStats);
7946                     return STREAM_UNALIGNED;
7947                 }
7948             }
7949 
7950             if ((listener->s_mgr.state == TCP_STATE_ESTABLISHED) &&
7951                     (listener->flush_mgr.flush_policy == STREAM_FLPOLICY_IGNORE))
7952             {
7953                 if ( SEQ_GT(tdb->end_seq, listener->r_nxt_ack))
7954                 {
7955                     /* set next ack so we are within the window going forward on
7956                      * this side. */
7957                     // FIXTHIS for ips, must move all the way to first hole or right end
7958                     listener->r_nxt_ack = tdb->end_seq;
7959                 }
7960             }
7961         }
7962         //For IPS mode trim packet if it overwrites OOO FIN in state_queue
7963         else if((listener->s_mgr.state_queue == TCP_STATE_CLOSE_WAIT) &&
7964                 (Stream_NormGetMode(listener->reassembly_policy, snort_conf, NORM_TCP_IPS) == NORM_MODE_ON))
7965         {
7966             if(SEQ_GT(tdb->end_seq, listener->s_mgr.transition_seq - 1))
7967             {
7968                 uint32_t delta = tdb->end_seq - (listener->s_mgr.transition_seq - 1);
7969                 if (p->dsize > delta)
7970                     NormalTrimPayload(p, delta, tdb);
7971             }
7972 
7973         }
7974 
7975         if(p->dsize != 0)
7976         {
7977             uint32_t r_nxt_ack_old = listener->r_nxt_ack;
7978             if (SEQ_GT(listener->r_win_base, listener->r_nxt_ack) ||
7979                     (listener->flags & TF_MISSING_PKT))
7980                 tcpssn->scb->ha_state.session_flags |= SSNFLAG_STREAM_ORDER_BAD;
7981 
7982             if (tcpssn->scb->ha_state.session_flags & SSNFLAG_STREAM_ORDER_BAD)
7983                 p->packet_flags |= PKT_STREAM_ORDER_BAD;
7984 
7985             ProcessTcpStream(listener, tcpssn, p, tdb, s5TcpPolicy);
7986 
7987             /* If we have moved the expected seq, overlapped segment, set BAD flag*/
7988             if (SEQ_GT(listener->r_nxt_ack, r_nxt_ack_old))
7989             {
7990                 tcpssn->scb->ha_state.session_flags |= SSNFLAG_STREAM_ORDER_BAD;
7991                 p->packet_flags |= PKT_STREAM_ORDER_BAD;
7992             }
7993         }
7994     }
7995 
7996     PREPROC_PROFILE_END(s5TcpDataPerfStats);
7997     return STREAM_UNALIGNED;
7998 }
7999 
StreamGetPolicy(SessionControlBlock * scb,StreamTcpPolicy * s5TcpPolicy,int direction)8000 uint16_t StreamGetPolicy(SessionControlBlock *scb, StreamTcpPolicy *s5TcpPolicy, int direction)
8001 {
8002 #ifdef TARGET_BASED
8003     uint16_t policy_id;
8004     /* Not caching this host_entry in the frag tracker so we can
8005      * swap the table out after processing this packet if we need
8006      * to.  */
8007     HostAttributeEntry *host_entry = NULL;
8008     int ssn_dir;
8009 
8010     if (!IsAdaptiveConfigured())
8011         return s5TcpPolicy->policy;
8012 
8013     if (direction == FROM_CLIENT)
8014     {
8015         host_entry = SFAT_LookupHostEntryByIP(&scb->server_ip);
8016         ssn_dir = SSN_DIR_FROM_SERVER;
8017     }
8018     else
8019     {
8020         host_entry = SFAT_LookupHostEntryByIP(&scb->client_ip);
8021         ssn_dir = SSN_DIR_FROM_CLIENT;
8022     }
8023     if (host_entry && (isStreamPolicySet(host_entry) == POLICY_SET))
8024     {
8025         policy_id = getStreamPolicy(host_entry);
8026 
8027         if (policy_id != SFAT_UNKNOWN_STREAM_POLICY)
8028         {
8029             STREAM_DEBUG_WRAP(DebugMessage(DEBUG_STREAM_STATE,
8030                         "StreamGetPolicy: Policy Map Entry: %d(%s)\n",
8031                         policy_id, reassembly_policy_names[policy_id]););
8032 
8033             /* Since we've already done the lookup, try to get the
8034              * application protocol id with that host_entry. */
8035             setAppProtocolIdFromHostEntry(scb, host_entry, ssn_dir);
8036             return policy_id;
8037         }
8038     }
8039 #endif
8040 
8041     STREAM_DEBUG_WRAP(DebugMessage(DEBUG_STREAM_STATE,
8042                 "StreamGetPolicy: Using configured default %d(%s)\n",
8043                 s5TcpPolicy->policy, reassembly_policy_names[s5TcpPolicy->policy]););
8044 
8045     return s5TcpPolicy->policy;
8046 }
8047 
SetTcpReassemblyPolicy(StreamTracker * st)8048 void SetTcpReassemblyPolicy(StreamTracker *st)
8049 {
8050     st->reassembly_policy = GetTcpReassemblyPolicy(st->os_policy);
8051 }
8052 
SetOSPolicy(TcpSession * tcpssn)8053 static void SetOSPolicy(TcpSession *tcpssn)
8054 {
8055     if (tcpssn->client.os_policy == 0)
8056     {
8057         tcpssn->client.os_policy = StreamGetPolicy(tcpssn->scb, tcpssn->client.tcp_policy, FROM_SERVER);
8058         SetTcpReassemblyPolicy(&tcpssn->client);
8059     }
8060 
8061     if (tcpssn->server.os_policy == 0)
8062     {
8063         tcpssn->server.os_policy = StreamGetPolicy(tcpssn->scb, tcpssn->server.tcp_policy, FROM_CLIENT);
8064         SetTcpReassemblyPolicy(&tcpssn->server);
8065     }
8066 }
8067 
ValidMacAddress(StreamTracker * talker,StreamTracker * listener,Packet * p)8068 static inline int ValidMacAddress(StreamTracker *talker,
8069         StreamTracker *listener,
8070         Packet *p)
8071 {
8072     int i;
8073     int ret = 0;
8074 
8075     if (p->eh == NULL)
8076         return 0;
8077 
8078     /* Use a for loop and byte comparison, which has proven to be
8079      * faster on pipelined architectures compared to a memcmp (setup
8080      * for memcmp is slow).  Not using a 4 byte and 2 byte long because
8081      * there is no guaranttee of memory alignment (and thus performance
8082      * issues similar to memcmp). */
8083     for (i=0;i<6;i++)
8084     {
8085         if ((talker->mac_addr[i] != p->eh->ether_src[i]))
8086         {
8087             if (p->packet_flags & PKT_FROM_CLIENT)
8088                 ret |= EVENT_SESSION_HIJACK_CLIENT;
8089             else
8090                 ret |= EVENT_SESSION_HIJACK_SERVER;
8091         }
8092 
8093         if (listener->mac_addr[i] != p->eh->ether_dst[i])
8094         {
8095             if (p->packet_flags & PKT_FROM_CLIENT)
8096                 ret |= EVENT_SESSION_HIJACK_SERVER;
8097             else
8098                 ret |= EVENT_SESSION_HIJACK_CLIENT;
8099         }
8100     }
8101     return ret;
8102 }
8103 
CopyMacAddr(Packet * p,TcpSession * tcpssn,int dir)8104 static inline void CopyMacAddr(Packet *p,
8105         TcpSession *tcpssn,
8106         int dir)
8107 {
8108     int i;
8109 
8110     /* Not ethernet based, nothing to do */
8111     if (p->eh == NULL)
8112         return;
8113 
8114     if (dir == FROM_CLIENT)
8115     {
8116         /* Client is SRC */
8117         for (i=0;i<6;i++)
8118         {
8119             tcpssn->client.mac_addr[i] = p->eh->ether_src[i];
8120             tcpssn->server.mac_addr[i] = p->eh->ether_dst[i];
8121         }
8122     }
8123     else
8124     {
8125         /* Server is SRC */
8126         for (i=0;i<6;i++)
8127         {
8128             tcpssn->server.mac_addr[i] = p->eh->ether_src[i];
8129             tcpssn->client.mac_addr[i] = p->eh->ether_dst[i];
8130         }
8131     }
8132 }
8133 
NewTcpSession(Packet * p,SessionControlBlock * scb,TcpDataBlock * tdb,StreamTcpPolicy * dstPolicy)8134 static int NewTcpSession(Packet *p, SessionControlBlock *scb, TcpDataBlock *tdb,
8135                          StreamTcpPolicy *dstPolicy)
8136 {
8137     MemBucket *tmpBucket = NULL;
8138     TcpSession *tmp = NULL;
8139     uint16_t server_port = 0;
8140     PROFILE_VARS;
8141 
8142     PREPROC_PROFILE_START(s5TcpNewSessPerfStats);
8143 
8144     if (TCP_ISFLAGSET(p->tcph, TH_SYN) &&
8145             !TCP_ISFLAGSET(p->tcph, TH_ACK))
8146     {
8147         /******************************************************************
8148          * start new sessions on proper SYN packets
8149          *****************************************************************/
8150         tmpBucket = session_api->alloc_protocol_session( SESSION_PROTO_TCP );
8151         if(!tmpBucket)
8152         {
8153             PREPROC_PROFILE_END(s5TcpNewSessPerfStats);
8154             return -1;
8155         }
8156         tmp = tmpBucket->data;
8157         STREAM_DEBUG_WRAP(DebugMessage(DEBUG_STREAM_STATE,
8158                     "Creating new session tracker on SYN!\n"););
8159 
8160 #ifdef DEBUG
8161         tmp->ssn_time.tv_sec = p->pkth->ts.tv_sec;
8162         tmp->ssn_time.tv_usec = p->pkth->ts.tv_usec;
8163 #endif
8164         scb->ha_state.session_flags |= SSNFLAG_SEEN_CLIENT;
8165 
8166         if((p->tcph->th_flags & (TH_CWR|TH_ECE)) == (TH_CWR|TH_ECE))
8167         {
8168             scb->ha_state.session_flags |= SSNFLAG_ECN_CLIENT_QUERY;
8169         }
8170 
8171         /* setup the stream trackers */
8172         tmp->client.s_mgr.state = TCP_STATE_SYN_SENT;
8173         tmp->client.isn = tdb->seq;
8174         tmp->client.l_unackd = tdb->seq + 1;
8175         tmp->client.l_nxt_seq = tmp->client.l_unackd;
8176 
8177         if ( tdb->seq != tdb->end_seq )
8178             tmp->client.l_nxt_seq += (tdb->end_seq - tdb->seq - 1);
8179 
8180         tmp->client.l_window = tdb->win;
8181         tmp->client.ts_last_pkt = p->pkth->ts.tv_sec;
8182 
8183         tmp->server.seglist_base_seq = tmp->client.l_unackd;
8184         tmp->server.r_nxt_ack = tmp->client.l_unackd;
8185         tmp->server.r_win_base = tdb->seq+1;
8186 
8187         STREAM_DEBUG_WRAP(DebugMessage(DEBUG_STREAM_STATE,
8188                     "seglist_base_seq = %X\n", tmp->server.seglist_base_seq););
8189         tmp->server.s_mgr.state = TCP_STATE_LISTEN;
8190 
8191         tmp->client.flags |= StreamGetTcpTimestamp(p, &tmp->client.ts_last, 0);
8192         if (tmp->client.ts_last == 0)
8193             tmp->client.flags |= TF_TSTAMP_ZERO;
8194         tmp->client.flags |= StreamGetMss(p, &tmp->client.mss);
8195         tmp->client.flags |= StreamGetWscale(p, &tmp->client.wscale);
8196 
8197 
8198         /* Set the StreamTcpPolicy for each direction (pkt from client) */
8199         tmp->client.tcp_policy = StreamPolicyLookup(scb, GET_SRC_IP(p));
8200         tmp->server.tcp_policy = dstPolicy;
8201 
8202         /* Server is destination */
8203         server_port = p->dp;
8204 
8205         CopyMacAddr(p, tmp, FROM_CLIENT);
8206     }
8207     else if (TCP_ISFLAGSET(p->tcph, (TH_SYN|TH_ACK)))
8208     {
8209         /******************************************************************
8210          * start new sessions on SYN/ACK from server
8211          *****************************************************************/
8212         tmpBucket = session_api->alloc_protocol_session( SESSION_PROTO_TCP );
8213         if(!tmpBucket)
8214         {
8215             PREPROC_PROFILE_END(s5TcpNewSessPerfStats);
8216             return -1;
8217         }
8218         tmp = tmpBucket->data;
8219         STREAM_DEBUG_WRAP(DebugMessage(DEBUG_STREAM_STATE,
8220                     "Creating new session tracker on SYN_ACK!\n"););
8221 
8222 #ifdef DEBUG
8223         tmp->ssn_time.tv_sec = p->pkth->ts.tv_sec;
8224         tmp->ssn_time.tv_usec = p->pkth->ts.tv_usec;
8225 #endif
8226         scb->ha_state.session_flags |= SSNFLAG_SEEN_SERVER;
8227 
8228         if((p->tcph->th_flags & (TH_CWR|TH_ECE)) == (TH_CWR|TH_ECE))
8229         {
8230             scb->ha_state.session_flags |= SSNFLAG_ECN_SERVER_REPLY;
8231         }
8232 
8233         /* setup the stream trackers */
8234         tmp->server.s_mgr.state = TCP_STATE_SYN_RCVD;
8235         tmp->server.isn = tdb->seq;
8236         tmp->server.l_unackd = tdb->seq + 1;
8237         tmp->server.l_nxt_seq = tmp->server.l_unackd;
8238         tmp->server.l_window = tdb->win;
8239 
8240         tmp->server.seglist_base_seq = tdb->ack;
8241         tmp->server.r_win_base = tdb->ack;
8242         tmp->server.r_nxt_ack = tdb->ack;
8243         tmp->server.ts_last_pkt = p->pkth->ts.tv_sec;
8244 
8245         tmp->client.seglist_base_seq = tmp->server.l_unackd;
8246         tmp->client.r_nxt_ack = tmp->server.l_unackd;
8247         tmp->client.r_win_base = tdb->seq+1;
8248         tmp->client.l_nxt_seq = tdb->ack;
8249         tmp->client.isn = tdb->ack-1;
8250 
8251         STREAM_DEBUG_WRAP(DebugMessage(DEBUG_STREAM_STATE,
8252                     "seglist_base_seq = %X\n", tmp->client.seglist_base_seq););
8253         tmp->client.s_mgr.state = TCP_STATE_SYN_SENT;
8254 
8255         tmp->server.flags |= StreamGetTcpTimestamp(p, &tmp->server.ts_last, 0);
8256         if (tmp->server.ts_last == 0)
8257             tmp->server.flags |= TF_TSTAMP_ZERO;
8258         tmp->server.flags |= StreamGetMss(p, &tmp->server.mss);
8259         tmp->server.flags |= StreamGetWscale(p, &tmp->server.wscale);
8260 
8261         /* Set the StreamTcpPolicy for each direction (pkt from server) */
8262         tmp->server.tcp_policy = StreamPolicyLookup(scb, GET_SRC_IP(p));
8263         tmp->client.tcp_policy = dstPolicy;
8264         scb->proto_policy = tmp->server.tcp_policy;
8265 
8266         /* Client is destination */
8267         server_port = p->sp;
8268 
8269         CopyMacAddr(p, tmp, FROM_SERVER);
8270     }
8271     else if ((p->tcph->th_flags & TH_ACK) &&
8272             !(p->tcph->th_flags & TH_RST) &&
8273             (scb->session_state & STREAM_STATE_ESTABLISHED))
8274     {
8275         /******************************************************************
8276          * start new sessions on completion of 3-way (ACK only, no data)
8277          *****************************************************************/
8278         tmpBucket = session_api->alloc_protocol_session( SESSION_PROTO_TCP );
8279         if(!tmpBucket)
8280         {
8281             PREPROC_PROFILE_END(s5TcpNewSessPerfStats);
8282             return -1;
8283         }
8284         tmp = tmpBucket->data;
8285         STREAM_DEBUG_WRAP(DebugMessage(DEBUG_STREAM_STATE,
8286                     "Creating new session tracker on ACK!\n"););
8287 
8288 #ifdef DEBUG
8289         tmp->ssn_time.tv_sec = p->pkth->ts.tv_sec;
8290         tmp->ssn_time.tv_usec = p->pkth->ts.tv_usec;
8291 #endif
8292         scb->ha_state.session_flags |= SSNFLAG_SEEN_CLIENT;
8293 
8294         if((p->tcph->th_flags & (TH_CWR|TH_ECE)) == (TH_CWR|TH_ECE))
8295         {
8296             scb->ha_state.session_flags |= SSNFLAG_ECN_CLIENT_QUERY;
8297         }
8298 
8299         /* setup the stream trackers */
8300         tmp->client.s_mgr.state = TCP_STATE_ESTABLISHED;
8301         tmp->client.isn = tdb->seq;
8302         tmp->client.l_unackd = tdb->seq + 1;
8303         tmp->client.l_nxt_seq = tmp->client.l_unackd;
8304         tmp->client.l_window = tdb->win;
8305 
8306         tmp->client.ts_last_pkt = p->pkth->ts.tv_sec;
8307 
8308         tmp->server.seglist_base_seq = tmp->client.l_unackd;
8309         tmp->server.r_nxt_ack = tmp->client.l_unackd;
8310         tmp->server.r_win_base = tdb->seq+1;
8311 
8312         STREAM_DEBUG_WRAP(DebugMessage(DEBUG_STREAM_STATE,
8313                     "seglist_base_seq = %X\n", tmp->server.seglist_base_seq););
8314         tmp->server.s_mgr.state = TCP_STATE_ESTABLISHED;
8315 
8316         tmp->client.flags |= StreamGetTcpTimestamp(p, &tmp->client.ts_last, 0);
8317         if (tmp->client.ts_last == 0)
8318             tmp->client.flags |= TF_TSTAMP_ZERO;
8319         tmp->client.flags |= StreamGetMss(p, &tmp->client.mss);
8320         tmp->client.flags |= StreamGetWscale(p, &tmp->client.wscale);
8321 
8322         /* Set the StreamTcpPolicy for each direction (pkt from client) */
8323         tmp->client.tcp_policy = StreamPolicyLookup(scb, GET_SRC_IP(p));
8324         tmp->server.tcp_policy = dstPolicy;
8325 
8326         /* Server is destination */
8327         server_port = p->dp;
8328 
8329         CopyMacAddr(p, tmp, FROM_CLIENT);
8330     }
8331     else if (p->dsize != 0)
8332     {
8333         /******************************************************************
8334          * start new sessions on data in packet
8335          *****************************************************************/
8336         tmpBucket = session_api->alloc_protocol_session( SESSION_PROTO_TCP );
8337         if(!tmpBucket)
8338         {
8339             PREPROC_PROFILE_END(s5TcpNewSessPerfStats);
8340             return -1;
8341         }
8342         tmp = tmpBucket->data;
8343         STREAM_DEBUG_WRAP(DebugMessage(DEBUG_STREAM_STATE,
8344                     "Creating new session tracker on data packet (ACK|PSH)!\n"););
8345 
8346 #ifdef DEBUG
8347         tmp->ssn_time.tv_sec = p->pkth->ts.tv_sec;
8348         tmp->ssn_time.tv_usec = p->pkth->ts.tv_usec;
8349 #endif
8350 
8351         if (scb->ha_state.direction == FROM_CLIENT)
8352         {
8353             STREAM_DEBUG_WRAP(DebugMessage(DEBUG_STREAM_STATE,
8354                         "Session direction is FROM_CLIENT\n"););
8355 
8356             /* Sender is client (src port is higher) */
8357             scb->ha_state.session_flags |= SSNFLAG_SEEN_CLIENT;
8358 
8359             if((p->tcph->th_flags & (TH_CWR|TH_ECE)) == (TH_CWR|TH_ECE))
8360             {
8361                 scb->ha_state.session_flags |= SSNFLAG_ECN_CLIENT_QUERY;
8362             }
8363 
8364             /* setup the stream trackers */
8365             tmp->client.s_mgr.state = TCP_STATE_ESTABLISHED;
8366             tmp->client.isn = tdb->seq;
8367             tmp->client.l_unackd = tdb->seq;
8368             tmp->client.l_nxt_seq = tmp->client.l_unackd;
8369             tmp->client.l_window = tdb->win;
8370             tmp->client.r_nxt_ack = tdb->ack;
8371             tmp->client.r_win_base = tdb->ack;
8372 
8373             tmp->client.ts_last_pkt = p->pkth->ts.tv_sec;
8374 
8375             tmp->server.seglist_base_seq = tmp->client.l_unackd;
8376             tmp->server.r_nxt_ack = tmp->client.l_unackd;
8377             tmp->server.r_win_base = tdb->seq;
8378             tmp->server.l_window = 0; /* reset later */
8379 
8380             /* Next server packet is what was ACKd */
8381             tmp->server.l_nxt_seq = tdb->ack;
8382             tmp->server.l_unackd = tdb->ack - 1;
8383 
8384             STREAM_DEBUG_WRAP(DebugMessage(DEBUG_STREAM_STATE,
8385                         "seglist_base_seq = %X\n", tmp->server.seglist_base_seq););
8386             tmp->server.s_mgr.state = TCP_STATE_ESTABLISHED;
8387 
8388             tmp->client.flags |= StreamGetTcpTimestamp(p, &tmp->client.ts_last, 0);
8389             if (tmp->client.ts_last == 0)
8390                 tmp->client.flags |= TF_TSTAMP_ZERO;
8391             tmp->client.flags |= StreamGetMss(p, &tmp->client.mss);
8392             tmp->client.flags |= StreamGetWscale(p, &tmp->client.wscale);
8393 
8394             /* Set the StreamTcpPolicy for each direction (pkt from client) */
8395             tmp->client.tcp_policy = StreamPolicyLookup(scb, GET_SRC_IP(p));
8396             tmp->server.tcp_policy = dstPolicy;
8397 
8398             /* Server is destination */
8399             server_port = p->dp;
8400 
8401             CopyMacAddr(p, tmp, FROM_CLIENT);
8402         }
8403         else
8404         {
8405             STREAM_DEBUG_WRAP(DebugMessage(DEBUG_STREAM_STATE,
8406                         "Session direction is FROM_SERVER\n"););
8407 
8408             /* Sender is server (src port is lower) */
8409             scb->ha_state.session_flags |= SSNFLAG_SEEN_SERVER;
8410 
8411             /* setup the stream trackers */
8412             tmp->server.s_mgr.state = TCP_STATE_ESTABLISHED;
8413             tmp->server.isn = tdb->seq;
8414             tmp->server.l_unackd = tdb->seq;
8415             tmp->server.l_nxt_seq = tmp->server.l_unackd;
8416             tmp->server.l_window = tdb->win;
8417 
8418             tmp->server.seglist_base_seq = tdb->ack;
8419             tmp->server.r_win_base = tdb->ack;
8420             tmp->server.r_nxt_ack = tdb->ack;
8421             tmp->server.ts_last_pkt = p->pkth->ts.tv_sec;
8422 
8423             tmp->client.seglist_base_seq = tmp->server.l_unackd;
8424             tmp->client.r_nxt_ack = tmp->server.l_unackd;
8425             tmp->client.r_win_base = tdb->seq;
8426             tmp->client.l_window = 0; /* reset later */
8427             tmp->client.isn = tdb->ack-1;
8428             tmp->client.l_nxt_seq = tdb->ack;
8429 
8430             STREAM_DEBUG_WRAP(DebugMessage(DEBUG_STREAM_STATE,
8431                         "seglist_base_seq = %X\n", tmp->client.seglist_base_seq););
8432             tmp->client.s_mgr.state = TCP_STATE_ESTABLISHED;
8433 
8434             tmp->server.flags |= StreamGetTcpTimestamp(p, &tmp->server.ts_last, 0);
8435             if (tmp->server.ts_last == 0)
8436                 tmp->server.flags |= TF_TSTAMP_ZERO;
8437             tmp->server.flags |= StreamGetMss(p, &tmp->server.mss);
8438             tmp->server.flags |= StreamGetWscale(p, &tmp->server.wscale);
8439 
8440             /* Set the StreamTcpPolicy for each direction (pkt from server) */
8441             tmp->server.tcp_policy = StreamPolicyLookup(scb, GET_SRC_IP(p));
8442             tmp->client.tcp_policy = dstPolicy;
8443             scb->proto_policy = tmp->server.tcp_policy;
8444 
8445             /* Client is destination */
8446             server_port = p->sp;
8447 
8448             CopyMacAddr(p, tmp, FROM_SERVER);
8449         }
8450     }
8451 
8452     if (tmp)
8453     {
8454         STREAM_DEBUG_WRAP(DebugMessage(DEBUG_STREAM_STATE,
8455                     "adding TcpSession to lightweight session\n"););
8456         scb->proto_specific_data = tmpBucket;
8457         scb->protocol = GET_IPH_PROTO(p);
8458         tmp->scb = scb;
8459 
8460         /* New session, previous was marked as reset.  Clear the
8461          * reset flag. */
8462         if (scb->ha_state.session_flags & SSNFLAG_RESET)
8463             scb->ha_state.session_flags &= ~SSNFLAG_RESET;
8464 
8465         SetOSPolicy(tmp);
8466 
8467         if ( (scb->ha_state.session_flags & SSNFLAG_CLIENT_SWAP) &&
8468                 !(scb->ha_state.session_flags & SSNFLAG_CLIENT_SWAPPED) )
8469         {
8470             StreamTracker trk = tmp->client;
8471             sfaddr_t ip = scb->client_ip;
8472             uint16_t port = scb->client_port;
8473 
8474             tmp->client = tmp->server;
8475             tmp->server = trk;
8476 
8477             scb->client_ip = scb->server_ip;
8478             scb->server_ip = ip;
8479 
8480             scb->client_port = scb->server_port;
8481             scb->server_port = port;
8482 
8483             if ( !TwoWayTraffic(scb) )
8484             {
8485                 if ( scb->ha_state.session_flags & SSNFLAG_SEEN_CLIENT )
8486                 {
8487                     scb->ha_state.session_flags ^= SSNFLAG_SEEN_CLIENT;
8488                     scb->ha_state.session_flags |= SSNFLAG_SEEN_SERVER;
8489                 }
8490                 else if ( scb->ha_state.session_flags & SSNFLAG_SEEN_SERVER )
8491                 {
8492                     scb->ha_state.session_flags ^= SSNFLAG_SEEN_SERVER;
8493                     scb->ha_state.session_flags |= SSNFLAG_SEEN_CLIENT;
8494                 }
8495             }
8496             scb->ha_state.session_flags |= SSNFLAG_CLIENT_SWAPPED;
8497         }
8498         /* Set up the flush behaviour, based on the configured info
8499          * for the server and client ports.
8500          */
8501         /* Yes, the server flush manager gets the info from the
8502          * policy's server port's the flush policy from the client
8503          * and visa-versa.
8504          *
8505          * For example, when policy said 'ports client 80', that means
8506          * reassemble packets from the client side (stored in the server's
8507          * flush buffer in the session) destined for port 80.  Port 80 is
8508          * the server port and we're reassembling the client side.
8509          * That should make this almost as clear as opaque mud!
8510          */
8511 #ifdef TARGET_BASED
8512         if (tmp->client.tcp_policy->flush_config_protocol[scb->ha_state.application_protocol].configured == 1)
8513         {
8514             StreamTracker* pst = &tmp->server;
8515             uint8_t flush_policy =
8516                 pst->tcp_policy->flush_config_protocol[scb->ha_state.application_protocol].client.flush_policy;
8517             InitFlushMgrByService(scb, pst, scb->ha_state.application_protocol, true, flush_policy);
8518         }
8519         else
8520 #endif
8521         {
8522             StreamTracker* pst = &tmp->server;
8523             uint8_t flush_policy =
8524                 pst->tcp_policy->flush_config[server_port].client.flush_policy;
8525             InitFlushMgrByPort(scb, pst, server_port, true, flush_policy, false);
8526         }
8527 
8528 #ifdef TARGET_BASED
8529         if (tmp->server.tcp_policy->flush_config_protocol[scb->ha_state.application_protocol].configured == 1)
8530         {
8531             StreamTracker* pst = &tmp->client;
8532             uint8_t flush_policy =
8533                 pst->tcp_policy->flush_config_protocol[scb->ha_state.application_protocol].server.flush_policy;
8534             InitFlushMgrByService(scb, pst, scb->ha_state.application_protocol, false, flush_policy);
8535         }
8536         else
8537 #endif
8538         {
8539             StreamTracker* pst = &tmp->client;
8540             uint8_t flush_policy =
8541                 pst->tcp_policy->flush_config[server_port].server.flush_policy;
8542             InitFlushMgrByPort(scb, pst, server_port, false, flush_policy, false);
8543         }
8544 
8545 
8546 #ifdef STREAM_DEBUG_ENABLED
8547         PrintTcpSession(tmp);
8548 #endif
8549 
8550         session_api->set_expire_timer(p, scb, dstPolicy->session_timeout);
8551 
8552         s5stats.tcp_streamtrackers_created++;
8553 
8554         AddStreamSession(&sfBase, scb->session_state & STREAM_STATE_MIDSTREAM ? SSNFLAG_MIDSTREAM : 0);
8555 
8556         StreamUpdatePerfBaseState(&sfBase, tmp->scb, TCP_STATE_SYN_SENT);
8557 
8558 #ifdef NORMALIZER
8559         tmp->ecn = 0;
8560 #endif
8561         tmp->session_decrypted = false;
8562         PREPROC_PROFILE_END(s5TcpNewSessPerfStats);
8563         return 1;
8564     }
8565 
8566     PREPROC_PROFILE_END(s5TcpNewSessPerfStats);
8567     return 0;
8568 }
8569 
8570 /* set_service_based_flush_policy
8571  *
8572  * Once appid detects the protocol, calling this api
8573  * to set the respective paf apis.
8574  * If paf function pointer already pointed to the
8575  * correct paf api, not going to set again.
8576  */
set_service_based_flush_policy(SessionControlBlock * scb)8577 void set_service_based_flush_policy(SessionControlBlock *scb)
8578 {
8579     TcpSession *tcp_session = NULL;
8580     StreamTracker* pst;
8581     uint8_t flush_policy;
8582     int ret;
8583 
8584 #ifdef TARGET_BASED
8585     if (scb->proto_specific_data)
8586         tcp_session = scb->proto_specific_data->data;
8587 
8588     if (tcp_session == NULL)
8589         return;
8590 
8591     if (tcp_session->client.tcp_policy->flush_config_protocol[scb->ha_state.application_protocol].configured == 1)
8592     {
8593         pst = &tcp_session->server;
8594         ret = cb_mask_cmp(((StreamConfig *)scb->stream_config)->tcp_config->paf_config,
8595                           scb->ha_state.application_protocol, true, pst->paf_state.cb_mask);
8596         if (ret <= 0)
8597         {
8598             return;
8599         }
8600 
8601         flush_policy =
8602             pst->tcp_policy->flush_config_protocol[scb->ha_state.application_protocol].client.flush_policy;
8603         InitFlushMgrByService(scb, pst, scb->ha_state.application_protocol, true, flush_policy);
8604     }
8605 
8606     if (tcp_session->server.tcp_policy->flush_config_protocol[scb->ha_state.application_protocol].configured == 1)
8607     {
8608         pst = &tcp_session->client;
8609         ret = cb_mask_cmp(((StreamConfig *)scb->stream_config)->tcp_config->paf_config,
8610                           scb->ha_state.application_protocol, false, pst->paf_state.cb_mask);
8611         if (ret <= 0)
8612         {
8613             return;
8614         }
8615 
8616         flush_policy =
8617             pst->tcp_policy->flush_config_protocol[scb->ha_state.application_protocol].server.flush_policy;
8618         InitFlushMgrByService(scb, pst, scb->ha_state.application_protocol, false, flush_policy);
8619     }
8620 #endif
8621 }
8622 
8623 
RepeatedSyn(StreamTracker * listener,StreamTracker * talker,TcpDataBlock * tdb,TcpSession * tcpssn)8624 static int RepeatedSyn(
8625         StreamTracker *listener, StreamTracker *talker,
8626         TcpDataBlock *tdb, TcpSession *tcpssn)
8627 {
8628     switch (listener->os_policy)
8629     {
8630         case STREAM_POLICY_WINDOWS:
8631         case STREAM_POLICY_WINDOWS2K3:
8632         case STREAM_POLICY_VISTA:
8633             /* Windows has some strange behaviour here.  If the
8634              * sequence of the reset is the next expected sequence,
8635              * it Resets.  Otherwise it ignores the 2nd SYN.
8636              */
8637             if (SEQ_EQ(tdb->seq, listener->r_nxt_ack))
8638             {
8639                 STREAM_DEBUG_WRAP(DebugMessage(DEBUG_STREAM_STATE,
8640                             "Got syn on established windows ssn, which causes Reset,"
8641                             "bailing\n"););
8642                 tcpssn->scb->ha_state.session_flags |= SSNFLAG_RESET;
8643                 talker->s_mgr.state = TCP_STATE_CLOSED;
8644                 return ACTION_RST;
8645             }
8646             else
8647             {
8648                 STREAM_DEBUG_WRAP(DebugMessage(DEBUG_STREAM_STATE,
8649                             "Got syn on established windows ssn, not causing Reset,"
8650                             "bailing\n"););
8651                 Discard();
8652                 return ACTION_NOTHING;
8653             }
8654             break;
8655         case STREAM_POLICY_MACOS:
8656             /* MACOS ignores a 2nd SYN, regardless of the sequence number. */
8657             STREAM_DEBUG_WRAP(DebugMessage(DEBUG_STREAM_STATE,
8658                         "Got syn on established macos ssn, not causing Reset,"
8659                         "bailing\n"););
8660             Discard();
8661             return ACTION_NOTHING;
8662             break;
8663         case STREAM_POLICY_FIRST:
8664         case STREAM_POLICY_NOACK:
8665         case STREAM_POLICY_LAST:
8666         case STREAM_POLICY_LINUX:
8667         case STREAM_POLICY_OLD_LINUX:
8668         case STREAM_POLICY_BSD:
8669         case STREAM_POLICY_SOLARIS:
8670         case STREAM_POLICY_HPUX11:
8671         case STREAM_POLICY_HPUX10:
8672         case STREAM_POLICY_IRIX:
8673             /* If its not a retransmission of the actual SYN... RESET */
8674             if(!SEQ_EQ(tdb->seq,talker->isn))
8675             {
8676                 STREAM_DEBUG_WRAP(DebugMessage(DEBUG_STREAM_STATE,
8677                             "Got syn on established ssn, which causes Reset, bailing\n"););
8678                 tcpssn->scb->ha_state.session_flags |= SSNFLAG_RESET;
8679                 talker->s_mgr.state = TCP_STATE_CLOSED;
8680                 return ACTION_RST;
8681             }
8682             else
8683             {
8684                 STREAM_DEBUG_WRAP(DebugMessage(DEBUG_STREAM_STATE,
8685                             "Got syn on established ssn, not causing Reset,"
8686                             "bailing\n"););
8687                 Discard();
8688                 return ACTION_NOTHING;
8689             }
8690             break;
8691     }
8692     return ACTION_NOTHING;
8693 }
8694 
LogTcpEvents(StreamTcpPolicy * s5TcpPolicy,int eventcode)8695 static void LogTcpEvents(StreamTcpPolicy *s5TcpPolicy, int eventcode)
8696 {
8697     if ( !eventcode )
8698         return;
8699 
8700     if (eventcode & EVENT_SYN_ON_EST)
8701         EventSynOnEst(s5TcpPolicy);
8702 
8703     if (eventcode & EVENT_DATA_ON_SYN)
8704         EventDataOnSyn(s5TcpPolicy);
8705 
8706     if (eventcode & EVENT_DATA_ON_CLOSED)
8707         EventDataOnClosed(s5TcpPolicy);
8708 
8709     if (eventcode & EVENT_BAD_TIMESTAMP)
8710         EventBadTimestamp(s5TcpPolicy);
8711 
8712     if (eventcode & EVENT_BAD_SEGMENT)
8713         EventBadSegment(s5TcpPolicy);
8714 
8715     if (eventcode & EVENT_WINDOW_TOO_LARGE)
8716         EventWindowTooLarge(s5TcpPolicy);
8717 
8718     if (eventcode & EVENT_EXCESSIVE_TCP_OVERLAPS)
8719         EventExcessiveOverlap(s5TcpPolicy);
8720 
8721     if (eventcode & EVENT_DATA_AFTER_RESET)
8722         EventDataAfterReset(s5TcpPolicy);
8723 
8724     if (eventcode & EVENT_SESSION_HIJACK_CLIENT)
8725         EventSessionHijackedClient(s5TcpPolicy);
8726 
8727     if (eventcode & EVENT_SESSION_HIJACK_SERVER)
8728         EventSessionHijackedServer(s5TcpPolicy);
8729 
8730     if (eventcode & EVENT_DATA_WITHOUT_FLAGS)
8731         EventDataWithoutFlags(s5TcpPolicy);
8732 
8733     if (eventcode & EVENT_4WHS)
8734         Event4whs(s5TcpPolicy);
8735 
8736     if (eventcode & EVENT_NO_TIMESTAMP)
8737         EventNoTimestamp(s5TcpPolicy);
8738 
8739     if (eventcode & EVENT_BAD_RST)
8740         EventBadReset(s5TcpPolicy);
8741 
8742     if (eventcode & EVENT_BAD_FIN)
8743         EventBadFin(s5TcpPolicy);
8744 
8745     if (eventcode & EVENT_BAD_ACK)
8746         EventBadAck(s5TcpPolicy);
8747 
8748     if (eventcode & EVENT_DATA_AFTER_RST_RCVD)
8749         EventDataAfterRstRcvd(s5TcpPolicy);
8750 
8751     if (eventcode & EVENT_WINDOW_SLAM)
8752         EventWindowSlam(s5TcpPolicy);
8753 }
8754 
DisableInspection(SessionControlBlock * scb,Packet * p,char ignore)8755 static inline void DisableInspection (SessionControlBlock *scb, Packet* p, char ignore)
8756 {
8757     /* Set the directions to ignore... */
8758     scb->ha_state.ignore_direction = ignore;
8759     StreamSetReassemblyTcp(scb, STREAM_FLPOLICY_IGNORE, ignore, STREAM_FLPOLICY_SET_ABSOLUTE);
8760     STREAM_DEBUG_WRAP(DebugMessage(DEBUG_STREAM_STATE,
8761                 "Stream: Ignoring packet from %d. Marking session marked as ignore.\n",
8762                 p->packet_flags & PKT_FROM_SERVER? "server" : "client"););
8763 
8764     session_api->disable_inspection(scb, p);
8765 }
8766 
checkFINTransitionStatus(const Packet * p,StreamTracker * listener)8767 static inline bool checkFINTransitionStatus(const Packet* p, StreamTracker *listener)
8768 {
8769     if((p->dsize != 0) && (listener->s_mgr.state_queue == TCP_STATE_CLOSE_WAIT) &&
8770             ((listener->s_mgr.transition_seq - 1) == listener->r_nxt_ack))
8771         return true;
8772     return false;
8773 }
8774 
ProcessTcp(SessionControlBlock * scb,Packet * p,TcpDataBlock * tdb,StreamTcpPolicy * s5TcpPolicy,SFXHASH_NODE * hash_node)8775 static int ProcessTcp(SessionControlBlock *scb, Packet *p, TcpDataBlock *tdb,
8776                       StreamTcpPolicy *s5TcpPolicy, SFXHASH_NODE *hash_node)
8777 {
8778     int retcode = ACTION_NOTHING;
8779     int eventcode = 0;
8780     char ignore;
8781     int got_ts = 0;
8782     int new_ssn = 0;
8783     int ts_action = ACTION_NOTHING;
8784     TcpSession *tcpssn = NULL;
8785     StreamTracker *talker = NULL;
8786     StreamTracker *listener = NULL;
8787     uint32_t require3Way = (s5TcpPolicy->flags & STREAM_CONFIG_REQUIRE_3WHS);
8788     bool process_fin = false;
8789     STREAM_DEBUG_WRAP(char *t = NULL; char *l = NULL;)
8790         PROFILE_VARS;
8791 
8792     if (scb->protocol != IPPROTO_TCP)
8793     {
8794         STREAM_DEBUG_WRAP(DebugMessage(DEBUG_STREAM_STATE,
8795                     "Lightweight session not TCP on TCP packet\n"););
8796         return retcode;
8797     }
8798 
8799     if (scb->proto_specific_data)
8800         tcpssn = (TcpSession *)scb->proto_specific_data->data;
8801 
8802     PREPROC_PROFILE_START(s5TcpStatePerfStats);
8803 
8804     if (tcpssn == NULL)
8805     {
8806         if ( ScPafEnabled() )
8807         {
8808             /* Check if the session is to be ignored */
8809             if (hash_node)
8810                 ignore = StreamExpectProcessNode(p, scb, hash_node);
8811             else
8812                 ignore = StreamExpectCheck(p, scb);
8813             if (ignore)
8814             {
8815                 DisableInspection(scb, p, ignore);
8816                 PREPROC_PROFILE_END(s5TcpStatePerfStats);
8817                 return retcode;
8818             }
8819         }
8820 
8821         if (TCP_ISFLAGSET(p->tcph, TH_SYN) && !TCP_ISFLAGSET(p->tcph, TH_ACK))
8822         {
8823             scb->session_state |= STREAM_STATE_SYN;
8824 
8825             if( require3Way || ( StreamPacketHasWscale( p ) & TF_WSCALE ) ||
8826                     ( ( p->dsize > 0 ) &&
8827                       ( StreamGetPolicy( scb, s5TcpPolicy, FROM_CLIENT ) == STREAM_POLICY_MACOS ) ) )
8828             {
8829                 /* Create TCP session if we
8830                  * 1) require 3-WAY HS, OR
8831                  * 2) client sent wscale option, OR
8832                  * 3) have data and its a MAC OS policy -- MAC
8833                  *    is the only one that accepts data on SYN
8834                  *    (and thus requires a TCP session at this point)
8835                  */
8836                 if(NewTcpSession(p, scb, tdb, s5TcpPolicy)== -1 )
8837                 {
8838                     PREPROC_PROFILE_END(s5TcpStatePerfStats);
8839                     return retcode;
8840                 }
8841                 tcpssn = (TcpSession *)scb->proto_specific_data->data;
8842                 new_ssn = 1;
8843                 NormalTrackECN(tcpssn, p->tcph, require3Way);
8844             }
8845 
8846             /* Nothing left todo here */
8847         }
8848         else if( TCP_ISFLAGSET( p->tcph, ( TH_SYN | TH_ACK ) ) )
8849         {
8850             scb->session_state |= STREAM_STATE_SYN_ACK;
8851             if (!require3Way || midstream_allowed)
8852             {
8853                 if(NewTcpSession(p, scb, tdb, s5TcpPolicy)== -1 )
8854                 {
8855                     PREPROC_PROFILE_END(s5TcpStatePerfStats);
8856                     return retcode;
8857                 }
8858                 tcpssn = (TcpSession *)scb->proto_specific_data->data;
8859                 new_ssn = 1;
8860             }
8861             NormalTrackECN(tcpssn, p->tcph, require3Way);
8862             /* Nothing left todo here */
8863         }
8864         else if( TCP_ISFLAGSET( p->tcph, TH_ACK ) && !TCP_ISFLAGSET( p->tcph, TH_RST )
8865                 &&
8866                 ( scb->session_state & STREAM_STATE_SYN_ACK ) )
8867         {
8868             /* TODO: do we need to verify the ACK field is >= the seq of the SYN-ACK? */
8869 
8870             /* 3-way Handshake complete, create TCP session */
8871             scb->session_state |= STREAM_STATE_ACK | STREAM_STATE_ESTABLISHED;
8872             if(NewTcpSession(p, scb, tdb, s5TcpPolicy)== -1 )
8873             {
8874                 PREPROC_PROFILE_END(s5TcpStatePerfStats);
8875                 return retcode;
8876             }
8877             tcpssn = (TcpSession *)scb->proto_specific_data->data;
8878             new_ssn = 1;
8879 
8880             NormalTrackECN(tcpssn, p->tcph, require3Way);
8881             StreamUpdatePerfBaseState(&sfBase, scb, TCP_STATE_ESTABLISHED);
8882         }
8883         else if ((p->dsize > 0) && (!require3Way || midstream_allowed))
8884         {
8885             // TBD-EDM not sure we need this here...
8886             //
8887             /*  need to figure out direction, etc
8888                 Assume from client, can update later */
8889             if (p->sp > p->dp)
8890             {
8891                 scb->ha_state.direction = FROM_CLIENT;
8892                 IP_COPY_VALUE(scb->client_ip, GET_SRC_IP(p));
8893                 scb->client_port = p->tcph->th_sport;
8894                 IP_COPY_VALUE(scb->server_ip, GET_DST_IP(p));
8895                 scb->server_port = p->tcph->th_dport;
8896             }
8897             else
8898             {
8899                 scb->ha_state.direction = FROM_SERVER;
8900                 IP_COPY_VALUE(scb->client_ip, GET_DST_IP(p));
8901                 scb->client_port = p->tcph->th_dport;
8902                 IP_COPY_VALUE(scb->server_ip, GET_SRC_IP(p));
8903                 scb->server_port = p->tcph->th_sport;
8904             }
8905             scb->session_state |= STREAM_STATE_MIDSTREAM;
8906             scb->ha_state.session_flags |= SSNFLAG_MIDSTREAM;
8907 
8908 
8909 #ifdef STREAM_DEBUG_ENABLED
8910             if (ScReadMode())
8911             {
8912                 /* If we're in readback mode... may only have one packet.
8913                  * That being packet with the exploit being tested, so
8914                  * mark this session as established, so rule option
8915                  * 'flow:established' works correctly.
8916                  */
8917                 STREAM_DEBUG_WRAP(
8918                         char timestamp[TIMEBUF_SIZE];
8919                         char src_addr[17];
8920                         char dst_addr[17];
8921                         memset((char *)timestamp, 0, TIMEBUF_SIZE);
8922                         ts_print((struct timeval *) &p->pkth->ts, timestamp);
8923                         SnortSnprintf(src_addr, 17, "%s",
8924                             inet_ntoa(GET_SRC_ADDR(p)));
8925                         SnortSnprintf(dst_addr, 17, "%s",
8926                             inet_ntoa(GET_DST_ADDR(p)));
8927                         DebugMessage(DEBUG_STREAM_STATE, "Session not established"
8928                             "on midstream-pickup of data packet.  Will be marked"
8929                             "as established when other side is seen. Packet Info:"
8930                             "Time: %s\tSrc: %s:%d\tDst: %s:%d\n",
8931                             timestamp, src_addr, p->sp, dst_addr, p->dp);
8932 
8933                         );
8934 #ifdef MIMIC_STREAM4_MIDSTREAM_BEHAVIOUR
8935                 scb->session_state |= STREAM_STATE_ESTABLISHED;
8936                 scb->ha_state.session_flags |= SSNFLAG_ESTABLISHED;
8937 #endif
8938             }
8939 #endif
8940             if(NewTcpSession(p, scb, tdb, s5TcpPolicy)== -1 )
8941             {
8942                 PREPROC_PROFILE_END(s5TcpStatePerfStats);
8943                 return retcode;
8944             }
8945             tcpssn = (TcpSession *)scb->proto_specific_data->data;
8946             new_ssn = 1;
8947             NormalTrackECN(tcpssn, p->tcph, require3Way);
8948 
8949             if (scb->session_state & STREAM_STATE_ESTABLISHED)
8950                 StreamUpdatePerfBaseState(&sfBase, scb, TCP_STATE_ESTABLISHED);
8951         }
8952         else if (p->dsize == 0)
8953         {
8954             /* Already have a scb, but no tcp session.
8955              * Probably just an ACK of already sent data (that
8956              * we missed).
8957              */
8958             /* Do nothing. */
8959             PREPROC_PROFILE_END(s5TcpStatePerfStats);
8960             return retcode;
8961         }
8962 
8963 
8964         /* This flag is set in session_expect when the event handler is set.
8965          * It is assumed that if we need to register the event handler before
8966          * analyzing the packet, we will also want to begin packet reassembly
8967          * immediately.  If a preprocessor does not want to set reassembly in
8968          * both directory, it will call set_reassembly again with the correct
8969          * parameters.
8970          */
8971         if (p->packet_flags & PKT_EARLY_REASSEMBLY)
8972         {
8973             p->packet_flags &= ~PKT_EARLY_REASSEMBLY;
8974             StreamSetReassemblyTcp(scb, STREAM_FLPOLICY_FOOTPRINT,
8975                    SSN_DIR_BOTH, STREAM_FLPOLICY_SET_ABSOLUTE);
8976         }
8977     }
8978     else
8979     {
8980 
8981         /* If session is already marked as established */
8982         if (!(scb->session_state & STREAM_STATE_ESTABLISHED))
8983         {
8984             if (hash_node)
8985                 ignore = StreamExpectProcessNode(p, scb, hash_node);
8986             else
8987                 ignore = StreamExpectCheck(p, scb);
8988             if (p->packet_flags & PKT_EARLY_REASSEMBLY)
8989             {
8990                 p->packet_flags &= ~PKT_EARLY_REASSEMBLY;
8991                 StreamSetReassemblyTcp(scb, STREAM_FLPOLICY_FOOTPRINT,
8992                     ~(ignore & SSN_DIR_BOTH) & SSN_DIR_BOTH, //Directions to not ignore
8993                     STREAM_FLPOLICY_SET_ABSOLUTE);
8994             }
8995 
8996             if(!require3Way || midstream_allowed)
8997             {
8998                 /* If not requiring 3-way Handshake... */
8999 
9000                 /* TCP session created on TH_SYN above,
9001                  * or maybe on SYN-ACK, or anything else */
9002 
9003                 /* Need to update Lightweight session state */
9004                 if (TCP_ISFLAGSET(p->tcph, (TH_SYN|TH_ACK)))
9005                 {
9006                     /* SYN-ACK from server */
9007                     if (scb->session_state != STREAM_STATE_NONE)
9008                     {
9009                         scb->session_state |= STREAM_STATE_SYN_ACK;
9010                     }
9011                 }
9012                 else if (TCP_ISFLAGSET(p->tcph, TH_ACK) &&
9013                         (scb->session_state & STREAM_STATE_SYN_ACK))
9014                 {
9015                     scb->session_state |= STREAM_STATE_ACK | STREAM_STATE_ESTABLISHED;
9016                     StreamUpdatePerfBaseState(&sfBase, scb, TCP_STATE_ESTABLISHED);
9017                 }
9018 
9019             }
9020         }
9021 
9022 #ifdef NORMALIZER
9023         if (TCP_ISFLAGSET(p->tcph, TH_SYN))
9024             NormalTrackECN(tcpssn, p->tcph, require3Way);
9025 #endif
9026     }
9027 
9028     two_way_traffic = TwoWayTraffic(scb);
9029     /* figure out direction of this packet */
9030     session_api->set_packet_direction_flag(p, scb);
9031 
9032     if(p->packet_flags & PKT_FROM_SERVER)
9033     {
9034         STREAM_DEBUG_WRAP(DebugMessage(DEBUG_STREAM_STATE,
9035                     "Stream: Updating on packet from server\n"););
9036         scb->ha_state.session_flags |= SSNFLAG_SEEN_SERVER;
9037         if (tcpssn)
9038         {
9039             talker = &tcpssn->server;
9040             listener = &tcpssn->client;
9041         }
9042 
9043         STREAM_DEBUG_WRAP(
9044                 t = "Server";
9045                 l = "Client");
9046 
9047         if ( talker && talker->s_mgr.state == TCP_STATE_LISTEN &&
9048                 ((p->tcph->th_flags & (TH_SYN|TH_ACK)) == TH_SYN) )
9049         {
9050             eventcode |= EVENT_4WHS;
9051         }
9052         /* If we picked this guy up midstream, finish the initialization */
9053         if ((scb->session_state & STREAM_STATE_MIDSTREAM) &&
9054                 !(scb->session_state & STREAM_STATE_ESTABLISHED))
9055         {
9056             FinishServerInit(p, tdb, tcpssn);
9057             if((p->tcph->th_flags & TH_ECE) &&
9058                     scb->ha_state.session_flags & SSNFLAG_ECN_CLIENT_QUERY)
9059             {
9060                 scb->ha_state.session_flags |= SSNFLAG_ECN_SERVER_REPLY;
9061             }
9062 
9063             if (scb->ha_state.session_flags & SSNFLAG_SEEN_CLIENT)
9064             {
9065                 // should TCP state go to established too?
9066                 scb->session_state |= STREAM_STATE_ESTABLISHED;
9067                 scb->ha_state.session_flags |= SSNFLAG_ESTABLISHED;
9068                 StreamUpdatePerfBaseState(&sfBase, scb, TCP_STATE_ESTABLISHED);
9069             }
9070         }
9071 #ifdef ACTIVE_RESPONSE
9072         if ( !scb->inner_server_ttl )
9073             SetTTL(scb, p, 0);
9074 #endif
9075     }
9076     else
9077     {
9078         STREAM_DEBUG_WRAP(DebugMessage(DEBUG_STREAM_STATE,
9079                     "Stream: Updating on packet from client\n"););
9080         /* if we got here we had to see the SYN already... */
9081         scb->ha_state.session_flags |= SSNFLAG_SEEN_CLIENT;
9082         if (tcpssn)
9083         {
9084             talker = &tcpssn->client;
9085             listener = &tcpssn->server;
9086         }
9087 
9088         STREAM_DEBUG_WRAP(
9089                 t = "Client";
9090                 l = "Server";);
9091 
9092         if ((scb->session_state & STREAM_STATE_MIDSTREAM) &&
9093                 !(scb->session_state & STREAM_STATE_ESTABLISHED))
9094         {
9095             /* Midstream and seen server. */
9096             if (scb->ha_state.session_flags & SSNFLAG_SEEN_SERVER)
9097             {
9098                 scb->session_state |= STREAM_STATE_ESTABLISHED;
9099                 scb->ha_state.session_flags |= SSNFLAG_ESTABLISHED;
9100             }
9101         }
9102 #ifdef ACTIVE_RESPONSE
9103         if ( !scb->inner_client_ttl )
9104             SetTTL(scb, p, 1);
9105 #endif
9106     }
9107     /* Check if there is a reload and policy is changed */
9108     if( listener && talker && listener->tcp_policy != s5TcpPolicy && talker->tcp_policy != s5TcpPolicy)
9109     {
9110         listener->tcp_policy = s5TcpPolicy;
9111         talker->tcp_policy = StreamPolicyLookup(scb, GET_SRC_IP(p));
9112     }
9113     /*
9114      * check for SYN on reset session
9115      */
9116     if ((scb->ha_state.session_flags & SSNFLAG_RESET) &&
9117             (p->tcph->th_flags & TH_SYN))
9118     {
9119         if ((!tcpssn) ||
9120                 ((listener->s_mgr.state == TCP_STATE_CLOSED) ||
9121                  (talker->s_mgr.state == TCP_STATE_CLOSED)))
9122         {
9123             /* Listener previously issued a reset */
9124             /* Talker is re-SYN-ing */
9125             struct session_state_cleanup_cache sscc;
9126 
9127             cleanup_cache_session_state( scb, &sscc );
9128             TcpSessionCleanupWithFreeApplicationData(scb);
9129             cleanup_log_session_state( "SYN on RST ssn", &sscc );
9130 
9131             if (p->tcph->th_flags & TH_RST)
9132             {
9133                 /* Got SYN/RST.  We're done. */
9134                 NormalTrimPayloadIfSyn(p, 0, tdb);
9135                 NormalTrimPayloadIfRst(p, 0, tdb);
9136                 tcpssn = NULL;
9137                 PREPROC_PROFILE_END(s5TcpStatePerfStats);
9138                 return retcode | ACTION_RST;
9139             }
9140             else if (TCP_ISFLAGSET(p->tcph, TH_SYN) &&
9141                     !TCP_ISFLAGSET(p->tcph, TH_ACK))
9142             {
9143                 scb->ha_state.direction = FROM_CLIENT;
9144                 IP_COPY_VALUE(scb->client_ip, GET_SRC_IP(p));
9145                 scb->client_port = p->tcph->th_sport;
9146                 IP_COPY_VALUE(scb->server_ip, GET_DST_IP(p));
9147                 scb->server_port = p->tcph->th_dport;
9148                 scb->session_state = STREAM_STATE_SYN;
9149 #ifdef ACTIVE_RESPONSE
9150                 SetTTL(scb, p, 1);
9151 #endif
9152                 if(NewTcpSession(p, scb, tdb, s5TcpPolicy)== -1 )
9153                 {
9154                     PREPROC_PROFILE_END(s5TcpStatePerfStats);
9155                     return retcode;
9156                 }
9157 
9158                 tcpssn = (TcpSession *)scb->proto_specific_data->data;
9159                 new_ssn = 1;
9160                 NormalTrackECN(tcpssn, p->tcph, require3Way);
9161 
9162                 if (tcpssn)
9163                 {
9164                     listener = &tcpssn->server;
9165                     talker = &tcpssn->client;
9166                 }
9167                 scb->ha_state.session_flags = SSNFLAG_SEEN_CLIENT;
9168             }
9169             else if (TCP_ISFLAGSET(p->tcph, (TH_SYN|TH_ACK)))
9170             {
9171                 scb->ha_state.direction = FROM_SERVER;
9172                 IP_COPY_VALUE(scb->client_ip, GET_DST_IP(p));
9173                 scb->client_port = p->tcph->th_dport;
9174                 IP_COPY_VALUE(scb->server_ip, GET_SRC_IP(p));
9175                 scb->server_port = p->tcph->th_sport;
9176                 scb->session_state = STREAM_STATE_SYN_ACK;
9177 #ifdef ACTIVE_RESPONSE
9178                 SetTTL(scb, p, 0);
9179 #endif
9180                 if(NewTcpSession(p, scb, tdb, s5TcpPolicy)== -1 )
9181                 {
9182                     PREPROC_PROFILE_END(s5TcpStatePerfStats);
9183                     return retcode;
9184                 }
9185                 tcpssn = (TcpSession *)scb->proto_specific_data->data;
9186                 new_ssn = 1;
9187                 NormalTrackECN(tcpssn, p->tcph, require3Way);
9188 
9189                 if (tcpssn)
9190                 {
9191                     listener = &tcpssn->client;
9192                     talker = &tcpssn->server;
9193                 }
9194                 scb->ha_state.session_flags = SSNFLAG_SEEN_SERVER;
9195             }
9196         }
9197         STREAM_DEBUG_WRAP(DebugMessage(DEBUG_STREAM_STATE,
9198                     "Got SYN pkt on reset ssn, re-SYN-ing\n"););
9199     }
9200 
9201     if (((p->packet_flags & PKT_FROM_SERVER) && (scb->ha_state.ignore_direction & SSN_DIR_FROM_CLIENT)) ||
9202             ((p->packet_flags & PKT_FROM_CLIENT) && (scb->ha_state.ignore_direction & SSN_DIR_FROM_SERVER)))
9203     {
9204         if (talker && (talker->flags & TF_FORCE_FLUSH))
9205         {
9206             StreamFlushTalker(p, scb);
9207             talker->flags &= ~TF_FORCE_FLUSH;
9208         }
9209 
9210         if (listener && (listener->flags & TF_FORCE_FLUSH))
9211         {
9212             StreamFlushListener(p, scb);
9213             listener->flags &= ~TF_FORCE_FLUSH;
9214         }
9215         p->packet_flags |= PKT_IGNORE;
9216         retcode |= ACTION_DISABLE_INSPECTION;
9217     }
9218 
9219     /* Check if the session is to be ignored */
9220     if ( !ScPafEnabled() )
9221     {
9222         if (hash_node)
9223             ignore = StreamExpectProcessNode(p, scb, hash_node);
9224         else
9225             ignore = StreamExpectCheck(p, scb);
9226         if (ignore)
9227         {
9228             DisableInspection(scb, p, ignore);
9229             PREPROC_PROFILE_END(s5TcpStatePerfStats);
9230             return retcode;
9231         }
9232     }
9233 
9234     /* Handle data on SYN */
9235     if (!IsTCPFastOpenPkt(p) && p->dsize && TCP_ISFLAGSET(p->tcph, TH_SYN))
9236     {
9237         /* MacOS accepts data on SYN, so don't alert if policy is MACOS */
9238         if (StreamGetPolicy(scb, s5TcpPolicy, FROM_CLIENT) !=
9239                 STREAM_POLICY_MACOS)
9240         {
9241 #ifdef NORMALIZER
9242             NormalTrimPayloadIfSyn(p, 0, tdb); // remove data on SYN
9243             if ( Normalize_GetMode(snort_conf, NORM_TCP_TRIM_SYN) == NORM_MODE_OFF)
9244 #endif
9245             {
9246                 STREAM_DEBUG_WRAP(DebugMessage(DEBUG_STREAM_STATE,
9247                             "Got data on SYN packet, not processing it\n"););
9248                 //EventDataOnSyn(s5TcpPolicy);
9249                 eventcode |= EVENT_DATA_ON_SYN;
9250                 retcode |= ACTION_BAD_PKT;
9251             }
9252         }
9253     }
9254 
9255     if (!tcpssn)
9256     {
9257         LogTcpEvents(s5TcpPolicy, eventcode);
9258         PREPROC_PROFILE_END(s5TcpStatePerfStats);
9259         return retcode;
9260     }
9261 
9262     STREAM_DEBUG_WRAP(DebugMessage(DEBUG_STREAM_STATE,
9263                 "   %s [talker] state: %s\n", t,
9264                 state_names[talker->s_mgr.state]););
9265     STREAM_DEBUG_WRAP(PrintFlushMgr(&talker->flush_mgr););
9266     STREAM_DEBUG_WRAP(DebugMessage(DEBUG_STREAM_STATE,
9267                 "   %s state: %s(%d)\n", l,
9268                 state_names[listener->s_mgr.state],
9269                 listener->s_mgr.state););
9270     STREAM_DEBUG_WRAP(PrintFlushMgr(&listener->flush_mgr););
9271 
9272     // may find better placement to eliminate redundant flag checks
9273     if(p->tcph->th_flags & TH_SYN)
9274         talker->s_mgr.sub_state |= SUB_SYN_SENT;
9275     if(p->tcph->th_flags & TH_ACK)
9276         talker->s_mgr.sub_state |= SUB_ACK_SENT;
9277 
9278     /*
9279      * process SYN ACK on unestablished sessions
9280      */
9281     if( (TCP_STATE_SYN_SENT == listener->s_mgr.state) &&
9282             (TCP_STATE_LISTEN == talker->s_mgr.state) )
9283     {
9284         if(p->tcph->th_flags & TH_ACK)
9285         {
9286             /*
9287              * make sure we've got a valid segment
9288              */
9289             if(!IsBetween(listener->l_unackd, listener->l_nxt_seq, tdb->ack))
9290             {
9291                 STREAM_DEBUG_WRAP(DebugMessage(DEBUG_STREAM_STATE,
9292                             "Pkt ack is out of bounds, bailing!\n"););
9293                 Discard();
9294                 NormalTrimPayloadIfWin(p, 0, tdb);
9295                 LogTcpEvents(listener->tcp_policy, eventcode);
9296                 PREPROC_PROFILE_END(s5TcpStatePerfStats);
9297                 return retcode | ACTION_BAD_PKT;
9298             }
9299         }
9300 
9301         talker->flags |= StreamGetTcpTimestamp(p, &tdb->ts, 0);
9302         if (tdb->ts == 0)
9303             talker->flags |= TF_TSTAMP_ZERO;
9304 
9305         /*
9306          * catch resets sent by server
9307          */
9308         if(p->tcph->th_flags & TH_RST)
9309         {
9310             STREAM_DEBUG_WRAP(DebugMessage(DEBUG_STREAM_STATE,
9311                         "got RST\n"););
9312 
9313             NormalTrimPayloadIfRst(p, 0, tdb);
9314 
9315             /* Reset is valid when in SYN_SENT if the
9316              * ack field ACKs the SYN.
9317              */
9318             if(ValidRstSynSent(listener, tdb))
9319             {
9320                 STREAM_DEBUG_WRAP(DebugMessage(DEBUG_STREAM_STATE,
9321                             "got RST, closing talker\n"););
9322                 /* Reset is valid */
9323                 /* Mark session as reset... Leave it around so that any
9324                  * additional data sent from one side or the other isn't
9325                  * processed (and is dropped in inline mode).
9326                  */
9327                 scb->ha_state.session_flags |= SSNFLAG_RESET;
9328                 talker->s_mgr.state = TCP_STATE_CLOSED;
9329                 StreamUpdatePerfBaseState(&sfBase, scb, TCP_STATE_CLOSING);
9330                 /* Leave listener open, data may be in transit */
9331                 LogTcpEvents(listener->tcp_policy, eventcode);
9332                 PREPROC_PROFILE_END(s5TcpStatePerfStats);
9333                 return retcode | ACTION_RST;
9334             }
9335             /* Reset not valid. */
9336             STREAM_DEBUG_WRAP(DebugMessage(DEBUG_STREAM_STATE,
9337                         "bad sequence number, bailing\n"););
9338             Discard();
9339             eventcode |= EVENT_BAD_RST;
9340             NormalDropPacket(p);
9341             LogTcpEvents(listener->tcp_policy, eventcode);
9342             PREPROC_PROFILE_END(s5TcpStatePerfStats);
9343             return retcode;
9344         }
9345 
9346         /*
9347          * finish up server init
9348          */
9349         if(p->tcph->th_flags & TH_SYN)
9350         {
9351             FinishServerInit(p, tdb, tcpssn);
9352             if (talker->flags & TF_TSTAMP)
9353             {
9354                 talker->ts_last_pkt = p->pkth->ts.tv_sec;
9355                 talker->ts_last = tdb->ts;
9356             }
9357             STREAM_DEBUG_WRAP(DebugMessage(DEBUG_STREAM_STATE,
9358                         "Finish server init got called!\n"););
9359         }
9360         else
9361         {
9362             STREAM_DEBUG_WRAP(DebugMessage(DEBUG_STREAM_STATE,
9363                         "Finish server init didn't get called!\n"););
9364         }
9365 
9366         if((p->tcph->th_flags & TH_ECE) &&
9367                 scb->ha_state.session_flags & SSNFLAG_ECN_CLIENT_QUERY)
9368         {
9369             scb->ha_state.session_flags |= SSNFLAG_ECN_SERVER_REPLY;
9370         }
9371 
9372         /*
9373          * explicitly set the state
9374          */
9375         listener->s_mgr.state = TCP_STATE_SYN_SENT;
9376         STREAM_DEBUG_WRAP(DebugMessage(DEBUG_STREAM_STATE,
9377                     "Accepted SYN ACK\n"););
9378     }
9379 
9380     /*
9381      * scale the window.  Only if BOTH client and server specified
9382      * wscale option as part of 3-way handshake.
9383      * This is per RFC 1323.
9384      */
9385     if ((talker->flags & TF_WSCALE) && (listener->flags & TF_WSCALE))
9386     {
9387         tdb->win <<= talker->wscale;
9388     }
9389 
9390     /* Check for session hijacking -- compare mac address to the ones
9391      * that were recorded at session startup.
9392      */
9393 #ifdef DAQ_PKT_FLAG_PRE_ROUTING
9394     if (!(p->pkth->flags & DAQ_PKT_FLAG_PRE_ROUTING) &&
9395             listener->tcp_policy->flags & STREAM_CONFIG_CHECK_SESSION_HIJACKING)
9396 #else
9397         if (listener->tcp_policy->flags & STREAM_CONFIG_CHECK_SESSION_HIJACKING)
9398 #endif
9399         {
9400             eventcode |= ValidMacAddress(talker, listener, p);
9401         }
9402 
9403     /* Check timestamps */
9404     ts_action = ValidTimestamp(talker, listener, tdb, p, &eventcode, &got_ts);
9405 
9406     /*
9407      * check RST validity
9408      */
9409     if(p->tcph->th_flags & TH_RST)
9410     {
9411         NormalTrimPayloadIfRst(p, 0, tdb);
9412 
9413         if(ValidRst(scb, listener, tdb))
9414         {
9415             STREAM_DEBUG_WRAP(DebugMessage(DEBUG_STREAM_STATE,
9416                         "Got RST, bailing\n"););
9417 
9418             if (
9419                     listener->s_mgr.state == TCP_STATE_FIN_WAIT_1 ||
9420                     listener->s_mgr.state == TCP_STATE_FIN_WAIT_2 ||
9421                     listener->s_mgr.state == TCP_STATE_CLOSE_WAIT ||
9422                     listener->s_mgr.state == TCP_STATE_LAST_ACK   ||
9423                     listener->s_mgr.state == TCP_STATE_CLOSING
9424                ) {
9425                 StreamFlushTalker(p, scb);
9426                 StreamFlushListener(p, scb);
9427                 scb->ha_state.session_flags |= SSNFLAG_FREE_APP_DATA;
9428             }
9429             scb->ha_state.session_flags |= SSNFLAG_RESET;
9430             talker->s_mgr.state = TCP_STATE_CLOSED;
9431             talker->s_mgr.sub_state |= SUB_RST_SENT;
9432             StreamUpdatePerfBaseState(&sfBase, scb, TCP_STATE_CLOSING);
9433 
9434 #ifdef NORMALIZER
9435             if ( Normalize_GetMode(snort_conf, NORM_TCP_IPS) == NORM_MODE_ON )
9436                 listener->s_mgr.state = TCP_STATE_CLOSED;
9437             /* else for ids:
9438                leave listener open, data may be in transit */
9439 #endif
9440 
9441             LogTcpEvents(listener->tcp_policy, eventcode);
9442             PREPROC_PROFILE_END(s5TcpStatePerfStats);
9443             return retcode | ACTION_RST;
9444         }
9445         /* Reset not valid. */
9446         STREAM_DEBUG_WRAP(DebugMessage(DEBUG_STREAM_STATE,
9447                     "bad sequence number, bailing\n"););
9448         Discard();
9449         eventcode |= EVENT_BAD_RST;
9450         NormalDropPacket(p);
9451         LogTcpEvents(listener->tcp_policy, eventcode);
9452         PREPROC_PROFILE_END(s5TcpStatePerfStats);
9453         return retcode | ts_action;
9454     }
9455     else
9456     {
9457         /* check for valid seqeuence/retrans */
9458         bool before_win_base = false;
9459         if( s5TcpPolicy->policy != STREAM_POLICY_NOACK )
9460         {
9461             if ( (listener->s_mgr.state >= TCP_STATE_ESTABLISHED) &&
9462                     !ValidSeq(p, scb, listener, tdb, &before_win_base) )
9463             {
9464                 STREAM_DEBUG_WRAP(DebugMessage(DEBUG_STREAM_STATE,
9465                             "bad sequence number, bailing\n"););
9466                 Discard();
9467                 if(before_win_base)
9468                     DisableAppPreprocessors(p);
9469                 NormalTrimPayloadIfWin(p, 0, tdb);
9470                 LogTcpEvents(listener->tcp_policy, eventcode);
9471                 PREPROC_PROFILE_END(s5TcpStatePerfStats);
9472                 return retcode | ts_action;
9473             }
9474         }
9475     }
9476 
9477     if (ts_action != ACTION_NOTHING)
9478     {
9479         STREAM_DEBUG_WRAP(DebugMessage(DEBUG_STREAM_STATE,
9480                     "bad timestamp, bailing\n"););
9481         Discard();
9482         // this packet was normalized elsewhere
9483         LogTcpEvents(listener->tcp_policy, eventcode);
9484         PREPROC_PROFILE_END(s5TcpStatePerfStats);
9485         return retcode | ts_action;
9486     }
9487 
9488     /*
9489      * update PAWS timestamps
9490      */
9491     STREAM_DEBUG_WRAP(DebugMessage(DEBUG_STREAM_STATE,
9492                 "PAWS update tdb->seq %lu > listener->r_win_base %lu\n",
9493                 tdb->seq, listener->r_win_base););
9494     if(got_ts && SEQ_EQ(listener->r_win_base, tdb->seq))
9495     {
9496         if((int32_t)(tdb->ts - talker->ts_last) >= 0 ||
9497                 (uint32_t)p->pkth->ts.tv_sec >= talker->ts_last_pkt+PAWS_24DAYS)
9498         {
9499             STREAM_DEBUG_WRAP(DebugMessage(DEBUG_STREAM_STATE,
9500                         "updating timestamps...\n"););
9501             talker->ts_last = tdb->ts;
9502             talker->ts_last_pkt = p->pkth->ts.tv_sec;
9503         }
9504     }
9505     else
9506     {
9507         STREAM_DEBUG_WRAP(DebugMessage(DEBUG_STREAM_STATE,
9508                     "not updating timestamps...\n"););
9509     }
9510 
9511     /*
9512      * check for repeat SYNs
9513      */
9514     if ( !new_ssn &&
9515             ((p->tcph->th_flags & (TH_SYN|TH_ACK)) == TH_SYN) )
9516     {
9517         int action;
9518 #ifdef NORMALIZER
9519         if ( !SEQ_EQ(tdb->seq, talker->isn) &&
9520                 NormalDropPacket(p) )
9521             action = ACTION_BAD_PKT;
9522         else
9523 #endif
9524             if ( talker->s_mgr.state >= TCP_STATE_ESTABLISHED )
9525                 action = RepeatedSyn(listener, talker, tdb, tcpssn);
9526             else
9527                 action = ACTION_NOTHING;
9528 
9529         if (action != ACTION_NOTHING)
9530         {
9531             /* got a bad SYN on the session, alert! */
9532             eventcode |= EVENT_SYN_ON_EST;
9533             LogTcpEvents(listener->tcp_policy, eventcode);
9534             PREPROC_PROFILE_END(s5TcpStatePerfStats);
9535             return retcode | action;
9536         }
9537     }
9538 
9539     /*
9540      * Check that the window is within the limits
9541      */
9542     if ( s5TcpPolicy->policy != STREAM_POLICY_NOACK )
9543     {
9544         if (listener->tcp_policy->max_window && (tdb->win > listener->tcp_policy->max_window))
9545         {
9546             STREAM_DEBUG_WRAP(DebugMessage(DEBUG_STREAM_STATE,
9547                         "Got window that was beyond the allowed policy value, bailing\n"););
9548             /* got a window too large, alert! */
9549             eventcode |= EVENT_WINDOW_TOO_LARGE;
9550             Discard();
9551             NormalDropPacket(p);
9552             LogTcpEvents(listener->tcp_policy, eventcode);
9553             PREPROC_PROFILE_END(s5TcpStatePerfStats);
9554             return retcode | ACTION_BAD_PKT;
9555         }
9556         else if ((p->packet_flags & PKT_FROM_CLIENT)
9557                 && (tdb->win <= SLAM_MAX) && (tdb->ack == listener->isn + 1)
9558                 && !(p->tcph->th_flags & (TH_FIN|TH_RST))
9559                 && !(scb->ha_state.session_flags & SSNFLAG_MIDSTREAM))
9560         {
9561             STREAM_DEBUG_WRAP(DebugMessage(DEBUG_STREAM_STATE,
9562                         "Window slammed shut!\n"););
9563             /* got a window slam alert! */
9564             eventcode |= EVENT_WINDOW_SLAM;
9565             Discard();
9566 
9567 #ifdef NORMALIZER
9568             if ( NormalDropPacket(p) )
9569             {
9570                 LogTcpEvents(listener->tcp_policy, eventcode);
9571                 PREPROC_PROFILE_END(s5TcpStatePerfStats);
9572                 return retcode | ACTION_BAD_PKT;
9573             }
9574 #endif
9575         }
9576     }
9577 
9578     if(talker->s_mgr.state_queue != TCP_STATE_NONE)
9579     {
9580         STREAM_DEBUG_WRAP(DebugMessage(DEBUG_STREAM_STATE,
9581                     "Found queued state transition on ack 0x%X, "
9582                     "current 0x%X!\n", talker->s_mgr.transition_seq,
9583                     tdb->ack););
9584         if(tdb->ack == talker->s_mgr.transition_seq)
9585         {
9586             STREAM_DEBUG_WRAP(DebugMessage(DEBUG_STREAM_STATE,
9587                         "accepting transition!\n"););
9588             talker->s_mgr.state = talker->s_mgr.state_queue;
9589             talker->s_mgr.state_queue = TCP_STATE_NONE;
9590             //If ACK is received for Queued FIN before previous data is received. Process FIN transition
9591             if(listener->s_mgr.state == TCP_STATE_ESTABLISHED)
9592             {
9593                 listener->l_nxt_seq++;
9594                 talker->r_nxt_ack = tdb->ack;
9595                 listener->s_mgr.sub_state |= SUB_FIN_SENT;
9596                 listener->s_mgr.state = TCP_STATE_FIN_WAIT_1;
9597 
9598                 StreamUpdatePerfBaseState(&sfBase, scb, TCP_STATE_CLOSING);
9599             }
9600         }
9601     }
9602 
9603     /*
9604      * process ACK flags
9605      */
9606     if(p->tcph->th_flags & TH_ACK)
9607     {
9608         STREAM_DEBUG_WRAP(DebugMessage(DEBUG_STREAM_STATE,
9609                     "Got an ACK...\n"););
9610         STREAM_DEBUG_WRAP(DebugMessage(DEBUG_STREAM_STATE,
9611                     "   %s [listener] state: %s\n", l,
9612                     state_names[listener->s_mgr.state]););
9613 
9614         switch(listener->s_mgr.state)
9615         {
9616             case TCP_STATE_SYN_SENT:
9617                 if ( !require3Way || midstream_allowed )
9618                     break;
9619                 // fall thru ...
9620             case TCP_STATE_SYN_RCVD:
9621                 STREAM_DEBUG_WRAP(DebugMessage(DEBUG_STREAM_STATE,
9622                             "listener state is SYN_SENT...\n"););
9623                 if(IsBetween(listener->l_unackd, listener->l_nxt_seq, tdb->ack) &&
9624                         ((!require3Way || midstream_allowed) ||
9625                          ((talker->s_mgr.sub_state == SUB_SETUP_OK) &&
9626                           (listener->s_mgr.sub_state == SUB_SETUP_OK)) ))
9627                 {
9628                     UpdateSsn(p, listener, talker, tdb);
9629                     scb->ha_state.session_flags |= SSNFLAG_ESTABLISHED;
9630                     scb->session_state |= STREAM_STATE_ESTABLISHED;
9631                     listener->s_mgr.state = TCP_STATE_ESTABLISHED;
9632                     talker->s_mgr.state = TCP_STATE_ESTABLISHED;
9633                     StreamUpdatePerfBaseState(&sfBase, scb, TCP_STATE_ESTABLISHED);
9634                     /* Indicate this packet completes 3-way handshake */
9635                     p->packet_flags |= PKT_STREAM_TWH;
9636                 }
9637 
9638                 talker->flags |= got_ts;
9639                 if(got_ts && SEQ_EQ(listener->r_nxt_ack, tdb->seq))
9640                 {
9641                     talker->ts_last_pkt = p->pkth->ts.tv_sec;
9642                     talker->ts_last = tdb->ts;
9643                 }
9644 
9645                 break;
9646 
9647             case TCP_STATE_ESTABLISHED:
9648                 /* Handle out-of-order/OOO ACK */
9649                 if ((Normalize_GetMode(snort_conf, NORM_TCP_IPS) == NORM_MODE_ON) &&
9650                     (SEQ_GT(tdb->ack, listener->l_nxt_seq)))
9651                 {
9652                     NormalDropPacket(p);
9653                     PREPROC_PROFILE_END(s5TcpStatePerfStats);
9654                     return retcode | ACTION_BAD_PKT;
9655                 }
9656                 UpdateSsn(p, listener, talker, tdb);
9657                 break;
9658 
9659             case TCP_STATE_CLOSE_WAIT:
9660                 UpdateSsn(p, listener, talker, tdb);
9661                 break;
9662 
9663             case TCP_STATE_FIN_WAIT_1:
9664                 STREAM_DEBUG_WRAP(DebugMessage(DEBUG_STREAM_STATE,
9665                             "tdb->ack %X >= talker->r_nxt_ack %X\n",
9666                             tdb->ack, talker->r_nxt_ack););
9667 
9668                 if ( SEQ_EQ(tdb->ack, listener->l_nxt_seq) )
9669                 {
9670                     if ( (listener->os_policy == STREAM_POLICY_WINDOWS) && (tdb->win == 0) )
9671                     {
9672                         eventcode |= EVENT_WINDOW_SLAM;
9673                         Discard();
9674 
9675 #ifdef NORMALIZER
9676                         if ( NormalDropPacket(p) )
9677                         {
9678                             LogTcpEvents(listener->tcp_policy, eventcode);
9679                             PREPROC_PROFILE_END(s5TcpStatePerfStats);
9680                             return retcode | ACTION_BAD_PKT;
9681                         }
9682 #endif
9683                     }
9684 
9685                     UpdateSsn(p, listener, talker, tdb);
9686                     listener->s_mgr.state = TCP_STATE_FIN_WAIT_2;
9687 
9688                     if ( (p->tcph->th_flags & TH_FIN) )
9689                     {
9690                         STREAM_DEBUG_WRAP(DebugMessage(DEBUG_STREAM_STATE,
9691                                     "seq ok, setting state!\n"););
9692 
9693                         if (talker->s_mgr.state_queue == TCP_STATE_NONE)
9694                         {
9695                             talker->s_mgr.state = TCP_STATE_LAST_ACK;
9696                             EndOfFileHandle(p, (TcpSession *)scb->proto_specific_data->data);
9697                         }
9698                         if ( scb->ha_state.session_flags & SSNFLAG_MIDSTREAM )
9699                         {
9700                             // FIXTHIS this should be handled below in fin section
9701                             // but midstream sessions fail the seq test
9702                             listener->s_mgr.state_queue = TCP_STATE_TIME_WAIT;
9703                             listener->s_mgr.transition_seq = tdb->end_seq;
9704                             listener->s_mgr.expected_flags = TH_ACK;
9705                         }
9706                     }
9707                     else if (listener->s_mgr.state_queue == TCP_STATE_CLOSING)
9708                     {
9709                         listener->s_mgr.state_queue = TCP_STATE_TIME_WAIT;
9710                         listener->s_mgr.transition_seq = tdb->end_seq;
9711                         listener->s_mgr.expected_flags = TH_ACK;
9712                     }
9713                 }
9714                 else
9715                 {
9716                     UpdateSsn(p, listener, talker, tdb);
9717                     STREAM_DEBUG_WRAP(DebugMessage(DEBUG_STREAM_STATE,
9718                                 "bad ack!\n"););
9719                 }
9720                 break;
9721 
9722             case TCP_STATE_FIN_WAIT_2:
9723                 if ( SEQ_GT(tdb->ack, listener->l_nxt_seq) )
9724                 {
9725                     eventcode |= EVENT_BAD_ACK;
9726                     LogTcpEvents(talker->tcp_policy, eventcode);
9727                     NormalDropPacket(p);
9728                     PREPROC_PROFILE_END(s5TcpStatePerfStats);
9729                     return retcode | ACTION_BAD_PKT;
9730                 }
9731                 UpdateSsn(p, listener, talker, tdb);
9732                 break;
9733 
9734             case TCP_STATE_CLOSING:
9735                 UpdateSsn(p, listener, talker, tdb);
9736                 if(SEQ_GEQ(tdb->end_seq, listener->r_nxt_ack))
9737                 {
9738                     listener->s_mgr.state = TCP_STATE_TIME_WAIT;
9739                 }
9740                 break;
9741 
9742             case TCP_STATE_LAST_ACK:
9743                 UpdateSsn(p, listener, talker, tdb);
9744 
9745                 if ( SEQ_EQ(tdb->ack, listener->l_nxt_seq) )
9746                 {
9747                     listener->s_mgr.state = TCP_STATE_CLOSED;
9748                 }
9749                 break;
9750 
9751             default:
9752                 // FIXTHIS safe to ignore when inline?
9753                 break;
9754         }
9755     }
9756 
9757 #ifdef HAVE_DAQ_ADDRESS_SPACE_ID
9758             tcpssn->priv_ptr = p->pkth->priv_ptr;
9759 #endif
9760     /*
9761      * handle data in the segment
9762      */
9763     if(p->dsize)
9764     {
9765         STREAM_DEBUG_WRAP(DebugMessage(DEBUG_STREAM_STATE,
9766                     "   %s state: %s(%d) getting data\n", l,
9767                     state_names[listener->s_mgr.state],
9768                     listener->s_mgr.state););
9769 
9770         // FIN means only that sender is done talking,
9771         // other side may continue yapping.
9772         if(TCP_STATE_FIN_WAIT_2 == talker->s_mgr.state ||
9773                 TCP_STATE_TIME_WAIT == talker->s_mgr.state)
9774         {
9775             /* data on a segment when we're not accepting data any more */
9776             /* alert! */
9777             //EventDataOnClosed(talker->tcp_policy);
9778             eventcode |= EVENT_DATA_ON_CLOSED;
9779             retcode |= ACTION_BAD_PKT;
9780             NormalDropPacket(p);
9781         }
9782         else if (TCP_STATE_CLOSED == talker->s_mgr.state)
9783         {
9784             /* data on a segment when we're not accepting data any more */
9785             /* alert! */
9786             if (scb->ha_state.session_flags & SSNFLAG_RESET)
9787             {
9788                 // no need to run detection PPs on this packet
9789                 DisableDetect( p );
9790 
9791                 //EventDataAfterReset(listener->tcp_policy);
9792                 if ( talker->s_mgr.sub_state & SUB_RST_SENT )
9793                     eventcode |= EVENT_DATA_AFTER_RESET;
9794                 else
9795                     eventcode |= EVENT_DATA_AFTER_RST_RCVD;
9796             }
9797             else
9798             {
9799                 //EventDataOnClosed(listener->tcp_policy);
9800                 eventcode |= EVENT_DATA_ON_CLOSED;
9801             }
9802             retcode |= ACTION_BAD_PKT;
9803             NormalDropPacket(p);
9804         }
9805         else if ((TCP_STATE_FIN_WAIT_1 == talker->s_mgr.state) &&
9806                  SEQ_GEQ(tdb->seq, (listener->s_mgr.transition_seq - 1)))
9807         {
9808             /* Alert! : Data on a segment when we're not accepting data any more */
9809             eventcode |= EVENT_DATA_ON_CLOSED;
9810             retcode |= ACTION_BAD_PKT;
9811             NormalDropPacket(p);
9812         }
9813         else
9814         {
9815             STREAM_DEBUG_WRAP(DebugMessage(DEBUG_STREAM_STATE,
9816                         "Queuing data on listener, t %s, l %s...\n",
9817                         flush_policy_names[talker->flush_mgr.flush_policy],
9818                         flush_policy_names[listener->flush_mgr.flush_policy]););
9819 
9820 #ifdef NORMALIZER
9821             if( s5TcpPolicy->policy != STREAM_POLICY_NOACK )
9822             {
9823                 // these normalizations can't be done if we missed setup. and
9824                 // window is zero in one direction until we've seen both sides.
9825                 // Avoid this normalization for Asymmetric traffic
9826                 if (( !(scb->ha_state.session_flags & SSNFLAG_MIDSTREAM) ) && TwoWayTraffic(scb))
9827                 {
9828                     // sender of syn w/mss limits payloads from peer
9829                     // since we store mss on sender side, use listener mss
9830                     // same reasoning for window size
9831                     StreamTracker* st = listener;
9832 
9833                     // trim to fit in window and mss as needed
9834                     NormalTrimPayloadIfWin(p, (st->r_win_base + st->l_window) - st->r_nxt_ack, tdb);
9835                     if ( st->mss )
9836                         NormalTrimPayloadIfMss(p, st->mss, tdb);
9837 
9838                     NormalCheckECN(tcpssn, p);
9839                 }
9840             }
9841 #endif
9842             /*
9843              * dunno if this is RFC but fragroute testing expects it
9844              * for the record, I've seen FTP data sessions that send
9845              * data packets with no tcp flags set
9846              */
9847             if ((p->tcph->th_flags != 0) || (s5TcpPolicy->policy == STREAM_POLICY_LINUX) || (s5TcpPolicy->policy == STREAM_POLICY_NOACK))
9848             {
9849                 ProcessTcpData(p, listener, tcpssn, tdb, s5TcpPolicy);
9850                 //Check if all segments are received. Process FIN transition
9851                 if(checkFINTransitionStatus(p, listener))
9852                     process_fin = true;
9853             }
9854             else
9855             {
9856                 eventcode |= EVENT_DATA_WITHOUT_FLAGS;
9857                 NormalDropPacket(p);
9858             }
9859         }
9860     }
9861 
9862     if((p->tcph->th_flags & TH_FIN) || process_fin) //FIN is received or process Queued FIN
9863     {
9864         STREAM_DEBUG_WRAP(DebugMessage(DEBUG_STREAM_STATE,
9865                     "Got an FIN...\n"););
9866         STREAM_DEBUG_WRAP(DebugMessage(DEBUG_STREAM_STATE,
9867                     "   %s state: %s(%d)\n", l,
9868                     state_names[talker->s_mgr.state],
9869                     talker->s_mgr.state););
9870 
9871         STREAM_DEBUG_WRAP(DebugMessage(DEBUG_STREAM_STATE,
9872                     "checking ack (0x%X) vs nxt_ack (0x%X)\n",
9873                     tdb->end_seq, listener->r_win_base););
9874 
9875         if(SEQ_LT(tdb->end_seq,listener->r_win_base))
9876         {
9877             STREAM_DEBUG_WRAP(DebugMessage(DEBUG_STREAM_STATE,
9878                         "FIN inside r_win_base, bailing\n"););
9879             goto dupfin;
9880         }
9881         else
9882         {
9883             //FIN is in order or we need to process FIN from state_queue
9884             if((tdb->end_seq == listener->r_nxt_ack) ||  process_fin ||
9885                 (talker->s_mgr.state > TCP_STATE_ESTABLISHED) ||
9886                 (listener->flush_mgr.flush_policy == STREAM_FLPOLICY_IGNORE))
9887             {
9888                 // need substate since we don't change state immediately
9889                 if ( (talker->s_mgr.state >= TCP_STATE_ESTABLISHED) &&
9890                         !(talker->s_mgr.sub_state & SUB_FIN_SENT) )
9891                 {
9892                     talker->l_nxt_seq++;
9893                     listener->r_nxt_ack++;
9894                     talker->s_mgr.sub_state |= SUB_FIN_SENT;
9895 
9896 #ifdef NORMALIZER
9897                     if ((listener->flush_mgr.flush_policy != STREAM_FLPOLICY_PROTOCOL) &&
9898                             (listener->flush_mgr.flush_policy != STREAM_FLPOLICY_PROTOCOL_IPS) &&
9899                             (listener->flush_mgr.flush_policy != STREAM_FLPOLICY_PROTOCOL_NOACK) &&
9900                             Normalize_GetMode(snort_conf, NORM_TCP_IPS) == NORM_MODE_ON)
9901                     {
9902                         p->packet_flags |= PKT_PDU_TAIL;
9903                     }
9904 #endif
9905                 }
9906                 switch(talker->s_mgr.state)
9907                 {
9908                     case TCP_STATE_SYN_RCVD:
9909                     case TCP_STATE_ESTABLISHED:
9910                         if (talker->s_mgr.state_queue == TCP_STATE_CLOSE_WAIT)
9911                         {
9912                             talker->s_mgr.state_queue = TCP_STATE_CLOSING;
9913                         }
9914                         talker->s_mgr.state = TCP_STATE_FIN_WAIT_1;
9915                         EndOfFileHandle(p, (TcpSession *) scb->proto_specific_data->data);
9916 #ifdef NORMALIZER
9917                         if ( !p->dsize )
9918                             CheckFlushPolicyOnData( ( ( StreamConfig * ) scb->stream_config )->tcp_config,
9919                                     tcpssn, talker, listener, tdb, p);
9920 #endif
9921                         StreamUpdatePerfBaseState(&sfBase, scb, TCP_STATE_CLOSING);
9922                         break;
9923 
9924                     case TCP_STATE_CLOSE_WAIT:
9925                         talker->s_mgr.state = TCP_STATE_LAST_ACK;
9926                         break;
9927 
9928                     case TCP_STATE_FIN_WAIT_1:
9929                         if (!p->dsize)
9930                             RetransmitHandle(p, tcpssn);
9931                         break;
9932 
9933                     default:
9934                         /* all other states stay where they are */
9935                         break;
9936                 }
9937 
9938                 if (!process_fin && ((talker->s_mgr.state == TCP_STATE_FIN_WAIT_1) ||
9939                         (talker->s_mgr.state == TCP_STATE_LAST_ACK)))
9940                 {
9941                     uint32_t end_seq = ( scb->ha_state.session_flags & SSNFLAG_MIDSTREAM ) ?
9942                         tdb->end_seq-1 : tdb->end_seq;
9943 
9944                     if ( (listener->s_mgr.expected_flags == TH_ACK) &&
9945                             SEQ_GEQ(end_seq, listener->s_mgr.transition_seq) )
9946                     {
9947                         STREAM_DEBUG_WRAP(DebugMessage(DEBUG_STREAM_STATE,
9948                                     "FIN beyond previous, ignoring\n"););
9949                         eventcode |= EVENT_BAD_FIN;
9950                         LogTcpEvents(talker->tcp_policy, eventcode);
9951                         NormalDropPacket(p);
9952                         PREPROC_PROFILE_END(s5TcpStatePerfStats);
9953 #ifdef HAVE_DAQ_ADDRESS_SPACE_ID
9954                         tcpssn->priv_ptr = NULL;
9955 #endif
9956                         return retcode | ACTION_BAD_PKT;
9957                     }
9958                 }
9959 
9960                 if(!process_fin)
9961                 {
9962                     switch ( listener->s_mgr.state )
9963                     {
9964                         case TCP_STATE_ESTABLISHED:
9965                             listener->s_mgr.state_queue = TCP_STATE_CLOSE_WAIT;
9966                             listener->s_mgr.transition_seq = tdb->end_seq + 1;
9967                             listener->s_mgr.expected_flags = TH_ACK;
9968                             break;
9969 
9970                         case TCP_STATE_FIN_WAIT_1:
9971                             listener->s_mgr.state_queue = TCP_STATE_CLOSING;
9972                             listener->s_mgr.transition_seq = tdb->end_seq + 1;
9973                             listener->s_mgr.expected_flags = TH_ACK;
9974                             break;
9975 
9976                         case TCP_STATE_FIN_WAIT_2:
9977                             listener->s_mgr.state_queue = TCP_STATE_TIME_WAIT;
9978                             listener->s_mgr.transition_seq = tdb->end_seq + 1;
9979                             listener->s_mgr.expected_flags = TH_ACK;
9980                             break;
9981 
9982                         case TCP_STATE_CLOSED:
9983                             listener->s_mgr.transition_seq = tdb->end_seq + 1;
9984                             break;
9985                     }
9986                 }
9987             }
9988             else
9989             {
9990                 //OOO FIN received
9991                 if((listener->s_mgr.state_queue == TCP_STATE_CLOSE_WAIT) && SEQ_LT(tdb->end_seq,listener->s_mgr.transition_seq))
9992                 {
9993                     STREAM_DEBUG_WRAP(DebugMessage(DEBUG_STREAM_STATE,
9994                                 "FIN inside transition_seq, bailing\n"););
9995                     goto dupfin;
9996                 }
9997                 if ((listener->s_mgr.state_queue == TCP_STATE_CLOSE_WAIT) ||
9998                         (talker->s_mgr.state == TCP_STATE_FIN_WAIT_1) ||
9999                             (talker->s_mgr.state == TCP_STATE_LAST_ACK))
10000                 {
10001                     uint32_t end_seq = ( scb->ha_state.session_flags & SSNFLAG_MIDSTREAM ) ?
10002                         tdb->end_seq-1 : tdb->end_seq;
10003 
10004                     if ( (listener->s_mgr.expected_flags == TH_ACK) &&
10005                             SEQ_GEQ(end_seq, listener->s_mgr.transition_seq) )
10006                     {
10007                         STREAM_DEBUG_WRAP(DebugMessage(DEBUG_STREAM_STATE,
10008                                     "FIN beyond previous, ignoring\n"););
10009                         eventcode |= EVENT_BAD_FIN;
10010                         LogTcpEvents(talker->tcp_policy, eventcode);
10011                         NormalDropPacket(p);
10012                         PREPROC_PROFILE_END(s5TcpStatePerfStats);
10013 #ifdef HAVE_DAQ_ADDRESS_SPACE_ID
10014                         tcpssn->priv_ptr = NULL;
10015 #endif
10016                         return retcode | ACTION_BAD_PKT;
10017                     }
10018                 }
10019                 switch ( listener->s_mgr.state )
10020                 {
10021                     case TCP_STATE_ESTABLISHED:
10022                         listener->s_mgr.state_queue = TCP_STATE_CLOSE_WAIT;
10023                         listener->s_mgr.transition_seq = tdb->end_seq + 1;
10024                         listener->s_mgr.expected_flags = TH_ACK;
10025                         break;
10026 
10027                     case TCP_STATE_CLOSED:
10028                         listener->s_mgr.transition_seq = tdb->end_seq + 1;
10029                         break;
10030                 }
10031             }
10032         }
10033     }
10034 
10035 dupfin:
10036 
10037     STREAM_DEBUG_WRAP(DebugMessage(DEBUG_STREAM_STATE,
10038                 "   %s [talker] state: %s\n", t,
10039                 state_names[talker->s_mgr.state]););
10040     STREAM_DEBUG_WRAP(DebugMessage(DEBUG_STREAM_STATE,
10041                 "   %s state: %s(%d)\n", l,
10042                 state_names[listener->s_mgr.state],
10043                 listener->s_mgr.state););
10044 
10045     /*
10046      * handle TIME_WAIT timer stuff
10047      */
10048 
10049     /* Handle Asymmetric connection closing, we will see only one
10050      * direction pkts. FIN_ACK handling.
10051      * Do not set state to closed prematurely when handling retry packets
10052      * to avoid retry loop - CSCvc08844.
10053      */
10054     if((!TwoWayTraffic(scb) &&
10055 #ifdef DAQ_PKT_FLAG_RETRY_PACKET
10056         !(p->pkth->flags & DAQ_PKT_FLAG_RETRY_PACKET) &&
10057 #endif
10058         (talker->s_mgr.state >= TCP_STATE_FIN_WAIT_1 || listener->s_mgr.state >= TCP_STATE_FIN_WAIT_1)))
10059     {
10060         if (TCP_ISFLAGSET(p->tcph, (TH_FIN|TH_ACK)))
10061         {
10062             if(talker->s_mgr.state >= TCP_STATE_FIN_WAIT_1)
10063                 talker->s_mgr.state = TCP_STATE_CLOSED;
10064             if(listener->s_mgr.state >= TCP_STATE_FIN_WAIT_1)
10065                 listener->s_mgr.state = TCP_STATE_CLOSED;
10066             listener->flags |= TF_FORCE_FLUSH;
10067         }
10068     }
10069 
10070     if((talker->s_mgr.state == TCP_STATE_TIME_WAIT && listener->s_mgr.state == TCP_STATE_CLOSED) ||
10071             (listener->s_mgr.state == TCP_STATE_TIME_WAIT && talker->s_mgr.state == TCP_STATE_CLOSED) ||
10072             (listener->s_mgr.state == TCP_STATE_TIME_WAIT && talker->s_mgr.state == TCP_STATE_TIME_WAIT)||
10073             (!TwoWayTraffic(scb)&& (talker->s_mgr.state == TCP_STATE_CLOSED || listener->s_mgr.state == TCP_STATE_CLOSED)))
10074     {
10075         //dropssn:
10076         STREAM_DEBUG_WRAP(DebugMessage(DEBUG_STREAM_STATE,
10077                     "Session terminating, flushing session buffers\n"););
10078 
10079 #ifdef HAVE_DAQ_ADDRESS_SPACE_ID
10080         tcpssn->priv_ptr = NULL;
10081 #endif
10082         if ( p->tcph->th_flags & TH_ACK )
10083             CheckFlushPolicyOnAck( ( ( StreamConfig * ) scb->stream_config )->tcp_config,
10084                        tcpssn, talker, listener, tdb, p);
10085 
10086         if(p->packet_flags & PKT_FROM_SERVER)
10087         {
10088             STREAM_DEBUG_WRAP(DebugMessage(DEBUG_STREAM_STATE,
10089                         "flushing FROM_SERVER\n"););
10090             if(talker->seg_bytes_logical)
10091             {
10092                 uint32_t flushed = flush_stream(tcpssn, talker, p,
10093                         GET_DST_IP(p), GET_SRC_IP(p),
10094                         p->tcph->th_dport, p->tcph->th_sport,
10095                         PKT_FROM_CLIENT);
10096 
10097                 if(flushed)
10098                 {
10099                     // FIXTHIS - these calls redundant?
10100                     purge_alerts(talker, talker->r_win_base, (void *)tcpssn->scb);
10101                     purge_to_seq(tcpssn, talker, talker->seglist->seq + flushed);
10102                 }
10103             }
10104 
10105             if(listener->seg_bytes_logical)
10106             {
10107                 uint32_t flushed = flush_stream(tcpssn, listener, p,
10108                         GET_SRC_IP(p), GET_DST_IP(p),
10109                         p->tcph->th_sport, p->tcph->th_dport,
10110                         PKT_FROM_SERVER);
10111 
10112                 if(flushed)
10113                 {
10114                     purge_alerts(listener, listener->r_win_base, (void *)tcpssn->scb);
10115                     purge_to_seq(tcpssn, listener, listener->seglist->seq + flushed);
10116                 }
10117             }
10118         }
10119         else
10120         {
10121             STREAM_DEBUG_WRAP(DebugMessage(DEBUG_STREAM_STATE,
10122                         "flushing FROM_CLIENT\n"););
10123             if(listener->seg_bytes_logical)
10124             {
10125                 uint32_t flushed = flush_stream(tcpssn, listener, p,
10126                         GET_SRC_IP(p), GET_DST_IP(p),
10127                         p->tcph->th_sport, p->tcph->th_dport,
10128                         PKT_FROM_CLIENT);
10129 
10130                 if(flushed)
10131                 {
10132                     purge_alerts(listener, listener->r_win_base, (void *)tcpssn->scb);
10133                     purge_to_seq(tcpssn, listener, listener->seglist->seq + flushed);
10134                 }
10135             }
10136 
10137             if(talker->seg_bytes_logical)
10138             {
10139                 uint32_t flushed = flush_stream(tcpssn, talker, p,
10140                         GET_DST_IP(p), GET_SRC_IP(p),
10141                         p->tcph->th_dport, p->tcph->th_sport,
10142                         PKT_FROM_SERVER);
10143 
10144                 if(flushed)
10145                 {
10146                     purge_alerts(talker, talker->r_win_base,(void *)tcpssn->scb);
10147                     purge_to_seq(tcpssn, talker, talker->seglist->seq + flushed);
10148                 }
10149             }
10150         }
10151         LogTcpEvents(listener->tcp_policy, eventcode);
10152         /* The last ACK is a part of the session.  Delete the session after processing is complete. */
10153         TcpSessionCleanup(scb, 0);
10154         scb->session_state |= STREAM_STATE_CLOSED;
10155         PREPROC_PROFILE_END(s5TcpStatePerfStats);
10156         return retcode | ACTION_LWSSN_CLOSED;
10157     }
10158     else if(listener->s_mgr.state == TCP_STATE_CLOSED && talker->s_mgr.state == TCP_STATE_SYN_SENT)
10159     {
10160         if(p->tcph->th_flags & TH_SYN &&
10161                 !(p->tcph->th_flags & TH_ACK) &&
10162                 !(p->tcph->th_flags & TH_RST))
10163         {
10164           session_api->set_expire_timer(p, scb, s5TcpPolicy->session_timeout);
10165         }
10166     }
10167 
10168     if((listener->flush_mgr.flush_policy == STREAM_FLPOLICY_FOOTPRINT_NOACK)
10169             || (listener->flush_mgr.flush_policy == STREAM_FLPOLICY_PROTOCOL_NOACK))
10170     {
10171         uint32_t flushed = 0;
10172         flushed = CheckFlushPolicyOnData( ( ( StreamConfig * ) scb->stream_config )->tcp_config,
10173                                 tcpssn, talker, listener, tdb, p);
10174         if (flushed)
10175         {
10176              if(listener->xtradata_mask && extra_data_log)
10177                   purge_alerts(listener, listener->seglist->seq + flushed, (void *)tcpssn->scb);
10178         }
10179     }
10180 #ifdef NORMALIZER
10181     else if ( p->dsize > 0 )
10182     {
10183         /* in case of Asymmetric traffic, enfore flush_policy from STREAM_FLPOLICY_FOOTPRINT to STREAM_FLPOLICY_FOOTPRINT_IPS
10184          * This will be applied on passive mode sessions, which has policy mode as STREAM_FLPOLICY_FOOTPRINT only
10185          */
10186         uint32_t flushed = 0;
10187         if (!TwoWayTraffic(scb) &&
10188                 (scb->session_state & ( STREAM_STATE_SYN | STREAM_STATE_SYN_ACK)) &&
10189                 !TCP_ISFLAGSET(p->tcph, TH_SYN))
10190         {
10191             if(listener->flush_mgr.flush_policy == STREAM_FLPOLICY_PROTOCOL)
10192                 listener->flush_mgr.flush_policy = STREAM_FLPOLICY_PROTOCOL_IPS;
10193             else if(listener->flush_mgr.flush_policy == STREAM_FLPOLICY_FOOTPRINT)
10194                 listener->flush_mgr.flush_policy = STREAM_FLPOLICY_FOOTPRINT_IPS;
10195         }
10196 
10197         flushed = CheckFlushPolicyOnData( ( ( StreamConfig * ) scb->stream_config )->tcp_config,
10198                                 tcpssn, talker, listener, tdb, p);
10199         if (!TwoWayTraffic(scb) && flushed &&
10200                 (scb->session_state & ( STREAM_STATE_SYN | STREAM_STATE_SYN_ACK)) &&
10201                 !TCP_ISFLAGSET(p->tcph, TH_SYN))
10202         {
10203             purge_to_seq(tcpssn, listener, listener->seglist->seq + flushed);
10204         }
10205         else if(flushed)
10206         {
10207             if(listener->xtradata_mask && extra_data_log)
10208                  purge_alerts(listener, listener->seglist->seq + flushed, (void *)tcpssn->scb);
10209         }
10210     }
10211 #endif
10212 
10213     if ( p->tcph->th_flags & TH_ACK )
10214         CheckFlushPolicyOnAck( ( ( StreamConfig * ) scb->stream_config )->tcp_config,
10215                                tcpssn, talker, listener, tdb, p);
10216 
10217     LogTcpEvents(listener->tcp_policy, eventcode);
10218     PREPROC_PROFILE_END(s5TcpStatePerfStats);
10219 #ifdef HAVE_DAQ_ADDRESS_SPACE_ID
10220     tcpssn->priv_ptr = NULL;
10221 #endif
10222     return retcode;
10223 }
10224 
10225 // this is for post-ack flushing
GetReverseDir(const Packet * p)10226 static inline uint32_t GetReverseDir (const Packet* p)
10227 {
10228     /* Remember, one side's packets are stored in the
10229      * other side's queue.  So when talker ACKs data,
10230      * we need to check if we're ready to flush.
10231      *
10232      * If we do decide to flush, the flush IP & port info
10233      * is the opposite of the packet -- again because this
10234      * is the ACK from the talker and we're flushing packets
10235      * that actually came from the listener.
10236      */
10237     if ( p->packet_flags & PKT_FROM_SERVER )
10238         return PKT_FROM_CLIENT;
10239 
10240     else if ( p->packet_flags & PKT_FROM_CLIENT )
10241         return PKT_FROM_SERVER;
10242 
10243     return 0;
10244 }
10245 
10246 #ifdef NORMALIZER
GetForwardDir(const Packet * p)10247 static inline uint32_t GetForwardDir (const Packet* p)
10248 {
10249     if ( p->packet_flags & PKT_FROM_SERVER )
10250         return PKT_FROM_SERVER;
10251 
10252     else if ( p->packet_flags & PKT_FROM_CLIENT )
10253         return PKT_FROM_CLIENT;
10254 
10255     return 0;
10256 }
10257 
CheckFlushCoercion(Packet * p,FlushMgr * fm,uint16_t flush_factor)10258 static inline int CheckFlushCoercion (
10259         Packet* p, FlushMgr* fm, uint16_t flush_factor
10260         ) {
10261     if ( !flush_factor )
10262         return 0;
10263 
10264     if (
10265             p->dsize &&
10266             (p->dsize < fm->last_size) &&
10267             (fm->last_count >= flush_factor) )
10268     {
10269         fm->last_size = 0;
10270         fm->last_count = 0;
10271         return 1;
10272     }
10273     if ( p->dsize > fm->last_size )
10274         fm->last_size = p->dsize;
10275 
10276     fm->last_count++;
10277     return 0;
10278 }
10279 
CheckFTPFlushCoercion(Packet * p,FlushMgr * fm)10280 static inline int CheckFTPFlushCoercion (Packet* p, FlushMgr* fm)
10281 {
10282 #ifdef HAVE_DAQ_DECRYPTED_SSL
10283     if (p->pkth->flags & DAQ_PKT_FLAG_DECRYPTED_SSL)
10284     {
10285       if (fm->flush)
10286         return 1;
10287       else
10288         return 0;
10289     }
10290 #endif
10291     if( p->dsize && p->dsize != fm->last_size )
10292     {
10293         fm->last_size = p->dsize;
10294         return 1;
10295     }
10296     return 0;
10297 }
10298 #endif
10299 
AutoDisable(StreamTracker * a,StreamTracker * b)10300 static inline bool AutoDisable (StreamTracker* a, StreamTracker* b)
10301 {
10302     if ( !a->flush_mgr.auto_disable )
10303         return false;
10304 
10305     a->flush_mgr.flush_policy = STREAM_FLPOLICY_IGNORE;
10306     purge_all(a);
10307 
10308     if ( b->flush_mgr.auto_disable )
10309     {
10310         b->flush_mgr.flush_policy = STREAM_FLPOLICY_IGNORE;
10311         purge_all(b);
10312     }
10313     return true;
10314 }
10315 
10316 #ifdef NORMALIZER
10317 /*
10318  * In case of Pre-ACK mode, check if we need to
10319  * block packet so that the payload deos not reach endpoint without
10320  * inspection.
10321  */
check_to_hold_packet(Packet * pkt,PAF_Status paf_state,StreamTracker * trk)10322 static inline bool check_to_hold_packet(Packet *pkt, PAF_Status paf_state,
10323             StreamTracker *trk)
10324 {
10325     if (((paf_state == PAF_PSEUDO_FLUSH_SEARCH) ||
10326          (paf_state == PAF_PSEUDO_FLUSH_SKIP)) &&
10327         !(pkt->packet_flags & PKT_PSEUDO_FLUSH))
10328         {
10329             if(trk->held_segment != NULL)
10330                 return FALSE;
10331 
10332             return TRUE;
10333         }
10334         return FALSE;
10335 }
10336 
hold_packet(Packet * pkt,StreamTracker * trk,StreamSegment * seg)10337 static inline void hold_packet(Packet *pkt, StreamTracker *trk,
10338      StreamSegment *seg)
10339 {
10340     trk->held_segment = seg;
10341     pkt->packet_flags |= PKT_FAST_BLOCK;
10342     Active_DropPacket(pkt);
10343 }
10344 
10345 // see flush_pdu_ackd() for details
10346 // the key difference is that we operate on forward moving data
10347 // because we don't wait until it is acknowledged
flush_pdu_ips(StreamTcpConfig * config,TcpSession * ssn,StreamTracker * trk,Packet * pkt,uint64_t * flags)10348 static inline uint32_t flush_pdu_ips ( StreamTcpConfig *config, TcpSession *ssn,
10349                                        StreamTracker *trk, Packet *pkt, uint64_t *flags )
10350 {
10351     bool to_srv = ( *flags == PKT_FROM_CLIENT );
10352     uint16_t srv_port = ( to_srv ? pkt->dp : pkt->sp );
10353     uint32_t total = 0, avail;
10354     StreamSegment* seg;
10355     PROFILE_VARS;
10356 
10357     PREPROC_PROFILE_START(s5TcpPAFPerfStats);
10358     avail = get_q_sequenced(trk);
10359     seg = trk->seglist_next;
10360 
10361     // * must stop if gap (checked in s5_paf_check)
10362     while ( seg && *flags && (total < avail) )
10363     {
10364         uint32_t flush_pt;
10365         uint32_t size = seg->size;
10366         uint32_t end = seg->seq + seg->size;
10367         uint32_t pos = s5_paf_position(&trk->paf_state);
10368 
10369         total += size;
10370 
10371         if ( s5_paf_initialized(&trk->paf_state) && SEQ_LEQ(end, pos) )
10372         {
10373             if (!seg->next && pkt->packet_flags & PKT_PSEUDO_FLUSH)
10374             {
10375                 *flags |= PKT_PSEUDO_FLUSH;
10376             } else {
10377                 seg = seg->next;
10378                 continue;
10379             }
10380         }
10381         //Used by h2_paf
10382         wire_packet = pkt;
10383         flush_policy_for_dir = trk->flush_mgr.flush_policy;
10384         flush_pt = s5_paf_check( config->paf_config, &trk->paf_state, ssn->scb,
10385                                  seg->payload, size, total, seg->seq, srv_port,
10386                                  flags, trk->flush_mgr.flush_pt);
10387 
10388         if (check_to_hold_packet(pkt, trk->paf_state.paf, trk))
10389         {
10390                 hold_packet(pkt, trk, seg);
10391         }
10392 
10393         if (*flags & PKT_PURGE)
10394         {
10395             //For HTTP/2 case where stream doesnt flush the data
10396             //Set the seglist value to SL_BUF_FLUSHED
10397             STREAM_DEBUG_WRAP(DebugMessage(DEBUG_STREAM_STATE,
10398                 "flush_pdu_ips and purge\n"););
10399             seg->buffered = SL_BUF_FLUSHED;
10400             return 0;
10401 
10402         }
10403         if ( flush_pt > 0 )
10404         {
10405             PREPROC_PROFILE_END(s5TcpPAFPerfStats);
10406             return flush_pt;
10407         }
10408         seg = seg->next;
10409     }
10410 
10411     PREPROC_PROFILE_END(s5TcpPAFPerfStats);
10412     return 0;
10413 }
10414 
CheckFlushPolicyOnData(StreamTcpConfig * config,TcpSession * tcpssn,StreamTracker * talker,StreamTracker * listener,TcpDataBlock * tdb,Packet * p)10415 static inline int CheckFlushPolicyOnData( StreamTcpConfig *config, TcpSession *tcpssn,
10416                                           StreamTracker *talker, StreamTracker *listener,
10417                                           TcpDataBlock *tdb, Packet *p)
10418 {
10419     uint32_t flushed = 0;
10420     uint32_t avail;
10421 
10422     STREAM_DEBUG_WRAP(DebugMessage(DEBUG_STREAM_STATE,
10423                 "In CheckFlushPolicyOnData\n"););
10424     STREAM_DEBUG_WRAP(DebugMessage(DEBUG_STREAM_STATE,
10425                 "Talker flush policy: %s\n",
10426                 flush_policy_names[talker->flush_mgr.flush_policy]););
10427     STREAM_DEBUG_WRAP(DebugMessage(DEBUG_STREAM_STATE,
10428                 "Listener flush policy: %s\n",
10429                 flush_policy_names[listener->flush_mgr.flush_policy]););
10430 
10431     switch(listener->flush_mgr.flush_policy)
10432     {
10433         case STREAM_FLPOLICY_IGNORE:
10434             STREAM_DEBUG_WRAP(DebugMessage(DEBUG_STREAM_STATE,
10435                         "STREAM_FLPOLICY_IGNORE\n"););
10436             return 0;
10437 
10438         case STREAM_FLPOLICY_FOOTPRINT_IPS_FTP:
10439             {
10440                 int coerce = 0;
10441                 STREAM_DEBUG_WRAP(DebugMessage(DEBUG_STREAM_STATE,
10442                             "STREAM_FLPOLICY_FOOTPRINT-IPS_FTP\n"););
10443 
10444 #ifdef NORMALIZER
10445                 if ( Normalize_GetMode(snort_conf, NORM_TCP_IPS) == NORM_MODE_ON )
10446                 {
10447 #ifdef DAQ_PKT_FLAG_SSL_DETECTED
10448                     //Do not do FTP-Normalization for FTPS traffic
10449                     if((p->pkth->flags & DAQ_PKT_FLAG_SSL_DETECTED) || (p->pkth->flags & DAQ_PKT_FLAG_SSL_SHELLO))
10450                     {
10451                         tcpssn->pp_flags |= PP_FTPTELNET_FTPS;
10452                         listener->flush_mgr.last_size = 0;
10453                     }
10454 #endif
10455                     if(!(tcpssn->pp_flags & PP_FTPTELNET_FTPS))
10456                     {
10457                         if(!listener->flush_mgr.last_size)
10458                         {
10459                             //Rely on mss if it exists, else use snaplen
10460                             if((tcpssn->client.mss > 0) && (tcpssn->server.mss > 0))
10461                             {
10462                                 uint32_t ftp_data_conn_mss = (tcpssn->client.mss < tcpssn->server.mss) ? tcpssn->client.mss : tcpssn->server.mss;
10463                                 listener->flush_mgr.last_size = ftp_data_conn_mss - p->tcp_options_len;
10464                             }
10465                             else
10466                                 listener->flush_mgr.last_size = pkt_snaplen - (p->data - p->pkt);
10467                         }
10468                         coerce = CheckFTPFlushCoercion(p, &listener->flush_mgr);
10469                         if(coerce)
10470                             CallFTPFlushProcessor(p);
10471                         listener->flush_mgr.flush = false;
10472                         talker->flush_mgr.flush = false;
10473                     }
10474                     if(!coerce)
10475                     {
10476                         if(tcpssn->pp_flags & PP_FTPTELNET_FTPS)
10477                             coerce = CheckFlushCoercion(p, &listener->flush_mgr, listener->tcp_policy->flush_factor);
10478                         avail = get_q_sequenced(listener);
10479 
10480                         if (
10481                                 (avail > 0) &&
10482                                 (coerce || (avail >= listener->flush_mgr.flush_pt) ||
10483                                  (avail && talker->s_mgr.state == TCP_STATE_FIN_WAIT_1))
10484                            ) {
10485                             uint32_t dir = GetForwardDir(p);
10486 
10487                             if ( talker->s_mgr.state == TCP_STATE_FIN_WAIT_1 )
10488                                 listener->flags |= TF_FORCE_FLUSH;
10489 
10490                             flushed = flush_to_seq(
10491                                     tcpssn, listener, avail, p,
10492                                     GET_SRC_IP(p), GET_DST_IP(p),
10493                                     p->tcph->th_sport, p->tcph->th_dport, dir);
10494                         }
10495                     }
10496                 }
10497 #endif
10498             }
10499             break;
10500 
10501         case STREAM_FLPOLICY_FOOTPRINT_IPS:
10502             {
10503                 int coerce;
10504                 STREAM_DEBUG_WRAP(DebugMessage(DEBUG_STREAM_STATE,
10505                             "STREAM_FLPOLICY_FOOTPRINT-IPS\n"););
10506 
10507                 avail = get_q_sequenced(listener);
10508                 coerce = CheckFlushCoercion(
10509                         p, &listener->flush_mgr, listener->tcp_policy->flush_factor);
10510 
10511                 if (
10512                         (avail > 0) &&
10513                         (coerce || (avail >= listener->flush_mgr.flush_pt) ||
10514                          (avail && talker->s_mgr.state == TCP_STATE_FIN_WAIT_1))
10515                    ) {
10516                     uint32_t dir = GetForwardDir(p);
10517 
10518                     if ( talker->s_mgr.state == TCP_STATE_FIN_WAIT_1 )
10519                         listener->flags |= TF_FORCE_FLUSH;
10520 
10521                     flushed = flush_to_seq(
10522                             tcpssn, listener, avail, p,
10523                             GET_SRC_IP(p), GET_DST_IP(p),
10524                             p->tcph->th_sport, p->tcph->th_dport, dir);
10525                 }
10526             }
10527             break;
10528 
10529         case STREAM_FLPOLICY_FOOTPRINT_NOACK:
10530             {
10531                 STREAM_DEBUG_WRAP(DebugMessage(DEBUG_STREAM_STATE,
10532                             "STREAM_FLPOLICY_FOOTPRINT-NOACK\n"););
10533 
10534                 avail = get_q_sequenced(listener);
10535                 CheckFlushCoercion(
10536                         p, &listener->flush_mgr, listener->tcp_policy->flush_factor);
10537 
10538                 if ( avail > 0)
10539                 {
10540                     uint32_t dir = GetForwardDir(p);
10541 
10542                     if ( talker->s_mgr.state == TCP_STATE_FIN_WAIT_1 )
10543                         listener->flags |= TF_FORCE_FLUSH;
10544 
10545                     flushed = flush_to_seq_noack(
10546                             tcpssn, listener, avail, p,
10547                             GET_SRC_IP(p), GET_DST_IP(p),
10548                             p->tcph->th_sport, p->tcph->th_dport, dir);
10549                 }
10550             }
10551             break;
10552 
10553         case STREAM_FLPOLICY_PROTOCOL_IPS:
10554         case STREAM_FLPOLICY_PROTOCOL_NOACK:
10555             {
10556                 uint64_t flags = GetForwardDir(p);
10557                 uint32_t flush_amt = flush_pdu_ips( config, tcpssn, listener, p, &flags);
10558                 uint32_t this_flush;
10559 
10560                 if (flush_amt == 0 && (flags & PKT_PURGE))
10561                 {
10562                     listener->seglist_next->buffered = SL_BUF_FLUSHED;
10563                     break;
10564                 }
10565                 while ( flush_amt > 0 )
10566                 {
10567                     if( flags & PKT_IGNORE )
10568                     {
10569                         StreamSegment *curseg = listener->seglist_next;
10570                         uint32_t size_to_flush = 0;
10571                         //set these ignored segments to FLUSHED
10572                         //so that these gets purged on ack
10573                         while ( curseg )
10574                         {
10575                             if( !curseg->buffered )
10576                             {
10577                                 size_to_flush += curseg->size;
10578                                 if( size_to_flush == flush_amt )
10579                                 {
10580                                     curseg->buffered = SL_BUF_FLUSHED;
10581                                     break;
10582                                 }
10583                                 else if( size_to_flush > flush_amt )
10584                                 {
10585                                     unsigned int  bytes_to_copy = curseg->size - (  size_to_flush - flush_amt);
10586                                     StreamSegment *newseg = NULL;
10587 
10588                                     if ( DupStreamNode(NULL, listener, curseg, &newseg) == STREAM_INSERT_OK )
10589                                     {
10590                                         curseg->size = bytes_to_copy;
10591                                         newseg->seq += bytes_to_copy;
10592                                         newseg->size -= bytes_to_copy;
10593                                         newseg->payload += bytes_to_copy + (curseg->payload - curseg->data);
10594                                         curseg->buffered = SL_BUF_FLUSHED;
10595                                     }
10596                                     break;
10597                                 }
10598                                 curseg->buffered = SL_BUF_FLUSHED;
10599                             }
10600                             curseg = curseg->next;
10601                         }
10602 
10603                         this_flush = flush_amt;
10604                         flags &= ~PKT_IGNORE;
10605                     }
10606                     // if this payload is exactly one pdu, don't
10607                     // actually flush, just use the raw packet
10608 
10609                     /*
10610                      * For pseudo flush case, fall back to the regular
10611                      * flush routine which takes care of handling
10612                      * pseudo flush case.
10613                      */
10614                     else if (!(p->packet_flags & PKT_PSEUDO_FLUSH) &&
10615                          listener->seglist_next &&
10616                         (tdb->seq == listener->seglist_next->seq) &&
10617                         (flush_amt == listener->seglist_next->size) &&
10618                         (flush_amt == p->dsize) )
10619                     {
10620                         this_flush = flush_amt;
10621                         if(!listener->paf_state.fpt_eoh){
10622                             listener->seglist_next->buffered = SL_BUF_FLUSHED;
10623                             listener->flush_count++;
10624                         }
10625                         p->packet_flags |=  flags & PKT_PDU_FULL;
10626                         /* Raw packet with only and complete http-post header is set with PKT_EVAL_DROP,
10627                          * it will be used to evalute drop/allow packet by preprocs
10628                          */
10629                         if (listener->paf_state.fpt_eoh)
10630                         {
10631                             p->packet_flags |= PKT_EVAL_DROP;
10632                         }
10633                         ShowRebuiltPacket(p);
10634                     }
10635                     else
10636                     {
10637                         this_flush = flush_to_seq(
10638                                 tcpssn, listener, flush_amt, p,
10639                                 GET_SRC_IP(p), GET_DST_IP(p),
10640                                 p->tcph->th_sport, p->tcph->th_dport, flags);
10641                     }
10642                     // if we didn't flush as expected, bail
10643                     // (we can flush less than max dsize)
10644                     if ( !this_flush )
10645                         break;
10646 
10647                     if(listener->paf_state.fpt_eoh)
10648                     {
10649                         listener->paf_state.fpt_eoh = 0;
10650                         tcpssn->pp_flags &= ~(PP_HTTPINSPECT_PAF_FLUSH_POST_HDR);
10651                     }
10652                     else
10653                         flushed += this_flush;
10654                     flags = GetForwardDir(p);
10655                     flush_amt = flush_pdu_ips( config, tcpssn, listener, p, &flags);
10656                 }
10657                 if ( !flags )
10658                 {
10659                     if ( AutoDisable(listener, talker) )
10660                         return 0;
10661 
10662                     if ( listener->flush_mgr.flush_policy == STREAM_FLPOLICY_PROTOCOL_NOACK )
10663                         listener->flush_mgr.flush_policy = STREAM_FLPOLICY_FOOTPRINT_NOACK;
10664                     else
10665                         listener->flush_mgr.flush_policy = STREAM_FLPOLICY_FOOTPRINT_IPS;
10666                     listener->flush_mgr.flush_pt += ScPafMax();
10667                     listener->flush_mgr.flush_type = STREAM_FT_PAF_MAX;
10668 
10669                     return CheckFlushPolicyOnData( config, tcpssn, talker, listener, tdb, p);
10670                 }
10671             }
10672             break;
10673     }
10674     listener->paf_state.fpt_eoh = 0;
10675     tcpssn->pp_flags &= ~(PP_HTTPINSPECT_PAF_FLUSH_POST_HDR);
10676     return flushed;
10677 }
10678 #endif
10679 
10680 // iterate over seglist and scan all new acked bytes
10681 // - new means not yet scanned
10682 // - must use seglist data (not packet) since this packet may plug a
10683 //   hole and enable paf scanning of following segments
10684 // - if we reach a flush point
10685 //   - return bytes to flush if data available (must be acked)
10686 //   - return zero if not yet received or received but not acked
10687 // - if we reach a skip point
10688 //   - jump ahead and resume scanning any available data
10689 // - must stop if we reach a gap
10690 // - one segment may lead to multiple checks since
10691 //   it may contain multiple encapsulated PDUs
10692 // - if we partially scan a segment we must save state so we
10693 //   know where we left off and can resume scanning the remainder
10694 
flush_pdu_ackd(StreamTcpConfig * config,TcpSession * ssn,StreamTracker * trk,Packet * pkt,uint64_t * flags)10695 static inline uint32_t flush_pdu_ackd ( StreamTcpConfig *config, TcpSession* ssn,
10696                                         StreamTracker* trk, Packet* pkt, uint64_t* flags)
10697 {
10698     bool to_srv = ( *flags == PKT_FROM_CLIENT );
10699     uint16_t srv_port = ( to_srv ? pkt->sp : pkt->dp );
10700     uint32_t total = 0;
10701     StreamSegment* seg;
10702     PROFILE_VARS;
10703 
10704     PREPROC_PROFILE_START(s5TcpPAFPerfStats);
10705     seg = SEQ_LT(trk->seglist_base_seq, trk->r_win_base) ? trk->seglist : NULL;
10706 
10707     // * must stop if not acked
10708     // * must use adjusted size of seg if not fully acked
10709     // * must stop if gap (checked in s5_paf_check)
10710     while ( seg && *flags && SEQ_LT(seg->seq, trk->r_win_base) )
10711     {
10712         uint32_t flush_pt;
10713         uint32_t size = seg->size;
10714         uint32_t end = seg->seq + seg->size;
10715         uint32_t pos = s5_paf_position(&trk->paf_state);
10716 
10717         if ( s5_paf_initialized(&trk->paf_state) && SEQ_LEQ(end, pos) )
10718         {
10719             total += size;
10720             seg = seg->next;
10721             continue;
10722         }
10723         if ( SEQ_GT(end, trk->r_win_base) )
10724             size = trk->r_win_base - seg->seq;
10725 
10726         total += size;
10727 
10728         wire_packet = pkt;
10729         flush_policy_for_dir = trk->flush_mgr.flush_policy;
10730         flush_pt = s5_paf_check( config->paf_config, &trk->paf_state, ssn->scb,
10731                                  seg->payload, size, total, seg->seq, srv_port,
10732                                  flags, trk->flush_mgr.flush_pt);
10733 
10734         if (*flags & PKT_PURGE)
10735         {
10736             //For HTTP 2.0 case where stream doesnt flush the data
10737             //Set the seglist value to SL_BUF_FLUSHED
10738             STREAM_DEBUG_WRAP(DebugMessage(DEBUG_STREAM_STATE,
10739                                  "Flag PKT_PURGE is set"););
10740             seg->buffered = SL_BUF_FLUSHED;
10741             return 0;
10742         }
10743         if ( flush_pt > 0 )
10744         {
10745             PREPROC_PROFILE_END(s5TcpPAFPerfStats);
10746             return flush_pt;
10747         }
10748         seg = seg->next;
10749     }
10750 
10751     PREPROC_PROFILE_END(s5TcpPAFPerfStats);
10752     return 0;
10753 }
10754 
CheckFlushPolicyOnAck(StreamTcpConfig * config,TcpSession * tcpssn,StreamTracker * talker,StreamTracker * listener,TcpDataBlock * tdb,Packet * p)10755 static int CheckFlushPolicyOnAck( StreamTcpConfig *config, TcpSession *tcpssn,
10756                                   StreamTracker *talker, StreamTracker *listener,
10757                                   TcpDataBlock *tdb, Packet *p)
10758 {
10759     uint32_t flushed = 0;
10760 
10761     STREAM_DEBUG_WRAP(DebugMessage(DEBUG_STREAM_STATE,
10762                 "In CheckFlushPolicyOnAck\n"););
10763     STREAM_DEBUG_WRAP(DebugMessage(DEBUG_STREAM_STATE,
10764                 "Talker flush policy: %s\n",
10765                 flush_policy_names[talker->flush_mgr.flush_policy]););
10766     STREAM_DEBUG_WRAP(DebugMessage(DEBUG_STREAM_STATE,
10767                 "Listener flush policy: %s\n",
10768                 flush_policy_names[listener->flush_mgr.flush_policy]););
10769 
10770     switch(talker->flush_mgr.flush_policy)
10771     {
10772         case STREAM_FLPOLICY_IGNORE:
10773             STREAM_DEBUG_WRAP(DebugMessage(DEBUG_STREAM_STATE,
10774                         "STREAM_FLPOLICY_IGNORE\n"););
10775             return 0;
10776 
10777         case STREAM_FLPOLICY_FOOTPRINT:
10778             STREAM_DEBUG_WRAP(DebugMessage(DEBUG_STREAM_STATE,
10779                         "STREAM_FLPOLICY_FOOTPRINT\n"););
10780             {
10781                 if(get_q_footprint(talker) >= talker->flush_mgr.flush_pt)
10782                 {
10783                     uint32_t dir = GetReverseDir(p);
10784 
10785                     flushed = flush_ackd(tcpssn, talker, p,
10786                             GET_DST_IP(p), GET_SRC_IP(p),
10787                             p->tcph->th_dport, p->tcph->th_sport, dir);
10788 
10789                     if(flushed)
10790                         purge_flushed_ackd(tcpssn, talker);
10791                 }
10792             }
10793             break;
10794 
10795         case STREAM_FLPOLICY_LOGICAL:
10796             STREAM_DEBUG_WRAP(DebugMessage(DEBUG_STREAM_STATE,
10797                         "STREAM_FLPOLICY_LOGICAL\n"););
10798             if(talker->seg_bytes_logical > talker->flush_mgr.flush_pt)
10799             {
10800                 uint32_t dir = GetReverseDir(p);
10801 
10802                 flushed = flush_ackd(tcpssn, talker, p,
10803                         GET_DST_IP(p), GET_SRC_IP(p),
10804                         p->tcph->th_dport, p->tcph->th_sport, dir);
10805 
10806                 if(flushed)
10807                     purge_flushed_ackd(tcpssn, talker);
10808             }
10809             break;
10810 
10811         case STREAM_FLPOLICY_RESPONSE:
10812             STREAM_DEBUG_WRAP(DebugMessage(DEBUG_STREAM_STATE,
10813                         "Running FLPOLICY_RESPONSE\n"););
10814             STREAM_DEBUG_WRAP(DebugMessage(DEBUG_STREAM_STATE,
10815                         "checking l.r_win_base (0x%X) > "
10816                         "t.seglist_base_seq (0x%X)\n",
10817                         talker->r_win_base, talker->seglist_base_seq););
10818 
10819             if(SEQ_GT(talker->r_win_base, talker->seglist_base_seq) &&
10820                     IsWellFormed(p, talker))
10821             {
10822                 uint32_t dir = GetReverseDir(p);
10823 
10824                 STREAM_DEBUG_WRAP(DebugMessage(DEBUG_STREAM_STATE,
10825                             "flushing talker, t->sbl: %d\n",
10826                             talker->seg_bytes_logical););
10827                 //PrintStreamTracker(talker);
10828                 //PrintStreamTracker(talker);
10829 
10830                 flushed = flush_ackd(tcpssn, talker, p,
10831                         GET_DST_IP(p), GET_SRC_IP(p),
10832                         p->tcph->th_dport, p->tcph->th_sport, dir);
10833 
10834                 STREAM_DEBUG_WRAP(DebugMessage(DEBUG_STREAM_STATE,
10835                             "bye bye data...\n"););
10836 
10837                 if(flushed)
10838                     purge_flushed_ackd(tcpssn, talker);
10839             }
10840             break;
10841 
10842         case STREAM_FLPOLICY_SLIDING_WINDOW:
10843             STREAM_DEBUG_WRAP(DebugMessage(DEBUG_STREAM_STATE,
10844                         "STREAM_FLPOLICY_SLIDING_WINDOW\n"););
10845             if(get_q_footprint(talker) >= talker->flush_mgr.flush_pt)
10846             {
10847                 uint32_t dir = GetReverseDir(p);
10848 
10849                 flushed = flush_ackd(tcpssn, talker, p,
10850                         GET_DST_IP(p), GET_SRC_IP(p),
10851                         p->tcph->th_dport, p->tcph->th_sport, dir);
10852 
10853                 STREAM_DEBUG_WRAP(DebugMessage(DEBUG_STREAM_STATE,
10854                             "Deleting head node for sliding window...\n"););
10855 
10856                 /* Base sequence for next window'd flush is the end
10857                  * of the first packet. */
10858                 talker->seglist_base_seq = talker->seglist->seq + talker->seglist->size;
10859                 StreamSeglistDeleteNode(talker, talker->seglist);
10860 
10861                 STREAM_DEBUG_WRAP(DebugMessage(DEBUG_STREAM_STATE,
10862                             "setting talker->seglist_base_seq to 0x%X\n",
10863                             talker->seglist->seq););
10864 
10865             }
10866             break;
10867 
10868 #if 0
10869         case STREAM_FLPOLICY_CONSUMED:
10870             STREAM_DEBUG_WRAP(DebugMessage(DEBUG_STREAM_STATE,
10871                         "STREAM_FLPOLICY_CONSUMED\n"););
10872             if(get_q_footprint(talker) >= talker->flush_mgr.flush_pt)
10873             {
10874                 uint32_t dir = GetReverseDir(p);
10875 
10876                 flushed = flush_ackd(tcpssn, talker, p,
10877                         p->iph->ip_dst.s_addr, p->iph->ip_src.s_addr,
10878                         p->tcph->th_dport, p->tcph->th_sport, dir);
10879 
10880                 STREAM_DEBUG_WRAP(DebugMessage(DEBUG_STREAM_STATE,
10881                             "Deleting head node for sliding window...\n"););
10882 
10883                 talker->seglist_base_seq = talker->seglist->seq + talker->seglist->size;
10884                 /* TODO: Delete up to the consumed bytes */
10885                 StreamSeglistDeleteNode(talker, talker->seglist);
10886 
10887                 STREAM_DEBUG_WRAP(DebugMessage(DEBUG_STREAM_STATE,
10888                             "setting talker->seglist_base_seq to 0x%X\n",
10889                             talker->seglist->seq););
10890 
10891             }
10892             break;
10893 #endif
10894         case STREAM_FLPOLICY_PROTOCOL:
10895             {
10896                 uint64_t flags = GetReverseDir(p);
10897                 uint32_t flush_amt = flush_pdu_ackd( config, tcpssn, talker, p, &flags);
10898 
10899                 while (flush_amt == 0 && (flags & PKT_PURGE))
10900                 {
10901                     purge_flushed_ackd(tcpssn, talker);
10902                     // Need to take care of other acked segments
10903                     flags = GetReverseDir(p);
10904                     flush_amt = flush_pdu_ackd( config, tcpssn, talker, p, &flags);
10905                 }
10906 
10907 
10908                 while ( flush_amt > 0 )
10909                 {
10910                     if( flags & PKT_IGNORE )
10911                     {
10912                         flushed = flush_amt;
10913                         flags &= ~PKT_IGNORE;
10914                     }
10915                     else if(talker->paf_state.fpt_eoh)
10916                     {
10917                         talker->paf_state.fpt_eoh = 0;
10918                         tcpssn->pp_flags &= ~(PP_HTTPINSPECT_PAF_FLUSH_POST_HDR);
10919                         flags = GetReverseDir(p);
10920                         flush_amt = flush_pdu_ackd( config, tcpssn, talker, p, &flags);
10921                         continue;
10922                     }
10923                     else
10924                     {
10925                         talker->seglist_next = talker->seglist;
10926                         talker->seglist_base_seq = talker->seglist->seq;
10927 
10928                         // for consistency with other cases, should return total
10929                         // but that breaks flushing pipelined pdus
10930                         flushed = flush_to_seq(
10931                                 tcpssn, talker, flush_amt, p,
10932                                 GET_DST_IP(p), GET_SRC_IP(p),
10933                                 p->tcph->th_dport, p->tcph->th_sport, flags);
10934                     }
10935 
10936                     // ideally we would purge just once after this loop
10937                     // but that throws off base
10938                     purge_to_seq(tcpssn, talker, talker->seglist->seq + flushed);
10939 
10940                     // if we didn't flush as expected, bail
10941                     // (we can flush less than max dsize)
10942                     if ( !flushed )
10943                         break;
10944 
10945                     flags = GetReverseDir(p);
10946                     flush_amt = flush_pdu_ackd( config, tcpssn, talker, p, &flags);
10947                 }
10948                 if ( !flags )
10949                 {
10950                     if ( AutoDisable(talker, listener) )
10951                         return 0;
10952 
10953                     talker->flush_mgr.flush_policy = STREAM_FLPOLICY_FOOTPRINT;
10954                     talker->flush_mgr.flush_pt += ScPafMax();
10955                     talker->flush_mgr.flush_type = STREAM_FT_PAF_MAX;
10956 
10957                     return CheckFlushPolicyOnAck( config, tcpssn, talker, listener, tdb, p );
10958                 }
10959             }
10960             break;
10961 
10962 #ifdef NORMALIZER
10963         case STREAM_FLPOLICY_FOOTPRINT_IPS:
10964         case STREAM_FLPOLICY_FOOTPRINT_IPS_FTP:
10965         case STREAM_FLPOLICY_PROTOCOL_IPS:
10966             purge_flushed_ackd(tcpssn, talker);
10967             break;
10968 #endif
10969         case STREAM_FLPOLICY_FOOTPRINT_NOACK:
10970         case STREAM_FLPOLICY_PROTOCOL_NOACK:
10971             purge_flushed_ackd(tcpssn, talker);
10972             break;
10973     }
10974 
10975     return flushed;
10976 }
10977 
StreamSeglistAddNode(StreamTracker * st,StreamSegment * prev,StreamSegment * new)10978 static void StreamSeglistAddNode(StreamTracker *st, StreamSegment *prev,
10979         StreamSegment *new)
10980 {
10981     s5stats.tcp_streamsegs_created++;
10982     if(prev)
10983     {
10984         new->next = prev->next;
10985         new->prev = prev;
10986         prev->next = new;
10987         if (new->next)
10988             new->next->prev = new;
10989         else
10990             st->seglist_tail = new;
10991     }
10992     else
10993     {
10994         new->next = st->seglist;
10995         if(new->next)
10996             new->next->prev = new;
10997         else
10998             st->seglist_tail = new;
10999         st->seglist = new;
11000     }
11001     st->seg_count++;
11002     //Calculate r_nxt_ack by walking the seglist to reach first hole or right end
11003     if(SEQ_LEQ(new->seq, st->r_nxt_ack))
11004     {
11005         while ( new->next && (new->next->seq == new->seq + new->size) )
11006         {
11007             new = new->next;
11008         }
11009         if(SEQ_LT(st->r_nxt_ack, new->seq + new->size))
11010           st->r_nxt_ack = new->seq + new->size;
11011     }
11012 #ifdef DEBUG
11013     new->ordinal = st->segment_ordinal++;
11014     if (new->next && (new->next->seq == new->seq))
11015     {
11016         LogMessage("Same seq to right, check me\n");
11017     }
11018 #endif
11019 }
11020 
StreamSeglistDeleteNode(StreamTracker * st,StreamSegment * seg)11021 static int StreamSeglistDeleteNode (StreamTracker* st, StreamSegment* seg)
11022 {
11023     int ret;
11024 
11025     assert(st && seg);
11026 
11027     STREAM_DEBUG_WRAP( DebugMessage(DEBUG_STREAM_STATE,
11028                 "Dropping segment at seq %X, len %d\n",
11029                 seg->seq, seg->size););
11030 
11031     if(seg->prev)
11032         seg->prev->next = seg->next;
11033     else
11034         st->seglist = seg->next;
11035 
11036     if(seg->next)
11037         seg->next->prev = seg->prev;
11038     else
11039         st->seglist_tail = seg->prev;
11040 
11041     st->seg_bytes_logical -= seg->size;
11042     st->seg_bytes_total -= seg->caplen;
11043 
11044     ret = seg->caplen;
11045 
11046     if (seg->buffered)
11047     {
11048         s5stats.tcp_rebuilt_seqs_used++;
11049         st->flush_count--;
11050     }
11051 
11052     if ( st->seglist_next == seg )
11053         st->seglist_next = NULL;
11054 
11055     SegmentFree(seg);
11056     st->seg_count--;
11057 
11058     return ret;
11059 }
11060 
StreamSeglistDeleteNodeTrim(StreamTracker * st,StreamSegment * seg,uint32_t flush_seq)11061 static int StreamSeglistDeleteNodeTrim (
11062         StreamTracker* st, StreamSegment* seg, uint32_t flush_seq)
11063 {
11064     assert(st && seg);
11065 
11066     /*urgent data is never sent flushed to preprocessors, hence avoid trimming segment having urg_offset >=1*/
11067     if( (seg->seq + seg->size - seg->urg_offset) > flush_seq )
11068     {
11069         /* If PAF is applicable and paf_state is set, we need to trim the segment when
11070          * we receive ACK for data less than the segment size.
11071          */
11072         if( s5_paf_active(&st->paf_state) )
11073         {
11074              uint32_t delta = flush_seq - seg->seq;
11075 
11076              if ( delta < seg->size )
11077              {
11078                   STREAM_DEBUG_WRAP( DebugMessage(DEBUG_STREAM_STATE,
11079                              "Left-Trimming segment at seq %X, len %d, delta %u\n",
11080                              seg->seq, seg->size, delta););
11081 
11082                   seg->seq = flush_seq;
11083                   seg->size -= (uint16_t)delta;
11084                   seg->payload += delta;
11085                   st->seg_bytes_logical -= delta;
11086                   return 0;
11087              }
11088         }
11089         /* If PAF is not applicable return without trim and delete when ACK is received for data
11090          * less than segment size.
11091          */
11092         else
11093         {
11094             /* If paf_state is PAF_ABORT and we receive ACK for bytes less than the segment size,
11095              * do not trim and do not delete from queue till we recive the ACK for remaining bytes.
11096              * example - FTP Data Session is always in default state which is PAF_ABORT, because PAF
11097              * is not applicable for FTP DATA, in this case if we receive ACK for data less than the
11098              * segment size, we should not trim OR delete this node till we get the ACK for complete
11099              * segment. */
11100              return 0;
11101         }
11102     }
11103     return StreamSeglistDeleteNode(st, seg);
11104 }
11105 
TcpUpdateDirection(SessionControlBlock * ssn,char dir,sfaddr_t * ip,uint16_t port)11106 void TcpUpdateDirection(SessionControlBlock *ssn, char dir,
11107         sfaddr_t* ip, uint16_t port)
11108 {
11109     TcpSession *tcpssn = (TcpSession *)ssn->proto_specific_data->data;
11110     sfaddr_t tmpIp;
11111     uint16_t tmpPort;
11112     StreamTracker tmpTracker;
11113 
11114     if (IP_EQUALITY(&tcpssn->tcp_client_ip, ip) && (tcpssn->tcp_client_port == port))
11115     {
11116         if ((dir == SSN_DIR_FROM_CLIENT) && (ssn->ha_state.direction == SSN_DIR_FROM_CLIENT))
11117         {
11118             /* Direction already set as client */
11119             return;
11120         }
11121     }
11122     else if (IP_EQUALITY(&tcpssn->tcp_server_ip, ip) && (tcpssn->tcp_server_port == port))
11123     {
11124         if ((dir == SSN_DIR_FROM_SERVER) && (ssn->ha_state.direction == SSN_DIR_FROM_SERVER))
11125         {
11126             /* Direction already set as server */
11127             return;
11128         }
11129     }
11130 
11131     /* Swap them -- leave ssn->ha_state.direction the same */
11132 
11133     /* XXX: Gotta be a more efficient way to do this without the memcpy */
11134     tmpIp = tcpssn->tcp_client_ip;
11135     tmpPort = tcpssn->tcp_client_port;
11136     tcpssn->tcp_client_ip = tcpssn->tcp_server_ip;
11137     tcpssn->tcp_client_port = tcpssn->tcp_server_port;
11138     tcpssn->tcp_server_ip = tmpIp;
11139     tcpssn->tcp_server_port = tmpPort;
11140 #ifdef HAVE_DAQ_ADDRESS_SPACE_ID
11141     SwapPacketHeaderFoo(tcpssn);
11142 #endif
11143     memcpy(&tmpTracker, &tcpssn->client, sizeof(StreamTracker));
11144     memcpy(&tcpssn->client, &tcpssn->server, sizeof(StreamTracker));
11145     memcpy(&tcpssn->server, &tmpTracker, sizeof(StreamTracker));
11146 
11147 }
11148 
11149 /* Iterates through the packets that were reassembled for
11150  * logging of tagged packets.
11151  */
GetTcpRebuiltPackets(Packet * p,SessionControlBlock * ssn,PacketIterator callback,void * userdata)11152 int GetTcpRebuiltPackets(Packet *p, SessionControlBlock *ssn, PacketIterator callback, void *userdata)
11153 {
11154     int packets = 0;
11155     TcpSession *tcpssn = NULL;
11156     StreamTracker *st;
11157     StreamSegment *ss;
11158     uint32_t start_seq = ntohl(p->tcph->th_seq);
11159     uint32_t end_seq = start_seq + p->dsize;
11160 
11161     if (!ssn || !ssn->proto_specific_data || !ssn->proto_specific_data->data)
11162     {
11163         return packets;
11164     }
11165 
11166     tcpssn = (TcpSession *)ssn->proto_specific_data->data;
11167 
11168     /* StreamTracker is the opposite of the ip of the reassembled
11169      * packet --> it came out the queue for the other side */
11170     if (IP_EQUALITY(GET_SRC_IP(p), &tcpssn->tcp_client_ip))
11171     {
11172         st = &tcpssn->server;
11173     }
11174     else
11175     {
11176         st = &tcpssn->client;
11177     }
11178 
11179     // skip over segments not covered by this reassembled packet
11180     for (ss = st->seglist; ss && SEQ_LT(ss->seq, start_seq); ss = ss->next);
11181 
11182     // return flushed segments only
11183     // For HTTP Post request End-of-Header Flush, if alert is raised, return the segments even though they are not buffered.
11184     for (; ss && ((ss->buffered == SL_BUF_FLUSHED) || (tcpssn->pp_flags & PP_HTTPINSPECT_PAF_FLUSH_POST_HDR)); ss = ss->next)
11185     {
11186         if (SEQ_GEQ(ss->seq,start_seq) && SEQ_LT(ss->seq, end_seq))
11187         {
11188             DAQ_PktHdr_t pkth;
11189             pkth.ts.tv_sec = ss->tv.tv_sec;
11190             pkth.ts.tv_usec = ss->tv.tv_usec;
11191             pkth.caplen = ss->caplen;
11192             pkth.pktlen = ss->pktlen;
11193 
11194             callback(&pkth, ss->pkt, userdata);
11195             packets++;
11196         }
11197         else
11198             break;
11199     }
11200 
11201     return packets;
11202 }
11203 
11204 /* Iterates through the packets that were reassembled for
11205  * logging of tagged packets.
11206  */
GetTcpStreamSegments(Packet * p,SessionControlBlock * ssn,StreamSegmentIterator callback,void * userdata)11207 int GetTcpStreamSegments(Packet *p, SessionControlBlock *ssn, StreamSegmentIterator callback,
11208         void *userdata)
11209 {
11210     int packets = 0;
11211     TcpSession *tcpssn = NULL;
11212     StreamTracker *st;
11213     StreamSegment *ss;
11214     uint32_t start_seq = ntohl(p->tcph->th_seq);
11215     uint32_t end_seq = start_seq + p->dsize;
11216 
11217     if (!ssn || !ssn->proto_specific_data || !ssn->proto_specific_data->data)
11218         return -1;
11219 
11220     tcpssn = (TcpSession *)ssn->proto_specific_data->data;
11221 
11222     /* StreamTracker is the opposite of the ip of the reassembled
11223      * packet --> it came out the queue for the other side */
11224     if (IP_EQUALITY(GET_SRC_IP(p), &tcpssn->tcp_client_ip))
11225         st = &tcpssn->server;
11226     else
11227         st = &tcpssn->client;
11228 
11229     // skip over segments not covered by this reassembled packet
11230     for (ss = st->seglist; ss && SEQ_LT(ss->seq, start_seq); ss = ss->next);
11231 
11232     // return flushed segments only
11233     // For HTTP Post request End-of-Header Flush, if alert is raised, return the segments even though they are not buffered.
11234     for (; ss && ((ss->buffered == SL_BUF_FLUSHED) || (tcpssn->pp_flags & PP_HTTPINSPECT_PAF_FLUSH_POST_HDR)); ss = ss->next)
11235     {
11236         if (SEQ_GEQ(ss->seq,start_seq) && SEQ_LT(ss->seq, end_seq))
11237         {
11238             DAQ_PktHdr_t pkth;
11239             uint32_t ajust_seq = ss->seq - (uint32_t)(ss->payload - ss->data);
11240             pkth.ts.tv_sec = ss->tv.tv_sec;
11241             pkth.ts.tv_usec = ss->tv.tv_usec;
11242             pkth.caplen = ss->caplen;
11243             pkth.pktlen = ss->pktlen;
11244 
11245             if (callback(&pkth, ss->pkt, ss->data, ajust_seq, userdata) != 0)
11246                 return -1;
11247 
11248             packets++;
11249         }
11250         else
11251             break;
11252     }
11253 
11254     return packets;
11255 }
11256 
StreamAddSessionAlertTcp(SessionControlBlock * scb,Packet * p,uint32_t gid,uint32_t sid)11257 int StreamAddSessionAlertTcp( SessionControlBlock* scb, Packet* p, uint32_t gid, uint32_t sid)
11258 {
11259     TcpSession *tcpssn = NULL;
11260     StreamTracker *st;
11261     StreamAlertInfo* ai;
11262 
11263     if (scb->proto_specific_data)
11264         tcpssn = (TcpSession *)scb->proto_specific_data->data;
11265 
11266     if (!tcpssn)
11267     {
11268         return 0;
11269     }
11270 
11271     if (IP_EQUALITY(GET_SRC_IP(p),&tcpssn->tcp_client_ip))
11272     {
11273         st = &tcpssn->server;
11274     }
11275     else
11276     {
11277         st = &tcpssn->client;
11278     }
11279 
11280     if (st->alert_count >= MAX_SESSION_ALERTS)
11281         return 0;
11282 
11283     ai = st->alerts + st->alert_count;
11284     ai->gid = gid;
11285     ai->sid = sid;
11286     ai->seq = GET_PKT_SEQ(p);
11287 
11288     if ( p->tcph->th_flags & TH_FIN )
11289         ai->seq--;
11290 
11291     st->alert_count++;
11292 
11293     return 0;
11294 }
11295 
StreamCheckSessionAlertTcp(SessionControlBlock * scb,Packet * p,uint32_t gid,uint32_t sid)11296 int StreamCheckSessionAlertTcp(SessionControlBlock *scb, Packet *p, uint32_t gid, uint32_t sid)
11297 {
11298     TcpSession *tcpssn = NULL;
11299     StreamTracker *st;
11300     int i;
11301     int iRet = 0;
11302 
11303     if (scb->proto_specific_data)
11304         tcpssn = (TcpSession *)scb->proto_specific_data->data;
11305 
11306     if (!tcpssn)
11307     {
11308         return 0;
11309     }
11310 
11311     /* If this is not a rebuilt packet, no need to check further */
11312     if (!(p->packet_flags & PKT_REBUILT_STREAM))
11313     {
11314         return 0;
11315     }
11316 
11317     if (IP_EQUALITY(GET_SRC_IP(p), &tcpssn->tcp_client_ip))
11318     {
11319         st = &tcpssn->server;
11320     }
11321     else
11322     {
11323         st = &tcpssn->client;
11324     }
11325 
11326     for (i=0;i<st->alert_count;i++)
11327     {
11328         /*  This is a rebuilt packet and if we've seen this alert before,
11329          *  return that we have previously alerted on original packet.
11330          */
11331         if ( st->alerts[i].gid == gid &&
11332                 st->alerts[i].sid == sid )
11333         {
11334             return -1;
11335         }
11336     }
11337 
11338     return iRet;
11339 }
11340 
StreamUpdateSessionAlertTcp(SessionControlBlock * scb,Packet * p,uint32_t gid,uint32_t sid,uint32_t event_id,uint32_t event_second)11341 int StreamUpdateSessionAlertTcp(SessionControlBlock *scb, Packet *p, uint32_t gid, uint32_t sid,
11342         uint32_t event_id, uint32_t event_second)
11343 {
11344     TcpSession *tcpssn = NULL;
11345     StreamTracker *st;
11346     int i;
11347     uint32_t seq_num;
11348 
11349     if (scb->proto_specific_data)
11350         tcpssn = (TcpSession *)scb->proto_specific_data->data;
11351 
11352     if (!tcpssn)
11353     {
11354         return 0;
11355     }
11356 
11357     if (IP_EQUALITY(GET_SRC_IP(p), &tcpssn->tcp_client_ip))
11358     {
11359         st = &tcpssn->server;
11360     }
11361     else
11362     {
11363         st = &tcpssn->client;
11364     }
11365 
11366     seq_num = GET_PKT_SEQ(p);
11367 
11368     if ( p->tcph->th_flags & TH_FIN )
11369         seq_num--;
11370 
11371     for (i=0;i<st->alert_count;i++)
11372     {
11373         StreamAlertInfo* ai = st->alerts + i;
11374 
11375         if ( ai->gid == gid &&
11376                 ai->sid == sid && SEQ_EQ(ai->seq, seq_num))
11377         {
11378             ai->event_id = event_id;
11379             ai->event_second = event_second;
11380             return 0;
11381         }
11382     }
11383 
11384     return -1;
11385 }
11386 
StreamSetExtraDataTcp(SessionControlBlock * scb,Packet * p,uint32_t xid)11387 void StreamSetExtraDataTcp (SessionControlBlock* scb, Packet* p, uint32_t xid)
11388 {
11389     TcpSession *tcpssn = NULL;
11390     StreamTracker *st;
11391 
11392     if (scb->proto_specific_data)
11393         tcpssn = (TcpSession *)scb->proto_specific_data->data;
11394 
11395     if (!tcpssn)
11396         return;
11397 
11398     if (IP_EQUALITY(GET_SRC_IP(p),&tcpssn->tcp_client_ip))
11399         st = &tcpssn->server;
11400     else
11401         st = &tcpssn->client;
11402 
11403     st->xtradata_mask |= BIT(xid);
11404     p->xtradata_mask |= BIT(xid);
11405 }
11406 
StreamClearExtraDataTcp(SessionControlBlock * scb,Packet * p,uint32_t xid)11407 void StreamClearExtraDataTcp (SessionControlBlock* scb, Packet* p, uint32_t xid)
11408 {
11409     TcpSession *tcpssn = NULL;
11410     StreamTracker *st;
11411 
11412     if (scb->proto_specific_data)
11413         tcpssn = (TcpSession *)scb->proto_specific_data->data;
11414 
11415     if (!tcpssn)
11416         return;
11417 
11418     if (IP_EQUALITY(GET_SRC_IP(p),&tcpssn->tcp_client_ip))
11419         st = &tcpssn->server;
11420     else
11421         st = &tcpssn->client;
11422 
11423     if ( xid )
11424         st->xtradata_mask &= ~BIT(xid);
11425     else
11426         st->xtradata_mask = 0;
11427 }
11428 
StreamGetReassemblyDirectionTcp(SessionControlBlock * scb)11429 char StreamGetReassemblyDirectionTcp(SessionControlBlock *scb)
11430 {
11431     TcpSession *tcpssn = NULL;
11432     char dir = SSN_DIR_NONE;
11433 
11434     if (!scb)
11435         return SSN_DIR_NONE;
11436 
11437     if (scb->proto_specific_data)
11438         tcpssn = (TcpSession *)scb->proto_specific_data->data;
11439 
11440     if (!tcpssn)
11441         return SSN_DIR_NONE;
11442 
11443     if ((tcpssn->server.flush_mgr.flush_policy != STREAM_FLPOLICY_NONE) &&
11444             (tcpssn->server.flush_mgr.flush_policy != STREAM_FLPOLICY_IGNORE))
11445     {
11446         dir |= SSN_DIR_TO_SERVER;
11447     }
11448 
11449     if ((tcpssn->client.flush_mgr.flush_policy != STREAM_FLPOLICY_NONE) &&
11450             (tcpssn->client.flush_mgr.flush_policy != STREAM_FLPOLICY_IGNORE))
11451     {
11452         dir |= SSN_DIR_TO_CLIENT;
11453     }
11454 
11455     return dir;
11456 }
11457 
getWirePacketTcp()11458 Packet* getWirePacketTcp()
11459 {
11460     return wire_packet;
11461 }
11462 
getFlushPolicyDirTcp()11463 uint8_t getFlushPolicyDirTcp()
11464 {
11465     if (flush_policy_for_dir == STREAM_FLPOLICY_FOOTPRINT_IPS   ||
11466         flush_policy_for_dir == STREAM_FLPOLICY_FOOTPRINT_NOACK ||
11467         flush_policy_for_dir == STREAM_FLPOLICY_PROTOCOL_IPS    ||
11468         flush_policy_for_dir == STREAM_FLPOLICY_PROTOCOL_NOACK)
11469     {
11470         return 1;
11471     }
11472     return 0;
11473 }
11474 
StreamGetFlushPointTcp(SessionControlBlock * scb,char dir)11475 uint32_t StreamGetFlushPointTcp(SessionControlBlock *scb, char dir)
11476 {
11477     TcpSession *tcpssn = NULL;
11478 
11479     if (scb == NULL)
11480         return 0;
11481 
11482     if (scb->proto_specific_data != NULL)
11483         tcpssn = (TcpSession *)scb->proto_specific_data->data;
11484 
11485     if (tcpssn == NULL)
11486         return 0;
11487 
11488     if (dir & SSN_DIR_TO_SERVER)
11489         return tcpssn->server.flush_mgr.flush_pt;
11490     else if (dir & SSN_DIR_TO_CLIENT)
11491         return tcpssn->client.flush_mgr.flush_pt;
11492 
11493     return 0;
11494 }
11495 
StreamSetFlushPointTcp(SessionControlBlock * scb,char dir,uint32_t flush_point)11496 void StreamSetFlushPointTcp(SessionControlBlock *scb, char dir, uint32_t flush_point)
11497 {
11498     TcpSession *tcpssn = NULL;
11499 
11500     if (scb == NULL)
11501         return;
11502 
11503     if (scb->proto_specific_data != NULL)
11504         tcpssn = (TcpSession *)scb->proto_specific_data->data;
11505 
11506     if (tcpssn == NULL)
11507         return;
11508 
11509     if (flush_point == 0)
11510         return;
11511 
11512     if (dir & SSN_DIR_TO_SERVER)
11513     {
11514         tcpssn->server.flush_mgr.flush_pt = flush_point;
11515         tcpssn->server.flush_mgr.last_size = 0;
11516         tcpssn->server.flush_mgr.last_count = 0;
11517         tcpssn->server.flush_mgr.flush_type = STREAM_FT_EXTERNAL;
11518     }
11519     else if (dir & SSN_DIR_TO_CLIENT)
11520     {
11521         tcpssn->client.flush_mgr.flush_pt = flush_point;
11522         tcpssn->client.flush_mgr.last_size = 0;
11523         tcpssn->client.flush_mgr.last_count = 0;
11524         tcpssn->client.flush_mgr.flush_type = STREAM_FT_EXTERNAL;
11525     }
11526 }
11527 
StreamSetReassemblyTcp(SessionControlBlock * scb,uint8_t flush_policy,char dir,char flags)11528 char StreamSetReassemblyTcp(SessionControlBlock *scb, uint8_t flush_policy, char dir, char flags)
11529 {
11530     TcpSession *tcpssn = NULL;
11531     uint16_t tmp_flags;
11532 
11533     if (!scb)
11534         return SSN_DIR_NONE;
11535 
11536     if (scb->proto_specific_data)
11537         tcpssn = (TcpSession *)scb->proto_specific_data->data;
11538 
11539     if (!tcpssn)
11540         return SSN_DIR_NONE;
11541 
11542     tmp_flags = (flush_policy == STREAM_FLPOLICY_IGNORE)? 0: TF_FIRST_PKT_MISSING;
11543     if (flags & STREAM_FLPOLICY_SET_APPEND)
11544     {
11545         if (dir & SSN_DIR_TO_SERVER)
11546         {
11547             if (tcpssn->server.flush_mgr.flush_policy != STREAM_FLPOLICY_NONE)
11548             {
11549                 /* Changing policy with APPEND, Bad */
11550                 DEBUG_WRAP(DebugMessage(DEBUG_STREAM_STATE,
11551                             "Stream: Changing client flush policy using "
11552                             "append is asking for trouble.  Ignored\n"););
11553             }
11554             else
11555             {
11556                 InitFlushMgr(snort_conf, &tcpssn->server.flush_mgr,
11557                         &tcpssn->server.tcp_policy->flush_point_list,
11558                         flush_policy, 0);
11559                 tcpssn->server.flags |= tmp_flags;
11560             }
11561         }
11562 
11563         if (dir & SSN_DIR_TO_CLIENT)
11564         {
11565             if (tcpssn->client.flush_mgr.flush_policy != STREAM_FLPOLICY_NONE)
11566             {
11567                 /* Changing policy with APPEND, Bad */
11568                 DEBUG_WRAP(DebugMessage(DEBUG_STREAM_STATE,
11569                             "Stream: Changing server flush policy using "
11570                             "append is asking for trouble.  Ignored\n"););
11571             }
11572             else
11573             {
11574                 InitFlushMgr(snort_conf, &tcpssn->client.flush_mgr,
11575                         &tcpssn->client.tcp_policy->flush_point_list,
11576                         flush_policy, 0);
11577                 tcpssn->client.flags |= tmp_flags;
11578             }
11579         }
11580 
11581     }
11582     else if (flags & STREAM_FLPOLICY_SET_ABSOLUTE)
11583     {
11584         if (dir & SSN_DIR_TO_SERVER)
11585         {
11586             //If the flush policy is already set to STREAM_FLPOLICY_FOOTPRINT_IPS_FTP, ssl preproc shouldn't reset the flush policy for FTPS.
11587             //Unset the pp_flags because SSL will send decrypted FTP traffic from here on
11588             if((tcpssn->pp_flags & PP_FTPTELNET_FTPS) && (tcpssn->server.flush_mgr.flush_policy == STREAM_FLPOLICY_FOOTPRINT_IPS_FTP))
11589             {
11590                 flush_policy = STREAM_FLPOLICY_FOOTPRINT_IPS_FTP;
11591                 tcpssn->pp_flags &= ~PP_FTPTELNET_FTPS;
11592             }
11593 
11594             InitFlushMgr(snort_conf, &tcpssn->server.flush_mgr,
11595                     &tcpssn->server.tcp_policy->flush_point_list,
11596                     flush_policy, 0);
11597             tcpssn->server.flags |= tmp_flags;
11598             if(tcpssn->server.flush_mgr.flush_policy == STREAM_FLPOLICY_FOOTPRINT_IPS)
11599             {
11600                 //set_application_data is done for ftp-data connection during TCPSession setup. Change the Flush policy for ftp-data only.
11601                 if(session_api->get_application_data(scb, PP_FTPTELNET))
11602                 {
11603                     tcpssn->server.flush_mgr.flush_policy = STREAM_FLPOLICY_FOOTPRINT_IPS_FTP;
11604                     tcpssn->server.flush_mgr.last_size = 0;
11605                 }
11606             }
11607         }
11608 
11609         if (dir & SSN_DIR_TO_CLIENT)
11610         {
11611             //If the flush policy is already set to STREAM_FLPOLICY_FOOTPRINT_IPS_FTP, ssl preproc shouldn't reset the flush policy for FTPS.
11612             //Unset the pp_flags because SSL will send decrypted FTP traffic from here on
11613             if((tcpssn->pp_flags & PP_FTPTELNET_FTPS) && (tcpssn->client.flush_mgr.flush_policy == STREAM_FLPOLICY_FOOTPRINT_IPS_FTP))
11614             {
11615                 flush_policy = STREAM_FLPOLICY_FOOTPRINT_IPS_FTP;
11616                 tcpssn->pp_flags &= ~PP_FTPTELNET_FTPS;
11617             }
11618 
11619             InitFlushMgr(snort_conf, &tcpssn->client.flush_mgr,
11620                     &tcpssn->client.tcp_policy->flush_point_list,
11621                     flush_policy, 0);
11622             tcpssn->client.flags |= tmp_flags;
11623             if(tcpssn->client.flush_mgr.flush_policy == STREAM_FLPOLICY_FOOTPRINT_IPS)
11624             {
11625                 //set_application_data is done for ftp-data connection during TCPSession setup. Change the Flush policy for ftp-data only.
11626                 if(session_api->get_application_data(scb, PP_FTPTELNET))
11627                 {
11628                     tcpssn->client.flush_mgr.flush_policy = STREAM_FLPOLICY_FOOTPRINT_IPS_FTP;
11629                     tcpssn->client.flush_mgr.last_size = 0;
11630                 }
11631             }
11632         }
11633     }
11634 
11635     return StreamGetReassemblyDirectionTcp(scb);
11636 }
11637 
StreamGetReassemblyFlushPolicyTcp(SessionControlBlock * scb,char dir)11638 char StreamGetReassemblyFlushPolicyTcp(SessionControlBlock *scb, char dir)
11639 {
11640     TcpSession *tcpssn = NULL;
11641 
11642     if (!scb)
11643         return STREAM_FLPOLICY_NONE;
11644 
11645     if (scb->proto_specific_data)
11646         tcpssn = (TcpSession *)scb->proto_specific_data->data;
11647 
11648     if (!tcpssn)
11649         return STREAM_FLPOLICY_NONE;
11650 
11651     if (dir & SSN_DIR_TO_SERVER)
11652     {
11653         return (char)tcpssn->server.flush_mgr.flush_policy;
11654     }
11655 
11656     if (dir & SSN_DIR_TO_CLIENT)
11657     {
11658         return (char)tcpssn->client.flush_mgr.flush_policy;
11659     }
11660     return STREAM_FLPOLICY_NONE;
11661 }
11662 
StreamIsStreamSequencedTcp(SessionControlBlock * scb,char dir)11663 char StreamIsStreamSequencedTcp(SessionControlBlock *scb, char dir)
11664 {
11665     TcpSession *tcpssn = NULL;
11666 
11667     if (!scb)
11668         return 1;
11669 
11670     if (scb->proto_specific_data)
11671         tcpssn = (TcpSession *)scb->proto_specific_data->data;
11672 
11673     if (!tcpssn)
11674         return 1;
11675 
11676     if (dir & SSN_DIR_FROM_CLIENT)
11677     {
11678         if ( tcpssn->server.flags & TF_MISSING_PREV_PKT )
11679             return 0;
11680     }
11681 
11682     if (dir & SSN_DIR_FROM_SERVER)
11683     {
11684         if ( tcpssn->client.flags & TF_MISSING_PREV_PKT )
11685             return 0;
11686     }
11687 
11688     return 1;
11689 }
11690 
11691 /* This will falsly return SSN_MISSING_BEFORE on the first reassembed
11692  * packet if reassembly for this direction was set mid-session */
StreamMissingInReassembledTcp(SessionControlBlock * scb,char dir)11693 int StreamMissingInReassembledTcp(SessionControlBlock *scb, char dir)
11694 {
11695     TcpSession *tcpssn = NULL;
11696 
11697     if (!scb)
11698         return SSN_MISSING_NONE;
11699 
11700     if (scb->proto_specific_data)
11701         tcpssn = (TcpSession *)scb->proto_specific_data->data;
11702 
11703     if (!tcpssn)
11704         return SSN_MISSING_NONE;
11705 
11706     if (dir & SSN_DIR_FROM_CLIENT)
11707     {
11708         if (tcpssn->server.flags & TF_MISSING_PREV_PKT)
11709             return SSN_MISSING_BEFORE;
11710     }
11711     else if (dir & SSN_DIR_FROM_SERVER)
11712     {
11713         if (tcpssn->client.flags & TF_MISSING_PREV_PKT)
11714             return SSN_MISSING_BEFORE;
11715     }
11716 
11717     return SSN_MISSING_NONE;
11718 }
11719 
StreamPacketsMissingTcp(SessionControlBlock * scb,char dir)11720 char StreamPacketsMissingTcp(SessionControlBlock *scb, char dir)
11721 {
11722     TcpSession *tcpssn = NULL;
11723 
11724     if (!scb)
11725         return 0;
11726 
11727     if (scb->proto_specific_data)
11728         tcpssn = (TcpSession *)scb->proto_specific_data->data;
11729 
11730     if (!tcpssn)
11731         return 0;
11732 
11733     if (dir & SSN_DIR_FROM_CLIENT)
11734     {
11735         if (tcpssn->server.flags & TF_PKT_MISSED)
11736             return 1;
11737     }
11738 
11739     if (dir & SSN_DIR_FROM_SERVER)
11740     {
11741         if (tcpssn->client.flags & TF_PKT_MISSED)
11742             return 1;
11743     }
11744 
11745     return 0;
11746 }
11747 
11748 #define SSOD_LESS_THAN 1
11749 #define SSOD_GREATER_THAN 2
11750 #define SSOD_EQUALS 3
11751 #define SSOD_LESS_THAN_OR_EQUALS 4
11752 #define SSOD_GREATER_THAN_OR_EQUALS 5
11753 #define SSOD_NOT_EQUALS 6
11754 
11755 #define SSOD_MATCH 1
11756 #define SSOD_NOMATCH 0
11757 typedef struct _StreamSizeOptionData
11758 {
11759     char operator;
11760     uint32_t size;
11761     char direction;
11762 } StreamSizeOptionData;
11763 
s5TcpStreamSizeInit(struct _SnortConfig * sc,char * name,char * parameters,void ** dataPtr)11764 int s5TcpStreamSizeInit(struct _SnortConfig *sc, char *name, char *parameters, void **dataPtr)
11765 {
11766     char **toks;
11767     int num_toks;
11768     char *endp;
11769     StreamSizeOptionData *ssod = NULL;
11770     toks = mSplit(parameters, ",", 4, &num_toks, 0);
11771 
11772     if (num_toks != 3)
11773     {
11774         FatalError("%s(%d): Invalid parameters for %s option\n",
11775                 file_name, file_line, name);
11776     }
11777 
11778     ssod = SnortPreprocAlloc(1, sizeof(StreamSizeOptionData), PP_STREAM,
11779                     PP_MEM_CATEGORY_CONFIG);
11780 
11781     if (!ssod)
11782     {
11783         FatalError("%s(%d): Failed to allocate data for %s option\n",
11784                 file_name, file_line, name);
11785     }
11786 
11787     /* Parse the direction.
11788      * Can be: client, server, both, either
11789      */
11790     if (!strcasecmp(toks[0], "client"))
11791     {
11792         ssod->direction = SSN_DIR_FROM_CLIENT;
11793     }
11794     else if (!strcasecmp(toks[0], "server"))
11795     {
11796         ssod->direction = SSN_DIR_FROM_SERVER;
11797     }
11798     else if (!strcasecmp(toks[0], "both"))
11799     {
11800         ssod->direction = SSN_DIR_BOTH;
11801     }
11802     else if (!strcasecmp(toks[0], "either"))
11803     {
11804         ssod->direction = SSN_DIR_NONE;
11805     }
11806     else
11807     {
11808         FatalError("%s(%d): Invalid direction: %s for option %s\n",
11809                 file_name, file_line, toks[0], name);
11810     }
11811 
11812     /* Parse the operator.
11813      * Can be: =, <, > , !=, <=, >=
11814      */
11815     if (!strcasecmp(toks[1], "="))
11816     {
11817         ssod->operator = SSOD_EQUALS;
11818     }
11819     else if (!strcasecmp(toks[1], "<"))
11820     {
11821         ssod->operator = SSOD_LESS_THAN;
11822     }
11823     else if (!strcasecmp(toks[1], ">"))
11824     {
11825         ssod->operator = SSOD_GREATER_THAN;
11826     }
11827     else if (!strcasecmp(toks[1], "!="))
11828     {
11829         ssod->operator = SSOD_NOT_EQUALS;
11830     }
11831     else if (!strcasecmp(toks[1], "<="))
11832     {
11833         ssod->operator = SSOD_LESS_THAN_OR_EQUALS;
11834     }
11835     else if (!strcasecmp(toks[1], ">="))
11836     {
11837         ssod->operator = SSOD_GREATER_THAN_OR_EQUALS;
11838     }
11839     else
11840     {
11841         FatalError("%s(%d): Invalid operator: %s for option %s\n",
11842                 file_name, file_line, toks[1], name);
11843     }
11844 
11845     ssod->size = SnortStrtoul(toks[2], &endp, 0);
11846     if ((endp == toks[2]) || (errno == ERANGE))
11847     {
11848         FatalError("%s(%d): Invalid size: %s for option %s\n",
11849                 file_name, file_line, toks[2], name);
11850     }
11851 
11852     *dataPtr = ssod;
11853     mSplitFree(&toks, num_toks);
11854 
11855     return 1;
11856 }
11857 
s5TcpStreamSizeCompare(uint32_t size1,uint32_t size2,char operator)11858 static inline int s5TcpStreamSizeCompare(uint32_t size1, uint32_t size2, char operator)
11859 {
11860     int retval = 0;
11861     switch (operator)
11862     {
11863         case SSOD_EQUALS:
11864             if (size1 == size2)
11865                 retval = 1;
11866             break;
11867         case SSOD_LESS_THAN:
11868             if (size1 < size2)
11869                 retval = 1;
11870             break;
11871         case SSOD_GREATER_THAN:
11872             if (size1 > size2)
11873                 retval = 1;
11874             break;
11875         case SSOD_NOT_EQUALS:
11876             if (size1 != size2)
11877                 retval = 1;
11878             break;
11879         case SSOD_LESS_THAN_OR_EQUALS:
11880             if (size1 <= size2)
11881                 retval = 1;
11882             break;
11883         case SSOD_GREATER_THAN_OR_EQUALS:
11884             if (size1 >= size2)
11885                 retval = 1;
11886             break;
11887         default:
11888             break;
11889     }
11890     return retval;
11891 }
11892 
s5TcpStreamSizeEval(void * p,const uint8_t ** cursor,void * dataPtr)11893 int s5TcpStreamSizeEval(void *p, const uint8_t **cursor, void *dataPtr)
11894 {
11895     Packet *pkt = p;
11896     SessionControlBlock *scb = NULL;
11897     TcpSession *tcpssn = NULL;
11898     StreamSizeOptionData *ssod = (StreamSizeOptionData *)dataPtr;
11899     uint32_t client_size;
11900     uint32_t server_size;
11901     PROFILE_VARS;
11902 
11903     if (!pkt || !pkt->ssnptr || !ssod || !pkt->tcph)
11904         return DETECTION_OPTION_NO_MATCH;
11905 
11906     scb = pkt->ssnptr;
11907     if (!scb->proto_specific_data)
11908         return DETECTION_OPTION_NO_MATCH;
11909 
11910     PREPROC_PROFILE_START(streamSizePerfStats);
11911 
11912     tcpssn = (TcpSession *)scb->proto_specific_data->data;
11913 
11914     if (tcpssn->client.l_nxt_seq > tcpssn->client.isn)
11915     {
11916         /* the normal case... */
11917         client_size = tcpssn->client.l_nxt_seq - tcpssn->client.isn;
11918     }
11919     else
11920     {
11921         /* the seq num wrapping case... */
11922         client_size = tcpssn->client.isn - tcpssn->client.l_nxt_seq;
11923     }
11924     if (tcpssn->server.l_nxt_seq > tcpssn->server.isn)
11925     {
11926         /* the normal case... */
11927         server_size = tcpssn->server.l_nxt_seq - tcpssn->server.isn;
11928     }
11929     else
11930     {
11931         /* the seq num wrapping case... */
11932         server_size = tcpssn->server.isn - tcpssn->server.l_nxt_seq;
11933     }
11934 
11935     switch (ssod->direction)
11936     {
11937         case SSN_DIR_FROM_CLIENT:
11938             if (s5TcpStreamSizeCompare(client_size, ssod->size, ssod->operator)
11939                     == SSOD_MATCH)
11940             {
11941                 PREPROC_PROFILE_END(streamSizePerfStats);
11942                 return DETECTION_OPTION_MATCH;
11943             }
11944             break;
11945         case SSN_DIR_FROM_SERVER:
11946             if (s5TcpStreamSizeCompare(server_size, ssod->size, ssod->operator)
11947                     == SSOD_MATCH)
11948             {
11949                 PREPROC_PROFILE_END(streamSizePerfStats);
11950                 return DETECTION_OPTION_MATCH;
11951             }
11952             break;
11953         case SSN_DIR_NONE: /* overloaded.  really, its an 'either' */
11954             if ((s5TcpStreamSizeCompare(client_size, ssod->size, ssod->operator)
11955                         == SSOD_MATCH) ||
11956                     (s5TcpStreamSizeCompare(server_size, ssod->size, ssod->operator)
11957                      == SSOD_MATCH))
11958             {
11959                 PREPROC_PROFILE_END(streamSizePerfStats);
11960                 return DETECTION_OPTION_MATCH;
11961             }
11962             break;
11963         case SSN_DIR_BOTH:
11964             if ((s5TcpStreamSizeCompare(client_size, ssod->size, ssod->operator)
11965                         == SSOD_MATCH) &&
11966                     (s5TcpStreamSizeCompare(server_size, ssod->size, ssod->operator)
11967                      == SSOD_MATCH))
11968             {
11969                 PREPROC_PROFILE_END(streamSizePerfStats);
11970                 return DETECTION_OPTION_MATCH;
11971             }
11972             break;
11973         default:
11974             break;
11975     }
11976     PREPROC_PROFILE_END(streamSizePerfStats);
11977     return DETECTION_OPTION_NO_MATCH;
11978 }
11979 
s5TcpStreamSizeCleanup(void * dataPtr)11980 void s5TcpStreamSizeCleanup(void *dataPtr)
11981 {
11982     StreamSizeOptionData *ssod = dataPtr;
11983     if (ssod)
11984     {
11985         SnortPreprocFree(ssod, sizeof(StreamSizeOptionData), PP_STREAM,
11986                          PP_MEM_CATEGORY_CONFIG);
11987     }
11988 }
11989 
11990 typedef struct _StreamReassembleRuleOptionData
11991 {
11992     char enable;
11993     char alert;
11994     char direction;
11995     char fastpath;
11996 } StreamReassembleRuleOptionData;
11997 
s5TcpStreamReassembleRuleOptionInit(struct _SnortConfig * sc,char * name,char * parameters,void ** dataPtr)11998 int s5TcpStreamReassembleRuleOptionInit(struct _SnortConfig *sc, char *name, char *parameters, void **dataPtr)
11999 {
12000     char **toks;
12001     int num_toks;
12002     StreamReassembleRuleOptionData *srod = NULL;
12003     toks = mSplit(parameters, ",", 4, &num_toks, 0);
12004 
12005     if (num_toks < 2)
12006     {
12007         FatalError("%s(%d): Invalid parameters for %s option\n",
12008                 file_name, file_line, name);
12009     }
12010 
12011     srod = SnortPreprocAlloc(1, sizeof(StreamReassembleRuleOptionData), PP_STREAM,
12012                         PP_MEM_CATEGORY_CONFIG);
12013 
12014     if (!srod)
12015     {
12016         FatalError("%s(%d): Failed to allocate data for %s option\n",
12017                 file_name, file_line, name);
12018     }
12019 
12020     /* Parse the action.
12021      * Can be: enable or disable
12022      */
12023     if (!strcasecmp(toks[0], "enable"))
12024     {
12025         srod->enable = 1;
12026     }
12027     else if (!strcasecmp(toks[0], "disable"))
12028     {
12029         srod->enable = 0;
12030     }
12031     else
12032     {
12033         FatalError("%s(%d): Invalid action: %s for option %s.  Valid "
12034                 "parameters are 'enable' or 'disable'\n",
12035                 file_name, file_line, toks[0], name);
12036     }
12037 
12038     /* Parse the direction.
12039      * Can be: client, server, both
12040      */
12041     /* Need to these around, so they match the ones specified via the stream5_tcp ports
12042      * option, ie, stream5_tcp: ports client enables reassembly on client-sourced traffic. */
12043     if (!strcasecmp(toks[1], "client"))
12044     {
12045         srod->direction = SSN_DIR_FROM_SERVER;
12046     }
12047     else if (!strcasecmp(toks[1], "server"))
12048     {
12049         srod->direction = SSN_DIR_FROM_CLIENT;
12050     }
12051     else if (!strcasecmp(toks[1], "both"))
12052     {
12053         srod->direction = SSN_DIR_BOTH;
12054     }
12055     else
12056     {
12057         FatalError("%s(%d): Invalid direction: %s for option %s\n",
12058                 file_name, file_line, toks[1], name);
12059     }
12060 
12061     /* Parse the optional parameters:
12062      * noalert flag, fastpath flag
12063      */
12064     srod->alert = 1;
12065     if (num_toks > 2)
12066     {
12067         int i = 2;
12068         for (; i< num_toks; i++)
12069         {
12070             if (!strcasecmp(toks[i], "noalert"))
12071             {
12072                 srod->alert = 0;
12073             }
12074             else if (!strcasecmp(toks[i], "fastpath"))
12075             {
12076                 srod->fastpath = 1;
12077                 if (srod->enable)
12078                 {
12079                     FatalError("%s(%d): Using 'fastpath' with 'enable' is "
12080                             "not valid for %s\n", file_name, file_line, name);
12081                 }
12082             }
12083             else
12084             {
12085                 FatalError("%s(%d): Invalid optional parameter: %s for option %s\n",
12086                         file_name, file_line, toks[i], name);
12087             }
12088         }
12089     }
12090 
12091     *dataPtr = srod;
12092     mSplitFree(&toks, num_toks);
12093 
12094     return 1;
12095 }
12096 
s5TcpStreamReassembleRuleOptionEval(void * p,const uint8_t ** cursor,void * dataPtr)12097 int s5TcpStreamReassembleRuleOptionEval(void *p, const uint8_t **cursor, void *dataPtr)
12098 {
12099     Packet *pkt = p;
12100     SessionControlBlock *scb = NULL;
12101     StreamReassembleRuleOptionData *srod = (StreamReassembleRuleOptionData *)dataPtr;
12102     PROFILE_VARS;
12103 
12104     if (!pkt || !pkt->ssnptr || !srod || !pkt->tcph)
12105         return 0;
12106 
12107     PREPROC_PROFILE_START(streamReassembleRuleOptionPerfStats);
12108     scb = pkt->ssnptr;
12109 
12110     if (!srod->enable) /* Turn it off */
12111         StreamSetReassemblyTcp(scb, STREAM_FLPOLICY_IGNORE, srod->direction, STREAM_FLPOLICY_SET_ABSOLUTE);
12112     else
12113         StreamSetReassemblyTcp(scb, STREAM_FLPOLICY_FOOTPRINT, srod->direction, STREAM_FLPOLICY_SET_ABSOLUTE);
12114 
12115     if (srod->fastpath)
12116     {
12117         /* Turn off inspection */
12118         scb->ha_state.ignore_direction |= srod->direction;
12119         session_api->disable_inspection(scb, pkt);
12120 
12121         /* TBD: Set TF_FORCE_FLUSH ? */
12122     }
12123 
12124     if (srod->alert)
12125     {
12126         PREPROC_PROFILE_END(streamReassembleRuleOptionPerfStats);
12127         return DETECTION_OPTION_MATCH;
12128     }
12129 
12130     PREPROC_PROFILE_END(streamReassembleRuleOptionPerfStats);
12131     return DETECTION_OPTION_NO_ALERT;
12132 }
12133 
s5TcpStreamReassembleRuleOptionCleanup(void * dataPtr)12134 void s5TcpStreamReassembleRuleOptionCleanup(void *dataPtr)
12135 {
12136     StreamReassembleRuleOptionData *srod = dataPtr;
12137     if (srod)
12138     {
12139         SnortPreprocFree(srod, sizeof(StreamReassembleRuleOptionData),
12140                  PP_STREAM, PP_MEM_CATEGORY_CONFIG);
12141     }
12142 }
12143 
s5TcpSetPortFilterStatus(struct _SnortConfig * sc,unsigned short port,uint16_t status,tSfPolicyId policyId,int parsing)12144 void s5TcpSetPortFilterStatus(struct _SnortConfig *sc, unsigned short port,
12145         uint16_t status, tSfPolicyId policyId, int parsing)
12146 {
12147     StreamConfig *config;
12148 
12149     config = getStreamPolicyConfig( policyId, parsing );
12150     if ( ( config != NULL ) && ( config->tcp_config != NULL ) )
12151         config->tcp_config->port_filter[ port ] |= status;
12152 }
12153 
s5TcpUnsetPortFilterStatus(struct _SnortConfig * sc,unsigned short port,uint16_t status,tSfPolicyId policyId,int parsing)12154 void s5TcpUnsetPortFilterStatus( struct _SnortConfig *sc, unsigned short port, uint16_t status,
12155         tSfPolicyId policyId, int parsing )
12156 {
12157     StreamConfig *config;
12158 
12159     config = getStreamPolicyConfig( policyId, parsing );
12160     if ( ( config != NULL ) && ( config->tcp_config != NULL ) )
12161         config->tcp_config->port_filter[ port ] &= ~status;
12162 }
12163 
s5TcpGetPortFilterStatus(struct _SnortConfig * sc,unsigned short port,tSfPolicyId policyId,int parsing)12164 int s5TcpGetPortFilterStatus(struct _SnortConfig *sc, unsigned short port, tSfPolicyId policyId, int parsing)
12165 {
12166     StreamConfig *config;
12167 
12168     config = getStreamPolicyConfig( policyId, parsing );
12169     if ( ( config != NULL ) && ( config->tcp_config != NULL ) )
12170         return ( int ) config->tcp_config->port_filter[ port ];
12171     else
12172         return PORT_MONITOR_NONE;
12173 }
12174 
s5TcpSetSynSessionStatus(struct _SnortConfig * sc,uint16_t status,tSfPolicyId policyId,int parsing)12175 void s5TcpSetSynSessionStatus(struct _SnortConfig *sc, uint16_t status, tSfPolicyId policyId, int parsing)
12176 {
12177     StreamConfig *config;
12178 
12179     if (status <= PORT_MONITOR_SESSION)
12180         return;
12181 
12182     config = getStreamPolicyConfig( policyId, parsing );
12183     if ( ( config != NULL ) && ( config->tcp_config != NULL ) )
12184         config->tcp_config->session_on_syn |= status;
12185 }
12186 
s5TcpUnsetSynSessionStatus(struct _SnortConfig * sc,uint16_t status,tSfPolicyId policyId,int parsing)12187 void s5TcpUnsetSynSessionStatus(struct _SnortConfig *sc, uint16_t status, tSfPolicyId policyId, int parsing)
12188 {
12189     StreamConfig *config;
12190 
12191     if (status <= PORT_MONITOR_SESSION)
12192         return;
12193 
12194     config = getStreamPolicyConfig( policyId, parsing );
12195     if ( ( config != NULL ) && ( config->tcp_config != NULL ) )
12196         config->tcp_config->session_on_syn &= ~status;
12197 }
12198 
targetPolicyIterate(void (* callback)(int))12199 static void targetPolicyIterate(void (*callback)(int))
12200 {
12201     unsigned int i;
12202 
12203     for (i = 0; i < snort_conf->num_policies_allocated; i++)
12204     {
12205         if (snort_conf->targeted_policies[i] != NULL)
12206         {
12207             callback(i);
12208         }
12209     }
12210 }
12211 
policyDecoderFlagsSaveNClear(int policyId)12212 static void policyDecoderFlagsSaveNClear(int policyId)
12213 {
12214     SnortPolicy *pPolicy = snort_conf->targeted_policies[policyId];
12215 
12216     if (pPolicy)
12217     {
12218         pPolicy->decoder_alert_flags_saved = pPolicy->decoder_alert_flags;
12219         pPolicy->decoder_drop_flags_saved  = pPolicy->decoder_drop_flags;
12220 
12221         pPolicy->decoder_alert_flags = 0;
12222         pPolicy->decoder_drop_flags = 0;
12223     }
12224 }
12225 
policyDecoderFlagsRestore(int policyId)12226 static void policyDecoderFlagsRestore(int policyId)
12227 {
12228     SnortPolicy *pPolicy = snort_conf->targeted_policies[policyId];
12229 
12230     if (pPolicy)
12231     {
12232         pPolicy->decoder_alert_flags = pPolicy->decoder_alert_flags_saved;
12233         pPolicy->decoder_drop_flags =  pPolicy->decoder_drop_flags_saved;
12234 
12235         pPolicy->decoder_alert_flags_saved = 0;
12236         pPolicy->decoder_drop_flags_saved = 0;
12237     }
12238 }
policyChecksumFlagsSaveNClear(int policyId)12239 static void policyChecksumFlagsSaveNClear(int policyId)
12240 {
12241     SnortPolicy *pPolicy = snort_conf->targeted_policies[policyId];
12242 
12243     if (pPolicy)
12244     {
12245         pPolicy->checksum_flags_saved = pPolicy->checksum_flags;
12246         pPolicy->checksum_flags = 0;
12247     }
12248 }
12249 
policyChecksumFlagsRestore(int policyId)12250 static void policyChecksumFlagsRestore(int policyId)
12251 {
12252     SnortPolicy *pPolicy = snort_conf->targeted_policies[policyId];
12253 
12254     if (pPolicy)
12255     {
12256         pPolicy->checksum_flags = pPolicy->checksum_flags_saved;
12257     }
12258 }
12259 
12260 typedef struct network_reassembly_ports
12261 {
12262     sfcidr_t *ip;
12263     uint8_t s_ports[MAXPORTS_STORAGE];
12264     uint8_t  c_ports[MAXPORTS_STORAGE];
12265 } NetworkReassemblyPorts;
12266 
12267 // single instance for saving ports registered with default policy...
12268 NetworkReassemblyPorts  default_nrps;
12269 
12270 // List head for list of networks and ports within that preprocs have requested for port
12271 // reassembly
12272 sfSDList targeted_nrps;
12273 
freeNrpNode(void * data)12274 static void freeNrpNode( void *data )
12275 {
12276     if( data )
12277     {
12278         NetworkReassemblyPorts *nrp = ( NetworkReassemblyPorts * ) data;
12279         if( nrp->ip != NULL )
12280             free( nrp->ip );
12281         SnortPreprocFree( data, sizeof( NetworkReassemblyPorts ),
12282                PP_STREAM, PP_MEM_CATEGORY_CONFIG );
12283     }
12284 }
12285 
StreamCreateReassemblyPortList(void)12286 static void StreamCreateReassemblyPortList( void )
12287 {
12288     //In SnortInit, we call ConfigurePreprocessors twice. The allocations done first need to be freed
12289     if(targeted_nrps.size > 0)
12290         StreamDestoryReassemblyPortList();
12291 
12292     sf_sdlist_init( &targeted_nrps, &freeNrpNode );
12293 }
12294 
StreamDestoryReassemblyPortList(void)12295 static void StreamDestoryReassemblyPortList( void )
12296 {
12297     sf_sdlist_purge( &targeted_nrps );
12298 }
12299 
initNetworkPortReassembly(sfcidr_t * ip,unsigned short port,int ra_dir)12300 static NetworkReassemblyPorts *initNetworkPortReassembly( sfcidr_t *ip, unsigned short port, int ra_dir )
12301 {
12302     NetworkReassemblyPorts *nrp = SnortPreprocAlloc( 1, sizeof( NetworkReassemblyPorts ),
12303                                      PP_STREAM, PP_MEM_CATEGORY_CONFIG );
12304 
12305     if( nrp == NULL )
12306     {
12307         ErrorMessage( " ERROR: Unable to allocate memory for initializing Network Reassembly Post List\n");
12308         return NULL;
12309     }
12310 
12311     nrp->ip = ip;
12312     if( ra_dir & SSN_DIR_FROM_SERVER )
12313         enablePort( nrp->s_ports, port );
12314 
12315     if( ra_dir & SSN_DIR_FROM_CLIENT )
12316         enablePort( nrp->c_ports, port );
12317 
12318     return nrp;
12319 }
12320 
registerPortForReassembly(char * network,uint16_t port,int ra_dir)12321 void registerPortForReassembly( char *network, uint16_t port, int ra_dir )
12322 {
12323     SFIP_RET status;
12324     SDListItem *net_node;
12325 
12326     // if network is NULL then this is a registration for the default policy
12327     if( network == NULL )
12328     {
12329         if( ra_dir & SSN_DIR_FROM_SERVER )
12330             enablePort( default_nrps.s_ports, port );
12331         if( ra_dir & SSN_DIR_FROM_CLIENT )
12332             enablePort( default_nrps.c_ports, port );
12333 
12334         return;
12335     }
12336     else
12337     {
12338         sfcidr_t *ip = sfip_alloc( network, &status );
12339         if ( status != SFIP_SUCCESS )
12340         {
12341             WarningMessage(
12342                     "Invalid network ( %s ) in reassembly registration request.", network );
12343             // free ip struct allocated above...
12344             if( ip != NULL )
12345                 sfip_free( ip );
12346             return;
12347         }
12348 
12349         net_node = sf_sdlist_head( &targeted_nrps );
12350         while( net_node != NULL )
12351         {
12352             SFIP_RET rc;
12353 
12354             NetworkReassemblyPorts *net_data = sf_sdlist_data( net_node );
12355             rc = sfip_compare( &net_data->ip->addr, &ip->addr );
12356             if( rc == SFIP_EQUAL )
12357             {
12358                 // already have this network in list, add the new port...
12359                 if( ra_dir & SSN_DIR_FROM_SERVER )
12360                     enablePort( net_data->s_ports, port );
12361                 if( ra_dir & SSN_DIR_FROM_CLIENT )
12362                     enablePort( net_data->c_ports, port );
12363                break;
12364             }
12365             else if( rc == SFIP_GREATER )
12366             {
12367                 // current network in list is 'greater' than network in registration request,
12368                 // this means request network is not in the list, so we add it as node before
12369                 // the current node...
12370                 // ptr to ip struct allocated above is stored in net data so set to NULL so
12371                 // we don't free it below...
12372                 NetworkReassemblyPorts *new_net = initNetworkPortReassembly( ip, port, ra_dir);
12373                 if( new_net != NULL)
12374                 {
12375                     sf_sdlist_ins_prev( &targeted_nrps, net_node, new_net );
12376                     ip = NULL;
12377                 }
12378                 break;
12379             }
12380             else
12381             {
12382                 // current network in list is 'less' than network in registration request...
12383                 // move to next entry
12384                 net_node = sf_sdlist_next( net_node );
12385             }
12386         }
12387 
12388         // finished searching list for matching network... if net_node is NULL then we did not
12389         // find a match AND all networks in the list are 'less than' or more general than the
12390         // request network...
12391         if( net_node == NULL )
12392         {
12393             // at list end and found no match, add new network to end of list
12394             // ptr to ip struct allocated above is stored in net data so set to NULL so
12395             // we don't free it below...
12396             NetworkReassemblyPorts *new_net = initNetworkPortReassembly( ip, port, ra_dir);
12397             if( new_net != NULL)
12398             {
12399                 sf_sdlist_ins_next( &targeted_nrps, sf_sdlist_tail( &targeted_nrps ), new_net );
12400                 ip = NULL;
12401             }
12402         }
12403 
12404         // free ip struct allocated above if not still in use...
12405         if( ip != NULL )
12406             sfip_free( ip );
12407     }
12408 }
12409 
enablePortsForReassembly(NetworkReassemblyPorts * nrp_list,StreamTcpPolicy * policy)12410 static void enablePortsForReassembly( NetworkReassemblyPorts *nrp_list, StreamTcpPolicy *policy )
12411 {
12412     uint32_t port;
12413 
12414     for( port = 0; port < MAXPORTS; port++)
12415     {
12416         if( isPortEnabled( nrp_list->s_ports, port ) )
12417         {
12418 #if 0
12419 // TBD-EDM
12420             InitFlushMgr(&policy->flush_config[port].server,
12421                     &policy->flush_point_list,
12422                     STREAM_FLPOLICY_FOOTPRINT, 0);
12423 #endif
12424         }
12425 
12426         if( isPortEnabled( nrp_list->c_ports, port ) )
12427         {
12428 #if 0
12429 // TBD-EDM
12430             InitFlushMgr(&policy->flush_config[port].client,
12431                     &policy->flush_point_list,
12432                     STREAM_FLPOLICY_FOOTPRINT, 0);
12433 #endif
12434         }
12435     }
12436 }
12437 
enableTargetedPolicyReassemblyPorts(StreamConfig * config)12438 void enableTargetedPolicyReassemblyPorts( StreamConfig *config )
12439 {
12440     SDListItem *prev_node;
12441     SDListItem *net_node = sf_sdlist_head( &targeted_nrps );
12442     while( net_node != NULL )
12443     {
12444         NetworkReassemblyPorts *nrp_list = sf_sdlist_data( net_node );
12445         StreamTcpPolicy *policy = StreamSearchTcpConfigForBoundPolicy( config->tcp_config,
12446                                                                        &nrp_list->ip->addr );
12447         if( policy == config->tcp_config->default_policy )
12448         {
12449             // no existing policy for this network...create a new one by cloning
12450             // the default policy
12451             policy = StreamTcpPolicyClone( config->tcp_config->default_policy,
12452                                            config );
12453         }
12454 
12455         // init the ports registered specifically for this network...
12456         enablePortsForReassembly( nrp_list, policy );
12457 
12458         // now look back up the list of networks and register ports from all networks
12459         // that contain the current network...
12460         prev_node = sf_sdlist_prev( net_node );
12461         while( prev_node != NULL )
12462         {
12463             NetworkReassemblyPorts *prev_nrp_list = sf_sdlist_data( prev_node );
12464 
12465             if( sfip_contains( prev_nrp_list->ip, &nrp_list->ip->addr ) == SFIP_CONTAINS )
12466                 enablePortsForReassembly( prev_nrp_list, policy );
12467             prev_node = sf_sdlist_prev( prev_node );
12468         }
12469 
12470         net_node = sf_sdlist_next( net_node );
12471     }
12472 }
12473 
enableRegisteredPortsForReassembly(struct _SnortConfig * sc)12474 void enableRegisteredPortsForReassembly( struct _SnortConfig *sc )
12475 {
12476     int idx;
12477     tSfPolicyUserContextId stream_cfg = (stream_parsing_config)? stream_parsing_config : stream_online_config;
12478     StreamConfig *config = (StreamConfig *) sfPolicyUserDataGet(stream_cfg, getParserPolicy(sc));
12479 
12480     // Since stream configs are inherited from the default,
12481     // we should attempt to fetch the default policy config
12482     // if the non-default lookup failed
12483     if (!config && getParserPolicy(sc) != getDefaultPolicy())
12484         config = (StreamConfig *) sfPolicyUserDataGet(
12485             stream_cfg,
12486             getDefaultPolicy()
12487         );
12488 
12489     if (!config)
12490     {
12491         WarningMessage(
12492             "Stream TCP not enabled in default configuration.\n"
12493         );
12494 
12495         return;
12496     }
12497 
12498 
12499     // iterate thru list of networks, init'ing all ports requested from reassembly for each
12500     enableTargetedPolicyReassemblyPorts( config );
12501 
12502     // ... now init ports registered with the default policy, these ports also get
12503     // registered with all targeted policies...
12504     enablePortsForReassembly( &default_nrps, config->tcp_config->default_policy );
12505 
12506     // enable ports in all target policies...
12507     for (idx = 0; idx < config->tcp_config->num_policies; idx++)
12508         enablePortsForReassembly( &default_nrps,  config->tcp_config->policy_list[ idx ] );
12509 
12510     // all ports registered for reassembly have been enabled in all appropriate networks,
12511     // free memory used to cache the requests...
12512     StreamDestoryReassemblyPortList( );
12513 }
12514 
12515 
SetFTPFileLocation(void * scbptr,bool flush)12516 void SetFTPFileLocation(void *scbptr ,bool flush)
12517 {
12518   SessionControlBlock *scb = ( SessionControlBlock * ) scbptr;
12519   TcpSession * tcpssn;
12520 
12521   if ( scb  && scb->proto_specific_data && scb->proto_specific_data->data)
12522   {
12523     tcpssn = (TcpSession *)scb->proto_specific_data->data;
12524     tcpssn->client.flush_mgr.flush = flush;
12525     tcpssn->server.flush_mgr.flush = flush;
12526   }
12527 }
12528 
12529 
unregisterPortForReassembly(char * network,uint16_t port,int ra_dir)12530 void unregisterPortForReassembly( char *network, uint16_t port, int ra_dir )
12531 {
12532 
12533     // TBD may not need this capability...
12534     WarningMessage( "Unregistering ports for reassembly not currently supported" );
12535     return;
12536 }
12537 
StreamIsSessionHttp2Tcp(SessionControlBlock * scb)12538 bool StreamIsSessionHttp2Tcp( SessionControlBlock *scb )
12539 {
12540     if ( scb->ha_state.session_flags & SSNFLAG_HTTP_2)
12541     {
12542         return true;
12543     }
12544     return false;
12545 }
12546 
StreamSetSessionHttp2Tcp(SessionControlBlock * scb)12547 void StreamSetSessionHttp2Tcp( SessionControlBlock *scb )
12548 {
12549     scb->ha_state.session_flags |= SSNFLAG_HTTP_2;
12550 }
12551 
StreamIsSessionHttp2UpgTcp(SessionControlBlock * scb)12552 bool StreamIsSessionHttp2UpgTcp( SessionControlBlock *scb )
12553 {
12554     if ( scb->ha_state.session_flags & SSNFLAG_HTTP_2_UPG)
12555     {
12556         return true;
12557     }
12558     return false;
12559 }
12560 
StreamSetSessionHttp2UpgTcp(SessionControlBlock * scb)12561 void StreamSetSessionHttp2UpgTcp( SessionControlBlock *scb )
12562 {
12563     scb->ha_state.session_flags |= SSNFLAG_HTTP_2_UPG;
12564 }
12565 
12566 #ifdef SNORT_RELOAD
SessionTCPReload(uint32_t max_sessions,uint16_t pruningTimeout,uint16_t nominalTimeout)12567 void SessionTCPReload(uint32_t max_sessions, uint16_t pruningTimeout, uint16_t nominalTimeout)
12568 {
12569     SessionReload(tcp_lws_cache, max_sessions, pruningTimeout, nominalTimeout
12570 #ifdef REG_TEST
12571                   , "TCP"
12572 #endif
12573                   );
12574 }
12575 
SessionTCPReloadAdjust(unsigned maxWork)12576 unsigned SessionTCPReloadAdjust(unsigned maxWork)
12577 {
12578     return SessionProtocolReloadAdjust(tcp_lws_cache, session_configuration->max_tcp_sessions,
12579                                        maxWork, session_configuration->memcap
12580 #ifdef REG_TEST
12581                                        , "TCP"
12582 #endif
12583                                        );
12584 }
12585 #endif
12586 
12587 #ifdef HAVE_DAQ_DECRYPTED_SSL
StreamSimulatePeerTcpAckp(SessionControlBlock * scb,uint8_t dir,uint32_t tcp_payload_len)12588 int StreamSimulatePeerTcpAckp( SessionControlBlock *scb, uint8_t dir, uint32_t tcp_payload_len )
12589 {
12590 
12591     StreamTracker *talker = NULL;
12592     StreamTracker *listener = NULL;
12593     TcpSession *tcpssn = NULL;
12594 
12595     if ((tcp_payload_len == 0) || !scb)
12596     {
12597         STREAM_DEBUG_WRAP(DebugMessage(DEBUG_STREAM_STATE,
12598                           "Stream: no SCB %p or zero length %d \n", scb, tcp_payload_len););
12599         return -1;
12600     }
12601     if (scb->proto_specific_data)
12602         tcpssn = (TcpSession *)scb->proto_specific_data->data;
12603     if (!tcpssn) {
12604         STREAM_DEBUG_WRAP(DebugMessage(DEBUG_STREAM_STATE,
12605                           "Stream: no tcpssn \n"););
12606         return -1;
12607     }
12608 
12609     if (dir == 0)
12610     {
12611         // Packet from Server. (p->packet_flags & PKT_FROM_SERVER) is TRUE.
12612         talker = &tcpssn->server;
12613         listener = &tcpssn->client;
12614     } else
12615     {
12616         talker = &tcpssn->client;
12617         listener = &tcpssn->server;
12618     }
12619     talker->l_unackd += tcp_payload_len;
12620     listener->r_win_base += tcp_payload_len;
12621     purge_flushed_ackd(tcpssn, listener);
12622 
12623     return 0;
12624 }
12625 #endif
12626 
get_tcp_used_mempool()12627 size_t get_tcp_used_mempool()
12628 {
12629     if (tcp_lws_cache && tcp_lws_cache->protocol_session_pool)
12630         return tcp_lws_cache->protocol_session_pool->used_memory;
12631 
12632     return 0;
12633 }
12634 
12635