exchange

Base system with REST service to issue digital coins, run by the payment service provider
Log | Files | Refs | Submodules | README | LICENSE

commit 67f81b4a71e0f27f8f43038f05576ef37d60301d
parent 4081d08f3afacb7489e301311e740dfdaabcecd7
Author: Christian Grothoff <christian@grothoff.org>
Date:   Sun, 31 May 2026 21:06:40 +0200

remove extension mechanism

Diffstat:
Mmeson.build | 1-
Msrc/auditor/taler-auditor-sync.c | 5-----
Msrc/benchmark/meson.build | 2--
Msrc/exchange-tools/meson.build | 2--
Msrc/exchange-tools/taler-exchange-offline.c | 384+++++--------------------------------------------------------------------------
Msrc/exchange/meson.build | 3---
Msrc/exchange/taler-exchange-httpd.c | 56+++++++++++++++++++++++++++++++++++---------------------
Msrc/exchange/taler-exchange-httpd.h | 18+++++++++---------
Msrc/exchange/taler-exchange-httpd_common_kyc.c | 2+-
Msrc/exchange/taler-exchange-httpd_configuration.c | 2+-
Dsrc/exchange/taler-exchange-httpd_extensions.c | 447-------------------------------------------------------------------------------
Dsrc/exchange/taler-exchange-httpd_extensions.h | 58----------------------------------------------------------
Msrc/exchange/taler-exchange-httpd_get-keys.c | 63---------------------------------------------------------------
Msrc/exchange/taler-exchange-httpd_management.h | 21---------------------
Msrc/exchange/taler-exchange-httpd_post-batch-deposit.c | 121++++++++++++++-----------------------------------------------------------------
Dsrc/exchange/taler-exchange-httpd_post-management-extensions.c | 301-------------------------------------------------------------------------------
Msrc/exchange/taler-exchange-httpd_post-reveal-melt.c | 2+-
Msrc/exchange/taler-exchange-httpd_post-withdraw.c | 4++--
Dsrc/exchangedb/add_policy_fulfillment_proof.c | 159-------------------------------------------------------------------------------
Dsrc/exchangedb/get_extension_manifest.c | 64----------------------------------------------------------------
Dsrc/exchangedb/get_policy_details.c | 60------------------------------------------------------------
Msrc/exchangedb/meson.build | 5-----
Dsrc/exchangedb/persist_policy_details.c | 74--------------------------------------------------------------------------
Dsrc/exchangedb/persist_policy_details.sql | 114-------------------------------------------------------------------------------
Dsrc/exchangedb/set_extension_manifest.c | 53-----------------------------------------------------
Msrc/exchangedb/sql-schema/meson.build | 1-
Dsrc/extensions/age_restriction/age_restriction.c | 263-------------------------------------------------------------------------------
Dsrc/extensions/age_restriction/meson.build | 23-----------------------
Dsrc/extensions/age_restriction_helper.c | 71-----------------------------------------------------------------------
Dsrc/extensions/extensions.c | 452-------------------------------------------------------------------------------
Dsrc/extensions/meson.build | 28----------------------------
Dsrc/include/exchange-database/add_policy_fulfillment_proof.h | 40----------------------------------------
Dsrc/include/exchange-database/get_extension_manifest.h | 42------------------------------------------
Dsrc/include/exchange-database/get_policy_details.h | 42------------------------------------------
Dsrc/include/exchange-database/persist_policy_details.h | 52----------------------------------------------------
Dsrc/include/exchange-database/set_extension_manifest.h | 43-------------------------------------------
Msrc/include/taler/exchange/get-keys.h | 10----------
Msrc/include/taler/exchange/meson.build | 1-
Dsrc/include/taler/exchange/post-management-extensions.h | 122-------------------------------------------------------------------------------
Msrc/include/taler/meson.build | 2--
Msrc/include/taler/taler_exchange_service.h | 1-
Dsrc/include/taler/taler_extensions.h | 385-------------------------------------------------------------------------------
Dsrc/include/taler/taler_extensions_policy.h | 204-------------------------------------------------------------------------------
Msrc/include/taler/taler_testing_lib.h | 22++++++++--------------
Msrc/lib/exchange_api_handle.c | 61++++++++++---------------------------------------------------
Dsrc/lib/exchange_api_post-management-extensions.c | 251-------------------------------------------------------------------------------
Msrc/lib/meson.build | 2--
Msrc/meson.build | 1-
Msrc/testing/meson.build | 9---------
Msrc/testing/test_exchange_api.c | 1-
Msrc/testing/test_exchange_api.conf | 5++---
Msrc/testing/test_exchange_api_age_restriction.c | 1-
Msrc/testing/test_exchange_api_age_restriction.conf | 6++----
Msrc/testing/test_exchange_p2p.c | 1-
Msrc/testing/testing_api_cmd_age_withdraw.c | 3+--
Msrc/testing/testing_api_cmd_batch_withdraw.c | 1-
Dsrc/testing/testing_api_cmd_offline_sign_extensions.c | 169-------------------------------------------------------------------------------
Msrc/testing/testing_api_cmd_withdraw.c | 1-
Msrc/testing/testing_api_loop.c | 41++++++++++++++++++++++++++++++++++++-----
59 files changed, 153 insertions(+), 4225 deletions(-)

