Main Page | Modules | Class List | Directories | File List | Class Members | File Members | Related Pages

hi_client.c File Reference

Main file for all the client functions and inspection flow. More...

#include <stdlib.h>
#include <stdio.h>
#include <string.h>
#include <ctype.h>
#include <sys/types.h>
#include "hi_ui_config.h"
#include "hi_si.h"
#include "hi_mi.h"
#include "hi_client.h"
#include "hi_eo_log.h"
#include "hi_util.h"
#include "hi_util_hbm.h"
#include "hi_return_codes.h"

Go to the source code of this file.

Defines

#define URI_END   1
#define NO_URI   -1
#define INVALID_HEX_VAL   -1

Typedefs

typedef s_URI_PTR URI_PTR
typedef int(* LOOKUP_FCN )(HI_SESSION *, u_char *, u_char *, u_char **, URI_PTR *)

Functions

static int CheckChunkEncoding (HI_SESSION *Session, u_char *start, u_char *end)
static INLINE u_char * FindPipelineReq (u_char *start, u_char *end)
static int IsHttpVersion (u_char **ptr, u_char *end)
static int find_rfc_delimiter (HI_SESSION *Session, u_char *start, u_char *end, u_char **ptr, URI_PTR *uri_ptr)
static int find_non_rfc_delimiter (HI_SESSION *Session, u_char *start, u_char *end, u_char **ptr, URI_PTR *uri_ptr)
static int NextNonWhiteSpace (HI_SESSION *Session, u_char *start, u_char *end, u_char **ptr, URI_PTR *uri_ptr)
static int SetPercentNorm (HI_SESSION *Session, u_char *start, u_char *end, u_char **ptr, URI_PTR *uri_ptr)
static INLINE int CheckLongDir (HI_SESSION *Session, URI_PTR *uri_ptr, u_char *ptr)
static int SetSlashNorm (HI_SESSION *Session, u_char *start, u_char *end, u_char **ptr, URI_PTR *uri_ptr)
static int SetBackSlashNorm (HI_SESSION *Session, u_char *start, u_char *end, u_char **ptr, URI_PTR *uri_ptr)
static int SetBinaryNorm (HI_SESSION *Session, u_char *start, u_char *end, u_char **ptr, URI_PTR *uri_ptr)
static int SetParamField (HI_SESSION *Session, u_char *start, u_char *end, u_char **ptr, URI_PTR *uri_ptr)
static int SetProxy (HI_SESSION *Session, u_char *start, u_char *end, u_char **ptr, URI_PTR *uri_ptr)
static int SetClientVars (HI_CLIENT *Client, URI_PTR *uri_ptr, u_int dsize)
static int StatelessInspection (HI_SESSION *Session, unsigned char *data, int dsize)
int hi_client_inspection (void *S, unsigned char *data, int dsize)
int hi_client_init (HTTPINSPECT_GLOBAL_CONF *GlobalConf)

Variables

static LOOKUP_FCN lookup_table [256]
static int hex_lookup [256]


Detailed Description

Main file for all the client functions and inspection flow.

Author:
Daniel Roelker <droelker@sourcefire.com>
Copyright (C) 2003-2005 Sourcefire,Inc.

The job of the client module is to analyze and inspect the HTTP protocol, finding where the various fields begin and end. This must be accomplished in a stateful and stateless manner.

While the fields are being determined, we also do checks for normalization, so we don't normalize fields that don't need it.

Currently, the only fields we check for this is the URI and the parameter fields.

NOTES:

Definition in file hi_client.c.


Define Documentation

#define INVALID_HEX_VAL   -1
 

Definition at line 43 of file hi_client.c.

Referenced by CheckChunkEncoding().

#define NO_URI   -1
 

Definition at line 42 of file hi_client.c.

Referenced by find_non_rfc_delimiter(), find_rfc_delimiter(), and NextNonWhiteSpace().

#define URI_END   1
 

