📄 hi_norm.c
字号:
return iNorm;}/*** NAME** GetChar::*//**** Wrapper for PercentDecode() and handles the return values from** PercentDecode().** ** This really decodes the chars for UnicodeDecode(). If the char is** a percent then we process stuff, otherwise we just increment the** pointer and return.** ** @param ServerConf the server configuration** @param start the start of the URI** @param end the end of the URI** @param ptr the current pointer into the URI** @param bare_byte value for a non-ASCII char or a decoded non-ASCII char** ** @return integer** ** @retval END_OF_BUFFER End of the buffer has been reached before decode.** @retval NON_ASCII_CHAR End of buffer during decoding, return decoded char.** @retval char return the valid decoded/undecoded char** ** @see PercentDecode()** @see GetByte()*/static int GetChar(HI_SESSION *Session, const u_char *start, const u_char *end, const u_char **ptr, int *bare_byte, URI_NORM_STATE *norm_state){ HTTPINSPECT_CONF *ServerConf = Session->server_conf; int iNorm; if(!hi_util_in_bounds(start, end, *ptr)) return END_OF_BUFFER; iNorm = (int)(**ptr); if(**ptr == '%' && ServerConf->ascii.on) { /* ** We go into percent encoding. */ iNorm = PercentDecode(Session, start, end, ptr, norm_state); /* ** If during the course of PercentDecode() we run into the end ** of the buffer, then we return early (WITHOUT INCREMENTING ptr) ** with a NON_ASCII_CHAR. */ if(iNorm == END_OF_BUFFER) return NON_ASCII_CHAR; *bare_byte = 0; } else { if(ServerConf->bare_byte.on && (u_char)iNorm > 0x7f) { if(hi_eo_generate_event(Session, ServerConf->bare_byte.alert) && !norm_state->param) { hi_eo_client_event_log(Session, HI_EO_CLIENT_BARE_BYTE, NULL, NULL); } /* ** Set the bare_byte flag */ *bare_byte = 0; } else { /* ** Set the bare_byte flag negative. */ *bare_byte = 1; } } /* ** Increment the buffer. */ (*ptr)++; return iNorm;}/*** NAME** UTF8Decode::*//*** Decode the UTF-8 sequences and check for valid codepoints via the** Unicode standard and the IIS standard.** ** We decode up to 3 bytes of UTF-8 because that's all I've been able to** get to work on various servers, so let's reduce some false positives.** So we decode valid UTF-8 sequences and then check the value. If the** value is ASCII, then it's decoded to that. Otherwise, if iis_unicode** is turned on, we will check the unicode codemap for valid IIS mappings.** If a mapping turns up, then we return the mapped ASCII.** ** @param ServerConf the server configuration** @param start the start of the URI** @param end the end of the URI** @param ptr the current pointer into the URI** ** @return integer** ** @retval NON_ASCII_CHAR Reached end of buffer while decoding** @retval char return the decoded or badly decoded char** ** @see GetByte()** @see UnicodeDecode()*/static int UTF8Decode(HI_SESSION *Session, const u_char *start, const u_char *end, const u_char **ptr, int iFirst, URI_NORM_STATE *norm_state){ HTTPINSPECT_CONF *ServerConf = Session->server_conf; int iBareByte; int iNorm; int iNumBytes; int iCtr; int iByte; /* ** Right now we support up to 3 byte unicode sequences. We can add ** more if any of the HTTP servers support more. */ if((iFirst & 0xe0) == 0xc0) { iNumBytes = 1; iNorm = iFirst & 0x1f; } else if((iFirst & 0xf0) == 0xe0) { iNumBytes = 2; iNorm = iFirst & 0x0f; } else { hi_stats.non_ascii++; /* ** This means that we have an invalid first sequence byte for ** a unicode sequence. So we just return the byte and move on. */ return iFirst; } /* ** This is the main loop for UTF-8 decoding. We check for the only ** valid sequence after the first byte whish is 0x80. Otherwise, ** it was invalid and we setnd a NON_ASCII_CHAR and continue on ** with our processing. */ for(iCtr = 0; iCtr < iNumBytes; iCtr++) { iByte = GetChar(Session, start, end, ptr, &iBareByte, norm_state); if(iByte == END_OF_BUFFER || iByte == NON_ASCII_CHAR || iBareByte) return NON_ASCII_CHAR; if((iByte & 0xc0) == 0x80) { iNorm <<= 6; iNorm |= (iByte & 0x3f); } else { hi_stats.non_ascii++; /* ** This means that we don't have a valid unicode sequence, so ** we just bail. */ return NON_ASCII_CHAR; } } /* ** Check for unicode as ASCII and if there is not an ASCII char then ** we return the space holder char. */ if(iNorm > 0x7f) { if(ServerConf->iis_unicode.on) { iNorm = ServerConf->iis_unicode_map[iNorm]; if(iNorm == HI_UI_NON_ASCII_CODEPOINT) { iNorm = NON_ASCII_CHAR; } if(hi_eo_generate_event(Session, ServerConf->iis_unicode.alert) && !norm_state->param) { hi_eo_client_event_log(Session, HI_EO_CLIENT_IIS_UNICODE, NULL, NULL); } hi_stats.unicode++; return iNorm; } else { hi_stats.non_ascii++; iNorm = NON_ASCII_CHAR; } } if(hi_eo_generate_event(Session, ServerConf->utf_8.alert) && !norm_state->param) { hi_eo_client_event_log(Session, HI_EO_CLIENT_UTF_8, NULL, NULL); } return iNorm;}/*** NAME** UnicodeDecode::*//**** Checks for the ServerConf values before we actually decode.** ** This function is really a ServerConf wrapper for UTF8Decode.**** @param ServerConf the server configuration** @param start the start of the URI** @param end the end of the URI** @param ptr the current pointer into the URI** ** @return integer** ** @retval char the decode/undecoded byte.** ** @see GetByte()*/static int UnicodeDecode(HI_SESSION *Session, const u_char *start, const u_char *end, const u_char **ptr, int iFirst, URI_NORM_STATE *norm_state){ HTTPINSPECT_CONF *ServerConf = Session->server_conf; int iNorm = iFirst; if(ServerConf->iis_unicode.on || ServerConf->utf_8.on) { iNorm = UTF8Decode(Session, start, end, ptr, iFirst, norm_state); } return iNorm;}/*** NAME** GetByte::*//**** Handles the first stage of URI decoding for the case of IIS double** decoding.** ** The first stage consists of ASCII decoding and unicode decoding. %U** decoding is handled in the ASCII decoding.** ** @param ServerConf the server configuration** @param start the start of the URI** @param end the end of the URI** @param ptr the current pointer into the URI** ** @return integer** ** @retval END_OF_BUFFER means that we've reached the end of buffer in** GetChar.** @retval iChar this is the character that was decoded.*/static int GetByte(HI_SESSION *Session, const u_char *start, const u_char *end, const u_char **ptr, URI_NORM_STATE *norm_state){ int iChar; int iBareByte; iChar = GetChar(Session, start, end, ptr, &iBareByte, norm_state); if(iChar == END_OF_BUFFER) return END_OF_BUFFER; if (iChar == NON_ASCII_CHAR) return NON_ASCII_CHAR; /* ** We now check for unicode bytes */ if((iChar & 0x80) && !iBareByte) { iChar = UnicodeDecode(Session, start, end, ptr, iChar, norm_state); } return iChar;}/*** NAME** DoubleDecode::*//**** The double decoding routine for IIS good times.** ** Coming into this function means that we just decoded a % or that** we just saw two percents in a row. We know which state we are** in depending if the first char is a '%' or not.**** In the IIS world, there are two decodes, but only some of the decode** options are valid. All options are valid in the first decode** stage, but the second decode stage only supports:** - %u encoding** - ascii**** Knowing this, we can decode appropriately.** ** @param ServerConf the server configuration** @param start the start of the URI** @param end the end of the URI** @param ptr the current pointer into the URI** @param norm_state the ptr to the URI norm state** ** @return integer** ** @retval NON_ASCII_CHAR End of buffer reached while decoding** @retval char The decoded char*/static int DoubleDecode(HI_SESSION *Session, const u_char *start, const u_char *end, const u_char **ptr, URI_NORM_STATE *norm_state){ HTTPINSPECT_CONF *ServerConf = Session->server_conf; int iByte; int iNorm; const u_char *orig_ptr; orig_ptr = *ptr; /* ** We now know that we have seen a previous % and that we need to ** decode the remaining bytes. We are in one of multiple cases: ** ** - %25xxxx ** - %%xx%xx ** - %u0025xxxx ** - etc. ** ** But, the one common factor is that they each started out with a ** % encoding of some type. ** ** So now we just get the remaining bytes and do the processing ** ourselves in this routine. */ iByte = GetByte(Session, start, end, ptr, norm_state); if(iByte == END_OF_BUFFER) return NON_ASCII_CHAR; if(valid_lookup[(u_char)iByte] < 0) { if(ServerConf->u_encoding.on && (toupper(iByte) == 'U')) { iNorm = UDecode(Session, start, end, ptr, GetByte, norm_state); if(iNorm == END_OF_BUFFER) { /* ** We have reached the end of the buffer while ** processing a U encoding. We keep the current ** pointer and return a NON_ASCII char for the ** bad encoding. */ return NON_ASCII_CHAR; } return iNorm; } return iByte; } iNorm = (hex_lookup[(u_char)iByte]<<4); iByte = GetByte(Session, start, end, ptr, norm_state); if(iByte == END_OF_BUFFER) return NON_ASCII_CHAR; if(valid_lookup[(u_char)iByte] < 0) { return iByte; } iNorm = (iNorm | (hex_lookup[(u_char)iByte])) & 0xff; if(hi_eo_generate_event(Session, ServerConf->double_decoding.alert) && (norm_state->param == NULL)) { hi_eo_client_event_log(Session, HI_EO_CLIENT_DOUBLE_DECODE, NULL, NULL);
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -