gnunet-svn
[Top][All Lists]
Advanced

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

[taler-anastasis] branch master updated: fix #7054: propagate more infor


From: gnunet
Subject: [taler-anastasis] branch master updated: fix #7054: propagate more information on the rate-limiting
Date: Fri, 31 Dec 2021 11:37:44 +0100

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

grothoff pushed a commit to branch master
in repository anastasis.

The following commit(s) were added to refs/heads/master by this push:
     new ce443bb  fix #7054: propagate more information on the rate-limiting
ce443bb is described below

commit ce443bb4d4815ac79170b81cae74fc8b8030ea54
Author: Christian Grothoff <christian@grothoff.org>
AuthorDate: Fri Dec 31 11:37:42 2021 +0100

    fix #7054: propagate more information on the rate-limiting
---
 doc/sphinx/rest.rst                            | 28 ++++++++++++++++--
 src/backend/anastasis-httpd_truth.c            | 41 ++++++++++++++++----------
 src/include/anastasis.h                        | 18 +++++++++++
 src/include/anastasis_service.h                | 17 +++++++++++
 src/lib/anastasis_recovery.c                   |  6 +++-
 src/reducer/anastasis_api_recovery_redux.c     | 16 +++++++---
 src/restclient/anastasis_api_keyshare_lookup.c | 38 ++++++++++++++++++++++++
 7 files changed, 142 insertions(+), 22 deletions(-)

diff --git a/doc/sphinx/rest.rst b/doc/sphinx/rest.rst
index a1c5810..9127354 100644
--- a/doc/sphinx/rest.rst
+++ b/doc/sphinx/rest.rst
@@ -425,7 +425,7 @@ charge per truth operation using GNU Taler.
 
       // For how many years from now would the client like us to
       // store the truth?
-      storage_duration_years: Integer;
+      storage_duration_years: number;
 
     }
 
@@ -482,6 +482,10 @@ charge per truth operation using GNU Taler.
     The decrypted ``truth`` does not match the expectations of the 
authentication
     backend, i.e. a phone number for sending an SMS is not a number, or
     an e-mail address for sending an E-mail is not a valid e-mail address.
+  :http:statuscode:`429 Too Many Requests`:
+    The client exceeded the number of allowed attempts at providing
+    a valid response for the given time interval.
+    The response format is given by `RateLimitedMessage`_.
   :http:statuscode:`503 Service Unavailable`:
     Server is out of Service.
 
@@ -543,9 +547,29 @@ charge per truth operation using GNU Taler.
       business_name: string;
 
       // What is the expected wire transfer subject?
-      wire_transfer_subject: Integer;
+      wire_transfer_subject: number;
 
       // Hint about the origin account that must be used.
       debit_account_hint: string;
 
     }
+
+
+  .. _RateLimitedMessage:
+  .. ts:def:: RateLimitedMessage
+
+    interface RateLimitedMessage {
+
+      // Taler error code, TALER_EC_ANASTASIS_TRUTH_RATE_LIMITED.
+      code: number;
+
+      // How many attempts are allowed per challenge?
+      request_limit: number;
+
+      // At what frequency are new challenges issued?
+      request_frequency: RelativeTime;
+
+      // The error message.
+      hint: string;
+
+    }
diff --git a/src/backend/anastasis-httpd_truth.c 
b/src/backend/anastasis-httpd_truth.c
index 6c05ef8..54969bf 100644
--- a/src/backend/anastasis-httpd_truth.c
+++ b/src/backend/anastasis-httpd_truth.c
@@ -236,6 +236,27 @@ static struct GetContext *gc_tail;
 static struct GNUNET_SCHEDULER_Task *to_task;
 
 
