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