improve status codes returned in case of denomination key troubles

This commit is contained in:
Christian Grothoff 2019-11-01 15:36:14 +01:00
parent 40d9674856
commit 375a47d502
No known key found for this signature in database
GPG Key ID: 939E6BE1E29FC3CC
11 changed files with 224 additions and 33 deletions

View File

@ -250,6 +250,8 @@ verify_and_execute_deposit (struct MHD_Connection *connection,
struct DepositContext dc;
struct TEH_KS_StateHandle *mks;
const struct TALER_EXCHANGEDB_DenominationKeyIssueInformation *dki;
enum TALER_ErrorCode ec;
unsigned int hc;
/* check signature */
dr.purpose.purpose = htonl (TALER_SIGNATURE_WALLET_COIN_DEPOSIT);
@ -287,12 +289,15 @@ verify_and_execute_deposit (struct MHD_Connection *connection,
}
dki = TEH_KS_denomination_key_lookup_by_hash (mks,
&deposit->coin.denom_pub_hash,
TEH_KS_DKU_DEPOSIT);
TEH_KS_DKU_DEPOSIT,
&ec,
&hc);
if (NULL == dki)
{
TEH_KS_release (mks);
return TEH_RESPONSE_reply_internal_db_error (connection,
TALER_EC_DEPOSIT_DB_DENOMINATION_KEY_UNKNOWN);
return TEH_RESPONSE_reply_with_error (connection,
ec,
hc);
}
TALER_amount_ntoh (&dc.value,
&dki->issue.properties.value);
@ -388,6 +393,7 @@ TEH_DEPOSIT_handler_deposit (struct TEH_RequestHandler *rh,
json_t *wire;
char *emsg;
enum TALER_ErrorCode ec;
unsigned int hc;
struct TALER_EXCHANGEDB_Deposit deposit;
struct TALER_EXCHANGEDB_DenominationKeyIssueInformation *dki;
struct TEH_KS_StateHandle *key_state;
@ -497,16 +503,17 @@ TEH_DEPOSIT_handler_deposit (struct TEH_RequestHandler *rh,
}
dki = TEH_KS_denomination_key_lookup_by_hash (key_state,
&deposit.coin.denom_pub_hash,
TEH_KS_DKU_DEPOSIT);
TEH_KS_DKU_DEPOSIT,
&ec,
&hc);
if (NULL == dki)
{
/* FIXME: #3887: if DK was revoked, we might want to give a 403 and not a 404! */
TEH_KS_release (key_state);
TALER_LOG_WARNING ("Unknown denomination key in /deposit request\n");
GNUNET_JSON_parse_free (spec);
return TEH_RESPONSE_reply_arg_unknown (connection,
TALER_EC_DEPOSIT_DENOMINATION_KEY_UNKNOWN,
"denom_pub");
return TEH_RESPONSE_reply_with_error (connection,
ec,
hc);
}
TALER_amount_ntoh (&deposit.deposit_fee,
&dki->issue.properties.fee_deposit);

View File

