return signed 404 statements for unknown denomination key hashes (#6889)

This commit is contained in:
Christian Grothoff 2021-05-25 20:52:58 +02:00
parent b2b1f88ab6
commit 0d1ab614c0
No known key found for this signature in database
GPG Key ID: 939E6BE1E29FC3CC
11 changed files with 137 additions and 78 deletions

View File

@ -431,21 +431,16 @@ TEH_handler_deposit (struct MHD_Connection *connection,
/* check denomination exists and is valid */ /* check denomination exists and is valid */
{ {
struct TEH_DenominationKey *dk; struct TEH_DenominationKey *dk;
enum TALER_ErrorCode ec;
unsigned int hc;
struct GNUNET_TIME_Absolute now; struct GNUNET_TIME_Absolute now;
MHD_RESULT mret;
dk = TEH_keys_denomination_by_hash (&deposit.coin.denom_pub_hash, dk = TEH_keys_denomination_by_hash (&deposit.coin.denom_pub_hash,
&ec, connection,
&hc); &mret);
if (NULL == dk) if (NULL == dk)
{ {
TALER_LOG_DEBUG ("Unknown denomination key in /deposit request\n");
GNUNET_JSON_parse_free (spec); GNUNET_JSON_parse_free (spec);
return TALER_MHD_reply_with_error (connection, return mret;
hc,
ec,
NULL);
} }
now = GNUNET_TIME_absolute_get (); now = GNUNET_TIME_absolute_get ();
if (now.abs_value_us >= dk->meta.expire_deposit.abs_value_us) if (now.abs_value_us >= dk->meta.expire_deposit.abs_value_us)

View File

@ -1801,30 +1801,32 @@ TEH_keys_get_state (void)
struct TEH_DenominationKey * struct TEH_DenominationKey *
TEH_keys_denomination_by_hash (const struct GNUNET_HashCode *h_denom_pub, TEH_keys_denomination_by_hash (const struct GNUNET_HashCode *h_denom_pub,
enum TALER_ErrorCode *ec, struct MHD_Connection *conn,
unsigned int *hc) MHD_RESULT *mret)
{ {
struct TEH_KeyStateHandle *ksh; struct TEH_KeyStateHandle *ksh;
ksh = TEH_keys_get_state (); ksh = TEH_keys_get_state ();
if (NULL == ksh) if (NULL == ksh)
{ {
*hc = MHD_HTTP_INTERNAL_SERVER_ERROR; *mret = TALER_MHD_reply_with_error (conn,
*ec = TALER_EC_EXCHANGE_GENERIC_KEYS_MISSING; MHD_HTTP_INTERNAL_SERVER_ERROR,
TALER_EC_EXCHANGE_GENERIC_KEYS_MISSING,
NULL);
return NULL; return NULL;
} }
return TEH_keys_denomination_by_hash2 (ksh, return TEH_keys_denomination_by_hash2 (ksh,
h_denom_pub, h_denom_pub,
ec, conn,
hc); mret);
} }
struct TEH_DenominationKey * struct TEH_DenominationKey *
TEH_keys_denomination_by_hash2 (struct TEH_KeyStateHandle *ksh, TEH_keys_denomination_by_hash2 (struct TEH_KeyStateHandle *ksh,
const struct GNUNET_HashCode *h_denom_pub, const struct GNUNET_HashCode *h_denom_pub,
enum TALER_ErrorCode *ec, struct MHD_Connection *conn,
unsigned int *hc) MHD_RESULT *mret)
{ {
struct TEH_DenominationKey *dk; struct TEH_DenominationKey *dk;
@ -1832,8 +1834,8 @@ TEH_keys_denomination_by_hash2 (struct TEH_KeyStateHandle *ksh,
h_denom_pub); h_denom_pub);
if (NULL == dk) if (NULL == dk)
{ {
*hc = MHD_HTTP_NOT_FOUND; *mret = TEH_RESPONSE_reply_unknown_denom_pub_hash (conn,
*ec = TALER_EC_EXCHANGE_GENERIC_DENOMINATION_KEY_UNKNOWN; h_denom_pub);
return NULL; return NULL;
} }
return dk; return dk;

View File

@ -129,15 +129,15 @@ TEH_keys_update_states (void);
* key state is resolved. * key state is resolved.
* *
* @param h_denom_pub hash of denomination public key * @param h_denom_pub hash of denomination public key
* @param[out] ec set to the error code, in case the operation failed * @param[in,out] connection used to return status message if NULL is returned
* @param[out] hc set to the HTTP status code to use * @param[out] mret set to the MHD status if NULL is returned
* @return the denomination key issue, * @return the denomination key issue,
* or NULL if @a h_denom_pub could not be found * or NULL if @a h_denom_pub could not be found
*/ */
struct TEH_DenominationKey * struct TEH_DenominationKey *
TEH_keys_denomination_by_hash (const struct GNUNET_HashCode *h_denom_pub, TEH_keys_denomination_by_hash (const struct GNUNET_HashCode *h_denom_pub,
enum TALER_ErrorCode *ec, struct MHD_Connection *conn,
unsigned int *hc); MHD_RESULT *mret);
/** /**
@ -148,16 +148,16 @@ TEH_keys_denomination_by_hash (const struct GNUNET_HashCode *h_denom_pub,
* *
* @param ksh key state state to look in * @param ksh key state state to look in
* @param h_denom_pub hash of denomination public key * @param h_denom_pub hash of denomination public key
* @param[out] ec set to the error code, in case the operation failed * @param[in,out] connection used to return status message if NULL is returned
* @param[out] hc set to the HTTP status code to use * @param[out] mret set to the MHD status if NULL is returned
* @return the denomination key issue, * @return the denomination key issue,
* or NULL if @a h_denom_pub could not be found * or NULL if @a h_denom_pub could not be found
*/ */
struct TEH_DenominationKey * struct TEH_DenominationKey *
TEH_keys_denomination_by_hash2 (struct TEH_KeyStateHandle *ksh, TEH_keys_denomination_by_hash2 (struct TEH_KeyStateHandle *ksh,
const struct GNUNET_HashCode *h_denom_pub, const struct GNUNET_HashCode *h_denom_pub,
enum TALER_ErrorCode *ec, struct MHD_Connection *conn,
unsigned int *hc); MHD_RESULT *mret);
/** /**
* Request to sign @a msg using the public key corresponding to * Request to sign @a msg using the public key corresponding to

View File

@ -466,22 +466,15 @@ check_for_denomination_key (struct MHD_Connection *connection,
/* Baseline: check if deposits/refreshs are generally /* Baseline: check if deposits/refreshs are generally
simply still allowed for this denomination */ simply still allowed for this denomination */
struct TEH_DenominationKey *dk; struct TEH_DenominationKey *dk;
unsigned int hc;
enum TALER_ErrorCode ec;
struct GNUNET_TIME_Absolute now; struct GNUNET_TIME_Absolute now;
MHD_RESULT mret;
dk = TEH_keys_denomination_by_hash ( dk = TEH_keys_denomination_by_hash (
&rmc->refresh_session.coin.denom_pub_hash, &rmc->refresh_session.coin.denom_pub_hash,
&ec, connection,
&hc); &mret);
if (NULL == dk) if (NULL == dk)
{ return mret;
return TALER_MHD_reply_with_error (
connection,
MHD_HTTP_NOT_FOUND,
TALER_EC_EXCHANGE_GENERIC_DENOMINATION_KEY_UNKNOWN,
NULL);
}
now = GNUNET_TIME_absolute_get (); now = GNUNET_TIME_absolute_get ();
if (now.abs_value_us >= dk->meta.expire_legal.abs_value_us) if (now.abs_value_us >= dk->meta.expire_legal.abs_value_us)
{ {

View File

@ -363,24 +363,15 @@ verify_and_execute_recoup (struct MHD_Connection *connection,
struct GNUNET_HashCode c_hash; struct GNUNET_HashCode c_hash;
void *coin_ev; void *coin_ev;
size_t coin_ev_size; size_t coin_ev_size;
enum TALER_ErrorCode ec; MHD_RESULT mret;
unsigned int hc;
struct GNUNET_TIME_Absolute now; struct GNUNET_TIME_Absolute now;
/* check denomination exists and is in recoup mode */ /* check denomination exists and is in recoup mode */
dk = TEH_keys_denomination_by_hash (&coin->denom_pub_hash, dk = TEH_keys_denomination_by_hash (&coin->denom_pub_hash,
&ec, connection,
&hc); &mret);
if (NULL == dk) if (NULL == dk)
{ return mret;
TALER_LOG_WARNING (
"Denomination key in recoup request not in recoup mode\n");
return TALER_MHD_reply_with_error (connection,
hc,
ec,
NULL);
}
now = GNUNET_TIME_absolute_get (); now = GNUNET_TIME_absolute_get ();
if (now.abs_value_us >= dk->meta.expire_deposit.abs_value_us) if (now.abs_value_us >= dk->meta.expire_deposit.abs_value_us)
{ {

View File

@ -565,8 +565,7 @@ resolve_refreshes_reveal_denominations (struct MHD_Connection *connection,
&dk_h[i]), &dk_h[i]),
GNUNET_JSON_spec_end () GNUNET_JSON_spec_end ()
}; };
unsigned int hc; MHD_RESULT mret;
enum TALER_ErrorCode ec;
res = TALER_MHD_parse_json_array (connection, res = TALER_MHD_parse_json_array (connection,
new_denoms_h_json, new_denoms_h_json,
@ -579,15 +578,10 @@ resolve_refreshes_reveal_denominations (struct MHD_Connection *connection,
} }
dks[i] = TEH_keys_denomination_by_hash2 (ksh, dks[i] = TEH_keys_denomination_by_hash2 (ksh,
&dk_h[i], &dk_h[i],
&ec, connection,
&hc); &mret);
if (NULL == dks[i]) if (NULL == dks[i])
{ return mret;
return TALER_MHD_reply_with_error (connection,
hc,
ec,
NULL);
}
if (now.abs_value_us >= dks[i]->meta.expire_withdraw.abs_value_us) if (now.abs_value_us >= dks[i]->meta.expire_withdraw.abs_value_us)
{ {

View File

@ -449,21 +449,17 @@ verify_and_execute_refund (struct MHD_Connection *connection,
{ {
/* Obtain information about the coin's denomination! */ /* Obtain information about the coin's denomination! */
struct TEH_DenominationKey *dk; struct TEH_DenominationKey *dk;
unsigned int hc; MHD_RESULT mret;
enum TALER_ErrorCode ec;
dk = TEH_keys_denomination_by_hash (&denom_hash, dk = TEH_keys_denomination_by_hash (&denom_hash,
&ec, connection,
&hc); &mret);
if (NULL == dk) if (NULL == dk)
{ {
/* DKI not found, but we do have a coin with this DK in our database; /* DKI not found, but we do have a coin with this DK in our database;
not good... */ not good... */
GNUNET_break (0); GNUNET_break (0);
return TALER_MHD_reply_with_error (connection, return mret;
hc,
ec,
NULL);
} }
if (GNUNET_TIME_absolute_get ().abs_value_us >= if (GNUNET_TIME_absolute_get ().abs_value_us >=

View File

@ -1,6 +1,6 @@
/* /*
This file is part of TALER This file is part of TALER
Copyright (C) 2014-2017 Taler Systems SA Copyright (C) 2014-2021 Taler Systems SA
TALER is free software; you can redistribute it and/or modify it under the TALER is free software; you can redistribute it and/or modify it under the
terms of the GNU Affero General Public License as published by the Free Software terms of the GNU Affero General Public License as published by the Free Software
@ -417,6 +417,55 @@ TEH_RESPONSE_compile_transaction_history (
} }
MHD_RESULT
TEH_RESPONSE_reply_unknown_denom_pub_hash (
struct MHD_Connection *connection,
const struct GNUNET_HashCode *dph)
{
struct TALER_ExchangePublicKeyP epub;
struct TALER_ExchangeSignatureP esig;
struct GNUNET_TIME_Absolute now;
enum TALER_ErrorCode ec;
now = GNUNET_TIME_absolute_get ();
GNUNET_TIME_round_abs (&now);
{
struct TALER_DenominationUnknownAffirmationPS dua = {
.purpose.size = htonl (sizeof (dua)),
.purpose.purpose = htonl (TALER_SIGNATURE_EXCHANGE_AFFIRM_DENOM_UNKNOWN),
.timestamp = GNUNET_TIME_absolute_hton (now),
.h_denom_pub = *dph,
};
ec = TEH_keys_exchange_sign (&dua,
&epub,
&esig);
}
if (TALER_EC_NONE != ec)
{
GNUNET_break (0);
return TALER_MHD_reply_with_error (connection,
MHD_HTTP_INTERNAL_SERVER_ERROR,
ec,
NULL);
}
return TALER_MHD_reply_json_pack (
connection,
MHD_HTTP_NOT_FOUND,
"{s:I,s:o,s:o,s:o,s:o}",
"code",
TALER_EC_EXCHANGE_GENERIC_DENOMINATION_KEY_UNKNOWN,
"timestamp",
GNUNET_JSON_from_time_abs (now),
"exchange_pub",
GNUNET_JSON_from_data_auto (&epub),
"exchange_sig",
GNUNET_JSON_from_data_auto (&esig),
"h_denom_pub",
GNUNET_JSON_from_data_auto (dph));
}
/** /**
* Send proof that a request is invalid to client because of * Send proof that a request is invalid to client because of
* insufficient funds. This function will create a message with all * insufficient funds. This function will create a message with all

View File

@ -48,6 +48,20 @@ TEH_RESPONSE_compile_reserve_history (
struct TALER_Amount *balance); struct TALER_Amount *balance);
/**
* Send assertion that the given denomination key hash
* is unknown to us at this time.
*
* @param connection connection to the client
* @param dph denomination public key hash
* @return MHD result code
*/
MHD_RESULT
TEH_RESPONSE_reply_unknown_denom_pub_hash (
struct MHD_Connection *connection,
const struct GNUNET_HashCode *dph);
/** /**
* Send proof that a request is invalid to client because of * Send proof that a request is invalid to client because of
* insufficient funds. This function will create a message with all * insufficient funds. This function will create a message with all

View File

@ -379,20 +379,16 @@ TEH_handler_withdraw (const struct TEH_RequestHandler *rh,
return (GNUNET_SYSERR == res) ? MHD_NO : MHD_YES; return (GNUNET_SYSERR == res) ? MHD_NO : MHD_YES;
} }
{ {
unsigned int hc; MHD_RESULT mret;
enum TALER_ErrorCode ec;
struct GNUNET_TIME_Absolute now; struct GNUNET_TIME_Absolute now;
dk = TEH_keys_denomination_by_hash (&wc.denom_pub_hash, dk = TEH_keys_denomination_by_hash (&wc.denom_pub_hash,
&ec, connection,
&hc); &mret);
if (NULL == dk) if (NULL == dk)
{ {
GNUNET_JSON_parse_free (spec); GNUNET_JSON_parse_free (spec);
return TALER_MHD_reply_with_error (connection, return mret;
hc,
ec,
NULL);
} }
now = GNUNET_TIME_absolute_get (); now = GNUNET_TIME_absolute_get ();
if (now.abs_value_us >= dk->meta.expire_withdraw.abs_value_us) if (now.abs_value_us >= dk->meta.expire_withdraw.abs_value_us)

View File

@ -155,6 +155,11 @@
*/ */
#define TALER_SIGNATURE_EXCHANGE_CONFIRM_RECOUP_REFRESH 1041 #define TALER_SIGNATURE_EXCHANGE_CONFIRM_RECOUP_REFRESH 1041
/**
* Signature where the Exchange confirms that it does not know a denomination (hash).
*/
#define TALER_SIGNATURE_EXCHANGE_AFFIRM_DENOM_UNKNOWN 1042
/**********************/ /**********************/
/* Auditor signatures */ /* Auditor signatures */
@ -1514,6 +1519,30 @@ struct TALER_RecoupRefreshConfirmationPS
}; };
/**
* Response by which the exchange affirms that it does not
* currently know a denomination by the given hash.
*/
struct TALER_DenominationUnknownAffirmationPS
{
/**
* Purpose is #TALER_SIGNATURE_EXCHANGE_AFFIRM_DENOM_UNKNOWN
*/
struct GNUNET_CRYPTO_EccSignaturePurpose purpose;
/**
* When did the exchange sign this message.
*/
struct GNUNET_TIME_AbsoluteNBO timestamp;
/**
* Hash of the public denomination key we do not know.
*/
struct GNUNET_HashCode h_denom_pub;
};
/** /**
* Response by which the exchange affirms that it has * Response by which the exchange affirms that it has
* closed a reserve and send back the funds. * closed a reserve and send back the funds.