gnunet-svn
[Top][All Lists]
Advanced

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

[taler-challenger] branch master updated (e23d3ce -> 7137581)


From: gnunet
Subject: [taler-challenger] branch master updated (e23d3ce -> 7137581)
Date: Wed, 14 Feb 2024 20:55:01 +0100

This is an automated email from the git hooks/post-receive script.

grothoff pushed a change to branch master
in repository challenger.

    from e23d3ce  -more logging
     new b466482  bugfixes to error handling
     new 7137581  preparations for #8405

The 2 revisions listed above as "new" are entirely new to this
repository and will be described in separate emails.  The revisions
listed as "add" were already present in the repository and have only
been added to this reference.


Summary of changes:
 src/challenger/challenger-httpd_authorize.c        |  12 +++
 src/challenger/challenger-httpd_challenge.c        |  42 ++++++--
 src/challenger/challenger-httpd_common.c           |  60 ++++++++++-
 src/challenger/challenger-httpd_common.h           |  30 +++++-
 src/challenger/challenger-httpd_solve.c            |  90 +++++++++++++---
 src/challengerdb/Makefile.am                       |  21 +++-
 ...challenger_do_challenge_set_address_and_pin.sql | 117 +++++++++++++++++++++
 .../pg_challenge_set_address_and_pin.c             | 103 ++++++------------
 .../pg_challenge_set_address_and_pin.h             |   7 +-
 src/challengerdb/pg_validate_solve_pin.c           |  68 +++++++-----
 src/challengerdb/pg_validate_solve_pin.h           |  17 ++-
 src/challengerdb/plugin_challengerdb_postgres.c    |   5 +-
 src/challengerdb/{drop.sql => procedures.sql.in}   |  11 +-
 src/include/challenger_database_plugin.h           |  16 ++-
 14 files changed, 456 insertions(+), 143 deletions(-)
 create mode 100644 
src/challengerdb/challenger_do_challenge_set_address_and_pin.sql
 copy src/challengerdb/{drop.sql => procedures.sql.in} (75%)

diff --git a/src/challenger/challenger-httpd_authorize.c 
b/src/challenger/challenger-httpd_authorize.c
index c2ba0fc..20f4136 100644
--- a/src/challenger/challenger-httpd_authorize.c
+++ b/src/challenger/challenger-httpd_authorize.c
@@ -23,6 +23,7 @@
 #include <gnunet/gnunet_util_lib.h>
 #include <taler/taler_templating_lib.h>
 #include "challenger-httpd_authorize.h"
+#include "challenger-httpd_common.h"
 
 
 MHD_RESULT
@@ -175,6 +176,17 @@ CH_handler_authorize (struct CH_HandlerContext *hc,
     case GNUNET_DB_STATUS_SUCCESS_ONE_RESULT:
       break;
     }
+    if (0 == address_attempts_left)
+    {
+      GNUNET_log (GNUNET_ERROR_TYPE_WARNING,
+                  "Refusing authorization: zero address attempts left\n");
+      return TALER_MHD_redirect_with_oauth_status (
+        hc->connection,
+        redirect_uri,
+        "unauthorized_client",
+        "client exceeded authorization attempts limit (too many addresses)",
+        NULL);
+    }
     {
       enum GNUNET_GenericReturnValue ret;
       json_t *args;
diff --git a/src/challenger/challenger-httpd_challenge.c 
b/src/challenger/challenger-httpd_challenge.c
index 6a66d35..a7242f0 100644
--- a/src/challenger/challenger-httpd_challenge.c
+++ b/src/challenger/challenger-httpd_challenge.c
@@ -26,6 +26,7 @@
 #include <taler/taler_templating_lib.h>
 #include <taler/taler_merchant_service.h>
 #include <taler/taler_signatures.h>
+#include "challenger-httpd_common.h"
 
 
 /**
@@ -84,6 +85,11 @@ struct ChallengeContext
    */
   char *data;
 
+  /**
+   * Where to redirect the client on errors?
+   */
+  char *client_redirect_uri;
+
   /**
    * When did we transmit last?
    */
@@ -129,6 +135,12 @@ struct ChallengeContext
    */
   enum GNUNET_GenericReturnValue suspended;
 
+  /**
+   * True if the provided address was refused, usually because
+   * the user tried too many different addresses already.
+   */
+  bool address_refused;
+
   /**
    * Should we retransmit the PIN?
    */
@@ -199,6 +211,7 @@ cleanup_ctx (void *cls)
   json_decref (bc->address);
   GNUNET_free (bc->data);
   GNUNET_free (bc->last_key);
+  GNUNET_free (bc->client_redirect_uri);
   GNUNET_free (bc);
 }
 
