📄 hi_client.c
字号:
** Normalization is detected when we are looking at the packet for the URI.** We look for the following issues:** - ////** - /../** - /./** - non-ascii charss** - %** - \** When these things are seen we point to the first occurence in the URI, or** where we have to start normalizing. If the URI is updated to a new** pointer, then the normalization pointer is reset and we start over.** Using this method should cut down the memcpy()s per URI, since most** URIs are not normalized.** ** If this function returns HI_NONFATAL_ERR, we return out of mode_inspection** with an error and abort HttpInspect processing, and continue on with** any other processing we do. The Session parameters that we use here are** reset in the next time that we do session_inspection, so we don't do** any initialization here.** ** @param Session pointer to the HTTP session** @param data pointer to the start of the packet payload** @param dsize size of the payload** ** @return integer** ** @retval HI_INVALID_ARG invalid argument** @retval HI_NONFATAL_ERR no URI detected** @retval HI_SUCCESS URI detected and Session pointers updated*/static int StatelessInspection(HI_SESSION *Session, const unsigned char *data, int dsize){ HTTPINSPECT_CONF *ServerConf; HTTPINSPECT_CONF *ClientConf; HI_CLIENT *Client; URI_PTR uri_ptr; URI_PTR post_ptr; const u_char *start; const u_char *end; const u_char *ptr; int iRet; int len; if(!Session || !data || dsize < 1) { return HI_INVALID_ARG; } ServerConf = Session->server_conf; if(!ServerConf) { return HI_INVALID_ARG; } ClientConf = Session->client_conf; if(!ClientConf) { return HI_INVALID_ARG; } Client = &Session->client; memset(&uri_ptr, 0x00, sizeof(URI_PTR)); memset(&post_ptr, 0x00, sizeof(URI_PTR)); /* ** We set the starting boundary depending on whether this request is ** a normal request or a pipeline request. The end boundary is always ** the same whether it is a pipeline request or other. */ if(Client->request.pipeline_req) { start = Client->request.pipeline_req; } else { start = data; } end = data + dsize; ptr = start; /* ** Apache and IIS strike again . . . Thanks Kanatoko ** - Ignore CRLFs at the beginning of the request. */ while(hi_util_in_bounds(start, end, ptr)) { if(*ptr < 0x21) { if(*ptr < 0x0E && *ptr > 0x08) { ptr++; continue; } else { if(*ptr == 0x20) { ptr++; continue; } } } break; } uri_ptr.uri = ptr; uri_ptr.uri_end = end; len = end - ptr; /* Need slightly special handling for POST requests * Since we don't normalize on the request method itself, * just do a strcmp here and skip the characters below. */ if(len > 4 && !strncasecmp("POST", (const char *)ptr, 4)) { hi_stats.post++; Client->request.method = HI_POST_METHOD; } else if(len > 3 && !strncasecmp("GET", (const char *)ptr, 3)) { hi_stats.get++; Client->request.method = HI_GET_METHOD; } else { Client->request.method = HI_UNKNOWN_METHOD; } /* This will set up the URI pointers - effectively extracting * the URI. */ iRet = hi_client_extract_uri( Session, ServerConf, Client, start, end, ptr, &uri_ptr); if(iRet == URI_END && (Client->request.method & (HI_POST_METHOD | HI_GET_METHOD))) { /* Need to skip over header and get to the body. * The unaptly named FindPipelineReq will do that. */ ptr = FindPipelineReq(ptr, end); post_ptr.uri = ptr; post_ptr.uri_end = end; if(ptr && (POST_END == hi_client_extract_post( Session, ServerConf, ptr, end, &post_ptr))) { hi_stats.post_params++; Client->request.post_raw = post_ptr.uri; Client->request.post_raw_size = post_ptr.uri_end - post_ptr.uri; Client->request.post_norm = post_ptr.norm; } else { Client->request.post_raw = NULL; Client->request.post_raw_size = 0; Client->request.post_norm = NULL; } } else { Client->request.post_raw = NULL; Client->request.post_raw_size = 0; Client->request.post_norm = NULL; } /* ** If there is a pipelined request in this packet, we should always ** see the first space followed by text (which is the URI). Without ** that first space, then we never get to the URI, so we should just ** return, since there is nothing else to inspect. */ if(Client->request.pipeline_req) { if(uri_ptr.uri != uri_ptr.first_sp_end) { if(Session->server_conf->chunk_length) CheckChunkEncoding(Session, start, end); return HI_NONFATAL_ERR; } } /* ** We set the HI_CLIENT variables from the URI_PTR structure. We also ** do error checking for the values in this routine as well. */ iRet = SetClientVars(Client, &uri_ptr, dsize); if (iRet) { return iRet; } /* ** One last check for an oversize directory. This gets the long ** directory when there is a beginning slash and no other slashes ** until the end of the packet. ** ** We do this check after we set the variables, just in case there ** was some errors while setting the variables. This could save some ** false positives on a bad URI setting. */ if(uri_ptr.uri_end) CheckLongDir(Session, &uri_ptr, uri_ptr.uri_end); /* ** Check for absolute URI and alert for proxy comm if necessary ** ** NOTE: ** Also check ClientConf for proxy configuration so we don't ** alert on outbound requests from legitimate proxies. */ if(uri_ptr.proxy && Session->global_conf->proxy_alert && (!ServerConf->allow_proxy && !ClientConf->allow_proxy)) { if(hi_eo_generate_event(Session, HI_EO_CLIENT_PROXY_USE)) { hi_eo_client_event_log(Session, HI_EO_CLIENT_PROXY_USE, NULL, NULL); } } /* ** Find the next pipeline request, if one is there. If we don't find ** a pipeline request, then we return NULL here, so this is always ** set to the correct value. */ if(!ServerConf->no_pipeline) { Client->request.pipeline_req = FindPipelineReq(uri_ptr.delimiter, end); } else { Client->request.pipeline_req = NULL; } if(Session->server_conf->chunk_length) CheckChunkEncoding(Session, uri_ptr.delimiter, end); return HI_SUCCESS;}int hi_client_inspection(void *S, const unsigned char *data, int dsize){ HTTPINSPECT_GLOBAL_CONF *GlobalConf; HI_SESSION *Session; int iRet; if(!S || !data || dsize < 1) { return HI_INVALID_ARG; } Session = (HI_SESSION *)S; if(!Session->global_conf) { return HI_INVALID_ARG; } GlobalConf = Session->global_conf; /* ** We inspect the HTTP protocol in either stateful mode or ** stateless mode. */ if(GlobalConf->inspection_type == HI_UI_CONFIG_STATEFUL) { /* ** This is where we do stateful inspection. */ return HI_NONFATAL_ERR; } else { /* ** Otherwise we assume stateless inspection */ iRet = StatelessInspection(Session, data, dsize); if (iRet) { return iRet; } } return HI_SUCCESS;}/*** NAME** hi_client_init::*//**** Initializes arrays and search algorithms depending on the type of** inspection that we are doing.** ** @param GlobalConf pointer to the global configuration** ** @return integer** ** @retval HI_SUCCESS function successful.*/int hi_client_init(HTTPINSPECT_GLOBAL_CONF *GlobalConf){ int iCtr; int iNum; if(GlobalConf->inspection_type == HI_UI_CONFIG_STATEFUL) { /* ** We don't have to do anything here yet. */ } else { memset(lookup_table, 0x00, sizeof(lookup_table)); memset(hex_lookup, -1, sizeof(hex_lookup)); /* ** Set up the non-ASCII register for processing. */ for(iCtr = 0x80; iCtr <= 0xff; iCtr++) { lookup_table[iCtr] = SetBinaryNorm; } lookup_table[0x00] = SetBinaryNorm; lookup_table[' '] = NextNonWhiteSpace; lookup_table['\r'] = find_rfc_delimiter; lookup_table['\n'] = find_non_rfc_delimiter; /* ** ASCII encoding */ lookup_table['%'] = SetPercentNorm; /* ** Looking for multiple slashes */ lookup_table['/'] = SetSlashNorm; /* ** Looking for backslashs */ lookup_table['\\'] = SetBackSlashNorm; /* ** Look up parameter field, so we don't alert on long directory ** strings, when the next slash in the parameter field. */ lookup_table['?'] = SetParamField; /* ** Look for absolute URI and proxy communication. */ lookup_table[':'] = SetProxy; /* ** Set up the hex array */ iNum = 0; for(iCtr = 48; iCtr < 58; iCtr++) { hex_lookup[iCtr] = iNum; iNum++; } /* ** Set the upper case values. */ iNum = 10; for(iCtr = 65; iCtr < 71; iCtr++) { hex_lookup[iCtr] = iNum; iNum++; } /* ** Set the lower case values. */ iNum = 10; for(iCtr = 97; iCtr < 103; iCtr++) { hex_lookup[iCtr] = iNum; iNum++; } } return HI_SUCCESS;}/**** This was just an initial testing program for these functions.*/#ifdef TEST_ME#include <sys/socket.h>#include <netinet/in.h>#include <arpa/inet.h>int main(int argc, char **argv){ HTTPINSPECT_GLOBAL_CONF GlobalConf; HI_SESSION *Session; HI_SI_INPUT SiInput; int iInspectMode = 0; int iRet; char data[] = "Hdslkfjaslfkj HTTP/00000.111111"; if((iRet = hi_ui_config_init_global_conf(&GlobalConf))) { printf("** error during global init.\n"); return iRet; } if((iRet = hi_ui_config_default(&GlobalConf))) { printf("** error config default.\n"); return iRet; } hi_ui_config_print_config(&GlobalConf); if((iRet = hi_client_init(&GlobalConf))) { printf("** error client init\n"); return iRet; } SiInput.sip = inet_addr("1.1.1.1"); SiInput.sip = inet_addr("1.1.1.2"); SiInput.dport = 80; SiInput.sport = 7880; if((iRet = hi_si_session_inspection(&GlobalConf, &Session, &SiInput, &iInspectMode))) { printf("** error session inspection\n"); return iRet; } printf("** iInspectMode = %d\n", iInspectMode); if((iRet = hi_mi_mode_inspection(Session, iInspectMode, data, strlen(data)))) { printf("** error mode_inspection\n"); return iRet; } return 0;}#endif
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -