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

hi_si.c

Go to the documentation of this file.
00001 /**
00002 **  @file       hi_si.c
00003 **
00004 **  @author     Daniel J. Roelker <droelker@sourcefire.com>
00005 **
00006 **  @brief      This file contains functions to select server configurations
00007 **              and begin the HttpInspect process.
00008 **
00009 **  The Session Inspection Module interfaces with the Stream Inspection 
00010 **  Module and the User Interface Module to select the appropriate 
00011 **  HttpInspect configuration and in the case of stateful inspection the
00012 **  Session Inspection Module retrieves the user-data from the Stream
00013 **  Module.  For stateless inspection, the Session Inspection Module uses
00014 **  the same structure for use by each packet.
00015 **
00016 **  The main responsibility of this module is to supply the appropriate
00017 **  data structures and configurations for the rest of the HttpInspect
00018 **  process.  The module also determines what type of data is being
00019 **  inspected, whether it is client, server, or neither.
00020 **
00021 **  NOTES:
00022 **
00023 **  - 2.25.03:  Initial Development.  DJR
00024 */
00025 #include <stdlib.h>
00026 #include <stdio.h>
00027 #include <string.h>
00028 
00029 #include "hi_return_codes.h"
00030 #include "hi_ui_config.h"
00031 #include "hi_ui_server_lookup.h"
00032 #include "hi_si.h"
00033 #include "hi_ad.h"
00034 
00035 /*
00036 **  NAME
00037 **    IsServer::
00038 */
00039 /**
00040 **  Given a server configuration and a port number, we decide if the port is
00041 **  in the HTTP server port list.
00042 **
00043 **  @param ServerConf pointer to the server configuration
00044 **  @param port       the port number to compare with the configuration
00045 **  @param pdir       the packet direction (from client, server, etc.)
00046 **
00047 **  @return integer
00048 **
00049 **  @retval  0 means that the port is not a server port
00050 **  @retval !0 means that the port is a server port
00051 */
00052 static int IsServer(HTTPINSPECT_CONF *ServerConf, unsigned short port)
00053 {
00054     if(ServerConf->ports[port])
00055     {
00056         return 1;
00057     }
00058 
00059     return 0;
00060 }
00061 
00062 /*
00063 **  NAME
00064 **    InitServerConf::
00065 */
00066 /**
00067 **  When a session is initialized, we must select the appropriate server 
00068 **  configuration and select the type of inspection based on the source and 
00069 **  destination ports.
00070 **
00071 **  IMPORTANT NOTE:
00072 **    We should check to make sure that there are some unique configurations, 
00073 **    otherwise we can just default to the global default and work some magic 
00074 **    that way.
00075 **
00076 **  @param GlobalConf     pointer to the global configuration
00077 **  @param ServerConf     pointer to the address of the server config so we can
00078 **                        set it.
00079 **  @param SiInput        pointer to the packet info (sip,dip,sport,dport)
00080 **  @param piInspectMode  pointer so we can set the inspection mode
00081 **  
00082 **  @return integer
00083 **  
00084 **  @retval HI_SUCCESS  function successful
00085 */
00086 static int InitServerConf(HTTPINSPECT_GLOBAL_CONF *GlobalConf, 
00087                           HTTPINSPECT_CONF **ServerConf, 
00088                           HTTPINSPECT_CONF **ClientConf, 
00089                           HI_SI_INPUT *SiInput, int *piInspectMode)
00090 {
00091     HTTPINSPECT_CONF *ServerConfSip;
00092     HTTPINSPECT_CONF *ServerConfDip;
00093     int iServerSip;
00094     int iServerDip;
00095     int iErr = 0;
00096 
00097     /*
00098     **  We find the server configurations for both the source and dest. IPs.
00099     **  There should be a check on the global configuration to see if there
00100     **  is at least one unique server configuration.  If there isn't then we
00101     **  assume the global server configuration.
00102     */
00103     ServerConfDip = hi_ui_server_lookup_find(GlobalConf->server_lookup, 
00104             SiInput->dip, &iErr);
00105     if(!ServerConfDip)
00106     {
00107         ServerConfDip = &GlobalConf->global_server;
00108     }
00109 
00110     ServerConfSip = hi_ui_server_lookup_find(GlobalConf->server_lookup,
00111             SiInput->sip, &iErr);
00112     if(!ServerConfSip)
00113     {
00114         ServerConfSip = &GlobalConf->global_server;
00115     }
00116 
00117     /*
00118     **  We check the IP and the port to see if the HTTP server is talking in
00119     **  the session.  This should tell us whether it is client communication
00120     **  or server configuration.  If both IPs and ports are servers, then there
00121     **  is a sort of problem.  We don't know which side is the client and which
00122     **  side is the server so we have to assume one.
00123     **
00124     **  In stateful processing, we only do this stage on the startup of a 
00125     **  session, so we can still assume that the initial packet is the client 
00126     **  talking.
00127     */
00128     iServerSip = IsServer(ServerConfSip, SiInput->sport);
00129     iServerDip = IsServer(ServerConfDip, SiInput->dport);
00130 
00131     /*
00132     **  We default to the no HTTP traffic case
00133     */
00134     *piInspectMode = HI_SI_NO_MODE;
00135     *ServerConf = NULL;
00136 
00137     /*
00138     **  Depending on the type of packet direction we get from the
00139     **  state machine, we evaluate client/server differently.
00140     */
00141     switch(SiInput->pdir)
00142     {
00143         case HI_SI_NO_MODE:
00144             /*
00145             **  We check for the case where both SIP and DIP 
00146             **  appear to be servers.  In this case, we assume client
00147             **  and process that way.
00148             */
00149             if(iServerSip && iServerDip)
00150             {
00151                 *piInspectMode = HI_SI_CLIENT_MODE;
00152                 *ServerConf = ServerConfDip;
00153                 *ClientConf = ServerConfSip;
00154             }
00155             else if(iServerSip)
00156             {
00157                 *piInspectMode = HI_SI_SERVER_MODE;
00158                 *ServerConf = ServerConfSip;
00159                 *ClientConf = ServerConfDip;
00160             }
00161             else if(iServerDip)
00162             {
00163                 *piInspectMode = HI_SI_CLIENT_MODE;
00164                 *ServerConf = ServerConfDip;
00165                 *ClientConf = ServerConfSip;
00166             }
00167             break;
00168 
00169         case HI_SI_CLIENT_MODE:
00170             if(iServerDip)
00171             {
00172                 *piInspectMode = HI_SI_CLIENT_MODE;
00173                 *ServerConf = ServerConfDip;
00174                 *ClientConf = ServerConfSip;
00175             }
00176             break;
00177 
00178         case HI_SI_SERVER_MODE:
00179             if(iServerSip)
00180             {
00181                 *piInspectMode = HI_SI_SERVER_MODE;
00182                 *ServerConf = ServerConfSip;
00183                 *ClientConf = ServerConfDip;
00184             }
00185             break;
00186 
00187         default:
00188             *piInspectMode = HI_SI_NO_MODE;
00189             *ServerConf = NULL;
00190             *ClientConf = NULL;
00191             break;
00192     }
00193             
00194     return HI_SUCCESS;
00195 }
00196     
00197 static int StatefulSessionInspection(HTTPINSPECT_GLOBAL_CONF *GlobalConf,
00198         HI_SESSION **Session, HI_SI_INPUT *SiInput, int *piInspectType)
00199 {
00200     /*
00201     **  We do stuff here for stateful session inspection in the next phase.
00202     */
00203 
00204     return HI_NONFATAL_ERR;
00205 }
00206 
00207 /*
00208 **  NAME
00209 **    ResetSession::
00210 */
00211 /**
00212 **  This function resets all the variables that need to be initialized for
00213 **  a new Session.  I've tried to keep this to a minimum, so we don't have
00214 **  to worry about initializing big structures.
00215 **  
00216 **  @param Session  pointer to the session to reset
00217 **  
00218 **  @return integer
00219 **  
00220 **  @retval HI_SUCCESS
00221 */
00222 static INLINE int ResetSession(HI_SESSION *Session)
00223 {
00224     
00225     Session->client.event_list.stack_count      = 0;
00226     Session->anom_server.event_list.stack_count = 0;
00227 
00228     Session->client.request.uri                 = NULL;
00229     Session->client.request.uri_norm            = NULL;
00230     Session->client.request.uri_size            = 0;
00231     Session->client.request.uri_norm_size       = 0;
00232 
00233     Session->client.request.pipeline_req        = NULL;
00234 
00235     return HI_SUCCESS;
00236 }
00237 
00238 /*
00239 **  NAME
00240 **    StatelessSessionInspection::
00241 */
00242 /**
00243 **  Initialize the session and server configurations for this packet/stream.
00244 **
00245 **  It is important to note in stateless mode that we assume no knowledge of the
00246 **  state of a connection, other than the knowledge that we can glean from an
00247 **  individual packet.  So in essence, each packet is it's own session and there
00248 **  is no knowledge retained from one packet to another.  If you want to track
00249 **  an HTTP session for real, use stateful mode.
00250 **
00251 **  In this function, we set the Session pointer (which includes the correct 
00252 **  server configuration).  The actual processing to find which IP is the 
00253 **  server and which is the client, is done in the InitServerConf() function.
00254 **
00255 **  @param GlobalConf    pointer to the global configuration
00256 **  @param Session       double pointer to the Session structure
00257 **  @param SiInput       pointer to the session information
00258 **  @param piInspectMode pointer so the inspection mode can be set
00259 **
00260 **  @return integer
00261 **
00262 **  @retval HI_SUCCESS function successful
00263 */
00264 static int StatelessSessionInspection(HTTPINSPECT_GLOBAL_CONF *GlobalConf,
00265         HI_SESSION **Session, HI_SI_INPUT *SiInput, int *piInspectMode)
00266 {
00267     static HI_SESSION StaticSession;
00268     HTTPINSPECT_CONF *ServerConf;
00269     HTTPINSPECT_CONF *ClientConf;
00270     int iRet;
00271 
00272     ResetSession(&StaticSession);
00273 
00274     if((iRet = InitServerConf(GlobalConf, &ServerConf, &ClientConf, SiInput, 
00275                     piInspectMode)))
00276     {
00277         return iRet;
00278     }
00279     
00280     StaticSession.server_conf = ServerConf;
00281     StaticSession.client_conf = ClientConf;
00282     StaticSession.global_conf = GlobalConf;
00283 
00284     *Session = &StaticSession;
00285 
00286     return HI_SUCCESS;
00287 }
00288     
00289 
00290 /*
00291 **  NAME
00292 **    hi_si_session_inspection::
00293 */
00294 /**
00295 **  The Session Inspection module selects the appropriate server configuration
00296 **  for the session, and the type of inspection to be performed (client or 
00297 **  server.)
00298 **
00299 **  When the Session Inspection module is in stateful mode, it checks to see if
00300 **  there is a HI_SESSION pointer already associated with the stream.  If there
00301 **  is, then it uses that session pointer, otherwise it calculates the server
00302 **  configuration using the HI_SI_INPUT and returns a HI_SESSION pointer.  In
00303 **  stateful mode, this means that memory is allocated, but in stateless mode,
00304 **  the same session pointer is used for all packets to reduce the allocation
00305 **  overhead.
00306 **
00307 **  The inspection mode can be either client, server, or neither.  In the case
00308 **  of neither, the packet is inspected for rogue HTTP servers and HTTP 
00309 **  tunneling.
00310 **
00311 **  @param GlobalConf    pointer to the global configuration
00312 **  @param Session       double pointer so the session can be set
00313 **  @param SiInput       session input pointer for data
00314 **  @param piInspectMode pointer for setting inspection mode
00315 **
00316 **  @return integer
00317 **
00318 **  @retval HI_SUCCESS        function successful
00319 **  @retval HI_MEM_ALLOC_FAIL failure to allocate memory
00320 **  @retval HI_INVALID_ARG    argument was invalid (NULL pointers, etc)
00321 */
00322 int hi_si_session_inspection(HTTPINSPECT_GLOBAL_CONF *GlobalConf,
00323         HI_SESSION **Session, HI_SI_INPUT *SiInput, int *piInspectMode)
00324 {
00325     int iRet;
00326 
00327     /*
00328     **  We get the server configuration and the session structure differently 
00329     **  depending on what type of inspection we are doing.  In the case of 
00330     **  stateful processing, we may get the session structure from the Stream
00331     **  Reassembly module (which includes the server configuration) or the 
00332     **  structure will be allocated and added to the stream pointer for the
00333     **  rest of the session.
00334     **
00335     **  In stateless mode, we just use a static variable that is contained in
00336     **  the function here.
00337     */
00338     if(GlobalConf->inspection_type == HI_UI_CONFIG_STATEFUL)
00339     {
00340         if((iRet = StatefulSessionInspection(GlobalConf, Session, SiInput, 
00341                         piInspectMode)))
00342         {
00343             return iRet;
00344         }
00345     }
00346     else
00347     {
00348         /*
00349         **  Assume stateless processing otherwise
00350         */
00351         if((iRet = StatelessSessionInspection(GlobalConf, Session, SiInput, 
00352                         piInspectMode)))
00353         {
00354             return iRet;
00355         }
00356     }
00357 
00358     return HI_SUCCESS;
00359 }

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