add logic to check signature over fees in /wire response (fixes #7802)

This commit is contained in:
Christian Grothoff 2023-04-13 17:30:53 +02:00
parent 4e9c43954e
commit eb2b4a131b
No known key found for this signature in database
GPG Key ID: 939E6BE1E29FC3CC

View File

@ -111,11 +111,13 @@ free_fees (struct FeeMap *fm)
/** /**
* Parse wire @a fees and return map. * Parse wire @a fees and return map.
* *
* @param master_pub master public key to use to check signatures
* @param fees json AggregateTransferFee to parse * @param fees json AggregateTransferFee to parse
* @return NULL on error * @return NULL on error
*/ */
static struct FeeMap * static struct FeeMap *
parse_fees (json_t *fees) parse_fees (const struct TALER_MasterPublicKeyP *master_pub,
json_t *fees)
{ {
struct FeeMap *fm = NULL; struct FeeMap *fm = NULL;
const char *key; const char *key;
@ -164,6 +166,19 @@ parse_fees (json_t *fees)
free_fees (fm); free_fees (fm);
return NULL; return NULL;
} }
if (GNUNET_OK !=
TALER_exchange_offline_wire_fee_verify (
key,
wa->start_date,
wa->end_date,
&wa->fees,
master_pub,
&wa->master_sig))
{
GNUNET_break_op (0);
free_fees (fm);
return NULL;
}
if (idx + 1 < len) if (idx + 1 < len)
wa->next = &fe->fee_list[idx + 1]; wa->next = &fe->fee_list[idx + 1];
else else
@ -227,8 +242,10 @@ handle_wire_finished (void *cls,
json_t *fees; json_t *fees;
unsigned int num_accounts; unsigned int num_accounts;
struct FeeMap *fm; struct FeeMap *fm;
const struct TALER_EXCHANGE_Keys *key_state; struct TALER_MasterPublicKeyP master_pub;
struct GNUNET_JSON_Specification spec[] = { struct GNUNET_JSON_Specification spec[] = {
GNUNET_JSON_spec_fixed_auto ("master_public_key",
&master_pub),
GNUNET_JSON_spec_json ("accounts", GNUNET_JSON_spec_json ("accounts",
&accounts), &accounts),
GNUNET_JSON_spec_json ("fees", GNUNET_JSON_spec_json ("fees",
@ -249,6 +266,21 @@ handle_wire_finished (void *cls,
hr.ec = TALER_EC_GENERIC_REPLY_MALFORMED; hr.ec = TALER_EC_GENERIC_REPLY_MALFORMED;
break; break;
} }
{
const struct TALER_EXCHANGE_Keys *key_state;
key_state = TALER_EXCHANGE_get_keys (wh->exchange);
if (0 != GNUNET_memcmp (&key_state->master_pub,
&master_pub))
{
/* bogus reply: master public key in /wire differs from that in /keys */
GNUNET_break_op (0);
hr.http_status = 0;
hr.ec = TALER_EC_GENERIC_REPLY_MALFORMED;
break;
}
}
if (0 == (num_accounts = json_array_size (accounts))) if (0 == (num_accounts = json_array_size (accounts)))
{ {
/* bogus reply */ /* bogus reply */
@ -258,7 +290,8 @@ handle_wire_finished (void *cls,
hr.ec = TALER_EC_GENERIC_REPLY_MALFORMED; hr.ec = TALER_EC_GENERIC_REPLY_MALFORMED;
break; break;
} }
if (NULL == (fm = parse_fees (fees))) if (NULL == (fm = parse_fees (&master_pub,
fees)))
{ {
/* bogus reply */ /* bogus reply */
GNUNET_break_op (0); GNUNET_break_op (0);
@ -268,7 +301,6 @@ handle_wire_finished (void *cls,
break; break;
} }
key_state = TALER_EXCHANGE_get_keys (wh->exchange);
/* parse accounts */ /* parse accounts */
{ {
struct TALER_EXCHANGE_WireAccount was[num_accounts]; struct TALER_EXCHANGE_WireAccount was[num_accounts];
@ -290,7 +322,7 @@ handle_wire_finished (void *cls,
i); i);
if (GNUNET_OK != if (GNUNET_OK !=
TALER_JSON_exchange_wire_signature_check (account, TALER_JSON_exchange_wire_signature_check (account,
&key_state->master_pub)) &master_pub))
{ {
/* bogus reply */ /* bogus reply */
GNUNET_break_op (0); GNUNET_break_op (0);