📄 hi_client.c
字号:
** ** @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 found the next non-whitespace** @retval HI_OUT_OF_BOUNDS whitespace to the end of the buffer** @retval URI_END delimiter found, end of URI** @retval NO_URI*/static int NextNonWhiteSpace(HI_SESSION *Session, u_char *start, u_char *end, u_char **ptr, URI_PTR *uri_ptr){ HTTPINSPECT_CONF *ServerConf = Session->server_conf; u_char **start_sp; u_char **end_sp; /* ** Reset the identifier, because we've just seen another space. We ** should only see the identifier immediately after a space followed ** by a delimiter. */ if(uri_ptr->ident) { if(ServerConf->non_strict) { /* ** In non-strict mode it is ok to see spaces after the ** "identifier", so we just increment the ptr and return. */ (*ptr)++; return HI_SUCCESS; } else { /* ** This means that we've already seen a space and a version ** identifier, and now that we've seen another space, we know ** that this can't be the URI so we just bail out with no ** URI. */ return NO_URI; } } uri_ptr->ident = NULL; /* ** We only check for one here, because both should be set if one ** is. */ if(uri_ptr->first_sp_end) { /* ** If the second space has been set, then this means that we have ** seen a third space, which we shouldn't see in the URI so we ** are now done and know there is no URI in this packet. */ if(uri_ptr->second_sp_end) { return NO_URI; } /* ** Since we've seen the second space, we need to update the uri ptr ** to the end of the first space, since the URI cannot be before the ** first space. */ uri_ptr->uri = uri_ptr->first_sp_end; uri_ptr->second_sp_start = *ptr; uri_ptr->second_sp_end = NULL; start_sp = &uri_ptr->second_sp_start; end_sp = &uri_ptr->second_sp_end; } else { /* ** This means that there is whitespace at the beginning of the line ** and we unset the URI so we can set it later if need be. ** ** This is mainly so we handle data that is all spaces correctly. ** ** In the normal case where we've seen text and then the first space, ** we leave the uri ptr pointing at the beginning of the data, and ** set the uri end after we've determined where to put it. */ if(start == *ptr) uri_ptr->uri = NULL; uri_ptr->first_sp_start = *ptr; uri_ptr->first_sp_end = NULL; start_sp = &uri_ptr->first_sp_start; end_sp = &uri_ptr->first_sp_end; } while(hi_util_in_bounds(start, end, *ptr)) { /* ** Check for whitespace */ if(**ptr == ' ') { (*ptr)++; continue; } else if((**ptr == '\t')) { if(ServerConf->apache_whitespace.on) { if(hi_eo_generate_event(Session, ServerConf->apache_whitespace.alert)) { hi_eo_client_event_log(Session, HI_EO_CLIENT_APACHE_WS, NULL, NULL); } (*ptr)++; continue; } else { return NO_URI; } } else { /* ** This sets the sp_end for whatever space delimiter we are on, ** whether that is the first space or the second space. */ *end_sp = *ptr; if(!IsHttpVersion(ptr, end)) { /* ** This is the default method and what we've been doing ** since the start of development. */ if(uri_ptr->second_sp_start) { /* ** There is no HTTP version indentifier at the beginning ** of the second space, and this means that there is no ** URI. */ if(ServerConf->non_strict) { /* ** In non-strict mode, we must assume the URI is ** between the first and second space, so now ** that we've seen the second space that's the ** identifier. */ uri_ptr->ident = *end_sp; uri_ptr->uri_end = *start_sp; return HI_SUCCESS; } else { /* ** Since we are in strict mode here, it means that ** we haven't seen a valid identifier, so there was ** no URI. */ return NO_URI; } } /* ** RESET NECESSARY URI_PTRs HERE. This is the place where ** the uri is updated. It can only happen once, so do it ** right here. ** ** When we get here it means that we have found the end of ** the FIRST whitespace, and that there was no delimiter, ** so we reset the uri pointers and other related ** pointers. */ uri_ptr->uri = *end_sp; uri_ptr->uri_end = end; uri_ptr->norm = NULL; uri_ptr->last_dir = NULL; uri_ptr->param = NULL; uri_ptr->proxy = NULL; } else { /* ** Means we found the HTTP version identifier and we reset ** the uri_end pointer to point to the beginning of the ** whitespace detected. ** ** This works for both "uri_is_here HTTP/1.0" and ** "METHOD uri_is_here HTTP/1.0", so it works when the ** identifier is after either the first or the second ** whitespace. */ uri_ptr->ident = *end_sp; uri_ptr->uri_end = *start_sp; } /* ** We found a non-whitespace char */ return HI_SUCCESS; } } /* ** This is the case where we've seen text and found a whitespace until ** the end of the buffer. In that case, we set the uri_end to the ** beginning of the whitespace. */ uri_ptr->uri_end = *start_sp; return HI_OUT_OF_BOUNDS;}/*** NAME** SetPercentNorm::*//**** Check for percent normalization in the URI buffer.** ** We don't do much here besides check the configuration, set the pointer,** and continue processing.**** @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 SetPercentNorm(HI_SESSION *Session, u_char *start, u_char *end, u_char **ptr, URI_PTR *uri_ptr){ HTTPINSPECT_CONF *ServerConf = Session->server_conf; if(!uri_ptr->norm && !uri_ptr->ident) { if(ServerConf->ascii.on) { uri_ptr->norm = *ptr; } } (*ptr)++; return HI_SUCCESS;}/*** NAME** CheckLongDir::*//**** We check the directory length against the global config.** ** @param Session pointer to the current session** @param uri_ptr pointer to the URI state** @param ptr pointer to the current index in buffer** ** @return integer** ** @retval HI_SUCCESS*/static INLINE int CheckLongDir(HI_SESSION *Session, URI_PTR *uri_ptr, u_char *ptr){ int iDirLen; /* ** Check for oversize directory */ if(Session->server_conf->long_dir && uri_ptr->last_dir && !uri_ptr->param) { iDirLen = ptr - uri_ptr->last_dir; if(iDirLen > Session->server_conf->long_dir) hi_eo_client_event_log(Session, HI_EO_CLIENT_OVERSIZE_DIR, NULL, NULL); } return HI_SUCCESS;}/*** NAME** SetSlashNorm::*//**** Check for any directory traversal or multi-slash normalization.** ** @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** @retval HI_OUT_OF_BOUNDS reached the end of the buffer*/static int SetSlashNorm(HI_SESSION *Session, u_char *start, u_char *end, 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, u_char *start, u_char *end, 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, u_char *start, u_char *end, 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, u_char *start, u_char *end, 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, u_char *start, u_char *end, 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)+1) == '/') { 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
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -