merchant

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

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


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