/** * 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 urlenp * @param data * @param startpos * @param endpos * @param 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, unsigned char *data, size_t startpos, size_t endpos, int c) { // Add field if we know it ended or if we know that // we've used all of the input data if ((c != -1) || (urlenp->_complete)) { // Add field 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 (endpos - startpos > 0) { bstr_builder_append_mem(urlenp->_bb, (char *) 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 field = bstr_dup_mem((char *) data + startpos, endpos - startpos); if (field == NULL) return; } // Process the field differently, depending on the current state if (urlenp->_state == HTP_URLENP_STATE_KEY) { // Store the name for later urlenp->_name = field; if (urlenp->_complete) { // Param with key but no value bstr *name = urlenp->_name; bstr *value = bstr_dup_c(""); if (urlenp->decode_url_encoding) { // htp_uriencoding_normalize_inplace(name); htp_decode_urlencoded_inplace(urlenp->tx->connp->cfg, urlenp->tx, name); } table_addn(urlenp->params, name, value); urlenp->_name = NULL; #ifdef HTP_DEBUG fprint_raw_data(stderr, "NAME", (unsigned char *) bstr_ptr(name), bstr_len(name)); fprint_raw_data(stderr, "VALUE", (unsigned char *) bstr_ptr(value), bstr_len(value)); #endif } } else { // Param with key and value bstr *name = urlenp->_name; bstr *value = field; if (urlenp->decode_url_encoding) { htp_decode_urlencoded_inplace(urlenp->tx->connp->cfg, urlenp->tx, name); htp_decode_urlencoded_inplace(urlenp->tx->connp->cfg, urlenp->tx, value); } table_addn(urlenp->params, name, value); urlenp->_name = NULL; #ifdef HTP_DEBUG fprint_raw_data(stderr, "NAME", (unsigned char *) bstr_ptr(name), bstr_len(name)); fprint_raw_data(stderr, "VALUE", (unsigned char *) bstr_ptr(value), bstr_len(value)); #endif } } else { // Make a copy of the data and store it in an array for later if (endpos - startpos > 0) { bstr_builder_append_mem(urlenp->_bb, (char *) data + startpos, endpos - startpos); } } }
/** * Transcode all parameters supplied in the table. * * @param connp * @param params * @param destroy_old */ int htp_transcode_params(htp_connp_t *connp, table_t **params, int destroy_old) { table_t *input_params = *params; // No transcoding unless necessary if (connp->cfg->internal_encoding == NULL) { return HTP_OK; } // Create a new table that will hold transcoded parameters table_t *output_params = connp->cfg->create_table(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) { // TODO Report iconv initialization error 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; void *tvalue; table_iterator_reset(input_params); while ((name = table_iterator_next(input_params, &tvalue)) != NULL) { bstr *new_name = NULL, *new_value = NULL; bstr *value = (bstr *)tvalue; // Convert name htp_transcode_bstr(cd, name, &new_name); if (new_name == NULL) { iconv_close(cd); table_iterator_reset(output_params); while(table_iterator_next(output_params, &tvalue) != NULL) { bstr *b = (bstr *)tvalue; bstr_free(&b); } 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); table_iterator_reset(output_params); while(table_iterator_next(output_params, &tvalue) != NULL) { bstr *b = (bstr *)tvalue; bstr_free(&b); } table_destroy(&output_params); return HTP_ERROR; } // Add to new table 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) { table_iterator_reset(input_params); while(table_iterator_next(input_params, &tvalue) != NULL) { bstr *b = (bstr *)tvalue; bstr_free(&b); } table_destroy(&input_params); } iconv_close(cd); return HTP_OK; }