summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorChristian Grothoff <christian@grothoff.org>2022-07-05 12:56:55 +0200
committerChristian Grothoff <christian@grothoff.org>2022-07-05 12:56:55 +0200
commit7201ce3166127e45f924c3119c3037917d32e594 (patch)
tree040aa858fbf78611081fb73239c71ee1ea735ec8
parent82cff16eea29fda6636b48d5980b48b1bc01236f (diff)
downloadexchange-7201ce3166127e45f924c3119c3037917d32e594.tar.gz
exchange-7201ce3166127e45f924c3119c3037917d32e594.tar.bz2
exchange-7201ce3166127e45f924c3119c3037917d32e594.zip
-handle withdraw CS nonce reuse more nicely
-rw-r--r--src/exchange/taler-exchange-httpd_withdraw.c15
-rw-r--r--src/exchangedb/exchange-0001-part.sql10
-rw-r--r--src/exchangedb/plugin_exchangedb_postgres.c5
-rw-r--r--src/include/taler_exchangedb_plugin.h2
4 files changed, 26 insertions, 6 deletions
diff --git a/src/exchange/taler-exchange-httpd_withdraw.c b/src/exchange/taler-exchange-httpd_withdraw.c
index 86d2c62b0..8d001488d 100644
--- a/src/exchange/taler-exchange-httpd_withdraw.c
+++ b/src/exchange/taler-exchange-httpd_withdraw.c
@@ -97,6 +97,7 @@ withdraw_transaction (void *cls,
enum GNUNET_DB_QueryStatus qs;
bool found = false;
bool balance_ok = false;
+ bool nonce_ok = false;
struct GNUNET_TIME_Timestamp now;
uint64_t ruuid;
const struct TALER_CsNonce *nonce;
@@ -108,16 +109,13 @@ withdraw_transaction (void *cls,
(TALER_DENOMINATION_CS == bp->cipher)
? &bp->details.cs_blinded_planchet.nonce
: NULL;
- // FIXME: what error is returned on nonce reuse?
- // Should expand function to return this error
- // specifically, and then we should return a
- // TALER_EC_EXCHANGE_WITHDRAW_NONCE_REUSE,
qs = TEH_plugin->do_withdraw (TEH_plugin->cls,
nonce,
&wc->collectable,
now,
&found,
&balance_ok,
+ &nonce_ok,
&wc->kyc,
&ruuid);
if (0 > qs)
@@ -146,6 +144,15 @@ withdraw_transaction (void *cls,
&wc->collectable.reserve_pub);
return GNUNET_DB_STATUS_HARD_ERROR;
}
+ if (! nonce_ok)
+ {
+ TEH_plugin->rollback (TEH_plugin->cls);
+ *mhd_ret = TALER_MHD_reply_with_error (connection,
+ MHD_HTTP_CONFLICT,
+ TALER_EC_EXCHANGE_WITHDRAW_NONCE_REUSE,
+ NULL);
+ return GNUNET_DB_STATUS_HARD_ERROR;
+ }
if ( (TEH_KYC_NONE != TEH_kyc_config.mode) &&
(! wc->kyc.ok) &&
(TALER_EXCHANGEDB_KYC_W2W == wc->kyc.type) )
diff --git a/src/exchangedb/exchange-0001-part.sql b/src/exchangedb/exchange-0001-part.sql
index e24129957..d002fed8c 100644
--- a/src/exchangedb/exchange-0001-part.sql
+++ b/src/exchangedb/exchange-0001-part.sql
@@ -1422,6 +1422,7 @@ CREATE OR REPLACE FUNCTION exchange_do_withdraw(
IN min_reserve_gc INT8,
OUT reserve_found BOOLEAN,
OUT balance_ok BOOLEAN,
+ OUT nonce_ok BOOLEAN,
OUT kycok BOOLEAN,
OUT account_uuid INT8,
OUT ruuid INT8)
@@ -1478,6 +1479,7 @@ THEN
-- reserve unknown
reserve_found=FALSE;
balance_ok=FALSE;
+ nonce_ok=TRUE;
kycok=FALSE;
account_uuid=0;
ruuid=2;
@@ -1511,6 +1513,7 @@ THEN
-- idempotent query, all constraints must be satisfied
reserve_found=TRUE;
balance_ok=TRUE;
+ nonce_ok=TRUE;
kycok=TRUE;
account_uuid=0;
RETURN;
@@ -1534,6 +1537,7 @@ ELSE
reserve_frac=reserve_frac - amount_frac;
ELSE
reserve_found=TRUE;
+ nonce_ok=TRUE; -- we do not really know
balance_ok=FALSE;
kycok=FALSE; -- we do not really know or care
account_uuid=0;
@@ -1585,10 +1589,12 @@ THEN
balance_ok=FALSE;
kycok=FALSE;
account_uuid=0;
- ruuid=1; -- FIXME: return error message more nicely!
- ASSERT false, 'nonce reuse attempted by client';
+ nonce_ok=FALSE;
+ RETURN;
END IF;
END IF;
+ELSE
+ nonce_ok=TRUE; -- no nonce, hence OK!
END IF;
diff --git a/src/exchangedb/plugin_exchangedb_postgres.c b/src/exchangedb/plugin_exchangedb_postgres.c
index 53be0364c..63f075210 100644
--- a/src/exchangedb/plugin_exchangedb_postgres.c
+++ b/src/exchangedb/plugin_exchangedb_postgres.c
@@ -827,6 +827,7 @@ prepare_statements (struct PostgresClosure *pg)
"SELECT "
" reserve_found"
",balance_ok"
+ ",nonce_ok"
",kycok AS kyc_ok"
",account_uuid AS payment_target_uuid"
",ruuid"
@@ -5906,6 +5907,7 @@ postgres_get_withdraw_info (
* @param now current time (rounded)
* @param[out] found set to true if the reserve was found
* @param[out] balance_ok set to true if the balance was sufficient
+ * @param[out] nonce_ok set to false if the nonce was reused
* @param[out] kyc set to true if the kyc status of the reserve is satisfied
* @param[out] ruuid set to the reserve's UUID (reserves table row)
* @return query execution status
@@ -5918,6 +5920,7 @@ postgres_do_withdraw (
struct GNUNET_TIME_Timestamp now,
bool *found,
bool *balance_ok,
+ bool *nonce_ok,
struct TALER_EXCHANGEDB_KycStatus *kyc,
uint64_t *ruuid)
{
@@ -5944,6 +5947,8 @@ postgres_do_withdraw (
balance_ok),
GNUNET_PQ_result_spec_bool ("kyc_ok",
&kyc->ok),
+ GNUNET_PQ_result_spec_bool ("nonce_ok",
+ nonce_ok),
GNUNET_PQ_result_spec_uint64 ("payment_target_uuid",
&kyc->payment_target_uuid),
GNUNET_PQ_result_spec_uint64 ("ruuid",
diff --git a/src/include/taler_exchangedb_plugin.h b/src/include/taler_exchangedb_plugin.h
index c3661d83b..4a871786f 100644
--- a/src/include/taler_exchangedb_plugin.h
+++ b/src/include/taler_exchangedb_plugin.h
@@ -3171,6 +3171,7 @@ struct TALER_EXCHANGEDB_Plugin
* @param now current time (rounded)
* @param[out] found set to true if the reserve was found
* @param[out] balance_ok set to true if the balance was sufficient
+ * @param[out] nonce_ok set to false if the nonce was reused
* @param[out] kyc set to the KYC status of the reserve
* @param[out] ruuid set to the reserve's UUID (reserves table row)
* @return query execution status
@@ -3183,6 +3184,7 @@ struct TALER_EXCHANGEDB_Plugin
struct GNUNET_TIME_Timestamp now,
bool *found,
bool *balance_ok,
+ bool *nonce_ok,
struct TALER_EXCHANGEDB_KycStatus *kyc_ok,
uint64_t *ruuid);