commit 690ce695415810012382f371fb11ab5f872bdeac
parent 68fa678c29f4fe74a12464998518a5ff59d2adc4
Author: Christian Grothoff <christian@grothoff.org>
Date: Tue, 5 Mar 2024 22:47:51 +0100
implement #8556
Diffstat:
4 files changed, 117 insertions(+), 0 deletions(-)
diff --git a/src/challenger/challenger-httpd.c b/src/challenger/challenger-httpd.c
@@ -95,6 +95,16 @@ struct GNUNET_TIME_Relative CH_validation_expiration;
struct GNUNET_TIME_Relative CH_pin_retransmission_frequency;
/**
+ * JSON object with key-object pairs mapping address keys (from the
+ * form) to an object with a field "regex" containing a regular
+ * expressions expressing restrictions on values for the address and a
+ * field "hint" (and possibly "hint_i18n") containing a human-readable
+ * message explaining the restriction. Missing map entries indicate
+ * that the input is unrestricted.
+ */
+json_t *CH_restrictions;
+
+/**
* Type of addresses this challenger validates.
*/
char *CH_address_type;
@@ -593,6 +603,31 @@ run (void *cls,
"ADDRESS_TYPE");
return;
}
+ {
+ char *restrictions;
+
+ if (GNUNET_OK ==
+ GNUNET_CONFIGURATION_get_value_string (config,
+ "CHALLENGER",
+ "ADDRESS_RESTRICTIONS",
+ &restrictions))
+ {
+ json_error_t err;
+
+ CH_restrictions = json_loads (restrictions,
+ JSON_REJECT_DUPLICATES,
+ &err);
+ GNUNET_free (restrictions);
+ if (NULL == CH_restrictions)
+ {
+ GNUNET_log_config_invalid (GNUNET_ERROR_TYPE_ERROR,
+ "CHALLENGER",
+ "ADDRESS_RESTRICTIONS",
+ err.text);
+ return;
+ }
+ }
+ }
global_ret = EXIT_NOTCONFIGURED;
GNUNET_SCHEDULER_add_shutdown (&do_shutdown,
diff --git a/src/challenger/challenger-httpd.h b/src/challenger/challenger-httpd.h
@@ -157,6 +157,16 @@ extern struct GNUNET_TIME_Relative CH_validation_expiration;
extern struct GNUNET_TIME_Relative CH_pin_retransmission_frequency;
/**
+ * JSON object with key-object pairs mapping address keys (from the
+ * form) to an object with a field "regex" containing a regular
+ * expressions expressing restrictions on values for the address and a
+ * field "hint" (and possibly "hint_i18n") containing a human-readable
+ * message explaining the restriction. Missing map entries indicate
+ * that the input is unrestricted.
+ */
+extern json_t *CH_restrictions;
+
+/**
* Kick MHD to run now, to be called after MHD_resume_connection().
* Basically, we need to explicitly resume MHD's event loop whenever
* we made progress serving a request. This function re-schedules
diff --git a/src/challenger/challenger-httpd_authorize.c b/src/challenger/challenger-httpd_authorize.c
@@ -207,6 +207,8 @@ CH_handler_authorize (struct CH_HandlerContext *hc,
"enter-%s-form",
CH_address_type);
args = GNUNET_JSON_PACK (
+ GNUNET_JSON_pack_object_incref ("restrictions",
+ CH_restrictions),
GNUNET_JSON_pack_bool ("fix_address",
0 == address_attempts_left),
GNUNET_JSON_pack_string ("nonce",
diff --git a/src/challenger/challenger-httpd_challenge.c b/src/challenger/challenger-httpd_challenge.c
@@ -20,6 +20,7 @@
*/
#include "platform.h"
#include "challenger-httpd.h"
+#include <regex.h>
#include <gnunet/gnunet_util_lib.h>
#include "challenger-httpd_challenge.h"
#include <taler/taler_json_lib.h>
@@ -429,6 +430,61 @@ post_iter (void *cls,
}
+/**
+ * Check if the given address satisfies our restrictions.
+ *
+ * @param address address data provided by the client
+ * @return NULL on success, otherwise the key that failed
+ */
+static const char *
+check_restrictions (const json_t *address)
+{
+ const char *key;
+ const json_t *val;
+
+ json_object_foreach ((json_t *) address, key, val)
+ {
+ const char *str = json_string_value (val);
+ const char *regex = json_string_value (
+ json_object_get (
+ json_object_get (CH_restrictions,
+ key),
+ "regex"));
+ regex_t re;
+
+ if (NULL == str)
+ return key;
+ if (NULL == regex)
+ continue;
+ if (0 != regcomp (&re,
+ regex,
+ REG_EXTENDED))
+ {
+ GNUNET_log (GNUNET_ERROR_TYPE_WARNING,
+ "Invalid regex `%s' address restriction specified for `%s'\n",
+ regex,
+ key);
+ continue;
+ }
+ if (0 != regexec (&re,
+ str,
+ 0,
+ NULL,
+ 0))
+ {
+ GNUNET_log (GNUNET_ERROR_TYPE_WARNING,
+ "Client input `%s' rejected as it does not match address restriction `%s' specified for `%s'\n",
+ str,
+ regex,
+ key);
+ return key;
+ }
+ regfree (&re);
+ }
+ return NULL;
+}
+
+
MHD_RESULT
CH_handler_challenge (struct CH_HandlerContext *hc,
const char *upload_data,
@@ -533,6 +589,20 @@ CH_handler_challenge (struct CH_HandlerContext *hc,
address);
free (address);
}
+ {
+ const char *bad_field;
+
+ bad_field = check_restrictions (bc->address);
+ if (NULL != bad_field)
+ {
+ GNUNET_break_op (0);
+ return TALER_TEMPLATING_reply_error (hc->connection,
+ "invalid-request",
+ MHD_HTTP_BAD_REQUEST,
+ TALER_EC_GENERIC_PARAMETER_MALFORMED,
+ bad_field);
+ }
+ }
if (! bc->db_finished)
{
enum GNUNET_DB_QueryStatus qs;