diff options
-rw-r--r-- | src/exchange/Makefile.am | 1 | ||||
-rw-r--r-- | src/exchange/taler-exchange-httpd.c | 8 | ||||
-rw-r--r-- | src/exchange/taler-exchange-httpd_payback.c | 185 | ||||
-rw-r--r-- | src/exchange/taler-exchange-httpd_refresh_payback.c | 57 | ||||
-rw-r--r-- | src/exchange/taler-exchange-httpd_refresh_payback.h | 49 |
5 files changed, 149 insertions, 151 deletions
diff --git a/src/exchange/Makefile.am b/src/exchange/Makefile.am index 2b5a10e9c..b5419a7a6 100644 --- a/src/exchange/Makefile.am +++ b/src/exchange/Makefile.am @@ -51,7 +51,6 @@ taler_exchange_httpd_SOURCES = \ taler-exchange-httpd_payback.c taler-exchange-httpd_payback.h \ taler-exchange-httpd_refresh_link.c taler-exchange-httpd_refresh_link.h \ taler-exchange-httpd_refresh_melt.c taler-exchange-httpd_refresh_melt.h \ - taler-exchange-httpd_refresh_payback.c taler-exchange-httpd_refresh_payback.h \ taler-exchange-httpd_refresh_reveal.c taler-exchange-httpd_refresh_reveal.h \ taler-exchange-httpd_refund.c taler-exchange-httpd_refund.h \ taler-exchange-httpd_reserve_status.c taler-exchange-httpd_reserve_status.h \ diff --git a/src/exchange/taler-exchange-httpd.c b/src/exchange/taler-exchange-httpd.c index 734f260ba..fe484979d 100644 --- a/src/exchange/taler-exchange-httpd.c +++ b/src/exchange/taler-exchange-httpd.c @@ -36,7 +36,6 @@ #include "taler-exchange-httpd_payback.h" #include "taler-exchange-httpd_refresh_link.h" #include "taler-exchange-httpd_refresh_melt.h" -#include "taler-exchange-httpd_refresh_payback.h" #include "taler-exchange-httpd_refresh_reveal.h" #include "taler-exchange-httpd_track_transfer.h" #include "taler-exchange-httpd_track_transaction.h" @@ -318,13 +317,6 @@ handle_mhd_request (void *cls, "Only GET is allowed", 0, &TEH_MHD_handler_send_json_pack_error, MHD_HTTP_METHOD_NOT_ALLOWED }, - { "/refresh/payback", MHD_HTTP_METHOD_POST, "application/json", - NULL, 0, - &TEH_REFRESH_handler_refresh_payback, MHD_HTTP_OK }, - { "/refresh/payback", NULL, "text/plain", - "Only POST is allowed", 0, - &TEH_MHD_handler_send_json_pack_error, MHD_HTTP_METHOD_NOT_ALLOWED }, - { "/track/transfer", MHD_HTTP_METHOD_GET, "application/json", NULL, 0, &TEH_TRACKING_handler_track_transfer, MHD_HTTP_OK }, diff --git a/src/exchange/taler-exchange-httpd_payback.c b/src/exchange/taler-exchange-httpd_payback.c index 2f1a2dde7..df79cea2c 100644 --- a/src/exchange/taler-exchange-httpd_payback.c +++ b/src/exchange/taler-exchange-httpd_payback.c @@ -44,7 +44,7 @@ */ static int reply_payback_unknown (struct MHD_Connection *connection, - enum TALER_ErrorCode ec) + enum TALER_ErrorCode ec) { return TEH_RESPONSE_reply_json_pack (connection, MHD_HTTP_NOT_FOUND, @@ -59,6 +59,54 @@ reply_payback_unknown (struct MHD_Connection *connection, * * @param connection connection to the client * @param coin_pub coin for which we are processing the payback request + * @param old_coin_pub public key of the old coin that will receive the payback + * @param amount the amount we will wire back + * @param timestamp when did the exchange receive the /payback request + * @return MHD result code + */ +static int +reply_payback_refresh_success (struct MHD_Connection *connection, + const struct TALER_CoinSpendPublicKeyP *coin_pub, + const struct TALER_CoinSpendPublicKeyP *old_coin_pub, + const struct TALER_Amount *amount, + struct GNUNET_TIME_Absolute timestamp) +{ + struct TALER_PaybackRefreshConfirmationPS pc; + struct TALER_ExchangePublicKeyP pub; + struct TALER_ExchangeSignatureP sig; + + pc.purpose.purpose = htonl (TALER_SIGNATURE_EXCHANGE_CONFIRM_PAYBACK_REFRESH); + pc.purpose.size = htonl (sizeof (struct TALER_PaybackRefreshConfirmationPS)); + pc.timestamp = GNUNET_TIME_absolute_hton (timestamp); + TALER_amount_hton (&pc.payback_amount, + amount); + pc.coin_pub = *coin_pub; + pc.old_coin_pub = *old_coin_pub; + if (GNUNET_OK != + TEH_KS_sign (&pc.purpose, + &pub, + &sig)) + { + return TEH_RESPONSE_reply_internal_error (connection, + TALER_EC_EXCHANGE_BAD_CONFIGURATION, + "no keys"); + } + return TEH_RESPONSE_reply_json_pack (connection, + MHD_HTTP_OK, + "{s:o, s:o, s:o, s:o, s:o}", + "old_coin_pub", GNUNET_JSON_from_data_auto (old_coin_pub), + "timestamp", GNUNET_JSON_from_time_abs (timestamp), + "amount", TALER_JSON_from_amount (amount), + "exchange_sig", GNUNET_JSON_from_data_auto (&sig), + "exchange_pub", GNUNET_JSON_from_data_auto (&pub)); +} + + +/** + * A wallet asked for /payback, return the successful response. + * + * @param connection connection to the client + * @param coin_pub coin for which we are processing the payback request * @param reserve_pub public key of the reserve that will receive the payback * @param amount the amount we will wire back * @param timestamp when did the exchange receive the /payback request @@ -66,10 +114,10 @@ reply_payback_unknown (struct MHD_Connection *connection, */ static int reply_payback_success (struct MHD_Connection *connection, - const struct TALER_CoinSpendPublicKeyP *coin_pub, - const struct TALER_ReservePublicKeyP *reserve_pub, - const struct TALER_Amount *amount, - struct GNUNET_TIME_Absolute timestamp) + const struct TALER_CoinSpendPublicKeyP *coin_pub, + const struct TALER_ReservePublicKeyP *reserve_pub, + const struct TALER_Amount *amount, + struct GNUNET_TIME_Absolute timestamp) { struct TALER_PaybackConfirmationPS pc; struct TALER_ExchangePublicKeyP pub; @@ -132,11 +180,20 @@ struct PaybackContext */ const struct TALER_CoinSpendSignatureP *coin_sig; - /** - * Set by #payback_transaction() to the reserve that will - * receive the payback. - */ - struct TALER_ReservePublicKeyP reserve_pub; + union + { + /** + * Set by #payback_transaction() to the reserve that will + * receive the payback, if #refreshed is #GNUNET_NO. + */ + struct TALER_ReservePublicKeyP reserve_pub; + + /** + * Set by #payback_transaction() to the old coin that will + * receive the payback, if #refreshed is #GNUNET_YES. + */ + struct TALER_CoinSpendPublicKeyP old_coin_pub; + } target; /** * Set by #payback_transaction() to the amount that will be paid back @@ -149,6 +206,11 @@ struct PaybackContext */ struct GNUNET_TIME_Absolute now; + /** + * #GNUNET_YES if the client claims the coin originated from a refresh. + */ + int refreshed; + }; @@ -183,19 +245,42 @@ payback_transaction (void *cls, /* Check whether a payback is allowed, and if so, to which reserve / account the money should go */ - qs = TEH_plugin->get_reserve_by_h_blind (TEH_plugin->cls, - session, - &pc->h_blind, - &pc->reserve_pub); - if (0 > qs) + if (pc->refreshed) { - if (GNUNET_DB_STATUS_HARD_ERROR == qs) + GNUNET_assert (0); // FIXME: not implemented in DB! +#if 0 + qs = TEH_plugin->get_old_coin_by_h_blind (TEH_plugin->cls, + session, + &pc->h_blind, + &pc->target.old_coin_pub); +#endif + if (0 > qs) { - GNUNET_break (0); - *mhd_ret = TEH_RESPONSE_reply_internal_db_error (connection, - TALER_EC_PAYBACK_DB_FETCH_FAILED); + if (GNUNET_DB_STATUS_HARD_ERROR == qs) + { + GNUNET_break (0); + *mhd_ret = TEH_RESPONSE_reply_internal_db_error (connection, + TALER_EC_PAYBACK_DB_FETCH_FAILED); + } + return qs; + } + } + else + { + qs = TEH_plugin->get_reserve_by_h_blind (TEH_plugin->cls, + session, + &pc->h_blind, + &pc->target.reserve_pub); + if (0 > qs) + { + if (GNUNET_DB_STATUS_HARD_ERROR == qs) + { + GNUNET_break (0); + *mhd_ret = TEH_RESPONSE_reply_internal_db_error (connection, + TALER_EC_PAYBACK_DB_FETCH_FAILED); + } + return qs; } - return qs; } if (GNUNET_DB_STATUS_SUCCESS_NO_RESULTS == qs) { @@ -266,15 +351,29 @@ payback_transaction (void *cls, (void) GNUNET_TIME_round_abs (&pc->now); /* add coin to list of wire transfers for payback */ - qs = TEH_plugin->insert_payback_request (TEH_plugin->cls, - session, - &pc->reserve_pub, - pc->coin, - pc->coin_sig, - pc->coin_bks, - &pc->amount, - &pc->h_blind, - pc->now); + if (pc->refreshed) + { + qs = TEH_plugin->insert_payback_refresh_request (TEH_plugin->cls, + session, + pc->coin, + pc->coin_sig, + pc->coin_bks, + &pc->amount, + &pc->h_blind, + pc->now); + } + else + { + qs = TEH_plugin->insert_payback_request (TEH_plugin->cls, + session, + &pc->target.reserve_pub, + pc->coin, + pc->coin_sig, + pc->coin_bks, + &pc->amount, + &pc->h_blind, + pc->now); + } if (0 > qs) { if (GNUNET_DB_STATUS_HARD_ERROR == qs) @@ -300,13 +399,15 @@ payback_transaction (void *cls, * @param coin information about the coin * @param coin_bks blinding data of the coin (to be checked) * @param coin_sig signature of the coin + * @param refreshed #GNUNET_YES if the coin was refreshed * @return MHD result code */ static int verify_and_execute_payback (struct MHD_Connection *connection, const struct TALER_CoinPublicInfo *coin, const struct TALER_DenominationBlindingKeyP *coin_bks, - const struct TALER_CoinSpendSignatureP *coin_sig) + const struct TALER_CoinSpendSignatureP *coin_sig, + int refreshed) { struct PaybackContext pc; struct TEH_KS_StateHandle *key_state; @@ -413,6 +514,7 @@ verify_and_execute_payback (struct MHD_Connection *connection, pc.coin_sig = coin_sig; pc.coin_bks = coin_bks; pc.coin = coin; + pc.refreshed = refreshed; { int mhd_ret; @@ -424,11 +526,17 @@ verify_and_execute_payback (struct MHD_Connection *connection, &pc)) return mhd_ret; } - return reply_payback_success (connection, - &coin->coin_pub, - &pc.reserve_pub, - &pc.amount, - pc.now); + return (refreshed) + ? reply_payback_refresh_success (connection, + &coin->coin_pub, + &pc.target.old_coin_pub, + &pc.amount, + pc.now) + : reply_payback_success (connection, + &coin->coin_pub, + &pc.target.reserve_pub, + &pc.amount, + pc.now); } @@ -458,6 +566,7 @@ TEH_PAYBACK_handler_payback (struct TEH_RequestHandler *rh, struct TALER_CoinPublicInfo coin; struct TALER_DenominationBlindingKeyP coin_bks; struct TALER_CoinSpendSignatureP coin_sig; + int refreshed = GNUNET_NO; struct GNUNET_JSON_Specification spec[] = { GNUNET_JSON_spec_fixed_auto ("denom_pub_hash", &coin.denom_pub_hash), @@ -469,6 +578,9 @@ TEH_PAYBACK_handler_payback (struct TEH_RequestHandler *rh, &coin_bks), GNUNET_JSON_spec_fixed_auto ("coin_sig", &coin_sig), + GNUNET_JSON_spec_mark_optional + (GNUNET_JSON_spec_boolean ("refreshed", + &refreshed)), GNUNET_JSON_spec_end () }; @@ -492,7 +604,8 @@ TEH_PAYBACK_handler_payback (struct TEH_RequestHandler *rh, res = verify_and_execute_payback (connection, &coin, &coin_bks, - &coin_sig); + &coin_sig, + refreshed); GNUNET_JSON_parse_free (spec); return res; } diff --git a/src/exchange/taler-exchange-httpd_refresh_payback.c b/src/exchange/taler-exchange-httpd_refresh_payback.c deleted file mode 100644 index 3687d19d8..000000000 --- a/src/exchange/taler-exchange-httpd_refresh_payback.c +++ /dev/null @@ -1,57 +0,0 @@ -/* - This file is part of TALER - Copyright (C) 2014-2019 Taler Systems SA - - 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 - Foundation; either version 3, or (at your option) any later version. - - TALER is distributed in the hope that it will be useful, but WITHOUT ANY - WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR - A PARTICULAR PURPOSE. See the GNU Affero General Public License for more details. - - You should have received a copy of the GNU Affero General Public License along with - TALER; see the file COPYING. If not, see <http://www.gnu.org/licenses/> -*/ -/** - * @file taler-exchange-httpd_refresh_link.c - * @brief Handle /refresh/link requests - * @author Florian Dold - * @author Benedikt Mueller - * @author Christian Grothoff - */ -#include "platform.h" -#include <gnunet/gnunet_util_lib.h> -#include <jansson.h> -#include <microhttpd.h> -#include "taler-exchange-httpd_parsing.h" -#include "taler-exchange-httpd_mhd.h" -#include "taler-exchange-httpd_refresh_payback.h" -#include "taler-exchange-httpd_responses.h" -#include "taler-exchange-httpd_keystate.h" - - -/** - * Handle a "/refresh/payback" request. Parses the request into the JSON - * components and then processes the request. - * - * @param rh context of the handler - * @param connection the MHD connection to handle - * @param[in,out] connection_cls the connection's closure (can be updated) - * @param upload_data upload data - * @param[in,out] upload_data_size number of bytes (left) in @a upload_data - * @return MHD result code - */ -int -TEH_REFRESH_handler_refresh_payback (struct TEH_RequestHandler *rh, - struct MHD_Connection *connection, - void **connection_cls, - const char *upload_data, - size_t *upload_data_size) -{ - GNUNET_break (0); - return MHD_NO; -} - - -/* end of taler-exchange-httpd_refresh_payback.c */ diff --git a/src/exchange/taler-exchange-httpd_refresh_payback.h b/src/exchange/taler-exchange-httpd_refresh_payback.h deleted file mode 100644 index 921715c76..000000000 --- a/src/exchange/taler-exchange-httpd_refresh_payback.h +++ /dev/null @@ -1,49 +0,0 @@ -/* - This file is part of TALER - Copyright (C) 2014-2019 Taler Systems SA - - 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 - Foundation; either version 3, or (at your option) any later version. - - TALER is distributed in the hope that it will be useful, but WITHOUT ANY - WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR - A PARTICULAR PURPOSE. See the GNU Affero General Public License for more details. - - You should have received a copy of the GNU Affero General Public License along with - TALER; see the file COPYING. If not, see <http://www.gnu.org/licenses/> -*/ -/** - * @file taler-exchange-httpd_refresh_payback.h - * @brief Handle /refresh/payback requests - * @author Florian Dold - * @author Christian Grothoff - */ -#ifndef TALER_EXCHANGE_HTTPD_REFRESH_PAYBACK_H -#define TALER_EXCHANGE_HTTPD_REFRESH_PAYBACK_H - -#include <gnunet/gnunet_util_lib.h> -#include <microhttpd.h> -#include "taler-exchange-httpd.h" - - -/** - * Handle a "/refresh/payback" request. Parses the request into the JSON - * components and then processes the request. - * - * @param rh context of the handler - * @param connection the MHD connection to handle - * @param[in,out] connection_cls the connection's closure (can be updated) - * @param upload_data upload data - * @param[in,out] upload_data_size number of bytes (left) in @a upload_data - * @return MHD result code - */ -int -TEH_REFRESH_handler_refresh_payback (struct TEH_RequestHandler *rh, - struct MHD_Connection *connection, - void **connection_cls, - const char *upload_data, - size_t *upload_data_size); - - -#endif |