merchant

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

taler-merchant-httpd_get-private-kyc.c (53595B)


      1 /*
      2   This file is part of GNU Taler
      3   (C) 2021-2026 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 src/backend/taler-merchant-httpd_get-private-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_exchanges.h"
     27 #include "taler-merchant-httpd_get-private-kyc.h"
     28 #include "taler-merchant-httpd_kyc-order.h"
     29 #include "taler-merchant-httpd_helper.h"
     30 #include "taler-merchant-httpd_get-exchanges.h"
     31 #include <taler/taler_json_lib.h>
     32 #include <taler/taler_templating_lib.h>
     33 #include <taler/taler_dbevents.h>
     34 #include <regex.h>
     35 #include "merchant-database/iterate_kyc_statuses.h"
     36 #include "merchant-database/event_listen.h"
     37 #include "merchant-database/set_instance.h"
     38 #include "merchant-database/get_tos_accepted_early.h"
     39 
     40 /**
     41  * Information we keep per /kyc request.
     42  */
     43 struct KycContext;
     44 
     45 
     46 /**
     47  * Structure for tracking requests to the exchange's
     48  * ``/kyc-check`` API.
     49  */
     50 struct ExchangeKycRequest
     51 {
     52   /**
     53    * Kept in a DLL.
     54    */
     55   struct ExchangeKycRequest *next;
     56 
     57   /**
     58    * Kept in a DLL.
     59    */
     60   struct ExchangeKycRequest *prev;
     61 
     62   /**
     63    * Find operation where we connect to the respective exchange.
     64    */
     65   struct TMH_EXCHANGES_KeysOperation *fo;
     66 
     67   /**
     68    * JSON array of payto-URIs with KYC auth wire transfer
     69    * instructions.  Provided if @e auth_ok is false and
     70    * @e kyc_auth_conflict is false.
     71    */
     72   json_t *pkaa;
     73 
     74   /**
     75    * The keys of the exchange.
     76    */
     77   struct TALER_EXCHANGE_Keys *keys;
     78 
     79   /**
     80    * KYC request this exchange request is made for.
     81    */
     82   struct KycContext *kc;
     83 
     84   /**
     85    * JSON array of AccountLimits that apply, NULL if
     86    * unknown (and likely defaults apply).
     87    */
     88   json_t *jlimits;
     89 
     90   /**
     91    * Our account's payto URI.
     92    */
     93   struct TALER_FullPayto payto_uri;
     94 
     95   /**
     96    * Base URL of the exchange.
     97    */
     98   char *exchange_url;
     99 
    100   /**
    101    * Hash of the wire account (with salt) we are checking.
    102    */
    103   struct TALER_MerchantWireHashP h_wire;
    104 
    105   /**
    106    * Current access token for the KYC SPA. Only set
    107    * if @e auth_ok is true.
    108    */
    109   struct TALER_AccountAccessTokenP access_token;
    110 
    111   /**
    112    * Timestamp when we last got a reply from the exchange.
    113    */
    114   struct GNUNET_TIME_Timestamp last_check;
    115 
    116   /**
    117    * Last HTTP status code obtained via /kyc-check from the exchange.
    118    */
    119   unsigned int last_http_status;
    120 
    121   /**
    122    * Last Taler error code returned from /kyc-check.
    123    */
    124   enum TALER_ErrorCode last_ec;
    125 
    126   /**
    127    * True if this account cannot work at this exchange because KYC auth is
    128    * impossible.
    129    */
    130   bool kyc_auth_conflict;
    131 
    132   /**
    133    * We could not get /keys from the exchange.
    134    */
    135   bool no_keys;
    136 
    137   /**
    138    * True if @e access_token is available.
    139    */
    140   bool auth_ok;
    141 
    142   /**
    143    * True if we believe no KYC is currently required
    144    * for this account at this exchange.
    145    */
    146   bool kyc_ok;
    147 
    148   /**
    149    * True if the exchange exposed to us that the account
    150    * is currently under AML review.
    151    */
    152   bool in_aml_review;
    153 
    154 };
    155 
    156 
    157 /**
    158  * Information we keep per /kyc request.
    159  */
    160 struct KycContext
    161 {
    162   /**
    163    * Stored in a DLL.
    164    */
    165   struct KycContext *next;
    166 
    167   /**
    168    * Stored in a DLL.
    169    */
    170   struct KycContext *prev;
    171 
    172   /**
    173    * Connection we are handling.
    174    */
    175   struct MHD_Connection *connection;
    176 
    177   /**
    178    * Instance we are serving.  We hold a reference.
    179    */
    180   struct TMH_MerchantInstance *mi;
    181 
    182   /**
    183    * Our handler context.
    184    */
    185   struct TMH_HandlerContext *hc;
    186 
    187   /**
    188    * JSON array where we are building up the array with
    189    * pending KYC operations.
    190    */
    191   json_t *kycs_data;
    192 
    193   /**
    194    * Head of DLL of requests we are making to an
    195    * exchange to inquire about the latest KYC status.
    196    */
    197   struct ExchangeKycRequest *exchange_pending_head;
    198 
    199   /**
    200    * Tail of DLL of requests we are making to an
    201    * exchange to inquire about the latest KYC status.
    202    */
    203   struct ExchangeKycRequest *exchange_pending_tail;
    204 
    205   /**
    206    * Notification handler from database on changes
    207    * to the KYC status.
    208    */
    209   struct GNUNET_DB_EventHandler *eh;
    210 
    211   /**
    212    * Set to the exchange URL, or NULL to not filter by
    213    * exchange.  "exchange_url" query parameter.
    214    */
    215   const char *exchange_url;
    216 
    217   /**
    218    * How long are we willing to wait for the exchange(s)?
    219    * Based on "timeout_ms" query parameter.
    220    */
    221   struct GNUNET_TIME_Absolute timeout;
    222 
    223   /**
    224    * Set to the h_wire of the merchant account if
    225    * @a have_h_wire is true, used to filter by account.
    226    * Set from "h_wire" query parameter.
    227    */
    228   struct TALER_MerchantWireHashP h_wire;
    229 
    230   /**
    231    * Set to the Etag of a response already known to the
    232    * client. We should only return from long-polling
    233    * on timeout (with "Not Modified") or when the Etag
    234    * of the response differs from what is given here.
    235    * Only set if @a have_lp_not_etag is true.
    236    * Set from "lp_etag" query parameter.
    237    */
    238   struct GNUNET_ShortHashCode lp_not_etag;
    239 
    240   /**
    241    * Specifies what status change we are long-polling for.  If specified, the
    242    * endpoint will only return once the status *matches* the given value.  If
    243    * multiple accounts or exchanges match the query, any account reaching the
    244    * STATUS will cause the response to be returned.
    245    */
    246   const char *lp_status;
    247 
    248   /**
    249    * Specifies what status change we are long-polling for.  If specified, the
    250    * endpoint will only return once the status no longer matches the given
    251    * value.  If multiple accounts or exchanges *no longer matches* the given
    252    * STATUS will cause the response to be returned.
    253    */
    254   const char *lp_not_status;
    255 
    256   /**
    257    * #GNUNET_NO if the @e connection was not suspended,
    258    * #GNUNET_YES if the @e connection was suspended,
    259    * #GNUNET_SYSERR if @e connection was resumed to as
    260    * part of #MH_force_pc_resume during shutdown.
    261    */
    262   enum GNUNET_GenericReturnValue suspended;
    263 
    264   /**
    265    * What state are we long-polling for? "lpt" argument.
    266    */
    267   enum TALER_EXCHANGE_KycLongPollTarget lpt;
    268 
    269   /**
    270    * Processing phase.
    271    */
    272   enum
    273   {
    274     PHASE_INIT = 0,
    275     PHASE_DETERMINE_LONG_POLL,
    276     PHASE_DATABASE_KYC_CHECK,
    277     PHASE_NO_ACCOUNTS,
    278     PHASE_GENERATE_RESPONSE,
    279     PHASE_IN_SHUTDOWN = 999,
    280     PHASE_RETURN_YES,
    281     PHASE_RETURN_NO,
    282     PHASE_SUSPENDED_ON_ACCOUNT,
    283     PHASE_SUSPENDED_ON_EXCHANGE,
    284   } phase;
    285 
    286   /**
    287    * Output format requested by the client.
    288    */
    289   enum
    290   {
    291     POF_JSON,
    292     POF_TEXT,
    293     POF_PDF
    294   } format;
    295 
    296   /**
    297    * Set to true if the database notified us about a change
    298    * in the account but we did not yet check the database
    299    * status as we were waiting on something else.
    300    */
    301   bool account_signal;
    302 
    303   /**
    304    * True if @e h_wire was given.
    305    */
    306   bool have_h_wire;
    307 
    308   /**
    309    * True if @e lp_not_etag was given.
    310    */
    311   bool have_lp_not_etag;
    312 
    313   /**
    314    * We're still waiting on the exchange to determine
    315    * the KYC status of our deposit(s).
    316    */
    317   bool return_immediately;
    318 
    319   /**
    320    * Are we currently still iterating over the database and
    321    * thus must not yet respond?
    322    */
    323   bool in_db;
    324 
    325   /**
    326    * The initial database read already requested an exchange refresh.
    327    */
    328   bool refresh_requested;
    329 };
    330 
    331 
    332 /**
    333  * Head of DLL.
    334  */
    335 static struct KycContext *kc_head;
    336 
    337 /**
    338  * Tail of DLL.
    339  */
    340 static struct KycContext *kc_tail;
    341 
    342 
    343 /* ******************* cleanup ***************** */
    344 
    345 void
    346 TMH_force_kyc_resume ()
    347 {
    348   for (struct KycContext *kc = kc_head;
    349        NULL != kc;
    350        kc = kc->next)
    351   {
    352     if (GNUNET_YES == kc->suspended)
    353     {
    354       kc->suspended = GNUNET_SYSERR;
    355       kc->phase = PHASE_IN_SHUTDOWN;
    356       MHD_resume_connection (kc->connection);
    357     }
    358   }
    359 }
    360 
    361 
    362 /**
    363  * Release resources of @a ekr
    364  *
    365  * @param[in] ekr key request data to clean up
    366  */
    367 static void
    368 ekr_cleanup (struct ExchangeKycRequest *ekr)
    369 {
    370   struct KycContext *kc = ekr->kc;
    371 
    372   GNUNET_CONTAINER_DLL_remove (kc->exchange_pending_head,
    373                                kc->exchange_pending_tail,
    374                                ekr);
    375   if (NULL != ekr->fo)
    376   {
    377     TMH_EXCHANGES_keys4exchange_cancel (ekr->fo);
    378     ekr->fo = NULL;
    379   }
    380   json_decref (ekr->pkaa);
    381   json_decref (ekr->jlimits);
    382   if (NULL != ekr->keys)
    383     TALER_EXCHANGE_keys_decref (ekr->keys);
    384   GNUNET_free (ekr->exchange_url);
    385   GNUNET_free (ekr->payto_uri.full_payto);
    386   GNUNET_free (ekr);
    387 }
    388 
    389 
    390 /**
    391  * Custom cleanup routine for a `struct KycContext`.
    392  *
    393  * @param cls the `struct KycContext` to clean up.
    394  */
    395 static void
    396 kyc_context_cleanup (void *cls)
    397 {
    398   struct KycContext *kc = cls;
    399   struct ExchangeKycRequest *ekr;
    400 
    401   while (NULL != (ekr = kc->exchange_pending_head))
    402   {
    403     ekr_cleanup (ekr);
    404   }
    405   if (NULL != kc->eh)
    406   {
    407     TALER_MERCHANTDB_event_listen_cancel (kc->eh);
    408     kc->eh = NULL;
    409   }
    410   GNUNET_CONTAINER_DLL_remove (kc_head,
    411                                kc_tail,
    412                                kc);
    413   json_decref (kc->kycs_data);
    414   TMH_instance_decref (kc->mi);
    415   GNUNET_free (kc);
    416 }
    417 
    418 
    419 /**
    420  * Finish handling the connection returning @a ret to MHD
    421  *
    422  * @param[in,out] kc connection we are handling
    423  * @param mhd_ret result to return for the @a kc request
    424  */
    425 static void
    426 finish_request (struct KycContext *kc,
    427                 enum MHD_Result mhd_ret)
    428 {
    429   kc->phase = (MHD_YES == mhd_ret)
    430     ? PHASE_RETURN_YES
    431     : PHASE_RETURN_NO;
    432 }
    433 
    434 
    435 /* ******************* phase_init ***************** */
    436 
    437 
    438 /**
    439  * Initialize basic data structures of the connection,
    440  * finishes parsing the request.
    441  *
    442  * @param[in,out] kc connection we are handling
    443  */
    444 static void
    445 phase_init (struct KycContext *kc)
    446 {
    447   kc->kycs_data = json_array ();
    448   GNUNET_assert (NULL != kc->kycs_data);
    449   /* process 'exchange_url' argument */
    450   kc->exchange_url = MHD_lookup_connection_value (
    451     kc->connection,
    452     MHD_GET_ARGUMENT_KIND,
    453     "exchange_url");
    454   if ( (NULL != kc->exchange_url) &&
    455        ( (! TALER_url_valid_charset (kc->exchange_url)) ||
    456          (! TALER_is_web_url (kc->exchange_url)) ) )
    457   {
    458     GNUNET_break_op (0);
    459     finish_request (kc,
    460                     TALER_MHD_reply_with_error (
    461                       kc->connection,
    462                       MHD_HTTP_BAD_REQUEST,
    463                       TALER_EC_GENERIC_PARAMETER_MALFORMED,
    464                       "exchange_url must be a valid HTTP(s) URL"));
    465     return;
    466   }
    467 
    468   /* Determine desired output format from Accept header */
    469   {
    470     const char *mime;
    471 
    472     mime = MHD_lookup_connection_value (kc->connection,
    473                                         MHD_HEADER_KIND,
    474                                         MHD_HTTP_HEADER_ACCEPT);
    475     if (NULL == mime)
    476       mime = "application/json";
    477     if (0 == strcmp (mime,
    478                      "*/*"))
    479       mime = "application/json";
    480     GNUNET_log (GNUNET_ERROR_TYPE_INFO,
    481                 "KYC status requested for format %s\n",
    482                 mime);
    483     if (0 == strcmp (mime,
    484                      "application/json"))
    485     {
    486       kc->format = POF_JSON;
    487     }
    488     else if (0 == strcmp (mime,
    489                           "text/plain"))
    490     {
    491       kc->format = POF_TEXT;
    492     }
    493 #if FUTURE
    494     else if (0 == strcmp (mime,
    495                           "application/pdf"))
    496     {
    497       kc->format = POF_PDF;
    498     }
    499 #endif
    500     else
    501     {
    502       GNUNET_break_op (0);
    503       finish_request (kc,
    504                       TALER_MHD_REPLY_JSON_PACK (
    505                         kc->connection,
    506                         MHD_HTTP_NOT_ACCEPTABLE,
    507                         GNUNET_JSON_pack_string ("hint",
    508                                                  mime)));
    509       return;
    510     }
    511   }
    512   kc->phase++;
    513 }
    514 
    515 
    516 /* ******************* phase_determine_long_poll ***************** */
    517 
    518 
    519 /**
    520  * Handle a DB event about an update relevant
    521  * for the processing of the kyc request.
    522  *
    523  * @param cls our `struct KycContext`
    524  * @param extra additional event data provided
    525  * @param extra_size number of bytes in @a extra
    526  */
    527 static void
    528 kyc_change_cb (void *cls,
    529                const void *extra,
    530                size_t extra_size)
    531 {
    532   struct KycContext *kc = cls;
    533 
    534   if ( (GNUNET_YES == kc->suspended) &&
    535        (PHASE_SUSPENDED_ON_ACCOUNT == kc->phase) )
    536   {
    537     GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
    538                 "Resuming KYC with gateway timeout\n");
    539     kc->suspended = GNUNET_NO;
    540     kc->phase = PHASE_DATABASE_KYC_CHECK;
    541     MHD_resume_connection (kc->connection);
    542     TALER_MHD_daemon_trigger (); /* we resumed, kick MHD */
    543   }
    544   else
    545   {
    546     /* remember for later */
    547     kc->account_signal = true;
    548   }
    549 }
    550 
    551 
    552 void
    553 TMH_kyc_keys_changed (const char *exchange_url)
    554 {
    555   for (struct KycContext *kc = kc_head;
    556        NULL != kc;
    557        kc = kc->next)
    558   {
    559     size_t off;
    560     const json_t *entry;
    561     bool affected = false;
    562 
    563     if (NULL == kc->eh)
    564       continue; /* no long poll */
    565     /* Completed account lookups live in the response; other lookups may
    566        still be waiting for keys. Check both to cover updates during reads. */
    567     json_array_foreach (kc->kycs_data, off, entry)
    568     {
    569       const char *url = json_string_value (json_object_get (entry,
    570                                                             "exchange_url"));
    571 
    572       if ( (NULL != url) &&
    573            (0 == strcmp (url, exchange_url)) )
    574       {
    575         affected = true;
    576         break;
    577       }
    578     }
    579     for (struct ExchangeKycRequest *ekr = kc->exchange_pending_head;
    580          (! affected) && (NULL != ekr);
    581          ekr = ekr->next)
    582       affected = (0 == strcmp (ekr->exchange_url, exchange_url));
    583     if (affected)
    584     {
    585       /* Keys affect ToS flags, default limits and KYC auth instructions.
    586          Recompute the full response and let its ETag determine whether to
    587          return. Like a status notification, this does not force a refresh. */
    588       kyc_change_cb (kc, NULL, 0);
    589     }
    590   }
    591 }
    592 
    593 
    594 /**
    595  * Suspend @a kc until we have a change in the account status.
    596  *
    597  * @param[in,out] kc request to suspend
    598  */
    599 static void
    600 wait_for_account (struct KycContext *kc)
    601 {
    602   GNUNET_assert (GNUNET_NO == kc->suspended);
    603   if (kc->account_signal)
    604   {
    605     /* we got a NOTIFY earlier, handle it immediately */
    606     kc->account_signal = false;
    607     kc->phase = PHASE_DATABASE_KYC_CHECK;
    608     return;
    609   }
    610   /* Wait on account notification */
    611   MHD_suspend_connection (kc->connection);
    612   kc->suspended = GNUNET_YES;
    613   kc->phase = PHASE_SUSPENDED_ON_ACCOUNT;
    614 }
    615 
    616 
    617 /**
    618  * Setup long-polling for the connection, if applicable.
    619  *
    620  * @param[in,out] kc connection we are handling
    621  */
    622 static void
    623 phase_determine_long_poll (struct KycContext *kc)
    624 {
    625   if (GNUNET_TIME_absolute_is_past (kc->timeout))
    626   {
    627     kc->phase++;
    628     return;
    629   }
    630   if (kc->have_h_wire)
    631   {
    632     struct TALER_MERCHANTDB_MerchantKycStatusChangeEventP ev = {
    633       .header.size = htons (sizeof (ev)),
    634       .header.type = htons (
    635         TALER_DBEVENT_MERCHANT_EXCHANGE_KYC_STATUS_CHANGED
    636         ),
    637       .merchant_pub = kc->mi->merchant_pub,
    638       .h_wire = kc->h_wire
    639     };
    640 
    641     kc->eh = TALER_MERCHANTDB_event_listen (
    642       TMH_db,
    643       &ev.header,
    644       GNUNET_TIME_absolute_get_remaining (kc->timeout),
    645       &kyc_change_cb,
    646       kc);
    647   }
    648   else
    649   {
    650     struct TALER_MERCHANTDB_InstanceKycStatusChangeEventP hdr = {
    651       .header.size = htons (sizeof (hdr)),
    652       .header.type = htons (TALER_DBEVENT_MERCHANT_KYC_STATUS_CHANGED),
    653       .merchant_pub = kc->mi->merchant_pub
    654     };
    655 
    656     kc->eh = TALER_MERCHANTDB_event_listen (
    657       TMH_db,
    658       &hdr.header,
    659       GNUNET_TIME_absolute_get_remaining (kc->timeout),
    660       &kyc_change_cb,
    661       kc);
    662   }
    663   kc->phase++;
    664 }
    665 
    666 
    667 /* ***************** phase_database_kyc_check ************** */
    668 
    669 
    670 /**
    671  * Maps @a ekr to a status code for clients to interpret the
    672  * overall result.
    673  *
    674  * @param ekr request summary
    675  * @return status of the KYC state as a string
    676  */
    677 static const char *
    678 map_to_status (const struct ExchangeKycRequest *ekr)
    679 {
    680   if (ekr->no_keys)
    681   {
    682     return "no-exchange-keys";
    683   }
    684   if (TALER_EC_MERCHANT_PRIVATE_ACCOUNT_NOT_ELIGIBLE_FOR_EXCHANGE ==
    685       ekr->last_ec)
    686     return "unsupported-account";
    687   if (ekr->kyc_ok)
    688   {
    689     if (NULL != ekr->jlimits)
    690     {
    691       size_t off;
    692       json_t *limit;
    693       json_array_foreach (ekr->jlimits, off, limit)
    694       {
    695         struct TALER_Amount threshold;
    696         enum TALER_KYCLOGIC_KycTriggerEvent operation_type;
    697         bool soft = false;
    698         struct GNUNET_JSON_Specification spec[] = {
    699           TALER_JSON_spec_kycte ("operation_type",
    700                                  &operation_type),
    701           TALER_JSON_spec_amount_any ("threshold",
    702                                       &threshold),
    703           GNUNET_JSON_spec_mark_optional (
    704             GNUNET_JSON_spec_bool ("soft_limit",
    705                                    &soft),
    706             NULL),
    707           GNUNET_JSON_spec_end ()
    708         };
    709 
    710         if (GNUNET_OK !=
    711             GNUNET_JSON_parse (limit,
    712                                spec,
    713                                NULL, NULL))
    714         {
    715           GNUNET_break (0);
    716           return "merchant-internal-error";
    717         }
    718         if (! TALER_amount_is_zero (&threshold))
    719           continue; /* only care about zero-limits */
    720         if (! soft)
    721           continue; /* only care about soft limits */
    722         if ( (operation_type == TALER_KYCLOGIC_KYC_TRIGGER_DEPOSIT) ||
    723              (operation_type == TALER_KYCLOGIC_KYC_TRIGGER_AGGREGATE) ||
    724              (operation_type == TALER_KYCLOGIC_KYC_TRIGGER_TRANSACTION) )
    725         {
    726           if (! ekr->auth_ok)
    727           {
    728             if (ekr->kyc_auth_conflict)
    729               return "kyc-wire-impossible";
    730             return "kyc-wire-required";
    731           }
    732           return "kyc-required";
    733         }
    734       }
    735     }
    736     if (NULL == ekr->jlimits)
    737     {
    738       /* check default limits */
    739       const struct TALER_EXCHANGE_Keys *keys = ekr->keys;
    740 
    741       for (unsigned int i = 0; i < keys->zero_limits_length; i++)
    742       {
    743         enum TALER_KYCLOGIC_KycTriggerEvent operation_type
    744           = keys->zero_limits[i].operation_type;
    745 
    746         if ( (operation_type == TALER_KYCLOGIC_KYC_TRIGGER_DEPOSIT) ||
    747              (operation_type == TALER_KYCLOGIC_KYC_TRIGGER_AGGREGATE) ||
    748              (operation_type == TALER_KYCLOGIC_KYC_TRIGGER_TRANSACTION) )
    749         {
    750           if (! ekr->auth_ok)
    751           {
    752             if (ekr->kyc_auth_conflict)
    753               return "kyc-wire-impossible";
    754             return "kyc-wire-required";
    755           }
    756           return "kyc-required";
    757         }
    758       }
    759     }
    760     return "ready";
    761   }
    762   if (! ekr->auth_ok)
    763   {
    764     if (ekr->kyc_auth_conflict)
    765       return "kyc-wire-impossible";
    766     return "kyc-wire-required";
    767   }
    768   if (ekr->in_aml_review)
    769     return "awaiting-aml-review";
    770   switch (ekr->last_http_status)
    771   {
    772   case 0:
    773     return "exchange-unreachable";
    774   case MHD_HTTP_OK:
    775     /* then we should have kyc_ok */
    776     GNUNET_break (0);
    777     return NULL;
    778   case MHD_HTTP_ACCEPTED:
    779     /* Then KYC is really what  is needed */
    780     return "kyc-required";
    781   case MHD_HTTP_NO_CONTENT:
    782     /* then we should have had kyc_ok! */
    783     GNUNET_break (0);
    784     return NULL;
    785   case MHD_HTTP_FORBIDDEN:
    786     /* then we should have had ! auth_ok */
    787     GNUNET_break (0);
    788     return NULL;
    789   case MHD_HTTP_NOT_FOUND:
    790     /* then we should have had ! auth_ok */
    791     GNUNET_break (0);
    792     return NULL;
    793   case MHD_HTTP_CONFLICT:
    794     /* then we should have had ! auth_ok */
    795     GNUNET_break (0);
    796     return NULL;
    797   case MHD_HTTP_INTERNAL_SERVER_ERROR:
    798     return "exchange-internal-error";
    799   case MHD_HTTP_GATEWAY_TIMEOUT:
    800     return "exchange-gateway-timeout";
    801   default:
    802     GNUNET_log (GNUNET_ERROR_TYPE_WARNING,
    803                 "Exchange responded with unexpected HTTP status %u to /kyc-check request!\n",
    804                 ekr->last_http_status);
    805     break;
    806   }
    807   return "exchange-status-invalid";
    808 }
    809 
    810 
    811 /**
    812  * We have found an exchange in status @a status. Clear any
    813  * long-pollers that wait for us having (or not having) this
    814  * status.
    815  *
    816  * @param[in,out] kc context
    817  * @param status the status we encountered
    818  */
    819 static void
    820 clear_status (struct KycContext *kc,
    821               const char *status)
    822 {
    823   if ( (NULL != kc->lp_status) &&
    824        (0 == strcmp (kc->lp_status,
    825                      status)) )
    826     kc->lp_status = NULL; /* satisfied! */
    827   if ( (NULL != kc->lp_not_status) &&
    828        (0 != strcmp (kc->lp_not_status,
    829                      status) ) )
    830     kc->lp_not_status = NULL; /* satisfied! */
    831 }
    832 
    833 
    834 /**
    835  * Pack the given @a limit into the JSON @a limits array.
    836  *
    837  * @param kc overall request context
    838  * @param limit account limit to pack
    839  * @param[in,out] limits JSON array to extend
    840  */
    841 static void
    842 pack_limit (const struct KycContext *kc,
    843             const struct TALER_EXCHANGE_AccountLimit *limit,
    844             json_t *limits)
    845 {
    846   json_t *jl;
    847 
    848   jl = GNUNET_JSON_PACK (
    849     TALER_JSON_pack_kycte ("operation_type",
    850                            limit->operation_type),
    851     (POF_TEXT == kc->format)
    852     ? GNUNET_JSON_pack_string ("interval",
    853                                GNUNET_TIME_relative2s (limit->timeframe,
    854                                                        true))
    855     : GNUNET_JSON_pack_time_rel ("timeframe",
    856                                  limit->timeframe),
    857     TALER_JSON_pack_amount ("threshold",
    858                             &limit->threshold),
    859     GNUNET_JSON_pack_bool ("soft_limit",
    860                            limit->soft_limit)
    861     );
    862   GNUNET_assert (0 ==
    863                  json_array_append_new (limits,
    864                                         jl));
    865 }
    866 
    867 
    868 /**
    869  * Return JSON array with AccountLimit objects giving
    870  * the current limits for this exchange.
    871  *
    872  * @param[in,out] ekr overall request context
    873  */
    874 static json_t *
    875 get_exchange_limits (
    876   struct ExchangeKycRequest *ekr)
    877 {
    878   const struct TALER_EXCHANGE_Keys *keys = ekr->keys;
    879   json_t *limits;
    880 
    881   if (NULL != ekr->jlimits)
    882   {
    883     GNUNET_log (GNUNET_ERROR_TYPE_INFO,
    884                 "Returning custom KYC limits\n");
    885     return json_incref (ekr->jlimits);
    886   }
    887   if (NULL == keys)
    888   {
    889     GNUNET_log (GNUNET_ERROR_TYPE_WARNING,
    890                 "No keys, thus no default KYC limits known\n");
    891     return NULL;
    892   }
    893   GNUNET_log (GNUNET_ERROR_TYPE_INFO,
    894               "Returning default KYC limits (%u/%u)\n",
    895               keys->hard_limits_length,
    896               keys->zero_limits_length);
    897   limits = json_array ();
    898   GNUNET_assert (NULL != limits);
    899   for (unsigned int i = 0; i<keys->hard_limits_length; i++)
    900   {
    901     const struct TALER_EXCHANGE_AccountLimit *limit
    902       = &keys->hard_limits[i];
    903 
    904     pack_limit (ekr->kc,
    905                 limit,
    906                 limits);
    907   }
    908   for (unsigned int i = 0; i<keys->zero_limits_length; i++)
    909   {
    910     const struct TALER_EXCHANGE_ZeroLimitedOperation *zlimit
    911       = &keys->zero_limits[i];
    912     json_t *jl;
    913     struct TALER_Amount zero;
    914 
    915     GNUNET_assert (GNUNET_OK ==
    916                    TALER_amount_set_zero (keys->currency,
    917                                           &zero));
    918     jl = GNUNET_JSON_PACK (
    919       TALER_JSON_pack_kycte ("operation_type",
    920                              zlimit->operation_type),
    921       GNUNET_JSON_pack_bool (
    922         "disallowed",
    923         true),
    924       (POF_TEXT == ekr->kc->format)
    925       ? GNUNET_JSON_pack_string (
    926         "interval",
    927         GNUNET_TIME_relative2s (GNUNET_TIME_UNIT_ZERO,
    928                                 true))
    929       : GNUNET_JSON_pack_time_rel ("timeframe",
    930                                    GNUNET_TIME_UNIT_ZERO),
    931       TALER_JSON_pack_amount ("threshold",
    932                               &zero),
    933       GNUNET_JSON_pack_bool ("soft_limit",
    934                              true)
    935       );
    936     GNUNET_assert (0 ==
    937                    json_array_append_new (limits,
    938                                           jl));
    939   }
    940   return limits;
    941 }
    942 
    943 
    944 /**
    945  * Take data from @a ekr to expand our response.
    946  *
    947  * @param ekr exchange we are done inspecting
    948  */
    949 static void
    950 ekr_expand_response (struct ExchangeKycRequest *ekr)
    951 {
    952   const struct KycContext *kc = ekr->kc;
    953   struct TMH_Exchange *e = TMH_EXCHANGES_lookup_exchange (ekr->exchange_url);
    954   const char *status;
    955   const char *q;
    956   char *short_account;
    957   bool kyc_swap_tos_acceptance = false;
    958   char *tos_accepted_early = NULL;
    959 
    960   GNUNET_assert (NULL != e);
    961   status = map_to_status (ekr);
    962   if (NULL == status)
    963   {
    964     GNUNET_break (0);
    965     status = "logic-bug";
    966   }
    967   clear_status (ekr->kc,
    968                 status);
    969   q = strchr (ekr->payto_uri.full_payto,
    970               '?');
    971   if (NULL == q)
    972     short_account = GNUNET_strdup (ekr->payto_uri.full_payto);
    973   else
    974     short_account = GNUNET_strndup (ekr->payto_uri.full_payto,
    975                                     q - ekr->payto_uri.full_payto);
    976   if (NULL != ekr->keys)
    977     kyc_swap_tos_acceptance = ekr->keys->kyc_swap_tos_acceptance;
    978   {
    979     enum GNUNET_DB_QueryStatus qs;
    980 
    981     qs = TALER_MERCHANTDB_set_instance (
    982       TMH_db,
    983       kc->mi->settings.id);
    984     if (0 >= qs)
    985     {
    986       GNUNET_break (0);
    987       tos_accepted_early = NULL;
    988     }
    989     else
    990     {
    991       qs = TALER_MERCHANTDB_get_tos_accepted_early (TMH_db,
    992                                                     kc->mi->settings.id,
    993                                                     ekr->exchange_url,
    994                                                     &tos_accepted_early);
    995       GNUNET_break (GNUNET_DB_STATUS_SUCCESS_ONE_RESULT ==
    996                     TALER_MERCHANTDB_set_instance (
    997                       TMH_db,
    998                       NULL));
    999       if (qs < 0)
   1000       {
   1001         GNUNET_break (0);
   1002         /* fall through with tos_accepted_early == NULL */
   1003         tos_accepted_early = NULL;
   1004       }
   1005     }
   1006   }
   1007   GNUNET_assert (
   1008     0 ==
   1009     json_array_append_new (
   1010       ekr->kc->kycs_data,
   1011       GNUNET_JSON_PACK (
   1012         (POF_TEXT == kc->format)
   1013         ? GNUNET_JSON_pack_string (
   1014           "short_payto_uri",
   1015           short_account)
   1016         : TALER_JSON_pack_full_payto (
   1017           "payto_uri",
   1018           ekr->payto_uri),
   1019         GNUNET_JSON_pack_data_auto (
   1020           "h_wire",
   1021           &ekr->h_wire),
   1022         GNUNET_JSON_pack_string (
   1023           "status",
   1024           status),
   1025         GNUNET_JSON_pack_string (
   1026           "exchange_url",
   1027           ekr->exchange_url),
   1028         GNUNET_JSON_pack_string (
   1029           "exchange_currency",
   1030           TMH_EXCHANGES_get_currency (e)),
   1031         GNUNET_JSON_pack_bool ("no_keys",
   1032                                ekr->no_keys),
   1033         GNUNET_JSON_pack_bool ("auth_conflict",
   1034                                ekr->kyc_auth_conflict),
   1035         GNUNET_JSON_pack_bool ("kyc_swap_tos_acceptance",
   1036                                kyc_swap_tos_acceptance),
   1037         GNUNET_JSON_pack_allow_null (
   1038           GNUNET_JSON_pack_string (
   1039             "tos_accepted_early",
   1040             tos_accepted_early)),
   1041         GNUNET_JSON_pack_uint64 ("exchange_http_status",
   1042                                  ekr->last_http_status),
   1043         GNUNET_JSON_pack_conditional (
   1044           TALER_EC_NONE != ekr->last_ec,
   1045           GNUNET_JSON_pack_uint64 ("exchange_code",
   1046                                    ekr->last_ec)),
   1047         GNUNET_JSON_pack_conditional (
   1048           ekr->auth_ok,
   1049           GNUNET_JSON_pack_data_auto (
   1050             "access_token",
   1051             &ekr->access_token)),
   1052         GNUNET_JSON_pack_allow_null (
   1053           GNUNET_JSON_pack_array_steal (
   1054             "limits",
   1055             get_exchange_limits (ekr))),
   1056         GNUNET_JSON_pack_allow_null (
   1057           GNUNET_JSON_pack_array_incref ("payto_kycauths",
   1058                                          ekr->pkaa))
   1059         )));
   1060   GNUNET_free (tos_accepted_early);
   1061   GNUNET_free (short_account);
   1062 }
   1063 
   1064 
   1065 /**
   1066  * We are done with the KYC request @a ekr.  Remove it from the work list and
   1067  * check if we are done overall.
   1068  *
   1069  * @param[in] ekr key request that is done (and will be freed)
   1070  */
   1071 static void
   1072 ekr_finished (struct ExchangeKycRequest *ekr)
   1073 {
   1074   struct KycContext *kc = ekr->kc;
   1075 
   1076   ekr_expand_response (ekr);
   1077   ekr_cleanup (ekr);
   1078   if (NULL != kc->exchange_pending_head)
   1079     return; /* wait for more */
   1080   if (kc->in_db)
   1081     return;
   1082   GNUNET_assert (GNUNET_YES == kc->suspended);
   1083   kc->phase = PHASE_GENERATE_RESPONSE;
   1084   kc->suspended = GNUNET_NO;
   1085   MHD_resume_connection (kc->connection);
   1086   TALER_MHD_daemon_trigger (); /* we resumed, kick MHD */
   1087 }
   1088 
   1089 
   1090 /**
   1091  * Figure out which exchange accounts from @a keys could
   1092  * be used for a KYC auth wire transfer from the account
   1093  * that @a ekr is checking. Will set the "pkaa" array
   1094  * in @a ekr.
   1095  *
   1096  * @param[in,out] ekr request we are processing
   1097  */
   1098 static void
   1099 determine_eligible_accounts (
   1100   struct ExchangeKycRequest *ekr)
   1101 {
   1102   struct KycContext *kc = ekr->kc;
   1103   const struct TALER_EXCHANGE_Keys *keys = ekr->keys;
   1104   struct TALER_Amount kyc_amount;
   1105   char *merchant_pub_str;
   1106   struct TALER_NormalizedPayto np;
   1107 
   1108   {
   1109     const struct TALER_EXCHANGE_GlobalFee *gf;
   1110 
   1111     gf = TALER_EXCHANGE_get_global_fee (keys,
   1112                                         GNUNET_TIME_timestamp_get ());
   1113     if (NULL == gf)
   1114     {
   1115       GNUNET_assert (GNUNET_OK ==
   1116                      TALER_amount_set_zero (keys->currency,
   1117                                             &kyc_amount));
   1118     }
   1119     else
   1120     {
   1121       /* FIXME-#9427: history fee should be globally renamed to KYC fee... */
   1122       kyc_amount = gf->fees.history;
   1123     }
   1124   }
   1125 
   1126   merchant_pub_str
   1127     = GNUNET_STRINGS_data_to_string_alloc (
   1128         &kc->mi->merchant_pub,
   1129         sizeof (kc->mi->merchant_pub));
   1130   /* For all accounts of the exchange */
   1131   np = TALER_payto_normalize (ekr->payto_uri);
   1132   for (unsigned int i = 0; i<keys->accounts_len; i++)
   1133   {
   1134     const struct TALER_EXCHANGE_WireAccount *account
   1135       = &keys->accounts[i];
   1136 
   1137     /* KYC auth transfers are never supported with conversion */
   1138     if (NULL != account->conversion_url)
   1139       continue;
   1140     /* filter by source account by credit_restrictions */
   1141     if (GNUNET_YES !=
   1142         TALER_EXCHANGE_test_account_allowed (account,
   1143                                              true, /* credit */
   1144                                              np))
   1145       continue;
   1146     /* exchange account is allowed, add it */
   1147     // FIXME: #11520: support short wire transfer subjects!
   1148     // if (NULL != account->prepared_transfer_url) // ...
   1149     {
   1150       const char *exchange_account_payto
   1151         = account->fpayto_uri.full_payto;
   1152       char *payto_kycauth;
   1153 
   1154       if (TALER_amount_is_zero (&kyc_amount))
   1155         GNUNET_asprintf (&payto_kycauth,
   1156                          "%s%cmessage=KYC:%s",
   1157                          exchange_account_payto,
   1158                          (NULL == strchr (exchange_account_payto,
   1159                                           '?'))
   1160                          ? '?'
   1161                          : '&',
   1162                          merchant_pub_str);
   1163       else
   1164         GNUNET_asprintf (&payto_kycauth,
   1165                          "%s%camount=%s&message=KYC:%s",
   1166                          exchange_account_payto,
   1167                          (NULL == strchr (exchange_account_payto,
   1168                                           '?'))
   1169                          ? '?'
   1170                          : '&',
   1171                          TALER_amount2s (&kyc_amount),
   1172                          merchant_pub_str);
   1173       GNUNET_log (GNUNET_ERROR_TYPE_INFO,
   1174                   "Found account %s where KYC auth is possible\n",
   1175                   payto_kycauth);
   1176       GNUNET_assert (0 ==
   1177                      json_array_append_new (ekr->pkaa,
   1178                                             json_string (payto_kycauth)));
   1179       GNUNET_free (payto_kycauth);
   1180     }
   1181   }
   1182   GNUNET_free (np.normalized_payto);
   1183   GNUNET_free (merchant_pub_str);
   1184 }
   1185 
   1186 
   1187 /**
   1188  * Function called with the result of a #TMH_EXCHANGES_keys4exchange()
   1189  * operation.  Runs the KYC check against the exchange.
   1190  *
   1191  * @param cls closure with our `struct ExchangeKycRequest *`
   1192  * @param keys keys of the exchange context
   1193  * @param exchange representation of the exchange
   1194  */
   1195 static void
   1196 kyc_with_exchange (void *cls,
   1197                    struct TALER_EXCHANGE_Keys *keys,
   1198                    struct TMH_Exchange *exchange)
   1199 {
   1200   struct ExchangeKycRequest *ekr = cls;
   1201 
   1202   (void) exchange;
   1203   ekr->fo = NULL;
   1204   if (NULL == keys)
   1205   {
   1206     GNUNET_log (GNUNET_ERROR_TYPE_WARNING,
   1207                 "Failed to download `%skeys`\n",
   1208                 ekr->exchange_url);
   1209     ekr->no_keys = true;
   1210     ekr_finished (ekr);
   1211     return;
   1212   }
   1213   GNUNET_log (GNUNET_ERROR_TYPE_INFO,
   1214               "Got /keys for `%s'\n",
   1215               ekr->exchange_url);
   1216   ekr->keys = TALER_EXCHANGE_keys_incref (keys);
   1217   if (! ekr->auth_ok)
   1218   {
   1219     ekr->pkaa = json_array ();
   1220     GNUNET_assert (NULL != ekr->pkaa);
   1221     determine_eligible_accounts (ekr);
   1222     if (0 == json_array_size (ekr->pkaa))
   1223     {
   1224       /* No KYC auth wire transfers are possible to this exchange from
   1225          our merchant bank account, so we cannot use this account with
   1226          this exchange if it has any KYC requirements! */
   1227       GNUNET_log (GNUNET_ERROR_TYPE_INFO,
   1228                   "KYC auth to `%s' impossible for merchant account `%s'\n",
   1229                   ekr->exchange_url,
   1230                   ekr->payto_uri.full_payto);
   1231       ekr->kyc_auth_conflict = true;
   1232     }
   1233   }
   1234   ekr_finished (ekr);
   1235 }
   1236 
   1237 
   1238 /**
   1239  * Closure for add_unreachable_status().
   1240  */
   1241 struct UnreachableContext
   1242 {
   1243   /**
   1244    * Where we are building the response.
   1245    */
   1246   struct KycContext *kc;
   1247 
   1248   /**
   1249    * Pointer to our account hash.
   1250    */
   1251   const struct TALER_MerchantWireHashP *h_wire;
   1252 
   1253   /**
   1254    * Bank account for which we have no status from any exchange.
   1255    */
   1256   struct TALER_FullPayto payto_uri;
   1257 
   1258 };
   1259 
   1260 
   1261 /**
   1262  * Add all trusted exchanges with "unknown" status for the
   1263  * bank account given in the context.
   1264  *
   1265  * @param cls a `struct UnreachableContext`
   1266  * @param url base URL of the exchange
   1267  * @param exchange internal handle for the exchange
   1268  */
   1269 static void
   1270 add_unreachable_status (void *cls,
   1271                         const char *url,
   1272                         const struct TMH_Exchange *exchange)
   1273 {
   1274   struct UnreachableContext *uc = cls;
   1275   struct KycContext *kc = uc->kc;
   1276 
   1277   clear_status (kc,
   1278                 "exchange-unreachable");
   1279   GNUNET_assert (
   1280     0 ==
   1281     json_array_append_new (
   1282       kc->kycs_data,
   1283       GNUNET_JSON_PACK (
   1284         TALER_JSON_pack_full_payto (
   1285           "payto_uri",
   1286           uc->payto_uri),
   1287         GNUNET_JSON_pack_data_auto (
   1288           "h_wire",
   1289           uc->h_wire),
   1290         GNUNET_JSON_pack_string (
   1291           "exchange_currency",
   1292           TMH_EXCHANGES_get_currency (exchange)),
   1293         GNUNET_JSON_pack_string (
   1294           "status",
   1295           "exchange-unreachable"),
   1296         GNUNET_JSON_pack_string (
   1297           "exchange_url",
   1298           url),
   1299         GNUNET_JSON_pack_bool ("no_keys",
   1300                                true),
   1301         GNUNET_JSON_pack_bool ("auth_conflict",
   1302                                false),
   1303         GNUNET_JSON_pack_uint64 ("exchange_http_status",
   1304                                  0)
   1305         )));
   1306 
   1307 }
   1308 
   1309 
   1310 /**
   1311  * Function called from iterate_kyc_statuses() with KYC status information
   1312  * for this merchant.
   1313  *
   1314  * @param cls our `struct KycContext *`
   1315  * @param h_wire hash of the wire account
   1316  * @param payto_uri payto:// URI of the merchant's bank account
   1317  * @param exchange_url base URL of the exchange for which this is a status
   1318  * @param last_check when did we last get an update on our KYC status from the exchange
   1319  * @param kyc_ok true if we satisfied the KYC requirements
   1320  * @param access_token access token for the KYC SPA, NULL if we cannot access it yet (need KYC auth wire transfer)
   1321  * @param last_http_status last HTTP status from /kyc-check
   1322  * @param last_ec last Taler error code from /kyc-check
   1323  * @param in_aml_review true if the account is pending review
   1324  * @param jlimits JSON array of applicable AccountLimits, or NULL if unknown (like defaults apply)
   1325  */
   1326 static void
   1327 kyc_status_cb (
   1328   void *cls,
   1329   const struct TALER_MerchantWireHashP *h_wire,
   1330   struct TALER_FullPayto payto_uri,
   1331   const char *exchange_url,
   1332   struct GNUNET_TIME_Timestamp last_check,
   1333   bool kyc_ok,
   1334   const struct TALER_AccountAccessTokenP *access_token,
   1335   unsigned int last_http_status,
   1336   enum TALER_ErrorCode last_ec,
   1337   bool in_aml_review,
   1338   const json_t *jlimits)
   1339 {
   1340   struct KycContext *kc = cls;
   1341   struct ExchangeKycRequest *ekr;
   1342 
   1343   if (NULL == exchange_url)
   1344   {
   1345     struct UnreachableContext uc = {
   1346       .kc = kc,
   1347       .h_wire = h_wire,
   1348       .payto_uri = payto_uri
   1349     };
   1350 
   1351     GNUNET_log (GNUNET_ERROR_TYPE_INFO,
   1352                 "Account has unknown KYC status for all exchanges.\n");
   1353     TMH_exchange_get_trusted (&add_unreachable_status,
   1354                               &uc);
   1355     return;
   1356   }
   1357   if (! TMH_EXCHANGES_check_trusted (exchange_url))
   1358   {
   1359     GNUNET_log (GNUNET_ERROR_TYPE_INFO,
   1360                 "Skipping exchange `%s': not trusted\n",
   1361                 exchange_url);
   1362     return;
   1363   }
   1364   GNUNET_log (GNUNET_ERROR_TYPE_INFO,
   1365               "KYC status for `%s' at `%s' is %u/%s/%s/%s\n",
   1366               payto_uri.full_payto,
   1367               exchange_url,
   1368               last_http_status,
   1369               kyc_ok ? "KYC OK" : "KYC NEEDED",
   1370               in_aml_review ? "IN AML REVIEW" : "NO AML REVIEW",
   1371               NULL == jlimits ? "DEFAULT LIMITS" : "CUSTOM LIMITS");
   1372   switch (kc->lpt)
   1373   {
   1374   case TALER_EXCHANGE_KLPT_NONE:
   1375     break;
   1376   case TALER_EXCHANGE_KLPT_KYC_AUTH_TRANSFER:
   1377     if (NULL != access_token)
   1378       kc->return_immediately = true;
   1379     break;
   1380   case TALER_EXCHANGE_KLPT_INVESTIGATION_DONE:
   1381     if (! in_aml_review)
   1382       kc->return_immediately = true;
   1383     break;
   1384   case TALER_EXCHANGE_KLPT_KYC_OK:
   1385     if (kyc_ok)
   1386       kc->return_immediately = true;
   1387     break;
   1388   }
   1389   ekr = GNUNET_new (struct ExchangeKycRequest);
   1390   GNUNET_CONTAINER_DLL_insert (kc->exchange_pending_head,
   1391                                kc->exchange_pending_tail,
   1392                                ekr);
   1393   ekr->last_http_status = last_http_status;
   1394   ekr->last_ec = last_ec;
   1395   if (NULL != jlimits)
   1396     ekr->jlimits = json_incref ((json_t *) jlimits);
   1397   ekr->h_wire = *h_wire;
   1398   ekr->exchange_url = GNUNET_strdup (exchange_url);
   1399   ekr->payto_uri.full_payto
   1400     = GNUNET_strdup (payto_uri.full_payto);
   1401   ekr->last_check = last_check;
   1402   ekr->kyc_ok = kyc_ok;
   1403   ekr->kc = kc;
   1404   ekr->in_aml_review = in_aml_review;
   1405   ekr->auth_ok = (NULL != access_token);
   1406   if ( (! ekr->auth_ok) ||
   1407        (NULL == ekr->jlimits) )
   1408   {
   1409     GNUNET_log (GNUNET_ERROR_TYPE_INFO,
   1410                 "Awaiting /keys from `%s'\n",
   1411                 exchange_url);
   1412     /* Figure out wire transfer instructions */
   1413     ekr->fo = TMH_EXCHANGES_keys4exchange (
   1414       exchange_url,
   1415       false,
   1416       &kyc_with_exchange,
   1417       ekr);
   1418     if (NULL == ekr->fo)
   1419     {
   1420       GNUNET_break (0);
   1421       ekr_finished (ekr);
   1422       return;
   1423     }
   1424     return;
   1425   }
   1426   ekr->access_token = *access_token;
   1427   ekr_finished (ekr);
   1428 }
   1429 
   1430 
   1431 /**
   1432  * Check our database for the KYC status. Determines if we then
   1433  * need to wait on exchange data or have no exchange and can
   1434  * immediately proceed to return 204.
   1435  *
   1436  * @param[in,out] kc connection we are handling
   1437  */
   1438 static void
   1439 phase_database_kyc_check (struct KycContext *kc)
   1440 {
   1441   enum GNUNET_DB_QueryStatus qs;
   1442 
   1443   GNUNET_log (GNUNET_ERROR_TYPE_INFO,
   1444               "Checking KYC status for %s (%d/%s)\n",
   1445               kc->mi->settings.id,
   1446               kc->have_h_wire,
   1447               kc->exchange_url);
   1448   /* We may run repeatedly due to long-polling; clear data
   1449      from previous runs first */
   1450   GNUNET_break (0 ==
   1451                 json_array_clear (kc->kycs_data));
   1452   /* On the /management/ path, the request was dispatched to the
   1453      admin instance, but we must query the instance in @e mi. */
   1454   qs = TALER_MERCHANTDB_set_instance (TMH_db,
   1455                                       kc->mi->settings.id);
   1456   if (GNUNET_DB_STATUS_SUCCESS_ONE_RESULT != qs)
   1457   {
   1458     GNUNET_break (0);
   1459     finish_request (kc,
   1460                     TALER_MHD_reply_with_error (
   1461                       kc->connection,
   1462                       (GNUNET_DB_STATUS_SUCCESS_NO_RESULTS == qs)
   1463                       ? MHD_HTTP_NOT_FOUND
   1464                       : MHD_HTTP_INTERNAL_SERVER_ERROR,
   1465                       (GNUNET_DB_STATUS_SUCCESS_NO_RESULTS == qs)
   1466                       ? TALER_EC_MERCHANT_GENERIC_INSTANCE_UNKNOWN
   1467                       : TALER_EC_GENERIC_DB_SETUP_FAILED,
   1468                       kc->mi->settings.id));
   1469     return;
   1470   }
   1471   kc->in_db = true;
   1472   qs = TALER_MERCHANTDB_iterate_kyc_statuses (
   1473     TMH_db,
   1474     kc->mi->settings.id,
   1475     kc->have_h_wire
   1476       ? &kc->h_wire
   1477       : NULL,
   1478     kc->exchange_url,
   1479     ! kc->refresh_requested,
   1480     &kyc_status_cb,
   1481     kc);
   1482   kc->in_db = false;
   1483   if (qs >= 0)
   1484     kc->refresh_requested = true;
   1485   GNUNET_log (GNUNET_ERROR_TYPE_INFO,
   1486               "iterate_kyc_statuses returned %d records\n",
   1487               (int) qs);
   1488   switch (qs)
   1489   {
   1490   case GNUNET_DB_STATUS_HARD_ERROR:
   1491   case GNUNET_DB_STATUS_SOFT_ERROR:
   1492     /* Database error */
   1493     GNUNET_break (0);
   1494     finish_request (kc,
   1495                     TALER_MHD_reply_with_ec (
   1496                       kc->connection,
   1497                       TALER_EC_GENERIC_DB_FETCH_FAILED,
   1498                       "iterate_kyc_statuses"));
   1499     return;
   1500   case GNUNET_DB_STATUS_SUCCESS_NO_RESULTS:
   1501     kc->phase = PHASE_NO_ACCOUNTS;
   1502     return;
   1503   case GNUNET_DB_STATUS_SUCCESS_ONE_RESULT:
   1504     /* Handled below */
   1505     break;
   1506   }
   1507   if (NULL == kc->exchange_pending_head)
   1508   {
   1509     kc->phase = PHASE_GENERATE_RESPONSE;
   1510     return;
   1511   }
   1512   MHD_suspend_connection (kc->connection);
   1513   kc->suspended = GNUNET_YES;
   1514   kc->phase = PHASE_SUSPENDED_ON_EXCHANGE;
   1515 }
   1516 
   1517 
   1518 /* ********************* phase_no_accounts *********** */
   1519 
   1520 /**
   1521  * We have no accounts, return a 204 No content,
   1522  * or suspend if long-polling.
   1523  *
   1524  * @param[in,out] kc connection we are handling
   1525  */
   1526 static void
   1527 phase_no_accounts (struct KycContext *kc)
   1528 {
   1529   /* We use an Etag of all zeros for the 204 status code */
   1530   static struct GNUNET_ShortHashCode zero_etag;
   1531   struct MHD_Response *response;
   1532 
   1533   /* no matching accounts, could not have suspended */
   1534   GNUNET_assert (GNUNET_NO == kc->suspended);
   1535   if (kc->have_lp_not_etag &&
   1536       (0 == GNUNET_memcmp (&zero_etag,
   1537                            &kc->lp_not_etag)) &&
   1538       (! GNUNET_TIME_absolute_is_past (kc->timeout)) )
   1539   {
   1540     GNUNET_log (GNUNET_ERROR_TYPE_INFO,
   1541                 "No matching accounts, suspending to wait for this to change\n");
   1542     MHD_suspend_connection (kc->connection);
   1543     kc->suspended = GNUNET_YES;
   1544     kc->phase = PHASE_SUSPENDED_ON_ACCOUNT;
   1545     return;
   1546   }
   1547   GNUNET_log (GNUNET_ERROR_TYPE_INFO,
   1548               "No matching accounts, returning empty response\n");
   1549   response = MHD_create_response_from_buffer_static (0,
   1550                                                      NULL);
   1551   TALER_MHD_add_global_headers (response,
   1552                                 false);
   1553   {
   1554     char *etag;
   1555 
   1556     etag = GNUNET_STRINGS_data_to_string_alloc (&zero_etag,
   1557                                                 sizeof (zero_etag));
   1558     GNUNET_break (MHD_YES ==
   1559                   MHD_add_response_header (response,
   1560                                            MHD_HTTP_HEADER_ETAG,
   1561                                            etag));
   1562     GNUNET_free (etag);
   1563   }
   1564   finish_request (kc,
   1565                   MHD_queue_response (kc->connection,
   1566                                       MHD_HTTP_NO_CONTENT,
   1567                                       response));
   1568   MHD_destroy_response (response);
   1569 }
   1570 
   1571 
   1572 /* ********************* phase_generate_response *********** */
   1573 
   1574 /**
   1575  * Resume the given KYC context and send the final response.  Stores the
   1576  * response in the @a kc and signals MHD to resume the connection.  Also
   1577  * ensures MHD runs immediately.
   1578  *
   1579  * @param kc KYC context
   1580  */
   1581 static void
   1582 resume_kyc_with_response (struct KycContext *kc)
   1583 {
   1584   struct GNUNET_ShortHashCode sh;
   1585   bool not_modified;
   1586   char *can;
   1587   unsigned int response_code;
   1588   struct MHD_Response *response;
   1589 
   1590   /* The database returns KYC records in a stable order, but entries that
   1591      require exchange /keys data are appended when their asynchronous lookup
   1592      finishes.  Sort only after all lookups are done so callback timing and
   1593      synthetic exchange-unreachable entries cannot affect the response or its
   1594      ETag. */
   1595   TMH_kyc_data_sort (kc->kycs_data);
   1596   can = TALER_JSON_canonicalize (kc->kycs_data);
   1597   GNUNET_assert (GNUNET_YES ==
   1598                  GNUNET_CRYPTO_hkdf_gnunet (&sh,
   1599                                             sizeof (sh),
   1600                                             "KYC-SALT",
   1601                                             strlen ("KYC-SALT"),
   1602                                             can,
   1603                                             strlen (can)));
   1604   not_modified = kc->have_lp_not_etag &&
   1605                  (0 == GNUNET_memcmp (&sh,
   1606                                       &kc->lp_not_etag));
   1607   if (not_modified &&
   1608       (! GNUNET_TIME_absolute_is_past (kc->timeout)) )
   1609   {
   1610     GNUNET_log (GNUNET_ERROR_TYPE_INFO,
   1611                 "Status unchanged, not returning response yet\n");
   1612     wait_for_account (kc);
   1613     GNUNET_free (can);
   1614     return;
   1615   }
   1616   {
   1617     const char *inm;
   1618 
   1619     inm = MHD_lookup_connection_value (kc->connection,
   1620                                        MHD_HEADER_KIND,
   1621                                        MHD_HTTP_HEADER_IF_NONE_MATCH);
   1622     if ( (NULL == inm) ||
   1623          ('"' != inm[0]) ||
   1624          ('"' != inm[strlen (inm) - 1]) ||
   1625          (0 != strncmp (inm + 1,
   1626                         can,
   1627                         strlen (can))) )
   1628       not_modified = false; /* must return full response */
   1629   }
   1630   GNUNET_free (can);
   1631   response_code = not_modified
   1632     ? MHD_HTTP_NOT_MODIFIED
   1633     : MHD_HTTP_OK;
   1634   switch (kc->format)
   1635   {
   1636   case POF_JSON:
   1637     response = TALER_MHD_MAKE_JSON_PACK (
   1638       GNUNET_JSON_pack_array_incref ("kyc_data",
   1639                                      kc->kycs_data));
   1640     break;
   1641   case POF_TEXT:
   1642     {
   1643       enum GNUNET_GenericReturnValue ret;
   1644       json_t *obj;
   1645 
   1646       obj = GNUNET_JSON_PACK (
   1647         GNUNET_JSON_pack_array_incref ("kyc_data",
   1648                                        kc->kycs_data));
   1649       ret = TALER_TEMPLATING_build (kc->connection,
   1650                                     &response_code,
   1651                                     "kyc_text",
   1652                                     kc->mi->settings.id,
   1653                                     NULL,
   1654                                     obj,
   1655                                     &response);
   1656       json_decref (obj);
   1657       switch (ret)
   1658       {
   1659       case GNUNET_SYSERR:
   1660         /* failed to even produce a response */
   1661         GNUNET_break (0);
   1662         kc->phase = PHASE_RETURN_NO;
   1663         return;
   1664       case GNUNET_NO:
   1665         finish_request (kc,
   1666                         MHD_queue_response (
   1667                           kc->connection,
   1668                           response_code,
   1669                           response));
   1670         MHD_destroy_response (response);
   1671         return;
   1672       case GNUNET_OK:
   1673         TALER_MHD_add_global_headers (response,
   1674                                       false);
   1675         GNUNET_break (MHD_YES ==
   1676                       MHD_add_response_header (response,
   1677                                                MHD_HTTP_HEADER_CONTENT_TYPE,
   1678                                                "text/plain"));
   1679         break;
   1680       } /* switch (ret) */
   1681     }
   1682     break;
   1683   case POF_PDF:
   1684     // not yet implemented
   1685     GNUNET_assert (0);
   1686     break;
   1687   }
   1688   {
   1689     char *etag;
   1690     char *qetag;
   1691 
   1692     etag = GNUNET_STRINGS_data_to_string_alloc (&sh,
   1693                                                 sizeof (sh));
   1694     GNUNET_asprintf (&qetag,
   1695                      "\"%s\"",
   1696                      etag);
   1697     GNUNET_break (MHD_YES ==
   1698                   MHD_add_response_header (response,
   1699                                            MHD_HTTP_HEADER_ETAG,
   1700                                            qetag));
   1701     GNUNET_free (qetag);
   1702     GNUNET_free (etag);
   1703   }
   1704   GNUNET_log (GNUNET_ERROR_TYPE_INFO,
   1705               "Resuming /kyc handling as exchange interaction is done (%u)\n",
   1706               MHD_HTTP_OK);
   1707   finish_request (kc,
   1708                   MHD_queue_response (
   1709                     kc->connection,
   1710                     response_code,
   1711                     response));
   1712   MHD_destroy_response (response);
   1713 }
   1714 
   1715 
   1716 /**
   1717  * We are done with asynchronous processing, generate the
   1718  * response for the @e kc.
   1719  *
   1720  * @param[in,out] kc KYC context to respond for
   1721  */
   1722 static void
   1723 phase_generate_response (struct KycContext *kc)
   1724 {
   1725   GNUNET_assert (NULL == kc->exchange_pending_head);
   1726   GNUNET_assert (GNUNET_NO == kc->suspended);
   1727   /* FIXME: mixing these two suspend conditions like this
   1728      does not seem sane */
   1729   if ( (! kc->return_immediately) &&
   1730        (! GNUNET_TIME_absolute_is_past (kc->timeout)) )
   1731   {
   1732     GNUNET_log (GNUNET_ERROR_TYPE_INFO,
   1733                 "Suspending: long poll target %d not reached\n",
   1734                 kc->lpt);
   1735     wait_for_account (kc);
   1736     return;
   1737   }
   1738   if ( (! GNUNET_TIME_absolute_is_past (kc->timeout)) &&
   1739        ( (NULL != kc->lp_not_status) ||
   1740          (NULL != kc->lp_status) ) )
   1741   {
   1742     GNUNET_log (GNUNET_ERROR_TYPE_INFO,
   1743                 "Long-poll target status not reached, not returning response yet\n");
   1744     wait_for_account (kc);
   1745     return;
   1746   }
   1747   /* All exchange requests done, create final
   1748      big response from cumulated replies */
   1749   resume_kyc_with_response (kc);
   1750 }
   1751 
   1752 
   1753 /* ******************* main logic ***************** */
   1754 
   1755 /**
   1756  * Check the KYC status of an instance.
   1757  *
   1758  * @param mi instance to check KYC status of
   1759  * @param connection the MHD connection to handle
   1760  * @param[in,out] hc context with further information about the request
   1761  * @return MHD result code
   1762  */
   1763 static enum MHD_Result
   1764 get_instances_ID_kyc (
   1765   struct TMH_MerchantInstance *mi,
   1766   struct MHD_Connection *connection,
   1767   struct TMH_HandlerContext *hc)
   1768 {
   1769   struct KycContext *kc = hc->ctx;
   1770 
   1771   if (NULL == kc)
   1772   {
   1773     kc = GNUNET_new (struct KycContext);
   1774     kc->mi = mi;
   1775     /* On the /management/ path, @a mi is not hc->instance, so
   1776        nothing else keeps it alive while we are suspended: an
   1777        instance reload or purge would otherwise free it. */
   1778     GNUNET_assert (mi->rc < UINT_MAX);
   1779     mi->rc++;
   1780     hc->ctx = kc;
   1781     hc->cc = &kyc_context_cleanup;
   1782     GNUNET_CONTAINER_DLL_insert (kc_head,
   1783                                  kc_tail,
   1784                                  kc);
   1785     kc->connection = connection;
   1786     kc->hc = hc;
   1787     TALER_MHD_parse_request_timeout (connection,
   1788                                      &kc->timeout);
   1789     {
   1790       uint64_t num = 0;
   1791       int val;
   1792 
   1793       TALER_MHD_parse_request_number (connection,
   1794                                       "lpt",
   1795                                       &num);
   1796       val = (int) num;
   1797       if ( (val < 0) ||
   1798            (val > TALER_EXCHANGE_KLPT_MAX) )
   1799       {
   1800         /* Protocol violation, but we can be graceful and
   1801            just ignore the long polling! */
   1802         GNUNET_break_op (0);
   1803         val = TALER_EXCHANGE_KLPT_NONE;
   1804       }
   1805       kc->lpt = (enum TALER_EXCHANGE_KycLongPollTarget) val;
   1806     }
   1807     kc->return_immediately
   1808       = (TALER_EXCHANGE_KLPT_NONE == kc->lpt);
   1809     kc->lp_status = MHD_lookup_connection_value (
   1810       connection,
   1811       MHD_GET_ARGUMENT_KIND,
   1812       "lp_status");
   1813     kc->lp_not_status = MHD_lookup_connection_value (
   1814       connection,
   1815       MHD_GET_ARGUMENT_KIND,
   1816       "lp_not_status");
   1817     TALER_MHD_parse_request_arg_auto (connection,
   1818                                       "h_wire",
   1819                                       &kc->h_wire,
   1820                                       kc->have_h_wire);
   1821     TALER_MHD_parse_request_arg_auto (connection,
   1822                                       "lp_not_etag",
   1823                                       &kc->lp_not_etag,
   1824                                       kc->have_lp_not_etag);
   1825   }
   1826   while (1)
   1827   {
   1828     switch (kc->phase)
   1829     {
   1830     case PHASE_INIT:
   1831       phase_init (kc);
   1832       break;
   1833     case PHASE_DETERMINE_LONG_POLL:
   1834       phase_determine_long_poll (kc);
   1835       break;
   1836     case PHASE_DATABASE_KYC_CHECK:
   1837       phase_database_kyc_check (kc);
   1838       break;
   1839     case PHASE_NO_ACCOUNTS:
   1840       phase_no_accounts (kc);
   1841       break;
   1842     case PHASE_GENERATE_RESPONSE:
   1843       phase_generate_response (kc);
   1844       break;
   1845     case PHASE_IN_SHUTDOWN:
   1846       /* during shutdown, we don't generate any more replies */
   1847       GNUNET_assert (GNUNET_SYSERR == kc->suspended);
   1848       return MHD_NO;
   1849     case PHASE_RETURN_YES:
   1850       return MHD_YES;
   1851     case PHASE_RETURN_NO:
   1852       return MHD_NO;
   1853     case PHASE_SUSPENDED_ON_ACCOUNT:
   1854       /* suspended */
   1855       GNUNET_assert (GNUNET_YES == kc->suspended);
   1856       return MHD_YES;
   1857     case PHASE_SUSPENDED_ON_EXCHANGE:
   1858       /* suspended */
   1859       GNUNET_assert (GNUNET_YES == kc->suspended);
   1860       return MHD_YES;
   1861     }
   1862   }
   1863 }
   1864 
   1865 
   1866 enum MHD_Result
   1867 TMH_private_get_instances_ID_kyc (
   1868   const struct TMH_RequestHandler *rh,
   1869   struct MHD_Connection *connection,
   1870   struct TMH_HandlerContext *hc)
   1871 {
   1872   struct TMH_MerchantInstance *mi = hc->instance;
   1873 
   1874   (void) rh;
   1875   return get_instances_ID_kyc (mi,
   1876                                connection,
   1877                                hc);
   1878 }
   1879 
   1880 
   1881 enum MHD_Result
   1882 TMH_private_get_instances_default_ID_kyc (
   1883   const struct TMH_RequestHandler *rh,
   1884   struct MHD_Connection *connection,
   1885   struct TMH_HandlerContext *hc)
   1886 {
   1887   struct TMH_MerchantInstance *mi;
   1888 
   1889   (void) rh;
   1890   mi = TMH_lookup_instance (hc->infix);
   1891   if (NULL == mi)
   1892   {
   1893     return TALER_MHD_reply_with_error (
   1894       connection,
   1895       MHD_HTTP_NOT_FOUND,
   1896       TALER_EC_MERCHANT_GENERIC_INSTANCE_UNKNOWN,
   1897       hc->infix);
   1898   }
   1899   return get_instances_ID_kyc (mi,
   1900                                connection,
   1901                                hc);
   1902 }
   1903 
   1904 
   1905 /* end of taler-merchant-httpd_get-private-kyc.c */