diff --git a/meson.build b/meson.build @@ -306,7 +306,6 @@ if not get_option('only-doc') libltversions = [ ['libtalerutil', '12:0:2'], ['libtalerjson', '7:0:3'], - ['libtalerextensions', '0:0:0'], ['libtalercurl', '0:1:0'], ['libtalerpq', '0:1:0'], ['libtalersq', '0:0:0'], diff --git a/src/auditor/taler-auditor-sync.c b/src/auditor/taler-auditor-sync.c @@ -25,7 +25,6 @@ #include "exchange-database/abort_shard.h" #include "exchange-database/activate_signing_key.h" #include "exchange-database/add_denomination_key.h" -#include "exchange-database/add_policy_fulfillment_proof.h" #include "exchange-database/aggregate.h" #include "exchange-database/begin_revolving_shard.h" #include "exchange-database/begin_shard.h" @@ -67,14 +66,12 @@ #include "exchange-database/get_denomination_revocation.h" #include "exchange-database/get_drain_profit.h" #include "exchange-database/get_expired_reserves.h" -#include "exchange-database/get_extension_manifest.h" #include "exchange-database/get_global_fee.h" #include "exchange-database/get_global_fees.h" #include "exchange-database/get_known_coin.h" #include "exchange-database/get_kyc_rules.h" #include "exchange-database/get_old_coin_by_h_blind.h" #include "exchange-database/get_pending_kyc_requirement_process.h" -#include "exchange-database/get_policy_details.h" #include "exchange-database/get_purse_deposit.h" #include "exchange-database/get_purse_request.h" #include "exchange-database/get_ready_deposit.h" @@ -150,7 +147,6 @@ #include "exchange-database/lookup_wire_transfer.h" #include "exchange-database/mark_refresh_reveal_success.h" #include "exchange-database/persist_kyc_attributes.h" -#include "exchange-database/persist_policy_details.h" #include "exchange-database/preflight.h" #include "exchange-database/profit_drains_get_pending.h" #include "exchange-database/profit_drains_set_finished.h" @@ -205,7 +201,6 @@ #include "exchange-database/select_withdrawals_above_serial_id.h" #include "exchange-database/select_withdraw_amounts_for_kyc_check.h" #include "exchange-database/set_aml_lock.h" -#include "exchange-database/set_extension_manifest.h" #include "exchange-database/set_purse_balance.h" #include "exchange-database/start_deferred_wire_out.h" #include "exchange-database/start.h" diff --git a/src/benchmark/meson.build b/src/benchmark/meson.build @@ -32,7 +32,6 @@ executable( libtalerexchange_dep, libtalerfakebank_dep, libtalerbank_dep, - libtalerextensions_dep, gnunetutil_dep, gnunetjson_dep, gnunetcurl_dep, @@ -55,7 +54,6 @@ executable( libtalerexchange_dep, libtalerfakebank_dep, libtalerbank_dep, - libtalerextensions_dep, gnunetutil_dep, gnunetjson_dep, gnunetcurl_dep, diff --git a/src/exchange-tools/meson.build b/src/exchange-tools/meson.build @@ -9,7 +9,6 @@ executable( libtalerutil_dep, libtalerjson_dep, libtalerexchange_dep, - libtalerextensions_dep, gnunetjson_dep, gnunetutil_dep, gnunetcurl_dep, @@ -45,7 +44,6 @@ executable( libtalerutil_dep, libtalerjson_dep, libtalerexchange_dep, - libtalerextensions_dep, gnunetjson_dep, gnunetutil_dep, gnunetcurl_dep, diff --git a/src/exchange-tools/taler-exchange-offline.c b/src/exchange-tools/taler-exchange-offline.c @@ -80,11 +80,6 @@ struct UploadKeysRequest; struct UploadKeysRequest #include "taler/exchange/post-management-keys.h" -struct UploadExtensionsRequest; -#define TALER_EXCHANGE_POST_MANAGEMENT_EXTENSIONS_RESULT_CLOSURE \ - struct UploadExtensionsRequest -#include "taler/exchange/post-management-extensions.h" - struct PartnerAddRequest; #define TALER_EXCHANGE_POST_MANAGEMENT_PARTNERS_RESULT_CLOSURE \ struct PartnerAddRequest @@ -94,7 +89,7 @@ struct PartnerAddRequest; char *const #include "taler/exchange/get-management-keys.h" -#include "taler/taler_extensions.h" +#include <microhttpd.h> #include <regex.h> @@ -176,11 +171,6 @@ struct PartnerAddRequest; #define OP_SETUP "exchange-setup-0" /** - * sign the enabled and configured extensions. - */ -#define OP_EXTENSIONS "exchange-extensions-0" - -/** * Generate message to drain profits. */ #define OP_DRAIN_PROFITS "exchange-drain-profits-0" @@ -221,12 +211,6 @@ static struct GNUNET_CURL_RescheduleContext *rc; static const struct GNUNET_CONFIGURATION_Handle *kcfg; /** - * Age restriction configuration - */ -static bool ar_enabled = false; -static struct TALER_AgeRestrictionConfig ar_config = {0}; - -/** * Return value from main(). */ static int global_ret; @@ -554,32 +538,6 @@ struct UploadKeysRequest size_t idx; }; -/** - * Ongoing /management/extensions request. - */ -struct UploadExtensionsRequest -{ - /** - * Kept in a DLL. - */ - struct UploadExtensionsRequest *next; - - /** - * Kept in a DLL. - */ - struct UploadExtensionsRequest *prev; - - /** - * Operation handle. - */ - struct TALER_EXCHANGE_PostManagementExtensionsHandle *h; - - /** - * Operation index. - */ - size_t idx; -}; - /** * Data structure for AML staff requests. @@ -758,16 +716,6 @@ static struct UploadKeysRequest *ukr_head; static struct UploadKeysRequest *ukr_tail; /** - * Active extensions upload requests. - */ -static struct UploadExtensionsRequest *uer_head; - -/** - * Active extensions upload requests. - */ -static struct UploadExtensionsRequest *uer_tail; - -/** * Active drain profits requests. */ struct DrainProfitsRequest *dpr_head; @@ -954,21 +902,6 @@ do_shutdown (void *cls) GNUNET_free (ukr); } } - { - struct UploadExtensionsRequest *uer; - - while (NULL != (uer = uer_head)) - { - GNUNET_log (GNUNET_ERROR_TYPE_ERROR, - "Aborting incomplete extensions signature upload #%u\n", - (unsigned int) uer->idx); - TALER_EXCHANGE_post_management_extensions_cancel (uer->h); - GNUNET_CONTAINER_DLL_remove (uer_head, - uer_tail, - uer); - GNUNET_free (uer); - } - } { struct DrainProfitsRequest *dpr; @@ -1042,7 +975,6 @@ test_shutdown (void) (NULL == wfr_head) && (NULL == gfr_head) && (NULL == ukr_head) && - (NULL == uer_head) && (NULL == dpr_head) && (NULL == mgkh) && (NULL == nxt) ) @@ -2331,136 +2263,6 @@ upload_keys (const char *exchange_url, } -/** - * Function called with information about the post upload extensions operation result. - * - * @param uer extension upload request - * @param er response data - */ -static void -extensions_cb ( - struct UploadExtensionsRequest *uer, - const struct TALER_EXCHANGE_PostManagementExtensionsResponse *er) -{ - const struct TALER_EXCHANGE_HttpResponse *hr = &er->hr; - - if (MHD_HTTP_NO_CONTENT != hr->http_status) - { - GNUNET_log (GNUNET_ERROR_TYPE_ERROR, - "Upload failed for command %u with status %u: %s (%s)\n", - (unsigned int) uer->idx, - hr->http_status, - TALER_ErrorCode_get_hint (hr->ec), - hr->hint); - global_ret = EXIT_FAILURE; - } - GNUNET_CONTAINER_DLL_remove (uer_head, - uer_tail, - uer); - GNUNET_free (uer); - test_shutdown (); -} - - -/** - * Upload extension configuration - * - * @param exchange_url base URL of the exchange - * @param idx index of the operation we are performing (for logging) - * @param value arguments for POSTing configurations of extensions - */ -static void -upload_extensions (const char *exchange_url, - size_t idx, - const json_t *value) -{ - const json_t *extensions; - struct TALER_MasterSignatureP sig; - const char *err_name; - unsigned int err_line; - struct GNUNET_JSON_Specification spec[] = { - GNUNET_JSON_spec_object_const ("extensions", - &extensions), - GNUNET_JSON_spec_fixed_auto ("extensions_sig", - &sig), - GNUNET_JSON_spec_end () - }; - - /* 1. Parse the signed extensions */ - if (GNUNET_OK != - GNUNET_JSON_parse (value, - spec, - &err_name, - &err_line)) - { - GNUNET_log (GNUNET_ERROR_TYPE_ERROR, - "Invalid input to set extensions: %s#%u at %u (skipping)\n", - err_name, - err_line, - (unsigned int) idx); - json_dumpf (value, - stderr, - JSON_INDENT (2)); - global_ret = EXIT_FAILURE; - GNUNET_SCHEDULER_shutdown (); - return; - } - - /* 2. Verify the signature */ - { - struct TALER_ExtensionManifestsHashP h_manifests; - - if (GNUNET_OK != - TALER_JSON_extensions_manifests_hash (extensions, - &h_manifests)) - { - GNUNET_log (GNUNET_ERROR_TYPE_ERROR, - "couldn't hash extensions' manifests\n"); - global_ret = EXIT_FAILURE; - GNUNET_SCHEDULER_shutdown (); - return; - } - - if (GNUNET_OK != - load_offline_key (GNUNET_NO)) - return; - - if (GNUNET_OK != TALER_exchange_offline_extension_manifests_hash_verify ( - &h_manifests, - &master_pub, - &sig)) - { - GNUNET_log (GNUNET_ERROR_TYPE_ERROR, - "invalid signature for extensions\n"); - global_ret = EXIT_FAILURE; - GNUNET_SCHEDULER_shutdown (); - return; - } - } - - /* 3. Upload the extensions */ - { - struct TALER_EXCHANGE_ManagementPostExtensionsData ped = { - .extensions = extensions, - .extensions_sig = sig, - }; - struct UploadExtensionsRequest *uer - = GNUNET_new (struct UploadExtensionsRequest); - - uer->idx = idx; - uer->h = TALER_EXCHANGE_post_management_extensions_create ( - ctx, - exchange_url, - &ped); - TALER_EXCHANGE_post_management_extensions_start (uer->h, - &extensions_cb, - uer); - GNUNET_CONTAINER_DLL_insert (uer_head, - uer_tail, - uer); - } -} - /** * Function called with information about the add partner operation. @@ -2731,10 +2533,6 @@ trigger_upload (const char *exchange_url) .cb = &upload_drain }, { - .key = OP_EXTENSIONS, - .cb = &upload_extensions - }, - { .key = OP_UPDATE_AML_STAFF, .cb = &update_aml_staff }, @@ -4927,7 +4725,10 @@ load_age_mask (const char*section_name) static const struct TALER_AgeMask null_mask = {0}; enum GNUNET_GenericReturnValue ret; - if (! ar_enabled) + if (GNUNET_YES != + GNUNET_CONFIGURATION_get_value_yesno (kcfg, + "exchange", + "AGE_RESTRICTION_ENABLED")) return null_mask; if (GNUNET_OK != (GNUNET_CONFIGURATION_have_value ( @@ -4945,7 +4746,24 @@ load_age_mask (const char*section_name) "AGE_RESTRICTED", "Value must be YES or NO\n"); if (GNUNET_YES == ret) - return ar_config.mask; + { + char *groups = NULL; + struct TALER_AgeMask mask = {0}; + + if (GNUNET_OK != + GNUNET_CONFIGURATION_get_value_string (kcfg, + "exchange", + "AGE_GROUPS", + &groups)) + groups = GNUNET_strdup ("8:10:12:14:16:18:21"); + if (GNUNET_OK == + TALER_parse_age_group_string (groups, &mask)) + { + GNUNET_free (groups); + return mask; + } + GNUNET_free (groups); + } return null_mask; } @@ -5276,108 +5094,6 @@ do_setup (char *const *args) } -/** - * Print the current extensions as configured - * - * @param args the array of command-line arguments to process next - */ -static void -do_extensions_show (char *const *args) -{ - const struct TALER_Extensions *it; - json_t *exts = json_object (); - json_t *obj; - - GNUNET_assert (NULL != exts); - for (it = TALER_extensions_get_head (); - NULL != it && NULL != it->extension; - it = it->next) - { - const struct TALER_Extension *extension = it->extension; - int ret; - - ret = json_object_set_new (exts, - extension->name, - extension->manifest (extension)); - GNUNET_assert (-1 != ret); - } - - obj = GNUNET_JSON_PACK ( - GNUNET_JSON_pack_object_steal ("extensions", - exts)); - GNUNET_log (GNUNET_ERROR_TYPE_MESSAGE, - "%s\n", - json_dumps (obj, - JSON_INDENT (2))); - json_decref (obj); - next (args); -} - - -/** - * Sign the configurations of the enabled extensions - */ -static void -do_extensions_sign (char *const *args) -{ - json_t *extensions = json_object (); - struct TALER_ExtensionManifestsHashP h_manifests; - struct TALER_MasterSignatureP sig; - const struct TALER_Extensions *it; - bool found = false; - json_t *obj; - - GNUNET_assert (NULL != extensions); - for (it = TALER_extensions_get_head (); - NULL != it && NULL != it->extension; - it = it->next) - { - const struct TALER_Extension *ext = it->extension; - GNUNET_assert (ext); - - found = true; - - GNUNET_assert (0 == - json_object_set_new (extensions, - ext->name, - ext->manifest (ext))); - } - - if (! found) - return; - - if (GNUNET_OK != - TALER_JSON_extensions_manifests_hash (extensions, - &h_manifests)) - { - json_decref (extensions); - GNUNET_log (GNUNET_ERROR_TYPE_ERROR, - "error while hashing manifest for extensions\n"); - return; - } - - if (GNUNET_OK != - load_offline_key (GNUNET_NO)) - { - json_decref (extensions); - return; - } - - TALER_exchange_offline_extension_manifests_hash_sign (&h_manifests, - &master_priv, - &sig); - obj = GNUNET_JSON_PACK ( - GNUNET_JSON_pack_object_steal ("extensions", - extensions), - GNUNET_JSON_pack_data_auto ( - "extensions_sig", - &sig)); - - output_operation (OP_EXTENSIONS, - obj); - next (args); -} - /** * Dispatch @a args in the @a cmds array. @@ -5424,39 +5140,6 @@ cmd_handler (char *const *args, } -static void -do_work_extensions (char *const *args) -{ - struct SubCommand cmds[] = { - { - .name = "show", - .help = - "show the extensions in the Taler-config and their configured parameters", - .cb = &do_extensions_show - }, - { - .name = "sign", - .help = - "sign the configuration of the extensions and publish it with the exchange", - .cb = &do_extensions_sign - }, - { - .name = NULL, - } - }; - - if (NULL == args[0]) - { - GNUNET_log (GNUNET_ERROR_TYPE_ERROR, - "You must provide a subcommand: `show` or `sign`.\n"); - GNUNET_SCHEDULER_shutdown (); - global_ret = EXIT_INVALIDARGUMENT; - return; - } - - cmd_handler (args, cmds); -} - static void work (void *cls) @@ -5564,11 +5247,6 @@ work (void *cls) "upload operation result to exchange (to be performed online!)", .cb = &do_upload }, - { - .name = "extensions", - .help = "subcommands for extension handling", - .cb = &do_work_extensions - }, /* list terminator */ { .name = NULL, @@ -5598,21 +5276,7 @@ run (void *cls, (void) cfgfile; kcfg = cfg; - /* load extensions */ - GNUNET_assert (GNUNET_OK == - TALER_extensions_init (kcfg)); - - /* setup age restriction, if applicable */ - { - const struct TALER_AgeRestrictionConfig *arc; - - if (NULL != - (arc = TALER_extensions_get_age_restriction_config ())) - { - ar_config = *arc; - ar_enabled = true; - } - } + /* age restriction is read per-denomination in load_age_mask() from [exchange] */ if (GNUNET_OK != diff --git a/src/exchange/meson.build b/src/exchange/meson.build @@ -182,7 +182,6 @@ taler_exchange_httpd_SOURCES = [ 'taler-exchange-httpd_configuration.c', 'taler-exchange-httpd_db.c', 'taler-exchange-httpd_get-deposits.c', - 'taler-exchange-httpd_extensions.c', 'taler-exchange-httpd_get-keys.c', 'taler-exchange-httpd_get-kyc-check-H_NORMALIZED_PAYTO.c', 'taler-exchange-httpd_get-kyc-info-ACCESS_TOKEN.c', @@ -196,7 +195,6 @@ taler_exchange_httpd_SOURCES = [ 'taler-exchange-httpd_post-management-auditors-AUDITOR_PUB-disable.c', 'taler-exchange-httpd_post-management-denominations-H_DENOM_PUB-revoke.c', 'taler-exchange-httpd_post-management-drain.c', - 'taler-exchange-httpd_post-management-extensions.c', 'taler-exchange-httpd_post-management-global-fees.c', 'taler-exchange-httpd_post-management-partners.c', 'taler-exchange-httpd_post-management-keys.c', @@ -241,7 +239,6 @@ executable( libtalerutil_dep, libtalerjson_dep, libtalerexchangedb_dep, - libtalerextensions_dep, libtalerkyclogic_dep, libtalertemplating_dep, gnunetutil_dep, diff --git a/src/exchange/taler-exchange-httpd.c b/src/exchange/taler-exchange-httpd.c @@ -47,7 +47,6 @@ #include "taler-exchange-httpd_get-config.h" #include "taler-exchange-httpd_get-contracts-CONTRACT_PUB.h" #include "taler-exchange-httpd_get-deposits.h" -#include "taler-exchange-httpd_extensions.h" #include "taler-exchange-httpd_get-keys.h" #include "taler-exchange-httpd_get-kyc-check-H_NORMALIZED_PAYTO.h" #include "taler-exchange-httpd_get-kyc-info-ACCESS_TOKEN.h" @@ -81,7 +80,6 @@ #include "taler-exchange-httpd_get-SPA.h" #include "taler-exchange-httpd_get-TERMS.h" #include "taler-exchange-httpd_get-transfers-WTID.h" -#include "taler/taler_extensions.h" #include <gnunet/gnunet_mhd_compat.h> #include "exchange-database/test_aml_officer.h" #include "exchange-database/preflight.h" @@ -116,7 +114,7 @@ const struct GNUNET_CONFIGURATION_Handle *TEH_cfg; bool TEH_age_restriction_enabled = false; -struct TALER_AgeRestrictionConfig TEH_age_restriction_config = {0}; +struct TALER_AgeMask TEH_age_restriction_mask = {0}; /** * Set to true if we started *any* HTTP daemons. @@ -215,14 +213,6 @@ int TEH_check_invariants_flag; bool TEH_suicide; /** - * Signature of the configuration of all enabled extensions, - * signed by the exchange's offline master key with purpose - * TALER_SIGNATURE_MASTER_EXTENSION. - */ -struct TALER_MasterSignatureP TEH_extensions_sig; -bool TEH_extensions_signed = false; - -/** * Value to return from main() */ static int global_ret; @@ -1311,10 +1301,6 @@ handle_post_management (struct TEH_RequestContext *rc, .handler = &TEH_handler_management_post_global_fees }, { - .arg0 = "extensions", - .handler = &TEH_handler_management_post_extensions - }, - { .arg0 = "drain", .handler = &TEH_handler_management_post_drain }, @@ -2753,7 +2739,6 @@ do_shutdown (void *cls) TEH_handler_aml_attributes_get_cleanup (); TALER_KYCLOGIC_kyc_done (); TALER_MHD_daemons_destroy (); - TEH_extensions_done (); TEH_keys_finished (); if (NULL != TEH_pg) { @@ -2887,12 +2872,41 @@ run (void *cls, GNUNET_SCHEDULER_shutdown (); return; } - if (GNUNET_OK != - TEH_extensions_init ()) + /* Initialize age restriction from [exchange] section */ + TEH_age_restriction_enabled = false; + memset (&TEH_age_restriction_mask, + 0, + sizeof (TEH_age_restriction_mask)); + if (GNUNET_YES == + GNUNET_CONFIGURATION_get_value_yesno (TEH_cfg, + "exchange", + "AGE_RESTRICTION_ENABLED")) { - global_ret = EXIT_NOTINSTALLED; - GNUNET_SCHEDULER_shutdown (); - return; + char *groups = NULL; + struct TALER_AgeMask mask = {0}; + + if (GNUNET_OK != + GNUNET_CONFIGURATION_get_value_string (TEH_cfg, + "exchange", + "AGE_GROUPS", + &groups)) + groups = GNUNET_strdup ( + "8:10:12:14:16:18:21"); + if (GNUNET_OK != + TALER_parse_age_group_string (groups, + &mask)) + { + GNUNET_log (GNUNET_ERROR_TYPE_ERROR, + "Invalid AGE_GROUPS value in [exchange]: %s\n", + groups); + GNUNET_free (groups); + global_ret = EXIT_NOTINSTALLED; + GNUNET_SCHEDULER_shutdown (); + return; + } + GNUNET_free (groups); + TEH_age_restriction_mask = mask; + TEH_age_restriction_enabled = true; } if (GNUNET_OK != TEH_keys_init ()) diff --git a/src/exchange/taler-exchange-httpd.h b/src/exchange/taler-exchange-httpd.h @@ -27,7 +27,6 @@ #include "taler/taler_json_lib.h" #include "taler/taler_util.h" #include "taler/taler_kyclogic_plugin.h" -#include "taler/taler_extensions.h" #include <gnunet/gnunet_mhd_compat.h> #include "exchangedb_lib.h" @@ -201,12 +200,6 @@ extern volatile bool MHD_terminating; */ extern struct GNUNET_CURL_Context *TEH_curl_ctx; -/* - * Signature of the offline master key of all enabled extensions' configuration - */ -extern struct TALER_MasterSignatureP TEH_extensions_sig; -extern bool TEH_extensions_signed; - /** * @brief Struct describing an URL and the handler for it. */ @@ -367,8 +360,15 @@ struct TEH_RequestHandler }; -/* Age restriction configuration */ +/** + * Is age restriction enabled on this exchange? + */ extern bool TEH_age_restriction_enabled; -extern struct TALER_AgeRestrictionConfig TEH_age_restriction_config; + +/** + * Age mask for the exchange; all age-restricted denominations use this mask. + * Only meaningful when @e TEH_age_restriction_enabled is true. + */ +extern struct TALER_AgeMask TEH_age_restriction_mask; #endif diff --git a/src/exchange/taler-exchange-httpd_common_kyc.c b/src/exchange/taler-exchange-httpd_common_kyc.c @@ -334,7 +334,7 @@ TEH_kyc_store_attributes ( enum GNUNET_GenericReturnValue ret; ret = TALER_parse_coarse_date (birthdate, - &TEH_age_restriction_config.mask, + &TEH_age_restriction_mask, &birthday); if (GNUNET_OK != ret) diff --git a/src/exchange/taler-exchange-httpd_configuration.c b/src/exchange/taler-exchange-httpd_configuration.c @@ -53,7 +53,7 @@ TEH_CONFIG_load_age_mask (const char *section_name) GNUNET_log (GNUNET_ERROR_TYPE_WARNING, "age restriction set in section %s, yet, age restriction is not enabled\n", section_name); - return TEH_age_restriction_config.mask; + return TEH_age_restriction_mask; } return null_mask; } diff --git a/src/exchange/taler-exchange-httpd_extensions.c b/src/exchange/taler-exchange-httpd_extensions.c @@ -1,447 +0,0 @@ -/* - This file is part of TALER - Copyright (C) 2021, 2023 Taler Systems SA - - TALER is free software; you can redistribute it and/or modify it under the - terms of the GNU Affero 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 Affero General Public License for more details. - You should have received a copy of the GNU Affero General Public License along with - TALER; see the file COPYING. If not, see <http://www.gnu.org/licenses/> -*/ -/** - * @file taler-exchange-httpd_extensions.c - * @brief Handle extensions (age-restriction, policy extensions) - * @author Özgür Kesim - */ -#include <gnunet/gnunet_json_lib.h> -#include "taler/taler_dbevents.h" -#include "taler-exchange-httpd_get-keys.h" -#include "taler-exchange-httpd_responses.h" -#include "taler-exchange-httpd_extensions.h" -#include "taler/taler_extensions_policy.h" -#include "taler/taler_json_lib.h" -#include "taler/taler_mhd_lib.h" -#include "taler/taler_extensions.h" -#include <jansson.h> -#include "exchange-database/set_extension_manifest.h" -#include "exchange-database/add_policy_fulfillment_proof.h" -#include "exchange-database/event_listen.h" -#include "exchange-database/event_listen_cancel.h" -#include "exchange-database/get_extension_manifest.h" -#include "exchange-database/get_policy_details.h" - -/** - * Handler listening for extensions updates by other exchange - * services. - */ -static struct GNUNET_DB_EventHandler *extensions_eh; - -/** - * Function called whenever another exchange process has updated - * the extensions data in the database. - * - * @param cls NULL - * @param extra type of the extension - * @param extra_size number of bytes in @a extra - */ -static void -extension_update_event_cb (void *cls, - const void *extra, - size_t extra_size) -{ - uint32_t nbo_type; - enum TALER_Extension_Type type; - const struct TALER_Extension *extension; - - (void) cls; - GNUNET_log (GNUNET_ERROR_TYPE_INFO, - "Received extensions update event\n"); - - if (sizeof(nbo_type) != extra_size) - { - GNUNET_break (0); - GNUNET_log (GNUNET_ERROR_TYPE_ERROR, - "Oops, incorrect size of extra for TALER_Extension_type\n"); - return; - } - - GNUNET_assert (NULL != extra); - - nbo_type = *(uint32_t *) extra; - type = (enum TALER_Extension_Type) (int) ntohl (nbo_type); - - /* Get the corresponding extension */ - extension = TALER_extensions_get_by_type (type); - if (NULL == extension) - { - GNUNET_break (0); - GNUNET_log (GNUNET_ERROR_TYPE_ERROR, - "Oops, unknown extension type: %d\n", type); - return; - } - - // Get the manifest from the database as string - { - char *manifest_str = NULL; - enum GNUNET_DB_QueryStatus qs; - json_error_t err; - json_t *manifest_js; - enum GNUNET_GenericReturnValue ret; - - qs = TALER_EXCHANGEDB_get_extension_manifest (TEH_pg, - extension->name, - &manifest_str); - - if (qs < 0) - { - GNUNET_log (GNUNET_ERROR_TYPE_ERROR, - "Couldn't get extension manifest\n"); - GNUNET_break (0); - return; - } - - // No config found -> disable extension - if (NULL == manifest_str) - { - GNUNET_log (GNUNET_ERROR_TYPE_ERROR, - "No manifest found for extension %s, disabling it\n", - extension->name); - extension->disable ((struct TALER_Extension *) extension); - return; - } - - // Parse the string as JSON - manifest_js = json_loads (manifest_str, JSON_DECODE_ANY, &err); - if (NULL == manifest_js) - { - GNUNET_log (GNUNET_ERROR_TYPE_ERROR, - "Failed to parse manifest for extension `%s' as JSON: %s (%s)\n", - extension->name, - err.text, - err.source); - GNUNET_break (0); - free (manifest_str); - return; - } - - // Call the parser for the extension - ret = extension->load_config ( - json_object_get (manifest_js, "config"), - (struct TALER_Extension *) extension); - - if (GNUNET_OK != ret) - { - GNUNET_log (GNUNET_ERROR_TYPE_ERROR, - "Couldn't parse configuration for extension %s from the manifest in the database: %s\n", - extension->name, - manifest_str); - GNUNET_break (0); - } - - free (manifest_str); - json_decref (manifest_js); - } - - /* Special case age restriction: Update global flag and mask */ - if (TALER_Extension_AgeRestriction == type) - { - const struct TALER_AgeRestrictionConfig *conf = - TALER_extensions_get_age_restriction_config (); - TEH_age_restriction_enabled = false; - if (NULL != conf) - { - TEH_age_restriction_enabled = extension->enabled; - TEH_age_restriction_config = *conf; - GNUNET_log (GNUNET_ERROR_TYPE_INFO, - "[age restriction] DB event has changed the config to %s with mask: %s\n", - TEH_age_restriction_enabled ? "enabled": "DISABLED", - TALER_age_mask_to_string (&conf->mask)); - } - } - - // Finally, call TEH_keys_update_states in order to refresh the cached - // values. - TEH_keys_update_states (); -} - - -enum GNUNET_GenericReturnValue -TEH_extensions_init () -{ - /* Set the event handler for updates */ - struct GNUNET_DB_EventHeaderP ev = { - .size = htons (sizeof (ev)), - .type = htons (TALER_DBEVENT_EXCHANGE_EXTENSIONS_UPDATED), - }; - - /* Load the shared libraries first */ - if (GNUNET_OK != - TALER_extensions_init (TEH_cfg)) - { - GNUNET_log (GNUNET_ERROR_TYPE_ERROR, - "failed to load extensions"); - return GNUNET_SYSERR; - } - - /* Check for age restriction */ - { - const struct TALER_AgeRestrictionConfig *arc; - - if (NULL != - (arc = TALER_extensions_get_age_restriction_config ())) - TEH_age_restriction_config = *arc; - } - - extensions_eh = TALER_EXCHANGEDB_event_listen (TEH_pg, - GNUNET_TIME_UNIT_FOREVER_REL, - &ev, - &extension_update_event_cb, - NULL); - if (NULL == extensions_eh) - { - GNUNET_break (0); - return GNUNET_SYSERR; - } - - /* Trigger the initial load of configuration from the db */ - for (const struct TALER_Extensions *it = TALER_extensions_get_head (); - NULL != it && NULL != it->extension; - it = it->next) - { - const struct TALER_Extension *ext = it->extension; - uint32_t typ = htonl (ext->type); - json_t *jmani; - char *manifest; - - jmani = ext->manifest (ext); - manifest = json_dumps (jmani, - JSON_COMPACT); - json_decref (jmani); - TALER_EXCHANGEDB_set_extension_manifest (TEH_pg, - ext->name, - manifest); - free (manifest); - extension_update_event_cb (NULL, - &typ, - sizeof(typ)); - } - - return GNUNET_OK; -} - - -void -TEH_extensions_done () -{ - if (NULL != extensions_eh) - { - TALER_TALER_EXCHANGEDB_event_listen_cancel (TEH_pg, - extensions_eh); - extensions_eh = NULL; - } -} - - -/* - * @brief Execute database transactions for /extensions/policy_* POST requests. - * - * @param cls a `struct TALER_PolicyFulfillmentOutcome` - * @param connection MHD request context - * @param[out] mhd_ret set to MHD status on error - * @return transaction status - */ -static enum GNUNET_DB_QueryStatus -policy_fulfillment_transaction ( - void *cls, - struct MHD_Connection *connection, - enum MHD_Result *mhd_ret) -{ - struct TALER_PolicyFulfillmentTransactionData *fulfillment = cls; - - /* FIXME[oec]: use connection and mhd_ret? */ - (void) connection; - (void) mhd_ret; - - return TALER_EXCHANGEDB_add_policy_fulfillment_proof (TEH_pg, - fulfillment); -} - - -/* FIXME[oec]-#7999: In this handler: do we transition correctly between states? */ -enum MHD_Result -TEH_extensions_post_handler ( - struct TEH_RequestContext *rc, - const json_t *root, - const char *const args[]) -{ - const struct TALER_Extension *ext = NULL; - json_t *output; - struct TALER_PolicyDetails *policy_details = NULL; - size_t policy_details_count = 0; - - - if (NULL == args[0]) - { - GNUNET_break_op (0); - return TALER_MHD_reply_with_error (rc->connection, - MHD_HTTP_NOT_FOUND, - TALER_EC_EXCHANGE_GENERIC_OPERATION_UNKNOWN, - "/extensions/$EXTENSION"); - } - - ext = TALER_extensions_get_by_name (args[0]); - if (NULL == ext) - { - GNUNET_break_op (0); - return TALER_MHD_reply_with_error (rc->connection, - MHD_HTTP_NOT_FOUND, - TALER_EC_EXCHANGE_GENERIC_OPERATION_UNKNOWN, - "/extensions/$EXTENSION unknown"); - } - - if (NULL == ext->policy_post_handler) - return TALER_MHD_reply_with_error (rc->connection, - MHD_HTTP_NOT_IMPLEMENTED, - TALER_EC_EXCHANGE_GENERIC_OPERATION_UNKNOWN, - "POST /extensions/$EXTENSION not supported"); - - /* Extract hash_codes and retrieve related policy_details from the DB */ - { - enum GNUNET_GenericReturnValue ret; - enum GNUNET_DB_QueryStatus qs; - const char *error_msg; - struct GNUNET_HashCode *hcs; - size_t len; - json_t*val; - size_t idx; - json_t *jhash_codes = json_object_get (root, - "policy_hash_codes"); - if (! json_is_array (jhash_codes)) - return TALER_MHD_reply_with_error (rc->connection, - MHD_HTTP_BAD_REQUEST, - TALER_EC_EXCHANGE_GENERIC_OPERATION_UNKNOWN, - "policy_hash_codes are missing"); - - len = json_array_size (jhash_codes); - hcs = GNUNET_new_array (len, - struct GNUNET_HashCode); - policy_details = GNUNET_new_array (len, - struct TALER_PolicyDetails); - ret = GNUNET_OK; - json_array_foreach (jhash_codes, idx, val) - { - struct GNUNET_JSON_Specification spec[] = { - GNUNET_JSON_spec_fixed_auto (NULL, &hcs[idx]), - GNUNET_JSON_spec_end () - }; - - ret = GNUNET_JSON_parse (val, - spec, - &error_msg, - NULL); - if (GNUNET_OK != ret) - break; - - qs = TALER_EXCHANGEDB_get_policy_details (TEH_pg, - &hcs[idx], - &policy_details[idx]); - if (0 > qs) - { - GNUNET_free (hcs); - GNUNET_free (policy_details); - return TALER_MHD_reply_with_error (rc->connection, - MHD_HTTP_BAD_REQUEST, - TALER_EC_EXCHANGE_GENERIC_OPERATION_UNKNOWN, - "a policy_hash_code couldn't be found"); - } - - /* We proceed according to the state of fulfillment */ - switch (policy_details[idx].fulfillment_state) - { - case TALER_PolicyFulfillmentReady: - break; - case TALER_PolicyFulfillmentInsufficient: - error_msg = "a policy is not yet fully funded"; - ret = GNUNET_SYSERR; - break; - case TALER_PolicyFulfillmentTimeout: - error_msg = "a policy is has already timed out"; - ret = GNUNET_SYSERR; - break; - case TALER_PolicyFulfillmentSuccess: - /* FIXME[oec]-#8001: Idempotency handling. */ - GNUNET_break (0); - break; - case TALER_PolicyFulfillmentFailure: - /* FIXME[oec]-#7999: What to do in the failure case? */ - GNUNET_break (0); - break; - default: - /* Unknown state */ - GNUNET_assert (0); - } - - if (GNUNET_OK != ret) - break; - } - - GNUNET_free (hcs); - - if (GNUNET_OK != ret) - { - GNUNET_free (policy_details); - return TALER_MHD_reply_with_error (rc->connection, - MHD_HTTP_BAD_REQUEST, - TALER_EC_EXCHANGE_GENERIC_OPERATION_UNKNOWN, - error_msg); - } - } - - - if (GNUNET_OK != - ext->policy_post_handler (root, - &args[1], - policy_details, - policy_details_count, - &output)) - { - return TALER_MHD_reply_json_steal ( - rc->connection, - output, - MHD_HTTP_BAD_REQUEST); - } - - /* execute fulfillment transaction */ - { - enum MHD_Result mhd_ret; - struct TALER_PolicyFulfillmentTransactionData fulfillment = { - .proof = root, - .timestamp = GNUNET_TIME_timestamp_get (), - .details = policy_details, - .details_count = policy_details_count - }; - - if (GNUNET_OK != - TEH_DB_run_transaction (rc->connection, - "execute policy fulfillment", - TEH_MT_REQUEST_POLICY_FULFILLMENT, - &mhd_ret, - &policy_fulfillment_transaction, - &fulfillment)) - { - json_decref (output); - return mhd_ret; - } - } - - return TALER_MHD_reply_json_steal (rc->connection, - output, - MHD_HTTP_OK); -} - - -/* end of taler-exchange-httpd_extensions.c */ diff --git a/src/exchange/taler-exchange-httpd_extensions.h b/src/exchange/taler-exchange-httpd_extensions.h @@ -1,58 +0,0 @@ -/* - This file is part of TALER - Copyright (C) 2021 Taler Systems SA - - TALER is free software; you can redistribute it and/or modify it under the - terms of the GNU Affero 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 Affero General Public License for more details. - - You should have received a copy of the GNU Affero General Public License along with - TALER; see the file COPYING. If not, see <http://www.gnu.org/licenses/> -*/ -/** - * @file taler-exchange-httpd_extensions.h - * @brief Manage extensions - * @author Özgür Kesim - */ -#ifndef TALER_EXCHANGE_HTTPD_EXTENSIONS_H -#define TALER_EXCHANGE_HTTPD_EXTENSIONS_H - -#include <gnunet/gnunet_util_lib.h> -#include <microhttpd.h> -#include "taler-exchange-httpd.h" - - -/** - * Initialize extensions - * - * @return #GNUNET_OK on success - */ -enum GNUNET_GenericReturnValue -TEH_extensions_init (void); - -/** - * Terminate the extension subsystem - */ -void -TEH_extensions_done (void); - - -/** - * Handle POST "/extensions/..." requests. - * - * @param rc request context - * @param root uploaded JSON data - * @param args array of additional options - * @return MHD result code - */ -enum MHD_Result -TEH_extensions_post_handler ( - struct TEH_RequestContext *rc, - const json_t *root, - const char *const args[]); - -#endif diff --git a/src/exchange/taler-exchange-httpd_get-keys.c b/src/exchange/taler-exchange-httpd_get-keys.c @@ -30,7 +30,6 @@ #include "taler-exchange-httpd_secmod-helpers.h" #include "taler-exchange-httpd_responses.h" #include "taler-exchange-httpd_configuration.h" -#include "taler/taler_extensions.h" #include "exchange-database/event_listen.h" #include "exchange-database/event_listen_cancel.h" #include "exchange-database/event_notify.h" @@ -1883,68 +1882,6 @@ create_krd (struct TEH_KeyStateHandle *ksh, GNUNET_JSON_pack_data_auto ("exchange_sig", &exchange_sig)); GNUNET_assert (NULL != keys); - /* Signal support for the configured, enabled extensions. */ - { - json_t *extensions = json_object (); - bool has_extensions = false; - - GNUNET_assert (NULL != extensions); - /* Fill in the configurations of the enabled extensions */ - for (const struct TALER_Extensions *iter = TALER_extensions_get_head (); - NULL != iter && NULL != iter->extension; - iter = iter->next) - { - const struct TALER_Extension *extension = iter->extension; - json_t *manifest; - int r; - - /* skip if not enabled */ - if (! extension->enabled) - continue; - - /* flag our findings so far */ - has_extensions = true; - - - manifest = extension->manifest (extension); - GNUNET_assert (manifest); - - r = json_object_set_new ( - extensions, - extension->name, - manifest); - GNUNET_assert (0 == r); - } - - /* Update the keys object with the extensions and its signature */ - if (has_extensions) - { - json_t *sig; - int r; - - r = json_object_set_new ( - keys, - "extensions", - extensions); - GNUNET_assert (0 == r); - - /* Add the signature of the extensions, if it is not zero */ - if (TEH_extensions_signed) - { - sig = GNUNET_JSON_PACK ( - GNUNET_JSON_pack_data_auto ("extensions_sig", - &TEH_extensions_sig)); - - r = json_object_update (keys, sig); - GNUNET_assert (0 == r); - } - } - else - { - json_decref (extensions); - } - } - { char *keys_json; diff --git a/src/exchange/taler-exchange-httpd_management.h b/src/exchange/taler-exchange-httpd_management.h @@ -149,19 +149,6 @@ TEH_handler_management_post_global_fees ( /** - * Handle a POST "/management/extensions" request. - * - * @param connection the MHD connection to handle - * @param root uploaded JSON data - * @return MHD result code - */ -enum MHD_Result -TEH_handler_management_post_extensions ( - struct MHD_Connection *connection, - const json_t *root); - - -/** * Handle a POST "/management/drain" request. * * @param connection the MHD connection to handle @@ -200,12 +187,4 @@ TEH_handler_management_partners ( const json_t *root); -/** - * Initialize extension configuration handling. - * - * @return #GNUNET_OK on success - */ -enum GNUNET_GenericReturnValue -TEH_extensions_init (void); - #endif diff --git a/src/exchange/taler-exchange-httpd_post-batch-deposit.c b/src/exchange/taler-exchange-httpd_post-batch-deposit.c @@ -27,7 +27,6 @@ #include <jansson.h> #include <microhttpd.h> #include <pthread.h> -#include "taler/taler_extensions_policy.h" #include "taler/taler_json_lib.h" #include "taler/taler_mhd_lib.h" #include "taler-exchange-httpd_common_kyc.h" @@ -39,7 +38,6 @@ #include "exchange-database/do_check_deposit_idempotent.h" #include "exchange-database/do_deposit.h" #include "exchange-database/get_wire_hash_for_contract.h" -#include "exchange-database/persist_policy_details.h" #include "exchange-database/preflight.h" @@ -80,12 +78,6 @@ struct BatchDepositContext struct TALER_EXCHANGEDB_CoinDepositInformation *cdis; /** - * Additional details for policy extension relevant for this - * deposit operation, possibly NULL! - */ - json_t *policy_json; - - /** * Response to return, if set. */ struct MHD_Response *response; @@ -96,22 +88,11 @@ struct BatchDepositContext struct TALER_EXCHANGEDB_KycStatus kyc; /** - * Hash over @e policy_details, might be all zero - */ - struct TALER_ExtensionPolicyHashP h_policy; - - /** * Hash over the merchant's payto://-URI with the wire salt. */ struct TALER_MerchantWireHashP h_wire; /** - * When @e policy_details are persisted, this contains the id of the record - * in the policy_details table. - */ - uint64_t policy_details_serial_id; - - /** * Hash over the normalized payto://-URI of the account we are * depositing into. */ @@ -136,13 +117,6 @@ struct BatchDepositContext struct TALER_EXCHANGEDB_BatchDeposit bd; /** - * If @e policy_json was present, the corresponding policy extension - * calculates these details. These will be persisted in the policy_details - * table. - */ - struct TALER_PolicyDetails policy_details; - - /** * HTTP status to return with @e response, or 0. */ unsigned int http_status; @@ -154,10 +128,9 @@ struct BatchDepositContext { BDC_PHASE_INIT = 0, BDC_PHASE_PARSE = 1, - BDC_PHASE_POLICY = 2, - BDC_PHASE_KYC = 3, - BDC_PHASE_TRANSACT = 4, - BDC_PHASE_REPLY_SUCCESS = 5, + BDC_PHASE_KYC = 2, + BDC_PHASE_TRANSACT = 3, + BDC_PHASE_REPLY_SUCCESS = 4, BDC_PHASE_SUSPENDED, BDC_PHASE_CHECK_KYC_RESULT, BDC_PHASE_GENERATE_REPLY_FAILURE, @@ -166,12 +139,6 @@ struct BatchDepositContext } phase; /** - * True, if no policy was present in the request. Then - * @e policy_json is NULL and @e h_policy will be all zero. - */ - bool has_no_policy; - - /** * KYC failed because a KYC auth transfer is needed * to establish the merchant_pub. */ @@ -250,7 +217,7 @@ bdc_phase_reply_success ( &TEH_keys_exchange_sign_, &bd->h_contract_terms, &bdc->h_wire, - bdc->has_no_policy ? NULL : &bdc->h_policy, + NULL, bdc->exchange_timestamp, bd->wire_deadline, bd->refund_deadline, @@ -308,23 +275,6 @@ batch_deposit_transaction (void *cls, bool balance_ok; bool in_conflict; - /* If the deposit has a policy associated to it, persist it. This will - * insert or update the record. */ - if (! bdc->has_no_policy) - { - qs = TALER_EXCHANGEDB_persist_policy_details ( - TEH_pg, - &bdc->policy_details, - &bdc->bd.policy_details_serial_id, - &bdc->accumulated_total_without_fee, - &bdc->policy_details.fulfillment_state); - if (qs < 0) - return qs; - - bdc->bd.policy_blocked = - bdc->policy_details.fulfillment_state != TALER_PolicyFulfillmentSuccess; - } - /* FIXME-#9373: replace by batch insert! */ for (unsigned int i = 0; i<bdc->bd.num_cdis; i++) { @@ -647,43 +597,6 @@ bdc_phase_kyc (struct BatchDepositContext *bdc) } -/** - * Handle policy. - * - * @param[in,out] bdc request context - */ -static void -bdc_phase_policy (struct BatchDepositContext *bdc) -{ - const char *error_hint = NULL; - - if (bdc->has_no_policy) - { - bdc->phase++; - return; - } - if (GNUNET_OK != - TALER_extensions_create_policy_details ( - TEH_currency, - bdc->policy_json, - &bdc->policy_details, - &error_hint)) - { - GNUNET_break_op (0); - finish_loop (bdc, - TALER_MHD_reply_with_error ( - bdc->rc->connection, - MHD_HTTP_BAD_REQUEST, - TALER_EC_EXCHANGE_DEPOSITS_POLICY_NOT_ACCEPTED, - error_hint)); - return; - } - - TALER_deposit_policy_hash (bdc->policy_json, - &bdc->h_policy); - bdc->phase++; -} - /** * Parse per-coin deposit information from @a jcoin @@ -868,7 +781,7 @@ parse_coin (const struct BatchDepositContext *bdc, cdi->coin.no_age_commitment ? NULL : &cdi->coin.h_age_commitment, - NULL != bdc->policy_json ? &bdc->h_policy : NULL, + NULL, &cdi->coin.denom_pub_hash, bd->wallet_timestamp, &bd->merchant_pub, @@ -903,7 +816,8 @@ bdc_phase_parse (struct BatchDepositContext *bdc, { struct TALER_EXCHANGEDB_BatchDeposit *bd = &bdc->bd; const json_t *coins; - const json_t *policy_json; + const json_t *policy_json = NULL; + bool has_no_policy = true; bool no_refund_deadline = true; struct GNUNET_JSON_Specification spec[] = { TALER_JSON_spec_full_payto_uri ("merchant_payto_uri", @@ -925,7 +839,7 @@ bdc_phase_parse (struct BatchDepositContext *bdc, GNUNET_JSON_spec_mark_optional ( GNUNET_JSON_spec_object_const ("policy", &policy_json), - &bdc->has_no_policy), + &has_no_policy), GNUNET_JSON_spec_timestamp ("timestamp", &bd->wallet_timestamp), GNUNET_JSON_spec_mark_optional ( @@ -993,8 +907,19 @@ bdc_phase_parse (struct BatchDepositContext *bdc, "merchant_sig")); return; } - bdc->policy_json - = json_incref ((json_t *) policy_json); + if (! has_no_policy) + { + GNUNET_break_op (0); + GNUNET_JSON_parse_free (spec); + finish_loop (bdc, + TALER_MHD_reply_with_error ( + bdc->rc->connection, + MHD_HTTP_BAD_REQUEST, + TALER_EC_EXCHANGE_DEPOSITS_POLICY_NOT_ACCEPTED, + "policy extensions not supported")); + return; + } + (void) policy_json; GNUNET_log (GNUNET_ERROR_TYPE_INFO, "Batch deposit into contract %s\n", GNUNET_h2s (&bd->h_contract_terms.hash)); @@ -1142,7 +1067,6 @@ bdc_cleaner (struct TEH_RequestContext *rc) GNUNET_free (bdc->cdis); } GNUNET_free (bdc->deposit_fees); - json_decref (bdc->policy_json); GNUNET_free (bdc); } @@ -1179,9 +1103,6 @@ TEH_handler_batch_deposit (struct TEH_RequestContext *rc, bdc_phase_parse (bdc, root); break; - case BDC_PHASE_POLICY: - bdc_phase_policy (bdc); - break; case BDC_PHASE_KYC: bdc_phase_kyc (bdc); break; diff --git a/src/exchange/taler-exchange-httpd_post-management-extensions.c b/src/exchange/taler-exchange-httpd_post-management-extensions.c @@ -1,301 +0,0 @@ -/* - This file is part of TALER - Copyright (C) 2021 Taler Systems SA - - TALER is free software; you can redistribute it and/or modify it under the - terms of the GNU Affero 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 Affero General Public License for more details. - - You should have received a copy of the GNU Affero General Public License along with - TALER; see the file COPYING. If not, see <http://www.gnu.org/licenses/> - */ -/** - * @file taler-exchange-httpd_post-management-extensions.c - * @brief Handle request to POST /management/extensions - * @author Özgür Kesim - */ -#include <gnunet/gnunet_util_lib.h> -#include <gnunet/gnunet_json_lib.h> -#include <jansson.h> -#include <microhttpd.h> -#include "taler/taler_json_lib.h" -#include "taler/taler_mhd_lib.h" -#include "taler/taler_signatures.h" -#include "taler-exchange-httpd_management.h" -#include "taler-exchange-httpd_responses.h" -#include "taler/taler_extensions.h" -#include "taler/taler_dbevents.h" -#include "exchange-database/set_extension_manifest.h" -#include "exchange-database/event_notify.h" - -/** - * Extension carries the necessary data for a particular extension. - * - */ -struct Extension -{ - enum TALER_Extension_Type type; - json_t *manifest; -}; - -/** - * Closure for the #set_extensions transaction - */ -struct SetExtensionsContext -{ - uint32_t num_extensions; - struct Extension *extensions; - struct TALER_MasterSignatureP extensions_sig; -}; - -/** - * Function implementing database transaction to set the manifests of - * extensions. It runs the transaction logic. - * - IF it returns a non-error code, the transaction logic MUST NOT queue a - * MHD response. - * - IF it returns an hard error, the transaction logic MUST queue a MHD - * response and set @a mhd_ret. - * - IF it returns the soft error code, the function MAY be called again to - * retry and MUST not queue a MHD response. - * - * @param cls closure with a `struct SetExtensionsContext` - * @param connection MHD request which triggered the transaction - * @param[out] mhd_ret set to MHD response status for @a connection, - * if transaction failed (!) - * @return transaction status - */ -static enum GNUNET_DB_QueryStatus -set_extensions (void *cls, - struct MHD_Connection *connection, - enum MHD_Result *mhd_ret) -{ - struct SetExtensionsContext *sec = cls; - - /* save the manifests of all extensions */ - for (uint32_t i = 0; i<sec->num_extensions; i++) - { - struct Extension *ext = &sec->extensions[i]; - const struct TALER_Extension *taler_ext; - enum GNUNET_DB_QueryStatus qs; - char *manifest; - - taler_ext = TALER_extensions_get_by_type (ext->type); - if (NULL == taler_ext) - { - /* No such extension found */ - GNUNET_break (0); - return GNUNET_DB_STATUS_HARD_ERROR; - } - - manifest = json_dumps (ext->manifest, JSON_COMPACT | JSON_SORT_KEYS); - if (NULL == manifest) - { - GNUNET_break (0); - *mhd_ret = TALER_MHD_reply_with_error (connection, - MHD_HTTP_INTERNAL_SERVER_ERROR, - TALER_EC_GENERIC_JSON_INVALID, - "convert configuration to string"); - return GNUNET_DB_STATUS_HARD_ERROR; - } - - qs = TALER_EXCHANGEDB_set_extension_manifest ( - TEH_pg, - taler_ext->name, - manifest); - - free (manifest); - - if (qs < 0) - { - if (GNUNET_DB_STATUS_SOFT_ERROR == qs) - return qs; - GNUNET_break (0); - *mhd_ret = TALER_MHD_reply_with_error (connection, - MHD_HTTP_INTERNAL_SERVER_ERROR, - TALER_EC_GENERIC_DB_STORE_FAILED, - "save extension configuration"); - } - - /* Success, trigger event */ - { - uint32_t nbo_type = htonl (sec->extensions[i].type); - struct GNUNET_DB_EventHeaderP ev = { - .size = htons (sizeof (ev)), - .type = htons (TALER_DBEVENT_EXCHANGE_EXTENSIONS_UPDATED) - }; - - TALER_EXCHANGEDB_event_notify (TEH_pg, - &ev, - &nbo_type, - sizeof(nbo_type)); - } - - } - - /* All extensions configured, update the signature */ - TEH_extensions_sig = sec->extensions_sig; - TEH_extensions_signed = true; - - return GNUNET_DB_STATUS_SUCCESS_ONE_RESULT; /* only 'success', so >=0, matters here */ -} - - -static enum GNUNET_GenericReturnValue -verify_extensions_from_json ( - const json_t *extensions, - struct SetExtensionsContext *sec) -{ - const char*name; - const struct TALER_Extension *extension; - size_t i = 0; - json_t *manifest; - - GNUNET_assert (NULL != extensions); - GNUNET_assert (json_is_object (extensions)); - - sec->num_extensions = json_object_size (extensions); - sec->extensions = GNUNET_new_array (sec->num_extensions, - struct Extension); - - json_object_foreach ((json_t *) extensions, name, manifest) - { - int critical = 0; - json_t *config; - const char *version = NULL; - - /* load and verify criticality, version, etc. */ - 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; - } - - if (GNUNET_OK != - TALER_extensions_parse_manifest ( - manifest, &critical, &version, &config)) - return GNUNET_SYSERR; - - if (critical != extension->critical - || 0 != strcmp (version, extension->version) // FIXME-oec: libtool compare - || NULL == config - || GNUNET_OK != extension->load_config (config, NULL)) - return GNUNET_SYSERR; - - sec->extensions[i].type = extension->type; - sec->extensions[i].manifest = json_copy (manifest); - } - - return GNUNET_OK; -} - - -enum MHD_Result -TEH_handler_management_post_extensions ( - struct MHD_Connection *connection, - const json_t *root) -{ - enum MHD_Result ret; - const json_t *extensions; - struct SetExtensionsContext sec = {0}; - struct GNUNET_JSON_Specification top_spec[] = { - GNUNET_JSON_spec_object_const ("extensions", - &extensions), - GNUNET_JSON_spec_fixed_auto ("extensions_sig", - &sec.extensions_sig), - GNUNET_JSON_spec_end () - }; - - /* Parse the top level json structure */ - { - enum GNUNET_GenericReturnValue res; - - res = TALER_MHD_parse_json_data (connection, - root, - top_spec); - if (GNUNET_SYSERR == res) - return MHD_NO; /* hard failure */ - if (GNUNET_NO == res) - return MHD_YES; /* failure */ - } - - /* Verify the signature */ - { - struct TALER_ExtensionManifestsHashP h_manifests; - - if (GNUNET_OK != - TALER_JSON_extensions_manifests_hash (extensions, - &h_manifests) || - GNUNET_OK != - TALER_exchange_offline_extension_manifests_hash_verify ( - &h_manifests, - &TEH_master_public_key, - &sec.extensions_sig)) - { - return TALER_MHD_reply_with_error ( - connection, - MHD_HTTP_BAD_REQUEST, - TALER_EC_GENERIC_PARAMETER_MALFORMED, - "invalid signuture"); - } - } - - GNUNET_log (GNUNET_ERROR_TYPE_INFO, - "Received /management/extensions\n"); - - /* Now parse individual extensions and signatures from those objects. */ - if (GNUNET_OK != - verify_extensions_from_json (extensions, &sec)) - { - return TALER_MHD_reply_with_error ( - connection, - MHD_HTTP_BAD_REQUEST, - TALER_EC_GENERIC_PARAMETER_MALFORMED, - "invalid object"); - } - - GNUNET_log (GNUNET_ERROR_TYPE_INFO, - "Received %u extensions\n", - sec.num_extensions); - - /* now run the transaction to persist the configurations */ - { - enum GNUNET_GenericReturnValue res; - - res = TEH_DB_run_transaction (connection, - "set extensions", - TEH_MT_REQUEST_OTHER, - &ret, - &set_extensions, - &sec); - - if (GNUNET_SYSERR == res) - goto CLEANUP; - } - - ret = TALER_MHD_reply_static ( - connection, - MHD_HTTP_NO_CONTENT, - NULL, - NULL, - 0); - -CLEANUP: - for (unsigned int i = 0; i < sec.num_extensions; i++) - { - if (NULL != sec.extensions[i].manifest) - { - json_decref (sec.extensions[i].manifest); - } - } - GNUNET_free (sec.extensions); - return ret; -} - - -/* end of taler-exchange-httpd_management_management_post_extensions.c */ diff --git a/src/exchange/taler-exchange-httpd_post-reveal-melt.c b/src/exchange/taler-exchange-httpd_post-reveal-melt.c @@ -188,7 +188,7 @@ compare_age_commitment ( { struct TALER_AgeCommitmentHashP ach; - actx->age_commitment.mask = TEH_age_restriction_config.mask; + actx->age_commitment.mask = TEH_age_restriction_mask; TALER_age_commitment_hash ( &actx->age_commitment, &ach); diff --git a/src/exchange/taler-exchange-httpd_post-withdraw.c b/src/exchange/taler-exchange-httpd_post-withdraw.c @@ -1145,7 +1145,7 @@ phase_check_reserve_signature ( ? NULL : &wc->request.withdraw.blinding_seed, (wc->request.withdraw.age_proof_required) - ? &TEH_age_restriction_config.mask + ? &TEH_age_restriction_mask : NULL, (wc->request.withdraw.age_proof_required) ? wc->request.withdraw.max_age @@ -1623,7 +1623,7 @@ withdraw_phase_parse ( { /* The age value MUST be on the beginning of an age group */ if (wc->request.withdraw.max_age != - TALER_get_lowest_age (&TEH_age_restriction_config.mask, + TALER_get_lowest_age (&TEH_age_restriction_mask, wc->request.withdraw.max_age)) { GNUNET_break_op (0); diff --git a/src/exchangedb/add_policy_fulfillment_proof.c b/src/exchangedb/add_policy_fulfillment_proof.c @@ -1,159 +0,0 @@ -/* - This file is part of TALER - Copyright (C) 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 exchangedb/add_policy_fulfillment_proof.c - * @brief Implementation of the add_policy_fulfillment_proof function for Postgres - * @author Christian Grothoff - */ -#include "platform.h" /* UNNECESSARY? */ -#include "taler/taler_error_codes.h" /* UNNECESSARY? */ -#include "taler/taler_dbevents.h" /* UNNECESSARY? */ -#include "taler/taler_pq_lib.h" -#include "exchange-database/add_policy_fulfillment_proof.h" -#include "helper.h" - - -/** - * Compares two indices into an array of hash codes according to - * GNUNET_CRYPTO_hash_cmp of the content at those index positions. - * - * Used in a call qsort_t in order to generate sorted policy_hash_codes. - */ -static int -hash_code_cmp ( - const void *hc1, - const void *hc2, - void *arg) -{ - size_t i1 = *(size_t *) hc1; - size_t i2 = *(size_t *) hc2; - const struct TALER_PolicyDetails *d = arg; - - return GNUNET_CRYPTO_hash_cmp (&d[i1].hash_code, - &d[i2].hash_code); -} - - -enum GNUNET_DB_QueryStatus -TALER_EXCHANGEDB_add_policy_fulfillment_proof ( - struct TALER_EXCHANGEDB_PostgresContext *pg, - struct TALER_PolicyFulfillmentTransactionData *fulfillment) -{ - enum GNUNET_DB_QueryStatus qs; - size_t count = fulfillment->details_count; - /* FIXME[Oec]: this seems to be prone to VLA attacks */ - struct GNUNET_HashCode hcs[GNUNET_NZL (count)]; - - /* Create the sorted policy_hash_codes */ - { - size_t idx[GNUNET_NZL (count)]; - for (size_t i = 0; i < count; i++) - idx[i] = i; - - /* Sort the indices according to the hash codes of the corresponding - * details. */ - qsort_r (idx, - count, - sizeof(size_t), - hash_code_cmp, - fulfillment->details); - - /* Finally, concatenate all hash_codes in sorted order */ - for (size_t i = 0; i < count; i++) - hcs[i] = fulfillment->details[idx[i]].hash_code; - } - - - /* Now, add the proof to the policy_fulfillments table, retrieve the - * record_id */ - { - struct GNUNET_PQ_QueryParam params[] = { - GNUNET_PQ_query_param_timestamp (&fulfillment->timestamp), - TALER_PQ_query_param_json (fulfillment->proof), - GNUNET_PQ_query_param_auto_from_type (&fulfillment->h_proof), - TALER_PQ_query_param_array_hash_code (count, hcs, pg->conn), - GNUNET_PQ_query_param_end - }; - struct GNUNET_PQ_ResultSpec rs[] = { - GNUNET_PQ_result_spec_uint64 ("fulfillment_id", - &fulfillment->fulfillment_id), - GNUNET_PQ_result_spec_end - }; - - PREPARE (pg, - "insert_proof_into_policy_fulfillments", - "INSERT INTO policy_fulfillments" - "(fulfillment_timestamp" - ",fulfillment_proof" - ",h_fulfillment_proof" - ",policy_hash_codes" - ") VALUES ($1, $2::TEXT::JSON, $3, $4)" - " RETURNING fulfillment_id" - " ON CONFLICT DO NOTHING;"); - qs = GNUNET_PQ_eval_prepared_singleton_select (pg->conn, - "insert_proof_into_policy_fulfillments", - params, - rs); - if (GNUNET_DB_STATUS_SUCCESS_ONE_RESULT != qs) - return qs; - } - - /* Now, set the states of each entry corresponding to the hash_codes in - * policy_details accordingly */ - for (size_t i = 0; i < count; i++) - { - struct TALER_PolicyDetails *pos = &fulfillment->details[i]; - { - struct GNUNET_PQ_QueryParam params[] = { - GNUNET_PQ_query_param_auto_from_type (&pos->hash_code), - GNUNET_PQ_query_param_timestamp (&pos->deadline), - TALER_PQ_query_param_amount (pg->conn, - &pos->commitment), - TALER_PQ_query_param_amount (pg->conn, - &pos->accumulated_total), - TALER_PQ_query_param_amount (pg->conn, - &pos->policy_fee), - TALER_PQ_query_param_amount (pg->conn, - &pos->transferable_amount), - GNUNET_PQ_query_param_auto_from_type (&pos->fulfillment_state), - GNUNET_PQ_query_param_end - }; - - PREPARE (pg, - "update_policy_details", - "UPDATE policy_details SET" - " deadline=$2" - ",commitment=$3" - ",accumulated_total=$4" - ",fee=$5" - ",transferable=$6" - ",fulfillment_state=$7" - " WHERE policy_hash_code=$1;"); - qs = GNUNET_PQ_eval_prepared_non_select (pg->conn, - "update_policy_details", - params); - if (qs < 0) - return qs; - } - } - - /* - * FIXME[oec]-#7999: When all policies of a deposit are fulfilled, - * unblock it and trigger a wire-transfer. - */ - - return qs; -} diff --git a/src/exchangedb/get_extension_manifest.c b/src/exchangedb/get_extension_manifest.c @@ -1,64 +0,0 @@ -/* - This file is part of TALER - Copyright (C) 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 exchangedb/get_extension_manifest.c - * @brief Implementation of the get_extension_manifest function for Postgres - * @author Christian Grothoff - */ -#include "taler/taler_pq_lib.h" -#include "exchange-database/get_extension_manifest.h" -#include "helper.h" - -/** - * Function called to get the manifest of an extension - * (age-restriction, policy_extension_...) - * - * @param pg the database context - * @param extension_name the name of the extension - * @param[out] manifest JSON object of the manifest as string - * @return transaction status code - */ -enum GNUNET_DB_QueryStatus -TALER_EXCHANGEDB_get_extension_manifest (struct - TALER_EXCHANGEDB_PostgresContext *pg, - const char *extension_name, - char **manifest) -{ - struct GNUNET_PQ_QueryParam params[] = { - GNUNET_PQ_query_param_string (extension_name), - GNUNET_PQ_query_param_end - }; - bool is_null; - struct GNUNET_PQ_ResultSpec rs[] = { - GNUNET_PQ_result_spec_allow_null ( - GNUNET_PQ_result_spec_string ("manifest", - manifest), - &is_null), - GNUNET_PQ_result_spec_end - }; - - *manifest = NULL; - PREPARE (pg, - "get_extension_manifest", - "SELECT" - " manifest" - " FROM extensions" - " WHERE name=$1;"); - return GNUNET_PQ_eval_prepared_singleton_select (pg->conn, - "get_extension_manifest", - params, - rs); -} diff --git a/src/exchangedb/get_policy_details.c b/src/exchangedb/get_policy_details.c @@ -1,60 +0,0 @@ -/* - This file is part of TALER - Copyright (C) 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 exchangedb/get_policy_details.c - * @brief Implementation of the get_policy_details function for Postgres - * @author Christian Grothoff - */ -#include "taler/taler_pq_lib.h" -#include "exchange-database/get_policy_details.h" -#include "helper.h" - -enum GNUNET_DB_QueryStatus -TALER_EXCHANGEDB_get_policy_details ( - struct TALER_EXCHANGEDB_PostgresContext *pg, - const struct GNUNET_HashCode *hc, - struct TALER_PolicyDetails *details) -{ - struct GNUNET_PQ_QueryParam params[] = { - GNUNET_PQ_query_param_auto_from_type (hc), - GNUNET_PQ_query_param_end - }; - struct GNUNET_PQ_ResultSpec rs[] = { - GNUNET_PQ_result_spec_timestamp ("deadline", - &details->deadline), - TALER_PQ_RESULT_SPEC_AMOUNT ("commitment", - &details->commitment), - TALER_PQ_RESULT_SPEC_AMOUNT ("accumulated_total", - &details->accumulated_total), - TALER_PQ_RESULT_SPEC_AMOUNT ("policy_fee", - &details->policy_fee), - TALER_PQ_RESULT_SPEC_AMOUNT ("transferable_amount", - &details->transferable_amount), - GNUNET_PQ_result_spec_auto_from_type ("state", - &details->fulfillment_state), - GNUNET_PQ_result_spec_allow_null ( - GNUNET_PQ_result_spec_uint64 ("policy_fulfillment_id", - &details->policy_fulfillment_id), - &details->no_policy_fulfillment_id), - GNUNET_PQ_result_spec_end - }; - - - return GNUNET_PQ_eval_prepared_singleton_select (pg->conn, - "get_policy_details", - params, - rs); -} diff --git a/src/exchangedb/meson.build b/src/exchangedb/meson.build @@ -53,7 +53,6 @@ libtalerexchangedb = library( 'abort_shard.c', 'activate_signing_key.c', 'add_denomination_key.c', - 'add_policy_fulfillment_proof.c', 'aggregate.c', 'begin_revolving_shard.c', 'begin_shard.c', @@ -97,14 +96,12 @@ libtalerexchangedb = library( 'get_denomination_revocation.c', 'get_drain_profit.c', 'get_expired_reserves.c', - 'get_extension_manifest.c', 'get_global_fee.c', 'get_global_fees.c', 'get_known_coin.c', 'get_kyc_rules.c', 'get_old_coin_by_h_blind.c', 'get_pending_kyc_requirement_process.c', - 'get_policy_details.c', 'get_purse_deposit.c', 'get_purse_request.c', 'get_ready_deposit.c', @@ -181,7 +178,6 @@ libtalerexchangedb = library( 'lookup_wire_transfer.c', 'mark_refresh_reveal_success.c', 'persist_kyc_attributes.c', - 'persist_policy_details.c', 'preflight.c', 'profit_drains_get_pending.c', 'profit_drains_set_finished.c', @@ -238,7 +234,6 @@ libtalerexchangedb = library( 'select_withdrawals_above_serial_id.c', 'select_withdraw_amounts_for_kyc_check.c', 'set_aml_lock.c', - 'set_extension_manifest.c', 'set_purse_balance.c', 'start.c', 'start_deferred_wire_out.c', diff --git a/src/exchangedb/persist_policy_details.c b/src/exchangedb/persist_policy_details.c @@ -1,74 +0,0 @@ -/* - This file is part of TALER - Copyright (C) 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 exchangedb/persist_policy_details.c - * @brief Implementation of the persist_policy_details function for Postgres - * @author Christian Grothoff - */ -#include "taler/taler_pq_lib.h" -#include "exchange-database/persist_policy_details.h" -#include "helper.h" - - -enum GNUNET_DB_QueryStatus -TALER_EXCHANGEDB_persist_policy_details ( - struct TALER_EXCHANGEDB_PostgresContext *pg, - const struct TALER_PolicyDetails *details, - uint64_t *policy_details_serial_id, - struct TALER_Amount *accumulated_total, - enum TALER_PolicyFulfillmentState *fulfillment_state) -{ - struct GNUNET_PQ_QueryParam params[] = { - GNUNET_PQ_query_param_auto_from_type (&details->hash_code), - TALER_PQ_query_param_json (details->policy_json), - GNUNET_PQ_query_param_timestamp (&details->deadline), - TALER_PQ_query_param_amount (pg->conn, - &details->commitment), - TALER_PQ_query_param_amount (pg->conn, - &details->accumulated_total), - TALER_PQ_query_param_amount (pg->conn, - &details->policy_fee), - TALER_PQ_query_param_amount (pg->conn, - &details->transferable_amount), - GNUNET_PQ_query_param_auto_from_type (&details->fulfillment_state), - (details->no_policy_fulfillment_id) - ? GNUNET_PQ_query_param_null () - : GNUNET_PQ_query_param_uint64 (&details->policy_fulfillment_id), - GNUNET_PQ_query_param_end - }; - struct GNUNET_PQ_ResultSpec rs[] = { - GNUNET_PQ_result_spec_uint64 ("policy_details_serial_id", - policy_details_serial_id), - TALER_PQ_RESULT_SPEC_AMOUNT ("accumulated_total", - accumulated_total), - GNUNET_PQ_result_spec_uint32 ("fulfillment_state", - fulfillment_state), - GNUNET_PQ_result_spec_end - }; - - PREPARE (pg, - "call_insert_or_update_policy_details", - "SELECT" - " out_policy_details_serial_id AS policy_details_serial_id" - ",out_accumulated_total AS accumulated_total" - ",out_fulfillment_state AS fulfillment_state" - " FROM exchange_do_insert_or_update_policy_details" - "($1, $2, $3, $4, $5, $6, $7, $8, $9);"); - return GNUNET_PQ_eval_prepared_singleton_select (pg->conn, - "call_insert_or_update_policy_details", - params, - rs); -} diff --git a/src/exchangedb/persist_policy_details.sql b/src/exchangedb/persist_policy_details.sql @@ -1,114 +0,0 @@ --- --- This file is part of TALER --- Copyright (C) 2014--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/> --- - -CREATE OR REPLACE FUNCTION exchange_do_insert_or_update_policy_details( - IN in_policy_hash_code BYTEA, - IN in_policy_json TEXT, - IN in_deadline INT8, - IN in_commitment taler_amount, - IN in_accumulated_total taler_amount, - IN in_fee taler_amount, - IN in_transferable taler_amount, - IN in_fulfillment_state SMALLINT, - OUT out_policy_details_serial_id INT8, - OUT out_accumulated_total taler_amount, - OUT out_fulfillment_state SMALLINT) -LANGUAGE plpgsql -AS $$ -DECLARE - cur_commitment taler_amount; -DECLARE - cur_accumulated_total taler_amount; -DECLARE - rval RECORD; -BEGIN - -- First, try to create a new entry. - INSERT INTO policy_details - (policy_hash_code, - policy_json, - deadline, - commitment, - accumulated_total, - fee, - transferable, - fulfillment_state) - VALUES (in_policy_hash_code, - in_policy_json, - in_deadline, - in_commitment, - in_accumulated_total, - in_fee, - in_transferable, - in_fulfillment_state) - ON CONFLICT (policy_hash_code) DO NOTHING - RETURNING policy_details_serial_id INTO out_policy_details_serial_id; - - -- If the insert was successful, return - -- We assume that the fullfilment_state was correct in first place. - IF FOUND THEN - out_accumulated_total = in_accumulated_total; - out_fulfillment_state = in_fulfillment_state; - RETURN; - END IF; - - -- We had a conflict, grab the parts we need to update. - SELECT policy_details_serial_id - ,commitment - ,accumulated_total - INTO rval - FROM policy_details - WHERE policy_hash_code = in_policy_hash_code; - - -- We use rval as workaround as we cannot select - -- directly into the amount due to Postgres limitations. - out_policy_details_serial_id := rval.policy_details_serial_id; - cur_commitment := rval.commitment; - cur_accumulated_total := rval.accumulated_total; - - -- calculate the new values (overflows throws exception) - out_accumulated_total.val = cur_accumulated_total.val + in_accumulated_total.val; - out_accumulated_total.frac = cur_accumulated_total.frac + in_accumulated_total.frac; - -- normalize - out_accumulated_total.val = out_accumulated_total.val + out_accumulated_total.frac / 100000000; - out_accumulated_total.frac = out_accumulated_total.frac % 100000000; - - IF (out_accumulated_total.val > (1 << 52)) - THEN - RAISE EXCEPTION 'accumulation overflow'; - END IF; - - - -- Set the fulfillment_state according to the values. - -- For now, we only update the state when it was INSUFFICIENT. - -- FIXME[oec] #7999: What to do in case of Failure or other state? - IF (out_fulfillment_state = 2) -- INSUFFICIENT - THEN - IF (out_accumulated_total.val >= cur_commitment.val OR - (out_accumulated_total.val = cur_commitment.val AND - out_accumulated_total.frac >= cur_commitment.frac)) - THEN - out_fulfillment_state = 3; -- READY - END IF; - END IF; - - -- Now, update the record - UPDATE exchange.policy_details - SET - accumulated = out_accumulated_total, - fulfillment_state = out_fulfillment_state - WHERE - policy_details_serial_id = out_policy_details_serial_id; -END $$; diff --git a/src/exchangedb/set_extension_manifest.c b/src/exchangedb/set_extension_manifest.c @@ -1,53 +0,0 @@ -/* - This file is part of TALER - Copyright (C) 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 exchangedb/set_extension_manifest.c - * @brief Implementation of the set_extension_manifest function for Postgres - * @author Christian Grothoff - */ -#include "taler/taler_pq_lib.h" -#include "exchange-database/set_extension_manifest.h" -#include "helper.h" - - -enum GNUNET_DB_QueryStatus -TALER_EXCHANGEDB_set_extension_manifest (struct - TALER_EXCHANGEDB_PostgresContext *pg, - const char *extension_name, - const char *manifest) -{ - struct GNUNET_PQ_QueryParam pcfg = - (NULL == manifest || 0 == *manifest) - ? GNUNET_PQ_query_param_null () - : GNUNET_PQ_query_param_string (manifest); - struct GNUNET_PQ_QueryParam params[] = { - GNUNET_PQ_query_param_string (extension_name), - pcfg, - GNUNET_PQ_query_param_end - }; - - - PREPARE (pg, - "set_extension_manifest", - "INSERT INTO extensions (name, manifest) VALUES ($1, $2) " - "ON CONFLICT (name) " - "DO UPDATE SET manifest=$2"); - - - return GNUNET_PQ_eval_prepared_non_select (pg->conn, - "set_extension_manifest", - params); -} diff --git a/src/exchangedb/sql-schema/meson.build b/src/exchangedb/sql-schema/meson.build @@ -29,7 +29,6 @@ procedures_sql = [ '../expire_purse.sql', '../insert_reserve_open_deposit.sql', '../do_reserve_open.sql', - '../persist_policy_details.sql', '../insert_aml_decision.sql', '../insert_successor_measure.sql', '../insert_aml_officer.sql', diff --git a/src/extensions/age_restriction/age_restriction.c b/src/extensions/age_restriction/age_restriction.c @@ -1,263 +0,0 @@ -/* - 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 age_restriction.c - * @brief Utility functions regarding age restriction - * @author Özgür Kesim - */ -#include "taler/taler_util.h" -#include "taler/taler_extensions.h" -#include "stdint.h" - -/* ================================================== - * - * Age Restriction TALER_Extension implementation - * - * ================================================== - */ - -/** - * @brief local configuration - */ - -static struct TALER_AgeRestrictionConfig AR_config = {0}; - -/** - * @brief implements the TALER_Extension.disable interface. - * - * @param ext Pointer to the current extension - */ -static void -age_restriction_disable ( - struct TALER_Extension *ext) -{ - if (NULL == ext) - return; - - ext->enabled = false; - ext->config = NULL; - - AR_config.mask.bits = 0; - AR_config.num_groups = 0; -} - - -/** - * @brief implements the TALER_Extension.load_config interface. - * - * @param ext if NULL, only tests the configuration - * @param jconfig the configuration as json - */ -static enum GNUNET_GenericReturnValue -age_restriction_load_config ( - const json_t *jconfig, - struct TALER_Extension *ext) -{ - struct TALER_AgeMask mask = {0}; - enum GNUNET_GenericReturnValue ret; - - ret = TALER_JSON_parse_age_groups (jconfig, &mask); - if (GNUNET_OK != ret) - return ret; - - /* only testing the parser */ - if (ext == NULL) - return GNUNET_OK; - - if (TALER_Extension_AgeRestriction != ext->type) - return GNUNET_SYSERR; - - if (mask.bits > 0) - { - /* if the mask is not zero, the first bit MUST be set */ - if (0 == (mask.bits & 1)) - return GNUNET_SYSERR; - - AR_config.mask.bits = mask.bits; - AR_config.num_groups = __builtin_popcount (mask.bits) - 1; - } - - ext->config = &AR_config; - ext->enabled = true; - - GNUNET_log (GNUNET_ERROR_TYPE_INFO, - "loaded new age restriction config with age groups: %s\n", - TALER_age_mask_to_string (&mask)); - - return GNUNET_OK; -} - - -/** - * @brief implements the TALER_Extension.manifest interface. - * - * @param ext if NULL, only tests the configuration - * @return configuration as json_t* object, maybe NULL - */ -static json_t * -age_restriction_manifest ( - const struct TALER_Extension *ext) -{ - json_t *conf; - - GNUNET_assert (NULL != ext); - - if (NULL == ext->config) - { - GNUNET_log (GNUNET_ERROR_TYPE_WARNING, - "age restriction not configured"); - return json_null (); - } - - conf = GNUNET_JSON_PACK ( - GNUNET_JSON_pack_string ("age_groups", - TALER_age_mask_to_string (&AR_config.mask)) - ); - return GNUNET_JSON_PACK ( - GNUNET_JSON_pack_bool ("critical", - ext->critical), - GNUNET_JSON_pack_string ("version", - ext->version), - GNUNET_JSON_pack_object_steal ("config", - conf) - ); -} - - -/* The extension for age restriction */ -struct TALER_Extension TE_age_restriction = { - .type = TALER_Extension_AgeRestriction, - .name = "age_restriction", - .critical = false, - .version = "1", - .enabled = false, /* disabled per default */ - .config = NULL, - .disable = &age_restriction_disable, - .load_config = &age_restriction_load_config, - .manifest = &age_restriction_manifest, - - /* This extension is not a policy extension */ - .create_policy_details = NULL, - .policy_get_handler = NULL, - .policy_post_handler = NULL, -}; - - -/** - * @brief implements the init() function for GNUNET_PLUGIN_load - * - * @param arg Pointer to the GNUNET_CONFIGURATION_Handle - * @return pointer to TALER_Extension on success or NULL otherwise. - */ -void * -libtaler_extension_age_restriction_init (void *arg); - -/* Declaration used to squash compiler warning */ -void * -libtaler_extension_age_restriction_init (void *arg) -{ - const struct GNUNET_CONFIGURATION_Handle *cfg = arg; - char *groups = NULL; - struct TALER_AgeMask mask = {0}; - - if ((GNUNET_YES != - GNUNET_CONFIGURATION_have_value (cfg, - TALER_EXTENSION_SECTION_AGE_RESTRICTION, - "ENABLED")) - || - (GNUNET_YES != - GNUNET_CONFIGURATION_get_value_yesno (cfg, - TALER_EXTENSION_SECTION_AGE_RESTRICTION, - "ENABLED"))) - { - GNUNET_log (GNUNET_ERROR_TYPE_ERROR, - "[age restriction] no section %s found in configuration\n", - TALER_EXTENSION_SECTION_AGE_RESTRICTION); - - return NULL; - } - - /* Age restriction is enabled, extract age groups */ - if ((GNUNET_YES == - GNUNET_CONFIGURATION_have_value (cfg, - TALER_EXTENSION_SECTION_AGE_RESTRICTION, - "AGE_GROUPS")) - && - (GNUNET_YES != - GNUNET_CONFIGURATION_get_value_string (cfg, - TALER_EXTENSION_SECTION_AGE_RESTRICTION, - "AGE_GROUPS", - &groups))) - { - GNUNET_log (GNUNET_ERROR_TYPE_ERROR, - "[age restriction] AGE_GROUPS in %s is not a string\n", - TALER_EXTENSION_SECTION_AGE_RESTRICTION); - - return NULL; - } - - if (NULL == groups) - groups = GNUNET_strdup (TALER_EXTENSION_AGE_RESTRICTION_DEFAULT_AGE_GROUPS); - - if (GNUNET_OK != TALER_parse_age_group_string (groups, &mask)) - { - GNUNET_log (GNUNET_ERROR_TYPE_ERROR, - "[age restriction] couldn't parse age groups: '%s'\n", - groups); - return NULL; - } - - AR_config.mask = mask; - AR_config.num_groups = __builtin_popcount (mask.bits) - 1; /* no underflow, first bit always set */ - - GNUNET_log (GNUNET_ERROR_TYPE_INFO, - "[age restriction] setting age mask to %s with #groups: %d\n", - TALER_age_mask_to_string (&AR_config.mask), - __builtin_popcount (AR_config.mask.bits) - 1); - - TE_age_restriction.config = &AR_config; - - /* Note: we do now have TE_age_restriction_config set, however the extension - * is not yet enabled! For age restriction to become active, load_config must - * have been called. */ - - GNUNET_free (groups); - return &TE_age_restriction; -} - - -/** - * @brief implements the done() function for GNUNET_PLUGIN_load - * - * @param arg unused - * @return pointer to TALER_Extension on success or NULL otherwise. - */ -void * -libtaler_extension_age_restriction_done (void *arg); - -/* Declaration used to squash compiler warning */ -void * -libtaler_extension_age_restriction_done (void *arg) -{ - GNUNET_log (GNUNET_ERROR_TYPE_INFO, - "[age restriction] disabling and unloading"); - AR_config.mask.bits = 0; - AR_config.num_groups = 0; - return NULL; -} - - -/* end of age_restriction.c */ diff --git a/src/extensions/age_restriction/meson.build b/src/extensions/age_restriction/meson.build @@ -1,23 +0,0 @@ -# This build file is in the public domain - -# Age restriction as extension library - -age_plugindir = get_option('libdir') / 'taler-exchange' - -shared_module( - 'taler_extension_age_restriction', - 'age_restriction.c', - install_rpath: rpath_option, - dependencies: [ - libtalerutil_dep, - libtalerjson_dep, - gnunetjson_dep, - gnunetutil_dep, - json_dep, - ], - include_directories: [incdir, configuration_inc], - install: true, - install_dir: age_plugindir, -) - - diff --git a/src/extensions/age_restriction_helper.c b/src/extensions/age_restriction_helper.c @@ -1,71 +0,0 @@ -/* - This file is part of TALER - Copyright (C) 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 age_restriction_helper.c - * @brief Helper functions for age restriction - * @author Özgür Kesim - */ - -#include "taler/taler_util.h" -#include "taler/taler_extensions.h" -#include "stdint.h" - - -const struct TALER_AgeRestrictionConfig * -TALER_extensions_get_age_restriction_config () -{ - const struct TALER_Extension *ext; - - ext = TALER_extensions_get_by_type (TALER_Extension_AgeRestriction); - if (NULL == ext) - return NULL; - - return ext->config; -} - - -bool -TALER_extensions_is_age_restriction_enabled () -{ - const struct TALER_Extension *ext; - - ext = TALER_extensions_get_by_type (TALER_Extension_AgeRestriction); - if (NULL == ext) - return false; - - return ext->enabled; -} - - -struct TALER_AgeMask -TALER_extensions_get_age_restriction_mask () -{ - const struct TALER_Extension *ext; - const struct TALER_AgeRestrictionConfig *conf; - - ext = TALER_extensions_get_by_type (TALER_Extension_AgeRestriction); - - if ((NULL == ext) || - (NULL == ext->config)) - return (struct TALER_AgeMask) {0} - ; - - conf = ext->config; - return conf->mask; -} - - -/* end age_restriction_helper.c */ diff --git a/src/extensions/extensions.c b/src/extensions/extensions.c @@ -1,452 +0,0 @@ -/* - 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" /* UNNECESSARY? */ -#include "taler/taler_extensions_policy.h" -#include "taler/taler_util.h" -#include "taler/taler_signatures.h" -#include "taler/taler_extensions.h" -#include "stdint.h" - -/* head of the list of all registered extensions */ -static struct TALER_Extensions TE_extensions = { - .next = NULL, - .extension = NULL, -}; - -const struct TALER_Extensions * -TALER_extensions_get_head () -{ - return &TE_extensions; -} - - -static enum GNUNET_GenericReturnValue -add_extension ( - const struct TALER_Extension *extension) -{ - /* Sanity checks */ - if ((NULL == extension) || - (NULL == extension->name) || - (NULL == extension->version) || - (NULL == extension->disable) || - (NULL == extension->load_config) || - (NULL == extension->manifest)) - { - GNUNET_log (GNUNET_ERROR_TYPE_ERROR, - "invalid extension\n"); - return GNUNET_SYSERR; - } - - if (NULL == TE_extensions.extension) /* first extension ?*/ - TE_extensions.extension = extension; - else - { - struct TALER_Extensions *iter; - struct TALER_Extensions *last; - - /* Check for collisions */ - for (iter = &TE_extensions; - NULL != iter && NULL != iter->extension; - iter = iter->next) - { - const struct TALER_Extension *ext = iter->extension; - last = iter; - if (extension->type == ext->type || - 0 == strcasecmp (extension->name, - ext->name)) - { - GNUNET_log (GNUNET_ERROR_TYPE_ERROR, - "extension collision for `%s'\n", - extension->name); - return GNUNET_NO; - } - } - - /* No collisions found, so add this extension to the list */ - { - struct TALER_Extensions *extn = GNUNET_new (struct TALER_Extensions); - extn->extension = extension; - last->next = extn; - } - } - - return GNUNET_OK; -} - - -const struct TALER_Extension * -TALER_extensions_get_by_type ( - enum TALER_Extension_Type type) -{ - for (const struct TALER_Extensions *it = &TE_extensions; - NULL != it && NULL != it->extension; - it = it->next) - { - if (it->extension->type == type) - return it->extension; - } - - /* 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 && ext->enabled); -} - - -const struct TALER_Extension * -TALER_extensions_get_by_name ( - const char *name) -{ - for (const struct TALER_Extensions *it = &TE_extensions; - NULL != it; - it = it->next) - { - if (0 == strcasecmp (name, it->extension->name)) - return it->extension; - } - /* No extension found, try to load it. */ - - return NULL; -} - - -enum GNUNET_GenericReturnValue -TALER_extensions_verify_manifests_signature ( - const json_t *manifests, - struct TALER_MasterSignatureP *extensions_sig, - struct TALER_MasterPublicKeyP *master_pub) -{ - struct TALER_ExtensionManifestsHashP h_manifests; - - if (GNUNET_OK != - TALER_JSON_extensions_manifests_hash (manifests, - &h_manifests)) - return GNUNET_SYSERR; - if (GNUNET_OK != - TALER_exchange_offline_extension_manifests_hash_verify ( - &h_manifests, - master_pub, - extensions_sig)) - return GNUNET_NO; - return GNUNET_OK; -} - - -/** - * Closure used in TALER_extensions_load_taler_config during call to - * GNUNET_CONFIGURATION_iterate_sections with configure_extension. - */ -struct LoadConfClosure -{ - const struct GNUNET_CONFIGURATION_Handle *cfg; - enum GNUNET_GenericReturnValue error; -}; - - -/** - * Used in TALER_extensions_load_taler_config during call to - * GNUNET_CONFIGURATION_iterate_sections to load the configuration - * of supported extensions. - * - * @param cls Closure of type LoadConfClosure - * @param section name of the current section - */ -static void -configure_extension ( - void *cls, - const char *section) -{ - struct LoadConfClosure *col = cls; - const char *name; - char lib_name[1024] = {0}; - 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; - - - /* Load the extension library */ - GNUNET_snprintf (lib_name, - sizeof(lib_name), - "libtaler_extension_%s", - name); - /* Lower-case extension name, config is case-insensitive */ - for (unsigned int i = 0; i < strlen (lib_name); i++) - lib_name[i] = tolower (lib_name[i]); - - extension = GNUNET_PLUGIN_load (TALER_EXCHANGE_project_data (), - lib_name, - (void *) col->cfg); - if (NULL == extension) - { - GNUNET_log (GNUNET_ERROR_TYPE_ERROR, - "Couldn't load extension library to `%s` (section [%s]).\n", - name, - section); - col->error = GNUNET_SYSERR; - return; - } - - - if (GNUNET_OK != add_extension (extension)) - { - /* FIXME[oec]: Ignoring return values here */ - GNUNET_log (GNUNET_ERROR_TYPE_ERROR, - "Couldn't add extension `%s` (section [%s]).\n", - name, - section); - col->error = GNUNET_SYSERR; - GNUNET_PLUGIN_unload ( - lib_name, - (void *) col->cfg); - return; - } - - GNUNET_log (GNUNET_ERROR_TYPE_INFO, - "extension library '%s' loaded\n", - lib_name); -} - - -static bool extensions_loaded = false; - -enum GNUNET_GenericReturnValue -TALER_extensions_init ( - const struct GNUNET_CONFIGURATION_Handle *cfg) -{ - struct LoadConfClosure col = { - .cfg = cfg, - .error = GNUNET_OK, - }; - - if (extensions_loaded) - return GNUNET_OK; - - GNUNET_CONFIGURATION_iterate_sections (cfg, - &configure_extension, - &col); - - if (GNUNET_OK == col.error) - extensions_loaded = true; - - return col.error; -} - - -enum GNUNET_GenericReturnValue -TALER_extensions_parse_manifest ( - json_t *obj, - int *critical, - const char **version, - json_t **config) -{ - enum GNUNET_GenericReturnValue ret; - struct GNUNET_JSON_Specification spec[] = { - GNUNET_JSON_spec_boolean ("critical", - critical), - GNUNET_JSON_spec_string ("version", - version), - GNUNET_JSON_spec_json ("config", - config), - GNUNET_JSON_spec_end () - }; - - *config = NULL; - if (GNUNET_OK != - (ret = GNUNET_JSON_parse (obj, - spec, - NULL, - NULL))) - return ret; - return GNUNET_OK; -} - - -enum GNUNET_GenericReturnValue -TALER_extensions_load_manifests ( - const json_t *extensions) -{ - const char *name; - json_t *manifest; - - GNUNET_assert (NULL != extensions); - GNUNET_assert (json_is_object (extensions)); - - json_object_foreach ((json_t *) extensions, name, manifest) - { - int critical; - const char *version; - json_t *config; - struct TALER_Extension *extension - = (struct TALER_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 != - TALER_extensions_parse_manifest ( - manifest, - &critical, - &version, - &config)) - return GNUNET_SYSERR; - - if (critical != extension->critical - || 0 != strcmp (version, - extension->version) // FIXME[oec]: libtool compare? - || NULL == config - || (GNUNET_OK != - extension->load_config (config, - NULL)) ) - return GNUNET_SYSERR; - - /* This _should_ work now */ - if (GNUNET_OK != - extension->load_config (config, - extension)) - return GNUNET_SYSERR; - - extension->enabled = true; - } - - /* make sure to disable all extensions that weren't mentioned in the json */ - for (const struct TALER_Extensions *it = TALER_extensions_get_head (); - NULL != it; - it = it->next) - { - if (NULL == json_object_get (extensions, it->extension->name)) - it->extension->disable ((struct TALER_Extension *) it); - } - - return GNUNET_OK; -} - - -/** - * Policy related - */ -static const char *fulfillment2str[] = { - [TALER_PolicyFulfillmentInitial] = "<init>", - [TALER_PolicyFulfillmentReady] = "Ready", - [TALER_PolicyFulfillmentSuccess] = "Success", - [TALER_PolicyFulfillmentFailure] = "Failure", - [TALER_PolicyFulfillmentTimeout] = "Timeout", - [TALER_PolicyFulfillmentInsufficient] = "Insufficient", -}; - -const char * -TALER_policy_fulfillment_state_str ( - enum TALER_PolicyFulfillmentState state) -{ - GNUNET_assert (TALER_PolicyFulfillmentStateCount > state); - return fulfillment2str[state]; -} - - -enum GNUNET_GenericReturnValue -TALER_extensions_create_policy_details ( - const char *currency, - const json_t *policy_options, - struct TALER_PolicyDetails *details, - const char **error_hint) -{ - enum GNUNET_GenericReturnValue ret; - const struct TALER_Extension *extension; - const json_t *jtype; - const char *type; - - *error_hint = NULL; - - if ((NULL == policy_options) || - (! json_is_object (policy_options))) - { - *error_hint = "invalid policy object"; - return GNUNET_SYSERR; - } - - jtype = json_object_get (policy_options, "type"); - if (NULL == jtype) - { - *error_hint = "no type in policy object"; - return GNUNET_SYSERR; - } - - type = json_string_value (jtype); - if (NULL == type) - { - *error_hint = "invalid type in policy object"; - return GNUNET_SYSERR; - } - - extension = TALER_extensions_get_by_name (type); - if ((NULL == extension) || - (NULL == extension->create_policy_details)) - { - GNUNET_break (0); - GNUNET_log (GNUNET_ERROR_TYPE_WARNING, - "Unsupported extension policy '%s' requested\n", - type); - return GNUNET_NO; - } - - /* Set state fields in the policy details to initial values. */ - GNUNET_assert (GNUNET_OK == - TALER_amount_set_zero (currency, - &details->accumulated_total)); - GNUNET_assert (GNUNET_OK == - TALER_amount_set_zero (currency, - &details->policy_fee)); - details->deadline = GNUNET_TIME_UNIT_FOREVER_TS; - details->fulfillment_state = TALER_PolicyFulfillmentInitial; - details->no_policy_fulfillment_id = true; - ret = extension->create_policy_details (currency, - policy_options, - details, - error_hint); - return ret; - -} - - -/* end of extensions.c */ diff --git a/src/extensions/meson.build b/src/extensions/meson.build @@ -1,28 +0,0 @@ -libtalerextensions_src = ['extensions.c', 'age_restriction_helper.c'] - -libtalerextensions = library( - 'talerextensions', - libtalerextensions_src, - soversion: solibversions['libtalerextensions']['soversion'], - version: solibversions['libtalerextensions']['soversion'], - install_rpath: rpath_option, - dependencies: [ - libtalerutil_dep, - libtalerjson_dep, - gnunetutil_dep, - gnunetjson_dep, - json_dep, - ], - include_directories: [incdir, configuration_inc], - install: true, - install_dir: get_option('libdir'), -) - -libtalerextensions_dep = declare_dependency(link_with: libtalerextensions) -pkg.generate( - libtalerextensions, - url: 'https://taler.net', - description: 'GNU Taler extensions library', -) - -subdir('age_restriction') diff --git a/src/include/exchange-database/add_policy_fulfillment_proof.h b/src/include/exchange-database/add_policy_fulfillment_proof.h @@ -1,40 +0,0 @@ -/* - This file is part of TALER - Copyright (C) 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 src/include/exchange-database/add_policy_fulfillment_proof.h - * @brief implementation of the add_policy_fulfillment_proof function for Postgres - * @author Christian Grothoff - */ -#ifndef EXCHANGE_DATABASE_ADD_POLICY_FULFILLMENT_PROOF_H -#define EXCHANGE_DATABASE_ADD_POLICY_FULFILLMENT_PROOF_H - -#include "exchangedb_lib.h" -#include "taler/taler_extensions_policy.h" - - -/** - * Add a proof of fulfillment into the policy_fulfillments table - * - * @param pg the database context - * @param fulfillment fullfilment transaction data to be added - * @return query execution status - */ -enum GNUNET_DB_QueryStatus -TALER_EXCHANGEDB_add_policy_fulfillment_proof ( - struct TALER_EXCHANGEDB_PostgresContext *pg, - struct TALER_PolicyFulfillmentTransactionData *fulfillment); - -#endif diff --git a/src/include/exchange-database/get_extension_manifest.h b/src/include/exchange-database/get_extension_manifest.h @@ -1,42 +0,0 @@ -/* - This file is part of TALER - Copyright (C) 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 src/include/exchange-database/get_extension_manifest.h - * @brief implementation of the get_extension_manifest function for Postgres - * @author Christian Grothoff - */ -#ifndef EXCHANGE_DATABASE_GET_EXTENSION_MANIFEST_H -#define EXCHANGE_DATABASE_GET_EXTENSION_MANIFEST_H - -#include "exchangedb_lib.h" - - -/** - * Function called to get the manifest of an extension - * (age-restriction, policy_extension_...) - * - * @param pg the database context - * @param extension_name the name of the extension - * @param[out] manifest JSON object of the manifest as string - * @return transaction status code - */ -enum GNUNET_DB_QueryStatus -TALER_EXCHANGEDB_get_extension_manifest (struct - TALER_EXCHANGEDB_PostgresContext *pg, - const char *extension_name, - char **manifest); - -#endif diff --git a/src/include/exchange-database/get_policy_details.h b/src/include/exchange-database/get_policy_details.h @@ -1,42 +0,0 @@ -/* - This file is part of TALER - Copyright (C) 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 src/include/exchange-database/get_policy_details.h - * @brief implementation of the get_policy_details function for Postgres - * @author Christian Grothoff - */ -#ifndef EXCHANGE_DATABASE_GET_POLICY_DETAILS_H -#define EXCHANGE_DATABASE_GET_POLICY_DETAILS_H - -#include "exchangedb_lib.h" -#include "taler/taler_extensions_policy.h" - - -/** - * Get the details of a policy, referenced by its hash code - * - * @param pg the database context - * @param hc The hash code under which the details to a particular policy should be found - * @param[out] details The found details - * @return query execution status - * */ -enum GNUNET_DB_QueryStatus -TALER_EXCHANGEDB_get_policy_details (struct TALER_EXCHANGEDB_PostgresContext *pg - , - const struct GNUNET_HashCode *hc, - struct TALER_PolicyDetails *details); - -#endif diff --git a/src/include/exchange-database/persist_policy_details.h b/src/include/exchange-database/persist_policy_details.h @@ -1,52 +0,0 @@ -/* - This file is part of TALER - Copyright (C) 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 src/include/exchange-database/persist_policy_details.h - * @brief implementation of the persist_policy_details function for Postgres - * @author Christian Grothoff - */ -#ifndef EXCHANGE_DATABASE_PERSIST_POLICY_DETAILS_H -#define EXCHANGE_DATABASE_PERSIST_POLICY_DETAILS_H - -#include "taler/taler_util.h" -#include "taler/taler_json_lib.h" -#include "exchangedb_lib.h" -#include "taler/taler_extensions_policy.h" - - -/** - * Persist the details to a policy in the policy_details table. If there - * already exists a policy, update the fields accordingly. - * - * @param pg database connection - * @param details The policy details that should be persisted. If an entry for - * the given details->hash_code exists, the values will be updated. - * @param[out] policy_details_serial_id The row ID of the policy details - * @param[out] accumulated_total The total amount accumulated in that policy - * @param[out] fulfillment_state The state of policy. If the state was Insufficient prior to the call and the provided deposit raises the accumulated_total above the commitment, it will be set to Ready. - * @return query execution status - */ -enum GNUNET_DB_QueryStatus -TALER_EXCHANGEDB_persist_policy_details (struct - TALER_EXCHANGEDB_PostgresContext *pg, - const struct TALER_PolicyDetails * - details, - uint64_t *policy_details_serial_id, - struct TALER_Amount *accumulated_total, - enum TALER_PolicyFulfillmentState * - fulfillment_state); - -#endif diff --git a/src/include/exchange-database/set_extension_manifest.h b/src/include/exchange-database/set_extension_manifest.h @@ -1,43 +0,0 @@ -/* - This file is part of TALER - Copyright (C) 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 src/include/exchange-database/set_extension_manifest.h - * @brief implementation of the set_extension_manifest function for Postgres - * @author Christian Grothoff - */ -#ifndef EXCHANGE_DATABASE_SET_EXTENSION_MANIFEST_H -#define EXCHANGE_DATABASE_SET_EXTENSION_MANIFEST_H - -#include "exchangedb_lib.h" - - -/** - * Function called to save the manifest of an extension - * (age-restriction, policy_extension_...) After successful storage of the - * configuration it triggers the corresponding event. - * - * @param pg the database context - * @param extension_name the name of the extension - * @param manifest JSON object of the configuration as string - * @return transaction status code - */ -enum GNUNET_DB_QueryStatus -TALER_EXCHANGEDB_set_extension_manifest (struct - TALER_EXCHANGEDB_PostgresContext *pg, - const char *extension_name, - const char *manifest); - -#endif diff --git a/src/include/taler/exchange/get-keys.h b/src/include/taler/exchange/get-keys.h @@ -530,11 +530,6 @@ struct TALER_EXCHANGE_Keys struct TALER_MasterPublicKeyP master_pub; /** - * Signature over extension configuration data, if any. - */ - struct TALER_MasterSignatureP extensions_sig; - - /** * Array of the exchange's online signing keys. */ struct TALER_EXCHANGE_SigningPublicKey *sign_keys; @@ -555,11 +550,6 @@ struct TALER_EXCHANGE_Keys struct TALER_EXCHANGE_GlobalFee *global_fees; /** - * Configuration data for extensions. - */ - json_t *extensions; - - /** * Supported Taler protocol version by the exchange. * String in the format current:revision:age using the * semantics of GNU libtool. See diff --git a/src/include/taler/exchange/meson.build b/src/include/taler/exchange/meson.build @@ -32,7 +32,6 @@ talerexchange_headers = [ 'post-management-auditors-AUDITOR_PUB-disable.h', 'post-management-denominations-H_DENOM_PUB-revoke.h', 'post-management-drain.h', - 'post-management-extensions.h', 'post-management-global-fees.h', 'post-management-keys.h', 'post-management-partners.h', diff --git a/src/include/taler/exchange/post-management-extensions.h b/src/include/taler/exchange/post-management-extensions.h @@ -1,122 +0,0 @@ -/* - This file is part of TALER - Copyright (C) 2014-2026 Taler Systems SA - - TALER is free software; you can redistribute it and/or modify it under the - terms of the GNU Affero 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 Affero General Public License for more details. - - You should have received a copy of the GNU Affero General Public License along with - TALER; see the file COPYING. If not, see <http://www.gnu.org/licenses/> - */ -/** - * @file include/taler/exchange/post-management-extensions.h - * @brief C interface for POST /management/extensions - * @author Christian Grothoff - */ -#ifndef _TALER_EXCHANGE__POST_MANAGEMENT_EXTENSIONS_H -#define _TALER_EXCHANGE__POST_MANAGEMENT_EXTENSIONS_H - -#include <taler/exchange/common.h> - -/** - * Information needed for a POST /management/extensions operation. - * - * It represents the interface ExchangeKeysResponse as defined in - * https://docs.taler.net/design-documents/006-extensions.html#exchange - */ -struct TALER_EXCHANGE_ManagementPostExtensionsData -{ - const json_t *extensions; - struct TALER_MasterSignatureP extensions_sig; -}; - - -/** - * Handle for an operation to POST /management/extensions. - */ -struct TALER_EXCHANGE_PostManagementExtensionsHandle; - - -/** - * Set up POST /management/extensions operation. - * Note that you must explicitly start the operation after setup. - * - * @param ctx the context - * @param url HTTP base URL for the exchange - * @param ped extension configuration data to POST - * @return handle to operation, NULL on error - */ -struct TALER_EXCHANGE_PostManagementExtensionsHandle * -TALER_EXCHANGE_post_management_extensions_create ( - struct GNUNET_CURL_Context *ctx, - const char *url, - const struct TALER_EXCHANGE_ManagementPostExtensionsData *ped); - - -/** - * Response from a POST /management/extensions request. - */ -struct TALER_EXCHANGE_PostManagementExtensionsResponse -{ - /** - * HTTP response data - */ - struct TALER_EXCHANGE_HttpResponse hr; -}; - - -#ifndef TALER_EXCHANGE_POST_MANAGEMENT_EXTENSIONS_RESULT_CLOSURE -/** - * Type of the closure used by - * the #TALER_EXCHANGE_PostManagementExtensionsCallback. - */ -#define TALER_EXCHANGE_POST_MANAGEMENT_EXTENSIONS_RESULT_CLOSURE void -#endif /* TALER_EXCHANGE_POST_MANAGEMENT_EXTENSIONS_RESULT_CLOSURE */ - -/** - * Type of the function that receives the result of a - * POST /management/extensions request. - * - * @param cls closure - * @param result result returned by the HTTP server - */ -typedef void -(*TALER_EXCHANGE_PostManagementExtensionsCallback)( - TALER_EXCHANGE_POST_MANAGEMENT_EXTENSIONS_RESULT_CLOSURE *cls, - const struct TALER_EXCHANGE_PostManagementExtensionsResponse *result); - - -/** - * Start POST /management/extensions operation. - * - * @param[in,out] pmeh operation to start - * @param cb function to call with the exchange's result - * @param cb_cls closure for @a cb - * @return status code, #TALER_EC_NONE on success - */ -enum TALER_ErrorCode -TALER_EXCHANGE_post_management_extensions_start ( - struct TALER_EXCHANGE_PostManagementExtensionsHandle *pmeh, - TALER_EXCHANGE_PostManagementExtensionsCallback cb, - TALER_EXCHANGE_POST_MANAGEMENT_EXTENSIONS_RESULT_CLOSURE *cb_cls); - - -/** - * Cancel POST /management/extensions operation. This function must not be - * called by clients after the - * TALER_EXCHANGE_PostManagementExtensionsCallback has been invoked (as in - * those cases it'll be called internally by the implementation already). - * - * @param[in] pmeh operation to cancel - */ -void -TALER_EXCHANGE_post_management_extensions_cancel ( - struct TALER_EXCHANGE_PostManagementExtensionsHandle *pmeh); - - -#endif /* _TALER_EXCHANGE__POST_MANAGEMENT_EXTENSIONS_H */ diff --git a/src/include/taler/meson.build b/src/include/taler/meson.build @@ -10,8 +10,6 @@ talerinclude_headers = [ 'taler_dbevents.h', 'taler_error_codes.h', 'taler_exchange_service.h', - 'taler_extensions.h', - 'taler_extensions_policy.h', 'taler_fakebank_lib.h', 'taler_kyclogic_lib.h', 'taler_kyclogic_plugin.h', diff --git a/src/include/taler/taler_exchange_service.h b/src/include/taler/taler_exchange_service.h @@ -55,7 +55,6 @@ #include <taler/exchange/post-kyc-wallet.h> /* UNNECESSARY? */ #include <taler/exchange/get-management-keys.h> /* UNNECESSARY? */ #include <taler/exchange/post-management-keys.h> /* UNNECESSARY? */ -#include <taler/exchange/post-management-extensions.h> /* UNNECESSARY? */ #include <taler/exchange/post-management-drain.h> /* UNNECESSARY? */ #include \ <taler/exchange/post-management-denominations-H_DENOM_PUB-revoke.h> diff --git a/src/include/taler/taler_extensions.h b/src/include/taler/taler_extensions.h @@ -1,385 +0,0 @@ -/* - This file is part of TALER - Copyright (C) 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 include/taler/taler_extensions.h - * @brief Interface for extensions - * @author Özgür Kesim - */ -#ifndef TALER_EXTENSIONS_H -#define TALER_EXTENSIONS_H - -#include <gnunet/gnunet_util_lib.h> -#include <taler/taler_json_lib.h> -#include <taler/taler_mhd_lib.h> -#include <taler/taler_extensions_policy.h> - - -#define TALER_EXTENSION_SECTION_PREFIX "exchange-extension-" - -enum TALER_Extension_Type -{ - TALER_Extension_PolicyNull = 0, - - TALER_Extension_AgeRestriction = 1, - TALER_Extension_PolicyMerchantRefund = 2, - TALER_Extension_PolicyBrandtVickeryAuction = 3, - TALER_Extension_PolicyEscrowedPayment = 4, - - TALER_Extension_MaxPredefined = 5 // Must be last of the predefined -}; - - -/* Forward declarations */ -enum TALER_PolicyFulfillmentState; -struct TALER_PolicyFulfillmentOutcome; - -/* - * @brief Represents the implementation of an extension. - * - * An "Extension" is an optional feature for the Exchange. - * There are only two types of extensions: - * - * a) Age restriction: This is a special feature that directly interacts with - * denominations and coins, but is not define policies during deposits, see b). - * The implementation of this extension doesn't have to implement any of the - * http- or depost-handlers in the struct. - * - * b) Policies for deposits: These are extensions that define policies (such - * as refund, escrow or auctions) for deposit requests. These extensions have - * to implement at least the deposit- and post-http-handler in the struct to be - * functional. - * - * In addition to the handlers defined in this struct, an extension must also - * be a plugin in the GNUNET_Plugin sense. That is, it must implement the - * functions - * 1: (void *ext)libtaler_extension_<name>_init(void *cfg) - * and - * 2: (void *)libtaler_extension_<name>_done(void *) - * - * In 1:, the input will be the GNUNET_CONFIGURATION_Handle to the TALER - * configuration and the output must be the struct TALER_Extension * on - * success, NULL otherwise. - * - * In 2:, no arguments are passed and NULL is expected to be returned. - */ -struct TALER_Extension -{ - /** - * Type of the extension. Only one extension of a type can be loaded - * at any time. - */ - enum TALER_Extension_Type type; - - /** - * The name of the extension, must be unique among all loaded extensions. It - * is used in URLs for /extension/$NAME as well. - */ - const char *name; - - /** - * Criticality of the extension. It has the same semantics as "critical" has - * for extensions in X.509: - * - if "true", the client must "understand" the extension before proceeding, - * - if "false", clients can safely skip extensions they do not understand. - * (see https://datatracker.ietf.org/doc/html/rfc5280#section-4.2) - */ - bool critical; - - /** - * Version of the extension must be provided in Taler's protocol version ranges notation, see - * https://docs.taler.net/core/api-common.html#protocol-version-ranges - */ - const char *version; - - /** - * If the extension is marked as enabled, it will be listed in the - * "extensions" field in the "/keys" response. - */ - bool enabled; - - /** - * Opaque (public) configuration object, set by the extension. - */ - void *config; - - - /** - * @brief Handler to to disable the extension. - * - * @param ext The current extension object - */ - void (*disable)(struct TALER_Extension *ext); - - /** - * @brief Handler to read an extension-specific configuration in JSON - * encoding and enable the extension. Must be implemented by the extension. - * - * @param[in] ext The extension object. If NULL, the configuration will only be checked. - * @param[in,out] config A JSON blob - * @return GNUNET_OK if the json was a valid configuration for the extension. - */ - enum GNUNET_GenericReturnValue (*load_config)( - const json_t *config, - struct TALER_Extension *ext); - - /** - * @brief Handler to return the manifest of the extension in JSON encoding. - * - * See - * https://docs.taler.net/design-documents/006-extensions.html#tsref-type-Extension - * for the definition. - * - * @param ext The extension object - * @return The JSON encoding of the extension, if enabled, NULL otherwise. - */ - json_t *(*manifest)( - const struct TALER_Extension *ext); - - /* ========================= - * Policy related handlers - * ========================= - */ - - /** - * @brief Handler to check an incoming policy and create a - * TALER_PolicyDetails. Can be NULL; - * - * When a deposit request refers to this extension in its policy - * (see https://docs.taler.net/core/api-exchange.html#deposit), this handler - * will be called before the deposit transaction. - * - * @param[in] currency Currency used in the exchange - * @param[in] policy_json Details about the policy, provided by the client - * during a deposit request. - * @param[out] details On success, will contain the details to the policy, - * evaluated by the corresponding policy handler. - * @param[out] error_hint On error, will contain a hint - * @return GNUNET_OK if the data was accepted by the extension. - */ - enum GNUNET_GenericReturnValue (*create_policy_details)( - const char *currency, - const json_t *policy_json, - struct TALER_PolicyDetails *details, - const char **error_hint); - - /** - * @brief Handler for POST-requests to the /extensions/$name endpoint. Can be NULL. - * - * @param[in] root The JSON body from the request - * @param[in] args Additional query parameters of the request. - * @param[in,out] details List of policy details related to the incoming fulfillment proof - * @param[in] details_len Size of the list @e details - * @param[out] output JSON output to return to the client - * @return GNUNET_OK on success. - */ - enum GNUNET_GenericReturnValue (*policy_post_handler)( - const json_t *root, - const char *const args[], - struct TALER_PolicyDetails *details, - size_t details_len, - json_t **output); - - /** - * @brief Handler for GET-requests to the /extensions/$name endpoint. Can be NULL. - * - * @param connection The current connection - * @param root The JSON body from the request - * @param args Additional query parameters of the request. - * @return MDH result - */ - enum MHD_Result (*policy_get_handler)( - struct MHD_Connection *connection, - const char *const args[]); -}; - - -/* - * @brief simply linked list of extensions - */ - -struct TALER_Extensions -{ - struct TALER_Extensions *next; - const struct TALER_Extension *extension; -}; - -/** - * Generic functions for extensions - */ - -/** - * @brief Loads the extensions as shared libraries, as specified in the given - * TALER configuration. - * - * @param cfg Handle to the TALER configuration - * @return #GNUNET_OK on success, #GNUNET_SYSERR if unknown extensions were found - * or any particular configuration couldn't be parsed. - */ -enum GNUNET_GenericReturnValue -TALER_extensions_init ( - const struct GNUNET_CONFIGURATION_Handle *cfg); - -/* - * @brief Parses a given JSON object as an extension manifest. - * - * @param[in] obj JSON object to parse as an extension manifest - * @param{out] critical will be set to 1 if the extension is critical according to obj - * @param[out] version will be set to the version of the extension according to obj - * @param[out] config will be set to the configuration of the extension according to obj - * @return OK on success, Error otherwise - */ -enum GNUNET_GenericReturnValue -TALER_extensions_parse_manifest ( - json_t *obj, - int *critical, - const char **version, - json_t **config); - -/* - * @brief Loads extensions according to the manifests. - * - * The JSON object must be of type ExtensionsManifestsResponse as described - * in https://docs.taler.net/design-documents/006-extensions.html#exchange - * - * @param cfg JSON object containing the manifests for all extensions - * @return #GNUNET_OK on success, #GNUNET_SYSERR if unknown extensions were - * found or any particular configuration couldn't be parsed. - */ -enum GNUNET_GenericReturnValue -TALER_extensions_load_manifests ( - const json_t *manifests); - -/* - * @brief Returns the head of the linked list of extensions. - */ -const struct TALER_Extensions * -TALER_extensions_get_head (void); - -/** - * @brief Finds and returns a supported extension by a given type. - * - * @param type of the extension to lookup - * @return extension found, or NULL (should not happen!) - */ -const struct TALER_Extension * -TALER_extensions_get_by_type ( - enum TALER_Extension_Type type); - - -/** - * @brief Finds and returns a supported extension by a given name. - * - * @param name name of the extension to lookup - * @return the extension, if found, NULL otherwise - */ -const struct TALER_Extension * -TALER_extensions_get_by_name ( - const char *name); - -/** - * @brief Check if a given type of an extension is enabled - * - * @param type type of to check - * @return true enabled, false if not enabled, will assert if type is not found. - */ -bool -TALER_extensions_is_enabled_type ( - enum TALER_Extension_Type type); - -/** - * @brief Check if an extension is enabled - * - * @param extension The extension handler. - * @return true enabled, false if not enabled, will assert if type is not found. - */ -bool -TALER_extensions_is_enabled ( - const struct TALER_Extension *extension); - -/* - * Verify the signature of a given JSON object for extensions with the master - * key of the exchange. - * - * The JSON object must be of type ExtensionsManifestsResponse as described in - * https://docs.taler.net/design-documents/006-extensions.html#exchange - * - * @param extensions JSON object with the extension configuration - * @param extensions_sig signature of the hash of the JSON object - * @param master_pub public key to verify the signature - * @return GNUNET_OK on success, GNUNET_SYSERR when hashing of the JSON fails - * and GNUNET_NO if the signature couldn't be verified. - */ -enum GNUNET_GenericReturnValue -TALER_extensions_verify_manifests_signature ( - const json_t *manifests, - struct TALER_MasterSignatureP *extensions_sig, - struct TALER_MasterPublicKeyP *master_pub); - - -/* - * TALER Age Restriction Extension - * - * This extension is special insofar as it directly interacts with coins and - * denominations. - * - * At the same time, it doesn't implement and http- or deposit-handlers. - */ - -#define TALER_EXTENSION_SECTION_AGE_RESTRICTION (TALER_EXTENSION_SECTION_PREFIX \ - "age_restriction") - -/** - * The default age mask represents the age groups - * 0-7, 8-9, 10-11, 12-13, 14-15, 16-17, 18-20, 21-... - */ -#define TALER_EXTENSION_AGE_RESTRICTION_DEFAULT_AGE_GROUPS "8:10:12:14:16:18:21" - - -/* - * @brief Configuration for Age Restriction - */ -struct TALER_AgeRestrictionConfig -{ - struct TALER_AgeMask mask; - uint8_t num_groups; -}; - - -/** - * @brief Retrieve the age restriction configuration - * - * @return age restriction configuration if present, otherwise NULL. - */ -const struct TALER_AgeRestrictionConfig * -TALER_extensions_get_age_restriction_config (void); - -/** - * @brief Check if age restriction is enabled - * - * @return true, if age restriction is loaded, configured and enabled; otherwise false. - */ -bool -TALER_extensions_is_age_restriction_enabled (void); - -/** - * @brief Return the age mask for age restriction - * - * @return configured age mask, if age restriction is loaded, configured and enabled; otherwise zero mask. - */ -struct TALER_AgeMask -TALER_extensions_get_age_restriction_mask (void); - -#endif diff --git a/src/include/taler/taler_extensions_policy.h b/src/include/taler/taler_extensions_policy.h @@ -1,204 +0,0 @@ -/* - This file is part of TALER - Copyright (C) 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 include/taler/taler_extensions_policy.h - * @brief Interface for policy extensions - * @author Özgür Kesim - */ -#ifndef TALER_EXTENSIONS_POLICY_H -#define TALER_EXTENSIONS_POLICY_H - -#include <gnunet/gnunet_util_lib.h> -#include <taler/taler_util.h> - - -/* - * @brief Describes the states of fulfillment of a policy bound to a deposit - * NOTE: These values must be in sync with their use in stored procedures, f.e. - * exchange_do_insert_or_update_policy_details. - */ -enum TALER_PolicyFulfillmentState -{ - /* Initial state of an fulfillment, before any other state. */ - TALER_PolicyFulfillmentInitial = 0, - - /* General error state of an fulfillment. */ - TALER_PolicyFulfillmentFailure = 1, - - /* The policy is not yet ready due to insufficient funding. More deposits are - * necessary for it to become ready . */ - TALER_PolicyFulfillmentInsufficient = 2, - - /* The policy is funded and ready, pending */ - TALER_PolicyFulfillmentReady = 3, - - /* Policy is provably fulfilled. */ - TALER_PolicyFulfillmentSuccess = 4, - - /* Policy fulfillment has timed out */ - TALER_PolicyFulfillmentTimeout = 5, - - TALER_PolicyFulfillmentStateCount = TALER_PolicyFulfillmentTimeout + 1 -}; - - -/* - * @brief Returns a string representation of the state of a policy fulfillment - */ -const char * -TALER_policy_fulfillment_state_str (enum TALER_PolicyFulfillmentState state); - - -/* @brief Details of a policy for a deposit request */ -struct TALER_PolicyDetails -{ - /* Hash code that should be used for the .policy_hash_code field when - * this policy is saved in the policy_details table. */ - struct GNUNET_HashCode hash_code; - - /* Content of the policy in its original JSON form */ - json_t *policy_json; - - /* When the deadline is met and the policy is still in "Ready" state, - * a timeout-handler will transfer the amount - * (total_amount - policy_fee - refreshable_amount) - * to the payto-URI from the corresponding deposit. The value - * amount_refreshable will be refreshable by the owner of the - * associated deposits's coins */ - struct GNUNET_TIME_Timestamp deadline; - - /* The amount to which this policy commits to. It must be at least as - * large as @e policy_fee. */ - struct TALER_Amount commitment; - - /* The total sum of contributions from coins so far to fund this - * policy. It must be at least as large as @commitment in order to be - * sufficiently funded. */ - struct TALER_Amount accumulated_total; - - /* The fee from the exchange for handling the policy. It is due when - * the state changes to Timeout or Success. */ - struct TALER_Amount policy_fee; - - /* The amount that will be transferred to the payto-URIs from the - * corresponding deposits when the fulfillment state changes to Timeout - * or Success. Note that a fulfillment handler can alter this upon - * arrival of a proof of fulfillment. The remaining amount - * (accumulated_amount - policy_amount - transferable_amount) */ - struct TALER_Amount transferable_amount; - - /* The state of fulfillment of a policy. - * - If the state is Insufficient, the client is required to call - * /deposit -maybe multiple times- with enough coins and the same - * policy details in order to reach the required amount. The state is - * then changed to Ready. - * - If the state changes to Timeout or Success, a handler will transfer - * the amount (total_amount - policy_fee - refreshable_amount) to the - * payto-URI from the corresponding deposit. The value - * amount_refreshable will be refreshable by the owner of the - * associated deposits's coins. */ - enum TALER_PolicyFulfillmentState fulfillment_state; - - /* If there is a proof of fulfillment, the row ID from the - * policy_fulfillment table */ - uint64_t policy_fulfillment_id; - bool no_policy_fulfillment_id; -}; - -/** - * @brief All information required for the database transaction when handling a - * proof of fulfillment request. - */ -struct TALER_PolicyFulfillmentTransactionData -{ - /* The incoming proof, provided by a client */ - const json_t *proof; - - /* The Hash of the proof */ - struct GNUNET_HashCode h_proof; - - /* The timestamp of retrieval of the proof */ - struct GNUNET_TIME_Timestamp timestamp; - - /* The ID of the proof in the policy_fulfillment table. Will be set - * during the transaction. Needed to fill the table - * policy_details_fulfillments. */ - uint64_t fulfillment_id; - - /* The list of policy details. Will be updated by the policy handler */ - struct TALER_PolicyDetails *details; - size_t details_count; -}; - - -/* - * @brief Extracts policy details from the deposit's policy options and the policy extensions - * - * @param[in] currency Currency used in the exchange - * @param[in] policy_options JSON of the policy options from a deposit request - * @param[out] details On GNUNET_OK, the parsed details - * @param[out] error_hint On GNUNET_SYSERR, will contain a hint for the reason why it failed - * @return GNUNET_OK on success, GNUNET_NO, when no extension was found. GNUNET_SYSERR when the JSON was - * invalid, with *error_hint maybe non-NULL. - */ -enum GNUNET_GenericReturnValue -TALER_extensions_create_policy_details ( - const char *currency, - const json_t *policy_options, - struct TALER_PolicyDetails *details, - const char **error_hint); - - -/* - * ================================ - * Merchant refund policy - * ================================ - */ -struct TALER_ExtensionPolicyMerchantRefundPolicyConfig -{ - struct GNUNET_TIME_Relative max_timeout; -}; - -/* - * ================================ - * Brandt-Vickrey Auctions policy - * ================================ - */ -/* - * @brief Configuration for Brandt-Vickrey auctions policy - */ -struct TALER_ExtensionPolicyBrandtVickreyAuctionConfig -{ - uint16_t max_bidders; - uint16_t max_prices; - struct TALER_Amount auction_fee; -}; - - -/* - * ================================ - * Escrowed Payments policy - * ================================ - */ -/* - * @brief Configuration for escrowed payments policy - */ -struct TALER_ExtensionPolicyEscrowedPaymentsConfig -{ - struct GNUNET_TIME_Relative max_timeout; -}; - -#endif diff --git a/src/include/taler/taler_testing_lib.h b/src/include/taler/taler_testing_lib.h @@ -123,6 +123,14 @@ /** + * Age restriction mask for the exchange under test. + * Set by TALER_TESTING_run_with_fakebank() when AGE_RESTRICTION_ENABLED + * is set in the [exchange] config section. + */ +extern struct TALER_AgeMask TALER_testing_age_restriction_mask; + + +/** * Common credentials used in a test. */ struct TALER_TESTING_Credentials @@ -2111,20 +2119,6 @@ TALER_TESTING_cmd_wire_del (const char *label, bool bad_sig); /** - * Sign all extensions that the exchange has to offer, f. e. the extension for - * age restriction. This has to be run before any withdrawal of age restricted - * can be performed. - * - * @param label command label. - * @param config_filename configuration filename. - * @return the command - */ -struct TALER_TESTING_Command -TALER_TESTING_cmd_exec_offline_sign_extensions (const char *label, - const char *config_filename); - - -/** * Sign all exchange denomination and online signing keys * with the "offline" key and provide those signatures to * the exchange. (Downloads the keys, makes the signature diff --git a/src/lib/exchange_api_handle.c b/src/lib/exchange_api_handle.c @@ -28,7 +28,6 @@ #include "taler/taler_json_lib.h" #include "taler/taler_auditor_service.h" #include "taler/taler_signatures.h" -#include "taler/taler_extensions.h" #include "exchange_api_handle.h" #include "taler/taler_curl_lib.h" @@ -918,9 +917,6 @@ TALER_EXCHANGE_decode_keys_json_ ( const json_t *denominations_by_group; const json_t *auditors_array; const json_t *recoup_array = NULL; - const json_t *manifests = NULL; - bool no_extensions = false; - bool no_signature = false; const json_t *accounts; const json_t *fees; const json_t *wads; @@ -1027,15 +1023,6 @@ TALER_EXCHANGE_decode_keys_json_ ( GNUNET_JSON_spec_bool ( "kyc_enabled", &key_data->kyc_enabled), - GNUNET_JSON_spec_mark_optional ( - GNUNET_JSON_spec_object_const ("extensions", - &manifests), - &no_extensions), - GNUNET_JSON_spec_mark_optional ( - GNUNET_JSON_spec_fixed_auto ( - "extensions_sig", - &key_data->extensions_sig), - &no_signature), GNUNET_JSON_spec_string ("version", &ver), GNUNET_JSON_spec_mark_optional ( @@ -1156,8 +1143,6 @@ TALER_EXCHANGE_decode_keys_json_ ( if (NULL != bank_compliance_language) key_data->bank_compliance_language = GNUNET_strdup (bank_compliance_language); - if (! no_extensions) - key_data->extensions = json_incref ((json_t *) manifests); } /* parse the global fees */ @@ -1259,32 +1244,6 @@ TALER_EXCHANGE_decode_keys_json_ ( key_data)); - /* Parse the supported extension(s): age-restriction. */ - /* FIXME[Oec]: maybe lift all this into a FP in TALER_Extension ? */ - if (! no_extensions) - { - if (no_signature) - { - GNUNET_log (GNUNET_ERROR_TYPE_WARNING, - "found extensions without signature\n"); - } - else - { - /* We have an extensions object. Verify its signature. */ - EXITIF (GNUNET_OK != - TALER_extensions_verify_manifests_signature ( - manifests, - &key_data->extensions_sig, - &key_data->master_pub)); - - /* Parse and set the the configuration of the extensions accordingly */ - EXITIF (GNUNET_OK != - TALER_extensions_load_manifests (manifests)); - } - - /* Assuming we might have now a new value for age_mask, set it in key_data */ - key_data->age_mask = TALER_extensions_get_age_restriction_mask (); - } /* * Parse the denomination keys, merging with the @@ -1387,6 +1346,16 @@ TALER_EXCHANGE_decode_keys_json_ ( } /* end of json_array_foreach over groups of denominations */ } /* end of scope for group_ojb/group_idx */ + /* Derive global age_mask from denomination keys */ + for (unsigned int i = 0; i < key_data->num_denom_keys; i++) + { + if (0 != key_data->denom_keys[i].key.age_mask.bits) + { + key_data->age_mask = key_data->denom_keys[i].key.age_mask; + break; + } + } + /* parse the auditor information */ { json_t *auditor_info; @@ -1694,7 +1663,6 @@ TALER_EXCHANGE_keys_decref (struct TALER_EXCHANGE_Keys *keys) GNUNET_array_grow (keys->zero_limits, keys->zero_limits_length, 0); - json_decref (keys->extensions); GNUNET_free (keys->cspec.name); json_decref (keys->cspec.map_alt_unit_names); GNUNET_array_grow (keys->cspec.common_amounts, @@ -2361,15 +2329,6 @@ TALER_EXCHANGE_keys_to_json (const struct TALER_EXCHANGE_Keys *kd) GNUNET_JSON_pack_bool ("kyc_enabled", kd->kyc_enabled), GNUNET_JSON_pack_allow_null ( - GNUNET_JSON_pack_object_incref ("extensions", - kd->extensions)), - GNUNET_JSON_pack_allow_null ( - GNUNET_is_zero (&kd->extensions_sig) - ? GNUNET_JSON_pack_string ("dummy", - NULL) - : GNUNET_JSON_pack_data_auto ("extensions_sig", - &kd->extensions_sig)), - GNUNET_JSON_pack_allow_null ( GNUNET_JSON_pack_array_steal ("wallet_balance_limit_without_kyc", wblwk)) diff --git a/src/lib/exchange_api_post-management-extensions.c b/src/lib/exchange_api_post-management-extensions.c @@ -1,251 +0,0 @@ -/* - This file is part of TALER - Copyright (C) 2015-2026 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 lib/exchange_api_post-management-extensions.c - * @brief functions to handle the settings for extensions (p2p and age restriction) - * @author Özgür Kesim - */ -#include "taler/taler_json_lib.h" -#include <gnunet/gnunet_curl_lib.h> -#include "taler/taler_extensions.h" -#include "taler/exchange/post-management-extensions.h" -#include "exchange_api_curl_defaults.h" -#include "taler/taler_curl_lib.h" - - -/** - * @brief Handle for a POST /management/extensions request. - */ -struct TALER_EXCHANGE_PostManagementExtensionsHandle -{ - - /** - * The base URL for this request. - */ - char *base_url; - - /** - * The full URL for this request, set during _start. - */ - char *url; - - /** - * Minor context that holds body and headers. - */ - struct TALER_CURL_PostContext post_ctx; - - /** - * Handle for the request. - */ - struct GNUNET_CURL_Job *job; - - /** - * Function to call with the result. - */ - TALER_EXCHANGE_PostManagementExtensionsCallback cb; - - /** - * Closure for @a cb. - */ - TALER_EXCHANGE_POST_MANAGEMENT_EXTENSIONS_RESULT_CLOSURE *cb_cls; - - /** - * Reference to the execution context. - */ - struct GNUNET_CURL_Context *ctx; - - /** - * Extension configuration data (we hold a reference). - */ - json_t *extensions; - - /** - * Signature over the extension configuration. - */ - struct TALER_MasterSignatureP extensions_sig; - -}; - - -/** - * Function called when we're done processing the - * HTTP POST /management/extensions request. - * - * @param cls the `struct TALER_EXCHANGE_PostManagementExtensionsHandle` - * @param response_code HTTP response code, 0 on error - * @param response response body, NULL if not in JSON - */ -static void -handle_post_extensions_finished (void *cls, - long response_code, - const void *response) -{ - struct TALER_EXCHANGE_PostManagementExtensionsHandle *pmeh = cls; - const json_t *json = response; - struct TALER_EXCHANGE_PostManagementExtensionsResponse res = { - .hr.http_status = (unsigned int) response_code, - .hr.reply = json - }; - - pmeh->job = NULL; - switch (response_code) - { - case MHD_HTTP_NO_CONTENT: - break; - case MHD_HTTP_FORBIDDEN: - res.hr.ec = TALER_JSON_get_error_code (json); - res.hr.hint = TALER_JSON_get_error_hint (json); - break; - case MHD_HTTP_NOT_FOUND: - GNUNET_log (GNUNET_ERROR_TYPE_ERROR, - "Server did not find handler at `%s'. Did you configure the correct exchange base URL?\n", - pmeh->url); - if (NULL != json) - { - res.hr.ec = TALER_JSON_get_error_code (json); - res.hr.hint = TALER_JSON_get_error_hint (json); - } - else - { - res.hr.ec = TALER_EC_GENERIC_INVALID_RESPONSE; - res.hr.hint = TALER_ErrorCode_get_hint (res.hr.ec); - } - break; - default: - /* unexpected response code */ - GNUNET_break_op (0); - res.hr.ec = TALER_JSON_get_error_code (json); - res.hr.hint = TALER_JSON_get_error_hint (json); - GNUNET_log (GNUNET_ERROR_TYPE_ERROR, - "Unexpected response code %u/%d for exchange management post extensions\n", - (unsigned int) response_code, - (int) res.hr.ec); - break; - } - if (NULL != pmeh->cb) - { - pmeh->cb (pmeh->cb_cls, - &res); - pmeh->cb = NULL; - } - TALER_EXCHANGE_post_management_extensions_cancel (pmeh); -} - - -struct TALER_EXCHANGE_PostManagementExtensionsHandle * -TALER_EXCHANGE_post_management_extensions_create ( - struct GNUNET_CURL_Context *ctx, - const char *url, - const struct TALER_EXCHANGE_ManagementPostExtensionsData *ped) -{ - struct TALER_EXCHANGE_PostManagementExtensionsHandle *pmeh; - - pmeh = GNUNET_new (struct TALER_EXCHANGE_PostManagementExtensionsHandle); - pmeh->ctx = ctx; - pmeh->base_url = GNUNET_strdup (url); - pmeh->extensions = json_incref ((json_t *) ped->extensions); - pmeh->extensions_sig = ped->extensions_sig; - return pmeh; -} - - -enum TALER_ErrorCode -TALER_EXCHANGE_post_management_extensions_start ( - struct TALER_EXCHANGE_PostManagementExtensionsHandle *pmeh, - TALER_EXCHANGE_PostManagementExtensionsCallback cb, - TALER_EXCHANGE_POST_MANAGEMENT_EXTENSIONS_RESULT_CLOSURE *cb_cls) -{ - CURL *eh = NULL; - json_t *body = NULL; - json_t *extensions; - - pmeh->cb = cb; - pmeh->cb_cls = cb_cls; - pmeh->url = TALER_url_join (pmeh->base_url, - "management/extensions", - NULL); - if (NULL == pmeh->url) - { - GNUNET_log (GNUNET_ERROR_TYPE_ERROR, - "Could not construct request URL.\n"); - return TALER_EC_GENERIC_CONFIGURATION_INVALID; - } - /* Transfer our reference to the body via steal; set to NULL first */ - extensions = pmeh->extensions; - pmeh->extensions = NULL; - body = GNUNET_JSON_PACK ( - GNUNET_JSON_pack_object_steal ("extensions", - extensions), - GNUNET_JSON_pack_data_auto ("extensions_sig", - &pmeh->extensions_sig)); - eh = TALER_EXCHANGE_curl_easy_get_ (pmeh->url); - if ( (NULL == eh) || - (GNUNET_OK != - TALER_curl_easy_post (&pmeh->post_ctx, - eh, - body)) ) - { - GNUNET_break (0); - if (NULL != eh) - curl_easy_cleanup (eh); - json_decref (body); - GNUNET_free (pmeh->url); - pmeh->url = NULL; - return TALER_EC_GENERIC_INTERNAL_INVARIANT_FAILURE; - } - json_decref (body); - GNUNET_log (GNUNET_ERROR_TYPE_INFO, - "Requesting URL '%s'\n", - pmeh->url); - pmeh->job = GNUNET_CURL_job_add2 (pmeh->ctx, - eh, - pmeh->post_ctx.headers, - &handle_post_extensions_finished, - pmeh); - if (NULL == pmeh->job) - { - TALER_curl_easy_post_finished (&pmeh->post_ctx); - GNUNET_free (pmeh->url); - pmeh->url = NULL; - return TALER_EC_GENERIC_INTERNAL_INVARIANT_FAILURE; - } - return TALER_EC_NONE; -} - - -void -TALER_EXCHANGE_post_management_extensions_cancel ( - struct TALER_EXCHANGE_PostManagementExtensionsHandle *pmeh) -{ - if (NULL != pmeh->job) - { - GNUNET_CURL_job_cancel (pmeh->job); - pmeh->job = NULL; - } - TALER_curl_easy_post_finished (&pmeh->post_ctx); - if (NULL != pmeh->extensions) - { - json_decref (pmeh->extensions); - pmeh->extensions = NULL; - } - GNUNET_free (pmeh->url); - GNUNET_free (pmeh->base_url); - GNUNET_free (pmeh); -} - - -/* end of exchange_api_post-management-extensions.c */ diff --git a/src/lib/meson.build b/src/lib/meson.build @@ -37,7 +37,6 @@ libtalerexchange_la_SOURCES = [ 'exchange_api_post-management-auditors.c', 'exchange_api_post-management-denominations-H_DENOM_PUB-revoke.c', 'exchange_api_post-management-drain.c', - 'exchange_api_post-management-extensions.c', 'exchange_api_post-management-global-fees.c', 'exchange_api_post-management-keys.c', 'exchange_api_post-management-partners.c', @@ -108,7 +107,6 @@ libtalerexchange = library( libtalerauditor_dep, libtalerkyclogic_dep, libtalercurl_dep, - libtalerextensions_dep, libtalerjson_dep, libtalerutil_dep, gnunetutil_dep, diff --git a/src/meson.build b/src/meson.build @@ -9,7 +9,6 @@ configure_file( subdir('include') subdir('util') subdir('json') -subdir('extensions') subdir('curl') subdir('pq') if sqlite_dep.found() diff --git a/src/testing/meson.build b/src/testing/meson.build @@ -60,7 +60,6 @@ libtalertesting_la_SOURCES = [ 'testing_api_cmd_offline_sign_global_fees.c', 'testing_api_cmd_offline_sign_wire_fees.c', 'testing_api_cmd_offline_sign_keys.c', - 'testing_api_cmd_offline_sign_extensions.c', 'testing_api_cmd_post_kyc_form.c', 'testing_api_cmd_post_kyc_start.c', 'testing_api_cmd_purse_create_deposit.c', @@ -111,7 +110,6 @@ libtalertesting = library( libtalerexchange_dep, libtalerexchangedb_dep, libtalermhd_dep, - libtalerextensions_dep, libtalerbank_dep, libtalerfakebank_dep, libtalerkyclogic_dep, @@ -155,7 +153,6 @@ if twister_dep.found() libtalerauditor_dep, libtalerexchange_dep, libtalerexchangedb_dep, - libtalerextensions_dep, libtalermhd_dep, libtalerjson_dep, libtalerutil_dep, @@ -357,7 +354,6 @@ test_exchange_api_cs = executable( libtalerfakebank_dep, libtalerjson_dep, libtalerutil_dep, - libtalerextensions_dep, json_dep, gcrypt_dep, gnunetutil_dep, @@ -382,7 +378,6 @@ test_exchange_api_rsa = executable( dependencies: [ libtalertesting_dep, libtalerexchange_dep, - libtalerextensions_dep, libtalerbank_dep, libtalerfakebank_dep, libtalerjson_dep, @@ -412,7 +407,6 @@ test_exchange_api_age_restriction_cs = executable( dependencies: [ libtalertesting_dep, libtalerexchange_dep, - libtalerextensions_dep, libtalerbank_dep, libtalerfakebank_dep, libtalerjson_dep, @@ -441,7 +435,6 @@ test_exchange_api_age_restriction_rsa = executable( dependencies: [ libtalertesting_dep, libtalerexchange_dep, - libtalerextensions_dep, libtalerbank_dep, libtalerfakebank_dep, libtalerjson_dep, @@ -470,7 +463,6 @@ test_exchange_api_p2p_cs = executable( dependencies: [ libtalertesting_dep, libtalerexchange_dep, - libtalerextensions_dep, libtalerbank_dep, libtalerfakebank_dep, libtalerjson_dep, @@ -499,7 +491,6 @@ test_exchange_api_p2p_rsa = executable( dependencies: [ libtalertesting_dep, libtalerexchange_dep, - libtalerextensions_dep, libtalerbank_dep, libtalerfakebank_dep, libtalerjson_dep, diff --git a/src/testing/test_exchange_api.c b/src/testing/test_exchange_api.c @@ -31,7 +31,6 @@ #include <microhttpd.h> #include "taler/taler_bank_service.h" #include "taler/taler_testing_lib.h" -#include "taler/taler_extensions.h" /** * Configuration file we use. One (big) configuration is used diff --git a/src/testing/test_exchange_api.conf b/src/testing/test_exchange_api.conf @@ -68,6 +68,8 @@ ENABLE_KYC = YES DISABLE_DIRECT_DEPOSIT = NO DB = postgres BASE_URL = http://localhost:8081/ +AGE_RESTRICTION_ENABLED = YES +#AGE_GROUPS = "8:10:12:14:16:18:21" [exchangedb-postgres] CONFIG = "postgres:///talercheck" @@ -395,6 +397,3 @@ TIMEFRAME = 1d # personal data via OAuth2 NEXT_MEASURES = run-oauth -[exchange-extension-age_restriction] -ENABLED = YES -#AGE_GROUPS = "8:10:12:14:16:18:21" diff --git a/src/testing/test_exchange_api_age_restriction.c b/src/testing/test_exchange_api_age_restriction.c @@ -28,7 +28,6 @@ #include <microhttpd.h> #include "taler/taler_bank_service.h" #include "taler/taler_testing_lib.h" -#include "taler/taler_extensions.h" /** * Configuration file we use. One (big) configuration is used diff --git a/src/testing/test_exchange_api_age_restriction.conf b/src/testing/test_exchange_api_age_restriction.conf @@ -30,6 +30,8 @@ BASE_URL = "http://localhost:8081/" EXPIRE_SHARD_SIZE ="300 ms" EXPIRE_IDLE_SLEEP_INTERVAL ="1 s" ENABLE_KYC = YES +AGE_RESTRICTION_ENABLED = YES +#AGE_GROUPS = "8:10:12:14:16:18:21" [exchangedb-postgres] CONFIG = "postgres:///talercheck" @@ -75,10 +77,6 @@ USERNAME = Exchange PASSWORD = password WIRE_GATEWAY_URL = "http://localhost:8082/accounts/2/taler-wire-gateway/" -[exchange-extension-age_restriction] -ENABLED = YES -#AGE_GROUPS = "8:10:12:14:16:18:21" - [kyc-provider-test-oauth2] LOGIC = oauth2 KYC_OAUTH2_VALIDITY = forever diff --git a/src/testing/test_exchange_p2p.c b/src/testing/test_exchange_p2p.c @@ -28,7 +28,6 @@ #include <microhttpd.h> #include "taler/taler_bank_service.h" #include "taler/taler_testing_lib.h" -#include "taler/taler_extensions.h" /** * Configuration file we use. One (big) configuration is used diff --git a/src/testing/testing_api_cmd_age_withdraw.c b/src/testing/testing_api_cmd_age_withdraw.c @@ -27,7 +27,6 @@ #include <microhttpd.h> #include <gnunet/gnunet_curl_lib.h> #include "taler/taler_signatures.h" -#include "taler/taler_extensions.h" #include "taler/taler_testing_lib.h" /* @@ -513,7 +512,7 @@ TALER_TESTING_cmd_withdraw_with_age_proof (const char *label, aws = GNUNET_new (struct AgeWithdrawState); aws->reserve_reference = reserve_reference; aws->expected_response_code = expected_response_code; - aws->mask = TALER_extensions_get_age_restriction_mask (); + aws->mask = TALER_testing_age_restriction_mask; aws->max_age = TALER_get_lowest_age (&aws->mask, max_age); cnt = 1; diff --git a/src/testing/testing_api_cmd_batch_withdraw.c b/src/testing/testing_api_cmd_batch_withdraw.c @@ -27,7 +27,6 @@ #include <microhttpd.h> #include <gnunet/gnunet_curl_lib.h> #include "taler/taler_signatures.h" -#include "taler/taler_extensions.h" #include "taler/taler_testing_lib.h" /** diff --git a/src/testing/testing_api_cmd_offline_sign_extensions.c b/src/testing/testing_api_cmd_offline_sign_extensions.c @@ -1,169 +0,0 @@ -/* - This file is part of TALER - Copyright (C) 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 testing/testing_api_cmd_offline_sign_extensions.c - * @brief run the taler-exchange-offline command to sign extensions (and therefore activate them) - * @author Özgür Kesim - */ -#include "platform.h" /* UNNECESSARY? */ -#include "taler/taler_json_lib.h" -#include <gnunet/gnunet_curl_lib.h> -#include "taler/taler_signatures.h" /* UNNECESSARY? */ -#include "taler/taler_testing_lib.h" - - -/** - * State for a "extensionssign" CMD. - */ -struct ExtensionsSignState -{ - - /** - * Process for the "extensionssign" command. - */ - struct GNUNET_Process *extensionssign_proc; - - /** - * Configuration file used by the command. - */ - const char *config_filename; - -}; - - -/** - * Run the command; calls the `taler-exchange-offline` program. - * - * @param cls closure. - * @param cmd the commaind being run. - * @param is interpreter state. - */ -static void -extensionssign_run (void *cls, - const struct TALER_TESTING_Command *cmd, - struct TALER_TESTING_Interpreter *is) -{ - struct ExtensionsSignState *ks = cls; - - ks->extensionssign_proc - = GNUNET_process_create (GNUNET_OS_INHERIT_STD_ERR); - if (GNUNET_OK != - GNUNET_process_run_command_va ( - ks->extensionssign_proc, - "taler-exchange-offline", - "taler-exchange-offline", - "-c", ks->config_filename, - "-L", "INFO", - "extensions", - "sign", - "upload", - NULL)) - { - GNUNET_break (0); - GNUNET_process_destroy (ks->extensionssign_proc); - ks->extensionssign_proc = NULL; - TALER_TESTING_interpreter_fail (is); - return; - } - TALER_TESTING_wait_for_sigchld (is); -} - - -/** - * Free the state of a "extensionssign" CMD, and possibly kills its - * process if it did not terminate correctly. - * - * @param cls closure. - * @param cmd the command being freed. - */ -static void -extensionssign_cleanup (void *cls, - const struct TALER_TESTING_Command *cmd) -{ - struct ExtensionsSignState *ks = cls; - - (void) cmd; - if (NULL != ks->extensionssign_proc) - { - GNUNET_break (GNUNET_OK == - GNUNET_process_kill (ks->extensionssign_proc, - SIGKILL)); - GNUNET_process_wait (ks->extensionssign_proc, - true, - NULL, - NULL); - GNUNET_process_destroy (ks->extensionssign_proc); - ks->extensionssign_proc = NULL; - } - GNUNET_free (ks); -} - - -/** - * Offer "extensionssign" CMD internal data to other commands. - * - * @param cls closure. - * @param[out] ret result - * @param trait name of the trait. - * @param index index number of the object to offer. - * @return #GNUNET_OK on success. - */ -static enum GNUNET_GenericReturnValue -extensionssign_traits (void *cls, - const void **ret, - const char *trait, - unsigned int index) -{ - struct ExtensionsSignState *ks = cls; - struct TALER_TESTING_Trait traits[] = { - TALER_TESTING_make_trait_process (&ks->extensionssign_proc), - TALER_TESTING_trait_end () - }; - - return TALER_TESTING_get_trait (traits, - ret, - trait, - index); -} - - -struct TALER_TESTING_Command -TALER_TESTING_cmd_exec_offline_sign_extensions (const char *label, - const char *config_filename) -{ - struct ExtensionsSignState *ks; - - ks = GNUNET_new (struct ExtensionsSignState); - ks->config_filename = config_filename; - { - struct TALER_TESTING_Command cmd = { - .cls = ks, - .label = label, - .run = &extensionssign_run, - .cleanup = &extensionssign_cleanup, - .traits = &extensionssign_traits - }; - - return cmd; - } -} - - -/* end of testing_api_cmd_exec_offline_sign_extensions.c */ diff --git a/src/testing/testing_api_cmd_withdraw.c b/src/testing/testing_api_cmd_withdraw.c @@ -27,7 +27,6 @@ #include <microhttpd.h> #include <gnunet/gnunet_curl_lib.h> #include "taler/taler_signatures.h" -#include "taler/taler_extensions.h" #include "taler/taler_testing_lib.h" #include "backoff.h" diff --git a/src/testing/testing_api_loop.c b/src/testing/testing_api_loop.c @@ -25,11 +25,18 @@ */ #include "taler/taler_json_lib.h" #include <gnunet/gnunet_curl_lib.h> -#include "taler/taler_extensions.h" +#include "taler/taler_util.h" #include "taler/taler_testing_lib.h" /** + * Age restriction mask for the exchange under test. + * Set during TALER_TESTING_run_with_fakebank by reading the [exchange] config. + */ +struct TALER_AgeMask TALER_testing_age_restriction_mask; + + +/** * The interpreter and its state */ struct TALER_TESTING_Interpreter @@ -649,11 +656,35 @@ TALER_TESTING_main (char *const *argv, GNUNET_break (0); return 77; } - if (GNUNET_OK != - TALER_extensions_init (cred->cfg)) + /* Initialize age restriction mask from [exchange] config */ + memset (&TALER_testing_age_restriction_mask, + 0, + sizeof (TALER_testing_age_restriction_mask)); + if (GNUNET_YES == + GNUNET_CONFIGURATION_get_value_yesno (cred->cfg, + "exchange", + "AGE_RESTRICTION_ENABLED")) { - GNUNET_break (0); - return 77; + char *groups = NULL; + + if (GNUNET_OK != + GNUNET_CONFIGURATION_get_value_string (cred->cfg, + "exchange", + "AGE_GROUPS", + &groups)) + groups = GNUNET_strdup ("8:10:12:14:16:18:21"); + if (GNUNET_OK != + TALER_parse_age_group_string (groups, + &TALER_testing_age_restriction_mask)) + { + GNUNET_log (GNUNET_ERROR_TYPE_ERROR, + "Invalid AGE_GROUPS in [exchange]: %s\n", + groups); + GNUNET_free (groups); + GNUNET_break (0); + return 77; + } + GNUNET_free (groups); } ret = TALER_TESTING_loop (main_cb, main_cb_cls);