exchange/src/extensions/extensions.c

347 lines
8.4 KiB
C
Raw Normal View History

/*
This file is part of TALER
Copyright (C) 2021-2022 Taler Systems SA
TALER is free software; you can redistribute it and/or modify it under the
terms of the GNU General Public License as published by the Free Software
Foundation; either version 3, or (at your option) any later version.
TALER is distributed in the hope that it will be useful, but WITHOUT ANY
WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR
A PARTICULAR PURPOSE. See the GNU General Public License for more details.
You should have received a copy of the GNU General Public License along with
TALER; see the file COPYING. If not, see <http://www.gnu.org/licenses/>
*/
/**
* @file extensions.c
* @brief Utility functions for extensions
* @author Özgür Kesim
*/
#include "platform.h"
#include "taler_util.h"
#include "taler_signatures.h"
#include "taler_extensions.h"
#include "stdint.h"
/* head of the list of all registered extensions */
2022-03-21 08:35:19 +01:00
// FIXME: remove unnecessary initializers.
// FIXME: remove unncessary "_" prefix.
static struct TALER_Extension *_extensions = NULL;
static bool _initialized = false;
2022-03-21 08:35:19 +01:00
void
TALER_extensions_init ()
{
2022-03-21 08:35:19 +01:00
// FIXME: a bit ugly. Why not have the age_restriction
// module have an initializer that registers itself here?
extern struct TALER_Extension _extension_age_restriction;
if (! _initialized)
_extensions = &_extension_age_restriction;
_initialized = true;
}
const struct TALER_Extension *
TALER_extensions_get_head ()
{
return _extensions;
}
2022-03-21 08:35:19 +01:00
// FIXME: 'new' is a C++ keyword, to NOT use for variable names
enum GNUNET_GenericReturnValue
TALER_extensions_add (
const struct TALER_Extension *new)
{
2022-03-21 08:35:19 +01:00
struct TALER_Extension *ext; // FIXME: limit scope to for() loop
if (_initialized)
return GNUNET_SYSERR;
GNUNET_assert (NULL != _extensions);
/* Sanity checks */
2022-03-21 08:35:19 +01:00
// FIXME: bracket all expressions
if (NULL == new ||
NULL == new->name ||
NULL == new->version ||
NULL == new->disable ||
NULL == new->test_json_config ||
NULL == new->load_json_config ||
NULL == new->config_to_json ||
NULL == new->load_taler_config ||
NULL == new->next)
{
2022-03-21 08:35:19 +01:00
GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
"invalid extension\n");
return GNUNET_SYSERR;
}
/* Check for collisions */
for (ext = _extensions; NULL != ext; ext = ext->next)
{
if (new->type == ext->type ||
2022-03-21 08:35:19 +01:00
0 == strcmp (new->name,
ext->name))
{
2022-03-21 08:35:19 +01:00
GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
"extension collision for `%s'\n",
new->name);
return GNUNET_NO;
}
}
/* No collisions found, so add this extension to the list */
ext->next = (struct TALER_Extension *) new;
return GNUNET_OK;
}
const struct TALER_Extension *
TALER_extensions_get_by_type (
enum TALER_Extension_Type type)
{
for (const struct TALER_Extension *it = _extensions;
NULL != it;
it = it->next)
{
if (it->type == type)
return it;
}
/* No extension found. */
return NULL;
}
bool
TALER_extensions_is_enabled_type (
enum TALER_Extension_Type type)
{
const struct TALER_Extension *ext =
TALER_extensions_get_by_type (type);
return (NULL != ext &&
TALER_extensions_is_enabled (ext));
}
const struct TALER_Extension *
TALER_extensions_get_by_name (
const char *name)
{
for (const struct TALER_Extension *it = _extensions;
NULL != it;
it = it->next)
{
2022-04-19 18:37:48 +02:00
if (0 == strcasecmp (name, it->name))
return it;
}
/* No extension found. */
return NULL;
}
enum GNUNET_GenericReturnValue
TALER_extensions_verify_json_config_signature (
json_t *extensions,
struct TALER_MasterSignatureP *extensions_sig,
struct TALER_MasterPublicKeyP *master_pub)
{
struct TALER_ExtensionConfigHashP h_config;
if (GNUNET_OK !=
2022-03-21 08:35:19 +01:00
TALER_JSON_extensions_config_hash (extensions,
&h_config))
return GNUNET_SYSERR;
2022-03-21 08:35:19 +01:00
if (GNUNET_OK !=
TALER_exchange_offline_extension_config_hash_verify (
&h_config,
master_pub,
extensions_sig))
return GNUNET_NO;
return GNUNET_OK;
}
2022-03-21 08:35:19 +01:00
// FIXME: use CamelCase to follow conventions
// FIXME: document struct and members
struct load_conf_closure
{
const struct GNUNET_CONFIGURATION_Handle *cfg;
enum GNUNET_GenericReturnValue error;
};
2022-03-21 08:35:19 +01:00
// FIXME: document
static void
collect_extensions (
void *cls,
const char *section)
{
struct load_conf_closure *col = cls;
const char *name;
const struct TALER_Extension *extension;
if (GNUNET_OK != col->error)
return;
if (0 != strncasecmp (section,
TALER_EXTENSION_SECTION_PREFIX,
sizeof(TALER_EXTENSION_SECTION_PREFIX) - 1))
{
return;
}
name = section + sizeof(TALER_EXTENSION_SECTION_PREFIX) - 1;
if (NULL == (extension = TALER_extensions_get_by_name (name)))
{
GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
"Unsupported extension `%s` (section [%s]).\n", name,
section);
col->error = GNUNET_SYSERR;
return;
}
if (GNUNET_OK !=
extension->load_taler_config (
(struct TALER_Extension *) extension,
col->cfg))
{
GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
"Couldn't parse configuration for extension `%s` (section [%s]).\n",
name,
section);
col->error = GNUNET_SYSERR;
return;
}
}
enum GNUNET_GenericReturnValue
TALER_extensions_load_taler_config (
const struct GNUNET_CONFIGURATION_Handle *cfg)
{
struct load_conf_closure col = {
.cfg = cfg,
.error = GNUNET_OK,
};
GNUNET_CONFIGURATION_iterate_sections (cfg,
&collect_extensions,
&col);
return col.error;
}
[age restriction] progress 14/n - withdraw and deposit Age restriction support for - withdraw is done and tested - deposit is done and tested TODOs: - melt/refresh/reveal - link ------ Added functions - TALER_age_restriction_commit - TALER_age_commitment_derive - TALER_age_commitment_hash - TALER_age_restriction_commitment_free_inside - Hash of age commitment passed around API boundaries Exchangedb adjustments for denominations - all prepared statements re: denominations now handle age_mask - signature parameters adjusted Hash and signature verification of /keys adjusted - Hashes of (normal) denominations and age-restricted denominations are calculated seperately - The hash of the age-restricted ones will then be added to the other hash - The total hash is signed/verified Tests for withdraw with age restriction added - TALER_EXCHANGE_DenomPublickey now carries age_mask - TALER_TESTING_cmd_withdraw_amount* takes age parameter - TALER_TESTING_find_pk takes boolean age_restricted - WithdrawState carries age_commitment and its hash - withdraw_run derives new age commitment, if applicable - Added age parameter to testing (13 as example) Various Fixes and changes - Fixes of post handler for /management/extensions - Fixes for offline tool extensions signing - Slight refactoring of extensions - Age restriction extension simplified - config is now global to extension - added global TEH_age_restriction_enabled and TEH_age_mask in taler-exchange-httpd - helper functions and macros introduced
2022-02-16 22:01:05 +01:00
enum GNUNET_GenericReturnValue
TALER_extensions_is_json_config (
json_t *obj,
int *critical,
const char **version,
json_t **config)
{
enum GNUNET_GenericReturnValue ret;
[age restriction] progress 14/n - withdraw and deposit Age restriction support for - withdraw is done and tested - deposit is done and tested TODOs: - melt/refresh/reveal - link ------ Added functions - TALER_age_restriction_commit - TALER_age_commitment_derive - TALER_age_commitment_hash - TALER_age_restriction_commitment_free_inside - Hash of age commitment passed around API boundaries Exchangedb adjustments for denominations - all prepared statements re: denominations now handle age_mask - signature parameters adjusted Hash and signature verification of /keys adjusted - Hashes of (normal) denominations and age-restricted denominations are calculated seperately - The hash of the age-restricted ones will then be added to the other hash - The total hash is signed/verified Tests for withdraw with age restriction added - TALER_EXCHANGE_DenomPublickey now carries age_mask - TALER_TESTING_cmd_withdraw_amount* takes age parameter - TALER_TESTING_find_pk takes boolean age_restricted - WithdrawState carries age_commitment and its hash - withdraw_run derives new age commitment, if applicable - Added age parameter to testing (13 as example) Various Fixes and changes - Fixes of post handler for /management/extensions - Fixes for offline tool extensions signing - Slight refactoring of extensions - Age restriction extension simplified - config is now global to extension - added global TEH_age_restriction_enabled and TEH_age_mask in taler-exchange-httpd - helper functions and macros introduced
2022-02-16 22:01:05 +01:00
json_t *cfg;
struct GNUNET_JSON_Specification spec[] = {
GNUNET_JSON_spec_boolean ("critical",
critical),
GNUNET_JSON_spec_string ("version",
version),
GNUNET_JSON_spec_json ("config",
[age restriction] progress 14/n - withdraw and deposit Age restriction support for - withdraw is done and tested - deposit is done and tested TODOs: - melt/refresh/reveal - link ------ Added functions - TALER_age_restriction_commit - TALER_age_commitment_derive - TALER_age_commitment_hash - TALER_age_restriction_commitment_free_inside - Hash of age commitment passed around API boundaries Exchangedb adjustments for denominations - all prepared statements re: denominations now handle age_mask - signature parameters adjusted Hash and signature verification of /keys adjusted - Hashes of (normal) denominations and age-restricted denominations are calculated seperately - The hash of the age-restricted ones will then be added to the other hash - The total hash is signed/verified Tests for withdraw with age restriction added - TALER_EXCHANGE_DenomPublickey now carries age_mask - TALER_TESTING_cmd_withdraw_amount* takes age parameter - TALER_TESTING_find_pk takes boolean age_restricted - WithdrawState carries age_commitment and its hash - withdraw_run derives new age commitment, if applicable - Added age parameter to testing (13 as example) Various Fixes and changes - Fixes of post handler for /management/extensions - Fixes for offline tool extensions signing - Slight refactoring of extensions - Age restriction extension simplified - config is now global to extension - added global TEH_age_restriction_enabled and TEH_age_mask in taler-exchange-httpd - helper functions and macros introduced
2022-02-16 22:01:05 +01:00
&cfg),
GNUNET_JSON_spec_end ()
};
2022-03-21 08:35:19 +01:00
ret = GNUNET_JSON_parse (obj,
spec,
NULL,
NULL);
// FIXME: convention says, 'true' path is for
// error handling.
if (GNUNET_OK == ret)
[age restriction] progress 14/n - withdraw and deposit Age restriction support for - withdraw is done and tested - deposit is done and tested TODOs: - melt/refresh/reveal - link ------ Added functions - TALER_age_restriction_commit - TALER_age_commitment_derive - TALER_age_commitment_hash - TALER_age_restriction_commitment_free_inside - Hash of age commitment passed around API boundaries Exchangedb adjustments for denominations - all prepared statements re: denominations now handle age_mask - signature parameters adjusted Hash and signature verification of /keys adjusted - Hashes of (normal) denominations and age-restricted denominations are calculated seperately - The hash of the age-restricted ones will then be added to the other hash - The total hash is signed/verified Tests for withdraw with age restriction added - TALER_EXCHANGE_DenomPublickey now carries age_mask - TALER_TESTING_cmd_withdraw_amount* takes age parameter - TALER_TESTING_find_pk takes boolean age_restricted - WithdrawState carries age_commitment and its hash - withdraw_run derives new age commitment, if applicable - Added age parameter to testing (13 as example) Various Fixes and changes - Fixes of post handler for /management/extensions - Fixes for offline tool extensions signing - Slight refactoring of extensions - Age restriction extension simplified - config is now global to extension - added global TEH_age_restriction_enabled and TEH_age_mask in taler-exchange-httpd - helper functions and macros introduced
2022-02-16 22:01:05 +01:00
{
*config = json_copy (cfg);
GNUNET_JSON_parse_free (spec);
[age restriction] progress 14/n - withdraw and deposit Age restriction support for - withdraw is done and tested - deposit is done and tested TODOs: - melt/refresh/reveal - link ------ Added functions - TALER_age_restriction_commit - TALER_age_commitment_derive - TALER_age_commitment_hash - TALER_age_restriction_commitment_free_inside - Hash of age commitment passed around API boundaries Exchangedb adjustments for denominations - all prepared statements re: denominations now handle age_mask - signature parameters adjusted Hash and signature verification of /keys adjusted - Hashes of (normal) denominations and age-restricted denominations are calculated seperately - The hash of the age-restricted ones will then be added to the other hash - The total hash is signed/verified Tests for withdraw with age restriction added - TALER_EXCHANGE_DenomPublickey now carries age_mask - TALER_TESTING_cmd_withdraw_amount* takes age parameter - TALER_TESTING_find_pk takes boolean age_restricted - WithdrawState carries age_commitment and its hash - withdraw_run derives new age commitment, if applicable - Added age parameter to testing (13 as example) Various Fixes and changes - Fixes of post handler for /management/extensions - Fixes for offline tool extensions signing - Slight refactoring of extensions - Age restriction extension simplified - config is now global to extension - added global TEH_age_restriction_enabled and TEH_age_mask in taler-exchange-httpd - helper functions and macros introduced
2022-02-16 22:01:05 +01:00
}
return ret;
}
enum GNUNET_GenericReturnValue
TALER_extensions_load_json_config (
json_t *extensions)
{
const char*name;
json_t *blob;
GNUNET_assert (NULL != extensions);
GNUNET_assert (json_is_object (extensions));
json_object_foreach (extensions, name, blob)
{
int critical;
const char *version;
json_t *config;
const struct TALER_Extension *extension =
TALER_extensions_get_by_name (name);
if (NULL == extension)
{
GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
"no such extension: %s\n", name);
return GNUNET_SYSERR;
}
/* load and verify criticality, version, etc. */
if (GNUNET_OK !=
[age restriction] progress 14/n - withdraw and deposit Age restriction support for - withdraw is done and tested - deposit is done and tested TODOs: - melt/refresh/reveal - link ------ Added functions - TALER_age_restriction_commit - TALER_age_commitment_derive - TALER_age_commitment_hash - TALER_age_restriction_commitment_free_inside - Hash of age commitment passed around API boundaries Exchangedb adjustments for denominations - all prepared statements re: denominations now handle age_mask - signature parameters adjusted Hash and signature verification of /keys adjusted - Hashes of (normal) denominations and age-restricted denominations are calculated seperately - The hash of the age-restricted ones will then be added to the other hash - The total hash is signed/verified Tests for withdraw with age restriction added - TALER_EXCHANGE_DenomPublickey now carries age_mask - TALER_TESTING_cmd_withdraw_amount* takes age parameter - TALER_TESTING_find_pk takes boolean age_restricted - WithdrawState carries age_commitment and its hash - withdraw_run derives new age commitment, if applicable - Added age parameter to testing (13 as example) Various Fixes and changes - Fixes of post handler for /management/extensions - Fixes for offline tool extensions signing - Slight refactoring of extensions - Age restriction extension simplified - config is now global to extension - added global TEH_age_restriction_enabled and TEH_age_mask in taler-exchange-httpd - helper functions and macros introduced
2022-02-16 22:01:05 +01:00
TALER_extensions_is_json_config (
blob, &critical, &version, &config))
return GNUNET_SYSERR;
if (critical != extension->critical
|| 0 != strcmp (version, extension->version) // TODO: libtool compare?
|| NULL == config
|| GNUNET_OK != extension->test_json_config (config))
return GNUNET_SYSERR;
/* This _should_ work now */
if (GNUNET_OK !=
extension->load_json_config ((struct TALER_Extension *) extension,
config))
return GNUNET_SYSERR;
}
/* make sure to disable all extensions that weren't mentioned in the json */
for (const struct TALER_Extension *it = TALER_extensions_get_head ();
NULL != it;
it = it->next)
{
if (NULL == json_object_get (extensions, it->name))
it->disable ((struct TALER_Extension *) it);
}
return GNUNET_OK;
}
[age restriction] progress 14/n - withdraw and deposit Age restriction support for - withdraw is done and tested - deposit is done and tested TODOs: - melt/refresh/reveal - link ------ Added functions - TALER_age_restriction_commit - TALER_age_commitment_derive - TALER_age_commitment_hash - TALER_age_restriction_commitment_free_inside - Hash of age commitment passed around API boundaries Exchangedb adjustments for denominations - all prepared statements re: denominations now handle age_mask - signature parameters adjusted Hash and signature verification of /keys adjusted - Hashes of (normal) denominations and age-restricted denominations are calculated seperately - The hash of the age-restricted ones will then be added to the other hash - The total hash is signed/verified Tests for withdraw with age restriction added - TALER_EXCHANGE_DenomPublickey now carries age_mask - TALER_TESTING_cmd_withdraw_amount* takes age parameter - TALER_TESTING_find_pk takes boolean age_restricted - WithdrawState carries age_commitment and its hash - withdraw_run derives new age commitment, if applicable - Added age parameter to testing (13 as example) Various Fixes and changes - Fixes of post handler for /management/extensions - Fixes for offline tool extensions signing - Slight refactoring of extensions - Age restriction extension simplified - config is now global to extension - added global TEH_age_restriction_enabled and TEH_age_mask in taler-exchange-httpd - helper functions and macros introduced
2022-02-16 22:01:05 +01:00
bool
TALER_extensions_age_restriction_is_enabled ()
{
const struct TALER_Extension *age =
TALER_extensions_get_by_type (TALER_Extension_AgeRestriction);
return (NULL != age &&
NULL != age->config_json &&
TALER_extensions_age_restriction_is_configured ());
}
/* end of extensions.c */