Definition at line 41 of file hi_client.c.

Referenced by find_non_rfc_delimiter(), find_rfc_delimiter(), and StatelessInspection().


Typedef Documentation

typedef int(* LOOKUP_FCN)(HI_SESSION *, u_char *, u_char *, u_char **, URI_PTR *)
 

This makes passing function arguments much more readable and easier to follow.

Definition at line 79 of file hi_client.c.

typedef struct s_URI_PTR URI_PTR
 

This structure holds pointers to the different sections of an HTTP request. We need to track where whitespace begins and ends, so we can evaluate the placement of the URI correctly.

For example,

GET / HTTP/1.0 ^ ^ start end

The end space pointers are set to NULL if there is space until the end of the buffer.


Function Documentation

static int CheckChunkEncoding HI_SESSION Session,
u_char *  start,
u_char *  end
[static]
 

This routine checks for chunk encoding anomalies in an HTTP client request packet.

We convert potential chunk lengths and test them against the user-defined max chunk length. We log events on any chunk lengths that are over this defined chunk lengths.

Chunks are skipped to save time when the chunk is contained in the packet.

We assume coming into this function that we are pointed at the beginning of what may be a chunk length. That's why the iCheckChunk var is set to 1.

Parameters:
Session pointer to the Session construct
start pointer to where to beginning of buffer
end pointer to the end of buffer
Returns:
integer
Return values:
HI_SUCCESS function successful
HI_INVALID_ARG invalid argument

Definition at line 116 of file hi_client.c.

References s_HTTPINSPECT_CONF::chunk_length, hex_lookup, hi_eo_client_event_log(), HI_EO_CLIENT_LARGE_CHUNK, hi_eo_generate_event(), HI_INVALID_ARG, HI_SUCCESS, hi_util_in_bounds(), int(), INVALID_HEX_VAL, NULL, and s_HI_SESSION::server_conf.

Referenced by StatelessInspection().

static INLINE int CheckLongDir HI_SESSION Session,
URI_PTR uri_ptr,
u_char *  ptr
[static]
 

We check the directory length against the global config.

Parameters:
Session pointer to the current session
uri_ptr pointer to the URI state
ptr pointer to the current index in buffer
Returns:
integer
Return values:
HI_SUCCESS 

Definition at line 847 of file hi_client.c.

References hi_eo_client_event_log(), HI_EO_CLIENT_OVERSIZE_DIR, hi_eo_generate_event(), HI_SUCCESS, s_URI_PTR::last_dir, s_HTTPINSPECT_CONF::long_dir, NULL, s_URI_PTR::param, and s_HI_SESSION::server_conf.

Referenced by hi_norm_uri(), InspectUriChar(), SetSlashNorm(), and StatelessInspection().

static int find_non_rfc_delimiter HI_SESSION Session,
u_char *  start,
u_char *  end,
u_char **  ptr,
URI_PTR uri_ptr
[static]
 

Check for non standard delimiter '
'.

It now appears that apache and iis both take this non-standard delimiter. So, we most likely will always look for it, but maybe give off a special alert or something.

Parameters:
ServerConf pointer to the server configuration
start pointer to the start of payload
end pointer to the end of the payload
ptr pointer to the pointer of the current index
uri_ptr pointer to the URI_PTR construct
Returns:
integer
Return values:
URI_END delimiter found, end of URI
NO_URI 

Definition at line 483 of file hi_client.c.

References s_HTTPINSPECT_CONF_OPT::alert, s_URI_PTR::delimiter, hi_eo_client_event_log(), HI_EO_CLIENT_IIS_DELIMITER, hi_eo_generate_event(), s_URI_PTR::ident, s_HTTPINSPECT_CONF::iis_delimiter, NO_URI, NULL, s_HTTPINSPECT_CONF_OPT::on, s_HI_SESSION::server_conf, s_URI_PTR::uri, URI_END, and s_URI_PTR::uri_end.

Referenced by hi_client_init().