@@ -518,6 +531,7 @@ CH_handler_challenge (struct CH_HandlerContext *hc,
   {
     enum GNUNET_DB_QueryStatus qs;
 
+    GNUNET_assert (NULL == bc->client_redirect_uri);
     qs = CH_db->challenge_set_address_and_pin (CH_db->cls,
                                                &bc->nonce,
                                                bc->address,
@@ -525,7 +539,9 @@ CH_handler_challenge (struct CH_HandlerContext *hc,
                                                &bc->tan,
                                                &bc->last_tx_time,
                                                &bc->pin_attempts_left,
-                                               &bc->retransmit);
+                                               &bc->retransmit,
+                                               &bc->client_redirect_uri,
+                                               &bc->address_refused);
     switch (qs)
     {
     case GNUNET_DB_STATUS_HARD_ERROR:
@@ -549,15 +565,27 @@ CH_handler_challenge (struct CH_HandlerContext *hc,
       break;
     }
     bc->db_finished = true;
+    if (bc->address_refused)
+    {
+      GNUNET_log (GNUNET_ERROR_TYPE_INFO,
+                  "Address changes exhausted address change limit for this 
process\n");
+      return TALER_MHD_redirect_with_oauth_status (
+        hc->connection,
+        bc->client_redirect_uri,
+        "unauthorized_client",
+        "client exceeded authorization attempts limit (too many addresses 
attempted)",
+        NULL);
+    }
     if (0 == bc->pin_attempts_left)
     {
       GNUNET_log (GNUNET_ERROR_TYPE_INFO,
-                  "Attempts exhausted for this PIN\n");
-      return TALER_TEMPLATING_reply_error (hc->connection,
-                                           "attempts-exhausted",
-                                           MHD_HTTP_TOO_MANY_REQUESTS,
-                                           
TALER_EC_CHALLENGER_TOO_MANY_ATTEMPTS,
-                                           NULL);
+                  "Address changes exhausted PIN limit for this address\n");
+      return TALER_MHD_redirect_with_oauth_status (
+        hc->connection,
+        bc->client_redirect_uri,
+        "unauthorized_client",
+        "client exceeded authorization attempts limit (too many PINs)",
+        NULL);
     }
 
     if (bc->retransmit)
diff --git a/src/challenger/challenger-httpd_common.c 
b/src/challenger/challenger-httpd_common.c
index 63f3612..ddd4404 100644
--- a/src/challenger/challenger-httpd_common.c
+++ b/src/challenger/challenger-httpd_common.c
@@ -1,6 +1,6 @@
 /*
   This file is part of Challenger
-  Copyright (C) 2023 Taler Systems SA
+  Copyright (C) 2023, 2024 Taler Systems SA
 
   Challenger is free software; you can redistribute it and/or modify it under 
the
   terms of the GNU Affero General Public License as published by the Free 
Software
@@ -157,3 +157,61 @@ TALER_MHD_reply_with_oauth_error (
   MHD_destroy_response (resp);
   return mret;
 }
+
+
+MHD_RESULT
+TALER_MHD_redirect_with_oauth_status (
+  struct MHD_Connection *connection,
+  const char *client_redirect_uri,
+  const char *oauth_error,
+  const char *oauth_error_description,
+  const char *oauth_error_uri)
+{
+  struct MHD_Response *response;
+
+  response = MHD_create_response_from_buffer (strlen (oauth_error),
+                                              (void *) oauth_error,
+                                              MHD_RESPMEM_PERSISTENT);
+  if (NULL == response)
+  {
+    GNUNET_break (0);
+    return MHD_NO;
+  }
+  TALER_MHD_add_global_headers (response);
+  GNUNET_break (MHD_YES ==
+                MHD_add_response_header (response,
+                                         MHD_HTTP_HEADER_CONTENT_TYPE,
+                                         "text/plain"));
+  {
+    char *url;
+
+    url = TALER_url_join (
+      client_redirect_uri,
+      "",
+      "error", oauth_error,
+      "error_description", oauth_error_description,
+      "error_uri", oauth_error_uri,
+      NULL);
+    if (MHD_NO ==
+        MHD_add_response_header (response,
+                                 MHD_HTTP_HEADER_LOCATION,
+                                 url))
+    {
+      GNUNET_break (0);
+      MHD_destroy_response (response);
+      GNUNET_free (url);
+      return MHD_NO;
+    }
+    GNUNET_free (url);
+  }
+
+  {
+    MHD_RESULT ret;
+
+    ret = MHD_queue_response (connection,
+                              MHD_HTTP_FOUND,
+                              response);
+    MHD_destroy_response (response);
+    return ret;
+  }
+}
diff --git a/src/challenger/challenger-httpd_common.h 
b/src/challenger/challenger-httpd_common.h
index 618dd3a..01d8482 100644
--- a/src/challenger/challenger-httpd_common.h
+++ b/src/challenger/challenger-httpd_common.h
@@ -79,11 +79,31 @@ CH_code_to_nonce (const char *code,
  * @return a MHD result code
  */
 MHD_RESULT
-TALER_MHD_reply_with_oauth_error (struct MHD_Connection *connection,
-                                  unsigned int http_status,
-                                  const char *oauth_error,
-                                  enum TALER_ErrorCode ec,
-                                  const char *detail);
+TALER_MHD_reply_with_oauth_error (
+  struct MHD_Connection *connection,
+  unsigned int http_status,
+  const char *oauth_error,
+  enum TALER_ErrorCode ec,
+  const char *detail);
 
+/**
+ * Redirect the client on @a connection to the given
+ * @a client_redirect_uri providing the given OAuth2.0
+ * error details.
+ *
+ * @param connection HTTP request to handle
+ * @param client_redirect_uri base URI where to redirect
+ * @param oauth_error error status to return (e.g. "invalid_scope")
+ * @param oauth_error_description longer description to return, optional, can 
be NULL
+ * @param oauth_error_uri URI with additional information about the error, 
optional, can be NULL
+ * @return MHD response queueing status
+ */
+MHD_RESULT
+TALER_MHD_redirect_with_oauth_status (
+  struct MHD_Connection *connection,
+  const char *client_redirect_uri,
+  const char *oauth_error,
+  const char *oauth_error_description,
+  const char *oauth_error_uri);
 
 #endif
diff --git a/src/challenger/challenger-httpd_solve.c 
b/src/challenger/challenger-httpd_solve.c
index 0d00ed9..54017b1 100644
--- a/src/challenger/challenger-httpd_solve.c
+++ b/src/challenger/challenger-httpd_solve.c
@@ -45,6 +45,11 @@ struct SolveContext
    */
   struct MHD_PostProcessor *pp;
 
+  /**
+   * OAuth2 client redirection URI for error reporting.
+   */
+  char *client_redirect_uri;
+
   /**
    * 0-terminated PIN submitted to us.
    */
@@ -54,6 +59,22 @@ struct SolveContext
    * Number of bytes in @a pin, excluding 0-terminator.
    */
   size_t pin_len;
+
+  /**
+   * How many address changes are still allowed?
+   */
+  uint32_t addr_left;
+
+  /**
+   * How many authentication attempts are still allowed?
+   */
+  uint32_t auth_attempts_left;
+
+  /**
+   * How many pin transmissions can still be requested?
+   */
+  uint32_t pin_transmissions_left;
+
 };
 
 
@@ -206,34 +227,71 @@ CH_handler_solve (struct CH_HandlerContext *hc,
     qs = CH_db->validate_solve_pin (CH_db->cls,
                                     &bc->nonce,
                                     pin,
-                                    &solved);
+                                    &solved,
+                                    &bc->addr_left,
+                                    &bc->auth_attempts_left,
+                                    &bc->pin_transmissions_left,
+                                    &bc->client_redirect_uri);
     switch (qs)
     {
     case GNUNET_DB_STATUS_HARD_ERROR:
-      return TALER_TEMPLATING_reply_error (hc->connection,
-                                           "internal-error",
-                                           MHD_HTTP_INTERNAL_SERVER_ERROR,
-                                           TALER_EC_GENERIC_DB_FETCH_FAILED,
-                                           "validate_solve_pin");
+      return TALER_TEMPLATING_reply_error (
+        hc->connection,
+        "internal-error",
+        MHD_HTTP_INTERNAL_SERVER_ERROR,
+        TALER_EC_GENERIC_DB_FETCH_FAILED,
+        "validate_solve_pin");
     case GNUNET_DB_STATUS_SOFT_ERROR:
       GNUNET_break (0);
       return MHD_NO;
     case GNUNET_DB_STATUS_SUCCESS_NO_RESULTS:
-      return TALER_TEMPLATING_reply_error (hc->connection,
-                                           "validation-unknown",
-                                           MHD_HTTP_NOT_FOUND,
-                                           
TALER_EC_CHALLENGER_GENERIC_VALIDATION_UNKNOWN,
-                                           NULL);
+      return TALER_TEMPLATING_reply_error (
+        hc->connection,
+        "validation-unknown",
+        MHD_HTTP_NOT_FOUND,
+        TALER_EC_CHALLENGER_GENERIC_VALIDATION_UNKNOWN,
+        NULL);
     case GNUNET_DB_STATUS_SUCCESS_ONE_RESULT:
       break;
     }
     if (! solved)
     {
-      return TALER_TEMPLATING_reply_error (hc->connection,
-                                           "invalid-pin",
-                                           MHD_HTTP_FORBIDDEN,
-                                           TALER_EC_CHALLENGER_INVALID_PIN,
-                                           NULL);
+      MHD_RESULT ret;
+      json_t *details;
+
+      if ( (0 == bc->addr_left) &&
+           (0 == bc->pin_transmissions_left) &&
+           (0 == bc->auth_attempts_left) )
+      {
+        GNUNET_log (GNUNET_ERROR_TYPE_INFO,
+                    "Client exhausted all chances to satisfy challenge\n");
+        return TALER_MHD_redirect_with_oauth_status (
+          hc->connection,
+          bc->client_redirect_uri,
+          "access_denied",
+          "users exhausted all possibilities of passing the check",
+          NULL);
+      }
+
+      GNUNET_log (GNUNET_ERROR_TYPE_INFO,
+                  "Invalid PIN supplied, client has chance to solve it 
again\n");
+      details = GNUNET_JSON_PACK (
+        TALER_JSON_pack_ec (TALER_EC_CHALLENGER_INVALID_PIN),
+        GNUNET_JSON_pack_uint64 ("addresses_left",
+                                 bc->addr_left),
+        GNUNET_JSON_pack_uint64 ("pin_transmissions_left",
+                                 bc->pin_transmissions_left),
+        GNUNET_JSON_pack_uint64 ("auth_attempts_left",
+                                 bc->auth_attempts_left)
+        );
+      ret = TALER_TEMPLATING_reply (hc->connection,
+                                    MHD_HTTP_FORBIDDEN,
+                                    "invalid-pin",
+                                    NULL,
+                                    NULL,
+                                    details);
+      json_decref (details);
+      return ret;
     }
   }
 
diff --git a/src/challengerdb/Makefile.am b/src/challengerdb/Makefile.am
index 1b1c70d..6f43ead 100644
--- a/src/challengerdb/Makefile.am
+++ b/src/challengerdb/Makefile.am
@@ -20,13 +20,29 @@ if USE_COVERAGE
   XLIB = -lgcov
 endif
 
+sqlinputs = \
+  challenger_do_*.sql \
+  procedures.sql.in
+
 sqldir = $(prefix)/share/challenger/sql/
 
 sql_DATA = \
   versioning.sql \
+  procedures.sql \
   challenger-0001.sql \
   drop.sql
 
+BUILT_SOURCES = \
+  procedures.sql
+
+CLEANFILES = \
+  exchange-0002.sql
+
+procedures.sql: procedures.sql.in challenger_do_*.sql
+       chmod +w $@ || true
+       gcc -E -P -undef - < procedures.sql.in 2>/dev/null | sed -e "s/--.*//" 
| awk 'NF' - >$@
+       chmod ugo-w $@
+
 bin_PROGRAMS = \
   challenger-dbinit
 
@@ -96,6 +112,9 @@ TESTS = \
   test_challenger_db-postgres
 
 EXTRA_DIST = \
+  $(sqlinputs) \
   $(pkgcfg_DATA) \
   $(sql_DATA) \
-  test_challenger_db_postgres.conf
+  test_challenger_db_postgres.conf \
+  pg_template.h pg_template.c \
+  pg_template.sh
diff --git a/src/challengerdb/challenger_do_challenge_set_address_and_pin.sql 
b/src/challengerdb/challenger_do_challenge_set_address_and_pin.sql
new file mode 100644
index 0000000..c12d629
--- /dev/null
+++ b/src/challengerdb/challenger_do_challenge_set_address_and_pin.sql
@@ -0,0 +1,117 @@
+--
+-- 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/>
+--
+
+
+
+CREATE OR REPLACE FUNCTION challenger_do_challenge_set_address_and_pin (
+  IN in_nonce BYTEA,
+  IN in_address TEXT,
+  IN in_next_tx_time 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_pin_transmit BOOLEAN,
+  OUT out_auth_attempts_left INT4,
+  OUT out_client_redirect_uri TEXT,
+  OUT out_address_refused 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
+  INTO my_status
+  FROM validations
+ WHERE nonce=in_nonce;
+
+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;
+  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_client_redirect_uri=my_status.client_redirect_uri;
+
+IF ( (0 == my_status.address_attempts_left) AND
+     (in_address != my_status.address) )
+THEN
+  out_address_refused=TRUE;
+  RETURN;
+END IF;
+out_address_refused=FALSE;
+
+IF (in_address != my_status.address)
+THEN
+  -- we are changing the address, update counters
+  my_status.address_attempts_left = 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_next_tx_time) )
+THEN
+  -- 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;
+  out_auth_attempts_left = 3;
+  out_pin_transmit=TRUE;
+  out_last_pin = in_tan;
+  my_status.last_tx_time = in_now;
+  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=$1;
+END IF;
+
+RETURN;
+
+END $$;
diff --git a/src/challengerdb/pg_challenge_set_address_and_pin.c 
b/src/challengerdb/pg_challenge_set_address_and_pin.c
index 51f1260..04bebed 100644
--- a/src/challengerdb/pg_challenge_set_address_and_pin.c
+++ b/src/challengerdb/pg_challenge_set_address_and_pin.c
@@ -35,7 +35,9 @@ CH_PG_challenge_set_address_and_pin (
   uint32_t *tan,
   struct GNUNET_TIME_Absolute *last_tx_time,
   uint32_t *auth_attempts_left,
-  bool *pin_transmit)
+  bool *pin_transmit,
+  char **client_redirect_uri,
+  bool *address_refused)
 {
   struct PostgresClosure *pg = cls;
   struct GNUNET_TIME_Absolute now
@@ -51,7 +53,10 @@ CH_PG_challenge_set_address_and_pin (
     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",
@@ -60,76 +65,36 @@ CH_PG_challenge_set_address_and_pin (
                                 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_bool ("address_refused",
+                                address_refused),
     GNUNET_PQ_result_spec_end
   };
+  enum GNUNET_DB_QueryStatus qs;
 
+  *client_redirect_uri = NULL;
   PREPARE (pg,
-           "challenge_set_address_and_pin",
-           "WITH decisions AS ("
-           "  SELECT "
-           "    ( (address IS NULL) OR"
-           "      (address != $2) ) AND"
-           "    (address_attempts_left > 0)"
-           "      AS addr_changed"
-           "   ,( (pin_transmissions_left > 0) OR"
-           "      (address_attempts_left > 0) ) AND"
-           "    ( (address IS NULL) OR"
-           "      (address != $2) OR"
-           "      (last_tx_time < $3) ) AS send_pin"
-           "    FROM validations"
-           "    WHERE nonce=$1"
-           "),"
-           "result AS ("
-           "UPDATE validations SET"
-           "  address_attempts_left=CASE"
-           "    WHEN (SELECT addr_changed FROM decisions)"
-           "    THEN address_attempts_left - 1 "
-           "    ELSE address_attempts_left "
-           "  END"
-           " ,last_pin = CASE "
-           "    WHEN (SELECT addr_changed FROM decisions)"
-           "    THEN $5"
-           "    ELSE last_pin"
-           "  END"
-           " ,pin_transmissions_left=CASE"
-           "    WHEN (SELECT addr_changed FROM decisions)"
-           "    THEN 3 "
-           "    ELSE CASE"
-           "      WHEN (SELECT send_pin FROM decisions)"
-           "      THEN pin_transmissions_left - 1"
-           "      ELSE pin_transmissions_left"
-           "    END"
-           "  END"
-           " ,auth_attempts_left=CASE"
-           "    WHEN (SELECT addr_changed FROM decisions)"
-           "    THEN 3 "
-           "    ELSE auth_attempts_left"
-           "  END"
-           " ,last_tx_time=CASE"
-           "    WHEN (SELECT send_pin FROM decisions)"
-           "    THEN $4"
-           "    ELSE last_tx_time"
-           "  END"
-           " ,address=CASE"
-           "    WHEN (SELECT addr_changed FROM decisions)"
-           "    THEN $2"
-           "    ELSE address"
-           "  END"
-           " WHERE nonce=$1"
-           " RETURNING"
-           "   last_tx_time"
-           "  ,last_pin"
-           "  ,auth_attempts_left"
-           ")"
-           " SELECT"
-           "  last_tx_time"
-           " ,decisions.send_pin AS pin_transmit"
-           " ,last_pin"
-           " ,auth_attempts_left"
-           " FROM result"
-           " FULL OUTER JOIN decisions ON (TRUE);");
-  return GNUNET_PQ_eval_prepared_singleton_select (pg->conn,
-                                                   
"challenge_set_address_and_pin",
-                                                   params,
-                                                   rs);
+           "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_auth_attempts_left AS auth_attempts_left"
+           ",out_client_redirect_uri AS client_redirect_uri"
+           ",out_address_refused AS address_refused"
+           " FROM challenger_do_challenge_set_address_and_pin"
+           " ($1,$2,$3,$4,$5);");
+  qs = GNUNET_PQ_eval_prepared_singleton_select (pg->conn,
+                                                 
"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/pg_challenge_set_address_and_pin.h 
b/src/challengerdb/pg_challenge_set_address_and_pin.h
index 8a5b72d..460942e 100644
--- a/src/challengerdb/pg_challenge_set_address_and_pin.h
+++ b/src/challengerdb/pg_challenge_set_address_and_pin.h
@@ -40,6 +40,8 @@
  * @param[out] last_tx_time set to the last time when we (presumably) send a 
PIN to @a address, input should be current time to use if the existing value 
for tx_time is past @a next_tx_time
  * @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)
  * @return transaction status:
  *   #GNUNET_DB_STATUS_SUCCESS_ONE_RESULT if the address was changed
  *   #GNUNET_DB_STATUS_SUCCESS_NO_RESULTS if we do not permit further changes 
to the address (attempts exhausted)
@@ -54,7 +56,8 @@ CH_PG_challenge_set_address_and_pin (
   uint32_t *tan,
   struct GNUNET_TIME_Absolute *last_tx_time,
   uint32_t *auth_attempts_left,
-  bool *pin_transmit);
-
+  bool *pin_transmit,
+  char **client_redirect_uri,
+  bool *address_refused);
 
 #endif
