diff options
author | Christian Grothoff <christian@grothoff.org> | 2021-08-27 17:44:01 +0200 |
---|---|---|
committer | Christian Grothoff <christian@grothoff.org> | 2021-08-27 17:44:01 +0200 |
commit | 2e2a558a59d0e7a25953cddf2afb67b7ab96135c (patch) | |
tree | a8bbc38cdb83092cea3624a855d63a5fb8a71603 /src/stasis/plugin_anastasis_postgres.c | |
parent | 3a6466bb3854863b4b35deb08cb2e4ed03ebf12b (diff) | |
download | anastasis-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.c | 154 |
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; |