diff options
Diffstat (limited to 'src/backend/taler-merchant-httpd_private-get-instances-ID-kyc.c')
-rw-r--r-- | src/backend/taler-merchant-httpd_private-get-instances-ID-kyc.c | 271 |
1 files changed, 140 insertions, 131 deletions
diff --git a/src/backend/taler-merchant-httpd_private-get-instances-ID-kyc.c b/src/backend/taler-merchant-httpd_private-get-instances-ID-kyc.c index 10c76013..8a338e7d 100644 --- a/src/backend/taler-merchant-httpd_private-get-instances-ID-kyc.c +++ b/src/backend/taler-merchant-httpd_private-get-instances-ID-kyc.c @@ -1,6 +1,6 @@ /* This file is part of GNU Taler - (C) 2021 Taler Systems SA + (C) 2021-2023 Taler Systems SA GNU Taler is free software; you can redistribute it and/or modify it under the terms of the GNU Affero General Public License as @@ -39,13 +39,13 @@ * How long should clients cache a KYC failure response? */ #define EXPIRATION_KYC_FAILURE GNUNET_TIME_relative_multiply ( \ - GNUNET_TIME_UNIT_MINUTES, 5) + GNUNET_TIME_UNIT_MINUTES, 5) /** * How long should clients cache a KYC success response? */ #define EXPIRATION_KYC_SUCCESS GNUNET_TIME_relative_multiply ( \ - GNUNET_TIME_UNIT_HOURS, 1) + GNUNET_TIME_UNIT_HOURS, 1) /** @@ -73,7 +73,7 @@ struct ExchangeKycRequest /** * Find operation where we connect to the respective exchange. */ - struct TMH_EXCHANGES_FindOperation *fo; + struct TMH_EXCHANGES_KeysOperation *fo; /** * KYC request this exchange request is made for. @@ -110,11 +110,6 @@ struct ExchangeKycRequest */ struct GNUNET_TIME_Timestamp last_check; - /** - * Last KYC status returned by the exchange. - */ - bool kyc_ok; - }; @@ -197,7 +192,7 @@ struct KycContext /** * How long are we willing to wait for the exchange(s)? */ - struct GNUNET_TIME_Relative timeout; + struct GNUNET_TIME_Absolute timeout; /** * HTTP status code to use for the reply, i.e 200 for "OK". @@ -283,7 +278,7 @@ kyc_context_cleanup (void *cls) } if (NULL != ekr->fo) { - TMH_EXCHANGES_find_exchange_cancel (ekr->fo); + TMH_EXCHANGES_keys4exchange_cancel (ekr->fo); ekr->fo = NULL; } GNUNET_free (ekr->exchange_url); @@ -310,9 +305,9 @@ kyc_context_cleanup (void *cls) /** - * Resume the given KYC context and send the given response. - * Stores the response in the @a kc and signals MHD to resume - * the connection. Also ensures MHD runs immediately. + * Resume the given KYC context and send the given response. Stores the + * response in the @a kc and signals MHD to resume the connection. Also + * ensures MHD runs immediately. * * @param kc KYC context * @param response_code response code to use @@ -400,7 +395,7 @@ handle_kyc_timeout (void *cls) } if (NULL != ekr->fo) { - TMH_EXCHANGES_find_exchange_cancel (ekr->fo); + TMH_EXCHANGES_keys4exchange_cancel (ekr->fo); ekr->fo = NULL; } GNUNET_assert ( @@ -433,9 +428,8 @@ handle_kyc_timeout (void *cls) /** - * We are done with the KYC request @a ekr. - * Remove it from the work list and check if - * we are done overall. + * We are done with the KYC request @a ekr. Remove it from the work list and + * check if we are done overall. * * @param[in] ekr key request that is done (and will be freed) */ @@ -453,7 +447,7 @@ ekr_finished (struct ExchangeKycRequest *ekr) if (NULL != kc->exchange_pending_head) return; /* wait for more */ /* All exchange requests done, create final - big response from cummulated replies */ + big response from cumulated replies */ if ( (0 == json_array_size (kc->pending_kycs)) && (0 == json_array_size (kc->timeout_kycs)) ) { @@ -500,15 +494,31 @@ exchange_check_cb (void *cls, { enum GNUNET_DB_QueryStatus qs; + if (TALER_AML_NORMAL != ks->details.ok.aml_status) + { + GNUNET_assert ( + 0 == + json_array_append_new ( + kc->pending_kycs, + GNUNET_JSON_PACK ( + GNUNET_JSON_pack_uint64 ( + "aml_status", + ks->details.ok.aml_status), + GNUNET_JSON_pack_string ("exchange_url", + ekr->exchange_url), + GNUNET_JSON_pack_string ("payto_uri", + ekr->payto_uri)))); + } qs = TMH_db->account_kyc_set_status (TMH_db->cls, kc->mi->settings.id, &ekr->h_wire, ekr->exchange_url, ekr->exchange_kyc_serial, - &ks->details.success.exchange_sig, - &ks->details.success.exchange_pub, - ks->details.success.timestamp, - true); + &ks->details.ok.exchange_sig, + &ks->details.ok.exchange_pub, + ks->details.ok.timestamp, + true, /* KYC OK */ + ks->details.ok.aml_status); if (qs < 0) { GNUNET_log (GNUNET_ERROR_TYPE_WARNING, @@ -517,18 +527,42 @@ exchange_check_cb (void *cls, } break; case MHD_HTTP_ACCEPTED: - GNUNET_assert ( - 0 == - json_array_append_new ( - kc->pending_kycs, - GNUNET_JSON_PACK ( - GNUNET_JSON_pack_string ("kyc_url", - ks->details.accepted.kyc_url), - GNUNET_JSON_pack_string ("exchange_url", - ekr->exchange_url), - GNUNET_JSON_pack_string ("payto_uri", - ekr->payto_uri)))); - break; + { + struct GNUNET_TIME_Timestamp now; + enum GNUNET_DB_QueryStatus qs; + + GNUNET_assert ( + 0 == + json_array_append_new ( + kc->pending_kycs, + GNUNET_JSON_PACK ( + GNUNET_JSON_pack_string ("kyc_url", + ks->details.accepted.kyc_url), + GNUNET_JSON_pack_uint64 ("aml_status", + ks->details.accepted.aml_status), + GNUNET_JSON_pack_string ("exchange_url", + ekr->exchange_url), + GNUNET_JSON_pack_string ("payto_uri", + ekr->payto_uri)))); + now = GNUNET_TIME_timestamp_get (); + qs = TMH_db->account_kyc_set_status ( + TMH_db->cls, + kc->mi->settings.id, + &ekr->h_wire, + ekr->exchange_url, + ekr->exchange_kyc_serial, + NULL, + NULL, + now, + false, /* KYC not OK */ + ks->details.accepted.aml_status); + if (qs < 0) + { + GNUNET_log (GNUNET_ERROR_TYPE_WARNING, + "Failed to store KYC status in database!\n"); + } + break; + } case MHD_HTTP_NO_CONTENT: { struct GNUNET_TIME_Timestamp now; @@ -543,7 +577,44 @@ exchange_check_cb (void *cls, NULL, NULL, now, - true); + true, /* KYC OK */ + TALER_AML_NORMAL); + if (qs < 0) + { + GNUNET_log (GNUNET_ERROR_TYPE_WARNING, + "Failed to store KYC status in database!\n"); + } + } + break; + case MHD_HTTP_UNAVAILABLE_FOR_LEGAL_REASONS: + { + struct GNUNET_TIME_Timestamp now; + enum GNUNET_DB_QueryStatus qs; + + GNUNET_assert ( + 0 == + json_array_append_new ( + kc->pending_kycs, + GNUNET_JSON_PACK ( + GNUNET_JSON_pack_uint64 ( + "aml_status", + ks->details.unavailable_for_legal_reasons.aml_status), + GNUNET_JSON_pack_string ("exchange_url", + ekr->exchange_url), + GNUNET_JSON_pack_string ("payto_uri", + ekr->payto_uri)))); + now = GNUNET_TIME_timestamp_get (); + qs = TMH_db->account_kyc_set_status ( + TMH_db->cls, + kc->mi->settings.id, + &ekr->h_wire, + ekr->exchange_url, + ekr->exchange_kyc_serial, + NULL, + NULL, + now, + true, /* KYC is OK, AML not... */ + ks->details.unavailable_for_legal_reasons.aml_status); if (qs < 0) { GNUNET_log (GNUNET_ERROR_TYPE_WARNING, @@ -574,70 +645,55 @@ exchange_check_cb (void *cls, /** - * Function called with the result of a #TMH_EXCHANGES_find_exchange() + * Function called with the result of a #TMH_EXCHANGES_keys4exchange() * operation. Runs the KYC check against the exchange. * * @param cls closure with our `struct ExchangeKycRequest *` - * @param hr HTTP response details - * @param eh handle to the exchange context - * @param payto_uri payto://-URI of the exchange - * @param wire_fee current applicable wire fee for dealing with @a eh, NULL if not available - * @param exchange_trusted true if this exchange is trusted by config + * @param keys keys of the exchange context + * @param exchange representation of the exchange */ static void kyc_with_exchange (void *cls, - const struct TALER_EXCHANGE_HttpResponse *hr, - struct TALER_EXCHANGE_Handle *eh, - const char *payto_uri, - const struct TALER_Amount *wire_fee, - bool exchange_trusted) + struct TALER_EXCHANGE_Keys *keys, + struct TMH_Exchange *exchange) { struct ExchangeKycRequest *ekr = cls; struct KycContext *kc = ekr->kc; struct TALER_PaytoHashP h_payto; - (void) payto_uri; - (void) wire_fee; - (void) exchange_trusted; + (void) exchange; ekr->fo = NULL; - if (MHD_HTTP_OK != hr->http_status) + if (NULL == keys) { - GNUNET_log (GNUNET_ERROR_TYPE_WARNING, - "Exchange responded with HTTP status %u (%d) to /kyc-check request!\n", - hr->http_status, - hr->ec); kc->response_code = MHD_HTTP_BAD_GATEWAY; GNUNET_assert ( 0 == json_array_append_new ( kc->timeout_kycs, GNUNET_JSON_PACK ( - GNUNET_JSON_pack_string ("exchange_url", - ekr->exchange_url), - GNUNET_JSON_pack_uint64 ("exchange_code", - hr->ec), - GNUNET_JSON_pack_uint64 ("exchange_http_status", - hr->http_status)))); + TALER_JSON_pack_ec ( + TALER_EC_MERCHANT_GENERIC_EXCHANGE_KEYS_FAILURE)))); ekr_finished (ekr); return; } TALER_payto_hash (ekr->payto_uri, &h_payto); ekr->kyc = TALER_EXCHANGE_kyc_check ( - eh, + TMH_curl_ctx, + ekr->exchange_url, + keys, ekr->exchange_kyc_serial, &h_payto, - /* FIXME: get from settings! */ - TALER_KYCLOGIC_KYC_UT_BUSINESS, - kc->timeout, + ekr->kc->mi->settings.ut, + GNUNET_TIME_absolute_get_remaining (kc->timeout), &exchange_check_cb, ekr); } /** - * Function called from ``account_kyc_get_status`` - * with KYC status information for this merchant. + * Function called from account_kyc_get_status() with KYC status information + * for this merchant. * * @param cls our `struct KycContext *` * @param h_wire hash of the wire account @@ -646,6 +702,7 @@ kyc_with_exchange (void *cls, * @param exchange_url base URL of the exchange for which this is a status * @param last_check when did we last get an update on our KYC status from the exchange * @param kyc_ok true if we satisfied the KYC requirements + * @param aml_decision latest AML decision known to us */ static void kyc_status_cb (void *cls, @@ -654,12 +711,14 @@ kyc_status_cb (void *cls, const char *payto_uri, const char *exchange_url, struct GNUNET_TIME_Timestamp last_check, - bool kyc_ok) + bool kyc_ok, + enum TALER_AmlDecisionState aml_decision) { struct KycContext *kc = cls; struct ExchangeKycRequest *ekr; if (kyc_ok && + (TALER_AML_PENDING != aml_decision) && (GNUNET_TIME_relative_cmp ( GNUNET_TIME_absolute_get_duration (last_check.abs_time), <, @@ -680,11 +739,9 @@ kyc_status_cb (void *cls, ekr->exchange_url = GNUNET_strdup (exchange_url); ekr->payto_uri = GNUNET_strdup (payto_uri); ekr->last_check = last_check; - ekr->kyc_ok = kyc_ok; ekr->kc = kc; - ekr->fo = TMH_EXCHANGES_find_exchange (exchange_url, - NULL, - GNUNET_NO, + ekr->fo = TMH_EXCHANGES_keys4exchange (exchange_url, + false, &kyc_with_exchange, ekr); } @@ -721,39 +778,13 @@ get_instances_ID_kyc (struct TMH_MerchantInstance *mi, kc->timeout_kycs = json_array (); GNUNET_assert (NULL != kc->timeout_kycs); - /* process 'timeout_ms' argument */ - { - const char *long_poll_timeout_s; - - long_poll_timeout_s - = MHD_lookup_connection_value (connection, - MHD_GET_ARGUMENT_KIND, - "timeout_ms"); - if (NULL != long_poll_timeout_s) - { - unsigned int timeout_ms; - char dummy; - - if (1 != sscanf (long_poll_timeout_s, - "%u%c", - &timeout_ms, - &dummy)) - { - GNUNET_break_op (0); - return TALER_MHD_reply_with_error (connection, - MHD_HTTP_BAD_REQUEST, - TALER_EC_GENERIC_PARAMETER_MALFORMED, - "timeout_ms must be non-negative number"); - } - kc->timeout = GNUNET_TIME_relative_multiply ( - GNUNET_TIME_UNIT_MILLISECONDS, - timeout_ms); - kc->timeout_task - = GNUNET_SCHEDULER_add_delayed (kc->timeout, - &handle_kyc_timeout, - kc); - } - } /* end timeout processing */ + TALER_MHD_parse_request_timeout (connection, + &kc->timeout); + if (! GNUNET_TIME_absolute_is_past (kc->timeout)) + kc->timeout_task + = GNUNET_SCHEDULER_add_at (kc->timeout, + &handle_kyc_timeout, + kc); /* process 'exchange_url' argument */ kc->exchange_url = MHD_lookup_connection_value (connection, @@ -775,32 +806,10 @@ get_instances_ID_kyc (struct TMH_MerchantInstance *mi, "exchange_url must be a valid HTTP(s) URL"); } - /* process 'h_wire' argument */ - { - const char *h_wire_s; - - h_wire_s - = MHD_lookup_connection_value (connection, - MHD_GET_ARGUMENT_KIND, - "h_wire"); - if (NULL != h_wire_s) - { - if (GNUNET_OK != - GNUNET_STRINGS_string_to_data (h_wire_s, - strlen (h_wire_s), - &kc->h_wire, - sizeof (kc->h_wire))) - { - GNUNET_break_op (0); - return TALER_MHD_reply_with_error (connection, - MHD_HTTP_BAD_REQUEST, - TALER_EC_GENERIC_PARAMETER_MALFORMED, - "h_wire must be Crockford base32 encoded hash"); - } - kc->have_h_wire = true; - } - } /* end of h_wire processing */ - + TALER_MHD_parse_request_arg_auto (connection, + "h_wire", + &kc->h_wire, + kc->have_h_wire); /* Check our database */ { enum GNUNET_DB_QueryStatus qs; |