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