From deabb1e506ae678eeec608649388a082ada7c11a Mon Sep 17 00:00:00 2001 From: Matyja Lukas Adam Date: Tue, 24 Oct 2023 09:17:40 +0200 Subject: [lib] delete some files --- src/lib/auditor_api_curl_defaults.c | 61 -- src/lib/auditor_api_curl_defaults.h | 38 - src/lib/auditor_api_deposit_confirmation.c | 418 -------- src/lib/auditor_api_exchanges.c | 244 ----- src/lib/auditor_api_get_config.c | 288 ----- src/lib/exchange_api_age_withdraw.c | 1117 -------------------- src/lib/exchange_api_age_withdraw_reveal.c | 471 --------- src/lib/exchange_api_auditor_add_denomination.c | 238 ----- src/lib/exchange_api_csr_melt.c | 317 ------ src/lib/exchange_api_kyc_check.c | 329 ------ src/lib/exchange_api_kyc_proof.c | 217 ---- src/lib/exchange_api_kyc_wallet.c | 230 ---- src/lib/exchange_api_lookup_aml_decision.c | 419 -------- src/lib/exchange_api_lookup_aml_decisions.c | 378 ------- src/lib/exchange_api_management_add_partner.c | 218 ---- src/lib/exchange_api_management_auditor_disable.c | 219 ---- src/lib/exchange_api_management_auditor_enable.c | 224 ---- src/lib/exchange_api_management_drain_profits.c | 213 ---- src/lib/exchange_api_management_post_extensions.c | 213 ---- src/lib/exchange_api_management_post_keys.c | 237 ----- ...change_api_management_revoke_denomination_key.c | 221 ---- .../exchange_api_management_revoke_signing_key.c | 211 ---- src/lib/exchange_api_management_set_global_fee.c | 235 ---- src/lib/exchange_api_management_set_wire_fee.c | 227 ---- .../exchange_api_management_update_aml_officer.c | 229 ---- src/lib/exchange_api_management_wire_disable.c | 220 ---- src/lib/exchange_api_management_wire_enable.c | 245 ----- src/lib/exchange_api_melt.c | 596 ----------- src/lib/exchange_api_recoup.c | 369 ------- src/lib/exchange_api_recoup_refresh.c | 363 ------- src/lib/exchange_api_refresh_common.c | 249 ----- src/lib/exchange_api_refresh_common.h | 201 ---- src/lib/exchange_api_refreshes_reveal.c | 531 ---------- src/lib/exchange_api_refund.c | 480 --------- src/lib/exchange_api_stefan.c | 320 ------ src/lib/test_stefan.c | 206 ---- 36 files changed, 10992 deletions(-) delete mode 100644 src/lib/auditor_api_curl_defaults.c delete mode 100644 src/lib/auditor_api_curl_defaults.h delete mode 100644 src/lib/auditor_api_deposit_confirmation.c delete mode 100644 src/lib/auditor_api_exchanges.c delete mode 100644 src/lib/auditor_api_get_config.c delete mode 100644 src/lib/exchange_api_age_withdraw.c delete mode 100644 src/lib/exchange_api_age_withdraw_reveal.c delete mode 100644 src/lib/exchange_api_auditor_add_denomination.c delete mode 100644 src/lib/exchange_api_csr_melt.c delete mode 100644 src/lib/exchange_api_kyc_check.c delete mode 100644 src/lib/exchange_api_kyc_proof.c delete mode 100644 src/lib/exchange_api_kyc_wallet.c delete mode 100644 src/lib/exchange_api_lookup_aml_decision.c delete mode 100644 src/lib/exchange_api_lookup_aml_decisions.c delete mode 100644 src/lib/exchange_api_management_add_partner.c delete mode 100644 src/lib/exchange_api_management_auditor_disable.c delete mode 100644 src/lib/exchange_api_management_auditor_enable.c delete mode 100644 src/lib/exchange_api_management_drain_profits.c delete mode 100644 src/lib/exchange_api_management_post_extensions.c delete mode 100644 src/lib/exchange_api_management_post_keys.c delete mode 100644 src/lib/exchange_api_management_revoke_denomination_key.c delete mode 100644 src/lib/exchange_api_management_revoke_signing_key.c delete mode 100644 src/lib/exchange_api_management_set_global_fee.c delete mode 100644 src/lib/exchange_api_management_set_wire_fee.c delete mode 100644 src/lib/exchange_api_management_update_aml_officer.c delete mode 100644 src/lib/exchange_api_management_wire_disable.c delete mode 100644 src/lib/exchange_api_management_wire_enable.c delete mode 100644 src/lib/exchange_api_melt.c delete mode 100644 src/lib/exchange_api_recoup.c delete mode 100644 src/lib/exchange_api_recoup_refresh.c delete mode 100644 src/lib/exchange_api_refresh_common.c delete mode 100644 src/lib/exchange_api_refresh_common.h delete mode 100644 src/lib/exchange_api_refreshes_reveal.c delete mode 100644 src/lib/exchange_api_refund.c delete mode 100644 src/lib/exchange_api_stefan.c delete mode 100644 src/lib/test_stefan.c diff --git a/src/lib/auditor_api_curl_defaults.c b/src/lib/auditor_api_curl_defaults.c deleted file mode 100644 index 81fcd7bac..000000000 --- a/src/lib/auditor_api_curl_defaults.c +++ /dev/null @@ -1,61 +0,0 @@ -/* - This file is part of TALER - Copyright (C) 2014-2018 Taler Systems SA - - TALER is free software; you can redistribute it and/or modify it under the - terms of the GNU General Public License as published by the Free Software - Foundation; either version 3, or (at your option) any later version. - - TALER is distributed in the hope that it will be useful, but WITHOUT ANY - WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR - A PARTICULAR PURPOSE. See the GNU General Public License for more details. - - You should have received a copy of the GNU General Public License along with - TALER; see the file COPYING. If not, see - -*/ -/** - * @file lib/auditor_api_curl_defaults.c - * @brief curl easy handle defaults - * @author Florian Dold - */ -#include "auditor_api_curl_defaults.h" - - -CURL * -TALER_AUDITOR_curl_easy_get_ (const char *url) -{ - CURL *eh; - struct GNUNET_AsyncScopeSave scope; - - GNUNET_async_scope_get (&scope); - - eh = curl_easy_init (); - if (NULL == eh) - return NULL; - GNUNET_assert (CURLE_OK == - curl_easy_setopt (eh, - CURLOPT_URL, - url)); - GNUNET_assert (CURLE_OK == - curl_easy_setopt (eh, - CURLOPT_FOLLOWLOCATION, - 1L)); - /* Enable compression (using whatever curl likes), see - https://curl.se/libcurl/c/CURLOPT_ACCEPT_ENCODING.html */ - GNUNET_break (CURLE_OK == - curl_easy_setopt (eh, - CURLOPT_ACCEPT_ENCODING, - "")); - /* limit MAXREDIRS to 5 as a simple security measure against - a potential infinite loop caused by a malicious target */ - GNUNET_assert (CURLE_OK == - curl_easy_setopt (eh, - CURLOPT_MAXREDIRS, - 5L)); - GNUNET_assert (CURLE_OK == - curl_easy_setopt (eh, - CURLOPT_TCP_FASTOPEN, - 1L)); - return eh; -} diff --git a/src/lib/auditor_api_curl_defaults.h b/src/lib/auditor_api_curl_defaults.h deleted file mode 100644 index 99e1e07e6..000000000 --- a/src/lib/auditor_api_curl_defaults.h +++ /dev/null @@ -1,38 +0,0 @@ -/* - This file is part of TALER - Copyright (C) 2014-2018 Taler Systems SA - - TALER is free software; you can redistribute it and/or modify it under the - terms of the GNU General Public License as published by the Free Software - Foundation; either version 3, or (at your option) any later version. - - TALER is distributed in the hope that it will be useful, but WITHOUT ANY - WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR - A PARTICULAR PURPOSE. See the GNU General Public License for more details. - - You should have received a copy of the GNU General Public License along with - TALER; see the file COPYING. If not, see - -*/ -/** - * @file lib/auditor_api_curl_defaults.h - * @brief curl easy handle defaults - * @author Florian Dold - */ -#ifndef _TALER_CURL_DEFAULTS_H -#define _TALER_CURL_DEFAULTS_H - -#include "platform.h" -#include - - -/** - * Get a curl handle with the right defaults - * for the auditor lib. In the future, we might manage a pool of connections here. - * - * @param url URL to query - */ -CURL * -TALER_AUDITOR_curl_easy_get_ (const char *url); - -#endif /* _TALER_CURL_DEFAULTS_H */ diff --git a/src/lib/auditor_api_deposit_confirmation.c b/src/lib/auditor_api_deposit_confirmation.c deleted file mode 100644 index 1e2ecc6cc..000000000 --- a/src/lib/auditor_api_deposit_confirmation.c +++ /dev/null @@ -1,418 +0,0 @@ -/* - This file is part of TALER - Copyright (C) 2014-2023 Taler Systems SA - - TALER is free software; you can redistribute it and/or modify it under the - terms of the GNU General Public License as published by the Free Software - Foundation; either version 3, or (at your option) any later version. - - TALER is distributed in the hope that it will be useful, but WITHOUT ANY - WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR - A PARTICULAR PURPOSE. See the GNU General Public License for more details. - - You should have received a copy of the GNU General Public License along with - TALER; see the file COPYING. If not, see - -*/ -/** - * @file lib/auditor_api_deposit_confirmation.c - * @brief Implementation of the /deposit request of the auditor's HTTP API - * @author Christian Grothoff - */ -#include "platform.h" -#include -#include /* just for HTTP status codes */ -#include -#include -#include -#include "taler_util.h" -#include "taler_curl_lib.h" -#include "taler_json_lib.h" -#include "taler_auditor_service.h" -#include "taler_signatures.h" -#include "auditor_api_curl_defaults.h" - - -/** - * @brief A DepositConfirmation Handle - */ -struct TALER_AUDITOR_DepositConfirmationHandle -{ - - /** - * The url for this request. - */ - char *url; - - /** - * Context for #TEH_curl_easy_post(). Keeps the data that must - * persist for Curl to make the upload. - */ - struct TALER_CURL_PostContext ctx; - - /** - * Handle for the request. - */ - struct GNUNET_CURL_Job *job; - - /** - * Function to call with the result. - */ - TALER_AUDITOR_DepositConfirmationResultCallback cb; - - /** - * Closure for @a cb. - */ - void *cb_cls; - -}; - - -/** - * Function called when we're done processing the - * HTTP /deposit-confirmation request. - * - * @param cls the `struct TALER_AUDITOR_DepositConfirmationHandle` - * @param response_code HTTP response code, 0 on error - * @param djson parsed JSON result, NULL on error - */ -static void -handle_deposit_confirmation_finished (void *cls, - long response_code, - const void *djson) -{ - const json_t *json = djson; - struct TALER_AUDITOR_DepositConfirmationHandle *dh = cls; - struct TALER_AUDITOR_DepositConfirmationResponse dcr = { - .hr.reply = json, - .hr.http_status = (unsigned int) response_code - }; - - dh->job = NULL; - switch (response_code) - { - case 0: - dcr.hr.ec = TALER_EC_GENERIC_INVALID_RESPONSE; - break; - case MHD_HTTP_OK: - dcr.hr.ec = TALER_EC_NONE; - break; - case MHD_HTTP_BAD_REQUEST: - dcr.hr.ec = TALER_JSON_get_error_code (json); - dcr.hr.hint = TALER_JSON_get_error_hint (json); - /* This should never happen, either us or the auditor is buggy - (or API version conflict); just pass JSON reply to the application */ - break; - case MHD_HTTP_FORBIDDEN: - dcr.hr.ec = TALER_JSON_get_error_code (json); - dcr.hr.hint = TALER_JSON_get_error_hint (json); - /* Nothing really to verify, auditor says one of the signatures is - invalid; as we checked them, this should never happen, we - should pass the JSON reply to the application */ - break; - case MHD_HTTP_NOT_FOUND: - dcr.hr.ec = TALER_JSON_get_error_code (json); - dcr.hr.hint = TALER_JSON_get_error_hint (json); - /* Nothing really to verify, this should never - happen, we should pass the JSON reply to the application */ - break; - case MHD_HTTP_GONE: - dcr.hr.ec = TALER_JSON_get_error_code (json); - dcr.hr.hint = TALER_JSON_get_error_hint (json); - /* Nothing really to verify, auditor says one of the signatures is - invalid; as we checked them, this should never happen, we - should pass the JSON reply to the application */ - break; - case MHD_HTTP_INTERNAL_SERVER_ERROR: - dcr.hr.ec = TALER_JSON_get_error_code (json); - dcr.hr.hint = TALER_JSON_get_error_hint (json); - /* Server had an internal issue; we should retry, but this API - leaves this to the application */ - break; - default: - /* unexpected response code */ - dcr.hr.ec = TALER_JSON_get_error_code (json); - dcr.hr.hint = TALER_JSON_get_error_hint (json); - GNUNET_log (GNUNET_ERROR_TYPE_ERROR, - "Unexpected response code %u/%d for auditor deposit confirmation\n", - (unsigned int) response_code, - dcr.hr.ec); - break; - } - dh->cb (dh->cb_cls, - &dcr); - TALER_AUDITOR_deposit_confirmation_cancel (dh); -} - - -/** - * Verify signature information about the deposit-confirmation. - * - * @param h_wire hash of merchant wire details - * @param h_policy hash over the policy extension, if any - * @param h_contract_terms hash of the contact of the merchant with the customer (further details are never disclosed to the auditor) - * @param exchange_timestamp timestamp when the deposit was received by the wallet - * @param wire_deadline by what time must the amount be wired to the merchant - * @param refund_deadline date until which the merchant can issue a refund to the customer via the auditor (can be zero if refunds are not allowed); must not be after the @a wire_deadline - * @param amount_without_fee the amount confirmed to be wired by the exchange to the merchant - * @param coin_pub coin’s public key - * @param merchant_pub the public key of the merchant (used to identify the merchant for refund requests) - * @param exchange_sig the signature made with purpose #TALER_SIGNATURE_EXCHANGE_CONFIRM_DEPOSIT - * @param exchange_pub the public key of the exchange that matches @a exchange_sig - * @param master_pub master public key of the exchange - * @param ep_start when does @a exchange_pub validity start - * @param ep_expire when does @a exchange_pub usage end - * @param ep_end when does @a exchange_pub legal validity end - * @param master_sig master signature affirming validity of @a exchange_pub - * @return #GNUNET_OK if signatures are OK, #GNUNET_SYSERR if not - */ -static enum GNUNET_GenericReturnValue -verify_signatures ( - const struct TALER_MerchantWireHashP *h_wire, - const struct TALER_ExtensionPolicyHashP *h_policy, - const struct TALER_PrivateContractHashP *h_contract_terms, - struct GNUNET_TIME_Timestamp exchange_timestamp, - struct GNUNET_TIME_Timestamp wire_deadline, - struct GNUNET_TIME_Timestamp refund_deadline, - const struct TALER_Amount *amount_without_fee, - unsigned int num_coins, - const struct TALER_CoinSpendSignatureP *coin_sigs[ - static num_coins], - const struct TALER_MerchantPublicKeyP *merchant_pub, - const struct TALER_ExchangePublicKeyP *exchange_pub, - const struct TALER_ExchangeSignatureP *exchange_sig, - const struct TALER_MasterPublicKeyP *master_pub, - struct GNUNET_TIME_Timestamp ep_start, - struct GNUNET_TIME_Timestamp ep_expire, - struct GNUNET_TIME_Timestamp ep_end, - const struct TALER_MasterSignatureP *master_sig) -{ - if (GNUNET_OK != - TALER_exchange_online_deposit_confirmation_verify ( - h_contract_terms, - h_wire, - h_policy, - exchange_timestamp, - wire_deadline, - refund_deadline, - amount_without_fee, - num_coins, - coin_sigs, - merchant_pub, - exchange_pub, - exchange_sig)) - { - GNUNET_break_op (0); - TALER_LOG_WARNING ( - "Invalid signature on /deposit-confirmation request!\n"); - { - TALER_LOG_DEBUG ("... amount_without_fee was %s\n", - TALER_amount2s (amount_without_fee)); - } - return GNUNET_SYSERR; - } - - if (GNUNET_OK != - TALER_exchange_offline_signkey_validity_verify ( - exchange_pub, - ep_start, - ep_expire, - ep_end, - master_pub, - master_sig)) - { - GNUNET_break (0); - TALER_LOG_WARNING ("Invalid signature on exchange signing key!\n"); - return GNUNET_SYSERR; - } - if (GNUNET_TIME_absolute_is_past (ep_end.abs_time)) - { - GNUNET_break (0); - TALER_LOG_WARNING ("Exchange signing key is no longer valid!\n"); - return GNUNET_SYSERR; - } - return GNUNET_OK; -} - - -struct TALER_AUDITOR_DepositConfirmationHandle * -TALER_AUDITOR_deposit_confirmation ( - struct GNUNET_CURL_Context *ctx, - const char *url, - const struct TALER_MerchantWireHashP *h_wire, - const struct TALER_ExtensionPolicyHashP *h_policy, - const struct TALER_PrivateContractHashP *h_contract_terms, - struct GNUNET_TIME_Timestamp exchange_timestamp, - struct GNUNET_TIME_Timestamp wire_deadline, - struct GNUNET_TIME_Timestamp refund_deadline, - const struct TALER_Amount *total_without_fee, - unsigned int num_coins, - const struct TALER_CoinSpendPublicKeyP *coin_pubs[ - static num_coins], - const struct TALER_CoinSpendSignatureP *coin_sigs[ - static num_coins], - const struct TALER_MerchantPublicKeyP *merchant_pub, - const struct TALER_ExchangePublicKeyP *exchange_pub, - const struct TALER_ExchangeSignatureP *exchange_sig, - const struct TALER_MasterPublicKeyP *master_pub, - struct GNUNET_TIME_Timestamp ep_start, - struct GNUNET_TIME_Timestamp ep_expire, - struct GNUNET_TIME_Timestamp ep_end, - const struct TALER_MasterSignatureP *master_sig, - TALER_AUDITOR_DepositConfirmationResultCallback cb, - void *cb_cls) -{ - struct TALER_AUDITOR_DepositConfirmationHandle *dh; - json_t *deposit_confirmation_obj; - CURL *eh; - json_t *jcoin_sigs; - json_t *jcoin_pubs; - - if (0 == num_coins) - { - GNUNET_break (0); - return NULL; - } - if (GNUNET_OK != - verify_signatures (h_wire, - h_policy, - h_contract_terms, - exchange_timestamp, - wire_deadline, - refund_deadline, - total_without_fee, - num_coins, - coin_sigs, - merchant_pub, - exchange_pub, - exchange_sig, - master_pub, - ep_start, - ep_expire, - ep_end, - master_sig)) - { - GNUNET_break_op (0); - return NULL; - } - jcoin_sigs = json_array (); - GNUNET_assert (NULL != jcoin_sigs); - jcoin_pubs = json_array (); - GNUNET_assert (NULL != jcoin_pubs); - for (unsigned int i = 0; icb = cb; - dh->cb_cls = cb_cls; - dh->url = TALER_url_join (url, - "deposit-confirmation", - NULL); - if (NULL == dh->url) - { - GNUNET_free (dh); - return NULL; - } - eh = TALER_AUDITOR_curl_easy_get_ (dh->url); - if ( (NULL == eh) || - (CURLE_OK != - curl_easy_setopt (eh, - CURLOPT_CUSTOMREQUEST, - "PUT")) || - (GNUNET_OK != - TALER_curl_easy_post (&dh->ctx, - eh, - deposit_confirmation_obj)) ) - { - GNUNET_break (0); - if (NULL != eh) - curl_easy_cleanup (eh); - json_decref (deposit_confirmation_obj); - GNUNET_free (dh->url); - GNUNET_free (dh); - return NULL; - } - json_decref (deposit_confirmation_obj); - GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, - "URL for deposit-confirmation: `%s'\n", - dh->url); - dh->job = GNUNET_CURL_job_add2 (ctx, - eh, - dh->ctx.headers, - &handle_deposit_confirmation_finished, - dh); - { - /* Disable 100 continue processing */ - struct curl_slist *x_headers; - - x_headers = curl_slist_append (NULL, - "Expect:"); - GNUNET_CURL_extend_headers (dh->job, - x_headers); - curl_slist_free_all (x_headers); - } - return dh; -} - - -void -TALER_AUDITOR_deposit_confirmation_cancel ( - struct TALER_AUDITOR_DepositConfirmationHandle *deposit_confirmation) -{ - if (NULL != deposit_confirmation->job) - { - GNUNET_CURL_job_cancel (deposit_confirmation->job); - deposit_confirmation->job = NULL; - } - GNUNET_free (deposit_confirmation->url); - TALER_curl_easy_post_finished (&deposit_confirmation->ctx); - GNUNET_free (deposit_confirmation); -} - - -/* end of auditor_api_deposit_confirmation.c */ diff --git a/src/lib/auditor_api_exchanges.c b/src/lib/auditor_api_exchanges.c deleted file mode 100644 index 897dfe60f..000000000 --- a/src/lib/auditor_api_exchanges.c +++ /dev/null @@ -1,244 +0,0 @@ -/* - This file is part of TALER - Copyright (C) 2014-2018 Taler Systems SA - - TALER is free software; you can redistribute it and/or modify it under the - terms of the GNU General Public License as published by the Free Software - Foundation; either version 3, or (at your option) any later version. - - TALER is distributed in the hope that it will be useful, but WITHOUT ANY - WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR - A PARTICULAR PURPOSE. See the GNU General Public License for more details. - - You should have received a copy of the GNU General Public License along with - TALER; see the file COPYING. If not, see - -*/ -/** - * @file lib/auditor_api_exchanges.c - * @brief Implementation of the /exchanges request of the auditor's HTTP API - * @author Christian Grothoff - */ -#include "platform.h" -#include -#include /* just for HTTP status codes */ -#include -#include -#include -#include "taler_json_lib.h" -#include "taler_auditor_service.h" -#include "taler_util.h" -#include "taler_curl_lib.h" -#include "taler_signatures.h" -#include "auditor_api_curl_defaults.h" - -/** - * How many exchanges do we allow a single auditor to - * audit at most? - */ -#define MAX_EXCHANGES 1024 - - -/** - * @brief A ListExchanges Handle - */ -struct TALER_AUDITOR_ListExchangesHandle -{ - - /** - * The url for this request. - */ - char *url; - - /** - * Handle for the request. - */ - struct GNUNET_CURL_Job *job; - - /** - * Function to call with the result. - */ - TALER_AUDITOR_ListExchangesResultCallback cb; - - /** - * Closure for @a cb. - */ - void *cb_cls; - -}; - - -/** - * Function called when we're done processing the - * HTTP /exchanges request. - * - * @param cls the `struct TALER_AUDITOR_ListExchangesHandle` - * @param response_code HTTP response code, 0 on error - * @param djson parsed JSON result, NULL on error - */ -static void -handle_exchanges_finished (void *cls, - long response_code, - const void *djson) -{ - const json_t *json = djson; - const json_t *ja; - unsigned int ja_len; - struct TALER_AUDITOR_ListExchangesHandle *leh = cls; - struct TALER_AUDITOR_ListExchangesResponse ler = { - .hr.reply = json, - .hr.http_status = (unsigned int) response_code - }; - - leh->job = NULL; - switch (response_code) - { - case 0: - ler.hr.ec = TALER_EC_GENERIC_INVALID_RESPONSE; - break; - case MHD_HTTP_OK: - ja = json_object_get (json, - "exchanges"); - if ( (NULL == ja) || - (! json_is_array (ja)) ) - { - GNUNET_break (0); - ler.hr.ec = TALER_EC_GENERIC_REPLY_MALFORMED; - ler.hr.http_status = 0; - break; - } - - ja_len = json_array_size (ja); - if (ja_len > MAX_EXCHANGES) - { - GNUNET_break (0); - ler.hr.ec = TALER_EC_GENERIC_REPLY_MALFORMED; - ler.hr.http_status = 0; - break; - } - { - struct TALER_AUDITOR_ExchangeInfo ei[GNUNET_NZL (ja_len)]; - bool ok = true; - - for (unsigned int i = 0; icb (leh->cb_cls, - &ler); - TALER_AUDITOR_list_exchanges_cancel (leh); - return; - } - case MHD_HTTP_BAD_REQUEST: - /* This should never happen, either us or the auditor is buggy - (or API version conflict); just pass JSON reply to the application */ - ler.hr.ec = TALER_JSON_get_error_code (json); - ler.hr.hint = TALER_JSON_get_error_hint (json); - break; - case MHD_HTTP_NOT_FOUND: - /* Nothing really to verify, this should never - happen, we should pass the JSON reply to the application */ - ler.hr.ec = TALER_JSON_get_error_code (json); - ler.hr.hint = TALER_JSON_get_error_hint (json); - break; - case MHD_HTTP_INTERNAL_SERVER_ERROR: - /* Server had an internal issue; we should retry, but this API - leaves this to the application */ - ler.hr.ec = TALER_JSON_get_error_code (json); - ler.hr.hint = TALER_JSON_get_error_hint (json); - break; - default: - /* unexpected response code */ - ler.hr.ec = TALER_JSON_get_error_code (json); - ler.hr.hint = TALER_JSON_get_error_hint (json); - GNUNET_log (GNUNET_ERROR_TYPE_ERROR, - "Unexpected response code %u/%d for auditor list-exchanges request\n", - (unsigned int) response_code, - (int) ler.hr.ec); - GNUNET_break_op (0); - break; - } - if (NULL != leh->cb) - leh->cb (leh->cb_cls, - &ler); - TALER_AUDITOR_list_exchanges_cancel (leh); -} - - -struct TALER_AUDITOR_ListExchangesHandle * -TALER_AUDITOR_list_exchanges (struct GNUNET_CURL_Context *ctx, - const char *url, - TALER_AUDITOR_ListExchangesResultCallback cb, - void *cb_cls) -{ - struct TALER_AUDITOR_ListExchangesHandle *leh; - CURL *eh; - - leh = GNUNET_new (struct TALER_AUDITOR_ListExchangesHandle); - leh->cb = cb; - leh->cb_cls = cb_cls; - leh->url = TALER_url_join (url, - "exchanges", - NULL); - if (NULL == leh->url) - { - GNUNET_free (leh); - return NULL; - } - GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, - "URL for list-exchanges: `%s'\n", - leh->url); - eh = TALER_AUDITOR_curl_easy_get_ (leh->url); - if (NULL == eh) - { - GNUNET_break (0); - GNUNET_free (leh->url); - GNUNET_free (leh); - return NULL; - } - leh->job = GNUNET_CURL_job_add (ctx, - eh, - &handle_exchanges_finished, - leh); - return leh; -} - - -void -TALER_AUDITOR_list_exchanges_cancel ( - struct TALER_AUDITOR_ListExchangesHandle *leh) -{ - if (NULL != leh->job) - { - GNUNET_CURL_job_cancel (leh->job); - leh->job = NULL; - } - GNUNET_free (leh->url); - GNUNET_free (leh); -} - - -/* end of auditor_api_exchanges.c */ diff --git a/src/lib/auditor_api_get_config.c b/src/lib/auditor_api_get_config.c deleted file mode 100644 index c9f366568..000000000 --- a/src/lib/auditor_api_get_config.c +++ /dev/null @@ -1,288 +0,0 @@ -/* - This file is part of TALER - Copyright (C) 2014-2023 Taler Systems SA - - TALER is free software; you can redistribute it and/or modify it under the - terms of the GNU General Public License as published by the Free Software - Foundation; either version 3, or (at your option) any later version. - - TALER is distributed in the hope that it will be useful, but WITHOUT ANY - WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR - A PARTICULAR PURPOSE. See the GNU General Public License for more details. - - You should have received a copy of the GNU General Public License along with - TALER; see the file COPYING. If not, see - -*/ -/** - * @file lib/auditor_api_get_config.c - * @brief Implementation of /config for the auditor's HTTP API - * @author Sree Harsha Totakura - * @author Christian Grothoff - */ -#include "platform.h" -#include -#include -#include "taler_json_lib.h" -#include "taler_auditor_service.h" -#include "taler_signatures.h" -#include "auditor_api_curl_defaults.h" - - -/** - * Which revision of the Taler auditor protocol is implemented - * by this library? Used to determine compatibility. - */ -#define TALER_PROTOCOL_CURRENT 0 - -/** - * How many revisions back are we compatible to? - */ -#define TALER_PROTOCOL_AGE 0 - - -/** - * Log error related to CURL operations. - * - * @param type log level - * @param function which function failed to run - * @param code what was the curl error code - */ -#define CURL_STRERROR(type, function, code) \ - GNUNET_log (type, "Curl function `%s' has failed at `%s:%d' with error: %s", \ - function, __FILE__, __LINE__, curl_easy_strerror (code)); - - -/** - * Handle for the get config request. - */ -struct TALER_AUDITOR_GetConfigHandle -{ - /** - * The context of this handle - */ - struct GNUNET_CURL_Context *ctx; - - /** - * Function to call with the auditor's certification data, - * NULL if this has already been done. - */ - TALER_AUDITOR_ConfigCallback config_cb; - - /** - * Closure to pass to @e config_cb. - */ - void *config_cb_cls; - - /** - * Data for the request to get the /config of a auditor, - * NULL once we are past stage #MHS_INIT. - */ - struct GNUNET_CURL_Job *vr; - - /** - * The url for the @e vr job. - */ - char *vr_url; - -}; - - -/* ***************** Internal /config fetching ************* */ - -/** - * Decode the JSON in @a resp_obj from the /config response and store the data - * in the @a key_data. - * - * @param[in] resp_obj JSON object to parse - * @param[in,out] vi where to store the results we decoded - * @param[out] vc where to store config compatibility data - * @return #TALER_EC_NONE on success - */ -static enum TALER_ErrorCode -decode_config_json (const json_t *resp_obj, - struct TALER_AUDITOR_ConfigInformation *vi, - enum TALER_AUDITOR_VersionCompatibility *vc) -{ - unsigned int age; - unsigned int revision; - unsigned int current; - char dummy; - const char *ver; - struct GNUNET_JSON_Specification spec[] = { - GNUNET_JSON_spec_string ("version", - &ver), - GNUNET_JSON_spec_fixed_auto ("auditor_public_key", - &vi->auditor_pub), - GNUNET_JSON_spec_end () - }; - - if (JSON_OBJECT != json_typeof (resp_obj)) - { - GNUNET_break_op (0); - return TALER_EC_GENERIC_JSON_INVALID; - } - /* check the config */ - if (GNUNET_OK != - GNUNET_JSON_parse (resp_obj, - spec, - NULL, NULL)) - { - GNUNET_break_op (0); - return TALER_EC_GENERIC_JSON_INVALID; - } - if (3 != sscanf (ver, - "%u:%u:%u%c", - ¤t, - &revision, - &age, - &dummy)) - { - GNUNET_break_op (0); - return TALER_EC_GENERIC_VERSION_MALFORMED; - } - vi->version = ver; - *vc = TALER_AUDITOR_VC_MATCH; - if (TALER_PROTOCOL_CURRENT < current) - { - *vc |= TALER_AUDITOR_VC_NEWER; - if (TALER_PROTOCOL_CURRENT < current - age) - *vc |= TALER_AUDITOR_VC_INCOMPATIBLE; - } - if (TALER_PROTOCOL_CURRENT > current) - { - *vc |= TALER_AUDITOR_VC_OLDER; - if (TALER_PROTOCOL_CURRENT - TALER_PROTOCOL_AGE > current) - *vc |= TALER_AUDITOR_VC_INCOMPATIBLE; - } - return TALER_EC_NONE; -} - - -/** - * Callback used when downloading the reply to a /config request - * is complete. - * - * @param cls the `struct TALER_AUDITOR_GetConfigHandle` - * @param response_code HTTP response code, 0 on error - * @param gresp_obj parsed JSON result, NULL on error, must be a `const json_t *` - */ -static void -config_completed_cb (void *cls, - long response_code, - const void *gresp_obj) -{ - struct TALER_AUDITOR_GetConfigHandle *auditor = cls; - const json_t *resp_obj = gresp_obj; - struct TALER_AUDITOR_ConfigResponse vr = { - .hr.reply = resp_obj, - .hr.http_status = (unsigned int) response_code - }; - - auditor->vr = NULL; - GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, - "Received config from URL `%s' with status %ld.\n", - auditor->vr_url, - response_code); - switch (response_code) - { - case 0: - GNUNET_break_op (0); - vr.hr.ec = TALER_EC_INVALID; - break; - case MHD_HTTP_OK: - if (NULL == resp_obj) - { - GNUNET_break_op (0); - vr.hr.http_status = 0; - vr.hr.ec = TALER_EC_GENERIC_INVALID_RESPONSE; - break; - } - vr.hr.ec = decode_config_json (resp_obj, - &vr.details.ok.vi, - &vr.details.ok.compat); - if (TALER_EC_NONE != vr.hr.ec) - { - GNUNET_break_op (0); - vr.hr.http_status = 0; - break; - } - break; - case MHD_HTTP_INTERNAL_SERVER_ERROR: - vr.hr.ec = TALER_JSON_get_error_code (resp_obj); - vr.hr.hint = TALER_JSON_get_error_hint (resp_obj); - break; - default: - vr.hr.ec = TALER_JSON_get_error_code (resp_obj); - vr.hr.hint = TALER_JSON_get_error_hint (resp_obj); - GNUNET_log (GNUNET_ERROR_TYPE_ERROR, - "Unexpected response code %u/%d\n", - (unsigned int) response_code, - (int) vr.hr.ec); - break; - } - auditor->config_cb (auditor->config_cb_cls, - &vr); - TALER_AUDITOR_get_config_cancel (auditor); -} - - -struct TALER_AUDITOR_GetConfigHandle * -TALER_AUDITOR_get_config (struct GNUNET_CURL_Context *ctx, - const char *url, - TALER_AUDITOR_ConfigCallback config_cb, - void *config_cb_cls) -{ - struct TALER_AUDITOR_GetConfigHandle *auditor; - CURL *eh; - - auditor = GNUNET_new (struct TALER_AUDITOR_GetConfigHandle); - auditor->config_cb = config_cb; - auditor->config_cb_cls = config_cb_cls; - auditor->ctx = ctx; - auditor->vr_url = TALER_url_join (url, - "config", - NULL); - if (NULL == auditor->vr_url) - { - GNUNET_break (0); - GNUNET_free (auditor->vr_url); - GNUNET_free (auditor); - return NULL; - } - GNUNET_log (GNUNET_ERROR_TYPE_INFO, - "Requesting auditor config with URL `%s'.\n", - auditor->vr_url); - eh = TALER_AUDITOR_curl_easy_get_ (auditor->vr_url); - if (NULL == eh) - { - GNUNET_break (0); - TALER_AUDITOR_get_config_cancel (auditor); - return NULL; - } - GNUNET_break (CURLE_OK == - curl_easy_setopt (eh, - CURLOPT_TIMEOUT, - (long) 300)); - auditor->vr = GNUNET_CURL_job_add (auditor->ctx, - eh, - &config_completed_cb, - auditor); - return auditor; -} - - -void -TALER_AUDITOR_get_config_cancel (struct TALER_AUDITOR_GetConfigHandle *auditor) -{ - if (NULL != auditor->vr) - { - GNUNET_CURL_job_cancel (auditor->vr); - auditor->vr = NULL; - } - GNUNET_free (auditor->vr_url); - GNUNET_free (auditor); -} - - -/* end of auditor_api_get_config.c */ diff --git a/src/lib/exchange_api_age_withdraw.c b/src/lib/exchange_api_age_withdraw.c deleted file mode 100644 index ea9c0371e..000000000 --- a/src/lib/exchange_api_age_withdraw.c +++ /dev/null @@ -1,1117 +0,0 @@ -/* - This file is part of TALER - Copyright (C) 2023 Taler Systems SA - - TALER is free software; you can redistribute it and/or modify it under the - terms of the GNU General Public License as published by the Free Software - Foundation; either version 3, or (at your option) any later version. - - TALER is distributed in the hope that it will be useful, but WITHOUT ANY - WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR - A PARTICULAR PURPOSE. See the GNU General Public License for more details. - - You should have received a copy of the GNU General Public License along with - TALER; see the file COPYING. If not, see - -*/ -/** - * @file lib/exchange_api_age_withdraw.c - * @brief Implementation of /reserves/$RESERVE_PUB/age-withdraw requests - * @author Özgür Kesim - */ - -#include "platform.h" -#include -#include -#include /* just for HTTP status codes */ -#include -#include -#include -#include -#include "taler_curl_lib.h" -#include "taler_error_codes.h" -#include "taler_json_lib.h" -#include "taler_exchange_service.h" -#include "exchange_api_common.h" -#include "exchange_api_handle.h" -#include "taler_signatures.h" -#include "exchange_api_curl_defaults.h" -#include "taler_util.h" - -/** - * A CoinCandidate is populated from a master secret - */ -struct CoinCandidate -{ - /** - * Master key material for the coin candidates. - */ - struct TALER_PlanchetMasterSecretP secret; - - /** - * The details derived form the master secrets - */ - struct TALER_EXCHANGE_AgeWithdrawCoinPrivateDetails details; - - /** - * Blinded hash of the coin - **/ - struct TALER_BlindedCoinHashP blinded_coin_h; - -}; - - -/** - * Closure for a call to /csr-withdraw, contains data that is needed to process - * the result. - */ -struct CSRClosure -{ - /* Points to the actual candidate in CoinData.coin_candidates, to continue - * to build its contents based on the results from /csr-withdraw */ - struct CoinCandidate *candidate; - - /* The planchet to finally generate. Points to the corresponding candidate - * in CoindData.planchet_details */ - struct TALER_PlanchetDetail *planchet; - - /* Handler to the originating call to /age-withdraw, needed to either - * cancel the running age-withdraw request (on failure of the current call - * to /csr-withdraw), or to eventually perform the protocol, once all - * csr-withdraw requests have successfully finished. */ - struct TALER_EXCHANGE_AgeWithdrawHandle *age_withdraw_handle; - - /* Denomination information, needed for CS coins for the - * step after /csr-withdraw */ - const struct TALER_EXCHANGE_DenomPublicKey *denom_pub; - - /* Handler for the CS R request */ - struct TALER_EXCHANGE_CsRWithdrawHandle *csr_withdraw_handle; -}; - -/** - * Data we keep per coin in the batch. - */ -struct CoinData -{ - /** - * The denomination of the coin. Must support age restriction, i.e - * its .keys.age_mask MUST not be 0 - */ - struct TALER_EXCHANGE_DenomPublicKey denom_pub; - - /** - * The Candidates for the coin - */ - struct CoinCandidate coin_candidates[TALER_CNC_KAPPA]; - - /** - * Details of the planchet(s). - */ - struct TALER_PlanchetDetail planchet_details[TALER_CNC_KAPPA]; - - /** - * Closure for each candidate of type CS for the preflight request to - * /csr-withdraw - */ - struct CSRClosure csr_cls[TALER_CNC_KAPPA]; -}; - -/** - * A /reserves/$RESERVE_PUB/age-withdraw request-handle for calls with - * pre-blinded planchets. Returned by TALER_EXCHANGE_age_withdraw_blinded. - */ -struct TALER_EXCHANGE_AgeWithdrawBlindedHandle -{ - - /** - * Reserve private key. - */ - const struct TALER_ReservePrivateKeyP *reserve_priv; - - /** - * Reserve public key, calculated - */ - struct TALER_ReservePublicKeyP reserve_pub; - - /** - * Signature of the reserve for the request, calculated after all - * parameters for the coins are collected. - */ - struct TALER_ReserveSignatureP reserve_sig; - - /* - * The denomination keys of the exchange - */ - struct TALER_EXCHANGE_Keys *keys; - - /** - * The age mask, extacted from the denominations. - * MUST be the same for all denominations - * - */ - struct TALER_AgeMask age_mask; - - /** - * Maximum age to commit to. - */ - uint8_t max_age; - - /** - * The commitment calculated as SHA512 hash over all blinded_coin_h - */ - struct TALER_AgeWithdrawCommitmentHashP h_commitment; - - /** - * Total amount requested (value plus withdraw fee). - */ - struct TALER_Amount amount_with_fee; - - /** - * Length of the @e blinded_input Array - */ - size_t num_input; - - /** - * The blinded planchet input for the call to /age-withdraw via - * TALER_EXCHANGE_age_withdraw_blinded - */ - const struct TALER_EXCHANGE_AgeWithdrawBlindedInput *blinded_input; - - /** - * The url for this request. - */ - char *request_url; - - /** - * Context for curl. - */ - struct GNUNET_CURL_Context *curl_ctx; - - /** - * CURL handle for the request job. - */ - struct GNUNET_CURL_Job *job; - - /** - * Post Context - */ - struct TALER_CURL_PostContext post_ctx; - - /** - * Function to call with age-withdraw response results. - */ - TALER_EXCHANGE_AgeWithdrawBlindedCallback callback; - - /** - * Closure for @e blinded_callback - */ - void *callback_cls; -}; - -/** - * A /reserves/$RESERVE_PUB/age-withdraw request-handle for calls from - * a wallet, i. e. when blinding data is available. - */ -struct TALER_EXCHANGE_AgeWithdrawHandle -{ - - /** - * Length of the @e coin_data Array - */ - size_t num_coins; - - /** - * The base-URL of the exchange. - */ - const char *exchange_url; - - /** - * Reserve private key. - */ - const struct TALER_ReservePrivateKeyP *reserve_priv; - - /** - * Reserve public key, calculated - */ - struct TALER_ReservePublicKeyP reserve_pub; - - /** - * Signature of the reserve for the request, calculated after all - * parameters for the coins are collected. - */ - struct TALER_ReserveSignatureP reserve_sig; - - /* - * The denomination keys of the exchange - */ - struct TALER_EXCHANGE_Keys *keys; - - /** - * The age mask, extacted from the denominations. - * MUST be the same for all denominations - * - */ - struct TALER_AgeMask age_mask; - - /** - * Maximum age to commit to. - */ - uint8_t max_age; - - /** - * Array of per-coin data - */ - struct CoinData *coin_data; - - /** - * Context for curl. - */ - struct GNUNET_CURL_Context *curl_ctx; - - struct - { - /** - * Number of /csr-withdraw requests still pending. - */ - unsigned int pending; - - /** - * CURL handle for the request job. - */ - struct GNUNET_CURL_Job *job; - } csr; - - - /** - * Function to call with age-withdraw response results. - */ - TALER_EXCHANGE_AgeWithdrawCallback callback; - - /** - * Closure for @e age_withdraw_cb - */ - void *callback_cls; - - /* The Handler for the actual call to the exchange */ - struct TALER_EXCHANGE_AgeWithdrawBlindedHandle *procotol_handle; -}; - -/** - * We got a 200 OK response for the /reserves/$RESERVE_PUB/age-withdraw operation. - * Extract the noreveal_index and return it to the caller. - * - * @param awbh operation handle - * @param j_response reply from the exchange - * @return #GNUNET_OK on success, #GNUNET_SYSERR on errors - */ -static enum GNUNET_GenericReturnValue -reserve_age_withdraw_ok ( - struct TALER_EXCHANGE_AgeWithdrawBlindedHandle *awbh, - const json_t *j_response) -{ - struct TALER_EXCHANGE_AgeWithdrawBlindedResponse response = { - .hr.reply = j_response, - .hr.http_status = MHD_HTTP_OK, - .details.ok.h_commitment = awbh->h_commitment - }; - struct TALER_ExchangeSignatureP exchange_sig; - struct GNUNET_JSON_Specification spec[] = { - GNUNET_JSON_spec_uint8 ("noreveal_index", - &response.details.ok.noreveal_index), - GNUNET_JSON_spec_fixed_auto ("exchange_sig", - &exchange_sig), - GNUNET_JSON_spec_fixed_auto ("exchange_pub", - &response.details.ok.exchange_pub), - GNUNET_JSON_spec_end () - }; - - if (GNUNET_OK!= - GNUNET_JSON_parse (j_response, - spec, - NULL, NULL)) - { - GNUNET_break_op (0); - return GNUNET_SYSERR; - } - - if (GNUNET_OK != - TALER_exchange_online_age_withdraw_confirmation_verify ( - &awbh->h_commitment, - response.details.ok.noreveal_index, - &response.details.ok.exchange_pub, - &exchange_sig)) - { - GNUNET_break_op (0); - return GNUNET_SYSERR; - - } - - awbh->callback (awbh->callback_cls, - &response); - /* make sure the callback isn't called again */ - awbh->callback = NULL; - - return GNUNET_OK; -} - - -/** - * Function called when we're done processing the - * HTTP /reserves/$RESERVE_PUB/age-withdraw request. - * - * @param cls the `struct TALER_EXCHANGE_AgeWithdrawHandle` - * @param response_code The HTTP response code - * @param response response data - */ -static void -handle_reserve_age_withdraw_blinded_finished ( - void *cls, - long response_code, - const void *response) -{ - struct TALER_EXCHANGE_AgeWithdrawBlindedHandle *awbh = cls; - const json_t *j_response = response; - struct TALER_EXCHANGE_AgeWithdrawBlindedResponse awbr = { - .hr.reply = j_response, - .hr.http_status = (unsigned int) response_code - }; - - awbh->job = NULL; - switch (response_code) - { - case 0: - awbr.hr.ec = TALER_EC_GENERIC_INVALID_RESPONSE; - break; - case MHD_HTTP_OK: - if (GNUNET_OK != - reserve_age_withdraw_ok (awbh, - j_response)) - { - GNUNET_break_op (0); - awbr.hr.http_status = 0; - awbr.hr.ec = TALER_EC_GENERIC_REPLY_MALFORMED; - break; - } - GNUNET_assert (NULL == awbh->callback); - TALER_EXCHANGE_age_withdraw_blinded_cancel (awbh); - return; - case MHD_HTTP_BAD_REQUEST: - /* This should never happen, either us or the exchange is buggy - (or API version conflict); just pass JSON reply to the application */ - awbr.hr.ec = TALER_JSON_get_error_code (j_response); - awbr.hr.hint = TALER_JSON_get_error_hint (j_response); - break; - case MHD_HTTP_FORBIDDEN: - GNUNET_break_op (0); - /* Nothing really to verify, exchange says one of the signatures is - invalid; as we checked them, this should never happen, we - should pass the JSON reply to the application */ - awbr.hr.ec = TALER_JSON_get_error_code (j_response); - awbr.hr.hint = TALER_JSON_get_error_hint (j_response); - break; - case MHD_HTTP_NOT_FOUND: - /* Nothing really to verify, the exchange basically just says - that it doesn't know this reserve. Can happen if we - query before the wire transfer went through. - We should simply pass the JSON reply to the application. */ - awbr.hr.ec = TALER_JSON_get_error_code (j_response); - awbr.hr.hint = TALER_JSON_get_error_hint (j_response); - break; - case MHD_HTTP_CONFLICT: - /* The age requirements might not have been met */ - awbr.hr.ec = TALER_JSON_get_error_code (j_response); - awbr.hr.hint = TALER_JSON_get_error_hint (j_response); - break; - case MHD_HTTP_GONE: - /* could happen if denomination was revoked */ - /* Note: one might want to check /keys for revocation - signature here, alas tricky in case our /keys - is outdated => left to clients */ - awbr.hr.ec = TALER_JSON_get_error_code (j_response); - awbr.hr.hint = TALER_JSON_get_error_hint (j_response); - break; - case MHD_HTTP_UNAVAILABLE_FOR_LEGAL_REASONS: - /* only validate reply is well-formed */ - { - uint64_t ptu; - struct GNUNET_JSON_Specification spec[] = { - GNUNET_JSON_spec_uint64 ("requirement_row", - &ptu), - GNUNET_JSON_spec_end () - }; - - if (GNUNET_OK != - GNUNET_JSON_parse (j_response, - spec, - NULL, NULL)) - { - GNUNET_break_op (0); - awbr.hr.http_status = 0; - awbr.hr.ec = TALER_EC_GENERIC_REPLY_MALFORMED; - break; - } - } - case MHD_HTTP_INTERNAL_SERVER_ERROR: - /* Server had an internal issue; we should retry, but this API - leaves this to the application */ - awbr.hr.ec = TALER_JSON_get_error_code (j_response); - awbr.hr.hint = TALER_JSON_get_error_hint (j_response); - break; - default: - /* unexpected response code */ - GNUNET_break_op (0); - awbr.hr.ec = TALER_JSON_get_error_code (j_response); - awbr.hr.hint = TALER_JSON_get_error_hint (j_response); - GNUNET_log (GNUNET_ERROR_TYPE_ERROR, - "Unexpected response code %u/%d for exchange age-withdraw\n", - (unsigned int) response_code, - (int) awbr.hr.ec); - break; - } - awbh->callback (awbh->callback_cls, - &awbr); - TALER_EXCHANGE_age_withdraw_blinded_cancel (awbh); -} - - -/** - * Runs the actual age-withdraw operation with the blinded planchets. - * - * @param[in,out] awbh age withdraw handler - */ -static void -perform_protocol ( - struct TALER_EXCHANGE_AgeWithdrawBlindedHandle *awbh) -{ -#define FAIL_IF(cond) \ - do { \ - if ((cond)) \ - { \ - GNUNET_break (! (cond)); \ - goto ERROR; \ - } \ - } while(0) - - struct GNUNET_HashContext *coins_hctx; - json_t *j_denoms = NULL; - json_t *j_array_candidates = NULL; - json_t *j_request_body = NULL; - CURL *curlh = NULL; - - GNUNET_assert (0 < awbh->num_input); - awbh->age_mask = awbh->blinded_input[0].denom_pub->key.age_mask; - - FAIL_IF (GNUNET_OK != - TALER_amount_set_zero (awbh->keys->currency, - &awbh->amount_with_fee)); - /* Accumulate total value with fees */ - for (size_t i = 0; i < awbh->num_input; i++) - { - struct TALER_Amount coin_total; - const struct TALER_EXCHANGE_DenomPublicKey *dpub = - awbh->blinded_input[i].denom_pub; - - FAIL_IF (0 > - TALER_amount_add (&coin_total, - &dpub->fees.withdraw, - &dpub->value)); - FAIL_IF (0 > - TALER_amount_add (&awbh->amount_with_fee, - &awbh->amount_with_fee, - &coin_total)); - } - - GNUNET_log (GNUNET_ERROR_TYPE_INFO, - "Attempting to age-withdraw from reserve %s with maximum age %d\n", - TALER_B2S (&awbh->reserve_pub), - awbh->max_age); - - coins_hctx = GNUNET_CRYPTO_hash_context_start (); - FAIL_IF (NULL == coins_hctx); - - - j_denoms = json_array (); - j_array_candidates = json_array (); - FAIL_IF ((NULL == j_denoms) || - (NULL == j_array_candidates)); - - for (size_t i = 0; i< awbh->num_input; i++) - { - /* Build the denomination array */ - { - const struct TALER_EXCHANGE_DenomPublicKey *denom_pub = - awbh->blinded_input[i].denom_pub; - const struct TALER_DenominationHashP *denom_h = &denom_pub->h_key; - json_t *jdenom; - - /* The mask must be the same for all coins */ - FAIL_IF (awbh->age_mask.bits != denom_pub->key.age_mask.bits); - - jdenom = GNUNET_JSON_PACK ( - GNUNET_JSON_pack_data_auto (NULL, - denom_h)); - FAIL_IF (NULL == jdenom); - FAIL_IF (0 < json_array_append_new (j_denoms, - jdenom)); - - /* Build the candidate array */ - { - json_t *j_can = json_array (); - FAIL_IF (NULL == j_can); - - for (size_t k = 0; k < TALER_CNC_KAPPA; k++) - { - struct TALER_BlindedCoinHashP bch; - const struct TALER_PlanchetDetail *planchet = - &awbh->blinded_input[i].planchet_details[k]; - json_t *jc = GNUNET_JSON_PACK ( - TALER_JSON_pack_blinded_planchet ( - NULL, - &planchet->blinded_planchet)); - - FAIL_IF (NULL == jc); - FAIL_IF (0 < json_array_append_new (j_can, - jc)); - - TALER_coin_ev_hash (&planchet->blinded_planchet, - &planchet->denom_pub_hash, - &bch); - - GNUNET_CRYPTO_hash_context_read (coins_hctx, - &bch, - sizeof(bch)); - } - - FAIL_IF (0 < json_array_append_new (j_array_candidates, - j_can)); - } - } - } - - /* Build the hash of the commitment */ - GNUNET_CRYPTO_hash_context_finish (coins_hctx, - &awbh->h_commitment.hash); - - /* Sign the request */ - TALER_wallet_age_withdraw_sign (&awbh->h_commitment, - &awbh->amount_with_fee, - &awbh->age_mask, - awbh->max_age, - awbh->reserve_priv, - &awbh->reserve_sig); - - /* Initiate the POST-request */ - j_request_body = GNUNET_JSON_PACK ( - GNUNET_JSON_pack_array_steal ("denom_hs", j_denoms), - GNUNET_JSON_pack_array_steal ("blinded_coin_evs", j_array_candidates), - GNUNET_JSON_pack_uint64 ("max_age", awbh->max_age), - GNUNET_JSON_pack_data_auto ("reserve_sig", &awbh->reserve_sig)); - FAIL_IF (NULL == j_request_body); - - curlh = TALER_EXCHANGE_curl_easy_get_ (awbh->request_url); - FAIL_IF (NULL == curlh); - FAIL_IF (GNUNET_OK != - TALER_curl_easy_post (&awbh->post_ctx, - curlh, - j_request_body)); - json_decref (j_request_body); - j_request_body = NULL; - - awbh->job = GNUNET_CURL_job_add2 ( - awbh->curl_ctx, - curlh, - awbh->post_ctx.headers, - &handle_reserve_age_withdraw_blinded_finished, - awbh); - FAIL_IF (NULL == awbh->job); - - /* No errors, return */ - return; - -ERROR: - if (NULL != j_denoms) - json_decref (j_denoms); - if (NULL != j_array_candidates) - json_decref (j_array_candidates); - if (NULL != j_request_body) - json_decref (j_request_body); - if (NULL != curlh) - curl_easy_cleanup (curlh); - TALER_EXCHANGE_age_withdraw_blinded_cancel (awbh); - return; -#undef FAIL_IF -} - - -/** - * @brief Callback to copy the results from the call to TALER_age_withdraw_blinded - * to the result for the originating call from TALER_age_withdraw. - * - * @param cls struct TALER_AgeWithdrawHandle - * @param awbr The response - */ -static void -copy_results ( - void *cls, - const struct TALER_EXCHANGE_AgeWithdrawBlindedResponse *awbr) -{ - struct TALER_EXCHANGE_AgeWithdrawHandle *awh = cls; - uint8_t k = awbr->details.ok.noreveal_index; - struct TALER_EXCHANGE_AgeWithdrawCoinPrivateDetails details[awh->num_coins]; - struct TALER_BlindedCoinHashP blinded_coin_hs[awh->num_coins]; - struct TALER_EXCHANGE_AgeWithdrawResponse resp = { - .hr = awbr->hr, - .details = { - .ok = { .noreveal_index = awbr->details.ok.noreveal_index, - .h_commitment = awbr->details.ok.h_commitment, - .exchange_pub = awbr->details.ok.exchange_pub, - .num_coins = awh->num_coins, - .coin_details = details, - .blinded_coin_hs = blinded_coin_hs}, - }, - }; - - for (size_t n = 0; n< awh->num_coins; n++) - { - details[n] = awh->coin_data[n].coin_candidates[k].details; - details[n].planchet = awh->coin_data[n].planchet_details[k]; - blinded_coin_hs[n] = awh->coin_data[n].coin_candidates[k].blinded_coin_h; - } - - awh->callback (awh->callback_cls, - &resp); - - awh->callback = NULL; -} - - -/** - * @brief Prepares and executes TALER_EXCHANGE_age_withdraw_blinded. - * If there were CS-denominations involved, started once the all calls - * to /csr-withdraw are done. - */ -static void -call_age_withdraw_blinded ( - struct TALER_EXCHANGE_AgeWithdrawHandle *awh) -{ - struct TALER_EXCHANGE_AgeWithdrawBlindedInput blinded_input[awh->num_coins]; - - /* Prepare the blinded planchets as input */ - for (size_t n = 0; n < awh->num_coins; n++) - { - blinded_input[n].denom_pub = &awh->coin_data[n].denom_pub; - for (uint8_t k = 0; k < TALER_CNC_KAPPA; k++) - blinded_input[n].planchet_details[k] = - awh->coin_data[n].planchet_details[k]; - } - - awh->procotol_handle = - TALER_EXCHANGE_age_withdraw_blinded ( - awh->curl_ctx, - awh->keys, - awh->exchange_url, - awh->reserve_priv, - awh->max_age, - awh->num_coins, - blinded_input, - copy_results, - awh); -} - - -/** - * Prepares the request URL for the age-withdraw request - * - * @param awbh The handler - * @param exchange_url The base-URL to the exchange - */ -static -enum GNUNET_GenericReturnValue -prepare_url ( - struct TALER_EXCHANGE_AgeWithdrawBlindedHandle *awbh, - const char *exchange_url) -{ - char arg_str[sizeof (struct TALER_ReservePublicKeyP) * 2 + 32]; - char pub_str[sizeof (struct TALER_ReservePublicKeyP) * 2]; - char *end; - - end = GNUNET_STRINGS_data_to_string ( - &awbh->reserve_pub, - sizeof (awbh->reserve_pub), - pub_str, - sizeof (pub_str)); - *end = '\0'; - GNUNET_snprintf (arg_str, - sizeof (arg_str), - "reserves/%s/age-withdraw", - pub_str); - - awbh->request_url = TALER_url_join (exchange_url, - arg_str, - NULL); - if (NULL == awbh->request_url) - { - GNUNET_break (0); - TALER_EXCHANGE_age_withdraw_blinded_cancel (awbh); - return GNUNET_SYSERR; - } - - return GNUNET_OK; -} - - -/** - * @brief Function called when CSR withdraw retrieval is finished - * - * @param cls the `struct CSRClosure *` - * @param csrr replies from the /csr-withdraw request - */ -static void -csr_withdraw_done ( - void *cls, - const struct TALER_EXCHANGE_CsRWithdrawResponse *csrr) -{ - struct CSRClosure *csr = cls; - struct CoinCandidate *can; - struct TALER_PlanchetDetail *planchet; - struct TALER_EXCHANGE_AgeWithdrawHandle *awh; - - GNUNET_assert (NULL != csr); - awh = csr->age_withdraw_handle; - planchet = csr->planchet; - can = csr->candidate; - - GNUNET_assert (NULL != can); - GNUNET_assert (NULL != planchet); - GNUNET_assert (NULL != awh); - - csr->csr_withdraw_handle = NULL; - - switch (csrr->hr.http_status) - { - case MHD_HTTP_OK: - { - bool success = false; - /* Complete the initialization of the coin with CS denomination */ - can->details.alg_values = csrr->details.ok.alg_values; - GNUNET_assert (can->details.alg_values.cipher - == TALER_DENOMINATION_CS); - TALER_planchet_setup_coin_priv (&can->secret, - &can->details.alg_values, - &can->details.coin_priv); - TALER_planchet_blinding_secret_create (&can->secret, - &can->details.alg_values, - &can->details.blinding_key); - /* This initializes the 2nd half of the - can->planchet_detail.blinded_planchet! */ - do { - if (GNUNET_OK != - TALER_planchet_prepare (&csr->denom_pub->key, - &can->details.alg_values, - &can->details.blinding_key, - &can->details.coin_priv, - &can->details.h_age_commitment, - &can->details.h_coin_pub, - planchet)) - { - GNUNET_break (0); - TALER_EXCHANGE_age_withdraw_cancel (awh); - break; - } - - if (GNUNET_OK != - TALER_coin_ev_hash (&planchet->blinded_planchet, - &planchet->denom_pub_hash, - &can->blinded_coin_h)) - { - GNUNET_break (0); - TALER_EXCHANGE_age_withdraw_cancel (awh); - break; - } - success = true; - } while(0); - - awh->csr.pending--; - - /* No more pending requests to /csr-withdraw, we can now perform the - * actual age-withdraw operation */ - if (0 == awh->csr.pending && success) - call_age_withdraw_blinded (awh); - return; - } - default: - break; - } - - TALER_EXCHANGE_age_withdraw_cancel (awh); -} - - -/** - * @brief Prepare the coins for the call to age-withdraw and calculates - * the total amount with fees. - * - * For denomination with CS as cipher, initiates the preflight to retrieve the - * csr-parameter via /csr-withdraw. - * - * @param awh The handler to the age-withdraw - * @param num_coins The number of coins in @e coin_inputs - * @param coin_inputs The input for the individual coin(-candidates) - * @return GNUNET_OK on success, GNUNET_SYSERR on failure - */ -static -enum GNUNET_GenericReturnValue -prepare_coins ( - struct TALER_EXCHANGE_AgeWithdrawHandle *awh, - size_t num_coins, - const struct TALER_EXCHANGE_AgeWithdrawCoinInput coin_inputs[ - static num_coins]) -{ -#define FAIL_IF(cond) \ - do { \ - if ((cond)) \ - { \ - GNUNET_break (! (cond)); \ - goto ERROR; \ - } \ - } while(0) - - GNUNET_assert (0 < num_coins); - awh->age_mask = coin_inputs[0].denom_pub->key.age_mask; - - awh->coin_data = GNUNET_new_array (awh->num_coins, - struct CoinData); - - for (size_t i = 0; i < num_coins; i++) - { - struct CoinData *cd = &awh->coin_data[i]; - const struct TALER_EXCHANGE_AgeWithdrawCoinInput *input = &coin_inputs[i]; - cd->denom_pub = *input->denom_pub; - - /* The mask must be the same for all coins */ - FAIL_IF (awh->age_mask.bits != input->denom_pub->key.age_mask.bits); - - TALER_denom_pub_deep_copy (&cd->denom_pub.key, - &input->denom_pub->key); - - for (uint8_t k = 0; k < TALER_CNC_KAPPA; k++) - { - struct CoinCandidate *can = &cd->coin_candidates[k]; - struct TALER_PlanchetDetail *planchet = &cd->planchet_details[k]; - - can->secret = input->secrets[k]; - /* Derive the age restriction from the given secret and - * the maximum age */ - TALER_age_restriction_from_secret ( - &can->secret, - &input->denom_pub->key.age_mask, - awh->max_age, - &can->details.age_commitment_proof); - - TALER_age_commitment_hash (&can->details.age_commitment_proof.commitment, - &can->details.h_age_commitment); - - switch (input->denom_pub->key.cipher) - { - case TALER_DENOMINATION_RSA: - { - can->details.alg_values.cipher = TALER_DENOMINATION_RSA; - TALER_planchet_setup_coin_priv (&can->secret, - &can->details.alg_values, - &can->details.coin_priv); - TALER_planchet_blinding_secret_create (&can->secret, - &can->details.alg_values, - &can->details.blinding_key); - FAIL_IF (GNUNET_OK != - TALER_planchet_prepare (&cd->denom_pub.key, - &can->details.alg_values, - &can->details.blinding_key, - &can->details.coin_priv, - &can->details.h_age_commitment, - &can->details.h_coin_pub, - planchet)); - FAIL_IF (GNUNET_OK != - TALER_coin_ev_hash (&planchet->blinded_planchet, - &planchet->denom_pub_hash, - &can->blinded_coin_h)); - break; - } - case TALER_DENOMINATION_CS: - { - can->details.alg_values.cipher = TALER_DENOMINATION_CS; - - struct CSRClosure *cls = &cd->csr_cls[k]; - /** - * Save the handler and the denomination for the callback - * after the call to csr-withdraw */ - cls->age_withdraw_handle = awh; - cls->candidate = can; - cls->planchet = planchet; - cls->denom_pub = &cd->denom_pub; - - TALER_cs_withdraw_nonce_derive ( - &can->secret, - &planchet->blinded_planchet.details.cs_blinded_planchet.nonce); - - /* Note that we only initialize the first half - of the blinded_planchet here; the other part - will be done after the /csr-withdraw request! */ - planchet->blinded_planchet.cipher = TALER_DENOMINATION_CS; - cls->csr_withdraw_handle = - TALER_EXCHANGE_csr_withdraw ( - awh->curl_ctx, - awh->exchange_url, - &cd->denom_pub, - &planchet->blinded_planchet.details.cs_blinded_planchet.nonce, - &csr_withdraw_done, - cls); - FAIL_IF (NULL == cls->csr_withdraw_handle); - - awh->csr.pending++; - break; - } - default: - FAIL_IF (1); - } - } - } - return GNUNET_OK; - -ERROR: - TALER_EXCHANGE_age_withdraw_cancel (awh); - return GNUNET_SYSERR; -#undef FAIL_IF -}; - -struct TALER_EXCHANGE_AgeWithdrawHandle * -TALER_EXCHANGE_age_withdraw ( - struct GNUNET_CURL_Context *curl_ctx, - struct TALER_EXCHANGE_Keys *keys, - const char *exchange_url, - const struct TALER_ReservePrivateKeyP *reserve_priv, - size_t num_coins, - const struct TALER_EXCHANGE_AgeWithdrawCoinInput coin_inputs[const static - num_coins], - uint8_t max_age, - TALER_EXCHANGE_AgeWithdrawCallback res_cb, - void *res_cb_cls) -{ - struct TALER_EXCHANGE_AgeWithdrawHandle *awh; - - awh = GNUNET_new (struct TALER_EXCHANGE_AgeWithdrawHandle); - awh->exchange_url = exchange_url; - awh->keys = TALER_EXCHANGE_keys_incref (keys); - awh->curl_ctx = curl_ctx; - awh->reserve_priv = reserve_priv; - awh->callback = res_cb; - awh->callback_cls = res_cb_cls; - awh->num_coins = num_coins; - awh->max_age = max_age; - - - if (GNUNET_OK != prepare_coins (awh, - num_coins, - coin_inputs)) - return NULL; - - /* If there were no CS denominations, we can now perform the actual - * age-withdraw protocol. Otherwise, there are calls to /csr-withdraw - * in flight and once they finish, the age-withdraw-protocol will be - * called from within the csr_withdraw_done-function. - */ - if (0 == awh->csr.pending) - call_age_withdraw_blinded (awh); - - return awh; -} - - -void -TALER_EXCHANGE_age_withdraw_cancel ( - struct TALER_EXCHANGE_AgeWithdrawHandle *awh) -{ - /* Cleanup coin data */ - for (unsigned int i = 0; inum_coins; i++) - { - struct CoinData *cd = &awh->coin_data[i]; - - for (uint8_t k = 0; k < TALER_CNC_KAPPA; k++) - { - struct TALER_PlanchetDetail *planchet = &cd->planchet_details[k]; - struct CSRClosure *cls = &cd->csr_cls[k]; - - if (NULL != cls->csr_withdraw_handle) - { - TALER_EXCHANGE_csr_withdraw_cancel (cls->csr_withdraw_handle); - cls->csr_withdraw_handle = NULL; - } - TALER_blinded_planchet_free (&planchet->blinded_planchet); - } - TALER_denom_pub_free (&cd->denom_pub.key); - } - GNUNET_free (awh->coin_data); - TALER_EXCHANGE_keys_decref (awh->keys); - TALER_EXCHANGE_age_withdraw_blinded_cancel (awh->procotol_handle); - awh->procotol_handle = NULL; - GNUNET_free (awh); -} - - -struct TALER_EXCHANGE_AgeWithdrawBlindedHandle * -TALER_EXCHANGE_age_withdraw_blinded ( - struct GNUNET_CURL_Context *curl_ctx, - struct TALER_EXCHANGE_Keys *keys, - const char *exchange_url, - const struct TALER_ReservePrivateKeyP *reserve_priv, - uint8_t max_age, - unsigned int num_input, - const struct TALER_EXCHANGE_AgeWithdrawBlindedInput blinded_input[static - num_input], - TALER_EXCHANGE_AgeWithdrawBlindedCallback res_cb, - void *res_cb_cls) -{ - struct TALER_EXCHANGE_AgeWithdrawBlindedHandle *awbh = - GNUNET_new (struct TALER_EXCHANGE_AgeWithdrawBlindedHandle); - - awbh->num_input = num_input; - awbh->blinded_input = blinded_input; - awbh->keys = TALER_EXCHANGE_keys_incref (keys); - awbh->curl_ctx = curl_ctx; - awbh->reserve_priv = reserve_priv; - awbh->callback = res_cb; - awbh->callback_cls = res_cb_cls; - awbh->max_age = max_age; - - GNUNET_CRYPTO_eddsa_key_get_public (&awbh->reserve_priv->eddsa_priv, - &awbh->reserve_pub.eddsa_pub); - - if (GNUNET_OK != prepare_url (awbh, - exchange_url)) - return NULL; - - perform_protocol (awbh); - return awbh; -} - - -void -TALER_EXCHANGE_age_withdraw_blinded_cancel ( - struct TALER_EXCHANGE_AgeWithdrawBlindedHandle *awbh) -{ - if (NULL == awbh) - return; - - if (NULL != awbh->job) - { - GNUNET_CURL_job_cancel (awbh->job); - awbh->job = NULL; - } - GNUNET_free (awbh->request_url); - TALER_EXCHANGE_keys_decref (awbh->keys); - TALER_curl_easy_post_finished (&awbh->post_ctx); - GNUNET_free (awbh); -} - - -/* exchange_api_age_withdraw.c */ diff --git a/src/lib/exchange_api_age_withdraw_reveal.c b/src/lib/exchange_api_age_withdraw_reveal.c deleted file mode 100644 index a448d109d..000000000 --- a/src/lib/exchange_api_age_withdraw_reveal.c +++ /dev/null @@ -1,471 +0,0 @@ -/* - This file is part of TALER - Copyright (C) 2023 Taler Systems SA - - TALER is free software; you can redistribute it and/or modify it under the - terms of the GNU General Public License as published by the Free Software - Foundation; either version 3, or (at your option) any later version. - - TALER is distributed in the hope that it will be useful, but WITHOUT ANY - WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR - A PARTICULAR PURPOSE. See the GNU General Public License for more details. - - You should have received a copy of the GNU General Public License along with - TALER; see the file COPYING. If not, see - -*/ -/** - * @file lib/exchange_api_age_withdraw_reveal.c - * @brief Implementation of /age-withdraw/$ACH/reveal requests - * @author Özgür Kesim - */ - -#include "platform.h" -#include -#include -#include /* just for HTTP status codes */ -#include -#include -#include -#include "taler_curl_lib.h" -#include "taler_json_lib.h" -#include "taler_exchange_service.h" -#include "exchange_api_common.h" -#include "exchange_api_handle.h" -#include "taler_signatures.h" -#include "exchange_api_curl_defaults.h" - -/** - * Handler for a running age-withdraw-reveal request - */ -struct TALER_EXCHANGE_AgeWithdrawRevealHandle -{ - - /* The index not to be disclosed */ - uint8_t noreveal_index; - - /* The age-withdraw commitment */ - struct TALER_AgeWithdrawCommitmentHashP h_commitment; - - /* The reserve's public key */ - const struct TALER_ReservePublicKeyP *reserve_pub; - - /* Number of coins */ - size_t num_coins; - - /* The @e num_coins * kappa coin secrets from the age-withdraw commitment */ - const struct TALER_EXCHANGE_AgeWithdrawCoinInput *coins_input; - - /* The url for the reveal request */ - const char *request_url; - - /** - * CURL handle for the request job. - */ - struct GNUNET_CURL_Job *job; - - /** - * Post Context - */ - struct TALER_CURL_PostContext post_ctx; - - /* Callback */ - TALER_EXCHANGE_AgeWithdrawRevealCallback callback; - - /* Reveal */ - void *callback_cls; -}; - - -/** - * We got a 200 OK response for the /age-withdraw/$ACH/reveal operation. - * Extract the signed blindedcoins and return it to the caller. - * - * @param awrh operation handle - * @param j_response reply from the exchange - * @return #GNUNET_OK on success, #GNUNET_SYSERR on errors - */ -static enum GNUNET_GenericReturnValue -age_withdraw_reveal_ok ( - struct TALER_EXCHANGE_AgeWithdrawRevealHandle *awrh, - const json_t *j_response) -{ - struct TALER_EXCHANGE_AgeWithdrawRevealResponse response = { - .hr.reply = j_response, - .hr.http_status = MHD_HTTP_OK, - }; - const json_t *j_sigs; - struct GNUNET_JSON_Specification spec[] = { - GNUNET_JSON_spec_array_const ("ev_sigs", - &j_sigs), - GNUNET_JSON_spec_end () - }; - - if (GNUNET_OK != GNUNET_JSON_parse (j_response, - spec, - NULL, NULL)) - { - GNUNET_break_op (0); - return GNUNET_SYSERR; - } - - if (awrh->num_coins != json_array_size (j_sigs)) - { - /* Number of coins generated does not match our expectation */ - GNUNET_break_op (0); - return GNUNET_SYSERR; - } - - { - struct TALER_BlindedDenominationSignature denom_sigs[awrh->num_coins]; - json_t *j_sig; - size_t n; - - /* Reconstruct the coins and unblind the signatures */ - json_array_foreach (j_sigs, n, j_sig) - { - struct GNUNET_JSON_Specification spec[] = { - TALER_JSON_spec_blinded_denom_sig (NULL, - &denom_sigs[n]), - GNUNET_JSON_spec_end () - }; - - if (GNUNET_OK != GNUNET_JSON_parse (j_sig, - spec, - NULL, NULL)) - { - GNUNET_break_op (0); - return GNUNET_SYSERR; - } - - } - - response.details.ok.num_sigs = awrh->num_coins; - response.details.ok.blinded_denom_sigs = denom_sigs; - awrh->callback (awrh->callback_cls, - &response); - /* Make sure the callback isn't called again */ - awrh->callback = NULL; - } - - return GNUNET_OK; -} - - -/** - * Function called when we're done processing the - * HTTP /age-withdraw/$ACH/reveal request. - * - * @param cls the `struct TALER_EXCHANGE_AgeWithdrawRevealHandle` - * @param response_code The HTTP response code - * @param response response data - */ -static void -handle_age_withdraw_reveal_finished ( - void *cls, - long response_code, - const void *response) -{ - struct TALER_EXCHANGE_AgeWithdrawRevealHandle *awrh = cls; - const json_t *j_response = response; - struct TALER_EXCHANGE_AgeWithdrawRevealResponse awr = { - .hr.reply = j_response, - .hr.http_status = (unsigned int) response_code - }; - - awrh->job = NULL; - /* FIXME[oec]: Only handle response-codes that are in the spec */ - switch (response_code) - { - case 0: - awr.hr.ec = TALER_EC_GENERIC_INVALID_RESPONSE; - break; - case MHD_HTTP_OK: - { - enum GNUNET_GenericReturnValue ret; - - ret = age_withdraw_reveal_ok (awrh, - j_response); - if (GNUNET_OK != ret) - { - GNUNET_break_op (0); - awr.hr.http_status = 0; - awr.hr.ec = TALER_EC_GENERIC_REPLY_MALFORMED; - break; - } - GNUNET_assert (NULL == awrh->callback); - TALER_EXCHANGE_age_withdraw_reveal_cancel (awrh); - return; - } - case MHD_HTTP_UNAVAILABLE_FOR_LEGAL_REASONS: - /* only validate reply is well-formed */ - { - uint64_t ptu; - struct GNUNET_JSON_Specification spec[] = { - GNUNET_JSON_spec_uint64 ("legitimization_uuid", - &ptu), - GNUNET_JSON_spec_end () - }; - - if (GNUNET_OK != - GNUNET_JSON_parse (j_response, - spec, - NULL, NULL)) - { - GNUNET_break_op (0); - awr.hr.http_status = 0; - awr.hr.ec = TALER_EC_GENERIC_REPLY_MALFORMED; - break; - } - } - case MHD_HTTP_BAD_REQUEST: - /* This should never happen, either us or the exchange is buggy - (or API version conflict); just pass JSON reply to the application */ - awr.hr.ec = TALER_JSON_get_error_code (j_response); - awr.hr.hint = TALER_JSON_get_error_hint (j_response); - break; - case MHD_HTTP_FORBIDDEN: - GNUNET_break_op (0); - /** - * This should never happen, as we don't sent any signatures - * to the exchange to verify. We should simply pass the JSON reply - * to the application - **/ - awr.hr.ec = TALER_JSON_get_error_code (j_response); - awr.hr.hint = TALER_JSON_get_error_hint (j_response); - break; - case MHD_HTTP_NOT_FOUND: - /* Nothing really to verify, the exchange basically just says - that it doesn't know this age-withdraw commitment. */ - awr.hr.ec = TALER_JSON_get_error_code (j_response); - awr.hr.hint = TALER_JSON_get_error_hint (j_response); - break; - case MHD_HTTP_CONFLICT: - /* An age commitment for one of the coins did not fulfill - * the required maximum age requirement of the corresponding - * reserve. - * Error code: TALER_EC_EXCHANGE_GENERIC_COIN_AGE_REQUIREMENT_FAILURE. - */ - awr.hr.ec = TALER_JSON_get_error_code (j_response); - awr.hr.hint = TALER_JSON_get_error_hint (j_response); - break; - case MHD_HTTP_GONE: - /* could happen if denomination was revoked */ - /* Note: one might want to check /keys for revocation - signature here, alas tricky in case our /keys - is outdated => left to clients */ - awr.hr.ec = TALER_JSON_get_error_code (j_response); - awr.hr.hint = TALER_JSON_get_error_hint (j_response); - break; - case MHD_HTTP_INTERNAL_SERVER_ERROR: - /* Server had an internal issue; we should retry, but this API - leaves this to the application */ - awr.hr.ec = TALER_JSON_get_error_code (j_response); - awr.hr.hint = TALER_JSON_get_error_hint (j_response); - break; - default: - /* unexpected response code */ - GNUNET_break_op (0); - awr.hr.ec = TALER_JSON_get_error_code (j_response); - awr.hr.hint = TALER_JSON_get_error_hint (j_response); - GNUNET_log (GNUNET_ERROR_TYPE_ERROR, - "Unexpected response code %u/%d for exchange age-withdraw\n", - (unsigned int) response_code, - (int) awr.hr.ec); - break; - } - awrh->callback (awrh->callback_cls, - &awr); - TALER_EXCHANGE_age_withdraw_reveal_cancel (awrh); -} - - -/** - * Prepares the request URL for the age-withdraw-reveal request - * - * @param exchange_url The base-URL to the exchange - * @param[in,out] awrh The handler - * @return GNUNET_OK on success, GNUNET_SYSERR otherwise - */ -static -enum GNUNET_GenericReturnValue -prepare_url ( - const char *exchange_url, - struct TALER_EXCHANGE_AgeWithdrawRevealHandle *awrh) -{ - char arg_str[sizeof (struct TALER_AgeWithdrawCommitmentHashP) * 2 + 32]; - char pub_str[sizeof (struct TALER_AgeWithdrawCommitmentHashP) * 2]; - char *end; - - end = GNUNET_STRINGS_data_to_string (&awrh->h_commitment, - sizeof (awrh->h_commitment), - pub_str, - sizeof (pub_str)); - *end = '\0'; - GNUNET_snprintf (arg_str, - sizeof (arg_str), - "age-withdraw/%s/reveal", - pub_str); - - awrh->request_url = TALER_url_join (exchange_url, - arg_str, - NULL); - if (NULL == awrh->request_url) - { - GNUNET_break (0); - TALER_EXCHANGE_age_withdraw_reveal_cancel (awrh); - return GNUNET_SYSERR; - } - - return GNUNET_OK; -} - - -/** - * Call /age-withdraw/$ACH/reveal - * - * @param curl_ctx The context for CURL - * @param awrh The handler - */ -static -void -perform_protocol ( - struct GNUNET_CURL_Context *curl_ctx, - struct TALER_EXCHANGE_AgeWithdrawRevealHandle *awrh) -{ - CURL *curlh = NULL; - json_t *j_request_body = NULL; - json_t *j_array_of_secrets = NULL; - json_t *j_secrets = NULL; - json_t *j_sec = NULL; - -#define FAIL_IF(cond) \ - do { \ - if ((cond)) \ - { \ - GNUNET_break (! (cond)); \ - goto ERROR; \ - } \ - } while(0) - - j_array_of_secrets = json_array (); - FAIL_IF (NULL == j_array_of_secrets); - - for (size_t n = 0; n < awrh->num_coins; n++) - { - const struct TALER_PlanchetMasterSecretP *secrets = - awrh->coins_input[n].secrets; - - j_secrets = json_array (); - FAIL_IF (NULL == j_secrets); - - for (uint8_t k = 0; k < TALER_CNC_KAPPA; k++) - { - const struct TALER_PlanchetMasterSecretP *secret = &secrets[k]; - if (awrh->noreveal_index == k) - continue; - - j_sec = GNUNET_JSON_PACK ( - GNUNET_JSON_pack_data_auto (NULL, secret)); - - FAIL_IF (NULL == j_sec); - FAIL_IF (0 < json_array_append_new (j_secrets, - j_sec)); - } - - FAIL_IF (0 < json_array_append_new (j_array_of_secrets, - j_secrets)); - } - j_request_body = GNUNET_JSON_PACK ( - GNUNET_JSON_pack_data_auto ("reserve_pub", - awrh->reserve_pub), - GNUNET_JSON_pack_array_steal ("disclosed_coin_secrets", - j_array_of_secrets)); - FAIL_IF (NULL == j_request_body); - - curlh = TALER_EXCHANGE_curl_easy_get_ (awrh->request_url); - FAIL_IF (NULL == curlh); - FAIL_IF (GNUNET_OK != - TALER_curl_easy_post (&awrh->post_ctx, - curlh, - j_request_body)); - json_decref (j_request_body); - j_request_body = NULL; - - awrh->job = GNUNET_CURL_job_add2 (curl_ctx, - curlh, - awrh->post_ctx.headers, - &handle_age_withdraw_reveal_finished, - awrh); - FAIL_IF (NULL == awrh->job); - - /* No error, return */ - return; - -ERROR: - if (NULL != j_sec) - json_decref (j_sec); - if (NULL != j_secrets) - json_decref (j_secrets); - if (NULL != j_array_of_secrets) - json_decref (j_array_of_secrets); - if (NULL != j_request_body) - json_decref (j_request_body); - if (NULL != curlh) - curl_easy_cleanup (curlh); - TALER_EXCHANGE_age_withdraw_reveal_cancel (awrh); - return; -#undef FAIL_IF -} - - -struct TALER_EXCHANGE_AgeWithdrawRevealHandle * -TALER_EXCHANGE_age_withdraw_reveal ( - struct GNUNET_CURL_Context *curl_ctx, - const char *exchange_url, - size_t num_coins, - const struct TALER_EXCHANGE_AgeWithdrawCoinInput coins_input[static - num_coins], - uint8_t noreveal_index, - const struct TALER_AgeWithdrawCommitmentHashP *h_commitment, - const struct TALER_ReservePublicKeyP *reserve_pub, - TALER_EXCHANGE_AgeWithdrawRevealCallback reveal_cb, - void *reveal_cb_cls) -{ - struct TALER_EXCHANGE_AgeWithdrawRevealHandle *awrh = - GNUNET_new (struct TALER_EXCHANGE_AgeWithdrawRevealHandle); - awrh->noreveal_index = noreveal_index; - awrh->h_commitment = *h_commitment; - awrh->num_coins = num_coins; - awrh->coins_input = coins_input; - awrh->callback = reveal_cb; - awrh->callback_cls = reveal_cb_cls; - awrh->reserve_pub = reserve_pub; - - if (GNUNET_OK != - prepare_url (exchange_url, - awrh)) - return NULL; - - perform_protocol (curl_ctx, awrh); - - return awrh; -} - - -void -TALER_EXCHANGE_age_withdraw_reveal_cancel ( - struct TALER_EXCHANGE_AgeWithdrawRevealHandle *awrh) -{ - if (NULL != awrh->job) - { - GNUNET_CURL_job_cancel (awrh->job); - awrh->job = NULL; - } - TALER_curl_easy_post_finished (&awrh->post_ctx); - /* FIXME[oec]: anything else left to cleanup!? */ - GNUNET_free (awrh); -} - - -/* exchange_api_age_withdraw_reveal.c */ diff --git a/src/lib/exchange_api_auditor_add_denomination.c b/src/lib/exchange_api_auditor_add_denomination.c deleted file mode 100644 index 89de0d7f1..000000000 --- a/src/lib/exchange_api_auditor_add_denomination.c +++ /dev/null @@ -1,238 +0,0 @@ -/* - This file is part of TALER - Copyright (C) 2015-2021 Taler Systems SA - - TALER is free software; you can redistribute it and/or modify it under the - terms of the GNU General Public License as published by the Free Software - Foundation; either version 3, or (at your option) any later version. - - TALER is distributed in the hope that it will be useful, but WITHOUT ANY - WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR - A PARTICULAR PURPOSE. See the GNU General Public License for more details. - - You should have received a copy of the GNU General Public License along with - TALER; see the file COPYING. If not, see - -*/ -/** - * @file lib/exchange_api_auditor_add_denomination.c - * @brief functions for the auditor to add its signature for denomination at the exchange - * @author Christian Grothoff - */ -#include "platform.h" -#include "taler_json_lib.h" -#include -#include "taler_exchange_service.h" -#include "auditor_api_curl_defaults.h" -#include "taler_signatures.h" -#include "taler_curl_lib.h" -#include "taler_json_lib.h" - - -struct TALER_EXCHANGE_AuditorAddDenominationHandle -{ - - /** - * The url for this request. - */ - char *url; - - /** - * Minor context that holds body and headers. - */ - struct TALER_CURL_PostContext post_ctx; - - /** - * Handle for the request. - */ - struct GNUNET_CURL_Job *job; - - /** - * Function to call with the result. - */ - TALER_EXCHANGE_AuditorAddDenominationCallback cb; - - /** - * Closure for @a cb. - */ - void *cb_cls; - - /** - * Reference to the execution context. - */ - struct GNUNET_CURL_Context *ctx; -}; - - -/** - * Function called when we're done processing the - * HTTP POST /auditor/$AUDITOR_PUB/$H_DENOM_PUB request. - * - * @param cls the `struct TALER_EXCHANGE_AuditorAddDenominationHandle *` - * @param response_code HTTP response code, 0 on error - * @param response response body, NULL if not in JSON - */ -static void -handle_auditor_add_denomination_finished (void *cls, - long response_code, - const void *response) -{ - struct TALER_EXCHANGE_AuditorAddDenominationHandle *ah = cls; - const json_t *json = response; - struct TALER_EXCHANGE_AuditorAddDenominationResponse adr = { - .hr.http_status = (unsigned int) response_code, - .hr.reply = json - }; - - ah->job = NULL; - switch (response_code) - { - case MHD_HTTP_NO_CONTENT: - break; - case MHD_HTTP_FORBIDDEN: - adr.hr.ec = TALER_JSON_get_error_code (json); - adr.hr.hint = TALER_JSON_get_error_hint (json); - break; - case MHD_HTTP_NOT_FOUND: - adr.hr.ec = TALER_JSON_get_error_code (json); - adr.hr.hint = TALER_JSON_get_error_hint (json); - break; - case MHD_HTTP_GONE: - adr.hr.ec = TALER_JSON_get_error_code (json); - adr.hr.hint = TALER_JSON_get_error_hint (json); - break; - case MHD_HTTP_PRECONDITION_FAILED: - adr.hr.ec = TALER_JSON_get_error_code (json); - adr.hr.hint = TALER_JSON_get_error_hint (json); - break; - default: - /* unexpected response code */ - if (NULL != json) - { - adr.hr.ec = TALER_JSON_get_error_code (json); - adr.hr.hint = TALER_JSON_get_error_hint (json); - GNUNET_log (GNUNET_ERROR_TYPE_ERROR, - "Unexpected response code %u/%d for exchange auditor-add-denomination at URL `%s'\n", - (unsigned int) response_code, - (int) adr.hr.ec, - ah->url); - } - else - { - adr.hr.ec = TALER_EC_GENERIC_INVALID_RESPONSE; - adr.hr.hint = NULL; - GNUNET_log (GNUNET_ERROR_TYPE_ERROR, - "Unexpected HTTP response code %u (no JSON returned) at URL `%s'\n", - (unsigned int) response_code, - ah->url); - } - break; - } - if (NULL != ah->cb) - { - ah->cb (ah->cb_cls, - &adr); - ah->cb = NULL; - } - TALER_EXCHANGE_add_auditor_denomination_cancel (ah); -} - - -struct TALER_EXCHANGE_AuditorAddDenominationHandle * -TALER_EXCHANGE_add_auditor_denomination ( - struct GNUNET_CURL_Context *ctx, - const char *url, - const struct TALER_DenominationHashP *h_denom_pub, - const struct TALER_AuditorPublicKeyP *auditor_pub, - const struct TALER_AuditorSignatureP *auditor_sig, - TALER_EXCHANGE_AuditorAddDenominationCallback cb, - void *cb_cls) -{ - struct TALER_EXCHANGE_AuditorAddDenominationHandle *ah; - CURL *eh; - json_t *body; - - ah = GNUNET_new (struct TALER_EXCHANGE_AuditorAddDenominationHandle); - ah->cb = cb; - ah->cb_cls = cb_cls; - ah->ctx = ctx; - { - char apub_str[sizeof (*auditor_pub) * 2]; - char denom_str[sizeof (*h_denom_pub) * 2]; - char arg_str[sizeof (apub_str) + sizeof (denom_str) + 32]; - char *end; - - end = GNUNET_STRINGS_data_to_string (auditor_pub, - sizeof (*auditor_pub), - apub_str, - sizeof (apub_str)); - *end = '\0'; - end = GNUNET_STRINGS_data_to_string (h_denom_pub, - sizeof (*h_denom_pub), - denom_str, - sizeof (denom_str)); - *end = '\0'; - GNUNET_snprintf (arg_str, - sizeof (arg_str), - "auditors/%s/%s", - apub_str, - denom_str); - ah->url = TALER_url_join (url, - arg_str, - NULL); - } - if (NULL == ah->url) - { - GNUNET_log (GNUNET_ERROR_TYPE_ERROR, - "Could not construct request URL.\n"); - GNUNET_free (ah); - return NULL; - } - body = GNUNET_JSON_PACK ( - GNUNET_JSON_pack_data_auto ("auditor_sig", - auditor_sig)); - eh = TALER_AUDITOR_curl_easy_get_ (ah->url); - if ( (NULL == eh) || - (GNUNET_OK != - TALER_curl_easy_post (&ah->post_ctx, - eh, - body)) ) - { - GNUNET_break (0); - if (NULL != eh) - curl_easy_cleanup (eh); - json_decref (body); - GNUNET_free (ah->url); - return NULL; - } - json_decref (body); - GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, - "Requesting URL '%s'\n", - ah->url); - ah->job = GNUNET_CURL_job_add2 (ctx, - eh, - ah->post_ctx.headers, - &handle_auditor_add_denomination_finished, - ah); - if (NULL == ah->job) - { - TALER_EXCHANGE_add_auditor_denomination_cancel (ah); - return NULL; - } - return ah; -} - - -void -TALER_EXCHANGE_add_auditor_denomination_cancel ( - struct TALER_EXCHANGE_AuditorAddDenominationHandle *ah) -{ - if (NULL != ah->job) - { - GNUNET_CURL_job_cancel (ah->job); - ah->job = NULL; - } - TALER_curl_easy_post_finished (&ah->post_ctx); - GNUNET_free (ah->url); - GNUNET_free (ah); -} diff --git a/src/lib/exchange_api_csr_melt.c b/src/lib/exchange_api_csr_melt.c deleted file mode 100644 index f59995af3..000000000 --- a/src/lib/exchange_api_csr_melt.c +++ /dev/null @@ -1,317 +0,0 @@ -/* - This file is part of TALER - Copyright (C) 2014-2022 Taler Systems SA - - TALER is free software; you can redistribute it and/or modify it under the - terms of the GNU General Public License as published by the Free Software - Foundation; either version 3, or (at your option) any later version. - - TALER is distributed in the hope that it will be useful, but WITHOUT ANY - WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR - A PARTICULAR PURPOSE. See the GNU General Public License for more details. - - You should have received a copy of the GNU General Public License along with - TALER; see the file COPYING. If not, see - -*/ -/** - * @file lib/exchange_api_csr_melt.c - * @brief Implementation of /csr-melt requests (get R in exchange used for Clause Schnorr refresh) - * @author Lucien Heuzeveldt - * @author Gian Demarmels - */ -#include "platform.h" -#include -#include /* just for HTTP status codes */ -#include -#include -#include -#include "taler_exchange_service.h" -#include "taler_json_lib.h" -#include "exchange_api_handle.h" -#include "taler_signatures.h" -#include "exchange_api_curl_defaults.h" - - -/** - * @brief A Clause Schnorr R Handle - */ -struct TALER_EXCHANGE_CsRMeltHandle -{ - - /** - * Function to call with the result. - */ - TALER_EXCHANGE_CsRMeltCallback cb; - - /** - * Closure for @a cb. - */ - void *cb_cls; - - /** - * The url for this request. - */ - char *url; - - /** - * Handle for the request. - */ - struct GNUNET_CURL_Job *job; - - /** - * Context for #TEH_curl_easy_post(). Keeps the data that must - * persist for Curl to make the upload. - */ - struct TALER_CURL_PostContext post_ctx; -}; - - -/** - * We got a 200 OK response for the /reserves/$RESERVE_PUB/withdraw operation. - * Extract the coin's signature and return it to the caller. The signature we - * get from the exchange is for the blinded value. Thus, we first must - * unblind it and then should verify its validity against our coin's hash. - * - * If everything checks out, we return the unblinded signature - * to the application via the callback. - * - * @param csrh operation handle - * @param arr reply from the exchange - * @param hr http response details - * @return #GNUNET_OK on success, #GNUNET_SYSERR on errors - */ -static enum GNUNET_GenericReturnValue -csr_ok (struct TALER_EXCHANGE_CsRMeltHandle *csrh, - const json_t *arr, - struct TALER_EXCHANGE_HttpResponse *hr) -{ - unsigned int alen = json_array_size (arr); - struct TALER_ExchangeWithdrawValues alg_values[GNUNET_NZL (alen)]; - struct TALER_EXCHANGE_CsRMeltResponse csrr = { - .hr = *hr, - .details.ok.alg_values_len = alen, - .details.ok.alg_values = alg_values - }; - - for (unsigned int i = 0; icb (csrh->cb_cls, - &csrr); - return GNUNET_OK; -} - - -/** - * Function called when we're done processing the HTTP /csr request. - * - * @param cls the `struct TALER_EXCHANGE_CsRMeltHandle` - * @param response_code HTTP response code, 0 on error - * @param response parsed JSON result, NULL on error - */ -static void -handle_csr_finished (void *cls, - long response_code, - const void *response) -{ - struct TALER_EXCHANGE_CsRMeltHandle *csrh = cls; - const json_t *j = response; - struct TALER_EXCHANGE_HttpResponse hr = { - .reply = j, - .http_status = (unsigned int) response_code - }; - struct TALER_EXCHANGE_CsRMeltResponse csrr = { - .hr = hr - }; - - csrh->job = NULL; - switch (response_code) - { - case 0: - csrr.hr.ec = TALER_EC_GENERIC_INVALID_RESPONSE; - break; - case MHD_HTTP_OK: - { - json_t *arr; - - arr = json_object_get (j, - "ewvs"); - if ( (NULL == arr) || - (0 == json_array_size (arr)) || - (GNUNET_OK != - csr_ok (csrh, - arr, - &hr)) ) - { - GNUNET_break_op (0); - csrr.hr.http_status = 0; - csrr.hr.ec = TALER_EC_GENERIC_REPLY_MALFORMED; - break; - } - } - TALER_EXCHANGE_csr_melt_cancel (csrh); - return; - case MHD_HTTP_BAD_REQUEST: - /* This should never happen, either us or the exchange is buggy - (or API version conflict); just pass JSON reply to the application */ - csrr.hr.ec = TALER_JSON_get_error_code (j); - csrr.hr.hint = TALER_JSON_get_error_hint (j); - break; - case MHD_HTTP_NOT_FOUND: - /* Nothing really to verify, the exchange basically just says - that it doesn't know the /csr endpoint or denomination. - Can happen if the exchange doesn't support Clause Schnorr. - We should simply pass the JSON reply to the application. */ - csrr.hr.ec = TALER_JSON_get_error_code (j); - csrr.hr.hint = TALER_JSON_get_error_hint (j); - break; - case MHD_HTTP_GONE: - /* could happen if denomination was revoked */ - /* Note: one might want to check /keys for revocation - signature here, alas tricky in case our /keys - is outdated => left to clients */ - csrr.hr.ec = TALER_JSON_get_error_code (j); - csrr.hr.hint = TALER_JSON_get_error_hint (j); - break; - case MHD_HTTP_INTERNAL_SERVER_ERROR: - /* Server had an internal issue; we should retry, but this API - leaves this to the application */ - csrr.hr.ec = TALER_JSON_get_error_code (j); - csrr.hr.hint = TALER_JSON_get_error_hint (j); - break; - default: - /* unexpected response code */ - GNUNET_break_op (0); - csrr.hr.ec = TALER_JSON_get_error_code (j); - csrr.hr.hint = TALER_JSON_get_error_hint (j); - GNUNET_log (GNUNET_ERROR_TYPE_ERROR, - "Unexpected response code %u/%d for CS R request\n", - (unsigned int) response_code, - (int) hr.ec); - break; - } - csrh->cb (csrh->cb_cls, - &csrr); - csrh->cb = NULL; - TALER_EXCHANGE_csr_melt_cancel (csrh); -} - - -struct TALER_EXCHANGE_CsRMeltHandle * -TALER_EXCHANGE_csr_melt ( - struct GNUNET_CURL_Context *ctx, - const char *url, - const struct TALER_RefreshMasterSecretP *rms, - unsigned int nks_len, - struct TALER_EXCHANGE_NonceKey nks[static nks_len], - TALER_EXCHANGE_CsRMeltCallback res_cb, - void *res_cb_cls) -{ - struct TALER_EXCHANGE_CsRMeltHandle *csrh; - json_t *csr_arr; - - if (0 == nks_len) - { - GNUNET_break (0); - return NULL; - } - for (unsigned int i = 0; ikey.cipher) - { - GNUNET_break (0); - return NULL; - } - csrh = GNUNET_new (struct TALER_EXCHANGE_CsRMeltHandle); - csrh->cb = res_cb; - csrh->cb_cls = res_cb_cls; - csr_arr = json_array (); - GNUNET_assert (NULL != csr_arr); - for (unsigned int i = 0; icnc_num), - GNUNET_JSON_pack_data_auto ("denom_pub_hash", - &nk->pk->h_key)); - GNUNET_assert (NULL != csr_obj); - GNUNET_assert (0 == - json_array_append_new (csr_arr, - csr_obj)); - } - csrh->url = TALER_url_join (url, - "csr-melt", - NULL); - if (NULL == csrh->url) - { - json_decref (csr_arr); - GNUNET_free (csrh); - return NULL; - } - { - CURL *eh; - json_t *req; - - req = GNUNET_JSON_PACK ( - GNUNET_JSON_pack_data_auto ("rms", - rms), - GNUNET_JSON_pack_array_steal ("nks", - csr_arr)); - eh = TALER_EXCHANGE_curl_easy_get_ (csrh->url); - if ( (NULL == eh) || - (GNUNET_OK != - TALER_curl_easy_post (&csrh->post_ctx, - eh, - req)) ) - { - GNUNET_break (0); - if (NULL != eh) - curl_easy_cleanup (eh); - json_decref (req); - GNUNET_free (csrh->url); - GNUNET_free (csrh); - return NULL; - } - json_decref (req); - csrh->job = GNUNET_CURL_job_add2 (ctx, - eh, - csrh->post_ctx.headers, - &handle_csr_finished, - csrh); - } - return csrh; -} - - -void -TALER_EXCHANGE_csr_melt_cancel (struct TALER_EXCHANGE_CsRMeltHandle *csrh) -{ - if (NULL != csrh->job) - { - GNUNET_CURL_job_cancel (csrh->job); - csrh->job = NULL; - } - GNUNET_free (csrh->url); - TALER_curl_easy_post_finished (&csrh->post_ctx); - GNUNET_free (csrh); -} diff --git a/src/lib/exchange_api_kyc_check.c b/src/lib/exchange_api_kyc_check.c deleted file mode 100644 index 373dd89a7..000000000 --- a/src/lib/exchange_api_kyc_check.c +++ /dev/null @@ -1,329 +0,0 @@ -/* - This file is part of TALER - Copyright (C) 2021-2023 Taler Systems SA - - TALER is free software; you can redistribute it and/or modify it under the - terms of the GNU General Public License as published by the Free Software - Foundation; either version 3, or (at your option) any later version. - - TALER is distributed in the hope that it will be useful, but WITHOUT ANY - WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR - A PARTICULAR PURPOSE. See the GNU General Public License for more details. - - You should have received a copy of the GNU General Public License along with - TALER; see the file COPYING. If not, see - -*/ -/** - * @file lib/exchange_api_kyc_check.c - * @brief Implementation of the /kyc-check request - * @author Christian Grothoff - */ -#include "platform.h" -#include /* just for HTTP check codes */ -#include -#include -#include "taler_exchange_service.h" -#include "taler_json_lib.h" -#include "exchange_api_handle.h" -#include "taler_signatures.h" -#include "exchange_api_curl_defaults.h" - - -/** - * @brief A ``/kyc-check`` handle - */ -struct TALER_EXCHANGE_KycCheckHandle -{ - - /** - * The url for this request. - */ - char *url; - - /** - * Keys of the exchange. - */ - struct TALER_EXCHANGE_Keys *keys; - - /** - * Handle for the request. - */ - struct GNUNET_CURL_Job *job; - - /** - * Function to call with the result. - */ - TALER_EXCHANGE_KycStatusCallback cb; - - /** - * Closure for @e cb. - */ - void *cb_cls; - - /** - * Hash of the payto:// URL that is being KYC'ed. - */ - struct TALER_PaytoHashP h_payto; - -}; - - -/** - * Function called when we're done processing the - * HTTP /kyc-check request. - * - * @param cls the `struct TALER_EXCHANGE_KycCheckHandle` - * @param response_code HTTP response code, 0 on error - * @param response parsed JSON result, NULL on error - */ -static void -handle_kyc_check_finished (void *cls, - long response_code, - const void *response) -{ - struct TALER_EXCHANGE_KycCheckHandle *kch = cls; - const json_t *j = response; - struct TALER_EXCHANGE_KycStatus ks = { - .http_status = (unsigned int) response_code - }; - - kch->job = NULL; - switch (response_code) - { - case 0: - ks.ec = TALER_EC_GENERIC_INVALID_RESPONSE; - break; - case MHD_HTTP_OK: - { - const json_t *kyc_details; - uint32_t status; - struct GNUNET_JSON_Specification spec[] = { - GNUNET_JSON_spec_fixed_auto ("exchange_sig", - &ks.details.ok.exchange_sig), - GNUNET_JSON_spec_fixed_auto ("exchange_pub", - &ks.details.ok.exchange_pub), - GNUNET_JSON_spec_timestamp ("now", - &ks.details.ok.timestamp), - GNUNET_JSON_spec_object_const ("kyc_details", - &kyc_details), - GNUNET_JSON_spec_uint32 ("aml_status", - &status), - GNUNET_JSON_spec_end () - }; - - if (GNUNET_OK != - GNUNET_JSON_parse (j, - spec, - NULL, NULL)) - { - GNUNET_break_op (0); - ks.http_status = 0; - ks.ec = TALER_EC_GENERIC_INVALID_RESPONSE; - break; - } - ks.details.ok.kyc_details = kyc_details; - ks.details.ok.aml_status - = (enum TALER_AmlDecisionState) status; - if (GNUNET_OK != - TALER_EXCHANGE_test_signing_key (kch->keys, - &ks.details.ok.exchange_pub)) - { - GNUNET_break_op (0); - ks.http_status = 0; - ks.ec = TALER_EC_GENERIC_INVALID_RESPONSE; - GNUNET_JSON_parse_free (spec); - break; - } - - if (GNUNET_OK != - TALER_exchange_online_account_setup_success_verify ( - &kch->h_payto, - ks.details.ok.kyc_details, - ks.details.ok.timestamp, - &ks.details.ok.exchange_pub, - &ks.details.ok.exchange_sig)) - { - GNUNET_break_op (0); - ks.http_status = 0; - ks.ec = TALER_EC_GENERIC_INVALID_RESPONSE; - GNUNET_JSON_parse_free (spec); - break; - } - kch->cb (kch->cb_cls, - &ks); - GNUNET_JSON_parse_free (spec); - TALER_EXCHANGE_kyc_check_cancel (kch); - return; - } - case MHD_HTTP_ACCEPTED: - { - uint32_t status; - struct GNUNET_JSON_Specification spec[] = { - GNUNET_JSON_spec_string ("kyc_url", - &ks.details.accepted.kyc_url), - GNUNET_JSON_spec_uint32 ("aml_status", - &status), - GNUNET_JSON_spec_end () - }; - - if (GNUNET_OK != - GNUNET_JSON_parse (j, - spec, - NULL, NULL)) - { - GNUNET_break_op (0); - ks.http_status = 0; - ks.ec = TALER_EC_GENERIC_INVALID_RESPONSE; - break; - } - ks.details.accepted.aml_status - = (enum TALER_AmlDecisionState) status; - kch->cb (kch->cb_cls, - &ks); - GNUNET_JSON_parse_free (spec); - TALER_EXCHANGE_kyc_check_cancel (kch); - return; - } - case MHD_HTTP_NO_CONTENT: - break; - case MHD_HTTP_BAD_REQUEST: - ks.ec = TALER_JSON_get_error_code (j); - /* This should never happen, either us or the exchange is buggy - (or API version conflict); just pass JSON reply to the application */ - break; - case MHD_HTTP_FORBIDDEN: - ks.ec = TALER_JSON_get_error_code (j); - break; - case MHD_HTTP_NOT_FOUND: - ks.ec = TALER_JSON_get_error_code (j); - break; - case MHD_HTTP_UNAVAILABLE_FOR_LEGAL_REASONS: - { - uint32_t status; - struct GNUNET_JSON_Specification spec[] = { - GNUNET_JSON_spec_uint32 ("aml_status", - &status), - GNUNET_JSON_spec_end () - }; - - if (GNUNET_OK != - GNUNET_JSON_parse (j, - spec, - NULL, NULL)) - { - GNUNET_break_op (0); - ks.http_status = 0; - ks.ec = TALER_EC_GENERIC_INVALID_RESPONSE; - break; - } - ks.details.unavailable_for_legal_reasons.aml_status - = (enum TALER_AmlDecisionState) status; - kch->cb (kch->cb_cls, - &ks); - GNUNET_JSON_parse_free (spec); - TALER_EXCHANGE_kyc_check_cancel (kch); - return; - } - case MHD_HTTP_INTERNAL_SERVER_ERROR: - ks.ec = TALER_JSON_get_error_code (j); - /* Server had an internal issue; we should retry, but this API - leaves this to the application */ - break; - default: - /* unexpected response code */ - GNUNET_break_op (0); - ks.ec = TALER_JSON_get_error_code (j); - GNUNET_log (GNUNET_ERROR_TYPE_ERROR, - "Unexpected response code %u/%d for exchange kyc_check\n", - (unsigned int) response_code, - (int) ks.ec); - break; - } - kch->cb (kch->cb_cls, - &ks); - TALER_EXCHANGE_kyc_check_cancel (kch); -} - - -struct TALER_EXCHANGE_KycCheckHandle * -TALER_EXCHANGE_kyc_check ( - struct GNUNET_CURL_Context *ctx, - const char *url, - struct TALER_EXCHANGE_Keys *keys, - uint64_t requirement_row, - const struct TALER_PaytoHashP *h_payto, - enum TALER_KYCLOGIC_KycUserType ut, - struct GNUNET_TIME_Relative timeout, - TALER_EXCHANGE_KycStatusCallback cb, - void *cb_cls) -{ - struct TALER_EXCHANGE_KycCheckHandle *kch; - CURL *eh; - char *arg_str; - - { - char payto_str[sizeof (*h_payto) * 2]; - char *end; - unsigned long long timeout_ms; - - end = GNUNET_STRINGS_data_to_string ( - h_payto, - sizeof (*h_payto), - payto_str, - sizeof (payto_str) - 1); - *end = '\0'; - timeout_ms = timeout.rel_value_us - / GNUNET_TIME_UNIT_MILLISECONDS.rel_value_us; - GNUNET_asprintf (&arg_str, - "kyc-check/%llu/%s/%s?timeout_ms=%llu", - (unsigned long long) requirement_row, - payto_str, - TALER_KYCLOGIC_kyc_user_type2s (ut), - timeout_ms); - } - kch = GNUNET_new (struct TALER_EXCHANGE_KycCheckHandle); - kch->h_payto = *h_payto; - kch->cb = cb; - kch->cb_cls = cb_cls; - kch->url = TALER_url_join (url, - arg_str, - NULL); - GNUNET_free (arg_str); - if (NULL == kch->url) - { - GNUNET_free (kch); - return NULL; - } - eh = TALER_EXCHANGE_curl_easy_get_ (kch->url); - if (NULL == eh) - { - GNUNET_break (0); - GNUNET_free (kch->url); - GNUNET_free (kch); - return NULL; - } - kch->keys = TALER_EXCHANGE_keys_incref (keys); - kch->job = GNUNET_CURL_job_add_with_ct_json (ctx, - eh, - &handle_kyc_check_finished, - kch); - return kch; -} - - -void -TALER_EXCHANGE_kyc_check_cancel (struct TALER_EXCHANGE_KycCheckHandle *kch) -{ - if (NULL != kch->job) - { - GNUNET_CURL_job_cancel (kch->job); - kch->job = NULL; - } - TALER_EXCHANGE_keys_decref (kch->keys); - GNUNET_free (kch->url); - GNUNET_free (kch); -} - - -/* end of exchange_api_kyc_check.c */ diff --git a/src/lib/exchange_api_kyc_proof.c b/src/lib/exchange_api_kyc_proof.c deleted file mode 100644 index e7cc9c4cf..000000000 --- a/src/lib/exchange_api_kyc_proof.c +++ /dev/null @@ -1,217 +0,0 @@ -/* - This file is part of TALER - Copyright (C) 2021, 2022 Taler Systems SA - - TALER is free software; you can redistribute it and/or modify it under the - terms of the GNU General Public License as published by the Free Software - Foundation; either version 3, or (at your option) any later version. - - TALER is distributed in the hope that it will be useful, but WITHOUT ANY - WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR - A PARTICULAR PURPOSE. See the GNU General Public License for more details. - - You should have received a copy of the GNU General Public License along with - TALER; see the file COPYING. If not, see - -*/ -/** - * @file lib/exchange_api_kyc_proof.c - * @brief Implementation of the /kyc-proof request - * @author Christian Grothoff - */ -#include "platform.h" -#include /* just for HTTP proof codes */ -#include -#include -#include "taler_exchange_service.h" -#include "taler_json_lib.h" -#include "exchange_api_handle.h" -#include "taler_signatures.h" -#include "exchange_api_curl_defaults.h" - - -/** - * @brief A ``/kyc-proof`` handle - */ -struct TALER_EXCHANGE_KycProofHandle -{ - - /** - * The url for this request. - */ - char *url; - - /** - * Handle to our CURL request. - */ - CURL *eh; - - /** - * Handle for the request. - */ - struct GNUNET_CURL_Job *job; - - /** - * Function to call with the result. - */ - TALER_EXCHANGE_KycProofCallback cb; - - /** - * Closure for @e cb. - */ - void *cb_cls; - -}; - - -/** - * Function called when we're done processing the - * HTTP /kyc-proof request. - * - * @param cls the `struct TALER_EXCHANGE_KycProofHandle` - * @param response_code HTTP response code, 0 on error - * @param body response body - * @param body_size number of bytes in @a body - */ -static void -handle_kyc_proof_finished (void *cls, - long response_code, - const void *body, - size_t body_size) -{ - struct TALER_EXCHANGE_KycProofHandle *kph = cls; - struct TALER_EXCHANGE_KycProofResponse kpr = { - .http_status = (unsigned int) response_code - }; - - (void) body; - (void) body_size; - kph->job = NULL; - switch (response_code) - { - case 0: - break; - case MHD_HTTP_SEE_OTHER: - { - char *redirect_url; - - GNUNET_assert (CURLE_OK == - curl_easy_getinfo (kph->eh, - CURLINFO_REDIRECT_URL, - &redirect_url)); - kpr.details.found.redirect_url = redirect_url; - break; - } - case MHD_HTTP_BAD_REQUEST: - /* This should never happen, either us or the exchange is buggy - (or API version conflict); just pass JSON reply to the application */ - break; - case MHD_HTTP_UNAUTHORIZED: - break; - case MHD_HTTP_FORBIDDEN: - break; - case MHD_HTTP_NOT_FOUND: - break; - case MHD_HTTP_BAD_GATEWAY: - /* Server had an internal issue; we should retry, but this API - leaves this to the application */ - break; - case MHD_HTTP_GATEWAY_TIMEOUT: - /* Server had an internal issue; we should retry, but this API - leaves this to the application */ - break; - default: - /* unexpected response code */ - GNUNET_break_op (0); - GNUNET_log (GNUNET_ERROR_TYPE_ERROR, - "Unexpected response code %u for exchange kyc_proof\n", - (unsigned int) response_code); - break; - } - kph->cb (kph->cb_cls, - &kpr); - TALER_EXCHANGE_kyc_proof_cancel (kph); -} - - -struct TALER_EXCHANGE_KycProofHandle * -TALER_EXCHANGE_kyc_proof ( - struct GNUNET_CURL_Context *ctx, - const char *url, - const struct TALER_PaytoHashP *h_payto, - const char *logic, - const char *args, - TALER_EXCHANGE_KycProofCallback cb, - void *cb_cls) -{ - struct TALER_EXCHANGE_KycProofHandle *kph; - char *arg_str; - - if (NULL == args) - args = ""; - else - GNUNET_assert (args[0] == '&'); - { - char hstr[sizeof (struct TALER_PaytoHashP) * 2]; - char *end; - - end = GNUNET_STRINGS_data_to_string (h_payto, - sizeof (*h_payto), - hstr, - sizeof (hstr)); - *end = '\0'; - GNUNET_asprintf (&arg_str, - "kyc-proof/%s?state=%s%s", - logic, - hstr, - args); - } - kph = GNUNET_new (struct TALER_EXCHANGE_KycProofHandle); - kph->cb = cb; - kph->cb_cls = cb_cls; - kph->url = TALER_url_join (url, - arg_str, - NULL); - GNUNET_free (arg_str); - if (NULL == kph->url) - { - GNUNET_free (kph); - return NULL; - } - kph->eh = TALER_EXCHANGE_curl_easy_get_ (kph->url); - if (NULL == kph->eh) - { - GNUNET_break (0); - GNUNET_free (kph->url); - GNUNET_free (kph); - return NULL; - } - /* disable location following, we want to learn the - result of a 303 redirect! */ - GNUNET_assert (CURLE_OK == - curl_easy_setopt (kph->eh, - CURLOPT_FOLLOWLOCATION, - 0L)); - kph->job = GNUNET_CURL_job_add_raw (ctx, - kph->eh, - NULL, - &handle_kyc_proof_finished, - kph); - return kph; -} - - -void -TALER_EXCHANGE_kyc_proof_cancel (struct TALER_EXCHANGE_KycProofHandle *kph) -{ - if (NULL != kph->job) - { - GNUNET_CURL_job_cancel (kph->job); - kph->job = NULL; - } - GNUNET_free (kph->url); - GNUNET_free (kph); -} - - -/* end of exchange_api_kyc_proof.c */ diff --git a/src/lib/exchange_api_kyc_wallet.c b/src/lib/exchange_api_kyc_wallet.c deleted file mode 100644 index 7197694ae..000000000 --- a/src/lib/exchange_api_kyc_wallet.c +++ /dev/null @@ -1,230 +0,0 @@ -/* - This file is part of TALER - Copyright (C) 2021 Taler Systems SA - - TALER is free software; you can redistribute it and/or modify it under the - terms of the GNU General Public License as published by the Free Software - Foundation; either version 3, or (at your option) any later version. - - TALER is distributed in the hope that it will be useful, but WITHOUT ANY - WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR - A PARTICULAR PURPOSE. See the GNU General Public License for more details. - - You should have received a copy of the GNU General Public License along with - TALER; see the file COPYING. If not, see - -*/ -/** - * @file lib/exchange_api_kyc_wallet.c - * @brief Implementation of the /kyc-wallet request - * @author Christian Grothoff - */ -#include "platform.h" -#include /* just for HTTP wallet codes */ -#include -#include -#include "taler_exchange_service.h" -#include "taler_json_lib.h" -#include "exchange_api_handle.h" -#include "taler_signatures.h" -#include "exchange_api_curl_defaults.h" - - -/** - * @brief A ``/kyc-wallet`` handle - */ -struct TALER_EXCHANGE_KycWalletHandle -{ - - /** - * Context for #TEH_curl_easy_post(). Keeps the data that must - * persist for Curl to make the upload. - */ - struct TALER_CURL_PostContext ctx; - - /** - * The url for this request. - */ - char *url; - - /** - * Handle for the request. - */ - struct GNUNET_CURL_Job *job; - - /** - * Function to call with the result. - */ - TALER_EXCHANGE_KycWalletCallback cb; - - /** - * Closure for @e cb. - */ - void *cb_cls; - -}; - - -/** - * Function called when we're done processing the - * HTTP /kyc-wallet request. - * - * @param cls the `struct TALER_EXCHANGE_KycWalletHandle` - * @param response_code HTTP response code, 0 on error - * @param response parsed JSON result, NULL on error - */ -static void -handle_kyc_wallet_finished (void *cls, - long response_code, - const void *response) -{ - struct TALER_EXCHANGE_KycWalletHandle *kwh = cls; - const json_t *j = response; - struct TALER_EXCHANGE_WalletKycResponse ks = { - .http_status = (unsigned int) response_code - }; - - kwh->job = NULL; - switch (response_code) - { - case 0: - ks.ec = TALER_EC_GENERIC_INVALID_RESPONSE; - break; - case MHD_HTTP_NO_CONTENT: - break; - case MHD_HTTP_BAD_REQUEST: - ks.ec = TALER_JSON_get_error_code (j); - /* This should never happen, either us or the exchange is buggy - (or API version conflict); just pass JSON reply to the application */ - break; - case MHD_HTTP_FORBIDDEN: - ks.ec = TALER_JSON_get_error_code (j); - break; - case MHD_HTTP_NOT_FOUND: - ks.ec = TALER_JSON_get_error_code (j); - break; - case MHD_HTTP_UNAVAILABLE_FOR_LEGAL_REASONS: - { - struct GNUNET_JSON_Specification spec[] = { - GNUNET_JSON_spec_fixed_auto ( - "h_payto", - &ks.details.unavailable_for_legal_reasons.h_payto), - GNUNET_JSON_spec_uint64 ( - "requirement_row", - &ks.details.unavailable_for_legal_reasons.requirement_row), - GNUNET_JSON_spec_end () - }; - - if (GNUNET_OK != - GNUNET_JSON_parse (j, - spec, - NULL, NULL)) - { - GNUNET_break_op (0); - ks.http_status = 0; - ks.ec = TALER_EC_GENERIC_INVALID_RESPONSE; - break; - } - break; - } - case MHD_HTTP_INTERNAL_SERVER_ERROR: - ks.ec = TALER_JSON_get_error_code (j); - /* Server had an internal issue; we should retry, but this API - leaves this to the application */ - break; - default: - /* unexpected response code */ - GNUNET_break_op (0); - ks.ec = TALER_JSON_get_error_code (j); - GNUNET_log (GNUNET_ERROR_TYPE_ERROR, - "Unexpected response code %u/%d for exchange /kyc-wallet\n", - (unsigned int) response_code, - (int) ks.ec); - break; - } - kwh->cb (kwh->cb_cls, - &ks); - TALER_EXCHANGE_kyc_wallet_cancel (kwh); -} - - -struct TALER_EXCHANGE_KycWalletHandle * -TALER_EXCHANGE_kyc_wallet ( - struct GNUNET_CURL_Context *ctx, - const char *url, - const struct TALER_ReservePrivateKeyP *reserve_priv, - const struct TALER_Amount *balance, - TALER_EXCHANGE_KycWalletCallback cb, - void *cb_cls) -{ - struct TALER_EXCHANGE_KycWalletHandle *kwh; - CURL *eh; - json_t *req; - struct TALER_ReservePublicKeyP reserve_pub; - struct TALER_ReserveSignatureP reserve_sig; - - GNUNET_CRYPTO_eddsa_key_get_public (&reserve_priv->eddsa_priv, - &reserve_pub.eddsa_pub); - TALER_wallet_account_setup_sign (reserve_priv, - balance, - &reserve_sig); - req = GNUNET_JSON_PACK ( - TALER_JSON_pack_amount ("balance", - balance), - GNUNET_JSON_pack_data_auto ("reserve_pub", - &reserve_pub), - GNUNET_JSON_pack_data_auto ("reserve_sig", - &reserve_sig)); - GNUNET_assert (NULL != req); - kwh = GNUNET_new (struct TALER_EXCHANGE_KycWalletHandle); - kwh->cb = cb; - kwh->cb_cls = cb_cls; - kwh->url = TALER_url_join (url, - "kyc-wallet", - NULL); - if (NULL == kwh->url) - { - json_decref (req); - GNUNET_free (kwh); - return NULL; - } - eh = TALER_EXCHANGE_curl_easy_get_ (kwh->url); - if ( (NULL == eh) || - (GNUNET_OK != - TALER_curl_easy_post (&kwh->ctx, - eh, - req)) ) - { - GNUNET_break (0); - if (NULL != eh) - curl_easy_cleanup (eh); - json_decref (req); - GNUNET_free (kwh->url); - GNUNET_free (kwh); - return NULL; - } - json_decref (req); - kwh->job = GNUNET_CURL_job_add2 (ctx, - eh, - kwh->ctx.headers, - &handle_kyc_wallet_finished, - kwh); - return kwh; -} - - -void -TALER_EXCHANGE_kyc_wallet_cancel (struct TALER_EXCHANGE_KycWalletHandle *kwh) -{ - if (NULL != kwh->job) - { - GNUNET_CURL_job_cancel (kwh->job); - kwh->job = NULL; - } - GNUNET_free (kwh->url); - TALER_curl_easy_post_finished (&kwh->ctx); - GNUNET_free (kwh); -} - - -/* end of exchange_api_kyc_wallet.c */ diff --git a/src/lib/exchange_api_lookup_aml_decision.c b/src/lib/exchange_api_lookup_aml_decision.c deleted file mode 100644 index 01e98213b..000000000 --- a/src/lib/exchange_api_lookup_aml_decision.c +++ /dev/null @@ -1,419 +0,0 @@ -/* - This file is part of TALER - Copyright (C) 2023 Taler Systems SA - - TALER is free software; you can redistribute it and/or modify it under the - terms of the GNU General Public License as published by the Free Software - Foundation; either version 3, or (at your option) any later version. - - TALER is distributed in the hope that it will be useful, but WITHOUT ANY - WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR - A PARTICULAR PURPOSE. See the GNU General Public License for more details. - - You should have received a copy of the GNU General Public License along with - TALER; see the file COPYING. If not, see - -*/ -/** - * @file lib/exchange_api_lookup_aml_decision.c - * @brief Implementation of the /aml/$OFFICER_PUB/decision request - * @author Christian Grothoff - */ -#include "platform.h" -#include /* just for HTTP status codes */ -#include -#include -#include "taler_exchange_service.h" -#include "taler_json_lib.h" -#include "exchange_api_handle.h" -#include "taler_signatures.h" -#include "exchange_api_curl_defaults.h" - - -/** - * @brief A /coins/$COIN_PUB/link Handle - */ -struct TALER_EXCHANGE_LookupAmlDecision -{ - - /** - * The url for this request. - */ - char *url; - - /** - * Handle for the request. - */ - struct GNUNET_CURL_Job *job; - - /** - * Function to call with the result. - */ - TALER_EXCHANGE_LookupAmlDecisionCallback decision_cb; - - /** - * Closure for @e cb. - */ - void *decision_cb_cls; - - /** - * HTTP headers for the job. - */ - struct curl_slist *job_headers; -}; - - -/** - * Parse AML decision history. - * - * @param aml_history JSON array with AML history - * @param[out] aml_history_ar where to write the result - * @return #GNUNET_OK on success - */ -static enum GNUNET_GenericReturnValue -parse_aml_history (const json_t *aml_history, - struct TALER_EXCHANGE_AmlDecisionDetail *aml_history_ar) -{ - json_t *obj; - size_t idx; - - json_array_foreach (aml_history, idx, obj) - { - struct TALER_EXCHANGE_AmlDecisionDetail *aml = &aml_history_ar[idx]; - uint32_t state32; - struct GNUNET_JSON_Specification spec[] = { - GNUNET_JSON_spec_timestamp ("decision_time", - &aml->decision_time), - GNUNET_JSON_spec_string ("justification", - &aml->justification), - TALER_JSON_spec_amount_any ("new_threshold", - &aml->new_threshold), - GNUNET_JSON_spec_uint32 ("new_state", - &state32), - GNUNET_JSON_spec_fixed_auto ("decider_pub", - &aml->decider_pub), - GNUNET_JSON_spec_end () - }; - - if (GNUNET_OK != - GNUNET_JSON_parse (obj, - spec, - NULL, - NULL)) - { - GNUNET_break_op (0); - return GNUNET_SYSERR; - } - aml->new_state = (enum TALER_AmlDecisionState) state32; - } - return GNUNET_OK; -} - - -/** - * Parse KYC response array. - * - * @param kyc_attributes JSON array with KYC details - * @param[out] kyc_attributes_ar where to write the result - * @return #GNUNET_OK on success - */ -static enum GNUNET_GenericReturnValue -parse_kyc_attributes (const json_t *kyc_attributes, - struct TALER_EXCHANGE_KycHistoryDetail *kyc_attributes_ar) -{ - json_t *obj; - size_t idx; - - json_array_foreach (kyc_attributes, idx, obj) - { - struct TALER_EXCHANGE_KycHistoryDetail *kyc = &kyc_attributes_ar[idx]; - struct GNUNET_JSON_Specification spec[] = { - GNUNET_JSON_spec_timestamp ("collection_time", - &kyc->collection_time), - GNUNET_JSON_spec_mark_optional ( - GNUNET_JSON_spec_object_const ("attributes", - &kyc->attributes), - NULL), - GNUNET_JSON_spec_string ("provider_section", - &kyc->provider_section), - GNUNET_JSON_spec_end () - }; - - if (GNUNET_OK != - GNUNET_JSON_parse (obj, - spec, - NULL, - NULL)) - { - GNUNET_break_op (0); - return GNUNET_SYSERR; - } - } - return GNUNET_OK; -} - - -/** - * Parse the provided decision data from the "200 OK" response. - * - * @param[in,out] lh handle (callback may be zero'ed out) - * @param json json reply with the data for one coin - * @return #GNUNET_OK on success, #GNUNET_SYSERR on error - */ -static enum GNUNET_GenericReturnValue -parse_decision_ok (struct TALER_EXCHANGE_LookupAmlDecision *lh, - const json_t *json) -{ - struct TALER_EXCHANGE_AmlDecisionResponse lr = { - .hr.reply = json, - .hr.http_status = MHD_HTTP_OK - }; - const json_t *aml_history; - const json_t *kyc_attributes; - struct GNUNET_JSON_Specification spec[] = { - GNUNET_JSON_spec_array_const ("aml_history", - &aml_history), - GNUNET_JSON_spec_array_const ("kyc_attributes", - &kyc_attributes), - GNUNET_JSON_spec_end () - }; - - if (GNUNET_OK != - GNUNET_JSON_parse (json, - spec, - NULL, - NULL)) - { - GNUNET_break_op (0); - return GNUNET_SYSERR; - } - lr.details.ok.aml_history_length = json_array_size (aml_history); - lr.details.ok.kyc_attributes_length = json_array_size (kyc_attributes); - { - struct TALER_EXCHANGE_AmlDecisionDetail aml_history_ar[ - GNUNET_NZL (lr.details.ok.aml_history_length)]; - struct TALER_EXCHANGE_KycHistoryDetail kyc_attributes_ar[ - GNUNET_NZL (lr.details.ok.kyc_attributes_length)]; - enum GNUNET_GenericReturnValue ret = GNUNET_SYSERR; - - memset (aml_history_ar, - 0, - sizeof (aml_history_ar)); - memset (kyc_attributes_ar, - 0, - sizeof (kyc_attributes_ar)); - lr.details.ok.aml_history = aml_history_ar; - lr.details.ok.kyc_attributes = kyc_attributes_ar; - ret = parse_aml_history (aml_history, - aml_history_ar); - if (GNUNET_OK == ret) - ret = parse_kyc_attributes (kyc_attributes, - kyc_attributes_ar); - if (GNUNET_OK == ret) - { - lh->decision_cb (lh->decision_cb_cls, - &lr); - lh->decision_cb = NULL; - } - return ret; - } -} - - -/** - * Function called when we're done processing the - * HTTP /aml/$OFFICER_PUB/decision request. - * - * @param cls the `struct TALER_EXCHANGE_LookupAmlDecision` - * @param response_code HTTP response code, 0 on error - * @param response parsed JSON result, NULL on error - */ -static void -handle_lookup_finished (void *cls, - long response_code, - const void *response) -{ - struct TALER_EXCHANGE_LookupAmlDecision *lh = cls; - const json_t *j = response; - struct TALER_EXCHANGE_AmlDecisionResponse lr = { - .hr.reply = j, - .hr.http_status = (unsigned int) response_code - }; - - lh->job = NULL; - switch (response_code) - { - case 0: - lr.hr.ec = TALER_EC_GENERIC_INVALID_RESPONSE; - break; - case MHD_HTTP_OK: - if (GNUNET_OK != - parse_decision_ok (lh, - j)) - { - GNUNET_break_op (0); - lr.hr.http_status = 0; - lr.hr.ec = TALER_EC_GENERIC_REPLY_MALFORMED; - break; - } - GNUNET_assert (NULL == lh->decision_cb); - TALER_EXCHANGE_lookup_aml_decision_cancel (lh); - return; - case MHD_HTTP_NO_CONTENT: - break; - case MHD_HTTP_BAD_REQUEST: - lr.hr.ec = TALER_JSON_get_error_code (j); - lr.hr.hint = TALER_JSON_get_error_hint (j); - /* This should never happen, either us or the exchange is buggy - (or API version conflict); just pass JSON reply to the application */ - break; - case MHD_HTTP_FORBIDDEN: - lr.hr.ec = TALER_JSON_get_error_code (j); - lr.hr.hint = TALER_JSON_get_error_hint (j); - /* Nothing really to verify, exchange says this coin was not melted; we - should pass the JSON reply to the application */ - break; - case MHD_HTTP_NOT_FOUND: - lr.hr.ec = TALER_JSON_get_error_code (j); - lr.hr.hint = TALER_JSON_get_error_hint (j); - /* Nothing really to verify, exchange says this coin was not melted; we - should pass the JSON reply to the application */ - break; - case MHD_HTTP_INTERNAL_SERVER_ERROR: - lr.hr.ec = TALER_JSON_get_error_code (j); - lr.hr.hint = TALER_JSON_get_error_hint (j); - /* Server had an internal issue; we should retry, but this API - leaves this to the application */ - break; - default: - /* unexpected response code */ - GNUNET_break_op (0); - lr.hr.ec = TALER_JSON_get_error_code (j); - lr.hr.hint = TALER_JSON_get_error_hint (j); - GNUNET_log (GNUNET_ERROR_TYPE_ERROR, - "Unexpected response code %u/%d for exchange lookup AML decision\n", - (unsigned int) response_code, - (int) lr.hr.ec); - break; - } - if (NULL != lh->decision_cb) - lh->decision_cb (lh->decision_cb_cls, - &lr); - TALER_EXCHANGE_lookup_aml_decision_cancel (lh); -} - - -struct TALER_EXCHANGE_LookupAmlDecision * -TALER_EXCHANGE_lookup_aml_decision ( - struct GNUNET_CURL_Context *ctx, - const char *exchange_url, - const struct TALER_PaytoHashP *h_payto, - const struct TALER_AmlOfficerPrivateKeyP *officer_priv, - bool history, - TALER_EXCHANGE_LookupAmlDecisionCallback cb, - void *cb_cls) -{ - struct TALER_EXCHANGE_LookupAmlDecision *lh; - CURL *eh; - struct TALER_AmlOfficerPublicKeyP officer_pub; - struct TALER_AmlOfficerSignatureP officer_sig; - char arg_str[sizeof (officer_pub) * 2 - + sizeof (*h_payto) * 2 + 32]; - - GNUNET_CRYPTO_eddsa_key_get_public (&officer_priv->eddsa_priv, - &officer_pub.eddsa_pub); - TALER_officer_aml_query_sign (officer_priv, - &officer_sig); - { - char pub_str[sizeof (officer_pub) * 2]; - char pt_str[sizeof (*h_payto) * 2]; - char *end; - - end = GNUNET_STRINGS_data_to_string ( - &officer_pub, - sizeof (officer_pub), - pub_str, - sizeof (pub_str)); - *end = '\0'; - end = GNUNET_STRINGS_data_to_string ( - h_payto, - sizeof (*h_payto), - pt_str, - sizeof (pt_str)); - *end = '\0'; - GNUNET_snprintf (arg_str, - sizeof (arg_str), - "aml/%s/decision/%s", - pub_str, - pt_str); - } - lh = GNUNET_new (struct TALER_EXCHANGE_LookupAmlDecision); - lh->decision_cb = cb; - lh->decision_cb_cls = cb_cls; - lh->url = TALER_url_join (exchange_url, - arg_str, - "history", - history - ? "true" - : NULL, - NULL); - if (NULL == lh->url) - { - GNUNET_free (lh); - return NULL; - } - eh = TALER_EXCHANGE_curl_easy_get_ (lh->url); - if (NULL == eh) - { - GNUNET_break (0); - GNUNET_free (lh->url); - GNUNET_free (lh); - return NULL; - } - { - char *hdr; - char sig_str[sizeof (officer_sig) * 2]; - char *end; - - end = GNUNET_STRINGS_data_to_string ( - &officer_sig, - sizeof (officer_sig), - sig_str, - sizeof (sig_str)); - *end = '\0'; - - GNUNET_asprintf (&hdr, - "%s: %s", - TALER_AML_OFFICER_SIGNATURE_HEADER, - sig_str); - lh->job_headers = curl_slist_append (NULL, - hdr); - GNUNET_free (hdr); - lh->job_headers = curl_slist_append (lh->job_headers, - "Content-type: application/json"); - lh->job = GNUNET_CURL_job_add2 (ctx, - eh, - lh->job_headers, - &handle_lookup_finished, - lh); - } - return lh; -} - - -void -TALER_EXCHANGE_lookup_aml_decision_cancel ( - struct TALER_EXCHANGE_LookupAmlDecision *lh) -{ - if (NULL != lh->job) - { - GNUNET_CURL_job_cancel (lh->job); - lh->job = NULL; - } - curl_slist_free_all (lh->job_headers); - GNUNET_free (lh->url); - GNUNET_free (lh); -} - - -/* end of exchange_api_lookup_aml_decision.c */ diff --git a/src/lib/exchange_api_lookup_aml_decisions.c b/src/lib/exchange_api_lookup_aml_decisions.c deleted file mode 100644 index 22222b1e4..000000000 --- a/src/lib/exchange_api_lookup_aml_decisions.c +++ /dev/null @@ -1,378 +0,0 @@ -/* - This file is part of TALER - Copyright (C) 2023 Taler Systems SA - - TALER is free software; you can redistribute it and/or modify it under the - terms of the GNU General Public License as published by the Free Software - Foundation; either version 3, or (at your option) any later version. - - TALER is distributed in the hope that it will be useful, but WITHOUT ANY - WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR - A PARTICULAR PURPOSE. See the GNU General Public License for more details. - - You should have received a copy of the GNU General Public License along with - TALER; see the file COPYING. If not, see - -*/ -/** - * @file lib/exchange_api_lookup_aml_decisions.c - * @brief Implementation of the /aml/$OFFICER_PUB/decisions request - * @author Christian Grothoff - */ -#include "platform.h" -#include /* just for HTTP status codes */ -#include -#include -#include "taler_exchange_service.h" -#include "taler_json_lib.h" -#include "exchange_api_handle.h" -#include "taler_signatures.h" -#include "exchange_api_curl_defaults.h" - - -/** - * @brief A /coins/$COIN_PUB/link Handle - */ -struct TALER_EXCHANGE_LookupAmlDecisions -{ - - /** - * The url for this request. - */ - char *url; - - /** - * Handle for the request. - */ - struct GNUNET_CURL_Job *job; - - /** - * Function to call with the result. - */ - TALER_EXCHANGE_LookupAmlDecisionsCallback decisions_cb; - - /** - * Closure for @e cb. - */ - void *decisions_cb_cls; - - /** - * HTTP headers for the job. - */ - struct curl_slist *job_headers; -}; - - -/** - * Parse AML decision summary array. - * - * @param decisions JSON array with AML decision summaries - * @param[out] decision_ar where to write the result - * @return #GNUNET_OK on success - */ -static enum GNUNET_GenericReturnValue -parse_aml_decisions (const json_t *decisions, - struct TALER_EXCHANGE_AmlDecisionSummary *decision_ar) -{ - json_t *obj; - size_t idx; - - json_array_foreach (decisions, idx, obj) - { - struct TALER_EXCHANGE_AmlDecisionSummary *decision = &decision_ar[idx]; - uint32_t state32; - struct GNUNET_JSON_Specification spec[] = { - GNUNET_JSON_spec_fixed_auto ("h_payto", - &decision->h_payto), - GNUNET_JSON_spec_uint32 ("current_state", - &state32), - TALER_JSON_spec_amount_any ("threshold", - &decision->threshold), - GNUNET_JSON_spec_uint64 ("rowid", - &decision->rowid), - GNUNET_JSON_spec_end () - }; - - if (GNUNET_OK != - GNUNET_JSON_parse (obj, - spec, - NULL, - NULL)) - { - GNUNET_break_op (0); - return GNUNET_SYSERR; - } - decision->current_state = (enum TALER_AmlDecisionState) state32; - } - return GNUNET_OK; -} - - -/** - * Parse the provided decision data from the "200 OK" response. - * - * @param[in,out] lh handle (callback may be zero'ed out) - * @param json json reply with the data for one coin - * @return #GNUNET_OK on success, #GNUNET_SYSERR on error - */ -static enum GNUNET_GenericReturnValue -parse_decisions_ok (struct TALER_EXCHANGE_LookupAmlDecisions *lh, - const json_t *json) -{ - struct TALER_EXCHANGE_AmlDecisionsResponse lr = { - .hr.reply = json, - .hr.http_status = MHD_HTTP_OK - }; - const json_t *records; - struct GNUNET_JSON_Specification spec[] = { - GNUNET_JSON_spec_array_const ("records", - &records), - GNUNET_JSON_spec_end () - }; - - if (GNUNET_OK != - GNUNET_JSON_parse (json, - spec, - NULL, - NULL)) - { - GNUNET_break_op (0); - return GNUNET_SYSERR; - } - lr.details.ok.decisions_length = json_array_size (records); - { - struct TALER_EXCHANGE_AmlDecisionSummary decisions[ - GNUNET_NZL (lr.details.ok.decisions_length)]; - enum GNUNET_GenericReturnValue ret = GNUNET_SYSERR; - - lr.details.ok.decisions = decisions; - ret = parse_aml_decisions (records, - decisions); - if (GNUNET_OK == ret) - { - lh->decisions_cb (lh->decisions_cb_cls, - &lr); - lh->decisions_cb = NULL; - } - return ret; - } -} - - -/** - * Function called when we're done processing the - * HTTP /aml/$OFFICER_PUB/decisions request. - * - * @param cls the `struct TALER_EXCHANGE_LookupAmlDecisions` - * @param response_code HTTP response code, 0 on error - * @param response parsed JSON result, NULL on error - */ -static void -handle_lookup_finished (void *cls, - long response_code, - const void *response) -{ - struct TALER_EXCHANGE_LookupAmlDecisions *lh = cls; - const json_t *j = response; - struct TALER_EXCHANGE_AmlDecisionsResponse lr = { - .hr.reply = j, - .hr.http_status = (unsigned int) response_code - }; - - lh->job = NULL; - switch (response_code) - { - case 0: - lr.hr.ec = TALER_EC_GENERIC_INVALID_RESPONSE; - break; - case MHD_HTTP_OK: - if (GNUNET_OK != - parse_decisions_ok (lh, - j)) - { - GNUNET_break_op (0); - lr.hr.http_status = 0; - lr.hr.ec = TALER_EC_GENERIC_REPLY_MALFORMED; - break; - } - GNUNET_assert (NULL == lh->decisions_cb); - TALER_EXCHANGE_lookup_aml_decisions_cancel (lh); - return; - case MHD_HTTP_NO_CONTENT: - break; - case MHD_HTTP_BAD_REQUEST: - lr.hr.ec = TALER_JSON_get_error_code (j); - lr.hr.hint = TALER_JSON_get_error_hint (j); - /* This should never happen, either us or the exchange is buggy - (or API version conflict); just pass JSON reply to the application */ - break; - case MHD_HTTP_FORBIDDEN: - lr.hr.ec = TALER_JSON_get_error_code (j); - lr.hr.hint = TALER_JSON_get_error_hint (j); - /* Nothing really to verify, exchange says this coin was not melted; we - should pass the JSON reply to the application */ - break; - case MHD_HTTP_NOT_FOUND: - lr.hr.ec = TALER_JSON_get_error_code (j); - lr.hr.hint = TALER_JSON_get_error_hint (j); - /* Nothing really to verify, exchange says this coin was not melted; we - should pass the JSON reply to the application */ - break; - case MHD_HTTP_INTERNAL_SERVER_ERROR: - lr.hr.ec = TALER_JSON_get_error_code (j); - lr.hr.hint = TALER_JSON_get_error_hint (j); - /* Server had an internal issue; we should retry, but this API - leaves this to the application */ - break; - default: - /* unexpected response code */ - GNUNET_break_op (0); - lr.hr.ec = TALER_JSON_get_error_code (j); - lr.hr.hint = TALER_JSON_get_error_hint (j); - GNUNET_log (GNUNET_ERROR_TYPE_ERROR, - "Unexpected response code %u/%d for lookup AML decisions\n", - (unsigned int) response_code, - (int) lr.hr.ec); - break; - } - if (NULL != lh->decisions_cb) - lh->decisions_cb (lh->decisions_cb_cls, - &lr); - TALER_EXCHANGE_lookup_aml_decisions_cancel (lh); -} - - -struct TALER_EXCHANGE_LookupAmlDecisions * -TALER_EXCHANGE_lookup_aml_decisions ( - struct GNUNET_CURL_Context *ctx, - const char *exchange_url, - uint64_t start, - int delta, - enum TALER_AmlDecisionState state, - const struct TALER_AmlOfficerPrivateKeyP *officer_priv, - TALER_EXCHANGE_LookupAmlDecisionsCallback cb, - void *cb_cls) -{ - struct TALER_EXCHANGE_LookupAmlDecisions *lh; - CURL *eh; - struct TALER_AmlOfficerPublicKeyP officer_pub; - struct TALER_AmlOfficerSignatureP officer_sig; - char arg_str[sizeof (struct TALER_AmlOfficerPublicKeyP) * 2 + 32]; - const char *state_str = NULL; - - switch (state) - { - case TALER_AML_NORMAL: - state_str = "normal"; - break; - case TALER_AML_PENDING: - state_str = "pending"; - break; - case TALER_AML_FROZEN: - state_str = "frozen"; - break; - } - GNUNET_assert (NULL != state_str); - GNUNET_CRYPTO_eddsa_key_get_public (&officer_priv->eddsa_priv, - &officer_pub.eddsa_pub); - TALER_officer_aml_query_sign (officer_priv, - &officer_sig); - { - char pub_str[sizeof (officer_pub) * 2]; - char *end; - - end = GNUNET_STRINGS_data_to_string ( - &officer_pub, - sizeof (officer_pub), - pub_str, - sizeof (pub_str)); - *end = '\0'; - GNUNET_snprintf (arg_str, - sizeof (arg_str), - "aml/%s/decisions/%s", - pub_str, - state_str); - } - lh = GNUNET_new (struct TALER_EXCHANGE_LookupAmlDecisions); - lh->decisions_cb = cb; - lh->decisions_cb_cls = cb_cls; - { - char delta_s[24]; - char start_s[24]; - - GNUNET_snprintf (delta_s, - sizeof (delta_s), - "%d", - delta); - GNUNET_snprintf (start_s, - sizeof (start_s), - "%llu", - (unsigned long long) start); - lh->url = TALER_url_join (exchange_url, - arg_str, - "delta", - delta_s, - "start", - start_s, - NULL); - } - if (NULL == lh->url) - { - GNUNET_free (lh); - return NULL; - } - eh = TALER_EXCHANGE_curl_easy_get_ (lh->url); - if (NULL == eh) - { - GNUNET_break (0); - GNUNET_free (lh->url); - GNUNET_free (lh); - return NULL; - } - { - char *hdr; - char sig_str[sizeof (officer_sig) * 2]; - char *end; - - end = GNUNET_STRINGS_data_to_string ( - &officer_sig, - sizeof (officer_sig), - sig_str, - sizeof (sig_str)); - *end = '\0'; - - GNUNET_asprintf (&hdr, - "%s: %s", - TALER_AML_OFFICER_SIGNATURE_HEADER, - sig_str); - lh->job_headers = curl_slist_append (NULL, - hdr); - GNUNET_free (hdr); - lh->job_headers = curl_slist_append (lh->job_headers, - "Content-type: application/json"); - lh->job = GNUNET_CURL_job_add2 (ctx, - eh, - lh->job_headers, - &handle_lookup_finished, - lh); - } - return lh; -} - - -void -TALER_EXCHANGE_lookup_aml_decisions_cancel ( - struct TALER_EXCHANGE_LookupAmlDecisions *lh) -{ - if (NULL != lh->job) - { - GNUNET_CURL_job_cancel (lh->job); - lh->job = NULL; - } - curl_slist_free_all (lh->job_headers); - GNUNET_free (lh->url); - GNUNET_free (lh); -} - - -/* end of exchange_api_lookup_aml_decisions.c */ diff --git a/src/lib/exchange_api_management_add_partner.c b/src/lib/exchange_api_management_add_partner.c deleted file mode 100644 index fec66c567..000000000 --- a/src/lib/exchange_api_management_add_partner.c +++ /dev/null @@ -1,218 +0,0 @@ -/* - This file is part of TALER - Copyright (C) 2023 Taler Systems SA - - TALER is free software; you can redistribute it and/or modify it under the - terms of the GNU General Public License as published by the Free Software - Foundation; either version 3, or (at your option) any later version. - - TALER is distributed in the hope that it will be useful, but WITHOUT ANY - WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR - A PARTICULAR PURPOSE. See the GNU General Public License for more details. - - You should have received a copy of the GNU General Public License along with - TALER; see the file COPYING. If not, see - -*/ -/** - * @file lib/exchange_api_management_add_partner.c - * @brief functions to add an partner by an AML officer - * @author Christian Grothoff - */ -#include "platform.h" -#include "taler_json_lib.h" -#include -#include "taler_exchange_service.h" -#include "exchange_api_curl_defaults.h" -#include "taler_signatures.h" -#include "taler_curl_lib.h" -#include "taler_json_lib.h" - - -struct TALER_EXCHANGE_ManagementAddPartner -{ - - /** - * The url for this request. - */ - char *url; - - /** - * Minor context that holds body and headers. - */ - struct TALER_CURL_PostContext post_ctx; - - /** - * Handle for the request. - */ - struct GNUNET_CURL_Job *job; - - /** - * Function to call with the result. - */ - TALER_EXCHANGE_ManagementAddPartnerCallback cb; - - /** - * Closure for @a cb. - */ - void *cb_cls; - - /** - * Reference to the execution context. - */ - struct GNUNET_CURL_Context *ctx; -}; - - -/** - * Function called when we're done processing the - * HTTP POST /management/partners request. - * - * @param cls the `struct TALER_EXCHANGE_ManagementAddPartner *` - * @param response_code HTTP response code, 0 on error - * @param response response body, NULL if not in JSON - */ -static void -handle_add_partner_finished (void *cls, - long response_code, - const void *response) -{ - struct TALER_EXCHANGE_ManagementAddPartner *wh = cls; - const json_t *json = response; - struct TALER_EXCHANGE_ManagementAddPartnerResponse apr = { - .hr.http_status = (unsigned int) response_code, - .hr.reply = json - }; - - wh->job = NULL; - switch (response_code) - { - case 0: - /* no reply */ - apr.hr.ec = TALER_EC_GENERIC_INVALID_RESPONSE; - apr.hr.hint = "server offline?"; - break; - case MHD_HTTP_NO_CONTENT: - break; - case MHD_HTTP_FORBIDDEN: - apr.hr.ec = TALER_JSON_get_error_code (json); - apr.hr.hint = TALER_JSON_get_error_hint (json); - break; - case MHD_HTTP_CONFLICT: - apr.hr.ec = TALER_JSON_get_error_code (json); - apr.hr.hint = TALER_JSON_get_error_hint (json); - break; - default: - /* unexpected response code */ - GNUNET_break_op (0); - apr.hr.ec = TALER_JSON_get_error_code (json); - apr.hr.hint = TALER_JSON_get_error_hint (json); - GNUNET_log (GNUNET_ERROR_TYPE_ERROR, - "Unexpected response code %u/%d for adding exchange partner\n", - (unsigned int) response_code, - (int) apr.hr.ec); - break; - } - if (NULL != wh->cb) - { - wh->cb (wh->cb_cls, - &apr); - wh->cb = NULL; - } - TALER_EXCHANGE_management_add_partner_cancel (wh); -} - - -struct TALER_EXCHANGE_ManagementAddPartner * -TALER_EXCHANGE_management_add_partner ( - struct GNUNET_CURL_Context *ctx, - const char *url, - const struct TALER_MasterPublicKeyP *partner_pub, - struct GNUNET_TIME_Timestamp start_date, - struct GNUNET_TIME_Timestamp end_date, - struct GNUNET_TIME_Relative wad_frequency, - const struct TALER_Amount *wad_fee, - const char *partner_base_url, - const struct TALER_MasterSignatureP *master_sig, - TALER_EXCHANGE_ManagementAddPartnerCallback cb, - void *cb_cls) -{ - struct TALER_EXCHANGE_ManagementAddPartner *wh; - CURL *eh; - json_t *body; - - wh = GNUNET_new (struct TALER_EXCHANGE_ManagementAddPartner); - wh->cb = cb; - wh->cb_cls = cb_cls; - wh->ctx = ctx; - wh->url = TALER_url_join (url, - "management/partners", - NULL); - if (NULL == wh->url) - { - GNUNET_log (GNUNET_ERROR_TYPE_ERROR, - "Could not construct request URL.\n"); - GNUNET_free (wh); - return NULL; - } - body = GNUNET_JSON_PACK ( - GNUNET_JSON_pack_string ("partner_base_url", - partner_base_url), - GNUNET_JSON_pack_timestamp ("start_date", - start_date), - GNUNET_JSON_pack_timestamp ("end_date", - end_date), - GNUNET_JSON_pack_time_rel ("wad_frequency", - wad_frequency), - GNUNET_JSON_pack_data_auto ("partner_pub", - &partner_pub), - GNUNET_JSON_pack_data_auto ("master_sig", - &master_sig), - TALER_JSON_pack_amount ("wad_fee", - wad_fee) - ); - eh = TALER_EXCHANGE_curl_easy_get_ (wh->url); - if ( (NULL == eh) || - (GNUNET_OK != - TALER_curl_easy_post (&wh->post_ctx, - eh, - body)) ) - { - GNUNET_break (0); - if (NULL != eh) - curl_easy_cleanup (eh); - json_decref (body); - GNUNET_free (wh->url); - return NULL; - } - json_decref (body); - GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, - "Requesting URL '%s'\n", - wh->url); - wh->job = GNUNET_CURL_job_add2 (ctx, - eh, - wh->post_ctx.headers, - &handle_add_partner_finished, - wh); - if (NULL == wh->job) - { - TALER_EXCHANGE_management_add_partner_cancel (wh); - return NULL; - } - return wh; -} - - -void -TALER_EXCHANGE_management_add_partner_cancel ( - struct TALER_EXCHANGE_ManagementAddPartner *wh) -{ - if (NULL != wh->job) - { - GNUNET_CURL_job_cancel (wh->job); - wh->job = NULL; - } - TALER_curl_easy_post_finished (&wh->post_ctx); - GNUNET_free (wh->url); - GNUNET_free (wh); -} diff --git a/src/lib/exchange_api_management_auditor_disable.c b/src/lib/exchange_api_management_auditor_disable.c deleted file mode 100644 index 8bce7f74f..000000000 --- a/src/lib/exchange_api_management_auditor_disable.c +++ /dev/null @@ -1,219 +0,0 @@ -/* - This file is part of TALER - Copyright (C) 2015-2021 Taler Systems SA - - TALER is free software; you can redistribute it and/or modify it under the - terms of the GNU General Public License as published by the Free Software - Foundation; either version 3, or (at your option) any later version. - - TALER is distributed in the hope that it will be useful, but WITHOUT ANY - WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR - A PARTICULAR PURPOSE. See the GNU General Public License for more details. - - You should have received a copy of the GNU General Public License along with - TALER; see the file COPYING. If not, see - -*/ -/** - * @file lib/exchange_api_management_auditor_disable.c - * @brief functions to disable an auditor - * @author Christian Grothoff - */ -#include "platform.h" -#include "taler_json_lib.h" -#include -#include "taler_exchange_service.h" -#include "exchange_api_curl_defaults.h" -#include "taler_signatures.h" -#include "taler_curl_lib.h" -#include "taler_json_lib.h" - -/** - * @brief Handle for a POST /management/auditors/$AUDITOR_PUB/disable request. - */ -struct TALER_EXCHANGE_ManagementAuditorDisableHandle -{ - - /** - * The url for this request. - */ - char *url; - - /** - * Minor context that holds body and headers. - */ - struct TALER_CURL_PostContext post_ctx; - - /** - * Handle for the request. - */ - struct GNUNET_CURL_Job *job; - - /** - * Function to call with the result. - */ - TALER_EXCHANGE_ManagementAuditorDisableCallback cb; - - /** - * Closure for @a cb. - */ - void *cb_cls; - - /** - * Reference to the execution context. - */ - struct GNUNET_CURL_Context *ctx; -}; - - -/** - * Function called when we're done processing the - * HTTP /management/auditors/%s/disable request. - * - * @param cls the `struct TALER_EXCHANGE_ManagementAuditorDisableHandle *` - * @param response_code HTTP response code, 0 on error - * @param response response body, NULL if not in JSON - */ -static void -handle_auditor_disable_finished (void *cls, - long response_code, - const void *response) -{ - struct TALER_EXCHANGE_ManagementAuditorDisableHandle *ah = cls; - const json_t *json = response; - struct TALER_EXCHANGE_ManagementAuditorDisableResponse adr = { - .hr.http_status = (unsigned int) response_code, - .hr.reply = json - }; - - ah->job = NULL; - switch (response_code) - { - case MHD_HTTP_NO_CONTENT: - break; - case MHD_HTTP_FORBIDDEN: - adr.hr.ec = TALER_JSON_get_error_code (json); - adr.hr.hint = TALER_JSON_get_error_hint (json); - break; - case MHD_HTTP_NOT_FOUND: - adr.hr.ec = TALER_JSON_get_error_code (json); - adr.hr.hint = TALER_JSON_get_error_hint (json); - break; - case MHD_HTTP_CONFLICT: - adr.hr.ec = TALER_JSON_get_error_code (json); - adr.hr.hint = TALER_JSON_get_error_hint (json); - break; - default: - /* unexpected response code */ - GNUNET_break_op (0); - adr.hr.ec = TALER_JSON_get_error_code (json); - adr.hr.hint = TALER_JSON_get_error_hint (json); - GNUNET_log (GNUNET_ERROR_TYPE_ERROR, - "Unexpected response code %u/%d for exchange management auditor disable\n", - (unsigned int) response_code, - (int) adr.hr.ec); - break; - } - if (NULL != ah->cb) - { - ah->cb (ah->cb_cls, - &adr); - ah->cb = NULL; - } - TALER_EXCHANGE_management_disable_auditor_cancel (ah); -} - - -struct TALER_EXCHANGE_ManagementAuditorDisableHandle * -TALER_EXCHANGE_management_disable_auditor ( - struct GNUNET_CURL_Context *ctx, - const char *url, - const struct TALER_AuditorPublicKeyP *auditor_pub, - struct GNUNET_TIME_Timestamp validity_end, - const struct TALER_MasterSignatureP *master_sig, - TALER_EXCHANGE_ManagementAuditorDisableCallback cb, - void *cb_cls) -{ - struct TALER_EXCHANGE_ManagementAuditorDisableHandle *ah; - CURL *eh; - json_t *body; - - ah = GNUNET_new (struct TALER_EXCHANGE_ManagementAuditorDisableHandle); - ah->cb = cb; - ah->cb_cls = cb_cls; - ah->ctx = ctx; - { - char epub_str[sizeof (*auditor_pub) * 2]; - char arg_str[sizeof (epub_str) + 64]; - char *end; - - end = GNUNET_STRINGS_data_to_string (auditor_pub, - sizeof (*auditor_pub), - epub_str, - sizeof (epub_str)); - *end = '\0'; - GNUNET_snprintf (arg_str, - sizeof (arg_str), - "management/auditors/%s/disable", - epub_str); - ah->url = TALER_url_join (url, - arg_str, - NULL); - } - if (NULL == ah->url) - { - GNUNET_log (GNUNET_ERROR_TYPE_ERROR, - "Could not construct request URL.\n"); - GNUNET_free (ah); - return NULL; - } - body = GNUNET_JSON_PACK ( - GNUNET_JSON_pack_data_auto ("master_sig", - master_sig), - GNUNET_JSON_pack_timestamp ("validity_end", - validity_end)); - eh = TALER_EXCHANGE_curl_easy_get_ (ah->url); - if ( (NULL == eh) || - (GNUNET_OK != - TALER_curl_easy_post (&ah->post_ctx, - eh, - body))) - { - GNUNET_break (0); - if (NULL != eh) - curl_easy_cleanup (eh); - json_decref (body); - GNUNET_free (ah->url); - return NULL; - } - json_decref (body); - GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, - "Requesting URL '%s'\n", - ah->url); - ah->job = GNUNET_CURL_job_add2 (ctx, - eh, - ah->post_ctx.headers, - &handle_auditor_disable_finished, - ah); - if (NULL == ah->job) - { - TALER_EXCHANGE_management_disable_auditor_cancel (ah); - return NULL; - } - return ah; -} - - -void -TALER_EXCHANGE_management_disable_auditor_cancel ( - struct TALER_EXCHANGE_ManagementAuditorDisableHandle *ah) -{ - if (NULL != ah->job) - { - GNUNET_CURL_job_cancel (ah->job); - ah->job = NULL; - } - TALER_curl_easy_post_finished (&ah->post_ctx); - GNUNET_free (ah->url); - GNUNET_free (ah); -} diff --git a/src/lib/exchange_api_management_auditor_enable.c b/src/lib/exchange_api_management_auditor_enable.c deleted file mode 100644 index 41c5049c2..000000000 --- a/src/lib/exchange_api_management_auditor_enable.c +++ /dev/null @@ -1,224 +0,0 @@ -/* - This file is part of TALER - Copyright (C) 2015-2021 Taler Systems SA - - TALER is free software; you can redistribute it and/or modify it under the - terms of the GNU General Public License as published by the Free Software - Foundation; either version 3, or (at your option) any later version. - - TALER is distributed in the hope that it will be useful, but WITHOUT ANY - WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR - A PARTICULAR PURPOSE. See the GNU General Public License for more details. - - You should have received a copy of the GNU General Public License along with - TALER; see the file COPYING. If not, see - -*/ -/** - * @file lib/exchange_api_management_auditor_enable.c - * @brief functions to enable an auditor - * @author Christian Grothoff - */ -#include "platform.h" -#include "taler_json_lib.h" -#include -#include "taler_exchange_service.h" -#include "exchange_api_curl_defaults.h" -#include "taler_signatures.h" -#include "taler_curl_lib.h" -#include "taler_json_lib.h" - - -/** - * @brief Handle for a POST /management/auditors request. - */ -struct TALER_EXCHANGE_ManagementAuditorEnableHandle -{ - - /** - * The url for this request. - */ - char *url; - - /** - * Minor context that holds body and headers. - */ - struct TALER_CURL_PostContext post_ctx; - - /** - * Handle for the request. - */ - struct GNUNET_CURL_Job *job; - - /** - * Function to call with the result. - */ - TALER_EXCHANGE_ManagementAuditorEnableCallback cb; - - /** - * Closure for @a cb. - */ - void *cb_cls; - - /** - * Reference to the execution context. - */ - struct GNUNET_CURL_Context *ctx; -}; - - -/** - * Function called when we're done processing the - * HTTP POST /management/auditors request. - * - * @param cls the `struct TALER_EXCHANGE_ManagementAuditorEnableHandle *` - * @param response_code HTTP response code, 0 on error - * @param response response body, NULL if not in JSON - */ -static void -handle_auditor_enable_finished (void *cls, - long response_code, - const void *response) -{ - struct TALER_EXCHANGE_ManagementAuditorEnableHandle *ah = cls; - const json_t *json = response; - struct TALER_EXCHANGE_ManagementAuditorEnableResponse aer = { - .hr.http_status = (unsigned int) response_code, - .hr.reply = json - }; - - ah->job = NULL; - switch (response_code) - { - case MHD_HTTP_NO_CONTENT: - break; - case MHD_HTTP_FORBIDDEN: - aer.hr.ec = TALER_JSON_get_error_code (json); - aer.hr.hint = TALER_JSON_get_error_hint (json); - break; - case MHD_HTTP_NOT_FOUND: - GNUNET_log (GNUNET_ERROR_TYPE_ERROR, - "Server did not find handler at `%s'. Did you configure the correct exchange base URL?\n", - ah->url); - if (NULL != json) - { - aer.hr.ec = TALER_JSON_get_error_code (json); - aer.hr.hint = TALER_JSON_get_error_hint (json); - } - else - { - aer.hr.ec = TALER_EC_GENERIC_INVALID_RESPONSE; - aer.hr.hint = TALER_ErrorCode_get_hint (aer.hr.ec); - } - break; - case MHD_HTTP_CONFLICT: - aer.hr.ec = TALER_JSON_get_error_code (json); - aer.hr.hint = TALER_JSON_get_error_hint (json); - break; - default: - /* unexpected response code */ - GNUNET_break_op (0); - aer.hr.ec = TALER_JSON_get_error_code (json); - aer.hr.hint = TALER_JSON_get_error_hint (json); - GNUNET_log (GNUNET_ERROR_TYPE_ERROR, - "Unexpected response code %u/%d for exchange management auditor enable\n", - (unsigned int) response_code, - (int) aer.hr.ec); - break; - } - if (NULL != ah->cb) - { - ah->cb (ah->cb_cls, - &aer); - ah->cb = NULL; - } - TALER_EXCHANGE_management_enable_auditor_cancel (ah); -} - - -struct TALER_EXCHANGE_ManagementAuditorEnableHandle * -TALER_EXCHANGE_management_enable_auditor ( - struct GNUNET_CURL_Context *ctx, - const char *url, - const struct TALER_AuditorPublicKeyP *auditor_pub, - const char *auditor_url, - const char *auditor_name, - struct GNUNET_TIME_Timestamp validity_start, - const struct TALER_MasterSignatureP *master_sig, - TALER_EXCHANGE_ManagementAuditorEnableCallback cb, - void *cb_cls) -{ - struct TALER_EXCHANGE_ManagementAuditorEnableHandle *ah; - CURL *eh; - json_t *body; - - ah = GNUNET_new (struct TALER_EXCHANGE_ManagementAuditorEnableHandle); - ah->cb = cb; - ah->cb_cls = cb_cls; - ah->ctx = ctx; - ah->url = TALER_url_join (url, - "management/auditors", - NULL); - if (NULL == ah->url) - { - GNUNET_log (GNUNET_ERROR_TYPE_ERROR, - "Could not construct request URL.\n"); - GNUNET_free (ah); - return NULL; - } - body = GNUNET_JSON_PACK ( - GNUNET_JSON_pack_string ("auditor_url", - auditor_url), - GNUNET_JSON_pack_string ("auditor_name", - auditor_name), - GNUNET_JSON_pack_data_auto ("auditor_pub", - auditor_pub), - GNUNET_JSON_pack_data_auto ("master_sig", - master_sig), - GNUNET_JSON_pack_timestamp ("validity_start", - validity_start)); - eh = TALER_EXCHANGE_curl_easy_get_ (ah->url); - if ( (NULL == eh) || - (GNUNET_OK != - TALER_curl_easy_post (&ah->post_ctx, - eh, - body)) ) - { - GNUNET_break (0); - json_decref (body); - if (NULL != eh) - curl_easy_cleanup (eh); - GNUNET_free (ah->url); - return NULL; - } - json_decref (body); - GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, - "Requesting URL '%s'\n", - ah->url); - ah->job = GNUNET_CURL_job_add2 (ctx, - eh, - ah->post_ctx.headers, - &handle_auditor_enable_finished, - ah); - if (NULL == ah->job) - { - TALER_EXCHANGE_management_enable_auditor_cancel (ah); - return NULL; - } - return ah; -} - - -void -TALER_EXCHANGE_management_enable_auditor_cancel ( - struct TALER_EXCHANGE_ManagementAuditorEnableHandle *ah) -{ - if (NULL != ah->job) - { - GNUNET_CURL_job_cancel (ah->job); - ah->job = NULL; - } - TALER_curl_easy_post_finished (&ah->post_ctx); - GNUNET_free (ah->url); - GNUNET_free (ah); -} diff --git a/src/lib/exchange_api_management_drain_profits.c b/src/lib/exchange_api_management_drain_profits.c deleted file mode 100644 index bc7232b87..000000000 --- a/src/lib/exchange_api_management_drain_profits.c +++ /dev/null @@ -1,213 +0,0 @@ -/* - This file is part of TALER - Copyright (C) 2020-2023 Taler Systems SA - - TALER is free software; you can redistribute it and/or modify it under the - terms of the GNU General Public License as published by the Free Software - Foundation; either version 3, or (at your option) any later version. - - TALER is distributed in the hope that it will be useful, but WITHOUT ANY - WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR - A PARTICULAR PURPOSE. See the GNU General Public License for more details. - - You should have received a copy of the GNU General Public License along with - TALER; see the file COPYING. If not, see - -*/ -/** - * @file lib/exchange_api_management_drain_profits.c - * @brief functions to set wire fees at an exchange - * @author Christian Grothoff - */ -#include "platform.h" -#include "taler_json_lib.h" -#include -#include "exchange_api_curl_defaults.h" -#include "taler_exchange_service.h" -#include "taler_signatures.h" -#include "taler_curl_lib.h" -#include "taler_json_lib.h" - - -struct TALER_EXCHANGE_ManagementDrainProfitsHandle -{ - - /** - * The url for this request. - */ - char *url; - - /** - * Minor context that holds body and headers. - */ - struct TALER_CURL_PostContext post_ctx; - - /** - * Handle for the request. - */ - struct GNUNET_CURL_Job *job; - - /** - * Function to call with the result. - */ - TALER_EXCHANGE_ManagementDrainProfitsCallback cb; - - /** - * Closure for @a cb. - */ - void *cb_cls; - - /** - * Reference to the execution context. - */ - struct GNUNET_CURL_Context *ctx; -}; - - -/** - * Function called when we're done processing the - * HTTP /management/drain request. - * - * @param cls the `struct TALER_EXCHANGE_ManagementDrainProfitsHandle *` - * @param response_code HTTP response code, 0 on error - * @param response response body, NULL if not in JSON - */ -static void -handle_drain_profits_finished (void *cls, - long response_code, - const void *response) -{ - struct TALER_EXCHANGE_ManagementDrainProfitsHandle *dp = cls; - const json_t *json = response; - struct TALER_EXCHANGE_ManagementDrainResponse dr = { - .hr.http_status = (unsigned int) response_code, - .hr.reply = json - }; - - dp->job = NULL; - switch (response_code) - { - case MHD_HTTP_NO_CONTENT: - break; - case MHD_HTTP_FORBIDDEN: - dr.hr.ec = TALER_JSON_get_error_code (json); - dr.hr.hint = TALER_JSON_get_error_hint (json); - break; - case MHD_HTTP_CONFLICT: - dr.hr.ec = TALER_JSON_get_error_code (json); - dr.hr.hint = TALER_JSON_get_error_hint (json); - break; - case MHD_HTTP_PRECONDITION_FAILED: - dr.hr.ec = TALER_JSON_get_error_code (json); - dr.hr.hint = TALER_JSON_get_error_hint (json); - break; - default: - /* unexpected response code */ - GNUNET_break_op (0); - dr.hr.ec = TALER_JSON_get_error_code (json); - dr.hr.hint = TALER_JSON_get_error_hint (json); - GNUNET_log (GNUNET_ERROR_TYPE_ERROR, - "Unexpected response code %u/%d for exchange management drain profits\n", - (unsigned int) response_code, - (int) dr.hr.ec); - break; - } - if (NULL != dp->cb) - { - dp->cb (dp->cb_cls, - &dr); - dp->cb = NULL; - } - TALER_EXCHANGE_management_drain_profits_cancel (dp); -} - - -struct TALER_EXCHANGE_ManagementDrainProfitsHandle * -TALER_EXCHANGE_management_drain_profits ( - struct GNUNET_CURL_Context *ctx, - const char *url, - const struct TALER_WireTransferIdentifierRawP *wtid, - const struct TALER_Amount *amount, - struct GNUNET_TIME_Timestamp date, - const char *account_section, - const char *payto_uri, - const struct TALER_MasterSignatureP *master_sig, - TALER_EXCHANGE_ManagementDrainProfitsCallback cb, - void *cb_cls) -{ - struct TALER_EXCHANGE_ManagementDrainProfitsHandle *dp; - CURL *eh; - json_t *body; - - dp = GNUNET_new (struct TALER_EXCHANGE_ManagementDrainProfitsHandle); - dp->cb = cb; - dp->cb_cls = cb_cls; - dp->ctx = ctx; - dp->url = TALER_url_join (url, - "management/drain", - NULL); - if (NULL == dp->url) - { - GNUNET_log (GNUNET_ERROR_TYPE_ERROR, - "Could not construct request URL.\n"); - GNUNET_free (dp); - return NULL; - } - body = GNUNET_JSON_PACK ( - GNUNET_JSON_pack_string ("debit_account_section", - account_section), - GNUNET_JSON_pack_string ("credit_payto_uri", - payto_uri), - GNUNET_JSON_pack_data_auto ("wtid", - wtid), - GNUNET_JSON_pack_data_auto ("master_sig", - master_sig), - GNUNET_JSON_pack_timestamp ("date", - date), - TALER_JSON_pack_amount ("amount", - amount)); - eh = TALER_EXCHANGE_curl_easy_get_ (dp->url); - if ( (NULL == eh) || - (GNUNET_OK != - TALER_curl_easy_post (&dp->post_ctx, - eh, - body)) ) - { - GNUNET_break (0); - if (NULL != eh) - curl_easy_cleanup (eh); - json_decref (body); - GNUNET_free (dp->url); - return NULL; - } - json_decref (body); - GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, - "Requesting URL '%s'\n", - dp->url); - dp->job = GNUNET_CURL_job_add2 (ctx, - eh, - dp->post_ctx.headers, - &handle_drain_profits_finished, - dp); - if (NULL == dp->job) - { - TALER_EXCHANGE_management_drain_profits_cancel (dp); - return NULL; - } - return dp; -} - - -void -TALER_EXCHANGE_management_drain_profits_cancel ( - struct TALER_EXCHANGE_ManagementDrainProfitsHandle *dp) -{ - if (NULL != dp->job) - { - GNUNET_CURL_job_cancel (dp->job); - dp->job = NULL; - } - TALER_curl_easy_post_finished (&dp->post_ctx); - GNUNET_free (dp->url); - GNUNET_free (dp); -} diff --git a/src/lib/exchange_api_management_post_extensions.c b/src/lib/exchange_api_management_post_extensions.c deleted file mode 100644 index 00d1c5e3f..000000000 --- a/src/lib/exchange_api_management_post_extensions.c +++ /dev/null @@ -1,213 +0,0 @@ -/* - This file is part of TALER - Copyright (C) 2015-2023 Taler Systems SA - - TALER is free software; you can redistribute it and/or modify it under the - terms of the GNU General Public License as published by the Free Software - Foundation; either version 3, or (at your option) any later version. - - TALER is distributed in the hope that it will be useful, but WITHOUT ANY - WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR - A PARTICULAR PURPOSE. See the GNU General Public License for more details. - - You should have received a copy of the GNU General Public License along with - TALER; see the file COPYING. If not, see - - */ -/** - * @file lib/exchange_api_management_post_extensions.c - * @brief functions to handle the settings for extensions (p2p and age restriction) - * @author Özgür Kesim - */ -#include "platform.h" -#include "taler_json_lib.h" -#include -#include "taler_extensions.h" -#include "exchange_api_curl_defaults.h" -#include "taler_exchange_service.h" -#include "taler_signatures.h" -#include "taler_curl_lib.h" -#include "taler_json_lib.h" - - -/** - * @brief Handle for a POST /management/extensions request. - */ -struct TALER_EXCHANGE_ManagementPostExtensionsHandle -{ - - /** - * The url for this request. - */ - char *url; - - /** - * Minor context that holds body and headers. - */ - struct TALER_CURL_PostContext post_ctx; - - /** - * Handle for the request. - */ - struct GNUNET_CURL_Job *job; - - /** - * Function to call with the result. - */ - TALER_EXCHANGE_ManagementPostExtensionsCallback cb; - - /** - * Closure for @a cb. - */ - void *cb_cls; - - /** - * Reference to the execution context. - */ - struct GNUNET_CURL_Context *ctx; -}; - - -/** - * Function called when we're done processing the - * HTTP POST /management/extensions request. - * - * @param cls the `struct TALER_EXCHANGE_ManagementPostExtensionsHandle *` - * @param response_code HTTP response code, 0 on error - * @param response response body, NULL if not in JSON - */ -static void -handle_post_extensions_finished (void *cls, - long response_code, - const void *response) -{ - struct TALER_EXCHANGE_ManagementPostExtensionsHandle *ph = cls; - const json_t *json = response; - struct TALER_EXCHANGE_ManagementPostExtensionsResponse per = { - .hr.http_status = (unsigned int) response_code, - .hr.reply = json - }; - - ph->job = NULL; - switch (response_code) - { - case MHD_HTTP_NO_CONTENT: - break; - case MHD_HTTP_FORBIDDEN: - per.hr.ec = TALER_JSON_get_error_code (json); - per.hr.hint = TALER_JSON_get_error_hint (json); - break; - case MHD_HTTP_NOT_FOUND: - GNUNET_log (GNUNET_ERROR_TYPE_ERROR, - "Server did not find handler at `%s'. Did you configure the correct exchange base URL?\n", - ph->url); - if (NULL != json) - { - per.hr.ec = TALER_JSON_get_error_code (json); - per.hr.hint = TALER_JSON_get_error_hint (json); - } - else - { - per.hr.ec = TALER_EC_GENERIC_INVALID_RESPONSE; - per.hr.hint = TALER_ErrorCode_get_hint (per.hr.ec); - } - break; - default: - /* unexpected response code */ - GNUNET_break_op (0); - per.hr.ec = TALER_JSON_get_error_code (json); - per.hr.hint = TALER_JSON_get_error_hint (json); - GNUNET_log (GNUNET_ERROR_TYPE_ERROR, - "Unexpected response code %u/%d for exchange management post extensions\n", - (unsigned int) response_code, - (int) per.hr.ec); - break; - } - if (NULL != ph->cb) - { - ph->cb (ph->cb_cls, - &per); - ph->cb = NULL; - } - TALER_EXCHANGE_management_post_extensions_cancel (ph); -} - - -struct TALER_EXCHANGE_ManagementPostExtensionsHandle * -TALER_EXCHANGE_management_post_extensions ( - struct GNUNET_CURL_Context *ctx, - const char *url, - const struct TALER_EXCHANGE_ManagementPostExtensionsData *ped, - TALER_EXCHANGE_ManagementPostExtensionsCallback cb, - void *cb_cls) -{ - struct TALER_EXCHANGE_ManagementPostExtensionsHandle *ph; - CURL *eh = NULL; - json_t *body = NULL; - - ph = GNUNET_new (struct TALER_EXCHANGE_ManagementPostExtensionsHandle); - ph->cb = cb; - ph->cb_cls = cb_cls; - ph->ctx = ctx; - ph->url = TALER_url_join (url, - "management/extensions", - NULL); - if (NULL == ph->url) - { - GNUNET_log (GNUNET_ERROR_TYPE_ERROR, - "Could not construct request URL.\n"); - GNUNET_free (ph); - return NULL; - } - - body = GNUNET_JSON_PACK ( - GNUNET_JSON_pack_object_steal ("extensions", - (json_t *) ped->extensions), - GNUNET_JSON_pack_data_auto ("extensions_sig", - &ped->extensions_sig)); - - eh = TALER_EXCHANGE_curl_easy_get_ (ph->url); - if ( (NULL == eh) || - (GNUNET_OK != - TALER_curl_easy_post (&ph->post_ctx, - eh, - body)) ) - { - GNUNET_break (0); - if (NULL != eh) - curl_easy_cleanup (eh); - json_decref (body); - GNUNET_free (ph->url); - return NULL; - } - json_decref (body); - GNUNET_log (GNUNET_ERROR_TYPE_INFO, - "Requesting URL '%s'\n", - ph->url); - ph->job = GNUNET_CURL_job_add2 (ctx, - eh, - ph->post_ctx.headers, - &handle_post_extensions_finished, - ph); - if (NULL == ph->job) - { - TALER_EXCHANGE_management_post_extensions_cancel (ph); - return NULL; - } - return ph; -} - - -void -TALER_EXCHANGE_management_post_extensions_cancel ( - struct TALER_EXCHANGE_ManagementPostExtensionsHandle *ph) -{ - if (NULL != ph->job) - { - GNUNET_CURL_job_cancel (ph->job); - ph->job = NULL; - } - TALER_curl_easy_post_finished (&ph->post_ctx); - GNUNET_free (ph->url); - GNUNET_free (ph); -} diff --git a/src/lib/exchange_api_management_post_keys.c b/src/lib/exchange_api_management_post_keys.c deleted file mode 100644 index a46124d90..000000000 --- a/src/lib/exchange_api_management_post_keys.c +++ /dev/null @@ -1,237 +0,0 @@ -/* - This file is part of TALER - Copyright (C) 2015-2021 Taler Systems SA - - TALER is free software; you can redistribute it and/or modify it under the - terms of the GNU General Public License as published by the Free Software - Foundation; either version 3, or (at your option) any later version. - - TALER is distributed in the hope that it will be useful, but WITHOUT ANY - WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR - A PARTICULAR PURPOSE. See the GNU General Public License for more details. - - You should have received a copy of the GNU General Public License along with - TALER; see the file COPYING. If not, see - -*/ -/** - * @file lib/exchange_api_management_post_keys.c - * @brief functions to affirm the validity of exchange keys using the master private key - * @author Christian Grothoff - */ -#include "platform.h" -#include "taler_json_lib.h" -#include -#include "taler_exchange_service.h" -#include "exchange_api_curl_defaults.h" -#include "taler_signatures.h" -#include "taler_curl_lib.h" -#include "taler_json_lib.h" - - -/** - * @brief Handle for a POST /management/keys request. - */ -struct TALER_EXCHANGE_ManagementPostKeysHandle -{ - - /** - * The url for this request. - */ - char *url; - - /** - * Minor context that holds body and headers. - */ - struct TALER_CURL_PostContext post_ctx; - - /** - * Handle for the request. - */ - struct GNUNET_CURL_Job *job; - - /** - * Function to call with the result. - */ - TALER_EXCHANGE_ManagementPostKeysCallback cb; - - /** - * Closure for @a cb. - */ - void *cb_cls; - - /** - * Reference to the execution context. - */ - struct GNUNET_CURL_Context *ctx; -}; - - -/** - * Function called when we're done processing the - * HTTP POST /management/keys request. - * - * @param cls the `struct TALER_EXCHANGE_ManagementPostKeysHandle *` - * @param response_code HTTP response code, 0 on error - * @param response response body, NULL if not in JSON - */ -static void -handle_post_keys_finished (void *cls, - long response_code, - const void *response) -{ - struct TALER_EXCHANGE_ManagementPostKeysHandle *ph = cls; - const json_t *json = response; - struct TALER_EXCHANGE_ManagementPostKeysResponse pkr = { - .hr.http_status = (unsigned int) response_code, - .hr.reply = json - }; - - ph->job = NULL; - switch (response_code) - { - case MHD_HTTP_NO_CONTENT: - break; - case MHD_HTTP_FORBIDDEN: - pkr.hr.ec = TALER_JSON_get_error_code (json); - pkr.hr.hint = TALER_JSON_get_error_hint (json); - break; - case MHD_HTTP_NOT_FOUND: - pkr.hr.ec = TALER_JSON_get_error_code (json); - pkr.hr.hint = TALER_JSON_get_error_hint (json); - break; - case MHD_HTTP_REQUEST_ENTITY_TOO_LARGE: - pkr.hr.ec = TALER_JSON_get_error_code (json); - pkr.hr.hint = TALER_JSON_get_error_hint (json); - break; - default: - /* unexpected response code */ - GNUNET_break_op (0); - pkr.hr.ec = TALER_JSON_get_error_code (json); - pkr.hr.hint = TALER_JSON_get_error_hint (json); - GNUNET_log (GNUNET_ERROR_TYPE_ERROR, - "Unexpected response code %u/%d for exchange management post keys\n", - (unsigned int) response_code, - (int) pkr.hr.ec); - break; - } - if (NULL != ph->cb) - { - ph->cb (ph->cb_cls, - &pkr); - ph->cb = NULL; - } - TALER_EXCHANGE_post_management_keys_cancel (ph); -} - - -struct TALER_EXCHANGE_ManagementPostKeysHandle * -TALER_EXCHANGE_post_management_keys ( - struct GNUNET_CURL_Context *ctx, - const char *url, - const struct TALER_EXCHANGE_ManagementPostKeysData *pkd, - TALER_EXCHANGE_ManagementPostKeysCallback cb, - void *cb_cls) -{ - struct TALER_EXCHANGE_ManagementPostKeysHandle *ph; - CURL *eh; - json_t *body; - json_t *denom_sigs; - json_t *signkey_sigs; - - ph = GNUNET_new (struct TALER_EXCHANGE_ManagementPostKeysHandle); - ph->cb = cb; - ph->cb_cls = cb_cls; - ph->ctx = ctx; - ph->url = TALER_url_join (url, - "management/keys", - NULL); - if (NULL == ph->url) - { - GNUNET_log (GNUNET_ERROR_TYPE_ERROR, - "Could not construct request URL.\n"); - GNUNET_free (ph); - return NULL; - } - denom_sigs = json_array (); - GNUNET_assert (NULL != denom_sigs); - for (unsigned int i = 0; inum_denom_sigs; i++) - { - const struct TALER_EXCHANGE_DenominationKeySignature *dks - = &pkd->denom_sigs[i]; - - GNUNET_assert (0 == - json_array_append_new ( - denom_sigs, - GNUNET_JSON_PACK ( - GNUNET_JSON_pack_data_auto ("h_denom_pub", - &dks->h_denom_pub), - GNUNET_JSON_pack_data_auto ("master_sig", - &dks->master_sig)))); - } - signkey_sigs = json_array (); - GNUNET_assert (NULL != signkey_sigs); - for (unsigned int i = 0; inum_sign_sigs; i++) - { - const struct TALER_EXCHANGE_SigningKeySignature *sks - = &pkd->sign_sigs[i]; - - GNUNET_assert (0 == - json_array_append_new ( - signkey_sigs, - GNUNET_JSON_PACK ( - GNUNET_JSON_pack_data_auto ("exchange_pub", - &sks->exchange_pub), - GNUNET_JSON_pack_data_auto ("master_sig", - &sks->master_sig)))); - } - body = GNUNET_JSON_PACK ( - GNUNET_JSON_pack_array_steal ("denom_sigs", - denom_sigs), - GNUNET_JSON_pack_array_steal ("signkey_sigs", - signkey_sigs)); - eh = TALER_EXCHANGE_curl_easy_get_ (ph->url); - if ( (NULL == eh) || - (GNUNET_OK != - TALER_curl_easy_post (&ph->post_ctx, - eh, - body)) ) - { - GNUNET_break (0); - if (NULL != eh) - curl_easy_cleanup (eh); - json_decref (body); - GNUNET_free (ph->url); - return NULL; - } - json_decref (body); - GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, - "Requesting URL '%s'\n", - ph->url); - ph->job = GNUNET_CURL_job_add2 (ctx, - eh, - ph->post_ctx.headers, - &handle_post_keys_finished, - ph); - if (NULL == ph->job) - { - TALER_EXCHANGE_post_management_keys_cancel (ph); - return NULL; - } - return ph; -} - - -void -TALER_EXCHANGE_post_management_keys_cancel ( - struct TALER_EXCHANGE_ManagementPostKeysHandle *ph) -{ - if (NULL != ph->job) - { - GNUNET_CURL_job_cancel (ph->job); - ph->job = NULL; - } - TALER_curl_easy_post_finished (&ph->post_ctx); - GNUNET_free (ph->url); - GNUNET_free (ph); -} diff --git a/src/lib/exchange_api_management_revoke_denomination_key.c b/src/lib/exchange_api_management_revoke_denomination_key.c deleted file mode 100644 index aa4d527a7..000000000 --- a/src/lib/exchange_api_management_revoke_denomination_key.c +++ /dev/null @@ -1,221 +0,0 @@ -/* - This file is part of TALER - Copyright (C) 2015-2020 Taler Systems SA - - TALER is free software; you can redistribute it and/or modify it under the - terms of the GNU General Public License as published by the Free Software - Foundation; either version 3, or (at your option) any later version. - - TALER is distributed in the hope that it will be useful, but WITHOUT ANY - WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR - A PARTICULAR PURPOSE. See the GNU General Public License for more details. - - You should have received a copy of the GNU General Public License along with - TALER; see the file COPYING. If not, see - -*/ -/** - * @file lib/exchange_api_management_revoke_denomination_key.c - * @brief functions to revoke an exchange denomination key - * @author Christian Grothoff - */ -#include "platform.h" -#include "taler_json_lib.h" -#include -#include "taler_exchange_service.h" -#include "exchange_api_curl_defaults.h" -#include "taler_signatures.h" -#include "taler_curl_lib.h" -#include "taler_json_lib.h" - - -/** - * @brief Handle for a POST /management/denominations/$H_DENOM_PUB/revoke request. - */ -struct TALER_EXCHANGE_ManagementRevokeDenominationKeyHandle -{ - - /** - * The url for this request. - */ - char *url; - - /** - * Minor context that holds body and headers. - */ - struct TALER_CURL_PostContext post_ctx; - - /** - * Handle for the request. - */ - struct GNUNET_CURL_Job *job; - - /** - * Function to call with the result. - */ - TALER_EXCHANGE_ManagementRevokeDenominationKeyCallback cb; - - /** - * Closure for @a cb. - */ - void *cb_cls; - - /** - * Reference to the execution context. - */ - struct GNUNET_CURL_Context *ctx; -}; - - -/** - * Function called when we're done processing the - * HTTP /management/denominations/$H_DENOM_PUB/revoke request. - * - * @param cls the `struct TALER_EXCHANGE_ManagementRevokeDenominationKeyHandle *` - * @param response_code HTTP response code, 0 on error - * @param response response body, NULL if not in JSON - */ -static void -handle_revoke_denomination_finished (void *cls, - long response_code, - const void *response) -{ - struct TALER_EXCHANGE_ManagementRevokeDenominationKeyHandle *rh = cls; - const json_t *json = response; - struct TALER_EXCHANGE_ManagementRevokeDenominationResponse rdr = { - .hr.http_status = (unsigned int) response_code, - .hr.reply = json - }; - - rh->job = NULL; - switch (response_code) - { - case 0: - /* no reply */ - rdr.hr.ec = TALER_EC_GENERIC_INVALID_RESPONSE; - rdr.hr.hint = "server offline?"; - break; - case MHD_HTTP_NO_CONTENT: - break; - case MHD_HTTP_FORBIDDEN: - rdr.hr.ec = TALER_JSON_get_error_code (json); - rdr.hr.hint = TALER_JSON_get_error_hint (json); - break; - default: - /* unexpected response code */ - GNUNET_break_op (0); - rdr.hr.ec = TALER_JSON_get_error_code (json); - rdr.hr.hint = TALER_JSON_get_error_hint (json); - GNUNET_log (GNUNET_ERROR_TYPE_ERROR, - "Unexpected response code %u/%d for exchange management revoke denomination\n", - (unsigned int) response_code, - (int) rdr.hr.ec); - break; - } - if (NULL != rh->cb) - { - rh->cb (rh->cb_cls, - &rdr); - rh->cb = NULL; - } - TALER_EXCHANGE_management_revoke_denomination_key_cancel (rh); -} - - -struct TALER_EXCHANGE_ManagementRevokeDenominationKeyHandle * -TALER_EXCHANGE_management_revoke_denomination_key ( - struct GNUNET_CURL_Context *ctx, - const char *url, - const struct TALER_DenominationHashP *h_denom_pub, - const struct TALER_MasterSignatureP *master_sig, - TALER_EXCHANGE_ManagementRevokeDenominationKeyCallback cb, - void *cb_cls) -{ - struct TALER_EXCHANGE_ManagementRevokeDenominationKeyHandle *rh; - CURL *eh; - json_t *body; - - rh = GNUNET_new (struct TALER_EXCHANGE_ManagementRevokeDenominationKeyHandle); - rh->cb = cb; - rh->cb_cls = cb_cls; - rh->ctx = ctx; - { - char epub_str[sizeof (*h_denom_pub) * 2]; - char arg_str[sizeof (epub_str) + 64]; - char *end; - - end = GNUNET_STRINGS_data_to_string (h_denom_pub, - sizeof (*h_denom_pub), - epub_str, - sizeof (epub_str)); - *end = '\0'; - GNUNET_snprintf (arg_str, - sizeof (arg_str), - "management/denominations/%s/revoke", - epub_str); - rh->url = TALER_url_join (url, - arg_str, - NULL); - } - if (NULL == rh->url) - { - GNUNET_log (GNUNET_ERROR_TYPE_ERROR, - "Could not construct request URL.\n"); - GNUNET_free (rh); - return NULL; - } - body = GNUNET_JSON_PACK ( - GNUNET_JSON_pack_data_auto ("master_sig", - master_sig)); - if (NULL == body) - { - GNUNET_break (0); - GNUNET_free (rh->url); - GNUNET_free (rh); - return NULL; - } - eh = TALER_EXCHANGE_curl_easy_get_ (rh->url); - if ( (NULL == eh) || - (GNUNET_OK != - TALER_curl_easy_post (&rh->post_ctx, - eh, - body)) ) - { - GNUNET_break (0); - if (NULL != eh) - curl_easy_cleanup (eh); - json_decref (body); - GNUNET_free (rh->url); - return NULL; - } - json_decref (body); - GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, - "Requesting URL '%s'\n", - rh->url); - rh->job = GNUNET_CURL_job_add2 (ctx, - eh, - rh->post_ctx.headers, - &handle_revoke_denomination_finished, - rh); - if (NULL == rh->job) - { - TALER_EXCHANGE_management_revoke_denomination_key_cancel (rh); - return NULL; - } - return rh; -} - - -void -TALER_EXCHANGE_management_revoke_denomination_key_cancel ( - struct TALER_EXCHANGE_ManagementRevokeDenominationKeyHandle *rh) -{ - if (NULL != rh->job) - { - GNUNET_CURL_job_cancel (rh->job); - rh->job = NULL; - } - TALER_curl_easy_post_finished (&rh->post_ctx); - GNUNET_free (rh->url); - GNUNET_free (rh); -} diff --git a/src/lib/exchange_api_management_revoke_signing_key.c b/src/lib/exchange_api_management_revoke_signing_key.c deleted file mode 100644 index c4d634248..000000000 --- a/src/lib/exchange_api_management_revoke_signing_key.c +++ /dev/null @@ -1,211 +0,0 @@ -/* - This file is part of TALER - Copyright (C) 2015-2021 Taler Systems SA - - TALER is free software; you can redistribute it and/or modify it under the - terms of the GNU General Public License as published by the Free Software - Foundation; either version 3, or (at your option) any later version. - - TALER is distributed in the hope that it will be useful, but WITHOUT ANY - WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR - A PARTICULAR PURPOSE. See the GNU General Public License for more details. - - You should have received a copy of the GNU General Public License along with - TALER; see the file COPYING. If not, see - -*/ -/** - * @file lib/exchange_api_management_revoke_signing_key.c - * @brief functions to revoke an exchange online signing key - * @author Christian Grothoff - */ -#include "platform.h" -#include "taler_json_lib.h" -#include -#include "taler_exchange_service.h" -#include "exchange_api_curl_defaults.h" -#include "taler_signatures.h" -#include "taler_curl_lib.h" -#include "taler_json_lib.h" - - -struct TALER_EXCHANGE_ManagementRevokeSigningKeyHandle -{ - - /** - * The url for this request. - */ - char *url; - - /** - * Minor context that holds body and headers. - */ - struct TALER_CURL_PostContext post_ctx; - - /** - * Handle for the request. - */ - struct GNUNET_CURL_Job *job; - - /** - * Function to call with the result. - */ - TALER_EXCHANGE_ManagementRevokeSigningKeyCallback cb; - - /** - * Closure for @a cb. - */ - void *cb_cls; - - /** - * Reference to the execution context. - */ - struct GNUNET_CURL_Context *ctx; -}; - - -/** - * Function called when we're done processing the - * HTTP /management/signkeys/%s/revoke request. - * - * @param cls the `struct TALER_EXCHANGE_ManagementRevokeSigningKeyHandle *` - * @param response_code HTTP response code, 0 on error - * @param response response body, NULL if not in JSON - */ -static void -handle_revoke_signing_finished (void *cls, - long response_code, - const void *response) -{ - struct TALER_EXCHANGE_ManagementRevokeSigningKeyHandle *rh = cls; - const json_t *json = response; - struct TALER_EXCHANGE_ManagementRevokeSigningKeyResponse rsr = { - .hr.http_status = (unsigned int) response_code, - .hr.reply = json - }; - - rh->job = NULL; - switch (response_code) - { - case 0: - /* no reply */ - rsr.hr.ec = TALER_EC_GENERIC_INVALID_RESPONSE; - rsr.hr.hint = "server offline?"; - break; - case MHD_HTTP_NO_CONTENT: - break; - case MHD_HTTP_FORBIDDEN: - rsr.hr.ec = TALER_JSON_get_error_code (json); - rsr.hr.hint = TALER_JSON_get_error_hint (json); - break; - default: - /* unexpected response code */ - GNUNET_break_op (0); - rsr.hr.ec = TALER_JSON_get_error_code (json); - rsr.hr.hint = TALER_JSON_get_error_hint (json); - GNUNET_log (GNUNET_ERROR_TYPE_ERROR, - "Unexpected response code %u/%d for exchange management revoke signkey\n", - (unsigned int) response_code, - (int) rsr.hr.ec); - break; - } - if (NULL != rh->cb) - { - rh->cb (rh->cb_cls, - &rsr); - rh->cb = NULL; - } - TALER_EXCHANGE_management_revoke_signing_key_cancel (rh); -} - - -struct TALER_EXCHANGE_ManagementRevokeSigningKeyHandle * -TALER_EXCHANGE_management_revoke_signing_key ( - struct GNUNET_CURL_Context *ctx, - const char *url, - const struct TALER_ExchangePublicKeyP *exchange_pub, - const struct TALER_MasterSignatureP *master_sig, - TALER_EXCHANGE_ManagementRevokeSigningKeyCallback cb, - void *cb_cls) -{ - struct TALER_EXCHANGE_ManagementRevokeSigningKeyHandle *rh; - CURL *eh; - json_t *body; - - rh = GNUNET_new (struct TALER_EXCHANGE_ManagementRevokeSigningKeyHandle); - rh->cb = cb; - rh->cb_cls = cb_cls; - rh->ctx = ctx; - { - char epub_str[sizeof (*exchange_pub) * 2]; - char arg_str[sizeof (epub_str) + 64]; - char *end; - - end = GNUNET_STRINGS_data_to_string (exchange_pub, - sizeof (*exchange_pub), - epub_str, - sizeof (epub_str)); - *end = '\0'; - GNUNET_snprintf (arg_str, - sizeof (arg_str), - "management/signkeys/%s/revoke", - epub_str); - rh->url = TALER_url_join (url, - arg_str, - NULL); - } - if (NULL == rh->url) - { - GNUNET_log (GNUNET_ERROR_TYPE_ERROR, - "Could not construct request URL.\n"); - GNUNET_free (rh); - return NULL; - } - body = GNUNET_JSON_PACK ( - GNUNET_JSON_pack_data_auto ("master_sig", - master_sig)); - eh = TALER_EXCHANGE_curl_easy_get_ (rh->url); - if ( (NULL == eh) || - (GNUNET_OK != - TALER_curl_easy_post (&rh->post_ctx, - eh, - body)) ) - { - GNUNET_break (0); - if (NULL != eh) - curl_easy_cleanup (eh); - json_decref (body); - GNUNET_free (rh->url); - return NULL; - } - json_decref (body); - GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, - "Requesting URL '%s'\n", - rh->url); - rh->job = GNUNET_CURL_job_add2 (ctx, - eh, - rh->post_ctx.headers, - &handle_revoke_signing_finished, - rh); - if (NULL == rh->job) - { - TALER_EXCHANGE_management_revoke_signing_key_cancel (rh); - return NULL; - } - return rh; -} - - -void -TALER_EXCHANGE_management_revoke_signing_key_cancel ( - struct TALER_EXCHANGE_ManagementRevokeSigningKeyHandle *rh) -{ - if (NULL != rh->job) - { - GNUNET_CURL_job_cancel (rh->job); - rh->job = NULL; - } - TALER_curl_easy_post_finished (&rh->post_ctx); - GNUNET_free (rh->url); - GNUNET_free (rh); -} diff --git a/src/lib/exchange_api_management_set_global_fee.c b/src/lib/exchange_api_management_set_global_fee.c deleted file mode 100644 index 54c37fd64..000000000 --- a/src/lib/exchange_api_management_set_global_fee.c +++ /dev/null @@ -1,235 +0,0 @@ -/* - This file is part of TALER - Copyright (C) 2020-2022 Taler Systems SA - - TALER is free software; you can redistribute it and/or modify it under the - terms of the GNU General Public License as published by the Free Software - Foundation; either version 3, or (at your option) any later version. - - TALER is distributed in the hope that it will be useful, but WITHOUT ANY - WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR - A PARTICULAR PURPOSE. See the GNU General Public License for more details. - - You should have received a copy of the GNU General Public License along with - TALER; see the file COPYING. If not, see - -*/ -/** - * @file lib/exchange_api_management_set_global_fee.c - * @brief functions to set global fees at an exchange - * @author Christian Grothoff - */ -#include "platform.h" -#include "taler_json_lib.h" -#include -#include "exchange_api_curl_defaults.h" -#include "taler_exchange_service.h" -#include "taler_signatures.h" -#include "taler_curl_lib.h" -#include "taler_json_lib.h" - - -struct TALER_EXCHANGE_ManagementSetGlobalFeeHandle -{ - - /** - * The url for this request. - */ - char *url; - - /** - * Minor context that holds body and headers. - */ - struct TALER_CURL_PostContext post_ctx; - - /** - * Handle for the request. - */ - struct GNUNET_CURL_Job *job; - - /** - * Function to call with the result. - */ - TALER_EXCHANGE_ManagementSetGlobalFeeCallback cb; - - /** - * Closure for @a cb. - */ - void *cb_cls; - - /** - * Reference to the execution context. - */ - struct GNUNET_CURL_Context *ctx; -}; - - -/** - * Function called when we're done processing the - * HTTP /management/global request. - * - * @param cls the `struct TALER_EXCHANGE_ManagementAuditorEnableHandle *` - * @param response_code HTTP response code, 0 on error - * @param response response body, NULL if not in JSON - */ -static void -handle_set_global_fee_finished (void *cls, - long response_code, - const void *response) -{ - struct TALER_EXCHANGE_ManagementSetGlobalFeeHandle *sgfh = cls; - const json_t *json = response; - struct TALER_EXCHANGE_ManagementSetGlobalFeeResponse sfr = { - .hr.http_status = (unsigned int) response_code, - .hr.reply = json - }; - - sgfh->job = NULL; - switch (response_code) - { - case MHD_HTTP_NO_CONTENT: - break; - case MHD_HTTP_FORBIDDEN: - sfr.hr.ec = TALER_JSON_get_error_code (json); - sfr.hr.hint = TALER_JSON_get_error_hint (json); - break; - case MHD_HTTP_NOT_FOUND: - GNUNET_log (GNUNET_ERROR_TYPE_ERROR, - "Server did not find handler at `%s'. Did you configure the correct exchange base URL?\n", - sgfh->url); - if (NULL != json) - { - sfr.hr.ec = TALER_JSON_get_error_code (json); - sfr.hr.hint = TALER_JSON_get_error_hint (json); - } - else - { - sfr.hr.ec = TALER_EC_GENERIC_INVALID_RESPONSE; - sfr.hr.hint = TALER_ErrorCode_get_hint (sfr.hr.ec); - } - break; - case MHD_HTTP_CONFLICT: - sfr.hr.ec = TALER_JSON_get_error_code (json); - sfr.hr.hint = TALER_JSON_get_error_hint (json); - break; - case MHD_HTTP_PRECONDITION_FAILED: - sfr.hr.ec = TALER_JSON_get_error_code (json); - sfr.hr.hint = TALER_JSON_get_error_hint (json); - break; - default: - /* unexpected response code */ - GNUNET_break_op (0); - sfr.hr.ec = TALER_JSON_get_error_code (json); - sfr.hr.hint = TALER_JSON_get_error_hint (json); - GNUNET_log (GNUNET_ERROR_TYPE_ERROR, - "Unexpected response code %u/%d for exchange management set global fee\n", - (unsigned int) response_code, - (int) sfr.hr.ec); - break; - } - if (NULL != sgfh->cb) - { - sgfh->cb (sgfh->cb_cls, - &sfr); - sgfh->cb = NULL; - } - TALER_EXCHANGE_management_set_global_fees_cancel (sgfh); -} - - -struct TALER_EXCHANGE_ManagementSetGlobalFeeHandle * -TALER_EXCHANGE_management_set_global_fees ( - struct GNUNET_CURL_Context *ctx, - const char *exchange_base_url, - struct GNUNET_TIME_Timestamp validity_start, - struct GNUNET_TIME_Timestamp validity_end, - const struct TALER_GlobalFeeSet *fees, - struct GNUNET_TIME_Relative purse_timeout, - struct GNUNET_TIME_Relative history_expiration, - uint32_t purse_account_limit, - const struct TALER_MasterSignatureP *master_sig, - TALER_EXCHANGE_ManagementSetGlobalFeeCallback cb, - void *cb_cls) -{ - struct TALER_EXCHANGE_ManagementSetGlobalFeeHandle *sgfh; - CURL *eh; - json_t *body; - - sgfh = GNUNET_new (struct TALER_EXCHANGE_ManagementSetGlobalFeeHandle); - sgfh->cb = cb; - sgfh->cb_cls = cb_cls; - sgfh->ctx = ctx; - sgfh->url = TALER_url_join (exchange_base_url, - "management/global-fee", - NULL); - if (NULL == sgfh->url) - { - GNUNET_log (GNUNET_ERROR_TYPE_ERROR, - "Could not construct request URL.\n"); - GNUNET_free (sgfh); - return NULL; - } - body = GNUNET_JSON_PACK ( - GNUNET_JSON_pack_data_auto ("master_sig", - master_sig), - GNUNET_JSON_pack_timestamp ("fee_start", - validity_start), - GNUNET_JSON_pack_timestamp ("fee_end", - validity_end), - TALER_JSON_pack_amount ("history_fee", - &fees->history), - TALER_JSON_pack_amount ("account_fee", - &fees->account), - TALER_JSON_pack_amount ("purse_fee", - &fees->purse), - GNUNET_JSON_pack_time_rel ("purse_timeout", - purse_timeout), - GNUNET_JSON_pack_time_rel ("history_expiration", - history_expiration), - GNUNET_JSON_pack_uint64 ("purse_account_limit", - purse_account_limit)); - eh = TALER_EXCHANGE_curl_easy_get_ (sgfh->url); - if ( (NULL == eh) || - (GNUNET_OK != - TALER_curl_easy_post (&sgfh->post_ctx, - eh, - body)) ) - { - GNUNET_break (0); - if (NULL != eh) - curl_easy_cleanup (eh); - json_decref (body); - GNUNET_free (sgfh->url); - return NULL; - } - json_decref (body); - GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, - "Requesting URL '%s'\n", - sgfh->url); - sgfh->job = GNUNET_CURL_job_add2 (ctx, - eh, - sgfh->post_ctx.headers, - &handle_set_global_fee_finished, - sgfh); - if (NULL == sgfh->job) - { - TALER_EXCHANGE_management_set_global_fees_cancel (sgfh); - return NULL; - } - return sgfh; -} - - -void -TALER_EXCHANGE_management_set_global_fees_cancel ( - struct TALER_EXCHANGE_ManagementSetGlobalFeeHandle *sgfh) -{ - if (NULL != sgfh->job) - { - GNUNET_CURL_job_cancel (sgfh->job); - sgfh->job = NULL; - } - TALER_curl_easy_post_finished (&sgfh->post_ctx); - GNUNET_free (sgfh->url); - GNUNET_free (sgfh); -} diff --git a/src/lib/exchange_api_management_set_wire_fee.c b/src/lib/exchange_api_management_set_wire_fee.c deleted file mode 100644 index 03cab8c99..000000000 --- a/src/lib/exchange_api_management_set_wire_fee.c +++ /dev/null @@ -1,227 +0,0 @@ -/* - This file is part of TALER - Copyright (C) 2020-2022 Taler Systems SA - - TALER is free software; you can redistribute it and/or modify it under the - terms of the GNU General Public License as published by the Free Software - Foundation; either version 3, or (at your option) any later version. - - TALER is distributed in the hope that it will be useful, but WITHOUT ANY - WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR - A PARTICULAR PURPOSE. See the GNU General Public License for more details. - - You should have received a copy of the GNU General Public License along with - TALER; see the file COPYING. If not, see - -*/ -/** - * @file lib/exchange_api_management_set_wire_fee.c - * @brief functions to set wire fees at an exchange - * @author Christian Grothoff - */ -#include "platform.h" -#include "taler_json_lib.h" -#include -#include "exchange_api_curl_defaults.h" -#include "taler_exchange_service.h" -#include "taler_signatures.h" -#include "taler_curl_lib.h" -#include "taler_json_lib.h" - - -struct TALER_EXCHANGE_ManagementSetWireFeeHandle -{ - - /** - * The url for this request. - */ - char *url; - - /** - * Minor context that holds body and headers. - */ - struct TALER_CURL_PostContext post_ctx; - - /** - * Handle for the request. - */ - struct GNUNET_CURL_Job *job; - - /** - * Function to call with the result. - */ - TALER_EXCHANGE_ManagementSetWireFeeCallback cb; - - /** - * Closure for @a cb. - */ - void *cb_cls; - - /** - * Reference to the execution context. - */ - struct GNUNET_CURL_Context *ctx; -}; - - -/** - * Function called when we're done processing the - * HTTP /management/wire request. - * - * @param cls the `struct TALER_EXCHANGE_ManagementAuditorEnableHandle *` - * @param response_code HTTP response code, 0 on error - * @param response response body, NULL if not in JSON - */ -static void -handle_set_wire_fee_finished (void *cls, - long response_code, - const void *response) -{ - struct TALER_EXCHANGE_ManagementSetWireFeeHandle *swfh = cls; - const json_t *json = response; - struct TALER_EXCHANGE_ManagementSetWireFeeResponse swr = { - .hr.http_status = (unsigned int) response_code, - .hr.reply = json - }; - - swfh->job = NULL; - switch (response_code) - { - case MHD_HTTP_NO_CONTENT: - break; - case MHD_HTTP_FORBIDDEN: - swr.hr.ec = TALER_JSON_get_error_code (json); - swr.hr.hint = TALER_JSON_get_error_hint (json); - break; - case MHD_HTTP_NOT_FOUND: - GNUNET_log (GNUNET_ERROR_TYPE_ERROR, - "Server did not find handler at `%s'. Did you configure the correct exchange base URL?\n", - swfh->url); - if (NULL != json) - { - swr.hr.ec = TALER_JSON_get_error_code (json); - swr.hr.hint = TALER_JSON_get_error_hint (json); - } - else - { - swr.hr.ec = TALER_EC_GENERIC_INVALID_RESPONSE; - swr.hr.hint = TALER_ErrorCode_get_hint (swr.hr.ec); - } - break; - case MHD_HTTP_CONFLICT: - swr.hr.ec = TALER_JSON_get_error_code (json); - swr.hr.hint = TALER_JSON_get_error_hint (json); - break; - case MHD_HTTP_PRECONDITION_FAILED: - swr.hr.ec = TALER_JSON_get_error_code (json); - swr.hr.hint = TALER_JSON_get_error_hint (json); - break; - default: - /* unexpected response code */ - GNUNET_break_op (0); - swr.hr.ec = TALER_JSON_get_error_code (json); - swr.hr.hint = TALER_JSON_get_error_hint (json); - GNUNET_log (GNUNET_ERROR_TYPE_ERROR, - "Unexpected response code %u/%d for exchange management set wire fee\n", - (unsigned int) response_code, - (int) swr.hr.ec); - break; - } - if (NULL != swfh->cb) - { - swfh->cb (swfh->cb_cls, - &swr); - swfh->cb = NULL; - } - TALER_EXCHANGE_management_set_wire_fees_cancel (swfh); -} - - -struct TALER_EXCHANGE_ManagementSetWireFeeHandle * -TALER_EXCHANGE_management_set_wire_fees ( - struct GNUNET_CURL_Context *ctx, - const char *exchange_base_url, - const char *wire_method, - struct GNUNET_TIME_Timestamp validity_start, - struct GNUNET_TIME_Timestamp validity_end, - const struct TALER_WireFeeSet *fees, - const struct TALER_MasterSignatureP *master_sig, - TALER_EXCHANGE_ManagementSetWireFeeCallback cb, - void *cb_cls) -{ - struct TALER_EXCHANGE_ManagementSetWireFeeHandle *swfh; - CURL *eh; - json_t *body; - - swfh = GNUNET_new (struct TALER_EXCHANGE_ManagementSetWireFeeHandle); - swfh->cb = cb; - swfh->cb_cls = cb_cls; - swfh->ctx = ctx; - swfh->url = TALER_url_join (exchange_base_url, - "management/wire-fee", - NULL); - if (NULL == swfh->url) - { - GNUNET_log (GNUNET_ERROR_TYPE_ERROR, - "Could not construct request URL.\n"); - GNUNET_free (swfh); - return NULL; - } - body = GNUNET_JSON_PACK ( - GNUNET_JSON_pack_string ("wire_method", - wire_method), - GNUNET_JSON_pack_data_auto ("master_sig", - master_sig), - GNUNET_JSON_pack_timestamp ("fee_start", - validity_start), - GNUNET_JSON_pack_timestamp ("fee_end", - validity_end), - TALER_JSON_pack_amount ("closing_fee", - &fees->closing), - TALER_JSON_pack_amount ("wire_fee", - &fees->wire)); - eh = TALER_EXCHANGE_curl_easy_get_ (swfh->url); - if ( (NULL == eh) || - (GNUNET_OK != - TALER_curl_easy_post (&swfh->post_ctx, - eh, - body)) ) - { - GNUNET_break (0); - if (NULL != eh) - curl_easy_cleanup (eh); - json_decref (body); - GNUNET_free (swfh->url); - return NULL; - } - json_decref (body); - GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, - "Requesting URL '%s'\n", - swfh->url); - swfh->job = GNUNET_CURL_job_add2 (ctx, - eh, - swfh->post_ctx.headers, - &handle_set_wire_fee_finished, - swfh); - if (NULL == swfh->job) - { - TALER_EXCHANGE_management_set_wire_fees_cancel (swfh); - return NULL; - } - return swfh; -} - - -void -TALER_EXCHANGE_management_set_wire_fees_cancel ( - struct TALER_EXCHANGE_ManagementSetWireFeeHandle *swfh) -{ - if (NULL != swfh->job) - { - GNUNET_CURL_job_cancel (swfh->job); - swfh->job = NULL; - } - TALER_curl_easy_post_finished (&swfh->post_ctx); - GNUNET_free (swfh->url); - GNUNET_free (swfh); -} diff --git a/src/lib/exchange_api_management_update_aml_officer.c b/src/lib/exchange_api_management_update_aml_officer.c deleted file mode 100644 index 76cbc7e8d..000000000 --- a/src/lib/exchange_api_management_update_aml_officer.c +++ /dev/null @@ -1,229 +0,0 @@ -/* - This file is part of TALER - Copyright (C) 2023 Taler Systems SA - - TALER is free software; you can redistribute it and/or modify it under the - terms of the GNU General Public License as published by the Free Software - Foundation; either version 3, or (at your option) any later version. - - TALER is distributed in the hope that it will be useful, but WITHOUT ANY - WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR - A PARTICULAR PURPOSE. See the GNU General Public License for more details. - - You should have received a copy of the GNU General Public License along with - TALER; see the file COPYING. If not, see - -*/ -/** - * @file lib/exchange_api_management_update_aml_officer.c - * @brief functions to update AML officer status - * @author Christian Grothoff - */ -#include "platform.h" -#include "taler_json_lib.h" -#include -#include "taler_exchange_service.h" -#include "exchange_api_curl_defaults.h" -#include "taler_signatures.h" -#include "taler_curl_lib.h" -#include "taler_json_lib.h" - - -struct TALER_EXCHANGE_ManagementUpdateAmlOfficer -{ - - /** - * The url for this request. - */ - char *url; - - /** - * Minor context that holds body and headers. - */ - struct TALER_CURL_PostContext post_ctx; - - /** - * Handle for the request. - */ - struct GNUNET_CURL_Job *job; - - /** - * Function to call with the result. - */ - TALER_EXCHANGE_ManagementUpdateAmlOfficerCallback cb; - - /** - * Closure for @a cb. - */ - void *cb_cls; - - /** - * Reference to the execution context. - */ - struct GNUNET_CURL_Context *ctx; -}; - - -/** - * Function called when we're done processing the - * HTTP /management/wire request. - * - * @param cls the `struct TALER_EXCHANGE_ManagementAuditorEnableHandle *` - * @param response_code HTTP response code, 0 on error - * @param response response body, NULL if not in JSON - */ -static void -handle_update_aml_officer_finished (void *cls, - long response_code, - const void *response) -{ - struct TALER_EXCHANGE_ManagementUpdateAmlOfficer *wh = cls; - const json_t *json = response; - struct TALER_EXCHANGE_ManagementUpdateAmlOfficerResponse uar = { - .hr.http_status = (unsigned int) response_code, - .hr.reply = json - }; - - wh->job = NULL; - switch (response_code) - { - case 0: - /* no reply */ - uar.hr.ec = TALER_EC_GENERIC_INVALID_RESPONSE; - uar.hr.hint = "server offline?"; - break; - case MHD_HTTP_NO_CONTENT: - break; - case MHD_HTTP_FORBIDDEN: - uar.hr.ec = TALER_JSON_get_error_code (json); - uar.hr.hint = TALER_JSON_get_error_hint (json); - break; - case MHD_HTTP_NOT_FOUND: - GNUNET_log (GNUNET_ERROR_TYPE_ERROR, - "Server did not find handler at `%s'. Did you configure the correct exchange base URL?\n", - wh->url); - if (NULL != json) - { - uar.hr.ec = TALER_JSON_get_error_code (json); - uar.hr.hint = TALER_JSON_get_error_hint (json); - } - else - { - uar.hr.ec = TALER_EC_GENERIC_INVALID_RESPONSE; - uar.hr.hint = TALER_ErrorCode_get_hint (uar.hr.ec); - } - break; - case MHD_HTTP_CONFLICT: - uar.hr.ec = TALER_JSON_get_error_code (json); - uar.hr.hint = TALER_JSON_get_error_hint (json); - break; - default: - /* unexpected response code */ - GNUNET_break_op (0); - uar.hr.ec = TALER_JSON_get_error_code (json); - uar.hr.hint = TALER_JSON_get_error_hint (json); - GNUNET_log (GNUNET_ERROR_TYPE_ERROR, - "Unexpected response code %u/%d for exchange management update AML officer\n", - (unsigned int) response_code, - (int) uar.hr.ec); - break; - } - if (NULL != wh->cb) - { - wh->cb (wh->cb_cls, - &uar); - wh->cb = NULL; - } - TALER_EXCHANGE_management_update_aml_officer_cancel (wh); -} - - -struct TALER_EXCHANGE_ManagementUpdateAmlOfficer * -TALER_EXCHANGE_management_update_aml_officer ( - struct GNUNET_CURL_Context *ctx, - const char *url, - const struct TALER_AmlOfficerPublicKeyP *officer_pub, - const char *officer_name, - struct GNUNET_TIME_Timestamp change_date, - bool is_active, - bool read_only, - const struct TALER_MasterSignatureP *master_sig, - TALER_EXCHANGE_ManagementUpdateAmlOfficerCallback cb, - void *cb_cls) -{ - struct TALER_EXCHANGE_ManagementUpdateAmlOfficer *wh; - CURL *eh; - json_t *body; - - wh = GNUNET_new (struct TALER_EXCHANGE_ManagementUpdateAmlOfficer); - wh->cb = cb; - wh->cb_cls = cb_cls; - wh->ctx = ctx; - wh->url = TALER_url_join (url, - "management/aml-officers", - NULL); - if (NULL == wh->url) - { - GNUNET_log (GNUNET_ERROR_TYPE_ERROR, - "Could not construct request URL.\n"); - GNUNET_free (wh); - return NULL; - } - body = GNUNET_JSON_PACK ( - GNUNET_JSON_pack_string ("officer_name", - officer_name), - GNUNET_JSON_pack_data_auto ("officer_pub", - officer_pub), - GNUNET_JSON_pack_data_auto ("master_sig", - master_sig), - GNUNET_JSON_pack_bool ("is_active", - is_active), - GNUNET_JSON_pack_bool ("read_only", - read_only), - GNUNET_JSON_pack_timestamp ("change_date", - change_date)); - eh = TALER_EXCHANGE_curl_easy_get_ (wh->url); - if ( (NULL == eh) || - (GNUNET_OK != - TALER_curl_easy_post (&wh->post_ctx, - eh, - body)) ) - { - GNUNET_break (0); - if (NULL != eh) - curl_easy_cleanup (eh); - json_decref (body); - GNUNET_free (wh->url); - return NULL; - } - json_decref (body); - GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, - "Requesting URL '%s'\n", - wh->url); - wh->job = GNUNET_CURL_job_add2 (ctx, - eh, - wh->post_ctx.headers, - &handle_update_aml_officer_finished, - wh); - if (NULL == wh->job) - { - TALER_EXCHANGE_management_update_aml_officer_cancel (wh); - return NULL; - } - return wh; -} - - -void -TALER_EXCHANGE_management_update_aml_officer_cancel ( - struct TALER_EXCHANGE_ManagementUpdateAmlOfficer *wh) -{ - if (NULL != wh->job) - { - GNUNET_CURL_job_cancel (wh->job); - wh->job = NULL; - } - TALER_curl_easy_post_finished (&wh->post_ctx); - GNUNET_free (wh->url); - GNUNET_free (wh); -} diff --git a/src/lib/exchange_api_management_wire_disable.c b/src/lib/exchange_api_management_wire_disable.c deleted file mode 100644 index 30749b0e4..000000000 --- a/src/lib/exchange_api_management_wire_disable.c +++ /dev/null @@ -1,220 +0,0 @@ -/* - This file is part of TALER - Copyright (C) 2015-2023 Taler Systems SA - - TALER is free software; you can redistribute it and/or modify it under the - terms of the GNU General Public License as published by the Free Software - Foundation; either version 3, or (at your option) any later version. - - TALER is distributed in the hope that it will be useful, but WITHOUT ANY - WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR - A PARTICULAR PURPOSE. See the GNU General Public License for more details. - - You should have received a copy of the GNU General Public License along with - TALER; see the file COPYING. If not, see - -*/ -/** - * @file lib/exchange_api_management_wire_disable.c - * @brief functions to disable an exchange wire method / bank account - * @author Christian Grothoff - */ -#include "platform.h" -#include "taler_json_lib.h" -#include -#include "taler_exchange_service.h" -#include "exchange_api_curl_defaults.h" -#include "taler_signatures.h" -#include "taler_curl_lib.h" -#include "taler_json_lib.h" - - -struct TALER_EXCHANGE_ManagementWireDisableHandle -{ - - /** - * The url for this request. - */ - char *url; - - /** - * Minor context that holds body and headers. - */ - struct TALER_CURL_PostContext post_ctx; - - /** - * Handle for the request. - */ - struct GNUNET_CURL_Job *job; - - /** - * Function to call with the result. - */ - TALER_EXCHANGE_ManagementWireDisableCallback cb; - - /** - * Closure for @a cb. - */ - void *cb_cls; - - /** - * Reference to the execution context. - */ - struct GNUNET_CURL_Context *ctx; -}; - - -/** - * Function called when we're done processing the - * HTTP /management/wire/disable request. - * - * @param cls the `struct TALER_EXCHANGE_ManagementAuditorDisableHandle *` - * @param response_code HTTP response code, 0 on error - * @param response response body, NULL if not in JSON - */ -static void -handle_auditor_disable_finished (void *cls, - long response_code, - const void *response) -{ - struct TALER_EXCHANGE_ManagementWireDisableHandle *wh = cls; - const json_t *json = response; - struct TALER_EXCHANGE_ManagementWireDisableResponse wdr = { - .hr.http_status = (unsigned int) response_code, - .hr.reply = json - }; - - wh->job = NULL; - switch (response_code) - { - case 0: - /* no reply */ - wdr.hr.ec = TALER_EC_GENERIC_INVALID_RESPONSE; - wdr.hr.hint = "server offline?"; - break; - case MHD_HTTP_NO_CONTENT: - break; - case MHD_HTTP_FORBIDDEN: - wdr.hr.ec = TALER_JSON_get_error_code (json); - wdr.hr.hint = TALER_JSON_get_error_hint (json); - break; - case MHD_HTTP_NOT_FOUND: - GNUNET_log (GNUNET_ERROR_TYPE_ERROR, - "Server did not find handler at `%s'. Did you configure the correct exchange base URL?\n", - wh->url); - if (NULL != json) - { - wdr.hr.ec = TALER_JSON_get_error_code (json); - wdr.hr.hint = TALER_JSON_get_error_hint (json); - } - else - { - wdr.hr.ec = TALER_EC_GENERIC_INVALID_RESPONSE; - wdr.hr.hint = TALER_ErrorCode_get_hint (wdr.hr.ec); - } - break; - case MHD_HTTP_CONFLICT: - wdr.hr.ec = TALER_JSON_get_error_code (json); - wdr.hr.hint = TALER_JSON_get_error_hint (json); - break; - default: - /* unexpected response code */ - GNUNET_break_op (0); - wdr.hr.ec = TALER_JSON_get_error_code (json); - wdr.hr.hint = TALER_JSON_get_error_hint (json); - GNUNET_log (GNUNET_ERROR_TYPE_ERROR, - "Unexpected response code %u/%d exchange management disable wire\n", - (unsigned int) response_code, - (int) wdr.hr.ec); - break; - } - if (NULL != wh->cb) - { - wh->cb (wh->cb_cls, - &wdr); - wh->cb = NULL; - } - TALER_EXCHANGE_management_disable_wire_cancel (wh); -} - - -struct TALER_EXCHANGE_ManagementWireDisableHandle * -TALER_EXCHANGE_management_disable_wire ( - struct GNUNET_CURL_Context *ctx, - const char *url, - const char *payto_uri, - struct GNUNET_TIME_Timestamp validity_end, - const struct TALER_MasterSignatureP *master_sig, - TALER_EXCHANGE_ManagementWireDisableCallback cb, - void *cb_cls) -{ - struct TALER_EXCHANGE_ManagementWireDisableHandle *wh; - CURL *eh; - json_t *body; - - wh = GNUNET_new (struct TALER_EXCHANGE_ManagementWireDisableHandle); - wh->cb = cb; - wh->cb_cls = cb_cls; - wh->ctx = ctx; - wh->url = TALER_url_join (url, - "management/wire/disable", - NULL); - if (NULL == wh->url) - { - GNUNET_log (GNUNET_ERROR_TYPE_ERROR, - "Could not construct request URL.\n"); - GNUNET_free (wh); - return NULL; - } - body = GNUNET_JSON_PACK ( - GNUNET_JSON_pack_string ("payto_uri", - payto_uri), - GNUNET_JSON_pack_data_auto ("master_sig_del", - master_sig), - GNUNET_JSON_pack_timestamp ("validity_end", - validity_end)); - eh = TALER_EXCHANGE_curl_easy_get_ (wh->url); - if ( (NULL == eh) || - (GNUNET_OK != - TALER_curl_easy_post (&wh->post_ctx, - eh, - body)) ) - { - GNUNET_break (0); - if (NULL != eh) - curl_easy_cleanup (eh); - json_decref (body); - GNUNET_free (wh->url); - return NULL; - } - json_decref (body); - GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, - "Requesting URL '%s'\n", - wh->url); - wh->job = GNUNET_CURL_job_add2 (ctx, - eh, - wh->post_ctx.headers, - &handle_auditor_disable_finished, - wh); - if (NULL == wh->job) - { - TALER_EXCHANGE_management_disable_wire_cancel (wh); - return NULL; - } - return wh; -} - - -void -TALER_EXCHANGE_management_disable_wire_cancel ( - struct TALER_EXCHANGE_ManagementWireDisableHandle *wh) -{ - if (NULL != wh->job) - { - GNUNET_CURL_job_cancel (wh->job); - wh->job = NULL; - } - TALER_curl_easy_post_finished (&wh->post_ctx); - GNUNET_free (wh->url); - GNUNET_free (wh); -} diff --git a/src/lib/exchange_api_management_wire_enable.c b/src/lib/exchange_api_management_wire_enable.c deleted file mode 100644 index 5add3e0b0..000000000 --- a/src/lib/exchange_api_management_wire_enable.c +++ /dev/null @@ -1,245 +0,0 @@ -/* - This file is part of TALER - Copyright (C) 2015-2023 Taler Systems SA - - TALER is free software; you can redistribute it and/or modify it under the - terms of the GNU General Public License as published by the Free Software - Foundation; either version 3, or (at your option) any later version. - - TALER is distributed in the hope that it will be useful, but WITHOUT ANY - WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR - A PARTICULAR PURPOSE. See the GNU General Public License for more details. - - You should have received a copy of the GNU General Public License along with - TALER; see the file COPYING. If not, see - -*/ -/** - * @file lib/exchange_api_management_wire_enable.c - * @brief functions to enable an exchange wire method / bank account - * @author Christian Grothoff - */ -#include "platform.h" -#include "taler_json_lib.h" -#include -#include "taler_exchange_service.h" -#include "exchange_api_curl_defaults.h" -#include "taler_signatures.h" -#include "taler_curl_lib.h" -#include "taler_json_lib.h" - - -struct TALER_EXCHANGE_ManagementWireEnableHandle -{ - - /** - * The url for this request. - */ - char *url; - - /** - * Minor context that holds body and headers. - */ - struct TALER_CURL_PostContext post_ctx; - - /** - * Handle for the request. - */ - struct GNUNET_CURL_Job *job; - - /** - * Function to call with the result. - */ - TALER_EXCHANGE_ManagementWireEnableCallback cb; - - /** - * Closure for @a cb. - */ - void *cb_cls; - - /** - * Reference to the execution context. - */ - struct GNUNET_CURL_Context *ctx; -}; - - -/** - * Function called when we're done processing the - * HTTP /management/wire request. - * - * @param cls the `struct TALER_EXCHANGE_ManagementAuditorEnableHandle *` - * @param response_code HTTP response code, 0 on error - * @param response response body, NULL if not in JSON - */ -static void -handle_auditor_enable_finished (void *cls, - long response_code, - const void *response) -{ - struct TALER_EXCHANGE_ManagementWireEnableHandle *wh = cls; - const json_t *json = response; - struct TALER_EXCHANGE_ManagementWireEnableResponse wer = { - .hr.http_status = (unsigned int) response_code, - .hr.reply = json - }; - - wh->job = NULL; - switch (response_code) - { - case 0: - /* no reply */ - wer.hr.ec = TALER_EC_GENERIC_INVALID_RESPONSE; - wer.hr.hint = "server offline?"; - break; - case MHD_HTTP_NO_CONTENT: - break; - case MHD_HTTP_FORBIDDEN: - wer.hr.ec = TALER_JSON_get_error_code (json); - wer.hr.hint = TALER_JSON_get_error_hint (json); - break; - case MHD_HTTP_NOT_FOUND: - GNUNET_log (GNUNET_ERROR_TYPE_ERROR, - "Server did not find handler at `%s'. Did you configure the correct exchange base URL?\n", - wh->url); - if (NULL != json) - { - wer.hr.ec = TALER_JSON_get_error_code (json); - wer.hr.hint = TALER_JSON_get_error_hint (json); - } - else - { - wer.hr.ec = TALER_EC_GENERIC_INVALID_RESPONSE; - wer.hr.hint = TALER_ErrorCode_get_hint (wer.hr.ec); - } - break; - case MHD_HTTP_CONFLICT: - wer.hr.ec = TALER_JSON_get_error_code (json); - wer.hr.hint = TALER_JSON_get_error_hint (json); - break; - default: - /* unexpected response code */ - GNUNET_break_op (0); - wer.hr.ec = TALER_JSON_get_error_code (json); - wer.hr.hint = TALER_JSON_get_error_hint (json); - GNUNET_log (GNUNET_ERROR_TYPE_ERROR, - "Unexpected response code %u/%d for exchange management enable wire\n", - (unsigned int) response_code, - (int) wer.hr.ec); - break; - } - if (NULL != wh->cb) - { - wh->cb (wh->cb_cls, - &wer); - wh->cb = NULL; - } - TALER_EXCHANGE_management_enable_wire_cancel (wh); -} - - -struct TALER_EXCHANGE_ManagementWireEnableHandle * -TALER_EXCHANGE_management_enable_wire ( - struct GNUNET_CURL_Context *ctx, - const char *url, - const char *payto_uri, - const char *conversion_url, - const json_t *debit_restrictions, - const json_t *credit_restrictions, - struct GNUNET_TIME_Timestamp validity_start, - const struct TALER_MasterSignatureP *master_sig1, - const struct TALER_MasterSignatureP *master_sig2, - TALER_EXCHANGE_ManagementWireEnableCallback cb, - void *cb_cls) -{ - struct TALER_EXCHANGE_ManagementWireEnableHandle *wh; - CURL *eh; - json_t *body; - - { - char *msg = TALER_payto_validate (payto_uri); - - if (NULL != msg) - { - GNUNET_log (GNUNET_ERROR_TYPE_ERROR, - "payto URI is malformed: %s\n", - msg); - GNUNET_free (msg); - return NULL; - } - } - wh = GNUNET_new (struct TALER_EXCHANGE_ManagementWireEnableHandle); - wh->cb = cb; - wh->cb_cls = cb_cls; - wh->ctx = ctx; - wh->url = TALER_url_join (url, - "management/wire", - NULL); - if (NULL == wh->url) - { - GNUNET_log (GNUNET_ERROR_TYPE_ERROR, - "Could not construct request URL.\n"); - GNUNET_free (wh); - return NULL; - } - body = GNUNET_JSON_PACK ( - GNUNET_JSON_pack_string ("payto_uri", - payto_uri), - GNUNET_JSON_pack_array_incref ("debit_restrictions", - (json_t *) debit_restrictions), - GNUNET_JSON_pack_array_incref ("credit_restrictions", - (json_t *) credit_restrictions), - GNUNET_JSON_pack_allow_null ( - GNUNET_JSON_pack_string ("conversion_url", - conversion_url)), - GNUNET_JSON_pack_data_auto ("master_sig_add", - master_sig1), - GNUNET_JSON_pack_data_auto ("master_sig_wire", - master_sig2), - GNUNET_JSON_pack_timestamp ("validity_start", - validity_start)); - eh = TALER_EXCHANGE_curl_easy_get_ (wh->url); - if ( (NULL == eh) || - (GNUNET_OK != - TALER_curl_easy_post (&wh->post_ctx, - eh, - body)) ) - { - GNUNET_break (0); - if (NULL != eh) - curl_easy_cleanup (eh); - json_decref (body); - GNUNET_free (wh->url); - return NULL; - } - json_decref (body); - GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, - "Requesting URL '%s'\n", - wh->url); - wh->job = GNUNET_CURL_job_add2 (ctx, - eh, - wh->post_ctx.headers, - &handle_auditor_enable_finished, - wh); - if (NULL == wh->job) - { - TALER_EXCHANGE_management_enable_wire_cancel (wh); - return NULL; - } - return wh; -} - - -void -TALER_EXCHANGE_management_enable_wire_cancel ( - struct TALER_EXCHANGE_ManagementWireEnableHandle *wh) -{ - if (NULL != wh->job) - { - GNUNET_CURL_job_cancel (wh->job); - wh->job = NULL; - } - TALER_curl_easy_post_finished (&wh->post_ctx); - GNUNET_free (wh->url); - GNUNET_free (wh); -} diff --git a/src/lib/exchange_api_melt.c b/src/lib/exchange_api_melt.c deleted file mode 100644 index ba4241dab..000000000 --- a/src/lib/exchange_api_melt.c +++ /dev/null @@ -1,596 +0,0 @@ -/* - This file is part of TALER - Copyright (C) 2015-2023 Taler Systems SA - - TALER is free software; you can redistribute it and/or modify it under the - terms of the GNU General Public License as published by the Free Software - Foundation; either version 3, or (at your option) any later version. - - TALER is distributed in the hope that it will be useful, but WITHOUT ANY - WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR - A PARTICULAR PURPOSE. See the GNU General Public License for more details. - - You should have received a copy of the GNU General Public License along with - TALER; see the file COPYING. If not, see - -*/ -/** - * @file lib/exchange_api_melt.c - * @brief Implementation of the /coins/$COIN_PUB/melt request - * @author Christian Grothoff - */ -#include "platform.h" -#include -#include /* just for HTTP status codes */ -#include -#include -#include -#include "taler_json_lib.h" -#include "taler_exchange_service.h" -#include "exchange_api_common.h" -#include "exchange_api_handle.h" -#include "taler_signatures.h" -#include "exchange_api_curl_defaults.h" -#include "exchange_api_refresh_common.h" - - -/** - * @brief A /coins/$COIN_PUB/melt Handle - */ -struct TALER_EXCHANGE_MeltHandle -{ - - /** - * The keys of the this request handle will use - */ - struct TALER_EXCHANGE_Keys *keys; - - /** - * The url for this request. - */ - char *url; - - /** - * The exchange base url. - */ - char *exchange_url; - - /** - * Curl context. - */ - struct GNUNET_CURL_Context *cctx; - - /** - * Context for #TEH_curl_easy_post(). Keeps the data that must - * persist for Curl to make the upload. - */ - struct TALER_CURL_PostContext ctx; - - /** - * Handle for the request. - */ - struct GNUNET_CURL_Job *job; - - /** - * Function to call with refresh melt failure results. - */ - TALER_EXCHANGE_MeltCallback melt_cb; - - /** - * Closure for @e result_cb and @e melt_failure_cb. - */ - void *melt_cb_cls; - - /** - * Actual information about the melt operation. - */ - struct MeltData md; - - /** - * The secret the entire melt operation is seeded from. - */ - struct TALER_RefreshMasterSecretP rms; - - /** - * Details about the characteristics of the requested melt operation. - */ - const struct TALER_EXCHANGE_RefreshData *rd; - - /** - * Array of `num_fresh_coins` per-coin values - * returned from melt operation. - */ - struct TALER_EXCHANGE_MeltBlindingDetail *mbds; - - /** - * Handle for the preflight request, or NULL. - */ - struct TALER_EXCHANGE_CsRMeltHandle *csr; - - /** - * Public key of the coin being melted. - */ - struct TALER_CoinSpendPublicKeyP coin_pub; - - /** - * Signature affirming the melt. - */ - struct TALER_CoinSpendSignatureP coin_sig; - - /** - * @brief Public information about the coin's denomination key - */ - const struct TALER_EXCHANGE_DenomPublicKey *dki; - - /** - * Gamma value chosen by the exchange during melt. - */ - uint32_t noreveal_index; - - /** - * True if we need to include @e rms in our melt request. - */ - bool send_rms; -}; - - -/** - * Verify that the signature on the "200 OK" response - * from the exchange is valid. - * - * @param[in,out] mh melt handle - * @param json json reply with the signature - * @param[out] exchange_pub public key of the exchange used for the signature - * @return #GNUNET_OK if the signature is valid, #GNUNET_SYSERR if not - */ -static enum GNUNET_GenericReturnValue -verify_melt_signature_ok (struct TALER_EXCHANGE_MeltHandle *mh, - const json_t *json, - struct TALER_ExchangePublicKeyP *exchange_pub) -{ - struct TALER_ExchangeSignatureP exchange_sig; - const struct TALER_EXCHANGE_Keys *key_state; - struct GNUNET_JSON_Specification spec[] = { - GNUNET_JSON_spec_fixed_auto ("exchange_sig", - &exchange_sig), - GNUNET_JSON_spec_fixed_auto ("exchange_pub", - exchange_pub), - GNUNET_JSON_spec_uint32 ("noreveal_index", - &mh->noreveal_index), - GNUNET_JSON_spec_end () - }; - - if (GNUNET_OK != - GNUNET_JSON_parse (json, - spec, - NULL, NULL)) - { - GNUNET_break_op (0); - return GNUNET_SYSERR; - } - /* check that exchange signing key is permitted */ - key_state = mh->keys; - if (GNUNET_OK != - TALER_EXCHANGE_test_signing_key (key_state, - exchange_pub)) - { - GNUNET_break_op (0); - return GNUNET_SYSERR; - } - - /* check that noreveal index is in permitted range */ - if (TALER_CNC_KAPPA <= mh->noreveal_index) - { - GNUNET_break_op (0); - return GNUNET_SYSERR; - } - - if (GNUNET_OK != - TALER_exchange_online_melt_confirmation_verify ( - &mh->md.rc, - mh->noreveal_index, - exchange_pub, - &exchange_sig)) - { - GNUNET_break_op (0); - return GNUNET_SYSERR; - } - return GNUNET_OK; -} - - -/** - * Function called when we're done processing the - * HTTP /coins/$COIN_PUB/melt request. - * - * @param cls the `struct TALER_EXCHANGE_MeltHandle` - * @param response_code HTTP response code, 0 on error - * @param response parsed JSON result, NULL on error - */ -static void -handle_melt_finished (void *cls, - long response_code, - const void *response) -{ - struct TALER_EXCHANGE_MeltHandle *mh = cls; - const json_t *j = response; - struct TALER_EXCHANGE_MeltResponse mr = { - .hr.reply = j, - .hr.http_status = (unsigned int) response_code - }; - - mh->job = NULL; - switch (response_code) - { - case 0: - mr.hr.ec = TALER_EC_GENERIC_INVALID_RESPONSE; - break; - case MHD_HTTP_OK: - if (GNUNET_OK != - verify_melt_signature_ok (mh, - j, - &mr.details.ok.sign_key)) - { - GNUNET_break_op (0); - mr.hr.http_status = 0; - mr.hr.ec = TALER_EC_EXCHANGE_MELT_INVALID_SIGNATURE_BY_EXCHANGE; - break; - } - mr.details.ok.noreveal_index = mh->noreveal_index; - mr.details.ok.num_mbds = mh->rd->fresh_pks_len; - mr.details.ok.mbds = mh->mbds; - mh->melt_cb (mh->melt_cb_cls, - &mr); - mh->melt_cb = NULL; - break; - case MHD_HTTP_BAD_REQUEST: - /* This should never happen, either us or the exchange is buggy - (or API version conflict); just pass JSON reply to the application */ - mr.hr.ec = TALER_JSON_get_error_code (j); - mr.hr.hint = TALER_JSON_get_error_hint (j); - break; - case MHD_HTTP_CONFLICT: - mr.hr.ec = TALER_JSON_get_error_code (j); - mr.hr.hint = TALER_JSON_get_error_hint (j); - break; - case MHD_HTTP_FORBIDDEN: - /* Nothing really to verify, exchange says one of the signatures is - invalid; assuming we checked them, this should never happen, we - should pass the JSON reply to the application */ - mr.hr.ec = TALER_JSON_get_error_code (j); - mr.hr.hint = TALER_JSON_get_error_hint (j); - break; - case MHD_HTTP_NOT_FOUND: - /* Nothing really to verify, this should never - happen, we should pass the JSON reply to the application */ - mr.hr.ec = TALER_JSON_get_error_code (j); - mr.hr.hint = TALER_JSON_get_error_hint (j); - break; - case MHD_HTTP_INTERNAL_SERVER_ERROR: - /* Server had an internal issue; we should retry, but this API - leaves this to the application */ - mr.hr.ec = TALER_JSON_get_error_code (j); - mr.hr.hint = TALER_JSON_get_error_hint (j); - break; - default: - /* unexpected response code */ - mr.hr.ec = TALER_JSON_get_error_code (j); - mr.hr.hint = TALER_JSON_get_error_hint (j); - GNUNET_log (GNUNET_ERROR_TYPE_ERROR, - "Unexpected response code %u/%d for exchange melt\n", - (unsigned int) response_code, - mr.hr.ec); - GNUNET_break_op (0); - break; - } - if (NULL != mh->melt_cb) - mh->melt_cb (mh->melt_cb_cls, - &mr); - TALER_EXCHANGE_melt_cancel (mh); -} - - -/** - * Start the actual melt operation, now that we have - * the exchange's input values. - * - * @param[in,out] mh melt operation to run - * @return #GNUNET_OK if we could start the operation - */ -static enum GNUNET_GenericReturnValue -start_melt (struct TALER_EXCHANGE_MeltHandle *mh) -{ - const struct TALER_EXCHANGE_Keys *key_state; - json_t *melt_obj; - CURL *eh; - char arg_str[sizeof (struct TALER_CoinSpendPublicKeyP) * 2 + 32]; - struct TALER_DenominationHashP h_denom_pub; - struct TALER_ExchangeWithdrawValues alg_values[mh->rd->fresh_pks_len]; - - for (unsigned int i = 0; ird->fresh_pks_len; i++) - alg_values[i] = mh->mbds[i].alg_value; - if (GNUNET_OK != - TALER_EXCHANGE_get_melt_data_ (&mh->rms, - mh->rd, - alg_values, - &mh->md)) - { - GNUNET_break (0); - return GNUNET_SYSERR; - } - TALER_denom_pub_hash (&mh->md.melted_coin.pub_key, - &h_denom_pub); - TALER_wallet_melt_sign ( - &mh->md.melted_coin.melt_amount_with_fee, - &mh->md.melted_coin.fee_melt, - &mh->md.rc, - &h_denom_pub, - mh->md.melted_coin.h_age_commitment, - &mh->md.melted_coin.coin_priv, - &mh->coin_sig); - GNUNET_CRYPTO_eddsa_key_get_public (&mh->md.melted_coin.coin_priv.eddsa_priv, - &mh->coin_pub.eddsa_pub); - melt_obj = GNUNET_JSON_PACK ( - GNUNET_JSON_pack_data_auto ("denom_pub_hash", - &h_denom_pub), - TALER_JSON_pack_denom_sig ("denom_sig", - &mh->md.melted_coin.sig), - GNUNET_JSON_pack_data_auto ("confirm_sig", - &mh->coin_sig), - TALER_JSON_pack_amount ("value_with_fee", - &mh->md.melted_coin.melt_amount_with_fee), - GNUNET_JSON_pack_data_auto ("rc", - &mh->md.rc), - GNUNET_JSON_pack_allow_null ( - (NULL != mh->md.melted_coin.h_age_commitment) - ? GNUNET_JSON_pack_data_auto ("age_commitment_hash", - mh->md.melted_coin.h_age_commitment) - : GNUNET_JSON_pack_string ("age_commitment_hash", - NULL)), - GNUNET_JSON_pack_allow_null ( - mh->send_rms - ? GNUNET_JSON_pack_data_auto ("rms", - &mh->rms) - : GNUNET_JSON_pack_string ("rms", - NULL))); - { - char pub_str[sizeof (struct TALER_CoinSpendPublicKeyP) * 2]; - char *end; - - end = GNUNET_STRINGS_data_to_string ( - &mh->coin_pub, - sizeof (struct TALER_CoinSpendPublicKeyP), - pub_str, - sizeof (pub_str)); - *end = '\0'; - GNUNET_snprintf (arg_str, - sizeof (arg_str), - "coins/%s/melt", - pub_str); - } - - key_state = mh->keys; - mh->dki = TALER_EXCHANGE_get_denomination_key (key_state, - &mh->md.melted_coin.pub_key); - - /* and now we can at last begin the actual request handling */ - - mh->url = TALER_url_join (mh->exchange_url, - arg_str, - NULL); - if (NULL == mh->url) - { - json_decref (melt_obj); - return GNUNET_SYSERR; - } - eh = TALER_EXCHANGE_curl_easy_get_ (mh->url); - if ( (NULL == eh) || - (GNUNET_OK != - TALER_curl_easy_post (&mh->ctx, - eh, - melt_obj)) ) - { - GNUNET_break (0); - if (NULL != eh) - curl_easy_cleanup (eh); - json_decref (melt_obj); - return GNUNET_SYSERR; - } - json_decref (melt_obj); - mh->job = GNUNET_CURL_job_add2 (mh->cctx, - eh, - mh->ctx.headers, - &handle_melt_finished, - mh); - return GNUNET_OK; -} - - -/** - * The melt request @a mh failed, return an error to - * the application and cancel the operation. - * - * @param[in] mh melt request that failed - * @param ec error code to fail with - */ -static void -fail_mh (struct TALER_EXCHANGE_MeltHandle *mh, - enum TALER_ErrorCode ec) -{ - struct TALER_EXCHANGE_MeltResponse mr = { - .hr.ec = ec - }; - - mh->melt_cb (mh->melt_cb_cls, - &mr); - TALER_EXCHANGE_melt_cancel (mh); -} - - -/** - * Callbacks of this type are used to serve the result of submitting a - * CS R request to a exchange. - * - * @param cls closure with our `struct TALER_EXCHANGE_MeltHandle *` - * @param csrr response details - */ -static void -csr_cb (void *cls, - const struct TALER_EXCHANGE_CsRMeltResponse *csrr) -{ - struct TALER_EXCHANGE_MeltHandle *mh = cls; - unsigned int nks_off = 0; - - mh->csr = NULL; - if (MHD_HTTP_OK != csrr->hr.http_status) - { - struct TALER_EXCHANGE_MeltResponse mr = { - .hr = csrr->hr - }; - - mr.hr.hint = "/csr-melt failed"; - mh->melt_cb (mh->melt_cb_cls, - &mr); - TALER_EXCHANGE_melt_cancel (mh); - return; - } - for (unsigned int i = 0; ird->fresh_pks_len; i++) - { - const struct TALER_EXCHANGE_DenomPublicKey *fresh_pk = - &mh->rd->fresh_pks[i]; - struct TALER_ExchangeWithdrawValues *wv = &mh->mbds[i].alg_value; - - switch (fresh_pk->key.cipher) - { - case TALER_DENOMINATION_INVALID: - GNUNET_break (0); - fail_mh (mh, - TALER_EC_GENERIC_CLIENT_INTERNAL_ERROR); - return; - case TALER_DENOMINATION_RSA: - GNUNET_assert (TALER_DENOMINATION_RSA == wv->cipher); - break; - case TALER_DENOMINATION_CS: - GNUNET_assert (TALER_DENOMINATION_CS == wv->cipher); - *wv = csrr->details.ok.alg_values[nks_off]; - nks_off++; - break; - } - } - mh->send_rms = true; - if (GNUNET_OK != - start_melt (mh)) - { - GNUNET_break (0); - fail_mh (mh, - TALER_EC_GENERIC_CLIENT_INTERNAL_ERROR); - return; - } -} - - -struct TALER_EXCHANGE_MeltHandle * -TALER_EXCHANGE_melt ( - struct GNUNET_CURL_Context *ctx, - const char *url, - struct TALER_EXCHANGE_Keys *keys, - const struct TALER_RefreshMasterSecretP *rms, - const struct TALER_EXCHANGE_RefreshData *rd, - TALER_EXCHANGE_MeltCallback melt_cb, - void *melt_cb_cls) -{ - struct TALER_EXCHANGE_NonceKey nks[GNUNET_NZL (rd->fresh_pks_len)]; - unsigned int nks_off = 0; - struct TALER_EXCHANGE_MeltHandle *mh; - - if (0 == rd->fresh_pks_len) - { - GNUNET_break (0); - return NULL; - } - mh = GNUNET_new (struct TALER_EXCHANGE_MeltHandle); - mh->noreveal_index = TALER_CNC_KAPPA; /* invalid value */ - mh->cctx = ctx; - mh->exchange_url = GNUNET_strdup (url); - mh->rd = rd; - mh->rms = *rms; - mh->melt_cb = melt_cb; - mh->melt_cb_cls = melt_cb_cls; - mh->mbds = GNUNET_new_array (rd->fresh_pks_len, - struct TALER_EXCHANGE_MeltBlindingDetail); - for (unsigned int i = 0; ifresh_pks_len; i++) - { - const struct TALER_EXCHANGE_DenomPublicKey *fresh_pk = &rd->fresh_pks[i]; - struct TALER_ExchangeWithdrawValues *wv = &mh->mbds[i].alg_value; - - switch (fresh_pk->key.cipher) - { - case TALER_DENOMINATION_INVALID: - GNUNET_break (0); - GNUNET_free (mh->mbds); - GNUNET_free (mh); - return NULL; - case TALER_DENOMINATION_RSA: - wv->cipher = TALER_DENOMINATION_RSA; - break; - case TALER_DENOMINATION_CS: - wv->cipher = TALER_DENOMINATION_CS; - nks[nks_off].pk = fresh_pk; - nks[nks_off].cnc_num = nks_off; - nks_off++; - break; - } - } - mh->keys = TALER_EXCHANGE_keys_incref (keys); - if (0 != nks_off) - { - mh->csr = TALER_EXCHANGE_csr_melt (ctx, - url, - rms, - nks_off, - nks, - &csr_cb, - mh); - if (NULL == mh->csr) - { - GNUNET_break (0); - TALER_EXCHANGE_melt_cancel (mh); - return NULL; - } - return mh; - } - if (GNUNET_OK != - start_melt (mh)) - { - GNUNET_break (0); - TALER_EXCHANGE_melt_cancel (mh); - return NULL; - } - return mh; -} - - -void -TALER_EXCHANGE_melt_cancel (struct TALER_EXCHANGE_MeltHandle *mh) -{ - if (NULL != mh->job) - { - GNUNET_CURL_job_cancel (mh->job); - mh->job = NULL; - } - if (NULL != mh->csr) - { - TALER_EXCHANGE_csr_melt_cancel (mh->csr); - mh->csr = NULL; - } - TALER_EXCHANGE_free_melt_data_ (&mh->md); /* does not free 'md' itself */ - GNUNET_free (mh->mbds); - GNUNET_free (mh->url); - GNUNET_free (mh->exchange_url); - TALER_curl_easy_post_finished (&mh->ctx); - TALER_EXCHANGE_keys_decref (mh->keys); - GNUNET_free (mh); -} - - -/* end of exchange_api_melt.c */ diff --git a/src/lib/exchange_api_recoup.c b/src/lib/exchange_api_recoup.c deleted file mode 100644 index cfd265f04..000000000 --- a/src/lib/exchange_api_recoup.c +++ /dev/null @@ -1,369 +0,0 @@ -/* - This file is part of TALER - Copyright (C) 2017-2023 Taler Systems SA - - TALER is free software; you can redistribute it and/or modify it under the - terms of the GNU General Public License as published by the Free Software - Foundation; either version 3, or (at your option) any later version. - - TALER is distributed in the hope that it will be useful, but WITHOUT ANY - WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR - A PARTICULAR PURPOSE. See the GNU General Public License for more details. - - You should have received a copy of the GNU General Public License along with - TALER; see the file COPYING. If not, see - -*/ -/** - * @file lib/exchange_api_recoup.c - * @brief Implementation of the /recoup request of the exchange's HTTP API - * @author Christian Grothoff - */ -#include "platform.h" -#include -#include /* just for HTTP status codes */ -#include -#include -#include -#include "taler_json_lib.h" -#include "taler_exchange_service.h" -#include "exchange_api_common.h" -#include "exchange_api_handle.h" -#include "taler_signatures.h" -#include "exchange_api_curl_defaults.h" - - -/** - * @brief A Recoup Handle - */ -struct TALER_EXCHANGE_RecoupHandle -{ - - /** - * The keys of the exchange this request handle will use - */ - struct TALER_EXCHANGE_Keys *keys; - - /** - * The url for this request. - */ - char *url; - - /** - * Context for #TEH_curl_easy_post(). Keeps the data that must - * persist for Curl to make the upload. - */ - struct TALER_CURL_PostContext ctx; - - /** - * Denomination key of the coin. - */ - struct TALER_EXCHANGE_DenomPublicKey pk; - - /** - * Our signature requesting the recoup. - */ - struct TALER_CoinSpendSignatureP coin_sig; - - /** - * Handle for the request. - */ - struct GNUNET_CURL_Job *job; - - /** - * Function to call with the result. - */ - TALER_EXCHANGE_RecoupResultCallback cb; - - /** - * Closure for @a cb. - */ - void *cb_cls; - - /** - * Public key of the coin we are trying to get paid back. - */ - struct TALER_CoinSpendPublicKeyP coin_pub; - -}; - - -/** - * Parse a recoup response. If it is valid, call the callback. - * - * @param ph recoup handle - * @param json json reply with the signature - * @return #GNUNET_OK if the signature is valid and we called the callback; - * #GNUNET_SYSERR if not (callback must still be called) - */ -static enum GNUNET_GenericReturnValue -process_recoup_response (const struct TALER_EXCHANGE_RecoupHandle *ph, - const json_t *json) -{ - struct TALER_EXCHANGE_RecoupResponse rr = { - .hr.reply = json, - .hr.http_status = MHD_HTTP_OK - }; - struct GNUNET_JSON_Specification spec_withdraw[] = { - GNUNET_JSON_spec_fixed_auto ("reserve_pub", - &rr.details.ok.reserve_pub), - GNUNET_JSON_spec_end () - }; - - if (GNUNET_OK != - GNUNET_JSON_parse (json, - spec_withdraw, - NULL, NULL)) - { - GNUNET_break_op (0); - return GNUNET_SYSERR; - } - ph->cb (ph->cb_cls, - &rr); - return GNUNET_OK; -} - - -/** - * Function called when we're done processing the - * HTTP /recoup request. - * - * @param cls the `struct TALER_EXCHANGE_RecoupHandle` - * @param response_code HTTP response code, 0 on error - * @param response parsed JSON result, NULL on error - */ -static void -handle_recoup_finished (void *cls, - long response_code, - const void *response) -{ - struct TALER_EXCHANGE_RecoupHandle *ph = cls; - const json_t *j = response; - struct TALER_EXCHANGE_RecoupResponse rr = { - .hr.reply = j, - .hr.http_status = (unsigned int) response_code - }; - - ph->job = NULL; - switch (response_code) - { - case 0: - rr.hr.ec = TALER_EC_GENERIC_INVALID_RESPONSE; - break; - case MHD_HTTP_OK: - if (GNUNET_OK != - process_recoup_response (ph, - j)) - { - GNUNET_break_op (0); - rr.hr.ec = TALER_EC_GENERIC_REPLY_MALFORMED; - rr.hr.http_status = 0; - break; - } - TALER_EXCHANGE_recoup_cancel (ph); - return; - case MHD_HTTP_BAD_REQUEST: - /* This should never happen, either us or the exchange is buggy - (or API version conflict); just pass JSON reply to the application */ - rr.hr.ec = TALER_JSON_get_error_code (j); - rr.hr.hint = TALER_JSON_get_error_hint (j); - break; - case MHD_HTTP_CONFLICT: - { - struct TALER_Amount min_key; - - rr.hr.ec = TALER_JSON_get_error_code (j); - rr.hr.hint = TALER_JSON_get_error_hint (j); - if (GNUNET_OK != - TALER_EXCHANGE_get_min_denomination_ (ph->keys, - &min_key)) - { - GNUNET_break (0); - rr.hr.ec = TALER_EC_GENERIC_REPLY_MALFORMED; - rr.hr.http_status = 0; - break; - } - break; - } - case MHD_HTTP_FORBIDDEN: - /* Nothing really to verify, exchange says one of the signatures is - invalid; as we checked them, this should never happen, we - should pass the JSON reply to the application */ - rr.hr.ec = TALER_JSON_get_error_code (j); - rr.hr.hint = TALER_JSON_get_error_hint (j); - break; - case MHD_HTTP_NOT_FOUND: - /* Nothing really to verify, this should never - happen, we should pass the JSON reply to the application */ - rr.hr.ec = TALER_JSON_get_error_code (j); - rr.hr.hint = TALER_JSON_get_error_hint (j); - break; - case MHD_HTTP_GONE: - /* Kind of normal: the money was already sent to the merchant - (it was too late for the refund). */ - rr.hr.ec = TALER_JSON_get_error_code (j); - rr.hr.hint = TALER_JSON_get_error_hint (j); - break; - case MHD_HTTP_INTERNAL_SERVER_ERROR: - /* Server had an internal issue; we should retry, but this API - leaves this to the application */ - rr.hr.ec = TALER_JSON_get_error_code (j); - rr.hr.hint = TALER_JSON_get_error_hint (j); - break; - default: - /* unexpected response code */ - rr.hr.ec = TALER_JSON_get_error_code (j); - rr.hr.hint = TALER_JSON_get_error_hint (j); - GNUNET_log (GNUNET_ERROR_TYPE_ERROR, - "Unexpected response code %u/%d for exchange recoup\n", - (unsigned int) response_code, - (int) rr.hr.ec); - GNUNET_break (0); - break; - } - ph->cb (ph->cb_cls, - &rr); - TALER_EXCHANGE_recoup_cancel (ph); -} - - -struct TALER_EXCHANGE_RecoupHandle * -TALER_EXCHANGE_recoup ( - struct GNUNET_CURL_Context *ctx, - const char *url, - struct TALER_EXCHANGE_Keys *keys, - const struct TALER_EXCHANGE_DenomPublicKey *pk, - const struct TALER_DenominationSignature *denom_sig, - const struct TALER_ExchangeWithdrawValues *exchange_vals, - const struct TALER_PlanchetMasterSecretP *ps, - TALER_EXCHANGE_RecoupResultCallback recoup_cb, - void *recoup_cb_cls) -{ - struct TALER_EXCHANGE_RecoupHandle *ph; - struct TALER_DenominationHashP h_denom_pub; - json_t *recoup_obj; - CURL *eh; - char arg_str[sizeof (struct TALER_CoinSpendPublicKeyP) * 2 + 32]; - struct TALER_CoinSpendPrivateKeyP coin_priv; - union TALER_DenominationBlindingKeyP bks; - - ph = GNUNET_new (struct TALER_EXCHANGE_RecoupHandle); - TALER_planchet_setup_coin_priv (ps, - exchange_vals, - &coin_priv); - TALER_planchet_blinding_secret_create (ps, - exchange_vals, - &bks); - GNUNET_CRYPTO_eddsa_key_get_public (&coin_priv.eddsa_priv, - &ph->coin_pub.eddsa_pub); - TALER_denom_pub_hash (&pk->key, - &h_denom_pub); - TALER_wallet_recoup_sign (&h_denom_pub, - &bks, - &coin_priv, - &ph->coin_sig); - recoup_obj = GNUNET_JSON_PACK ( - GNUNET_JSON_pack_data_auto ("denom_pub_hash", - &h_denom_pub), - TALER_JSON_pack_denom_sig ("denom_sig", - denom_sig), - TALER_JSON_pack_exchange_withdraw_values ("ewv", - exchange_vals), - GNUNET_JSON_pack_data_auto ("coin_sig", - &ph->coin_sig), - GNUNET_JSON_pack_data_auto ("coin_blind_key_secret", - &bks)); - if (TALER_DENOMINATION_CS == denom_sig->cipher) - { - struct TALER_CsNonce nonce; - - /* NOTE: this is not elegant, and as per the note in TALER_coin_ev_hash() - it is not strictly clear that the nonce is needed. Best case would be - to find a way to include it more 'naturally' somehow, for example with - the variant union version of bks! */ - TALER_cs_withdraw_nonce_derive (ps, - &nonce); - GNUNET_assert ( - 0 == - json_object_set_new (recoup_obj, - "cs_nonce", - GNUNET_JSON_from_data_auto ( - &nonce))); - } - - { - char pub_str[sizeof (struct TALER_CoinSpendPublicKeyP) * 2]; - char *end; - - end = GNUNET_STRINGS_data_to_string ( - &ph->coin_pub, - sizeof (struct TALER_CoinSpendPublicKeyP), - pub_str, - sizeof (pub_str)); - *end = '\0'; - GNUNET_snprintf (arg_str, - sizeof (arg_str), - "coins/%s/recoup", - pub_str); - } - - ph->pk = *pk; - memset (&ph->pk.key, - 0, - sizeof (ph->pk.key)); /* zero out, as lifetime cannot be warranted */ - ph->cb = recoup_cb; - ph->cb_cls = recoup_cb_cls; - ph->url = TALER_url_join (url, - arg_str, - NULL); - if (NULL == ph->url) - { - json_decref (recoup_obj); - GNUNET_free (ph); - return NULL; - } - eh = TALER_EXCHANGE_curl_easy_get_ (ph->url); - if ( (NULL == eh) || - (GNUNET_OK != - TALER_curl_easy_post (&ph->ctx, - eh, - recoup_obj)) ) - { - GNUNET_break (0); - if (NULL != eh) - curl_easy_cleanup (eh); - json_decref (recoup_obj); - GNUNET_free (ph->url); - GNUNET_free (ph); - return NULL; - } - json_decref (recoup_obj); - GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, - "URL for recoup: `%s'\n", - ph->url); - ph->keys = TALER_EXCHANGE_keys_incref (keys); - ph->job = GNUNET_CURL_job_add2 (ctx, - eh, - ph->ctx.headers, - &handle_recoup_finished, - ph); - return ph; -} - - -void -TALER_EXCHANGE_recoup_cancel (struct TALER_EXCHANGE_RecoupHandle *ph) -{ - if (NULL != ph->job) - { - GNUNET_CURL_job_cancel (ph->job); - ph->job = NULL; - } - GNUNET_free (ph->url); - TALER_curl_easy_post_finished (&ph->ctx); - TALER_EXCHANGE_keys_decref (ph->keys); - GNUNET_free (ph); -} - - -/* end of exchange_api_recoup.c */ diff --git a/src/lib/exchange_api_recoup_refresh.c b/src/lib/exchange_api_recoup_refresh.c deleted file mode 100644 index 0bcd44dec..000000000 --- a/src/lib/exchange_api_recoup_refresh.c +++ /dev/null @@ -1,363 +0,0 @@ -/* - This file is part of TALER - Copyright (C) 2017-2023 Taler Systems SA - - TALER is free software; you can redistribute it and/or modify it under the - terms of the GNU General Public License as published by the Free Software - Foundation; either version 3, or (at your option) any later version. - - TALER is distributed in the hope that it will be useful, but WITHOUT ANY - WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR - A PARTICULAR PURPOSE. See the GNU General Public License for more details. - - You should have received a copy of the GNU General Public License along with - TALER; see the file COPYING. If not, see - -*/ -/** - * @file lib/exchange_api_recoup_refresh.c - * @brief Implementation of the /recoup-refresh request of the exchange's HTTP API - * @author Christian Grothoff - */ -#include "platform.h" -#include -#include /* just for HTTP status codes */ -#include -#include -#include -#include "taler_json_lib.h" -#include "taler_exchange_service.h" -#include "exchange_api_common.h" -#include "exchange_api_handle.h" -#include "taler_signatures.h" -#include "exchange_api_curl_defaults.h" - - -/** - * @brief A Recoup Handle - */ -struct TALER_EXCHANGE_RecoupRefreshHandle -{ - - /** - * The keys of the exchange this request handle will use - */ - struct TALER_EXCHANGE_Keys *keys; - - /** - * The url for this request. - */ - char *url; - - /** - * Context for #TEH_curl_easy_post(). Keeps the data that must - * persist for Curl to make the upload. - */ - struct TALER_CURL_PostContext ctx; - - /** - * Denomination key of the coin. - */ - struct TALER_EXCHANGE_DenomPublicKey pk; - - /** - * Handle for the request. - */ - struct GNUNET_CURL_Job *job; - - /** - * Function to call with the result. - */ - TALER_EXCHANGE_RecoupRefreshResultCallback cb; - - /** - * Closure for @a cb. - */ - void *cb_cls; - - /** - * Public key of the coin we are trying to get paid back. - */ - struct TALER_CoinSpendPublicKeyP coin_pub; - - /** - * Signature affirming the recoup-refresh operation. - */ - struct TALER_CoinSpendSignatureP coin_sig; - -}; - - -/** - * Parse a recoup-refresh response. If it is valid, call the callback. - * - * @param ph recoup handle - * @param json json reply with the signature - * @return #GNUNET_OK if the signature is valid and we called the callback; - * #GNUNET_SYSERR if not (callback must still be called) - */ -static enum GNUNET_GenericReturnValue -process_recoup_response ( - const struct TALER_EXCHANGE_RecoupRefreshHandle *ph, - const json_t *json) -{ - struct TALER_EXCHANGE_RecoupRefreshResponse rrr = { - .hr.reply = json, - .hr.http_status = MHD_HTTP_OK - }; - struct GNUNET_JSON_Specification spec_refresh[] = { - GNUNET_JSON_spec_fixed_auto ("old_coin_pub", - &rrr.details.ok.old_coin_pub), - GNUNET_JSON_spec_end () - }; - - if (GNUNET_OK != - GNUNET_JSON_parse (json, - spec_refresh, - NULL, NULL)) - { - GNUNET_break_op (0); - return GNUNET_SYSERR; - } - ph->cb (ph->cb_cls, - &rrr); - return GNUNET_OK; -} - - -/** - * Function called when we're done processing the - * HTTP /recoup-refresh request. - * - * @param cls the `struct TALER_EXCHANGE_RecoupRefreshHandle` - * @param response_code HTTP response code, 0 on error - * @param response parsed JSON result, NULL on error - */ -static void -handle_recoup_refresh_finished (void *cls, - long response_code, - const void *response) -{ - struct TALER_EXCHANGE_RecoupRefreshHandle *ph = cls; - const json_t *j = response; - struct TALER_EXCHANGE_RecoupRefreshResponse rrr = { - .hr.reply = j, - .hr.http_status = (unsigned int) response_code - }; - - ph->job = NULL; - switch (response_code) - { - case 0: - rrr.hr.ec = TALER_EC_GENERIC_INVALID_RESPONSE; - break; - case MHD_HTTP_OK: - if (GNUNET_OK != - process_recoup_response (ph, - j)) - { - GNUNET_break_op (0); - rrr.hr.ec = TALER_EC_GENERIC_REPLY_MALFORMED; - rrr.hr.http_status = 0; - break; - } - TALER_EXCHANGE_recoup_refresh_cancel (ph); - return; - case MHD_HTTP_BAD_REQUEST: - /* This should never happen, either us or the exchange is buggy - (or API version conflict); just pass JSON reply to the application */ - rrr.hr.ec = TALER_JSON_get_error_code (j); - rrr.hr.hint = TALER_JSON_get_error_hint (j); - break; - case MHD_HTTP_FORBIDDEN: - /* Nothing really to verify, exchange says one of the signatures is - invalid; as we checked them, this should never happen, we - should pass the JSON reply to the application */ - rrr.hr.ec = TALER_JSON_get_error_code (j); - rrr.hr.hint = TALER_JSON_get_error_hint (j); - break; - case MHD_HTTP_NOT_FOUND: - /* Nothing really to verify, this should never - happen, we should pass the JSON reply to the application */ - rrr.hr.ec = TALER_JSON_get_error_code (j); - rrr.hr.hint = TALER_JSON_get_error_hint (j); - break; - case MHD_HTTP_CONFLICT: - rrr.hr.ec = TALER_JSON_get_error_code (j); - rrr.hr.hint = TALER_JSON_get_error_hint (j); - break; - case MHD_HTTP_GONE: - /* Kind of normal: the money was already sent to the merchant - (it was too late for the refund). */ - rrr.hr.ec = TALER_JSON_get_error_code (j); - rrr.hr.hint = TALER_JSON_get_error_hint (j); - break; - case MHD_HTTP_INTERNAL_SERVER_ERROR: - /* Server had an internal issue; we should retry, but this API - leaves this to the application */ - rrr.hr.ec = TALER_JSON_get_error_code (j); - rrr.hr.hint = TALER_JSON_get_error_hint (j); - break; - default: - /* unexpected response code */ - rrr.hr.ec = TALER_JSON_get_error_code (j); - rrr.hr.hint = TALER_JSON_get_error_hint (j); - GNUNET_log (GNUNET_ERROR_TYPE_ERROR, - "Unexpected response code %u/%d for exchange recoup\n", - (unsigned int) response_code, - (int) rrr.hr.ec); - GNUNET_break (0); - break; - } - ph->cb (ph->cb_cls, - &rrr); - TALER_EXCHANGE_recoup_refresh_cancel (ph); -} - - -struct TALER_EXCHANGE_RecoupRefreshHandle * -TALER_EXCHANGE_recoup_refresh ( - struct GNUNET_CURL_Context *ctx, - const char *url, - struct TALER_EXCHANGE_Keys *keys, - const struct TALER_EXCHANGE_DenomPublicKey *pk, - const struct TALER_DenominationSignature *denom_sig, - const struct TALER_ExchangeWithdrawValues *exchange_vals, - const struct TALER_RefreshMasterSecretP *rms, - const struct TALER_PlanchetMasterSecretP *ps, - unsigned int idx, - TALER_EXCHANGE_RecoupRefreshResultCallback recoup_cb, - void *recoup_cb_cls) -{ - struct TALER_EXCHANGE_RecoupRefreshHandle *ph; - struct TALER_DenominationHashP h_denom_pub; - json_t *recoup_obj; - CURL *eh; - char arg_str[sizeof (struct TALER_CoinSpendPublicKeyP) * 2 + 32]; - struct TALER_CoinSpendPrivateKeyP coin_priv; - union TALER_DenominationBlindingKeyP bks; - - GNUNET_assert (NULL != recoup_cb); - ph = GNUNET_new (struct TALER_EXCHANGE_RecoupRefreshHandle); - ph->pk = *pk; - memset (&ph->pk.key, - 0, - sizeof (ph->pk.key)); /* zero out, as lifetime cannot be warranted */ - ph->cb = recoup_cb; - ph->cb_cls = recoup_cb_cls; - TALER_planchet_setup_coin_priv (ps, - exchange_vals, - &coin_priv); - TALER_planchet_blinding_secret_create (ps, - exchange_vals, - &bks); - GNUNET_CRYPTO_eddsa_key_get_public (&coin_priv.eddsa_priv, - &ph->coin_pub.eddsa_pub); - TALER_denom_pub_hash (&pk->key, - &h_denom_pub); - TALER_wallet_recoup_refresh_sign (&h_denom_pub, - &bks, - &coin_priv, - &ph->coin_sig); - recoup_obj = GNUNET_JSON_PACK ( - GNUNET_JSON_pack_data_auto ("denom_pub_hash", - &h_denom_pub), - TALER_JSON_pack_denom_sig ("denom_sig", - denom_sig), - TALER_JSON_pack_exchange_withdraw_values ("ewv", - exchange_vals), - GNUNET_JSON_pack_data_auto ("coin_sig", - &ph->coin_sig), - GNUNET_JSON_pack_data_auto ("coin_blind_key_secret", - &bks)); - - if (TALER_DENOMINATION_CS == denom_sig->cipher) - { - struct TALER_CsNonce nonce; - - /* NOTE: this is not elegant, and as per the note in TALER_coin_ev_hash() - it is not strictly clear that the nonce is needed. Best case would be - to find a way to include it more 'naturally' somehow, for example with - the variant union version of bks! */ - TALER_cs_refresh_nonce_derive (rms, - idx, - &nonce); - GNUNET_assert ( - 0 == - json_object_set_new (recoup_obj, - "cs_nonce", - GNUNET_JSON_from_data_auto ( - &nonce))); - } - - { - char pub_str[sizeof (struct TALER_CoinSpendPublicKeyP) * 2]; - char *end; - - end = GNUNET_STRINGS_data_to_string ( - &ph->coin_pub, - sizeof (struct TALER_CoinSpendPublicKeyP), - pub_str, - sizeof (pub_str)); - *end = '\0'; - GNUNET_snprintf (arg_str, - sizeof (arg_str), - "coins/%s/recoup-refresh", - pub_str); - } - - ph->url = TALER_url_join (url, - arg_str, - NULL); - if (NULL == ph->url) - { - json_decref (recoup_obj); - GNUNET_free (ph); - return NULL; - } - eh = TALER_EXCHANGE_curl_easy_get_ (ph->url); - if ( (NULL == eh) || - (GNUNET_OK != - TALER_curl_easy_post (&ph->ctx, - eh, - recoup_obj)) ) - { - GNUNET_break (0); - if (NULL != eh) - curl_easy_cleanup (eh); - json_decref (recoup_obj); - GNUNET_free (ph->url); - GNUNET_free (ph); - return NULL; - } - json_decref (recoup_obj); - GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, - "URL for recoup-refresh: `%s'\n", - ph->url); - ph->keys = TALER_EXCHANGE_keys_incref (keys); - ph->job = GNUNET_CURL_job_add2 (ctx, - eh, - ph->ctx.headers, - &handle_recoup_refresh_finished, - ph); - return ph; -} - - -void -TALER_EXCHANGE_recoup_refresh_cancel ( - struct TALER_EXCHANGE_RecoupRefreshHandle *ph) -{ - if (NULL != ph->job) - { - GNUNET_CURL_job_cancel (ph->job); - ph->job = NULL; - } - GNUNET_free (ph->url); - TALER_curl_easy_post_finished (&ph->ctx); - TALER_EXCHANGE_keys_decref (ph->keys); - GNUNET_free (ph); -} - - -/* end of exchange_api_recoup_refresh.c */ diff --git a/src/lib/exchange_api_refresh_common.c b/src/lib/exchange_api_refresh_common.c deleted file mode 100644 index 0a6665b55..000000000 --- a/src/lib/exchange_api_refresh_common.c +++ /dev/null @@ -1,249 +0,0 @@ -/* - This file is part of TALER - Copyright (C) 2015-2022 Taler Systems SA - - TALER is free software; you can redistribute it and/or modify it under the - terms of the GNU General Public License as published by the Free Software - Foundation; either version 3, or (at your option) any later version. - - TALER is distributed in the hope that it will be useful, but WITHOUT ANY - WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR - A PARTICULAR PURPOSE. See the GNU General Public License for more details. - - You should have received a copy of the GNU General Public License along with - TALER; see the file COPYING. If not, see - -*/ -/** - * @file lib/exchange_api_refresh_common.c - * @brief Serialization logic shared between melt and reveal steps during refreshing - * @author Christian Grothoff - */ -#include "platform.h" -#include "exchange_api_refresh_common.h" - - -void -TALER_EXCHANGE_free_melt_data_ (struct MeltData *md) -{ - for (unsigned int i = 0; i < TALER_CNC_KAPPA; i++) - { - struct TALER_RefreshCoinData *rcds = md->rcd[i]; - - if (NULL == rcds) - continue; - for (unsigned int j = 0; j < md->num_fresh_coins; j++) - TALER_blinded_planchet_free (&rcds[j].blinded_planchet); - GNUNET_free (rcds); - } - TALER_denom_pub_free (&md->melted_coin.pub_key); - TALER_denom_sig_free (&md->melted_coin.sig); - if (NULL != md->fcds) - { - for (unsigned int j = 0; jnum_fresh_coins; j++) - { - struct FreshCoinData *fcd = &md->fcds[j]; - - TALER_denom_pub_free (&fcd->fresh_pk); - for (size_t i = 0; i < TALER_CNC_KAPPA; i++) - { - TALER_age_commitment_proof_free (fcd->age_commitment_proofs[i]); - GNUNET_free (fcd->age_commitment_proofs[i]); - } - } - GNUNET_free (md->fcds); - } - /* Finally, clean up a bit... */ - GNUNET_CRYPTO_zero_keys (md, - sizeof (struct MeltData)); -} - - -enum GNUNET_GenericReturnValue -TALER_EXCHANGE_get_melt_data_ ( - const struct TALER_RefreshMasterSecretP *rms, - const struct TALER_EXCHANGE_RefreshData *rd, - const struct TALER_ExchangeWithdrawValues *alg_values, - struct MeltData *md) -{ - struct TALER_Amount total; - struct TALER_CoinSpendPublicKeyP coin_pub; - struct TALER_CsNonce nonces[rd->fresh_pks_len]; - bool uses_cs = false; - - GNUNET_CRYPTO_eddsa_key_get_public (&rd->melt_priv.eddsa_priv, - &coin_pub.eddsa_pub); - /* build up melt data structure */ - memset (md, - 0, - sizeof (*md)); - md->num_fresh_coins = rd->fresh_pks_len; - md->melted_coin.coin_priv = rd->melt_priv; - md->melted_coin.melt_amount_with_fee = rd->melt_amount; - md->melted_coin.fee_melt = rd->melt_pk.fees.refresh; - md->melted_coin.original_value = rd->melt_pk.value; - md->melted_coin.expire_deposit = rd->melt_pk.expire_deposit; - md->melted_coin.age_commitment_proof = rd->melt_age_commitment_proof; - md->melted_coin.h_age_commitment = rd->melt_h_age_commitment; - - GNUNET_assert (GNUNET_OK == - TALER_amount_set_zero (rd->melt_amount.currency, - &total)); - TALER_denom_pub_deep_copy (&md->melted_coin.pub_key, - &rd->melt_pk.key); - TALER_denom_sig_deep_copy (&md->melted_coin.sig, - &rd->melt_sig); - md->fcds = GNUNET_new_array (md->num_fresh_coins, - struct FreshCoinData); - for (unsigned int j = 0; jfresh_pks_len; j++) - { - struct FreshCoinData *fcd = &md->fcds[j]; - - if (alg_values[j].cipher != rd->fresh_pks[j].key.cipher) - { - GNUNET_break (0); - TALER_EXCHANGE_free_melt_data_ (md); - return GNUNET_SYSERR; - } - if (TALER_DENOMINATION_CS == alg_values[j].cipher) - { - uses_cs = true; - TALER_cs_refresh_nonce_derive ( - rms, - j, - &nonces[j]); - } - TALER_denom_pub_deep_copy (&fcd->fresh_pk, - &rd->fresh_pks[j].key); - if ( (0 > - TALER_amount_add (&total, - &total, - &rd->fresh_pks[j].value)) || - (0 > - TALER_amount_add (&total, - &total, - &rd->fresh_pks[j].fees.withdraw)) ) - { - GNUNET_break (0); - TALER_EXCHANGE_free_melt_data_ (md); - return GNUNET_SYSERR; - } - } - - /* verify that melt_amount is above total cost */ - if (1 == - TALER_amount_cmp (&total, - &rd->melt_amount) ) - { - /* Eh, this operation is more expensive than the - @a melt_amount. This is not OK. */ - GNUNET_break (0); - TALER_EXCHANGE_free_melt_data_ (md); - return GNUNET_SYSERR; - } - - /* build up coins */ - for (unsigned int i = 0; imelt_priv, - i, - &md->transfer_priv[i]); - - GNUNET_CRYPTO_ecdhe_key_get_public ( - &md->transfer_priv[i].ecdhe_priv, - &md->transfer_pub[i].ecdhe_pub); - - TALER_link_derive_transfer_secret (&rd->melt_priv, - &md->transfer_priv[i], - &trans_sec); - - md->rcd[i] = GNUNET_new_array (rd->fresh_pks_len, - struct TALER_RefreshCoinData); - - for (unsigned int j = 0; jfresh_pks_len; j++) - { - struct FreshCoinData *fcd = &md->fcds[j]; - struct TALER_CoinSpendPrivateKeyP *coin_priv = &fcd->coin_priv; - struct TALER_PlanchetMasterSecretP *ps = &fcd->ps[i]; - struct TALER_RefreshCoinData *rcd = &md->rcd[i][j]; - union TALER_DenominationBlindingKeyP *bks = &fcd->bks[i]; - struct TALER_PlanchetDetail pd; - struct TALER_CoinPubHashP c_hash; - struct TALER_AgeCommitmentHash ach; - struct TALER_AgeCommitmentHash *pah = NULL; - - TALER_transfer_secret_to_planchet_secret (&trans_sec, - j, - ps); - - TALER_planchet_setup_coin_priv (ps, - &alg_values[j], - coin_priv); - - TALER_planchet_blinding_secret_create (ps, - &alg_values[j], - bks); - - if (NULL != rd->melt_age_commitment_proof) - { - fcd->age_commitment_proofs[i] = GNUNET_new (struct - TALER_AgeCommitmentProof); - - GNUNET_assert (GNUNET_OK == - TALER_age_commitment_derive ( - md->melted_coin.age_commitment_proof, - &trans_sec.key, - fcd->age_commitment_proofs[i])); - - TALER_age_commitment_hash ( - &fcd->age_commitment_proofs[i]->commitment, - &ach); - pah = &ach; - } - - if (TALER_DENOMINATION_CS == alg_values[j].cipher) - pd.blinded_planchet.details.cs_blinded_planchet.nonce = nonces[j]; - - if (GNUNET_OK != - TALER_planchet_prepare (&fcd->fresh_pk, - &alg_values[j], - bks, - coin_priv, - pah, - &c_hash, - &pd)) - { - GNUNET_break_op (0); - TALER_EXCHANGE_free_melt_data_ (md); - return GNUNET_SYSERR; - } - rcd->blinded_planchet = pd.blinded_planchet; - rcd->dk = &fcd->fresh_pk; - } - } - - /* Finally, compute refresh commitment */ - { - struct TALER_RefreshCommitmentEntry rce[TALER_CNC_KAPPA]; - - for (unsigned int i = 0; itransfer_pub[i]; - rce[i].new_coins = md->rcd[i]; - } - TALER_refresh_get_commitment (&md->rc, - TALER_CNC_KAPPA, - uses_cs - ? rms - : NULL, - rd->fresh_pks_len, - rce, - &coin_pub, - &rd->melt_amount); - } - return GNUNET_OK; -} diff --git a/src/lib/exchange_api_refresh_common.h b/src/lib/exchange_api_refresh_common.h deleted file mode 100644 index 0cb80f17e..000000000 --- a/src/lib/exchange_api_refresh_common.h +++ /dev/null @@ -1,201 +0,0 @@ -/* - This file is part of TALER - Copyright (C) 2015-2022 Taler Systems SA - - TALER is free software; you can redistribute it and/or modify it under the - terms of the GNU General Public License as published by the Free Software - Foundation; either version 3, or (at your option) any later version. - - TALER is distributed in the hope that it will be useful, but WITHOUT ANY - WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR - A PARTICULAR PURPOSE. See the GNU General Public License for more details. - - You should have received a copy of the GNU General Public License along with - TALER; see the file COPYING. If not, see - -*/ -/** - * @file lib/exchange_api_refresh_common.h - * @brief shared (serialization) logic for refresh protocol - * @author Christian Grothoff - */ -#ifndef REFRESH_COMMON_H -#define REFRESH_COMMON_H -#include -#include "taler_json_lib.h" -#include "taler_exchange_service.h" -#include "taler_signatures.h" - - -/** - * Information about a coin we are melting. - */ -struct MeltedCoin -{ - /** - * Private key of the coin. - */ - struct TALER_CoinSpendPrivateKeyP coin_priv; - - /** - * Amount this coin contributes to the melt, including fee. - */ - struct TALER_Amount melt_amount_with_fee; - - /** - * The applicable fee for melting a coin of this denomination - */ - struct TALER_Amount fee_melt; - - /** - * The original value of the coin. - */ - struct TALER_Amount original_value; - - /** - * The original age commitment, its proof and its hash. MUST be NULL if no - * age commitment was set. - */ - const struct TALER_AgeCommitmentProof *age_commitment_proof; - const struct TALER_AgeCommitmentHash *h_age_commitment; - - /** - * Timestamp indicating when coins of this denomination become invalid. - */ - struct GNUNET_TIME_Timestamp expire_deposit; - - /** - * Denomination key of the original coin. - */ - struct TALER_DenominationPublicKey pub_key; - - /** - * Exchange's signature over the coin. - */ - struct TALER_DenominationSignature sig; - -}; - - -/** - * Data we keep for each fresh coin created in the - * melt process. - */ -struct FreshCoinData -{ - /** - * Denomination public key of the coin. - */ - struct TALER_DenominationPublicKey fresh_pk; - - /** - * Array of planchet secrets for the coins, depending - * on the cut-and-choose. - */ - struct TALER_PlanchetMasterSecretP ps[TALER_CNC_KAPPA]; - - /** - * Private key of the coin. - */ - struct TALER_CoinSpendPrivateKeyP coin_priv; - - /** - * Arrays of age commitments and proofs to be created, one for each - * cut-and-choose dimension. NULL if age restriction is not applicable. - */ - struct TALER_AgeCommitmentProof *age_commitment_proofs[TALER_CNC_KAPPA]; - - /** - * Blinding key secrets for the coins, depending on the - * cut-and-choose. - */ - union TALER_DenominationBlindingKeyP bks[TALER_CNC_KAPPA]; - -}; - - -/** - * Melt data in non-serialized format for convenient processing. - */ -struct MeltData -{ - - /** - * Hash over the committed data during refresh operation. - */ - struct TALER_RefreshCommitmentP rc; - - /** - * Information about the melted coin. - */ - struct MeltedCoin melted_coin; - - /** - * Array of length @e num_fresh_coins with information - * about each fresh coin. - */ - struct FreshCoinData *fcds; - - /** - * Transfer secrets, one per cut and choose. - */ - struct TALER_TransferSecretP trans_sec[TALER_CNC_KAPPA]; - - /** - * Transfer private keys for each cut-and-choose dimension. - */ - struct TALER_TransferPrivateKeyP transfer_priv[TALER_CNC_KAPPA]; - - /** - * Transfer public key of this commitment. - */ - struct TALER_TransferPublicKeyP transfer_pub[TALER_CNC_KAPPA]; - - /** - * Transfer secrets, one per cut and choose. - */ - struct TALER_RefreshCommitmentEntry rce[TALER_CNC_KAPPA]; - - /** - * Blinded planchets and denominations of the fresh coins, depending on the cut-and-choose. Array of length - * @e num_fresh_coins. - */ - struct TALER_RefreshCoinData *rcd[TALER_CNC_KAPPA]; - - /** - * Number of coins we are creating - */ - uint16_t num_fresh_coins; - -}; - - -/** - * Compute the melt data from the refresh data and secret. - * - * @param rms secret internals of the refresh-reveal operation - * @param rd refresh data with the characteristics of the operation - * @param alg_values contributions from the exchange into the melt - * @param[out] md where to write the derived melt data - */ -enum GNUNET_GenericReturnValue -TALER_EXCHANGE_get_melt_data_ ( - const struct TALER_RefreshMasterSecretP *rms, - const struct TALER_EXCHANGE_RefreshData *rd, - const struct TALER_ExchangeWithdrawValues *alg_values, - struct MeltData *md); - - -/** - * Free all information associated with a melting session. Note - * that we allow the melting session to be only partially initialized, - * as we use this function also when freeing melt data that was not - * fully initialized. - * - * @param[in] md melting data to release, the pointer itself is NOT - * freed (as it is typically not allocated by itself) - */ -void -TALER_EXCHANGE_free_melt_data_ (struct MeltData *md); - -#endif diff --git a/src/lib/exchange_api_refreshes_reveal.c b/src/lib/exchange_api_refreshes_reveal.c deleted file mode 100644 index 220682992..000000000 --- a/src/lib/exchange_api_refreshes_reveal.c +++ /dev/null @@ -1,531 +0,0 @@ -/* - This file is part of TALER - Copyright (C) 2015-2023 Taler Systems SA - - TALER is free software; you can redistribute it and/or modify it under the - terms of the GNU General Public License as published by the Free Software - Foundation; either version 3, or (at your option) any later version. - - TALER is distributed in the hope that it will be useful, but WITHOUT ANY - WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR - A PARTICULAR PURPOSE. See the GNU General Public License for more details. - - You should have received a copy of the GNU General Public License along with - TALER; see the file COPYING. If not, see - -*/ -/** - * @file lib/exchange_api_refreshes_reveal.c - * @brief Implementation of the /refreshes/$RCH/reveal requests - * @author Christian Grothoff - */ -#include "platform.h" -#include -#include /* just for HTTP status codes */ -#include -#include -#include -#include "taler_json_lib.h" -#include "taler_exchange_service.h" -#include "exchange_api_handle.h" -#include "taler_signatures.h" -#include "exchange_api_curl_defaults.h" -#include "exchange_api_refresh_common.h" - - -/** - * @brief A /refreshes/$RCH/reveal Handle - */ -struct TALER_EXCHANGE_RefreshesRevealHandle -{ - - /** - * The url for this request. - */ - char *url; - - /** - * Context for #TEH_curl_easy_post(). Keeps the data that must - * persist for Curl to make the upload. - */ - struct TALER_CURL_PostContext ctx; - - /** - * Handle for the request. - */ - struct GNUNET_CURL_Job *job; - - /** - * Exchange-contributed values to the operation. - */ - struct TALER_ExchangeWithdrawValues *alg_values; - - /** - * Function to call with the result. - */ - TALER_EXCHANGE_RefreshesRevealCallback reveal_cb; - - /** - * Closure for @e reveal_cb. - */ - void *reveal_cb_cls; - - /** - * Actual information about the melt operation. - */ - struct MeltData md; - - /** - * The index selected by the exchange in cut-and-choose to not be revealed. - */ - uint16_t noreveal_index; - -}; - - -/** - * We got a 200 OK response for the /refreshes/$RCH/reveal operation. Extract - * the coin signatures and return them to the caller. The signatures we get - * from the exchange is for the blinded value. Thus, we first must unblind - * them and then should verify their validity. - * - * If everything checks out, we return the unblinded signatures - * to the application via the callback. - * - * @param rrh operation handle - * @param json reply from the exchange - * @param[out] rcis array of length `num_fresh_coins`, initialized to contain the coin data - * @return #GNUNET_OK on success, #GNUNET_SYSERR on errors - */ -static enum GNUNET_GenericReturnValue -refresh_reveal_ok (struct TALER_EXCHANGE_RefreshesRevealHandle *rrh, - const json_t *json, - struct TALER_EXCHANGE_RevealedCoinInfo *rcis) -{ - const json_t *jsona; - struct GNUNET_JSON_Specification outer_spec[] = { - GNUNET_JSON_spec_array_const ("ev_sigs", - &jsona), - GNUNET_JSON_spec_end () - }; - - if (GNUNET_OK != - GNUNET_JSON_parse (json, - outer_spec, - NULL, NULL)) - { - GNUNET_break_op (0); - return GNUNET_SYSERR; - } - if (rrh->md.num_fresh_coins != json_array_size (jsona)) - { - /* Number of coins generated does not match our expectation */ - GNUNET_break_op (0); - return GNUNET_SYSERR; - } - for (unsigned int i = 0; imd.num_fresh_coins; i++) - { - struct TALER_EXCHANGE_RevealedCoinInfo *rci = &rcis[i]; - const struct FreshCoinData *fcd = &rrh->md.fcds[i]; - const struct TALER_DenominationPublicKey *pk; - json_t *jsonai; - struct TALER_BlindedDenominationSignature blind_sig; - struct TALER_CoinSpendPublicKeyP coin_pub; - struct TALER_CoinPubHashP coin_hash; - struct GNUNET_JSON_Specification spec[] = { - TALER_JSON_spec_blinded_denom_sig ("ev_sig", - &blind_sig), - GNUNET_JSON_spec_end () - }; - struct TALER_FreshCoin coin; - union TALER_DenominationBlindingKeyP bks; - const struct TALER_AgeCommitmentHash *pah = NULL; - - rci->ps = fcd->ps[rrh->noreveal_index]; - rci->bks = fcd->bks[rrh->noreveal_index]; - rci->age_commitment_proof = NULL; - - pk = &fcd->fresh_pk; - jsonai = json_array_get (jsona, i); - - GNUNET_assert (NULL != jsonai); - - if (NULL != rrh->md.melted_coin.age_commitment_proof) - { - rci->age_commitment_proof = - fcd->age_commitment_proofs[rrh->noreveal_index]; - - TALER_age_commitment_hash (&rci->age_commitment_proof->commitment, - &rci->h_age_commitment); - pah = &rci->h_age_commitment; - } - - if (GNUNET_OK != - GNUNET_JSON_parse (jsonai, - spec, - NULL, NULL)) - { - GNUNET_break_op (0); - return GNUNET_SYSERR; - } - - TALER_planchet_setup_coin_priv (&rci->ps, - &rrh->alg_values[i], - &rci->coin_priv); - TALER_planchet_blinding_secret_create (&rci->ps, - &rrh->alg_values[i], - &bks); - /* needed to verify the signature, and we didn't store it earlier, - hence recomputing it here... */ - GNUNET_CRYPTO_eddsa_key_get_public (&rci->coin_priv.eddsa_priv, - &coin_pub.eddsa_pub); - TALER_coin_pub_hash ( - &coin_pub, - pah, - &coin_hash); - if (GNUNET_OK != - TALER_planchet_to_coin ( - pk, - &blind_sig, - &bks, - &rci->coin_priv, - pah, - &coin_hash, - &rrh->alg_values[i], - &coin)) - { - GNUNET_break_op (0); - GNUNET_JSON_parse_free (spec); - return GNUNET_SYSERR; - } - GNUNET_JSON_parse_free (spec); - rci->sig = coin.sig; - } - return GNUNET_OK; -} - - -/** - * Function called when we're done processing the - * HTTP /refreshes/$RCH/reveal request. - * - * @param cls the `struct TALER_EXCHANGE_RefreshHandle` - * @param response_code HTTP response code, 0 on error - * @param response parsed JSON result, NULL on error - */ -static void -handle_refresh_reveal_finished (void *cls, - long response_code, - const void *response) -{ - struct TALER_EXCHANGE_RefreshesRevealHandle *rrh = cls; - const json_t *j = response; - struct TALER_EXCHANGE_RevealResult rr = { - .hr.reply = j, - .hr.http_status = (unsigned int) response_code - }; - - rrh->job = NULL; - switch (response_code) - { - case 0: - rr.hr.ec = TALER_EC_GENERIC_INVALID_RESPONSE; - break; - case MHD_HTTP_OK: - { - struct TALER_EXCHANGE_RevealedCoinInfo rcis[rrh->md.num_fresh_coins]; - enum GNUNET_GenericReturnValue ret; - - memset (rcis, - 0, - sizeof (rcis)); - ret = refresh_reveal_ok (rrh, - j, - rcis); - if (GNUNET_OK != ret) - { - rr.hr.http_status = 0; - rr.hr.ec = TALER_EC_GENERIC_REPLY_MALFORMED; - break; - } - else - { - GNUNET_assert (rrh->noreveal_index < TALER_CNC_KAPPA); - rr.details.ok.num_coins = rrh->md.num_fresh_coins; - rr.details.ok.coins = rcis; - rrh->reveal_cb (rrh->reveal_cb_cls, - &rr); - rrh->reveal_cb = NULL; - } - for (unsigned int i = 0; imd.num_fresh_coins; i++) - { - TALER_denom_sig_free (&rcis[i].sig); - TALER_age_commitment_proof_free (rcis[i].age_commitment_proof); - } - TALER_EXCHANGE_refreshes_reveal_cancel (rrh); - return; - } - case MHD_HTTP_BAD_REQUEST: - /* This should never happen, either us or the exchange is buggy - (or API version conflict); just pass JSON reply to the application */ - rr.hr.ec = TALER_JSON_get_error_code (j); - rr.hr.hint = TALER_JSON_get_error_hint (j); - break; - case MHD_HTTP_CONFLICT: - /* Nothing really to verify, exchange says our reveal is inconsistent - with our commitment, so either side is buggy; we - should pass the JSON reply to the application */ - rr.hr.ec = TALER_JSON_get_error_code (j); - rr.hr.hint = TALER_JSON_get_error_hint (j); - break; - case MHD_HTTP_GONE: - /* Server claims key expired or has been revoked */ - rr.hr.ec = TALER_JSON_get_error_code (j); - rr.hr.hint = TALER_JSON_get_error_hint (j); - break; - case MHD_HTTP_INTERNAL_SERVER_ERROR: - /* Server had an internal issue; we should retry, but this API - leaves this to the application */ - rr.hr.ec = TALER_JSON_get_error_code (j); - rr.hr.hint = TALER_JSON_get_error_hint (j); - break; - default: - /* unexpected response code */ - GNUNET_break_op (0); - rr.hr.ec = TALER_JSON_get_error_code (j); - rr.hr.hint = TALER_JSON_get_error_hint (j); - GNUNET_log (GNUNET_ERROR_TYPE_ERROR, - "Unexpected response code %u/%d for exchange refreshes reveal\n", - (unsigned int) response_code, - (int) rr.hr.ec); - break; - } - if (NULL != rrh->reveal_cb) - rrh->reveal_cb (rrh->reveal_cb_cls, - &rr); - TALER_EXCHANGE_refreshes_reveal_cancel (rrh); -} - - -struct TALER_EXCHANGE_RefreshesRevealHandle * -TALER_EXCHANGE_refreshes_reveal ( - struct GNUNET_CURL_Context *ctx, - const char *url, - const struct TALER_RefreshMasterSecretP *rms, - const struct TALER_EXCHANGE_RefreshData *rd, - unsigned int num_coins, - const struct TALER_ExchangeWithdrawValues alg_values[static num_coins], - uint32_t noreveal_index, - TALER_EXCHANGE_RefreshesRevealCallback reveal_cb, - void *reveal_cb_cls) -{ - struct TALER_EXCHANGE_RefreshesRevealHandle *rrh; - json_t *transfer_privs; - json_t *new_denoms_h; - json_t *coin_evs; - json_t *reveal_obj; - json_t *link_sigs; - json_t *old_age_commitment = NULL; - CURL *eh; - struct MeltData md; - char arg_str[sizeof (struct TALER_RefreshCommitmentP) * 2 + 32]; - bool send_rms = false; - - GNUNET_assert (num_coins == rd->fresh_pks_len); - if (noreveal_index >= TALER_CNC_KAPPA) - { - /* We check this here, as it would be really bad to below just - disclose all the transfer keys. Note that this error should - have been caught way earlier when the exchange replied, but maybe - we had some internal corruption that changed the value... */ - GNUNET_break (0); - return NULL; - } - if (GNUNET_OK != - TALER_EXCHANGE_get_melt_data_ (rms, - rd, - alg_values, - &md)) - { - GNUNET_break (0); - return NULL; - } - - /* now new_denoms */ - GNUNET_assert (NULL != (new_denoms_h = json_array ())); - GNUNET_assert (NULL != (coin_evs = json_array ())); - GNUNET_assert (NULL != (link_sigs = json_array ())); - for (unsigned int i = 0; iblinded_planchet)))); - { - struct TALER_CoinSpendSignatureP link_sig; - struct TALER_BlindedCoinHashP bch; - - TALER_coin_ev_hash (&rcd->blinded_planchet, - &denom_hash, - &bch); - TALER_wallet_link_sign ( - &denom_hash, - &md.transfer_pub[noreveal_index], - &bch, - &md.melted_coin.coin_priv, - &link_sig); - GNUNET_assert (0 == - json_array_append_new ( - link_sigs, - GNUNET_JSON_from_data_auto (&link_sig))); - } - } - - /* build array of transfer private keys */ - GNUNET_assert (NULL != (transfer_privs = json_array ())); - for (unsigned int j = 0; jmelt_age_commitment_proof) - { - GNUNET_assert (NULL != rd->melt_h_age_commitment); - GNUNET_assert (NULL != (old_age_commitment = json_array ())); - - for (size_t i = 0; i < rd->melt_age_commitment_proof->commitment.num; i++) - { - enum GNUNET_GenericReturnValue ret; - ret = json_array_append_new ( - old_age_commitment, - GNUNET_JSON_from_data_auto ( - &rd->melt_age_commitment_proof->commitment.keys[i])); - GNUNET_assert (0 == ret); - } - } - - /* build main JSON request */ - reveal_obj = GNUNET_JSON_PACK ( - GNUNET_JSON_pack_data_auto ("transfer_pub", - &md.transfer_pub[noreveal_index]), - GNUNET_JSON_pack_allow_null ( - send_rms - ? GNUNET_JSON_pack_data_auto ("rms", - rms) - : GNUNET_JSON_pack_string ("rms", - NULL)), - GNUNET_JSON_pack_allow_null ( - GNUNET_JSON_pack_array_steal ("old_age_commitment", - old_age_commitment)), - GNUNET_JSON_pack_array_steal ("transfer_privs", - transfer_privs), - GNUNET_JSON_pack_array_steal ("link_sigs", - link_sigs), - GNUNET_JSON_pack_array_steal ("new_denoms_h", - new_denoms_h), - GNUNET_JSON_pack_array_steal ("coin_evs", - coin_evs)); - { - char pub_str[sizeof (struct TALER_RefreshCommitmentP) * 2]; - char *end; - - end = GNUNET_STRINGS_data_to_string (&md.rc, - sizeof (md.rc), - pub_str, - sizeof (pub_str)); - *end = '\0'; - GNUNET_snprintf (arg_str, - sizeof (arg_str), - "refreshes/%s/reveal", - pub_str); - } - /* finally, we can actually issue the request */ - rrh = GNUNET_new (struct TALER_EXCHANGE_RefreshesRevealHandle); - rrh->noreveal_index = noreveal_index; - rrh->reveal_cb = reveal_cb; - rrh->reveal_cb_cls = reveal_cb_cls; - rrh->md = md; - rrh->alg_values - = GNUNET_memdup (alg_values, - md.num_fresh_coins - * sizeof (struct TALER_ExchangeWithdrawValues)); - rrh->url = TALER_url_join (url, - arg_str, - NULL); - if (NULL == rrh->url) - { - json_decref (reveal_obj); - TALER_EXCHANGE_free_melt_data_ (&md); - GNUNET_free (rrh->alg_values); - GNUNET_free (rrh); - return NULL; - } - - eh = TALER_EXCHANGE_curl_easy_get_ (rrh->url); - if ( (NULL == eh) || - (GNUNET_OK != - TALER_curl_easy_post (&rrh->ctx, - eh, - reveal_obj)) ) - { - GNUNET_break (0); - if (NULL != eh) - curl_easy_cleanup (eh); - json_decref (reveal_obj); - TALER_EXCHANGE_free_melt_data_ (&md); - GNUNET_free (rrh->alg_values); - GNUNET_free (rrh->url); - GNUNET_free (rrh); - return NULL; - } - json_decref (reveal_obj); - rrh->job = GNUNET_CURL_job_add2 (ctx, - eh, - rrh->ctx.headers, - &handle_refresh_reveal_finished, - rrh); - return rrh; -} - - -void -TALER_EXCHANGE_refreshes_reveal_cancel ( - struct TALER_EXCHANGE_RefreshesRevealHandle *rrh) -{ - if (NULL != rrh->job) - { - GNUNET_CURL_job_cancel (rrh->job); - rrh->job = NULL; - } - GNUNET_free (rrh->alg_values); - GNUNET_free (rrh->url); - TALER_curl_easy_post_finished (&rrh->ctx); - TALER_EXCHANGE_free_melt_data_ (&rrh->md); - GNUNET_free (rrh); -} - - -/* exchange_api_refreshes_reveal.c */ diff --git a/src/lib/exchange_api_refund.c b/src/lib/exchange_api_refund.c deleted file mode 100644 index 7401bfe4f..000000000 --- a/src/lib/exchange_api_refund.c +++ /dev/null @@ -1,480 +0,0 @@ -/* - This file is part of TALER - Copyright (C) 2014-2023 Taler Systems SA - - TALER is free software; you can redistribute it and/or modify it under the - terms of the GNU General Public License as published by the Free Software - Foundation; either version 3, or (at your option) any later version. - - TALER is distributed in the hope that it will be useful, but WITHOUT ANY - WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR - A PARTICULAR PURPOSE. See the GNU General Public License for more details. - - You should have received a copy of the GNU General Public License along with - TALER; see the file COPYING. If not, see - -*/ -/** - * @file lib/exchange_api_refund.c - * @brief Implementation of the /refund request of the exchange's HTTP API - * @author Christian Grothoff - */ -#include "platform.h" -#include -#include /* just for HTTP status codes */ -#include -#include -#include -#include "taler_json_lib.h" -#include "taler_exchange_service.h" -#include "exchange_api_handle.h" -#include "taler_signatures.h" -#include "exchange_api_curl_defaults.h" - - -/** - * @brief A Refund Handle - */ -struct TALER_EXCHANGE_RefundHandle -{ - - /** - * The keys of the exchange this request handle will use - */ - struct TALER_EXCHANGE_Keys *keys; - - /** - * The url for this request. - */ - char *url; - - /** - * Context for #TEH_curl_easy_post(). Keeps the data that must - * persist for Curl to make the upload. - */ - struct TALER_CURL_PostContext ctx; - - /** - * Handle for the request. - */ - struct GNUNET_CURL_Job *job; - - /** - * Function to call with the result. - */ - TALER_EXCHANGE_RefundCallback cb; - - /** - * Closure for @a cb. - */ - void *cb_cls; - - /** - * Hash over the proposal data to identify the contract - * which is being refunded. - */ - struct TALER_PrivateContractHashP h_contract_terms; - - /** - * The coin's public key. This is the value that must have been - * signed (blindly) by the Exchange. - */ - struct TALER_CoinSpendPublicKeyP coin_pub; - - /** - * The Merchant's public key. Allows the merchant to later refund - * the transaction or to inquire about the wire transfer identifier. - */ - struct TALER_MerchantPublicKeyP merchant; - - /** - * Merchant-generated transaction ID for the refund. - */ - uint64_t rtransaction_id; - - /** - * Amount to be refunded, including refund fee charged by the - * exchange to the customer. - */ - struct TALER_Amount refund_amount; - -}; - - -/** - * Verify that the signature on the "200 OK" response - * from the exchange is valid. - * - * @param[in,out] rh refund handle (refund fee added) - * @param json json reply with the signature - * @param[out] exchange_pub set to the exchange's public key - * @param[out] exchange_sig set to the exchange's signature - * @return #GNUNET_OK if the signature is valid, #GNUNET_SYSERR if not - */ -static enum GNUNET_GenericReturnValue -verify_refund_signature_ok (struct TALER_EXCHANGE_RefundHandle *rh, - const json_t *json, - struct TALER_ExchangePublicKeyP *exchange_pub, - struct TALER_ExchangeSignatureP *exchange_sig) -{ - struct GNUNET_JSON_Specification spec[] = { - GNUNET_JSON_spec_fixed_auto ("exchange_sig", - exchange_sig), - GNUNET_JSON_spec_fixed_auto ("exchange_pub", - exchange_pub), - GNUNET_JSON_spec_end () - }; - - if (GNUNET_OK != - GNUNET_JSON_parse (json, - spec, - NULL, NULL)) - { - GNUNET_break_op (0); - return GNUNET_SYSERR; - } - if (GNUNET_OK != - TALER_EXCHANGE_test_signing_key (rh->keys, - exchange_pub)) - { - GNUNET_break_op (0); - return GNUNET_SYSERR; - } - if (GNUNET_OK != - TALER_exchange_online_refund_confirmation_verify ( - &rh->h_contract_terms, - &rh->coin_pub, - &rh->merchant, - rh->rtransaction_id, - &rh->refund_amount, - exchange_pub, - exchange_sig)) - { - GNUNET_break_op (0); - return GNUNET_SYSERR; - } - return GNUNET_OK; -} - - -/** - * Verify that the information on the "412 Dependency Failed" response - * from the exchange is valid and indeed shows that there is a refund - * transaction ID reuse going on. - * - * @param[in,out] rh refund handle (refund fee added) - * @param json json reply with the signature - * @return #GNUNET_OK if the signature is valid, #GNUNET_SYSERR if not - */ -static enum GNUNET_GenericReturnValue -verify_failed_dependency_ok (struct TALER_EXCHANGE_RefundHandle *rh, - const json_t *json) -{ - const json_t *h; - json_t *e; - struct GNUNET_JSON_Specification spec[] = { - GNUNET_JSON_spec_array_const ("history", - &h), - GNUNET_JSON_spec_end () - }; - - if (GNUNET_OK != - GNUNET_JSON_parse (json, - spec, - NULL, NULL)) - { - GNUNET_break_op (0); - return GNUNET_SYSERR; - } - if (1 != json_array_size (h)) - { - GNUNET_break_op (0); - return GNUNET_SYSERR; - } - e = json_array_get (h, 0); - { - struct TALER_Amount amount; - const char *type; - struct TALER_MerchantSignatureP sig; - struct TALER_Amount refund_fee; - struct TALER_PrivateContractHashP h_contract_terms; - uint64_t rtransaction_id; - struct TALER_MerchantPublicKeyP merchant_pub; - struct GNUNET_JSON_Specification ispec[] = { - TALER_JSON_spec_amount_any ("amount", - &amount), - GNUNET_JSON_spec_string ("type", - &type), - TALER_JSON_spec_amount_any ("refund_fee", - &refund_fee), - GNUNET_JSON_spec_fixed_auto ("merchant_sig", - &sig), - GNUNET_JSON_spec_fixed_auto ("h_contract_terms", - &h_contract_terms), - GNUNET_JSON_spec_fixed_auto ("merchant_pub", - &merchant_pub), - GNUNET_JSON_spec_uint64 ("rtransaction_id", - &rtransaction_id), - GNUNET_JSON_spec_end () - }; - - if (GNUNET_OK != - GNUNET_JSON_parse (e, - ispec, - NULL, NULL)) - { - GNUNET_break_op (0); - return GNUNET_SYSERR; - } - if (GNUNET_OK != - TALER_merchant_refund_verify (&rh->coin_pub, - &h_contract_terms, - rtransaction_id, - &amount, - &merchant_pub, - &sig)) - { - GNUNET_break_op (0); - return GNUNET_SYSERR; - } - if ( (rtransaction_id != rh->rtransaction_id) || - (0 != GNUNET_memcmp (&rh->h_contract_terms, - &h_contract_terms)) || - (0 != GNUNET_memcmp (&rh->merchant, - &merchant_pub)) || - (0 == TALER_amount_cmp (&rh->refund_amount, - &amount)) ) - { - GNUNET_break_op (0); - return GNUNET_SYSERR; - } - } - return GNUNET_OK; -} - - -/** - * Function called when we're done processing the - * HTTP /refund request. - * - * @param cls the `struct TALER_EXCHANGE_RefundHandle` - * @param response_code HTTP response code, 0 on error - * @param response parsed JSON result, NULL on error - */ -static void -handle_refund_finished (void *cls, - long response_code, - const void *response) -{ - struct TALER_EXCHANGE_RefundHandle *rh = cls; - const json_t *j = response; - struct TALER_EXCHANGE_RefundResponse rr = { - .hr.reply = j, - .hr.http_status = (unsigned int) response_code - }; - - rh->job = NULL; - switch (response_code) - { - case 0: - rr.hr.ec = TALER_EC_GENERIC_INVALID_RESPONSE; - break; - case MHD_HTTP_OK: - if (GNUNET_OK != - verify_refund_signature_ok (rh, - j, - &rr.details.ok.exchange_pub, - &rr.details.ok.exchange_sig)) - { - GNUNET_break_op (0); - rr.hr.http_status = 0; - rr.hr.ec = TALER_EC_EXCHANGE_REFUND_INVALID_SIGNATURE_BY_EXCHANGE; - } - break; - case MHD_HTTP_BAD_REQUEST: - /* This should never happen, either us or the exchange is buggy - (or API version conflict); also can happen if the currency - differs (which we should obviously never support). - Just pass JSON reply to the application */ - rr.hr.ec = TALER_JSON_get_error_code (j); - rr.hr.hint = TALER_JSON_get_error_hint (j); - break; - case MHD_HTTP_FORBIDDEN: - /* Nothing really to verify, exchange says one of the signatures is - invalid; as we checked them, this should never happen, we - should pass the JSON reply to the application */ - rr.hr.ec = TALER_JSON_get_error_code (j); - rr.hr.hint = TALER_JSON_get_error_hint (j); - break; - case MHD_HTTP_NOT_FOUND: - /* Nothing really to verify, this should never - happen, we should pass the JSON reply to the application */ - rr.hr.ec = TALER_JSON_get_error_code (j); - rr.hr.hint = TALER_JSON_get_error_hint (j); - break; - case MHD_HTTP_CONFLICT: - /* Requested total refunds exceed deposited amount */ - rr.hr.ec = TALER_JSON_get_error_code (j); - rr.hr.hint = TALER_JSON_get_error_hint (j); - break; - case MHD_HTTP_GONE: - /* Kind of normal: the money was already sent to the merchant - (it was too late for the refund). */ - rr.hr.ec = TALER_JSON_get_error_code (j); - rr.hr.hint = TALER_JSON_get_error_hint (j); - break; - case MHD_HTTP_PRECONDITION_FAILED: - if (GNUNET_OK != - verify_failed_dependency_ok (rh, - j)) - { - GNUNET_break (0); - rr.hr.http_status = 0; - rr.hr.ec = TALER_EC_EXCHANGE_REFUND_INVALID_FAILURE_PROOF_BY_EXCHANGE; - rr.hr.hint = "failed precondition proof returned by exchange is invalid"; - break; - } - /* Two different refund requests were made about the same deposit, but - carrying identical refund transaction ids. */ - rr.hr.ec = TALER_JSON_get_error_code (j); - rr.hr.hint = TALER_JSON_get_error_hint (j); - break; - case MHD_HTTP_INTERNAL_SERVER_ERROR: - /* Server had an internal issue; we should retry, but this API - leaves this to the application */ - rr.hr.ec = TALER_JSON_get_error_code (j); - rr.hr.hint = TALER_JSON_get_error_hint (j); - break; - default: - /* unexpected response code */ - GNUNET_break_op (0); - rr.hr.ec = TALER_JSON_get_error_code (j); - rr.hr.hint = TALER_JSON_get_error_hint (j); - GNUNET_log (GNUNET_ERROR_TYPE_ERROR, - "Unexpected response code %u/%d for exchange refund\n", - (unsigned int) response_code, - rr.hr.ec); - break; - } - rh->cb (rh->cb_cls, - &rr); - TALER_EXCHANGE_refund_cancel (rh); -} - - -struct TALER_EXCHANGE_RefundHandle * -TALER_EXCHANGE_refund ( - struct GNUNET_CURL_Context *ctx, - const char *url, - struct TALER_EXCHANGE_Keys *keys, - const struct TALER_Amount *amount, - const struct TALER_PrivateContractHashP *h_contract_terms, - const struct TALER_CoinSpendPublicKeyP *coin_pub, - uint64_t rtransaction_id, - const struct TALER_MerchantPrivateKeyP *merchant_priv, - TALER_EXCHANGE_RefundCallback cb, - void *cb_cls) -{ - struct TALER_MerchantPublicKeyP merchant_pub; - struct TALER_MerchantSignatureP merchant_sig; - struct TALER_EXCHANGE_RefundHandle *rh; - json_t *refund_obj; - CURL *eh; - char arg_str[sizeof (struct TALER_CoinSpendPublicKeyP) * 2 + 32]; - - GNUNET_CRYPTO_eddsa_key_get_public (&merchant_priv->eddsa_priv, - &merchant_pub.eddsa_pub); - TALER_merchant_refund_sign (coin_pub, - h_contract_terms, - rtransaction_id, - amount, - merchant_priv, - &merchant_sig); - { - char pub_str[sizeof (struct TALER_CoinSpendPublicKeyP) * 2]; - char *end; - - end = GNUNET_STRINGS_data_to_string ( - coin_pub, - sizeof (struct TALER_CoinSpendPublicKeyP), - pub_str, - sizeof (pub_str)); - *end = '\0'; - GNUNET_snprintf (arg_str, - sizeof (arg_str), - "coins/%s/refund", - pub_str); - } - refund_obj = GNUNET_JSON_PACK ( - TALER_JSON_pack_amount ("refund_amount", - amount), - GNUNET_JSON_pack_data_auto ("h_contract_terms", - h_contract_terms), - GNUNET_JSON_pack_uint64 ("rtransaction_id", - rtransaction_id), - GNUNET_JSON_pack_data_auto ("merchant_pub", - &merchant_pub), - GNUNET_JSON_pack_data_auto ("merchant_sig", - &merchant_sig)); - rh = GNUNET_new (struct TALER_EXCHANGE_RefundHandle); - rh->cb = cb; - rh->cb_cls = cb_cls; - rh->url = TALER_url_join (url, - arg_str, - NULL); - if (NULL == rh->url) - { - json_decref (refund_obj); - GNUNET_free (rh); - return NULL; - } - rh->h_contract_terms = *h_contract_terms; - rh->coin_pub = *coin_pub; - rh->merchant = merchant_pub; - rh->rtransaction_id = rtransaction_id; - rh->refund_amount = *amount; - eh = TALER_EXCHANGE_curl_easy_get_ (rh->url); - if ( (NULL == eh) || - (GNUNET_OK != - TALER_curl_easy_post (&rh->ctx, - eh, - refund_obj)) ) - { - GNUNET_break (0); - if (NULL != eh) - curl_easy_cleanup (eh); - json_decref (refund_obj); - GNUNET_free (rh->url); - GNUNET_free (rh); - return NULL; - } - json_decref (refund_obj); - GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, - "URL for refund: `%s'\n", - rh->url); - rh->keys = TALER_EXCHANGE_keys_incref (keys); - rh->job = GNUNET_CURL_job_add2 (ctx, - eh, - rh->ctx.headers, - &handle_refund_finished, - rh); - return rh; -} - - -void -TALER_EXCHANGE_refund_cancel (struct TALER_EXCHANGE_RefundHandle *refund) -{ - if (NULL != refund->job) - { - GNUNET_CURL_job_cancel (refund->job); - refund->job = NULL; - } - GNUNET_free (refund->url); - TALER_curl_easy_post_finished (&refund->ctx); - TALER_EXCHANGE_keys_decref (refund->keys); - GNUNET_free (refund); -} - - -/* end of exchange_api_refund.c */ diff --git a/src/lib/exchange_api_stefan.c b/src/lib/exchange_api_stefan.c deleted file mode 100644 index c3576cd73..000000000 --- a/src/lib/exchange_api_stefan.c +++ /dev/null @@ -1,320 +0,0 @@ -/* - This file is part of TALER - Copyright (C) 2023 Taler Systems SA - - TALER is free software; you can redistribute it and/or modify it under the - terms of the GNU General Public License as published by the Free Software - Foundation; either version 3, or (at your option) any later version. - - TALER is distributed in the hope that it will be useful, but WITHOUT ANY - WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR - A PARTICULAR PURPOSE. See the GNU General Public License for more details. - - You should have received a copy of the GNU General Public License along with - TALER; see the file COPYING. If not, see - -*/ -/** - * @file lib/exchange_api_stefan.c - * @brief calculations on the STEFAN curve - * @author Christian Grothoff - */ -#include "platform.h" -#include "taler_json_lib.h" -#include -#include "exchange_api_handle.h" -#include - - -/** - * Determine smallest denomination in @a keys. - * - * @param keys exchange response to evaluate - * @return NULL on error (no denominations) - */ -static const struct TALER_Amount * -get_unit (const struct TALER_EXCHANGE_Keys *keys) -{ - const struct TALER_Amount *min = NULL; - - for (unsigned int i = 0; inum_denom_keys; i++) - { - const struct TALER_EXCHANGE_DenomPublicKey *dk - = &keys->denom_keys[i]; - - if ( (NULL == min) || - (1 == TALER_amount_cmp (min, - /* > */ - &dk->value)) ) - min = &dk->value; - } - GNUNET_break (NULL != min); - return min; -} - - -/** - * Convert amount to double for STEFAN curve evaluation. - * - * @param a input amount - * @return (rounded) amount as a double - */ -static double -amount_to_double (const struct TALER_Amount *a) -{ - double d = (double) a->value; - - d += a->fraction / ((double) TALER_AMOUNT_FRAC_BASE); - return d; -} - - -/** - * Convert double to amount for STEFAN curve evaluation. - * - * @param dv input amount - * @param currency deisred currency - * @param[out] rval (rounded) amount as a double - */ -static void -double_to_amount (double dv, - const char *currency, - struct TALER_Amount *rval) -{ - double rem; - - GNUNET_assert (GNUNET_OK == - TALER_amount_set_zero (currency, - rval)); - rval->value = floorl (dv); - rem = dv - ((double) rval->value); - if (rem < 0.0) - rem = 0.0; - rem *= TALER_AMOUNT_FRAC_BASE; - rval->fraction = floorl (rem); - if (rval->fraction >= TALER_AMOUNT_FRAC_BASE) - { - /* Strange, multiplication overflowed our range, - round up value instead */ - rval->fraction = 0; - rval->value += 1; - } -} - - -enum GNUNET_GenericReturnValue -TALER_EXCHANGE_keys_stefan_b2n ( - const struct TALER_EXCHANGE_Keys *keys, - const struct TALER_Amount *brut, - struct TALER_Amount *net) -{ - const struct TALER_Amount *min; - double log_d = amount_to_double (&keys->stefan_log); - double lin_d = keys->stefan_lin; - double abs_d = amount_to_double (&keys->stefan_abs); - double bru_d = amount_to_double (brut); - double min_d; - double fee_d; - double net_d; - - if (TALER_amount_is_zero (brut)) - { - *net = *brut; - return GNUNET_NO; - } - min = get_unit (keys); - if (NULL == min) - return GNUNET_SYSERR; - if (1.0f <= keys->stefan_lin) - { - /* This cannot work, linear STEFAN fee estimate always - exceed any gross amount. */ - GNUNET_break_op (0); - return GNUNET_SYSERR; - } - min_d = amount_to_double (min); - fee_d = abs_d - + log_d * log2 (bru_d / min_d) - + lin_d * bru_d; - if (fee_d > bru_d) - { - GNUNET_assert (GNUNET_OK == - TALER_amount_set_zero (brut->currency, - net)); - return GNUNET_NO; - } - net_d = bru_d - fee_d; - double_to_amount (net_d, - brut->currency, - net); - return GNUNET_OK; -} - - -/** - * Our function - * f(x) := ne + ab + lo * log2(x/mi) + li * x - x - * for #newton(). - */ -static double -eval_f (double mi, - double ab, - double lo, - double li, - double ne, - double x) -{ - return ne + ab + lo * log2 (x / mi) + li * x - x; -} - - -/** - * Our function - * f'(x) := lo / log(2) / x + li - 1 - * for #newton(). - */ -static double -eval_fp (double mi, - double lo, - double li, - double ne, - double x) -{ - return lo / log (2) / x + li - 1; -} - - -/** - * Use Newton's method to find x where f(x)=0. - * - * @return x where "eval_f(x)==0". - */ -static double -newton (double mi, - double ab, - double lo, - double li, - double ne) -{ - const double eps = 0.00000001; /* max error allowed */ - double min_ab = ne + ab; /* result cannot be smaller than this! */ - /* compute lower bounds by various heuristics */ - double min_ab_li = min_ab + min_ab * li; - double min_ab_li_lo = min_ab_li + log2 (min_ab_li / mi) * lo; - double min_ab_lo = min_ab + log2 (min_ab / mi) * lo; - double min_ab_lo_li = min_ab_lo + min_ab_lo * li; - /* take global lower bound */ - double x_min = GNUNET_MAX (min_ab_lo_li, - min_ab_li_lo); - double x = x_min; /* use lower bound as starting point */ - - /* Objective: invert - ne := br - ab - lo * log2 (br/mi) - li * br - to find 'br'. - Method: use Newton's method to find root of: - f(x) := ne + ab + lo * log2 (x/mi) + li * x - x - using also - f'(x) := lo / log(2) / x + li - 1 - */ - /* Loop to abort in case of divergence; - 100 is already very high, 2-4 is normal! */ - for (unsigned int i = 0; i<100; i++) - { - double fx = eval_f (mi, ab, lo, li, ne, x); - double fxp = eval_fp (mi, lo, li, ne, x); - double x_new = x - fx / fxp; - - if (fabs (x - x_new) <= eps) - { - GNUNET_log (GNUNET_ERROR_TYPE_INFO, - "Needed %u rounds from %f to result BRUT %f => NET: %f\n", - i, - x_min, - x_new, - x_new - ab - li * x_new - lo * log2 (x / mi)); - return x_new; - } - if (x_new < x_min) - { - GNUNET_log (GNUNET_ERROR_TYPE_WARNING, - "Divergence, obtained very bad estimate %f after %u rounds!\n", - x_new, - i); - return x_min; - } - x = x_new; - } - GNUNET_log (GNUNET_ERROR_TYPE_WARNING, - "Slow convergence, returning bad estimate %f!\n", - x); - return x; -} - - -enum GNUNET_GenericReturnValue -TALER_EXCHANGE_keys_stefan_n2b ( - const struct TALER_EXCHANGE_Keys *keys, - const struct TALER_Amount *net, - struct TALER_Amount *brut) -{ - const struct TALER_Amount *min; - double lin_d = keys->stefan_lin; - double log_d = amount_to_double (&keys->stefan_log); - double abs_d = amount_to_double (&keys->stefan_abs); - double net_d = amount_to_double (net); - double min_d; - double brut_d; - - if (TALER_amount_is_zero (net)) - { - *brut = *net; - return GNUNET_NO; - } - min = get_unit (keys); - if (NULL == min) - return GNUNET_SYSERR; - if (1.0f <= keys->stefan_lin) - { - /* This cannot work, linear STEFAN fee estimate always - exceed any gross amount. */ - GNUNET_break_op (0); - return GNUNET_SYSERR; - } - min_d = amount_to_double (min); - brut_d = newton (min_d, - abs_d, - log_d, - lin_d, - net_d); - double_to_amount (brut_d, - net->currency, - brut); - return GNUNET_OK; -} - - -void -TALER_EXCHANGE_keys_stefan_round ( - const struct TALER_EXCHANGE_Keys *keys, - struct TALER_Amount *val) -{ - const struct TALER_Amount *min; - uint32_t mod = 1; - uint32_t frac; - uint32_t rst; - - min = get_unit (keys); - if (NULL == min) - return; - frac = min->fraction; - while (0 == frac % 10) - { - mod *= 10; - frac /= 10; - } - rst = val->fraction % mod; - if (rst < mod / 2) - val->fraction -= rst; - else - val->fraction += mod - rst; -} diff --git a/src/lib/test_stefan.c b/src/lib/test_stefan.c deleted file mode 100644 index 838cca769..000000000 --- a/src/lib/test_stefan.c +++ /dev/null @@ -1,206 +0,0 @@ -/* - This file is part of TALER - Copyright (C) 2023 Taler Systems SA - - TALER is free software; you can redistribute it and/or modify it under the - terms of the GNU General Public License as published by the Free Software - Foundation; either version 3, or (at your option) any later version. - - TALER is distributed in the hope that it will be useful, but WITHOUT ANY - WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR - A PARTICULAR PURPOSE. See the GNU General Public License for more details. - - You should have received a copy of the GNU General Public License along with - TALER; see the file COPYING. If not, see - -*/ -/** - * @file lib/test_stefan.c - * @brief test calculations on the STEFAN curve - * @author Christian Grothoff - */ -#include "platform.h" -#include "taler_json_lib.h" -#include -#include "exchange_api_handle.h" - - -/** - * Check if @a a and @a b are numerically close. - * - * @param a an amount - * @param b an amount - * @return true if both values are quite close - */ -static bool -amount_close (const struct TALER_Amount *a, - const struct TALER_Amount *b) -{ - struct TALER_Amount delta; - - switch (TALER_amount_cmp (a, - b)) - { - case -1: /* a < b */ - GNUNET_assert (0 < - TALER_amount_subtract (&delta, - b, - a)); - break; - case 0: - /* perfect */ - return true; - case 1: /* a > b */ - GNUNET_assert (0 < - TALER_amount_subtract (&delta, - a, - b)); - break; - } - GNUNET_log (GNUNET_ERROR_TYPE_INFO, - "Rounding error is %s\n", - TALER_amount2s (&delta)); - if (delta.value > 0) - { - GNUNET_break (0); - return false; - } - if (delta.fraction > 5000) - { - GNUNET_break (0); - return false; - } - return true; /* let's consider this a rounding error */ -} - - -int -main (int argc, - char **argv) -{ - struct TALER_EXCHANGE_DenomPublicKey dk; - struct TALER_EXCHANGE_Keys keys = { - .denom_keys = &dk, - .num_denom_keys = 1 - }; - struct TALER_Amount brut; - struct TALER_Amount net; - - (void) argc; - (void) argv; - GNUNET_log_setup ("test-stefan", - "INFO", - NULL); - GNUNET_assert (GNUNET_OK == - TALER_string_to_amount ("MAGIC:0.13", - &dk.value)); - GNUNET_assert (GNUNET_OK == - TALER_string_to_amount ("MAGIC:1", - &keys.stefan_abs)); - GNUNET_assert (GNUNET_OK == - TALER_string_to_amount ("MAGIC:0.13", - &keys.stefan_log)); - keys.stefan_lin = 1.15; - GNUNET_assert (GNUNET_OK == - TALER_string_to_amount ("MAGIC:4", - &brut)); - GNUNET_log_skip (1, - GNUNET_NO); - GNUNET_assert (GNUNET_SYSERR == - TALER_EXCHANGE_keys_stefan_b2n (&keys, - &brut, - &net)); - GNUNET_assert (GNUNET_OK == - TALER_string_to_amount ("MAGIC:4", - &net)); - GNUNET_log_skip (1, - GNUNET_NO); - GNUNET_assert (GNUNET_SYSERR == - TALER_EXCHANGE_keys_stefan_n2b (&keys, - &net, - &brut)); - keys.stefan_lin = 1.0; - GNUNET_assert (GNUNET_OK == - TALER_string_to_amount ("MAGIC:4", - &brut)); - GNUNET_log_skip (1, - GNUNET_NO); - GNUNET_assert (GNUNET_SYSERR == - TALER_EXCHANGE_keys_stefan_b2n (&keys, - &brut, - &net)); - GNUNET_assert (GNUNET_OK == - TALER_string_to_amount ("MAGIC:4", - &net)); - GNUNET_log_skip (1, - GNUNET_NO); - GNUNET_assert (GNUNET_SYSERR == - TALER_EXCHANGE_keys_stefan_n2b (&keys, - &net, - &brut)); - GNUNET_assert (0 == GNUNET_get_log_skip ()); - keys.stefan_lin = 0.1; - - /* try various values for lin and log STEFAN values */ - for (unsigned int li = 1; li < 13; li += 1) - { - keys.stefan_lin = 1.0 * li / 100.0; - - for (unsigned int lx = 1; lx < 100; lx += 1) - { - keys.stefan_log.fraction = lx * TALER_AMOUNT_FRAC_BASE / 100; - - /* Check brutto-to-netto is stable */ - for (unsigned int i = 0; i<10; i++) - { - struct TALER_Amount rval; - - brut.value = i; - brut.fraction = i * TALER_AMOUNT_FRAC_BASE / 10; - GNUNET_assert (GNUNET_SYSERR != - TALER_EXCHANGE_keys_stefan_b2n (&keys, - &brut, - &net)); - GNUNET_assert (GNUNET_SYSERR != - TALER_EXCHANGE_keys_stefan_n2b (&keys, - &net, - &rval)); - if (TALER_amount_is_zero (&net)) - GNUNET_assert (TALER_amount_is_zero (&rval)); - else - { - GNUNET_assert (amount_close (&brut, - &rval)); - TALER_EXCHANGE_keys_stefan_round (&keys, - &rval); - GNUNET_assert (amount_close (&brut, - &rval)); - } - } - - /* Check netto-to-brutto is stable */ - for (unsigned int i = 0; i<10; i++) - { - struct TALER_Amount rval; - - net.value = i; - net.fraction = i * TALER_AMOUNT_FRAC_BASE / 10; - GNUNET_assert (GNUNET_SYSERR != - TALER_EXCHANGE_keys_stefan_n2b (&keys, - &net, - &brut)); - GNUNET_assert (GNUNET_SYSERR != - TALER_EXCHANGE_keys_stefan_b2n (&keys, - &brut, - &rval)); - GNUNET_assert (amount_close (&net, - &rval)); - TALER_EXCHANGE_keys_stefan_round (&keys, - &rval); - GNUNET_assert (amount_close (&net, - &rval)); - } - } - } - return 0; -} -- cgit v1.2.3