diff options
-rw-r--r-- | src/exchange/taler-exchange-httpd_kyc-proof.c | 9 | ||||
-rw-r--r-- | src/exchange/taler-exchange-httpd_kyc-webhook.c | 40 | ||||
-rw-r--r-- | src/include/taler_attributes.h | 74 | ||||
-rw-r--r-- | src/include/taler_crypto_lib.h | 16 | ||||
-rw-r--r-- | src/include/taler_kyclogic_plugin.h | 2 | ||||
-rw-r--r-- | src/kyclogic/plugin_kyclogic_kycaid.c | 17 | ||||
-rw-r--r-- | src/kyclogic/plugin_kyclogic_oauth2.c | 1 | ||||
-rw-r--r-- | src/kyclogic/plugin_kyclogic_persona.c | 7 | ||||
-rw-r--r-- | src/kyclogic/taler-exchange-kyc-tester.c | 3 | ||||
-rw-r--r-- | src/util/util.c | 52 |
10 files changed, 211 insertions, 10 deletions
diff --git a/src/exchange/taler-exchange-httpd_kyc-proof.c b/src/exchange/taler-exchange-httpd_kyc-proof.c index 11d179667..6d06f0c82 100644 --- a/src/exchange/taler-exchange-httpd_kyc-proof.c +++ b/src/exchange/taler-exchange-httpd_kyc-proof.c @@ -24,6 +24,7 @@ #include <jansson.h> #include <microhttpd.h> #include <pthread.h> +#include "taler_attributes.h" #include "taler_json_lib.h" #include "taler_kyclogic_lib.h" #include "taler_mhd_lib.h" @@ -200,12 +201,10 @@ proof_cb ( const char *birthdate; struct GNUNET_ShortHashCode kyc_prox; - // FIXME: compute kyc_prox properly! - memset (&kyc_prox, - 0, - sizeof (kyc_prox)); + TALER_CRYPTO_attributes_to_kyc_prox (attributes, + &kyc_prox); birthdate = json_string_value (json_object_get (attributes, - "birthdate")); + TALER_ATTRIBUTE_BIRTHDATE)); TALER_CRYPTO_kyc_attributes_encrypt (&TEH_attribute_key, attributes, &ea, diff --git a/src/exchange/taler-exchange-httpd_kyc-webhook.c b/src/exchange/taler-exchange-httpd_kyc-webhook.c index 73038c139..e3acc1b46 100644 --- a/src/exchange/taler-exchange-httpd_kyc-webhook.c +++ b/src/exchange/taler-exchange-httpd_kyc-webhook.c @@ -24,6 +24,7 @@ #include <jansson.h> #include <microhttpd.h> #include <pthread.h> +#include "taler_attributes.h" #include "taler_json_lib.h" #include "taler_mhd_lib.h" #include "taler_kyclogic_lib.h" @@ -140,8 +141,7 @@ TEH_kyc_webhook_cleanup (void) /** - * Function called with the result of a webhook - * operation. + * Function called with the result of a KYC webhook operation. * * Note that the "decref" for the @a response * will be done by the plugin. @@ -154,6 +154,7 @@ TEH_kyc_webhook_cleanup (void) * @param provider_legitimization_id set to legitimization process ID at the provider, or NULL if not supported or unknown * @param status KYC status * @param expiration until when is the KYC check valid + * @param attributes user attributes returned by the provider * @param http_status HTTP status code of @a response * @param[in] response to return to the HTTP client */ @@ -167,6 +168,7 @@ webhook_finished_cb ( const char *provider_legitimization_id, enum TALER_KYCLOGIC_KycStatus status, struct GNUNET_TIME_Absolute expiration, + const json_t *attributes, unsigned int http_status, struct MHD_Response *response) { @@ -179,7 +181,39 @@ webhook_finished_cb ( /* _successfully_ resumed case */ { enum GNUNET_DB_QueryStatus qs; - + size_t eas; + void *ea; + const char *birthdate; + struct GNUNET_ShortHashCode kyc_prox; + + TALER_CRYPTO_attributes_to_kyc_prox (attributes, + &kyc_prox); + birthdate = json_string_value (json_object_get (attributes, + TALER_ATTRIBUTE_BIRTHDATE)); + TALER_CRYPTO_kyc_attributes_encrypt (&TEH_attribute_key, + attributes, + &ea, + &eas); + qs = TEH_plugin->insert_kyc_attributes ( + TEH_plugin->cls, + account_id, + &kyc_prox, + provider_section, + birthdate, + GNUNET_TIME_timestamp_get (), + GNUNET_TIME_absolute_to_timestamp (expiration), + eas, + ea); + GNUNET_free (ea); + if (qs < 0) + { + GNUNET_break (0); + kwh->response = TALER_MHD_make_error (TALER_EC_GENERIC_DB_STORE_FAILED, + "insert_kyc_attributes"); + kwh->response_code = MHD_HTTP_INTERNAL_SERVER_ERROR; + kwh_resume (kwh); + return; + } qs = TEH_plugin->update_kyc_process_by_row (TEH_plugin->cls, process_row, provider_section, diff --git a/src/include/taler_attributes.h b/src/include/taler_attributes.h new file mode 100644 index 000000000..6c2a2b033 --- /dev/null +++ b/src/include/taler_attributes.h @@ -0,0 +1,74 @@ +/* + This file is part of GNU Taler + Copyright (C) 2023 Taler Systems SA + + GNU Taler is free software: you can redistribute it and/or modify it + under the terms of the GNU Lesser General Public License as published + by the Free Software Foundation, either version 3 of the License, + or (at your option) any later version. + + GNU 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 + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public License + along with this program. If not, see <http://www.gnu.org/licenses/>. + + SPDX-License-Identifier: LGPL3.0-or-later + + Note: the LGPL does not apply to all components of GNU Taler, + but it does apply to this file. + */ +/** + * @file src/include/taler_attributes.h + * @brief GNU Taler database event types, TO BE generated via https://gana.gnunet.org/ + */ +#ifndef GNU_TALER_ATTRIBUTES_H +#define GNU_TALER_ATTRIBUTES_H + +#ifdef __cplusplus +extern "C" { +#if 0 /* keep Emacsens' auto-indent happy */ +} +#endif +#endif + +/** + * Full name, when known/possible using "Lastname, Firstname(s)" format, + * but "Firstname(s) Lastname" or "Firstname M. Lastname" should also be + * tolerated (as is "Name", especially if the person only has one name). + * If the person has no name, an empty string must be given. + * NULL for not collected. + */ +#define TALER_ATTRIBUTE_FULL_NAME "full_name" + +/** + * Birthdate of the person, as far as known. YYYY-MM-DD, a value + * of 0 (for DD, MM or even YYYY) is to be used for 'unknown' + * according to official records. + * Thus, 1950-00-00 stands for a birthdate in 1950 with unknown + * day and month. If official documents record January 1st or + * some other date instead, that day may also be specified. + * NULL for not collected. + */ +#define TALER_ATTRIBUTE_BIRTHDATE "birthdate" + +/** + * Citizenship(s) of the person using 2-letter country codes ("US", "DE", + * "FR", "IT", etc.) separated by commas if multiple citizenships are + * confirmed ("EN,US,DE"). Note that in the latter case it is not guaranteed + * that all nationalities were necessarily recorded. Empty string for + * stateless persons. NULL for not collected. + */ +#define TALER_ATTRIBUTE_NATIONALITIES "nationalities" + + +#if 0 /* keep Emacsens' auto-indent happy */ +{ +#endif +#ifdef __cplusplus +} +#endif + +#endif diff --git a/src/include/taler_crypto_lib.h b/src/include/taler_crypto_lib.h index 6658ee0a1..dfd40e1d4 100644 --- a/src/include/taler_crypto_lib.h +++ b/src/include/taler_crypto_lib.h @@ -1,6 +1,6 @@ /* This file is part of TALER - Copyright (C) 2014-2022 Taler Systems SA + Copyright (C) 2014-2023 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 @@ -1836,6 +1836,20 @@ TALER_CRYPTO_kyc_attributes_decrypt ( /** + * Takes a set of KYC attributes and extracts key + * data that we use to detect similar / duplicate + * entries in the database. + * + * @param attr set of KYC attributes + * @param[out] kyc_prox set to the proximity hash + */ +void +TALER_CRYPTO_attributes_to_kyc_prox ( + const json_t *attr, + struct GNUNET_ShortHashCode *kyc_prox); + + +/** * Check if a coin is valid; that is, whether the denomination key exists, * is not expired, and the signature is correct. * diff --git a/src/include/taler_kyclogic_plugin.h b/src/include/taler_kyclogic_plugin.h index 1782af917..a7e222179 100644 --- a/src/include/taler_kyclogic_plugin.h +++ b/src/include/taler_kyclogic_plugin.h @@ -189,6 +189,7 @@ typedef void * @param provider_legitimization_id set to legitimization process ID at the provider, or NULL if not supported or unknown * @param status KYC status * @param expiration until when is the KYC check valid + * @param attributes user attributes returned by the provider * @param http_status HTTP status code of @a response * @param[in] response to return to the HTTP client */ @@ -202,6 +203,7 @@ typedef void const char *provider_legitimization_id, enum TALER_KYCLOGIC_KycStatus status, struct GNUNET_TIME_Absolute expiration, + const json_t *attributes, unsigned int http_status, struct MHD_Response *response); diff --git a/src/kyclogic/plugin_kyclogic_kycaid.c b/src/kyclogic/plugin_kyclogic_kycaid.c index 6926135c3..e34795540 100644 --- a/src/kyclogic/plugin_kyclogic_kycaid.c +++ b/src/kyclogic/plugin_kyclogic_kycaid.c @@ -811,6 +811,7 @@ handle_webhook_finished (void *cls, wh->verification_id, TALER_KYCLOGIC_STATUS_PROVIDER_FAILED, GNUNET_TIME_UNIT_ZERO_ABS, /* expiration */ + NULL, MHD_HTTP_BAD_GATEWAY, resp); break; @@ -824,6 +825,11 @@ handle_webhook_finished (void *cls, MHD_RESPMEM_PERSISTENT); if (verified) { + json_t *attr; + + attr = json_object (); + // FIXME: initialize attributes! + GNUNET_assert (NULL != attr); expiration = GNUNET_TIME_relative_to_absolute (wh->pd->validity); wh->cb (wh->cb_cls, wh->process_row, @@ -833,8 +839,10 @@ handle_webhook_finished (void *cls, wh->verification_id, TALER_KYCLOGIC_STATUS_SUCCESS, expiration, + attr, MHD_HTTP_NO_CONTENT, resp); + json_decref (attr); } else { @@ -846,6 +854,7 @@ handle_webhook_finished (void *cls, wh->verification_id, TALER_KYCLOGIC_STATUS_USER_ABORTED, GNUNET_TIME_UNIT_ZERO_ABS, + NULL, MHD_HTTP_NO_CONTENT, resp); } @@ -872,6 +881,7 @@ handle_webhook_finished (void *cls, wh->verification_id, TALER_KYCLOGIC_STATUS_PROVIDER_FAILED, GNUNET_TIME_UNIT_ZERO_ABS, /* expiration */ + NULL, MHD_HTTP_INTERNAL_SERVER_ERROR, resp); break; @@ -893,6 +903,7 @@ handle_webhook_finished (void *cls, wh->verification_id, TALER_KYCLOGIC_STATUS_PROVIDER_FAILED, GNUNET_TIME_UNIT_ZERO_ABS, /* expiration */ + NULL, MHD_HTTP_NETWORK_AUTHENTICATION_REQUIRED, resp); break; @@ -910,6 +921,7 @@ handle_webhook_finished (void *cls, wh->verification_id, TALER_KYCLOGIC_STATUS_PROVIDER_FAILED, GNUNET_TIME_UNIT_ZERO_ABS, /* expiration */ + NULL, MHD_HTTP_GATEWAY_TIMEOUT, resp); break; @@ -933,6 +945,7 @@ handle_webhook_finished (void *cls, wh->verification_id, TALER_KYCLOGIC_STATUS_PROVIDER_FAILED, GNUNET_TIME_UNIT_ZERO_ABS, /* expiration */ + NULL, MHD_HTTP_BAD_GATEWAY, resp); break; @@ -950,6 +963,7 @@ handle_webhook_finished (void *cls, wh->verification_id, TALER_KYCLOGIC_STATUS_PROVIDER_FAILED, GNUNET_TIME_UNIT_ZERO_ABS, /* expiration */ + NULL, MHD_HTTP_SERVICE_UNAVAILABLE, resp); break; @@ -967,6 +981,7 @@ handle_webhook_finished (void *cls, wh->verification_id, TALER_KYCLOGIC_STATUS_PROVIDER_FAILED, GNUNET_TIME_UNIT_ZERO_ABS, /* expiration */ + NULL, MHD_HTTP_BAD_GATEWAY, resp); break; @@ -990,6 +1005,7 @@ handle_webhook_finished (void *cls, wh->verification_id, TALER_KYCLOGIC_STATUS_PROVIDER_FAILED, GNUNET_TIME_UNIT_ZERO_ABS, /* expiration */ + NULL, MHD_HTTP_BAD_GATEWAY, resp); break; @@ -1018,6 +1034,7 @@ async_webhook_reply (void *cls) wh->verification_id, /* provider legi ID */ TALER_KYCLOGIC_STATUS_PROVIDER_FAILED, GNUNET_TIME_UNIT_ZERO_ABS, /* expiration */ + NULL, wh->response_code, wh->resp); kycaid_webhook_cancel (wh); diff --git a/src/kyclogic/plugin_kyclogic_oauth2.c b/src/kyclogic/plugin_kyclogic_oauth2.c index f5a08e92e..d4aaf4494 100644 --- a/src/kyclogic/plugin_kyclogic_oauth2.c +++ b/src/kyclogic/plugin_kyclogic_oauth2.c @@ -1211,6 +1211,7 @@ wh_return_not_found (void *cls) NULL, TALER_KYCLOGIC_STATUS_KEEP, GNUNET_TIME_UNIT_ZERO_ABS, + NULL, MHD_HTTP_NOT_FOUND, response); GNUNET_free (wh); diff --git a/src/kyclogic/plugin_kyclogic_persona.c b/src/kyclogic/plugin_kyclogic_persona.c index 9f3952558..b833f795d 100644 --- a/src/kyclogic/plugin_kyclogic_persona.c +++ b/src/kyclogic/plugin_kyclogic_persona.c @@ -1457,6 +1457,7 @@ webhook_generic_reply (struct TALER_KYCLOGIC_WebhookHandle *wh, { struct MHD_Response *resp; struct GNUNET_TIME_Absolute expiration; + json_t *attr; if (TALER_KYCLOGIC_STATUS_SUCCESS == status) expiration = GNUNET_TIME_relative_to_absolute (wh->pd->validity); @@ -1466,6 +1467,9 @@ webhook_generic_reply (struct TALER_KYCLOGIC_WebhookHandle *wh, "", MHD_RESPMEM_PERSISTENT); TALER_MHD_add_global_headers (resp); + attr = json_object (); + // FIXME: fetch attributes! + GNUNET_assert (NULL != attr); wh->cb (wh->cb_cls, wh->process_row, &wh->h_payto, @@ -1474,8 +1478,10 @@ webhook_generic_reply (struct TALER_KYCLOGIC_WebhookHandle *wh, inquiry_id, status, expiration, + attr, http_status, resp); + json_decref (attr); } @@ -1773,6 +1779,7 @@ async_webhook_reply (void *cls) wh->inquiry_id, /* provider legi ID */ TALER_KYCLOGIC_STATUS_PROVIDER_FAILED, GNUNET_TIME_UNIT_ZERO_ABS, /* expiration */ + NULL, wh->response_code, wh->resp); persona_webhook_cancel (wh); diff --git a/src/kyclogic/taler-exchange-kyc-tester.c b/src/kyclogic/taler-exchange-kyc-tester.c index bb473c682..bb9c61d5b 100644 --- a/src/kyclogic/taler-exchange-kyc-tester.c +++ b/src/kyclogic/taler-exchange-kyc-tester.c @@ -436,6 +436,7 @@ kyc_webhook_cleanup (void) * @param provider_legitimization_id set to legitimization process ID at the provider, or NULL if not supported or unknown * @param status KYC status * @param expiration until when is the KYC check valid + * @param attributes user attributes returned by the provider * @param http_status HTTP status code of @a response * @param[in] response to return to the HTTP client */ @@ -449,6 +450,7 @@ webhook_finished_cb ( const char *provider_legitimization_id, enum TALER_KYCLOGIC_KycStatus status, struct GNUNET_TIME_Absolute expiration, + const json_t *attributes, unsigned int http_status, struct MHD_Response *response) { @@ -457,6 +459,7 @@ webhook_finished_cb ( (void) expiration; (void) provider_section; kwh->wh = NULL; + GNUNET_break (NULL != attributes); GNUNET_break (0 == GNUNET_memcmp (account_id, &cmd_line_h_payto)); GNUNET_break (0 == strcmp (provider_user_id, diff --git a/src/util/util.c b/src/util/util.c index 5321b31ed..96d791912 100644 --- a/src/util/util.c +++ b/src/util/util.c @@ -1,6 +1,6 @@ /* This file is part of TALER - Copyright (C) 2014-2020 Taler Systems SA + Copyright (C) 2014-2023 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 @@ -19,9 +19,12 @@ * @author Sree Harsha Totakura <sreeharsha@totakura.in> * @author Florian Dold * @author Benedikt Mueller + * @author Christian Grothoff */ #include "platform.h" #include "taler_util.h" +#include "taler_attributes.h" +#include <gnunet/gnunet_json_lib.h> const char * @@ -243,4 +246,51 @@ strchrnul (const char *s, #endif +void +TALER_CRYPTO_attributes_to_kyc_prox ( + const json_t *attr, + struct GNUNET_ShortHashCode *kyc_prox) +{ + const char *name = NULL; + const char *birthdate = NULL; + struct GNUNET_JSON_Specification spec[] = { + GNUNET_JSON_spec_mark_optional ( + GNUNET_JSON_spec_string (TALER_ATTRIBUTE_FULL_NAME, + &name), + NULL), + GNUNET_JSON_spec_mark_optional ( + GNUNET_JSON_spec_string (TALER_ATTRIBUTE_BIRTHDATE, + &birthdate), + NULL), + GNUNET_JSON_spec_end () + }; + + if (GNUNET_OK != + GNUNET_JSON_parse (attr, + spec, + NULL, NULL)) + { + GNUNET_break (0); + memset (kyc_prox, + 0, + sizeof (*kyc_prox)); + return; + } + GNUNET_assert (GNUNET_YES == + GNUNET_CRYPTO_kdf ( + kyc_prox, + sizeof (*kyc_prox), + name, + (NULL == name) + ? 0 + : strlen (name), + birthdate, + (NULL == birthdate) + ? 0 + : strlen (birthdate), + NULL, + 0)); +} + + /* end of util.c */ |