aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorChristian Grothoff <christian@grothoff.org>2017-07-21 15:54:57 +0200
committerChristian Grothoff <christian@grothoff.org>2017-07-21 23:19:47 +0200
commita7552719e982e1f1380f7478fc539d002336371e (patch)
tree1b5d6b06c37a2b529d589313ef34c883d83bb7c4
parentf3918c1df5a39ebd1a4455edd36ca4ccc35d0cbb (diff)
work for #4943 (incomplete)
-rw-r--r--src/backend/taler-merchant-httpd_track-transaction.c1
-rw-r--r--src/backend/taler-merchant-httpd_track-transfer.c124
-rw-r--r--src/include/taler_merchant_service.h107
-rw-r--r--src/lib/merchant_api_track_transfer.c12
-rw-r--r--src/lib/test_merchant_api.c3
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,