Line data Source code
1 : /*
2 : This file is part of TALER
3 : Copyright (C) 2021-2022 Taler Systems SA
4 :
5 : TALER is free software; you can redistribute it and/or modify it under the
6 : terms of the GNU General Public License as published by the Free Software
7 : Foundation; either version 3, or (at your option) any later version.
8 :
9 : TALER is distributed in the hope that it will be useful, but WITHOUT ANY
10 : WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR
11 : A PARTICULAR PURPOSE. See the GNU General Public License for more details.
12 :
13 : You should have received a copy of the GNU General Public License along with
14 : TALER; see the file COPYING. If not, see <http://www.gnu.org/licenses/>
15 : */
16 : /**
17 : * @file age_restriction.c
18 : * @brief Utility functions regarding age restriction
19 : * @author Özgür Kesim
20 : */
21 : #include "platform.h"
22 : #include "taler_util.h"
23 : #include "taler_extensions.h"
24 : #include "stdint.h"
25 :
26 : /* ==================================================
27 : *
28 : * Age Restriction TALER_Extension implementation
29 : *
30 : * ==================================================
31 : */
32 :
33 : /**
34 : * @brief local configuration
35 : */
36 :
37 : static struct TALER_AgeRestrictionConfig AR_config = {0};
38 :
39 : /**
40 : * @brief implements the TALER_Extension.disable interface.
41 : *
42 : * @param ext Pointer to the current extension
43 : */
44 : static void
45 0 : age_restriction_disable (
46 : struct TALER_Extension *ext)
47 : {
48 0 : if (NULL == ext)
49 0 : return;
50 :
51 0 : ext->enabled = false;
52 0 : ext->config = NULL;
53 :
54 0 : AR_config.mask.bits = 0;
55 0 : AR_config.num_groups = 0;
56 : }
57 :
58 :
59 : /**
60 : * @brief implements the TALER_Extension.load_config interface.
61 : *
62 : * @param ext if NULL, only tests the configuration
63 : * @param jconfig the configuration as json
64 : */
65 : static enum GNUNET_GenericReturnValue
66 11 : age_restriction_load_config (
67 : const json_t *jconfig,
68 : struct TALER_Extension *ext)
69 : {
70 11 : struct TALER_AgeMask mask = {0};
71 : enum GNUNET_GenericReturnValue ret;
72 :
73 11 : ret = TALER_JSON_parse_age_groups (jconfig, &mask);
74 11 : if (GNUNET_OK != ret)
75 0 : return ret;
76 :
77 : /* only testing the parser */
78 11 : if (ext == NULL)
79 0 : return GNUNET_OK;
80 :
81 11 : if (TALER_Extension_AgeRestriction != ext->type)
82 0 : return GNUNET_SYSERR;
83 :
84 11 : if (mask.bits > 0)
85 : {
86 : /* if the mask is not zero, the first bit MUST be set */
87 11 : if (0 == (mask.bits & 1))
88 0 : return GNUNET_SYSERR;
89 :
90 11 : AR_config.mask.bits = mask.bits;
91 11 : AR_config.num_groups = __builtin_popcount (mask.bits) - 1;
92 : }
93 :
94 11 : ext->config = &AR_config;
95 11 : ext->enabled = true;
96 :
97 11 : GNUNET_log (GNUNET_ERROR_TYPE_INFO,
98 : "loaded new age restriction config with age groups: %s\n",
99 : TALER_age_mask_to_string (&mask));
100 :
101 11 : return GNUNET_OK;
102 : }
103 :
104 :
105 : /**
106 : * @brief implements the TALER_Extension.manifest interface.
107 : *
108 : * @param ext if NULL, only tests the configuration
109 : * @return configuration as json_t* object, maybe NULL
110 : */
111 : static json_t *
112 651 : age_restriction_manifest (
113 : const struct TALER_Extension *ext)
114 : {
115 : json_t *conf;
116 :
117 651 : GNUNET_assert (NULL != ext);
118 :
119 651 : if (NULL == ext->config)
120 : {
121 0 : GNUNET_log (GNUNET_ERROR_TYPE_WARNING,
122 : "age restriction not configured");
123 0 : return json_null ();
124 : }
125 :
126 651 : conf = GNUNET_JSON_PACK (
127 : GNUNET_JSON_pack_string ("age_groups",
128 : TALER_age_mask_to_string (&AR_config.mask))
129 : );
130 651 : return GNUNET_JSON_PACK (
131 : GNUNET_JSON_pack_bool ("critical",
132 : ext->critical),
133 : GNUNET_JSON_pack_string ("version",
134 : ext->version),
135 : GNUNET_JSON_pack_object_steal ("config",
136 : conf)
137 : );
138 : }
139 :
140 :
141 : /* The extension for age restriction */
142 : struct TALER_Extension TE_age_restriction = {
143 : .type = TALER_Extension_AgeRestriction,
144 : .name = "age_restriction",
145 : .critical = false,
146 : .version = "1",
147 : .enabled = false, /* disabled per default */
148 : .config = NULL,
149 : .disable = &age_restriction_disable,
150 : .load_config = &age_restriction_load_config,
151 : .manifest = &age_restriction_manifest,
152 :
153 : /* This extension is not a policy extension */
154 : .create_policy_details = NULL,
155 : .policy_get_handler = NULL,
156 : .policy_post_handler = NULL,
157 : };
158 :
159 :
160 : /**
161 : * @brief implements the init() function for GNUNET_PLUGIN_load
162 : *
163 : * @param arg Pointer to the GNUNET_CONFIGURATION_Handle
164 : * @return pointer to TALER_Extension on success or NULL otherwise.
165 : */
166 : void *
167 : libtaler_extension_age_restriction_init (void *arg);
168 :
169 : /* Declaration used to squash compiler warning */
170 : void *
171 50 : libtaler_extension_age_restriction_init (void *arg)
172 : {
173 50 : const struct GNUNET_CONFIGURATION_Handle *cfg = arg;
174 50 : char *groups = NULL;
175 50 : struct TALER_AgeMask mask = {0};
176 :
177 50 : if ((GNUNET_YES !=
178 50 : GNUNET_CONFIGURATION_have_value (cfg,
179 : TALER_EXTENSION_SECTION_AGE_RESTRICTION,
180 : "ENABLED"))
181 50 : ||
182 : (GNUNET_YES !=
183 50 : GNUNET_CONFIGURATION_get_value_yesno (cfg,
184 : TALER_EXTENSION_SECTION_AGE_RESTRICTION,
185 : "ENABLED")))
186 : {
187 0 : GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
188 : "[age restriction] no section %s found in configuration\n",
189 : TALER_EXTENSION_SECTION_AGE_RESTRICTION);
190 :
191 0 : return NULL;
192 : }
193 :
194 : /* Age restriction is enabled, extract age groups */
195 50 : if ((GNUNET_YES ==
196 50 : GNUNET_CONFIGURATION_have_value (cfg,
197 : TALER_EXTENSION_SECTION_AGE_RESTRICTION,
198 : "AGE_GROUPS"))
199 0 : &&
200 : (GNUNET_YES !=
201 0 : GNUNET_CONFIGURATION_get_value_string (cfg,
202 : TALER_EXTENSION_SECTION_AGE_RESTRICTION,
203 : "AGE_GROUPS",
204 : &groups)))
205 : {
206 0 : GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
207 : "[age restriction] AGE_GROUPS in %s is not a string\n",
208 : TALER_EXTENSION_SECTION_AGE_RESTRICTION);
209 :
210 0 : return NULL;
211 : }
212 :
213 50 : if (NULL == groups)
214 50 : groups = GNUNET_strdup (TALER_EXTENSION_AGE_RESTRICTION_DEFAULT_AGE_GROUPS);
215 :
216 50 : if (GNUNET_OK != TALER_parse_age_group_string (groups, &mask))
217 : {
218 0 : GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
219 : "[age restriction] couldn't parse age groups: '%s'\n",
220 : groups);
221 0 : return NULL;
222 : }
223 :
224 50 : AR_config.mask = mask;
225 50 : AR_config.num_groups = __builtin_popcount (mask.bits) - 1; /* no underflow, first bit always set */
226 :
227 50 : GNUNET_log (GNUNET_ERROR_TYPE_INFO,
228 : "[age restriction] setting age mask to %s with #groups: %d\n",
229 : TALER_age_mask_to_string (&AR_config.mask),
230 : __builtin_popcount (AR_config.mask.bits) - 1);
231 :
232 50 : TE_age_restriction.config = &AR_config;
233 :
234 : /* Note: we do now have TE_age_restriction_config set, however the extension
235 : * is not yet enabled! For age restriction to become active, load_config must
236 : * have been called. */
237 :
238 50 : GNUNET_free (groups);
239 50 : return &TE_age_restriction;
240 : }
241 :
242 :
243 : /**
244 : * @brief implements the done() function for GNUNET_PLUGIN_load
245 : *
246 : * @param arg unused
247 : * @return pointer to TALER_Extension on success or NULL otherwise.
248 : */
249 : void *
250 : libtaler_extension_age_restriction_done (void *arg);
251 :
252 : /* Declaration used to squash compiler warning */
253 : void *
254 0 : libtaler_extension_age_restriction_done (void *arg)
255 : {
256 0 : GNUNET_log (GNUNET_ERROR_TYPE_INFO,
257 : "[age restriction] disabling and unloading");
258 0 : AR_config.mask.bits = 0;
259 0 : AR_config.num_groups = 0;
260 0 : return NULL;
261 : }
262 :
263 :
264 : /* end of age_restriction.c */
|