static int find_rfc_delimiter HI_SESSION Session,
u_char *  start,
u_char *  end,
u_char **  ptr,
URI_PTR uri_ptr
[static]
 

Check for standard RFC HTTP delimiter.

If we find the delimiter, we return that URI_PTR structures should be checked, which bails us out of the loop. If there isn't a RFC delimiter, then we bail with a no URI. Otherwise, we check for out of bounds.

Parameters:
ServerConf pointer to the server configuration
start pointer to the start of payload
end pointer to the end of the payload
ptr pointer to the pointer of the current index
uri_ptr pointer to the URI_PTR construct
Returns:
integer
Return values:
HI_OUT_OF_BOUNDS 
URI_END end of the URI is found, check URI_PTR.
NO_URI malformed delimiter, no URI.

Definition at line 420 of file hi_client.c.

References s_URI_PTR::delimiter, HI_OUT_OF_BOUNDS, hi_util_in_bounds(), s_URI_PTR::ident, NO_URI, s_URI_PTR::uri, URI_END, and s_URI_PTR::uri_end.

Referenced by hi_client_init().

static INLINE u_char* FindPipelineReq u_char *  start,
u_char *  end
[static]
 

Catch multiple requests per packet, by returning pointer to after the end of the request header if there is another request.

There are 4 types of "valid" delimiters that we look for. They are: "\r\n\r\n" "\r\n\n" "\n\r\n" "\n\n" The only patterns that we really only need to look for are: "\n\r\n" "\n\n" The reason being that these two patterns are suffixes of the other patterns. So once we find those, we are all good.

Parameters:
start pointer to the start of text
end pointer to the end of text
Returns:
pointer
Return values:
NULL Did not find pipeline request
!NULL Found another possible request.

Definition at line 266 of file hi_client.c.

References NULL.

Referenced by StatelessInspection().

int hi_client_init HTTPINSPECT_GLOBAL_CONF GlobalConf  ) 
 

Initializes arrays and search algorithms depending on the type of inspection that we are doing.

Parameters:
GlobalConf pointer to the global configuration
Returns:
integer
Return values:
HI_SUCCESS function successful.

Definition at line 1532 of file hi_client.c.

References find_non_rfc_delimiter(), find_rfc_delimiter(), hex_lookup, HI_SUCCESS, HI_UI_CONFIG_STATEFUL, s_HTTPINSPECT_GLOBAL_CONF::inspection_type, lookup_table, memset, NextNonWhiteSpace(), SetBackSlashNorm(), SetBinaryNorm(), SetParamField(), SetPercentNorm(), SetProxy(), and SetSlashNorm().

Referenced by HttpInspectInit().

int hi_client_inspection void *  S,
unsigned char *  data,
int  dsize
 

Definition at line 1472 of file hi_client.c.

References s_HI_SESSION::global_conf, GlobalConf, HI_INVALID_ARG, HI_NONFATAL_ERR, HI_SUCCESS, HI_UI_CONFIG_STATEFUL, s_HTTPINSPECT_GLOBAL_CONF::inspection_type, and StatelessInspection().

Referenced by hi_mi_mode_inspection().

static int IsHttpVersion u_char **  ptr,
u_char *  end
[static]
 

This checks that there is a version following a space with in an HTTP packet.

This function gets called when a whitespace area has ended, and we want to know if a version identifier is followed directly after. So we look for the rfc standard "HTTP/" and report appropriately. We also need to make sure that the function succeeds given an end of buffer, so for instance if the buffer ends like " HTT", we still assume that this is a valid version identifier because of TCP segmentation.

We also check for the 0.9 standard of GET URI
. When we see a or a
, then we just return with the pointer still pointing to that char. The reason is because on the next loop, we'll do the evaluation that we normally do and finish up processing there.

