challenger

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

commit 9046d46b17c89514d0bc0867e032df46af3ad518
parent 021714a54961523d3a84ebe8fd6ffa476fac56ba
Author: Christian Grothoff <christian@grothoff.org>
Date:   Tue, 25 Apr 2023 15:47:09 +0200

implement DB functions

Diffstat:
Msrc/challengerdb/pg_client_check.c | 34++++++++++++++++++++++++++++++----
Msrc/challengerdb/pg_client_check.h | 8++++----
Msrc/challengerdb/pg_validate_challenge_open.c | 25++++++++++++++++++++++---
Msrc/challengerdb/pg_validate_challenge_open.h | 4++--
Msrc/challengerdb/pg_validate_login_address.c | 46++++++++++++++++++++++++++++++++++++++++++++--
Msrc/challengerdb/pg_validate_login_pin.c | 23+++++++++++++++++++++--
Msrc/challengerdb/pg_validate_solve_pin.c | 43+++++++++++++++++++++++++++++++++++++++++--
Msrc/challengerdb/pg_validation_get.c | 46++++++++++++++++++++++++++++++++++++++++++++--
Msrc/challengerdb/pg_validation_setup.c | 20++++++++++++++++++--
Msrc/include/challenger_database_plugin.h | 12++++++------
10 files changed, 232 insertions(+), 29 deletions(-)