diff --git a/src/challengerdb/pg_validate_solve_pin.c 
b/src/challengerdb/pg_validate_solve_pin.c
index 61f4837..077134f 100644
--- a/src/challengerdb/pg_validate_solve_pin.c
+++ b/src/challengerdb/pg_validate_solve_pin.c
@@ -30,7 +30,11 @@ enum GNUNET_DB_QueryStatus
 CH_PG_validate_solve_pin (void *cls,
                           const struct CHALLENGER_ValidationNonceP *nonce,
                           uint32_t new_pin,
-                          bool *solved)
+                          bool *solved,
+                          uint32_t *addr_left,
+                          uint32_t *auth_attempts_left,
+                          uint32_t *pin_transmissions_left,
+                          char **client_redirect_uri)
 {
   struct PostgresClosure *pg = cls;
   struct GNUNET_PQ_QueryParam params[] = {
@@ -38,39 +42,45 @@ CH_PG_validate_solve_pin (void *cls,
     GNUNET_PQ_query_param_uint32 (&new_pin),
     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_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_end
   };
+  enum GNUNET_DB_QueryStatus qs;
 
-  /* We set all remaining attempts to zero to prevent
-     user from changing the address after already having
-     succeeded with the process. */
+  *client_redirect_uri = NULL;
   PREPARE (pg,
-           "validate_solve_pin",
-           "UPDATE validations SET"
-           "  auth_attempts_left=CASE"
-           "    WHEN last_pin = $2"
-           "    THEN 0"
-           "    ELSE auth_attempts_left - 1"
-           "  END"
-           " ,address_attempts_left=CASE"
-           "    WHEN last_pin = $2"
-           "    THEN 0"
-           "    ELSE address_attempts_left"
-           "  END"
-           " ,pin_transmissions_left=CASE"
-           "    WHEN last_pin = $2"
-           "    THEN 0"
-           "    ELSE pin_transmissions_left"
-           "  END"
-           " WHERE nonce=$1"
-           "   AND auth_attempts_left > 0"
-           " RETURNING"
-           "   (last_pin = $2) AS solved;");
-  return GNUNET_PQ_eval_prepared_singleton_select (pg->conn,
-                                                   "validate_solve_pin",
-                                                   params,
-                                                   rs);
+           "do_validate_solve_pin",
+           "SELECT "
+           " out_not_found AS not_found"
+           ",out_solved AS solved"
+           ",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_solve_pin"
+           " ($1,$2);");
+  qs = GNUNET_PQ_eval_prepared_singleton_select (pg->conn,
+                                                 "do_validate_solve_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/pg_validate_solve_pin.h 
b/src/challengerdb/pg_validate_solve_pin.h
index 91870d6..a2d7c6d 100644
--- a/src/challengerdb/pg_validate_solve_pin.h
+++ b/src/challengerdb/pg_validate_solve_pin.h
@@ -33,16 +33,25 @@
  * @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] addr_left set to number of address changes remaining
+ * @param[out] auth_attempts_left set to number of authentication attempts 
remaining
+ * @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
-CH_PG_validate_solve_pin (void *cls,
-                          const struct CHALLENGER_ValidationNonceP *nonce,
-                          uint32_t new_pin,
-                          bool *solved);
+CH_PG_validate_solve_pin (
+  void *cls,
+  const struct CHALLENGER_ValidationNonceP *nonce,
+  uint32_t new_pin,
+  bool *solved,
+  uint32_t *addr_left,
+  uint32_t *auth_attempts_left,
+  uint32_t *pin_transmissions_left,
+  char **client_redirect_uri);
 
 
 #endif
diff --git a/src/challengerdb/plugin_challengerdb_postgres.c 
b/src/challengerdb/plugin_challengerdb_postgres.c
index 5f13c05..1dd700a 100644
--- a/src/challengerdb/plugin_challengerdb_postgres.c
+++ b/src/challengerdb/plugin_challengerdb_postgres.c
@@ -322,6 +322,7 @@ postgres_create_tables (void *cls)
     GNUNET_PQ_make_execute ("SET search_path TO challenger;"),
     GNUNET_PQ_EXECUTE_STATEMENT_END
   };
