merchant

Merchant backend to process payments, run by merchants
Log | Files | Refs | Submodules | README | LICENSE

taler-merchant-httpd_private-get-instances-ID-kyc.c (35203B)


      1 /*
      2   This file is part of GNU Taler
      3   (C) 2021-2024 Taler Systems SA
      4 
      5   GNU Taler is free software; you can redistribute it and/or modify
      6   it under the terms of the GNU Affero General Public License as
      7   published by the Free Software Foundation; either version 3,
      8   or (at your option) any later version.
      9 
     10   GNU Taler is distributed in the hope that it will be useful, but
     11   WITHOUT ANY WARRANTY; without even the implied warranty of
     12   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
     13   GNU General Public License for more details.
     14 
     15   You should have received a copy of the GNU General Public
     16   License along with TALER; see the file COPYING.  If not,
     17   see <http://www.gnu.org/licenses/>
     18 */
     19 
     20 /**
     21  * @file taler-merchant-httpd_private-get-instances-ID-kyc.c
     22  * @brief implementing GET /instances/$ID/kyc request handling
     23  * @author Christian Grothoff
     24  */
     25 #include "platform.h"
     26 #include "taler-merchant-httpd_private-get-instances-ID-kyc.h"
     27 #include "taler-merchant-httpd_helper.h"
     28 #include "taler-merchant-httpd_exchanges.h"
     29 #include <taler/taler_json_lib.h>
     30 #include <taler/taler_dbevents.h>
     31 #include <regex.h>
     32 
     33 /**
     34  * Information we keep per /kyc request.
     35  */
     36 struct KycContext;
     37 
     38 
     39 /**
     40  * Structure for tracking requests to the exchange's
     41  * ``/kyc-check`` API.
     42  */
     43 struct ExchangeKycRequest
     44 {
     45   /**
     46    * Kept in a DLL.
     47    */
     48   struct ExchangeKycRequest *next;
     49 
     50   /**
     51    * Kept in a DLL.
     52    */
     53   struct ExchangeKycRequest *prev;
     54 
     55   /**
     56    * Find operation where we connect to the respective exchange.
     57    */
     58   struct TMH_EXCHANGES_KeysOperation *fo;
     59 
     60   /**
     61    * JSON array of payto-URIs with KYC auth wire transfer
     62    * instructions.  Provided if @e auth_ok is false and
     63    * @e kyc_auth_conflict is false.
     64    */
     65   json_t *pkaa;
     66 
     67   /**
     68    * The keys of the exchange.
     69    */
     70   struct TALER_EXCHANGE_Keys *keys;
     71 
     72   /**
     73    * KYC request this exchange request is made for.
     74    */
     75   struct KycContext *kc;
     76 
     77   /**
     78    * JSON array of AccountLimits that apply, NULL if
     79    * unknown (and likely defaults apply).
     80    */
     81   json_t *jlimits;
     82 
     83   /**
     84    * Our account's payto URI.
     85    */
     86   struct TALER_FullPayto payto_uri;
     87 
     88   /**
     89    * Base URL of the exchange.
     90    */
     91   char *exchange_url;
     92 
     93   /**
     94    * Hash of the wire account (with salt) we are checking.
     95    */
     96   struct TALER_MerchantWireHashP h_wire;
     97 
     98   /**
     99    * Current access token for the KYC SPA. Only set
    100    * if @e auth_ok is true.
    101    */
    102   struct TALER_AccountAccessTokenP access_token;
    103 
    104   /**
    105    * Timestamp when we last got a reply from the exchange.
    106    */
    107   struct GNUNET_TIME_Timestamp last_check;
    108 
    109   /**
    110    * Last HTTP status code obtained via /kyc-check from
    111    * the exchange.
    112    */
    113   unsigned int last_http_status;
    114 
    115   /**
    116    * Last Taler error code returned from /kyc-check.
    117    */
    118   enum TALER_ErrorCode last_ec;
    119 
    120   /**
    121    * True if this account
    122    * cannot work at this exchange because KYC auth is
    123    * impossible.
    124    */
    125   bool kyc_auth_conflict;
    126 
    127   /**
    128    * We could not get /keys from the exchange.
    129    */
    130   bool no_keys;
    131 
    132   /**
    133    * True if @e access_token is available.
    134    */
    135   bool auth_ok;
    136 
    137   /**
    138    * True if we believe no KYC is currently required
    139    * for this account at this exchange.
    140    */
    141   bool kyc_ok;
    142 
    143   /**
    144    * True if the exchange exposed to us that the account
    145    * is currently under AML review.
    146    */
    147   bool in_aml_review;
    148 
    149 
    150 };
    151 
    152 
    153 /**
    154  * Information we keep per /kyc request.
    155  */
    156 struct KycContext
    157 {
    158   /**
    159    * Stored in a DLL.
    160    */
    161   struct KycContext *next;
    162 
    163   /**
    164    * Stored in a DLL.
    165    */
    166   struct KycContext *prev;
    167 
    168   /**
    169    * Connection we are handling.
    170    */
    171   struct MHD_Connection *connection;
    172 
    173   /**
    174    * Instance we are serving.
    175    */
    176   struct TMH_MerchantInstance *mi;
    177 
    178   /**
    179    * Our handler context.
    180    */
    181   struct TMH_HandlerContext *hc;
    182 
    183   /**
    184    * Response to return, NULL if we don't have one yet.
    185    */
    186   struct MHD_Response *response;
    187 
    188   /**
    189    * JSON array where we are building up the array with
    190    * pending KYC operations.
    191    */
    192   json_t *kycs_data;
    193 
    194   /**
    195    * Head of DLL of requests we are making to an
    196    * exchange to inquire about the latest KYC status.
    197    */
    198   struct ExchangeKycRequest *exchange_pending_head;
    199 
    200   /**
    201    * Tail of DLL of requests we are making to an
    202    * exchange to inquire about the latest KYC status.
    203    */
    204   struct ExchangeKycRequest *exchange_pending_tail;
    205 
    206   /**
    207    * Set to the exchange URL, or NULL to not filter by
    208    * exchange.
    209    */
    210   const char *exchange_url;
    211 
    212   /**
    213    * Notification handler from database on changes
    214    * to the KYC status.
    215    */
    216   struct GNUNET_DB_EventHandler *eh;
    217 
    218   /**
    219    * Set to the h_wire of the merchant account if
    220    * @a have_h_wire is true, used to filter by account.
    221    */
    222   struct TALER_MerchantWireHashP h_wire;
    223 
    224   /**
    225    * How long are we willing to wait for the exchange(s)?
    226    */
    227   struct GNUNET_TIME_Absolute timeout;
    228 
    229   /**
    230    * HTTP status code to use for the reply, i.e 200 for "OK".
    231    * Special value UINT_MAX is used to indicate hard errors
    232    * (no reply, return #MHD_NO).
    233    */
    234   unsigned int response_code;
    235 
    236   /**
    237    * #GNUNET_NO if the @e connection was not suspended,
    238    * #GNUNET_YES if the @e connection was suspended,
    239    * #GNUNET_SYSERR if @e connection was resumed to as
    240    * part of #MH_force_pc_resume during shutdown.
    241    */
    242   enum GNUNET_GenericReturnValue suspended;
    243 
    244   /**
    245    * What state are we long-polling for?
    246    */
    247   enum TALER_EXCHANGE_KycLongPollTarget lpt;
    248 
    249   /**
    250    * True if @e h_wire was given.
    251    */
    252   bool have_h_wire;
    253 
    254   /**
    255    * We're still waiting on the exchange to determine
    256    * the KYC status of our deposit(s).
    257    */
    258   bool return_immediately;
    259 
    260 };
    261 
    262 
    263 /**
    264  * Head of DLL.
    265  */
    266 static struct KycContext *kc_head;
    267 
    268 /**
    269  * Tail of DLL.
    270  */
    271 static struct KycContext *kc_tail;
    272 
    273 
    274 void
    275 TMH_force_kyc_resume ()
    276 {
    277   for (struct KycContext *kc = kc_head;
    278        NULL != kc;
    279        kc = kc->next)
    280   {
    281     if (GNUNET_YES == kc->suspended)
    282     {
    283       kc->suspended = GNUNET_SYSERR;
    284       MHD_resume_connection (kc->connection);
    285     }
    286   }
    287 }
    288 
    289 
    290 /**
    291  * Custom cleanup routine for a `struct KycContext`.
    292  *
    293  * @param cls the `struct KycContext` to clean up.
    294  */
    295 static void
    296 kyc_context_cleanup (void *cls)
    297 {
    298   struct KycContext *kc = cls;
    299   struct ExchangeKycRequest *ekr;
    300 
    301   while (NULL != (ekr = kc->exchange_pending_head))
    302   {
    303     GNUNET_CONTAINER_DLL_remove (kc->exchange_pending_head,
    304                                  kc->exchange_pending_tail,
    305                                  ekr);
    306     if (NULL != ekr->fo)
    307     {
    308       TMH_EXCHANGES_keys4exchange_cancel (ekr->fo);
    309       ekr->fo = NULL;
    310     }
    311     json_decref (ekr->pkaa);
    312     json_decref (ekr->jlimits);
    313     if (NULL != ekr->keys)
    314       TALER_EXCHANGE_keys_decref (ekr->keys);
    315     GNUNET_free (ekr->exchange_url);
    316     GNUNET_free (ekr->payto_uri.full_payto);
    317     GNUNET_free (ekr);
    318   }
    319   if (NULL != kc->eh)
    320   {
    321     TMH_db->event_listen_cancel (kc->eh);
    322     kc->eh = NULL;
    323   }
    324   if (NULL != kc->response)
    325   {
    326     MHD_destroy_response (kc->response);
    327     kc->response = NULL;
    328   }
    329   GNUNET_CONTAINER_DLL_remove (kc_head,
    330                                kc_tail,
    331                                kc);
    332   json_decref (kc->kycs_data);
    333   GNUNET_free (kc);
    334 }
    335 
    336 
    337 /**
    338  * Resume the given KYC context and send the final response.  Stores the
    339  * response in the @a kc and signals MHD to resume the connection.  Also
    340  * ensures MHD runs immediately.
    341  *
    342  * @param kc KYC context
    343  */
    344 static void
    345 resume_kyc_with_response (struct KycContext *kc)
    346 {
    347   kc->response_code = MHD_HTTP_OK;
    348   kc->response = TALER_MHD_MAKE_JSON_PACK (
    349     GNUNET_JSON_pack_array_incref ("kyc_data",
    350                                    kc->kycs_data));
    351   GNUNET_log (GNUNET_ERROR_TYPE_INFO,
    352               "Resuming /kyc handling as exchange interaction is done (%u)\n",
    353               MHD_HTTP_OK);
    354   if (GNUNET_YES == kc->suspended)
    355   {
    356     kc->suspended = GNUNET_NO;
    357     MHD_resume_connection (kc->connection);
    358     TALER_MHD_daemon_trigger (); /* we resumed, kick MHD */
    359   }
    360 }
    361 
    362 
    363 /**
    364  * Handle a DB event about an update relevant
    365  * for the processing of the kyc request.
    366  *
    367  * @param cls our `struct KycContext`
    368  * @param extra additional event data provided
    369  * @param extra_size number of bytes in @a extra
    370  */
    371 static void
    372 kyc_change_cb (void *cls,
    373                const void *extra,
    374                size_t extra_size)
    375 {
    376   struct KycContext *kc = cls;
    377 
    378   if (GNUNET_YES == kc->suspended)
    379   {
    380     GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
    381                 "Resuming KYC with gateway timeout\n");
    382     kc->suspended = GNUNET_NO;
    383     MHD_resume_connection (kc->connection);
    384     TALER_MHD_daemon_trigger (); /* we resumed, kick MHD */
    385   }
    386 }
    387 
    388 
    389 /**
    390  * Pack the given @a limit into the JSON @a limits array.
    391  *
    392  * @param limit account limit to pack
    393  * @param[in,out] limits JSON array to extend
    394  */
    395 static void
    396 pack_limit (const struct TALER_EXCHANGE_AccountLimit *limit,
    397             json_t *limits)
    398 {
    399   json_t *jl;
    400 
    401   jl = GNUNET_JSON_PACK (
    402     TALER_JSON_pack_kycte ("operation_type",
    403                            limit->operation_type),
    404     GNUNET_JSON_pack_time_rel ("timeframe",
    405                                limit->timeframe),
    406     TALER_JSON_pack_amount ("threshold",
    407                             &limit->threshold),
    408     GNUNET_JSON_pack_bool ("soft_limit",
    409                            limit->soft_limit)
    410     );
    411   GNUNET_assert (0 ==
    412                  json_array_append_new (limits,
    413                                         jl));
    414 }
    415 
    416 
    417 /**
    418  * Return JSON array with AccountLimit objects giving
    419  * the current limits for this exchange.
    420  *
    421  * @param[in,out] ekr overall request context
    422  */
    423 static json_t *
    424 get_exchange_limits (
    425   struct ExchangeKycRequest *ekr)
    426 {
    427   const struct TALER_EXCHANGE_Keys *keys = ekr->keys;
    428   json_t *limits;
    429 
    430   if (NULL != ekr->jlimits)
    431   {
    432     GNUNET_log (GNUNET_ERROR_TYPE_INFO,
    433                 "Returning custom KYC limits\n");
    434     return json_incref (ekr->jlimits);
    435   }
    436   if (NULL == keys)
    437   {
    438     GNUNET_log (GNUNET_ERROR_TYPE_WARNING,
    439                 "No keys, thus no default KYC limits known\n");
    440     return NULL;
    441   }
    442   GNUNET_log (GNUNET_ERROR_TYPE_INFO,
    443               "Returning default KYC limits (%u/%u)\n",
    444               keys->hard_limits_length,
    445               keys->zero_limits_length);
    446   limits = json_array ();
    447   GNUNET_assert (NULL != limits);
    448   for (unsigned int i = 0; i<keys->hard_limits_length; i++)
    449   {
    450     const struct TALER_EXCHANGE_AccountLimit *limit
    451       = &keys->hard_limits[i];
    452 
    453     pack_limit (limit,
    454                 limits);
    455   }
    456   for (unsigned int i = 0; i<keys->zero_limits_length; i++)
    457   {
    458     const struct TALER_EXCHANGE_ZeroLimitedOperation *zlimit
    459       = &keys->zero_limits[i];
    460     json_t *jl;
    461     struct TALER_Amount zero;
    462 
    463     GNUNET_assert (GNUNET_OK ==
    464                    TALER_amount_set_zero (keys->currency,
    465                                           &zero));
    466     jl = GNUNET_JSON_PACK (
    467       TALER_JSON_pack_kycte ("operation_type",
    468                              zlimit->operation_type),
    469       GNUNET_JSON_pack_time_rel ("timeframe",
    470                                  GNUNET_TIME_UNIT_ZERO),
    471       TALER_JSON_pack_amount ("threshold",
    472                               &zero),
    473       GNUNET_JSON_pack_bool ("soft_limit",
    474                              true)
    475       );
    476     GNUNET_assert (0 ==
    477                    json_array_append_new (limits,
    478                                           jl));
    479   }
    480   return limits;
    481 }
    482 
    483 
    484 /**
    485  * Maps @a ekr to a status code for clients to interpret the
    486  * overall result.
    487  *
    488  * @param ekr request summary
    489  * @return status of the KYC state as a string
    490  */
    491 static const char *
    492 map_to_status (const struct ExchangeKycRequest *ekr)
    493 {
    494   if (ekr->no_keys)
    495   {
    496     return "no-exchange-keys";
    497   }
    498   if (ekr->kyc_ok)
    499   {
    500     if (NULL != ekr->jlimits)
    501     {
    502       size_t off;
    503       json_t *limit;
    504       json_array_foreach (ekr->jlimits, off, limit)
    505       {
    506         struct TALER_Amount threshold;
    507         enum TALER_KYCLOGIC_KycTriggerEvent operation_type;
    508         bool soft = false;
    509         struct GNUNET_JSON_Specification spec[] = {
    510           TALER_JSON_spec_kycte ("operation_type",
    511                                  &operation_type),
    512           TALER_JSON_spec_amount_any ("threshold",
    513                                       &threshold),
    514           GNUNET_JSON_spec_mark_optional (
    515             GNUNET_JSON_spec_bool ("soft_limit",
    516                                    &soft),
    517             NULL),
    518           GNUNET_JSON_spec_end ()
    519         };
    520 
    521         if (GNUNET_OK !=
    522             GNUNET_JSON_parse (limit,
    523                                spec,
    524                                NULL, NULL))
    525         {
    526           GNUNET_break (0);
    527           return "merchant-internal-error";
    528         }
    529         if (! TALER_amount_is_zero (&threshold))
    530           continue; /* only care about zero-limits */
    531         if (! soft)
    532           continue; /* only care about soft limits */
    533         if ( (operation_type == TALER_KYCLOGIC_KYC_TRIGGER_DEPOSIT) ||
    534              (operation_type == TALER_KYCLOGIC_KYC_TRIGGER_AGGREGATE) ||
    535              (operation_type == TALER_KYCLOGIC_KYC_TRIGGER_TRANSACTION) )
    536         {
    537           if (! ekr->auth_ok)
    538           {
    539             if (ekr->kyc_auth_conflict)
    540               return "kyc-wire-impossible";
    541             return "kyc-wire-required";
    542           }
    543           return "kyc-required";
    544         }
    545       }
    546     }
    547     if (NULL == ekr->jlimits)
    548     {
    549       /* check default limits */
    550       const struct TALER_EXCHANGE_Keys *keys = ekr->keys;
    551 
    552       for (unsigned int i = 0; i < keys->zero_limits_length; i++)
    553       {
    554         enum TALER_KYCLOGIC_KycTriggerEvent operation_type
    555           = keys->zero_limits[i].operation_type;
    556 
    557         if ( (operation_type == TALER_KYCLOGIC_KYC_TRIGGER_DEPOSIT) ||
    558              (operation_type == TALER_KYCLOGIC_KYC_TRIGGER_AGGREGATE) ||
    559              (operation_type == TALER_KYCLOGIC_KYC_TRIGGER_TRANSACTION) )
    560         {
    561           if (! ekr->auth_ok)
    562           {
    563             if (ekr->kyc_auth_conflict)
    564               return "kyc-wire-impossible";
    565             return "kyc-wire-required";
    566           }
    567           return "kyc-required";
    568         }
    569       }
    570     }
    571     return "ready";
    572   }
    573   if (! ekr->auth_ok)
    574   {
    575     if (ekr->kyc_auth_conflict)
    576       return "kyc-wire-impossible";
    577     return "kyc-wire-required";
    578   }
    579   if (ekr->in_aml_review)
    580     return "awaiting-aml-review";
    581   switch (ekr->last_http_status)
    582   {
    583   case 0:
    584     return "exchange-unreachable";
    585   case MHD_HTTP_OK:
    586     /* then we should have kyc_ok */
    587     GNUNET_break (0);
    588     return NULL;
    589   case MHD_HTTP_ACCEPTED:
    590     /* Then KYC is really what  is needed */
    591     return "kyc-required";
    592   case MHD_HTTP_NO_CONTENT:
    593     /* then we should have had kyc_ok! */
    594     GNUNET_break (0);
    595     return NULL;
    596   case MHD_HTTP_FORBIDDEN:
    597     /* then we should have had ! auth_ok */
    598     GNUNET_break (0);
    599     return NULL;
    600   case MHD_HTTP_NOT_FOUND:
    601     /* then we should have had ! auth_ok */
    602     GNUNET_break (0);
    603     return NULL;
    604   case MHD_HTTP_CONFLICT:
    605     /* then we should have had ! auth_ok */
    606     GNUNET_break (0);
    607     return NULL;
    608   case MHD_HTTP_INTERNAL_SERVER_ERROR:
    609     return "exchange-internal-error";
    610   case MHD_HTTP_GATEWAY_TIMEOUT:
    611     return "exchange-gateway-timeout";
    612   default:
    613     GNUNET_log (GNUNET_ERROR_TYPE_WARNING,
    614                 "Exchange responded with unexpected HTTP status %u to /kyc-check request!\n",
    615                 ekr->last_http_status);
    616     break;
    617   }
    618   return "exchange-status-invalid";
    619 }
    620 
    621 
    622 /**
    623  * Take data from @a ekr to expand our response.
    624  *
    625  * @param ekr exchange we are done inspecting
    626  */
    627 static void
    628 ekr_expand_response (struct ExchangeKycRequest *ekr)
    629 {
    630   const char *status;
    631 
    632   status = map_to_status (ekr);
    633   if (NULL == status)
    634   {
    635     GNUNET_break (0);
    636     status = "logic-bug";
    637   }
    638   GNUNET_assert (
    639     0 ==
    640     json_array_append_new (
    641       ekr->kc->kycs_data,
    642       GNUNET_JSON_PACK (
    643         TALER_JSON_pack_full_payto (
    644           "payto_uri",
    645           ekr->payto_uri),
    646         GNUNET_JSON_pack_data_auto (
    647           "h_wire",
    648           &ekr->h_wire),
    649         GNUNET_JSON_pack_string (
    650           "status",
    651           status),
    652         GNUNET_JSON_pack_string (
    653           "exchange_url",
    654           ekr->exchange_url),
    655         GNUNET_JSON_pack_bool ("no_keys",
    656                                ekr->no_keys),
    657         GNUNET_JSON_pack_bool ("auth_conflict",
    658                                ekr->kyc_auth_conflict),
    659         GNUNET_JSON_pack_uint64 ("exchange_http_status",
    660                                  ekr->last_http_status),
    661         (TALER_EC_NONE == ekr->last_ec)
    662         ? GNUNET_JSON_pack_allow_null (
    663           GNUNET_JSON_pack_string (
    664             "dummy",
    665             NULL))
    666         : GNUNET_JSON_pack_uint64 ("exchange_code",
    667                                    ekr->last_ec),
    668         ekr->auth_ok
    669         ? GNUNET_JSON_pack_data_auto (
    670           "access_token",
    671           &ekr->access_token)
    672         : GNUNET_JSON_pack_allow_null (
    673           GNUNET_JSON_pack_string (
    674             "dummy",
    675             NULL)),
    676         GNUNET_JSON_pack_allow_null (
    677           GNUNET_JSON_pack_array_steal (
    678             "limits",
    679             get_exchange_limits (ekr))),
    680         GNUNET_JSON_pack_allow_null (
    681           GNUNET_JSON_pack_array_incref ("payto_kycauths",
    682                                          ekr->pkaa))
    683         )));
    684 }
    685 
    686 
    687 /**
    688  * We are done with asynchronous processing, generate the
    689  * response for the @e kc.
    690  *
    691  * @param[in,out] kc KYC context to respond for
    692  */
    693 static void
    694 kc_respond (struct KycContext *kc)
    695 {
    696   if ( (! kc->return_immediately) &&
    697        (! GNUNET_TIME_absolute_is_past (kc->timeout)) )
    698   {
    699     if (GNUNET_NO == kc->suspended)
    700     {
    701       GNUNET_log (GNUNET_ERROR_TYPE_INFO,
    702                   "Suspending: long poll target %d not reached\n",
    703                   kc->lpt);
    704       MHD_suspend_connection (kc->connection);
    705       kc->suspended = GNUNET_YES;
    706     }
    707     else
    708     {
    709       GNUNET_log (GNUNET_ERROR_TYPE_INFO,
    710                   "Remaining suspended: long poll target %d not reached\n",
    711                   kc->lpt);
    712     }
    713     return;
    714   }
    715   /* All exchange requests done, create final
    716      big response from cumulated replies */
    717   resume_kyc_with_response (kc);
    718 }
    719 
    720 
    721 /**
    722  * We are done with the KYC request @a ekr.  Remove it from the work list and
    723  * check if we are done overall.
    724  *
    725  * @param[in] ekr key request that is done (and will be freed)
    726  */
    727 static void
    728 ekr_finished (struct ExchangeKycRequest *ekr)
    729 {
    730   struct KycContext *kc = ekr->kc;
    731 
    732   ekr_expand_response (ekr);
    733   GNUNET_CONTAINER_DLL_remove (kc->exchange_pending_head,
    734                                kc->exchange_pending_tail,
    735                                ekr);
    736   json_decref (ekr->jlimits);
    737   json_decref (ekr->pkaa);
    738   if (NULL != ekr->keys)
    739     TALER_EXCHANGE_keys_decref (ekr->keys);
    740   GNUNET_free (ekr->exchange_url);
    741   GNUNET_free (ekr->payto_uri.full_payto);
    742   GNUNET_free (ekr);
    743 
    744   if (NULL != kc->exchange_pending_head)
    745     return; /* wait for more */
    746   kc_respond (kc);
    747 }
    748 
    749 
    750 /**
    751  * Figure out which exchange accounts from @a keys could
    752  * be used for a KYC auth wire transfer from the account
    753  * that @a ekr is checking. Will set the "pkaa" array
    754  * in @a ekr.
    755  *
    756  * @param[in,out] ekr request we are processing
    757  */
    758 static void
    759 determine_eligible_accounts (
    760   struct ExchangeKycRequest *ekr)
    761 {
    762   struct KycContext *kc = ekr->kc;
    763   const struct TALER_EXCHANGE_Keys *keys = ekr->keys;
    764   struct TALER_Amount kyc_amount;
    765   char *merchant_pub_str;
    766   struct TALER_NormalizedPayto np;
    767 
    768   ekr->pkaa = json_array ();
    769   GNUNET_assert (NULL != ekr->pkaa);
    770   {
    771     const struct TALER_EXCHANGE_GlobalFee *gf;
    772 
    773     gf = TALER_EXCHANGE_get_global_fee (keys,
    774                                         GNUNET_TIME_timestamp_get ());
    775     if (NULL == gf)
    776     {
    777       GNUNET_assert (GNUNET_OK ==
    778                      TALER_amount_set_zero (keys->currency,
    779                                             &kyc_amount));
    780     }
    781     else
    782     {
    783       /* FIXME-#9427: history fee should be globally renamed to KYC fee... */
    784       kyc_amount = gf->fees.history;
    785     }
    786   }
    787 
    788   merchant_pub_str
    789     = GNUNET_STRINGS_data_to_string_alloc (
    790         &kc->mi->merchant_pub,
    791         sizeof (kc->mi->merchant_pub));
    792   /* For all accounts of the exchange */
    793   np = TALER_payto_normalize (ekr->payto_uri);
    794   for (unsigned int i = 0; i<keys->accounts_len; i++)
    795   {
    796     const struct TALER_EXCHANGE_WireAccount *account
    797       = &keys->accounts[i];
    798 
    799     /* KYC auth transfers are never supported with conversion */
    800     if (NULL != account->conversion_url)
    801       continue;
    802     /* filter by source account by credit_restrictions */
    803     if (GNUNET_YES !=
    804         TALER_EXCHANGE_test_account_allowed (account,
    805                                              true, /* credit */
    806                                              np))
    807       continue;
    808     /* exchange account is allowed, add it */
    809     {
    810       const char *exchange_account_payto
    811         = account->fpayto_uri.full_payto;
    812       char *payto_kycauth;
    813 
    814       if (TALER_amount_is_zero (&kyc_amount))
    815         GNUNET_asprintf (&payto_kycauth,
    816                          "%s%cmessage=KYC:%s",
    817                          exchange_account_payto,
    818                          (NULL == strchr (exchange_account_payto,
    819                                           '?'))
    820                          ? '?'
    821                          : '&',
    822                          merchant_pub_str);
    823       else
    824         GNUNET_asprintf (&payto_kycauth,
    825                          "%s%camount=%s&message=KYC:%s",
    826                          exchange_account_payto,
    827                          (NULL == strchr (exchange_account_payto,
    828                                           '?'))
    829                          ? '?'
    830                          : '&',
    831                          TALER_amount2s (&kyc_amount),
    832                          merchant_pub_str);
    833       GNUNET_log (GNUNET_ERROR_TYPE_INFO,
    834                   "Found account %s where KYC auth is possible\n",
    835                   payto_kycauth);
    836       GNUNET_assert (0 ==
    837                      json_array_append_new (ekr->pkaa,
    838                                             json_string (payto_kycauth)));
    839       GNUNET_free (payto_kycauth);
    840     }
    841   }
    842   GNUNET_free (np.normalized_payto);
    843   GNUNET_free (merchant_pub_str);
    844 }
    845 
    846 
    847 /**
    848  * Function called with the result of a #TMH_EXCHANGES_keys4exchange()
    849  * operation.  Runs the KYC check against the exchange.
    850  *
    851  * @param cls closure with our `struct ExchangeKycRequest *`
    852  * @param keys keys of the exchange context
    853  * @param exchange representation of the exchange
    854  */
    855 static void
    856 kyc_with_exchange (void *cls,
    857                    struct TALER_EXCHANGE_Keys *keys,
    858                    struct TMH_Exchange *exchange)
    859 {
    860   struct ExchangeKycRequest *ekr = cls;
    861 
    862   (void) exchange;
    863   ekr->fo = NULL;
    864   if (NULL == keys)
    865   {
    866     GNUNET_log (GNUNET_ERROR_TYPE_WARNING,
    867                 "Failed to download `%skeys`\n",
    868                 ekr->exchange_url);
    869     ekr->no_keys = true;
    870     ekr_finished (ekr);
    871     return;
    872   }
    873   ekr->keys = TALER_EXCHANGE_keys_incref (keys);
    874   if (! ekr->auth_ok)
    875   {
    876     determine_eligible_accounts (ekr);
    877     if (0 == json_array_size (ekr->pkaa))
    878     {
    879       /* No KYC auth wire transfers are possible to this exchange from
    880          our merchant bank account, so we cannot use this account with
    881          this exchange if it has any KYC requirements! */
    882       GNUNET_log (GNUNET_ERROR_TYPE_INFO,
    883                   "KYC auth to `%s' impossible for merchant account `%s'\n",
    884                   ekr->exchange_url,
    885                   ekr->payto_uri.full_payto);
    886       ekr->kyc_auth_conflict = true;
    887     }
    888   }
    889   ekr_finished (ekr);
    890 }
    891 
    892 
    893 /**
    894  * Closure for add_unreachable_status().
    895  */
    896 struct UnreachableContext
    897 {
    898   /**
    899    * Where we are building the response.
    900    */
    901   struct KycContext *kc;
    902 
    903   /**
    904    * Pointer to our account hash.
    905    */
    906   const struct TALER_MerchantWireHashP *h_wire;
    907 
    908   /**
    909    * Bank account for which we have no status from any exchange.
    910    */
    911   struct TALER_FullPayto payto_uri;
    912 
    913 };
    914 
    915 /**
    916  * Add all trusted exchanges with "unknown" status for the
    917  * bank account given in the context.
    918  *
    919  * @param cls a `struct UnreachableContext`
    920  * @param url base URL of the exchange
    921  * @param exchange internal handle for the exchange
    922  */
    923 static void
    924 add_unreachable_status (void *cls,
    925                         const char *url,
    926                         const struct TMH_Exchange *exchange)
    927 {
    928   struct UnreachableContext *uc = cls;
    929   struct KycContext *kc = uc->kc;
    930 
    931   GNUNET_assert (
    932     0 ==
    933     json_array_append_new (
    934       kc->kycs_data,
    935       GNUNET_JSON_PACK (
    936         TALER_JSON_pack_full_payto (
    937           "payto_uri",
    938           uc->payto_uri),
    939         GNUNET_JSON_pack_data_auto (
    940           "h_wire",
    941           uc->h_wire),
    942         GNUNET_JSON_pack_string (
    943           "status",
    944           "exchange-unreachable"),
    945         GNUNET_JSON_pack_string (
    946           "exchange_url",
    947           url),
    948         GNUNET_JSON_pack_bool ("no_keys",
    949                                true),
    950         GNUNET_JSON_pack_bool ("auth_conflict",
    951                                false),
    952         GNUNET_JSON_pack_uint64 ("exchange_http_status",
    953                                  0)
    954         )));
    955 
    956 }
    957 
    958 
    959 /**
    960  * Function called from account_kyc_get_status() with KYC status information
    961  * for this merchant.
    962  *
    963  * @param cls our `struct KycContext *`
    964  * @param h_wire hash of the wire account
    965  * @param payto_uri payto:// URI of the merchant's bank account
    966  * @param exchange_url base URL of the exchange for which this is a status
    967  * @param last_check when did we last get an update on our KYC status from the exchange
    968  * @param kyc_ok true if we satisfied the KYC requirements
    969  * @param access_token access token for the KYC SPA, NULL if we cannot access it yet (need KYC auth wire transfer)
    970  * @param last_http_status last HTTP status from /kyc-check
    971  * @param last_ec last Taler error code from /kyc-check
    972  * @param in_aml_review true if the account is pending review
    973  * @param jlimits JSON array of applicable AccountLimits, or NULL if unknown (like defaults apply)
    974  */
    975 static void
    976 kyc_status_cb (
    977   void *cls,
    978   const struct TALER_MerchantWireHashP *h_wire,
    979   struct TALER_FullPayto payto_uri,
    980   const char *exchange_url,
    981   struct GNUNET_TIME_Timestamp last_check,
    982   bool kyc_ok,
    983   const struct TALER_AccountAccessTokenP *access_token,
    984   unsigned int last_http_status,
    985   enum TALER_ErrorCode last_ec,
    986   bool in_aml_review,
    987   const json_t *jlimits)
    988 {
    989   struct KycContext *kc = cls;
    990   struct ExchangeKycRequest *ekr;
    991 
    992   if (NULL == exchange_url)
    993   {
    994     struct UnreachableContext uc = {
    995       .kc = kc,
    996       .h_wire = h_wire,
    997       .payto_uri = payto_uri
    998     };
    999 
   1000     GNUNET_log (GNUNET_ERROR_TYPE_INFO,
   1001                 "Account has unknown KYC status for all exchanges.\n");
   1002     TMH_exchange_get_trusted (&add_unreachable_status,
   1003                               &uc);
   1004     kc_respond (kc);
   1005     return;
   1006   }
   1007   if (! TMH_EXCHANGES_check_trusted (exchange_url))
   1008   {
   1009     GNUNET_log (GNUNET_ERROR_TYPE_INFO,
   1010                 "Skipping exchange `%s': not trusted\n",
   1011                 exchange_url);
   1012     return;
   1013   }
   1014   GNUNET_log (GNUNET_ERROR_TYPE_INFO,
   1015               "KYC status for `%s' at `%s' is %u/%s/%s/%s\n",
   1016               payto_uri.full_payto,
   1017               exchange_url,
   1018               last_http_status,
   1019               kyc_ok ? "KYC OK" : "KYC NEEDED",
   1020               in_aml_review ? "IN AML REVIEW" : "NO AML REVIEW",
   1021               NULL == jlimits ? "DEFAULT LIMITS" : "CUSTOM LIMITS");
   1022   switch (kc->lpt)
   1023   {
   1024   case TALER_EXCHANGE_KLPT_NONE:
   1025     break;
   1026   case TALER_EXCHANGE_KLPT_KYC_AUTH_TRANSFER:
   1027     if (NULL != access_token)
   1028       kc->return_immediately = true;
   1029     break;
   1030   case TALER_EXCHANGE_KLPT_INVESTIGATION_DONE:
   1031     if (! in_aml_review)
   1032       kc->return_immediately = true;
   1033     break;
   1034   case TALER_EXCHANGE_KLPT_KYC_OK:
   1035     if (kyc_ok)
   1036       kc->return_immediately = true;
   1037     break;
   1038   }
   1039   ekr = GNUNET_new (struct ExchangeKycRequest);
   1040   GNUNET_CONTAINER_DLL_insert (kc->exchange_pending_head,
   1041                                kc->exchange_pending_tail,
   1042                                ekr);
   1043   ekr->last_http_status = last_http_status;
   1044   ekr->last_ec = last_ec;
   1045   if (NULL != jlimits)
   1046     ekr->jlimits = json_incref ((json_t *) jlimits);
   1047   ekr->h_wire = *h_wire;
   1048   ekr->exchange_url = GNUNET_strdup (exchange_url);
   1049   ekr->payto_uri.full_payto
   1050     = GNUNET_strdup (payto_uri.full_payto);
   1051   ekr->last_check = last_check;
   1052   ekr->kyc_ok = kyc_ok;
   1053   ekr->kc = kc;
   1054   ekr->in_aml_review = in_aml_review;
   1055   ekr->auth_ok = (NULL != access_token);
   1056   if ( (! ekr->auth_ok) ||
   1057        (NULL == ekr->jlimits) )
   1058   {
   1059     /* Figure out wire transfer instructions */
   1060     if (GNUNET_NO == kc->suspended)
   1061     {
   1062       MHD_suspend_connection (kc->connection);
   1063       kc->suspended = GNUNET_YES;
   1064     }
   1065     ekr->fo = TMH_EXCHANGES_keys4exchange (
   1066       exchange_url,
   1067       false,
   1068       &kyc_with_exchange,
   1069       ekr);
   1070     if (NULL == ekr->fo)
   1071     {
   1072       GNUNET_break (0);
   1073       ekr_finished (ekr);
   1074       return;
   1075     }
   1076     return;
   1077   }
   1078   ekr->access_token = *access_token;
   1079   ekr_finished (ekr);
   1080 }
   1081 
   1082 
   1083 /**
   1084  * Check the KYC status of an instance.
   1085  *
   1086  * @param mi instance to check KYC status of
   1087  * @param connection the MHD connection to handle
   1088  * @param[in,out] hc context with further information about the request
   1089  * @return MHD result code
   1090  */
   1091 static MHD_RESULT
   1092 get_instances_ID_kyc (
   1093   struct TMH_MerchantInstance *mi,
   1094   struct MHD_Connection *connection,
   1095   struct TMH_HandlerContext *hc)
   1096 {
   1097   struct KycContext *kc = hc->ctx;
   1098 
   1099   if (NULL == kc)
   1100   {
   1101     kc = GNUNET_new (struct KycContext);
   1102     kc->mi = mi;
   1103     hc->ctx = kc;
   1104     hc->cc = &kyc_context_cleanup;
   1105     GNUNET_CONTAINER_DLL_insert (kc_head,
   1106                                  kc_tail,
   1107                                  kc);
   1108     kc->connection = connection;
   1109     kc->hc = hc;
   1110     kc->kycs_data = json_array ();
   1111     GNUNET_assert (NULL != kc->kycs_data);
   1112     TALER_MHD_parse_request_timeout (connection,
   1113                                      &kc->timeout);
   1114     {
   1115       uint64_t num = 0;
   1116       int val;
   1117 
   1118       TALER_MHD_parse_request_number (connection,
   1119                                       "lpt",
   1120                                       &num);
   1121       val = (int) num;
   1122       if ( (val < 0) ||
   1123            (val > TALER_EXCHANGE_KLPT_MAX) )
   1124       {
   1125         /* Protocol violation, but we can be graceful and
   1126            just ignore the long polling! */
   1127         GNUNET_break_op (0);
   1128         val = TALER_EXCHANGE_KLPT_NONE;
   1129       }
   1130       kc->lpt = (enum TALER_EXCHANGE_KycLongPollTarget) val;
   1131     }
   1132     kc->return_immediately
   1133       = (TALER_EXCHANGE_KLPT_NONE == kc->lpt);
   1134     /* process 'exchange_url' argument */
   1135     kc->exchange_url = MHD_lookup_connection_value (
   1136       connection,
   1137       MHD_GET_ARGUMENT_KIND,
   1138       "exchange_url");
   1139     if ( (NULL != kc->exchange_url) &&
   1140          ( (! TALER_url_valid_charset (kc->exchange_url)) ||
   1141            (! TALER_is_web_url (kc->exchange_url)) ) )
   1142     {
   1143       GNUNET_break_op (0);
   1144       return TALER_MHD_reply_with_error (
   1145         connection,
   1146         MHD_HTTP_BAD_REQUEST,
   1147         TALER_EC_GENERIC_PARAMETER_MALFORMED,
   1148         "exchange_url must be a valid HTTP(s) URL");
   1149     }
   1150 
   1151     TALER_MHD_parse_request_arg_auto (connection,
   1152                                       "h_wire",
   1153                                       &kc->h_wire,
   1154                                       kc->have_h_wire);
   1155 
   1156     if ( (TALER_EXCHANGE_KLPT_NONE != kc->lpt) &&
   1157          (! GNUNET_TIME_absolute_is_past (kc->timeout)) )
   1158     {
   1159       if (kc->have_h_wire)
   1160       {
   1161         struct TALER_MERCHANTDB_MerchantKycStatusChangeEventP ev = {
   1162           .header.size = htons (sizeof (ev)),
   1163           .header.type = htons (
   1164             TALER_DBEVENT_MERCHANT_EXCHANGE_KYC_STATUS_CHANGED
   1165             ),
   1166           .h_wire = kc->h_wire
   1167         };
   1168 
   1169         kc->eh = TMH_db->event_listen (
   1170           TMH_db->cls,
   1171           &ev.header,
   1172           GNUNET_TIME_absolute_get_remaining (kc->timeout),
   1173           &kyc_change_cb,
   1174           kc);
   1175       }
   1176       else
   1177       {
   1178         struct GNUNET_DB_EventHeaderP hdr = {
   1179           .size = htons (sizeof (hdr)),
   1180           .type = htons (TALER_DBEVENT_MERCHANT_KYC_STATUS_CHANGED)
   1181         };
   1182 
   1183         kc->eh = TMH_db->event_listen (
   1184           TMH_db->cls,
   1185           &hdr,
   1186           GNUNET_TIME_absolute_get_remaining (kc->timeout),
   1187           &kyc_change_cb,
   1188           kc);
   1189       }
   1190     } /* end register LISTEN hooks */
   1191   } /* end 1st time initialization */
   1192 
   1193   if (GNUNET_SYSERR == kc->suspended)
   1194     return MHD_NO; /* during shutdown, we don't generate any more replies */
   1195   GNUNET_assert (GNUNET_NO == kc->suspended);
   1196 
   1197   if (NULL != kc->response)
   1198     return MHD_queue_response (connection,
   1199                                kc->response_code,
   1200                                kc->response);
   1201 
   1202   /* Check our database */
   1203   {
   1204     enum GNUNET_DB_QueryStatus qs;
   1205 
   1206     GNUNET_break (0 ==
   1207                   json_array_clear (kc->kycs_data));
   1208     GNUNET_log (GNUNET_ERROR_TYPE_INFO,
   1209                 "Checking KYC status for %s (%d/%s)\n",
   1210                 mi->settings.id,
   1211                 kc->have_h_wire,
   1212                 kc->exchange_url);
   1213     qs = TMH_db->account_kyc_get_status (
   1214       TMH_db->cls,
   1215       mi->settings.id,
   1216       kc->have_h_wire
   1217       ? &kc->h_wire
   1218       : NULL,
   1219       kc->exchange_url,
   1220       &kyc_status_cb,
   1221       kc);
   1222     GNUNET_log (GNUNET_ERROR_TYPE_INFO,
   1223                 "account_kyc_get_status returned %d records\n",
   1224                 (int) qs);
   1225     if (qs < 0)
   1226     {
   1227       /* Database error */
   1228       GNUNET_break (0);
   1229       if (GNUNET_YES == kc->suspended)
   1230       {
   1231         /* must have suspended before DB error, resume! */
   1232         MHD_resume_connection (connection);
   1233         kc->suspended = GNUNET_NO;
   1234       }
   1235       return TALER_MHD_reply_with_ec (
   1236         connection,
   1237         TALER_EC_GENERIC_DB_FETCH_FAILED,
   1238         "account_kyc_get_status");
   1239     }
   1240     if (GNUNET_DB_STATUS_SUCCESS_NO_RESULTS == qs)
   1241     {
   1242       /* no matching accounts, could not have suspended */
   1243       GNUNET_assert (GNUNET_NO == kc->suspended);
   1244       return TALER_MHD_reply_static (connection,
   1245                                      MHD_HTTP_NO_CONTENT,
   1246                                      NULL,
   1247                                      NULL,
   1248                                      0);
   1249     }
   1250   }
   1251   if (GNUNET_YES == kc->suspended)
   1252     return MHD_YES;
   1253   /* Should have generated a response */
   1254   GNUNET_break (NULL != kc->response);
   1255   return MHD_queue_response (connection,
   1256                              kc->response_code,
   1257                              kc->response);
   1258 }
   1259 
   1260 
   1261 MHD_RESULT
   1262 TMH_private_get_instances_ID_kyc (
   1263   const struct TMH_RequestHandler *rh,
   1264   struct MHD_Connection *connection,
   1265   struct TMH_HandlerContext *hc)
   1266 {
   1267   struct TMH_MerchantInstance *mi = hc->instance;
   1268 
   1269   (void) rh;
   1270   return get_instances_ID_kyc (mi,
   1271                                connection,
   1272                                hc);
   1273 }
   1274 
   1275 
   1276 MHD_RESULT
   1277 TMH_private_get_instances_default_ID_kyc (
   1278   const struct TMH_RequestHandler *rh,
   1279   struct MHD_Connection *connection,
   1280   struct TMH_HandlerContext *hc)
   1281 {
   1282   struct TMH_MerchantInstance *mi;
   1283 
   1284   (void) rh;
   1285   mi = TMH_lookup_instance (hc->infix);
   1286   if (NULL == mi)
   1287   {
   1288     return TALER_MHD_reply_with_error (
   1289       connection,
   1290       MHD_HTTP_NOT_FOUND,
   1291       TALER_EC_MERCHANT_GENERIC_INSTANCE_UNKNOWN,
   1292       hc->infix);
   1293   }
   1294   return get_instances_ID_kyc (mi,
   1295                                connection,
   1296                                hc);
   1297 }
   1298 
   1299 
   1300 /* end of taler-merchant-httpd_private-get-instances-ID-kyc.c */