exchange

Base system with REST service to issue digital coins, run by the payment service provider
Log | Files | Refs | Submodules | README | LICENSE

commit 8a8d55a376551750891c9a73e6d219665a3acb5c
parent 2afadf85abaf9c97475c18994c11b8859ef27288
Author: Christian Grothoff <christian@grothoff.org>
Date:   Thu,  2 Jan 2025 12:25:16 +0100

-add missing meta-data equality check for proper idempotency checking on /management/keys

Diffstat:
Msrc/exchange/taler-exchange-httpd_management_post_keys.c | 91+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++--
Msrc/include/taler_exchangedb_plugin.h | 2++
2 files changed, 91 insertions(+), 2 deletions(-)

diff --git a/src/exchange/taler-exchange-httpd_management_post_keys.c b/src/exchange/taler-exchange-httpd_management_post_keys.c @@ -118,6 +118,73 @@ struct AddKeysContext /** + * Compare meta-data of two denomination keys for equality, + * except for the "serial" number. + * + * @param m1 meta data to compare to @a m2 + * @param m2 meta data to compare to @a m1 + * @return true if both are equal + */ +static bool +denomination_meta_cmp ( + const struct TALER_EXCHANGEDB_DenominationKeyMetaData *m1, + const struct TALER_EXCHANGEDB_DenominationKeyMetaData *m2) +{ + if ( (GNUNET_TIME_timestamp_cmp (m1->start, + !=, + m2->start)) || + (GNUNET_TIME_timestamp_cmp (m1->expire_withdraw, + !=, + m2->expire_withdraw)) || + (GNUNET_TIME_timestamp_cmp (m1->expire_deposit, + !=, + m2->expire_deposit)) || + (GNUNET_TIME_timestamp_cmp (m1->expire_legal, + !=, + m2->expire_legal)) ) + return false; + if (0 != + TALER_amount_cmp (&m1->value, + &m2->value)) + return false; + if (0 != + GNUNET_memcmp (&m1->fees, + &m2->fees)) + return false; + if (m1->age_mask.bits != + m2->age_mask.bits) + return false; + return true; +} + + +/** + * Compare meta-data of two signing keys for equality. + * + * @param m1 meta data to compare to @a m2 + * @param m2 meta data to compare to @a m1 + * @return true if both are equal + */ +static bool +signkey_meta_cmp ( + const struct TALER_EXCHANGEDB_SignkeyMetaData *m1, + const struct TALER_EXCHANGEDB_SignkeyMetaData *m2) +{ + if ( (GNUNET_TIME_timestamp_cmp (m1->start, + !=, + m2->start)) || + (GNUNET_TIME_timestamp_cmp (m1->expire_sign, + !=, + m2->expire_sign)) || + (GNUNET_TIME_timestamp_cmp (m1->expire_legal, + !=, + m2->expire_legal)) ) + return false; + return true; +} + + +/** * Function implementing database transaction to add offline signing keys. * Runs the transaction logic; IF it returns a non-error code, the transaction * logic MUST NOT queue a MHD response. IF it returns an hard error, the @@ -163,7 +230,17 @@ add_keys (void *cls, } if (GNUNET_DB_STATUS_SUCCESS_ONE_RESULT == qs) { - /* FIXME: assert meta === d->meta might be good */ + if (! denomination_meta_cmp (&d->meta, + &meta)) + { + GNUNET_break_op (0); + *mhd_ret = TALER_MHD_reply_with_error ( + connection, + MHD_HTTP_CONFLICT, + TALER_EC_EXCHANGE_MANAGEMENT_CONFLICTING_DENOMINATION_META_DATA, + "conflicting meta data previously set for the same denomination key"); + return GNUNET_DB_STATUS_HARD_ERROR; + } GNUNET_log (GNUNET_ERROR_TYPE_INFO, "Denomination key %s already active, skipping\n", GNUNET_h2s (&d->h_denom_pub.hash)); @@ -216,7 +293,17 @@ add_keys (void *cls, } if (GNUNET_DB_STATUS_SUCCESS_ONE_RESULT == qs) { - /* FIXME: assert meta === d->meta might be good */ + if (! signkey_meta_cmp (&s->meta, + &meta)) + { + GNUNET_break_op (0); + *mhd_ret = TALER_MHD_reply_with_error ( + connection, + MHD_HTTP_CONFLICT, + TALER_EC_EXCHANGE_MANAGEMENT_CONFLICTING_SIGNKEY_META_DATA, + "conflicting meta data previously set for the same signing key"); + return GNUNET_DB_STATUS_HARD_ERROR; + } GNUNET_log (GNUNET_ERROR_TYPE_INFO, "Signing key %s already active, skipping\n", TALER_B2S (&s->exchange_pub)); diff --git a/src/include/taler_exchangedb_plugin.h b/src/include/taler_exchangedb_plugin.h @@ -1005,6 +1005,8 @@ struct TALER_EXCHANGEDB_Reserve /** * Meta data about a denomination public key. + * If this is changed, you must also adjust + * taler-exchange-httpd_management_post_keys.c::denomination_meta_cmp(). */ struct TALER_EXCHANGEDB_DenominationKeyMetaData {