summaryrefslogtreecommitdiff
path: root/src/extensions/age_restriction/age_restriction.c
diff options
context:
space:
mode:
Diffstat (limited to 'src/extensions/age_restriction/age_restriction.c')
-rw-r--r--src/extensions/age_restriction/age_restriction.c256
1 files changed, 256 insertions, 0 deletions
diff --git a/src/extensions/age_restriction/age_restriction.c b/src/extensions/age_restriction/age_restriction.c
new file mode 100644
index 000000000..08b598d50
--- /dev/null
+++ b/src/extensions/age_restriction/age_restriction.c
@@ -0,0 +1,256 @@
+/*
+ This file is part of TALER
+ Copyright (C) 2021-2022 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/>
+ */
+/**
+ * @file age_restriction.c
+ * @brief Utility functions regarding age restriction
+ * @author Özgür Kesim
+ */
+#include "platform.h"
+#include "taler_util.h"
+#include "taler_extensions.h"
+#include "stdint.h"
+
+/* ==================================================
+ *
+ * Age Restriction TALER_Extension implementation
+ *
+ * ==================================================
+ */
+
+/**
+ * @brief local configuration
+ */
+
+static struct TALER_AgeRestrictionConfig AR_config = {0};
+
+/**
+ * @brief implements the TALER_Extension.disable interface.
+ *
+ * @param ext Pointer to the current extension
+ */
+static void
+age_restriction_disable (
+ struct TALER_Extension *ext)
+{
+ if (NULL == ext)
+ return;
+
+ ext->enabled = false;
+ ext->config = NULL;
+
+ AR_config.mask.bits = 0;
+ AR_config.num_groups = 0;
+}
+
+
+/**
+ * @brief implements the TALER_Extension.load_config interface.
+ *
+ * @param ext if NULL, only tests the configuration
+ * @param jconfig the configuration as json
+ */
+static enum GNUNET_GenericReturnValue
+age_restriction_load_config (
+ const json_t *jconfig,
+ struct TALER_Extension *ext)
+{
+ struct TALER_AgeMask mask = {0};
+ enum GNUNET_GenericReturnValue ret;
+
+ ret = TALER_JSON_parse_age_groups (jconfig, &mask);
+ if (GNUNET_OK != ret)
+ return ret;
+
+ /* only testing the parser */
+ if (ext == NULL)
+ return GNUNET_OK;
+
+ if (TALER_Extension_AgeRestriction != ext->type)
+ return GNUNET_SYSERR;
+
+ if (mask.bits > 0)
+ {
+ /* if the mask is not zero, the first bit MUST be set */
+ if (0 == (mask.bits & 1))
+ return GNUNET_SYSERR;
+
+ AR_config.mask.bits = mask.bits;
+ AR_config.num_groups = __builtin_popcount (mask.bits) - 1;
+ }
+
+ ext->config = &AR_config;
+ ext->enabled = true;
+
+ GNUNET_log (GNUNET_ERROR_TYPE_INFO,
+ "loaded new age restriction config with age groups: %s\n",
+ TALER_age_mask_to_string (&mask));
+
+ return GNUNET_OK;
+}
+
+
+/**
+ * @brief implements the TALER_Extension.manifest interface.
+ *
+ * @param ext if NULL, only tests the configuration
+ * @return configuration as json_t* object, maybe NULL
+ */
+static json_t *
+age_restriction_manifest (
+ const struct TALER_Extension *ext)
+{
+ json_t *conf;
+
+ GNUNET_assert (NULL != ext);
+
+ if (NULL == ext->config)
+ {
+ GNUNET_log (GNUNET_ERROR_TYPE_WARNING,
+ "age restriction not configured");
+ return json_null ();
+ }
+
+ conf = GNUNET_JSON_PACK (
+ GNUNET_JSON_pack_string ("age_groups",
+ TALER_age_mask_to_string (&AR_config.mask))
+ );
+ return GNUNET_JSON_PACK (
+ GNUNET_JSON_pack_bool ("critical",
+ ext->critical),
+ GNUNET_JSON_pack_string ("version",
+ ext->version),
+ GNUNET_JSON_pack_object_steal ("config",
+ conf)
+ );
+}
+
+
+/* The extension for age restriction */
+struct TALER_Extension TE_age_restriction = {
+ .type = TALER_Extension_AgeRestriction,
+ .name = "age_restriction",
+ .critical = false,
+ .version = "1",
+ .enabled = false, /* disabled per default */
+ .config = NULL,
+ .disable = &age_restriction_disable,
+ .load_config = &age_restriction_load_config,
+ .manifest = &age_restriction_manifest,
+
+ /* This extension is not a policy extension */
+ .create_policy_details = NULL,
+ .policy_get_handler = NULL,
+ .policy_post_handler = NULL,
+};
+
+
+/**
+ * @brief implements the init() function for GNUNET_PLUGIN_load
+ *
+ * @param arg Pointer to the GNUNET_CONFIGURATION_Handle
+ * @return pointer to TALER_Extension on success or NULL otherwise.
+ */
+void *
+libtaler_extension_age_restriction_init (void *arg)
+{
+ const struct GNUNET_CONFIGURATION_Handle *cfg = arg;
+ char *groups = NULL;
+ struct TALER_AgeMask mask = {0};
+
+ if ((GNUNET_YES !=
+ GNUNET_CONFIGURATION_have_value (cfg,
+ TALER_EXTENSION_SECTION_AGE_RESTRICTION,
+ "ENABLED"))
+ ||
+ (GNUNET_YES !=
+ GNUNET_CONFIGURATION_get_value_yesno (cfg,
+ TALER_EXTENSION_SECTION_AGE_RESTRICTION,
+ "ENABLED")))
+ {
+ GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
+ "[age restriction] no section %s found in configuration\n",
+ TALER_EXTENSION_SECTION_AGE_RESTRICTION);
+
+ return NULL;
+ }
+
+ /* Age restriction is enabled, extract age groups */
+ if ((GNUNET_YES ==
+ GNUNET_CONFIGURATION_have_value (cfg,
+ TALER_EXTENSION_SECTION_AGE_RESTRICTION,
+ "AGE_GROUPS"))
+ &&
+ (GNUNET_YES !=
+ GNUNET_CONFIGURATION_get_value_string (cfg,
+ TALER_EXTENSION_SECTION_AGE_RESTRICTION,
+ "AGE_GROUPS",
+ &groups)))
+ {
+ GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
+ "[age restriction] AGE_GROUPS in %s is not a string\n",
+ TALER_EXTENSION_SECTION_AGE_RESTRICTION);
+
+ return NULL;
+ }
+
+ if (NULL == groups)
+ groups = GNUNET_strdup (TALER_EXTENSION_AGE_RESTRICTION_DEFAULT_AGE_GROUPS);
+
+ if (GNUNET_OK != TALER_parse_age_group_string (groups, &mask))
+ {
+ GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
+ "[age restriction] couldn't parse age groups: '%s'\n",
+ groups);
+ return NULL;
+ }
+
+ AR_config.mask = mask;
+ AR_config.num_groups = __builtin_popcount (mask.bits) - 1; /* no underflow, first bit always set */
+
+ GNUNET_log (GNUNET_ERROR_TYPE_INFO,
+ "[age restriction] setting age mask to %s with #groups: %d\n",
+ TALER_age_mask_to_string (&AR_config.mask),
+ __builtin_popcount (AR_config.mask.bits) - 1);
+
+ TE_age_restriction.config = &AR_config;
+
+ /* Note: we do now have TE_age_restriction_config set, however the extension
+ * is not yet enabled! For age restriction to become active, load_config must
+ * have been called. */
+
+ GNUNET_free (groups);
+ return &TE_age_restriction;
+}
+
+
+/**
+ * @brief implements the done() function for GNUNET_PLUGIN_load
+ *
+ * @param arg unused
+ * @return pointer to TALER_Extension on success or NULL otherwise.
+ */
+void *
+libtaler_extension_age_restriction_done (void *arg)
+{
+ GNUNET_log (GNUNET_ERROR_TYPE_INFO,
+ "[age restriction] disabling and unloading");
+ AR_config.mask.bits = 0;
+ AR_config.num_groups = 0;
+ return NULL;
+}
+
+
+/* end of age_restriction.c */