+/**
+ * Generate a response telling the client that answering this
+ * challenge failed because the rate limit has been exceeded.
+ *
+ * @param gc request to answer for
+ * @return MHD status code
+ */
+static MHD_RESULT
+reply_rate_limited (const struct GetContext *gc)
+{
+  return TALER_MHD_REPLY_JSON_PACK (
+    gc->connection,
+    MHD_HTTP_TOO_MANY_REQUESTS,
+    TALER_MHD_PACK_EC (TALER_EC_ANASTASIS_TRUTH_RATE_LIMITED),
+    GNUNET_JSON_pack_uint64 ("request_limit",
+                             gc->authorization->retry_counter),
+    GNUNET_JSON_pack_time_rel ("request_frequency",
+                               gc->authorization->code_rotation_period));
+}
+
+
 /**
  * Timeout requests that are past their due date.
  *
@@ -991,9 +1012,8 @@ run_authorization_process (struct MHD_Connection 
*connection,
 
 
 /**
- * Use the database to rate-limit queries to the
- * authentication procedure, but without actually
- * storing 'real' challenge codes.
+ * Use the database to rate-limit queries to the authentication
+ * procedure, but without actually storing 'real' challenge codes.
  *
  * @param[in,out] gc context to rate limit requests for
  * @return #GNUNET_OK if rate-limiting passes,
@@ -1034,10 +1054,7 @@ rate_limit (struct GetContext *gc)
   if (GNUNET_DB_STATUS_SUCCESS_NO_RESULTS == qs)
   {
     return (MHD_YES ==
-            TALER_MHD_reply_with_error (gc->connection,
-                                        MHD_HTTP_TOO_MANY_REQUESTS,
-                                        TALER_EC_ANASTASIS_TRUTH_RATE_LIMITED,
-                                        NULL))
+            reply_rate_limited (gc))
       ? GNUNET_NO
       : GNUNET_SYSERR;
   }
@@ -1066,10 +1083,7 @@ rate_limit (struct GetContext *gc)
       : GNUNET_SYSERR;
   case ANASTASIS_DB_CODE_STATUS_NO_RESULTS:
     return (MHD_YES ==
-            TALER_MHD_reply_with_error (gc->connection,
-                                        MHD_HTTP_TOO_MANY_REQUESTS,
-                                        TALER_EC_ANASTASIS_TRUTH_RATE_LIMITED,
-                                        NULL))
+            reply_rate_limited (gc))
       ? GNUNET_NO
       : GNUNET_SYSERR;
   case ANASTASIS_DB_CODE_STATUS_VALID_CODE_STORED:
@@ -1640,10 +1654,7 @@ AH_handler_truth_get (
       case GNUNET_DB_STATUS_SUCCESS_NO_RESULTS:
         /* 0 == retry_counter of existing challenge => rate limit exceeded */
         GNUNET_free (decrypted_truth);
-        return TALER_MHD_reply_with_error (connection,
-                                           MHD_HTTP_TOO_MANY_REQUESTS,
-                                           
TALER_EC_ANASTASIS_TRUTH_RATE_LIMITED,
-                                           NULL);
+        return reply_rate_limited (gc);
       case GNUNET_DB_STATUS_SUCCESS_ONE_RESULT:
         /* challenge code was stored successfully*/
         GNUNET_log (GNUNET_ERROR_TYPE_INFO,
diff --git a/src/include/anastasis.h b/src/include/anastasis.h
index fd7ed40..b957f18 100644
--- a/src/include/anastasis.h
+++ b/src/include/anastasis.h
@@ -207,6 +207,24 @@ struct ANASTASIS_ChallengeStartResponse
       unsigned int http_status;
     } open_challenge;
 
