challenger

OAuth 2.0-based authentication service that validates user can receive messages at a certain address
Log | Files | Refs | Submodules | README | LICENSE

commit a90483affc1af150a8cea6cde4195b8843dafd34
parent 93f42dd13e38027396690eec8973641d573b4e2e
Author: Christian Grothoff <christian@grothoff.org>
Date:   Tue,  8 Apr 2025 13:00:36 +0200

add retries on soft failures

Diffstat:
Msrc/challenger/challenger-httpd_authorize.c | 94++++++++++++++++++++++++++++++++++++++++++++++---------------------------------
Msrc/challenger/challenger-httpd_challenge.c | 84++++++++++++++++++++++++++++++++++++++++++++++---------------------------------
Msrc/challenger/challenger-httpd_info.c | 15++++++++++++++-
Msrc/challenger/challenger-httpd_setup.c | 14++++++++++++++
Msrc/challenger/challenger-httpd_solve.c | 76++++++++++++++++++++++++++++++++++++++++++++++------------------------------
5 files changed, 178 insertions(+), 105 deletions(-)

diff --git a/src/challenger/challenger-httpd_authorize.c b/src/challenger/challenger-httpd_authorize.c @@ -28,6 +28,11 @@ #include "challenger_cm_enums.h" /** + * Maximum number of retries for the database interaction. + */ +#define MAX_RETRIES 3 + +/** * Generate error reply in the format requested by * the client. * @@ -212,46 +217,57 @@ CH_handler_authorize (struct CH_HandlerContext *hc, /* authorize_start will return 0 if a 'redirect_uri' was configured for the client and this one differs. */ - qs = CH_db->authorize_start (CH_db->cls, - &nonce, - client_id, - scope, - state, - redirect_uri, - code_challenge, - (uint32_t) code_challenge_method_enum, - &last_address, - &address_attempts_left, - &pin_transmissions_left, - &auth_attempts_left, - &solved, - &last_tx_time); - switch (qs) + for (unsigned int r = 0; r<MAX_RETRIES; r++) { - case GNUNET_DB_STATUS_HARD_ERROR: - GNUNET_break (0); - return reply_error ( - hc, - "internal-error", - MHD_HTTP_INTERNAL_SERVER_ERROR, - TALER_EC_GENERIC_DB_STORE_FAILED, - "authorize_start"); - case GNUNET_DB_STATUS_SOFT_ERROR: - GNUNET_break (0); - return MHD_NO; - case GNUNET_DB_STATUS_SUCCESS_NO_RESULTS: - GNUNET_break_op (0); - GNUNET_log (GNUNET_ERROR_TYPE_INFO, - "Failed to find authorization process of client %llu for nonce `%s'\n", - client_id, - hc->path); - return reply_error ( - hc, - "validation-unknown", - MHD_HTTP_NOT_FOUND, - TALER_EC_CHALLENGER_GENERIC_VALIDATION_UNKNOWN, - NULL); - case GNUNET_DB_STATUS_SUCCESS_ONE_RESULT: + qs = CH_db->authorize_start (CH_db->cls, + &nonce, + client_id, + scope, + state, + redirect_uri, + code_challenge, + (uint32_t) code_challenge_method_enum, + &last_address, + &address_attempts_left, + &pin_transmissions_left, + &auth_attempts_left, + &solved, + &last_tx_time); + switch (qs) + { + case GNUNET_DB_STATUS_HARD_ERROR: + GNUNET_break (0); + return reply_error ( + hc, + "internal-error", + MHD_HTTP_INTERNAL_SERVER_ERROR, + TALER_EC_GENERIC_DB_STORE_FAILED, + "authorize_start"); + case GNUNET_DB_STATUS_SOFT_ERROR: + if (r < MAX_RETRIES - 1) + continue; + GNUNET_break (0); + return reply_error ( + hc, + "internal-error", + MHD_HTTP_INTERNAL_SERVER_ERROR, + TALER_EC_GENERIC_DB_STORE_FAILED, + "authorize_start"); + case GNUNET_DB_STATUS_SUCCESS_NO_RESULTS: + GNUNET_break_op (0); + GNUNET_log (GNUNET_ERROR_TYPE_INFO, + "Failed to find authorization process of client %llu for nonce `%s'\n", + client_id, + hc->path); + return reply_error ( + hc, + "validation-unknown", + MHD_HTTP_NOT_FOUND, + TALER_EC_CHALLENGER_GENERIC_VALIDATION_UNKNOWN, + NULL); + case GNUNET_DB_STATUS_SUCCESS_ONE_RESULT: + break; + } break; } if (0 == CH_get_output_type (hc->connection)) diff --git a/src/challenger/challenger-httpd_challenge.c b/src/challenger/challenger-httpd_challenge.c @@ -28,6 +28,10 @@ #include <taler/taler_signatures.h> #include "challenger-httpd_common.h" +/** + * Maximum number of retries for the database interaction. + */ +#define MAX_RETRIES 3 /** * Context for a /challenge operation. @@ -687,42 +691,52 @@ CH_handler_challenge (struct CH_HandlerContext *hc, } if (! bc->db_finished) { - enum GNUNET_DB_QueryStatus qs; - - GNUNET_assert (NULL == bc->client_redirect_uri); - qs = CH_db->challenge_set_address_and_pin ( - CH_db->cls, - &bc->nonce, - bc->address, - CH_validation_duration, - &bc->tan, - &bc->state, - &bc->last_tx_time, - &bc->pin_attempts_left, - &bc->retransmit, - &bc->client_redirect_uri, - &bc->address_refused, - &bc->solved); - switch (qs) + for (unsigned int r = 0; r < MAX_RETRIES; r++) { - case GNUNET_DB_STATUS_HARD_ERROR: - GNUNET_break (0); - return reply_error (bc, - "internal-error", - MHD_HTTP_INTERNAL_SERVER_ERROR, - TALER_EC_GENERIC_DB_STORE_FAILED, - "set-address-and-pin"); - case GNUNET_DB_STATUS_SOFT_ERROR: - GNUNET_break (0); - return MHD_NO; - case GNUNET_DB_STATUS_SUCCESS_NO_RESULTS: - GNUNET_break_op (0); - return reply_error (bc, - "validation-unknown", - MHD_HTTP_NOT_FOUND, - TALER_EC_CHALLENGER_GENERIC_VALIDATION_UNKNOWN, - NULL); - case GNUNET_DB_STATUS_SUCCESS_ONE_RESULT: + enum GNUNET_DB_QueryStatus qs; + + GNUNET_assert (NULL == bc->client_redirect_uri); + qs = CH_db->challenge_set_address_and_pin ( + CH_db->cls, + &bc->nonce, + bc->address, + CH_validation_duration, + &bc->tan, + &bc->state, + &bc->last_tx_time, + &bc->pin_attempts_left, + &bc->retransmit, + &bc->client_redirect_uri, + &bc->address_refused, + &bc->solved); + switch (qs) + { + case GNUNET_DB_STATUS_HARD_ERROR: + GNUNET_break (0); + return reply_error (bc, + "internal-error", + MHD_HTTP_INTERNAL_SERVER_ERROR, + TALER_EC_GENERIC_DB_STORE_FAILED, + "set-address-and-pin"); + case GNUNET_DB_STATUS_SOFT_ERROR: + if (r < MAX_RETRIES - 1) + continue; + GNUNET_break (0); + return reply_error (bc, + "internal-error", + MHD_HTTP_INTERNAL_SERVER_ERROR, + TALER_EC_GENERIC_DB_STORE_FAILED, + "set-address-and-pin"); + case GNUNET_DB_STATUS_SUCCESS_NO_RESULTS: + GNUNET_break_op (0); + return reply_error (bc, + "validation-unknown", + MHD_HTTP_NOT_FOUND, + TALER_EC_CHALLENGER_GENERIC_VALIDATION_UNKNOWN, + NULL); + case GNUNET_DB_STATUS_SUCCESS_ONE_RESULT: + break; + } break; } bc->db_finished = true; diff --git a/src/challenger/challenger-httpd_info.c b/src/challenger/challenger-httpd_info.c @@ -30,6 +30,11 @@ #define BEARER_PREFIX "Bearer " +/** + * Maximum number of retries for the database interaction. + */ +#define MAX_RETRIES 3 + MHD_RESULT CH_handler_info (struct CH_HandlerContext *hc, const char *upload_data, @@ -78,6 +83,7 @@ CH_handler_info (struct CH_HandlerContext *hc, } /* Check token is valid */ + for (unsigned int r = 0; r<MAX_RETRIES; r++) { uint64_t id; json_t *address; @@ -98,8 +104,13 @@ CH_handler_info (struct CH_HandlerContext *hc, TALER_EC_GENERIC_DB_FETCH_FAILED, "info_get_token"); case GNUNET_DB_STATUS_SOFT_ERROR: + if (r < MAX_RETRIES - 1) + continue; GNUNET_break (0); - return MHD_NO; + return TALER_MHD_reply_with_error (hc->connection, + MHD_HTTP_INTERNAL_SERVER_ERROR, + TALER_EC_GENERIC_DB_FETCH_FAILED, + "info_get_token"); case GNUNET_DB_STATUS_SUCCESS_NO_RESULTS: return TALER_MHD_reply_with_error (hc->connection, MHD_HTTP_NOT_FOUND, @@ -120,4 +131,6 @@ CH_handler_info (struct CH_HandlerContext *hc, GNUNET_JSON_pack_timestamp ("expires", address_expiration)); } + GNUNET_assert (0); + return MHD_NO; } diff --git a/src/challenger/challenger-httpd_setup.c b/src/challenger/challenger-httpd_setup.c @@ -24,6 +24,11 @@ #include "challenger-httpd_setup.h" #include "challenger-httpd_common.h" +/** + * Maximum number of retries for the database interaction. + */ +#define MAX_RETRIES 3 + struct SetupContext { @@ -134,6 +139,7 @@ CH_handler_setup (struct CH_HandlerContext *hc, MHD_HTTP_HEADER_AUTHORIZATION); } + for (unsigned int r = 0; r<MAX_RETRIES; r++) { enum GNUNET_DB_QueryStatus qs; char *client_url = NULL; @@ -146,7 +152,14 @@ CH_handler_setup (struct CH_HandlerContext *hc, switch (qs) { case GNUNET_DB_STATUS_HARD_ERROR: + GNUNET_break (0); + return TALER_MHD_reply_with_error (hc->connection, + MHD_HTTP_INTERNAL_SERVER_ERROR, + TALER_EC_GENERIC_DB_FETCH_FAILED, + NULL); case GNUNET_DB_STATUS_SOFT_ERROR: + if (r < MAX_RETRIES - 1) + continue; GNUNET_break (0); return TALER_MHD_reply_with_error (hc->connection, MHD_HTTP_INTERNAL_SERVER_ERROR, @@ -161,6 +174,7 @@ CH_handler_setup (struct CH_HandlerContext *hc, break; } GNUNET_free (client_url); + break; } { diff --git a/src/challenger/challenger-httpd_solve.c b/src/challenger/challenger-httpd_solve.c @@ -27,6 +27,10 @@ #include <taler/taler_templating_lib.h> #include <taler/taler_signatures.h> +/** + * Maximum number of retries for the database interaction. + */ +#define MAX_RETRIES 3 /** * Context for a /solve operation. @@ -265,37 +269,49 @@ CH_handler_solve (struct CH_HandlerContext *hc, "pin"); } - qs = CH_db->validate_solve_pin (CH_db->cls, - &bc->nonce, - pin, - &solved, - &exhausted, - &no_challenge, - &bc->state, - &bc->addr_left, - &bc->auth_attempts_left, - &bc->pin_transmissions_left, - &bc->client_redirect_uri); - switch (qs) + for (unsigned int r = 0; r<MAX_RETRIES; r++) { - case GNUNET_DB_STATUS_HARD_ERROR: - return reply_error ( - bc, - "internal-error", - MHD_HTTP_INTERNAL_SERVER_ERROR, - TALER_EC_GENERIC_DB_FETCH_FAILED, - "validate_solve_pin"); - case GNUNET_DB_STATUS_SOFT_ERROR: - GNUNET_break (0); - return MHD_NO; - case GNUNET_DB_STATUS_SUCCESS_NO_RESULTS: - return reply_error ( - bc, - "validation-unknown", - MHD_HTTP_NOT_FOUND, - TALER_EC_CHALLENGER_GENERIC_VALIDATION_UNKNOWN, - NULL); - case GNUNET_DB_STATUS_SUCCESS_ONE_RESULT: + qs = CH_db->validate_solve_pin (CH_db->cls, + &bc->nonce, + pin, + &solved, + &exhausted, + &no_challenge, + &bc->state, + &bc->addr_left, + &bc->auth_attempts_left, + &bc->pin_transmissions_left, + &bc->client_redirect_uri); + switch (qs) + { + case GNUNET_DB_STATUS_HARD_ERROR: + GNUNET_break (0); + return reply_error ( + bc, + "internal-error", + MHD_HTTP_INTERNAL_SERVER_ERROR, + TALER_EC_GENERIC_DB_FETCH_FAILED, + "validate_solve_pin"); + case GNUNET_DB_STATUS_SOFT_ERROR: + if (r < MAX_RETRIES - 1) + continue; + GNUNET_break (0); + return reply_error ( + bc, + "internal-error", + MHD_HTTP_INTERNAL_SERVER_ERROR, + TALER_EC_GENERIC_DB_FETCH_FAILED, + "validate_solve_pin"); + case GNUNET_DB_STATUS_SUCCESS_NO_RESULTS: + return reply_error ( + bc, + "validation-unknown", + MHD_HTTP_NOT_FOUND, + TALER_EC_CHALLENGER_GENERIC_VALIDATION_UNKNOWN, + NULL); + case GNUNET_DB_STATUS_SUCCESS_ONE_RESULT: + break; + } break; } if (! solved)