summaryrefslogtreecommitdiff
path: root/src/stasis/plugin_anastasis_postgres.c
diff options
context:
space:
mode:
authorChristian Grothoff <christian@grothoff.org>2021-08-27 17:44:01 +0200
committerChristian Grothoff <christian@grothoff.org>2021-08-27 17:44:01 +0200
commit2e2a558a59d0e7a25953cddf2afb67b7ab96135c (patch)
treea8bbc38cdb83092cea3624a855d63a5fb8a71603 /src/stasis/plugin_anastasis_postgres.c
parent3a6466bb3854863b4b35deb08cb2e4ed03ebf12b (diff)
downloadanastasis-2e2a558a59d0e7a25953cddf2afb67b7ab96135c.tar.gz
anastasis-2e2a558a59d0e7a25953cddf2afb67b7ab96135c.tar.bz2
anastasis-2e2a558a59d0e7a25953cddf2afb67b7ab96135c.zip
fix retry counter logic, deal with negative retry counters, limit code reuse for iban method
Diffstat (limited to 'src/stasis/plugin_anastasis_postgres.c')
-rw-r--r--src/stasis/plugin_anastasis_postgres.c154
1 files changed, 23 insertions, 131 deletions
diff --git a/src/stasis/plugin_anastasis_postgres.c b/src/stasis/plugin_anastasis_postgres.c
index 506c304..8ee16ad 100644
--- a/src/stasis/plugin_anastasis_postgres.c
+++ b/src/stasis/plugin_anastasis_postgres.c
@@ -1763,6 +1763,11 @@ struct CheckValidityContext
struct PostgresClosure *pg;
/**
+ * Set to the matching challenge code (if @e valid).
+ */
+ uint64_t code;
+
+ /**
* Set to true if a code matching @e hashed_code was found.
*/
bool valid;
@@ -1828,6 +1833,7 @@ check_valid_code (void *cls,
cvc->hashed_code))
{
cvc->valid = true;
+ cvc->code = server_code;
cvc->satisfied = (0 != sat);
}
else
@@ -1862,6 +1868,7 @@ check_valid_code (void *cls,
* @param cls closure
* @param truth_uuid identification of the challenge which the code corresponds to
* @param hashed_code code which the user provided and wants to verify
+ * @param[out] code set to the original numeric code
* @param[out] satisfied set to true if the challenge is set to satisfied
* @return code validity status
*/
@@ -1870,6 +1877,7 @@ postgres_verify_challenge_code (
void *cls,
const struct ANASTASIS_CRYPTO_TruthUUIDP *truth_uuid,
const struct GNUNET_HashCode *hashed_code,
+ uint64_t *code,
bool *satisfied)
{
struct PostgresClosure *pg = cls;
@@ -1897,6 +1905,7 @@ postgres_verify_challenge_code (
if ( (qs < 0) ||
(cvc.db_failure) )
return ANASTASIS_DB_CODE_STATUS_HARD_ERROR;
+ *code = cvc.code;
if (cvc.valid)
{
*satisfied = cvc.satisfied;
@@ -2059,7 +2068,7 @@ postgres_create_challenge_code (
const struct ANASTASIS_CRYPTO_TruthUUIDP *truth_uuid,
struct GNUNET_TIME_Relative rotation_period,
struct GNUNET_TIME_Relative validity_period,
- unsigned int retry_counter,
+ uint32_t retry_counter,
struct GNUNET_TIME_Absolute *retransmission_date,
uint64_t *code)
{
@@ -2117,15 +2126,22 @@ postgres_create_challenge_code (
case GNUNET_DB_STATUS_SOFT_ERROR:
goto retry;
case GNUNET_DB_STATUS_SUCCESS_NO_RESULTS:
- /* no active challenge, create fresh one (below) */
+ GNUNET_log (GNUNET_ERROR_TYPE_INFO,
+ "No active challenge found, creating a fresh one\n");
break;
case GNUNET_DB_STATUS_SUCCESS_ONE_RESULT:
if (0 == old_retry_counter)
{
rollback (pg);
+ GNUNET_log (GNUNET_ERROR_TYPE_INFO,
+ "Active challenge %llu has zero tries left, refusing to create another one\n",
+ (unsigned long long) code);
return GNUNET_DB_STATUS_SUCCESS_NO_RESULTS;
}
rollback (pg);
+ GNUNET_log (GNUNET_ERROR_TYPE_INFO,
+ "Active challenge has %u tries left, returning old challenge\n",
+ (unsigned int) old_retry_counter);
return qs;
}
}
@@ -2158,132 +2174,9 @@ postgres_create_challenge_code (
rollback (pg);
return GNUNET_DB_STATUS_HARD_ERROR;
case GNUNET_DB_STATUS_SUCCESS_ONE_RESULT:
- break;
- }
- }
- qs = commit_transaction (pg);
- if (GNUNET_DB_STATUS_SOFT_ERROR == qs)
- goto retry;
- if (qs < 0)
- return qs;
- return GNUNET_DB_STATUS_SUCCESS_ONE_RESULT;
-retry:
- rollback (pg);
- }
- return GNUNET_DB_STATUS_SOFT_ERROR;
-}
-
-
-/**
- * Setup challenge code for a given challenge identified by the
- * challenge public key. The function will first check if there is
- * already a valid code for this challenge present and won't insert
- * a new one in this case. This variant is not rate-limited, will
- * return the existing challenge if it has not yet expired and will
- * simply create new challenges when the old ones need to be
- * rotated.
- *
- * @param cls closure
- * @param truth_uuid the identifier for the challenge
- * @param rotation_period for how long is the code available
- * @param validity_period for how long is the code available
- * @param[out] code set to the code which will be checked for later
- * @return transaction status,
- * #GNUNET_DB_STATUS_SUCCESS_ONE_RESULT if @a code is now in the DB
- */
-static enum GNUNET_DB_QueryStatus
-postgres_get_unlimited_challenge_code (
- void *cls,
- const struct ANASTASIS_CRYPTO_TruthUUIDP *truth_uuid,
- struct GNUNET_TIME_Relative rotation_period,
- struct GNUNET_TIME_Relative validity_period,
- uint64_t *code)
-{
- struct PostgresClosure *pg = cls;
- enum GNUNET_DB_QueryStatus qs;
- struct GNUNET_TIME_Absolute now = GNUNET_TIME_absolute_get ();
- struct GNUNET_TIME_Absolute expiration_date;
- struct GNUNET_TIME_Absolute ex_rot;
-
- check_connection (pg);
- GNUNET_TIME_round_abs (&now);
- expiration_date = GNUNET_TIME_absolute_add (now,
- validity_period);
- ex_rot = GNUNET_TIME_absolute_subtract (now,
- rotation_period);
- for (unsigned int retries = 0; retries<MAX_RETRIES; retries++)
- {
- if (GNUNET_OK !=
- begin_transaction (pg,
- "get_unlimited_challenge_code"))
- {
- GNUNET_break (0);
- return GNUNET_DB_STATUS_HARD_ERROR;
- }
-
- {
- struct GNUNET_PQ_QueryParam params[] = {
- GNUNET_PQ_query_param_auto_from_type (truth_uuid),
- TALER_PQ_query_param_absolute_time (&now),
- TALER_PQ_query_param_absolute_time (&ex_rot),
- GNUNET_PQ_query_param_end
- };
- struct GNUNET_PQ_ResultSpec rs[] = {
- GNUNET_PQ_result_spec_uint64 ("code",
- code),
- GNUNET_PQ_result_spec_end
- };
- enum GNUNET_DB_QueryStatus qs;
-
- qs = GNUNET_PQ_eval_prepared_singleton_select (pg->conn,
- "challengecode_select_meta",
- params,
- rs);
- switch (qs)
- {
- case GNUNET_DB_STATUS_HARD_ERROR:
- GNUNET_break (0);
- rollback (pg);
- return qs;
- case GNUNET_DB_STATUS_SOFT_ERROR:
- goto retry;
- case GNUNET_DB_STATUS_SUCCESS_NO_RESULTS:
- /* no active challenge, create fresh one (below) */
- break;
- case GNUNET_DB_STATUS_SUCCESS_ONE_RESULT:
- rollback (pg);
- return qs;
- }
- }
-
- *code = GNUNET_CRYPTO_random_u64 (GNUNET_CRYPTO_QUALITY_NONCE,
- NONCE_MAX_VALUE);
- {
- uint32_t retry_counter = UINT32_MAX;
- struct GNUNET_PQ_QueryParam params[] = {
- GNUNET_PQ_query_param_auto_from_type (truth_uuid),
- GNUNET_PQ_query_param_uint64 (code),
- TALER_PQ_query_param_absolute_time (&now),
- TALER_PQ_query_param_absolute_time (&expiration_date),
- GNUNET_PQ_query_param_uint32 (&retry_counter),
- GNUNET_PQ_query_param_end
- };
-
- qs = GNUNET_PQ_eval_prepared_non_select (pg->conn,
- "challengecode_insert",
- params);
- switch (qs)
- {
- case GNUNET_DB_STATUS_HARD_ERROR:
- rollback (pg);
- return GNUNET_DB_STATUS_HARD_ERROR;
- case GNUNET_DB_STATUS_SOFT_ERROR:
- goto retry;
- case GNUNET_DB_STATUS_SUCCESS_NO_RESULTS:
- GNUNET_break (0);
- rollback (pg);
- return GNUNET_DB_STATUS_HARD_ERROR;
- case GNUNET_DB_STATUS_SUCCESS_ONE_RESULT:
+ GNUNET_log (GNUNET_ERROR_TYPE_INFO,
+ "Created fresh challenge with %u tries left\n",
+ (unsigned int) retry_counter);
break;
}
}
@@ -2675,7 +2568,7 @@ libanastasis_plugin_db_postgres_init (void *cls)
" FROM anastasis_challengecode"
" WHERE truth_uuid=$1"
" AND expiration_date > $2"
- " AND retry_counter > 0;",
+ " AND retry_counter != 0;",
2),
GNUNET_PQ_make_prepare ("challengecode_set_satisfied",
"UPDATE anastasis_challengecode"
@@ -2715,7 +2608,7 @@ libanastasis_plugin_db_postgres_init (void *cls)
" SET retry_counter=retry_counter - 1"
" WHERE truth_uuid=$1"
" AND code=$2"
- " AND retry_counter > 0;",
+ " AND retry_counter != 0;",
1),
GNUNET_PQ_make_prepare ("challengepayment_dec_counter",
"UPDATE anastasis_challenge_payment"
@@ -2807,7 +2700,6 @@ libanastasis_plugin_db_postgres_init (void *cls)
plugin->test_challenge_code_satisfied =
&postgres_test_challenge_code_satisfied;
plugin->create_challenge_code = &postgres_create_challenge_code;
- plugin->get_unlimited_challenge_code = &postgres_get_unlimited_challenge_code;
plugin->mark_challenge_sent = &postgres_mark_challenge_sent;
plugin->challenge_gc = &postgres_challenge_gc;
plugin->record_truth_upload_payment = &postgres_record_truth_upload_payment;