Parameters:
start pointer to the start of the version identifier
end pointer to the end of the buffer (could be the end of the data section, or just to the beginning of the delimiter.
Returns:
integer
Return values:
1 this is an HTTP version identifier
0 this is not an HTTP identifier, or bad parameters

Definition at line 343 of file hi_client.c.

Referenced by NextNonWhiteSpace().

static int NextNonWhiteSpace HI_SESSION Session,
u_char *  start,
u_char *  end,
u_char **  ptr,
URI_PTR uri_ptr
[static]
 

Update the URI_PTR fields spaces, find the next non-white space char, and validate the HTTP version identifier after the spaces.

This is the main part of the URI algorithm. This verifies that there isn't too many spaces in the data to be a URI, it checks that after the second space that there is an HTTP identifier or otherwise it's no good. Also, if we've found an identifier after the first whitespace, and find another whitespace, there is no URI.

The uri and uri_end pointers are updated in this function depending on what space we are at, and if the space was followed by the HTTP identifier. (NOTE: the HTTP delimiter is no longer "HTTP/", but can also be "\r\n", "\n", or "\r". This is the defunct method, and we deal with it in the IsHttpVersion and delimiter functions.)

Parameters:
ServerConf pointer to the server configuration
start pointer to the start of payload
end pointer to the end of the payload
ptr pointer to the pointer of the current index
uri_ptr pointer to the URI_PTR construct
Returns:
integer
Return values:
HI_SUCCESS found the next non-whitespace
HI_OUT_OF_BOUNDS whitespace to the end of the buffer
URI_END delimiter found, end of URI
NO_URI 

Definition at line 570 of file hi_client.c.

References s_HTTPINSPECT_CONF_OPT::alert, s_HTTPINSPECT_CONF::apache_whitespace, s_URI_PTR::first_sp_end, s_URI_PTR::first_sp_start, HI_EO_CLIENT_APACHE_WS, hi_eo_client_event_log(), hi_eo_generate_event(), HI_OUT_OF_BOUNDS, HI_SUCCESS, hi_util_in_bounds(), s_URI_PTR::ident, IsHttpVersion(), s_URI_PTR::last_dir, NO_URI, s_HTTPINSPECT_CONF::non_strict, s_URI_PTR::norm, NULL, s_HTTPINSPECT_CONF_OPT::on, s_URI_PTR::param, s_URI_PTR::proxy, s_URI_PTR::second_sp_end, s_URI_PTR::second_sp_start, s_HI_SESSION::server_conf, s_HTTPINSPECT_CONF::tab_uri_delimiter, s_URI_PTR::uri, and s_URI_PTR::uri_end.

Referenced by hi_client_init().

static int SetBackSlashNorm HI_SESSION Session,
u_char *  start,
u_char *  end,
u_char **  ptr,
URI_PTR uri_ptr
[static]
 

Check for backslashes and if we need to normalize.

This really just checks the configuration option, and sets the norm variable if applicable.

Parameters:
ServerConf pointer to the server configuration
start pointer to the start of payload
end pointer to the end of the payload
ptr pointer to the pointer of the current index
uri_ptr pointer to the URI_PTR construct
Returns:
integer
Return values:
HI_SUCCESS function successful

Definition at line 977 of file hi_client.c.

References HI_SUCCESS, s_URI_PTR::ident, s_HTTPINSPECT_CONF::iis_backslash, s_URI_PTR::norm, s_HTTPINSPECT_CONF_OPT::on, and s_HI_SESSION::server_conf.

Referenced by hi_client_init().

static int SetBinaryNorm HI_SESSION Session,
u_char *  start,
u_char *  end,
u_char **  ptr,
URI_PTR uri_ptr
[static]
 

Look for non-ASCII chars in the URI.

We look for these chars in the URI and set the normalization variable if it's not already set. I think we really only need this for IIS servers, but we may want to know if it's in the URI too.

Parameters:
ServerConf pointer to the server configuration
start pointer to the start of payload
end pointer to the end of the payload
ptr pointer to the pointer of the current index
uri_ptr pointer to the URI_PTR construct
Returns:
integer
Return values:
HI_SUCCESS function successful

Definition at line 1016 of file hi_client.c.

References HI_SUCCESS, s_URI_PTR::ident, and s_URI_PTR::norm.

Referenced by hi_client_init().

static int SetClientVars HI_CLIENT Client,
URI_PTR uri_ptr,
u_int  dsize
[static]
 

This is where we set the HI_CLIENT values that we found during URI discovery. This also covers checking these values for errors.

Parameters:
Client pointer to HI_CLIENT structure
uri_ptr pointer to the uri data
Returns:
integer
Return values:
HI_NONFATAL_ERR problem with the uri values.
HI_SUCCESS values set successfully

Definition at line 1117 of file hi_client.c.

References HI_NONFATAL_ERR, HI_SUCCESS, s_URI_PTR::norm, NULL, s_HI_CLIENT::request, s_HI_CLIENT_REQ::uri, s_URI_PTR::uri, s_URI_PTR::uri_end, s_HI_CLIENT_REQ::uri_norm, and s_HI_CLIENT_REQ::uri_size.

Referenced by StatelessInspection().

static int SetParamField HI_SESSION Session,
u_char *  start,
u_char *  end,
u_char **  ptr,
URI_PTR uri_ptr
[static]
 

This function sets the parameter field as the first '?'. The big thing is that we set the param value, so we don't false positive long dir events when it's really just a long parameter field.

Parameters:
ServerConf pointer to the server configuration
start pointer to the start of payload
end pointer to the end of the payload
ptr pointer to the pointer of the current index
uri_ptr pointer to the URI_PTR construct
Returns:
integer
Return values:
HI_SUCCESS function successful

Definition at line 1048 of file hi_client.c.

References HI_SUCCESS, s_URI_PTR::ident, and s_URI_PTR::param.

Referenced by hi_client_init().

static int SetPercentNorm HI_SESSION Session,
u_char *  start,
u_char *  end,
u_char **  ptr,
URI_PTR uri_ptr
[static]
 

Check for percent normalization in the URI buffer.

We don't do much here besides check the configuration, set the pointer, and continue processing.

Parameters:
ServerConf pointer to the server configuration
start pointer to the start of payload
end pointer to the end of the payload
ptr pointer to the pointer of the current index
uri_ptr pointer to the URI_PTR construct
Returns:
integer
Return values:
HI_SUCCESS function successful

Definition at line 814 of file hi_client.c.

References s_HTTPINSPECT_CONF::ascii, HI_SUCCESS, s_URI_PTR::ident, s_URI_PTR::norm, s_HTTPINSPECT_CONF_OPT::on, and s_HI_SESSION::server_conf.

Referenced by hi_client_init().

static int SetProxy HI_SESSION Session,
u_char *  start,
u_char *  end,
u_char **  ptr,
URI_PTR uri_ptr
[static]
 

This function checks for an absolute URI in the URI.

Parameters:
ServerConf pointer to the server configuration
start pointer to the start of payload
end pointer to the end of the payload
ptr pointer to the pointer of the current index
uri_ptr pointer to the URI_PTR construct
Returns:
integer
Return values:
HI_SUCCESS function successful

Definition at line 1077 of file hi_client.c.

References s_HTTPINSPECT_CONF::allow_proxy, s_HI_SESSION::global_conf, HI_SUCCESS, hi_util_in_bounds(), s_URI_PTR::ident, s_URI_PTR::last_dir, s_URI_PTR::proxy, s_HTTPINSPECT_GLOBAL_CONF::proxy_alert, and s_HI_SESSION::server_conf.

Referenced by hi_client_init().

static int SetSlashNorm HI_SESSION Session,
u_char *  start,
u_char *  end,
u_char **  ptr,
URI_PTR uri_ptr
[static]
 

Check for any directory traversal or multi-slash normalization.

Parameters:
ServerConf pointer to the server configuration
start pointer to the start of payload
end pointer to the end of the payload
ptr pointer to the pointer of the current index
uri_ptr pointer to the URI_PTR construct
Returns:
integer
Return values:
HI_SUCCESS function successful
HI_OUT_OF_BOUNDS reached the end of the buffer

Definition at line 890 of file hi_client.c.

References CheckLongDir(), s_HTTPINSPECT_CONF::directory, HI_OUT_OF_BOUNDS, HI_SUCCESS, hi_util_in_bounds(), s_URI_PTR::ident, s_URI_PTR::last_dir, s_HTTPINSPECT_CONF::multiple_slash, s_URI_PTR::norm, NULL, s_HTTPINSPECT_CONF_OPT::on, and s_HI_SESSION::server_conf.

Referenced by hi_client_init().

static int StatelessInspection HI_SESSION Session,
unsigned char *  data,
int  dsize
[static]
 

Find the URI and determine whether the URI needs to be normalized.

This is a big step in stateless inspection, because we need to reliably find the URI and when possible filter out non-URIs. We do this using a simple state machine that is based on characters found in the data buffer.

Another important aspect of the stateless inspection is the ability to track and inspect pipelined requests. It is VERY IMPORTANT to reset the pipeline_req pointer, since we don't memset the whole structure. This pointer is reset in the hi_si_session_inspection() function. Check there for more details.

Normalization is detected when we are looking at the packet for the URI. We look for the following issues:

  • ////
  • /../
  • /./
  • non-ascii charss
  • %
  • \ When these things are seen we point to the first occurence in the URI, or where we have to start normalizing. If the URI is updated to a new pointer, then the normalization pointer is reset and we start over. Using this method should cut down the memcpy()s per URI, since most URIs are not normalized.

If this function returns HI_NONFATAL_ERR, we return out of mode_inspection with an error and abort HttpInspect processing, and continue on with any other processing we do. The Session parameters that we use here are reset in the next time that we do session_inspection, so we don't do any initialization here.

Parameters:
Session pointer to the HTTP session
data pointer to the start of the packet payload
dsize size of the payload
Returns:
integer
Return values:
HI_INVALID_ARG invalid argument
HI_NONFATAL_ERR no URI detected
HI_SUCCESS URI detected and Session pointers updated

Definition at line 1233 of file hi_client.c.

References s_HTTPINSPECT_CONF::allow_proxy, CheckChunkEncoding(), CheckLongDir(), s_HTTPINSPECT_CONF::chunk_length, s_HI_SESSION::client, s_HI_SESSION::client_conf, s_URI_PTR::delimiter, FindPipelineReq(), s_URI_PTR::first_sp_end, s_HI_SESSION::global_conf, hi_eo_client_event_log(), HI_EO_CLIENT_PROXY_USE, hi_eo_generate_event(), HI_INVALID_ARG, HI_NONFATAL_ERR, HI_OUT_OF_BOUNDS, HI_SUCCESS, hi_util_in_bounds(), lookup_table, memset, s_HTTPINSPECT_CONF::no_pipeline, NULL, s_HI_CLIENT_REQ::pipeline_req, s_URI_PTR::proxy, s_HTTPINSPECT_GLOBAL_CONF::proxy_alert, s_HI_CLIENT::request, s_HI_SESSION::server_conf, SetClientVars(), s_URI_PTR::uri, URI_END, and s_URI_PTR::uri_end.

Referenced by hi_client_inspection().


Variable Documentation

int hex_lookup[256] [static]
 

Definition at line 87 of file hi_client.c.

Referenced by CheckChunkEncoding(), DoubleDecode(), hi_client_init(), hi_norm_init(), PercentDecode(), and UDecode().

LOOKUP_FCN lookup_table[256] [static]
 

Definition at line 86 of file hi_client.c.

Referenced by hi_client_init(), and StatelessInspection().


Generated on Sun May 14 14:51:24 2006 by  doxygen 1.4.2