+    /**
+     * Details for #ANASTASIS_CHALLENGE_STATUS_RATE_LIMIT_EXCEEDED.
+     */
+    struct
+    {
+
+      /**
+       * How many requests are allowed at most per @e request_frequency?
+       */
+      uint32_t request_limit;
+
+      /**
+       * Frequency at which requests are allowed / new challenges are
+       * created.
+       */
+      struct GNUNET_TIME_Relative request_frequency;
+
+    } rate_limit_exceeded;
 
     /**
      * Response with details if
diff --git a/src/include/anastasis_service.h b/src/include/anastasis_service.h
index b6b3d76..0ef31d6 100644
--- a/src/include/anastasis_service.h
+++ b/src/include/anastasis_service.h
@@ -570,6 +570,23 @@ struct ANASTASIS_KeyShareDownloadDetails
     } payment_required;
 
 
+    struct
+    {
+
+      /**
+       * How many requests are allowed at most per @e request_frequency?
+       */
+      uint32_t request_limit;
+
+      /**
+       * Frequency at which requests are allowed / new challenges are
+       * created.
+       */
+      struct GNUNET_TIME_Relative request_frequency;
+
+    } rate_limit_exceeded;
+
+
     /**
      * Response with details about a server-side failure, if
      * @e status is #ANASTASIS_KSD_SERVER_ERROR,
diff --git a/src/lib/anastasis_recovery.c b/src/lib/anastasis_recovery.c
index b85b0f6..3a7943e 100644
--- a/src/lib/anastasis_recovery.c
+++ b/src/lib/anastasis_recovery.c
@@ -319,7 +319,11 @@ keyshare_lookup_cb (void *cls,
     {
       struct ANASTASIS_ChallengeStartResponse csr = {
         .cs = ANASTASIS_CHALLENGE_STATUS_RATE_LIMIT_EXCEEDED,
-        .challenge = c
+        .challenge = c,
+        .details.rate_limit_exceeded.request_limit
+          = dd->details.rate_limit_exceeded.request_limit,
+        .details.rate_limit_exceeded.request_frequency
+          = dd->details.rate_limit_exceeded.request_frequency
       };
 
       c->af (c->af_cls,
diff --git a/src/reducer/anastasis_api_recovery_redux.c 
b/src/reducer/anastasis_api_recovery_redux.c
index a26b6ad..088ff7e 100644
--- a/src/reducer/anastasis_api_recovery_redux.c
+++ b/src/reducer/anastasis_api_recovery_redux.c
@@ -765,10 +765,18 @@ answer_feedback_cb (
       json_t *err;
 
       err = GNUNET_JSON_PACK (
-        GNUNET_JSON_pack_string ("state",
-                                 "rate-limit-exceeded"),
-        GNUNET_JSON_pack_uint64 ("error_code",
-                                 TALER_EC_ANASTASIS_TRUTH_RATE_LIMITED));
+        GNUNET_JSON_pack_string (
+          "state",
+          "rate-limit-exceeded"),
+        GNUNET_JSON_pack_uint64 (
+          "request_limit",
+          csr->details.rate_limit_exceeded.request_limit),
+        GNUNET_JSON_pack_time_rel (
+          "request_frequency",
+          csr->details.rate_limit_exceeded.request_frequency),
+        GNUNET_JSON_pack_uint64 (
+          "error_code",
+          TALER_EC_ANASTASIS_TRUTH_RATE_LIMITED));
       GNUNET_assert (0 ==
                      json_object_set_new (feedback,
                                           uuid,
diff --git a/src/restclient/anastasis_api_keyshare_lookup.c 
b/src/restclient/anastasis_api_keyshare_lookup.c
index 13390c9..99924d1 100644
--- a/src/restclient/anastasis_api_keyshare_lookup.c
+++ b/src/restclient/anastasis_api_keyshare_lookup.c
@@ -258,6 +258,44 @@ handle_keyshare_lookup_finished (void *cls,
     break;
   case MHD_HTTP_TOO_MANY_REQUESTS:
     kdd.status = ANASTASIS_KSD_RATE_LIMIT_EXCEEDED;
+    {
+      struct GNUNET_JSON_Specification spec[] = {
+        GNUNET_JSON_spec_uint32 (
+          "request_limit",
+          &kdd.details.rate_limit_exceeded.request_limit),
+        GNUNET_JSON_spec_relative_time (
+          "request_frequency",
+          &kdd.details.rate_limit_exceeded.request_frequency),
+        GNUNET_JSON_spec_end ()
+      };
+      json_t *reply;
+
+      reply = json_loadb (data,
+                          data_size,
+                          JSON_REJECT_DUPLICATES,
+                          NULL);
+      if (NULL == reply)
+      {
+        GNUNET_break_op (0);
+        kdd.status = ANASTASIS_KSD_SERVER_ERROR;
+        kdd.details.server_failure.ec = TALER_EC_GENERIC_INVALID_RESPONSE;
+        kdd.details.server_failure.http_status = response_code;
+        break;
+      }
+      if (GNUNET_OK !=
+          GNUNET_JSON_parse (reply,
+                             spec,
+                             NULL, NULL))
+      {
+        GNUNET_break_op (0);
+        kdd.status = ANASTASIS_KSD_SERVER_ERROR;
+        kdd.details.server_failure.ec = TALER_JSON_get_error_code (reply);
+        kdd.details.server_failure.http_status = response_code;
+        json_decref (reply);
+        break;
+      }
+      json_decref (reply);
+    }
     break;
   case MHD_HTTP_INTERNAL_SERVER_ERROR:
     /* Server had an internal issue; we should retry, but this API

-- 
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]