exchange

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

commit 975a36d70b48ba6d337bacc7066f23d1d241580a
parent 390f0850310573649b7b33bcb1112b6cbe5ff6ee
Author: Christian Grothoff <christian@grothoff.org>
Date:   Sun,  5 Jan 2025 17:10:30 +0100

work on #9053 (WiP)

Diffstat:
Mdebian/taler-exchange.install | 2++
Mdoc/Makefile.am | 9+++++----
Msrc/exchange/.gitignore | 1+
Msrc/exchange/Makefile.am | 16+++++++++++++++-
Asrc/exchange/taler-exchange-sanctionscheck.c | 434+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
Msrc/exchangedb/Makefile.am | 2++
Asrc/exchangedb/pg_insert_sanction_list_hit.c | 41+++++++++++++++++++++++++++++++++++++++++
Asrc/exchangedb/pg_insert_sanction_list_hit.h | 53+++++++++++++++++++++++++++++++++++++++++++++++++++++
Asrc/exchangedb/pg_select_all_kyc_attributes.c | 37+++++++++++++++++++++++++++++++++++++
Asrc/exchangedb/pg_select_all_kyc_attributes.h | 43+++++++++++++++++++++++++++++++++++++++++++
Msrc/exchangedb/plugin_exchangedb_postgres.c | 6++++++
Msrc/include/taler_exchangedb_plugin.h | 67+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
Msrc/include/taler_kyclogic_lib.h | 8++++----
Msrc/kyclogic/kyclogic_sanctions.c | 16++++++++--------
14 files changed, 718 insertions(+), 17 deletions(-)

