challenger

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

commit d8d009521d384a78b9889e18bb470f9281b5e8f1
parent 836da1b8cc42ef9d076200686da0aa0be9a8ba67
Author: Christian Grothoff <christian@grothoff.org>
Date:   Wed, 22 Jul 2026 03:01:52 +0200

challengerdb: rename functions to match new naming conventions

Diffstat:
Acontrib/check-db-naming.py | 144+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
Acontrib/ci/jobs/6-db-naming/job.sh | 4++++
Mmeson.build | 2+-
Msrc/challenger/challenger-admin.c | 28++++++++++++++--------------
Msrc/challenger/challenger-httpd_authorize.c | 37+++++++++++++++++++------------------
Msrc/challenger/challenger-httpd_challenge.c | 42+++++++++++++++++++++---------------------
Msrc/challenger/challenger-httpd_common.c | 6+++---
Msrc/challenger/challenger-httpd_info.c | 18+++++++++---------
Msrc/challenger/challenger-httpd_setup.c | 76+++++++++++++++-------------------------------------------------------------
Msrc/challenger/challenger-httpd_solve.c | 10+++++-----
Msrc/challenger/challenger-httpd_token.c | 35+++++++++++++++++------------------
Dsrc/challengerdb/address_get.c | 56--------------------------------------------------------
Dsrc/challengerdb/authorize_start.c | 113-------------------------------------------------------------------------------
Dsrc/challengerdb/challenge_set_address_and_pin.c | 125-------------------------------------------------------------------------------
Dsrc/challengerdb/challenger_do_challenge_set_address_and_pin.sql | 141-------------------------------------------------------------------------------
Dsrc/challengerdb/client_add.c | 60------------------------------------------------------------
Dsrc/challengerdb/client_check.c | 117-------------------------------------------------------------------------------
Dsrc/challengerdb/client_delete.c | 45---------------------------------------------
Dsrc/challengerdb/client_modify.c | 52----------------------------------------------------
Asrc/challengerdb/delete_client.c | 45+++++++++++++++++++++++++++++++++++++++++++++
Asrc/challengerdb/do_challenge_address.c | 122+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
Asrc/challengerdb/do_challenge_address.sql | 141+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
Asrc/challengerdb/do_insert_token.c | 74++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
Asrc/challengerdb/do_insert_validation.c | 74++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
Asrc/challengerdb/do_solve_challenge.c | 109+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
Rsrc/challengerdb/challenger_do_validate_and_solve_pin.sql -> src/challengerdb/do_solve_challenge.sql | 0
Asrc/challengerdb/get_client.c | 60++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
Asrc/challengerdb/get_client_by_uri.c | 57+++++++++++++++++++++++++++++++++++++++++++++++++++++++++
Asrc/challengerdb/get_token.c | 71+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
Asrc/challengerdb/get_validation.c | 86+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
Asrc/challengerdb/get_validation_address.c | 57+++++++++++++++++++++++++++++++++++++++++++++++++++++++++
Asrc/challengerdb/get_validation_pkce.c | 99+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
Dsrc/challengerdb/info_get_token.c | 71-----------------------------------------------------------------------
Asrc/challengerdb/insert_client.c | 60++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
Msrc/challengerdb/meson.build | 31++++++++++++++++---------------
Msrc/challengerdb/pg.c | 2+-
Msrc/challengerdb/pg_helper.h | 2+-
Dsrc/challengerdb/setup_nonce.c | 60------------------------------------------------------------
Dsrc/challengerdb/token_add_token.c | 74--------------------------------------------------------------------------
Asrc/challengerdb/update_client.c | 52++++++++++++++++++++++++++++++++++++++++++++++++++++
Asrc/challengerdb/update_validation.c | 113+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
Dsrc/challengerdb/validate_solve_pin.c | 109-------------------------------------------------------------------------------
Dsrc/challengerdb/validation_get.c | 86-------------------------------------------------------------------------------
Dsrc/challengerdb/validation_get_pkce.c | 99-------------------------------------------------------------------------------
Dsrc/include/challenger-database/address_get.h | 46----------------------------------------------
Dsrc/include/challenger-database/authorize_start.h | 79-------------------------------------------------------------------------------
Dsrc/include/challenger-database/challenge_set_address_and_pin.h | 71-----------------------------------------------------------------------
Dsrc/include/challenger-database/client_add.h | 49-------------------------------------------------
Dsrc/include/challenger-database/client_check.h | 67-------------------------------------------------------------------
Dsrc/include/challenger-database/client_delete.h | 39---------------------------------------
Dsrc/include/challenger-database/client_modify.h | 44--------------------------------------------
Asrc/include/challenger-database/delete_client.h | 39+++++++++++++++++++++++++++++++++++++++
Asrc/include/challenger-database/do_challenge_address.h | 71+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
Asrc/include/challenger-database/do_insert_token.h | 49+++++++++++++++++++++++++++++++++++++++++++++++++
Asrc/include/challenger-database/do_insert_validation.h | 59+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
Asrc/include/challenger-database/do_solve_challenge.h | 67+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
Asrc/include/challenger-database/get_client.h | 51+++++++++++++++++++++++++++++++++++++++++++++++++++
Asrc/include/challenger-database/get_client_by_uri.h | 47+++++++++++++++++++++++++++++++++++++++++++++++
Asrc/include/challenger-database/get_token.h | 48++++++++++++++++++++++++++++++++++++++++++++++++
Asrc/include/challenger-database/get_validation.h | 57+++++++++++++++++++++++++++++++++++++++++++++++++++++++++
Asrc/include/challenger-database/get_validation_address.h | 47+++++++++++++++++++++++++++++++++++++++++++++++
Asrc/include/challenger-database/get_validation_pkce.h | 64++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
Dsrc/include/challenger-database/info_get_token.h | 48------------------------------------------------
Asrc/include/challenger-database/insert_client.h | 49+++++++++++++++++++++++++++++++++++++++++++++++++
Dsrc/include/challenger-database/setup_nonce.h | 51---------------------------------------------------
Dsrc/include/challenger-database/token_add_token.h | 49-------------------------------------------------
Asrc/include/challenger-database/update_client.h | 44++++++++++++++++++++++++++++++++++++++++++++
Asrc/include/challenger-database/update_validation.h | 79+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
Dsrc/include/challenger-database/validate_solve_pin.h | 67-------------------------------------------------------------------
Dsrc/include/challenger-database/validation_get.h | 57---------------------------------------------------------
Dsrc/include/challenger-database/validation_get_pkce.h | 64----------------------------------------------------------------
71 files changed, 2261 insertions(+), 2106 deletions(-)