@ -1954,6 +1954,8 @@ TEH_KS_acquire_ (struct GNUNET_TIME_Absolute now,
* @param key_state state to look in
* @param denom_pub_hash hash of denomination public key
* @param use purpose for which the key is being located
* @param ec[out] set to the error code, in case the operation failed
* @param hc[out] set to the HTTP status code to use
* @return the denomination key issue,
* or NULL if denom_pub could not be found (or is not valid at this time for the given @a use)
*/
@ -1962,7 +1964,9 @@ TEH_KS_denomination_key_lookup_by_hash (const struct
TEH_KS_StateHandle *key_state,
const struct
GNUNET_HashCode *denom_pub_hash,
enum TEH_KS_DenominationKeyUse use)
enum TEH_KS_DenominationKeyUse use,
enum TALER_ErrorCode *ec,
unsigned int *hc)
{
struct TALER_EXCHANGEDB_DenominationKeyIssueInformation *dki;
struct GNUNET_TIME_Absolute now;
@ -1976,7 +1980,25 @@ TEH_KS_denomination_key_lookup_by_hash (const struct
dki = GNUNET_CONTAINER_multihashmap_get (key_state->revoked_map,
denom_pub_hash);
if (NULL == dki)
{
*hc = MHD_HTTP_NOT_FOUND;
switch (use)
{
case TEH_KS_DKU_PAYBACK:
*ec = TALER_EC_PAYBACK_DENOMINATION_KEY_UNKNOWN;
break;
case TEH_KS_DKU_ZOMBIE:
*ec = TALER_EC_REFRESH_PAYBACK_DENOMINATION_KEY_NOT_FOUND;
break;
case TEH_KS_DKU_WITHDRAW:
*ec = TALER_EC_WITHDRAW_DENOMINATION_KEY_NOT_FOUND;
break;
case TEH_KS_DKU_DEPOSIT:
*ec = TALER_EC_DEPOSIT_DENOMINATION_KEY_UNKNOWN;
break;
}
return NULL;
}
now = GNUNET_TIME_absolute_get ();
if (now.abs_value_us <
GNUNET_TIME_absolute_ntoh (dki->issue.properties.start).abs_value_us)
@ -1984,6 +2006,22 @@ TEH_KS_denomination_key_lookup_by_hash (const struct
GNUNET_log (GNUNET_ERROR_TYPE_INFO,
"Not returning DKI for %s, as start time is in the future\n",
GNUNET_h2s (denom_pub_hash));
*hc = MHD_HTTP_PRECONDITION_FAILED;
switch (use)
{
case TEH_KS_DKU_PAYBACK:
*ec = TALER_EC_PAYBACK_DENOMINATION_VALIDITY_IN_FUTURE;
break;
case TEH_KS_DKU_ZOMBIE:
*ec = TALER_EC_REFRESH_PAYBACK_DENOMINATION_VALIDITY_IN_FUTURE;
break;
case TEH_KS_DKU_WITHDRAW:
*ec = TALER_EC_WITHDRAW_VALIDITY_IN_FUTURE;
break;
case TEH_KS_DKU_DEPOSIT:
*ec = TALER_EC_DEPOSIT_DENOMINATION_VALIDITY_IN_FUTURE;
break;
}
return NULL;
}
now = GNUNET_TIME_absolute_get ();
@ -1997,6 +2035,8 @@ TEH_KS_denomination_key_lookup_by_hash (const struct
GNUNET_log (GNUNET_ERROR_TYPE_INFO,
"Not returning DKI for %s, as time to create coins has passed\n",
GNUNET_h2s (denom_pub_hash));
*ec = TALER_EC_WITHDRAW_VALIDITY_IN_PAST;
*hc = MHD_HTTP_GONE;
return NULL;
}
if (NULL == dki->denom_priv.rsa_private_key)
@ -2004,6 +2044,8 @@ TEH_KS_denomination_key_lookup_by_hash (const struct
GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
"Not returning DKI of %s for WITHDRAW operation as we lack the private key, even though the withdraw period did not yet expire!\n",
GNUNET_h2s (denom_pub_hash));
*ec = TALER_EC_DENOMINATION_KEY_LOST;
*hc = MHD_HTTP_SERVICE_UNAVAILABLE;
return NULL;
}
break;
@ -2015,6 +2057,8 @@ TEH_KS_denomination_key_lookup_by_hash (const struct
GNUNET_log (GNUNET_ERROR_TYPE_INFO,
"Not returning DKI for %s, as time to spend coin has passed\n",
GNUNET_h2s (denom_pub_hash));
*ec = TALER_EC_DEPOSIT_DENOMINATION_EXPIRED;
*hc = MHD_HTTP_GONE;
return NULL;
}
break;
@ -2026,6 +2070,8 @@ TEH_KS_denomination_key_lookup_by_hash (const struct
GNUNET_log (GNUNET_ERROR_TYPE_INFO,
"Not returning DKI for %s, as time to payback coin has passed\n",
GNUNET_h2s (denom_pub_hash));
*ec = TALER_EC_REFRESH_PAYBACK_DENOMINATION_EXPIRED;
*hc = MHD_HTTP_GONE;
return NULL;
}
break;
@ -2037,6 +2083,8 @@ TEH_KS_denomination_key_lookup_by_hash (const struct
GNUNET_log (GNUNET_ERROR_TYPE_INFO,
"Not returning DKI for %s, as legal expiration of coin has passed\n",
GNUNET_h2s (denom_pub_hash));
*ec = TALER_EC_REFRESH_ZOMBIE_DENOMINATION_EXPIRED;
*hc = MHD_HTTP_GONE;
return NULL;
}
break;

View File

@ -129,6 +129,8 @@ enum TEH_KS_DenominationKeyUse
* @param key_state state to look in
* @param denom_pub_hash hash of denomination public key
* @param use purpose for which the key is being located
* @param ec[out] set to the error code, in case the operation failed
* @param hc[out] set to the HTTP status code to use
* @return the denomination key issue,
* or NULL if denom_pub could not be found (or is not valid at this time for the given @a use)
*/
@ -137,7 +139,9 @@ TEH_KS_denomination_key_lookup_by_hash (const struct
TEH_KS_StateHandle *key_state,
const struct
GNUNET_HashCode *denom_pub_hash,
enum TEH_KS_DenominationKeyUse use);
enum TEH_KS_DenominationKeyUse use,
enum TALER_ErrorCode *ec,
unsigned int *hc);
/**

View File

@ -429,6 +429,8 @@ verify_and_execute_payback (struct MHD_Connection *connection,
struct GNUNET_HashCode c_hash;
char *coin_ev;
size_t coin_ev_size;
enum TALER_ErrorCode ec;
unsigned int hc;
/* check denomination exists and is in payback mode */
key_state = TEH_KS_acquire (GNUNET_TIME_absolute_get ());
@ -441,15 +443,17 @@ verify_and_execute_payback (struct MHD_Connection *connection,
}
dki = TEH_KS_denomination_key_lookup_by_hash (key_state,
&coin->denom_pub_hash,
TEH_KS_DKU_PAYBACK);
TEH_KS_DKU_PAYBACK,
&ec,
&hc);
if (NULL == dki)
{
TEH_KS_release (key_state);
TALER_LOG_WARNING (
"Denomination key in /payback request not in payback mode\n");
return TEH_RESPONSE_reply_arg_unknown (connection,
TALER_EC_PAYBACK_DENOMINATION_KEY_UNKNOWN,
"denom_pub");
return TEH_RESPONSE_reply_with_error (connection,
ec,
hc);
}
TALER_amount_ntoh (&pc.value,
&dki->issue.properties.value);