+  enum GNUNET_GenericReturnValue ret;
 
   conn = GNUNET_PQ_connect_with_cfg (pc->cfg,
                                      "challengerdb-postgres",
@@ -330,8 +331,10 @@ postgres_create_tables (void *cls)
                                      NULL);
   if (NULL == conn)
     return GNUNET_SYSERR;
+  ret = GNUNET_PQ_exec_sql (conn,
+                            "procedures");
   GNUNET_PQ_disconnect (conn);
-  return GNUNET_OK;
+  return ret;
 }
 
 
diff --git a/src/challengerdb/drop.sql b/src/challengerdb/procedures.sql.in
similarity index 75%
copy from src/challengerdb/drop.sql
copy to src/challengerdb/procedures.sql.in
index da51320..3636b94 100644
--- a/src/challengerdb/drop.sql
+++ b/src/challengerdb/procedures.sql.in
@@ -1,6 +1,6 @@
 --
 -- This file is part of TALER
--- Copyright (C) 2021, 2022 Taler Systems SA
+-- 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
@@ -14,12 +14,11 @@
 -- TALER; see the file COPYING.  If not, see <http://www.gnu.org/licenses/>
 --
 
--- Everything in one big transaction
 BEGIN;
 
--- Unregister patch (0001.sql)
-SELECT _v.unregister_patch('challenger-0001');
-DROP SCHEMA challenger CASCADE;
+SET search_path TO challenger;
+
+#include "challenger_do_challenge_set_address_and_pin.sql"
+#include "challenger_do_validate_and_solve_pin.sql"
 
