commit 3c76780d16abacb829d29b4d8ea882852218789d
parent 84bd5a2f569516ed9c8617b25da17cac7adeac44
Author: Christian Grothoff <christian@grothoff.org>
Date: Sun, 2 Aug 2026 21:07:48 +0200
prevent OOB on trait tokens (testing library)
Diffstat:
2 files changed, 32 insertions(+), 18 deletions(-)
diff --git a/src/backend/taler-merchant-httpd_mfa.c b/src/backend/taler-merchant-httpd_mfa.c
@@ -189,6 +189,26 @@ mfa_challenge_check (
case GNUNET_DB_STATUS_SUCCESS_ONE_RESULT:
break;
}
+
+ /* The MFA challenge table (merchant.tan_challenges) is global across
+ instances and challenge IDs are only unique globally. Ensure the
+ challenge actually belongs to the instance handling this request;
+ otherwise one instance could satisfy its MFA requirement using
+ another instance's challenge. (Defense-in-depth: challenge_id and
+ the body hash already bind the challenge to a specific request.) */
+ if ( (NULL != hc->instance) &&
+ (NULL != hc->instance->settings.id) &&
+ ( (NULL == instance_id) ||
+ (0 != strcmp (instance_id,
+ hc->instance->settings.id)) ) )
+ {
+ GNUNET_log (GNUNET_ERROR_TYPE_WARNING,
+ "Challenge %s is for a different instance!\n",
+ challenge_id);
+ GNUNET_free (instance_id);
+ *solved = false;
+ return GNUNET_OK;
+ }
GNUNET_free (instance_id);
if (xop != op)
diff --git a/src/testing/testing_api_cmd_pay_order.c b/src/testing/testing_api_cmd_pay_order.c
@@ -1508,19 +1508,11 @@ pay_traits (void *cls,
const char *trait,
unsigned int index)
{
-
struct PayState *ps = cls;
const char *order_id;
const struct TALER_TESTING_Command *proposal_cmd;
const struct TALER_MerchantPublicKeyP *merchant_pub;
- if (NULL != ps->token_reference &&
- index >= ps->num_issued_tokens)
- {
- GNUNET_break (0);
- return GNUNET_NO;
- }
-
if (NULL ==
(proposal_cmd =
TALER_TESTING_interpreter_lookup_command (ps->is,
@@ -1551,6 +1543,16 @@ pay_traits (void *cls,
&ps->amount_with_fee_parsed));
{
struct TALER_TESTING_Trait traits[] = {
+ /* these must be first, see 'off' below */
+ TALER_TESTING_make_trait_token_priv (
+ index,
+ &ps->issued_tokens[index].token_priv),
+ TALER_TESTING_make_trait_token_issue_pub (
+ index,
+ &ps->issued_tokens[index].issue_pub),
+ TALER_TESTING_make_trait_token_issue_sig (
+ index,
+ &ps->issued_tokens[index].issue_sig),
TALER_TESTING_make_trait_proposal_reference (ps->proposal_reference),
TALER_TESTING_make_trait_coin_reference (0,
ps->coin_reference),
@@ -1560,19 +1562,11 @@ pay_traits (void *cls,
TALER_TESTING_make_trait_amount (&ps->amount_with_fee_parsed),
TALER_TESTING_make_trait_otp_key (ps->pos_key),
TALER_TESTING_make_trait_otp_alg (&ps->pos_alg),
- TALER_TESTING_make_trait_token_priv (index,
- &ps->issued_tokens[index].
- token_priv),
- TALER_TESTING_make_trait_token_issue_pub (index,
- &ps->issued_tokens[index].
- issue_pub),
- TALER_TESTING_make_trait_token_issue_sig (index,
- &ps->issued_tokens[index].
- issue_sig),
TALER_TESTING_trait_end ()
};
+ unsigned int off = (index >= ps->num_issued_tokens) ? 3 : 0;
- return TALER_TESTING_get_trait (traits,
+ return TALER_TESTING_get_trait (&traits[off],
ret,
trait,
index);