1 /* Copyright (C) 2007-2010 Open Information Security Foundation
2  *
3  * You can copy, redistribute or modify this Program under the terms of
4  * the GNU General Public License version 2 as published by the Free
5  * Software Foundation.
6  *
7  * This program is distributed in the hope that it will be useful,
8  * but WITHOUT ANY WARRANTY; without even the implied warranty of
9  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
10  * GNU General Public License for more details.
11  *
12  * You should have received a copy of the GNU General Public License
13  * version 2 along with this program; if not, write to the Free Software
14  * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
15  * 02110-1301, USA.
16  */
17 
18 /**
19  * \file
20  *
21  * \author Victor Julien <victor@inliniac.net>
22  */
23 
24 #ifndef __STREAM_TCP_PRIVATE_H__
25 #define __STREAM_TCP_PRIVATE_H__
26 
27 #include "tree.h"
28 #include "decode.h"
29 #include "util-pool.h"
30 #include "util-pool-thread.h"
31 #include "util-streaming-buffer.h"
32 
33 #define STREAMTCP_QUEUE_FLAG_TS     0x01
34 #define STREAMTCP_QUEUE_FLAG_WS     0x02
35 #define STREAMTCP_QUEUE_FLAG_SACK   0x04
36 
37 /** currently only SYN/ACK */
38 typedef struct TcpStateQueue_ {
39     uint8_t flags;
40     uint8_t wscale;
41     uint16_t win;
42     uint32_t seq;
43     uint32_t ack;
44     uint32_t ts;
45     uint32_t pkt_ts;
46     struct TcpStateQueue_ *next;
47 } TcpStateQueue;
48 
49 typedef struct StreamTcpSackRecord {
50     uint32_t le;    /**< left edge, host order */
51     uint32_t re;    /**< right edge, host order */
52     RB_ENTRY(StreamTcpSackRecord) rb;
53 } StreamTcpSackRecord;
54 
55 int TcpSackCompare(struct StreamTcpSackRecord *a, struct StreamTcpSackRecord *b);
56 
57 /* red-black tree prototype for SACK records */
58 RB_HEAD(TCPSACK, StreamTcpSackRecord);
59 RB_PROTOTYPE(TCPSACK, StreamTcpSackRecord, rb, TcpSackCompare);
60 
61 typedef struct TcpSegment {
62     PoolThreadReserved res;
63     uint16_t payload_len;       /**< actual size of the payload */
64     uint32_t seq;
65     RB_ENTRY(TcpSegment) __attribute__((__packed__)) rb;
66     StreamingBufferSegment sbseg;
67 } __attribute__((__packed__)) TcpSegment;
68 
69 /** \brief compare function for the Segment tree
70  *
71  *  Main sort point is the sequence number. When sequence numbers
72  *  are equal compare payload_len as well. This way the tree is
73  *  sorted by seq, and in case of duplicate seqs we are sorted
74  *  small to large.
75  */
76 int TcpSegmentCompare(struct TcpSegment *a, struct TcpSegment *b);
77 
78 /* red-black tree prototype for TcpSegment */
79 RB_HEAD(TCPSEG, TcpSegment);
80 RB_PROTOTYPE(TCPSEG, TcpSegment, rb, TcpSegmentCompare);
81 
82 #define TCP_SEG_LEN(seg)        (seg)->payload_len
83 #define TCP_SEG_OFFSET(seg)     (seg)->sbseg.stream_offset
84 
85 #define SEG_SEQ_RIGHT_EDGE(seg) ((seg)->seq + TCP_SEG_LEN((seg)))
86 
87 /* get right edge of sequence space of seen segments.
88  * Only use if STREAM_HAS_SEEN_DATA is true. */
89 #define STREAM_SEQ_RIGHT_EDGE(stream)   (stream)->segs_right_edge
90 #define STREAM_RIGHT_EDGE(stream)       (STREAM_BASE_OFFSET((stream)) + (STREAM_SEQ_RIGHT_EDGE((stream)) - (stream)->base_seq))
91 /* return true if we have seen data segments. */
92 #define STREAM_HAS_SEEN_DATA(stream)    (!RB_EMPTY(&(stream)->sb.sbb_tree) || (stream)->sb.stream_offset || (stream)->sb.buf_offset)
93 
94 typedef struct TcpStream_ {
95     uint16_t flags:12;              /**< Flag specific to the stream e.g. Timestamp */
96     /* coccinelle: TcpStream:flags:STREAMTCP_STREAM_FLAG_ */
97     uint16_t wscale:4;              /**< wscale setting in this direction, 4 bits as max val is 15 */
98     uint8_t os_policy;              /**< target based OS policy used for reassembly and handling packets*/
99     uint8_t tcp_flags;              /**< TCP flags seen */
100 
101     uint32_t isn;                   /**< initial sequence number */
102     uint32_t next_seq;              /**< next expected sequence number */
103     uint32_t last_ack;              /**< last ack'd sequence number in this stream */
104     uint32_t next_win;              /**< next max seq within window */
105     uint32_t window;                /**< current window setting, after wscale is applied */
106 
107     uint32_t last_ts;               /**< Time stamp (TSVAL) of the last seen packet for this stream*/
108     uint32_t last_pkt_ts;           /**< Time of last seen packet for this stream (needed for PAWS update)
109                                          This will be used to validate the last_ts, when connection has been idle for
110                                          longer time.(RFC 1323)*/
111     /* reassembly */
112     uint32_t base_seq;              /**< seq where we are left with reassebly. Matches STREAM_BASE_OFFSET below. */
113 
114     uint32_t app_progress_rel;      /**< app-layer progress relative to STREAM_BASE_OFFSET */
115     uint32_t raw_progress_rel;      /**< raw reassembly progress relative to STREAM_BASE_OFFSET */
116     uint32_t log_progress_rel;      /**< streaming logger progress relative to STREAM_BASE_OFFSET */
117 
118     uint32_t min_inspect_depth;     /**< min inspect size set by the app layer, to make sure enough data
119                                      *   remains available for inspection together with app layer buffers */
120     uint32_t data_required;         /**< data required from STREAM_APP_PROGRESS before calling app-layer again */
121 
122     StreamingBuffer sb;
123     struct TCPSEG seg_tree;         /**< red black tree of TCP segments. Data is stored in TcpStream::sb */
124     uint32_t segs_right_edge;
125 
126     uint32_t sack_size;             /**< combined size of the SACK ranges currently in our tree. Updated
127                                      *   at INSERT/REMOVE time. */
128     struct TCPSACK sack_tree;       /**< red back tree of TCP SACK records. */
129 } TcpStream;
130 
131 #define STREAM_BASE_OFFSET(stream)  ((stream)->sb.stream_offset)
132 #define STREAM_APP_PROGRESS(stream) (STREAM_BASE_OFFSET((stream)) + (stream)->app_progress_rel)
133 #define STREAM_RAW_PROGRESS(stream) (STREAM_BASE_OFFSET((stream)) + (stream)->raw_progress_rel)
134 #define STREAM_LOG_PROGRESS(stream) (STREAM_BASE_OFFSET((stream)) + (stream)->log_progress_rel)
135 
136 /* from /usr/include/netinet/tcp.h */
137 enum TcpState
138 {
139     TCP_NONE,
140     TCP_LISTEN,
141     TCP_SYN_SENT,
142     TCP_SYN_RECV,
143     TCP_ESTABLISHED,
144     TCP_FIN_WAIT1,
145     TCP_FIN_WAIT2,
146     TCP_TIME_WAIT,
147     TCP_LAST_ACK,
148     TCP_CLOSE_WAIT,
149     TCP_CLOSING,
150     TCP_CLOSED,
151 };
152 
153 /*
154  * Per SESSION flags
155  */
156 
157 /** Flag for mid stream session */
158 #define STREAMTCP_FLAG_MIDSTREAM                    0x0001
159 /** Flag for mid stream established session */
160 #define STREAMTCP_FLAG_MIDSTREAM_ESTABLISHED        0x0002
161 /** Flag for mid session when syn/ack is received */
162 #define STREAMTCP_FLAG_MIDSTREAM_SYNACK             0x0004
163 /** Flag for TCP Timestamp option */
164 #define STREAMTCP_FLAG_TIMESTAMP                    0x0008
165 /** Server supports wscale (even though it can be 0) */
166 #define STREAMTCP_FLAG_SERVER_WSCALE                0x0010
167 /** Closed by RST */
168 #define STREAMTCP_FLAG_CLOSED_BY_RST                0x0020
169 /** Flag to indicate that the session is handling asynchronous stream.*/
170 #define STREAMTCP_FLAG_ASYNC                        0x0040
171 /** Flag to indicate we're dealing with 4WHS: SYN, SYN, SYN/ACK, ACK
172  * (http://www.breakingpointsystems.com/community/blog/tcp-portals-the-three-way-handshake-is-a-lie) */
173 #define STREAMTCP_FLAG_4WHS                         0x0080
174 /** Flag to indicate that this session is possible trying to evade the detection
175  *  (http://www.packetstan.com/2010/06/recently-ive-been-on-campaign-to-make.html) */
176 #define STREAMTCP_FLAG_DETECTION_EVASION_ATTEMPT    0x0100
177 /** Flag to indicate the client (SYN pkt) permits SACK */
178 #define STREAMTCP_FLAG_CLIENT_SACKOK                0x0200
179 /** Flag to indicate both sides of the session permit SACK (SYN + SYN/ACK) */
180 #define STREAMTCP_FLAG_SACKOK                       0x0400
181 // vacancy
182 /** 3WHS confirmed by server -- if suri sees 3whs ACK but server doesn't (pkt
183  *  is lost on the way to server), SYN/ACK is retransmitted. If server sends
184  *  normal packet we assume 3whs to be completed. Only used for SYN/ACK resend
185  *  event. */
186 #define STREAMTCP_FLAG_3WHS_CONFIRMED               0x1000
187 /** App Layer tracking/reassembly is disabled */
188 #define STREAMTCP_FLAG_APP_LAYER_DISABLED           0x2000
189 /** Stream can be bypass */
190 #define STREAMTCP_FLAG_BYPASS                       0x4000
191 /** SSN uses TCP Fast Open */
192 #define STREAMTCP_FLAG_TCP_FAST_OPEN                0x8000
193 
194 /*
195  * Per STREAM flags
196  */
197 
198 // bit 0 vacant
199 /** Flag to avoid stream reassembly/app layer inspection for the stream */
200 #define STREAMTCP_STREAM_FLAG_NOREASSEMBLY                  BIT_U16(1)
201 /** we received a keep alive */
202 #define STREAMTCP_STREAM_FLAG_KEEPALIVE                     BIT_U16(2)
203 /** Stream has reached it's reassembly depth, all further packets are ignored */
204 #define STREAMTCP_STREAM_FLAG_DEPTH_REACHED                 BIT_U16(3)
205 /** Trigger reassembly next time we need 'raw' */
206 #define STREAMTCP_STREAM_FLAG_TRIGGER_RAW                   BIT_U16(4)
207 /** Stream supports TIMESTAMP -- used to set ssn STREAMTCP_FLAG_TIMESTAMP
208  *  flag. */
209 #define STREAMTCP_STREAM_FLAG_TIMESTAMP                     BIT_U16(5)
210 /** Flag to indicate the zero value of timestamp */
211 #define STREAMTCP_STREAM_FLAG_ZERO_TIMESTAMP                BIT_U16(6)
212 /** App proto detection completed */
213 #define STREAMTCP_STREAM_FLAG_APPPROTO_DETECTION_COMPLETED  BIT_U16(7)
214 /** App proto detection skipped */
215 #define STREAMTCP_STREAM_FLAG_APPPROTO_DETECTION_SKIPPED    BIT_U16(8)
216 /** Raw reassembly disabled for new segments */
217 #define STREAMTCP_STREAM_FLAG_NEW_RAW_DISABLED              BIT_U16(9)
218 /** Raw reassembly disabled completely */
219 #define STREAMTCP_STREAM_FLAG_DISABLE_RAW                   BIT_U16(10)
220 
221 #define STREAMTCP_STREAM_FLAG_RST_RECV                      BIT_U16(11)
222 
223 /** NOTE: flags field is 12 bits */
224 
225 
226 
227 
228 #define PAWS_24DAYS         2073600         /**< 24 days in seconds */
229 
230 #define PKT_IS_IN_RIGHT_DIR(ssn, p)        ((ssn)->flags & STREAMTCP_FLAG_MIDSTREAM_SYNACK ? \
231                                             PKT_IS_TOSERVER(p) ? (p)->flowflags &= ~FLOW_PKT_TOSERVER \
232                                             (p)->flowflags |= FLOW_PKT_TOCLIENT : (p)->flowflags &= ~FLOW_PKT_TOCLIENT \
233                                             (p)->flowflags |= FLOW_PKT_TOSERVER : 0)
234 
235 /* Macro's for comparing Sequence numbers
236  * Page 810 from TCP/IP Illustrated, Volume 2. */
237 #define SEQ_EQ(a,b)  ((int32_t)((a) - (b)) == 0)
238 #define SEQ_LT(a,b)  ((int32_t)((a) - (b)) <  0)
239 #define SEQ_LEQ(a,b) ((int32_t)((a) - (b)) <= 0)
240 #define SEQ_GT(a,b)  ((int32_t)((a) - (b)) >  0)
241 #define SEQ_GEQ(a,b) ((int32_t)((a) - (b)) >= 0)
242 
243 #define STREAMTCP_SET_RA_BASE_SEQ(stream, seq) { \
244     do { \
245         (stream)->base_seq = (seq) + 1;    \
246     } while(0); \
247 }
248 
249 #define StreamTcpSetEvent(p, e) {                                           \
250     if ((p)->flags & PKT_STREAM_NO_EVENTS) {                                \
251         SCLogDebug("not setting event %d on pkt %p (%"PRIu64"), "     \
252                    "stream in known bad condition", (e), p, (p)->pcap_cnt); \
253     } else {                                                                \
254         SCLogDebug("setting event %d on pkt %p (%"PRIu64")",          \
255                     (e), p, (p)->pcap_cnt);                                 \
256         ENGINE_SET_EVENT((p), (e));                                         \
257     }                                                                       \
258 }
259 
260 typedef struct TcpSession_ {
261     PoolThreadReserved res;
262     uint8_t state:4;                        /**< tcp state from state enum */
263     uint8_t pstate:4;                       /**< previous state */
264     uint8_t queue_len;                      /**< length of queue list below */
265     int8_t data_first_seen_dir;
266     /** track all the tcp flags we've seen */
267     uint8_t tcp_packet_flags;
268     /* coccinelle: TcpSession:flags:STREAMTCP_FLAG */
269     uint16_t flags;
270     uint32_t reassembly_depth;      /**< reassembly depth for the stream */
271     TcpStream server;
272     TcpStream client;
273     TcpStateQueue *queue;                   /**< list of SYN/ACK candidates */
274 } TcpSession;
275 
276 #define StreamTcpSetStreamFlagAppProtoDetectionCompleted(stream) \
277     ((stream)->flags |= STREAMTCP_STREAM_FLAG_APPPROTO_DETECTION_COMPLETED)
278 #define StreamTcpIsSetStreamFlagAppProtoDetectionCompleted(stream) \
279     ((stream)->flags & STREAMTCP_STREAM_FLAG_APPPROTO_DETECTION_COMPLETED)
280 #define StreamTcpResetStreamFlagAppProtoDetectionCompleted(stream) \
281     ((stream)->flags &= ~STREAMTCP_STREAM_FLAG_APPPROTO_DETECTION_COMPLETED);
282 #define StreamTcpDisableAppLayerReassembly(ssn) do { \
283         SCLogDebug("setting STREAMTCP_FLAG_APP_LAYER_DISABLED on ssn %p", ssn); \
284         ((ssn)->flags |= STREAMTCP_FLAG_APP_LAYER_DISABLED); \
285     } while (0);
286 
287 #endif /* __STREAM_TCP_PRIVATE_H__ */
288