age_restriction.c (7450B)
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/platform.h" 22 #include "taler/taler_util.h" 23 #include "taler/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 age_restriction_disable ( 46 struct TALER_Extension *ext) 47 { 48 if (NULL == ext) 49 return; 50 51 ext->enabled = false; 52 ext->config = NULL; 53 54 AR_config.mask.bits = 0; 55 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 age_restriction_load_config ( 67 const json_t *jconfig, 68 struct TALER_Extension *ext) 69 { 70 struct TALER_AgeMask mask = {0}; 71 enum GNUNET_GenericReturnValue ret; 72 73 ret = TALER_JSON_parse_age_groups (jconfig, &mask); 74 if (GNUNET_OK != ret) 75 return ret; 76 77 /* only testing the parser */ 78 if (ext == NULL) 79 return GNUNET_OK; 80 81 if (TALER_Extension_AgeRestriction != ext->type) 82 return GNUNET_SYSERR; 83 84 if (mask.bits > 0) 85 { 86 /* if the mask is not zero, the first bit MUST be set */ 87 if (0 == (mask.bits & 1)) 88 return GNUNET_SYSERR; 89 90 AR_config.mask.bits = mask.bits; 91 AR_config.num_groups = __builtin_popcount (mask.bits) - 1; 92 } 93 94 ext->config = &AR_config; 95 ext->enabled = true; 96 97 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 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 age_restriction_manifest ( 113 const struct TALER_Extension *ext) 114 { 115 json_t *conf; 116 117 GNUNET_assert (NULL != ext); 118 119 if (NULL == ext->config) 120 { 121 GNUNET_log (GNUNET_ERROR_TYPE_WARNING, 122 "age restriction not configured"); 123 return json_null (); 124 } 125 126 conf = GNUNET_JSON_PACK ( 127 GNUNET_JSON_pack_string ("age_groups", 128 TALER_age_mask_to_string (&AR_config.mask)) 129 ); 130 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 libtaler_extension_age_restriction_init (void *arg) 172 { 173 const struct GNUNET_CONFIGURATION_Handle *cfg = arg; 174 char *groups = NULL; 175 struct TALER_AgeMask mask = {0}; 176 177 if ((GNUNET_YES != 178 GNUNET_CONFIGURATION_have_value (cfg, 179 TALER_EXTENSION_SECTION_AGE_RESTRICTION, 180 "ENABLED")) 181 || 182 (GNUNET_YES != 183 GNUNET_CONFIGURATION_get_value_yesno (cfg, 184 TALER_EXTENSION_SECTION_AGE_RESTRICTION, 185 "ENABLED"))) 186 { 187 GNUNET_log (GNUNET_ERROR_TYPE_ERROR, 188 "[age restriction] no section %s found in configuration\n", 189 TALER_EXTENSION_SECTION_AGE_RESTRICTION); 190 191 return NULL; 192 } 193 194 /* Age restriction is enabled, extract age groups */ 195 if ((GNUNET_YES == 196 GNUNET_CONFIGURATION_have_value (cfg, 197 TALER_EXTENSION_SECTION_AGE_RESTRICTION, 198 "AGE_GROUPS")) 199 && 200 (GNUNET_YES != 201 GNUNET_CONFIGURATION_get_value_string (cfg, 202 TALER_EXTENSION_SECTION_AGE_RESTRICTION, 203 "AGE_GROUPS", 204 &groups))) 205 { 206 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 return NULL; 211 } 212 213 if (NULL == groups) 214 groups = GNUNET_strdup (TALER_EXTENSION_AGE_RESTRICTION_DEFAULT_AGE_GROUPS); 215 216 if (GNUNET_OK != TALER_parse_age_group_string (groups, &mask)) 217 { 218 GNUNET_log (GNUNET_ERROR_TYPE_ERROR, 219 "[age restriction] couldn't parse age groups: '%s'\n", 220 groups); 221 return NULL; 222 } 223 224 AR_config.mask = mask; 225 AR_config.num_groups = __builtin_popcount (mask.bits) - 1; /* no underflow, first bit always set */ 226 227 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 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 GNUNET_free (groups); 239 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 libtaler_extension_age_restriction_done (void *arg) 255 { 256 GNUNET_log (GNUNET_ERROR_TYPE_INFO, 257 "[age restriction] disabling and unloading"); 258 AR_config.mask.bits = 0; 259 AR_config.num_groups = 0; 260 return NULL; 261 } 262 263 264 /* end of age_restriction.c */