summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorChristian Grothoff <christian@grothoff.org>2018-01-16 12:39:46 +0100
committerChristian Grothoff <christian@grothoff.org>2018-01-16 12:39:46 +0100
commit0d50ba20bb0746e1e33e7e4d5f050110044310c1 (patch)
treefd9118781fa5a28632892bdb2b09aa50db166d1d
parent55cd81c3d60aaaeeca8eae3825a5f91be1a81a16 (diff)
downloadmerchant-0d50ba20bb0746e1e33e7e4d5f050110044310c1.tar.gz
merchant-0d50ba20bb0746e1e33e7e4d5f050110044310c1.tar.bz2
merchant-0d50ba20bb0746e1e33e7e4d5f050110044310c1.zip
fix a few memory leaks
-rw-r--r--src/backend/taler-merchant-httpd.c16
-rw-r--r--src/backend/taler-merchant-httpd_pay.c122
-rw-r--r--src/backend/taler-merchant-httpd_proposal.c53
-rw-r--r--src/backend/taler-merchant-httpd_refund.c34
-rw-r--r--src/backenddb/plugin_merchantdb_postgres.c2
-rw-r--r--src/lib/test_merchant_api.c1
6 files changed, 140 insertions, 88 deletions
diff --git a/src/backend/taler-merchant-httpd.c b/src/backend/taler-merchant-httpd.c
index 8f030884..0ae5d39f 100644
--- a/src/backend/taler-merchant-httpd.c
+++ b/src/backend/taler-merchant-httpd.c
@@ -315,6 +315,7 @@ hashmap_free (void *cls,
json_decref (mi->j_wire);
GNUNET_free (mi->id);
GNUNET_free (mi->keyfile);
+ GNUNET_free (mi->name);
GNUNET_free_non_null (mi->tip_exchange);
GNUNET_free (mi);
return GNUNET_YES;
@@ -552,7 +553,10 @@ instances_iterator_cb (void *cls,
mi = GNUNET_new (struct MerchantInstance);
if (GNUNET_OK !=
- GNUNET_CONFIGURATION_get_value_string (iic->config, section, "NAME", &mi->name))
+ GNUNET_CONFIGURATION_get_value_string (iic->config,
+ section,
+ "NAME",
+ &mi->name))
{
GNUNET_log_config_missing (GNUNET_ERROR_TYPE_ERROR,
section,
@@ -571,6 +575,7 @@ instances_iterator_cb (void *cls,
GNUNET_log_config_missing (GNUNET_ERROR_TYPE_ERROR,
section,
"KEYFILE");
+ GNUNET_free (mi->name);
GNUNET_free (mi);
GNUNET_SCHEDULER_shutdown ();
return;
@@ -593,6 +598,8 @@ instances_iterator_cb (void *cls,
GNUNET_log_config_missing (GNUNET_ERROR_TYPE_ERROR,
section,
"TIP_RESERVE_PRIV_FILENAME");
+ GNUNET_free (mi->keyfile);
+ GNUNET_free (mi->name);
GNUNET_free (mi);
GNUNET_SCHEDULER_shutdown ();
return;
@@ -605,6 +612,8 @@ instances_iterator_cb (void *cls,
"TIP_RESERVE_PRIV_FILENAME",
"Failed to read private key");
GNUNET_free (tip_reserves);
+ GNUNET_free (mi->keyfile);
+ GNUNET_free (mi->name);
GNUNET_free (mi);
GNUNET_SCHEDULER_shutdown ();
return;
@@ -624,6 +633,7 @@ instances_iterator_cb (void *cls,
{
GNUNET_break (0);
GNUNET_free (mi->keyfile);
+ GNUNET_free (mi->name);
GNUNET_free (mi);
GNUNET_SCHEDULER_shutdown ();
return;
@@ -1295,7 +1305,9 @@ main (int argc,
* @returns the URL, must be freed with #GNUNET_free
*/
char *
-TMH_make_absolute_backend_url (struct MHD_Connection *connection, char *path, ...)
+TMH_make_absolute_backend_url (struct MHD_Connection *connection,
+ char *path,
+ ...)
{
static CURL *curl = NULL;
if (NULL == curl)
diff --git a/src/backend/taler-merchant-httpd_pay.c b/src/backend/taler-merchant-httpd_pay.c
index a635c65c..8f248a2e 100644
--- a/src/backend/taler-merchant-httpd_pay.c
+++ b/src/backend/taler-merchant-httpd_pay.c
@@ -70,7 +70,7 @@ struct DepositConfirmation
* URL of the exchange that issued this coin.
*/
char *exchange_url;
-
+
/**
* Denomination of this coin.
*/
@@ -127,7 +127,7 @@ struct DepositConfirmation
* #GNUNET_YES if this coin was refunded.
*/
int refunded;
-
+
};
@@ -203,7 +203,7 @@ struct PayContext
* URL of the exchange used for the last @e fo.
*/
const char *current_exchange;
-
+
/**
* Placeholder for #TMH_PARSE_post_json() to keep its internal state.
*/
@@ -272,7 +272,7 @@ struct PayContext
* set, what is the total amount we already refunded?
*/
struct TALER_Amount total_refunded;
-
+
/**
* Wire transfer deadline. How soon would the merchant like the
* wire transfer to be executed? (Can be given by the frontend
@@ -314,7 +314,7 @@ struct PayContext
* How often have we retried the 'main' transaction?
*/
unsigned int retry_counter;
-
+
/**
* Number of transactions still pending. Initially set to
* @e coins_cnt, decremented on each transaction that
@@ -462,56 +462,61 @@ sign_success_response (struct PayContext *pc)
const char *errmsg;
struct GNUNET_CRYPTO_EddsaSignature sig;
struct PaymentResponsePS mr;
-
+ json_t *resp;
+ struct MHD_Response *mret;
refunds = TM_get_refund_json (pc->mi,
&pc->h_contract_terms,
&ec,
&errmsg);
- if (NULL == refunds)
+ if (NULL == refunds)
return TMH_RESPONSE_make_error (ec,
errmsg);
-
+
mr.purpose.purpose = htonl (TALER_SIGNATURE_MERCHANT_PAYMENT_OK);
mr.purpose.size = htonl (sizeof (mr));
mr.h_contract_terms = pc->h_contract_terms;
-
GNUNET_CRYPTO_eddsa_sign (&pc->mi->privkey.eddsa_priv,
&mr.purpose,
&sig);
-
- json_t *resp = json_pack ("{s:O, s:o, s:o, s:o}",
- "contract_terms",
- pc->contract_terms,
- "sig",
- GNUNET_JSON_from_data_auto (&sig),
- "h_contract_terms",
- GNUNET_JSON_from_data (&pc->h_contract_terms,
- sizeof (struct GNUNET_HashCode)),
- "refund_permissions",
- refunds);
-
-
- if (NULL != pc->session_id) {
+ resp = json_pack ("{s:O, s:o, s:o, s:o}",
+ "contract_terms",
+ pc->contract_terms,
+ "sig",
+ GNUNET_JSON_from_data_auto (&sig),
+ "h_contract_terms",
+ GNUNET_JSON_from_data (&pc->h_contract_terms,
+ sizeof (struct GNUNET_HashCode)),
+ "refund_permissions",
+ refunds);
+
+ if (NULL != pc->session_id)
+ {
struct GNUNET_CRYPTO_EddsaSignature session_sig;
struct TALER_MerchantPaySessionSigPS mps;
GNUNET_assert (NULL != pc->order_id);
-
mps.purpose.size = htonl (sizeof (struct TALER_MerchantPaySessionSigPS));
mps.purpose.purpose = htonl (TALER_SIGNATURE_MERCHANT_PAY_SESSION);
- GNUNET_CRYPTO_hash (pc->order_id, strlen (pc->order_id), &mps.h_order_id);
- GNUNET_CRYPTO_hash (pc->session_id, strlen (pc->session_id), &mps.h_session_id);
+ GNUNET_CRYPTO_hash (pc->order_id,
+ strlen (pc->order_id),
+ &mps.h_order_id);
+ GNUNET_CRYPTO_hash (pc->session_id,
+ strlen (pc->session_id),
+ &mps.h_session_id);
GNUNET_CRYPTO_eddsa_sign (&pc->mi->privkey.eddsa_priv,
&mps.purpose,
&session_sig);
-
- json_object_set (resp, "session_sig", GNUNET_JSON_from_data_auto (&session_sig));
+ json_object_set (resp,
+ "session_sig",
+ GNUNET_JSON_from_data_auto (&session_sig));
}
- return TMH_RESPONSE_make_json (resp);
+ mret = TMH_RESPONSE_make_json (resp);
+ json_decref (resp);
+ return mret;
}
@@ -522,7 +527,7 @@ sign_success_response (struct PayContext *pc)
* @param http_status http status code to return
* @param ec taler error code to return
* @param msg human readable error message
- */
+ */
static void
resume_pay_with_error (struct PayContext *pc,
unsigned int http_status,
@@ -669,11 +674,11 @@ check_payment_sufficient (struct PayContext *pc)
}
-
+
/* Now compare exchange wire fee compared to what we are willing to
pay */
if (GNUNET_YES !=
- TALER_amount_cmp_currency (&total_wire_fee,
+ TALER_amount_cmp_currency (&total_wire_fee,
&pc->max_wire_fee))
{
GNUNET_break (0);
@@ -682,7 +687,7 @@ check_payment_sufficient (struct PayContext *pc)
if (GNUNET_OK ==
TALER_amount_subtract (&wire_fee_delta,
- &total_wire_fee,
+ &total_wire_fee,
&pc->max_wire_fee))
{
/* Actual wire fee is indeed higher than our maximum, compute
@@ -704,7 +709,7 @@ check_payment_sufficient (struct PayContext *pc)
TALER_amount_subtract (&acc_amount,
&acc_amount,
&pc->total_refunded));
-
+
/* Now check that the customer paid enough for the full contract */
if (-1 == TALER_amount_cmp (&pc->max_fee,
&acc_fee))
@@ -1070,7 +1075,7 @@ process_pay_with_exchange (void *cls,
dc->deposit_fee = denom_details->fee_deposit;
dc->refund_fee = denom_details->fee_refund;
dc->wire_fee = *wire_fee;
-
+
GNUNET_assert (NULL != pc->mi->j_wire);
GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
"Timing for this payment, wire_deadline: %llu, refund_deadline: %llu\n",
@@ -1210,7 +1215,7 @@ check_coin_paid (void *cls,
for (unsigned int i=0;i<pc->coins_cnt;i++)
{
struct DepositConfirmation *dc = &pc->dc[i];
-
+
if (GNUNET_YES == dc->found_in_db)
continue; /* processed earlier */
/* Get matching coin from results*/
@@ -1246,7 +1251,7 @@ check_coin_paid (void *cls,
}
dc->deposit_fee = *deposit_fee;
dc->refund_fee = *refund_fee;
- dc->wire_fee = *wire_fee;
+ dc->wire_fee = *wire_fee;
dc->amount_with_fee = *amount_with_fee;
dc->found_in_db = GNUNET_YES;
pc->pending--;
@@ -1281,7 +1286,7 @@ parse_pay (struct MHD_Connection *connection,
int res;
struct GNUNET_JSON_Specification spec[] = {
GNUNET_JSON_spec_string ("mode",
- &mode),
+ &mode),
GNUNET_JSON_spec_json ("coins",
&coins),
GNUNET_JSON_spec_string ("order_id",
@@ -1301,9 +1306,10 @@ parse_pay (struct MHD_Connection *connection,
return res;
}
- pc->session_id = json_string_value (json_object_get (root, "session_id"));
+ pc->session_id = json_string_value (json_object_get (root,
+ "session_id"));
pc->order_id = order_id;
-
+ GNUNET_assert (NULL == pc->contract_terms);
qs = db->find_contract_terms (db->cls,
&pc->contract_terms,
order_id,
@@ -1391,10 +1397,8 @@ parse_pay (struct MHD_Connection *connection,
}
GNUNET_log (GNUNET_ERROR_TYPE_INFO,
- "/pay: picked instance %s with key %s\n",
- pc->mi->id,
- GNUNET_STRINGS_data_to_string_alloc (&pc->mi->pubkey,
- sizeof (pc->mi->pubkey)));
+ "/pay: picked instance %s\n",
+ pc->mi->id);
{
struct GNUNET_JSON_Specification espec[] = {
@@ -1582,7 +1586,7 @@ check_coin_refunded (void *cls,
for (unsigned int i=0;i<pc->coins_cnt;i++)
{
struct DepositConfirmation *dc = &pc->dc[i];
-
+
/* Get matching coin from results*/
if (0 != memcmp (coin_pub,
&dc->coin_pub,
@@ -1594,7 +1598,7 @@ check_coin_refunded (void *cls,
&pc->total_refunded,
refund_amount));
}
- }
+ }
}
@@ -1607,7 +1611,7 @@ check_coin_refunded (void *cls,
*/
static void
begin_transaction (struct PayContext *pc)
-{
+{
enum GNUNET_DB_QueryStatus qs;
/* Avoid re-trying transactions on soft errors forever! */
@@ -1621,7 +1625,7 @@ begin_transaction (struct PayContext *pc)
"hint", "Soft merchant database error: retry counter exceeded"));
return;
}
-
+
GNUNET_assert (GNUNET_YES == pc->suspended);
/* First, try to see if we have all we need already done */
@@ -1643,7 +1647,7 @@ begin_transaction (struct PayContext *pc)
GNUNET_break (GNUNET_OK ==
TALER_amount_get_zero (pc->amount.currency,
&pc->total_refunded));
-
+
/* Check if some of these coins already succeeded */
qs = db->find_payments (db->cls,
&pc->h_contract_terms,
@@ -1731,7 +1735,7 @@ begin_transaction (struct PayContext *pc)
"Merchant database error: could not commit");
return;
}
-
+
{
json_t *refunds;
@@ -1755,7 +1759,7 @@ begin_transaction (struct PayContext *pc)
&pc->dc[i].amount_with_fee);
TALER_amount_hton (&rr.refund_fee,
&pc->dc[i].refund_fee);
-
+
if (GNUNET_OK !=
GNUNET_CRYPTO_eddsa_sign (&pc->mi->privkey.eddsa_priv,
&rr.purpose,
@@ -1774,7 +1778,7 @@ begin_transaction (struct PayContext *pc)
json_pack ("{s:I, s:o, s:o}",
"rtransaction_id", (json_int_t) rtransactionid,
"coin_pub", GNUNET_JSON_from_data_auto (&rr.coin_pub),
- "merchant_sig", GNUNET_JSON_from_data_auto (&msig)));
+ "merchant_sig", GNUNET_JSON_from_data_auto (&msig)));
}
resume_pay_with_response (pc,
MHD_HTTP_OK,
@@ -1786,7 +1790,7 @@ begin_transaction (struct PayContext *pc)
}
/* Default PC_MODE_PAY mode */
- /* Final termination case: all coins already known, just
+ /* Final termination case: all coins already known, just
generate ultimate outcome. */
if (0 == pc->pending)
{
@@ -1802,7 +1806,7 @@ begin_transaction (struct PayContext *pc)
if (0 <= qs)
qs = db->commit (db->cls);
if (0 > qs)
- {
+ {
if (GNUNET_DB_STATUS_SOFT_ERROR == qs)
{
begin_transaction (pc);
@@ -1824,14 +1828,14 @@ begin_transaction (struct PayContext *pc)
return;
}
-
+
/* Check if transaction is already known, if not store it. */
{
struct GNUNET_HashCode h_xwire;
struct GNUNET_TIME_Absolute xtimestamp;
struct GNUNET_TIME_Absolute xrefund;
struct TALER_Amount xtotal_amount;
-
+
qs = db->find_transaction (db->cls,
&pc->h_contract_terms,
&pc->mi->pubkey,
@@ -1876,7 +1880,7 @@ begin_transaction (struct PayContext *pc)
return;
}
}
-
+
if (GNUNET_DB_STATUS_SUCCESS_NO_RESULTS == qs)
{
struct GNUNET_TIME_Absolute now;
@@ -1971,8 +1975,8 @@ begin_transaction (struct PayContext *pc)
so we can just rollback */
db->rollback (db->cls);
}
-
- /* Ok, we need to first go to the network.
+
+ /* Ok, we need to first go to the network.
Do that interaction in *tiny* transactions. */
find_next_exchange (pc);
}
diff --git a/src/backend/taler-merchant-httpd_proposal.c b/src/backend/taler-merchant-httpd_proposal.c
index 278a28e7..31e3fb39 100644
--- a/src/backend/taler-merchant-httpd_proposal.c
+++ b/src/backend/taler-merchant-httpd_proposal.c
@@ -156,6 +156,7 @@ proposal_put (struct MHD_Connection *connection,
GNUNET_JSON_spec_end ()
};
enum GNUNET_DB_QueryStatus qs;
+ const char *instance;
/* Add order_id if it doesn't exist. */
if (NULL ==
@@ -246,39 +247,65 @@ proposal_put (struct MHD_Connection *connection,
json_integer ((json_int_t) default_wire_fee_amortization));
}
- if (NULL == json_object_get (order, "pay_url"))
+ if (NULL == json_object_get (order,
+ "pay_url"))
{
char *url;
- url = TMH_make_absolute_backend_url (connection, "pay", NULL);
- json_object_set_new (order, "pay_url", json_string (url));
+
+ url = TMH_make_absolute_backend_url (connection,
+ "pay",
+ NULL);
+ json_object_set_new (order,
+ "pay_url",
+ json_string (url));
+ GNUNET_free (url);
}
- if (NULL == json_object_get (order, "products"))
+ if (NULL == json_object_get (order,
+ "products"))
{
// FIXME: When there is no explicit product,
// should we create a singleton product list?
- json_object_set_new (order, "products", json_array ());
+ json_object_set_new (order,
+ "products",
+ json_array ());
}
- const char *instance = json_string_value (json_object_get (order, "instance"));
+ instance = json_string_value (json_object_get (order,
+ "instance"));
if (NULL != instance)
{
// The frontend either fully specifieds the "merchant" field, or just gives
// the backend the "instance" name and lets it fill out.
struct MerchantInstance *mi = TMH_lookup_instance (instance);
+ json_t *merchant;
+
if (NULL == mi)
{
return TMH_RESPONSE_reply_internal_error (connection,
TALER_EC_PROPOSAL_ORDER_PARSE_ERROR,
"merchant instance not found");
}
- json_t *merchant = json_object ();
- json_object_set_new (merchant, "instance", json_string (instance));
- json_object_set_new (merchant, "name", json_string (mi->name));
- json_object_set_new (merchant, "jurisdiction", json_string ("none"));
- json_object_set_new (merchant, "address", json_string ("none"));
- json_object_set_new (order, "merchant", merchant);
- json_object_del (order, "instance");
+ merchant = json_object ();
+ /* FIXME: should the 'instance' field really be included in the
+ contract? This is really internal to the business! */
+ json_object_set_new (merchant,
+ "instance",
+ json_string (instance));
+ json_object_set_new (merchant,
+ "name",
+ json_string (mi->name));
+ json_object_set_new (merchant,
+ "jurisdiction",
+ json_string ("none"));
+ json_object_set_new (merchant,
+ "address",
+ json_string ("none"));
+ json_object_set_new (order,
+ "merchant",
+ merchant);
+ json_object_del (order,
+ "instance");
}
/* extract fields we need to sign separately */
diff --git a/src/backend/taler-merchant-httpd_refund.c b/src/backend/taler-merchant-httpd_refund.c
index 8df1ea46..c81be528 100644
--- a/src/backend/taler-merchant-httpd_refund.c
+++ b/src/backend/taler-merchant-httpd_refund.c
@@ -429,6 +429,7 @@ MH_handler_refund_lookup (struct TMH_RequestHandler *rh,
}
/* Convert order id to h_contract_terms */
+ contract_terms = NULL;
qs = db->find_contract_terms (db->cls,
&contract_terms,
order_id,
@@ -462,25 +463,32 @@ MH_handler_refund_lookup (struct TMH_RequestHandler *rh,
GNUNET_break (0);
GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
"Could not hash contract terms\n");
+ json_decref (contract_terms);
return TMH_RESPONSE_reply_internal_error (connection,
TALER_EC_INTERNAL_LOGIC_ERROR,
"Could not hash contract terms");
}
+ json_decref (contract_terms);
- json_t *response;
- enum TALER_ErrorCode ec;
- const char *errmsg;
-
- response = TM_get_refund_json (mi, &h_contract_terms, &ec, &errmsg);
-
- if (NULL == response) {
- return TMH_RESPONSE_reply_internal_error (connection, ec, errmsg);
+ {
+ json_t *response;
+ enum TALER_ErrorCode ec;
+ const char *errmsg;
+
+ response = TM_get_refund_json (mi,
+ &h_contract_terms,
+ &ec,
+ &errmsg);
+ if (NULL == response)
+ return TMH_RESPONSE_reply_internal_error (connection,
+ ec,
+ errmsg);
+ return TMH_RESPONSE_reply_json_pack (connection,
+ MHD_HTTP_OK,
+ "{s:o}",
+ "refund_permissions",
+ response);
}
-
- return TMH_RESPONSE_reply_json_pack (connection,
- MHD_HTTP_OK,
- "{s:o}",
- "refund_permissions", response);
}
diff --git a/src/backenddb/plugin_merchantdb_postgres.c b/src/backenddb/plugin_merchantdb_postgres.c
index e5d36330..57f11ec7 100644
--- a/src/backenddb/plugin_merchantdb_postgres.c
+++ b/src/backenddb/plugin_merchantdb_postgres.c
@@ -1115,7 +1115,7 @@ postgres_store_deposit (void *cls,
"Storing payment for h_contract_terms `%s', coin_pub: `%s', amount_with_fee: %s\n",
GNUNET_h2s (h_contract_terms),
TALER_B2S (coin_pub),
- TALER_amount_to_string (amount_with_fee));
+ TALER_amount2s (amount_with_fee));
GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
"Merchant pub is `%s'\n",
TALER_B2S (merchant_pub));
diff --git a/src/lib/test_merchant_api.c b/src/lib/test_merchant_api.c
index 48ee8826..e9679669 100644
--- a/src/lib/test_merchant_api.c
+++ b/src/lib/test_merchant_api.c
@@ -2218,6 +2218,7 @@ pickup_withdraw_cb (void *cls,
if (NULL == cmd->details.tip_pickup.sigs)
cmd->details.tip_pickup.sigs = GNUNET_new_array (cmd->details.tip_pickup.num_coins,
struct TALER_DenominationSignature);
+ GNUNET_assert (NULL == cmd->details.tip_pickup.sigs[wh->off].rsa_signature);
cmd->details.tip_pickup.sigs[wh->off].rsa_signature
= GNUNET_CRYPTO_rsa_signature_dup (sig->rsa_signature);
for (unsigned int i=0;i<cmd->details.tip_pickup.num_coins;i++)