/** * Parses a single v0 request cookie and places the results into tx->request_cookies. * * @param[in] connp * @param[in] data * @param[in] len * @return HTP_OK on success, HTP_ERROR on error. */ int htp_parse_single_cookie_v0(htp_connp_t *connp, unsigned char *data, size_t len) { if (len == 0) return HTP_OK; size_t pos = 0; // Look for '=' while ((pos < len) && (data[pos] != '=')) pos++; if (pos == 0) return HTP_OK; // Ignore nameless cookies bstr *name = bstr_dup_mem(data, pos); if (name == NULL) return HTP_ERROR; bstr *value = NULL; if (pos == len) { // Cookie is empty value = bstr_dup_c(""); } else { // Cookie is not empty value = bstr_dup_mem(data + pos + 1, len - pos - 1); } if (value == NULL) { bstr_free(name); return HTP_ERROR; } // Add cookie directly htp_table_addn(connp->in_tx->request_cookies, name, value); return HTP_OK; }
/** * Transcode all parameters supplied in the table. * * @param[in] connp * @param[in] params * @param[in] destroy_old */ int htp_transcode_params(htp_connp_t *connp, htp_table_t **params, int destroy_old) { htp_table_t *input_params = *params; // No transcoding unless necessary if ((connp->cfg->internal_encoding == NULL)||(connp->cfg->request_encoding == NULL)) return HTP_OK; // Create a new table that will hold transcoded parameters htp_table_t *output_params = htp_table_create(htp_table_size(input_params)); if (output_params == NULL) return HTP_ERROR; // Initialize iconv iconv_t cd = iconv_open(connp->cfg->internal_encoding, connp->cfg->request_encoding); if (cd == (iconv_t) -1) { htp_table_destroy(output_params); return HTP_ERROR; } #if (_LIBICONV_VERSION >= 0x0108) int iconv_param = 0; iconvctl(cd, ICONV_SET_TRANSLITERATE, &iconv_param); iconv_param = 1; iconvctl(cd, ICONV_SET_DISCARD_ILSEQ, &iconv_param); #endif // Convert the parameters, one by one bstr *name = NULL; bstr *value = NULL; for (int i = 0, n = htp_table_size(input_params); i < n; i++) { value = htp_table_get_index(input_params, i, &name); bstr *new_name = NULL, *new_value = NULL; // Convert name htp_transcode_bstr(cd, name, &new_name); if (new_name == NULL) { iconv_close(cd); bstr *b = NULL; for (int j = 0, k = htp_table_size(output_params); j < k; j++) { b = htp_table_get_index(output_params, j, NULL); bstr_free(b); } htp_table_destroy(output_params); return HTP_ERROR; } // Convert value htp_transcode_bstr(cd, value, &new_value); if (new_value == NULL) { bstr_free(new_name); iconv_close(cd); bstr *b = NULL; for (int j = 0, k = htp_table_size(output_params); j < k; j++) { b = htp_table_get_index(output_params, j, NULL); bstr_free(b); } htp_table_destroy(output_params); return HTP_ERROR; } // Add to new table htp_table_addn(output_params, new_name, new_value); } // Replace the old parameter table *params = output_params; // Destroy the old parameter table if necessary if (destroy_old) { bstr *b = NULL; for (int i = 0, n = htp_table_size(input_params); i < n; i++) { b = htp_table_get_index(input_params, i, NULL); bstr_free(b); } htp_table_destroy(input_params); } iconv_close(cd); return HTP_OK; }
/** * This method is invoked whenever a piece of data, belonging to a single field (name or value) * becomes available. It will either create a new parameter or store the transient information * until a parameter can be created. * * @param[in] urlenp * @param[in] data * @param[in] startpos * @param[in] endpos * @param[in] c Should contain -1 if the reason this function is called is because the end of * the current data chunk is reached. */ static void htp_urlenp_add_field_piece(htp_urlenp_t *urlenp, const unsigned char *data, size_t startpos, size_t endpos, int last_char) { // Add field if we know it ended (last_char is something other than -1) // or if we know that there won't be any more input data (urlenp->_complete is true). if ((last_char != -1) || (urlenp->_complete)) { // Prepare the field value, assembling from multiple pieces as necessary. bstr *field = NULL; // Did we use the string builder for this field? if (bstr_builder_size(urlenp->_bb) > 0) { // The current field consists of more than once piece, we have to use the string builder. // Add current piece to string builder. if ((data != NULL) && (endpos - startpos > 0)) { bstr_builder_append_mem(urlenp->_bb, data + startpos, endpos - startpos); } // Generate the field and clear the string builder. field = bstr_builder_to_str(urlenp->_bb); if (field == NULL) return; bstr_builder_clear(urlenp->_bb); } else { // We only have the current piece to work with, so no need to involve the string builder. if ((data != NULL) && (endpos - startpos > 0)) { field = bstr_dup_mem(data + startpos, endpos - startpos); if (field == NULL) return; } } // Process field as key or value, as appropriate. if (urlenp->_state == HTP_URLENP_STATE_KEY) { // Key. // If there is no more work left to do, then we have a single key. Add it. if ((urlenp->_complete)||(last_char == urlenp->argument_separator)) { // Handling empty pairs is tricky. We don't want to create a pair for // an entirely empty input, but in some cases it may be appropriate // (e.g., /index.php?&q=2). if ((field != NULL)||(last_char == urlenp->argument_separator)) { // Add one pair, with an empty value and possibly empty key too. bstr *name = field; if (name == NULL) { name = bstr_dup_c(""); if (name == NULL) return; } bstr *value = bstr_dup_c(""); if (value == NULL) { bstr_free(name); return; } if (urlenp->decode_url_encoding) { htp_tx_urldecode_params_inplace(urlenp->tx, name); } htp_table_addn(urlenp->params, name, value); urlenp->_name = NULL; #ifdef HTP_DEBUG fprint_raw_data(stderr, "NAME", bstr_ptr(name), bstr_len(name)); fprint_raw_data(stderr, "VALUE", bstr_ptr(value), bstr_len(value)); #endif } } else { // This key will possibly be followed by a value, so keep it for later. urlenp->_name = field; } } else { // Value (with a key remembered from before). bstr *name = urlenp->_name; urlenp->_name = NULL; if (name == NULL) { name = bstr_dup_c(""); if (name == NULL) { bstr_free(field); return; } } bstr *value = field; if (value == NULL) { value = bstr_dup_c(""); if (value == NULL) { bstr_free(name); return; } } if (urlenp->decode_url_encoding) { htp_tx_urldecode_params_inplace(urlenp->tx, name); htp_tx_urldecode_params_inplace(urlenp->tx, value); } htp_table_addn(urlenp->params, name, value); #ifdef HTP_DEBUG fprint_raw_data(stderr, "NAME", bstr_ptr(name), bstr_len(name)); fprint_raw_data(stderr, "VALUE", bstr_ptr(value), bstr_len(value)); #endif } } else { // The field has not ended. We'll make a copy of of the available data for later. if ((data != NULL) && (endpos - startpos > 0)) { bstr_builder_append_mem(urlenp->_bb, data + startpos, endpos - startpos); } } }