#include <stdlib.h>
#include <stdio.h>
#include <string.h>
#include <ctype.h>
#include <sys/types.h>
#include "hi_client_norm.h"
#include "hi_eo.h"
#include "hi_eo_events.h"
#include "hi_eo_log.h"
#include "hi_ui_iis_unicode_map.h"
#include "hi_return_codes.h"
#include "hi_si.h"
#include "hi_util.h"
#include "hi_util_xmalloc.h"
Go to the source code of this file.
Defines | |
#define | MAX_DIRS 2048 |
#define | NO_HEX_VAL -1 |
#define | BASE36_VAL -2 |
#define | HEX_VAL 1 |
#define | GET_ERR 0x80000000 |
#define | END_OF_BUFFER -1 |
#define | DOUBLE_ENCODING -2 |
#define | DIR_TRAV -2 |
#define | NON_ASCII_CHAR 0xff |
Typedefs | |
typedef s_URI_NORM_STATE | URI_NORM_STATE |
typedef int(* | DECODE_FUNC )(HI_SESSION *, u_char *, u_char *, u_char **, URI_NORM_STATE *) |
Functions | |
static int | GetPtr (HI_SESSION *Session, u_char *start, u_char *end, u_char **ptr, URI_NORM_STATE *norm_state) |
static int | UDecode (HI_SESSION *Session, u_char *start, u_char *end, u_char **ptr, DECODE_FUNC get_byte, URI_NORM_STATE *norm_state) |
static int | PercentDecode (HI_SESSION *Session, u_char *start, u_char *end, u_char **ptr, URI_NORM_STATE *norm_state) |
static int | GetChar (HI_SESSION *Session, u_char *start, u_char *end, u_char **ptr, int *bare_byte, URI_NORM_STATE *norm_state) |
static int | UTF8Decode (HI_SESSION *Session, u_char *start, u_char *end, u_char **ptr, int iFirst, URI_NORM_STATE *norm_state) |
static int | UnicodeDecode (HI_SESSION *Session, u_char *start, u_char *end, u_char **ptr, int iFirst, URI_NORM_STATE *norm_state) |
static int | GetByte (HI_SESSION *Session, u_char *start, u_char *end, u_char **ptr, URI_NORM_STATE *norm_state) |
static int | DoubleDecode (HI_SESSION *Session, u_char *start, u_char *end, u_char **ptr, URI_NORM_STATE *norm_state) |
static int | GetDecodedByte (HI_SESSION *Session, u_char *start, u_char *end, u_char **ptr, URI_NORM_STATE *norm_state) |
static int | DirTrav (HI_SESSION *Session, URI_NORM_STATE *norm_state, u_char *ub_start, u_char **ub_ptr) |
static int | DirSet (URI_NORM_STATE *norm_state, u_char **ub_ptr) |
static int | DirNorm (HI_SESSION *Session, u_char *start, u_char *end, u_char **ptr, URI_NORM_STATE *norm_state) |
static int | CheckLongDir (HI_SESSION *Session, URI_NORM_STATE *norm_state, u_char *ub_ptr) |
static INLINE int | InspectUriChar (HI_SESSION *Session, int iChar, URI_NORM_STATE *norm_state, u_char *start, u_char *end, u_char **ptr, u_char *ub_start, u_char *ub_end, u_char **ub_ptr) |
int | hi_norm_uri (HI_SESSION *Session, u_char *uribuf, int *uribuf_size, u_char *uri, int uri_size) |
int | hi_norm_init (HTTPINSPECT_GLOBAL_CONF *GlobalConf) |
int | hi_normalization (HI_SESSION *Session, int iInspectMode) |
Variables | |
static int | hex_lookup [256] |
static int | valid_lookup [256] |
NOTES:
Definition in file hi_norm.c.
|
Definition at line 35 of file hi_norm.c. Referenced by hi_norm_init(), and PercentDecode(). |
|
Definition at line 46 of file hi_norm.c. Referenced by DirNorm(), and InspectUriChar(). |
|
Definition at line 45 of file hi_norm.c. Referenced by GetPtr(), and PercentDecode(). |
|
Definition at line 44 of file hi_norm.c. Referenced by DirNorm(), DoubleDecode(), GetByte(), GetChar(), GetDecodedByte(), GetPtr(), hi_norm_uri(), InspectUriChar(), PercentDecode(), and UTF8Decode(). |
|
This define checks for negative return codes, since we have multiple reasons to error. This just cuts the return code checks, especially as we add more errors. Definition at line 43 of file hi_norm.c. Referenced by PercentDecode(), and UDecode(). |
|
Definition at line 36 of file hi_norm.c. Referenced by hi_norm_init(). |
|
Definition at line 32 of file hi_norm.c. Referenced by DirSet(). |
|
Definition at line 34 of file hi_norm.c. Referenced by hi_norm_init(). |
|
Definition at line 48 of file hi_norm.c. Referenced by DoubleDecode(), GetByte(), GetChar(), PercentDecode(), UDecode(), and UTF8Decode(). |
|
|
|
|
|
This function checks for long directory names in the request URI.
Definition at line 1136 of file hi_norm.c. References s_URI_NORM_STATE::dir_count, s_URI_NORM_STATE::dir_track, hi_eo_client_event_log(), HI_EO_CLIENT_OVERSIZE_DIR, hi_eo_generate_event(), HI_SUCCESS, s_HTTPINSPECT_CONF::long_dir, NULL, s_URI_NORM_STATE::param, and s_HI_SESSION::server_conf. |
|
The main function for dealing with multiple slashes, self-referential directories, and directory traversals. This routine does GetDecodedByte() while looking for directory foo. It's called every time that we see a slash in the main hi_norm_uri. Most of the time we just enter this loop, find a non-directory-foo char and return that char. hi_norm_uri() takes care of the directory state updating and so forth. But when we run into trouble with directories, this function takes care of that. We loop through multiple slashes until we get to the next directory. We also loop through self-referential directories until we get to the next directory. Then finally we deal with directory traversals. With directory traversals we do a kind of "look ahead". We verify that there is indeed a directory traversal, and then set the ptr back to the beginning of the '/', so when we iterate through hi_norm_uri() we catch it. The return value for this function is usually the character after the directory. When there was a directory traversal, it returns the value DIR_TRAV. And when END_OF_BUFFER is returned, it means that we've really hit the end of the buffer, or we were looping through multiple slashes and self-referential directories until the end of the URI buffer.
Definition at line 996 of file hi_norm.c. References s_HTTPINSPECT_CONF_OPT::alert, DIR_TRAV, s_HTTPINSPECT_CONF::directory, END_OF_BUFFER, GetDecodedByte(), HI_EO_CLIENT_DIR_TRAV, hi_eo_client_event_log(), HI_EO_CLIENT_MULTI_SLASH, HI_EO_CLIENT_SELF_DIR_TRAV, hi_eo_generate_event(), s_HTTPINSPECT_CONF::multiple_slash, NULL, s_HTTPINSPECT_CONF_OPT::on, s_URI_NORM_STATE::param, and s_HI_SESSION::server_conf. Referenced by InspectUriChar(). |
|
Set the directory by writing a '/' to the normalization buffer and updating the directory stack. This gets called after every slash that isn't a directory traversal. We just write a '/' and then update the directory stack to point to the last directory, in the case of future directory traversals.
Definition at line 930 of file hi_norm.c. References s_URI_NORM_STATE::dir_count, s_URI_NORM_STATE::dir_track, HI_SUCCESS, MAX_DIRS, and s_URI_NORM_STATE::param. Referenced by InspectUriChar(). |
|
Set the ub_ptr and update the URI_NORM_STATE. The main point of this function is to take care of the details in updating the directory stack and setting the buffer pointer to the last directory.
Definition at line 868 of file hi_norm.c. References s_HTTPINSPECT_CONF_OPT::alert, s_URI_NORM_STATE::dir_count, s_URI_NORM_STATE::dir_track, hi_eo_client_event_log(), HI_EO_CLIENT_WEBROOT_DIR, hi_eo_generate_event(), HI_SUCCESS, NULL, s_URI_NORM_STATE::param, s_HI_SESSION::server_conf, and s_HTTPINSPECT_CONF::webroot. Referenced by InspectUriChar(). |
|
The double decoding routine for IIS good times. Coming into this function means that we just decoded a % or that we just saw two percents in a row. We know which state we are in depending if the first char is a '' or not. In the IIS world, there are two decodes, but only some of the decode options are valid. All options are valid in the first decode stage, but the second decode stage only supports:
Knowing this, we can decode appropriately.
Definition at line 706 of file hi_norm.c. References s_HTTPINSPECT_CONF_OPT::alert, s_HTTPINSPECT_CONF::double_decoding, END_OF_BUFFER, GetByte(), hex_lookup, HI_EO_CLIENT_DOUBLE_DECODE, hi_eo_client_event_log(), hi_eo_generate_event(), NON_ASCII_CHAR, NULL, s_HTTPINSPECT_CONF_OPT::on, s_URI_NORM_STATE::param, s_HI_SESSION::server_conf, s_HTTPINSPECT_CONF::u_encoding, UDecode(), and valid_lookup. Referenced by GetDecodedByte(). |
|
Handles the first stage of URI decoding for the case of IIS double decoding. The first stage consists of ASCII decoding and unicode decoding. U decoding is handled in the ASCII decoding.
Definition at line 655 of file hi_norm.c. References END_OF_BUFFER, GetChar(), NON_ASCII_CHAR, and UnicodeDecode(). Referenced by DoubleDecode(), and GetDecodedByte(). |
|
Wrapper for PercentDecode() and handles the return values from PercentDecode(). This really decodes the chars for UnicodeDecode(). If the char is a percent then we process stuff, otherwise we just increment the pointer and return.
Definition at line 407 of file hi_norm.c. References s_HTTPINSPECT_CONF_OPT::alert, s_HTTPINSPECT_CONF::ascii, s_HTTPINSPECT_CONF::bare_byte, END_OF_BUFFER, HI_EO_CLIENT_BARE_BYTE, hi_eo_client_event_log(), hi_eo_generate_event(), hi_util_in_bounds(), int(), NON_ASCII_CHAR, NULL, s_HTTPINSPECT_CONF_OPT::on, s_URI_NORM_STATE::param, PercentDecode(), and s_HI_SESSION::server_conf. Referenced by GetByte(), and UTF8Decode(). |
|
This is the final GetByte routine. The value that is returned from this routine is the final decoded byte, and normalization can begin. This routine handles the double phase of decoding that IIS is fond of. So to recap all the decoding up until this point. The first phase is to call GetByte(). GetByte() returns the first stage of decoding, which handles the UTF-8 decoding. If we have decoded a % of some type, then we head into DoubleDecode() if the ServerConf allows it. What returns from DoubleDecode is the final result.
Definition at line 814 of file hi_norm.c. References s_HTTPINSPECT_CONF_OPT::alert, s_HTTPINSPECT_CONF::double_decoding, DoubleDecode(), END_OF_BUFFER, GetByte(), hi_eo_client_event_log(), HI_EO_CLIENT_IIS_BACKSLASH, hi_eo_generate_event(), s_HTTPINSPECT_CONF::iis_backslash, NULL, s_HTTPINSPECT_CONF_OPT::on, s_URI_NORM_STATE::param, and s_HI_SESSION::server_conf. Referenced by DirNorm(), and hi_norm_uri(). |
|
This routine is for getting bytes in the U decode. This checks the current bounds and checking for the double decoding. This routine differs from the other Get routines because it returns other values than just END_OF_BUFFER and the char. We also return DOUBLE_ENCODING if there is a % and double decoding is turned on. When using this function it is important to note that it increments the buffer before checking the bounds. So, if you call this function in a loop and don't check for END_OF_BUFFER being returned, then you are going to overwrite the buffer. If I put the check in, you would just be in an never-ending loop. So just use this correctly.
Definition at line 100 of file hi_norm.c. References s_HTTPINSPECT_CONF::double_decoding, DOUBLE_ENCODING, END_OF_BUFFER, hi_util_in_bounds(), s_HTTPINSPECT_CONF_OPT::on, and s_HI_SESSION::server_conf. Referenced by PercentDecode(). |
|
Initialize the arrays neccessary to normalize the HTTP protocol fields. Currently, we set a hex_lookup array where we can convert the hex encoding that we encounter in the URI into numbers we deal with.
Definition at line 1477 of file hi_norm.c. References BASE36_VAL, hex_lookup, HEX_VAL, HI_SUCCESS, memset, NO_HEX_VAL, and valid_lookup. Referenced by HttpInspectInit(). |
|
Normalize the URI into the URI normalize buffer. This is the routine that users call to normalize the URI. It iterates through the URI buffer decoding the next character and is then checked for any directory problems before writing the decoded character into the normalizing buffer. We return the length of the normalized URI buffer in the variable, uribuf_size. This value is passed in as the max size of the normalization buffer, which we then set in iMaxUriBufSize for later reference. If there was some sort of problem during normalizing we set the normalized URI buffer size to 0 and return HI_NONFATAL_ERR.
Definition at line 1376 of file hi_norm.c. References CheckLongDir(), s_URI_NORM_STATE::dir_count, END_OF_BUFFER, GetDecodedByte(), hi_eo_client_event_log(), HI_EO_CLIENT_NON_RFC_CHAR, hi_eo_generate_event(), HI_NONFATAL_ERR, HI_SUCCESS, hi_util_in_bounds(), InspectUriChar(), s_HTTPINSPECT_CONF::non_rfc_chars, NULL, s_URI_NORM_STATE::param, and s_HI_SESSION::server_conf. Referenced by UriNorm(). |
|
Wrap the logic for normalizing different inspection modes. We call the various normalization modes here, and adjust the appropriate Session constructs.
Definition at line 1555 of file hi_norm.c. References hi_client_norm(), HI_INVALID_ARG, HI_SI_CLIENT_MODE, and HI_SUCCESS. Referenced by SnortHttpInspect(). |
|
This function inspects the normalized chars for any other processing that we need to do, such as directory traversals. The main things that we check for here are '/' and '?'. There reason for '/' is that we do directory traversals. If it's a slash, we call the routine that will normalize mutli-slashes, self-referential dirs, and dir traversals. We do all that processing here and call the appropriate functions. The '?' is so we can mark the parameter field, and check for oversize directories one last time. Once the parameter field is set, we don't do any more oversize directory checks since we aren't in the url any more.
Definition at line 1202 of file hi_norm.c. References CheckLongDir(), s_URI_NORM_STATE::dir_count, DIR_TRAV, DirNorm(), DirSet(), DirTrav(), END_OF_BUFFER, hi_eo_client_event_log(), HI_EO_CLIENT_NON_RFC_CHAR, hi_eo_generate_event(), HI_NONFATAL_ERR, HI_SUCCESS, hi_util_in_bounds(), s_HTTPINSPECT_CONF::non_rfc_chars, NULL, s_URI_NORM_STATE::param, and s_HI_SESSION::server_conf. Referenced by hi_norm_uri(). |
|
This is the first level of decoding, and deals with ASCII, U, and double decoding. This function is the main decoding function. It handles all the ASCII encoding and the U encoding, and tells us when there is a double encoding. We use the GetPtr() routine to get the bytes for us. This routine checks for DOUBLE_ENCODING and tells us about it if it finds something, so we can reset the ptrs and run it through the double decoding routine. The philosophy behind this routine is that if we run out of buffer we return such, the only other thing we return besides the decodes char is a NON_ASCII_CHAR in the case that we try and decode something like tt. This is no good, so we return a place holder.
Definition at line 253 of file hi_norm.c. References s_HTTPINSPECT_CONF_OPT::alert, s_HTTPINSPECT_CONF::ascii, s_HTTPINSPECT_CONF::base36, BASE36_VAL, DOUBLE_ENCODING, END_OF_BUFFER, GET_ERR, GetPtr(), hex_lookup, HI_EO_CLIENT_ASCII, HI_EO_CLIENT_BASE36, hi_eo_client_event_log(), hi_eo_generate_event(), NON_ASCII_CHAR, NULL, s_HTTPINSPECT_CONF_OPT::on, s_URI_NORM_STATE::param, s_HI_SESSION::server_conf, s_HTTPINSPECT_CONF::u_encoding, UDecode(), and valid_lookup. Referenced by GetChar(). |
|
Handles the single decode for U encoding. This routine receives the ptr pointing to the u. We check the bounds and continue with processing. u encoding works by specifying the exact codepoint to be used. For example, u002f would be /. So this all seems fine. BUT, the problem is that IIS maps multiple codepoints to ASCII characters. So, u2044 also maps to /. So this is what we need to handle here. This routine only handles the single encoding. For double decoding, u is handled in DoubleDecode(). It's the same routine, with just the GetByte function different. We use a get_byte function to get the bytes, so we can use this routine for PercentDecode and for DoubleDecode.
Definition at line 150 of file hi_norm.c. References s_HTTPINSPECT_CONF_OPT::alert, GET_ERR, hex_lookup, hi_eo_client_event_log(), HI_EO_CLIENT_IIS_UNICODE, HI_EO_CLIENT_U_ENCODE, hi_eo_generate_event(), HI_UI_NON_ASCII_CODEPOINT, s_HTTPINSPECT_CONF::iis_unicode, s_HTTPINSPECT_CONF::iis_unicode_map, NON_ASCII_CHAR, NULL, s_HTTPINSPECT_CONF_OPT::on, s_URI_NORM_STATE::param, s_HTTPINSPECT_CONF::u_encoding, and valid_lookup. Referenced by DoubleDecode(), and PercentDecode(). |
|
Checks for the ServerConf values before we actually decode. This function is really a ServerConf wrapper for UTF8Decode.
Definition at line 618 of file hi_norm.c. References s_HTTPINSPECT_CONF::iis_unicode, s_HTTPINSPECT_CONF_OPT::on, s_HI_SESSION::server_conf, UTF8Decode(), and s_HTTPINSPECT_CONF::utf_8. Referenced by GetByte(). |
|
Decode the UTF-8 sequences and check for valid codepoints via the Unicode standard and the IIS standard. We decode up to 3 bytes of UTF-8 because that's all I've been able to get to work on various servers, so let's reduce some false positives. So we decode valid UTF-8 sequences and then check the value. If the value is ASCII, then it's decoded to that. Otherwise, if iis_unicode is turned on, we will check the unicode codemap for valid IIS mappings. If a mapping turns up, then we return the mapped ASCII.
Definition at line 497 of file hi_norm.c. References s_HTTPINSPECT_CONF_OPT::alert, END_OF_BUFFER, GetChar(), hi_eo_client_event_log(), HI_EO_CLIENT_IIS_UNICODE, HI_EO_CLIENT_UTF_8, hi_eo_generate_event(), HI_UI_NON_ASCII_CODEPOINT, s_HTTPINSPECT_CONF::iis_unicode, s_HTTPINSPECT_CONF::iis_unicode_map, NON_ASCII_CHAR, NULL, s_HTTPINSPECT_CONF_OPT::on, s_URI_NORM_STATE::param, s_HI_SESSION::server_conf, and s_HTTPINSPECT_CONF::utf_8. Referenced by UnicodeDecode(). |
|
|
|
Definition at line 67 of file hi_norm.c. Referenced by DoubleDecode(), hi_norm_init(), PercentDecode(), and UDecode(). |