commit 0cae15196ceb54817b33c6889aeb0322f431fff4
parent 20a7fc60c486342b5203ce9e1467bc111b51f47b
Author: Christian Grothoff <christian@grothoff.org>
Date: Tue, 3 Nov 2026 23:00:34 +0100
do not skip check if merely the timestamp matches
Diffstat:
1 file changed, 43 insertions(+), 4 deletions(-)
diff --git a/src/auditor/taler-helper-auditor-aml.c b/src/auditor/taler-helper-auditor-aml.c
@@ -157,6 +157,12 @@ struct StaffStatus
bool read_only;
/**
+ * Hash of the legal name of the member at this status. Kept instead of
+ * the name itself so that the entry owns no memory.
+ */
+ struct GNUNET_HashCode h_name;
+
+ /**
* Did the exchange's offline master key actually sign this status?
* A status that fails this check confers no authority.
*/
@@ -221,6 +227,24 @@ staff_key (const struct TALER_AmlOfficerPublicKeyP *decider_pub,
/**
+ * Compute the hash of the legal name @a decider_name.
+ *
+ * @param decider_name legal name of the staff member, NULL if not given
+ * @param[out] h_name set to the hash to use
+ */
+static void
+staff_name_hash (const char *decider_name,
+ struct GNUNET_HashCode *h_name)
+{
+ if (NULL == decider_name)
+ decider_name = "";
+ GNUNET_CRYPTO_hash (decider_name,
+ strlen (decider_name),
+ h_name);
+}
+
+
+/**
* Look up @a decider_pub in #staff_map, creating the entry if needed.
*
* @param decider_pub public key of the staff member
@@ -375,7 +399,8 @@ known_staff_cb (void *cls,
};
(void) cls;
- (void) decider_name;
+ staff_name_hash (decider_name,
+ &ss.h_name);
staff_member_add (sm,
&ss);
/* We are called oldest-first, so the last call for a member leaves the
@@ -423,13 +448,27 @@ check_staff_cb (void *cls,
(void) cls;
TALER_ARL_USE_PP (aml_staff_uuid) = rowid + 1;
+ staff_name_hash (decider_name,
+ &ss.h_name);
for (unsigned int i = 0; i < sm->num_statuses; i++)
{
- if (GNUNET_TIME_timestamp_cmp (sm->statuses[i].last_change,
+ const struct StaffStatus *os = &sm->statuses[i];
+
+ if (GNUNET_TIME_timestamp_cmp (os->last_change,
==,
last_change))
- return GNUNET_OK; /* already seen and judged in an earlier round */
- if (GNUNET_TIME_timestamp_cmp (sm->statuses[i].last_change,
+ {
+ if ( (os->is_active == is_active) &&
+ (os->read_only == read_only) &&
+ (0 == GNUNET_memcmp (&os->h_name,
+ &ss.h_name)) )
+ return GNUNET_OK; /* already seen and judged in an earlier round */
+ /* Same timestamp, but a different status: this widens (or narrows) the
+ officer's authority and must be judged and recorded like any other
+ status change. */
+ continue;
+ }
+ if (GNUNET_TIME_timestamp_cmp (os->last_change,
>,
last_change))
regression = true;