📄 hi_client.c
字号:
** ** @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, 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;}/*** 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.** ** 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, unsigned char *data, int dsize){ HTTPINSPECT_CONF *ServerConf; HI_CLIENT *Client; URI_PTR uri_ptr; u_char *start; u_char *end; u_char *ptr; int iRet; if(!Session || !data || dsize < 1) { return HI_INVALID_ARG; } ServerConf = Session->server_conf; if(!ServerConf) { return HI_INVALID_ARG; } Client = &Session->client; memset(&uri_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; uri_ptr.uri = start; uri_ptr.uri_end = end; /* ** 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]) { if((iRet = (lookup_table[*ptr])(Session, start, end, &ptr, &uri_ptr))) { 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 */ { /* ** 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) { if((Client->request.pipeline_req = FindPipelineReq(ptr, end))) { return HI_SUCCESS; } } } if(Session->server_conf->chunk_length) CheckChunkEncoding(Session, start, end); 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++; } /* ** 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. */ if((iRet = SetClientVars(Client, &uri_ptr, dsize))) { 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. */ CheckLongDir(Session, &uri_ptr, ptr); /* ** Check for absolute URI and alert for proxy comm if necessary */ if(uri_ptr.proxy && Session->global_conf->proxy_alert && !ServerConf->allow_proxy) { 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(Client->request.pipeline_req) printf("** pipeline_req = %c\n", *Client->request.pipeline_req); */ if(!Client->request.pipeline_req) { if(Session->server_conf->chunk_length) CheckChunkEncoding(Session, uri_ptr.delimiter, end); } return HI_SUCCESS;}int hi_client_inspection(void *S, 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 */ if((iRet = StatelessInspection(Session, data, dsize))) { 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['\t'] = 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 + -