/** * Extracts chunk length. * * @param[in] connp * @returns HTP_OK on state change, HTP_ERROR on error, or HTP_DATA when more data is needed. */ htp_status_t htp_connp_RES_BODY_CHUNKED_LENGTH(htp_connp_t *connp) { for (;;) { OUT_COPY_BYTE_OR_RETURN(connp); // Have we reached the end of the line? if (connp->out_next_byte == LF) { unsigned char *data; size_t len; if (htp_connp_res_consolidate_data(connp, &data, &len) != HTP_OK) { return HTP_ERROR; } connp->out_tx->response_message_len += len; #ifdef HTP_DEBUG fprint_raw_data(stderr, "Chunk length line", data, len); #endif htp_chomp(data, &len); connp->out_chunked_length = htp_parse_chunked_length(data, len); htp_connp_res_clear_buffer(connp); // Handle chunk length if (connp->out_chunked_length > 0) { // More data available connp->out_state = htp_connp_RES_BODY_CHUNKED_DATA; } else if (connp->out_chunked_length == 0) { // End of data connp->out_state = htp_connp_RES_HEADERS; connp->out_tx->response_progress = HTP_RESPONSE_TRAILER; } else { // Invalid chunk length htp_log(connp, HTP_LOG_MARK, HTP_LOG_ERROR, 0, "Response chunk encoding: Invalid chunk length: %d", connp->out_chunked_length); return HTP_ERROR; } return HTP_OK; } } return HTP_ERROR; }
/** * Extracts chunk length. * * @param[in] connp * @returns HTP_OK on state change, HTP_ERROR on error, or HTP_DATA when more data is needed. */ htp_status_t htp_connp_REQ_BODY_CHUNKED_LENGTH(htp_connp_t *connp) { for (;;) { IN_COPY_BYTE_OR_RETURN(connp); // Have we reached the end of the line? if (connp->in_next_byte == LF) { unsigned char *data; size_t len; htp_connp_req_consolidate_data(connp, &data, &len); connp->in_tx->request_message_len += len; #ifdef HTP_DEBUG fprint_raw_data(stderr, "Chunk length line", data, len); #endif htp_chomp(data, &len); connp->in_chunked_length = htp_parse_chunked_length(data, len); htp_connp_req_clear_buffer(connp); // Handle chunk length. if (connp->in_chunked_length > 0) { // More data available. // TODO Add a check (flag) for excessive chunk length. connp->in_state = htp_connp_REQ_BODY_CHUNKED_DATA; } else if (connp->in_chunked_length == 0) { // End of data connp->in_state = htp_connp_REQ_HEADERS; connp->in_tx->request_progress = HTP_REQUEST_TRAILER; } else { // Invalid chunk length. htp_log(connp, HTP_LOG_MARK, HTP_LOG_ERROR, 0, "Request chunk encoding: Invalid chunk length"); return HTP_ERROR; } return HTP_OK; } } return HTP_ERROR; }
/** * Extracts chunk length. * * @param connp * @returns HTP_OK on state change, HTTP_ERROR on error, or HTP_DATA when more data is needed. */ int htp_connp_REQ_BODY_CHUNKED_LENGTH(htp_connp_t *connp) { for (;;) { IN_COPY_BYTE_OR_RETURN(connp); connp->in_tx->request_message_len++; // Have we reached the end of the line? if (connp->in_next_byte == LF) { htp_chomp(connp->in_line, &connp->in_line_len); // Extract chunk length connp->in_chunked_length = htp_parse_chunked_length(connp->in_line, connp->in_line_len); // Cleanup for the next line connp->in_line_len = 0; // Handle chunk length if (connp->in_chunked_length > 0) { // More data available // TODO Add a check for chunk length connp->in_state = htp_connp_REQ_BODY_CHUNKED_DATA; } else if (connp->in_chunked_length == 0) { // End of data connp->in_state = htp_connp_REQ_HEADERS; connp->in_tx->progress[0] = TX_PROGRESS_REQ_TRAILER; } else { // Invalid chunk length htp_log(connp, HTP_LOG_MARK, HTP_LOG_ERROR, 0, "Request chunk encoding: Invalid chunk length"); return HTP_ERROR; } return HTP_OK; } } return HTP_ERROR; }
TEST(UtilTest, ParseChunkedLength) { EXPECT_EQ(0x12a5, htp_parse_chunked_length((unsigned char*)"12a5",4)); }