exchange

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

commit 19173147e396d0431859d66bf94c6fa8a8c350a0
parent 3665a932b381d5e539b2bd8fdb65209cf8b8ed56
Author: Christian Grothoff <christian@grothoff.org>
Date:   Tue, 22 Apr 2025 13:00:05 +0200

fix #9767: filter rules by payto wire method

Diffstat:
Msrc/exchange/taler-exchange-httpd_common_kyc.c | 3+++
Msrc/exchangedb/exchangedb_aml.c | 1+
Msrc/include/taler_kyclogic_lib.h | 6++++++
Msrc/kyclogic/kyclogic_api.c | 133++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++-------------
4 files changed, 121 insertions(+), 22 deletions(-)

diff --git a/src/exchange/taler-exchange-httpd_common_kyc.c b/src/exchange/taler-exchange-httpd_common_kyc.c @@ -417,6 +417,7 @@ TEH_kyc_run_measure_for_attributes ( kat->kyc_aml = TALER_KYCLOGIC_run_aml_program ( kat->jmeasures, + kat->is_wallet, kat->measure_index, &TALER_EXCHANGEDB_current_attributes_builder, &hbc, @@ -550,6 +551,7 @@ TEH_kyc_run_measure_directly ( kat->kyc_aml = TALER_KYCLOGIC_run_aml_program3 ( + kat->is_wallet, instant_ms, &TALER_EXCHANGEDB_current_attributes_builder, &hbc, @@ -800,6 +802,7 @@ TEH_kyc_fallback ( = TALER_KYCLOGIC_run_aml_program2 ( kcc.prog_name, kcc.context, + is_wallet, &TALER_EXCHANGEDB_current_attributes_builder, &hbc, &TALER_EXCHANGEDB_current_rule_builder, diff --git a/src/exchangedb/exchangedb_aml.c b/src/exchangedb/exchangedb_aml.c @@ -471,6 +471,7 @@ run_measure (struct TALER_EXCHANGEDB_RuleUpdater *ru, m->prog_name); GNUNET_assert (NULL == ru->t); ru->amlh = TALER_KYCLOGIC_run_aml_program3 ( + ru->is_wallet, m, &TALER_EXCHANGEDB_current_attributes_builder, &hbc, diff --git a/src/include/taler_kyclogic_lib.h b/src/include/taler_kyclogic_lib.h @@ -920,6 +920,7 @@ typedef json_t * * @param jmeasures current KYC/AML rules to apply; * they determine also the AML program and * provide the context + * @param is_wallet true if this is for a wallet * @param measure_index which KYC measure yielded the * @a attributes * @param current_attributes_cb function to get current KYC attributes @@ -943,6 +944,7 @@ typedef json_t * struct TALER_KYCLOGIC_AmlProgramRunnerHandle * TALER_KYCLOGIC_run_aml_program ( const json_t *jmeasures, + bool is_wallet, unsigned int measure_index, TALER_KYCLOGIC_HistoryBuilderCallback current_attributes_cb, void *current_attributes_cb_cls, @@ -962,6 +964,7 @@ TALER_KYCLOGIC_run_aml_program ( * * @param prog_name name of AML program to run * @param context context to run with + * @param is_wallet true if this is for a wallet * @param current_attributes_cb function to get current KYC attributes * @param current_attributes_cb_cls closure for @a current_attributes_cb * @param current_rules_cb callback to get current KYC rules that apply to the account @@ -984,6 +987,7 @@ struct TALER_KYCLOGIC_AmlProgramRunnerHandle * TALER_KYCLOGIC_run_aml_program2 ( const char *prog_name, const json_t *context, + bool is_wallet, TALER_KYCLOGIC_HistoryBuilderCallback current_attributes_cb, void *current_attributes_cb_cls, TALER_KYCLOGIC_HistoryBuilderCallback current_rules_cb, @@ -1001,6 +1005,7 @@ TALER_KYCLOGIC_run_aml_program2 ( * Run AML program specified by the given * measure. * + * @param is_wallet true if this is for a wallet * @param measure measure with program name and context * to run * @param current_attributes_cb function to get current KYC attributes @@ -1023,6 +1028,7 @@ TALER_KYCLOGIC_run_aml_program2 ( */ struct TALER_KYCLOGIC_AmlProgramRunnerHandle * TALER_KYCLOGIC_run_aml_program3 ( + bool is_wallet, const struct TALER_KYCLOGIC_Measure *measure, TALER_KYCLOGIC_HistoryBuilderCallback current_attributes_cb, void *current_attributes_cb_cls, diff --git a/src/kyclogic/kyclogic_api.c b/src/kyclogic/kyclogic_api.c @@ -1,6 +1,6 @@ /* This file is part of TALER - Copyright (C) 2022-2024 Taler Systems SA + Copyright (C) 2022-2025 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 @@ -23,6 +23,11 @@ #include "taler_kyclogic_lib.h" /** + * Log verbosely, including possibly privacy-sensitive data. + */ +#define DEBUG 1 + +/** * Name of the KYC measure that may never be passed. Useful if some * operations/amounts are categorically forbidden. */ @@ -142,12 +147,6 @@ struct TALER_KYCLOGIC_LegitimizationRuleSet char *successor_measure; /** - * This object in JSON format. Excludes *default* measures even - * if these are the default rules. - */ - json_t *jlrs; - - /** * Array of the rules. */ struct TALER_KYCLOGIC_KycRule *kyc_rules; @@ -341,6 +340,18 @@ static char *cfg_filename; */ static char *my_currency; +/** + * Default LegitimizationRuleSet for wallets. Excludes *default* measures + * even if these are the default rules. + */ +static json_t *wallet_default_lrs; + +/** + * Default LegitimizationRuleSet for bank accounts. Excludes *default* measures + * even if these are the default rules. + */ +static json_t *bankaccount_default_lrs; + struct GNUNET_TIME_Timestamp TALER_KYCLOGIC_rules_get_expiration ( @@ -728,9 +739,6 @@ TALER_KYCLOGIC_rules_parse (const json_t *jlrs) } } - - lrs->jlrs - = json_incref ((json_t *) jlrs); lrs->kyc_rules = GNUNET_new_array (lrs->num_kyc_rules, struct TALER_KYCLOGIC_KycRule); @@ -870,7 +878,6 @@ TALER_KYCLOGIC_rules_free (struct TALER_KYCLOGIC_LegitimizationRuleSet *lrs) json_decref (measure->context); } GNUNET_free (lrs->kyc_rules); - json_decref (lrs->jlrs); GNUNET_free (lrs->custom_measures); GNUNET_free (lrs->successor_measure); GNUNET_free (lrs); @@ -2837,7 +2844,8 @@ TALER_KYCLOGIC_kyc_init ( .cfg = cfg, .result = true }; - json_t *jkyc_rules; + json_t *jkyc_rules_w; + json_t *jkyc_rules_a; if (NULL != cfg_fn) cfg_filename = GNUNET_strdup (cfg_fn); @@ -2891,8 +2899,10 @@ TALER_KYCLOGIC_kyc_init ( default_rules.num_kyc_rules, sizeof (struct TALER_KYCLOGIC_KycRule), &sort_by_timeframe); - jkyc_rules = json_array (); - GNUNET_assert (NULL != jkyc_rules); + jkyc_rules_w = json_array (); + GNUNET_assert (NULL != jkyc_rules_w); + jkyc_rules_a = json_array (); + GNUNET_assert (NULL != jkyc_rules_a); for (unsigned int i=0; i<default_rules.num_kyc_rules; i++) { @@ -2950,16 +2960,73 @@ TALER_KYCLOGIC_kyc_init ( GNUNET_JSON_pack_bool ("is_and_combinator", rule->is_and_combinator) ); - GNUNET_assert (0 == - json_array_append_new (jkyc_rules, - jrule)); + switch (rule->trigger) + { + case TALER_KYCLOGIC_KYC_TRIGGER_NONE: + GNUNET_break (0); + break; + case TALER_KYCLOGIC_KYC_TRIGGER_WITHDRAW: + GNUNET_assert (0 == + json_array_append (jkyc_rules_a, + jrule)); + break; + case TALER_KYCLOGIC_KYC_TRIGGER_DEPOSIT: + GNUNET_assert (0 == + json_array_append (jkyc_rules_a, + jrule)); + break; + case TALER_KYCLOGIC_KYC_TRIGGER_P2P_RECEIVE: + GNUNET_assert (0 == + json_array_append (jkyc_rules_w, + jrule)); + break; + case TALER_KYCLOGIC_KYC_TRIGGER_WALLET_BALANCE: + GNUNET_assert (0 == + json_array_append (jkyc_rules_w, + jrule)); + break; + case TALER_KYCLOGIC_KYC_TRIGGER_RESERVE_CLOSE: + GNUNET_assert (0 == + json_array_append (jkyc_rules_a, + jrule)); + break; + case TALER_KYCLOGIC_KYC_TRIGGER_AGGREGATE: + GNUNET_assert (0 == + json_array_append (jkyc_rules_a, + jrule)); + break; + case TALER_KYCLOGIC_KYC_TRIGGER_TRANSACTION: + GNUNET_assert (0 == + json_array_append (jkyc_rules_a, + jrule)); + GNUNET_assert (0 == + json_array_append (jkyc_rules_w, + jrule)); + break; + case TALER_KYCLOGIC_KYC_TRIGGER_REFUND: + GNUNET_assert (0 == + json_array_append (jkyc_rules_a, + jrule)); + GNUNET_assert (0 == + json_array_append (jkyc_rules_w, + jrule)); + break; + } + json_decref (jrule); } - default_rules.jlrs + wallet_default_lrs = GNUNET_JSON_PACK ( GNUNET_JSON_pack_timestamp ("expiration_time", GNUNET_TIME_UNIT_FOREVER_TS), GNUNET_JSON_pack_array_steal ("rules", - jkyc_rules) + jkyc_rules_w) + ); + bankaccount_default_lrs + = GNUNET_JSON_PACK ( + GNUNET_JSON_pack_timestamp ("expiration_time", + GNUNET_TIME_UNIT_FOREVER_TS), + GNUNET_JSON_pack_array_steal ("rules", + jkyc_rules_a) ); for (unsigned int i=0; i<default_rules.num_custom_measures; i++) @@ -4011,12 +4078,14 @@ handle_aml_output ( GNUNET_SCHEDULER_cancel (aprh->async_cb); aprh->async_cb = NULL; } +#if DEBUG GNUNET_log (GNUNET_ERROR_TYPE_INFO, "AML program %s output is:\n", aprh->program->program_name); json_dumpf (result, stderr, JSON_INDENT (2)); +#endif memset (apr, 0, sizeof (*apr)); @@ -4306,6 +4375,7 @@ handle_aml_timeout (void *cls) struct TALER_KYCLOGIC_AmlProgramRunnerHandle * TALER_KYCLOGIC_run_aml_program ( const json_t *jmeasures, + bool is_wallet, unsigned int measure_index, TALER_KYCLOGIC_HistoryBuilderCallback current_attributes_cb, void *current_attributes_cb_cls, @@ -4339,6 +4409,7 @@ TALER_KYCLOGIC_run_aml_program ( } return TALER_KYCLOGIC_run_aml_program2 (prog_name, context, + is_wallet, current_attributes_cb, current_attributes_cb_cls, current_rules_cb, @@ -4357,6 +4428,7 @@ struct TALER_KYCLOGIC_AmlProgramRunnerHandle * TALER_KYCLOGIC_run_aml_program2 ( const char *prog_name, const json_t *context, + bool is_wallet, TALER_KYCLOGIC_HistoryBuilderCallback current_attributes_cb, void *current_attributes_cb_cls, TALER_KYCLOGIC_HistoryBuilderCallback current_rules_cb, @@ -4390,6 +4462,7 @@ TALER_KYCLOGIC_run_aml_program2 ( if (0 != (API_ATTRIBUTES & prog->input_mask)) { attributes = current_attributes_cb (current_attributes_cb_cls); +#if DEBUG GNUNET_log (GNUNET_ERROR_TYPE_INFO, "KYC attributes for AML program %s are:\n", prog_name); @@ -4398,6 +4471,7 @@ TALER_KYCLOGIC_run_aml_program2 ( JSON_INDENT (2)); fprintf (stderr, "\n"); +#endif for (unsigned int i = 0; i<prog->num_required_attributes; i++) { const char *rattr = prog->required_attributes[i]; @@ -4409,9 +4483,11 @@ TALER_KYCLOGIC_run_aml_program2 ( "KYC attributes lack required attribute `%s' for AML program %s\n", rattr, prog->program_name); +#if DEBUG json_dumpf (attributes, stderr, JSON_INDENT (2)); +#endif aprh->apr.status = TALER_KYCLOGIC_AMLR_FAILURE; aprh->apr.details.failure.fallback_measure = prog->fallback; @@ -4443,9 +4519,11 @@ TALER_KYCLOGIC_run_aml_program2 ( "Context lacks required field `%s' for AML program %s\n", rctx, prog->program_name); +#if DEBUG json_dumpf (context, stderr, JSON_INDENT (2)); +#endif aprh->apr.status = TALER_KYCLOGIC_AMLR_FAILURE; aprh->apr.details.failure.fallback_measure = prog->fallback; @@ -4477,7 +4555,10 @@ TALER_KYCLOGIC_run_aml_program2 ( else current_rules = current_rules_cb (current_rules_cb_cls); if (0 != (API_DEFAULT_RULES & prog->input_mask)) - jdefault_rules = default_rules.jlrs; + jdefault_rules = + (is_wallet + ? wallet_default_lrs + : bankaccount_default_lrs); else jdefault_rules = NULL; { @@ -4516,9 +4597,11 @@ TALER_KYCLOGIC_run_aml_program2 ( extra_args); GNUNET_assert (NULL != args); GNUNET_assert (NULL != args[0]); +#if DEBUG json_dumpf (input, stderr, JSON_INDENT (2)); +#endif aprh->proc = TALER_JSON_external_conversion_start ( input, &handle_aml_output, @@ -4538,6 +4621,7 @@ TALER_KYCLOGIC_run_aml_program2 ( struct TALER_KYCLOGIC_AmlProgramRunnerHandle * TALER_KYCLOGIC_run_aml_program3 ( + bool is_wallet, const struct TALER_KYCLOGIC_Measure *measure, TALER_KYCLOGIC_HistoryBuilderCallback current_attributes_cb, void *current_attributes_cb_cls, @@ -4554,6 +4638,7 @@ TALER_KYCLOGIC_run_aml_program3 ( return TALER_KYCLOGIC_run_aml_program2 ( measure->prog_name, measure->context, + is_wallet, current_attributes_cb, current_attributes_cb_cls, current_rules_cb, @@ -4674,8 +4759,12 @@ TALER_KYCLOGIC_get_zero_limits () json_t * TALER_KYCLOGIC_get_default_legi_rules (bool for_wallet) { - // FIXME-#9767: specialize based on 'for_wallet'! - return json_incref ((json_t *) default_rules.jlrs); + const json_t *r; + + r = (for_wallet + ? wallet_default_lrs + : bankaccount_default_lrs); + return json_incref ((json_t *) r); }