/** * Creates a new URLENCODED parser. * * @return New parser, or NULL on memory allocation failure. */ htp_urlenp_t *htp_urlenp_create(htp_tx_t *tx) { htp_urlenp_t *urlenp = calloc(1, sizeof (htp_urlenp_t)); if (urlenp == NULL) return NULL; urlenp->tx = tx; urlenp->params = htp_table_create(HTP_URLENP_DEFAULT_PARAMS_SIZE); if (urlenp->params == NULL) { free(urlenp); return NULL; } urlenp->_bb = bstr_builder_create(); if (urlenp->_bb == NULL) { htp_table_destroy(urlenp->params); free(urlenp); return NULL; } urlenp->argument_separator = '&'; urlenp->decode_url_encoding = 1; urlenp->_state = HTP_URLENP_STATE_KEY; return urlenp; }
void htp_table_destroy_ex(htp_table_t *table) { if (table == NULL) return; // Change allocation strategy in order to // prevent the keys from being freed. table->alloc_type = HTP_TABLE_KEYS_REFERENCED; htp_table_destroy(table); }
htp_status_t htp_tx_res_set_headers_clear(htp_tx_t *tx) { if ((tx == NULL) || (tx->response_headers == NULL)) return HTP_ERROR; htp_header_t *h = NULL; for (size_t i = 0, n = htp_table_size(tx->response_headers); i < n; i++) { h = htp_table_get_index(tx->response_headers, i, NULL); bstr_free(h->name); bstr_free(h->value); free(h); } htp_table_destroy(tx->response_headers); tx->response_headers = htp_table_create(32); if (tx->response_headers == NULL) return HTP_ERROR; return HTP_OK; }
/** * Destroys an existing URLENCODED parser. * * @param[in] urlenp */ void htp_urlenp_destroy(htp_urlenp_t *urlenp) { if (urlenp == NULL) return; if (urlenp->_name != NULL) { bstr_free(urlenp->_name); } bstr_builder_destroy(urlenp->_bb); if (urlenp->params != NULL) { // Destroy parameters. for (size_t i = 0, n = htp_table_size(urlenp->params); i < n; i++) { bstr *b = htp_table_get_index(urlenp->params, i, NULL); // Parameter name will be freed by the table code. bstr_free(b); } htp_table_destroy(urlenp->params); } free(urlenp); }
/** * 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; }
void htp_tx_destroy_incomplete(htp_tx_t *tx) { if (tx == NULL) return; // Disconnect transaction from other structures. htp_conn_remove_tx(tx->conn, tx); htp_connp_tx_remove(tx->connp, tx); // Request fields. bstr_free(tx->request_line); bstr_free(tx->request_method); bstr_free(tx->request_uri); bstr_free(tx->request_protocol); bstr_free(tx->request_content_type); bstr_free(tx->request_hostname); htp_uri_free(tx->parsed_uri_raw); htp_uri_free(tx->parsed_uri); // Request_headers. if (tx->request_headers != NULL) { htp_header_t *h = NULL; for (size_t i = 0, n = htp_table_size(tx->request_headers); i < n; i++) { h = htp_table_get_index(tx->request_headers, i, NULL); bstr_free(h->name); bstr_free(h->value); free(h); } htp_table_destroy(tx->request_headers); } // Request parsers. htp_urlenp_destroy(tx->request_urlenp_query); htp_urlenp_destroy(tx->request_urlenp_body); htp_mpartp_destroy(tx->request_mpartp); // Request parameters. htp_param_t *param = NULL; for (size_t i = 0, n = htp_table_size(tx->request_params); i < n; i++) { param = htp_table_get_index(tx->request_params, i, NULL); free(param->name); free(param->value); free(param); } htp_table_destroy(tx->request_params); // Request cookies. if (tx->request_cookies != NULL) { bstr *b = NULL; for (size_t i = 0, n = htp_table_size(tx->request_cookies); i < n; i++) { b = htp_table_get_index(tx->request_cookies, i, NULL); bstr_free(b); } htp_table_destroy(tx->request_cookies); } htp_hook_destroy(tx->hook_request_body_data); // Response fields. bstr_free(tx->response_line); bstr_free(tx->response_protocol); bstr_free(tx->response_status); bstr_free(tx->response_message); bstr_free(tx->response_content_type); // Destroy response headers. if (tx->response_headers != NULL) { htp_header_t *h = NULL; for (size_t i = 0, n = htp_table_size(tx->response_headers); i < n; i++) { h = htp_table_get_index(tx->response_headers, i, NULL); bstr_free(h->name); bstr_free(h->value); free(h); } htp_table_destroy(tx->response_headers); } // If we're using a private configuration structure, destroy it. if (tx->is_config_shared == HTP_CONFIG_PRIVATE) { htp_config_destroy(tx->cfg); } free(tx); }
void htp_tx_destroy(htp_tx_t *tx) { bstr_free(tx->request_line); bstr_free(tx->request_line_raw); bstr_free(tx->request_method); bstr_free(tx->request_uri); bstr_free(tx->request_uri_normalized); bstr_free(tx->request_protocol); bstr_free(tx->request_headers_sep); if (tx->parsed_uri != NULL) { bstr_free(tx->parsed_uri->scheme); bstr_free(tx->parsed_uri->username); bstr_free(tx->parsed_uri->password); bstr_free(tx->parsed_uri->hostname); bstr_free(tx->parsed_uri->port); bstr_free(tx->parsed_uri->path); bstr_free(tx->parsed_uri->query); bstr_free(tx->parsed_uri->fragment); free(tx->parsed_uri); } if (tx->parsed_uri_incomplete != NULL) { bstr_free(tx->parsed_uri_incomplete->scheme); bstr_free(tx->parsed_uri_incomplete->username); bstr_free(tx->parsed_uri_incomplete->password); bstr_free(tx->parsed_uri_incomplete->hostname); bstr_free(tx->parsed_uri_incomplete->port); bstr_free(tx->parsed_uri_incomplete->path); bstr_free(tx->parsed_uri_incomplete->query); bstr_free(tx->parsed_uri_incomplete->fragment); free(tx->parsed_uri_incomplete); } // Destroy request_header_lines. if (tx->request_header_lines != NULL) { for (int i = 0, n = htp_list_size(tx->request_header_lines); i < n; i++) { htp_header_line_t *hl = htp_list_get(tx->request_header_lines, i); bstr_free(hl->line); // No need to destroy hl->header because // htp_header_line_t does not own it. free(hl); } htp_list_destroy(tx->request_header_lines); tx->request_header_lines = NULL; } // Destroy request_headers. if (tx->request_headers != NULL) { htp_header_t *h = NULL; for (int i = 0, n = htp_table_size(tx->request_headers); i < n; i++) { h = htp_table_get_index(tx->request_headers, i, NULL); bstr_free(h->name); bstr_free(h->value); free(h); } htp_table_destroy(tx->request_headers); } if (tx->request_headers_raw != NULL) { bstr_free(tx->request_headers_raw); } if (tx->response_headers_raw != NULL) { bstr_free(tx->response_headers_raw); } bstr_free(tx->response_line); bstr_free(tx->response_line_raw); bstr_free(tx->response_protocol); bstr_free(tx->response_status); bstr_free(tx->response_message); bstr_free(tx->response_headers_sep); // Destroy response_header_lines. if (tx->response_header_lines != NULL) { for (int i = 0, n = htp_list_size(tx->response_header_lines); i < n; i++) { htp_header_line_t *hl = htp_list_get(tx->response_header_lines, i); bstr_free(hl->line); // No need to destroy hl->header because // htp_header_line_t does not own it. free(hl); } htp_list_destroy(tx->response_header_lines); tx->response_header_lines = NULL; } // Destroy response headers. if (tx->response_headers != NULL) { htp_header_t *h = NULL; for (int i = 0, n = htp_table_size(tx->response_headers); i < n; i++) { h = htp_table_get_index(tx->response_headers, i, NULL); bstr_free(h->name); bstr_free(h->value); free(h); } htp_table_destroy(tx->response_headers); } // Tell the connection to remove this transaction from the list. htp_conn_remove_tx(tx->conn, tx); // Invalidate the pointer to this transactions held // by the connection parser. This is to allow a transaction // to be destroyed from within the final response callback. if (tx->connp != NULL) { if (tx->connp->out_tx == tx) { tx->connp->out_tx = NULL; } } bstr_free(tx->request_content_type); bstr_free(tx->response_content_type); // Parsers htp_urlenp_destroy(tx->request_urlenp_query); htp_urlenp_destroy(tx->request_urlenp_body); htp_mpartp_destroy(tx->request_mpartp); // Request parameters htp_param_t *param = NULL; for (int i = 0, n = htp_table_size(tx->request_params); i < n; i++) { param = htp_table_get_index(tx->request_params, i, NULL); free(param->name); free(param->value); free(param); } htp_table_destroy(tx->request_params); // Request cookies if (tx->request_cookies != NULL) { bstr *b = NULL; for (int i = 0, n = htp_table_size(tx->request_cookies); i < n; i++) { b = htp_table_get_index(tx->request_cookies, i, NULL); bstr_free(b); } htp_table_destroy(tx->request_cookies); } htp_hook_destroy(tx->hook_request_body_data); // If we're using a private configuration, destroy it. if (tx->is_config_shared == HTP_CONFIG_PRIVATE) { htp_config_destroy(tx->cfg); } free(tx); }