From 0d1ab614c06f60f79de75a0f2ec30c33a69820dd Mon Sep 17 00:00:00 2001 From: Christian Grothoff Date: Tue, 25 May 2021 20:52:58 +0200 Subject: return signed 404 statements for unknown denomination key hashes (#6889) --- src/exchange/taler-exchange-httpd_deposit.c | 13 ++---- src/exchange/taler-exchange-httpd_keys.c | 22 +++++----- src/exchange/taler-exchange-httpd_keys.h | 16 +++---- src/exchange/taler-exchange-httpd_melt.c | 15 ++----- src/exchange/taler-exchange-httpd_recoup.c | 17 ++------ .../taler-exchange-httpd_refreshes_reveal.c | 14 ++---- src/exchange/taler-exchange-httpd_refund.c | 12 ++--- src/exchange/taler-exchange-httpd_responses.c | 51 +++++++++++++++++++++- src/exchange/taler-exchange-httpd_responses.h | 14 ++++++ src/exchange/taler-exchange-httpd_withdraw.c | 12 ++--- src/include/taler_signatures.h | 29 ++++++++++++ 11 files changed, 137 insertions(+), 78 deletions(-) diff --git a/src/exchange/taler-exchange-httpd_deposit.c b/src/exchange/taler-exchange-httpd_deposit.c index 2f7d49c93..44c3d14cf 100644 --- a/src/exchange/taler-exchange-httpd_deposit.c +++ b/src/exchange/taler-exchange-httpd_deposit.c @@ -431,21 +431,16 @@ TEH_handler_deposit (struct MHD_Connection *connection, /* check denomination exists and is valid */ { struct TEH_DenominationKey *dk; - enum TALER_ErrorCode ec; - unsigned int hc; struct GNUNET_TIME_Absolute now; + MHD_RESULT mret; dk = TEH_keys_denomination_by_hash (&deposit.coin.denom_pub_hash, - &ec, - &hc); + connection, + &mret); if (NULL == dk) { - TALER_LOG_DEBUG ("Unknown denomination key in /deposit request\n"); GNUNET_JSON_parse_free (spec); - return TALER_MHD_reply_with_error (connection, - hc, - ec, - NULL); + return mret; } now = GNUNET_TIME_absolute_get (); if (now.abs_value_us >= dk->meta.expire_deposit.abs_value_us) diff --git a/src/exchange/taler-exchange-httpd_keys.c b/src/exchange/taler-exchange-httpd_keys.c index 579cb6b36..a0d359e32 100644 --- a/src/exchange/taler-exchange-httpd_keys.c +++ b/src/exchange/taler-exchange-httpd_keys.c @@ -1801,30 +1801,32 @@ TEH_keys_get_state (void) struct TEH_DenominationKey * TEH_keys_denomination_by_hash (const struct GNUNET_HashCode *h_denom_pub, - enum TALER_ErrorCode *ec, - unsigned int *hc) + struct MHD_Connection *conn, + MHD_RESULT *mret) { struct TEH_KeyStateHandle *ksh; ksh = TEH_keys_get_state (); if (NULL == ksh) { - *hc = MHD_HTTP_INTERNAL_SERVER_ERROR; - *ec = TALER_EC_EXCHANGE_GENERIC_KEYS_MISSING; + *mret = TALER_MHD_reply_with_error (conn, + MHD_HTTP_INTERNAL_SERVER_ERROR, + TALER_EC_EXCHANGE_GENERIC_KEYS_MISSING, + NULL); return NULL; } return TEH_keys_denomination_by_hash2 (ksh, h_denom_pub, - ec, - hc); + conn, + mret); } struct TEH_DenominationKey * TEH_keys_denomination_by_hash2 (struct TEH_KeyStateHandle *ksh, const struct GNUNET_HashCode *h_denom_pub, - enum TALER_ErrorCode *ec, - unsigned int *hc) + struct MHD_Connection *conn, + MHD_RESULT *mret) { struct TEH_DenominationKey *dk; @@ -1832,8 +1834,8 @@ TEH_keys_denomination_by_hash2 (struct TEH_KeyStateHandle *ksh, h_denom_pub); if (NULL == dk) { - *hc = MHD_HTTP_NOT_FOUND; - *ec = TALER_EC_EXCHANGE_GENERIC_DENOMINATION_KEY_UNKNOWN; + *mret = TEH_RESPONSE_reply_unknown_denom_pub_hash (conn, + h_denom_pub); return NULL; } return dk; diff --git a/src/exchange/taler-exchange-httpd_keys.h b/src/exchange/taler-exchange-httpd_keys.h index eeb4bdd2d..c13e97882 100644 --- a/src/exchange/taler-exchange-httpd_keys.h +++ b/src/exchange/taler-exchange-httpd_keys.h @@ -129,15 +129,15 @@ TEH_keys_update_states (void); * key state is resolved. * * @param h_denom_pub hash of denomination public key - * @param[out] ec set to the error code, in case the operation failed - * @param[out] hc set to the HTTP status code to use + * @param[in,out] connection used to return status message if NULL is returned + * @param[out] mret set to the MHD status if NULL is returned * @return the denomination key issue, * or NULL if @a h_denom_pub could not be found */ struct TEH_DenominationKey * TEH_keys_denomination_by_hash (const struct GNUNET_HashCode *h_denom_pub, - enum TALER_ErrorCode *ec, - unsigned int *hc); + struct MHD_Connection *conn, + MHD_RESULT *mret); /** @@ -148,16 +148,16 @@ TEH_keys_denomination_by_hash (const struct GNUNET_HashCode *h_denom_pub, * * @param ksh key state state to look in * @param h_denom_pub hash of denomination public key - * @param[out] ec set to the error code, in case the operation failed - * @param[out] hc set to the HTTP status code to use + * @param[in,out] connection used to return status message if NULL is returned + * @param[out] mret set to the MHD status if NULL is returned * @return the denomination key issue, * or NULL if @a h_denom_pub could not be found */ struct TEH_DenominationKey * TEH_keys_denomination_by_hash2 (struct TEH_KeyStateHandle *ksh, const struct GNUNET_HashCode *h_denom_pub, - enum TALER_ErrorCode *ec, - unsigned int *hc); + struct MHD_Connection *conn, + MHD_RESULT *mret); /** * Request to sign @a msg using the public key corresponding to diff --git a/src/exchange/taler-exchange-httpd_melt.c b/src/exchange/taler-exchange-httpd_melt.c index 143e3f3ac..5e9ae7f0d 100644 --- a/src/exchange/taler-exchange-httpd_melt.c +++ b/src/exchange/taler-exchange-httpd_melt.c @@ -466,22 +466,15 @@ check_for_denomination_key (struct MHD_Connection *connection, /* Baseline: check if deposits/refreshs are generally simply still allowed for this denomination */ struct TEH_DenominationKey *dk; - unsigned int hc; - enum TALER_ErrorCode ec; struct GNUNET_TIME_Absolute now; + MHD_RESULT mret; dk = TEH_keys_denomination_by_hash ( &rmc->refresh_session.coin.denom_pub_hash, - &ec, - &hc); + connection, + &mret); if (NULL == dk) - { - return TALER_MHD_reply_with_error ( - connection, - MHD_HTTP_NOT_FOUND, - TALER_EC_EXCHANGE_GENERIC_DENOMINATION_KEY_UNKNOWN, - NULL); - } + return mret; now = GNUNET_TIME_absolute_get (); if (now.abs_value_us >= dk->meta.expire_legal.abs_value_us) { diff --git a/src/exchange/taler-exchange-httpd_recoup.c b/src/exchange/taler-exchange-httpd_recoup.c index f63bf0722..c1aadb83e 100644 --- a/src/exchange/taler-exchange-httpd_recoup.c +++ b/src/exchange/taler-exchange-httpd_recoup.c @@ -363,24 +363,15 @@ verify_and_execute_recoup (struct MHD_Connection *connection, struct GNUNET_HashCode c_hash; void *coin_ev; size_t coin_ev_size; - enum TALER_ErrorCode ec; - unsigned int hc; + MHD_RESULT mret; struct GNUNET_TIME_Absolute now; /* check denomination exists and is in recoup mode */ dk = TEH_keys_denomination_by_hash (&coin->denom_pub_hash, - &ec, - &hc); + connection, + &mret); if (NULL == dk) - { - TALER_LOG_WARNING ( - "Denomination key in recoup request not in recoup mode\n"); - return TALER_MHD_reply_with_error (connection, - hc, - ec, - NULL); - } - + return mret; now = GNUNET_TIME_absolute_get (); if (now.abs_value_us >= dk->meta.expire_deposit.abs_value_us) { diff --git a/src/exchange/taler-exchange-httpd_refreshes_reveal.c b/src/exchange/taler-exchange-httpd_refreshes_reveal.c index d7ec02c88..b6b1849c7 100644 --- a/src/exchange/taler-exchange-httpd_refreshes_reveal.c +++ b/src/exchange/taler-exchange-httpd_refreshes_reveal.c @@ -565,8 +565,7 @@ resolve_refreshes_reveal_denominations (struct MHD_Connection *connection, &dk_h[i]), GNUNET_JSON_spec_end () }; - unsigned int hc; - enum TALER_ErrorCode ec; + MHD_RESULT mret; res = TALER_MHD_parse_json_array (connection, new_denoms_h_json, @@ -579,15 +578,10 @@ resolve_refreshes_reveal_denominations (struct MHD_Connection *connection, } dks[i] = TEH_keys_denomination_by_hash2 (ksh, &dk_h[i], - &ec, - &hc); + connection, + &mret); if (NULL == dks[i]) - { - return TALER_MHD_reply_with_error (connection, - hc, - ec, - NULL); - } + return mret; if (now.abs_value_us >= dks[i]->meta.expire_withdraw.abs_value_us) { diff --git a/src/exchange/taler-exchange-httpd_refund.c b/src/exchange/taler-exchange-httpd_refund.c index ace6e28f4..56d987d94 100644 --- a/src/exchange/taler-exchange-httpd_refund.c +++ b/src/exchange/taler-exchange-httpd_refund.c @@ -449,21 +449,17 @@ verify_and_execute_refund (struct MHD_Connection *connection, { /* Obtain information about the coin's denomination! */ struct TEH_DenominationKey *dk; - unsigned int hc; - enum TALER_ErrorCode ec; + MHD_RESULT mret; dk = TEH_keys_denomination_by_hash (&denom_hash, - &ec, - &hc); + connection, + &mret); if (NULL == dk) { /* DKI not found, but we do have a coin with this DK in our database; not good... */ GNUNET_break (0); - return TALER_MHD_reply_with_error (connection, - hc, - ec, - NULL); + return mret; } if (GNUNET_TIME_absolute_get ().abs_value_us >= diff --git a/src/exchange/taler-exchange-httpd_responses.c b/src/exchange/taler-exchange-httpd_responses.c index ea9729af0..234074747 100644 --- a/src/exchange/taler-exchange-httpd_responses.c +++ b/src/exchange/taler-exchange-httpd_responses.c @@ -1,6 +1,6 @@ /* This file is part of TALER - Copyright (C) 2014-2017 Taler Systems SA + Copyright (C) 2014-2021 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 @@ -417,6 +417,55 @@ TEH_RESPONSE_compile_transaction_history ( } +MHD_RESULT +TEH_RESPONSE_reply_unknown_denom_pub_hash ( + struct MHD_Connection *connection, + const struct GNUNET_HashCode *dph) +{ + struct TALER_ExchangePublicKeyP epub; + struct TALER_ExchangeSignatureP esig; + struct GNUNET_TIME_Absolute now; + enum TALER_ErrorCode ec; + + now = GNUNET_TIME_absolute_get (); + GNUNET_TIME_round_abs (&now); + { + struct TALER_DenominationUnknownAffirmationPS dua = { + .purpose.size = htonl (sizeof (dua)), + .purpose.purpose = htonl (TALER_SIGNATURE_EXCHANGE_AFFIRM_DENOM_UNKNOWN), + .timestamp = GNUNET_TIME_absolute_hton (now), + .h_denom_pub = *dph, + }; + + ec = TEH_keys_exchange_sign (&dua, + &epub, + &esig); + } + if (TALER_EC_NONE != ec) + { + GNUNET_break (0); + return TALER_MHD_reply_with_error (connection, + MHD_HTTP_INTERNAL_SERVER_ERROR, + ec, + NULL); + } + return TALER_MHD_reply_json_pack ( + connection, + MHD_HTTP_NOT_FOUND, + "{s:I,s:o,s:o,s:o,s:o}", + "code", + TALER_EC_EXCHANGE_GENERIC_DENOMINATION_KEY_UNKNOWN, + "timestamp", + GNUNET_JSON_from_time_abs (now), + "exchange_pub", + GNUNET_JSON_from_data_auto (&epub), + "exchange_sig", + GNUNET_JSON_from_data_auto (&esig), + "h_denom_pub", + GNUNET_JSON_from_data_auto (dph)); +} + + /** * Send proof that a request is invalid to client because of * insufficient funds. This function will create a message with all diff --git a/src/exchange/taler-exchange-httpd_responses.h b/src/exchange/taler-exchange-httpd_responses.h index 6486b5d93..7182629eb 100644 --- a/src/exchange/taler-exchange-httpd_responses.h +++ b/src/exchange/taler-exchange-httpd_responses.h @@ -48,6 +48,20 @@ TEH_RESPONSE_compile_reserve_history ( struct TALER_Amount *balance); +/** + * Send assertion that the given denomination key hash + * is unknown to us at this time. + * + * @param connection connection to the client + * @param dph denomination public key hash + * @return MHD result code + */ +MHD_RESULT +TEH_RESPONSE_reply_unknown_denom_pub_hash ( + struct MHD_Connection *connection, + const struct GNUNET_HashCode *dph); + + /** * Send proof that a request is invalid to client because of * insufficient funds. This function will create a message with all diff --git a/src/exchange/taler-exchange-httpd_withdraw.c b/src/exchange/taler-exchange-httpd_withdraw.c index 68a8e5fd0..5833fcf48 100644 --- a/src/exchange/taler-exchange-httpd_withdraw.c +++ b/src/exchange/taler-exchange-httpd_withdraw.c @@ -379,20 +379,16 @@ TEH_handler_withdraw (const struct TEH_RequestHandler *rh, return (GNUNET_SYSERR == res) ? MHD_NO : MHD_YES; } { - unsigned int hc; - enum TALER_ErrorCode ec; + MHD_RESULT mret; struct GNUNET_TIME_Absolute now; dk = TEH_keys_denomination_by_hash (&wc.denom_pub_hash, - &ec, - &hc); + connection, + &mret); if (NULL == dk) { GNUNET_JSON_parse_free (spec); - return TALER_MHD_reply_with_error (connection, - hc, - ec, - NULL); + return mret; } now = GNUNET_TIME_absolute_get (); if (now.abs_value_us >= dk->meta.expire_withdraw.abs_value_us) diff --git a/src/include/taler_signatures.h b/src/include/taler_signatures.h index f80a71d7c..1a64d52f6 100644 --- a/src/include/taler_signatures.h +++ b/src/include/taler_signatures.h @@ -155,6 +155,11 @@ */ #define TALER_SIGNATURE_EXCHANGE_CONFIRM_RECOUP_REFRESH 1041 +/** + * Signature where the Exchange confirms that it does not know a denomination (hash). + */ +#define TALER_SIGNATURE_EXCHANGE_AFFIRM_DENOM_UNKNOWN 1042 + /**********************/ /* Auditor signatures */ @@ -1514,6 +1519,30 @@ struct TALER_RecoupRefreshConfirmationPS }; +/** + * Response by which the exchange affirms that it does not + * currently know a denomination by the given hash. + */ +struct TALER_DenominationUnknownAffirmationPS +{ + + /** + * Purpose is #TALER_SIGNATURE_EXCHANGE_AFFIRM_DENOM_UNKNOWN + */ + struct GNUNET_CRYPTO_EccSignaturePurpose purpose; + + /** + * When did the exchange sign this message. + */ + struct GNUNET_TIME_AbsoluteNBO timestamp; + + /** + * Hash of the public denomination key we do not know. + */ + struct GNUNET_HashCode h_denom_pub; +}; + + /** * Response by which the exchange affirms that it has * closed a reserve and send back the funds. -- cgit v1.2.3