--- And we're out of here...
 COMMIT;
diff --git a/src/include/challenger_database_plugin.h 
b/src/include/challenger_database_plugin.h
index ccceb7c..3d35cc2 100644
--- a/src/include/challenger_database_plugin.h
+++ b/src/include/challenger_database_plugin.h
@@ -261,6 +261,8 @@ struct CHALLENGER_DatabasePlugin
    * @param[out] last_tx_time set to the last time when we (presumably) send a 
PIN to @a address, input should be current time to use if the existing value 
for tx_time is past @a next_tx_time
    * @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)
    * @return transaction status:
    *   #GNUNET_DB_STATUS_SUCCESS_ONE_RESULT if the address was changed
    *   #GNUNET_DB_STATUS_SUCCESS_NO_RESULTS if we do not permit further 
changes to the address (attempts exhausted)
@@ -275,7 +277,9 @@ struct CHALLENGER_DatabasePlugin
     uint32_t *tan,
     struct GNUNET_TIME_Absolute *last_tx_time,
     uint32_t *auth_attempts_left,
-    bool *pin_transmit);
+    bool *pin_transmit,
+    char **client_redirect_uri,
+    bool *address_refused);
 
 
   /**
@@ -285,6 +289,10 @@ struct CHALLENGER_DatabasePlugin
    * @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] addr_left set to number of address changes remaining
+   * @param[out] auth_attempts_left set to number of authentication attempts 
remaining
+   * @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
@@ -294,7 +302,11 @@ struct CHALLENGER_DatabasePlugin
   (*validate_solve_pin)(void *cls,
                         const struct CHALLENGER_ValidationNonceP *nonce,
                         uint32_t new_pin,
-                        bool *solved);
+                        bool *solved,
+                        uint32_t *addr_left,
+                        uint32_t *auth_attempts_left,
+                        uint32_t *pin_transmissions_left,
+                        char **client_redirect_uri);
 
 
   /**

-- 
To stop receiving notification emails like this one, please contact
gnunet@gnunet.org.



reply via email to

[Prev in Thread] Current Thread [Next in Thread]