diff --git a/debian/taler-exchange.install b/debian/taler-exchange.install @@ -22,6 +22,7 @@ usr/bin/taler-exchange-kyc-persona-converter.sh usr/bin/taler-exchange-kyc-tester usr/bin/taler-exchange-kyc-trigger usr/bin/taler-exchange-router +usr/bin/taler-exchange-sanctionscheck usr/bin/taler-exchange-secmod-cs usr/bin/taler-exchange-secmod-eddsa usr/bin/taler-exchange-secmod-rsa @@ -43,6 +44,7 @@ usr/share/man/man1/taler-exchange-kyc-aml-pep-trigger.1 usr/share/man/man1/taler-exchange-kyc-tester.1 usr/share/man/man1/taler-exchange-kyc-trigger.1 usr/share/man/man1/taler-exchange-router.1 +usr/share/man/man1/taler-exchange-sanctionscheck.1 usr/share/man/man1/taler-exchange-secmod-cs.1 usr/share/man/man1/taler-exchange-secmod-eddsa.1 usr/share/man/man1/taler-exchange-secmod-rsa.1 diff --git a/doc/Makefile.am b/doc/Makefile.am @@ -30,20 +30,21 @@ man_MANS = \ prebuilt/man/taler-exchange-kyc-trigger.1 \ prebuilt/man/taler-exchange-offline.1 \ prebuilt/man/taler-exchange-router.1 \ + prebuilt/man/taler-exchange-sanctionscheck.1 \ prebuilt/man/taler-exchange-secmod-cs.1 \ prebuilt/man/taler-exchange-secmod-eddsa.1 \ prebuilt/man/taler-exchange-secmod-rsa.1 \ prebuilt/man/taler-exchange-transfer.1 \ - prebuilt/man/taler-exchange-wire-gateway-client.1\ + prebuilt/man/taler-exchange-wire-gateway-client.1 \ prebuilt/man/taler-exchange-wirewatch.1 \ prebuilt/man/taler-fakebank-run.1 \ - prebuilt/man/taler-helper-auditor-aggregation.1 \ + prebuilt/man/taler-helper-auditor-aggregation.1 \ prebuilt/man/taler-helper-auditor-coins.1 \ prebuilt/man/taler-helper-auditor-deposits.1\ prebuilt/man/taler-helper-auditor-purses.1 \ prebuilt/man/taler-helper-auditor-reserves.1\ - prebuilt/man/taler-helper-auditor-wire-credit.1 \ - prebuilt/man/taler-helper-auditor-wire-debit.1 \ + prebuilt/man/taler-helper-auditor-wire-credit.1 \ + prebuilt/man/taler-helper-auditor-wire-debit.1 \ prebuilt/man/taler-terms-generator.1 \ prebuilt/man/taler-unified-setup.1 diff --git a/src/exchange/.gitignore b/src/exchange/.gitignore @@ -11,3 +11,4 @@ taler-exchange-closer taler-exchange-transfer taler-exchange-router taler-exchange-expire +taler-exchange-sanctionscheck diff --git a/src/exchange/Makefile.am b/src/exchange/Makefile.am @@ -31,6 +31,7 @@ bin_PROGRAMS = \ taler-exchange-expire \ taler-exchange-httpd \ taler-exchange-router \ + taler-exchange-sanctionscheck \ taler-exchange-transfer \ taler-exchange-wirewatch @@ -43,9 +44,9 @@ taler_exchange_aggregator_LDADD = \ $(top_builddir)/src/util/libtalerutil.la \ $(top_builddir)/src/bank-lib/libtalerbank.la \ $(top_builddir)/src/exchangedb/libtalerexchangedb.la \ - -ljansson \ -lgnunetcurl \ -lgnunetutil \ + -ljansson \ $(XLIB) @@ -101,6 +102,19 @@ taler_exchange_router_LDADD = \ -lgnunetutil \ $(XLIB) +taler_exchange_sanctionscheck_SOURCES = \ + taler-exchange-sanctionscheck.c +taler_exchange_sanctionscheck_LDADD = \ + $(LIBGCRYPT_LIBS) \ + $(top_builddir)/src/kyclogic/libtalerkyclogic.la \ + $(top_builddir)/src/json/libtalerjson.la \ + $(top_builddir)/src/util/libtalerutil.la \ + $(top_builddir)/src/exchangedb/libtalerexchangedb.la \ + -lgnunetjson \ + -ljansson \ + -lgnunetutil \ + $(XLIB) + taler_exchange_transfer_SOURCES = \ taler-exchange-transfer.c taler_exchange_transfer_LDADD = \ diff --git a/src/exchange/taler-exchange-sanctionscheck.c b/src/exchange/taler-exchange-sanctionscheck.c @@ -0,0 +1,434 @@ +/* + This file is part of TALER + Copyright (C) 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 + 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-sanctionscheck.c + * @brief Process that checks all existing customers against a sanctions list + * @author Christian Grothoff + */ +#include "platform.h" +#include <gnunet/gnunet_util_lib.h> +#include <jansson.h> +#include <pthread.h> +#include <microhttpd.h> +#include "taler_exchangedb_lib.h" +#include "taler_exchangedb_plugin.h" +#include "taler_json_lib.h" +#include "taler_kyclogic_lib.h" + + +/** + * Account we are currently checking. + */ +struct Account +{ + /** + * Kept in a DLL. + */ + struct Account *next; + + /** + * Kept in a DLL. + */ + struct Account *prev; + + /** + * Original properties of the account. + */ + json_t *properties; + + /** + * Evaluation entry with the sanction list checker. + */ + struct TALER_KYCLOGIC_EvaluationEntry *ee; + + /** + * Row of the attributes in the kyc_attributes table. + */ + uint64_t row_id; + + /** + * Hash of the normalized payto:// URI of the account. + */ + struct TALER_NormalizedPaytoHashP h_payto; + +}; + + +/** + * The exchange's configuration (global) + */ +static const struct GNUNET_CONFIGURATION_Handle *cfg; + +/** + * Our DB plugin. + */ +static struct TALER_EXCHANGEDB_Plugin *db_plugin; + +/** + * Helper process for the actual rating. + */ +static struct TALER_KYCLOGIC_SanctionRater *sr; + +/** + * Value to return from main(). 0 on success, non-zero on + * on serious errors. + */ +static int global_ret; + +/** + * Key used to encrypt KYC attribute data in our database. + */ +static struct TALER_AttributeEncryptionKeyP attribute_key; + +/** + * Account rules to set if we have a good match against the + * sanction list and should freeze an account immediately. + */ +static json_t *freeze_rules; + +/** + * Head of DLL of accounts we are currently checking. + */ +static struct Account *acc_head; + +/** + * Tail of DLL of accounts we are currently checking. + */ +static struct Account *acc_tail; + + +/** + * We're being aborted with CTRL-C (or SIGTERM). Shut down. + * + * @param cls closure + */ +static void +shutdown_task (void *cls) +{ + struct Account *acc; + + (void) cls; + while (NULL != (acc = acc_head)) + { + GNUNET_CONTAINER_DLL_remove (acc_head, + acc_tail, + acc); + json_decref (acc->properties); + GNUNET_free (acc); + } + + if (NULL != sr) + { + TALER_KYCLOGIC_sanction_rater_stop (sr); + sr = NULL; + } + TALER_EXCHANGEDB_plugin_unload (db_plugin); + db_plugin = NULL; + cfg = NULL; +} + + +/** + * Function called with the result of a sanction evaluation. + * + * @param cls closure + * @param ec error code, #TALER_EC_NONE on success + * @param best_match identifies the sanction list entry with the best match + * @param rating likelihood of the match, from 0 (none) to 1 (perfect) + * @param confidence confidence in the evaluation, from 0 (none) to 1 (perfect) + */ +static void +sanction_cb (void *cls, + enum TALER_ErrorCode ec, + const char *best_match, + double rating, + double confidence) +{ + struct Account *acc = cls; + bool freeze = false; + bool investigate = false; + + // FIXME-#9053: formulas to be improved and customized via configuration + if ( (rating > 0.95) && + (confidence > 0.95) ) + { + freeze = true; + investigate = true; + } + else if (rating > 0.95 - confidence) + { + investigate = true; + } + if (freeze || investigate) + { + static const char *freeze_event[] = { + "sanction-list-hit-account-frozen", + }; + static const char *partial_match_event[] = { + "sanction-list-hit-partial-account-investigated", + }; + enum GNUNET_DB_QueryStatus qs; + json_t *properties; + const char **events; + json_t *new_rules; + + new_rules = freeze ? freeze_rules : NULL; + events = freeze ? freeze_event : partial_match_event; + properties = GNUNET_JSON_PACK ( + GNUNET_JSON_pack_string ("sanction_list_best_match", + best_match), + GNUNET_JSON_pack_double ("sanction_list_rating", + rating), + GNUNET_JSON_pack_double ("sanction_list_confidence", + confidence)); + GNUNET_assert (0 == + json_object_update_missing (properties, + acc->properties)); + qs = db_plugin->insert_sanction_list_hit (db_plugin->cls, + &acc->h_payto, + investigate, + new_rules, + properties, + 1, + events); + json_decref (properties); + if (qs < 0) + { + GNUNET_log (GNUNET_ERROR_TYPE_ERROR, + "Failed to insert sanction list evaluation result\n"); + global_ret = EXIT_FAILURE; + GNUNET_SCHEDULER_shutdown (); + return; + } + } + GNUNET_CONTAINER_DLL_remove (acc_head, + acc_tail, + acc); + json_decref (acc->properties); + GNUNET_free (acc); + if (NULL != acc_head) + return; /* more work */ + { + enum GNUNET_DB_QueryStatus qs; + + qs = db_plugin->commit (db_plugin->cls); + if (qs < 0) + { + GNUNET_log (GNUNET_ERROR_TYPE_ERROR, + "Failed to commit DB transaction\n"); + global_ret = EXIT_NOTCONFIGURED; + GNUNET_SCHEDULER_shutdown (); + return; + } + } + GNUNET_SCHEDULER_shutdown (); +} + + +/** + * Function called on each account. + * + * @param cls closure + * @param row_id row of the attributes in the database + * @param h_payto account for which the attribute data is stored + * @param provider_name provider that must be checked + * @param collection_time when was the data collected + * @param expiration_time when does the data expire + * @param properties properties that were set for @a h_payto + * @param enc_attributes_size number of bytes in @a enc_attributes + * @param enc_attributes encrypted attribute data + * @return true to continue to iterate + */ +static bool +account_cb (void *cls, + uint64_t row_id, + const struct TALER_NormalizedPaytoHashP *h_payto, + const char *provider_name, + struct GNUNET_TIME_Timestamp collection_time, + struct GNUNET_TIME_Timestamp expiration_time, + const json_t *properties, + size_t enc_attributes_size, + const void *enc_attributes) +{ + json_t *attributes; + struct Account *acc; + + (void) cls; + /* FIXME-#9053: GANA-ize the property key */ + if (json_boolean_value (json_object_get (properties, + "sanction-list-suppress"))) + { + GNUNET_log (GNUNET_ERROR_TYPE_INFO, + "Skipping %llu as suppressed by staff as false-positive\n", + (unsigned long long) row_id); + return true; + } + attributes = TALER_CRYPTO_kyc_attributes_decrypt (&attribute_key, + enc_attributes, + enc_attributes_size); + if (NULL == attributes) + { + GNUNET_log (GNUNET_ERROR_TYPE_ERROR, + "Failed to decrypt attributes at row #%llu\n", + (unsigned long long) row_id); + return true; + } + acc = GNUNET_new (struct Account); + acc->row_id = row_id; + acc->h_payto = *h_payto; + acc->properties = json_incref ((json_t *) properties); + acc->ee = TALER_KYCLOGIC_sanction_rater_eval (sr, + attributes, + &sanction_cb, + acc); + if (NULL == acc->ee) + { + GNUNET_free (acc); + return false; + } + GNUNET_CONTAINER_DLL_insert (acc_head, + acc_tail, + acc); + return true; +} + + +/** + * First task. + * + * @param cls closure, NULL + * @param args remaining command-line arguments + * @param cfgfile name of the configuration file used (for saving, can be NULL!) + * @param c configuration + */ +static void +run (void *cls, + char *const *args, + const char *cfgfile, + const struct GNUNET_CONFIGURATION_Handle *c) +{ + enum GNUNET_DB_QueryStatus qs; + + (void) cls; + (void) args; + (void) cfgfile; + cfg = c; + + { + char *attr_enc_key_str; + + if (GNUNET_OK != + GNUNET_CONFIGURATION_get_value_string (cfg, + "exchange", + "ATTRIBUTE_ENCRYPTION_KEY", + &attr_enc_key_str)) + { + GNUNET_log_config_missing (GNUNET_ERROR_TYPE_ERROR, + "exchange", + "ATTRIBUTE_ENCRYPTION_KEY"); + global_ret = EXIT_NOTCONFIGURED; + return; + } + GNUNET_CRYPTO_hash (attr_enc_key_str, + strlen (attr_enc_key_str), + &attribute_key.hash); + GNUNET_free (attr_enc_key_str); + } + if (NULL == + (db_plugin = TALER_EXCHANGEDB_plugin_load (cfg, + false))) + { + GNUNET_log (GNUNET_ERROR_TYPE_ERROR, + "Failed to initialize DB subsystem\n"); + global_ret = EXIT_NOTCONFIGURED; + return; + } + GNUNET_SCHEDULER_add_shutdown (&shutdown_task, + cls); + sr = TALER_KYCLOGIC_sanction_rater_start (args[0], + args); + if (NULL == sr) + { + global_ret = EXIT_INVALIDARGUMENT; + GNUNET_break (0); + GNUNET_SCHEDULER_shutdown (); + return; + } + if (GNUNET_OK != + db_plugin->start (db_plugin->cls, + "sanctionscheck")) + { + GNUNET_log (GNUNET_ERROR_TYPE_ERROR, + "Failed to begin DB transaction\n"); + global_ret = EXIT_NOTCONFIGURED; + GNUNET_SCHEDULER_shutdown (); + return; + } + qs = db_plugin->select_all_kyc_attributes (db_plugin->cls, + &account_cb, + NULL); + if (qs < 0) + { + global_ret = EXIT_FAILURE; + GNUNET_break (0); + GNUNET_SCHEDULER_shutdown (); + return; + } + if (GNUNET_DB_STATUS_SUCCESS_NO_RESULTS == qs) + { + db_plugin->rollback (db_plugin->cls); + GNUNET_SCHEDULER_shutdown (); + return; + } + GNUNET_assert (NULL != acc_head); +} + + +/** + * The main function of taler-exchange-sanctionscheck + * + * @param argc number of arguments from the command line + * @param argv command line arguments + * @return 0 ok, non-zero on error + */ +int +main (int argc, + char *const *argv) +{ + struct GNUNET_GETOPT_CommandLineOption options[] = { + GNUNET_GETOPT_option_version (VERSION "-" VCS_VERSION), + GNUNET_GETOPT_OPTION_END + }; + enum GNUNET_GenericReturnValue ret; + + freeze_rules = NULL; /* FIXME-#9053: set to JSON rules that freeze the account */ + ret = GNUNET_PROGRAM_run ( + TALER_EXCHANGE_project_data (), + argc, argv, + "taler-exchange-sanctionscheck", + gettext_noop ( + "process that checks all existing customer accounts against a sanctions list"), + options, + &run, NULL); + if (GNUNET_SYSERR == ret) + return EXIT_INVALIDARGUMENT; + if (GNUNET_NO == ret) + return EXIT_SUCCESS; + return global_ret; +} + + +/* end of taler-exchange-sanctionscheck.c */ diff --git a/src/exchangedb/Makefile.am b/src/exchangedb/Makefile.am @@ -219,6 +219,7 @@ libtaler_plugin_exchangedb_postgres_la_SOURCES = \ pg_insert_refund.h pg_insert_refund.c \ pg_insert_reserve_closed.h pg_insert_reserve_closed.c \ pg_insert_reserve_open_deposit.c pg_insert_reserve_open_deposit.h \ + pg_insert_sanction_list_hit.h pg_insert_sanction_list_hit.c \ pg_insert_signkey_revocation.h pg_insert_signkey_revocation.c \ pg_insert_successor_measure.h pg_insert_successor_measure.c \ pg_insert_wire.h pg_insert_wire.c \ @@ -270,6 +271,7 @@ libtaler_plugin_exchangedb_postgres_la_SOURCES = \ pg_select_aggregation_amounts_for_kyc_check.h pg_select_aggregation_amounts_for_kyc_check.c \ pg_select_aggregation_transient.h pg_select_aggregation_transient.c \ pg_select_aggregations_above_serial.h pg_select_aggregations_above_serial.c \ + pg_select_all_kyc_attributes.h pg_select_all_kyc_attributes.c \ pg_select_all_purse_decisions_above_serial_id.h pg_select_all_purse_decisions_above_serial_id.c \ pg_select_all_purse_deletions_above_serial_id.h pg_select_all_purse_deletions_above_serial_id.c \ pg_select_aml_attributes.h pg_select_aml_attributes.c \ diff --git a/src/exchangedb/pg_insert_sanction_list_hit.c b/src/exchangedb/pg_insert_sanction_list_hit.c @@ -0,0 +1,41 @@ +/* + This file is part of TALER + Copyright (C) 2025 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/pg_insert_sanction_list_hit.c + * @brief Implementation of the insert_sanction_list_hit function for Postgres + * @author Christian Grothoff + */ +#include "platform.h" +#include "taler_error_codes.h" +#include "taler_dbevents.h" +#include "taler_pq_lib.h" +#include "pg_insert_sanction_list_hit.h" +#include "pg_helper.h" + + +enum GNUNET_DB_QueryStatus +TEH_PG_insert_sanction_list_hit ( + void *cls, + const struct TALER_NormalizedPaytoHashP *h_payto, + bool to_investigate, + const json_t *new_rules, + const json_t *account_properties, + unsigned int num_events, + const char **events) +{ + GNUNET_break (0); // FIXME-#9053: not implemented + return -2; +} diff --git a/src/exchangedb/pg_insert_sanction_list_hit.h b/src/exchangedb/pg_insert_sanction_list_hit.h @@ -0,0 +1,53 @@ +/* + This file is part of TALER + Copyright (C) 2025 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/pg_insert_sanction_list_hit.h + * @brief implementation of the insert_sanction_list_hit function for Postgres + * @author Christian Grothoff + */ +#ifndef PG_INSERT_SANCTION_LIST_HIT_H +#define PG_INSERT_SANCTION_LIST_HIT_H + +#include "taler_util.h" +#include "taler_json_lib.h" +#include "taler_exchangedb_plugin.h" + + +/** + * Update sanction list hit status of the given account. + * + * @param cls closure + * @param h_payto account for which the hit is to be stored + * @param to_investigate true to flag account for investigation, + * false to **preserve** existing status + * @param new_rules new KYC rules to apply to the account, NULL to preserve + * existing rules + * @param account_properties new account properties + * @param num_events length of the @a events array + * @param events array of KYC events to trigger + * @return database transaction status + */ +enum GNUNET_DB_QueryStatus +TEH_PG_insert_sanction_list_hit ( + void *cls, + const struct TALER_NormalizedPaytoHashP *h_payto, + bool to_investigate, + const json_t *new_rules, + const json_t *account_properties, + unsigned int num_events, + const char **events); + +#endif diff --git a/src/exchangedb/pg_select_all_kyc_attributes.c b/src/exchangedb/pg_select_all_kyc_attributes.c @@ -0,0 +1,37 @@ +/* + This file is part of TALER + Copyright (C) 2025 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/pg_select_all_kyc_attributes.c + * @brief Implementation of the select_all_kyc_attributes function for Postgres + * @author Christian Grothoff + */ +#include "platform.h" +#include "taler_error_codes.h" +#include "taler_dbevents.h" +#include "taler_pq_lib.h" +#include "pg_select_all_kyc_attributes.h" +#include "pg_helper.h" + + +enum GNUNET_DB_QueryStatus +TEH_PG_select_all_kyc_attributes ( + void *cls, + TALER_EXCHANGEDB_AllAttributesCallback cb, + void *cb_cls) +{ + GNUNET_break (0); // FIXME-#9053: not implemented + return -2; +} diff --git a/src/exchangedb/pg_select_all_kyc_attributes.h b/src/exchangedb/pg_select_all_kyc_attributes.h @@ -0,0 +1,43 @@ +/* + This file is part of TALER + Copyright (C) 2025 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/pg_select_all_kyc_attributes.h + * @brief implementation of the select_all_kyc_attributes function for Postgres + * @author Christian Grothoff + */ +#ifndef PG_SELECT_ALL_KYC_ATTRIBUTES_H +#define PG_SELECT_ALL_KYC_ATTRIBUTES_H + +#include "taler_util.h" +#include "taler_json_lib.h" +#include "taler_exchangedb_plugin.h" + + +/** + * Lookup all KYC attributes. + * + * @param cls closure + * @param cb callback to invoke on each match + * @param cb_cls closure for @a cb + * @return database transaction status + */ +enum GNUNET_DB_QueryStatus +TEH_PG_select_all_kyc_attributes ( + void *cls, + TALER_EXCHANGEDB_AllAttributesCallback cb, + void *cb_cls); + +#endif diff --git a/src/exchangedb/plugin_exchangedb_postgres.c b/src/exchangedb/plugin_exchangedb_postgres.c @@ -123,6 +123,7 @@ #include "pg_insert_refund.h" #include "pg_insert_reserve_closed.h" #include "pg_insert_reserve_open_deposit.h" +#include "pg_insert_sanction_list_hit.h" #include "pg_insert_signkey_revocation.h" #include "pg_insert_successor_measure.h" #include "pg_insert_wire.h" @@ -174,6 +175,7 @@ #include "pg_select_aggregation_amounts_for_kyc_check.h" #include "pg_select_aggregation_transient.h" #include "pg_select_aggregations_above_serial.h" +#include "pg_select_all_kyc_attributes.h" #include "pg_select_all_purse_decisions_above_serial_id.h" #include "pg_select_all_purse_deletions_above_serial_id.h" #include "pg_select_aml_attributes.h" @@ -721,6 +723,10 @@ libtaler_plugin_exchangedb_postgres_init (void *cls) = &TEH_PG_lookup_signing_key; plugin->lookup_h_payto_by_access_token = &TEH_PG_lookup_h_payto_by_access_token; + plugin->insert_sanction_list_hit + = &TEH_PG_insert_sanction_list_hit; + plugin->select_all_kyc_attributes + = &TEH_PG_select_all_kyc_attributes; plugin->begin_shard = &TEH_PG_begin_shard; plugin->abort_shard diff --git a/src/include/taler_exchangedb_plugin.h b/src/include/taler_exchangedb_plugin.h @@ -3671,6 +3671,33 @@ typedef void /** + * Return KYC attribute information. + * + * @param cls closure + * @param row_id current row in kyc_attributes table + * @param h_payto account the attributes are about + * @param provider_name name of the provider that collected the attributes + * @param collection_time when were the attributes collected + * @param expiration_time when does the data expire + * @param properties properties that were set for @a h_payto + * @param enc_attributes_size size of @a enc_attributes + * @param enc_attributes the encrypted collected attributes + * @return true to continue to iterate + */ +typedef bool +(*TALER_EXCHANGEDB_AllAttributesCallback)( + void *cls, + uint64_t row_id, + const struct TALER_NormalizedPaytoHashP *h_payto, + const char *provider_name, + struct GNUNET_TIME_Timestamp collection_time, + struct GNUNET_TIME_Timestamp expiration_time, + const json_t *properties, + size_t enc_attributes_size, + const void *enc_attributes); + + +/** * @brief The plugin API, returned from the plugin's "init" function. * The argument given to "init" is simply a configuration handle. */ @@ -7354,6 +7381,31 @@ struct TALER_EXCHANGEDB_Plugin /** + * Update sanction list hit status of the given account. + * + * @param cls closure + * @param h_payto account for which the hit is to be stored + * @param to_investigate true to flag account for investigation, + * false to **preserve** existing status + * @param new_rules new KYC rules to apply to the account, NULL to preserve + * existing rules + * @param account_properties new account properties + * @param num_events length of the @a events array + * @param events array of KYC events to trigger + * @return database transaction status + */ + enum GNUNET_DB_QueryStatus + (*insert_sanction_list_hit)( + void *cls, + const struct TALER_NormalizedPaytoHashP *h_payto, + bool to_investigate, + const json_t *new_rules, + const json_t *account_properties, + unsigned int num_events, + const char **events); + + + /** * Update AML program status to finished (and failed). * * @param cls closure @@ -7404,6 +7456,21 @@ struct TALER_EXCHANGEDB_Plugin /** + * Lookup all KYC attributes. + * + * @param cls closure + * @param cb callback to invoke on each match + * @param cb_cls closure for @a cb + * @return database transaction status + */ + enum GNUNET_DB_QueryStatus + (*select_all_kyc_attributes)( + void *cls, + TALER_EXCHANGEDB_AllAttributesCallback cb, + void *cb_cls); + + + /** * Lookup legitimization measures. * * @param cls closure diff --git a/src/include/taler_kyclogic_lib.h b/src/include/taler_kyclogic_lib.h @@ -1163,9 +1163,9 @@ typedef void * @return handle for sanction list rating */ struct TALER_KYCLOGIC_SanctionRater * -TALER_KYCLOGIC_saction_rater_start ( +TALER_KYCLOGIC_sanction_rater_start ( const char *binary, - const char **argv); + char *const*argv); /** @@ -1183,7 +1183,7 @@ struct TALER_KYCLOGIC_EvaluationEntry; * @return NULL on error */ struct TALER_KYCLOGIC_EvaluationEntry * -TALER_KYCLOGIC_saction_rater_eval ( +TALER_KYCLOGIC_sanction_rater_eval ( struct TALER_KYCLOGIC_SanctionRater *sr, const json_t *attributes, TALER_KYCLOGIC_SanctionResultCallback cb, @@ -1196,7 +1196,7 @@ TALER_KYCLOGIC_saction_rater_eval ( * @param[in] sr process to stop */ void -TALER_KYCLOGIC_saction_rater_stop ( +TALER_KYCLOGIC_sanction_rater_stop ( struct TALER_KYCLOGIC_SanctionRater *sr); #endif diff --git a/src/kyclogic/kyclogic_sanctions.c b/src/kyclogic/kyclogic_sanctions.c @@ -163,7 +163,7 @@ fail_hard (struct TALER_KYCLOGIC_SanctionRater *sr) sr->ee_tail, ee); ee->cb (ee->cb_cls, - /* FIXME: better EC? */ + /* FIXME-#9053: better EC? */ TALER_EC_GENERIC_INTERNAL_INVARIANT_FAILURE, NULL, 1.0, @@ -428,8 +428,8 @@ child_done_cb (void *cls, struct TALER_KYCLOGIC_SanctionRater * -TALER_KYCLOGIC_saction_rater_start (const char *binary, - const char **argv) +TALER_KYCLOGIC_sanction_rater_start (const char *binary, + char *const*argv) { struct TALER_KYCLOGIC_SanctionRater *sr; struct GNUNET_DISK_PipeHandle *pipe_stdin; @@ -482,10 +482,10 @@ TALER_KYCLOGIC_saction_rater_start (const char *binary, struct TALER_KYCLOGIC_EvaluationEntry * -TALER_KYCLOGIC_saction_rater_eval (struct TALER_KYCLOGIC_SanctionRater *sr, - const json_t *attributes, - TALER_KYCLOGIC_SanctionResultCallback cb, - void *cb_cls) +TALER_KYCLOGIC_sanction_rater_eval (struct TALER_KYCLOGIC_SanctionRater *sr, + const json_t *attributes, + TALER_KYCLOGIC_SanctionResultCallback cb, + void *cb_cls) { struct TALER_KYCLOGIC_EvaluationEntry *ee; @@ -514,7 +514,7 @@ TALER_KYCLOGIC_saction_rater_eval (struct TALER_KYCLOGIC_SanctionRater *sr, void -TALER_KYCLOGIC_saction_rater_stop ( +TALER_KYCLOGIC_sanction_rater_stop ( struct TALER_KYCLOGIC_SanctionRater *sr) { fail_hard (sr);