diff --git a/src/challengerdb/pg_client_check.c b/src/challengerdb/pg_client_check.c @@ -25,13 +25,39 @@ #include "pg_client_check.h" #include "pg_helper.h" + enum GNUNET_DB_QueryStatus CH_PG_client_check (void *cls, - const char *client_url, + uint64_t client_id, const char *client_secret, uint32_t counter_increment, - uint64_t *client_id) + char **client_url) { - GNUNET_break (0); - return GNUNET_DB_STATUS_HARD_ERROR; + struct PostgresClosure *pg = cls; + struct GNUNET_PQ_QueryParam params[] = { + GNUNET_PQ_query_param_uint64 (&client_id), + GNUNET_PQ_query_param_string (client_secret), + GNUNET_PQ_query_param_uint32 (&counter_increment), + GNUNET_PQ_query_param_end + }; + struct GNUNET_PQ_ResultSpec rs[] = { + GNUNET_PQ_result_spec_allow_null ( + GNUNET_PQ_result_spec_string ("url", + client_url), + NULL), + GNUNET_PQ_result_spec_end + }; + + *client_url = NULL; + PREPARE (pg, + "client_check", + "UPDATE clients SET" + " validation_counter=validation_counter+$3" + " WHERE client_id=$1" + " AND client_secret=$2" + " RETURNING client_url"); + return GNUNET_PQ_eval_prepared_singleton_select (pg->conn, + "client_check", + params, + rs); } diff --git a/src/challengerdb/pg_client_check.h b/src/challengerdb/pg_client_check.h @@ -32,17 +32,17 @@ * client is incremented by the given value if the client was found. * * @param cls - * @param client_url URL of the client + * @param client_id unique row of the client * @param client_secret secret of the client * @param counter_increment change in validation counter - * @param[out] client_id set to unique row of the client + * @param[out] client_url set to URL of the client (if any) * @return transaction status */ enum GNUNET_DB_QueryStatus CH_PG_client_check (void *cls, - const char *client_url, + uint64_t client_id, const char *client_secret, uint32_t counter_increment, - uint64_t *client_id); + char **client_url); #endif diff --git a/src/challengerdb/pg_validate_challenge_open.c b/src/challengerdb/pg_validate_challenge_open.c @@ -29,8 +29,27 @@ enum GNUNET_DB_QueryStatus CH_PG_validate_challenge_open (void *cls, const struct CHALLENGER_ValidationNonceP *nonce, - bool *open) + bool *is_open) { - GNUNET_break (0); - return GNUNET_DB_STATUS_HARD_ERROR; + struct PostgresClosure *pg = cls; + struct GNUNET_PQ_QueryParam params[] = { + GNUNET_PQ_query_param_auto_from_type (nonce), + GNUNET_PQ_query_param_end + }; + struct GNUNET_PQ_ResultSpec rs[] = { + GNUNET_PQ_result_spec_bool ("is_open", + is_open), + GNUNET_PQ_result_spec_end + }; + + PREPARE (pg, + "validate_test_open", + "SELECT FROM validations " + " address IS NOT NULL AS is_open" + " WHERE nonce=$1" + " AND auth_attempts_left > 0;"); + return GNUNET_PQ_eval_prepared_singleton_select (pg->conn, + "validate_test_open", + params, + rs); } diff --git a/src/challengerdb/pg_validate_challenge_open.h b/src/challengerdb/pg_validate_challenge_open.h @@ -31,7 +31,7 @@ * * @param cls * @param nonce unique nonce to use to identify the validation - * @param[out] open set to true if a challenge was sent + * @param[out] is_open set to true if a challenge was sent * @return transaction status: * #GNUNET_DB_SUCCESS_ONE_RESULT if the nonce was found * #GNUNET_DB_SUCCESS_NO_RESULTS if we do not know the nonce @@ -40,6 +40,6 @@ enum GNUNET_DB_QueryStatus CH_PG_validate_challenge_open (void *cls, const struct CHALLENGER_ValidationNonceP *nonce, - bool *open); + bool *is_open); #endif diff --git a/src/challengerdb/pg_validate_login_address.c b/src/challengerdb/pg_validate_login_address.c @@ -37,6 +37,48 @@ CH_PG_validate_login_address (void *cls, uint32_t *last_pin, uint32_t *pin_attempts_left) { - GNUNET_break (0); - return GNUNET_DB_STATUS_HARD_ERROR; + struct PostgresClosure *pg = cls; + struct GNUNET_PQ_QueryParam params[] = { + GNUNET_PQ_query_param_auto_from_type (nonce), + GNUNET_PQ_query_param_string (address), + GNUNET_PQ_query_param_string (client_scope), + GNUNET_PQ_query_param_string (client_state), + NULL != client_redirect_url + ? GNUNET_PQ_query_param_string (client_redirect_url) + : GNUNET_PQ_query_param_null (), + GNUNET_PQ_query_param_end + }; + struct GNUNET_PQ_ResultSpec rs[] = { + GNUNET_PQ_result_spec_absolute_time ("last_tx_time", + last_tx_time), + GNUNET_PQ_result_spec_uint32 ("last_pin", + last_pin), + GNUNET_PQ_result_spec_uint32 ("pin_attempts_left", + pin_attempts_left), + GNUNET_PQ_result_spec_end + }; + + PREPARE (pg, + "validate_set_address", + "UPDATE validations SET" + " address_attempts_left=CASE" + " WHEN address != $2" + " THEN address_attempts_left - 1" + " ELSE address_attempts_left" + " END" + " ,address=$2" + " ,client_scope=$3" + " ,client_state=$4" + " ,client_redirect_url=$5" + " WHERE nonce=$1" + " AND (address_attempts_left > 0" + " OR address == $2)" + " RETURNING" + " last_tx_time" + " ,last_pin" + " ,pin_attempts_left;"); + return GNUNET_PQ_eval_prepared_singleton_select (pg->conn, + "validate_set_address", + params, + rs); } diff --git a/src/challengerdb/pg_validate_login_pin.c b/src/challengerdb/pg_validate_login_pin.c @@ -33,6 +33,25 @@ CH_PG_validate_login_pin (void *cls, uint32_t new_pin, uint32_t auth_attempts_allowed) { - GNUNET_break (0); - return GNUNET_DB_STATUS_HARD_ERROR; + struct PostgresClosure *pg = cls; + struct GNUNET_PQ_QueryParam params[] = { + GNUNET_PQ_query_param_auto_from_type (nonce), + GNUNET_PQ_query_param_absolute_time (&tx_time), + GNUNET_PQ_query_param_uint32 (&new_pin), + GNUNET_PQ_query_param_uint32 (&auth_attempts_allowed), + GNUNET_PQ_query_param_end + }; + + PREPARE (pg, + "validate_login_set_pin", + "UPDATE validations SET" + " last_tx_time=$2" + " ,last_pin=$3" + " ,auth_attempts_left=$4" + " ,pin_attempts_left=pin_attempts_left - 1" + " WHERE nonce=$1" + " AND pin_attempts_left > 0;"); + return GNUNET_PQ_eval_prepared_non_select (pg->conn, + "validate_login_set_pin", + params); } diff --git a/src/challengerdb/pg_validate_solve_pin.c b/src/challengerdb/pg_validate_solve_pin.c @@ -32,6 +32,45 @@ CH_PG_validate_solve_pin (void *cls, uint32_t new_pin, bool *solved) { - GNUNET_break (0); - return GNUNET_DB_STATUS_HARD_ERROR; + struct PostgresClosure *pg = cls; + struct GNUNET_PQ_QueryParam params[] = { + GNUNET_PQ_query_param_auto_from_type (nonce), + GNUNET_PQ_query_param_uint32 (&new_pin), + GNUNET_PQ_query_param_end + }; + struct GNUNET_PQ_ResultSpec rs[] = { + GNUNET_PQ_result_spec_bool ("solved", + solved), + GNUNET_PQ_result_spec_end + }; + + /* We set all remaining attempts to zero to prevent + user from changing the address after already having + succeeded with the process. */ + PREPARE (pg, + "validate_solve_pin", + "UPDATE validations SET" + " auth_attempts_left=CASE" + " WHEN last_pin == $2" + " THEN 0" + " ELSE auth_attempts_left - 1" + " END" + " ,address_attempts_left=CASE" + " WHEN last_pin == $2" + " THEN 0" + " ELSE address_attempts_left" + " END" + " ,pin_attempts_left=CASE" + " WHEN last_pin == $2" + " THEN 0" + " ELSE pin_attempts_left" + " END" + " WHERE nonce=$1" + " AND auth_attempts_left > 0" + " RETURNING" + " (last_pin == $2) AS solved;"); + return GNUNET_PQ_eval_prepared_singleton_select (pg->conn, + "validate_solve_pin", + params, + rs); } diff --git a/src/challengerdb/pg_validation_get.c b/src/challengerdb/pg_validation_get.c @@ -34,6 +34,48 @@ CH_PG_validation_get (void *cls, char **client_state, char **client_redirect_url) { - GNUNET_break (0); - return GNUNET_DB_STATUS_HARD_ERROR; + struct PostgresClosure *pg = cls; + struct GNUNET_PQ_QueryParam params[] = { + GNUNET_PQ_query_param_auto_from_type (nonce), + GNUNET_PQ_query_param_end + }; + struct GNUNET_PQ_ResultSpec rs[] = { + GNUNET_PQ_result_spec_string ("client_secret", + client_secret), + GNUNET_PQ_result_spec_allow_null ( + GNUNET_PQ_result_spec_string ("address", + address), + NULL), + GNUNET_PQ_result_spec_allow_null ( + GNUNET_PQ_result_spec_string ("client_scope", + client_scope), + NULL), + GNUNET_PQ_result_spec_allow_null ( + GNUNET_PQ_result_spec_string ("client_state", + client_state), + NULL), + GNUNET_PQ_result_spec_string ("redirect_url", + client_redirect_url), + GNUNET_PQ_result_spec_end + }; + + *client_scope = NULL; + *client_state = NULL; + *address = NULL; + PREPARE (pg, + "validation_get", + "SELECT " + " client_secret" + " ,address" + " ,client_scope" + " ,client_state" + " ,COALESCE(client_redirect_url,url) AS redirect_url" + " FROM validations" + " JOIN clients " + " USING (client_serial_id)" + " WHERE nonce=$1"); + return GNUNET_PQ_eval_prepared_singleton_select (pg->conn, + "validation_get", + params, + rs); } diff --git a/src/challengerdb/pg_validation_setup.c b/src/challengerdb/pg_validation_setup.c @@ -32,6 +32,22 @@ CH_PG_validation_setup (void *cls, const struct CHALLENGER_ValidationNonceP *nonce, struct GNUNET_TIME_Absolute expiration_time) { - GNUNET_break (0); - return GNUNET_DB_STATUS_HARD_ERROR; + struct PostgresClosure *pg = cls; + struct GNUNET_PQ_QueryParam params[] = { + GNUNET_PQ_query_param_uint64 (&client_id), + GNUNET_PQ_query_param_auto_from_type (nonce), + GNUNET_PQ_query_param_absolute_time (&expiration_time), + GNUNET_PQ_query_param_end + }; + + PREPARE (pg, + "validation_setup", + "INSERT INTO validations" + " (client_serial_id" + " ,nonce" + " ,expiration_time" + ") VALUES ($1, $2, $3);"); + return GNUNET_PQ_eval_prepared_non_select (pg->conn, + "validation_setup", + params); } diff --git a/src/include/challenger_database_plugin.h b/src/include/challenger_database_plugin.h @@ -173,18 +173,18 @@ struct CHALLENGER_DatabasePlugin * client is incremented by the given value if the client was found. * * @param cls - * @param client_url URL of the client + * @param client_id ID of the client * @param client_secret secret of the client * @param counter_increment change in validation counter - * @param[out] client_id set to unique row of the client + * @param[out] client_url set client redirect URL (if known) * @return transaction status */ enum GNUNET_DB_QueryStatus (*client_check)(void *cls, - const char *client_url, + uint64_t client_id, const char *client_secret, uint32_t counter_increment, - uint64_t *client_id); + char **client_url); /** @@ -263,7 +263,7 @@ struct CHALLENGER_DatabasePlugin * * @param cls * @param nonce unique nonce to use to identify the validation - * @param[out] open set to true if a challenge was sent + * @param[out] is_open set to true if a challenge was sent * @return transaction status: * #GNUNET_DB_SUCCESS_ONE_RESULT if the nonce was found * #GNUNET_DB_SUCCESS_NO_RESULTS if we do not know the nonce @@ -272,7 +272,7 @@ struct CHALLENGER_DatabasePlugin enum GNUNET_DB_QueryStatus (*validate_challenge_open)(void *cls, const struct CHALLENGER_ValidationNonceP *nonce, - bool *open); + bool *is_open); /**