00001 /** 00002 ** @file hi_server.c 00003 ** 00004 ** @author Daniel Roelker <droelker@sourcefire.com> 00005 ** 00006 ** @brief Handles inspection of HTTP server responses. 00007 ** 00008 ** HttpInspect handles server responses in a stateless manner because we 00009 ** are really only interested in the first response packet that contains 00010 ** the HTTP response code, headers, and the payload. 00011 ** 00012 ** The first big thing is to incorporate the HTTP protocol flow 00013 ** analyzer. 00014 ** 00015 ** NOTES: 00016 ** - Initial development. DJR 00017 */ 00018 #include <stdio.h> 00019 00020 #include "hi_ui_config.h" 00021 #include "hi_si.h" 00022 #include "hi_return_codes.h" 00023 #include "hi_server.h" 00024 00025 /** 00026 ** NAME 00027 ** IsHttpServerData:: 00028 */ 00029 /** 00030 ** Inspect an HTTP server response packet to determine the state. 00031 ** 00032 ** We inspect this packet and determine whether we are in the beginning 00033 ** of a response header or if we are looking at payload. We limit the 00034 ** amount of inspection done on responses by only inspecting the HTTP header 00035 ** and some payload. If the whole packet is a payload, then we just ignore 00036 ** it, since we inspected the previous header and payload. 00037 ** 00038 ** We limit the amount of the payload by adjusting the Server structure 00039 ** members, header and header size. 00040 ** 00041 ** @param Server the server structure 00042 ** @param data pointer to the beginning of payload 00043 ** @param dsize the size of the payload 00044 ** @param flow_depth the amount of header and payload to inspect 00045 ** 00046 ** @return integer 00047 ** 00048 ** @retval HI_INVALID_ARG invalid argument 00049 ** @retval HI_SUCCESS function success 00050 */ 00051 static int IsHttpServerData(HI_SERVER *Server, u_char *data, int dsize, 00052 int flow_depth) 00053 { 00054 /* 00055 ** HTTP:Server-Side-Session-Performance-Optimization 00056 ** This drops Server->Client packets which are not part of the 00057 ** HTTP Response header. It can miss part of the response header 00058 ** if the header is sent as multiple packets. 00059 */ 00060 if(!data) 00061 { 00062 return HI_INVALID_ARG; 00063 } 00064 00065 /* 00066 ** Let's set up the data pointers. 00067 */ 00068 Server->header = data; 00069 Server->header_size = dsize; 00070 00071 /* 00072 ** This indicates that we want to inspect the complete response, so 00073 ** we don't waste any time otherwise. 00074 */ 00075 if(flow_depth < 1) 00076 { 00077 return HI_SUCCESS; 00078 } 00079 00080 if(dsize > 4 ) 00081 { 00082 if( (data[0]!='H') || (data[1]!='T') || 00083 (data[2]!='T') || (data[3]!='P') ) 00084 { 00085 Server->header_size = 0; 00086 Server->header = NULL; 00087 00088 return HI_SUCCESS; 00089 } 00090 00091 /* 00092 ** OK its an HTTP response header. 00093 ** 00094 ** Now, limit the amount we inspect, 00095 ** we could just examine this whole packet, 00096 ** since it's usually full of HTTP Response info. 00097 ** For protocol analysis purposes we probably ought to 00098 ** let the whole thing get processed, or have a 00099 ** different pattern match length and protocol inspection 00100 ** length. 00101 */ 00102 00103 if(dsize > flow_depth) 00104 { 00105 Server->header_size = flow_depth; 00106 } 00107 } 00108 00109 return HI_SUCCESS; 00110 } 00111 00112 static int ServerInspection(HI_SESSION *Session, unsigned char *data, 00113 int dsize) 00114 { 00115 HI_SERVER *Server; 00116 int iRet; 00117 00118 Server = &(Session->server); 00119 00120 /* 00121 ** There's really only one thing that we do right now for server 00122 ** responses, that's HTTP flow. 00123 */ 00124 if((iRet = IsHttpServerData(Server, data, dsize, 00125 Session->server_conf->flow_depth))) 00126 { 00127 return iRet; 00128 } 00129 00130 return HI_SUCCESS; 00131 } 00132 00133 int hi_server_inspection(void *S, unsigned char *data, int dsize) 00134 { 00135 HI_SESSION *Session; 00136 00137 int iRet; 00138 00139 if(!S || !data || dsize < 1) 00140 { 00141 return HI_INVALID_ARG; 00142 } 00143 00144 Session = (HI_SESSION *)S; 00145 00146 /* 00147 ** Let's inspect the server response. 00148 */ 00149 if((iRet = ServerInspection(Session, data, dsize))) 00150 { 00151 return iRet; 00152 } 00153 00154 return HI_SUCCESS; 00155 }