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:
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
{