"Fossies" - the Fresh Open Source Software Archive 
Member "snort-2.9.17/src/preprocessors/HttpInspect/client/hi_client_norm.c" (16 Oct 2020, 13836 Bytes) of package /linux/misc/snort-2.9.17.tar.gz:
As a special service "Fossies" has tried to format the requested source page into HTML format using (guessed) C and C++ source code syntax highlighting (style:
standard) with prefixed line numbers and
code folding option.
Alternatively you can here
view or
download the uninterpreted source code file.
For more information about "hi_client_norm.c" see the
Fossies "Dox" file reference documentation and the latest
Fossies "Diffs" side-by-side code changes report:
2.9.16.1_vs_2.9.17.
1 /****************************************************************************
2 *
3 * Copyright (C) 2014-2020 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 /**
24 ** @file hi_client_norm.c
25 **
26 ** @author Daniel Roelker <droelker@sourcefire.com>
27 **
28 ** @brief HTTP client normalization routines
29 **
30 ** We deal with the normalization of HTTP client requests headers and
31 ** URI.
32 **
33 ** In this file, we handle all the different HTTP request URI evasions. The
34 ** list is:
35 ** - ASCII decoding
36 ** - UTF-8 decoding
37 ** - IIS Unicode decoding
38 ** - Directory traversals (self-referential and traversal)
39 ** - Multiple Slashes
40 ** - Double decoding
41 ** - %U decoding
42 ** - Bare Byte Unicode decoding
43 **
44 ** Base 36 is deprecated and essentially a noop
45 ** - Base36 decoding
46 **
47 ** NOTES:
48 ** - Initial development. DJR
49 */
50 #include <stdlib.h>
51 #include <stdio.h>
52 #include <sys/types.h>
53 #include <ctype.h>
54
55 #ifdef HAVE_CONFIG_H
56 #include "config.h"
57 #endif
58
59 #include "hi_norm.h"
60 #include "hi_util.h"
61 #include "hi_return_codes.h"
62
63 #include "snort_bounds.h"
64
65
66 int hi_split_header_cookie(HI_SESSION *Session, u_char *header, int *i_header_len,
67 u_char *cookie_header, int *i_cookie_len,
68 const u_char *raw_header, int i_raw_header_len,
69 COOKIE_PTR *cookie)
70 {
71 int iRet = HI_SUCCESS;
72 COOKIE_PTR *last_cookie = NULL;
73 COOKIE_PTR *first_cookie = cookie;
74 const u_char *raw_header_end = raw_header + i_raw_header_len;
75 int this_cookie_len = 0;
76 const u_char *this_header_start = raw_header;
77 const u_char *this_header_end;
78 int this_header_len = 0;
79 const u_char *header_end;
80 const u_char *cookie_end;
81
82 if (!cookie || !i_header_len || !i_cookie_len)
83 return HI_INVALID_ARG;
84
85 /* Can't use hi_util_in_bounds header because == is okay */
86 if (cookie->cookie_end > raw_header + i_raw_header_len)
87 return HI_OUT_OF_BOUNDS;
88
89 header_end = (const u_char *)(header + *i_header_len);
90 *i_header_len = 0;
91 cookie_end = (const u_char *)(cookie_header + *i_cookie_len);
92 *i_cookie_len = 0;
93
94 do
95 {
96 this_cookie_len = cookie->cookie_end - cookie->cookie;
97 this_header_end = cookie->cookie;
98 this_header_len = this_header_end - this_header_start;
99
100 /* Trim the header and only copy what we can store in the buf */
101 if (*i_header_len + this_header_len > MAX_URI)
102 {
103 this_header_len = MAX_URI - *i_header_len;
104 }
105 /* Copy out the headers from start to beginning of the cookie */
106 if (this_header_len > 0)
107 {
108 if (SafeMemcpy(header + *i_header_len, this_header_start, this_header_len, header, header_end) == SAFEMEM_SUCCESS)
109 {
110 *i_header_len += this_header_len;
111 }
112 }
113 else
114 {
115 DEBUG_WRAP(DebugMessage(DEBUG_HTTPINSPECT, "HttpInspect: no leading header: %d to %d\n",
116 this_header_end - this_header_start, this_header_len););
117 }
118
119 /* Trim the cookie and only copy what we can store in the buf */
120 if (*i_cookie_len + this_cookie_len > MAX_URI)
121 {
122 this_cookie_len = MAX_URI - *i_cookie_len;
123 }
124 /* And copy the cookie */
125 if (this_cookie_len > 0)
126 {
127 if (SafeMemcpy(cookie_header + *i_cookie_len, cookie->cookie, this_cookie_len, cookie_header, cookie_end) == SAFEMEM_SUCCESS)
128 {
129 *i_cookie_len += this_cookie_len;
130 }
131 }
132 else
133 {
134 DEBUG_WRAP(DebugMessage(DEBUG_HTTPINSPECT, "HttpInspect: trimming cookie: %d to %d\n",
135 cookie->cookie_end - cookie->cookie, this_cookie_len););
136 }
137
138 /* update for the next one */
139 this_header_start = cookie->cookie_end;
140 cookie = cookie->next;
141 if (last_cookie && (last_cookie != first_cookie))
142 {
143 free(last_cookie);
144 hi_stats.mem_used -= sizeof(COOKIE_PTR);
145 }
146 last_cookie = cookie;
147 if (!cookie)
148 {
149 this_header_len = raw_header + i_raw_header_len - this_header_start;
150 }
151 else
152 {
153 this_header_len = cookie->cookie - this_header_start;
154 }
155 this_header_end = this_header_start + this_header_len;
156
157 if ((*i_header_len == MAX_URI) ||
158 (*i_cookie_len == MAX_URI))
159 {
160 last_cookie = NULL;
161 }
162 }
163 while (last_cookie);
164
165 /* Clear out the 'first' cookie since we're done with it */
166 /* Eliminates unexptected 'reuse' in the case of pipeline'd requests. */
167 memset(first_cookie, 0, sizeof(COOKIE_PTR));
168
169 if (this_header_len && hi_util_in_bounds(raw_header, raw_header_end, this_header_start))
170 {
171 /* Trim the header and only copy what we can store in the buf */
172 if (*i_header_len + this_header_len > MAX_URI)
173 {
174 this_header_len = MAX_URI - *i_header_len;
175 }
176
177 /* Copy the remaining headers after the last cookie */
178 if (this_header_len > 0)
179 {
180 if (SafeMemcpy(header + *i_header_len, this_header_start, this_header_len, header, header_end) == SAFEMEM_SUCCESS)
181 {
182 *i_header_len += this_header_len;
183 }
184 }
185 else
186 {
187 DEBUG_WRAP(DebugMessage(DEBUG_HTTPINSPECT, "HttpInspect: no leading header: %d to %d\n",
188 this_header_end - this_header_start, this_header_len););
189
190 }
191 }
192
193 return iRet;
194 }
195
196 int hi_client_norm(HI_SESSION *Session)
197 {
198 static u_char UriBuf[MAX_URI];
199 static u_char HeaderBuf[MAX_URI];
200 static u_char CookieBuf[MAX_URI];
201 static u_char RawHeaderBuf[MAX_URI];
202 static u_char RawCookieBuf[MAX_URI];
203 static u_char PostBuf[MAX_URI];
204 HI_CLIENT_REQ *ClientReq;
205 int iRet;
206 int iUriBufSize = MAX_URI;
207 int iRawHeaderBufSize = MAX_URI;
208 int iRawCookieBufSize = MAX_URI;
209 int iHeaderBufSize = MAX_URI;
210 int iCookieBufSize = MAX_URI;
211 int iPostBufSize = MAX_URI;
212 uint16_t encodeType = 0;
213 u_int updated_uri_size = 0;
214 const u_char *updated_uri_start = NULL;
215
216 if(!Session || !Session->server_conf)
217 {
218 return HI_INVALID_ARG;
219 }
220
221 ClientReq = &Session->client.request;
222 ClientReq->uri_encode_type = 0;
223 ClientReq->header_encode_type = 0;
224 ClientReq->cookie_encode_type = 0;
225 ClientReq->post_encode_type = 0;
226
227 /* Handle URI normalization */
228 if(ClientReq->uri_norm)
229 {
230 updated_uri_start = ClientReq->uri;
231 updated_uri_size = ClientReq->uri_size;
232 Session->norm_flags &= ~HI_BODY;
233 if(proxy_start && (ClientReq->uri == proxy_start))
234 {
235 if(hi_util_in_bounds(ClientReq->uri, (ClientReq->uri + ClientReq->uri_size), proxy_end))
236 {
237 updated_uri_start = proxy_end;
238 updated_uri_size = (ClientReq->uri_size) - (proxy_end - proxy_start);
239 }
240
241 }
242 proxy_start = proxy_end = NULL;
243 iRet = hi_norm_uri(Session, UriBuf, &iUriBufSize,
244 updated_uri_start, updated_uri_size, &encodeType);
245 if (iRet == HI_NONFATAL_ERR)
246 {
247 /* There was a non-fatal problem normalizing */
248 ClientReq->uri_norm = NULL;
249 ClientReq->uri_norm_size = 0;
250 ClientReq->uri_encode_type = 0;
251 }
252 else
253 {
254 /* Client code is expecting these to be set to non-NULL if
255 * normalization occurred. */
256 ClientReq->uri_norm = UriBuf;
257 ClientReq->uri_norm_size = iUriBufSize;
258 ClientReq->uri_encode_type = encodeType;
259 }
260 encodeType = 0;
261 }
262 else
263 {
264 if(proxy_start && (ClientReq->uri == proxy_start))
265 {
266 if(hi_util_in_bounds(ClientReq->uri, (ClientReq->uri + ClientReq->uri_size), proxy_end))
267 {
268 ClientReq->uri_norm = proxy_end;
269 ClientReq->uri_norm_size = (ClientReq->uri_size) - (proxy_end - proxy_start);
270 }
271 }
272 proxy_start = proxy_end = NULL;
273 }
274
275 if (ClientReq->cookie.cookie)
276 {
277 /* There is an HTTP header with a cookie, look for the cookie &
278 * separate the two buffers */
279 iRet = hi_split_header_cookie(Session,
280 RawHeaderBuf, &iRawHeaderBufSize,
281 RawCookieBuf, &iRawCookieBufSize,
282 ClientReq->header_raw, ClientReq->header_raw_size,
283 &ClientReq->cookie);
284 if( iRet == HI_SUCCESS )
285 {
286 ClientReq->cookie.cookie = RawCookieBuf;
287 ClientReq->cookie.cookie_end = RawCookieBuf + iRawCookieBufSize;
288
289 }
290 }
291 else
292 {
293 if (ClientReq->header_raw_size)
294 {
295 if (ClientReq->header_raw_size > MAX_URI)
296 {
297 ClientReq->header_raw_size = MAX_URI;
298 }
299 /* Limiting to MAX_URI above should cause this to always return SAFEMEM_SUCCESS */
300 SafeMemcpy(RawHeaderBuf, ClientReq->header_raw, ClientReq->header_raw_size,
301 &RawHeaderBuf[0], &RawHeaderBuf[0] + iRawHeaderBufSize);
302 }
303 iRawHeaderBufSize = ClientReq->header_raw_size;
304 iRawCookieBufSize = 0;
305 }
306
307 if(ClientReq->header_norm && Session->server_conf->normalize_headers)
308 {
309 Session->norm_flags &= ~HI_BODY;
310 iRet = hi_norm_uri(Session, HeaderBuf, &iHeaderBufSize,
311 RawHeaderBuf, iRawHeaderBufSize, &encodeType);
312 if (iRet == HI_NONFATAL_ERR)
313 {
314 /* There was a non-fatal problem normalizing */
315 ClientReq->header_norm = NULL;
316 ClientReq->header_norm_size = 0;
317 ClientReq->header_encode_type = 0;
318 }
319 else
320 {
321 /* Client code is expecting these to be set to non-NULL if
322 * normalization occurred. */
323 ClientReq->header_norm = HeaderBuf;
324 ClientReq->header_norm_size = iHeaderBufSize;
325 ClientReq->header_encode_type = encodeType;
326 }
327 encodeType = 0;
328 }
329 else
330 {
331 /* Client code is expecting these to be set to non-NULL if
332 * normalization occurred. */
333 if (iRawHeaderBufSize)
334 {
335 ClientReq->header_norm = RawHeaderBuf;
336 ClientReq->header_norm_size = iRawHeaderBufSize;
337 ClientReq->header_encode_type = 0;
338 }
339 }
340
341 if(ClientReq->cookie.cookie && Session->server_conf->normalize_cookies)
342 {
343 Session->norm_flags &= ~HI_BODY;
344 iRet = hi_norm_uri(Session, CookieBuf, &iCookieBufSize,
345 RawCookieBuf, iRawCookieBufSize, &encodeType);
346 if (iRet == HI_NONFATAL_ERR)
347 {
348 /* There was a non-fatal problem normalizing */
349 ClientReq->cookie_norm = NULL;
350 ClientReq->cookie_norm_size = 0;
351 ClientReq->cookie_encode_type = 0;
352 }
353 else
354 {
355 /* Client code is expecting these to be set to non-NULL if
356 * normalization occurred. */
357 ClientReq->cookie_norm = CookieBuf;
358 ClientReq->cookie_norm_size = iCookieBufSize;
359 ClientReq->cookie_encode_type = encodeType;
360 }
361 encodeType = 0;
362 }
363 else
364 {
365 /* Client code is expecting these to be set to non-NULL if
366 * normalization occurred. */
367 if (iRawCookieBufSize)
368 {
369 ClientReq->cookie_norm = RawCookieBuf;
370 ClientReq->cookie_norm_size = iRawCookieBufSize;
371 ClientReq->cookie_encode_type = 0;
372 }
373 }
374
375 /* Handle normalization of post methods.
376 * Note: posts go into a different buffer. */
377 if(ClientReq->post_norm)
378 {
379 Session->norm_flags |= HI_BODY;
380 iRet = hi_norm_uri(Session, PostBuf, &iPostBufSize,
381 ClientReq->post_raw, ClientReq->post_raw_size, &encodeType);
382 if (iRet == HI_NONFATAL_ERR)
383 {
384 ClientReq->post_norm = NULL;
385 ClientReq->post_norm_size = 0;
386 ClientReq->post_encode_type = 0;
387 }
388 else
389 {
390 ClientReq->post_norm = PostBuf;
391 ClientReq->post_norm_size = iPostBufSize;
392 ClientReq->post_encode_type = encodeType;
393 }
394 encodeType = 0;
395 }
396
397 /*
398 printf("** uri_norm = |");
399 for(iCtr = 0; iCtr < ClientReq->uri_norm_size; iCtr++)
400 {
401 if(!isascii((int)ClientReq->uri_norm[iCtr]) ||
402 !isprint((int)ClientReq->uri_norm[iCtr]))
403 {
404 printf(".[%.2x]", ClientReq->uri_norm[iCtr]);
405 continue;
406 }
407 printf("%c", ClientReq->uri_norm[iCtr]);
408 }
409 printf("| size = %u\n", ClientReq->uri_norm_size);
410 */
411
412 return HI_SUCCESS;
413 }