merchant

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

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


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