📄 hi_client.c
字号:
static int SetSlashNorm(HI_SESSION *Session, const u_char *start, const u_char *end, const u_char **ptr, URI_PTR *uri_ptr){ HTTPINSPECT_CONF *ServerConf = Session->server_conf; CheckLongDir(Session, uri_ptr, *ptr); uri_ptr->last_dir = *ptr; if(!uri_ptr->norm && !uri_ptr->ident) { uri_ptr->norm = *ptr; (*ptr)++; if(!hi_util_in_bounds(start,end, *ptr)) { /* ** This is the case where there is a slash as the last char ** and we don't want to normalize that since there really ** is nothing to normalize. */ uri_ptr->norm = NULL; return HI_OUT_OF_BOUNDS; } /* ** Check for directory traversals */ if(ServerConf->directory.on) { if(**ptr == '.') { (*ptr)++; if(!hi_util_in_bounds(start, end, *ptr)) { uri_ptr->norm = NULL; return HI_OUT_OF_BOUNDS; } if(**ptr == '.' || ** ptr == '/') { return HI_SUCCESS; } } } /* ** Check for multiple slash normalization */ if(ServerConf->multiple_slash.on) { if(**ptr == '/') { return HI_SUCCESS; } } uri_ptr->norm = NULL; return HI_SUCCESS; } (*ptr)++; return HI_SUCCESS;}/*** NAME** SetBackSlashNorm::*//**** Check for backslashes and if we need to normalize.** ** This really just checks the configuration option, and sets the norm** variable if applicable.** ** @param ServerConf pointer to the server configuration** @param start pointer to the start of payload** @param end pointer to the end of the payload** @param ptr pointer to the pointer of the current index** @param uri_ptr pointer to the URI_PTR construct ** ** @return integer** ** @retval HI_SUCCESS function successful*/static int SetBackSlashNorm(HI_SESSION *Session, const u_char *start, const u_char *end, const u_char **ptr, URI_PTR *uri_ptr){ HTTPINSPECT_CONF *ServerConf = Session->server_conf; if(!uri_ptr->norm && !uri_ptr->ident) { if(ServerConf->iis_backslash.on) { uri_ptr->norm = *ptr; } } (*ptr)++; return HI_SUCCESS;}/*** NAME** SetBinaryNorm::*//**** Look for non-ASCII chars in the URI.** ** We look for these chars in the URI and set the normalization variable** if it's not already set. I think we really only need this for IIS** servers, but we may want to know if it's in the URI too.** ** @param ServerConf pointer to the server configuration** @param start pointer to the start of payload** @param end pointer to the end of the payload** @param ptr pointer to the pointer of the current index** @param uri_ptr pointer to the URI_PTR construct ** ** @return integer** ** @retval HI_SUCCESS function successful*/static int SetBinaryNorm(HI_SESSION *Session, const u_char *start, const u_char *end, const u_char **ptr, URI_PTR *uri_ptr){ if(!uri_ptr->norm && !uri_ptr->ident) { uri_ptr->norm = *ptr; } (*ptr)++; return HI_SUCCESS;}/*** NAME** SetParamField::*//**** This function sets the parameter field as the first '?'. The big thing** is that we set the param value, so we don't false positive long dir** events when it's really just a long parameter field.** ** @param ServerConf pointer to the server configuration** @param start pointer to the start of payload** @param end pointer to the end of the payload** @param ptr pointer to the pointer of the current index** @param uri_ptr pointer to the URI_PTR construct ** ** @return integer** ** @retval HI_SUCCESS function successful*/static int SetParamField(HI_SESSION *Session, const u_char *start, const u_char *end, const u_char **ptr, URI_PTR *uri_ptr){ if(!uri_ptr->ident) { uri_ptr->param = *ptr; } (*ptr)++; return HI_SUCCESS;}/*** NAME** SetProxy::*//**** This function checks for an absolute URI in the URI.** ** @param ServerConf pointer to the server configuration** @param start pointer to the start of payload** @param end pointer to the end of the payload** @param ptr pointer to the pointer of the current index** @param uri_ptr pointer to the URI_PTR construct ** ** @return integer** ** @retval HI_SUCCESS function successful*/static int SetProxy(HI_SESSION *Session, const u_char *start, const u_char *end, const u_char **ptr, URI_PTR *uri_ptr){ HTTPINSPECT_CONF *ServerConf = Session->server_conf; if(!uri_ptr->ident && !uri_ptr->last_dir) { if(Session->global_conf->proxy_alert && !ServerConf->allow_proxy) { if(hi_util_in_bounds(start, end, ((*ptr)+2))) { if(*((*ptr)+1) == '/' && *((*ptr)+2) == '/') { uri_ptr->proxy = *ptr; } } } } (*ptr)++; return HI_SUCCESS;}/*** NAME** SetClientVars::*//**** This is where we set the HI_CLIENT values that we found during URI** discovery. This also covers checking these values for errors.** ** @param Client pointer to HI_CLIENT structure** @param uri_ptr pointer to the uri data** ** @return integer** ** @retval HI_NONFATAL_ERR problem with the uri values.** @retval HI_SUCCESS values set successfully*/static int SetClientVars(HI_CLIENT *Client, URI_PTR *uri_ptr, u_int dsize){ /* ** We got here either because we found the delimiter or we are ** out of bounds. */ /* if(uri_ptr->first_sp_start) printf("** first_start = %c\n", *uri_ptr->first_sp_start); if(uri_ptr->first_sp_end) printf("** first_end = %c\n", *uri_ptr->first_sp_end); if(uri_ptr->second_sp_start) printf("** second_start = %c\n", *uri_ptr->second_sp_start); if(uri_ptr->second_sp_end) printf("** second_end = %c\n", *uri_ptr->second_sp_end); if(uri_ptr->delimiter) printf("** delimiter = %c\n", *uri_ptr->delimiter); if(uri_ptr->uri) printf("** uri = %c\n", *uri_ptr->uri); if(uri_ptr->norm) printf("** norm = %.2x\n", *uri_ptr->norm); */ /* ** This means that there was only spaces or delimiters within the ** complete URI. In this case, there is no valid URI so we just ** return such. */ if(uri_ptr->uri == NULL) { return HI_NONFATAL_ERR; } /* ** This is where we set the Session variables before moving into more ** HttpInspect processing. If we don't get to this point, then we don't ** need to set these variables since we would have aborted with a ** NONFATAL_ERR. */ Client->request.uri = uri_ptr->uri; Client->request.uri_size = uri_ptr->uri_end - uri_ptr->uri; Client->request.uri_norm = uri_ptr->norm; /* ** LAST RESORT: ** ** This is one of the last checks we do to make sure that we didn't ** mess up or anything. */ if(Client->request.uri_size < 1 || Client->request.uri_size > dsize) { /* ** Bad stuff, let's just bail. */ return HI_NONFATAL_ERR; } /* printf("** Norm = %s\n", Client->request.uri_norm ? "YES" : "NO"); printf("** URI: |%.*s| size = %u\n", Client->request.uri_size, Client->request.uri, Client->request.uri_size); */ return HI_SUCCESS;}static INLINE int hi_client_extract_post( HI_SESSION *Session, HTTPINSPECT_CONF *ServerConf, const u_char *ptr, const u_char *end, URI_PTR *result){ int iRet; const u_char *start = ptr; Session->norm_flags &= HI_BODY; /* Limit search depth */ if(ServerConf->post_depth && ((end - ptr) > ServerConf->post_depth)) { end = ptr + ServerConf->post_depth; result->uri_end = end; } result->uri = start; while(hi_util_in_bounds(start, end, ptr)) { if(lookup_table[*ptr] || ServerConf->whitespace[*ptr]) { if(lookup_table[*ptr]) { iRet = (lookup_table[*ptr])(Session, start, end, &ptr, result); } else { iRet = NextNonWhiteSpace(Session, start, end, &ptr, result); } if(iRet == URI_END || iRet == HI_OUT_OF_BOUNDS) { return POST_END; } else if(iRet != HI_SUCCESS) { return HI_NONFATAL_ERR; } } ptr++; } return POST_END;}static INLINE int hi_client_extract_uri( HI_SESSION *Session, HTTPINSPECT_CONF *ServerConf, HI_CLIENT * Client, const u_char *start, const u_char *end, const u_char *ptr, URI_PTR *uri_ptr){ int iRet = HI_SUCCESS; Session->norm_flags &= ~HI_BODY; /* ** This loop compares each char to an array of functions ** (one for each char) and calling that function if there is one. ** ** If there is no function, then we just increment the char ptr and ** continue processing. ** ** If there is a function, we call that function and process. It's ** important to note that the function that is called is responsible ** for incrementing the ptr to the next char to be inspected. The ** loop does not increment the pointer when a function is called to ** allow the maximum flexibility to the functions. */ while(hi_util_in_bounds(start, end, ptr)) { if(lookup_table[*ptr] || ServerConf->whitespace[*ptr]) { if(lookup_table[*ptr]) { iRet = (lookup_table[*ptr])(Session, start, end, &ptr, uri_ptr); } else { iRet = NextNonWhiteSpace(Session, start, end, &ptr, uri_ptr); } if(iRet) { if(iRet == URI_END) { /* ** You found a URI, let's break and check it out. */ break; } else if(iRet == HI_OUT_OF_BOUNDS) { /* ** Means you've reached the end of the buffer. THIS ** DOESN'T MEAN YOU HAVEN'T FOUND A URI. */ break; } else /* NO_URI */ { /* ** Check for chunk encoding, because the delimiter can ** also be a space, which would look like a pipeline request ** to us if we don't do this first. */ if(Session->server_conf->chunk_length) CheckChunkEncoding(Session, start, end); /* ** We only inspect the packet for another pipeline ** request if there wasn't a previous pipeline request. ** The reason that we do this is because */ if(!Client->request.pipeline_req) { /* ** Just because there was no URI in the first part ** the packet, doesn't mean that this isn't a ** pipelined request that has been segmented. */ if(!ServerConf->no_pipeline) { Client->request.pipeline_req = FindPipelineReq(ptr, end); if(Client->request.pipeline_req) { return HI_SUCCESS; } } } return HI_NONFATAL_ERR; } } else { /* ** This means that we found the next non-whitespace char ** and since we are already pointed there, so we just ** continue. */ continue; } } ptr++; } return iRet;}/*** NAME** StatelessInspection::*//**** Find the URI and determine whether the URI needs to be normalized.** ** This is a big step in stateless inspection, because we need to reliably** find the URI and when possible filter out non-URIs. We do this using a** simple state machine that is based on characters found in the data** buffer.** ** Another important aspect of the stateless inspection is the ability to** track and inspect pipelined requests. It is VERY IMPORTANT to reset the** pipeline_req pointer, since we don't memset the whole structure. This** pointer is reset in the hi_si_session_inspection() function. Check there** for more details.**
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -