"Fossies" - the Fresh Open Source Software Archive

Member "snort-2.9.17/src/preprocessors/HttpInspect/server/hi_server.c" (16 Oct 2020, 92555 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_server.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_server.c
   25 **
   26 **  @author     Daniel Roelker <droelker@sourcefire.com>
   27 **
   28 **  @brief      Handles inspection of HTTP server responses.
   29 **
   30 **  HttpInspect handles server responses in a stateless manner because we
   31 **  are really only interested in the first response packet that contains
   32 **  the HTTP response code, headers, and the payload.
   33 **
   34 **  The first big thing is to incorporate the HTTP protocol flow
   35 **  analyzer.
   36 **
   37 **  NOTES:
   38 **      - Initial development.  DJR
   39 */
   40 #ifdef HAVE_CONFIG_H
   41 #include "config.h"
   42 #endif
   43 
   44 #include <stdio.h>
   45 #include <string.h>
   46 #include <zlib.h>
   47 #include "mempool.h"
   48 #include "hi_paf.h"
   49 extern MemPool *hi_gzip_mempool;
   50 extern uint8_t decompression_buffer[];
   51 
   52 extern uint8_t dechunk_buffer[];
   53 static bool simple_response = false;
   54 
   55 #include "hi_server.h"
   56 #include "hi_ui_config.h"
   57 #include "hi_return_codes.h"
   58 #include "hi_si.h"
   59 #include "hi_eo_log.h"
   60 #include "snort_bounds.h"
   61 #include "detection_util.h"
   62 #include "stream_api.h"
   63 #include "sfutil/util_unfold.h"
   64 
   65 #if defined(FEAT_OPEN_APPID)
   66 #include "spp_stream6.h"
   67 #endif /* defined(FEAT_OPEN_APPID) */
   68 
   69 #define STAT_END 100
   70 #define HTTPRESP_HEADER_NAME__COOKIE "Set-Cookie"
   71 #define HTTPRESP_HEADER_LENGTH__COOKIE 10
   72 #define HTTPRESP_HEADER_NAME__CONTENT_ENCODING "Content-Encoding"
   73 #define HTTPRESP_HEADER_LENGTH__CONTENT_ENCODING 16
   74 #define HTTPRESP_HEADER_NAME__GZIP "gzip"
   75 #define HTTPRESP_HEADER_NAME__XGZIP "x-gzip"
   76 #define HTTPRESP_HEADER_LENGTH__GZIP 4
   77 #define HTTPRESP_HEADER_LENGTH__XGZIP 6
   78 #define HTTPRESP_HEADER_NAME__DEFLATE "deflate"
   79 #define HTTPRESP_HEADER_LENGTH__DEFLATE 7
   80 #define HTTPRESP_HEADER_NAME__CONTENT_LENGTH "Content-length"
   81 #define HTTPRESP_HEADER_LENGTH__CONTENT_LENGTH 14
   82 #define HTTPRESP_HEADER_NAME__CONTENT_TYPE "Content-Type"
   83 #define HTTPRESP_HEADER_LENGTH__CONTENT_TYPE 12
   84 #define HTTPRESP_HEADER_NAME__TRANSFER_ENCODING "Transfer-Encoding"
   85 #define HTTPRESP_HEADER_LENGTH__TRANSFER_ENCODING 17
   86 #define HTTPRESP_HEADER_NAME__CONTENT_RANGE "Content-Range"
   87 #define HTTPRESP_HEADER_LENGTH__CONTENT_RANGE 13
   88 #define HTTPRESP_HEADER_NAME__ACCEPT_RANGES "Accept-Ranges"
   89 #define HTTPRESP_HEADER_LENGTH__ACCEPT_RANGES 13
   90 #if defined(FEAT_OPEN_APPID)
   91 #define HEADER_NAME__VIA "Via"
   92 #define HEADER_LENGTH__VIA sizeof(HEADER_NAME__VIA)-1
   93 #define HEADER_NAME__SERVER "Server"
   94 #define HEADER_LENGTH__SERVER sizeof(HEADER_NAME__SERVER)-1
   95 #define HEADER_NAME__X_WORKING_WITH "X-Working-With"
   96 #define HEADER_LENGTH__X_WORKING_WITH sizeof(HEADER_NAME__X_WORKING_WITH)-1
   97 #endif /* defined(FEAT_OPEN_APPID) */
   98 
   99 extern fd_config_t hi_fd_conf;
  100 
  101 typedef int (*LOOKUP_FCN)(HI_SESSION *, const u_char *, const u_char *, const u_char **,
  102             URI_PTR *);
  103 extern LOOKUP_FCN lookup_table[256];
  104 extern int NextNonWhiteSpace(HI_SESSION *, const u_char *, const u_char *, const u_char **, URI_PTR *);
  105 extern int CheckChunkEncoding(HI_SESSION *, const u_char *, const u_char *, const u_char **, u_char *,
  106                               uint32_t , uint32_t, uint32_t *, uint32_t *, HttpSessionData *, int);
  107 extern int IsHttpVersion(const u_char **, const u_char *);
  108 extern int find_rfc_delimiter(HI_SESSION *, const u_char *, const u_char *, const u_char **, URI_PTR *);
  109 extern int find_non_rfc_delimiter(HI_SESSION *, const u_char *, const u_char *, const u_char **, URI_PTR *);
  110 extern int NextNonWhiteSpace(HI_SESSION *, const u_char *, const u_char *, const u_char **, URI_PTR *);
  111 extern int SetPercentNorm(HI_SESSION *, const u_char *, const u_char *, const u_char **, URI_PTR *);
  112 extern int SetSlashNorm(HI_SESSION *, const u_char *, const u_char *, const u_char **, URI_PTR *);
  113 extern int SetBackSlashNorm(HI_SESSION *, const u_char *, const u_char *, const u_char **, URI_PTR *);
  114 extern int SetPlusNorm(HI_SESSION *, const u_char *, const u_char *, const u_char **, URI_PTR *);
  115 extern int SetBinaryNorm(HI_SESSION *, const u_char *, const u_char *, const u_char **, URI_PTR *);
  116 extern int SetParamField(HI_SESSION *, const u_char *, const u_char *, const u_char **, URI_PTR *);
  117 extern int SetProxy(HI_SESSION *, const u_char *, const u_char *, const u_char **, URI_PTR *);
  118 extern const u_char *extract_http_cookie(const u_char *p, const u_char *end, HEADER_PTR *, HEADER_FIELD_PTR *);
  119 extern const u_char *extract_http_content_length(HI_SESSION *, HTTPINSPECT_CONF *, const u_char *, const u_char *, const u_char *, HEADER_PTR *, HEADER_FIELD_PTR *, int) ;
  120 
  121 #define CLR_SERVER_HEADER(Server) \
  122     do { \
  123             Server->response.header_raw = NULL;\
  124             Server->response.header_raw_size = 0;\
  125             Server->response.header_norm = NULL; \
  126             Server->response.header_norm_size = 0 ;\
  127             Server->response.cookie.cookie = NULL;\
  128             Server->response.cookie.cookie_end = NULL;\
  129             if(Server->response.cookie.next) {\
  130                 COOKIE_PTR *cookie = Server->response.cookie.next; \
  131                 do { \
  132                     Server->response.cookie.next = Server->response.cookie.next->next; \
  133                     free(cookie); \
  134                     cookie = Server->response.cookie.next; \
  135                 }while(cookie);\
  136             }\
  137             Server->response.cookie.next = NULL;\
  138             Server->response.cookie_norm = NULL;\
  139             Server->response.cookie_norm_size = 0;\
  140     } while(0);
  141 
  142 #define CLR_SERVER_STAT(Server) \
  143     do { \
  144             Server->response.status_msg = NULL;\
  145             Server->response.status_code = NULL;\
  146             Server->response.status_code_size = 0;\
  147             Server->response.status_msg_size = 0;\
  148     }while(0);
  149 
  150 #define CLR_SERVER_STAT_MSG(Server) \
  151     do { \
  152             Server->response.status_msg = NULL;\
  153             Server->response.status_msg_size = 0;\
  154         }while(0);
  155 
  156 #define CLR_SERVER_BODY(Server)\
  157     do { \
  158             Server->response.body = NULL;\
  159             Server->response.body_size = 0;\
  160             Server->response.body_raw = NULL;\
  161             Server->response.body_raw_size = 0;\
  162     }while(0);
  163 
  164 static inline void clearHttpRespBuffer(HI_SERVER *Server)
  165 {
  166     CLR_SERVER_HEADER(Server);
  167     CLR_SERVER_STAT(Server);
  168     CLR_SERVER_BODY(Server);
  169 }
  170 
  171 static inline const u_char *MovePastDelims(const u_char *start, const u_char *end,const u_char *ptr)
  172 {
  173 
  174     while(hi_util_in_bounds(start, end, ptr))
  175     {
  176        if(*ptr < 0x21)
  177         {
  178             if(*ptr < 0x0E && *ptr > 0x08)
  179             {
  180                 ptr++;
  181                 continue;
  182             }
  183             else
  184             {
  185                 if(*ptr == 0x20)
  186                 {
  187                     ptr++;
  188                     continue;
  189                 }
  190             }
  191         }
  192 
  193         break;
  194     }
  195 
  196     return ptr;
  197 }
  198 
  199 void CheckSkipAlertMultipleColon(HI_SESSION *Session, const u_char *start, const u_char *end, const u_char **ptr, int iInspectMode)
  200 {
  201     if (hi_util_in_bounds(start, end, *ptr) && **ptr == ':')
  202     {
  203         if (iInspectMode == HI_SI_SERVER_MODE && hi_eo_generate_event(Session, HI_EO_SERVER_MULTIPLE_COLON_BETN_KEY_VALUE))
  204         {
  205             hi_eo_server_event_log(Session, HI_EO_SERVER_MULTIPLE_COLON_BETN_KEY_VALUE, NULL, NULL);
  206         }
  207         else if (iInspectMode == HI_SI_CLIENT_MODE && hi_eo_generate_event(Session, HI_EO_CLIENT_MULTIPLE_COLON_BETN_KEY_VALUE))
  208         {
  209             hi_eo_client_event_log(Session, HI_EO_CLIENT_MULTIPLE_COLON_BETN_KEY_VALUE, NULL, NULL);
  210         }
  211         while (hi_util_in_bounds(start, end, *ptr) && **ptr == ':') (*ptr)++;
  212     }
  213 }
  214 
  215 /**
  216  ** CheckSkipAlertCharsBeforeColon:
  217  **
  218  ** This function skips any invalid characters between
  219  ** http response header and ':'.
  220  **/
  221 static inline void CheckSkipAlertCharsBeforeColon(HI_SESSION *Session, const u_char *start,
  222                          const u_char *end, const u_char **ptr)
  223 {
  224     bool invalid_char = false;
  225 
  226     while ( (hi_util_in_bounds(start, end, *ptr)) && (**ptr != ':')) {
  227         switch(**ptr) {
  228         case ' ':
  229     case '\t':
  230         (*ptr)++;
  231             break;
  232 
  233     case '\0':
  234     case '\r':
  235     case '\n':
  236     case '\v':
  237     case '\f':
  238         invalid_char = true;
  239         (*ptr)++;
  240         break;
  241 
  242         default:
  243         return;
  244         }
  245 
  246     if (invalid_char &&
  247         hi_eo_generate_event(Session, HI_EO_SERVER_INVALID_CHAR_BETN_KEY_VALUE)) {
  248         hi_eo_server_event_log(Session, HI_EO_SERVER_INVALID_CHAR_BETN_KEY_VALUE, NULL, NULL);
  249         }
  250     }
  251 }
  252 
  253 /**
  254 **  NAME
  255 **    IsHttpServerData::
  256 */
  257 /**
  258 **  Inspect an HTTP server response packet to determine the state.
  259 **
  260 **  We inspect this packet and determine whether we are in the beginning
  261 **  of a response header or if we are looking at payload.  We limit the
  262 **  amount of inspection done on responses by only inspecting the HTTP header
  263 **  and some payload.  If the whole packet is a payload, then we just ignore
  264 **  it, since we inspected the previous header and payload.
  265 **
  266 **  We limit the amount of the payload by adjusting the Server structure
  267 **  members, header and header size.
  268 **
  269 **  @param Server      the server structure
  270 **  @param data        pointer to the beginning of payload
  271 **  @param dsize       the size of the payload
  272 **  @param flow_depth  the amount of header and payload to inspect
  273 **
  274 **  @return integer
  275 **
  276 **  @retval HI_INVALID_ARG invalid argument
  277 **  @retval HI_SUCCESS     function success
  278 */
  279 static int IsHttpServerData(HI_SESSION *Session, Packet *p, HttpSessionData *sd)
  280 {
  281     const u_char *start;
  282     const u_char *end;
  283     const u_char *ptr;
  284     int len;
  285     uint32_t seq_num = 0;
  286     HI_SERVER *Server;
  287     HTTPINSPECT_CONF *ServerConf;
  288 
  289     ServerConf = Session->server_conf;
  290     if(!ServerConf)
  291         return HI_INVALID_ARG;
  292 
  293     Server = &(Session->server);
  294 
  295     clearHttpRespBuffer(Server);
  296     /*
  297     ** HTTP:Server-Side-Session-Performance-Optimization
  298     ** This drops Server->Client packets which are not part of the
  299     ** HTTP Response header. It can miss part of the response header
  300     ** if the header is sent as multiple packets.
  301     */
  302     if(!(p->data))
  303     {
  304         return HI_INVALID_ARG;
  305     }
  306 
  307     seq_num = GET_PKT_SEQ(p);
  308 
  309     /*
  310     **  Let's set up the data pointers.
  311     */
  312     Server->response.header_raw      = p->data;
  313     Server->response.header_raw_size = p->dsize;
  314 
  315     start = p->data;
  316     end = p->data + p->dsize;
  317     ptr = start;
  318 
  319     ptr = MovePastDelims(start,end,ptr);
  320 
  321     len = end - ptr;
  322     if ( len > 4 )
  323     {
  324         if(!IsHttpVersion(&ptr, end))
  325         {
  326             p->packet_flags |= PKT_HTTP_DECODE;
  327             ApplyFlowDepth(ServerConf, p, sd, 0, 0, seq_num);
  328             return HI_SUCCESS;
  329         }
  330         else
  331         {
  332             if(ServerConf->server_flow_depth > 0)
  333             {
  334                 if(sd)
  335                 {
  336                     sd->resp_state.flow_depth_excd = false;
  337                     sd->resp_state.max_seq = seq_num + ServerConf->server_flow_depth;
  338                 }
  339             }
  340             p->packet_flags |= PKT_HTTP_DECODE;
  341             ApplyFlowDepth(ServerConf, p, sd, 0, 0, seq_num);
  342             return HI_SUCCESS;
  343         }
  344     }
  345     else
  346     {
  347         return HI_SUCCESS;
  348     }
  349 
  350 
  351     return HI_SUCCESS;
  352 }
  353 
  354 static inline int hi_server_extract_status_msg( const u_char *start, const u_char *ptr,
  355         const u_char *end, URI_PTR *result)
  356 {
  357     int iRet = HI_SUCCESS;
  358     SkipBlankSpace(start,end,&ptr);
  359 
  360     if (  hi_util_in_bounds(start, end, ptr) )
  361     {
  362         const u_char *crlf = (u_char *)SnortStrnStr((const char *)ptr, end - ptr, "\n");
  363         result->uri = ptr;
  364         if (crlf)
  365         {
  366             if(crlf[-1] == '\r')
  367                 result->uri_end = crlf - 1;
  368             else
  369                 result->uri_end = crlf;
  370             ptr = crlf;
  371         }
  372         else
  373         {
  374             result->uri_end =end;
  375         }
  376 
  377         if(result->uri < result->uri_end)
  378             iRet = STAT_END;
  379         else
  380             iRet = HI_OUT_OF_BOUNDS;
  381     }
  382     else
  383         iRet = HI_OUT_OF_BOUNDS;
  384 
  385     return iRet;
  386 }
  387 
  388 
  389 static inline int hi_server_extract_status_code(HI_SESSION *Session, const u_char *start, const u_char *ptr,
  390         const u_char *end, URI_PTR *result)
  391 {
  392     int iRet = HI_SUCCESS;
  393     SkipBlankSpace(start,end,&ptr);
  394 
  395     result->uri = ptr;
  396     result->uri_end = ptr;
  397 
  398     while(  hi_util_in_bounds(start, end, ptr) )
  399     {
  400         if(isdigit((int)*ptr))
  401         {
  402             SkipDigits(start, end, &ptr);
  403             if (  hi_util_in_bounds(start, end, ptr) )
  404             {
  405                 if(isspace((int)*ptr))
  406                 {
  407                     result->uri_end = ptr;
  408                     iRet = STAT_END;
  409                     return iRet;
  410                 }
  411                 else
  412                 {
  413                     result->uri_end = ptr;
  414                     iRet = HI_NONFATAL_ERR;
  415                     return iRet;
  416                 }
  417 
  418             }
  419             else
  420             {
  421                 iRet = HI_OUT_OF_BOUNDS;
  422                 return iRet;
  423             }
  424 
  425         }
  426         else
  427         {
  428 
  429             if(hi_eo_generate_event(Session, HI_EO_SERVER_INVALID_STATCODE))
  430             {
  431                 hi_eo_server_event_log(Session, HI_EO_SERVER_INVALID_STATCODE, NULL, NULL);
  432             }
  433             ptr++;
  434         }
  435     }
  436 
  437     iRet = HI_OUT_OF_BOUNDS;
  438 
  439     return iRet;
  440 }
  441 
  442 /* Given a string, removes header folding (\r\n followed by linear whitespace)
  443  * and exits when the end of a header is found, defined as \n followed by a
  444  * non-whitespace.  This is especially helpful for HTML.
  445  *  Returns -1 if the header is too long and cant normalise completely */
  446 
  447 int sf_unfold_http_header(HI_SESSION *Session, const uint8_t *inbuf,
  448         uint32_t inbuf_size, uint8_t *outbuf,
  449         uint32_t outbuf_size, uint32_t *output_bytes,
  450         int *folded)
  451 {
  452     int num_spaces = 0;
  453     bool line_folding = false;
  454     const uint8_t *cursor = NULL, *endofinbuf = NULL;
  455     uint8_t *outbuf_ptr = NULL;
  456     uint32_t n = 0;
  457     enum CursorState {CURSOR_STATE_NORMAL, CURSOR_STATE_NEWLINE};
  458     uint8_t state = CURSOR_STATE_NORMAL;
  459     cursor = inbuf;
  460     endofinbuf = inbuf + inbuf_size;
  461     outbuf_ptr = outbuf;
  462 
  463     /* Keep adding chars until we get to the end of the line.  If we get to the
  464      * end of the line and the next line starts with a tab or space, add the space
  465      * to the buffer and keep reading.  If the next line does not start with a
  466      * tab or space, stop reading because that's the end of the header. */
  467     while((cursor < endofinbuf) && (n < outbuf_size))
  468     {
  469         switch (state)
  470         {
  471             case CURSOR_STATE_NORMAL:
  472             if(*cursor == '\r')
  473             {
  474                 if( (cursor + 1 < endofinbuf && *++cursor == '\n'))
  475                 {
  476                     state = CURSOR_STATE_NEWLINE;
  477                 }
  478                 else
  479                 {
  480                     *outbuf_ptr++ = *cursor;
  481                     n++;
  482                 }
  483             }
  484             else if( *cursor  == '\n')
  485             {
  486                 state = CURSOR_STATE_NEWLINE;
  487             }
  488             else
  489             {
  490                 *outbuf_ptr++ = *cursor;
  491                 n++;
  492             }
  493             break;
  494 
  495             case CURSOR_STATE_NEWLINE:
  496             if((*cursor == ' ') || (*cursor == '\t'))
  497             {
  498                 num_spaces++;
  499                 line_folding = true;
  500             }
  501             else if( line_folding )
  502             {
  503                 if(*cursor != '\n')
  504                     state = CURSOR_STATE_NORMAL;
  505                 line_folding = false;
  506                 if(hi_server_is_known_header(cursor, endofinbuf))
  507                 {
  508                     if(hi_eo_generate_event(Session, HI_EO_SERVER_INVALID_HEADER_FOLDING))
  509                     {
  510                         hi_eo_server_event_log(Session,
  511                                 HI_EO_SERVER_INVALID_HEADER_FOLDING, NULL, NULL);
  512                     }
  513                 }
  514                 *outbuf_ptr++ = *cursor;
  515                 n++;
  516             }
  517             else if((*cursor == 0x0b) || (*cursor == 0x0c))
  518             {
  519                 if(hi_eo_generate_event(Session, HI_EO_SERVER_INVALID_HEADER_FOLDING))
  520                 {
  521                     hi_eo_server_event_log(Session,
  522                             HI_EO_SERVER_INVALID_HEADER_FOLDING, NULL, NULL);
  523                 }
  524                goto exit_loop;
  525             }
  526             else
  527                 goto exit_loop;
  528             break;
  529 
  530         }
  531         cursor++;
  532     }
  533 exit_loop:
  534 
  535     if(n < outbuf_size)
  536         *outbuf_ptr = '\0';
  537 
  538     *output_bytes = outbuf_ptr - outbuf;
  539     if(folded)
  540         *folded = num_spaces;
  541     if( n < outbuf_size)
  542         return 0;
  543     return -1;
  544 }
  545 
  546 
  547 /* Grab the argument of "charset=foo" from a Content-Type header */
  548 static inline const u_char *extract_http_content_type_charset(HI_SESSION *Session,
  549         HttpSessionData *hsd, const u_char *p, const u_char *start, const u_char *end )
  550 {
  551     size_t cmplen;
  552     uint8_t unfold_buf[DECODE_BLEN];
  553     uint32_t unfold_size =0;
  554     const char *ptr, *ptr_end;
  555 
  556     if (hsd == NULL)
  557         return p;
  558 
  559     /* Don't trim spaces so p is set to end of header */
  560     sf_unfold_http_header(Session, p, end-p, unfold_buf,
  561               sizeof(unfold_buf), &unfold_size, 0);
  562     if (!unfold_size)
  563     {
  564         set_decode_utf_state_charset(&(hsd->utf_state), CHARSET_DEFAULT);
  565         return p;
  566     }
  567     p += unfold_size;
  568 
  569     ptr = (const char *)unfold_buf;
  570     ptr_end = (const char *)(ptr + strlen((const char *)unfold_buf));
  571 
  572     ptr = SnortStrcasestr(ptr, (int)(ptr_end - ptr), "text");
  573     if (!ptr)
  574     {
  575         set_decode_utf_state_charset(&(hsd->utf_state), CHARSET_DEFAULT);
  576         return p;
  577     }
  578 
  579     ptr = SnortStrcasestr(ptr, (int)(ptr_end - ptr), "utf-");
  580     if (!ptr)
  581     {
  582         set_decode_utf_state_charset(&(hsd->utf_state), CHARSET_UNKNOWN);
  583         return p;
  584     }
  585     ptr += 4; /* length of "utf-" */
  586     cmplen = ptr_end - ptr;
  587 
  588     if ((cmplen > 0) && (*ptr == '8'))
  589     {
  590         set_decode_utf_state_charset(&(hsd->utf_state), CHARSET_DEFAULT);
  591     }
  592     else if ((cmplen > 0) && (*ptr == '7'))
  593     {
  594         set_decode_utf_state_charset(&(hsd->utf_state), CHARSET_UTF7);
  595         if(hi_eo_generate_event(Session, HI_EO_SERVER_UTF7))
  596             hi_eo_server_event_log(Session, HI_EO_SERVER_UTF7, NULL, NULL);
  597     }
  598     else if (cmplen >= 4)
  599     {
  600         if ( !strncasecmp(ptr, "16le", 4) )
  601             set_decode_utf_state_charset(&(hsd->utf_state), CHARSET_UTF16LE);
  602         else if ( !strncasecmp(ptr, "16be", 4) )
  603             set_decode_utf_state_charset(&(hsd->utf_state), CHARSET_UTF16BE);
  604         else if ( !strncasecmp(ptr, "32le", 4) )
  605             set_decode_utf_state_charset(&(hsd->utf_state), CHARSET_UTF32LE);
  606         else if ( !strncasecmp(ptr, "32be", 4) )
  607             set_decode_utf_state_charset(&(hsd->utf_state), CHARSET_UTF32BE);
  608         else
  609             set_decode_utf_state_charset(&(hsd->utf_state), CHARSET_UNKNOWN);
  610     }
  611     else
  612         set_decode_utf_state_charset(&(hsd->utf_state), CHARSET_UNKNOWN);
  613 
  614     return p;
  615 }
  616 
  617 static inline const u_char *extract_http_content_encoding(HTTPINSPECT_CONF *ServerConf,
  618         const u_char *p, const u_char *start, const u_char *end, HEADER_PTR *header_ptr,
  619         HEADER_FIELD_PTR *header_field_ptr,HI_SESSION *Session)
  620 {
  621     const u_char *crlf;
  622     int space_present = 0;
  623     if (header_ptr->content_encoding.cont_encoding_start)
  624     {
  625         if(hi_eo_generate_event(Session, HI_EO_SERVER_MULTIPLE_CONTENT_ENCODING))
  626         {
  627             hi_eo_server_event_log(Session, HI_EO_SERVER_MULTIPLE_CONTENT_ENCODING, NULL, NULL);
  628         }
  629 
  630         header_ptr->header.uri_end = p;
  631         header_ptr->content_encoding.compress_fmt = 0;
  632         return p;
  633     }
  634     else
  635     {
  636         header_field_ptr->content_encoding = &header_ptr->content_encoding;
  637         header_field_ptr->content_encoding->cont_encoding_start =
  638             header_field_ptr->content_encoding->cont_encoding_end = NULL;
  639         header_field_ptr->content_encoding->compress_fmt = 0;
  640         p = p + HTTPRESP_HEADER_LENGTH__CONTENT_ENCODING;
  641     }
  642     CheckSkipAlertCharsBeforeColon(Session, start, end, &p);
  643     if(hi_util_in_bounds(start, end, p) && *p == ':')
  644     {
  645         p++;
  646         CheckSkipAlertMultipleColon(Session, start, end, &p, HI_SI_SERVER_MODE);
  647 
  648         if (  hi_util_in_bounds(start, end, p) )
  649         {
  650             if ( ServerConf->profile == HI_APACHE || ServerConf->profile == HI_ALL)
  651             {
  652                 SkipWhiteSpace(start,end,&p);
  653             }
  654             else
  655             {
  656                 SkipBlankAndNewLine(start,end,&p);
  657             }
  658             if( hi_util_in_bounds(start, end, p))
  659             {
  660                 if ( *p == '\n' )
  661                 {
  662                     while(hi_util_in_bounds(start, end, p))
  663                     {
  664                         if ( *p == '\n')
  665                         {
  666                             p++;
  667                             while( hi_util_in_bounds(start, end, p) && ( *p == ' ' || *p == '\t'))
  668                             {
  669                                 space_present = 1;
  670                                 p++;
  671                             }
  672                             if ( space_present )
  673                             {
  674                                 if ( isalpha((int)*p))
  675                                     break;
  676                                 else if(isspace((int)*p) && (ServerConf->profile == HI_APACHE || ServerConf->profile == HI_ALL) )
  677                                 {
  678                                     SkipWhiteSpace(start,end,&p);
  679                                 }
  680                                 else
  681                                     return p;
  682                             }
  683                             else
  684                                 return p;
  685                         }
  686                         else
  687                             break;
  688                     }
  689                 }
  690                 if(isalpha((int)*p))
  691                 {
  692                     header_field_ptr->content_encoding->cont_encoding_start = p;
  693                     while(hi_util_in_bounds(start, end, p) && *p!='\n' )
  694                     {
  695                         if(IsHeaderFieldName(p, end, HTTPRESP_HEADER_NAME__GZIP, HTTPRESP_HEADER_LENGTH__GZIP) ||
  696                                 IsHeaderFieldName(p, end, HTTPRESP_HEADER_NAME__XGZIP, HTTPRESP_HEADER_LENGTH__XGZIP))
  697                         {
  698                             if (header_ptr->content_encoding.compress_fmt)
  699                             {
  700                                  if(hi_eo_generate_event(Session, HI_EO_SERVER_MULTIPLE_CONTENT_ENCODING))
  701                                  {
  702                                      hi_eo_server_event_log(Session, HI_EO_SERVER_MULTIPLE_CONTENT_ENCODING, NULL, NULL);
  703                                  }
  704                             }
  705                             header_field_ptr->content_encoding->compress_fmt |= HTTP_RESP_COMPRESS_TYPE__GZIP;
  706                             p = p + HTTPRESP_HEADER_LENGTH__GZIP;
  707                             continue;
  708                         }
  709                         else if(IsHeaderFieldName(p, end, HTTPRESP_HEADER_NAME__DEFLATE, HTTPRESP_HEADER_LENGTH__DEFLATE))
  710                         {
  711                             if (header_ptr->content_encoding.compress_fmt)
  712                             {
  713                                 if(hi_eo_generate_event(Session, HI_EO_SERVER_MULTIPLE_CONTENT_ENCODING))
  714                                 {
  715                                     hi_eo_server_event_log(Session, HI_EO_SERVER_MULTIPLE_CONTENT_ENCODING, NULL, NULL);
  716                                 }
  717                             }
  718                             header_field_ptr->content_encoding->compress_fmt |= HTTP_RESP_COMPRESS_TYPE__DEFLATE;
  719                             p = p + HTTPRESP_HEADER_LENGTH__DEFLATE;
  720                             continue;
  721                         }
  722                         else
  723                             p++;
  724                     }
  725 
  726                     /*crlf = (u_char *)SnortStrnStr((const char *)p, end - p, "\n");
  727                     if(crlf)
  728                     {
  729                         p = crlf;
  730                     }
  731                     else
  732                     {
  733                         header_ptr->header.uri_end = end ;
  734                         return end;
  735                     }*/
  736                 }
  737                 else
  738                     return p;
  739             }
  740         }
  741     }
  742     else
  743     {
  744         if(hi_util_in_bounds(start, end, p))
  745         {
  746             crlf = (u_char *)SnortStrnStr((const char *)p, end - p, "\n");
  747             if(crlf)
  748             {
  749                 p = crlf;
  750             }
  751             else
  752             {
  753                 header_ptr->header.uri_end = end ;
  754                 return end;
  755             }
  756         }
  757     }
  758     if(!p || !hi_util_in_bounds(start, end, p))
  759         p = end;
  760 
  761     return p;
  762 }
  763 
  764 /*
  765  * extract_http_content_range() will extract required data from content-range
  766  * field. Focus is for, when the units is "bytes".
  767  *  The possible syntax as follows,
  768  *    content-range: <units> <start_pos>-<end_pos>/<total_len>
  769  *    content-range: <units> * /<total_len>
  770  *    content-range: <units> <start_pos>-<end_pos>/ *
  771  */
  772 static const u_char *extract_http_content_range(HI_SESSION *Session,
  773              const u_char *p, const u_char *start, const u_char *end,
  774              HEADER_PTR *header_ptr)
  775 {
  776     u_char *crlf = NULL;
  777     const u_char *unit_start = NULL;
  778     int is_byte_range = false;
  779 
  780     SkipBlankSpace(start,end,&p);
  781     if (hi_util_in_bounds(start, end, p) && *p == ':')
  782     {
  783         p++;
  784         CheckSkipAlertMultipleColon(Session, start, end, &p, HI_SI_SERVER_MODE);
  785         while (hi_util_in_bounds(start, end, p))
  786         {
  787             if ((*p == ' ') || (*p == '\t'))
  788             {
  789                 p++;
  790                 break;
  791             }
  792             p++;
  793         }
  794         if (hi_util_in_bounds(start, end, p))
  795         {
  796             /* extract unit */
  797             unit_start = p;
  798             while (hi_util_in_bounds(start, end, p) && ( *p != ' '))
  799             {
  800                 p++;
  801             }
  802 
  803             if (*p != ' ')
  804             {
  805                 if (hi_eo_generate_event(Session, HI_EO_SERVER_INVALID_CONTENT_RANGE_UNIT_FMT))
  806                 {
  807                     hi_eo_server_event_log(Session, HI_EO_SERVER_INVALID_CONTENT_RANGE_UNIT_FMT, NULL, NULL);
  808                 }
  809                 header_ptr->range_flag = RANGE_WITH_RESP_ERROR;
  810                 return end;
  811             }
  812 
  813             /* Set flag, when unit is bytes. Based on unit, flow will change */
  814             if (!strncasecmp((const char *)unit_start, RANGE_UNIT_BYTE, 5))
  815             {
  816                 is_byte_range = true;
  817             }
  818             else
  819             {
  820                 is_byte_range = false;
  821             }
  822             p++;
  823 
  824             if (hi_util_in_bounds(start, end, p))
  825             {
  826                 if (is_byte_range == true)
  827                 {
  828                     if (isdigit((int)*p))
  829                     {
  830                         /*if start with digit, then expectation is 
  831                           "<start_pos>-<end_pos>/<total_len>" or "<start_pos>-<end_pos>/ *"
  832                           There is no whitespace between / and * To make it comment added the space
  833                           pattern other than above mentioned format will flag as error */
  834                         uint64_t start_range = 0;
  835                         uint64_t end_range = 0;
  836                         uint64_t len = 0;
  837                         const u_char *start_ptr = NULL;
  838                         const u_char *end_ptr = NULL;
  839                         const u_char *len_ptr = NULL;
  840                         const u_char *ret_ptr = NULL;
  841                         int is_valid_range = false;
  842                         int delim_1 = false;
  843                         int delim_2 = false;
  844                         int assign = false;
  845 
  846                         start_ptr = p;
  847                         p++;
  848                         while (hi_util_in_bounds(start, end, p))
  849                         {
  850                             if (!isdigit((int)*p))
  851                             {
  852                                 if (*p == '-')
  853                                 {
  854                                     if ((delim_2 == true) || (delim_1 == true))
  855                                     {
  856                                         break;
  857                                     }
  858                                     delim_1 = true;
  859                                     assign = true;
  860                                     p++;
  861                                     continue;
  862                                 } 
  863                                 else if (*p == '/')
  864                                 {
  865                                     if ((delim_1 == false) || (delim_2 == true))
  866                                     {
  867                                         break;
  868                                     }
  869                                     delim_2 = true;
  870                                     assign = true;
  871                                     p++;
  872                                     continue;
  873                                 }
  874                                 else if ((*p == '*') || (*p == '\r') || (*p == '\n'))
  875                                 {
  876                                     if ((delim_1 == false) || (delim_2 == false))
  877                                     {
  878                                         break;
  879                                     }
  880                                     is_valid_range = true;
  881                                     break;
  882                                 }
  883                                 break;
  884                             } 
  885 
  886                             /* Here digit only come */
  887                             if (assign == true)
  888                             {
  889                                 if ((delim_2 == false) && (delim_1 == true))
  890                                 {
  891                                     end_ptr = p;
  892                                 }
  893                                 else if ((delim_1 == true) && (delim_2 == true))
  894                                 {
  895                                     len_ptr = p;
  896                                 }
  897                                 else
  898                                 {
  899                                     assign = false;
  900                                     break;
  901                                 }
  902                                 assign = false;
  903                             }
  904                             p++;       
  905                         }
  906 
  907                         if (is_valid_range == true)
  908                         {
  909                             /* Now check total_len, * means set the flag accordingly
  910                                or convert str to value and flag as full content
  911                                when differnce between start_pos and end_pos and sum with 1
  912                                equals to total_len, otherwise partial flag set */
  913                             if (*p == '*')
  914                             {
  915                                 header_ptr->range_flag = RANGE_WITH_RESP_UNKNOWN_CONTENT_SIZE;
  916                             }
  917                             else if ((start_ptr) && (end_ptr) && (len_ptr))
  918                             {
  919                                 int error = false;
  920 
  921                                 start_range = (uint64_t)SnortStrtol((char *)start_ptr, (char**)&ret_ptr, 10);
  922                                 if ((errno == ERANGE) || (start_ptr == ret_ptr) || (start_range > 0xFFFFFFFF))
  923                                 {
  924                                     error = true;
  925                                 }
  926 
  927                                 ret_ptr = NULL;
  928                                 end_range = (uint64_t)SnortStrtol((char *)end_ptr, (char**)&ret_ptr, 10);
  929                                 if ((errno == ERANGE) || (end_ptr == ret_ptr) || (end_range > 0xFFFFFFFF))
  930                                 {
  931                                     error = true;
  932                                 }
  933 
  934                                 ret_ptr = NULL;
  935                                 len = (uint64_t)SnortStrtol((char *)len_ptr, (char**)&ret_ptr, 10);
  936                                 if ((errno == ERANGE) || (len_ptr == ret_ptr) || (len > 0xFFFFFFFF))
  937                                 {
  938                                     error = true;
  939                                 }
  940 
  941                                 if (error == false)
  942                                 {
  943                                     if (((end_range - start_range) + 1) == len)
  944                                     {
  945                                         header_ptr->range_flag = RANGE_WITH_RESP_FULL_CONTENT;
  946                                     }
  947                                     else
  948                                     {
  949                                         header_ptr->range_flag = RANGE_WITH_RESP_PARTIAL_CONTENT;
  950                                     }
  951                                 }
  952                                 else
  953                                 {
  954                                     header_ptr->range_flag = RANGE_WITH_RESP_ERROR;
  955                                 }
  956                             }
  957                             else
  958                             { 
  959                                 header_ptr->range_flag = RANGE_WITH_RESP_ERROR;
  960                             }
  961 
  962                             crlf = (u_char *)SnortStrnStr((const char *)p, end - p, "\n");
  963                             if (crlf)
  964                             {
  965                                 return p;
  966                             }
  967                             else
  968                             {
  969                                 header_ptr->header.uri_end = end;
  970                                 return end;
  971                             }
  972                         }
  973                     }
  974                     else if (*p == '*')
  975                     {
  976                         /* To check pattern, "* /<total_len>" and set flag accordingly */
  977                         header_ptr->range_flag = RANGE_WITH_UNKNOWN_CONTENT_RANGE;
  978                         p++;
  979                         if (hi_util_in_bounds(start, end, p))
  980                         {
  981                             if (*p == '/')
  982                             {
  983                                 p++;
  984                                 if (hi_util_in_bounds(start, end, p))
  985                                 {
  986                                     if (isdigit((int)*p))
  987                                     {
  988                                         p++;
  989                                         while (hi_util_in_bounds(start, end, p))
  990                                         {
  991                                             if (isdigit((int)*p))
  992                                             {
  993                                                 p++;
  994                                                 continue;
  995                                             }
  996                                             else if ((*p == '\r') || (*p == '\n')) /* digit followed by \r or \n */
  997                                             {
  998                                                 crlf = (u_char *)SnortStrnStr((const char *)p, end - p, "\n");
  999                                                 if (crlf)
 1000                                                 {
 1001                                                     return p;
 1002                                                 }
 1003                                                 else
 1004                                                 {
 1005                                                     header_ptr->header.uri_end = end;
 1006                                                     return end;
 1007                                                 }
 1008                                             }
 1009                                         }
 1010                                     }
 1011                                 }
 1012                             }
 1013                         }
 1014                     }
 1015                     header_ptr->range_flag = RANGE_WITH_RESP_ERROR;
 1016                     crlf = (u_char *)SnortStrnStr((const char *)p, end - p, "\n");
 1017                     if (crlf)
 1018                     {
 1019                         p = crlf;
 1020                         return p;
 1021                     }
 1022                     else
 1023                     {
 1024                         header_ptr->header.uri_end = end;
 1025                         return end;
 1026                     }
 1027                 }
 1028                 else
 1029                 {
 1030                     /* other than byte range is out of scope for snort */
 1031                     while (hi_util_in_bounds(start, end, p))
 1032                     {
 1033                         if ((*p == '\r') || (*p == '\n'))
 1034                         {
 1035                             header_ptr->range_flag = RANGE_WITH_RESP_NON_BYTE;
 1036                             crlf = (u_char *)SnortStrnStr((const char *)p, end - p, "\n");
 1037                             if (crlf)
 1038                             {
 1039                                 p = crlf;
 1040                                 return p;
 1041                             }
 1042                             else
 1043                             {
 1044                                 header_ptr->header.uri_end = end;
 1045                                 return end;
 1046                             }
 1047                         }
 1048                         p++;
 1049                     }
 1050                 } 
 1051             }
 1052         }
 1053     }
 1054     header_ptr->range_flag = RANGE_WITH_RESP_ERROR;
 1055     crlf = (u_char *)SnortStrnStr((const char *)p, end - p, "\n");
 1056     if (crlf)
 1057     {
 1058         p = crlf;
 1059         return p;
 1060     }
 1061     else
 1062     {
 1063         header_ptr->header.uri_end = end;
 1064         return end;
 1065     }
 1066 }
 1067 
 1068 /* extract_http_accept_ranges will extract and set flag based on bytes unit */ 
 1069 static const u_char *extract_http_accept_ranges(HI_SESSION *Session,
 1070              const u_char *p, const u_char *start, const u_char *end,
 1071              HEADER_PTR *header_ptr, uint16_t *accept_range_flag)
 1072 {
 1073     const u_char *start_ptr = NULL;
 1074     const u_char *end_ptr = NULL;
 1075     u_char *crlf = NULL;
 1076     int len = 0;
 1077 
 1078     *accept_range_flag = ACCEPT_RANGE_UNKNOWN;
 1079     SkipBlankSpace(start,end,&p);
 1080 
 1081     if (hi_util_in_bounds(start, end, p) && (*p == ':'))
 1082     {
 1083         p++;
 1084         CheckSkipAlertMultipleColon(Session, start, end, &p, HI_SI_SERVER_MODE);
 1085         while (hi_util_in_bounds(start, end, p))
 1086         {
 1087             if ((*p == ' ') || (*p == '\t') || (*p == ','))
 1088             {
 1089                 p++;
 1090                 break;
 1091             }
 1092             p++;
 1093         }
 1094 
 1095         if (hi_util_in_bounds(start, end, p))
 1096         {
 1097             start_ptr = p;
 1098             while (hi_util_in_bounds(start, end, p))
 1099             {
 1100                 if ((*p == '\r') || (*p == '\n'))
 1101                 {
 1102                     end_ptr = (p - 1);
 1103                     break;
 1104                 }
 1105                 p++;
 1106             }
 1107 
 1108             if (start_ptr && end_ptr)
 1109             {
 1110                 len = end_ptr - start_ptr;
 1111                 if ((len >= 5) && (SnortStrcasestr((const char *)start, len, "bytes")))
 1112                 {
 1113                     *accept_range_flag = ACCEPT_RANGE_BYTES;
 1114                 }
 1115                 else if ((len >= 4) && (!strncasecmp((const char *)start, "none", 4)))
 1116                 {
 1117                     *accept_range_flag = ACCEPT_RANGE_NONE;
 1118                 }
 1119                 else
 1120                 {
 1121                     *accept_range_flag = ACCEPT_RANGE_OTHER;
 1122                 }
 1123             }
 1124         }
 1125     }    
 1126 
 1127     crlf = (u_char *)SnortStrnStr((const char *)p, end - p, "\n");
 1128     if (crlf)
 1129     {
 1130         p = crlf;
 1131         return p;
 1132     }
 1133     else
 1134     {
 1135         header_ptr->header.uri_end = end;
 1136         return end;
 1137     }
 1138 }
 1139 
 1140 const u_char *extract_http_transfer_encoding(HI_SESSION *Session, HttpSessionData *hsd,
 1141      const u_char *p, const u_char *start, const u_char *end,
 1142      HEADER_PTR *header_ptr, int iInspectMode)
 1143 {
 1144     uint8_t unfold_buf[DECODE_BLEN];
 1145     uint32_t unfold_size =0;
 1146     const u_char *start_ptr, *end_ptr, *cur_ptr;
 1147 
 1148 
 1149     SkipBlankSpace(start,end,&p);
 1150 
 1151     if(hi_util_in_bounds(start, end, p) && *p == ':')
 1152     {
 1153         p++;
 1154         CheckSkipAlertMultipleColon(Session, start, end, &p, iInspectMode);
 1155 
 1156         if(hi_util_in_bounds(start, end, p))
 1157             sf_unfold_http_header(Session, p, end-p, unfold_buf,
 1158             sizeof(unfold_buf), &unfold_size, 0);
 1159 
 1160         if(!unfold_size)
 1161         {
 1162             header_ptr->header.uri_end = end;
 1163             return end;
 1164         }
 1165 
 1166         p = p + unfold_size;
 1167 
 1168         start_ptr = unfold_buf;
 1169         cur_ptr = unfold_buf;
 1170         end_ptr = unfold_buf + unfold_size;
 1171         SkipBlankSpace(start_ptr,end_ptr,&cur_ptr);
 1172 
 1173         start_ptr = cur_ptr;
 1174 
 1175         start_ptr = (u_char *)SnortStrcasestr((const char *)start_ptr, (end_ptr - start_ptr), "chunked");
 1176         if (start_ptr)
 1177         {
 1178             if ((iInspectMode == HI_SI_SERVER_MODE) && hsd)
 1179             {
 1180                 hsd->resp_state.last_pkt_chunked = 1;
 1181                 hsd->resp_state.last_pkt_contlen = 0;
 1182             }
 1183             header_ptr->content_len.len = 0 ;
 1184             header_ptr->content_len.cont_len_start = NULL;
 1185             header_ptr->is_chunked = true;
 1186         }
 1187     }
 1188     else
 1189     {
 1190         header_ptr->header.uri_end = end;
 1191         return end;
 1192     }
 1193 
 1194     return p;
 1195 }
 1196 
 1197 #if defined(FEAT_OPEN_APPID)
 1198 static const u_char *extract_http_server_header(HI_SESSION *Session, const u_char *p, const u_char *start,
 1199         const u_char *end, HEADER_PTR  *header_ptr, HEADER_LOCATION *headerLoc)
 1200 {
 1201     int num_spaces = 0;
 1202     uint8_t unfold_buf[DECODE_BLEN];
 1203     uint32_t unfold_size =0;
 1204     const u_char *end_ptr, *cur_ptr;
 1205 
 1206     SkipBlankSpace(start,end,&p);
 1207 
 1208     if(hi_util_in_bounds(start, end, p) && *p == ':')
 1209     {
 1210         p++;
 1211         CheckSkipAlertMultipleColon(Session, start, end, &p, HI_SI_SERVER_MODE);
 1212 
 1213         if(hi_util_in_bounds(start, end, p))
 1214             sf_unfold_http_header(Session, p, end-p, unfold_buf,
 1215         sizeof(unfold_buf), &unfold_size, &num_spaces);
 1216 
 1217         if(!unfold_size)
 1218         {
 1219             header_ptr->header.uri_end = end;
 1220             return end;
 1221         }
 1222 
 1223         p = p + unfold_size;
 1224 
 1225         cur_ptr = unfold_buf;
 1226         end_ptr = unfold_buf + unfold_size;
 1227         SkipBlankSpace(unfold_buf,end_ptr,&cur_ptr);
 1228 
 1229         {
 1230             unsigned field_strlen = (unsigned)(end_ptr - cur_ptr); 
 1231             if (field_strlen)
 1232             {
 1233                 headerLoc->start = (u_char *)strndup((const char *)cur_ptr, field_strlen);
 1234                 if (NULL == headerLoc->start)
 1235                 {
 1236                     /* treat this out-of-memory error as a parse failure */
 1237                     header_ptr->header.uri_end = end;
 1238                     return end;
 1239                 }
 1240                 /* now that we have the memory, fill in len. */
 1241                 headerLoc->len = field_strlen;
 1242             }
 1243         }
 1244     }
 1245     else
 1246     {
 1247         header_ptr->header.uri_end = end;
 1248         return end;
 1249     }
 1250 
 1251     return p;
 1252 
 1253 }
 1254 #endif /* defined(FEAT_OPEN_APPID) */
 1255 
 1256 static inline const u_char *extractHttpRespHeaderFieldValues(HTTPINSPECT_CONF *ServerConf,
 1257         const u_char *p, const u_char *offset, const u_char *start,
 1258         const u_char *end, HEADER_PTR *header_ptr,
 1259         HEADER_FIELD_PTR *header_field_ptr, int parse_cont_encoding, bool parse_trans_encoding,
 1260         HttpSessionData *hsd, HI_SESSION *Session)
 1261 {
 1262     if (((p - offset) == 0) && ((*p == 'S') || (*p == 's')))
 1263     {
 1264         /* Search for 'Cookie' at beginning, starting from current *p */
 1265         if ( ServerConf->enable_cookie &&
 1266                 IsHeaderFieldName(p, end, HTTPRESP_HEADER_NAME__COOKIE,
 1267                     HTTPRESP_HEADER_LENGTH__COOKIE))
 1268         {
 1269             p = extract_http_cookie((p + HTTPRESP_HEADER_LENGTH__COOKIE), end, header_ptr, header_field_ptr);
 1270         }
 1271 #if defined(FEAT_OPEN_APPID)
 1272         else if ((ServerConf->appid_enabled) && (IsHeaderFieldName(p, end, HEADER_NAME__SERVER, HEADER_LENGTH__SERVER)))
 1273         {
 1274             p = p + HEADER_LENGTH__SERVER;
 1275             p = extract_http_server_header(Session, p, start, end, header_ptr, &header_ptr->server);
 1276         }
 1277 #endif /* defined(FEAT_OPEN_APPID) */
 1278     }
 1279     else if (((p - offset) == 0) && ((*p == 'C') || (*p == 'c')))
 1280     {
 1281         if ( IsHeaderFieldName(p, end, HTTPRESP_HEADER_NAME__CONTENT_TYPE,
 1282                                HTTPRESP_HEADER_LENGTH__CONTENT_TYPE) && ServerConf->normalize_utf)
 1283         {
 1284 #if defined(FEAT_OPEN_APPID)
 1285             const u_char *ptr;
 1286             ptr = p + HTTPRESP_HEADER_LENGTH__CONTENT_TYPE;
 1287 #endif /* defined(FEAT_OPEN_APPID) */
 1288             p = extract_http_content_type_charset(Session, hsd, p, start, end);
 1289 #if defined(FEAT_OPEN_APPID)
 1290             header_ptr->contentType.start = ptr;
 1291             SkipBlankColon(ptr, p, &header_ptr->contentType.start);
 1292             header_ptr->contentType.len = p - header_ptr->contentType.start;
 1293 #endif /* defined(FEAT_OPEN_APPID) */
 1294         }
 1295 
 1296         else if ( IsHeaderFieldName(p, end, HTTPRESP_HEADER_NAME__CONTENT_ENCODING,
 1297                     HTTPRESP_HEADER_LENGTH__CONTENT_ENCODING) && ServerConf->extract_gzip &&
 1298                     parse_cont_encoding)
 1299         {
 1300             p = extract_http_content_encoding(ServerConf, p, start, end, header_ptr, header_field_ptr,Session);
 1301         }
 1302         else if ( IsHeaderFieldName(p, end, HTTPRESP_HEADER_NAME__CONTENT_LENGTH,
 1303                 HTTPRESP_HEADER_LENGTH__CONTENT_LENGTH) )
 1304         {
 1305             if(hsd && !hsd->resp_state.last_pkt_chunked)
 1306                 p = extract_http_content_length(Session, ServerConf, p, start, end, header_ptr, header_field_ptr, HI_SI_SERVER_MODE );
 1307         }
 1308         else if (IsHeaderFieldName(p, end, HTTPRESP_HEADER_NAME__CONTENT_RANGE, HTTPRESP_HEADER_LENGTH__CONTENT_RANGE))
 1309         {
 1310             p = p + HTTPRESP_HEADER_LENGTH__CONTENT_RANGE;
 1311             p = extract_http_content_range(Session, p, start, end, header_ptr);
 1312         }
 1313     }
 1314     else if (((p - offset) == 0) && ((*p == 'T') || (*p == 't')))
 1315     {
 1316         if ( IsHeaderFieldName(p, end, HTTPRESP_HEADER_NAME__TRANSFER_ENCODING,
 1317                                HTTPRESP_HEADER_LENGTH__TRANSFER_ENCODING) && parse_trans_encoding )
 1318         {
 1319             p = p + HTTPRESP_HEADER_LENGTH__TRANSFER_ENCODING;
 1320             p = extract_http_transfer_encoding(Session, hsd, p, start, end, header_ptr, HI_SI_SERVER_MODE);
 1321         }
 1322     }
 1323     else if (((p - offset) == 0) && ((*p == 'A') || (*p == 'a')))
 1324     {
 1325         if (IsHeaderFieldName(p, end, HTTPRESP_HEADER_NAME__ACCEPT_RANGES, 
 1326                                HTTPRESP_HEADER_LENGTH__ACCEPT_RANGES))
 1327         {
 1328             uint16_t accept_range_flag = 0;
 1329             p = p + HTTPRESP_HEADER_LENGTH__ACCEPT_RANGES;
 1330             p = extract_http_accept_ranges(Session, p, start, end, header_ptr, &accept_range_flag);
 1331             Session->server.response.accept_range_flag = accept_range_flag;
 1332         }
 1333     }
 1334 #if defined(FEAT_OPEN_APPID)
 1335     else if(((p - offset) == 0) && ((*p == 'V') || (*p == 'v')))
 1336     {
 1337         if((ServerConf->appid_enabled) && (IsHeaderFieldName(p, end, HEADER_NAME__VIA, HEADER_LENGTH__VIA)))
 1338         {
 1339             p = p + HEADER_LENGTH__VIA;
 1340             p = extract_http_server_header(Session, p, start, end, header_ptr, &header_ptr->via);
 1341         }
 1342     }
 1343     else if(((p - offset) == 0) && ((*p == 'X') || (*p == 'x')))
 1344     {
 1345         if((ServerConf->appid_enabled) && (IsHeaderFieldName(p, end, HEADER_NAME__X_WORKING_WITH, HEADER_LENGTH__X_WORKING_WITH)))
 1346         {
 1347             p = p + HEADER_LENGTH__X_WORKING_WITH;
 1348             p = extract_http_server_header(Session, p, start, end, header_ptr, &header_ptr->xWorkingWith);
 1349         }
 1350     }
 1351 #endif /* defined(FEAT_OPEN_APPID) */
 1352     return p;
 1353 }
 1354 
 1355 int hi_server_is_known_header(
 1356     const u_char *p, const u_char *end)
 1357 {
 1358 
 1359     if ((*p == 'C') || (*p == 'c'))
 1360     {
 1361         if (IsHeaderFieldName(p, end, HTTPRESP_HEADER_NAME__CONTENT_TYPE,
 1362                                HTTPRESP_HEADER_LENGTH__CONTENT_TYPE) ||
 1363            IsHeaderFieldName(p, end, HTTPRESP_HEADER_NAME__CONTENT_ENCODING,
 1364                     HTTPRESP_HEADER_LENGTH__CONTENT_ENCODING) ||
 1365            IsHeaderFieldName(p, end, HTTPRESP_HEADER_NAME__CONTENT_LENGTH,
 1366                 HTTPRESP_HEADER_LENGTH__CONTENT_LENGTH))
 1367         {
 1368             return 1;
 1369         }
 1370     }
 1371 
 1372     if ((*p == 'T') || (*p == 't'))
 1373     {
 1374         if (IsHeaderFieldName(p, end, HTTPRESP_HEADER_NAME__TRANSFER_ENCODING,
 1375                                HTTPRESP_HEADER_LENGTH__TRANSFER_ENCODING))
 1376         {
 1377             return 1;
 1378         }
 1379     }
 1380 
 1381     return 0;
 1382 }
 1383 
 1384 static inline const u_char *hi_server_extract_header(
 1385         HI_SESSION *Session, HTTPINSPECT_CONF *ServerConf,
 1386             HEADER_PTR *header_ptr, const u_char *start,
 1387             const u_char *end, int parse_cont_encoding,
 1388             bool parse_trans_encoding, HttpSessionData *hsd)
 1389 {
 1390     const u_char *p;
 1391     const u_char *offset;
 1392     HEADER_FIELD_PTR header_field_ptr ;
 1393     bool newline = false;
 1394 
 1395     if(!start || !end)
 1396         return NULL;
 1397 
 1398     p = start;
 1399 
 1400     offset = (u_char*)p;
 1401 
 1402     header_ptr->header.uri = p;
 1403     header_ptr->header.uri_end = end;
 1404     header_ptr->content_encoding.compress_fmt = 0;
 1405     header_ptr->content_len.len = 0;
 1406     header_ptr->is_chunked = false;
 1407 
 1408     while (hi_util_in_bounds(start, end, p))
 1409     {
 1410         if(*p == '\n')
 1411         {
 1412             newline = true;
 1413             p++;
 1414 
 1415             offset = (u_char*)p;
 1416 
 1417             if (!hi_util_in_bounds(start, end, p))
 1418             {
 1419                 header_ptr->header.uri_end = p;
 1420                 return p;
 1421             }
 1422 
 1423             if (*p < 0x0E)
 1424             {
 1425                 if(*p == '\r')
 1426                 {
 1427                     p++;
 1428 
 1429                     if(hi_util_in_bounds(start, end, p) && (*p == '\n'))
 1430                     {
 1431                         p++;
 1432                         header_ptr->header.uri_end = p;
 1433                         hsd->resp_state.eoh_found = true;
 1434                         return p;
 1435                     }
 1436                 }
 1437                 else if(*p == '\n')
 1438                 {
 1439                     p++;
 1440                     header_ptr->header.uri_end = p;
 1441                     hsd->resp_state.eoh_found = true;
 1442                     return p;
 1443                 }
 1444             }
 1445             else if ( (p = extractHttpRespHeaderFieldValues(ServerConf, p, offset,
 1446                             start, end, header_ptr, &header_field_ptr,
 1447                             parse_cont_encoding, parse_trans_encoding, hsd, Session)) == end)
 1448             {
 1449                 return end;
 1450             }
 1451 
 1452         }
 1453         else if( (p == header_ptr->header.uri) &&
 1454                 (p = extractHttpRespHeaderFieldValues(ServerConf, p, offset,
 1455                           start, end, header_ptr, &header_field_ptr,
 1456                           parse_cont_encoding, parse_trans_encoding, hsd, Session)) == end)
 1457         {
 1458             return end;
 1459         }
 1460         if ( *p == '\n')
 1461         {
 1462             newline = true;
 1463             continue;
 1464         }
 1465         if (newline && (*p == '\t' || *p == ' '))
 1466         {
 1467             while(*p == '\t' ||  *p == ' ')
 1468                 p++;
 1469 
 1470             if (hi_util_in_bounds(start, end, p) &&
 1471                     hi_server_is_known_header(p, end))
 1472             {
 1473                 if(hi_eo_generate_event(Session, HI_EO_SERVER_INVALID_HEADER_FOLDING))
 1474                 {
 1475                     hi_eo_server_event_log(Session, HI_EO_SERVER_INVALID_HEADER_FOLDING,
 1476                             NULL, NULL);
 1477                 }
 1478                 newline = false;
 1479             }
 1480         }
 1481         else
 1482         {
 1483             newline = false;
 1484             p++;
 1485         }
 1486     }
 1487 
 1488     header_ptr->header.uri_end = p;
 1489     return p;
 1490 }
 1491 
 1492 static inline int hi_server_extract_body(
 1493                         HI_SESSION *Session, HttpSessionData *sd,
 1494                         const u_char *ptr, const u_char *end, URI_PTR *result)
 1495 {
 1496     HTTPINSPECT_CONF *ServerConf;
 1497     const u_char *start = ptr;
 1498     int iRet = HI_SUCCESS;
 1499     const u_char *post_end = end;
 1500     uint32_t updated_chunk_remainder = 0;
 1501     uint32_t chunk_read = 0;
 1502     int64_t bytes_to_read = 0;
 1503     ServerConf = Session->server_conf;
 1504 
 1505     switch(ServerConf->server_extract_size)
 1506     {
 1507         case -1:
 1508             result->uri = result->uri_end = NULL;
 1509             return iRet;
 1510         case 0:
 1511             break;
 1512         default:
 1513             if(sd->resp_state.data_extracted < ServerConf->server_extract_size)
 1514             {
 1515                 bytes_to_read = ServerConf->server_extract_size - sd->resp_state.data_extracted;
 1516                 if((end-ptr) > bytes_to_read )
 1517                 {
 1518                     end = ptr + bytes_to_read;
 1519                 }
 1520                 else
 1521                     bytes_to_read = (end-ptr);
 1522                 sd->resp_state.data_extracted += (int)bytes_to_read;
 1523             }
 1524             else
 1525             {
 1526                 result->uri = result->uri_end = NULL;
 1527                 return iRet;
 1528             }
 1529     }
 1530 
 1531 /*    if( ServerConf->server_flow_depth && ((end - ptr) > ServerConf->server_flow_depth) )
 1532     {
 1533         end = ptr + ServerConf->server_flow_depth;
 1534     }*/
 1535 
 1536     if (!(sd->resp_state.last_pkt_contlen))
 1537     {
 1538         if( ServerConf->chunk_length || ServerConf->small_chunk_length.size )
 1539         {
 1540             if (sd->resp_state.last_pkt_chunked
 1541                 && CheckChunkEncoding(Session, start, end, &post_end,
 1542                                       (u_char *)HttpDecodeBuf.data, sizeof(HttpDecodeBuf.data),
 1543                                       sd->resp_state.chunk_remainder, &updated_chunk_remainder, &chunk_read,
 1544                                       sd, HI_SI_SERVER_MODE) == 1)
 1545             {
 1546                 sd->resp_state.chunk_remainder = updated_chunk_remainder;
 1547                 sd->resp_state.last_pkt_chunked = 1;
 1548                 result->uri = (u_char *)HttpDecodeBuf.data;
 1549                 result->uri_end = result->uri + chunk_read;
 1550                 return iRet;
 1551             }
 1552             else
 1553             {
 1554                 if(!(sd->resp_state.last_pkt_chunked) && !simple_response)
 1555                 {
 1556                     if(hi_eo_generate_event(Session, HI_EO_SERVER_NO_CONTLEN))
 1557                     {
 1558                         hi_eo_server_event_log(Session, HI_EO_SERVER_NO_CONTLEN, NULL, NULL);
 1559                     }
 1560                 }
 1561                 else
 1562                     sd->resp_state.last_pkt_chunked = 0;
 1563                 result->uri = start;
 1564                 result->uri_end = end;
 1565             }
 1566         }
 1567         else
 1568         {
 1569             result->uri = start;
 1570             result->uri_end = end;
 1571             return iRet;
 1572         }
 1573     }
 1574 
 1575     result->uri = start;
 1576     result->uri_end = end;
 1577 
 1578     return STAT_END;
 1579 }
 1580 
 1581 static void LogFileDecomp( void *Context, int Event )
 1582 {
 1583     if( Context != NULL )
 1584         if(hi_eo_generate_event((HI_SESSION *)Context, Event))
 1585             hi_eo_server_event_log((HI_SESSION *)Context, Event, NULL, NULL);
 1586 }
 1587 
 1588 static void InitFileDecomp(HttpSessionData *hsd, HI_SESSION *session, void* ssnptr)
 1589 {
 1590     fd_session_p_t fd_session;
 1591 
 1592     if((hsd == NULL) || (session == NULL) || (session->server_conf == NULL) ||
 1593        (session->global_conf == NULL) || (hi_fd_conf.fd_MemPool == NULL) )
 1594         return;
 1595 
 1596     if( (fd_session = File_Decomp_New(ssnptr)) == (fd_session_p_t)NULL )
 1597         return;
 1598 
 1599     hsd->fd_state = fd_session;
 1600     fd_session->Modes = session->server_conf->file_decomp_modes;
 1601 
 1602     fd_session->Alert_Callback = LogFileDecomp;
 1603     fd_session->Alert_Context = session;
 1604 
 1605     if( (session->server_conf->unlimited_decompress) != 0 )
 1606     {
 1607         fd_session->Compr_Depth = 0;
 1608         fd_session->Decompr_Depth = 0;
 1609     }
 1610     else
 1611     {
 1612         fd_session->Compr_Depth = session->global_conf->compr_depth;
 1613         fd_session->Decompr_Depth = session->global_conf->decompr_depth;
 1614     }
 1615 
 1616     (void)File_Decomp_Init( fd_session );
 1617 }
 1618 
 1619 static void SetGzipBuffers(HttpSessionData *hsd, HI_SESSION *session, void* scbPtr)
 1620 {
 1621     if ((hsd != NULL) && (hsd->decomp_state == NULL)
 1622             && (session != NULL) && (session->server_conf != NULL)
 1623             && (session->global_conf != NULL) && session->server_conf->extract_gzip)
 1624     {
 1625         MemBucket *bkt = mempool_alloc(hi_gzip_mempool);
 1626 
 1627         if (bkt != NULL)
 1628         {
 1629             bkt->scbPtr = scbPtr;
 1630             hsd->decomp_state = bkt->data;
 1631             hsd->decomp_state->bkt = bkt;
 1632             if (session->server_conf->unlimited_decompress)
 1633             {
 1634                 hsd->decomp_state->compr_depth = MAX_GZIP_DEPTH;
 1635                 hsd->decomp_state->decompr_depth = MAX_GZIP_DEPTH;
 1636             }
 1637             else
 1638             {
 1639                 hsd->decomp_state->compr_depth = session->global_conf->compr_depth;
 1640                 hsd->decomp_state->decompr_depth = session->global_conf->decompr_depth;
 1641             }
 1642             hsd->decomp_state->inflate_init = 0;
 1643             hsd->decomp_state->stage = HTTP_DECOMP_START;
 1644         }
 1645         else
 1646         {
 1647             mempool_free(hi_gzip_mempool, bkt);
 1648         }
 1649     }
 1650 }
 1651 
 1652 int uncompress_gzip ( HI_SESSION *Session, u_char *dest, int destLen, const u_char *source,
 1653         int sourceLen, HttpSessionData *sd, int *total_bytes_read, int compr_fmt)
 1654 {
 1655     z_streamp streamp;
 1656     int err;
 1657     int iRet = HI_SUCCESS;
 1658     int bytes_read_so_far;
 1659 
 1660     streamp = &sd->decomp_state->d_stream;
 1661 
 1662     /* Are we starting a new packet or continuing on the current one? */
 1663     if (sd->decomp_state->stage == HTTP_DECOMP_START)
 1664     {
 1665         streamp->next_in = (Bytef*)source;
 1666         streamp->avail_in = (uInt)sourceLen;
 1667         if ((uLong)streamp->avail_in != (uLong)sourceLen)
 1668         {
 1669             sd->decomp_state->stage = HTTP_DECOMP_FIN;
 1670             return HI_FATAL_ERR;
 1671         }
 1672         bytes_read_so_far = 0;
 1673     }
 1674     else 
 1675     {
 1676         bytes_read_so_far = streamp->total_out;
 1677     }
 1678 
 1679     streamp->next_out = dest;
 1680     streamp->avail_out = (uInt)destLen;
 1681     if ((uLong)streamp->avail_out != (uLong)destLen)
 1682     {
 1683         return HI_FATAL_ERR;
 1684     }
 1685 
 1686 
 1687     if(!sd->decomp_state->inflate_init)
 1688     {
 1689         sd->decomp_state->inflate_init = 1;
 1690         streamp->zalloc = (alloc_func)0;
 1691         streamp->zfree = (free_func)0;
 1692         if(compr_fmt & HTTP_RESP_COMPRESS_TYPE__DEFLATE)
 1693             err = inflateInit(streamp);
 1694         else
 1695             err = inflateInit2(streamp, GZIP_WBITS);
 1696         if (err != Z_OK)
 1697         {
 1698             return HI_FATAL_ERR;
 1699         }
 1700     }
 1701     else if (sd->decomp_state->stage != HTTP_DECOMP_MID)
 1702     {
 1703         streamp->total_in = 0;
 1704         streamp->total_out =0;
 1705     }
 1706 
 1707     err = inflate(streamp, Z_SYNC_FLUSH);
 1708     if ((!sd->decomp_state->deflate_initialized)
 1709             && (err == Z_DATA_ERROR)
 1710             && (compr_fmt & HTTP_RESP_COMPRESS_TYPE__DEFLATE))
 1711     {
 1712         inflateEnd(streamp);
 1713         err = inflateInit2(streamp,DEFLATE_RAW_WBITS);
 1714         if (err != Z_OK)
 1715         {
 1716             return HI_FATAL_ERR;
 1717         }
 1718 
 1719         sd->decomp_state->deflate_initialized = true;
 1720 
 1721         streamp->next_in = (Bytef*)source;
 1722         streamp->avail_in = (uInt)sourceLen;
 1723 
 1724         err = inflate(streamp, Z_SYNC_FLUSH);
 1725     }
 1726 
 1727     if ((err != Z_STREAM_END) && (err !=Z_OK))
 1728     {
 1729 
 1730         /* If some of the compressed data is decompressed we need to provide that for detection */
 1731         if (( streamp->total_out > 0) && (err != Z_DATA_ERROR))
 1732         {
 1733             *total_bytes_read = streamp->total_out;
 1734             iRet = HI_NONFATAL_ERR;
 1735         }
 1736         else
 1737             iRet = HI_FATAL_ERR;
 1738         inflateEnd(streamp);
 1739         sd->decomp_state->stage = HTTP_DECOMP_FIN;
 1740         return iRet;
 1741     }
 1742     *total_bytes_read = streamp->total_out - bytes_read_so_far;
 1743 
 1744     /* Check if we need to decompress more */
 1745     if(err == Z_STREAM_END)
 1746     {
 1747         if(streamp->avail_in != 0 )
 1748         {
 1749             /* We have a case here where  uncompression returned END, yet data is available for compression */
 1750             if(streamp->total_out > 0)
 1751             {
 1752                 //Partial decompression case, log an alert
 1753                 if(hi_eo_generate_event(Session, HI_EO_SERVER_PARTIAL_DECOMPRESSION_FAIL))
 1754                 {
 1755                     hi_eo_server_event_log(Session, HI_EO_SERVER_PARTIAL_DECOMPRESSION_FAIL, NULL, NULL);
 1756                 }
 1757             }
 1758             else
 1759             {
 1760                 //Proceed with non-fatal error and generate decompression failed event
 1761                 iRet = HI_NONFATAL_ERR;
 1762             }
 1763         }
 1764         sd->decomp_state->stage = HTTP_DECOMP_FIN;
 1765         return iRet;
 1766     }
 1767     else if (sd->decomp_state->d_stream.total_in < sourceLen && *total_bytes_read != 0)
 1768         sd->decomp_state->stage = HTTP_DECOMP_MID;
 1769     else
 1770         sd->decomp_state->stage = HTTP_DECOMP_FIN;
 1771     return HI_SUCCESS;
 1772 }
 1773 
 1774 static inline int hi_server_decompress(HI_SESSION *Session, HttpSessionData *sd, const u_char *ptr,
 1775         const u_char *end, URI_PTR *result, bool start_of_body)
 1776 {
 1777     const u_char *start = ptr;
 1778     int rawbuf_size = end - ptr;
 1779     int iRet = HI_SUCCESS;
 1780     int zRet = HI_SUCCESS;
 1781     int compr_depth, decompr_depth;
 1782     int compr_bytes_read, decompr_bytes_read;
 1783     int compr_avail, decompr_avail;
 1784     int total_bytes_read = 0;
 1785     static uint32_t updated_chunk_remainder = 0;
 1786     static uint32_t chunk_read = 0;
 1787     uint32_t saved_chunk_size = 0;
 1788 
 1789     compr_depth = sd->decomp_state->compr_depth;
 1790     decompr_depth = sd->decomp_state->decompr_depth;
 1791     compr_bytes_read = sd->decomp_state->compr_bytes_read;
 1792     decompr_bytes_read = sd->decomp_state->decompr_bytes_read;
 1793     saved_chunk_size = sd->resp_state.chunk_remainder;
 1794 
 1795     if(Session->server_conf->unlimited_decompress)
 1796     {
 1797         compr_avail = compr_depth;
 1798         decompr_avail = decompr_depth;
 1799     }
 1800     else
 1801     {
 1802         compr_avail = compr_depth-compr_bytes_read;
 1803         decompr_avail = decompr_depth - decompr_bytes_read;
 1804     }
 1805 
 1806     /* Apply the server extract size
 1807      * If the server extract size is set then we need to decompress only upto the
 1808      * server flow depth
 1809      */
 1810     switch ( Session->server_conf->server_extract_size)
 1811     {
 1812         case -1:
 1813             decompr_avail=0;
 1814             break;
 1815         case 0:
 1816             break;
 1817         default:
 1818             if(sd->resp_state.data_extracted < Session->server_conf->server_extract_size)
 1819             {
 1820                 if(decompr_avail > (Session->server_conf->server_extract_size - sd->resp_state.data_extracted))
 1821                     decompr_avail = (int)(Session->server_conf->server_extract_size - sd->resp_state.data_extracted);
 1822             }
 1823             else
 1824             {
 1825                 decompr_avail = 0;
 1826             }
 1827             break;
 1828     }
 1829 
 1830     if ((compr_avail <= 0) || (decompr_avail <= 0))
 1831     {
 1832         (void)File_Decomp_Reset(sd->fd_state);
 1833         ResetGzipState(sd->decomp_state);
 1834         ResetRespState(&(sd->resp_state));
 1835         return iRet;
 1836     }
 1837 
 1838 
 1839     if(rawbuf_size < compr_avail)
 1840     {
 1841         compr_avail = rawbuf_size;
 1842     }
 1843 
 1844     if(!(sd->resp_state.last_pkt_contlen))
 1845     {
 1846         if(sd->resp_state.last_pkt_chunked)
 1847         {
 1848             int cRet = 1;
 1849             if(!(sd->decomp_state && sd->decomp_state->stage == HTTP_DECOMP_MID))
 1850             {
 1851                 chunk_read = 0;
 1852                 updated_chunk_remainder = 0;
 1853                 cRet = CheckChunkEncoding(Session, start, end, NULL, dechunk_buffer, compr_avail,
 1854                            sd->resp_state.chunk_remainder, &updated_chunk_remainder, &chunk_read,
 1855                            sd, HI_SI_SERVER_MODE);
 1856             }
 1857             if(cRet == 1)
 1858             {
 1859                 sd->resp_state.chunk_remainder = updated_chunk_remainder;
 1860                 compr_avail = chunk_read;
 1861                 zRet = uncompress_gzip(Session, decompression_buffer, decompr_avail, dechunk_buffer,
 1862                            compr_avail, sd, &total_bytes_read, sd->decomp_state->compress_fmt);
 1863             }
 1864         }
 1865         else
 1866         {
 1867             /* No Content-Length or Transfer-Encoding : chunked */
 1868             if(hi_eo_generate_event(Session, HI_EO_SERVER_NO_CONTLEN))
 1869             {
 1870                 hi_eo_server_event_log(Session, HI_EO_SERVER_NO_CONTLEN, NULL, NULL);
 1871             }
 1872 
 1873             zRet = uncompress_gzip(Session, decompression_buffer, decompr_avail, ptr, compr_avail,
 1874                     sd, &total_bytes_read, sd->decomp_state->compress_fmt);
 1875         }
 1876     }
 1877     else
 1878     {
 1879         zRet = uncompress_gzip(Session, decompression_buffer, decompr_avail, ptr, compr_avail,
 1880                 sd, &total_bytes_read, sd->decomp_state->compress_fmt);
 1881     }
 1882     if(!Session->server_conf->unlimited_decompress)
 1883         sd->decomp_state->stage = HTTP_DECOMP_FIN;
 1884 
 1885     if((zRet == HI_SUCCESS) || (zRet == HI_NONFATAL_ERR))
 1886     {
 1887         sd->decomp_state->compr_bytes_read += compr_avail;
 1888         hi_stats.compr_bytes_read += compr_avail;
 1889 
 1890         result->uri = decompression_buffer;
 1891         if ( total_bytes_read < decompr_avail )
 1892         {
 1893             result->uri_end = decompression_buffer + total_bytes_read;
 1894             sd->decomp_state->decompr_bytes_read += total_bytes_read;
 1895             sd->resp_state.data_extracted += total_bytes_read;
 1896             hi_stats.decompr_bytes_read += total_bytes_read;
 1897         }
 1898         else
 1899         {
 1900             result->uri_end = decompression_buffer + decompr_avail;
 1901             sd->decomp_state->decompr_bytes_read += decompr_avail;
 1902             sd->resp_state.data_extracted += decompr_avail;
 1903             hi_stats.decompr_bytes_read += decompr_avail;
 1904         }
 1905     }
 1906     else
 1907     {
 1908         if(!sd->decomp_state->decompr_bytes_read)
 1909         {
 1910             sd->resp_state.chunk_remainder = saved_chunk_size;
 1911             iRet = HI_NONFATAL_ERR;
 1912         }
 1913         else
 1914             ResetRespState(&(sd->resp_state));
 1915         (void)File_Decomp_Reset(sd->fd_state);
 1916         ResetGzipState(sd->decomp_state);
 1917         sd->decomp_state->stage = HTTP_DECOMP_FIN;
 1918     }
 1919 
 1920     if(zRet!=HI_SUCCESS && start_of_body)
 1921     {
 1922         if(hi_eo_generate_event(Session, HI_EO_SERVER_DECOMPR_FAILED))
 1923         {
 1924             hi_eo_server_event_log(Session, HI_EO_SERVER_DECOMPR_FAILED, NULL, NULL);
 1925         }
 1926     }
 1927 
 1928     return iRet;
 1929 
 1930 
 1931 }
 1932 
 1933 static inline int hi_server_inspect_body(HI_SESSION *Session, HttpSessionData *sd, const u_char *ptr,
 1934                         const u_char *end, URI_PTR *result, bool start_of_body)
 1935 {
 1936     int iRet = HI_SUCCESS;
 1937 
 1938     result->uri =ptr;
 1939     result->uri_end = end;
 1940     if(!Session || !sd )
 1941     {
 1942         if ((sd != NULL))
 1943         {
 1944             (void)File_Decomp_Reset(sd->fd_state);
 1945             ResetGzipState(sd->decomp_state);
 1946             ResetRespState(&(sd->resp_state));
 1947         }
 1948         return HI_INVALID_ARG;
 1949     }
 1950 
 1951     if((sd->decomp_state != NULL) && sd->decomp_state->decompress_data)
 1952     {
 1953         iRet = hi_server_decompress(Session, sd, ptr, end, result, start_of_body);
 1954         if(iRet == HI_NONFATAL_ERR)
 1955         {
 1956             sd->resp_state.inspect_body = 1;
 1957             result->uri = ptr;
 1958             result->uri_end = end;
 1959             iRet = hi_server_extract_body(Session, sd, ptr, end, result);
 1960         }
 1961     }
 1962     else
 1963     {
 1964         result->uri = ptr;
 1965         result->uri_end = end;
 1966         iRet = hi_server_extract_body(Session, sd, ptr, end, result);
 1967     }
 1968 
 1969     return iRet;
 1970 
 1971 }
 1972 void ApplyFlowDepth(HTTPINSPECT_CONF *ServerConf, Packet *p,
 1973         HttpSessionData *sd, int resp_header_size, int read_only, uint32_t seq_num)
 1974 {
 1975     if(!ServerConf->server_flow_depth)
 1976     {
 1977         SetDetectLimit(p, p->dsize);
 1978     }
 1979     else if(ServerConf->server_flow_depth == -1)
 1980     {
 1981         SetDetectLimit(p, resp_header_size);
 1982     }
 1983     else
 1984     {
 1985         if(sd != NULL)
 1986         {
 1987             if(!(sd->resp_state.flow_depth_excd ))
 1988             {
 1989                 if(sd->resp_state.max_seq)
 1990                 {
 1991                     if(SEQ_GEQ((sd->resp_state.max_seq), seq_num))
 1992                     {
 1993                         if(((uint32_t)p->dsize) > (sd->resp_state.max_seq- seq_num))
 1994                         {
 1995                             SetDetectLimit(p, (uint16_t)(sd->resp_state.max_seq-seq_num));
 1996                             if( !read_only )
 1997                                 sd->resp_state.flow_depth_excd = true;
 1998                             return;
 1999                         }
 2000                         else
 2001                         {
 2002                             SetDetectLimit(p, p->dsize);
 2003                             return;
 2004                         }
 2005                     }
 2006                     else
 2007                     {
 2008                         if( !read_only )
 2009                             sd->resp_state.flow_depth_excd = true;
 2010                         SetDetectLimit(p, resp_header_size);
 2011                         return;
 2012                     }
 2013                 }
 2014                 else
 2015                 {
 2016                     if( !read_only )
 2017                         sd->resp_state.flow_depth_excd = false;
 2018                     SetDetectLimit(p, (((ServerConf->server_flow_depth) < p->dsize)? ServerConf->server_flow_depth: p->dsize));
 2019                 }
 2020             }
 2021             else
 2022             {
 2023                 SetDetectLimit(p, 0);
 2024                 return;
 2025             }
 2026 
 2027         }
 2028         else
 2029         {
 2030 
 2031             SetDetectLimit(p, (((ServerConf->server_flow_depth) < p->dsize)? (ServerConf->server_flow_depth): (p->dsize)));
 2032         }
 2033     }
 2034 }
 2035 
 2036 static inline void ResetState (HttpSessionData* sd)
 2037 {
 2038     (void)File_Decomp_Reset(sd->fd_state);
 2039     ResetGzipState(sd->decomp_state);
 2040     ResetRespState(&(sd->resp_state));
 2041 }
 2042 
 2043 int HttpResponseInspection(HI_SESSION *Session, Packet *p, const unsigned char *data,
 2044         int dsize, HttpSessionData *sd)
 2045 {
 2046     HTTPINSPECT_CONF *ServerConf;
 2047     URI_PTR stat_code_ptr;
 2048     URI_PTR stat_msg_ptr;
 2049     HEADER_PTR header_ptr;
 2050     URI_PTR body_ptr;
 2051     HI_SERVER *Server;
 2052 
 2053     const u_char *start;
 2054     const u_char *end;
 2055     const u_char *ptr;
 2056     int len;
 2057     int iRet = 0;
 2058     int resp_header_size = 0;
 2059     /* Refers to the stream reassembled packets when reassembly is turned on.
 2060      * Refers to all packets when reassembly is turned off.
 2061      */
 2062     int not_stream_insert = 1;
 2063     int parse_cont_encoding = 1;
 2064     int status;
 2065     int expected_pkt = 0;
 2066     int alt_dsize;
 2067     uint32_t seq_num = 0;
 2068 
 2069     static uint32_t paf_bytes_total = 0;
 2070     static int paf_bytes_curr = 0;
 2071     uint32_t paf_bytes_processed = 0;
 2072     bool parse_trans_encoding = true;
 2073 
 2074     if (ScPafEnabled())
 2075     {
 2076     paf_bytes_processed = hi_paf_resp_bytes_processed(p->ssnptr);
 2077     paf_bytes_curr = paf_bytes_processed - paf_bytes_total;
 2078     paf_bytes_total = paf_bytes_processed;
 2079     if (paf_bytes_curr < 0)
 2080         paf_bytes_curr = paf_bytes_processed;
 2081     }
 2082 
 2083     if (!Session || !p || !data || (dsize == 0))
 2084         return HI_INVALID_ARG;
 2085 
 2086     ServerConf = Session->server_conf;
 2087     if(!ServerConf)
 2088         return HI_INVALID_ARG;
 2089 
 2090 
 2091     Server = &(Session->server);
 2092     clearHttpRespBuffer(Server);
 2093 
 2094     seq_num = GET_PKT_SEQ(p);
 2095 
 2096     if ( ScPafEnabled() )
 2097     {
 2098         expected_pkt = !PacketHasStartOfPDU(p);
 2099         parse_cont_encoding = !expected_pkt;
 2100         not_stream_insert = PacketHasPAFPayload(p);
 2101         parse_trans_encoding = !hi_paf_disable_te(p->ssnptr, false);
 2102 
 2103         if ( !expected_pkt )
 2104         {
 2105             simple_response = false;
 2106             if ( sd )
 2107             {
 2108                 if (!sd->decomp_state || (sd->decomp_state->stage != HTTP_DECOMP_MID))
 2109                     ResetState(sd);
 2110             }
 2111         }
 2112         else if ( sd )
 2113         {
 2114             if(hi_paf_simple_request(p->ssnptr))
 2115             {
 2116                 simple_response = true;
 2117                 if(!(sd->resp_state.next_seq))
 2118                 {
 2119                     /*first simple response packet */
 2120                     sd->resp_state.next_seq = seq_num + p->dsize;
 2121                     if(ServerConf->server_flow_depth == -1)
 2122                             sd->resp_state.flow_depth_excd = true;
 2123                     else
 2124                     {
 2125                         sd->resp_state.flow_depth_excd = false;
 2126                         sd->resp_state.max_seq = seq_num + ServerConf->server_flow_depth;
 2127                     }
 2128 
 2129                 }
 2130             }
 2131             else
 2132                 simple_response = false;
 2133 
 2134             if(ServerConf->server_extract_size)
 2135             {
 2136                 /*Packet is beyond the extract limit*/
 2137                 if ( sd && (sd->resp_state.data_extracted > ServerConf->server_extract_size ))
 2138                 {
 2139                     expected_pkt = 0;
 2140                     ResetState(sd);
 2141                     if (sd->decomp_state)
 2142                         sd->decomp_state->stage = HTTP_DECOMP_FIN;
 2143                 }
 2144             }
 2145         }
 2146     }
 2147     // when PAF is hardened, the following can be removed
 2148     else if ( (sd != NULL) )
 2149     {
 2150         /* If the previously inspected packet in this session identified as a body
 2151          * and if the packets are stream inserted wait for reassembled */
 2152         if (sd->resp_state.inspect_reassembled)
 2153         {
 2154             if(p->packet_flags & PKT_STREAM_INSERT)
 2155             {
 2156                 parse_cont_encoding = 0;
 2157                 not_stream_insert = 0;
 2158             }
 2159         }
 2160         /* If this packet is the next expected packet to be inspected and is out of sequence
 2161          * clear out the resp state*/
 2162         if(( sd->decomp_state && sd->decomp_state->decompress_data) && parse_cont_encoding)
 2163         {
 2164             if( sd->resp_state.next_seq &&
 2165                     (seq_num == sd->resp_state.next_seq) )
 2166             {
 2167                 sd->resp_state.next_seq = seq_num + p->dsize;
 2168                 expected_pkt = 1;
 2169             }
 2170             else
 2171             {
 2172                 (void)File_Decomp_Reset(sd->fd_state);
 2173                 ResetRespState(&(sd->resp_state));
 2174                 if(sd->decomp_state && sd->decomp_state->stage != HTTP_DECOMP_START)
 2175                 {
 2176                     ResetGzipState(sd->decomp_state);
 2177                     sd->decomp_state->stage = HTTP_DECOMP_FIN;
 2178                 }
 2179                 else
 2180                     ResetGzipState(sd->decomp_state);
 2181             }
 2182         }
 2183         else
 2184         if(sd->resp_state.inspect_body && not_stream_insert)
 2185         {
 2186             /* If the server extrtact size is 0 then we need to check if the packet
 2187              * is in sequence
 2188              */
 2189             if(!ServerConf->server_extract_size)
 2190             {
 2191                 if( sd->resp_state.next_seq &&
 2192                         (seq_num == sd->resp_state.next_seq) )
 2193                 {
 2194                     sd->resp_state.next_seq = seq_num + p->dsize;
 2195                     expected_pkt = 1;
 2196                 }
 2197                 else
 2198                 {
 2199                     (void)File_Decomp_Reset(sd->fd_state);
 2200                     ResetRespState(&(sd->resp_state));
 2201                     if(sd->decomp_state && sd->decomp_state->stage != HTTP_DECOMP_START)
 2202                     {
 2203                         ResetGzipState(sd->decomp_state);
 2204                         sd->decomp_state->stage = HTTP_DECOMP_FIN;
 2205                     }
 2206                     else
 2207                         ResetGzipState(sd->decomp_state);
 2208                 }
 2209             }
 2210             else
 2211             {
 2212 
 2213                 if( (ServerConf->server_extract_size > 0) &&(sd->resp_state.data_extracted > ServerConf->server_extract_size))
 2214                 {
 2215                     expected_pkt = 1;
 2216                 }
 2217                 else
 2218                 {
 2219                     (void)File_Decomp_Reset(sd->fd_state);
 2220                     ResetRespState(&(sd->resp_state));
 2221                     if(sd->decomp_state && sd->decomp_state->stage != HTTP_DECOMP_START)
 2222                     {
 2223                         ResetGzipState(sd->decomp_state);
 2224                         sd->decomp_state->stage = HTTP_DECOMP_FIN;
 2225                     }
 2226                     else
 2227                         ResetGzipState(sd->decomp_state);
 2228                 }
 2229 
 2230             }
 2231 
 2232         }
 2233     }
 2234 
 2235     memset(&stat_code_ptr, 0x00, sizeof(URI_PTR));
 2236     memset(&stat_msg_ptr, 0x00, sizeof(URI_PTR));
 2237     memset(&header_ptr, 0x00, sizeof(HEADER_PTR));
 2238     memset(&body_ptr, 0x00, sizeof(URI_PTR));
 2239 
 2240     start = data;
 2241     end = data + dsize;
 2242     ptr = start;
 2243 
 2244     /* moving past the CRLF */
 2245 
 2246     while(hi_util_in_bounds(start, end, ptr))
 2247     {
 2248         if(*ptr < 0x21)
 2249         {
 2250             if(*ptr < 0x0E && *ptr > 0x08)
 2251             {
 2252                 ptr++;
 2253                 continue;
 2254             }
 2255             else
 2256             {
 2257                 if(*ptr == 0x20)
 2258                 {
 2259                     ptr++;
 2260                     continue;
 2261                 }
 2262             }
 2263         }
 2264 
 2265         break;
 2266     }
 2267 
 2268     /*after doing this we need to basically check for version, status code and status message*/
 2269     if(( PacketHasStartOfPDU(p)) &&
 2270         ((*ptr != 'H') || *(ptr+1) != 'T' || *(ptr+2) != 'T'
 2271           || *(ptr+3) != 'P' || *(ptr+4) != '/'))
 2272     {
 2273         if( !(ptr = (u_char *)SnortStrcasestr((const char *)ptr, end-ptr, "HTTP/")))
 2274         {
 2275             CLR_SERVER_HEADER(Server);
 2276             return HI_SUCCESS;
 2277         }
 2278     }
 2279 
 2280     len = end - ptr;
 2281 
 2282     if ( len > 4 )
 2283     {
 2284         bool header = false;
 2285 
 2286         p->packet_flags |= PKT_HTTP_DECODE;
 2287         if(!sd->resp_state.inspect_reassembled ||
 2288            !PacketHasPAFPayload(p) ||
 2289            PacketHasStartOfPDU(p) ||
 2290            !ScPafEnabled())
 2291             header = IsHttpVersion(&ptr, end);
 2292 
 2293         if(!header)
 2294         {
 2295             if(expected_pkt)
 2296                 ptr = start;
 2297             else
 2298             {
 2299                 ApplyFlowDepth(ServerConf, p, sd, resp_header_size, 0, seq_num);
 2300                 if ( not_stream_insert && (sd != NULL))
 2301                 {
 2302                     (void)File_Decomp_Reset(sd->fd_state);
 2303                     ResetGzipState(sd->decomp_state);
 2304                     ResetRespState(&(sd->resp_state));
 2305                 }
 2306                 CLR_SERVER_HEADER(Server);
 2307                 return HI_SUCCESS;
 2308             }
 2309         }
 2310         else
 2311         {
 2312             simple_response = false;
 2313             /* This is a next expected packet to be decompressed but the packet is a
 2314              * valid HTTP response. So the gzip decompression ends here */
 2315             if(expected_pkt)
 2316             {
 2317                 expected_pkt = 0;
 2318                 (void)File_Decomp_Reset(sd->fd_state);
 2319                 ResetGzipState(sd->decomp_state);
 2320                 ResetRespState(&(sd->resp_state));
 2321                 sd->resp_state.flow_depth_excd = false;
 2322             }
 2323             while(hi_util_in_bounds(start, end, ptr))
 2324             {
 2325                 if (isspace((int)*ptr))
 2326                     break;
 2327                 ptr++;
 2328             }
 2329 
 2330         }
 2331     }
 2332     else if (expected_pkt)
 2333     {
 2334         ptr = start;
 2335     }
 2336     else
 2337     {
 2338         return HI_SUCCESS;
 2339     }
 2340 
 2341     /*If this is the next expected packet to be decompressed, send this packet
 2342      * decompression */
 2343 
 2344     if (expected_pkt)
 2345     {
 2346         bool resp_eoh = false;
 2347     if (ScPafEnabled() && !sd->resp_state.eoh_found)
 2348     {
 2349         // check for EOH in this packet
 2350             if ((resp_eoh = hi_paf_resp_eoh(p->ssnptr)))
 2351         {
 2352             sd->resp_state.eoh_found = true;
 2353             ptr += paf_bytes_curr; // jump to body offset
 2354             if (ptr == end)
 2355                return HI_SUCCESS;
 2356         }
 2357         }
 2358 
 2359         if (hi_util_in_bounds(start, end, ptr))
 2360         {
 2361             iRet = hi_server_inspect_body(Session, sd, ptr, end, &body_ptr, resp_eoh | !sd->resp_state.data_extracted); 
 2362         }
 2363     }
 2364     else
 2365     {
 2366         iRet = hi_server_extract_status_code(Session, start,ptr,end , &stat_code_ptr);
 2367 
 2368         if ( iRet != HI_OUT_OF_BOUNDS )
 2369         {
 2370             Server->response.status_code = stat_code_ptr.uri;
 2371             Server->response.status_code_size = stat_code_ptr.uri_end - stat_code_ptr.uri;
 2372             if ( (int)Server->response.status_code_size <= 0)
 2373             {
 2374                 CLR_SERVER_STAT(Server);
 2375             }
 2376             else
 2377             {
 2378                 iRet = hi_server_extract_status_msg(start, stat_code_ptr.uri_end ,
 2379                         end, &stat_msg_ptr);
 2380 
 2381                 if ( stat_msg_ptr.uri )
 2382                 {
 2383                     Server->response.status_msg = stat_msg_ptr.uri;
 2384                     Server->response.status_msg_size = stat_msg_ptr.uri_end - stat_msg_ptr.uri;
 2385                     if ((int)Server->response.status_msg_size <= 0)
 2386                     {
 2387                         CLR_SERVER_STAT_MSG(Server);
 2388                     }
 2389                     {
 2390                         header_ptr.range_flag = HTTP_RANGE_NONE;
 2391                         ptr =  hi_server_extract_header(Session, ServerConf, &header_ptr,
 2392                                             stat_msg_ptr.uri_end , end, parse_cont_encoding, parse_trans_encoding, sd );
 2393 
 2394                         if (header_ptr.range_flag != HTTP_RANGE_NONE)
 2395                         {
 2396                             Server->response.range_flag = header_ptr.range_flag;
 2397                         } 
 2398                         else
 2399                         {
 2400                             Server->response.range_flag = HTTP_RESP_RANGE_NONE;
 2401                         }
 2402                     }
 2403                 }
 2404                 else
 2405                 {
 2406                     CLR_SERVER_STAT(Server);
 2407                 }
 2408             }
 2409 
 2410             if (header_ptr.header.uri)
 2411             {
 2412                 Server->response.header_raw = header_ptr.header.uri;
 2413                 Server->response.header_raw_size =
 2414                     header_ptr.header.uri_end - header_ptr.header.uri;
 2415                 if(!Server->response.header_raw_size)
 2416                 {
 2417                     CLR_SERVER_HEADER(Server);
 2418                 }
 2419                 else
 2420                 {
 2421                     resp_header_size = (header_ptr.header.uri_end - p->data);
 2422                     hi_stats.resp_headers++;
 2423                     Server->response.header_norm = header_ptr.header.uri;
 2424                     if (header_ptr.cookie.cookie)
 2425                     {
 2426                         hi_stats.resp_cookies++;
 2427                         Server->response.cookie.cookie = header_ptr.cookie.cookie;
 2428                         Server->response.cookie.cookie_end = header_ptr.cookie.cookie_end;
 2429                         Server->response.cookie.next = header_ptr.cookie.next;
 2430                     }
 2431                     else
 2432                     {
 2433                         Server->response.cookie.cookie = NULL;
 2434                         Server->response.cookie.cookie_end = NULL;
 2435                         Server->response.cookie.next = NULL;
 2436                     }
 2437                     if (sd != NULL)
 2438                     {
 2439                         if( header_ptr.content_encoding.compress_fmt )
 2440                         {
 2441                             hi_stats.gzip_pkts++;
 2442 
 2443                             /* We've got gzip data - grab buffer from mempool and attach
 2444                              * to session data if server is configured to do so */
 2445                             if (sd->decomp_state == NULL)
 2446                                 SetGzipBuffers(sd, Session, p->ssnptr);
 2447 
 2448                             if (sd->decomp_state != NULL)
 2449                             {
 2450                                 sd->decomp_state->decompress_data = 1;
 2451                                 sd->decomp_state->compress_fmt =
 2452                                                             header_ptr.content_encoding.compress_fmt;
 2453                             }
 2454 
 2455                         }
 2456                         else
 2457                         {
 2458                             sd->resp_state.inspect_body = 1;
 2459                         }
 2460 
 2461                         if( ServerConf->file_decomp_modes != 0 )
 2462                         {
 2463                             InitFileDecomp(sd, Session,p->ssnptr);
 2464                         }
 2465 
 2466                         sd->resp_state.last_pkt_contlen = (header_ptr.content_len.len != 0);
 2467                         if(ServerConf->server_flow_depth == -1)
 2468                             sd->resp_state.flow_depth_excd = true;
 2469                         else
 2470                         {
 2471                             sd->resp_state.flow_depth_excd = false;
 2472                             sd->resp_state.max_seq = seq_num +
 2473                                         (header_ptr.header.uri_end - start)+ ServerConf->server_flow_depth;
 2474                         }
 2475 
 2476                         if (p->packet_flags & PKT_STREAM_INSERT)
 2477                         {
 2478                             if ( ScPafEnabled() )
 2479                             {
 2480                                 if ( p->packet_flags & PKT_PDU_TAIL )
 2481                                     expected_pkt = 1;
 2482                                 else
 2483                                     sd->resp_state.inspect_reassembled = 1;
 2484                             }
 2485                             else if (
 2486                                 header_ptr.content_len.cont_len_start &&
 2487                                 ((uint32_t)(end - (header_ptr.header.uri_end)) >= header_ptr.content_len.len))
 2488                             {
 2489                                 /* change this when the api is fixed to flush correctly */
 2490                                 //stream_api->response_flush_stream(p);
 2491                                 expected_pkt = 1;
 2492                             }
 2493                             else
 2494                                 sd->resp_state.inspect_reassembled = 1;
 2495                         }
 2496                         else
 2497                         {
 2498                             if(p->packet_flags & PKT_REBUILT_STREAM)
 2499                                 sd->resp_state.inspect_reassembled = 1;
 2500 
 2501                             expected_pkt = 1;
 2502                         }
 2503                         if(expected_pkt)
 2504                         {
 2505                             sd->resp_state.next_seq = seq_num + p->dsize;
 2506 
 2507                             if(hi_util_in_bounds(start, end, header_ptr.header.uri_end))
 2508                             {
 2509                                 iRet = hi_server_inspect_body(Session, sd, header_ptr.header.uri_end,
 2510                                                                 end, &body_ptr, PacketHasStartOfPDU(p) || !ScPafEnabled());
 2511                             }
 2512                         }
 2513                     }
 2514                 }
 2515             }
 2516             else
 2517             {
 2518                 CLR_SERVER_HEADER(Server);
 2519 
 2520             }
 2521         }
 2522         else
 2523         {
 2524             CLR_SERVER_STAT(Server);
 2525         }
 2526     }
 2527 
 2528     if( body_ptr.uri )
 2529     {
 2530         Server->response.body = body_ptr.uri;
 2531         Server->response.body_size = body_ptr.uri_end - body_ptr.uri;
 2532         Server->response.body_raw = body_ptr.uri;
 2533         Server->response.body_raw_size = body_ptr.uri_end - body_ptr.uri;
 2534         if( Server->response.body_size > 0)
 2535         {
 2536             if ( Server->response.body_size < sizeof(HttpDecodeBuf.data) )
 2537             {
 2538                 alt_dsize = Server->response.body_size;
 2539             }
 2540             else
 2541             {
 2542                 alt_dsize = sizeof(HttpDecodeBuf.data);
 2543             }
 2544             /* not checking if sd== NULL as the body_ptr.uri = NULL when sd === NULL in hi_server_inspect_body */
 2545             if(sd->decomp_state && sd->decomp_state->decompress_data)
 2546             {
 2547                 status = SafeMemcpy(HttpDecodeBuf.data, Server->response.body,
 2548                                             alt_dsize, HttpDecodeBuf.data, HttpDecodeBuf.data + sizeof(HttpDecodeBuf.data));
 2549                 if( status != SAFEMEM_SUCCESS  )
 2550                 {
 2551                     CLR_SERVER_HEADER(Server);
 2552                     CLR_SERVER_STAT_MSG(Server);
 2553                     CLR_SERVER_STAT(Server);
 2554                     return HI_MEM_ALLOC_FAIL;
 2555                 }
 2556 
 2557                 SetHttpDecode((uint16_t)alt_dsize);
 2558                 Server->response.body = HttpDecodeBuf.data;
 2559                 Server->response.body_size = HttpDecodeBuf.len;
 2560                 sd->log_flags |= HTTP_LOG_GZIP_DATA;
 2561             }
 2562             else
 2563             {
 2564                 if(sd->resp_state.last_pkt_chunked)
 2565                 {
 2566                     SetHttpDecode((uint16_t)alt_dsize);
 2567                     Server->response.body = HttpDecodeBuf.data;
 2568                     Server->response.body_size = HttpDecodeBuf.len;
 2569                 }
 2570                 else
 2571                 {
 2572                     Server->response.body_size = alt_dsize;
 2573                 }
 2574             }
 2575 
 2576             if ((get_decode_utf_state_charset(&(sd->utf_state)) != CHARSET_DEFAULT)
 2577                     || (ServerConf->normalize_javascript && Server->response.body_size))
 2578             {
 2579                 if ( Server->response.body_size < sizeof(HttpDecodeBuf.data) )
 2580                 {
 2581                     alt_dsize = Server->response.body_size;
 2582                 }
 2583                 else
 2584                 {
 2585                     alt_dsize = sizeof(HttpDecodeBuf.data);
 2586                 }
 2587                 Server->response.body_size = alt_dsize;
 2588                 SetHttpDecode((uint16_t)alt_dsize);
 2589             }
 2590         }
 2591 
 2592     }
 2593 
 2594 #if defined(FEAT_OPEN_APPID)
 2595     //copy over extracted headers for appId
 2596     if ((ServerConf->appid_enabled))
 2597     {
 2598         HttpParsedHeaders headers;
 2599         memset(&headers, 0, sizeof(headers));
 2600         headers.via = header_ptr.via;
 2601         headers.server = header_ptr.server;
 2602         headers.xWorkingWith = header_ptr.xWorkingWith;
 2603         headers.contentType = header_ptr.contentType;
 2604         if (Server->response.status_code)
 2605         {
 2606             headers.responseCode.start = Server->response.status_code;
 2607             headers.responseCode.len = Server->response.status_code_size;
 2608         }
 2609 
 2610         /*callback into appId with header values extracted. */
 2611         CallHttpHeaderProcessors(p, &headers);
 2612         free((void*)headers.server.start);
 2613         free((void*)headers.via.start);
 2614         free((void*)headers.xWorkingWith.start);
 2615     }
 2616 
 2617 #endif /* defined(FEAT_OPEN_APPID) */
 2618 
 2619     ApplyFlowDepth(ServerConf, p, sd, resp_header_size, 0, seq_num);
 2620 
 2621     return HI_SUCCESS;
 2622 }
 2623 
 2624 int ServerInspection(HI_SESSION *Session, Packet *p, HttpSessionData *hsd)
 2625 {
 2626     int iRet;
 2627 
 2628     if ((p->data == NULL) || (p->dsize == 0))
 2629     {
 2630         return HI_INVALID_ARG;
 2631     }
 2632 
 2633 #if defined(FEAT_OPEN_APPID)
 2634     if ( Session->server_conf->inspect_response || Session->server_conf->appid_enabled)
 2635 #else
 2636     if ( Session->server_conf->inspect_response )
 2637 #endif /* defined(FEAT_OPEN_APPID) */
 2638     {
 2639         iRet = HttpResponseInspection(Session, p, p->data, p->dsize, hsd);
 2640     }
 2641     else
 2642     {
 2643         iRet = IsHttpServerData(Session, p, hsd);
 2644     }
 2645 
 2646     if (iRet)
 2647     {
 2648         return iRet;
 2649     }
 2650 
 2651     return HI_SUCCESS;
 2652 }
 2653 
 2654 int hi_server_inspection(void *S, Packet *p, HttpSessionData *hsd)
 2655 {
 2656     HI_SESSION *Session;
 2657 
 2658     int iRet;
 2659 
 2660     if(!S )
 2661     {
 2662         return HI_INVALID_ARG;
 2663     }
 2664 
 2665     Session = (HI_SESSION *)S;
 2666 
 2667     /*  IF Server->enable_xff is not enabled, we are not going to do anything related to
 2668         Extradata list update. if XFF is not enabled req_id and resp_id will be zero always .
 2669     */
 2670     if (Session->server_conf->enable_xff)
 2671     {
 2672        if( ScPafEnabled() )
 2673        {
 2674        uint8_t find_id;
 2675 
 2676            if(hsd->http_resp_id == XFF_MAX_PIPELINE_REQ)
 2677               hsd->http_resp_id = 0;
 2678            if( PacketHasStartOfPDU(p) )
 2679            {
 2680               hsd->http_resp_id++;
 2681               if( hsd->tList_count != 0 )
 2682                  hsd->tList_count--;
 2683            }
 2684            hsd->is_response = 1;
 2685 
 2686            find_id = (hsd->http_resp_id - 1 );
 2687            if( !find_id )
 2688                find_id = XFF_MAX_PIPELINE_REQ;
 2689 
 2690            if( (hsd->tList_start != NULL) && ( hsd->tList_start->tID == find_id ) )
 2691                deleteNode_tList(hsd);
 2692        }
 2693     }
 2694 
 2695     /*
 2696     **  Let's inspect the server response.
 2697     */
 2698     iRet = ServerInspection(Session, p, hsd);
 2699     if (iRet)
 2700     {
 2701         return iRet;
 2702     }
 2703 
 2704     return HI_SUCCESS;
 2705 }