diff options
author | Christian Grothoff <christian@grothoff.org> | 2017-07-21 15:54:57 +0200 |
---|---|---|
committer | Christian Grothoff <christian@grothoff.org> | 2017-07-21 23:19:47 +0200 |
commit | a7552719e982e1f1380f7478fc539d002336371e (patch) | |
tree | 1b5d6b06c37a2b529d589313ef34c883d83bb7c4 | |
parent | f3918c1df5a39ebd1a4455edd36ca4ccc35d0cbb (diff) |
work for #4943 (incomplete)
-rw-r--r-- | src/backend/taler-merchant-httpd_track-transaction.c | 1 | ||||
-rw-r--r-- | src/backend/taler-merchant-httpd_track-transfer.c | 124 | ||||
-rw-r--r-- | src/include/taler_merchant_service.h | 107 | ||||
-rw-r--r-- | src/lib/merchant_api_track_transfer.c | 12 | ||||
-rw-r--r-- | src/lib/test_merchant_api.c | 3 |
5 files changed, 194 insertions, 53 deletions
diff --git a/src/backend/taler-merchant-httpd_track-transaction.c b/src/backend/taler-merchant-httpd_track-transaction.c index d0dbe83d..5101f3fd 100644 --- a/src/backend/taler-merchant-httpd_track-transaction.c +++ b/src/backend/taler-merchant-httpd_track-transaction.c @@ -95,7 +95,6 @@ make_track_transaction_ok (unsigned int num_transfers, } - /** * Context for a /track/transaction operation. */ diff --git a/src/backend/taler-merchant-httpd_track-transfer.c b/src/backend/taler-merchant-httpd_track-transfer.c index d38cb662..4d55b7a9 100644 --- a/src/backend/taler-merchant-httpd_track-transfer.c +++ b/src/backend/taler-merchant-httpd_track-transfer.c @@ -96,6 +96,11 @@ struct TrackTransferContext char *uri; /** + * Wire method used for the transfer. + */ + char *wire_method; + + /** * Pointer to the detail that we are currently * checking in #check_transfer(). */ @@ -183,6 +188,11 @@ free_transfer_track_context (struct TrackTransferContext *rctx) GNUNET_free (rctx->uri); rctx->uri = NULL; } + if (NULL != rctx->wire_method) + { + GNUNET_free (rctx->wire_method); + rctx->wire_method = NULL; + } GNUNET_free (rctx); } @@ -459,7 +469,7 @@ check_transfer (void *cls, "exchange_deposit_proof", exchange_proof, "conflict_offset", (json_int_t) rctx->current_offset, "exchange_transfer_proof", rctx->original_response, - "coin_pub", GNUNET_JSON_from_data_auto (coin_pub), + "coin_pub", GNUNET_JSON_from_data_auto (coin_pub), "h_contract_terms", GNUNET_JSON_from_data_auto (&ttd->h_contract_terms), "amount_with_fee", TALER_JSON_from_amount (amount_with_fee), "deposit_fee", TALER_JSON_from_amount (deposit_fee)); @@ -470,6 +480,89 @@ check_transfer (void *cls, /** + * Check that the given @a wire_fee is what the + * @a exchange_pub should charge at the @a execution_time. + * If the fee is correct (according to our database), + * return #GNUNET_OK. If we do not have the fee structure + * in our DB, we just accept it and return #GNUNET_NO; + * if we have proof that the fee is bogus, we respond with + * the proof to the client and return #GNUNET_SYSERR. + * + * @param rctx context of the transfer to respond to + * @param json response from the exchange + * @param execution_time time of the wire transfer + * @param wire_fee fee claimed by the exchange + * @return #GNUNET_SYSERR if we returned hard proof of + * missbehavior from the exchange to the client + */ +static int +check_wire_fee (struct TrackTransferContext *rctx, + const json_t *json, + struct GNUNET_TIME_Absolute execution_time, + const struct TALER_Amount *wire_fee) +{ + const struct TALER_MasterPublicKeyP *master_pub; + struct GNUNET_HashCode h_wire_method; + struct TALER_Amount expected_fee; + struct TALER_Amount closing_fee; + struct TALER_MasterSignatureP master_sig; + struct GNUNET_TIME_Absolute start_date; + struct GNUNET_TIME_Absolute end_date; + enum GNUNET_DB_QueryStatus qs; + const struct TALER_EXCHANGE_Keys *keys; + + keys = TALER_EXCHANGE_get_keys (rctx->eh); + if (NULL == keys) + { + GNUNET_break (0); + return GNUNET_NO; + } + master_pub = &keys->master_pub; + GNUNET_CRYPTO_hash (rctx->wire_method, + strlen (rctx->wire_method) + 1, + &h_wire_method); + qs = db->lookup_wire_fee (db->cls, + master_pub, + &h_wire_method, + execution_time, + &expected_fee, + &closing_fee, + &start_date, + &end_date, + &master_sig); + if (0 >= qs) + { + GNUNET_log (GNUNET_ERROR_TYPE_WARNING, + "Failed to find wire fee for `%s' at %s in DB, accepting blindly that the fee is %s\n", + TALER_B2S (master_pub), + GNUNET_STRINGS_absolute_time_to_string (execution_time), + TALER_amount2s (wire_fee)); + return GNUNET_NO; + } + if (0 <= TALER_amount_cmp (&expected_fee, + wire_fee)) + return GNUNET_OK; /* expected_fee >= wire_fee */ + + /* Wire fee check failed, export proof to client */ + resume_track_transfer_with_response + (rctx, + MHD_HTTP_INTERNAL_SERVER_ERROR, + TMH_RESPONSE_make_json_pack ("{s:I, s:o, s:o, s:o, s:o, s:o, s:o, s:o, s:o, s:O}", + "code", (json_int_t) TALER_EC_TRACK_TRANSFER_JSON_BAD_WIRE_FEE, + "wire_fee", TALER_JSON_from_amount (wire_fee), + "execution_time", GNUNET_JSON_from_time_abs (execution_time), + "expected_wire_fee", TALER_JSON_from_amount (&expected_fee), + "expected_closing_fee", TALER_JSON_from_amount (&closing_fee), + "start_date", GNUNET_JSON_from_time_abs (start_date), + "end_date", GNUNET_JSON_from_time_abs (end_date), + "master_sig", GNUNET_JSON_from_data_auto (&master_sig), + "master_pub", GNUNET_JSON_from_data_auto (master_pub), + "json", json)); + return GNUNET_SYSERR; +} + + +/** * Function called with detailed wire transfer data, including all * of the coin transactions that were combined into the wire transfer. * @@ -546,6 +639,14 @@ wire_transfer_cb (void *cls, return; } rctx->original_response = json; + + if (GNUNET_SYSERR == + check_wire_fee (rctx, + json, + execution_time, + wire_fee)) + return; + for (unsigned int i=0;i<details_length;i++) { rctx->current_offset = i; @@ -775,6 +876,7 @@ MH_handler_track_transfer (struct TMH_RequestHandler *rh, const char *str; const char *uri; const char *instance_str; + const char *wire_method; int ret; enum GNUNET_DB_QueryStatus qs; @@ -831,6 +933,26 @@ MH_handler_track_transfer (struct TMH_RequestHandler *rh, "exchange"); rctx->uri = GNUNET_strdup (uri); + wire_method = MHD_lookup_connection_value (connection, + MHD_GET_ARGUMENT_KIND, + "wire_method"); + if (NULL == wire_method) + { + if (1) + { + /* temporary work-around until demo is adjusted... */ + GNUNET_break (0); + wire_method = "test"; + GNUNET_log (GNUNET_ERROR_TYPE_ERROR, + "Client needs fixing, see API change for #4943!\n"); + } + else + return TMH_RESPONSE_reply_arg_missing (connection, + TALER_EC_PARAMETER_MISSING, + "wire_method"); + } + rctx->wire_method = GNUNET_strdup (wire_method); + instance_str = MHD_lookup_connection_value (connection, MHD_GET_ARGUMENT_KIND, "instance"); diff --git a/src/include/taler_merchant_service.h b/src/include/taler_merchant_service.h index fa739772..ab31701a 100644 --- a/src/include/taler_merchant_service.h +++ b/src/include/taler_merchant_service.h @@ -1,6 +1,6 @@ /* This file is part of TALER - Copyright (C) 2014, 2015, 2016 INRIA + Copyright (C) 2014-2017 INRIA TALER is free software; you can redistribute it and/or modify it under the terms of the GNU Affero General Public License as published by the Free Software @@ -30,23 +30,11 @@ /* ********************* /refund ************************** */ -struct TALER_MERCHANT_RefundIncreaseOperation; - -struct TALER_MERCHANT_RefundLookupOperation; - /** - * Callback to process a POST /refund request - * - * @param cls closure - * @param http_status HTTP status code for this request - * @param ec taler-specific error code - * @param obj the response body + * Handle for a GET /refund operation. */ -typedef void -(*TALER_MERCHANT_RefundIncreaseCallback) (void *cls, - unsigned int http_status, - enum TALER_ErrorCode ec, - const json_t *obj); +struct TALER_MERCHANT_RefundLookupOperation; + /** * Callback to process a GET /refund request @@ -58,9 +46,9 @@ typedef void */ typedef void (*TALER_MERCHANT_RefundLookupCallback) (void *cls, - unsigned int http_status, - enum TALER_ErrorCode ec, - const json_t *obj); + unsigned int http_status, + enum TALER_ErrorCode ec, + const json_t *obj); /** * Does a GET /refund. @@ -81,6 +69,36 @@ TALER_MERCHANT_refund_lookup (struct GNUNET_CURL_Context *ctx, void *cb_cls); /** + * Cancel a GET /refund request. + * + * @param rlo the refund increasing operation to cancel + */ +void +TALER_MERCHANT_refund_lookup_cancel (struct TALER_MERCHANT_RefundLookupOperation *rlo); + + +/** + * Handle for a POST /refund operation. + */ +struct TALER_MERCHANT_RefundIncreaseOperation; + + +/** + * Callback to process a POST /refund request + * + * @param cls closure + * @param http_status HTTP status code for this request + * @param ec taler-specific error code + * @param obj the response body + */ +typedef void +(*TALER_MERCHANT_RefundIncreaseCallback) (void *cls, + unsigned int http_status, + enum TALER_ErrorCode ec, + const json_t *obj); + + +/** * Increase the refund associated to a order * * @param ctx the CURL context used to connect to the backend @@ -110,13 +128,6 @@ TALER_MERCHANT_refund_increase (struct GNUNET_CURL_Context *ctx, void TALER_MERCHANT_refund_increase_cancel (struct TALER_MERCHANT_RefundIncreaseOperation *rio); -/** - * Cancel a GET /refund request. - * - * @param rlo the refund increasing operation to cancel - */ -void -TALER_MERCHANT_refund_lookup_cancel (struct TALER_MERCHANT_RefundLookupOperation *rlo); /* ********************* /proposal *********************** */ @@ -127,11 +138,6 @@ TALER_MERCHANT_refund_lookup_cancel (struct TALER_MERCHANT_RefundLookupOperation struct TALER_MERCHANT_ProposalOperation; /** - * Handle to a GET /proposal operation - */ -struct TALER_MERCHANT_ProposalLookupOperation; - -/** * Callbacks of this type are used to serve the result of submitting a * /contract request to a merchant. * @@ -155,19 +161,6 @@ typedef void /** - * Callback called to work a GET /proposal response. - * - * @param cls closure - * @param http_status HTTP status code of the request - * @param body JSON containing the response's payload. - * In case of errors, it contains the appropriate error encoding. - */ -typedef void -(*TALER_MERCHANT_ProposalLookupOperationCallback) (void *cls, - unsigned int http_status, - const json_t *body); - -/** * PUT an order to the backend and receives the related proposal. * * @param ctx execution context @@ -197,6 +190,26 @@ TALER_MERCHANT_proposal_cancel (struct TALER_MERCHANT_ProposalOperation *po); /** + * Handle to a GET /proposal operation + */ +struct TALER_MERCHANT_ProposalLookupOperation; + + +/** + * Callback called to work a GET /proposal response. + * + * @param cls closure + * @param http_status HTTP status code of the request + * @param body JSON containing the response's payload. + * In case of errors, it contains the appropriate error encoding. + */ +typedef void +(*TALER_MERCHANT_ProposalLookupOperationCallback) (void *cls, + unsigned int http_status, + const json_t *body); + + +/** * Calls the GET /proposal API at the backend. That is, * retrieve a proposal data by providing its transaction id. * @@ -456,7 +469,8 @@ struct TALER_MERCHANT_TrackTransferHandle; * by the exchange for a given h_contract_terms, by _one_ wire * transfer. */ -struct TALER_MERCHANT_TrackTransferDetails { +struct TALER_MERCHANT_TrackTransferDetails +{ /** * Total amount paid back by the exchange. @@ -501,12 +515,14 @@ typedef void unsigned int details_length, const struct TALER_MERCHANT_TrackTransferDetails *details); + /** * Request backend to return deposits associated with a given wtid. * * @param ctx execution context * @param backend_uri base URI of the backend * @param instance which merchant instance is going to be tracked + * @param wire_method wire method used for the wire transfer * @param wtid base32 string indicating a wtid * @param exchange base URL of the exchange in charge of returning the wanted information * @param track_transfer_cb the callback to call when a reply for this request is available @@ -517,6 +533,7 @@ struct TALER_MERCHANT_TrackTransferHandle * TALER_MERCHANT_track_transfer (struct GNUNET_CURL_Context *ctx, const char *backend_uri, const char *instance, + const char *wire_method, const struct TALER_WireTransferIdentifierRawP *wtid, const char *exchange_uri, TALER_MERCHANT_TrackTransferCallback track_transfer_cb, diff --git a/src/lib/merchant_api_track_transfer.c b/src/lib/merchant_api_track_transfer.c index f0b65903..f3a35b5d 100644 --- a/src/lib/merchant_api_track_transfer.c +++ b/src/lib/merchant_api_track_transfer.c @@ -1,6 +1,6 @@ /* This file is part of TALER - Copyright (C) 2014, 2015, 2016 GNUnet e.V. and INRIA + Copyright (C) 2014-2017 GNUnet e.V. and INRIA TALER is free software; you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License as published by the Free Software @@ -112,9 +112,8 @@ check_track_transfer_response_ok (struct TALER_MERCHANT_TrackTransferHandle *wdh num_details = json_array_size (deposits); { struct TALER_MERCHANT_TrackTransferDetails details[num_details]; - unsigned int i; - for (i=0;i<num_details;i++) + for (unsigned int i=0;i<num_details;i++) { struct TALER_MERCHANT_TrackTransferDetails *detail = &details[i]; json_t *deposit = json_array_get (deposits, i); @@ -217,6 +216,7 @@ handle_track_transfer_finished (void *cls, * @param ctx execution context * @param backend_uri base URI of the backend * @param instance which merchant instance is going to be tracked + * @param wire_method wire method used for the wire transfer * @param wtid base32 string indicating a wtid * @param exchange_uri base URL of the exchange in charge of returning the wanted information * @param track_transfer_cb the callback to call when a reply for this request is available @@ -227,6 +227,7 @@ struct TALER_MERCHANT_TrackTransferHandle * TALER_MERCHANT_track_transfer (struct GNUNET_CURL_Context *ctx, const char *backend_uri, const char *instance, + const char *wire_method, const struct TALER_WireTransferIdentifierRawP *wtid, const char *exchange_uri, TALER_MERCHANT_TrackTransferCallback track_transfer_cb, @@ -247,11 +248,12 @@ TALER_MERCHANT_track_transfer (struct GNUNET_CURL_Context *ctx, base = MAH_path_to_url_ (backend_uri, "/track/transfer"); GNUNET_asprintf (&tdo->url, - "%s?wtid=%s&exchange=%s&instance=%s", + "%s?wtid=%s&exchange=%s&instance=%s&wire_method", base, wtid_str, exchange_uri, - instance); + instance, + wire_method); GNUNET_free (base); GNUNET_free (wtid_str); eh = curl_easy_init (); diff --git a/src/lib/test_merchant_api.c b/src/lib/test_merchant_api.c index 69bc4c36..7ee108c2 100644 --- a/src/lib/test_merchant_api.c +++ b/src/lib/test_merchant_api.c @@ -2041,7 +2041,7 @@ interpreter_run (void *cls) merchant_sig = ref->details.proposal.merchant_sig; GNUNET_assert (NULL != ref->details.proposal.contract_terms); { - /* Get information that need to be replied in the deposit permission */ + /* Get information that needs to be replied in the deposit permission */ struct GNUNET_JSON_Specification spec[] = { GNUNET_JSON_spec_string ("order_id", &order_id), GNUNET_JSON_spec_absolute_time ("refund_deadline", &refund_deadline), @@ -2207,6 +2207,7 @@ interpreter_run (void *cls) = TALER_MERCHANT_track_transfer (ctx, MERCHANT_URI, instance, + "test", &wtid, EXCHANGE_URI, &track_transfer_cb, |