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