View File

@ -447,6 +447,8 @@ TEH_REFRESH_handler_refresh_melt (struct TEH_RequestHandler *rh,
json_t *root;
struct RefreshMeltContext rmc;
int res;
unsigned int hc;
enum TALER_ErrorCode ec;
struct TEH_KS_StateHandle *key_state;
struct GNUNET_JSON_Specification spec[] = {
GNUNET_JSON_spec_fixed_auto ("coin_pub",
@ -501,7 +503,9 @@ TEH_REFRESH_handler_refresh_melt (struct TEH_RequestHandler *rh,
rmc.dki = TEH_KS_denomination_key_lookup_by_hash (key_state,
&rmc.refresh_session.coin.
denom_pub_hash,
TEH_KS_DKU_DEPOSIT);
TEH_KS_DKU_DEPOSIT,
&ec,
&hc);
/* Consider case that denomination was revoked but
this coin was already seen and thus refresh is OK. */
if (NULL == rmc.dki)
@ -511,7 +515,9 @@ TEH_REFRESH_handler_refresh_melt (struct TEH_RequestHandler *rh,
dki = TEH_KS_denomination_key_lookup_by_hash (key_state,
&rmc.refresh_session.coin.
denom_pub_hash,
TEH_KS_DKU_PAYBACK);
TEH_KS_DKU_PAYBACK,
&ec,
&hc);
if (NULL != dki)
{
struct TALER_CoinPublicInfo coin_info;
@ -547,7 +553,9 @@ TEH_REFRESH_handler_refresh_melt (struct TEH_RequestHandler *rh,
dki = TEH_KS_denomination_key_lookup_by_hash (key_state,
&rmc.refresh_session.coin.
denom_pub_hash,
TEH_KS_DKU_ZOMBIE);
TEH_KS_DKU_ZOMBIE,
&ec,
&hc);
if (NULL != dki)
{
rmc.dki = dki;
@ -558,9 +566,9 @@ TEH_REFRESH_handler_refresh_melt (struct TEH_RequestHandler *rh,
if (NULL == rmc.dki)
{
TALER_LOG_WARNING ("Unknown denomination key in /refresh/melt request\n");
res = TEH_RESPONSE_reply_arg_unknown (connection,
TALER_EC_REFRESH_MELT_DENOMINATION_KEY_NOT_FOUND,
"denom_pub");
res = TEH_RESPONSE_reply_with_error (connection,
ec,
hc);
goto cleanup;
}

View File

@ -610,6 +610,8 @@ handle_refresh_reveal_json (struct MHD_Connection *connection,
&dki_h[i]),
GNUNET_JSON_spec_end ()
};
unsigned int hc;
enum TALER_ErrorCode ec;
res = TEH_PARSE_json_array (connection,
new_denoms_h_json,
@ -623,13 +625,15 @@ handle_refresh_reveal_json (struct MHD_Connection *connection,
}
dkis[i] = TEH_KS_denomination_key_lookup_by_hash (key_state,
&dki_h[i],
TEH_KS_DKU_WITHDRAW);
TEH_KS_DKU_WITHDRAW,
&ec,
&hc);
if (NULL == dkis[i])
{
TEH_KS_release (key_state);
return TEH_RESPONSE_reply_arg_invalid (connection,
TALER_EC_REFRESH_REVEAL_FRESH_DENOMINATION_KEY_NOT_FOUND,
"new_denoms_h");
return TEH_RESPONSE_reply_with_error (connection,
ec,
hc);
}
GNUNET_assert (NULL != dkis[i]->denom_priv.rsa_private_key);
}

View File

@ -161,6 +161,8 @@ refund_transaction (void *cls,
int deposit_found;
int refund_found;
int fee_cmp;
unsigned int hc;
enum TALER_ErrorCode ec;
dep = NULL;
ref = NULL;
@ -354,7 +356,9 @@ refund_transaction (void *cls,
}
dki = TEH_KS_denomination_key_lookup_by_hash (mks,
&dep->coin.denom_pub_hash,
TEH_KS_DKU_DEPOSIT);
TEH_KS_DKU_DEPOSIT,
&ec,
&hc);
if (NULL == dki)
{
/* DKI not found, but we do have a coin with this DK in our database;
@ -363,9 +367,9 @@ refund_transaction (void *cls,
TEH_KS_release (mks);
TEH_plugin->free_coin_transaction_list (TEH_plugin->cls,
tl);
*mhd_ret = TEH_RESPONSE_reply_internal_error (connection,
TALER_EC_REFUND_DENOMINATION_KEY_NOT_FOUND,
"denomination key not found");
*mhd_ret = TEH_RESPONSE_reply_with_error (connection,
ec,
hc);
return GNUNET_DB_STATUS_HARD_ERROR;
}
TALER_amount_ntoh (&expect_fee,

View File

@ -365,6 +365,8 @@ TEH_RESERVE_handler_reserve_withdraw (struct TEH_RequestHandler *rh,
json_t *root;
int res;
int mhd_ret;
unsigned int hc;
enum TALER_ErrorCode ec;
struct TALER_Amount amount;
struct TALER_Amount fee_withdraw;
struct GNUNET_JSON_Specification spec[] = {
@ -407,14 +409,16 @@ TEH_RESERVE_handler_reserve_withdraw (struct TEH_RequestHandler *rh,
}
wc.dki = TEH_KS_denomination_key_lookup_by_hash (wc.key_state,
&wc.denom_pub_hash,
TEH_KS_DKU_WITHDRAW);
TEH_KS_DKU_WITHDRAW,
&ec,
&hc);
if (NULL == wc.dki)
{
GNUNET_JSON_parse_free (spec);
TEH_KS_release (wc.key_state);
return TEH_RESPONSE_reply_arg_unknown (connection,
TALER_EC_WITHDRAW_DENOMINATION_KEY_NOT_FOUND,
"denom_pub");
return TEH_RESPONSE_reply_with_error (connection,
ec,
hc);
}
GNUNET_assert (NULL != wc.dki->denom_priv.rsa_private_key);
TALER_amount_ntoh (&amount,

View File

@ -361,6 +361,26 @@ TEH_RESPONSE_reply_internal_error (struct MHD_Connection *connection,
}
/**
* Send a response indicating an error.
*
* @param connection the MHD connection to use
* @param ec error code uniquely identifying the error
* @param http_status HTTP status code to use
* @return a MHD result code
*/
int
TEH_RESPONSE_reply_with_error (struct MHD_Connection *connection,
enum TALER_ErrorCode ec,
unsigned int http_status)
{
return TEH_RESPONSE_reply_json_pack (connection,
http_status,
"{s:I}",
"code", (json_int_t) ec);
}
/**
* Send a response indicating an external error.
*

View File

@ -170,6 +170,20 @@ TEH_RESPONSE_reply_internal_error (struct MHD_Connection *connection,
const char *hint);
/**
* Send a response indicating an error.
*
* @param connection the MHD connection to use
* @param ec error code uniquely identifying the error
* @param http_status HTTP status code to use
* @return a MHD result code
*/
int
TEH_RESPONSE_reply_with_error (struct MHD_Connection *connection,
enum TALER_ErrorCode ec,
unsigned int http_status);
/**
* Send a response indicating an external error.
*

View File

@ -297,6 +297,29 @@ enum TALER_ErrorCode
*/
TALER_EC_WITHDRAW_RESERVE_HISTORY_IMPOSSIBLE = 1113,
/**
* Validity period of the coin to be withdrawn
* is in the future. Returned with an HTTP
* status of #MHD_HTTP_PRECONDITION_FAILED.
*/
TALER_EC_WITHDRAW_VALIDITY_IN_FUTURE = 1114,
/**
* Withdraw period of the coin to be withdrawn
* is in the past. Returned with an HTTP
* status of #MHD_HTTP_GONE.
*/
TALER_EC_WITHDRAW_VALIDITY_IN_PAST = 1115,
/**
* The private key associated with the denomination
* key is unknown to the server, possibly because
* the key was revoked. Returned with an HTTP
* status of #MHD_HTTP_SERVICE_UNAVAILABLE.
*/
TALER_EC_DENOMINATION_KEY_LOST = 1116,
/**
* The exchange failed to obtain the transaction history of the
* given reserve from the database.
@ -453,6 +476,20 @@ enum TALER_ErrorCode
*/
TALER_EC_DEPOSIT_INVALID_TIMESTAMP = 1218,
/**
* Validity period of the denomination key
* is in the future. Returned with an HTTP
* status of #MHD_HTTP_PRECONDITION_FAILED.
*/
TALER_EC_DEPOSIT_DENOMINATION_VALIDITY_IN_FUTURE = 1219,
/**
* Denomination key of the coin is past the
* deposit deadline. Returned with an HTTP
* status of #MHD_HTTP_GONE.
*/
TALER_EC_DEPOSIT_DENOMINATION_EXPIRED = 1220,
/**
* The respective coin did not have sufficient residual value
@ -531,6 +568,35 @@ enum TALER_ErrorCode
*/
TALER_EC_REFRESH_MELT_COIN_EXPIRED_NO_ZOMBIE = 1309,
/**
* The exchange is unaware of the denomination key that was
* used to sign the melted zombie coin. This response is provided
* with HTTP status code MHD_HTTP_NOT_FOUND.
*/
TALER_EC_REFRESH_PAYBACK_DENOMINATION_KEY_NOT_FOUND = 1301,
/**
* Validity period of the denomination key
* is in the future. Returned with an HTTP
* status of #MHD_HTTP_PRECONDITION_FAILED.
*/
TALER_EC_REFRESH_PAYBACK_DENOMINATION_VALIDITY_IN_FUTURE = 1301,
/**
* Denomination key of the coin is past the
* deposit deadline. Returned with an HTTP
* status of #MHD_HTTP_GONE.
*/
TALER_EC_REFRESH_PAYBACK_DENOMINATION_EXPIRED = 1302,
/**
* Denomination key of the coin is past the
* deposit deadline. Returned with an HTTP
* status of #MHD_HTTP_GONE.
*/
TALER_EC_REFRESH_ZOMBIE_DENOMINATION_EXPIRED = 1303,
/**
* The provided transfer keys do not match up with the
* original commitment. Information about the original
@ -921,7 +987,15 @@ enum TALER_ErrorCode
* This response is provided with an HTTP status code of
* MHD_HTTP_INTERNAL_SERVER_ERROR
*/
TALER_EC_PAYBACK_COIN_BALANCE_NEGATIVE = 1857,
TALER_EC_PAYBACK_COIN_BALANCE_NEGATIVE = 1859,
/**
* Validity period of the denomination key
* is in the future. Returned with an HTTP
* status of #MHD_HTTP_PRECONDITION_FAILED.
*/
TALER_EC_PAYBACK_DENOMINATION_VALIDITY_IN_FUTURE = 1860,
/**
* The "have" parameter was not a natural number.