From c20f955ae43a57208b40d9a7978a7f089592ad60 Mon Sep 17 00:00:00 2001 From: Christian Grothoff Date: Wed, 9 Dec 2015 15:36:34 +0100 Subject: [PATCH] towards /deposit/wtid handling (more skeleton work) --- src/include/taler_crypto_lib.h | 12 ++++ src/include/taler_mintdb_plugin.h | 42 ++++++++++++ src/mint/taler-mint-httpd_db.c | 93 +++++++++++++++++++++++++++ src/mint/taler-mint-httpd_db.h | 20 ++++++ src/mint/taler-mint-httpd_responses.c | 51 +++++++++++++++ src/mint/taler-mint-httpd_responses.h | 40 ++++++++++++ src/mint/taler-mint-httpd_tracking.c | 86 ++++++++++++++++++++++++- src/mintdb/plugin_mintdb_postgres.c | 32 ++++++++- 8 files changed, 372 insertions(+), 4 deletions(-) diff --git a/src/include/taler_crypto_lib.h b/src/include/taler_crypto_lib.h index a3c21b386..7a4bcb831 100644 --- a/src/include/taler_crypto_lib.h +++ b/src/include/taler_crypto_lib.h @@ -101,6 +101,18 @@ struct TALER_MerchantPrivateKeyP }; +/** + * @brief Type of signatures made by merchants. + */ +struct TALER_MerchantSignatureP +{ + /** + * Taler uses EdDSA for merchants. + */ + struct GNUNET_CRYPTO_EddsaSignature eddsa_sig; +}; + + /** * @brief Type of transfer public keys used during refresh * operations. diff --git a/src/include/taler_mintdb_plugin.h b/src/include/taler_mintdb_plugin.h index d83cf9d44..d9a1c6c85 100644 --- a/src/include/taler_mintdb_plugin.h +++ b/src/include/taler_mintdb_plugin.h @@ -568,6 +568,23 @@ typedef void const struct TALER_EncryptedLinkSecretP *shared_secret_enc); +/** + * Function called with the results of the lookup of the + * wire transfer identifier information. + * + * @param cls closure + * @param wtid base32-encoded wire transfer identifier, NULL + * if the transaction was not yet done + * @param execution_time when was the transaction done, or + * when we expect it to be done (if @a wtid was NULL); + * #GNUNET_TIME_UNIT_FOREVER_ABS if the /deposit is unknown + * to the mint + */ +typedef void +(*TALER_MINTDB_DepositWtidCallback)(void *cls, + const char *wtid, + struct GNUNET_TIME_Absolute execution_time); + /** * @brief The plugin API, returned from the plugin's "init" function. * The argument given to "init" is simply a configuration handle. @@ -1177,6 +1194,31 @@ struct TALER_MINTDB_Plugin struct TALER_MINTDB_TransactionList *list); + /** + * Try to find the wire transfer details for a deposit operation. + * If we did not execute the deposit yet, return when it is supposed + * to be executed. + * + * @param cls closure + * @param h_contract hash of the contract + * @param h_wire hash of merchant wire details + * @param coin_pub public key of deposited coin + * @param merchant_pub merchant public key + * @param transaction_id transaction identifier + * @param cb function to call with the result + * @param cb_cls closure to pass to @a cb + * @return #GNUNET_OK on success, #GNUNET_SYSERR on DB errors + */ + int + (*wire_lookup_deposit_wtid)(void *cls, + const struct GNUNET_HashCode *h_contract, + const struct GNUNET_HashCode *h_wire, + const struct TALER_CoinSpendPublicKeyP *coin_pub, + const struct TALER_MerchantPublicKeyP *merchant_pub, + uint64_t transaction_id, + TALER_MINTDB_DepositWtidCallback cb, + void *cb_cls); + }; diff --git a/src/mint/taler-mint-httpd_db.c b/src/mint/taler-mint-httpd_db.c index 2d8af2759..7f0fdb0a9 100644 --- a/src/mint/taler-mint-httpd_db.c +++ b/src/mint/taler-mint-httpd_db.c @@ -1551,4 +1551,97 @@ TMH_DB_execute_admin_add_incoming (struct MHD_Connection *connection, } +/** + * Closure for #handle_wtid_data. + */ +struct DepositWtidContext +{ + + /** + * Where should we send the reply? + */ + struct MHD_Connection *connection; + + /** + * MHD result code to return. + */ + int res; +}; + + +/** + * Function called with the results of the lookup of the + * wire transfer identifier information. + * + * @param cls our context for transmission + * @param wtid base32-encoded wire transfer identifier, NULL + * if the transaction was not yet done + * @param execution_time when was the transaction done, or + * when we expect it to be done (if @a wtid was NULL); + * #GNUNET_TIME_UNIT_FOREVER_ABS if the /deposit is unknown + * to the mint + */ +static void +handle_wtid_data (void *cls, + const char *wtid, + struct GNUNET_TIME_Absolute execution_time) +{ + struct DepositWtidContext *ctx = cls; + + if (NULL == wtid) + { + if (GNUNET_TIME_UNIT_FOREVER_ABS.abs_value_us == + execution_time.abs_value_us) + return TMH_RESPONSE_reply_deposit_unknown (ctx->connection); + else + return TMH_RESPONSE_reply_deposit_pending (ctx->connection); + } + else + { + return TMH_RESPONSE_reply_deposit_wtid (ctx->connection); + } +} + + +/** + * Execute a "/deposit/wtid". Returns the transfer information + * associated with the given deposit. + * + * @param connection the MHD connection to handle + * @param h_contract hash of the contract + * @param h_wire hash of the wire details + * @param coin_pub public key of the coin to link + * @param merchant_pub public key of the merchant + * @param transaction_id transaction ID of the merchant + * @return MHD result code + */ +int +TMH_DB_execute_deposit_wtid (struct MHD_Connection *connection, + const struct GNUNET_HashCode *h_contract, + const struct GNUNET_HashCode *h_wire, + const struct TALER_CoinSpendPublicKeyP *coin_pub, + const struct TALER_MerchantPublicKeyP *merchant_pub, + uint64_t transaction_id) +{ + int ret; + struct DepositWtidContext ctx; + + ctx.connection = connection; + ret = TMH_plugin->wire_lookup_deposit_wtid (TMH_plugin->cls, + h_contract, + h_wire, + coin_pub, + merchant_pub, + transaction_id, + &handle_wtid_data, + connection); + if (GNUNET_SYSERR == ret) + { + GNUNET_break (0); + return TMH_RESPONSE_reply_internal_db_error (connection); + } + return ctx.res; +} + + /* end of taler-mint-httpd_db.c */ diff --git a/src/mint/taler-mint-httpd_db.h b/src/mint/taler-mint-httpd_db.h index f1d9fbfb8..d9adba2d9 100644 --- a/src/mint/taler-mint-httpd_db.h +++ b/src/mint/taler-mint-httpd_db.h @@ -192,5 +192,25 @@ TMH_DB_execute_admin_add_incoming (struct MHD_Connection *connection, json_t *wire); +/** + * Execute a "/deposit/wtid". Returns the transfer information + * associated with the given deposit. + * + * @param connection the MHD connection to handle + * @param h_contract hash of the contract + * @param h_wire hash of the wire details + * @param coin_pub public key of the coin to link + * @param merchant_pub public key of the merchant + * @param transaction_id transaction ID of the merchant + * @return MHD result code + */ +int +TMH_DB_execute_deposit_wtid (struct MHD_Connection *connection, + const struct GNUNET_HashCode *h_contract, + const struct GNUNET_HashCode *h_wire, + const struct TALER_CoinSpendPublicKeyP *coin_pub, + const struct TALER_MerchantPublicKeyP *merchant_pub, + uint64_t transaction_id); + #endif /* TALER_MINT_HTTPD_DB_H */ diff --git a/src/mint/taler-mint-httpd_responses.c b/src/mint/taler-mint-httpd_responses.c index 3b04fdb3c..f3498b469 100644 --- a/src/mint/taler-mint-httpd_responses.c +++ b/src/mint/taler-mint-httpd_responses.c @@ -1050,4 +1050,55 @@ TMH_RESPONSE_reply_refresh_link_success (struct MHD_Connection *connection, } +/** + * A merchant asked for details about a deposit, but + * we do not know anything about the deposit. Generate the + * 404 reply. + * + * @param connection connection to the client + * @param + * @return MHD result code + */ +int +TMH_RESPONSE_reply_deposit_unknown (struct MHD_Connection *connection, + ...) +{ + GNUNET_break (0); // FIXME: not implemented + return MHD_NO; +} + + +/** + * A merchant asked for details about a deposit, but + * we did not execute the deposit yet. Generate a 202 reply. + * + * @param connection connection to the client + * @param + * @return MHD result code + */ +int +TMH_RESPONSE_reply_deposit_pending (struct MHD_Connection *connection, + ...) +{ + GNUNET_break (0); // FIXME: not implemented + return MHD_NO; +} + + +/** + * A merchant asked for details about a deposit. Provide + * them. Generates the 200 reply. + * + * @param connection connection to the client + * @param + * @return MHD result code + */ +int +TMH_RESPONSE_reply_deposit_wtid (struct MHD_Connection *connection, + ...) +{ + GNUNET_break (0); // FIXME: not implemented + return MHD_NO; +} + /* end of taler-mint-httpd_responses.c */ diff --git a/src/mint/taler-mint-httpd_responses.h b/src/mint/taler-mint-httpd_responses.h index 9746ef90b..5d1523b4b 100644 --- a/src/mint/taler-mint-httpd_responses.h +++ b/src/mint/taler-mint-httpd_responses.h @@ -247,6 +247,46 @@ TMH_RESPONSE_reply_deposit_insufficient_funds (struct MHD_Connection *connection const struct TALER_MINTDB_TransactionList *tl); +/** + * A merchant asked for details about a deposit, but + * we do not know anything about the deposit. Generate the + * 404 reply. + * + * @param connection connection to the client + * @param + * @return MHD result code + */ +int +TMH_RESPONSE_reply_deposit_unknown (struct MHD_Connection *connection, + ...); + + +/** + * A merchant asked for details about a deposit, but + * we did not execute the deposit yet. Generate a 202 reply. + * + * @param connection connection to the client + * @param + * @return MHD result code + */ +int +TMH_RESPONSE_reply_deposit_pending (struct MHD_Connection *connection, + ...); + + +/** + * A merchant asked for details about a deposit. Provide + * them. Generates the 200 reply. + * + * @param connection connection to the client + * @param + * @return MHD result code + */ +int +TMH_RESPONSE_reply_deposit_wtid (struct MHD_Connection *connection, + ...); + + /** * Send reserve status information to client. * diff --git a/src/mint/taler-mint-httpd_tracking.c b/src/mint/taler-mint-httpd_tracking.c index beb4b4dd1..59d029429 100644 --- a/src/mint/taler-mint-httpd_tracking.c +++ b/src/mint/taler-mint-httpd_tracking.c @@ -23,6 +23,7 @@ #include #include #include +#include "taler_signatures.h" #include "taler-mint-httpd_parsing.h" #include "taler-mint-httpd_tracking.h" #include "taler-mint-httpd_responses.h" @@ -50,6 +51,43 @@ TMH_TRACKING_handler_wire_deposits (struct TMH_RequestHandler *rh, } +/** + * Check the merchant signature, and if it is valid, + * return the wire transfer identifier. + * + * @param connection the MHD connection to handle + * @param tps signed request to execute + * @param merchant_pub public key from the merchant + * @param merchant_sig signature from the merchant (to be checked) + * @param transaction_id transaction ID (in host byte order) + * @return MHD result code + */ +static int +check_and_handle_deposit_wtid_request (struct MHD_Connection *connection, + const struct TALER_DepositTrackPS *tps, + struct TALER_MerchantPublicKeyP *merchant_pub, + struct TALER_MerchantSignatureP *merchant_sig, + uint64_t transaction_id) +{ + if (GNUNET_OK != + GNUNET_CRYPTO_eddsa_verify (TALER_SIGNATURE_MERCHANT_DEPOSIT_WTID, + &tps->purpose, + &merchant_sig->eddsa_sig, + &merchant_pub->eddsa_pub)) + { + GNUNET_break_op (0); + return TMH_RESPONSE_reply_signature_invalid (connection, + "merchant_sig"); + } + return TMH_DB_execute_deposit_wtid (connection, + &tps->h_contract, + &tps->h_wire, + &tps->coin_pub, + merchant_pub, + transaction_id); +} + + /** * Handle a "/deposit/wtid" request. * @@ -59,7 +97,7 @@ TMH_TRACKING_handler_wire_deposits (struct TMH_RequestHandler *rh, * @param upload_data upload data * @param[in,out] upload_data_size number of bytes (left) in @a upload_data * @return MHD result code - */ + */ int TMH_TRACKING_handler_deposit_wtid (struct TMH_RequestHandler *rh, struct MHD_Connection *connection, @@ -67,8 +105,50 @@ TMH_TRACKING_handler_deposit_wtid (struct TMH_RequestHandler *rh, const char *upload_data, size_t *upload_data_size) { - GNUNET_break (0); // not implemented - return MHD_NO; + int res; + json_t *json; + struct TALER_DepositTrackPS tps; + uint64_t transaction_id; + struct TALER_MerchantSignatureP merchant_sig; + struct TALER_MerchantPublicKeyP merchant_pub; + struct TMH_PARSE_FieldSpecification spec[] = { + TMH_PARSE_member_fixed ("H_wire", &tps.h_wire), + TMH_PARSE_member_fixed ("H_contract", &tps.h_contract), + TMH_PARSE_member_fixed ("coin_pub", &tps.coin_pub), + TMH_PARSE_member_uint64 ("transaction_id", &transaction_id), + TMH_PARSE_member_fixed ("merchant_pub", &merchant_pub), + TMH_PARSE_member_fixed ("merchant_sig", &merchant_sig), + TMH_PARSE_MEMBER_END + }; + + res = TMH_PARSE_post_json (connection, + connection_cls, + upload_data, + upload_data_size, + &json); + if (GNUNET_SYSERR == res) + return MHD_NO; + if ( (GNUNET_NO == res) || (NULL == json) ) + return MHD_YES; + res = TMH_PARSE_json_data (connection, + json, + spec); + if (GNUNET_OK != res) + { + json_decref (json); + return (GNUNET_NO == res) ? MHD_YES : MHD_NO; + } + tps.purpose.size = htonl (sizeof (struct TALER_DepositTrackPS)); + tps.purpose.purpose = htonl (TALER_SIGNATURE_MERCHANT_DEPOSIT_WTID); + tps.transaction_id = GNUNET_htonll (transaction_id); + res = check_and_handle_deposit_wtid_request (connection, + &tps, + &merchant_pub, + &merchant_sig, + transaction_id); + TMH_PARSE_release_data (spec); + json_decref (json); + return res; } diff --git a/src/mintdb/plugin_mintdb_postgres.c b/src/mintdb/plugin_mintdb_postgres.c index f2d652b2e..62af73c87 100644 --- a/src/mintdb/plugin_mintdb_postgres.c +++ b/src/mintdb/plugin_mintdb_postgres.c @@ -3356,7 +3356,6 @@ postgres_get_coin_transactions (void *cls, } PQclear (result); } - /* FIXME: Handle locked coins (#3625) */ return head; cleanup: if (NULL != head) @@ -3366,6 +3365,36 @@ postgres_get_coin_transactions (void *cls, } +/** + * Try to find the wire transfer details for a deposit operation. + * If we did not execute the deposit yet, return when it is supposed + * to be executed. + * + * @param cls closure + * @param h_contract hash of the contract + * @param h_wire hash of merchant wire details + * @param coin_pub public key of deposited coin + * @param merchant_pub merchant public key + * @param transaction_id transaction identifier + * @param cb function to call with the result + * @param cb_cls closure to pass to @a cb + * @return #GNUNET_OK on success, #GNUNET_SYSERR on DB errors + */ +static int +postgres_wire_lookup_deposit_wtid (void *cls, + const struct GNUNET_HashCode *h_contract, + const struct GNUNET_HashCode *h_wire, + const struct TALER_CoinSpendPublicKeyP *coin_pub, + const struct TALER_MerchantPublicKeyP *merchant_pub, + uint64_t transaction_id, + TALER_MINTDB_DepositWtidCallback cb, + void *cb_cls) +{ + GNUNET_break (0); // not implemented + return GNUNET_SYSERR; +} + + /** * Initialize Postgres database subsystem. * @@ -3437,6 +3466,7 @@ libtaler_plugin_mintdb_postgres_init (void *cls) plugin->get_transfer = &postgres_get_transfer; plugin->get_coin_transactions = &postgres_get_coin_transactions; plugin->free_coin_transaction_list = &common_free_coin_transaction_list; + plugin->wire_lookup_deposit_wtid = &postgres_wire_lookup_deposit_wtid; return plugin; }