LCOV - code coverage report
Current view: top level - extensions - extensions.c (source / functions) Hit Total Coverage
Test: GNU Taler exchange coverage report Lines: 12 109 11.0 %
Date: 2022-08-25 06:15:09 Functions: 1 11 9.1 %
Legend: Lines: hit not hit

          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 extensions.c
      18             :  * @brief Utility functions for extensions
      19             :  * @author Özgür Kesim
      20             :  */
      21             : #include "platform.h"
      22             : #include "taler_util.h"
      23             : #include "taler_signatures.h"
      24             : #include "taler_extensions.h"
      25             : #include "stdint.h"
      26             : 
      27             : 
      28             : /* head of the list of all registered extensions */
      29             : static struct TALER_Extension *TE_extensions = NULL;
      30             : 
      31             : 
      32             : const struct TALER_Extension *
      33           0 : TALER_extensions_get_head ()
      34             : {
      35           0 :   return TE_extensions;
      36             : }
      37             : 
      38             : 
      39             : enum GNUNET_GenericReturnValue
      40           4 : TALER_extensions_add (
      41             :   struct TALER_Extension *extension)
      42             : {
      43             :   /* Sanity checks */
      44           4 :   if ((NULL == extension) ||
      45           4 :       (NULL == extension->name) ||
      46           4 :       (NULL == extension->version) ||
      47           4 :       (NULL == extension->disable) ||
      48           4 :       (NULL == extension->test_json_config) ||
      49           4 :       (NULL == extension->load_json_config) ||
      50           4 :       (NULL == extension->config_to_json) ||
      51           4 :       (NULL == extension->load_taler_config))
      52             :   {
      53           0 :     GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
      54             :                 "invalid extension\n");
      55           0 :     return GNUNET_SYSERR;
      56             :   }
      57             : 
      58           4 :   if (NULL == TE_extensions) /* first extension ?*/
      59           4 :     TE_extensions = (struct TALER_Extension *) extension;
      60             :   else
      61             :   {
      62             :     struct TALER_Extension *iter;
      63             :     struct TALER_Extension *last;
      64             : 
      65             :     /* Check for collisions */
      66           0 :     for (iter = TE_extensions; NULL != iter; iter = iter->next)
      67             :     {
      68           0 :       last = iter;
      69           0 :       if (extension->type == iter->type ||
      70           0 :           0 == strcasecmp (extension->name,
      71           0 :                            iter->name))
      72             :       {
      73           0 :         GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
      74             :                     "extension collision for `%s'\n",
      75             :                     extension->name);
      76           0 :         return GNUNET_NO;
      77             :       }
      78             :     }
      79             : 
      80             :     /* No collisions found, so add this extension to the list */
      81           0 :     last->next = extension;
      82             :   }
      83             : 
      84           4 :   return GNUNET_OK;
      85             : }
      86             : 
      87             : 
      88             : const struct TALER_Extension *
      89           0 : TALER_extensions_get_by_type (
      90             :   enum TALER_Extension_Type type)
      91             : {
      92           0 :   for (const struct TALER_Extension *it = TE_extensions;
      93             :        NULL != it;
      94           0 :        it = it->next)
      95             :   {
      96           0 :     if (it->type == type)
      97           0 :       return it;
      98             :   }
      99             : 
     100             :   /* No extension found. */
     101           0 :   return NULL;
     102             : }
     103             : 
     104             : 
     105             : bool
     106           0 : TALER_extensions_is_enabled_type (
     107             :   enum TALER_Extension_Type type)
     108             : {
     109             :   const struct TALER_Extension *ext =
     110           0 :     TALER_extensions_get_by_type (type);
     111             : 
     112           0 :   return (NULL != ext &&
     113           0 :           TALER_extensions_is_enabled (ext));
     114             : }
     115             : 
     116             : 
     117             : const struct TALER_Extension *
     118           0 : TALER_extensions_get_by_name (
     119             :   const char *name)
     120             : {
     121           0 :   for (const struct TALER_Extension *it = TE_extensions;
     122             :        NULL != it;
     123           0 :        it = it->next)
     124             :   {
     125           0 :     if (0 == strcasecmp (name, it->name))
     126           0 :       return it;
     127             :   }
     128             :   /* No extension found. */
     129           0 :   return NULL;
     130             : }
     131             : 
     132             : 
     133             : enum GNUNET_GenericReturnValue
     134           0 : TALER_extensions_verify_json_config_signature (
     135             :   json_t *extensions,
     136             :   struct TALER_MasterSignatureP *extensions_sig,
     137             :   struct TALER_MasterPublicKeyP *master_pub)
     138             : {
     139             :   struct TALER_ExtensionConfigHashP h_config;
     140             : 
     141           0 :   if (GNUNET_OK !=
     142           0 :       TALER_JSON_extensions_config_hash (extensions,
     143             :                                          &h_config))
     144           0 :     return GNUNET_SYSERR;
     145           0 :   if (GNUNET_OK !=
     146           0 :       TALER_exchange_offline_extension_config_hash_verify (
     147             :         &h_config,
     148             :         master_pub,
     149             :         extensions_sig))
     150           0 :     return GNUNET_NO;
     151           0 :   return GNUNET_OK;
     152             : }
     153             : 
     154             : 
     155             : /*
     156             :  * Closure used in TALER_extensions_load_taler_config during call to
     157             :  * GNUNET_CONFIGURATION_iterate_sections with configure_extension.
     158             :  */
     159             : struct LoadConfClosure
     160             : {
     161             :   const struct GNUNET_CONFIGURATION_Handle *cfg;
     162             :   enum GNUNET_GenericReturnValue error;
     163             : };
     164             : 
     165             : 
     166             : /*
     167             :  * Used in TALER_extensions_load_taler_config during call to
     168             :  * GNUNET_CONFIGURATION_iterate_sections to load the configuration
     169             :  * of supported extensions.
     170             :  *
     171             :  * @param cls Closure of type LoadConfClosure
     172             :  * @param section name of the current section
     173             :  */
     174             : static void
     175           0 : configure_extension (
     176             :   void *cls,
     177             :   const char *section)
     178             : {
     179           0 :   struct LoadConfClosure *col = cls;
     180             :   const char *name;
     181             :   const struct TALER_Extension *extension;
     182             : 
     183           0 :   if (GNUNET_OK != col->error)
     184           0 :     return;
     185             : 
     186           0 :   if (0 != strncasecmp (section,
     187             :                         TALER_EXTENSION_SECTION_PREFIX,
     188             :                         sizeof(TALER_EXTENSION_SECTION_PREFIX) - 1))
     189           0 :     return;
     190             : 
     191           0 :   name = section + sizeof(TALER_EXTENSION_SECTION_PREFIX) - 1;
     192             : 
     193           0 :   if (NULL ==
     194           0 :       (extension = TALER_extensions_get_by_name (name)))
     195             :   {
     196           0 :     GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
     197             :                 "Unsupported extension `%s` (section [%s]).\n", name,
     198             :                 section);
     199           0 :     col->error = GNUNET_SYSERR;
     200           0 :     return;
     201             :   }
     202             : 
     203           0 :   if (GNUNET_OK !=
     204           0 :       extension->load_taler_config (
     205             :         (struct TALER_Extension *) extension,
     206             :         col->cfg))
     207             :   {
     208           0 :     GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
     209             :                 "Couldn't parse configuration for extension `%s` (section [%s]).\n",
     210             :                 name,
     211             :                 section);
     212           0 :     col->error = GNUNET_SYSERR;
     213           0 :     return;
     214             :   }
     215             : }
     216             : 
     217             : 
     218             : enum GNUNET_GenericReturnValue
     219           0 : TALER_extensions_load_taler_config (
     220             :   const struct GNUNET_CONFIGURATION_Handle *cfg)
     221             : {
     222           0 :   struct LoadConfClosure col = {
     223             :     .cfg = cfg,
     224             :     .error = GNUNET_OK,
     225             :   };
     226             : 
     227           0 :   GNUNET_CONFIGURATION_iterate_sections (cfg,
     228             :                                          &configure_extension,
     229             :                                          &col);
     230           0 :   return col.error;
     231             : }
     232             : 
     233             : 
     234             : enum GNUNET_GenericReturnValue
     235           0 : TALER_extensions_is_json_config (
     236             :   json_t *obj,
     237             :   int *critical,
     238             :   const char **version,
     239             :   json_t **config)
     240             : {
     241             :   enum GNUNET_GenericReturnValue ret;
     242             :   json_t *cfg;
     243             :   struct GNUNET_JSON_Specification spec[] = {
     244           0 :     GNUNET_JSON_spec_boolean ("critical",
     245             :                               critical),
     246           0 :     GNUNET_JSON_spec_string ("version",
     247             :                              version),
     248           0 :     GNUNET_JSON_spec_json ("config",
     249             :                            &cfg),
     250           0 :     GNUNET_JSON_spec_end ()
     251             :   };
     252             : 
     253           0 :   if (GNUNET_OK !=
     254           0 :       (ret = GNUNET_JSON_parse (obj,
     255             :                                 spec,
     256             :                                 NULL,
     257             :                                 NULL)))
     258           0 :     return ret;
     259             : 
     260           0 :   *config = json_copy (cfg);
     261           0 :   GNUNET_JSON_parse_free (spec);
     262             : 
     263           0 :   return GNUNET_OK;
     264             : }
     265             : 
     266             : 
     267             : enum GNUNET_GenericReturnValue
     268           0 : TALER_extensions_load_json_config (
     269             :   json_t *extensions)
     270             : {
     271             :   const char*name;
     272             :   json_t *blob;
     273             : 
     274           0 :   GNUNET_assert (NULL != extensions);
     275           0 :   GNUNET_assert (json_is_object (extensions));
     276             : 
     277           0 :   json_object_foreach (extensions, name, blob)
     278             :   {
     279             :     int critical;
     280             :     const char *version;
     281             :     json_t *config;
     282             :     const struct TALER_Extension *extension =
     283           0 :       TALER_extensions_get_by_name (name);
     284             : 
     285           0 :     if (NULL == extension)
     286             :     {
     287           0 :       GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
     288             :                   "no such extension: %s\n", name);
     289           0 :       return GNUNET_SYSERR;
     290             :     }
     291             : 
     292             :     /* load and verify criticality, version, etc. */
     293           0 :     if (GNUNET_OK !=
     294           0 :         TALER_extensions_is_json_config (
     295             :           blob, &critical, &version, &config))
     296           0 :       return GNUNET_SYSERR;
     297             : 
     298           0 :     if (critical != extension->critical
     299           0 :         || 0 != strcmp (version, extension->version) // TODO: libtool compare?
     300           0 :         || NULL == config
     301           0 :         || GNUNET_OK != extension->test_json_config (config))
     302           0 :       return GNUNET_SYSERR;
     303             : 
     304             :     /* This _should_ work now */
     305           0 :     if (GNUNET_OK !=
     306           0 :         extension->load_json_config ((struct TALER_Extension *) extension,
     307             :                                      config))
     308           0 :       return GNUNET_SYSERR;
     309             :   }
     310             : 
     311             :   /* make sure to disable all extensions that weren't mentioned in the json */
     312           0 :   for (const struct TALER_Extension *it = TALER_extensions_get_head ();
     313             :        NULL != it;
     314           0 :        it = it->next)
     315             :   {
     316           0 :     if (NULL == json_object_get (extensions, it->name))
     317           0 :       it->disable ((struct TALER_Extension *) it);
     318             :   }
     319             : 
     320           0 :   return GNUNET_OK;
     321             : }
     322             : 
     323             : 
     324             : bool
     325           0 : TALER_extensions_age_restriction_is_enabled ()
     326             : {
     327             :   const struct TALER_Extension *age =
     328           0 :     TALER_extensions_get_by_type (TALER_Extension_AgeRestriction);
     329             : 
     330           0 :   return (NULL != age &&
     331           0 :           NULL != age->config_json &&
     332           0 :           TALER_extensions_age_restriction_is_configured ());
     333             : }
     334             : 
     335             : 
     336             : /* end of extensions.c */

Generated by: LCOV version 1.14