diff options
Diffstat (limited to 'src/lib/exchange_api_purse_merge.c')
-rw-r--r-- | src/lib/exchange_api_purse_merge.c | 191 |
1 files changed, 71 insertions, 120 deletions
diff --git a/src/lib/exchange_api_purse_merge.c b/src/lib/exchange_api_purse_merge.c index a32b44d48..c013b29d2 100644 --- a/src/lib/exchange_api_purse_merge.c +++ b/src/lib/exchange_api_purse_merge.c @@ -1,6 +1,6 @@ /* This file is part of TALER - Copyright (C) 2022 Taler Systems SA + Copyright (C) 2022-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 @@ -29,6 +29,7 @@ #include "taler_json_lib.h" #include "taler_exchange_service.h" #include "exchange_api_handle.h" +#include "exchange_api_common.h" #include "taler_signatures.h" #include "exchange_api_curl_defaults.h" @@ -40,9 +41,9 @@ struct TALER_EXCHANGE_AccountMergeHandle { /** - * The connection to exchange this request handle will use + * The keys of the exchange this request handle will use */ - struct TALER_EXCHANGE_Handle *exchange; + struct TALER_EXCHANGE_Keys *keys; /** * The url for this request. @@ -76,6 +77,11 @@ struct TALER_EXCHANGE_AccountMergeHandle char *provider_url; /** + * Signature for our operation. + */ + struct TALER_PurseMergeSignatureP merge_sig; + + /** * Expected value in the purse after fees. */ struct TALER_Amount purse_value_after_fees; @@ -104,51 +110,13 @@ struct TALER_EXCHANGE_AccountMergeHandle * Our merge key. */ struct TALER_PurseMergePrivateKeyP merge_priv; -}; - -static char * -make_payto (const char *exchange_url, - const struct TALER_ReservePublicKeyP *reserve_pub) -{ - char pub_str[sizeof (*reserve_pub) * 2]; - char *end; - bool is_http; - char *reserve_url; + /** + * Reserve signature affirming the merge. + */ + struct TALER_ReserveSignatureP reserve_sig; - end = GNUNET_STRINGS_data_to_string ( - reserve_pub, - sizeof (*reserve_pub), - pub_str, - sizeof (pub_str)); - *end = '\0'; - if (0 == strncmp (exchange_url, - "http://", - strlen ("http://"))) - { - is_http = true; - exchange_url = &exchange_url[strlen ("http://")]; - } - else if (0 == strncmp (exchange_url, - "https://", - strlen ("https://"))) - { - is_http = false; - exchange_url = &exchange_url[strlen ("https://")]; - } - else - { - GNUNET_break (0); - return NULL; - } - /* exchange_url includes trailing '/' */ - GNUNET_asprintf (&reserve_url, - "payto://%s/%s%s", - is_http ? "taler+http" : "taler", - exchange_url, - pub_str); - return reserve_url; -} +}; /** @@ -168,7 +136,8 @@ handle_purse_merge_finished (void *cls, const json_t *j = response; struct TALER_EXCHANGE_AccountMergeResponse dr = { .hr.reply = j, - .hr.http_status = (unsigned int) response_code + .hr.http_status = (unsigned int) response_code, + .reserve_sig = &pch->reserve_sig }; pch->job = NULL; @@ -179,18 +148,14 @@ handle_purse_merge_finished (void *cls, break; case MHD_HTTP_OK: { - const struct TALER_EXCHANGE_Keys *key_state; - struct GNUNET_TIME_Timestamp etime; struct TALER_Amount total_deposited; - struct TALER_ExchangeSignatureP exchange_sig; - struct TALER_ExchangePublicKeyP exchange_pub; struct GNUNET_JSON_Specification spec[] = { GNUNET_JSON_spec_fixed_auto ("exchange_sig", - &exchange_sig), + &dr.details.ok.exchange_sig), GNUNET_JSON_spec_fixed_auto ("exchange_pub", - &exchange_pub), + &dr.details.ok.exchange_pub), GNUNET_JSON_spec_timestamp ("exchange_timestamp", - &etime), + &dr.details.ok.etime), TALER_JSON_spec_amount ("merge_amount", pch->purse_value_after_fees.currency, &total_deposited), @@ -207,10 +172,9 @@ handle_purse_merge_finished (void *cls, dr.hr.ec = TALER_EC_GENERIC_REPLY_MALFORMED; break; } - key_state = TALER_EXCHANGE_get_keys (pch->exchange); if (GNUNET_OK != - TALER_EXCHANGE_test_signing_key (key_state, - &exchange_pub)) + TALER_EXCHANGE_test_signing_key (pch->keys, + &dr.details.ok.exchange_pub)) { GNUNET_break_op (0); dr.hr.http_status = 0; @@ -219,15 +183,15 @@ handle_purse_merge_finished (void *cls, } if (GNUNET_OK != TALER_exchange_online_purse_merged_verify ( - etime, + dr.details.ok.etime, pch->purse_expiration, &pch->purse_value_after_fees, &pch->purse_pub, &pch->h_contract_terms, &pch->reserve_pub, pch->provider_url, - &exchange_pub, - &exchange_sig)) + &dr.details.ok.exchange_pub, + &dr.details.ok.exchange_sig)) { GNUNET_break_op (0); dr.hr.http_status = 0; @@ -262,58 +226,24 @@ handle_purse_merge_finished (void *cls, break; case MHD_HTTP_CONFLICT: { - struct TALER_PurseMergeSignatureP merge_sig; - struct GNUNET_TIME_Timestamp merge_timestamp; - const char *partner_url = NULL; - struct TALER_ReservePublicKeyP reserve_pub; - struct GNUNET_JSON_Specification spec[] = { - GNUNET_JSON_spec_fixed_auto ("reserve_pub", - &reserve_pub), - GNUNET_JSON_spec_fixed_auto ("merge_sig", - &merge_sig), - GNUNET_JSON_spec_timestamp ("merge_timestamp", - &merge_timestamp), - GNUNET_JSON_spec_mark_optional ( - GNUNET_JSON_spec_string ("partner_base_url", - &partner_url), - NULL), - GNUNET_JSON_spec_end () - }; struct TALER_PurseMergePublicKeyP merge_pub; - char *payto_uri; - if (GNUNET_OK != - GNUNET_JSON_parse (j, - spec, - NULL, NULL)) - { - GNUNET_break_op (0); - dr.hr.http_status = 0; - dr.hr.ec = TALER_EC_GENERIC_REPLY_MALFORMED; - break; - } GNUNET_CRYPTO_eddsa_key_get_public (&pch->merge_priv.eddsa_priv, &merge_pub.eddsa_pub); - if (NULL == partner_url) - partner_url = pch->provider_url; - payto_uri = make_payto (partner_url, - &reserve_pub); if (GNUNET_OK != - TALER_wallet_purse_merge_verify ( - payto_uri, - merge_timestamp, - &pch->purse_pub, + TALER_EXCHANGE_check_purse_merge_conflict_ ( + &pch->merge_sig, &merge_pub, - &merge_sig)) + &pch->purse_pub, + pch->provider_url, + j)) { GNUNET_break_op (0); dr.hr.http_status = 0; dr.hr.ec = TALER_EC_GENERIC_REPLY_MALFORMED; - GNUNET_free (payto_uri); break; } - GNUNET_free (payto_uri); - /* conflict is real */ + break; } break; case MHD_HTTP_GONE: @@ -324,6 +254,27 @@ handle_purse_merge_finished (void *cls, dr.hr.ec = TALER_JSON_get_error_code (j); dr.hr.hint = TALER_JSON_get_error_hint (j); break; + case MHD_HTTP_UNAVAILABLE_FOR_LEGAL_REASONS: + { + struct GNUNET_JSON_Specification spec[] = { + GNUNET_JSON_spec_uint64 ( + "requirement_row", + &dr.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); + dr.hr.http_status = 0; + dr.hr.ec = TALER_EC_GENERIC_REPLY_MALFORMED; + break; + } + } + break; case MHD_HTTP_INTERNAL_SERVER_ERROR: dr.hr.ec = TALER_JSON_get_error_code (j); dr.hr.hint = TALER_JSON_get_error_hint (j); @@ -349,7 +300,9 @@ handle_purse_merge_finished (void *cls, struct TALER_EXCHANGE_AccountMergeHandle * TALER_EXCHANGE_account_merge ( - struct TALER_EXCHANGE_Handle *exchange, + struct GNUNET_CURL_Context *ctx, + const char *url, + struct TALER_EXCHANGE_Keys *keys, const char *reserve_exchange_url, const struct TALER_ReservePrivateKeyP *reserve_priv, const struct TALER_PurseContractPublicKeyP *purse_pub, @@ -363,16 +316,12 @@ TALER_EXCHANGE_account_merge ( void *cb_cls) { struct TALER_EXCHANGE_AccountMergeHandle *pch; - struct GNUNET_CURL_Context *ctx; json_t *merge_obj; CURL *eh; - struct TALER_PurseMergeSignatureP merge_sig; - struct TALER_ReserveSignatureP reserve_sig; char arg_str[sizeof (pch->purse_pub) * 2 + 32]; char *reserve_url; pch = GNUNET_new (struct TALER_EXCHANGE_AccountMergeHandle); - pch->exchange = exchange; pch->merge_priv = *merge_priv; pch->cb = cb; pch->cb_cls = cb_cls; @@ -381,14 +330,12 @@ TALER_EXCHANGE_account_merge ( pch->purse_expiration = purse_expiration; pch->purse_value_after_fees = *purse_value_after_fees; if (NULL == reserve_exchange_url) - pch->provider_url = GNUNET_strdup (exchange->url); + pch->provider_url = GNUNET_strdup (url); else pch->provider_url = GNUNET_strdup (reserve_exchange_url); GNUNET_CRYPTO_eddsa_key_get_public (&reserve_priv->eddsa_priv, &pch->reserve_pub.eddsa_pub); - GNUNET_assert (GNUNET_YES == - TEAH_handle_is_ready (exchange)); { char pub_str[sizeof (*purse_pub) * 2]; char *end; @@ -401,11 +348,11 @@ TALER_EXCHANGE_account_merge ( *end = '\0'; GNUNET_snprintf (arg_str, sizeof (arg_str), - "/purses/%s/merge", + "purses/%s/merge", pub_str); } - reserve_url = make_payto (pch->provider_url, - &pch->reserve_pub); + reserve_url = TALER_reserve_make_payto (pch->provider_url, + &pch->reserve_pub); if (NULL == reserve_url) { GNUNET_break (0); @@ -413,8 +360,9 @@ TALER_EXCHANGE_account_merge ( GNUNET_free (pch); return NULL; } - pch->url = TEAH_path_to_url (exchange, - arg_str); + pch->url = TALER_url_join (url, + arg_str, + NULL); if (NULL == pch->url) { GNUNET_break (0); @@ -427,12 +375,13 @@ TALER_EXCHANGE_account_merge ( merge_timestamp, purse_pub, merge_priv, - &merge_sig); + &pch->merge_sig); { struct TALER_Amount zero_purse_fee; - TALER_amount_set_zero (purse_value_after_fees->currency, - &zero_purse_fee); + GNUNET_assert (GNUNET_OK == + TALER_amount_set_zero (purse_value_after_fees->currency, + &zero_purse_fee)); TALER_wallet_account_merge_sign (merge_timestamp, purse_pub, purse_expiration, @@ -442,18 +391,19 @@ TALER_EXCHANGE_account_merge ( min_age, TALER_WAMF_MODE_MERGE_FULLY_PAID_PURSE, reserve_priv, - &reserve_sig); + &pch->reserve_sig); } merge_obj = GNUNET_JSON_PACK ( GNUNET_JSON_pack_string ("payto_uri", reserve_url), GNUNET_JSON_pack_data_auto ("merge_sig", - &merge_sig), + &pch->merge_sig), GNUNET_JSON_pack_data_auto ("reserve_sig", - &reserve_sig), + &pch->reserve_sig), GNUNET_JSON_pack_timestamp ("merge_timestamp", merge_timestamp)); GNUNET_assert (NULL != merge_obj); + GNUNET_free (reserve_url); eh = TALER_EXCHANGE_curl_easy_get_ (pch->url); if ( (NULL == eh) || (GNUNET_OK != @@ -474,7 +424,7 @@ TALER_EXCHANGE_account_merge ( GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "URL for purse merge: `%s'\n", pch->url); - ctx = TEAH_handle_to_context (exchange); + pch->keys = TALER_EXCHANGE_keys_incref (keys); pch->job = GNUNET_CURL_job_add2 (ctx, eh, pch->ctx.headers, @@ -496,6 +446,7 @@ TALER_EXCHANGE_account_merge_cancel ( GNUNET_free (pch->url); GNUNET_free (pch->provider_url); TALER_curl_easy_post_finished (&pch->ctx); + TALER_EXCHANGE_keys_decref (pch->keys); GNUNET_free (pch); } |