diff --git a/contrib/check-db-naming.py b/contrib/check-db-naming.py @@ -0,0 +1,144 @@ +#!/usr/bin/env python3 +"""Enforce the database layer naming convention. + +Rules checked: + + 1. every public function's name starts with the name of the file it lives in + 2. the file's own name uses a prefix from the closed set, or is exempt + 3. iterate_ iff the function takes a caller-supplied callback; get_ iff not + 4. a .h exists beside every .c, and every .sql that is not schema or + boilerplate is named after the .c that runs it + 5. every prepared statement is named after the function preparing it + 6. no prepared statement name is used in two files + 7. no numeric suffixes and no repeated library prefix + +Run from the top of the source tree; exits non-zero on any violation. +""" +import re +import sys +import pathlib + +# ---------------------------------------------------------------- CONFIG -- +# (impl dir, header dir, symbol prefix, .c basename prefix) +LAYERS = [ + ("src/challengerdb", "src/include/challenger-database", "CHALLENGERDB_", + ""), +] + +# Prefixes that describe what the caller gets. +PREFIXES = ("get_", "get_count_", "get_exists_", "iterate_", + "insert_", "update_", "update_to_", "delete_", "do_") + +# Not CRUD: DDL and maintenance. Keep this list short and justified -- every +# entry is a rule the checker stops enforcing. Connection handling +# (CHALLENGERDB_connect/_connect_admin/_disconnect) lives in pg.c, which is +# skipped below, and challenger has no explicit transaction control. +EXEMPT = { + "create_tables", "drop_tables", "gc", "preflight", +} + +# Files that are not part of the API surface at all: the connection handling, +# the shared PREPARE macro, the copy-me template, and the dbinit binary. +SKIP = {"pg", "pg_helper", "template", "challenger-dbinit"} + +# SQL that belongs to the schema rather than to one API function. +SQL_NOT_A_FUNCTION = {"versioning", "drop", "commit", "procedures-prelude"} +SQL_SCHEMA_RE = re.compile(r"^challenger-\d+$") +# ------------------------------------------------------------ END CONFIG -- + +PREP = re.compile(r'PREPARE\s*\(\s*\w+\s*,\s*"([A-Za-z0-9_]+)"', re.S) + +errors = [] + + +def check_layer(impl_dir, hdr_dir, prefix, fpfx): + impl, hdr = pathlib.Path(impl_dir), pathlib.Path(hdr_dir) + if not impl.is_dir(): + return + decl = re.compile(r"^" + re.escape(prefix) + r"(\w+)\s*\((.*?)\)\s*;", + re.S | re.M) + stmt_owner = {} + stems = set() + + for c in sorted(impl.glob("*.c")): + if c.stem in SKIP or c.stem.startswith("test_") \ + or c.stem.startswith("plugin_"): + continue + if fpfx and not c.stem.startswith(fpfx): + continue + stem = c.stem[len(fpfx):] if fpfx else c.stem + stems.add(stem) + + # 2. prefix from the closed set, or exempt + if stem not in EXEMPT and not stem.startswith(PREFIXES): + errors.append(f"{c}: '{stem}' uses no approved prefix") + + # 7. numeric suffix + if re.search(r"\d$", stem): + errors.append(f"{c}: '{stem}' ends in a digit") + + # 4. matching header + h = hdr / (stem + ".h") + if stem not in EXEMPT and not h.exists(): + errors.append(f"{c}: no matching header {h}") + + text = c.read_text(errors="replace") + + # 5. prepared statements named after the function + for s in dict.fromkeys(PREP.findall(text)): + if s != stem and not s.startswith(stem + "_"): + errors.append( + f"{c}: prepared statement '{s}' is not named after " + f"'{stem}'") + # 6. cross-file uniqueness + if s in stmt_owner and stmt_owner[s] != str(c): + errors.append( + f"{c}: prepared statement '{s}' also prepared in " + f"{stmt_owner[s]}") + stmt_owner[s] = str(c) + + if not h.exists(): + continue + htext = re.sub(r"/\*.*?\*/", "", h.read_text(errors="replace"), + flags=re.S) + for name, params in decl.findall(htext): + # 1. declared names belong to their file. Exempt entries are the + # documented multi-function modules, so this does not apply there. + if (stem not in EXEMPT + and name != stem and not name.startswith(stem + "_")): + errors.append( + f"{h}: declares '{name}', which does not belong to " + f"'{stem}'") + # 3. iterate_ iff callback + has_cb = bool(re.search(r"\w*(Callback|Iterator)\s+\w+", params)) + if name.startswith("iterate_") and not has_cb: + errors.append( + f"{h}: '{name}' is iterate_ but takes no callback") + if name.startswith("get_") and has_cb: + errors.append(f"{h}: '{name}' takes a callback; use iterate_") + + # 4. an amalgamated .sql is named after the .c that runs it, so that a + # renamed function cannot leave its stored procedure behind. + for s in sorted(impl.glob("*.sql")): + if s.stem in SQL_NOT_A_FUNCTION or SQL_SCHEMA_RE.match(s.stem): + continue + if s.stem not in stems: + errors.append(f"{s}: no {impl}/{s.stem}.c runs this SQL") + + # 7. repeated library prefix anywhere in the tree + head = prefix.split("_")[0] + for f in list(impl.glob("*.[ch]")) + list(hdr.glob("*.h")): + if "unc-backup" in f.name: + continue + if re.search(r"\b" + re.escape(head) + r"_" + re.escape(prefix), + f.read_text(errors="replace")): + errors.append(f"{f}: repeated '{prefix}' prefix") + + +for a in LAYERS: + check_layer(*a) + +for e in errors: + print("ERROR:", e) +print(f"\ndb-naming: {len(errors)} violation(s)") +sys.exit(1 if errors else 0) diff --git a/contrib/ci/jobs/6-db-naming/job.sh b/contrib/ci/jobs/6-db-naming/job.sh @@ -0,0 +1,4 @@ +#!/usr/bin/env bash +set -exuo pipefail + +exec ./contrib/check-db-naming.py diff --git a/meson.build b/meson.build @@ -221,7 +221,7 @@ if not get_option('only-doc') libltversions = [ ['libchallengerutil', '0:1:0'], - ['libchallengerdb', '0:1:0'], + ['libchallengerdb', '1:0:0'], ] solibversions = {} diff --git a/src/challenger/challenger-admin.c b/src/challenger/challenger-admin.c @@ -23,10 +23,10 @@ #include <gnunet/gnunet_db_lib.h> #include "challenger_util.h" #include "challenger_database_lib.h" -#include "challenger-database/client_delete.h" -#include "challenger-database/client_check.h" -#include "challenger-database/client_modify.h" -#include "challenger-database/client_add.h" +#include "challenger-database/delete_client.h" +#include "challenger-database/get_client_by_uri.h" +#include "challenger-database/update_client.h" +#include "challenger-database/insert_client.h" #include "challenger-database/preflight.h" @@ -121,7 +121,7 @@ run (void *cls, global_ret = EXIT_INVALIDARGUMENT; goto cleanup; } - qs = CHALLENGERDB_client_delete (db, + qs = CHALLENGERDB_delete_client (db, redirect_uri); switch (qs) { @@ -177,7 +177,7 @@ run (void *cls, goto cleanup; } - qs = CHALLENGERDB_client_modify (db, + qs = CHALLENGERDB_update_client (db, row_id, redirect_uri, client_secret); @@ -207,10 +207,10 @@ run (void *cls, enum GNUNET_DB_QueryStatus qs; uint64_t row_id; - qs = CHALLENGERDB_client_check2 (db, - redirect_uri, - client_secret, - &row_id); + qs = CHALLENGERDB_get_client_by_uri (db, + redirect_uri, + client_secret, + &row_id); switch (qs) { case GNUNET_DB_STATUS_SOFT_ERROR: @@ -231,10 +231,10 @@ run (void *cls, (unsigned long long) row_id); goto cleanup; } - qs = CHALLENGERDB_client_add (db, - redirect_uri, - client_secret, - &row_id); + qs = CHALLENGERDB_insert_client (db, + redirect_uri, + client_secret, + &row_id); switch (qs) { case GNUNET_DB_STATUS_SOFT_ERROR: diff --git a/src/challenger/challenger-httpd_authorize.c b/src/challenger/challenger-httpd_authorize.c @@ -26,7 +26,7 @@ #include "challenger-httpd_authorize.h" #include "challenger-httpd_common.h" #include "challenger-httpd_spa.h" -#include "challenger-database/authorize_start.h" +#include "challenger-database/update_validation.h" #include "challenger_cm_enums.h" /** @@ -215,24 +215,25 @@ CH_handler_authorize (struct CH_HandlerContext *hc, bool solved; enum GNUNET_DB_QueryStatus qs; - /* authorize_start will return 0 if a 'redirect_uri' was + /* update_validation will return 0 if a 'redirect_uri' was configured for the client and this one differs. */ for (unsigned int r = 0; r<MAX_RETRIES; r++) { - qs = CHALLENGERDB_authorize_start (CH_context, - &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); + qs = CHALLENGERDB_update_validation (CH_context, + &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: @@ -241,7 +242,7 @@ CH_handler_authorize (struct CH_HandlerContext *hc, hc, MHD_HTTP_INTERNAL_SERVER_ERROR, TALER_EC_GENERIC_DB_STORE_FAILED, - "authorize_start"); + "update_validation"); case GNUNET_DB_STATUS_SOFT_ERROR: if (r < MAX_RETRIES - 1) continue; @@ -250,7 +251,7 @@ CH_handler_authorize (struct CH_HandlerContext *hc, hc, MHD_HTTP_INTERNAL_SERVER_ERROR, TALER_EC_GENERIC_DB_STORE_FAILED, - "authorize_start"); + "update_validation"); case GNUNET_DB_STATUS_SUCCESS_NO_RESULTS: GNUNET_break_op (0); GNUNET_log (GNUNET_ERROR_TYPE_INFO, diff --git a/src/challenger/challenger-httpd_challenge.c b/src/challenger/challenger-httpd_challenge.c @@ -28,8 +28,8 @@ #include <taler/taler_mhd_lib.h> #include <taler/taler_templating_lib.h> #include <taler/taler_signatures.h> -#include "challenger-database/challenge_set_address_and_pin.h" -#include "challenger-database/address_get.h" +#include "challenger-database/do_challenge_address.h" +#include "challenger-database/get_validation_address.h" #include "challenger-httpd_common.h" /** @@ -860,9 +860,9 @@ CH_handler_challenge (struct CH_HandlerContext *hc, json_t *ro; GNUNET_assert (NULL == bc->client_redirect_uri); - qs = CHALLENGERDB_address_get (CH_context, - &bc->nonce, - &old_address); + qs = CHALLENGERDB_get_validation_address (CH_context, + &bc->nonce, + &old_address); switch (qs) { case GNUNET_DB_STATUS_HARD_ERROR: @@ -870,7 +870,7 @@ CH_handler_challenge (struct CH_HandlerContext *hc, return reply_error (bc, MHD_HTTP_INTERNAL_SERVER_ERROR, TALER_EC_GENERIC_DB_FETCH_FAILED, - "validation-get"); + "get_validation_address"); case GNUNET_DB_STATUS_SOFT_ERROR: if (r < MAX_RETRIES - 1) continue; @@ -878,7 +878,7 @@ CH_handler_challenge (struct CH_HandlerContext *hc, return reply_error (bc, MHD_HTTP_INTERNAL_SERVER_ERROR, TALER_EC_GENERIC_DB_FETCH_FAILED, - "validation-get"); + "get_validation_address"); case GNUNET_DB_STATUS_SUCCESS_NO_RESULTS: GNUNET_break_op (0); return reply_error (bc, @@ -909,18 +909,18 @@ CH_handler_challenge (struct CH_HandlerContext *hc, "read_only", ro)); - qs = CHALLENGERDB_challenge_set_address_and_pin (CH_context, - &bc->nonce, - bc->address, - CH_pin_retransmission_frequency, - &bc->tan, - &bc->state, - &bc->last_tx_time, - &bc->pin_attempts_left, - &bc->retransmit, - &bc->client_redirect_uri, - &bc->address_refused, - &bc->solved); + qs = CHALLENGERDB_do_challenge_address (CH_context, + &bc->nonce, + bc->address, + CH_pin_retransmission_frequency, + &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: @@ -928,7 +928,7 @@ CH_handler_challenge (struct CH_HandlerContext *hc, return reply_error (bc, MHD_HTTP_INTERNAL_SERVER_ERROR, TALER_EC_GENERIC_DB_STORE_FAILED, - "set-address-and-pin"); + "do_challenge_address"); case GNUNET_DB_STATUS_SOFT_ERROR: if (r < MAX_RETRIES - 1) continue; @@ -936,7 +936,7 @@ CH_handler_challenge (struct CH_HandlerContext *hc, return reply_error (bc, MHD_HTTP_INTERNAL_SERVER_ERROR, TALER_EC_GENERIC_DB_STORE_FAILED, - "set-address-and-pin"); + "do_challenge_address"); case GNUNET_DB_STATUS_SUCCESS_NO_RESULTS: GNUNET_break_op (0); return reply_error (bc, diff --git a/src/challenger/challenger-httpd_common.c b/src/challenger/challenger-httpd_common.c @@ -21,7 +21,7 @@ #include "platform.h" #include "challenger-httpd_common.h" #include <gnunet/gnunet_pq_lib.h> -#include "challenger-database/validation_get.h" +#include "challenger-database/get_validation.h" /** @@ -208,7 +208,7 @@ CH_build_full_redirect_url ( enum GNUNET_DB_QueryStatus qs; enum MHD_Result ret; - qs = CHALLENGERDB_validation_get (CH_context, + qs = CHALLENGERDB_get_validation (CH_context, nonce, &client_secret, &address, @@ -224,7 +224,7 @@ CH_build_full_redirect_url ( connection, MHD_HTTP_INTERNAL_SERVER_ERROR, TALER_EC_GENERIC_DB_FETCH_FAILED, - "validation_get"); + "get_validation"); return (MHD_NO == ret) ? GNUNET_SYSERR : GNUNET_NO; case GNUNET_DB_STATUS_SUCCESS_NO_RESULTS: GNUNET_break (0); diff --git a/src/challenger/challenger-httpd_info.c b/src/challenger/challenger-httpd_info.c @@ -24,7 +24,7 @@ #include <gnunet/gnunet_db_lib.h> #include "challenger-httpd_common.h" #include "challenger-httpd_info.h" -#include "challenger-database/info_get_token.h" +#include "challenger-database/get_token.h" /** @@ -94,11 +94,11 @@ CH_handler_info (struct CH_HandlerContext *hc, enum GNUNET_DB_QueryStatus qs; struct GNUNET_TIME_Timestamp address_expiration; - qs = CHALLENGERDB_info_get_token (CH_context, - &grant, - &id, - &address, - &address_expiration); + qs = CHALLENGERDB_get_token (CH_context, + &grant, + &id, + &address, + &address_expiration); switch (qs) { case GNUNET_DB_STATUS_HARD_ERROR: @@ -106,7 +106,7 @@ CH_handler_info (struct CH_HandlerContext *hc, return TALER_MHD_reply_with_error (hc->connection, MHD_HTTP_INTERNAL_SERVER_ERROR, TALER_EC_GENERIC_DB_FETCH_FAILED, - "info_get_token"); + "get_token"); case GNUNET_DB_STATUS_SOFT_ERROR: if (r < MAX_RETRIES - 1) continue; @@ -114,12 +114,12 @@ CH_handler_info (struct CH_HandlerContext *hc, return TALER_MHD_reply_with_error (hc->connection, MHD_HTTP_INTERNAL_SERVER_ERROR, TALER_EC_GENERIC_DB_FETCH_FAILED, - "info_get_token"); + "get_token"); case GNUNET_DB_STATUS_SUCCESS_NO_RESULTS: return TALER_MHD_reply_with_error (hc->connection, MHD_HTTP_NOT_FOUND, TALER_EC_CHALLENGER_GRANT_UNKNOWN, - "info_get_token"); + "get_token"); case GNUNET_DB_STATUS_SUCCESS_ONE_RESULT: break; } diff --git a/src/challenger/challenger-httpd_setup.c b/src/challenger/challenger-httpd_setup.c @@ -24,16 +24,10 @@ #include <gnunet/gnunet_db_lib.h> #include "challenger-httpd_setup.h" #include "challenger-httpd_common.h" -#include "challenger-database/setup_nonce.h" -#include "challenger-database/client_check.h" +#include "challenger-database/do_insert_validation.h" /** - * Maximum number of retries for the database interaction. - */ -#define MAX_RETRIES 3 - -/** * Set to 1 to dump addresses into the log. */ #define DEBUG 0 @@ -175,50 +169,6 @@ CH_handler_setup (struct CH_HandlerContext *hc, "read_only"); } } - /* FIXME: the two transactions below should be folded - into a single transaction (both to only increment - the validation counter on success and for performance). */ - for (unsigned int r = 0; r<MAX_RETRIES; r++) - { - enum GNUNET_DB_QueryStatus qs; - char *client_url = NULL; - - qs = CHALLENGERDB_client_check (CH_context, - (uint64_t) client_id, - client_secret, - 1, - &client_url); - 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, - "client_check"); - 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, - TALER_EC_GENERIC_DB_FETCH_FAILED, - "client_check"); - case GNUNET_DB_STATUS_SUCCESS_NO_RESULTS: - return TALER_MHD_reply_with_error ( - hc->connection, - MHD_HTTP_NOT_FOUND, - TALER_EC_CHALLENGER_GENERIC_CLIENT_UNKNOWN, - NULL); - case GNUNET_DB_STATUS_SUCCESS_ONE_RESULT: - break; - } - GNUNET_free (client_url); - break; - } - { struct CHALLENGER_ValidationNonceP nonce; struct GNUNET_TIME_Absolute expiration_time; @@ -227,11 +177,15 @@ CH_handler_setup (struct CH_HandlerContext *hc, expiration_time = GNUNET_TIME_relative_to_absolute (CH_validation_duration); GNUNET_CRYPTO_random_block (&nonce, sizeof (nonce)); - qs = CHALLENGERDB_setup_nonce (CH_context, - client_id, - &nonce, - expiration_time, - sc->root); + /* Authenticating the client, charging it for the validation and + creating the validation row all happen in this one statement, so + the validation counter only moves if the setup really succeeded. */ + qs = CHALLENGERDB_do_insert_validation (CH_context, + client_id, + client_secret, + &nonce, + expiration_time, + sc->root); switch (qs) { case GNUNET_DB_STATUS_HARD_ERROR: @@ -241,14 +195,14 @@ CH_handler_setup (struct CH_HandlerContext *hc, hc->connection, MHD_HTTP_INTERNAL_SERVER_ERROR, TALER_EC_GENERIC_DB_STORE_FAILED, - "setup_nonce"); + "do_insert_validation"); case GNUNET_DB_STATUS_SUCCESS_NO_RESULTS: - GNUNET_break (0); + /* Nothing was inserted, so the client did not authenticate. */ return TALER_MHD_reply_with_error ( hc->connection, - MHD_HTTP_INTERNAL_SERVER_ERROR, - TALER_EC_GENERIC_INTERNAL_INVARIANT_FAILURE, - "no results from setup_nonce"); + MHD_HTTP_NOT_FOUND, + TALER_EC_CHALLENGER_GENERIC_CLIENT_UNKNOWN, + NULL); case GNUNET_DB_STATUS_SUCCESS_ONE_RESULT: break; } diff --git a/src/challenger/challenger-httpd_solve.c b/src/challenger/challenger-httpd_solve.c @@ -27,8 +27,8 @@ #include <taler/taler_json_lib.h> #include <taler/taler_templating_lib.h> #include <taler/taler_signatures.h> -#include "challenger-database/validation_get.h" -#include "challenger-database/validate_solve_pin.h" +#include "challenger-database/get_validation.h" +#include "challenger-database/do_solve_challenge.h" /** @@ -279,7 +279,7 @@ CH_handler_solve (struct CH_HandlerContext *hc, for (unsigned int r = 0; r<MAX_RETRIES; r++) { - qs = CHALLENGERDB_validate_solve_pin (CH_context, + qs = CHALLENGERDB_do_solve_challenge (CH_context, &bc->nonce, pin, &solved, @@ -298,7 +298,7 @@ CH_handler_solve (struct CH_HandlerContext *hc, hc->connection, MHD_HTTP_INTERNAL_SERVER_ERROR, TALER_EC_GENERIC_DB_FETCH_FAILED, - "validate_solve_pin"); + "do_solve_challenge"); case GNUNET_DB_STATUS_SOFT_ERROR: if (r < MAX_RETRIES - 1) continue; @@ -307,7 +307,7 @@ CH_handler_solve (struct CH_HandlerContext *hc, hc->connection, MHD_HTTP_INTERNAL_SERVER_ERROR, TALER_EC_GENERIC_DB_FETCH_FAILED, - "validate_solve_pin"); + "do_solve_challenge"); case GNUNET_DB_STATUS_SUCCESS_NO_RESULTS: return TALER_MHD_reply_with_error ( hc->connection, diff --git a/src/challenger/challenger-httpd_token.c b/src/challenger/challenger-httpd_token.c @@ -27,9 +27,9 @@ #include <taler/taler_json_lib.h> #include <taler/taler_signatures.h> #include "challenger_cm_enums.h" -#include "challenger-database/validation_get_pkce.h" -#include "challenger-database/client_check.h" -#include "challenger-database/token_add_token.h" +#include "challenger-database/get_validation_pkce.h" +#include "challenger-database/get_client.h" +#include "challenger-database/do_insert_token.h" #define MAX_RETRIES 3 @@ -357,11 +357,10 @@ CH_handler_token (struct CH_HandlerContext *hc, for (unsigned int r = 0; r < MAX_RETRIES; r++) { - qs = CHALLENGERDB_client_check (CH_context, - client_id, - bc->client_secret, - 0, /* do not increment */ - &client_url); + qs = CHALLENGERDB_get_client (CH_context, + client_id, + bc->client_secret, + &client_url); switch (qs) { case GNUNET_DB_STATUS_HARD_ERROR: @@ -370,7 +369,7 @@ CH_handler_token (struct CH_HandlerContext *hc, hc->connection, MHD_HTTP_INTERNAL_SERVER_ERROR, TALER_EC_GENERIC_DB_FETCH_FAILED, - "client_check"); + "get_client"); case GNUNET_DB_STATUS_SOFT_ERROR: continue; case GNUNET_DB_STATUS_SUCCESS_NO_RESULTS: @@ -393,7 +392,7 @@ CH_handler_token (struct CH_HandlerContext *hc, hc->connection, MHD_HTTP_INTERNAL_SERVER_ERROR, TALER_EC_GENERIC_DB_SOFT_FAILURE, - "client_check"); + "get_client"); } if ( (NULL != client_url) && (0 != strcmp (client_url, @@ -447,7 +446,7 @@ CH_handler_token (struct CH_HandlerContext *hc, &code_dummy)); for (unsigned int r = 0; r < MAX_RETRIES; r++) { - qs = CHALLENGERDB_validation_get_pkce (CH_context, + qs = CHALLENGERDB_get_validation_pkce (CH_context, &bc->nonce, (uint64_t) code_client_id, &client_secret, @@ -465,7 +464,7 @@ CH_handler_token (struct CH_HandlerContext *hc, hc->connection, MHD_HTTP_INTERNAL_SERVER_ERROR, TALER_EC_GENERIC_DB_FETCH_FAILED, - "validation_get_pkce"); + "get_validation_pkce"); case GNUNET_DB_STATUS_SOFT_ERROR: continue; case GNUNET_DB_STATUS_SUCCESS_NO_RESULTS: @@ -475,7 +474,7 @@ CH_handler_token (struct CH_HandlerContext *hc, MHD_HTTP_BAD_REQUEST, "invalid_grant", TALER_EC_CHALLENGER_GENERIC_VALIDATION_UNKNOWN, - "validation_get_pkce"); + "get_validation_pkce"); case GNUNET_DB_STATUS_SUCCESS_ONE_RESULT: break; } @@ -488,7 +487,7 @@ CH_handler_token (struct CH_HandlerContext *hc, hc->connection, MHD_HTTP_INTERNAL_SERVER_ERROR, TALER_EC_GENERIC_DB_SOFT_FAILURE, - "validation_get_pkce"); + "get_validation_pkce"); } code_challenge_method_enum = CHALLENGER_cm_from_int ( @@ -746,7 +745,7 @@ CH_handler_token (struct CH_HandlerContext *hc, sizeof (token)); for (unsigned int r = 0; r < MAX_RETRIES; r++) { - qs = CHALLENGERDB_token_add_token (CH_context, + qs = CHALLENGERDB_do_insert_token (CH_context, &bc->nonce, &token, CH_token_expiration, @@ -759,7 +758,7 @@ CH_handler_token (struct CH_HandlerContext *hc, hc->connection, MHD_HTTP_INTERNAL_SERVER_ERROR, TALER_EC_GENERIC_DB_STORE_FAILED, - "token_add_token"); + "do_insert_token"); case GNUNET_DB_STATUS_SOFT_ERROR: continue; case GNUNET_DB_STATUS_SUCCESS_NO_RESULTS: @@ -769,7 +768,7 @@ CH_handler_token (struct CH_HandlerContext *hc, MHD_HTTP_BAD_REQUEST, "invalid_grant", TALER_EC_CHALLENGER_GRANT_UNKNOWN, - "token_add_token"); + "do_insert_token"); case GNUNET_DB_STATUS_SUCCESS_ONE_RESULT: break; } @@ -782,7 +781,7 @@ CH_handler_token (struct CH_HandlerContext *hc, hc->connection, MHD_HTTP_INTERNAL_SERVER_ERROR, TALER_EC_GENERIC_DB_SOFT_FAILURE, - "token_add_token"); + "do_insert_token"); } diff --git a/src/challengerdb/address_get.c b/src/challengerdb/address_get.c @@ -1,56 +0,0 @@ -/* - This file is part of Challenger - Copyright (C) 2025 Taler Systems SA - - Challenger is free software; you can redistribute it and/or modify it under the - terms of the GNU General Public License as published by the Free Software - Foundation; either version 3, or (at your option) any later version. - - Challenger is distributed in the hope that it will be useful, but WITHOUT ANY - WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR - A PARTICULAR PURPOSE. See the GNU General Public License for more details. - - You should have received a copy of the GNU General Public License along with - Challenger; see the file COPYING. If not, see <http://www.gnu.org/licenses/> - */ -/** - * @file src/challengerdb/address_get.c - * @brief Implementation of the address_get function for Postgres - * @author Christian Grothoff - */ -#include "platform.h" -#include <taler/taler_error_codes.h> -#include <taler/taler_dbevents.h> -#include <taler/taler_pq_lib.h> -#include "address_get.h" -#include "pg_helper.h" - -enum GNUNET_DB_QueryStatus -CHALLENGERDB_address_get (struct CHALLENGERDB_PostgresContext *ctx, - const struct CHALLENGER_ValidationNonceP *nonce, - json_t **address) -{ - 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_allow_null ( - TALER_PQ_result_spec_json ("address", - address), - NULL), - GNUNET_PQ_result_spec_end - }; - - *address = NULL; - PREPARE (ctx, - "address_get", - "SELECT " - " address" - " FROM validations" - " WHERE nonce=$1"); - return GNUNET_PQ_eval_prepared_singleton_select (ctx->conn, - "address_get", - params, - rs); -} diff --git a/src/challengerdb/authorize_start.c b/src/challengerdb/authorize_start.c @@ -1,113 +0,0 @@ -/* - This file is part of Challenger - Copyright (C) 2023 Taler Systems SA - - Challenger is free software; you can redistribute it and/or modify it under the - terms of the GNU General Public License as published by the Free Software - Foundation; either version 3, or (at your option) any later version. - - Challenger is distributed in the hope that it will be useful, but WITHOUT ANY - WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR - A PARTICULAR PURPOSE. See the GNU General Public License for more details. - - You should have received a copy of the GNU General Public License along with - Challenger; see the file COPYING. If not, see <http://www.gnu.org/licenses/> - */ -/** - * @file src/challengerdb/authorize_start.c - * @brief Implementation of the authorize_start function for Postgres - * @author Christian Grothoff - * @author Bohdan Potuzhnyi - * @author Vlada Svirsh - */ -#include "platform.h" -#include <taler/taler_error_codes.h> -#include <taler/taler_dbevents.h> -#include <taler/taler_pq_lib.h> -#include "authorize_start.h" -#include "pg_helper.h" - - -enum GNUNET_DB_QueryStatus -CHALLENGERDB_authorize_start ( - struct CHALLENGERDB_PostgresContext *ctx, - const struct CHALLENGER_ValidationNonceP *nonce, - uint64_t client_id, - const char *client_scope, - const char *client_state, - const char *client_redirect_uri, - const char *code_challenge, - uint32_t code_challenge_method, - json_t **last_address, - uint32_t *address_attempts_left, - uint32_t *pin_transmissions_left, - uint32_t *auth_attempts_left, - bool *solved, - struct GNUNET_TIME_Absolute *last_tx_time) -{ - struct GNUNET_TIME_Absolute now - = GNUNET_TIME_absolute_get (); - struct GNUNET_PQ_QueryParam params[] = { - GNUNET_PQ_query_param_auto_from_type (nonce), - GNUNET_PQ_query_param_uint64 (&client_id), - NULL != client_scope - ? GNUNET_PQ_query_param_string (client_scope) - : GNUNET_PQ_query_param_null (), - NULL != client_state - ? GNUNET_PQ_query_param_string (client_state) - : GNUNET_PQ_query_param_null (), - NULL != client_redirect_uri - ? GNUNET_PQ_query_param_string (client_redirect_uri) - : GNUNET_PQ_query_param_null (), - NULL != code_challenge - ? GNUNET_PQ_query_param_string (code_challenge) - : GNUNET_PQ_query_param_null (), - GNUNET_PQ_query_param_uint32 (&code_challenge_method), - GNUNET_PQ_query_param_absolute_time (&now), - GNUNET_PQ_query_param_end - }; - struct GNUNET_PQ_ResultSpec rs[] = { - GNUNET_PQ_result_spec_allow_null ( - TALER_PQ_result_spec_json ("address", - last_address), - NULL), - GNUNET_PQ_result_spec_uint32 ("address_attempts_left", - address_attempts_left), - GNUNET_PQ_result_spec_uint32 ("pin_transmissions_left", - pin_transmissions_left), - GNUNET_PQ_result_spec_uint32 ("auth_attempts_left", - auth_attempts_left), - GNUNET_PQ_result_spec_bool ("solved", - solved), - GNUNET_PQ_result_spec_absolute_time ("last_tx_time", - last_tx_time), - GNUNET_PQ_result_spec_end - }; - - *last_address = NULL; - PREPARE (ctx, - "authorize_start_validation", - "UPDATE validations SET" - " client_scope=$3" - " ,client_state=$4" - " ,client_redirect_uri=COALESCE($5::VARCHAR,client_redirect_uri)" - " ,code_challenge=$6" - " ,code_challenge_method=$7" - " WHERE nonce=$1" - " AND client_serial_id=$2" - " AND expiration_time > $8" - " AND ( ($5::VARCHAR=client_redirect_uri)" - " OR ( ($5::VARCHAR IS NULL)" - " AND (client_redirect_uri IS NOT NULL) ) )" - " RETURNING" - " address" - " ,address_attempts_left" - " ,pin_transmissions_left" - " ,GREATEST(0, auth_attempts_left) AS auth_attempts_left" - " ,auth_attempts_left = -1 AS solved" - " ,last_tx_time;"); - return GNUNET_PQ_eval_prepared_singleton_select (ctx->conn, - "authorize_start_validation", - params, - rs); -} diff --git a/src/challengerdb/challenge_set_address_and_pin.c b/src/challengerdb/challenge_set_address_and_pin.c @@ -1,125 +0,0 @@ -/* - This file is part of Challenger - Copyright (C) 2023 Taler Systems SA - - Challenger is free software; you can redistribute it and/or modify it under the - terms of the GNU General Public License as published by the Free Software - Foundation; either version 3, or (at your option) any later version. - - Challenger is distributed in the hope that it will be useful, but WITHOUT ANY - WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR - A PARTICULAR PURPOSE. See the GNU General Public License for more details. - - You should have received a copy of the GNU General Public License along with - Challenger; see the file COPYING. If not, see <http://www.gnu.org/licenses/> - */ -/** - * @file src/challengerdb/challenge_set_address_and_pin.c - * @brief Implementation of the challenge_set_address_and_pin function for Postgres - * @author Christian Grothoff - */ -#include "platform.h" -#include <taler/taler_error_codes.h> -#include <taler/taler_dbevents.h> -#include <taler/taler_pq_lib.h> -#include "challenge_set_address_and_pin.h" -#include "pg_helper.h" - - -enum GNUNET_DB_QueryStatus -CHALLENGERDB_challenge_set_address_and_pin (struct - CHALLENGERDB_PostgresContext *ctx, - const struct - CHALLENGER_ValidationNonceP *nonce, - const json_t *address, - struct GNUNET_TIME_Relative - retransmission_frequency, - uint32_t *tan, - char **state, - struct GNUNET_TIME_Absolute * - last_tx_time, - uint32_t *auth_attempts_left, - bool *pin_transmit, - char **client_redirect_uri, - bool *address_refused, - bool *solved) -{ - struct GNUNET_TIME_Absolute now - = GNUNET_TIME_absolute_get (); - /* We must gate retransmission on - last_tx_time + retransmission_frequency <= now - but 'last_tx_time' is only read (under FOR UPDATE) inside the stored - procedure, so we cannot form that sum here. We therefore pass the - equivalent, inverted form: the *newest* 'last_tx_time' for which a - retransmission is still due. The SQL then merely checks - last_tx_time <= retransmit_cutoff. - Note that this is deliberately a subtraction from 'now', not - 'now + retransmission_frequency': the value is compared against a - timestamp in the *past*. GNUNET_TIME_absolute_subtract() saturates at - zero rather than underflowing, so a FOREVER frequency degrades to - "never *re*transmit" (the initial PIN, sent when last_tx_time is still 0, - is unaffected). */ - struct GNUNET_TIME_Absolute retransmit_cutoff - = GNUNET_TIME_absolute_subtract (now, - retransmission_frequency); - struct GNUNET_PQ_QueryParam params[] = { - GNUNET_PQ_query_param_auto_from_type (nonce), - TALER_PQ_query_param_json (address), - GNUNET_PQ_query_param_absolute_time (&retransmit_cutoff), - GNUNET_PQ_query_param_absolute_time (&now), - GNUNET_PQ_query_param_uint32 (tan), - GNUNET_PQ_query_param_end - }; - bool not_found; - struct GNUNET_PQ_ResultSpec rs[] = { - GNUNET_PQ_result_spec_bool ("not_found", - &not_found), - GNUNET_PQ_result_spec_absolute_time ("last_tx_time", - last_tx_time), - GNUNET_PQ_result_spec_uint32 ("last_pin", - tan), - GNUNET_PQ_result_spec_bool ("pin_transmit", - pin_transmit), - GNUNET_PQ_result_spec_uint32 ("auth_attempts_left", - auth_attempts_left), - GNUNET_PQ_result_spec_allow_null ( - GNUNET_PQ_result_spec_string ("client_redirect_uri", - client_redirect_uri), - NULL), - GNUNET_PQ_result_spec_allow_null ( - GNUNET_PQ_result_spec_string ("state", - state), - NULL), - GNUNET_PQ_result_spec_bool ("address_refused", - address_refused), - GNUNET_PQ_result_spec_bool ("solved", - solved), - GNUNET_PQ_result_spec_end - }; - enum GNUNET_DB_QueryStatus qs; - - *client_redirect_uri = NULL; - PREPARE (ctx, - "do_challenge_set_address_and_pin", - "SELECT " - " out_not_found AS not_found" - ",out_last_tx_time AS last_tx_time" - ",out_pin_transmit AS pin_transmit" - ",out_last_pin AS last_pin" - ",out_state AS state" - ",out_auth_attempts_left AS auth_attempts_left" - ",out_client_redirect_uri AS client_redirect_uri" - ",out_address_refused AS address_refused" - ",out_solved AS solved" - " FROM challenger_do_challenge_set_address_and_pin" - " ($1,$2,$3,$4,$5);"); - qs = GNUNET_PQ_eval_prepared_singleton_select (ctx->conn, - "do_challenge_set_address_and_pin", - params, - rs); - if (qs <= 0) - return qs; - if (not_found) - return GNUNET_DB_STATUS_SUCCESS_NO_RESULTS; - return qs; -} diff --git a/src/challengerdb/challenger_do_challenge_set_address_and_pin.sql b/src/challengerdb/challenger_do_challenge_set_address_and_pin.sql @@ -1,141 +0,0 @@ --- --- This file is part of TALER --- Copyright (C) 2024 Taler Systems SA --- --- TALER is free software; you can redistribute it and/or modify it under the --- terms of the GNU General Public License as published by the Free Software --- Foundation; either version 3, or (at your option) any later version. --- --- TALER is distributed in the hope that it will be useful, but WITHOUT ANY --- WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR --- A PARTICULAR PURPOSE. See the GNU General Public License for more details. --- --- You should have received a copy of the GNU General Public License along with --- TALER; see the file COPYING. If not, see <http://www.gnu.org/licenses/> --- - - -DROP FUNCTION IF EXISTS challenger_do_challenge_set_address_and_pin; -CREATE FUNCTION challenger_do_challenge_set_address_and_pin ( - IN in_nonce BYTEA, - IN in_address TEXT, - -- Newest last_tx_time for which a (re)transmission is still due, that is - -- 'now - retransmission_frequency'. Computed by the caller because - -- last_tx_time is only known here; see challenge_set_address_and_pin.c. - IN in_retransmit_cutoff INT8, - IN in_now INT8, - IN in_tan INT4, - OUT out_not_found BOOLEAN, - OUT out_last_tx_time INT8, - OUT out_last_pin INT4, - OUT out_state TEXT, - OUT out_pin_transmit BOOLEAN, - OUT out_auth_attempts_left INT4, - OUT out_client_redirect_uri TEXT, - OUT out_address_refused BOOLEAN, - OUT out_solved BOOLEAN) -LANGUAGE plpgsql -AS $$ -DECLARE - my_status RECORD; - my_do_update BOOL; -BEGIN - -my_do_update = FALSE; - -SELECT address - ,address_attempts_left - ,pin_transmissions_left - ,last_tx_time - ,client_redirect_uri - ,last_pin - ,auth_attempts_left - ,client_state - INTO my_status - FROM validations - WHERE nonce=in_nonce - AND expiration_time > in_now - FOR UPDATE; - -IF NOT FOUND -THEN - out_not_found=TRUE; - out_last_tx_time=0; - out_last_pin=0; - out_pin_transmit=FALSE; - out_auth_attempts_left=0; - out_client_redirect_uri=NULL; - out_address_refused=TRUE; - out_solved=FALSE; - out_state=NULL; - RETURN; -END IF; -out_not_found=FALSE; -out_last_tx_time=my_status.last_tx_time; -out_last_pin=my_status.last_pin; -out_pin_transmit=FALSE; -out_auth_attempts_left=my_status.auth_attempts_left; -out_state=my_status.client_state; -out_client_redirect_uri=my_status.client_redirect_uri; - -IF ( 0 > my_status.auth_attempts_left ) -- this challenge is solved -THEN - out_address_refused=TRUE; - out_solved=TRUE; - out_auth_attempts_left=0; - RETURN; -END IF; -out_solved=FALSE; - -IF ( (0 = my_status.address_attempts_left) AND - (in_address != my_status.address) ) -THEN - out_address_refused=TRUE; - out_last_pin=0; - RETURN; -END IF; -out_address_refused=FALSE; - -IF ( (my_status.address IS NULL) OR - (in_address != my_status.address) ) -THEN - -- we are changing the address, update counters - my_status.address_attempts_left - = GREATEST(0,my_status.address_attempts_left - 1); - my_status.address = in_address; - my_status.pin_transmissions_left = 3; - my_status.last_tx_time = 0; - my_do_update=TRUE; -END IF; - -IF ( (my_status.pin_transmissions_left > 0) AND - (my_status.last_tx_time <= in_retransmit_cutoff) ) -THEN - -- enough time has passed since the last transmission, so - -- we are changing the PIN, update counters - my_status.pin_transmissions_left = my_status.pin_transmissions_left - 1; - my_status.last_pin = in_tan; - my_status.auth_attempts_left = 3; - my_status.last_tx_time = in_now; - out_auth_attempts_left = 3; - out_pin_transmit=TRUE; - out_last_pin = in_tan; - out_last_tx_time = in_now; - my_do_update=TRUE; -END IF; - -IF my_do_update -THEN - UPDATE validations SET - address=my_status.address - ,address_attempts_left=my_status.address_attempts_left - ,pin_transmissions_left=my_status.pin_transmissions_left - ,last_tx_time=my_status.last_tx_time - ,last_pin=my_status.last_pin - ,auth_attempts_left=my_status.auth_attempts_left - WHERE nonce=in_nonce; -END IF; - -RETURN; - -END $$; diff --git a/src/challengerdb/client_add.c b/src/challengerdb/client_add.c @@ -1,60 +0,0 @@ -/* - This file is part of Challenger - Copyright (C) 2023 Taler Systems SA - - Challenger is free software; you can redistribute it and/or modify it under the - terms of the GNU General Public License as published by the Free Software - Foundation; either version 3, or (at your option) any later version. - - Challenger is distributed in the hope that it will be useful, but WITHOUT ANY - WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR - A PARTICULAR PURPOSE. See the GNU General Public License for more details. - - You should have received a copy of the GNU General Public License along with - Challenger; see the file COPYING. If not, see <http://www.gnu.org/licenses/> - */ -/** - * @file src/challengerdb/client_add.c - * @brief Implementation of the client_add function for Postgres - * @author Christian Grothoff - */ -#include "platform.h" -#include <taler/taler_error_codes.h> -#include <taler/taler_dbevents.h> -#include <taler/taler_pq_lib.h> -#include "client_add.h" -#include "pg_helper.h" - - -enum GNUNET_DB_QueryStatus -CHALLENGERDB_client_add (struct CHALLENGERDB_PostgresContext *ctx, - const char *client_redirect_uri, - const char *client_secret, - uint64_t *client_id) -{ - struct GNUNET_PQ_QueryParam params[] = { - GNUNET_PQ_query_param_string (client_redirect_uri), - GNUNET_PQ_query_param_string (client_secret), - GNUNET_PQ_query_param_end - }; - struct GNUNET_PQ_ResultSpec rs[] = { - GNUNET_PQ_result_spec_uint64 ("client_serial_id", - client_id), - GNUNET_PQ_result_spec_end - }; - - *client_id = 0; - PREPARE (ctx, - "client_add", - "INSERT INTO clients" - " (uri" - " ,client_secret" - ") VALUES " - "($1, $2)" - " ON CONFLICT DO NOTHING" /* CONFLICT on (uri) */ - " RETURNING client_serial_id"); - return GNUNET_PQ_eval_prepared_singleton_select (ctx->conn, - "client_add", - params, - rs); -} diff --git a/src/challengerdb/client_check.c b/src/challengerdb/client_check.c @@ -1,117 +0,0 @@ -/* - This file is part of Challenger - Copyright (C) 2023 Taler Systems SA - - Challenger is free software; you can redistribute it and/or modify it under the - terms of the GNU General Public License as published by the Free Software - Foundation; either version 3, or (at your option) any later version. - - Challenger is distributed in the hope that it will be useful, but WITHOUT ANY - WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR - A PARTICULAR PURPOSE. See the GNU General Public License for more details. - - You should have received a copy of the GNU General Public License along with - Challenger; see the file COPYING. If not, see <http://www.gnu.org/licenses/> - */ -/** - * @file src/challengerdb/client_check.c - * @brief Implementation of the client_check function for Postgres - * @author Christian Grothoff - */ -#include "platform.h" -#include <taler/taler_error_codes.h> -#include <taler/taler_dbevents.h> -#include <taler/taler_pq_lib.h> -#include "client_check.h" -#include "pg_helper.h" - - -enum GNUNET_DB_QueryStatus -CHALLENGERDB_client_check ( - struct CHALLENGERDB_PostgresContext *ctx, - uint64_t client_id, - const char *client_secret, - uint32_t counter_increment, - char **client_redirect_uri) -{ - struct GNUNET_PQ_ResultSpec rs[] = { - GNUNET_PQ_result_spec_allow_null ( - GNUNET_PQ_result_spec_string ("uri", - client_redirect_uri), - NULL), - GNUNET_PQ_result_spec_end - }; - - *client_redirect_uri = NULL; - if (0 == counter_increment) - { - struct GNUNET_PQ_QueryParam params[] = { - GNUNET_PQ_query_param_uint64 (&client_id), - GNUNET_PQ_query_param_string (client_secret), - GNUNET_PQ_query_param_end - }; - - PREPARE (ctx, - "client_check_ro", - "SELECT uri" - " FROM clients" - " WHERE client_serial_id=$1" - " AND client_secret=$2;"); - return GNUNET_PQ_eval_prepared_singleton_select (ctx->conn, - "client_check_ro", - params, - rs); - } - else - { - 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 - }; - - PREPARE (ctx, - "client_check", - "UPDATE clients SET" - " validation_counter=validation_counter+CAST($3::INT4 AS INT8)" - " WHERE client_serial_id=$1" - " AND client_secret=$2" - " RETURNING uri;"); - return GNUNET_PQ_eval_prepared_singleton_select (ctx->conn, - "client_check", - params, - rs); - } -} - - -enum GNUNET_DB_QueryStatus -CHALLENGERDB_client_check2 ( - struct CHALLENGERDB_PostgresContext *ctx, - const char *client_uri, - const char *client_secret, - uint64_t *client_id) -{ - struct GNUNET_PQ_QueryParam params[] = { - GNUNET_PQ_query_param_string (client_uri), - GNUNET_PQ_query_param_string (client_secret), - GNUNET_PQ_query_param_end - }; - struct GNUNET_PQ_ResultSpec rs[] = { - GNUNET_PQ_result_spec_uint64 ("client_serial_id", - client_id), - GNUNET_PQ_result_spec_end - }; - - PREPARE (ctx, - "client_check2", - "SELECT client_serial_id" - " FROM clients" - " WHERE uri=$1" - " AND client_secret=$2;"); - return GNUNET_PQ_eval_prepared_singleton_select (ctx->conn, - "client_check2", - params, - rs); -} diff --git a/src/challengerdb/client_delete.c b/src/challengerdb/client_delete.c @@ -1,45 +0,0 @@ -/* - This file is part of Challenger - Copyright (C) 2023 Taler Systems SA - - Challenger is free software; you can redistribute it and/or modify it under the - terms of the GNU General Public License as published by the Free Software - Foundation; either version 3, or (at your option) any later version. - - Challenger is distributed in the hope that it will be useful, but WITHOUT ANY - WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR - A PARTICULAR PURPOSE. See the GNU General Public License for more details. - - You should have received a copy of the GNU General Public License along with - Challenger; see the file COPYING. If not, see <http://www.gnu.org/licenses/> - */ -/** - * @file src/challengerdb/client_delete.c - * @brief Implementation of the client_delete function for Postgres - * @author Christian Grothoff - */ -#include "platform.h" -#include <taler/taler_error_codes.h> -#include <taler/taler_dbevents.h> -#include <taler/taler_pq_lib.h> -#include "client_delete.h" -#include "pg_helper.h" - - -enum GNUNET_DB_QueryStatus -CHALLENGERDB_client_delete (struct CHALLENGERDB_PostgresContext *ctx, - const char *client_redirect_uri) -{ - struct GNUNET_PQ_QueryParam params[] = { - GNUNET_PQ_query_param_string (client_redirect_uri), - GNUNET_PQ_query_param_end - }; - - PREPARE (ctx, - "client_delete", - "DELETE FROM clients" - " WHERE uri=$1;"); - return GNUNET_PQ_eval_prepared_non_select (ctx->conn, - "client_delete", - params); -} diff --git a/src/challengerdb/client_modify.c b/src/challengerdb/client_modify.c @@ -1,52 +0,0 @@ -/* - This file is part of Challenger - Copyright (C) 2024 Taler Systems SA - - Challenger is free software; you can redistribute it and/or modify it under the - terms of the GNU General Public License as published by the Free Software - Foundation; either version 3, or (at your option) any later version. - - Challenger is distributed in the hope that it will be useful, but WITHOUT ANY - WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR - A PARTICULAR PURPOSE. See the GNU General Public License for more details. - - You should have received a copy of the GNU General Public License along with - Challenger; see the file COPYING. If not, see <http://www.gnu.org/licenses/> - */ -/** - * @file src/challengerdb/client_modify.c - * @brief Implementation of the client_modify function for Postgres - * @author Christian Grothoff - */ -#include "platform.h" -#include <taler/taler_error_codes.h> -#include <taler/taler_dbevents.h> -#include <taler/taler_pq_lib.h> -#include "client_modify.h" -#include "pg_helper.h" - -enum GNUNET_DB_QueryStatus -CHALLENGERDB_client_modify (struct CHALLENGERDB_PostgresContext *ctx, - uint64_t client_id, - const char *client_redirect_uri, - const char *client_secret) -{ - struct GNUNET_PQ_QueryParam params[] = { - GNUNET_PQ_query_param_uint64 (&client_id), - GNUNET_PQ_query_param_string (client_redirect_uri), - NULL == client_secret - ? GNUNET_PQ_query_param_null () - : GNUNET_PQ_query_param_string (client_secret), - GNUNET_PQ_query_param_end - }; - - PREPARE (ctx, - "client_modify", - "UPDATE clients" - " SET uri=$2" - " ,client_secret=COALESCE($3,client_secret)" - " WHERE client_serial_id=$1"); - return GNUNET_PQ_eval_prepared_non_select (ctx->conn, - "client_modify", - params); -} diff --git a/src/challengerdb/delete_client.c b/src/challengerdb/delete_client.c @@ -0,0 +1,45 @@ +/* + This file is part of Challenger + Copyright (C) 2023 Taler Systems SA + + Challenger is free software; you can redistribute it and/or modify it under the + terms of the GNU General Public License as published by the Free Software + Foundation; either version 3, or (at your option) any later version. + + Challenger is distributed in the hope that it will be useful, but WITHOUT ANY + WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR + A PARTICULAR PURPOSE. See the GNU General Public License for more details. + + You should have received a copy of the GNU General Public License along with + Challenger; see the file COPYING. If not, see <http://www.gnu.org/licenses/> + */ +/** + * @file src/challengerdb/delete_client.c + * @brief Implementation of the delete_client function for Postgres + * @author Christian Grothoff + */ +#include "platform.h" +#include <taler/taler_error_codes.h> +#include <taler/taler_dbevents.h> +#include <taler/taler_pq_lib.h> +#include "delete_client.h" +#include "pg_helper.h" + + +enum GNUNET_DB_QueryStatus +CHALLENGERDB_delete_client (struct CHALLENGERDB_PostgresContext *ctx, + const char *client_redirect_uri) +{ + struct GNUNET_PQ_QueryParam params[] = { + GNUNET_PQ_query_param_string (client_redirect_uri), + GNUNET_PQ_query_param_end + }; + + PREPARE (ctx, + "delete_client", + "DELETE FROM clients" + " WHERE uri=$1;"); + return GNUNET_PQ_eval_prepared_non_select (ctx->conn, + "delete_client", + params); +} diff --git a/src/challengerdb/do_challenge_address.c b/src/challengerdb/do_challenge_address.c @@ -0,0 +1,122 @@ +/* + This file is part of Challenger + Copyright (C) 2023 Taler Systems SA + + Challenger is free software; you can redistribute it and/or modify it under the + terms of the GNU General Public License as published by the Free Software + Foundation; either version 3, or (at your option) any later version. + + Challenger is distributed in the hope that it will be useful, but WITHOUT ANY + WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR + A PARTICULAR PURPOSE. See the GNU General Public License for more details. + + You should have received a copy of the GNU General Public License along with + Challenger; see the file COPYING. If not, see <http://www.gnu.org/licenses/> + */ +/** + * @file src/challengerdb/do_challenge_address.c + * @brief Implementation of the do_challenge_address function for Postgres + * @author Christian Grothoff + */ +#include "platform.h" +#include <taler/taler_error_codes.h> +#include <taler/taler_dbevents.h> +#include <taler/taler_pq_lib.h> +#include "do_challenge_address.h" +#include "pg_helper.h" + + +enum GNUNET_DB_QueryStatus +CHALLENGERDB_do_challenge_address ( + struct CHALLENGERDB_PostgresContext *ctx, + const struct CHALLENGER_ValidationNonceP *nonce, + const json_t *address, + struct GNUNET_TIME_Relative retransmission_frequency, + uint32_t *tan, + char **state, + struct GNUNET_TIME_Absolute *last_tx_time, + uint32_t *auth_attempts_left, + bool *pin_transmit, + char **client_redirect_uri, + bool *address_refused, + bool *solved) +{ + struct GNUNET_TIME_Absolute now + = GNUNET_TIME_absolute_get (); + /* We must gate retransmission on + last_tx_time + retransmission_frequency <= now + but 'last_tx_time' is only read (under FOR UPDATE) inside the stored + procedure, so we cannot form that sum here. We therefore pass the + equivalent, inverted form: the *newest* 'last_tx_time' for which a + retransmission is still due. The SQL then merely checks + last_tx_time <= retransmit_cutoff. + Note that this is deliberately a subtraction from 'now', not + 'now + retransmission_frequency': the value is compared against a + timestamp in the *past*. GNUNET_TIME_absolute_subtract() saturates at + zero rather than underflowing, so a FOREVER frequency degrades to + "never *re*transmit" (the initial PIN, sent when last_tx_time is still 0, + is unaffected). */ + struct GNUNET_TIME_Absolute retransmit_cutoff + = GNUNET_TIME_absolute_subtract (now, + retransmission_frequency); + struct GNUNET_PQ_QueryParam params[] = { + GNUNET_PQ_query_param_auto_from_type (nonce), + TALER_PQ_query_param_json (address), + GNUNET_PQ_query_param_absolute_time (&retransmit_cutoff), + GNUNET_PQ_query_param_absolute_time (&now), + GNUNET_PQ_query_param_uint32 (tan), + GNUNET_PQ_query_param_end + }; + bool not_found; + struct GNUNET_PQ_ResultSpec rs[] = { + GNUNET_PQ_result_spec_bool ("not_found", + &not_found), + GNUNET_PQ_result_spec_absolute_time ("last_tx_time", + last_tx_time), + GNUNET_PQ_result_spec_uint32 ("last_pin", + tan), + GNUNET_PQ_result_spec_bool ("pin_transmit", + pin_transmit), + GNUNET_PQ_result_spec_uint32 ("auth_attempts_left", + auth_attempts_left), + GNUNET_PQ_result_spec_allow_null ( + GNUNET_PQ_result_spec_string ("client_redirect_uri", + client_redirect_uri), + NULL), + GNUNET_PQ_result_spec_allow_null ( + GNUNET_PQ_result_spec_string ("state", + state), + NULL), + GNUNET_PQ_result_spec_bool ("address_refused", + address_refused), + GNUNET_PQ_result_spec_bool ("solved", + solved), + GNUNET_PQ_result_spec_end + }; + enum GNUNET_DB_QueryStatus qs; + + *client_redirect_uri = NULL; + PREPARE (ctx, + "do_challenge_address", + "SELECT " + " out_not_found AS not_found" + ",out_last_tx_time AS last_tx_time" + ",out_pin_transmit AS pin_transmit" + ",out_last_pin AS last_pin" + ",out_state AS state" + ",out_auth_attempts_left AS auth_attempts_left" + ",out_client_redirect_uri AS client_redirect_uri" + ",out_address_refused AS address_refused" + ",out_solved AS solved" + " FROM challenger_do_challenge_set_address_and_pin" + " ($1,$2,$3,$4,$5);"); + qs = GNUNET_PQ_eval_prepared_singleton_select (ctx->conn, + "do_challenge_address", + params, + rs); + if (qs <= 0) + return qs; + if (not_found) + return GNUNET_DB_STATUS_SUCCESS_NO_RESULTS; + return qs; +} diff --git a/src/challengerdb/do_challenge_address.sql b/src/challengerdb/do_challenge_address.sql @@ -0,0 +1,141 @@ +-- +-- This file is part of TALER +-- Copyright (C) 2024 Taler Systems SA +-- +-- TALER is free software; you can redistribute it and/or modify it under the +-- terms of the GNU General Public License as published by the Free Software +-- Foundation; either version 3, or (at your option) any later version. +-- +-- TALER is distributed in the hope that it will be useful, but WITHOUT ANY +-- WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR +-- A PARTICULAR PURPOSE. See the GNU General Public License for more details. +-- +-- You should have received a copy of the GNU General Public License along with +-- TALER; see the file COPYING. If not, see <http://www.gnu.org/licenses/> +-- + + +DROP FUNCTION IF EXISTS challenger_do_challenge_set_address_and_pin; +CREATE FUNCTION challenger_do_challenge_set_address_and_pin ( + IN in_nonce BYTEA, + IN in_address TEXT, + -- Newest last_tx_time for which a (re)transmission is still due, that is + -- 'now - retransmission_frequency'. Computed by the caller because + -- last_tx_time is only known here; see do_challenge_address.c. + IN in_retransmit_cutoff INT8, + IN in_now INT8, + IN in_tan INT4, + OUT out_not_found BOOLEAN, + OUT out_last_tx_time INT8, + OUT out_last_pin INT4, + OUT out_state TEXT, + OUT out_pin_transmit BOOLEAN, + OUT out_auth_attempts_left INT4, + OUT out_client_redirect_uri TEXT, + OUT out_address_refused BOOLEAN, + OUT out_solved BOOLEAN) +LANGUAGE plpgsql +AS $$ +DECLARE + my_status RECORD; + my_do_update BOOL; +BEGIN + +my_do_update = FALSE; + +SELECT address + ,address_attempts_left + ,pin_transmissions_left + ,last_tx_time + ,client_redirect_uri + ,last_pin + ,auth_attempts_left + ,client_state + INTO my_status + FROM validations + WHERE nonce=in_nonce + AND expiration_time > in_now + FOR UPDATE; + +IF NOT FOUND +THEN + out_not_found=TRUE; + out_last_tx_time=0; + out_last_pin=0; + out_pin_transmit=FALSE; + out_auth_attempts_left=0; + out_client_redirect_uri=NULL; + out_address_refused=TRUE; + out_solved=FALSE; + out_state=NULL; + RETURN; +END IF; +out_not_found=FALSE; +out_last_tx_time=my_status.last_tx_time; +out_last_pin=my_status.last_pin; +out_pin_transmit=FALSE; +out_auth_attempts_left=my_status.auth_attempts_left; +out_state=my_status.client_state; +out_client_redirect_uri=my_status.client_redirect_uri; + +IF ( 0 > my_status.auth_attempts_left ) -- this challenge is solved +THEN + out_address_refused=TRUE; + out_solved=TRUE; + out_auth_attempts_left=0; + RETURN; +END IF; +out_solved=FALSE; + +IF ( (0 = my_status.address_attempts_left) AND + (in_address != my_status.address) ) +THEN + out_address_refused=TRUE; + out_last_pin=0; + RETURN; +END IF; +out_address_refused=FALSE; + +IF ( (my_status.address IS NULL) OR + (in_address != my_status.address) ) +THEN + -- we are changing the address, update counters + my_status.address_attempts_left + = GREATEST(0,my_status.address_attempts_left - 1); + my_status.address = in_address; + my_status.pin_transmissions_left = 3; + my_status.last_tx_time = 0; + my_do_update=TRUE; +END IF; + +IF ( (my_status.pin_transmissions_left > 0) AND + (my_status.last_tx_time <= in_retransmit_cutoff) ) +THEN + -- enough time has passed since the last transmission, so + -- we are changing the PIN, update counters + my_status.pin_transmissions_left = my_status.pin_transmissions_left - 1; + my_status.last_pin = in_tan; + my_status.auth_attempts_left = 3; + my_status.last_tx_time = in_now; + out_auth_attempts_left = 3; + out_pin_transmit=TRUE; + out_last_pin = in_tan; + out_last_tx_time = in_now; + my_do_update=TRUE; +END IF; + +IF my_do_update +THEN + UPDATE validations SET + address=my_status.address + ,address_attempts_left=my_status.address_attempts_left + ,pin_transmissions_left=my_status.pin_transmissions_left + ,last_tx_time=my_status.last_tx_time + ,last_pin=my_status.last_pin + ,auth_attempts_left=my_status.auth_attempts_left + WHERE nonce=in_nonce; +END IF; + +RETURN; + +END $$; diff --git a/src/challengerdb/do_insert_token.c b/src/challengerdb/do_insert_token.c @@ -0,0 +1,74 @@ +/* + This file is part of Challenger + Copyright (C) 2023 Taler Systems SA + + Challenger is free software; you can redistribute it and/or modify it under the + terms of the GNU General Public License as published by the Free Software + Foundation; either version 3, or (at your option) any later version. + + Challenger is distributed in the hope that it will be useful, but WITHOUT ANY + WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR + A PARTICULAR PURPOSE. See the GNU General Public License for more details. + + You should have received a copy of the GNU General Public License along with + Challenger; see the file COPYING. If not, see <http://www.gnu.org/licenses/> + */ +/** + * @file src/challengerdb/do_insert_token.c + * @brief Implementation of the do_insert_token function for Postgres + * @author Christian Grothoff + */ +#include "platform.h" +#include <taler/taler_error_codes.h> +#include <taler/taler_dbevents.h> +#include <taler/taler_pq_lib.h> +#include "do_insert_token.h" +#include "pg_helper.h" + + +enum GNUNET_DB_QueryStatus +CHALLENGERDB_do_insert_token (struct CHALLENGERDB_PostgresContext *ctx, + const struct CHALLENGER_ValidationNonceP *nonce, + const struct CHALLENGER_AccessTokenP *token, + struct GNUNET_TIME_Relative token_expiration, + struct GNUNET_TIME_Relative address_expiration) +{ + struct GNUNET_TIME_Absolute ge + = GNUNET_TIME_relative_to_absolute (token_expiration); + struct GNUNET_PQ_QueryParam params[] = { + GNUNET_PQ_query_param_auto_from_type (nonce), + GNUNET_PQ_query_param_auto_from_type (token), + GNUNET_PQ_query_param_absolute_time (&ge), + GNUNET_PQ_query_param_relative_time (&address_expiration), + GNUNET_PQ_query_param_end + }; + + /* Redemption must be atomic and one-shot (RFC 6749 4.1.2): consume the + validation by deleting it as we mint the token, so the same authorization + code cannot be replayed to mint additional tokens. A replay finds no + matching validations row and thus inserts no token (NO_RESULTS), which the + caller maps to 'invalid_grant'. The 'address IS NOT NULL' guard avoids + violating the tokens.address NOT NULL constraint (and only consumes a + validation that actually carries a solved address). */ + PREPARE (ctx, + "do_insert_token", + "WITH consumed AS (" + " DELETE FROM validations" + " WHERE nonce=$1" + " AND address IS NOT NULL" + " RETURNING address, last_tx_time" + ") INSERT INTO tokens" + " (access_token" + " ,address" + " ,token_expiration_time" + " ,address_expiration_time" + ") SELECT" + " $2" + " ,address" + " ,$3" + " ,LEAST($4, 9223372036854775807::BIGINT - last_tx_time) + last_tx_time" + " FROM consumed;"); + return GNUNET_PQ_eval_prepared_non_select (ctx->conn, + "do_insert_token", + params); +} diff --git a/src/challengerdb/do_insert_validation.c b/src/challengerdb/do_insert_validation.c @@ -0,0 +1,74 @@ +/* + This file is part of Challenger + Copyright (C) 2023 Taler Systems SA + + Challenger is free software; you can redistribute it and/or modify it under the + terms of the GNU General Public License as published by the Free Software + Foundation; either version 3, or (at your option) any later version. + + Challenger is distributed in the hope that it will be useful, but WITHOUT ANY + WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR + A PARTICULAR PURPOSE. See the GNU General Public License for more details. + + You should have received a copy of the GNU General Public License along with + Challenger; see the file COPYING. If not, see <http://www.gnu.org/licenses/> + */ +/** + * @file src/challengerdb/do_insert_validation.c + * @brief Implementation of the do_insert_validation function for Postgres + * @author Christian Grothoff + */ +#include "platform.h" +#include <taler/taler_error_codes.h> +#include <taler/taler_dbevents.h> +#include <taler/taler_pq_lib.h> +#include "do_insert_validation.h" +#include "pg_helper.h" + + +enum GNUNET_DB_QueryStatus +CHALLENGERDB_do_insert_validation (struct CHALLENGERDB_PostgresContext *ctx, + uint64_t client_id, + const char *client_secret, + const struct + CHALLENGER_ValidationNonceP *nonce, + struct GNUNET_TIME_Absolute expiration_time, + const json_t *initial_address) +{ + struct GNUNET_PQ_QueryParam params[] = { + GNUNET_PQ_query_param_uint64 (&client_id), + GNUNET_PQ_query_param_string (client_secret), + GNUNET_PQ_query_param_auto_from_type (nonce), + GNUNET_PQ_query_param_absolute_time (&expiration_time), + NULL == initial_address + ? GNUNET_PQ_query_param_null () + : TALER_PQ_query_param_json (initial_address), + GNUNET_PQ_query_param_end + }; + + /* Authenticating the client, charging it for the validation and creating + the validation row must happen together: the counter may only move if + the validation is really created. Doing it in one statement also saves + the round trips of an explicit transaction. A client that does not + exist (or presents the wrong secret) leaves the CTE empty, so nothing is + inserted and the caller sees NO_RESULTS. */ + PREPARE (ctx, + "do_insert_validation", + "WITH charged AS (" + " UPDATE clients" + " SET validation_counter=validation_counter+1" + " WHERE client_serial_id=$1" + " AND client_secret=$2" + " RETURNING client_serial_id, uri" + ") INSERT INTO validations" + " (client_serial_id" + " ,nonce" + " ,expiration_time" + " ,client_redirect_uri" + " ,address" + ") SELECT client_serial_id, $3, $4, uri, $5" + " FROM charged;"); + return GNUNET_PQ_eval_prepared_non_select (ctx->conn, + "do_insert_validation", + params); +} diff --git a/src/challengerdb/do_solve_challenge.c b/src/challengerdb/do_solve_challenge.c @@ -0,0 +1,109 @@ +/* + This file is part of Challenger + Copyright (C) 2023 Taler Systems SA + + Challenger is free software; you can redistribute it and/or modify it under the + terms of the GNU General Public License as published by the Free Software + Foundation; either version 3, or (at your option) any later version. + + Challenger is distributed in the hope that it will be useful, but WITHOUT ANY + WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR + A PARTICULAR PURPOSE. See the GNU General Public License for more details. + + You should have received a copy of the GNU General Public License along with + Challenger; see the file COPYING. If not, see <http://www.gnu.org/licenses/> + */ +/** + * @file src/challengerdb/do_solve_challenge.c + * @brief Implementation of the do_solve_challenge function for Postgres + * @author Christian Grothoff + */ +#include "platform.h" +#include <taler/taler_error_codes.h> +#include <taler/taler_dbevents.h> +#include <taler/taler_pq_lib.h> +#include "do_solve_challenge.h" +#include "pg_helper.h" + + +enum GNUNET_DB_QueryStatus +CHALLENGERDB_do_solve_challenge ( + struct CHALLENGERDB_PostgresContext *ctx, + const struct CHALLENGER_ValidationNonceP *nonce, + uint32_t new_pin, + bool *solved, + bool *exhausted, + bool *no_challenge, + char **state, + uint32_t *addr_left, + uint32_t *auth_attempts_left, + uint32_t *pin_transmissions_left, + char **client_redirect_uri) +{ + struct GNUNET_TIME_Absolute now + = GNUNET_TIME_absolute_get (); + struct GNUNET_PQ_QueryParam params[] = { + GNUNET_PQ_query_param_auto_from_type (nonce), + GNUNET_PQ_query_param_uint32 (&new_pin), + GNUNET_PQ_query_param_absolute_time (&now), + GNUNET_PQ_query_param_end + }; + bool not_found; + struct GNUNET_PQ_ResultSpec rs[] = { + GNUNET_PQ_result_spec_bool ("not_found", + &not_found), + GNUNET_PQ_result_spec_bool ("solved", + solved), + GNUNET_PQ_result_spec_bool ("exhausted", + exhausted), + GNUNET_PQ_result_spec_bool ("no_challenge", + no_challenge), + GNUNET_PQ_result_spec_uint32 ("address_attempts_left", + addr_left), + GNUNET_PQ_result_spec_uint32 ("auth_attempts_left", + auth_attempts_left), + GNUNET_PQ_result_spec_uint32 ("pin_transmissions_left", + pin_transmissions_left), + GNUNET_PQ_result_spec_allow_null ( + GNUNET_PQ_result_spec_string ("client_redirect_uri", + client_redirect_uri), + NULL), + GNUNET_PQ_result_spec_allow_null ( + GNUNET_PQ_result_spec_string ("state", + state), + NULL), + GNUNET_PQ_result_spec_end + }; + enum GNUNET_DB_QueryStatus qs; + + *client_redirect_uri = NULL; + PREPARE (ctx, + "do_solve_challenge", + "SELECT " + " out_not_found AS not_found" + ",out_solved AS solved" + ",out_exhausted AS exhausted" + ",out_no_challenge AS no_challenge" + ",out_state AS state" + ",out_address_attempts_left AS address_attempts_left" + ",out_auth_attempts_left AS auth_attempts_left" + ",out_pin_transmissions_left AS pin_transmissions_left" + ",out_client_redirect_uri AS client_redirect_uri" + " FROM challenger_do_validate_and_solve_pin" + " ($1,$2,$3);"); + qs = GNUNET_PQ_eval_prepared_singleton_select (ctx->conn, + "do_solve_challenge", + params, + rs); + if (qs <= 0) + return qs; + if (not_found) + return GNUNET_DB_STATUS_SUCCESS_NO_RESULTS; + /* On the solved path the stored procedure returns the -1 sentinel (kept in + the DB to mark the challenge as solved), which the uint32 result spec reads + as 4294967295. That value is not meaningful to the caller (which only + reads it when !solved); normalize it to 0 to avoid leaking the sentinel. */ + if (*solved) + *auth_attempts_left = 0; + return qs; +} diff --git a/src/challengerdb/challenger_do_validate_and_solve_pin.sql b/src/challengerdb/do_solve_challenge.sql diff --git a/src/challengerdb/get_client.c b/src/challengerdb/get_client.c @@ -0,0 +1,60 @@ +/* + This file is part of Challenger + Copyright (C) 2023 Taler Systems SA + + Challenger is free software; you can redistribute it and/or modify it under the + terms of the GNU General Public License as published by the Free Software + Foundation; either version 3, or (at your option) any later version. + + Challenger is distributed in the hope that it will be useful, but WITHOUT ANY + WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR + A PARTICULAR PURPOSE. See the GNU General Public License for more details. + + You should have received a copy of the GNU General Public License along with + Challenger; see the file COPYING. If not, see <http://www.gnu.org/licenses/> + */ +/** + * @file src/challengerdb/get_client.c + * @brief Implementation of the get_client function for Postgres + * @author Christian Grothoff + */ +#include "platform.h" +#include <taler/taler_error_codes.h> +#include <taler/taler_dbevents.h> +#include <taler/taler_pq_lib.h> +#include "get_client.h" +#include "pg_helper.h" + + +enum GNUNET_DB_QueryStatus +CHALLENGERDB_get_client ( + struct CHALLENGERDB_PostgresContext *ctx, + uint64_t client_id, + const char *client_secret, + char **client_redirect_uri) +{ + struct GNUNET_PQ_QueryParam params[] = { + GNUNET_PQ_query_param_uint64 (&client_id), + GNUNET_PQ_query_param_string (client_secret), + GNUNET_PQ_query_param_end + }; + struct GNUNET_PQ_ResultSpec rs[] = { + GNUNET_PQ_result_spec_allow_null ( + GNUNET_PQ_result_spec_string ("uri", + client_redirect_uri), + NULL), + GNUNET_PQ_result_spec_end + }; + + *client_redirect_uri = NULL; + PREPARE (ctx, + "get_client", + "SELECT uri" + " FROM clients" + " WHERE client_serial_id=$1" + " AND client_secret=$2;"); + return GNUNET_PQ_eval_prepared_singleton_select (ctx->conn, + "get_client", + params, + rs); +} diff --git a/src/challengerdb/get_client_by_uri.c b/src/challengerdb/get_client_by_uri.c @@ -0,0 +1,57 @@ +/* + This file is part of Challenger + Copyright (C) 2023 Taler Systems SA + + Challenger is free software; you can redistribute it and/or modify it under the + terms of the GNU General Public License as published by the Free Software + Foundation; either version 3, or (at your option) any later version. + + Challenger is distributed in the hope that it will be useful, but WITHOUT ANY + WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR + A PARTICULAR PURPOSE. See the GNU General Public License for more details. + + You should have received a copy of the GNU General Public License along with + Challenger; see the file COPYING. If not, see <http://www.gnu.org/licenses/> + */ +/** + * @file src/challengerdb/get_client_by_uri.c + * @brief Implementation of the get_client_by_uri function for Postgres + * @author Christian Grothoff + */ +#include "platform.h" +#include <taler/taler_error_codes.h> +#include <taler/taler_dbevents.h> +#include <taler/taler_pq_lib.h> +#include "get_client_by_uri.h" +#include "pg_helper.h" + + +enum GNUNET_DB_QueryStatus +CHALLENGERDB_get_client_by_uri ( + struct CHALLENGERDB_PostgresContext *ctx, + const char *client_uri, + const char *client_secret, + uint64_t *client_id) +{ + struct GNUNET_PQ_QueryParam params[] = { + GNUNET_PQ_query_param_string (client_uri), + GNUNET_PQ_query_param_string (client_secret), + GNUNET_PQ_query_param_end + }; + struct GNUNET_PQ_ResultSpec rs[] = { + GNUNET_PQ_result_spec_uint64 ("client_serial_id", + client_id), + GNUNET_PQ_result_spec_end + }; + + PREPARE (ctx, + "get_client_by_uri", + "SELECT client_serial_id" + " FROM clients" + " WHERE uri=$1" + " AND client_secret=$2;"); + return GNUNET_PQ_eval_prepared_singleton_select (ctx->conn, + "get_client_by_uri", + params, + rs); +} diff --git a/src/challengerdb/get_token.c b/src/challengerdb/get_token.c @@ -0,0 +1,71 @@ +/* + This file is part of Challenger + Copyright (C) 2023 Taler Systems SA + + Challenger is free software; you can redistribute it and/or modify it under the + terms of the GNU General Public License as published by the Free Software + Foundation; either version 3, or (at your option) any later version. + + Challenger is distributed in the hope that it will be useful, but WITHOUT ANY + WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR + A PARTICULAR PURPOSE. See the GNU General Public License for more details. + + You should have received a copy of the GNU General Public License along with + Challenger; see the file COPYING. If not, see <http://www.gnu.org/licenses/> + */ +/** + * @file src/challengerdb/get_token.c + * @brief Implementation of the get_token function for Postgres + * @author Christian Grothoff + */ +#include "platform.h" +#include <taler/taler_error_codes.h> +#include <taler/taler_dbevents.h> +#include <taler/taler_pq_lib.h> +#include "get_token.h" +#include "pg_helper.h" + + +enum GNUNET_DB_QueryStatus +CHALLENGERDB_get_token (struct CHALLENGERDB_PostgresContext *ctx, + const struct CHALLENGER_AccessTokenP *token, + uint64_t *rowid, + json_t **address, + struct GNUNET_TIME_Timestamp *address_expiration) +{ + struct GNUNET_TIME_Absolute now + = GNUNET_TIME_absolute_get (); + struct GNUNET_PQ_QueryParam params[] = { + GNUNET_PQ_query_param_auto_from_type (token), + GNUNET_PQ_query_param_absolute_time (&now), + GNUNET_PQ_query_param_end + }; + struct GNUNET_TIME_Absolute at; + struct GNUNET_PQ_ResultSpec rs[] = { + GNUNET_PQ_result_spec_uint64 ("rowid", + rowid), + TALER_PQ_result_spec_json ("address", + address), + GNUNET_PQ_result_spec_absolute_time ("address_expiration_time", + &at), + GNUNET_PQ_result_spec_end + }; + enum GNUNET_DB_QueryStatus qs; + + PREPARE (ctx, + "get_token", + "SELECT " + " grant_serial_id AS rowid" + " ,address" + " ,address_expiration_time" + " FROM tokens" + " WHERE access_token=$1" + " AND token_expiration_time > $2"); + qs = GNUNET_PQ_eval_prepared_singleton_select (ctx->conn, + "get_token", + params, + rs); + if (qs > 0) + *address_expiration = GNUNET_TIME_absolute_to_timestamp (at); + return qs; +} diff --git a/src/challengerdb/get_validation.c b/src/challengerdb/get_validation.c @@ -0,0 +1,86 @@ +/* + This file is part of Challenger + Copyright (C) 2023 Taler Systems SA + + Challenger is free software; you can redistribute it and/or modify it under the + terms of the GNU General Public License as published by the Free Software + Foundation; either version 3, or (at your option) any later version. + + Challenger is distributed in the hope that it will be useful, but WITHOUT ANY + WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR + A PARTICULAR PURPOSE. See the GNU General Public License for more details. + + You should have received a copy of the GNU General Public License along with + Challenger; see the file COPYING. If not, see <http://www.gnu.org/licenses/> + */ +/** + * @file src/challengerdb/get_validation.c + * @brief Implementation of the get_validation function for Postgres + * @author Christian Grothoff + */ +#include "platform.h" +#include <taler/taler_error_codes.h> +#include <taler/taler_dbevents.h> +#include <taler/taler_pq_lib.h> +#include "get_validation.h" +#include "pg_helper.h" + + +enum GNUNET_DB_QueryStatus +CHALLENGERDB_get_validation ( + struct CHALLENGERDB_PostgresContext *ctx, + const struct CHALLENGER_ValidationNonceP *nonce, + char **client_secret, + json_t **address, + char **client_scope, + char **client_state, + char **client_redirect_uri) +{ + struct GNUNET_TIME_Absolute now + = GNUNET_TIME_absolute_get (); + struct GNUNET_PQ_QueryParam params[] = { + GNUNET_PQ_query_param_auto_from_type (nonce), + GNUNET_PQ_query_param_absolute_time (&now), + 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 ( + TALER_PQ_result_spec_json ("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_uri", + client_redirect_uri), + GNUNET_PQ_result_spec_end + }; + + *client_scope = NULL; + *client_state = NULL; + *address = NULL; + PREPARE (ctx, + "get_validation", + "SELECT " + " client_secret" + " ,address" + " ,client_scope" + " ,client_state" + " ,COALESCE(client_redirect_uri,uri) AS redirect_uri" + " FROM validations" + " JOIN clients " + " USING (client_serial_id)" + " WHERE nonce=$1" + " AND expiration_time > $2"); + return GNUNET_PQ_eval_prepared_singleton_select (ctx->conn, + "get_validation", + params, + rs); +} diff --git a/src/challengerdb/get_validation_address.c b/src/challengerdb/get_validation_address.c @@ -0,0 +1,57 @@ +/* + This file is part of Challenger + Copyright (C) 2025 Taler Systems SA + + Challenger is free software; you can redistribute it and/or modify it under the + terms of the GNU General Public License as published by the Free Software + Foundation; either version 3, or (at your option) any later version. + + Challenger is distributed in the hope that it will be useful, but WITHOUT ANY + WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR + A PARTICULAR PURPOSE. See the GNU General Public License for more details. + + You should have received a copy of the GNU General Public License along with + Challenger; see the file COPYING. If not, see <http://www.gnu.org/licenses/> + */ +/** + * @file src/challengerdb/get_validation_address.c + * @brief Implementation of the get_validation_address function for Postgres + * @author Christian Grothoff + */ +#include "platform.h" +#include <taler/taler_error_codes.h> +#include <taler/taler_dbevents.h> +#include <taler/taler_pq_lib.h> +#include "get_validation_address.h" +#include "pg_helper.h" + +enum GNUNET_DB_QueryStatus +CHALLENGERDB_get_validation_address (struct CHALLENGERDB_PostgresContext *ctx, + const struct CHALLENGER_ValidationNonceP * + nonce, + json_t **address) +{ + 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_allow_null ( + TALER_PQ_result_spec_json ("address", + address), + NULL), + GNUNET_PQ_result_spec_end + }; + + *address = NULL; + PREPARE (ctx, + "get_validation_address", + "SELECT " + " address" + " FROM validations" + " WHERE nonce=$1"); + return GNUNET_PQ_eval_prepared_singleton_select (ctx->conn, + "get_validation_address", + params, + rs); +} diff --git a/src/challengerdb/get_validation_pkce.c b/src/challengerdb/get_validation_pkce.c @@ -0,0 +1,99 @@ +/* + This file is part of Challenger + Copyright (C) 2023 Taler Systems SA + + Challenger is free software; you can redistribute it and/or modify it under the + terms of the GNU General Public License as published by the Free Software + Foundation; either version 3, or (at your option) any later version. + + Challenger is distributed in the hope that it will be useful, but WITHOUT ANY + WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR + A PARTICULAR PURPOSE. See the GNU General Public License for more details. + + You should have received a copy of the GNU General Public License along with + Challenger; see the file COPYING. If not, see <http://www.gnu.org/licenses/> + */ +/** + * @file src/challengerdb/get_validation_pkce.c + * @brief Implementation of the get_validation_pkce function for Postgres + * @author Bohdan Potuzhnyi + * @author Vlada Svirsh + */ +#include "platform.h" +#include <taler/taler_error_codes.h> +#include <taler/taler_dbevents.h> +#include <taler/taler_pq_lib.h> +#include "get_validation_pkce.h" +#include "pg_helper.h" + +enum GNUNET_DB_QueryStatus +CHALLENGERDB_get_validation_pkce ( + struct CHALLENGERDB_PostgresContext *ctx, + const struct CHALLENGER_ValidationNonceP *nonce, + uint64_t client_id, + char **client_secret, + json_t **address, + char **client_scope, + char **client_state, + char **client_redirect_uri, + char **code_challenge, + uint32_t *code_challenge_method) +{ + struct GNUNET_TIME_Absolute now + = GNUNET_TIME_absolute_get (); + struct GNUNET_PQ_QueryParam params[] = { + GNUNET_PQ_query_param_auto_from_type (nonce), + GNUNET_PQ_query_param_absolute_time (&now), + GNUNET_PQ_query_param_uint64 (&client_id), + 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 ( + TALER_PQ_result_spec_json ("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_uri", + client_redirect_uri), + GNUNET_PQ_result_spec_allow_null ( + GNUNET_PQ_result_spec_string ("code_challenge", + code_challenge), + NULL), + GNUNET_PQ_result_spec_uint32 ("code_challenge_method", + code_challenge_method), + GNUNET_PQ_result_spec_end + }; + + *client_scope = NULL; + *client_state = NULL; + *address = NULL; + PREPARE (ctx, + "get_validation_pkce", + "SELECT " + " client_secret" + " ,address" + " ,client_scope" + " ,client_state" + " ,COALESCE(client_redirect_uri,uri) AS redirect_uri" + " ,code_challenge" + " ,code_challenge_method" + " FROM validations" + " JOIN clients " + " USING (client_serial_id)" + " WHERE nonce=$1" + " AND expiration_time > $2" + " AND client_serial_id=$3"); + return GNUNET_PQ_eval_prepared_singleton_select (ctx->conn, + "get_validation_pkce", + params, + rs); +} diff --git a/src/challengerdb/info_get_token.c b/src/challengerdb/info_get_token.c @@ -1,71 +0,0 @@ -/* - This file is part of Challenger - Copyright (C) 2023 Taler Systems SA - - Challenger is free software; you can redistribute it and/or modify it under the - terms of the GNU General Public License as published by the Free Software - Foundation; either version 3, or (at your option) any later version. - - Challenger is distributed in the hope that it will be useful, but WITHOUT ANY - WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR - A PARTICULAR PURPOSE. See the GNU General Public License for more details. - - You should have received a copy of the GNU General Public License along with - Challenger; see the file COPYING. If not, see <http://www.gnu.org/licenses/> - */ -/** - * @file src/challengerdb/info_get_token.c - * @brief Implementation of the info_get_token function for Postgres - * @author Christian Grothoff - */ -#include "platform.h" -#include <taler/taler_error_codes.h> -#include <taler/taler_dbevents.h> -#include <taler/taler_pq_lib.h> -#include "info_get_token.h" -#include "pg_helper.h" - - -enum GNUNET_DB_QueryStatus -CHALLENGERDB_info_get_token (struct CHALLENGERDB_PostgresContext *ctx, - const struct CHALLENGER_AccessTokenP *token, - uint64_t *rowid, - json_t **address, - struct GNUNET_TIME_Timestamp *address_expiration) -{ - struct GNUNET_TIME_Absolute now - = GNUNET_TIME_absolute_get (); - struct GNUNET_PQ_QueryParam params[] = { - GNUNET_PQ_query_param_auto_from_type (token), - GNUNET_PQ_query_param_absolute_time (&now), - GNUNET_PQ_query_param_end - }; - struct GNUNET_TIME_Absolute at; - struct GNUNET_PQ_ResultSpec rs[] = { - GNUNET_PQ_result_spec_uint64 ("rowid", - rowid), - TALER_PQ_result_spec_json ("address", - address), - GNUNET_PQ_result_spec_absolute_time ("address_expiration_time", - &at), - GNUNET_PQ_result_spec_end - }; - enum GNUNET_DB_QueryStatus qs; - - PREPARE (ctx, - "info_get_token", - "SELECT " - " grant_serial_id AS rowid" - " ,address" - " ,address_expiration_time" - " FROM tokens" - " WHERE access_token=$1" - " AND token_expiration_time > $2"); - qs = GNUNET_PQ_eval_prepared_singleton_select (ctx->conn, - "info_get_token", - params, - rs); - if (qs > 0) - *address_expiration = GNUNET_TIME_absolute_to_timestamp (at); - return qs; -} diff --git a/src/challengerdb/insert_client.c b/src/challengerdb/insert_client.c @@ -0,0 +1,60 @@ +/* + This file is part of Challenger + Copyright (C) 2023 Taler Systems SA + + Challenger is free software; you can redistribute it and/or modify it under the + terms of the GNU General Public License as published by the Free Software + Foundation; either version 3, or (at your option) any later version. + + Challenger is distributed in the hope that it will be useful, but WITHOUT ANY + WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR + A PARTICULAR PURPOSE. See the GNU General Public License for more details. + + You should have received a copy of the GNU General Public License along with + Challenger; see the file COPYING. If not, see <http://www.gnu.org/licenses/> + */ +/** + * @file src/challengerdb/insert_client.c + * @brief Implementation of the insert_client function for Postgres + * @author Christian Grothoff + */ +#include "platform.h" +#include <taler/taler_error_codes.h> +#include <taler/taler_dbevents.h> +#include <taler/taler_pq_lib.h> +#include "insert_client.h" +#include "pg_helper.h" + + +enum GNUNET_DB_QueryStatus +CHALLENGERDB_insert_client (struct CHALLENGERDB_PostgresContext *ctx, + const char *client_redirect_uri, + const char *client_secret, + uint64_t *client_id) +{ + struct GNUNET_PQ_QueryParam params[] = { + GNUNET_PQ_query_param_string (client_redirect_uri), + GNUNET_PQ_query_param_string (client_secret), + GNUNET_PQ_query_param_end + }; + struct GNUNET_PQ_ResultSpec rs[] = { + GNUNET_PQ_result_spec_uint64 ("client_serial_id", + client_id), + GNUNET_PQ_result_spec_end + }; + + *client_id = 0; + PREPARE (ctx, + "insert_client", + "INSERT INTO clients" + " (uri" + " ,client_secret" + ") VALUES " + "($1, $2)" + " ON CONFLICT DO NOTHING" /* CONFLICT on (uri) */ + " RETURNING client_serial_id"); + return GNUNET_PQ_eval_prepared_singleton_select (ctx->conn, + "insert_client", + params, + rs); +} diff --git a/src/challengerdb/meson.build b/src/challengerdb/meson.build @@ -7,8 +7,8 @@ sqldir = get_option('datadir') / 'challenger' / 'sql' procedures_sql = [ 'procedures-prelude.sql', - 'challenger_do_challenge_set_address_and_pin.sql', - 'challenger_do_validate_and_solve_pin.sql', + 'do_challenge_address.sql', + 'do_solve_challenge.sql', 'commit.sql', ] @@ -35,24 +35,25 @@ foreach g : generated_sql endforeach libchallengerdb_SOURCES = [ - 'address_get.c', - 'client_add.c', - 'client_modify.c', - 'client_delete.c', - 'client_check.c', + 'get_validation_address.c', + 'insert_client.c', + 'update_client.c', + 'delete_client.c', + 'get_client.c', + 'get_client_by_uri.c', 'create_tables.c', 'drop_tables.c', 'gc.c', - 'info_get_token.c', - 'token_add_token.c', - 'setup_nonce.c', + 'get_token.c', + 'do_insert_token.c', + 'do_insert_validation.c', 'preflight.c', 'pg.c', - 'authorize_start.c', - 'challenge_set_address_and_pin.c', - 'validate_solve_pin.c', - 'validation_get.c', - 'validation_get_pkce.c', + 'update_validation.c', + 'do_challenge_address.c', + 'do_solve_challenge.c', + 'get_validation.c', + 'get_validation_pkce.c', ] libchallengerdb = library( 'challengerdb', diff --git a/src/challengerdb/pg.c b/src/challengerdb/pg.c @@ -14,7 +14,7 @@ Challenger; see the file COPYING. If not, see <http://www.gnu.org/licenses/> */ /** - * @file challengerdb/plugin_challengerdb_postgres.c + * @file src/challengerdb/pg.c * @brief database helper functions for postgres used by challenger * @author Christian Grothoff */ diff --git a/src/challengerdb/pg_helper.h b/src/challengerdb/pg_helper.h @@ -14,7 +14,7 @@ Challenger; see the file COPYING. If not, see <http://www.gnu.org/licenses/> */ /** - * @file challengerdb/pg_helper.h + * @file src/challengerdb/pg_helper.h * @brief database helper definitions * @author Christian Grothoff */ diff --git a/src/challengerdb/setup_nonce.c b/src/challengerdb/setup_nonce.c @@ -1,60 +0,0 @@ -/* - This file is part of Challenger - Copyright (C) 2023 Taler Systems SA - - Challenger is free software; you can redistribute it and/or modify it under the - terms of the GNU General Public License as published by the Free Software - Foundation; either version 3, or (at your option) any later version. - - Challenger is distributed in the hope that it will be useful, but WITHOUT ANY - WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR - A PARTICULAR PURPOSE. See the GNU General Public License for more details. - - You should have received a copy of the GNU General Public License along with - Challenger; see the file COPYING. If not, see <http://www.gnu.org/licenses/> - */ -/** - * @file src/challengerdb/setup_nonce.c - * @brief Implementation of the validation_setup function for Postgres - * @author Christian Grothoff - */ -#include "platform.h" -#include <taler/taler_error_codes.h> -#include <taler/taler_dbevents.h> -#include <taler/taler_pq_lib.h> -#include "setup_nonce.h" -#include "pg_helper.h" - - -enum GNUNET_DB_QueryStatus -CHALLENGERDB_setup_nonce (struct CHALLENGERDB_PostgresContext *ctx, - uint64_t client_id, - const struct CHALLENGER_ValidationNonceP *nonce, - struct GNUNET_TIME_Absolute expiration_time, - const json_t *initial_address) -{ - 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), - NULL == initial_address - ? GNUNET_PQ_query_param_null () - : TALER_PQ_query_param_json (initial_address), - GNUNET_PQ_query_param_end - }; - - PREPARE (ctx, - "setup_nonce", - "INSERT INTO validations" - " (client_serial_id" - " ,nonce" - " ,expiration_time" - " ,client_redirect_uri" - " ,address" - ") SELECT $1, $2, $3, uri, $4" - " FROM CLIENTS" - " WHERE client_serial_id=$1;"); - return GNUNET_PQ_eval_prepared_non_select (ctx->conn, - "setup_nonce", - params); -} diff --git a/src/challengerdb/token_add_token.c b/src/challengerdb/token_add_token.c @@ -1,74 +0,0 @@ -/* - This file is part of Challenger - Copyright (C) 2023 Taler Systems SA - - Challenger is free software; you can redistribute it and/or modify it under the - terms of the GNU General Public License as published by the Free Software - Foundation; either version 3, or (at your option) any later version. - - Challenger is distributed in the hope that it will be useful, but WITHOUT ANY - WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR - A PARTICULAR PURPOSE. See the GNU General Public License for more details. - - You should have received a copy of the GNU General Public License along with - Challenger; see the file COPYING. If not, see <http://www.gnu.org/licenses/> - */ -/** - * @file src/challengerdb/token_add_token.c - * @brief Implementation of the token_add_token function for Postgres - * @author Christian Grothoff - */ -#include "platform.h" -#include <taler/taler_error_codes.h> -#include <taler/taler_dbevents.h> -#include <taler/taler_pq_lib.h> -#include "token_add_token.h" -#include "pg_helper.h" - - -enum GNUNET_DB_QueryStatus -CHALLENGERDB_token_add_token (struct CHALLENGERDB_PostgresContext *ctx, - const struct CHALLENGER_ValidationNonceP *nonce, - const struct CHALLENGER_AccessTokenP *token, - struct GNUNET_TIME_Relative token_expiration, - struct GNUNET_TIME_Relative address_expiration) -{ - struct GNUNET_TIME_Absolute ge - = GNUNET_TIME_relative_to_absolute (token_expiration); - struct GNUNET_PQ_QueryParam params[] = { - GNUNET_PQ_query_param_auto_from_type (nonce), - GNUNET_PQ_query_param_auto_from_type (token), - GNUNET_PQ_query_param_absolute_time (&ge), - GNUNET_PQ_query_param_relative_time (&address_expiration), - GNUNET_PQ_query_param_end - }; - - /* Redemption must be atomic and one-shot (RFC 6749 4.1.2): consume the - validation by deleting it as we mint the token, so the same authorization - code cannot be replayed to mint additional tokens. A replay finds no - matching validations row and thus inserts no token (NO_RESULTS), which the - caller maps to 'invalid_grant'. The 'address IS NOT NULL' guard avoids - violating the tokens.address NOT NULL constraint (and only consumes a - validation that actually carries a solved address). */ - PREPARE (ctx, - "token_add_token", - "WITH consumed AS (" - " DELETE FROM validations" - " WHERE nonce=$1" - " AND address IS NOT NULL" - " RETURNING address, last_tx_time" - ") INSERT INTO tokens" - " (access_token" - " ,address" - " ,token_expiration_time" - " ,address_expiration_time" - ") SELECT" - " $2" - " ,address" - " ,$3" - " ,LEAST($4, 9223372036854775807::BIGINT - last_tx_time) + last_tx_time" - " FROM consumed;"); - return GNUNET_PQ_eval_prepared_non_select (ctx->conn, - "token_add_token", - params); -} diff --git a/src/challengerdb/update_client.c b/src/challengerdb/update_client.c @@ -0,0 +1,52 @@ +/* + This file is part of Challenger + Copyright (C) 2024 Taler Systems SA + + Challenger is free software; you can redistribute it and/or modify it under the + terms of the GNU General Public License as published by the Free Software + Foundation; either version 3, or (at your option) any later version. + + Challenger is distributed in the hope that it will be useful, but WITHOUT ANY + WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR + A PARTICULAR PURPOSE. See the GNU General Public License for more details. + + You should have received a copy of the GNU General Public License along with + Challenger; see the file COPYING. If not, see <http://www.gnu.org/licenses/> + */ +/** + * @file src/challengerdb/update_client.c + * @brief Implementation of the update_client function for Postgres + * @author Christian Grothoff + */ +#include "platform.h" +#include <taler/taler_error_codes.h> +#include <taler/taler_dbevents.h> +#include <taler/taler_pq_lib.h> +#include "update_client.h" +#include "pg_helper.h" + +enum GNUNET_DB_QueryStatus +CHALLENGERDB_update_client (struct CHALLENGERDB_PostgresContext *ctx, + uint64_t client_id, + const char *client_redirect_uri, + const char *client_secret) +{ + struct GNUNET_PQ_QueryParam params[] = { + GNUNET_PQ_query_param_uint64 (&client_id), + GNUNET_PQ_query_param_string (client_redirect_uri), + NULL == client_secret + ? GNUNET_PQ_query_param_null () + : GNUNET_PQ_query_param_string (client_secret), + GNUNET_PQ_query_param_end + }; + + PREPARE (ctx, + "update_client", + "UPDATE clients" + " SET uri=$2" + " ,client_secret=COALESCE($3,client_secret)" + " WHERE client_serial_id=$1"); + return GNUNET_PQ_eval_prepared_non_select (ctx->conn, + "update_client", + params); +} diff --git a/src/challengerdb/update_validation.c b/src/challengerdb/update_validation.c @@ -0,0 +1,113 @@ +/* + This file is part of Challenger + Copyright (C) 2023 Taler Systems SA + + Challenger is free software; you can redistribute it and/or modify it under the + terms of the GNU General Public License as published by the Free Software + Foundation; either version 3, or (at your option) any later version. + + Challenger is distributed in the hope that it will be useful, but WITHOUT ANY + WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR + A PARTICULAR PURPOSE. See the GNU General Public License for more details. + + You should have received a copy of the GNU General Public License along with + Challenger; see the file COPYING. If not, see <http://www.gnu.org/licenses/> + */ +/** + * @file src/challengerdb/update_validation.c + * @brief Implementation of the update_validation function for Postgres + * @author Christian Grothoff + * @author Bohdan Potuzhnyi + * @author Vlada Svirsh + */ +#include "platform.h" +#include <taler/taler_error_codes.h> +#include <taler/taler_dbevents.h> +#include <taler/taler_pq_lib.h> +#include "update_validation.h" +#include "pg_helper.h" + + +enum GNUNET_DB_QueryStatus +CHALLENGERDB_update_validation ( + struct CHALLENGERDB_PostgresContext *ctx, + const struct CHALLENGER_ValidationNonceP *nonce, + uint64_t client_id, + const char *client_scope, + const char *client_state, + const char *client_redirect_uri, + const char *code_challenge, + uint32_t code_challenge_method, + json_t **last_address, + uint32_t *address_attempts_left, + uint32_t *pin_transmissions_left, + uint32_t *auth_attempts_left, + bool *solved, + struct GNUNET_TIME_Absolute *last_tx_time) +{ + struct GNUNET_TIME_Absolute now + = GNUNET_TIME_absolute_get (); + struct GNUNET_PQ_QueryParam params[] = { + GNUNET_PQ_query_param_auto_from_type (nonce), + GNUNET_PQ_query_param_uint64 (&client_id), + NULL != client_scope + ? GNUNET_PQ_query_param_string (client_scope) + : GNUNET_PQ_query_param_null (), + NULL != client_state + ? GNUNET_PQ_query_param_string (client_state) + : GNUNET_PQ_query_param_null (), + NULL != client_redirect_uri + ? GNUNET_PQ_query_param_string (client_redirect_uri) + : GNUNET_PQ_query_param_null (), + NULL != code_challenge + ? GNUNET_PQ_query_param_string (code_challenge) + : GNUNET_PQ_query_param_null (), + GNUNET_PQ_query_param_uint32 (&code_challenge_method), + GNUNET_PQ_query_param_absolute_time (&now), + GNUNET_PQ_query_param_end + }; + struct GNUNET_PQ_ResultSpec rs[] = { + GNUNET_PQ_result_spec_allow_null ( + TALER_PQ_result_spec_json ("address", + last_address), + NULL), + GNUNET_PQ_result_spec_uint32 ("address_attempts_left", + address_attempts_left), + GNUNET_PQ_result_spec_uint32 ("pin_transmissions_left", + pin_transmissions_left), + GNUNET_PQ_result_spec_uint32 ("auth_attempts_left", + auth_attempts_left), + GNUNET_PQ_result_spec_bool ("solved", + solved), + GNUNET_PQ_result_spec_absolute_time ("last_tx_time", + last_tx_time), + GNUNET_PQ_result_spec_end + }; + + *last_address = NULL; + PREPARE (ctx, + "update_validation", + "UPDATE validations SET" + " client_scope=$3" + " ,client_state=$4" + " ,client_redirect_uri=COALESCE($5::VARCHAR,client_redirect_uri)" + " ,code_challenge=$6" + " ,code_challenge_method=$7" + " WHERE nonce=$1" + " AND client_serial_id=$2" + " AND expiration_time > $8" + " AND ( ($5::VARCHAR=client_redirect_uri)" + " OR ( ($5::VARCHAR IS NULL)" + " AND (client_redirect_uri IS NOT NULL) ) )" + " RETURNING" + " address" + " ,address_attempts_left" + " ,pin_transmissions_left" + " ,GREATEST(0, auth_attempts_left) AS auth_attempts_left" + " ,auth_attempts_left = -1 AS solved" + " ,last_tx_time;"); + return GNUNET_PQ_eval_prepared_singleton_select (ctx->conn, + "update_validation", + params, + rs); +} diff --git a/src/challengerdb/validate_solve_pin.c b/src/challengerdb/validate_solve_pin.c @@ -1,109 +0,0 @@ -/* - This file is part of Challenger - Copyright (C) 2023 Taler Systems SA - - Challenger is free software; you can redistribute it and/or modify it under the - terms of the GNU General Public License as published by the Free Software - Foundation; either version 3, or (at your option) any later version. - - Challenger is distributed in the hope that it will be useful, but WITHOUT ANY - WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR - A PARTICULAR PURPOSE. See the GNU General Public License for more details. - - You should have received a copy of the GNU General Public License along with - Challenger; see the file COPYING. If not, see <http://www.gnu.org/licenses/> - */ -/** - * @file src/challengerdb/validate_solve_pin.c - * @brief Implementation of the validate_solve_pin function for Postgres - * @author Christian Grothoff - */ -#include "platform.h" -#include <taler/taler_error_codes.h> -#include <taler/taler_dbevents.h> -#include <taler/taler_pq_lib.h> -#include "validate_solve_pin.h" -#include "pg_helper.h" - - -enum GNUNET_DB_QueryStatus -CHALLENGERDB_validate_solve_pin ( - struct CHALLENGERDB_PostgresContext *ctx, - const struct CHALLENGER_ValidationNonceP *nonce, - uint32_t new_pin, - bool *solved, - bool *exhausted, - bool *no_challenge, - char **state, - uint32_t *addr_left, - uint32_t *auth_attempts_left, - uint32_t *pin_transmissions_left, - char **client_redirect_uri) -{ - struct GNUNET_TIME_Absolute now - = GNUNET_TIME_absolute_get (); - struct GNUNET_PQ_QueryParam params[] = { - GNUNET_PQ_query_param_auto_from_type (nonce), - GNUNET_PQ_query_param_uint32 (&new_pin), - GNUNET_PQ_query_param_absolute_time (&now), - GNUNET_PQ_query_param_end - }; - bool not_found; - struct GNUNET_PQ_ResultSpec rs[] = { - GNUNET_PQ_result_spec_bool ("not_found", - &not_found), - GNUNET_PQ_result_spec_bool ("solved", - solved), - GNUNET_PQ_result_spec_bool ("exhausted", - exhausted), - GNUNET_PQ_result_spec_bool ("no_challenge", - no_challenge), - GNUNET_PQ_result_spec_uint32 ("address_attempts_left", - addr_left), - GNUNET_PQ_result_spec_uint32 ("auth_attempts_left", - auth_attempts_left), - GNUNET_PQ_result_spec_uint32 ("pin_transmissions_left", - pin_transmissions_left), - GNUNET_PQ_result_spec_allow_null ( - GNUNET_PQ_result_spec_string ("client_redirect_uri", - client_redirect_uri), - NULL), - GNUNET_PQ_result_spec_allow_null ( - GNUNET_PQ_result_spec_string ("state", - state), - NULL), - GNUNET_PQ_result_spec_end - }; - enum GNUNET_DB_QueryStatus qs; - - *client_redirect_uri = NULL; - PREPARE (ctx, - "do_validate_solve_pin", - "SELECT " - " out_not_found AS not_found" - ",out_solved AS solved" - ",out_exhausted AS exhausted" - ",out_no_challenge AS no_challenge" - ",out_state AS state" - ",out_address_attempts_left AS address_attempts_left" - ",out_auth_attempts_left AS auth_attempts_left" - ",out_pin_transmissions_left AS pin_transmissions_left" - ",out_client_redirect_uri AS client_redirect_uri" - " FROM challenger_do_validate_and_solve_pin" - " ($1,$2,$3);"); - qs = GNUNET_PQ_eval_prepared_singleton_select (ctx->conn, - "do_validate_solve_pin", - params, - rs); - if (qs <= 0) - return qs; - if (not_found) - return GNUNET_DB_STATUS_SUCCESS_NO_RESULTS; - /* On the solved path the stored procedure returns the -1 sentinel (kept in - the DB to mark the challenge as solved), which the uint32 result spec reads - as 4294967295. That value is not meaningful to the caller (which only - reads it when !solved); normalize it to 0 to avoid leaking the sentinel. */ - if (*solved) - *auth_attempts_left = 0; - return qs; -} diff --git a/src/challengerdb/validation_get.c b/src/challengerdb/validation_get.c @@ -1,86 +0,0 @@ -/* - This file is part of Challenger - Copyright (C) 2023 Taler Systems SA - - Challenger is free software; you can redistribute it and/or modify it under the - terms of the GNU General Public License as published by the Free Software - Foundation; either version 3, or (at your option) any later version. - - Challenger is distributed in the hope that it will be useful, but WITHOUT ANY - WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR - A PARTICULAR PURPOSE. See the GNU General Public License for more details. - - You should have received a copy of the GNU General Public License along with - Challenger; see the file COPYING. If not, see <http://www.gnu.org/licenses/> - */ -/** - * @file src/challengerdb/validation_get.c - * @brief Implementation of the validation_get function for Postgres - * @author Christian Grothoff - */ -#include "platform.h" -#include <taler/taler_error_codes.h> -#include <taler/taler_dbevents.h> -#include <taler/taler_pq_lib.h> -#include "validation_get.h" -#include "pg_helper.h" - - -enum GNUNET_DB_QueryStatus -CHALLENGERDB_validation_get ( - struct CHALLENGERDB_PostgresContext *ctx, - const struct CHALLENGER_ValidationNonceP *nonce, - char **client_secret, - json_t **address, - char **client_scope, - char **client_state, - char **client_redirect_uri) -{ - struct GNUNET_TIME_Absolute now - = GNUNET_TIME_absolute_get (); - struct GNUNET_PQ_QueryParam params[] = { - GNUNET_PQ_query_param_auto_from_type (nonce), - GNUNET_PQ_query_param_absolute_time (&now), - 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 ( - TALER_PQ_result_spec_json ("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_uri", - client_redirect_uri), - GNUNET_PQ_result_spec_end - }; - - *client_scope = NULL; - *client_state = NULL; - *address = NULL; - PREPARE (ctx, - "validation_get", - "SELECT " - " client_secret" - " ,address" - " ,client_scope" - " ,client_state" - " ,COALESCE(client_redirect_uri,uri) AS redirect_uri" - " FROM validations" - " JOIN clients " - " USING (client_serial_id)" - " WHERE nonce=$1" - " AND expiration_time > $2"); - return GNUNET_PQ_eval_prepared_singleton_select (ctx->conn, - "validation_get", - params, - rs); -} diff --git a/src/challengerdb/validation_get_pkce.c b/src/challengerdb/validation_get_pkce.c @@ -1,99 +0,0 @@ -/* - This file is part of Challenger - Copyright (C) 2023 Taler Systems SA - - Challenger is free software; you can redistribute it and/or modify it under the - terms of the GNU General Public License as published by the Free Software - Foundation; either version 3, or (at your option) any later version. - - Challenger is distributed in the hope that it will be useful, but WITHOUT ANY - WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR - A PARTICULAR PURPOSE. See the GNU General Public License for more details. - - You should have received a copy of the GNU General Public License along with - Challenger; see the file COPYING. If not, see <http://www.gnu.org/licenses/> - */ -/** - * @file src/challengerdb/validation_get_pkce.c - * @brief Implementation of the validation_get_pkce function for Postgres - * @author Bohdan Potuzhnyi - * @author Vlada Svirsh - */ -#include "platform.h" -#include <taler/taler_error_codes.h> -#include <taler/taler_dbevents.h> -#include <taler/taler_pq_lib.h> -#include "validation_get_pkce.h" -#include "pg_helper.h" - -enum GNUNET_DB_QueryStatus -CHALLENGERDB_validation_get_pkce ( - struct CHALLENGERDB_PostgresContext *ctx, - const struct CHALLENGER_ValidationNonceP *nonce, - uint64_t client_id, - char **client_secret, - json_t **address, - char **client_scope, - char **client_state, - char **client_redirect_uri, - char **code_challenge, - uint32_t *code_challenge_method) -{ - struct GNUNET_TIME_Absolute now - = GNUNET_TIME_absolute_get (); - struct GNUNET_PQ_QueryParam params[] = { - GNUNET_PQ_query_param_auto_from_type (nonce), - GNUNET_PQ_query_param_absolute_time (&now), - GNUNET_PQ_query_param_uint64 (&client_id), - 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 ( - TALER_PQ_result_spec_json ("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_uri", - client_redirect_uri), - GNUNET_PQ_result_spec_allow_null ( - GNUNET_PQ_result_spec_string ("code_challenge", - code_challenge), - NULL), - GNUNET_PQ_result_spec_uint32 ("code_challenge_method", - code_challenge_method), - GNUNET_PQ_result_spec_end - }; - - *client_scope = NULL; - *client_state = NULL; - *address = NULL; - PREPARE (ctx, - "validation_get_pkce", - "SELECT " - " client_secret" - " ,address" - " ,client_scope" - " ,client_state" - " ,COALESCE(client_redirect_uri,uri) AS redirect_uri" - " ,code_challenge" - " ,code_challenge_method" - " FROM validations" - " JOIN clients " - " USING (client_serial_id)" - " WHERE nonce=$1" - " AND expiration_time > $2" - " AND client_serial_id=$3"); - return GNUNET_PQ_eval_prepared_singleton_select (ctx->conn, - "validation_get_pkce", - params, - rs); -} diff --git a/src/include/challenger-database/address_get.h b/src/include/challenger-database/address_get.h @@ -1,46 +0,0 @@ -/* - This file is part of Challenger - Copyright (C) 2025 Taler Systems SA - - Challenger is free software; you can redistribute it and/or modify it under the - terms of the GNU General Public License as published by the Free Software - Foundation; either version 3, or (at your option) any later version. - - Challenger is distributed in the hope that it will be useful, but WITHOUT ANY - WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR - A PARTICULAR PURPOSE. See the GNU General Public License for more details. - - You should have received a copy of the GNU General Public License along with - Challenger; see the file COPYING. If not, see <http://www.gnu.org/licenses/> - */ -/** - * @file src/include/challenger-database/address_get.h - * @brief implementation of the address_get function for Postgres - * @author Christian Grothoff - */ -#ifndef CHALLENGER_DATABASE_ADDRESS_GET_H -#define CHALLENGER_DATABASE_ADDRESS_GET_H - -#include <taler/taler_util.h> -#include <taler/taler_json_lib.h> -#include "challenger_util.h" -#include "challenger_database_lib.h" - - -/** - * Return address details. - * - * @param cls - * @param nonce unique nonce to use to identify the validation - * @param[out] address set to client-provided address (or to NULL) - * @return transaction status: - * #GNUNET_DB_STATUS_SUCCESS_ONE_RESULT if the nonce was found - * #GNUNET_DB_STATUS_SUCCESS_NO_RESULTS if we do not know the nonce - * #GNUNET_DB_STATUS_HARD_ERROR on failure - */ -enum GNUNET_DB_QueryStatus -CHALLENGERDB_address_get (struct CHALLENGERDB_PostgresContext *ctx, - const struct CHALLENGER_ValidationNonceP *nonce, - json_t **address); - -#endif diff --git a/src/include/challenger-database/authorize_start.h b/src/include/challenger-database/authorize_start.h @@ -1,79 +0,0 @@ -/* - This file is part of Challenger - Copyright (C) 2023 Taler Systems SA - - Challenger is free software; you can redistribute it and/or modify it under the - terms of the GNU General Public License as published by the Free Software - Foundation; either version 3, or (at your option) any later version. - - Challenger is distributed in the hope that it will be useful, but WITHOUT ANY - WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR - A PARTICULAR PURPOSE. See the GNU General Public License for more details. - - You should have received a copy of the GNU General Public License along with - Challenger; see the file COPYING. If not, see <http://www.gnu.org/licenses/> - */ -/** - * @file src/include/challenger-database/authorize_start.h - * @brief implementation of the authorize_start function for Postgres - * @author Christian Grothoff - * @author Bohdan Potuzhnyi - * @author Vlada Svirsh - */ -#ifndef CHALLENGER_DATABASE_AUTHORIZE_START_H -#define CHALLENGER_DATABASE_AUTHORIZE_START_H - -#include <taler/taler_util.h> -#include <taler/taler_json_lib.h> -#include "challenger_util.h" -#include "challenger_database_lib.h" - - -/** - * Begin the authorization phase of a validation: record the client's OAuth2 - * scope, state, redirect URI and PKCE code challenge on the validation - * identified by @a nonce, and return the current status (last address, - * remaining attempt counters, whether it is already solved). Succeeds only if - * the supplied @a client_redirect_uri matches the one registered for the client. - * - * @param cls - * @param nonce unique nonce to use to identify the validation - * @param client_id client that initiated the validation - * @param client_scope scope of the validation - * @param client_state state of the client - * @param client_redirect_uri where to redirect at the end, NULL to use a unique one registered for the client - * @param code_challenge PKCE code challenge - * @param code_challenge_method PKCE code challenge method enum - * @param[out] last_address set to the last address used - * @param[out] address_attempts_left set to number of address changing attempts left for this address - * @param[out] pin_transmissions_left set to number of times the PIN can still be re-requested - * @param[out] auth_attempts_left set to number of authentication attempts remaining - * @param[out] solved set to true if the challenge is already solved - * @param[out] last_tx_time set to the last time when we (presumably) send a PIN to @a last_address; 0 if never sent - * @return transaction status: - * #GNUNET_DB_STATUS_SUCCESS_ONE_RESULT if the validation exists and the - * OAuth2 scope/state/redirect/PKCE parameters were recorded - * #GNUNET_DB_STATUS_SUCCESS_NO_RESULTS if no validation matches @a nonce and - * @a client_id, or the supplied @a client_redirect_uri does not match the - * redirect URI registered for the client - * #GNUNET_DB_STATUS_HARD_ERROR on failure - */ -enum GNUNET_DB_QueryStatus -CHALLENGERDB_authorize_start ( - struct CHALLENGERDB_PostgresContext *ctx, - const struct CHALLENGER_ValidationNonceP *nonce, - uint64_t client_id, - const char *client_scope, - const char *client_state, - const char *client_redirect_uri, - const char *code_challenge, - uint32_t code_challenge_method, - json_t **last_address, - uint32_t *address_attempts_left, - uint32_t *pin_transmissions_left, - uint32_t *auth_attempts_left, - bool *solved, - struct GNUNET_TIME_Absolute *last_tx_time); - - -#endif diff --git a/src/include/challenger-database/challenge_set_address_and_pin.h b/src/include/challenger-database/challenge_set_address_and_pin.h @@ -1,71 +0,0 @@ -/* - This file is part of Challenger - Copyright (C) 2023 Taler Systems SA - - Challenger is free software; you can redistribute it and/or modify it under the - terms of the GNU General Public License as published by the Free Software - Foundation; either version 3, or (at your option) any later version. - - Challenger is distributed in the hope that it will be useful, but WITHOUT ANY - WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR - A PARTICULAR PURPOSE. See the GNU General Public License for more details. - - You should have received a copy of the GNU General Public License along with - Challenger; see the file COPYING. If not, see <http://www.gnu.org/licenses/> - */ -/** - * @file src/include/challenger-database/challenge_set_address_and_pin.h - * @brief implementation of the challenge_set_address_and_pin function for Postgres - * @author Christian Grothoff - */ -#ifndef CHALLENGER_DATABASE_CHALLENGE_SET_ADDRESS_AND_PIN_H -#define CHALLENGER_DATABASE_CHALLENGE_SET_ADDRESS_AND_PIN_H - -#include <taler/taler_util.h> -#include <taler/taler_json_lib.h> -#include "challenger_util.h" -#include "challenger_database_lib.h" - - -/** - * Set the user-provided address in a validation process. Updates - * the address and decrements the "addresses left" counter. If the - * address did not change, the operation is successful even without - * the counter change. - * - * @param cls - * @param nonce unique nonce to use to identify the validation - * @param address the new address to validate - * @param retransmission_frequency minimum time that must have passed since the - * last transmission before the PIN is (re)transmitted to @a address again - * @param[in,out] tan set to the PIN/TAN last send to @a address, input should be random PIN/TAN to use if address did not change - * @param[out] state set to client's OAuth2 state if available - * @param[out] last_tx_time set to the last time when we (presumably) send a PIN to @a address - * @param[out] pin_transmit set to true if we should transmit the @a last_pin to the @a address - * @param[out] auth_attempts_left set to number of attempts the user has left on this pin - * @param[out] client_redirect_uri redirection URI of the client (for reporting failures) - * @param[out] address_refused set to true if the address was refused (address change attempts exhausted) - * @param[out] solved set to true if the challenge is already solved - * @return transaction status: - * #GNUNET_DB_STATUS_SUCCESS_ONE_RESULT if the validation @a nonce exists - * (inspect @a address_refused / @a solved / @a pin_transmit for the actual - * outcome) - * #GNUNET_DB_STATUS_SUCCESS_NO_RESULTS if the validation @a nonce is unknown - * #GNUNET_DB_STATUS_HARD_ERROR on failure - */ -enum GNUNET_DB_QueryStatus -CHALLENGERDB_challenge_set_address_and_pin ( - struct CHALLENGERDB_PostgresContext *ctx, - const struct CHALLENGER_ValidationNonceP *nonce, - const json_t *address, - struct GNUNET_TIME_Relative retransmission_frequency, - uint32_t *tan, - char **state, - struct GNUNET_TIME_Absolute *last_tx_time, - uint32_t *auth_attempts_left, - bool *pin_transmit, - char **client_redirect_uri, - bool *address_refused, - bool *solved); - -#endif diff --git a/src/include/challenger-database/client_add.h b/src/include/challenger-database/client_add.h @@ -1,49 +0,0 @@ -/* - This file is part of Challenger - Copyright (C) 2023 Taler Systems SA - - Challenger is free software; you can redistribute it and/or modify it under the - terms of the GNU General Public License as published by the Free Software - Foundation; either version 3, or (at your option) any later version. - - Challenger is distributed in the hope that it will be useful, but WITHOUT ANY - WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR - A PARTICULAR PURPOSE. See the GNU General Public License for more details. - - You should have received a copy of the GNU General Public License along with - Challenger; see the file COPYING. If not, see <http://www.gnu.org/licenses/> - */ -/** - * @file src/include/challenger-database/client_add.h - * @brief implementation of the client_add function for Postgres - * @author Christian Grothoff - */ -#ifndef CHALLENGER_DATABASE_CLIENT_ADD_H -#define CHALLENGER_DATABASE_CLIENT_ADD_H - -#include <taler/taler_util.h> -#include <taler/taler_json_lib.h> - -struct CHALLENGERDB_PostgresContext; -/** - * Add client to the list of authorized clients. - * - * @param cls - * @param client_url URL of the client - * @param client_secret authorization secret for the client - * @param[out] client_id set to the client ID on success; left at 0 if the - * client already exists (duplicate URI: ON CONFLICT DO NOTHING) - * @return transaction status: - * #GNUNET_DB_STATUS_SUCCESS_ONE_RESULT if the client was added - * #GNUNET_DB_STATUS_SUCCESS_NO_RESULTS if a client with this URI already - * exists (nothing inserted, @a client_id left 0) - * #GNUNET_DB_STATUS_HARD_ERROR on failure - */ -enum GNUNET_DB_QueryStatus -CHALLENGERDB_client_add (struct CHALLENGERDB_PostgresContext *ctx, - const char *client_url, - const char *client_secret, - uint64_t *client_id); - - -#endif diff --git a/src/include/challenger-database/client_check.h b/src/include/challenger-database/client_check.h @@ -1,67 +0,0 @@ -/* - This file is part of Challenger - Copyright (C) 2023 Taler Systems SA - - Challenger is free software; you can redistribute it and/or modify it under the - terms of the GNU General Public License as published by the Free Software - Foundation; either version 3, or (at your option) any later version. - - Challenger is distributed in the hope that it will be useful, but WITHOUT ANY - WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR - A PARTICULAR PURPOSE. See the GNU General Public License for more details. - - You should have received a copy of the GNU General Public License along with - Challenger; see the file COPYING. If not, see <http://www.gnu.org/licenses/> - */ -/** - * @file src/include/challenger-database/client_check.h - * @brief implementation of the client_check function for Postgres - * @author Christian Grothoff - */ -#ifndef CHALLENGER_DATABASE_CLIENT_CHECK_H -#define CHALLENGER_DATABASE_CLIENT_CHECK_H - -#include <taler/taler_util.h> -#include <taler/taler_json_lib.h> -#include "challenger_util.h" -#include "challenger_database_lib.h" - - -/** - * Check if a client is in the list of authorized clients. If @a - * counter_increment is non-zero, the validation counter of the - * client is incremented by the given value if the client was found. - * - * @param cls - * @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_url set to URL of the client (if any) - * @return transaction status - */ -enum GNUNET_DB_QueryStatus -CHALLENGERDB_client_check ( - struct CHALLENGERDB_PostgresContext *ctx, - uint64_t client_id, - const char *client_secret, - uint32_t counter_increment, - char **client_url); - - -/** - * Check if a client is in the list of authorized clients. - * - * @param cls - * @param client_url client redirect URL (if known) - * @param client_secret secret of the client - * @param[out] client_id set to the ID of the client if found - * @return transaction status - */ -enum GNUNET_DB_QueryStatus -CHALLENGERDB_client_check2 ( - struct CHALLENGERDB_PostgresContext *ctx, - const char *client_url, - const char *client_secret, - uint64_t *client_id); - -#endif diff --git a/src/include/challenger-database/client_delete.h b/src/include/challenger-database/client_delete.h @@ -1,39 +0,0 @@ -/* - This file is part of Challenger - Copyright (C) 2023 Taler Systems SA - - Challenger is free software; you can redistribute it and/or modify it under the - terms of the GNU General Public License as published by the Free Software - Foundation; either version 3, or (at your option) any later version. - - Challenger is distributed in the hope that it will be useful, but WITHOUT ANY - WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR - A PARTICULAR PURPOSE. See the GNU General Public License for more details. - - You should have received a copy of the GNU General Public License along with - Challenger; see the file COPYING. If not, see <http://www.gnu.org/licenses/> - */ -/** - * @file src/include/challenger-database/client_delete.h - * @brief implementation of the client_delete function for Postgres - * @author Christian Grothoff - */ -#ifndef CHALLENGER_DATABASE_CLIENT_DELETE_H -#define CHALLENGER_DATABASE_CLIENT_DELETE_H - -#include <taler/taler_util.h> -#include <taler/taler_json_lib.h> - -struct CHALLENGERDB_PostgresContext; -/** - * Delete client from the list of authorized clients. - * - * @param cls - * @param client_url URL of the client - * @return transaction status - */ -enum GNUNET_DB_QueryStatus -CHALLENGERDB_client_delete (struct CHALLENGERDB_PostgresContext *ctx, - const char *client_url); - -#endif diff --git a/src/include/challenger-database/client_modify.h b/src/include/challenger-database/client_modify.h @@ -1,44 +0,0 @@ -/* - This file is part of Challenger - Copyright (C) 2024 Taler Systems SA - - Challenger is free software; you can redistribute it and/or modify it under the - terms of the GNU General Public License as published by the Free Software - Foundation; either version 3, or (at your option) any later version. - - Challenger is distributed in the hope that it will be useful, but WITHOUT ANY - WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR - A PARTICULAR PURPOSE. See the GNU General Public License for more details. - - You should have received a copy of the GNU General Public License along with - Challenger; see the file COPYING. If not, see <http://www.gnu.org/licenses/> - */ -/** - * @file src/include/challenger-database/client_modify.h - * @brief implementation of the client_modify function for Postgres - * @author Christian Grothoff - */ -#ifndef CHALLENGER_DATABASE_CLIENT_MODIFY_H -#define CHALLENGER_DATABASE_CLIENT_MODIFY_H - -#include <taler/taler_util.h> -#include <taler/taler_json_lib.h> - -struct CHALLENGERDB_PostgresContext; -/** - * Modify client to the list of authorized clients. - * - * @param cls - * @param client_id the client ID on success - * @param client_url URL of the client - * @param client_secret authorization secret for the client, NULL to not modify the secret - * @return transaction status - */ -enum GNUNET_DB_QueryStatus -CHALLENGERDB_client_modify (struct CHALLENGERDB_PostgresContext *ctx, - uint64_t client_id, - const char *client_url, - const char *client_secret); - - -#endif diff --git a/src/include/challenger-database/delete_client.h b/src/include/challenger-database/delete_client.h @@ -0,0 +1,39 @@ +/* + This file is part of Challenger + Copyright (C) 2023 Taler Systems SA + + Challenger is free software; you can redistribute it and/or modify it under the + terms of the GNU General Public License as published by the Free Software + Foundation; either version 3, or (at your option) any later version. + + Challenger is distributed in the hope that it will be useful, but WITHOUT ANY + WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR + A PARTICULAR PURPOSE. See the GNU General Public License for more details. + + You should have received a copy of the GNU General Public License along with + Challenger; see the file COPYING. If not, see <http://www.gnu.org/licenses/> + */ +/** + * @file src/include/challenger-database/delete_client.h + * @brief implementation of the delete_client function for Postgres + * @author Christian Grothoff + */ +#ifndef CHALLENGER_DATABASE_DELETE_CLIENT_H +#define CHALLENGER_DATABASE_DELETE_CLIENT_H + +#include <taler/taler_util.h> +#include <taler/taler_json_lib.h> + +struct CHALLENGERDB_PostgresContext; +/** + * Delete client from the list of authorized clients. + * + * @param cls + * @param client_url URL of the client + * @return transaction status + */ +enum GNUNET_DB_QueryStatus +CHALLENGERDB_delete_client (struct CHALLENGERDB_PostgresContext *ctx, + const char *client_url); + +#endif diff --git a/src/include/challenger-database/do_challenge_address.h b/src/include/challenger-database/do_challenge_address.h @@ -0,0 +1,71 @@ +/* + This file is part of Challenger + Copyright (C) 2023 Taler Systems SA + + Challenger is free software; you can redistribute it and/or modify it under the + terms of the GNU General Public License as published by the Free Software + Foundation; either version 3, or (at your option) any later version. + + Challenger is distributed in the hope that it will be useful, but WITHOUT ANY + WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR + A PARTICULAR PURPOSE. See the GNU General Public License for more details. + + You should have received a copy of the GNU General Public License along with + Challenger; see the file COPYING. If not, see <http://www.gnu.org/licenses/> + */ +/** + * @file src/include/challenger-database/do_challenge_address.h + * @brief implementation of the do_challenge_address function for Postgres + * @author Christian Grothoff + */ +#ifndef CHALLENGER_DATABASE_DO_CHALLENGE_ADDRESS_H +#define CHALLENGER_DATABASE_DO_CHALLENGE_ADDRESS_H + +#include <taler/taler_util.h> +#include <taler/taler_json_lib.h> +#include "challenger_util.h" +#include "challenger_database_lib.h" + + +/** + * Set the user-provided address in a validation process. Updates + * the address and decrements the "addresses left" counter. If the + * address did not change, the operation is successful even without + * the counter change. + * + * @param cls + * @param nonce unique nonce to use to identify the validation + * @param address the new address to validate + * @param retransmission_frequency minimum time that must have passed since the + * last transmission before the PIN is (re)transmitted to @a address again + * @param[in,out] tan set to the PIN/TAN last send to @a address, input should be random PIN/TAN to use if address did not change + * @param[out] state set to client's OAuth2 state if available + * @param[out] last_tx_time set to the last time when we (presumably) send a PIN to @a address + * @param[out] pin_transmit set to true if we should transmit the @a last_pin to the @a address + * @param[out] auth_attempts_left set to number of attempts the user has left on this pin + * @param[out] client_redirect_uri redirection URI of the client (for reporting failures) + * @param[out] address_refused set to true if the address was refused (address change attempts exhausted) + * @param[out] solved set to true if the challenge is already solved + * @return transaction status: + * #GNUNET_DB_STATUS_SUCCESS_ONE_RESULT if the validation @a nonce exists + * (inspect @a address_refused / @a solved / @a pin_transmit for the actual + * outcome) + * #GNUNET_DB_STATUS_SUCCESS_NO_RESULTS if the validation @a nonce is unknown + * #GNUNET_DB_STATUS_HARD_ERROR on failure + */ +enum GNUNET_DB_QueryStatus +CHALLENGERDB_do_challenge_address ( + struct CHALLENGERDB_PostgresContext *ctx, + const struct CHALLENGER_ValidationNonceP *nonce, + const json_t *address, + struct GNUNET_TIME_Relative retransmission_frequency, + uint32_t *tan, + char **state, + struct GNUNET_TIME_Absolute *last_tx_time, + uint32_t *auth_attempts_left, + bool *pin_transmit, + char **client_redirect_uri, + bool *address_refused, + bool *solved); + +#endif diff --git a/src/include/challenger-database/do_insert_token.h b/src/include/challenger-database/do_insert_token.h @@ -0,0 +1,49 @@ +/* + This file is part of Challenger + Copyright (C) 2023 Taler Systems SA + + Challenger is free software; you can redistribute it and/or modify it under the + terms of the GNU General Public License as published by the Free Software + Foundation; either version 3, or (at your option) any later version. + + Challenger is distributed in the hope that it will be useful, but WITHOUT ANY + WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR + A PARTICULAR PURPOSE. See the GNU General Public License for more details. + + You should have received a copy of the GNU General Public License along with + Challenger; see the file COPYING. If not, see <http://www.gnu.org/licenses/> + */ +/** + * @file src/include/challenger-database/do_insert_token.h + * @brief implementation of the do_insert_token function for Postgres + * @author Christian Grothoff + */ +#ifndef CHALLENGER_DATABASE_DO_INSERT_TOKEN_H +#define CHALLENGER_DATABASE_DO_INSERT_TOKEN_H + +#include <taler/taler_util.h> +#include <taler/taler_json_lib.h> +#include "challenger_util.h" +#include "challenger_database_lib.h" + + +/** + * Add access @a grant to address under @a nonce. + * + * @param cls closure + * @param nonce validation process to grant access to + * @param grant grant token that grants access + * @param grant_expiration for how long should the grant be valid + * @param address_expiration for how long after validation do we consider addresses to be valid + * @return transaction status + */ +enum GNUNET_DB_QueryStatus +CHALLENGERDB_do_insert_token ( + struct CHALLENGERDB_PostgresContext *ctx, + const struct CHALLENGER_ValidationNonceP *nonce, + const struct CHALLENGER_AccessTokenP *grant, + struct GNUNET_TIME_Relative grant_expiration, + struct GNUNET_TIME_Relative address_expiration); + + +#endif diff --git a/src/include/challenger-database/do_insert_validation.h b/src/include/challenger-database/do_insert_validation.h @@ -0,0 +1,59 @@ +/* + This file is part of Challenger + Copyright (C) 2023 Taler Systems SA + + Challenger is free software; you can redistribute it and/or modify it under the + terms of the GNU General Public License as published by the Free Software + Foundation; either version 3, or (at your option) any later version. + + Challenger is distributed in the hope that it will be useful, but WITHOUT ANY + WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR + A PARTICULAR PURPOSE. See the GNU General Public License for more details. + + You should have received a copy of the GNU General Public License along with + Challenger; see the file COPYING. If not, see <http://www.gnu.org/licenses/> + */ +/** + * @file src/include/challenger-database/do_insert_validation.h + * @brief implementation of the do_insert_validation function for Postgres + * @author Christian Grothoff + */ +#ifndef CHALLENGER_DATABASE_DO_INSERT_VALIDATION_H +#define CHALLENGER_DATABASE_DO_INSERT_VALIDATION_H + +#include <taler/taler_util.h> +#include <taler/taler_json_lib.h> +#include "challenger_util.h" +#include "challenger_database_lib.h" + + +/** + * Start validation process by setting up a validation entry. Allows + * the respective user who learns the @a nonce to later begin the + * process. + * + * Authenticates the client against @a client_secret and charges it for + * the validation (by incrementing @e validation_counter) in the same + * statement that inserts the row, so the counter moves if and only if + * the validation was actually created. + * + * @param ctx database context + * @param client_id ID of the client + * @param client_secret secret of the client + * @param nonce unique nonce to use to identify the validation + * @param expiration_time when will the validation expire + * @param initial_address address the user should validate, + * NULL if the user should enter it themselves + * @return transaction status, #GNUNET_DB_STATUS_SUCCESS_NO_RESULTS if + * there is no such client or @a client_secret does not match + */ +enum GNUNET_DB_QueryStatus +CHALLENGERDB_do_insert_validation ( + struct CHALLENGERDB_PostgresContext *ctx, + uint64_t client_id, + const char *client_secret, + const struct CHALLENGER_ValidationNonceP *nonce, + struct GNUNET_TIME_Absolute expiration_time, + const json_t *initial_address); + +#endif diff --git a/src/include/challenger-database/do_solve_challenge.h b/src/include/challenger-database/do_solve_challenge.h @@ -0,0 +1,67 @@ +/* + This file is part of Challenger + Copyright (C) 2023 Taler Systems SA + + Challenger is free software; you can redistribute it and/or modify it under the + terms of the GNU General Public License as published by the Free Software + Foundation; either version 3, or (at your option) any later version. + + Challenger is distributed in the hope that it will be useful, but WITHOUT ANY + WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR + A PARTICULAR PURPOSE. See the GNU General Public License for more details. + + You should have received a copy of the GNU General Public License along with + Challenger; see the file COPYING. If not, see <http://www.gnu.org/licenses/> + */ +/** + * @file src/include/challenger-database/do_solve_challenge.h + * @brief implementation of the do_solve_challenge function for Postgres + * @author Christian Grothoff + */ +#ifndef CHALLENGER_DATABASE_DO_SOLVE_CHALLENGE_H +#define CHALLENGER_DATABASE_DO_SOLVE_CHALLENGE_H + +#include <taler/taler_util.h> +#include <taler/taler_json_lib.h> +#include "challenger_util.h" +#include "challenger_database_lib.h" + + +/** + * Check PIN entered to validate an address. + * + * @param cls + * @param nonce unique nonce to use to identify the validation + * @param new_pin the PIN the user entered + * @param[out] solved set to true if the PIN was correct + * @param[out] exhausted set to true if the number of attempts to enter the correct PIN was exhausted before this call and @a new_pin was not evaluated + * @param[out] no_challenge set to true if we never even issued a challenge + * @param[out] state set to client's OAuth2 state if available + * @param[out] addr_left set to number of address changes remaining + * @param[out] auth_attempts_left set to number of authentication attempts + * remaining; only meaningful when @a solved is false (on the solved + * path the stored procedure uses a -1 sentinel, which is normalized + * to 0 here) + * @param[out] pin_transmissions_left set to number of times the PIN can still be re-requested + * @param[out] client_redirect_uri set to OAuth2 client redirect URI + * @return transaction status: + * #GNUNET_DB_STATUS_SUCCESS_ONE_RESULT if the nonce was found + * #GNUNET_DB_STATUS_SUCCESS_NO_RESULTS if we do not know the nonce + * #GNUNET_DB_STATUS_HARD_ERROR on failure + */ +enum GNUNET_DB_QueryStatus +CHALLENGERDB_do_solve_challenge ( + struct CHALLENGERDB_PostgresContext *ctx, + const struct CHALLENGER_ValidationNonceP *nonce, + uint32_t new_pin, + bool *solved, + bool *exhausted, + bool *no_challenge, + char **state, + uint32_t *addr_left, + uint32_t *auth_attempts_left, + uint32_t *pin_transmissions_left, + char **client_redirect_uri); + + +#endif diff --git a/src/include/challenger-database/get_client.h b/src/include/challenger-database/get_client.h @@ -0,0 +1,51 @@ +/* + This file is part of Challenger + Copyright (C) 2023 Taler Systems SA + + Challenger is free software; you can redistribute it and/or modify it under the + terms of the GNU General Public License as published by the Free Software + Foundation; either version 3, or (at your option) any later version. + + Challenger is distributed in the hope that it will be useful, but WITHOUT ANY + WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR + A PARTICULAR PURPOSE. See the GNU General Public License for more details. + + You should have received a copy of the GNU General Public License along with + Challenger; see the file COPYING. If not, see <http://www.gnu.org/licenses/> + */ +/** + * @file src/include/challenger-database/get_client.h + * @brief implementation of the get_client function for Postgres + * @author Christian Grothoff + */ +#ifndef CHALLENGER_DATABASE_GET_CLIENT_H +#define CHALLENGER_DATABASE_GET_CLIENT_H + +#include <taler/taler_util.h> +#include <taler/taler_json_lib.h> +#include "challenger_util.h" +#include "challenger_database_lib.h" + + +/** + * Look up the client with row @a client_id, authenticating it against + * @a client_secret, and return its redirect URI. Pure read; callers + * that must also charge the client for the lookup use + * #CHALLENGERDB_do_insert_validation(), which authenticates and bumps + * the validation counter in the same statement. + * + * @param ctx database context + * @param client_id unique row of the client + * @param client_secret secret of the client + * @param[out] client_url set to URL of the client (if any) + * @return transaction status, #GNUNET_DB_STATUS_SUCCESS_NO_RESULTS if + * there is no such client or @a client_secret does not match + */ +enum GNUNET_DB_QueryStatus +CHALLENGERDB_get_client ( + struct CHALLENGERDB_PostgresContext *ctx, + uint64_t client_id, + const char *client_secret, + char **client_url); + +#endif diff --git a/src/include/challenger-database/get_client_by_uri.h b/src/include/challenger-database/get_client_by_uri.h @@ -0,0 +1,47 @@ +/* + This file is part of Challenger + Copyright (C) 2023 Taler Systems SA + + Challenger is free software; you can redistribute it and/or modify it under the + terms of the GNU General Public License as published by the Free Software + Foundation; either version 3, or (at your option) any later version. + + Challenger is distributed in the hope that it will be useful, but WITHOUT ANY + WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR + A PARTICULAR PURPOSE. See the GNU General Public License for more details. + + You should have received a copy of the GNU General Public License along with + Challenger; see the file COPYING. If not, see <http://www.gnu.org/licenses/> + */ +/** + * @file src/include/challenger-database/get_client_by_uri.h + * @brief implementation of the get_client_by_uri function for Postgres + * @author Christian Grothoff + */ +#ifndef CHALLENGER_DATABASE_GET_CLIENT_BY_URI_H +#define CHALLENGER_DATABASE_GET_CLIENT_BY_URI_H + +#include <taler/taler_util.h> +#include <taler/taler_json_lib.h> +#include "challenger_util.h" +#include "challenger_database_lib.h" + + +/** + * Look up the client authorized under the given redirect URI + * and secret. Read-only. + * + * @param cls + * @param client_url client redirect URL (if known) + * @param client_secret secret of the client + * @param[out] client_id set to the ID of the client if found + * @return transaction status + */ +enum GNUNET_DB_QueryStatus +CHALLENGERDB_get_client_by_uri ( + struct CHALLENGERDB_PostgresContext *ctx, + const char *client_url, + const char *client_secret, + uint64_t *client_id); + +#endif diff --git a/src/include/challenger-database/get_token.h b/src/include/challenger-database/get_token.h @@ -0,0 +1,48 @@ +/* + This file is part of Challenger + Copyright (C) 2023 Taler Systems SA + + Challenger is free software; you can redistribute it and/or modify it under the + terms of the GNU General Public License as published by the Free Software + Foundation; either version 3, or (at your option) any later version. + + Challenger is distributed in the hope that it will be useful, but WITHOUT ANY + WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR + A PARTICULAR PURPOSE. See the GNU General Public License for more details. + + You should have received a copy of the GNU General Public License along with + Challenger; see the file COPYING. If not, see <http://www.gnu.org/licenses/> + */ +/** + * @file src/include/challenger-database/get_token.h + * @brief implementation of the get_token function for Postgres + * @author Christian Grothoff + */ +#ifndef CHALLENGER_DATABASE_GET_TOKEN_H +#define CHALLENGER_DATABASE_GET_TOKEN_H + +#include <taler/taler_util.h> +#include <jansson.h> +#include "challenger_util.h" +#include "challenger_database_lib.h" + + +/** + * Return @a address which @a grant gives access to. + * + * @param cls closure + * @param grant grant token that grants access + * @param[out] rowid account identifier within challenger + * @param[out] address set to the address under @a grant + * @param[out] address_expiration set to how long we consider @a address to be valid + * @return transaction status + */ +enum GNUNET_DB_QueryStatus +CHALLENGERDB_get_token (struct CHALLENGERDB_PostgresContext *ctx, + const struct CHALLENGER_AccessTokenP *grant, + uint64_t *rowid, + json_t **address, + struct GNUNET_TIME_Timestamp *address_expiration); + + +#endif diff --git a/src/include/challenger-database/get_validation.h b/src/include/challenger-database/get_validation.h @@ -0,0 +1,57 @@ +/* + This file is part of Challenger + Copyright (C) 2023 Taler Systems SA + + Challenger is free software; you can redistribute it and/or modify it under the + terms of the GNU General Public License as published by the Free Software + Foundation; either version 3, or (at your option) any later version. + + Challenger is distributed in the hope that it will be useful, but WITHOUT ANY + WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR + A PARTICULAR PURPOSE. See the GNU General Public License for more details. + + You should have received a copy of the GNU General Public License along with + Challenger; see the file COPYING. If not, see <http://www.gnu.org/licenses/> + */ +/** + * @file src/include/challenger-database/get_validation.h + * @brief implementation of the get_validation function for Postgres + * @author Christian Grothoff + */ +#ifndef CHALLENGER_DATABASE_GET_VALIDATION_H +#define CHALLENGER_DATABASE_GET_VALIDATION_H + +#include <taler/taler_util.h> +#include <taler/taler_json_lib.h> +#include "challenger_util.h" +#include "challenger_database_lib.h" + + +/** + * Return validation details. Used by ``/solve``, ``/auth`` and + * ``/info`` endpoints to authorize and return validated user + * address to the client. + * + * @param cls + * @param nonce unique nonce to use to identify the validation + * @param[out] client_secret set to secret of client (for client that setup the challenge) + * @param[out] address set to client-provided address + * @param[out] client_scope set to OAuth2 scope + * @param[out] client_state set to client state + * @param[out] client_redirect_uri set to client redirect URL + * @return transaction status: + * #GNUNET_DB_STATUS_SUCCESS_ONE_RESULT if the nonce was found + * #GNUNET_DB_STATUS_SUCCESS_NO_RESULTS if we do not know the nonce + * #GNUNET_DB_STATUS_HARD_ERROR on failure + */ +enum GNUNET_DB_QueryStatus +CHALLENGERDB_get_validation ( + struct CHALLENGERDB_PostgresContext *ctx, + const struct CHALLENGER_ValidationNonceP *nonce, + char **client_secret, + json_t **address, + char **client_scope, + char **client_state, + char **client_redirect_uri); + +#endif diff --git a/src/include/challenger-database/get_validation_address.h b/src/include/challenger-database/get_validation_address.h @@ -0,0 +1,47 @@ +/* + This file is part of Challenger + Copyright (C) 2025 Taler Systems SA + + Challenger is free software; you can redistribute it and/or modify it under the + terms of the GNU General Public License as published by the Free Software + Foundation; either version 3, or (at your option) any later version. + + Challenger is distributed in the hope that it will be useful, but WITHOUT ANY + WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR + A PARTICULAR PURPOSE. See the GNU General Public License for more details. + + You should have received a copy of the GNU General Public License along with + Challenger; see the file COPYING. If not, see <http://www.gnu.org/licenses/> + */ +/** + * @file src/include/challenger-database/get_validation_address.h + * @brief implementation of the get_validation_address function for Postgres + * @author Christian Grothoff + */ +#ifndef CHALLENGER_DATABASE_GET_VALIDATION_ADDRESS_H +#define CHALLENGER_DATABASE_GET_VALIDATION_ADDRESS_H + +#include <taler/taler_util.h> +#include <taler/taler_json_lib.h> +#include "challenger_util.h" +#include "challenger_database_lib.h" + + +/** + * Return address details. + * + * @param cls + * @param nonce unique nonce to use to identify the validation + * @param[out] address set to client-provided address (or to NULL) + * @return transaction status: + * #GNUNET_DB_STATUS_SUCCESS_ONE_RESULT if the nonce was found + * #GNUNET_DB_STATUS_SUCCESS_NO_RESULTS if we do not know the nonce + * #GNUNET_DB_STATUS_HARD_ERROR on failure + */ +enum GNUNET_DB_QueryStatus +CHALLENGERDB_get_validation_address (struct CHALLENGERDB_PostgresContext *ctx, + const struct CHALLENGER_ValidationNonceP * + nonce, + json_t **address); + +#endif diff --git a/src/include/challenger-database/get_validation_pkce.h b/src/include/challenger-database/get_validation_pkce.h @@ -0,0 +1,64 @@ +/* + This file is part of Challenger + Copyright (C) 2023 Taler Systems SA + + Challenger is free software; you can redistribute it and/or modify it under the + terms of the GNU General Public License as published by the Free Software + Foundation; either version 3, or (at your option) any later version. + + Challenger is distributed in the hope that it will be useful, but WITHOUT ANY + WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR + A PARTICULAR PURPOSE. See the GNU General Public License for more details. + + You should have received a copy of the GNU General Public License along with + Challenger; see the file COPYING. If not, see <http://www.gnu.org/licenses/> + */ +/** + * @file src/include/challenger-database/get_validation_pkce.h + * @brief implementation of the get_validation_pkce function for Postgres + * @author Bohdan Potuzhnyi + * @author Vlada Svirsh + */ +#ifndef CHALLENGER_DATABASE_GET_VALIDATION_PKCE_H +#define CHALLENGER_DATABASE_GET_VALIDATION_PKCE_H + +#include <taler/taler_util.h> +#include <taler/taler_json_lib.h> +#include "challenger_util.h" +#include "challenger_database_lib.h" + + +/** + * Return validation details. Used by ``/solve``, ``/auth`` and + * ``/info`` endpoints to authorize and return validated user + * address to the client. + * + * @param cls + * @param nonce unique nonce to use to identify the validation + * @param client_id serial id of the authenticated client redeeming the code + * @param[out] client_secret set to secret of client (for client that setup the challenge) + * @param[out] address set to client-provided address + * @param[out] client_scope set to OAuth2 scope + * @param[out] client_state set to client state + * @param[out] client_redirect_uri set to client redirect URL + * @param[out] code_challenge set to PKCE code challenge + * @param[out] code_challenge_method set to PKCE code challenge method enum + * @return transaction status: + * #GNUNET_DB_STATUS_SUCCESS_ONE_RESULT if the nonce was found + * #GNUNET_DB_STATUS_SUCCESS_NO_RESULTS if we do not know the nonce + * #GNUNET_DB_STATUS_HARD_ERROR on failure + */ +enum GNUNET_DB_QueryStatus +CHALLENGERDB_get_validation_pkce ( + struct CHALLENGERDB_PostgresContext *ctx, + const struct CHALLENGER_ValidationNonceP *nonce, + uint64_t client_id, + char **client_secret, + json_t **address, + char **client_scope, + char **client_state, + char **client_redirect_uri, + char **code_challenge, + uint32_t *code_challenge_method); + +#endif diff --git a/src/include/challenger-database/info_get_token.h b/src/include/challenger-database/info_get_token.h @@ -1,48 +0,0 @@ -/* - This file is part of Challenger - Copyright (C) 2023 Taler Systems SA - - Challenger is free software; you can redistribute it and/or modify it under the - terms of the GNU General Public License as published by the Free Software - Foundation; either version 3, or (at your option) any later version. - - Challenger is distributed in the hope that it will be useful, but WITHOUT ANY - WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR - A PARTICULAR PURPOSE. See the GNU General Public License for more details. - - You should have received a copy of the GNU General Public License along with - Challenger; see the file COPYING. If not, see <http://www.gnu.org/licenses/> - */ -/** - * @file src/include/challenger-database/info_get_token.h - * @brief implementation of the info_get_token function for Postgres - * @author Christian Grothoff - */ -#ifndef CHALLENGER_DATABASE_INFO_GET_TOKEN_H -#define CHALLENGER_DATABASE_INFO_GET_TOKEN_H - -#include <taler/taler_util.h> -#include <jansson.h> -#include "challenger_util.h" -#include "challenger_database_lib.h" - - -/** - * Return @a address which @a grant gives access to. - * - * @param cls closure - * @param grant grant token that grants access - * @param[out] rowid account identifier within challenger - * @param[out] address set to the address under @a grant - * @param[out] address_expiration set to how long we consider @a address to be valid - * @return transaction status - */ -enum GNUNET_DB_QueryStatus -CHALLENGERDB_info_get_token (struct CHALLENGERDB_PostgresContext *ctx, - const struct CHALLENGER_AccessTokenP *grant, - uint64_t *rowid, - json_t **address, - struct GNUNET_TIME_Timestamp *address_expiration); - - -#endif diff --git a/src/include/challenger-database/insert_client.h b/src/include/challenger-database/insert_client.h @@ -0,0 +1,49 @@ +/* + This file is part of Challenger + Copyright (C) 2023 Taler Systems SA + + Challenger is free software; you can redistribute it and/or modify it under the + terms of the GNU General Public License as published by the Free Software + Foundation; either version 3, or (at your option) any later version. + + Challenger is distributed in the hope that it will be useful, but WITHOUT ANY + WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR + A PARTICULAR PURPOSE. See the GNU General Public License for more details. + + You should have received a copy of the GNU General Public License along with + Challenger; see the file COPYING. If not, see <http://www.gnu.org/licenses/> + */ +/** + * @file src/include/challenger-database/insert_client.h + * @brief implementation of the insert_client function for Postgres + * @author Christian Grothoff + */ +#ifndef CHALLENGER_DATABASE_INSERT_CLIENT_H +#define CHALLENGER_DATABASE_INSERT_CLIENT_H + +#include <taler/taler_util.h> +#include <taler/taler_json_lib.h> + +struct CHALLENGERDB_PostgresContext; +/** + * Add client to the list of authorized clients. + * + * @param cls + * @param client_url URL of the client + * @param client_secret authorization secret for the client + * @param[out] client_id set to the client ID on success; left at 0 if the + * client already exists (duplicate URI: ON CONFLICT DO NOTHING) + * @return transaction status: + * #GNUNET_DB_STATUS_SUCCESS_ONE_RESULT if the client was added + * #GNUNET_DB_STATUS_SUCCESS_NO_RESULTS if a client with this URI already + * exists (nothing inserted, @a client_id left 0) + * #GNUNET_DB_STATUS_HARD_ERROR on failure + */ +enum GNUNET_DB_QueryStatus +CHALLENGERDB_insert_client (struct CHALLENGERDB_PostgresContext *ctx, + const char *client_url, + const char *client_secret, + uint64_t *client_id); + + +#endif diff --git a/src/include/challenger-database/setup_nonce.h b/src/include/challenger-database/setup_nonce.h @@ -1,51 +0,0 @@ -/* - This file is part of Challenger - Copyright (C) 2023 Taler Systems SA - - Challenger is free software; you can redistribute it and/or modify it under the - terms of the GNU General Public License as published by the Free Software - Foundation; either version 3, or (at your option) any later version. - - Challenger is distributed in the hope that it will be useful, but WITHOUT ANY - WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR - A PARTICULAR PURPOSE. See the GNU General Public License for more details. - - You should have received a copy of the GNU General Public License along with - Challenger; see the file COPYING. If not, see <http://www.gnu.org/licenses/> - */ -/** - * @file src/include/challenger-database/setup_nonce.h - * @brief implementation of the validation_setup function for Postgres - * @author Christian Grothoff - */ -#ifndef CHALLENGER_DATABASE_SETUP_NONCE_H -#define CHALLENGER_DATABASE_SETUP_NONCE_H - -#include <taler/taler_util.h> -#include <taler/taler_json_lib.h> -#include "challenger_util.h" -#include "challenger_database_lib.h" - - -/** - * Start validation process by setting up a validation entry. Allows - * the respective user who learns the @a nonce to later begin the - * process. - * - * @param cls closure - * @param client_id ID of the client - * @param nonce unique nonce to use to identify the validation - * @param expiration_time when will the validation expire - * @param initial_address address the user should validate, - * NULL if the user should enter it themselves - * @return transaction status - */ -enum GNUNET_DB_QueryStatus -CHALLENGERDB_setup_nonce ( - struct CHALLENGERDB_PostgresContext *ctx, - uint64_t client_id, - const struct CHALLENGER_ValidationNonceP *nonce, - struct GNUNET_TIME_Absolute expiration_time, - const json_t *initial_address); - -#endif diff --git a/src/include/challenger-database/token_add_token.h b/src/include/challenger-database/token_add_token.h @@ -1,49 +0,0 @@ -/* - This file is part of Challenger - Copyright (C) 2023 Taler Systems SA - - Challenger is free software; you can redistribute it and/or modify it under the - terms of the GNU General Public License as published by the Free Software - Foundation; either version 3, or (at your option) any later version. - - Challenger is distributed in the hope that it will be useful, but WITHOUT ANY - WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR - A PARTICULAR PURPOSE. See the GNU General Public License for more details. - - You should have received a copy of the GNU General Public License along with - Challenger; see the file COPYING. If not, see <http://www.gnu.org/licenses/> - */ -/** - * @file src/include/challenger-database/token_add_token.h - * @brief implementation of the token_add_token function for Postgres - * @author Christian Grothoff - */ -#ifndef CHALLENGER_DATABASE_TOKEN_ADD_TOKEN_H -#define CHALLENGER_DATABASE_TOKEN_ADD_TOKEN_H - -#include <taler/taler_util.h> -#include <taler/taler_json_lib.h> -#include "challenger_util.h" -#include "challenger_database_lib.h" - - -/** - * Add access @a grant to address under @a nonce. - * - * @param cls closure - * @param nonce validation process to grant access to - * @param grant grant token that grants access - * @param grant_expiration for how long should the grant be valid - * @param address_expiration for how long after validation do we consider addresses to be valid - * @return transaction status - */ -enum GNUNET_DB_QueryStatus -CHALLENGERDB_token_add_token ( - struct CHALLENGERDB_PostgresContext *ctx, - const struct CHALLENGER_ValidationNonceP *nonce, - const struct CHALLENGER_AccessTokenP *grant, - struct GNUNET_TIME_Relative grant_expiration, - struct GNUNET_TIME_Relative address_expiration); - - -#endif diff --git a/src/include/challenger-database/update_client.h b/src/include/challenger-database/update_client.h @@ -0,0 +1,44 @@ +/* + This file is part of Challenger + Copyright (C) 2024 Taler Systems SA + + Challenger is free software; you can redistribute it and/or modify it under the + terms of the GNU General Public License as published by the Free Software + Foundation; either version 3, or (at your option) any later version. + + Challenger is distributed in the hope that it will be useful, but WITHOUT ANY + WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR + A PARTICULAR PURPOSE. See the GNU General Public License for more details. + + You should have received a copy of the GNU General Public License along with + Challenger; see the file COPYING. If not, see <http://www.gnu.org/licenses/> + */ +/** + * @file src/include/challenger-database/update_client.h + * @brief implementation of the update_client function for Postgres + * @author Christian Grothoff + */ +#ifndef CHALLENGER_DATABASE_UPDATE_CLIENT_H +#define CHALLENGER_DATABASE_UPDATE_CLIENT_H + +#include <taler/taler_util.h> +#include <taler/taler_json_lib.h> + +struct CHALLENGERDB_PostgresContext; +/** + * Modify client to the list of authorized clients. + * + * @param cls + * @param client_id the client ID on success + * @param client_url URL of the client + * @param client_secret authorization secret for the client, NULL to not modify the secret + * @return transaction status + */ +enum GNUNET_DB_QueryStatus +CHALLENGERDB_update_client (struct CHALLENGERDB_PostgresContext *ctx, + uint64_t client_id, + const char *client_url, + const char *client_secret); + + +#endif diff --git a/src/include/challenger-database/update_validation.h b/src/include/challenger-database/update_validation.h @@ -0,0 +1,79 @@ +/* + This file is part of Challenger + Copyright (C) 2023 Taler Systems SA + + Challenger is free software; you can redistribute it and/or modify it under the + terms of the GNU General Public License as published by the Free Software + Foundation; either version 3, or (at your option) any later version. + + Challenger is distributed in the hope that it will be useful, but WITHOUT ANY + WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR + A PARTICULAR PURPOSE. See the GNU General Public License for more details. + + You should have received a copy of the GNU General Public License along with + Challenger; see the file COPYING. If not, see <http://www.gnu.org/licenses/> + */ +/** + * @file src/include/challenger-database/update_validation.h + * @brief implementation of the update_validation function for Postgres + * @author Christian Grothoff + * @author Bohdan Potuzhnyi + * @author Vlada Svirsh + */ +#ifndef CHALLENGER_DATABASE_UPDATE_VALIDATION_H +#define CHALLENGER_DATABASE_UPDATE_VALIDATION_H + +#include <taler/taler_util.h> +#include <taler/taler_json_lib.h> +#include "challenger_util.h" +#include "challenger_database_lib.h" + + +/** + * Begin the authorization phase of a validation: record the client's OAuth2 + * scope, state, redirect URI and PKCE code challenge on the validation + * identified by @a nonce, and return the current status (last address, + * remaining attempt counters, whether it is already solved). Succeeds only if + * the supplied @a client_redirect_uri matches the one registered for the client. + * + * @param cls + * @param nonce unique nonce to use to identify the validation + * @param client_id client that initiated the validation + * @param client_scope scope of the validation + * @param client_state state of the client + * @param client_redirect_uri where to redirect at the end, NULL to use a unique one registered for the client + * @param code_challenge PKCE code challenge + * @param code_challenge_method PKCE code challenge method enum + * @param[out] last_address set to the last address used + * @param[out] address_attempts_left set to number of address changing attempts left for this address + * @param[out] pin_transmissions_left set to number of times the PIN can still be re-requested + * @param[out] auth_attempts_left set to number of authentication attempts remaining + * @param[out] solved set to true if the challenge is already solved + * @param[out] last_tx_time set to the last time when we (presumably) send a PIN to @a last_address; 0 if never sent + * @return transaction status: + * #GNUNET_DB_STATUS_SUCCESS_ONE_RESULT if the validation exists and the + * OAuth2 scope/state/redirect/PKCE parameters were recorded + * #GNUNET_DB_STATUS_SUCCESS_NO_RESULTS if no validation matches @a nonce and + * @a client_id, or the supplied @a client_redirect_uri does not match the + * redirect URI registered for the client + * #GNUNET_DB_STATUS_HARD_ERROR on failure + */ +enum GNUNET_DB_QueryStatus +CHALLENGERDB_update_validation ( + struct CHALLENGERDB_PostgresContext *ctx, + const struct CHALLENGER_ValidationNonceP *nonce, + uint64_t client_id, + const char *client_scope, + const char *client_state, + const char *client_redirect_uri, + const char *code_challenge, + uint32_t code_challenge_method, + json_t **last_address, + uint32_t *address_attempts_left, + uint32_t *pin_transmissions_left, + uint32_t *auth_attempts_left, + bool *solved, + struct GNUNET_TIME_Absolute *last_tx_time); + + +#endif diff --git a/src/include/challenger-database/validate_solve_pin.h b/src/include/challenger-database/validate_solve_pin.h @@ -1,67 +0,0 @@ -/* - This file is part of Challenger - Copyright (C) 2023 Taler Systems SA - - Challenger is free software; you can redistribute it and/or modify it under the - terms of the GNU General Public License as published by the Free Software - Foundation; either version 3, or (at your option) any later version. - - Challenger is distributed in the hope that it will be useful, but WITHOUT ANY - WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR - A PARTICULAR PURPOSE. See the GNU General Public License for more details. - - You should have received a copy of the GNU General Public License along with - Challenger; see the file COPYING. If not, see <http://www.gnu.org/licenses/> - */ -/** - * @file src/include/challenger-database/validate_solve_pin.h - * @brief implementation of the validate_solve_pin function for Postgres - * @author Christian Grothoff - */ -#ifndef CHALLENGER_DATABASE_VALIDATE_SOLVE_PIN_H -#define CHALLENGER_DATABASE_VALIDATE_SOLVE_PIN_H - -#include <taler/taler_util.h> -#include <taler/taler_json_lib.h> -#include "challenger_util.h" -#include "challenger_database_lib.h" - - -/** - * Check PIN entered to validate an address. - * - * @param cls - * @param nonce unique nonce to use to identify the validation - * @param new_pin the PIN the user entered - * @param[out] solved set to true if the PIN was correct - * @param[out] exhausted set to true if the number of attempts to enter the correct PIN was exhausted before this call and @a new_pin was not evaluated - * @param[out] no_challenge set to true if we never even issued a challenge - * @param[out] state set to client's OAuth2 state if available - * @param[out] addr_left set to number of address changes remaining - * @param[out] auth_attempts_left set to number of authentication attempts - * remaining; only meaningful when @a solved is false (on the solved - * path the stored procedure uses a -1 sentinel, which is normalized - * to 0 here) - * @param[out] pin_transmissions_left set to number of times the PIN can still be re-requested - * @param[out] client_redirect_uri set to OAuth2 client redirect URI - * @return transaction status: - * #GNUNET_DB_STATUS_SUCCESS_ONE_RESULT if the nonce was found - * #GNUNET_DB_STATUS_SUCCESS_NO_RESULTS if we do not know the nonce - * #GNUNET_DB_STATUS_HARD_ERROR on failure - */ -enum GNUNET_DB_QueryStatus -CHALLENGERDB_validate_solve_pin ( - struct CHALLENGERDB_PostgresContext *ctx, - const struct CHALLENGER_ValidationNonceP *nonce, - uint32_t new_pin, - bool *solved, - bool *exhausted, - bool *no_challenge, - char **state, - uint32_t *addr_left, - uint32_t *auth_attempts_left, - uint32_t *pin_transmissions_left, - char **client_redirect_uri); - - -#endif diff --git a/src/include/challenger-database/validation_get.h b/src/include/challenger-database/validation_get.h @@ -1,57 +0,0 @@ -/* - This file is part of Challenger - Copyright (C) 2023 Taler Systems SA - - Challenger is free software; you can redistribute it and/or modify it under the - terms of the GNU General Public License as published by the Free Software - Foundation; either version 3, or (at your option) any later version. - - Challenger is distributed in the hope that it will be useful, but WITHOUT ANY - WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR - A PARTICULAR PURPOSE. See the GNU General Public License for more details. - - You should have received a copy of the GNU General Public License along with - Challenger; see the file COPYING. If not, see <http://www.gnu.org/licenses/> - */ -/** - * @file src/include/challenger-database/validation_get.h - * @brief implementation of the validation_get function for Postgres - * @author Christian Grothoff - */ -#ifndef CHALLENGER_DATABASE_VALIDATION_GET_H -#define CHALLENGER_DATABASE_VALIDATION_GET_H - -#include <taler/taler_util.h> -#include <taler/taler_json_lib.h> -#include "challenger_util.h" -#include "challenger_database_lib.h" - - -/** - * Return validation details. Used by ``/solve``, ``/auth`` and - * ``/info`` endpoints to authorize and return validated user - * address to the client. - * - * @param cls - * @param nonce unique nonce to use to identify the validation - * @param[out] client_secret set to secret of client (for client that setup the challenge) - * @param[out] address set to client-provided address - * @param[out] client_scope set to OAuth2 scope - * @param[out] client_state set to client state - * @param[out] client_redirect_uri set to client redirect URL - * @return transaction status: - * #GNUNET_DB_STATUS_SUCCESS_ONE_RESULT if the nonce was found - * #GNUNET_DB_STATUS_SUCCESS_NO_RESULTS if we do not know the nonce - * #GNUNET_DB_STATUS_HARD_ERROR on failure - */ -enum GNUNET_DB_QueryStatus -CHALLENGERDB_validation_get ( - struct CHALLENGERDB_PostgresContext *ctx, - const struct CHALLENGER_ValidationNonceP *nonce, - char **client_secret, - json_t **address, - char **client_scope, - char **client_state, - char **client_redirect_uri); - -#endif diff --git a/src/include/challenger-database/validation_get_pkce.h b/src/include/challenger-database/validation_get_pkce.h @@ -1,64 +0,0 @@ -/* - This file is part of Challenger - Copyright (C) 2023 Taler Systems SA - - Challenger is free software; you can redistribute it and/or modify it under the - terms of the GNU General Public License as published by the Free Software - Foundation; either version 3, or (at your option) any later version. - - Challenger is distributed in the hope that it will be useful, but WITHOUT ANY - WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR - A PARTICULAR PURPOSE. See the GNU General Public License for more details. - - You should have received a copy of the GNU General Public License along with - Challenger; see the file COPYING. If not, see <http://www.gnu.org/licenses/> - */ -/** - * @file src/include/challenger-database/validation_get_pkce.h - * @brief implementation of the validation_get_pkce function for Postgres - * @author Bohdan Potuzhnyi - * @author Vlada Svirsh - */ -#ifndef CHALLENGER_DATABASE_VALIDATION_GET_PKCE_H -#define CHALLENGER_DATABASE_VALIDATION_GET_PKCE_H - -#include <taler/taler_util.h> -#include <taler/taler_json_lib.h> -#include "challenger_util.h" -#include "challenger_database_lib.h" - - -/** - * Return validation details. Used by ``/solve``, ``/auth`` and - * ``/info`` endpoints to authorize and return validated user - * address to the client. - * - * @param cls - * @param nonce unique nonce to use to identify the validation - * @param client_id serial id of the authenticated client redeeming the code - * @param[out] client_secret set to secret of client (for client that setup the challenge) - * @param[out] address set to client-provided address - * @param[out] client_scope set to OAuth2 scope - * @param[out] client_state set to client state - * @param[out] client_redirect_uri set to client redirect URL - * @param[out] code_challenge set to PKCE code challenge - * @param[out] code_challenge_method set to PKCE code challenge method enum - * @return transaction status: - * #GNUNET_DB_STATUS_SUCCESS_ONE_RESULT if the nonce was found - * #GNUNET_DB_STATUS_SUCCESS_NO_RESULTS if we do not know the nonce - * #GNUNET_DB_STATUS_HARD_ERROR on failure - */ -enum GNUNET_DB_QueryStatus -CHALLENGERDB_validation_get_pkce ( - struct CHALLENGERDB_PostgresContext *ctx, - const struct CHALLENGER_ValidationNonceP *nonce, - uint64_t client_id, - char **client_secret, - json_t **address, - char **client_scope, - char **client_state, - char **client_redirect_uri, - char **code_challenge, - uint32_t *code_challenge_method); - -#endif