From 73b8b9e975e0ce0be169a669a06f436223bb2c9d Mon Sep 17 00:00:00 2001 From: Christian Grothoff Date: Tue, 19 Sep 2023 17:07:08 +0200 Subject: fix report when same exchange URL is configured in multiple configuration sections --- src/lib/merchant_api_post_order_pay.c | 284 +--------------------------------- 1 file changed, 4 insertions(+), 280 deletions(-) (limited to 'src/lib') diff --git a/src/lib/merchant_api_post_order_pay.c b/src/lib/merchant_api_post_order_pay.c index fc2e9a29..5a5c1631 100644 --- a/src/lib/merchant_api_post_order_pay.c +++ b/src/lib/merchant_api_post_order_pay.c @@ -108,12 +108,6 @@ struct TALER_MERCHANT_OrderPayHandle */ json_t *error_history; - /** - * Handle to the exchange that issued a problematic - * coin (if any). - */ - struct TALER_EXCHANGE_GetKeysHandle *exchange; - /** * Number of @e coins we are paying with. */ @@ -128,254 +122,6 @@ struct TALER_MERCHANT_OrderPayHandle }; -/** - * We got a 409 response back from the exchange (or the merchant). - * Now we need to check the provided cryptographic proof that the - * coin was actually already spent! - * - * @param oph operation handle - * @param keys key data from the exchange - * @return #GNUNET_OK if conflict is valid - */ -static enum GNUNET_GenericReturnValue -check_conflict (struct TALER_MERCHANT_OrderPayHandle *oph, - const struct TALER_EXCHANGE_Keys *keys) -{ - struct TALER_Amount spent; - struct TALER_Amount spent_plus_contrib; - struct TALER_DenominationHashP h_denom_pub_pc; - const struct TALER_EXCHANGE_DenomPublicKey *dpk; - - TALER_denom_pub_hash (&oph->error_pc->denom_pub, - &h_denom_pub_pc); - dpk = TALER_EXCHANGE_get_denomination_key_by_hash ( - keys, - &h_denom_pub_pc); - if (GNUNET_OK != - TALER_EXCHANGE_verify_coin_history (dpk, - &oph->error_pc->coin_pub, - oph->error_history, - &spent)) - { - /* Exchange's history fails to verify */ - GNUNET_break_op (0); - return GNUNET_SYSERR; - } - if (0 > - TALER_amount_add (&spent_plus_contrib, - &spent, - &oph->error_pc->amount_with_fee)) - { - /* We got an integer overflow? Bad application! */ - GNUNET_break (0); - return GNUNET_SYSERR; - } - if (-1 != TALER_amount_cmp (&oph->error_pc->denom_value, - &spent_plus_contrib)) - { - /* according to our calculations, the transaction should - have still worked, AND we did not get any proof of - coin public key re-use; hence: exchange error! */ - GNUNET_break_op (0); - return GNUNET_SYSERR; - } - GNUNET_log (GNUNET_ERROR_TYPE_INFO, - "Accepting proof of double-spending (or coin public key re-use)\n"); - return GNUNET_OK; -} - - -/** - * We got the fee structure from the exchange. Now - * validate the conflict error. - * - * @param cls a `struct TALER_MERCHANT_OrderPayHandle` - * @param kr reply from the exchange - * @param keys keys of the exchange - */ -static void -cert_cb (void *cls, - const struct TALER_EXCHANGE_KeysResponse *kr, - struct TALER_EXCHANGE_Keys *keys) -{ - struct TALER_MERCHANT_OrderPayHandle *oph = cls; - const struct TALER_EXCHANGE_HttpResponse *ehr = &kr->hr; - - oph->exchange = NULL; - if ( (MHD_HTTP_OK != ehr->http_status) || - (NULL == kr->details.ok.keys) || - (NULL == keys) ) - { - struct TALER_MERCHANT_PayResponse pr = { - .hr.http_status = MHD_HTTP_CONFLICT, - .hr.exchange_http_status = ehr->http_status, - .hr.ec = TALER_EC_EXCHANGE_GENERIC_KEYS_MISSING, - .hr.reply = oph->full_reply, - .hr.exchange_reply = ehr->reply, - .hr.hint = "failed to download /keys from the exchange" - }; - - oph->pay_cb (oph->pay_cb_cls, - &pr); - TALER_MERCHANT_order_pay_cancel (oph); - return; - } - if (TALER_EXCHANGE_VC_INCOMPATIBLE & kr->details.ok.compat) - { - struct TALER_MERCHANT_PayResponse pr = { - .hr.http_status = MHD_HTTP_CONFLICT, - .hr.exchange_http_status = 0, - .hr.ec = TALER_EC_WALLET_EXCHANGE_PROTOCOL_VERSION_INCOMPATIBLE, - .hr.reply = oph->full_reply, - .hr.exchange_reply = ehr->reply, - .hr.hint = "could not check error: incompatible exchange version" - }; - - oph->pay_cb (oph->pay_cb_cls, - &pr); - TALER_MERCHANT_order_pay_cancel (oph); - TALER_EXCHANGE_keys_decref (keys); - return; - } - - if (GNUNET_OK != - check_conflict (oph, - kr->details.ok.keys)) - { - struct TALER_MERCHANT_PayResponse pr = { - .hr.http_status = 0, - .hr.ec = TALER_EC_GENERIC_INVALID_RESPONSE, - .hr.reply = oph->full_reply - }; - - oph->pay_cb (oph->pay_cb_cls, - &pr); - TALER_MERCHANT_order_pay_cancel (oph); - TALER_EXCHANGE_keys_decref (keys); - return; - } - - { - struct TALER_MERCHANT_PayResponse pr = { - .hr.http_status = MHD_HTTP_CONFLICT, - .hr.ec = TALER_JSON_get_error_code (oph->full_reply), - .hr.reply = oph->full_reply - }; - - oph->pay_cb (oph->pay_cb_cls, - &pr); - TALER_MERCHANT_order_pay_cancel (oph); - TALER_EXCHANGE_keys_decref (keys); - } -} - - -/** - * We got a 409 response back from the exchange (or the merchant). - * Now we need to check the provided cryptograophic proof that the - * coin was actually already spent! - * - * @param[in,out] oph handle of the original pay operation - * @param[in,out] pr response to modify if #GNUNET_OK is returned - * @param json cryptograophic proof returned by the - * exchange/merchant - * @return #GNUNET_OK if proof checks out, - * #GNUNET_SYSERR if it is wrong, - * #GNUNET_NO if checking continues asynchronously - */ -static enum GNUNET_GenericReturnValue -parse_conflict (struct TALER_MERCHANT_OrderPayHandle *oph, - struct TALER_MERCHANT_PayResponse *pr, - const json_t *json) -{ - const json_t *ereply; - const char *exchange_url; - struct GNUNET_JSON_Specification spec[] = { - GNUNET_JSON_spec_object_const ("exchange_reply", - &ereply), - GNUNET_JSON_spec_string ("exchange_url", - &exchange_url), - GNUNET_JSON_spec_end () - }; - struct TALER_CoinSpendPublicKeyP coin_pub; - struct GNUNET_JSON_Specification hspec[] = { - GNUNET_JSON_spec_json ("history", - &oph->error_history), - GNUNET_JSON_spec_fixed_auto ("coin_pub", - &coin_pub), - GNUNET_JSON_spec_end () - }; - enum TALER_ErrorCode ec = TALER_JSON_get_error_code (json); - - switch (ec) - { - case TALER_EC_GENERIC_CURRENCY_MISMATCH: - /* no proof to check, still very strange, as we - should have checked that the currency matches */ - GNUNET_break_op (0); - TALER_MERCHANT_parse_error_details_ (json, - MHD_HTTP_CONFLICT, - &pr->hr); - return GNUNET_OK; - case TALER_EC_MERCHANT_POST_ORDERS_ID_PAY_ALREADY_PAID: - /* We can only be happy and accept the result; - FIXME: parse the refunds... */ - TALER_MERCHANT_parse_error_details_ (json, - MHD_HTTP_CONFLICT, - &pr->hr); - return GNUNET_OK; - case TALER_EC_MERCHANT_POST_ORDERS_ID_PAY_INSUFFICIENT_FUNDS: - /* main case, handled below */ - break; - default: - GNUNET_break_op (0); - GNUNET_log (GNUNET_ERROR_TYPE_ERROR, - "Unexpected error code %d: %s\n", - ec, - TALER_ErrorCode_get_hint (ec)); - return GNUNET_SYSERR; - } - - if (GNUNET_OK != - GNUNET_JSON_parse (json, - spec, - NULL, NULL)) - { - GNUNET_break_op (0); - return GNUNET_SYSERR; - } - if (GNUNET_OK != - GNUNET_JSON_parse (ereply, - hspec, - NULL, NULL)) - { - GNUNET_break_op (0); - return GNUNET_SYSERR; - } - - for (unsigned int i = 0; inum_coins; i++) - { - if (0 == - GNUNET_memcmp (&oph->coins[i].coin_pub, - &coin_pub)) - { - oph->error_pc = &oph->coins[i]; - oph->full_reply = json_incref ((json_t *) json); - oph->exchange = TALER_EXCHANGE_get_keys (oph->ctx, - oph->error_pc->exchange_url, - NULL, - &cert_cb, - oph); - return GNUNET_NO; - } - } - GNUNET_break_op (0); /* complaint is not about any of the coins - that we actually paid with... */ - GNUNET_JSON_parse_free (hspec); - return GNUNET_SYSERR; -} - - /** * Function called when we're done processing the * HTTP /pay request. @@ -486,27 +232,10 @@ handle_pay_finished (void *cls, Pass on to application. */ break; case MHD_HTTP_CONFLICT: - { - enum GNUNET_GenericReturnValue ret; - - ret = parse_conflict (oph, - &pr, - json); - switch (ret) - { - case GNUNET_OK: - /* continued below, 'pr' was modified */ - break; - case GNUNET_NO: - /* handled asynchronously! */ - return; /* ! */ - case GNUNET_SYSERR: - GNUNET_break_op (0); - pr.hr.http_status = 0; - break; - } - break; - } + TALER_MERCHANT_parse_error_details_ (json, + MHD_HTTP_CONFLICT, + &pr.hr); + break; case MHD_HTTP_GONE: TALER_MERCHANT_parse_error_details_ (json, response_code, @@ -830,11 +559,6 @@ TALER_MERCHANT_order_pay_cancel (struct TALER_MERCHANT_OrderPayHandle *oph) GNUNET_CURL_job_cancel (oph->job); oph->job = NULL; } - if (NULL != oph->exchange) - { - TALER_EXCHANGE_get_keys_cancel (oph->exchange); - oph->exchange = NULL; - } TALER_curl_easy_post_finished (&oph->post_ctx); json_decref (oph->error_history); json_decref (oph->full_reply); -- cgit v1.2.3