1 /****************************************************************************
2 *
3 * Copyright (C) 2014-2021 Cisco and/or its affiliates. All rights reserved.
4 * Copyright (C) 2003-2013 Sourcefire, Inc.
5 *
6 * This program is free software; you can redistribute it and/or modify
7 * it under the terms of the GNU General Public License Version 2 as
8 * published by the Free Software Foundation. You may not use, modify or
9 * distribute this program under any other version of the GNU General
10 * Public License.
11 *
12 * This program is distributed in the hope that it will be useful,
13 * but WITHOUT ANY WARRANTY; without even the implied warranty of
14 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
15 * GNU General Public License for more details.
16 *
17 * You should have received a copy of the GNU General Public License
18 * along with this program; if not, write to the Free Software
19 * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
20 *
21 ****************************************************************************/
22
23 #ifndef __SNORT_HTTPINSPECT_H__
24 #define __SNORT_HTTPINSPECT_H__
25
26 #include "decode.h"
27 #include "session_api.h"
28 #include "stream_api.h"
29 #include "hi_ui_config.h"
30 #include "util_utf.h"
31 #include "detection_util.h"
32 #include "mempool.h"
33 #include "str_search.h"
34 #include "util_jsnorm.h"
35 #include "memory_stats.h"
36
37 #include <zlib.h>
38
39 extern MemPool *http_mempool;
40 extern MemPool *mime_decode_mempool;
41 extern MemPool *mime_log_mempool;
42
43 extern DataBuffer HttpDecodeBuf;
44
45 #ifdef PERF_PROFILING
46 extern PreprocStats hi2PerfStats;
47 extern PreprocStats hi2InitPerfStats;
48 extern PreprocStats hi2PayloadPerfStats;
49 extern PreprocStats hi2PseudoPerfStats;
50 #endif
51
52 /**
53 ** The definition of the configuration separators in the snort.conf
54 ** configure line.
55 */
56 #define CONF_SEPARATORS " \t\n\r"
57 #define MAX_METHOD_LEN 256
58
59 /*
60 ** These are the definitions of the parser section delimiting
61 ** keywords to configure HttpInspect. When one of these keywords
62 ** are seen, we begin a new section.
63 */
64 #define GLOBAL "global"
65 #define GLOBAL_SERVER "global_server"
66 #define SERVER "server"
67 #define CLIENT "client"
68
69 #define DEFAULT_HTTP_MEMCAP 150994944 /* 144 MB */
70 #define MIN_HTTP_MEMCAP 2304
71 #define MAX_HTTP_MEMCAP 603979776 /* 576 MB */
72 #define MAX_URI_EXTRACTED 2048
73 #define MAX_HOSTNAME 256
74
75
76 #define DEFAULT_MAX_GZIP_MEM 838860
77 #define GZIP_MEM_MIN 3276
78 #define MAX_GZIP_DEPTH 65535
79 #define DEFAULT_COMP_DEPTH 1460
80 #define DEFAULT_DECOMP_DEPTH 2920
81
82 #define DEFLATE_RAW_WBITS -15
83 #define DEFLATE_WBITS 15
84 #define GZIP_WBITS 31
85
86 #define XFF_MAX_PIPELINE_REQ 255
87
88
89 #define CONTENT_NONE 0x00
90 #define PARTIAL_CONTENT 0x01
91 #define FULL_CONTENT 0x02
92 #define GET_REQ_WITH_RANGE 0x04
93
94 typedef enum _HttpRespCompressType
95 {
96 HTTP_RESP_COMPRESS_TYPE__GZIP = 0x00000001,
97 HTTP_RESP_COMPRESS_TYPE__DEFLATE = 0x00000002
98
99 } _HttpRespCompressType;
100
101 typedef enum _DecompressStage
102 {
103 HTTP_DECOMP_START,
104 HTTP_DECOMP_MID,
105 HTTP_DECOMP_FIN
106 } DecompressStage;
107
108 typedef struct s_DECOMPRESS_STATE
109 {
110 uint8_t inflate_init;
111 uint16_t compress_fmt;
112 uint8_t decompress_data;
113 int compr_bytes_read;
114 int decompr_bytes_read;
115 int compr_depth;
116 int decompr_depth;
117 z_stream d_stream;
118 MemBucket *bkt;
119 bool deflate_initialized;
120 DecompressStage stage;
121 } DECOMPRESS_STATE;
122
123 typedef enum _ChunkLenState
124 {
125 CHUNK_LEN_DEFAULT = 0,
126 CHUNK_LEN_INCOMPLETE
127 } ChunkLenState;
128
129 typedef struct s_HTTP_RESP_STATE
130 {
131 uint8_t inspect_body;
132 uint8_t inspect_reassembled;
133 uint8_t last_pkt_contlen;
134 uint8_t last_pkt_chunked;
135 uint32_t next_seq;
136 uint32_t chunk_remainder;
137 int data_extracted;
138 uint32_t max_seq;
139 bool flow_depth_excd;
140 bool eoh_found;
141 uint8_t look_for_partial_content;
142 uint8_t chunk_len_state;
143 }HTTP_RESP_STATE;
144
145 typedef struct s_HTTP_LOG_STATE
146 {
147 uint32_t uri_bytes;
148 uint32_t hostname_bytes;
149 MemBucket *log_bucket;
150 uint8_t *uri_extracted;
151 uint8_t *hostname_extracted;
152 }HTTP_LOG_STATE;
153
154 typedef struct _Transaction
155 {
156 uint8_t tID;
157 sfaddr_t *true_ip;
158 struct _Transaction *next;
159 }Transaction;
160
161 typedef struct _HttpSessionData
162 {
163 uint64_t event_flags;
164 HTTP_RESP_STATE resp_state;
165 DECOMPRESS_STATE *decomp_state;
166 HTTP_LOG_STATE *log_state;
167 decode_utf_state_t utf_state;
168 uint8_t log_flags;
169 uint8_t cli_small_chunk_count;
170 uint8_t srv_small_chunk_count;
171 uint8_t http_req_id;
172 uint8_t http_resp_id;
173 uint8_t is_response;
174 uint8_t tList_count;
175 MimeState *mime_ssn;
176 fd_session_p_t fd_state;
177 Transaction *tList_start;
178 Transaction *tList_end;
179 } HttpSessionData;
180
181 typedef struct _HISearch
182 {
183 char *name;
184 int name_len;
185
186 } HISearch;
187
188 typedef struct _HiSearchToken
189 {
190 char *name;
191 int name_len;
192 int search_id;
193 } HiSearchToken;
194
195 typedef struct _HISearchInfo
196 {
197 int id;
198 int index;
199 int length;
200 } HISearchInfo;
201
202
203 #define COPY_URI 1
204 #define COPY_HOSTNAME 2
205
206 #define HTTP_LOG_URI 0x0001
207 #define HTTP_LOG_HOSTNAME 0x0002
208 #define HTTP_LOG_GZIP_DATA 0x0004
209 #define HTTP_LOG_JSNORM_DATA 0x0008
210
211 typedef enum _HiSearchIdEnum
212 {
213 HI_JAVASCRIPT = 0,
214 HI_LAST
215 } HiSearchId;
216
217 typedef enum _HtmlSearchIdEnum
218 {
219 HTML_JS = 0,
220 HTML_EMA,
221 HTML_VB,
222 HTML_LAST
223 } HtmlSearchId;
224
225 extern void *hi_javascript_search_mpse;
226 extern void *hi_htmltype_search_mpse;
227 extern HISearch hi_js_search[HI_LAST];
228 extern HISearch hi_html_search[HTML_LAST];
229 extern HISearch *hi_current_search;
230 extern HISearchInfo hi_search_info;
231
232 void ApplyFlowDepth(HTTPINSPECT_CONF *, Packet *, HttpSessionData *, int, int, uint32_t);
233
234
235
236 int SnortHttpInspect(HTTPINSPECT_GLOBAL_CONF *GlobalConf, Packet *p);
237 int ProcessGlobalConf(HTTPINSPECT_GLOBAL_CONF *, char *, int, char **saveptr);
238 int PrintGlobalConf(HTTPINSPECT_GLOBAL_CONF *);
239 int ProcessUniqueServerConf(struct _SnortConfig *, HTTPINSPECT_GLOBAL_CONF *, char *, int, char **);
240 int HttpInspectInitializeGlobalConfig(HTTPINSPECT_GLOBAL_CONF *, char *, int);
241 HttpSessionData * SetNewHttpSessionData(Packet *, void *);
242 void FreeHttpSessionData(void *data);
243 int GetHttpTrueIP(void *data, uint8_t **buf, uint32_t *len, uint32_t *type);
244 int GetHttpGzipData(void *data, uint8_t **buf, uint32_t *len, uint32_t *type);
245 int GetHttpJSNormData(void *data, uint8_t **buf, uint32_t *len, uint32_t *type);
246 int GetHttpUriData(void *data, uint8_t **buf, uint32_t *len, uint32_t *type);
247 int GetHttpHostnameData(void *data, uint8_t **buf, uint32_t *len, uint32_t *type);
248 void HI_SearchInit(void);
249 void HI_SearchFree(void);
250 int HI_SearchStrFound(void *, void *, int , void *, void *);
251 int GetHttpFlowDepth(void *, uint32_t);
252 uint8_t isHttpRespPartialCont(void *data);
253 bool GetHttpFastBlockingStatus();
254
GetHttpSessionData(Packet * p)255 static inline HttpSessionData * GetHttpSessionData(Packet *p)
256 {
257 if (p->ssnptr == NULL)
258 return NULL;
259 return (HttpSessionData *)session_api->get_application_data(p->ssnptr, PP_HTTPINSPECT);
260 }
261
freeTransactionNode(Transaction * tPtr)262 static inline void freeTransactionNode(Transaction *tPtr)
263 {
264 if(tPtr->true_ip)
265 sfaddr_free(tPtr->true_ip);
266 SnortPreprocFree(tPtr, sizeof (Transaction), PP_HTTPINSPECT, PP_MEM_CATEGORY_SESSION);
267 hi_stats.mem_used -= sizeof(Transaction);
268 }
269
deleteNode_tList(HttpSessionData * hsd)270 static inline void deleteNode_tList(HttpSessionData *hsd)
271 {
272 Transaction *tmp = hsd->tList_start;
273 hsd->tList_start = hsd->tList_start->next;
274 if( hsd->tList_start == NULL )
275 hsd->tList_end = NULL;
276 freeTransactionNode(tmp);
277 }
278
GetTrueIPForSession(void * data)279 static inline sfaddr_t *GetTrueIPForSession(void *data)
280 {
281 HttpSessionData *hsd = NULL;
282
283 if (data == NULL)
284 return NULL;
285 hsd = (HttpSessionData *)session_api->get_application_data(data, PP_HTTPINSPECT);
286
287 if(hsd == NULL)
288 return NULL;
289
290 if( hsd->tList_start != NULL )
291 {
292 if ((hsd->is_response == 0) && ( hsd->http_req_id == hsd->tList_end->tID ) )
293 return hsd->tList_end->true_ip;
294 else if ( (hsd->is_response == 1) && (hsd->http_resp_id == hsd->tList_start->tID ) )
295 return hsd->tList_start->true_ip;
296 }
297
298 return NULL;
299 }
300
ResetGzipState(DECOMPRESS_STATE * ds)301 static inline void ResetGzipState(DECOMPRESS_STATE *ds)
302 {
303 if (ds == NULL)
304 return;
305
306 inflateEnd(&(ds->d_stream));
307
308 ds->inflate_init = 0;
309 ds->deflate_initialized = false;
310 ds->compr_bytes_read = 0;
311 ds->decompr_bytes_read = 0;
312 ds->compress_fmt = 0;
313 ds->decompress_data = 0;
314 ds->stage = HTTP_DECOMP_START;
315 }
316
ResetRespState(HTTP_RESP_STATE * ds)317 static inline void ResetRespState(HTTP_RESP_STATE *ds)
318 {
319 if (ds == NULL)
320 return;
321 ds->inspect_body = 0;
322 ds->last_pkt_contlen = 0;
323 ds->last_pkt_chunked = 0;
324 ds->inspect_reassembled = 0;
325 ds->next_seq = 0;
326 ds->chunk_remainder = 0;
327 ds->data_extracted = 0;
328 ds->max_seq = 0;
329 }
330
SetLogBuffers(HttpSessionData * hsd,void * scbPtr)331 static inline int SetLogBuffers(HttpSessionData *hsd, void* scbPtr)
332 {
333 int iRet = 0;
334 if (hsd->log_state == NULL)
335 {
336 MemBucket *bkt = mempool_alloc(http_mempool);
337
338 if (bkt != NULL)
339 {
340 hsd->log_state = (HTTP_LOG_STATE *)SnortPreprocAlloc(1, sizeof(HTTP_LOG_STATE),
341 PP_HTTPINSPECT, PP_MEM_CATEGORY_SESSION);
342 if( hsd->log_state != NULL )
343 {
344 bkt->scbPtr = scbPtr;
345 hsd->log_state->log_bucket = bkt;
346 hsd->log_state->uri_bytes = 0;
347 hsd->log_state->hostname_bytes = 0;
348 hsd->log_state->uri_extracted = (uint8_t *)bkt->data;
349 hsd->log_state->hostname_extracted = (uint8_t *)bkt->data + MAX_URI_EXTRACTED;
350 }
351 else
352 {
353 mempool_free(http_mempool, bkt);
354 iRet = -1;
355 }
356 }
357 else
358 iRet = -1;
359 }
360
361 return iRet;
362 }
363
SetHttpDecode(uint16_t altLen)364 static inline void SetHttpDecode(uint16_t altLen)
365 {
366 HttpDecodeBuf.len = altLen;
367 }
368
369
370 #endif
371