diff options
author | Christian Grothoff <christian@grothoff.org> | 2018-01-16 12:39:46 +0100 |
---|---|---|
committer | Christian Grothoff <christian@grothoff.org> | 2018-01-16 12:39:46 +0100 |
commit | 0d50ba20bb0746e1e33e7e4d5f050110044310c1 (patch) | |
tree | fd9118781fa5a28632892bdb2b09aa50db166d1d | |
parent | 55cd81c3d60aaaeeca8eae3825a5f91be1a81a16 (diff) | |
download | merchant-0d50ba20bb0746e1e33e7e4d5f050110044310c1.tar.gz merchant-0d50ba20bb0746e1e33e7e4d5f050110044310c1.tar.bz2 merchant-0d50ba20bb0746e1e33e7e4d5f050110044310c1.zip |
fix a few memory leaks
-rw-r--r-- | src/backend/taler-merchant-httpd.c | 16 | ||||
-rw-r--r-- | src/backend/taler-merchant-httpd_pay.c | 122 | ||||
-rw-r--r-- | src/backend/taler-merchant-httpd_proposal.c | 53 | ||||
-rw-r--r-- | src/backend/taler-merchant-httpd_refund.c | 34 | ||||
-rw-r--r-- | src/backenddb/plugin_merchantdb_postgres.c | 2 | ||||
-rw-r--r-- | src/lib/test_merchant_api.c | 1 |
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++) |