exchange

Base system with REST service to issue digital coins, run by the payment service provider
Log | Files | Refs | Submodules | README | LICENSE

kyclogic_api.c (151039B)


      1 /*
      2   This file is part of TALER
      3   Copyright (C) 2022-2025 Taler Systems SA
      4 
      5   TALER is free software; you can redistribute it and/or modify it under the
      6   terms of the GNU Affero General Public License as published by the Free Software
      7   Foundation; either version 3, or (at your option) any later version.
      8 
      9   TALER is distributed in the hope that it will be useful, but WITHOUT ANY
     10   WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR
     11   A PARTICULAR PURPOSE.  See the GNU Affero General Public License for more details.
     12 
     13   You should have received a copy of the GNU Affero General Public License along with
     14   TALER; see the file COPYING.  If not, see <http://www.gnu.org/licenses/>
     15 */
     16 /**
     17  * @file kyclogic_api.c
     18  * @brief server-side KYC API
     19  * @author Christian Grothoff
     20  */
     21 #include "platform.h"  /* UNNECESSARY? */
     22 #include "taler/taler_json_lib.h"
     23 #include "taler/taler_kyclogic_lib.h"
     24 
     25 /**
     26  * Log verbosely, including possibly privacy-sensitive data.
     27  */
     28 #define DEBUG 1
     29 
     30 /**
     31  * Name of the KYC measure that may never be passed. Useful if some
     32  * operations/amounts are categorically forbidden.
     33  */
     34 #define KYC_MEASURE_IMPOSSIBLE "verboten"
     35 
     36 /**
     37  * Information about a KYC provider.
     38  */
     39 struct TALER_KYCLOGIC_KycProvider
     40 {
     41 
     42   /**
     43    * Name of the provider.
     44    */
     45   char *provider_name;
     46 
     47   /**
     48    * Logic to run for this provider.
     49    */
     50   struct TALER_KYCLOGIC_Plugin *logic;
     51 
     52   /**
     53    * Provider-specific details to pass to the @e logic functions.
     54    */
     55   struct TALER_KYCLOGIC_ProviderDetails *pd;
     56 
     57   /**
     58    * Maximum time to reuse a process when the provider does not report its
     59    * authoritative expiration.
     60    */
     61   struct GNUNET_TIME_Relative process_timeout;
     62 
     63 };
     64 
     65 
     66 /**
     67  * Rule that triggers some measure(s).
     68  */
     69 struct TALER_KYCLOGIC_KycRule
     70 {
     71 
     72   /**
     73    * Name of the rule (configuration section name).
     74    * NULL if not from the configuration.
     75    */
     76   char *rule_name;
     77 
     78   /**
     79    * Rule set with custom measures that this KYC rule
     80    * is part of.
     81    */
     82   const struct TALER_KYCLOGIC_LegitimizationRuleSet *lrs;
     83 
     84   /**
     85    * Timeframe to consider for computing the amount
     86    * to compare against the @e limit.  Zero for the
     87    * wallet balance trigger (as not applicable).
     88    */
     89   struct GNUNET_TIME_Relative timeframe;
     90 
     91   /**
     92    * Maximum amount that can be transacted until
     93    * the rule triggers.
     94    */
     95   struct TALER_Amount threshold;
     96 
     97   /**
     98    * Array of names of measures to apply on this trigger.
     99    */
    100   char **next_measures;
    101 
    102   /**
    103    * Length of the @e next_measures array.
    104    */
    105   unsigned int num_measures;
    106 
    107   /**
    108    * Display priority for this rule.
    109    */
    110   uint32_t display_priority;
    111 
    112   /**
    113    * What operation type is this rule for?
    114    */
    115   enum TALER_KYCLOGIC_KycTriggerEvent trigger;
    116 
    117   /**
    118    * True if all @e next_measures will eventually need to
    119    * be satisfied, False if the user has a choice between them.
    120    */
    121   bool is_and_combinator;
    122 
    123   /**
    124    * True if this rule and the general nature of the next measures
    125    * should be exposed to the client.
    126    */
    127   bool exposed;
    128 
    129   /**
    130    * True if any of the measures is 'verboten' and
    131    * thus this rule cannot ever be satisfied.
    132    */
    133   bool verboten;
    134 
    135 };
    136 
    137 
    138 /**
    139  * Set of rules that applies to an account.
    140  */
    141 struct TALER_KYCLOGIC_LegitimizationRuleSet
    142 {
    143 
    144   /**
    145    * When does this rule set expire?
    146    */
    147   struct GNUNET_TIME_Timestamp expiration_time;
    148 
    149   /**
    150    * Name of the successor measure after expiration.
    151    * NULL to revert to default rules.
    152    */
    153   char *successor_measure;
    154 
    155   /**
    156    * Array of the rules.
    157    */
    158   struct TALER_KYCLOGIC_KycRule *kyc_rules;
    159 
    160   /**
    161    * Array of custom measures the @e kyc_rules may refer
    162    * to.
    163    */
    164   struct TALER_KYCLOGIC_Measure *custom_measures;
    165 
    166   /**
    167    * Length of the @e kyc_rules array.
    168    */
    169   unsigned int num_kyc_rules;
    170 
    171   /**
    172    * Length of the @e custom_measures array.
    173    */
    174   unsigned int num_custom_measures;
    175 
    176 };
    177 
    178 
    179 /**
    180  * AML program inputs as per "-i" option of the AML program.
    181  * This is a bitmask.
    182  */
    183 enum AmlProgramInputs
    184 {
    185   /**
    186    * No inputs are needed.
    187    */
    188   API_NONE = 0,
    189 
    190   /**
    191    * Context is needed.
    192    */
    193   API_CONTEXT = 1,
    194 
    195   /**
    196    * Current (just submitted) attributes needed.
    197    */
    198   API_ATTRIBUTES = 2,
    199 
    200   /**
    201    * Current AML rules are needed.
    202    */
    203   API_CURRENT_RULES = 4,
    204 
    205   /**
    206    * Default AML rules (that apply to fresh accounts) are needed.
    207    */
    208   API_DEFAULT_RULES = 8,
    209 
    210   /**
    211    * Account AML history is needed, possibly length-limited,
    212    * see ``aml_history_length_limit``.
    213    */
    214   API_AML_HISTORY = 16,
    215 
    216   /**
    217    * Account KYC history is needed, possibly length-limited,
    218    * see ``kyc_history_length_limit``
    219    */
    220   API_KYC_HISTORY = 32,
    221 
    222 };
    223 
    224 
    225 /**
    226  * AML programs.
    227  */
    228 struct TALER_KYCLOGIC_AmlProgram
    229 {
    230 
    231   /**
    232    * Name of the AML program configuration section.
    233    */
    234   char *program_name;
    235 
    236   /**
    237    * Name of the AML program (binary) to run.
    238    */
    239   char *command;
    240 
    241   /**
    242    * Human-readable description of what this AML helper
    243    * program will do.
    244    */
    245   char *description;
    246 
    247   /**
    248    * Name of an original measure to take in case the
    249    * @e command fails, NULL to fallback to default rules.
    250    */
    251   char *fallback;
    252 
    253   /**
    254    * Output of @e command "-r".
    255    */
    256   char **required_contexts;
    257 
    258   /**
    259    * Length of the @e required_contexts array.
    260    */
    261   unsigned int num_required_contexts;
    262 
    263   /**
    264    * Output of @e command "-a".
    265    */
    266   char **required_attributes;
    267 
    268   /**
    269    * Length of the @e required_attributes array.
    270    */
    271   unsigned int num_required_attributes;
    272 
    273   /**
    274    * Bitmask of inputs this AML program would like (based on '-i').
    275    */
    276   enum AmlProgramInputs input_mask;
    277 
    278   /**
    279    * How many entries of the AML history are requested;
    280    * negative number if we want the latest entries only.
    281    */
    282   long long aml_history_length_limit;
    283 
    284   /**
    285    * How many entries of the KYC history are requested;
    286    * negative number if we want the latest entries only.
    287    */
    288   long long kyc_history_length_limit;
    289 
    290 };
    291 
    292 
    293 /**
    294  * Array of @e num_kyc_logics KYC logic plugins we have loaded.
    295  */
    296 static struct TALER_KYCLOGIC_Plugin **kyc_logics;
    297 
    298 /**
    299  * Length of the #kyc_logics array.
    300  */
    301 static unsigned int num_kyc_logics;
    302 
    303 /**
    304  * Array of configured providers.
    305  */
    306 static struct TALER_KYCLOGIC_KycProvider **kyc_providers;
    307 
    308 /**
    309  * Length of the #kyc_providers array.
    310  */
    311 static unsigned int num_kyc_providers;
    312 
    313 /**
    314  * Array of @e num_kyc_checks known types of
    315  * KYC checks.
    316  */
    317 static struct TALER_KYCLOGIC_KycCheck **kyc_checks;
    318 
    319 /**
    320  * Length of the #kyc_checks array.
    321  */
    322 static unsigned int num_kyc_checks;
    323 
    324 /**
    325  * Rules that apply if we do not have an AMLA record.
    326  */
    327 static struct TALER_KYCLOGIC_LegitimizationRuleSet default_rules;
    328 
    329 /**
    330  * Array of available AML programs.
    331  */
    332 static struct TALER_KYCLOGIC_AmlProgram **aml_programs;
    333 
    334 /**
    335  * Length of the #aml_programs array.
    336  */
    337 static unsigned int num_aml_programs;
    338 
    339 /**
    340  * Name of our configuration file.
    341  */
    342 static char *cfg_filename;
    343 
    344 /**
    345  * Currency we expect to see in all rules.
    346  */
    347 static char *my_currency;
    348 
    349 /**
    350  * Default LegitimizationRuleSet for wallets.  Excludes *default* measures
    351  * even if these are the default rules.
    352  */
    353 static json_t *wallet_default_lrs;
    354 
    355 /**
    356  * Default LegitimizationRuleSet for bank accounts.  Excludes *default* measures
    357  * even if these are the default rules.
    358  */
    359 static json_t *bankaccount_default_lrs;
    360 
    361 
    362 /**
    363  * Convert the ASCII string in @a s to lower-case. Here,
    364  * @a s must only contain the characters "[a-zA-Z0-9.-_]",
    365  * otherwise the function fails and returns false.
    366  *
    367  * @param[in,out] s string to lower-case
    368  * @return true on success, if false is returned, the
    369  *  value in @a s may be partially transformed
    370  */
    371 static bool
    372 ascii_lower (char *s)
    373 {
    374   for (size_t i = 0; '\0' != s[i]; i++)
    375   {
    376     int c = (int) s[i];
    377 
    378     if (isdigit (c))
    379       continue;
    380     if (isalpha (c))
    381     {
    382       s[i] = (char) tolower (c);
    383       continue;
    384     }
    385     if ( ('-' == c) ||
    386          ('.' == c) ||
    387          ('_' == c) )
    388       continue;
    389     return false;
    390   }
    391   return true;
    392 }
    393 
    394 
    395 /**
    396  * Convert the ASCII string in @a s to lower-case. Here,
    397  * @a s must only contain the characters "[a-zA-Z0-9 \n\t;.-_]",
    398  * otherwise the function fails and returns false.
    399  * Note that the main difference to ascii_lower is that
    400  * " \n\t;" are allowed.
    401  *
    402  * @param[in,out] s string to lower-case
    403  * @return true on success, if false is returned, the
    404  *  value in @a s may be partially transformed
    405  */
    406 static bool
    407 token_list_lower (char *s)
    408 {
    409   for (size_t i = 0; '\0' != s[i]; i++)
    410   {
    411     int c = (int) s[i];
    412 
    413     if (isdigit (c))
    414       continue;
    415     if (isalpha (c))
    416     {
    417       s[i] = (char) tolower (c);
    418       continue;
    419     }
    420     if ( ('-' == c) ||
    421          (' ' == c) ||
    422          ('.' == c) ||
    423          ('\n' == c) ||
    424          ('\t' == c) ||
    425          (';' == c) ||
    426          ('_' == c) )
    427       continue;
    428     return false;
    429   }
    430   return true;
    431 }
    432 
    433 
    434 /**
    435  * Check that @a section begins with @a prefix and afterwards
    436  * only contains characters "[a-zA-Z0-9-_]". If so, convert all
    437  * characters to lower-case and return the result.
    438  *
    439  * @param prefix section prefix to match
    440  * @param section section name to match against
    441  * @return NULL if @a prefix does not match or @a section contains
    442  *    invalid characters after the prefix
    443  */
    444 static char *
    445 normalize_section_with_prefix (const char *prefix,
    446                                const char *section)
    447 {
    448   char *ret;
    449 
    450   if (0 != strncasecmp (section,
    451                         prefix,
    452                         strlen (prefix)))
    453     return NULL; /* no match */
    454   ret = GNUNET_strdup (section);
    455   if (! ascii_lower (ret))
    456   {
    457     GNUNET_free (ret);
    458     return NULL;
    459   }
    460   return ret;
    461 }
    462 
    463 
    464 struct GNUNET_TIME_Timestamp
    465 TALER_KYCLOGIC_rules_get_expiration (
    466   const struct TALER_KYCLOGIC_LegitimizationRuleSet *lrs)
    467 {
    468   if (NULL == lrs)
    469     return GNUNET_TIME_UNIT_FOREVER_TS;
    470   return lrs->expiration_time;
    471 }
    472 
    473 
    474 const struct TALER_KYCLOGIC_Measure *
    475 TALER_KYCLOGIC_rules_get_successor (
    476   const struct TALER_KYCLOGIC_LegitimizationRuleSet *lrs)
    477 {
    478   const char *successor_measure_name = lrs->successor_measure;
    479 
    480   if (NULL == successor_measure_name)
    481   {
    482     return NULL;
    483   }
    484   return TALER_KYCLOGIC_get_measure (
    485     lrs,
    486     successor_measure_name);
    487 }
    488 
    489 
    490 /**
    491  * Check if @a trigger applies to our context.
    492  *
    493  * @param trigger the trigger to evaluate
    494  * @param is_wallet #GNUNET_YES if this is for a wallet,
    495  *         #GNUNET_NO for account,
    496  *         #GNUNET_SYSERR for unknown (returns all rules)
    497  * @return true if @a trigger applies in this context
    498  */
    499 static bool
    500 trigger_applies (enum TALER_KYCLOGIC_KycTriggerEvent trigger,
    501                  enum GNUNET_GenericReturnValue is_wallet)
    502 {
    503   switch (trigger)
    504   {
    505   case TALER_KYCLOGIC_KYC_TRIGGER_NONE:
    506     GNUNET_break (0);
    507     break;
    508   case TALER_KYCLOGIC_KYC_TRIGGER_WITHDRAW:
    509     return GNUNET_YES != is_wallet;
    510   case TALER_KYCLOGIC_KYC_TRIGGER_DEPOSIT:
    511     return GNUNET_YES != is_wallet;
    512   case TALER_KYCLOGIC_KYC_TRIGGER_P2P_RECEIVE:
    513     return GNUNET_NO != is_wallet;
    514   case TALER_KYCLOGIC_KYC_TRIGGER_WALLET_BALANCE:
    515     return GNUNET_NO != is_wallet;
    516   case TALER_KYCLOGIC_KYC_TRIGGER_RESERVE_CLOSE:
    517     return GNUNET_YES != is_wallet;
    518   case TALER_KYCLOGIC_KYC_TRIGGER_AGGREGATE:
    519     return GNUNET_YES != is_wallet;
    520   case TALER_KYCLOGIC_KYC_TRIGGER_TRANSACTION:
    521     return true;
    522   case TALER_KYCLOGIC_KYC_TRIGGER_REFUND:
    523     return true;
    524   }
    525   GNUNET_break (0);
    526   return true;
    527 }
    528 
    529 
    530 /**
    531  * Lookup a KYC check by @a check_name
    532  *
    533  * @param check_name name to search for
    534  * @return NULL if not found
    535  */
    536 static struct TALER_KYCLOGIC_KycCheck *
    537 find_check (const char *check_name)
    538 {
    539   for (unsigned int i = 0; i<num_kyc_checks; i++)
    540   {
    541     struct TALER_KYCLOGIC_KycCheck *kyc_check
    542       = kyc_checks[i];
    543 
    544     if (0 == strcasecmp (check_name,
    545                          kyc_check->check_name))
    546       return kyc_check;
    547   }
    548   GNUNET_log (GNUNET_ERROR_TYPE_WARNING,
    549               "Check `%s' unknown\n",
    550               check_name);
    551   return NULL;
    552 }
    553 
    554 
    555 /**
    556  * Lookup AML program by @a program_name
    557  *
    558  * @param program_name name to search for
    559  * @return NULL if not found
    560  */
    561 static struct TALER_KYCLOGIC_AmlProgram *
    562 find_program (const char *program_name)
    563 {
    564   if (NULL == program_name)
    565   {
    566     GNUNET_break (0);
    567     return NULL;
    568   }
    569   for (unsigned int i = 0; i<num_aml_programs; i++)
    570   {
    571     struct TALER_KYCLOGIC_AmlProgram *program
    572       = aml_programs[i];
    573 
    574     if (0 == strcasecmp (program_name,
    575                          program->program_name))
    576       return program;
    577   }
    578   GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
    579               "AML program `%s' unknown\n",
    580               program_name);
    581   return NULL;
    582 }
    583 
    584 
    585 /**
    586  * Lookup KYC provider by @a provider_name
    587  *
    588  * @param provider_name name to search for
    589  * @return NULL if not found
    590  */
    591 static struct TALER_KYCLOGIC_KycProvider *
    592 find_provider (const char *provider_name)
    593 {
    594   for (unsigned int i = 0; i<num_kyc_providers; i++)
    595   {
    596     struct TALER_KYCLOGIC_KycProvider *provider
    597       = kyc_providers[i];
    598 
    599     if (0 == strcasecmp (provider_name,
    600                          provider->provider_name))
    601       return provider;
    602   }
    603   GNUNET_log (GNUNET_ERROR_TYPE_WARNING,
    604               "KYC provider `%s' unknown\n",
    605               provider_name);
    606   return NULL;
    607 }
    608 
    609 
    610 /**
    611  * Check that @a measure is well-formed and internally
    612  * consistent.
    613  *
    614  * @param measure measure to check
    615  * @return true if measure is well-formed
    616  */
    617 static bool
    618 check_measure (const struct TALER_KYCLOGIC_Measure *measure)
    619 {
    620   const struct TALER_KYCLOGIC_KycCheck *check;
    621 
    622   if (! ascii_lower (measure->measure_name))
    623   {
    624     GNUNET_break (0);
    625     return false;
    626   }
    627   if (! ascii_lower (measure->check_name))
    628   {
    629     GNUNET_break (0);
    630     return false;
    631   }
    632   if ( (NULL != measure->prog_name) &&
    633        (! ascii_lower (measure->prog_name)) )
    634   {
    635     GNUNET_break (0);
    636     return false;
    637   }
    638 
    639   if (0 == strcasecmp (measure->check_name,
    640                        "skip"))
    641   {
    642     check = NULL;
    643   }
    644   else
    645   {
    646     check = find_check (measure->check_name);
    647     if (NULL == check)
    648     {
    649       GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
    650                   "Unknown check `%s' used in measure `%s'\n",
    651                   measure->check_name,
    652                   measure->measure_name);
    653       return false;
    654     }
    655   }
    656   if ( (NULL == check) ||
    657        (TALER_KYCLOGIC_CT_INFO != check->type) )
    658   {
    659     const struct TALER_KYCLOGIC_AmlProgram *program;
    660 
    661     program = find_program (measure->prog_name);
    662     if (NULL == program)
    663     {
    664       GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
    665                   "Unknown program `%s' used in measure `%s'\n",
    666                   measure->prog_name,
    667                   measure->measure_name);
    668       return false;
    669     }
    670     for (unsigned int j = 0; j<program->num_required_contexts; j++)
    671     {
    672       const char *required_context = program->required_contexts[j];
    673 
    674       if (NULL ==
    675           json_object_get (measure->context,
    676                            required_context))
    677       {
    678         GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
    679                     "Measure `%s' lacks required context `%s' for AML program `%s'\n",
    680                     measure->measure_name,
    681                     required_context,
    682                     program->program_name);
    683         return false;
    684       }
    685     }
    686     if (0 == strcasecmp (measure->check_name,
    687                          "skip"))
    688     {
    689       if (0 != program->num_required_attributes)
    690       {
    691         GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
    692                     "AML program `%s' of measure `%s' has required attributes, but check is of type `skip' and thus cannot provide any!\n",
    693                     program->program_name,
    694                     measure->measure_name);
    695         return false;
    696       }
    697       return true;
    698     }
    699     for (unsigned int j = 0; j<program->num_required_attributes; j++)
    700     {
    701       const char *required_attribute = program->required_attributes[j];
    702       bool found = false;
    703 
    704       if (NULL != check)
    705       {
    706         for (unsigned int i = 0; i<check->num_outputs; i++)
    707         {
    708           if (0 == strcasecmp (required_attribute,
    709                                check->outputs[i]))
    710           {
    711             found = true;
    712             break;
    713           }
    714         }
    715       }
    716       if (! found)
    717       {
    718         GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
    719                     "Check `%s' of measure `%s' does not provide required output `%s' for AML program `%s'\n",
    720                     measure->check_name,
    721                     measure->measure_name,
    722                     required_attribute,
    723                     program->program_name);
    724         return false;
    725       }
    726     }
    727   }
    728   else
    729   {
    730     /* Check is of type "INFO" */
    731     if (NULL != measure->prog_name)
    732       GNUNET_log (GNUNET_ERROR_TYPE_WARNING,
    733                   "Program `%s' used in INFO measure `%s' will never be used.\n",
    734                   measure->prog_name,
    735                   measure->measure_name);
    736     if (0 == strcasecmp (measure->check_name,
    737                          "skip"))
    738     {
    739       GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
    740                   "INFO check of measure `%s' should not be called `skip'.\n",
    741                   measure->measure_name);
    742       return false;
    743     }
    744   }
    745   if (NULL != check)
    746   {
    747     for (unsigned int j = 0; j<check->num_requires; j++)
    748     {
    749       const char *required_input = check->requires[j];
    750 
    751       if (NULL ==
    752           json_object_get (measure->context,
    753                            required_input))
    754       {
    755         GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
    756                     "Measure `%s' lacks required context `%s' for check `%s'\n",
    757                     measure->measure_name,
    758                     required_input,
    759                     measure->check_name);
    760         return false;
    761       }
    762     }
    763   }
    764   return true;
    765 }
    766 
    767 
    768 /**
    769  * Find measure @a measure_name in @a lrs.
    770  * If measure is not found in @a lrs, fall back to
    771  * default measures.
    772  *
    773  * @param lrs rule set to search, can be NULL to only search default measures
    774  * @param measure_name name of measure to find
    775  * @return NULL if not found, otherwise the measure
    776  */
    777 static const struct TALER_KYCLOGIC_Measure *
    778 find_measure (
    779   const struct TALER_KYCLOGIC_LegitimizationRuleSet *lrs,
    780   const char *measure_name)
    781 {
    782   if (NULL != lrs)
    783   {
    784     for (unsigned int i = 0; i<lrs->num_custom_measures; i++)
    785     {
    786       const struct TALER_KYCLOGIC_Measure *cm
    787         = &lrs->custom_measures[i];
    788 
    789       if (0 == strcasecmp (measure_name,
    790                            cm->measure_name))
    791         return cm;
    792     }
    793   }
    794   if (lrs != &default_rules)
    795   {
    796     /* Try measures from default rules */
    797     for (unsigned int i = 0; i<default_rules.num_custom_measures; i++)
    798     {
    799       const struct TALER_KYCLOGIC_Measure *cm
    800         = &default_rules.custom_measures[i];
    801 
    802       if (0 == strcasecmp (measure_name,
    803                            cm->measure_name))
    804         return cm;
    805     }
    806   }
    807   GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
    808               "Measure `%s' not found\n",
    809               measure_name);
    810   return NULL;
    811 }
    812 
    813 
    814 struct TALER_KYCLOGIC_LegitimizationRuleSet *
    815 TALER_KYCLOGIC_rules_parse (const json_t *jlrs)
    816 {
    817   struct GNUNET_TIME_Timestamp expiration_time;
    818   const char *successor_measure = NULL;
    819   const json_t *jrules;
    820   const json_t *jcustom_measures;
    821   struct GNUNET_JSON_Specification spec[] = {
    822     GNUNET_JSON_spec_timestamp (
    823       "expiration_time",
    824       &expiration_time),
    825     GNUNET_JSON_spec_mark_optional (
    826       GNUNET_JSON_spec_string (
    827         "successor_measure",
    828         &successor_measure),
    829       NULL),
    830     GNUNET_JSON_spec_array_const ("rules",
    831                                   &jrules),
    832     GNUNET_JSON_spec_object_const ("custom_measures",
    833                                    &jcustom_measures),
    834     GNUNET_JSON_spec_end ()
    835   };
    836   struct TALER_KYCLOGIC_LegitimizationRuleSet *lrs;
    837   const char *err;
    838   unsigned int line;
    839 
    840   if (NULL == jlrs)
    841   {
    842     GNUNET_break_op (0);
    843     return NULL;
    844   }
    845   if (GNUNET_OK !=
    846       GNUNET_JSON_parse (jlrs,
    847                          spec,
    848                          &err,
    849                          &line))
    850   {
    851     GNUNET_break_op (0);
    852     GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
    853                 "Legitimization rules have incorrect input field `%s'\n",
    854                 err);
    855     json_dumpf (jlrs,
    856                 stderr,
    857                 JSON_INDENT (2));
    858     return NULL;
    859   }
    860   lrs = GNUNET_new (struct TALER_KYCLOGIC_LegitimizationRuleSet);
    861   lrs->expiration_time = expiration_time;
    862   lrs->successor_measure
    863     = (NULL == successor_measure)
    864     ? NULL
    865     : GNUNET_strdup (successor_measure);
    866   if ( (NULL != lrs->successor_measure) &&
    867        (! ascii_lower (lrs->successor_measure)) )
    868   {
    869     GNUNET_break (0);
    870     goto cleanup;
    871   }
    872   lrs->num_custom_measures
    873     = (unsigned int) json_object_size (jcustom_measures);
    874   if (((size_t) lrs->num_custom_measures) !=
    875       json_object_size (jcustom_measures))
    876   {
    877     GNUNET_break (0);
    878     goto cleanup;
    879   }
    880 
    881   if (0 != lrs->num_custom_measures)
    882   {
    883     lrs->custom_measures
    884       = GNUNET_new_array (lrs->num_custom_measures,
    885                           struct TALER_KYCLOGIC_Measure);
    886 
    887     {
    888       const json_t *jmeasure;
    889       const char *measure_name;
    890       unsigned int off = 0;
    891 
    892       json_object_foreach ((json_t *) jcustom_measures,
    893                            measure_name,
    894                            jmeasure)
    895       {
    896         const char *check_name;
    897         const char *prog_name = NULL;
    898         const json_t *context = NULL;
    899         bool voluntary = false;
    900         struct TALER_KYCLOGIC_Measure *measure
    901           = &lrs->custom_measures[off++];
    902         struct GNUNET_JSON_Specification ispec[] = {
    903           GNUNET_JSON_spec_string ("check_name",
    904                                    &check_name),
    905           GNUNET_JSON_spec_mark_optional (
    906             GNUNET_JSON_spec_string ("prog_name",
    907                                      &prog_name),
    908             NULL),
    909           GNUNET_JSON_spec_mark_optional (
    910             GNUNET_JSON_spec_object_const ("context",
    911                                            &context),
    912             NULL),
    913           GNUNET_JSON_spec_mark_optional (
    914             GNUNET_JSON_spec_bool ("voluntary",
    915                                    &voluntary),
    916             NULL),
    917           GNUNET_JSON_spec_end ()
    918         };
    919 
    920         if (GNUNET_OK !=
    921             GNUNET_JSON_parse (jmeasure,
    922                                ispec,
    923                                NULL, NULL))
    924         {
    925           GNUNET_break_op (0);
    926           goto cleanup;
    927         }
    928         measure->measure_name
    929           = GNUNET_strdup (measure_name);
    930         measure->check_name
    931           = GNUNET_strdup (check_name);
    932         if (NULL != prog_name)
    933           measure->prog_name
    934             = GNUNET_strdup (prog_name);
    935         measure->voluntary
    936           = voluntary;
    937         if (NULL != context)
    938           measure->context
    939             = json_incref ((json_t*) context);
    940         if (! check_measure (measure))
    941         {
    942           GNUNET_break_op (0);
    943           goto cleanup;
    944         }
    945       }
    946     }
    947   }
    948 
    949   lrs->num_kyc_rules
    950     = (unsigned int) json_array_size (jrules);
    951   if (((size_t) lrs->num_kyc_rules) !=
    952       json_array_size (jrules))
    953   {
    954     GNUNET_break (0);
    955     goto cleanup;
    956   }
    957   lrs->kyc_rules
    958     = GNUNET_new_array (lrs->num_kyc_rules,
    959                         struct TALER_KYCLOGIC_KycRule);
    960   {
    961     const json_t *jrule;
    962     size_t off;
    963 
    964     json_array_foreach ((json_t *) jrules,
    965                         off,
    966                         jrule)
    967     {
    968       struct TALER_KYCLOGIC_KycRule *rule
    969         = &lrs->kyc_rules[off];
    970       const json_t *jmeasures;
    971       const char *rn = NULL;
    972       struct GNUNET_JSON_Specification ispec[] = {
    973         TALER_JSON_spec_kycte ("operation_type",
    974                                &rule->trigger),
    975         TALER_JSON_spec_amount ("threshold",
    976                                 my_currency,
    977                                 &rule->threshold),
    978         GNUNET_JSON_spec_relative_time ("timeframe",
    979                                         &rule->timeframe),
    980         GNUNET_JSON_spec_array_const ("measures",
    981                                       &jmeasures),
    982         GNUNET_JSON_spec_uint32 ("display_priority",
    983                                  &rule->display_priority),
    984         GNUNET_JSON_spec_mark_optional (
    985           GNUNET_JSON_spec_bool ("exposed",
    986                                  &rule->exposed),
    987           NULL),
    988         GNUNET_JSON_spec_mark_optional (
    989           GNUNET_JSON_spec_string ("rule_name",
    990                                    &rn),
    991           NULL),
    992         GNUNET_JSON_spec_mark_optional (
    993           GNUNET_JSON_spec_bool ("is_and_combinator",
    994                                  &rule->is_and_combinator),
    995           NULL),
    996         GNUNET_JSON_spec_end ()
    997       };
    998 
    999       if (GNUNET_OK !=
   1000           GNUNET_JSON_parse (jrule,
   1001                              ispec,
   1002                              NULL, NULL))
   1003       {
   1004         GNUNET_break_op (0);
   1005         goto cleanup;
   1006       }
   1007       GNUNET_log (GNUNET_ERROR_TYPE_INFO,
   1008                   "Parsed KYC rule %u for %d with threshold %s\n",
   1009                   (unsigned int) off,
   1010                   (int) rule->trigger,
   1011                   TALER_amount2s (&rule->threshold));
   1012       rule->lrs = lrs;
   1013       if (NULL != rn)
   1014         rule->rule_name = GNUNET_strdup (rn);
   1015       rule->num_measures = json_array_size (jmeasures);
   1016       rule->next_measures
   1017         = GNUNET_new_array (rule->num_measures,
   1018                             char *);
   1019       if (((size_t) rule->num_measures) !=
   1020           json_array_size (jmeasures))
   1021       {
   1022         GNUNET_break (0);
   1023         goto cleanup;
   1024       }
   1025       {
   1026         size_t j;
   1027         json_t *jmeasure;
   1028 
   1029         json_array_foreach (jmeasures,
   1030                             j,
   1031                             jmeasure)
   1032         {
   1033           const char *str;
   1034 
   1035           str = json_string_value (jmeasure);
   1036           if (NULL == str)
   1037           {
   1038             GNUNET_break (0);
   1039             goto cleanup;
   1040           }
   1041           if (0 == strcasecmp (str,
   1042                                KYC_MEASURE_IMPOSSIBLE))
   1043           {
   1044             rule->verboten = true;
   1045             continue;
   1046           }
   1047 
   1048           rule->next_measures[j]
   1049             = GNUNET_strdup (str);
   1050           if (! ascii_lower (rule->next_measures[j]))
   1051           {
   1052             GNUNET_break (0);
   1053             goto cleanup;
   1054           }
   1055           if (NULL ==
   1056               find_measure (lrs,
   1057                             rule->next_measures[j]))
   1058           {
   1059             GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
   1060                         "Measure `%s' specified in rule set unknown\n",
   1061                         str);
   1062             GNUNET_break_op (0);
   1063             goto cleanup;
   1064           }
   1065         }
   1066       }
   1067     }
   1068   }
   1069   return lrs;
   1070 cleanup:
   1071   TALER_KYCLOGIC_rules_free (lrs);
   1072   return NULL;
   1073 }
   1074 
   1075 
   1076 /**
   1077  * Free rules in @a lrs but not @a lrs itself.
   1078  *
   1079  * @param[in,out] lrs rule set to free
   1080  */
   1081 static void
   1082 free_rules (struct TALER_KYCLOGIC_LegitimizationRuleSet *lrs)
   1083 {
   1084   if (NULL == lrs)
   1085     return;
   1086   for (unsigned int i = 0; i<lrs->num_kyc_rules; i++)
   1087   {
   1088     struct TALER_KYCLOGIC_KycRule *rule
   1089       = &lrs->kyc_rules[i];
   1090 
   1091     for (unsigned int j = 0; j<rule->num_measures; j++)
   1092       GNUNET_free (rule->next_measures[j]);
   1093     GNUNET_array_grow (rule->next_measures,
   1094                        rule->num_measures,
   1095                        0);
   1096     GNUNET_free (rule->rule_name);
   1097   }
   1098   GNUNET_array_grow (lrs->kyc_rules,
   1099                      lrs->num_kyc_rules,
   1100                      0);
   1101   for (unsigned int i = 0; i<lrs->num_custom_measures; i++)
   1102   {
   1103     struct TALER_KYCLOGIC_Measure *measure
   1104       = &lrs->custom_measures[i];
   1105 
   1106     GNUNET_free (measure->measure_name);
   1107     GNUNET_free (measure->check_name);
   1108     GNUNET_free (measure->prog_name);
   1109     json_decref (measure->context);
   1110   }
   1111   GNUNET_array_grow (lrs->custom_measures,
   1112                      lrs->num_custom_measures,
   1113                      0);
   1114   GNUNET_free (lrs->successor_measure);
   1115 }
   1116 
   1117 
   1118 void
   1119 TALER_KYCLOGIC_rules_free (struct TALER_KYCLOGIC_LegitimizationRuleSet *lrs)
   1120 {
   1121   if (NULL == lrs)
   1122     return;
   1123   free_rules (lrs);
   1124   GNUNET_free (lrs);
   1125 }
   1126 
   1127 
   1128 const char *
   1129 TALER_KYCLOGIC_rule2s (
   1130   const struct TALER_KYCLOGIC_KycRule *r)
   1131 {
   1132   return r->rule_name;
   1133 }
   1134 
   1135 
   1136 const char *
   1137 TALER_KYCLOGIC_status2s (enum TALER_KYCLOGIC_KycStatus status)
   1138 {
   1139   switch (status)
   1140   {
   1141   case TALER_KYCLOGIC_STATUS_SUCCESS:
   1142     return "success";
   1143   case TALER_KYCLOGIC_STATUS_USER:
   1144     return "user";
   1145   case TALER_KYCLOGIC_STATUS_PROVIDER:
   1146     return "provider";
   1147   case TALER_KYCLOGIC_STATUS_FAILED:
   1148     return "failed";
   1149   case TALER_KYCLOGIC_STATUS_PENDING:
   1150     return "pending";
   1151   case TALER_KYCLOGIC_STATUS_ABORTED:
   1152     return "aborted";
   1153   case TALER_KYCLOGIC_STATUS_USER_PENDING:
   1154     return "pending with user";
   1155   case TALER_KYCLOGIC_STATUS_PROVIDER_PENDING:
   1156     return "pending at provider";
   1157   case TALER_KYCLOGIC_STATUS_USER_ABORTED:
   1158     return "aborted by user";
   1159   case TALER_KYCLOGIC_STATUS_PROVIDER_FAILED:
   1160     return "failed by provider";
   1161   case TALER_KYCLOGIC_STATUS_KEEP:
   1162     return "keep";
   1163   case TALER_KYCLOGIC_STATUS_INTERNAL_ERROR:
   1164     return "internal error";
   1165   }
   1166   return "unknown status";
   1167 }
   1168 
   1169 
   1170 json_t *
   1171 TALER_KYCLOGIC_rules_to_limits (const json_t *jrules,
   1172                                 enum GNUNET_GenericReturnValue is_wallet)
   1173 {
   1174   if (NULL == jrules)
   1175   {
   1176     /* default limits apply */
   1177     const struct TALER_KYCLOGIC_KycRule *rules
   1178       = default_rules.kyc_rules;
   1179     unsigned int num_rules
   1180       = default_rules.num_kyc_rules;
   1181     json_t *jlimits;
   1182 
   1183     jlimits = json_array ();
   1184     GNUNET_assert (NULL != jlimits);
   1185     for (unsigned int i = 0; i<num_rules; i++)
   1186     {
   1187       const struct TALER_KYCLOGIC_KycRule *rule = &rules[i];
   1188       json_t *limit;
   1189 
   1190       if (! rule->exposed)
   1191         continue;
   1192       if (! trigger_applies (rule->trigger,
   1193                              is_wallet))
   1194         continue;
   1195       limit = GNUNET_JSON_PACK (
   1196         GNUNET_JSON_pack_allow_null (
   1197           GNUNET_JSON_pack_string ("rule_name",
   1198                                    rule->rule_name)),
   1199         GNUNET_JSON_pack_bool ("soft_limit",
   1200                                ! rule->verboten),
   1201         TALER_JSON_pack_kycte ("operation_type",
   1202                                rule->trigger),
   1203         GNUNET_JSON_pack_time_rel ("timeframe",
   1204                                    rule->timeframe),
   1205         TALER_JSON_pack_amount ("threshold",
   1206                                 &rule->threshold)
   1207         );
   1208       GNUNET_assert (0 ==
   1209                      json_array_append_new (jlimits,
   1210                                             limit));
   1211     }
   1212     return jlimits;
   1213   }
   1214 
   1215   {
   1216     const json_t *rules;
   1217     json_t *limits;
   1218     json_t *limit;
   1219     json_t *rule;
   1220     size_t idx;
   1221 
   1222     rules = json_object_get (jrules,
   1223                              "rules");
   1224     limits = json_array ();
   1225     GNUNET_assert (NULL != limits);
   1226     json_array_foreach ((json_t *) rules, idx, rule)
   1227     {
   1228       struct GNUNET_TIME_Relative timeframe;
   1229       struct TALER_Amount threshold;
   1230       bool exposed = false;
   1231       const json_t *jmeasures;
   1232       const char *rule_name = NULL;
   1233       enum TALER_KYCLOGIC_KycTriggerEvent operation_type;
   1234       struct GNUNET_JSON_Specification spec[] = {
   1235         TALER_JSON_spec_kycte ("operation_type",
   1236                                &operation_type),
   1237         GNUNET_JSON_spec_relative_time ("timeframe",
   1238                                         &timeframe),
   1239         TALER_JSON_spec_amount ("threshold",
   1240                                 my_currency,
   1241                                 &threshold),
   1242         GNUNET_JSON_spec_array_const ("measures",
   1243                                       &jmeasures),
   1244         GNUNET_JSON_spec_mark_optional (
   1245           GNUNET_JSON_spec_bool ("exposed",
   1246                                  &exposed),
   1247           NULL),
   1248         GNUNET_JSON_spec_mark_optional (
   1249           GNUNET_JSON_spec_string ("rule_name",
   1250                                    &rule_name),
   1251           NULL),
   1252         GNUNET_JSON_spec_end ()
   1253       };
   1254       bool forbidden = false;
   1255       size_t i;
   1256       json_t *jmeasure;
   1257 
   1258       if (GNUNET_OK !=
   1259           GNUNET_JSON_parse (rule,
   1260                              spec,
   1261                              NULL, NULL))
   1262       {
   1263         GNUNET_break_op (0);
   1264         json_decref (limits);
   1265         return NULL;
   1266       }
   1267       if (! exposed)
   1268         continue;
   1269       if (! trigger_applies (operation_type,
   1270                              is_wallet))
   1271       {
   1272         GNUNET_log (GNUNET_ERROR_TYPE_INFO,
   1273                     "Skipping rule #%u that does not apply to %s\n",
   1274                     (unsigned int) idx,
   1275                     is_wallet ? "wallets" : "accounts");
   1276         json_dumpf (rule,
   1277                     stderr,
   1278                     JSON_INDENT (2));
   1279         continue;
   1280       }
   1281       json_array_foreach (jmeasures, i, jmeasure)
   1282       {
   1283         const char *val;
   1284 
   1285         val = json_string_value (jmeasure);
   1286         if (NULL == val)
   1287         {
   1288           GNUNET_break_op (0);
   1289           json_decref (limits);
   1290           return NULL;
   1291         }
   1292         if (0 == strcasecmp (KYC_MEASURE_IMPOSSIBLE,
   1293                              val))
   1294           forbidden = true;
   1295       }
   1296 
   1297       limit = GNUNET_JSON_PACK (
   1298         GNUNET_JSON_pack_allow_null (
   1299           GNUNET_JSON_pack_string ("rule_name",
   1300                                    rule_name)),
   1301         TALER_JSON_pack_kycte (
   1302           "operation_type",
   1303           operation_type),
   1304         GNUNET_JSON_pack_time_rel (
   1305           "timeframe",
   1306           timeframe),
   1307         TALER_JSON_pack_amount (
   1308           "threshold",
   1309           &threshold),
   1310         /* optional since v21, defaults to 'false' */
   1311         GNUNET_JSON_pack_bool (
   1312           "soft_limit",
   1313           ! forbidden));
   1314       GNUNET_assert (0 ==
   1315                      json_array_append_new (limits,
   1316                                             limit));
   1317     }
   1318     return limits;
   1319   }
   1320 }
   1321 
   1322 
   1323 bool
   1324 TALER_KYCLOGIC_rules_require_tos_acceptance (const json_t *jrules)
   1325 {
   1326   struct TALER_KYCLOGIC_LegitimizationRuleSet *lrs;
   1327   const struct TALER_KYCLOGIC_LegitimizationRuleSet *rs;
   1328   bool found = false;
   1329 
   1330   if (NULL == jrules)
   1331   {
   1332     /* default rules apply */
   1333     lrs = NULL;
   1334     rs = &default_rules;
   1335   }
   1336   else
   1337   {
   1338     lrs = TALER_KYCLOGIC_rules_parse (jrules);
   1339     if (NULL == lrs)
   1340     {
   1341       GNUNET_break_op (0);
   1342       return false;
   1343     }
   1344     rs = lrs;
   1345   }
   1346   for (unsigned int i = 0; (! found) && (i < rs->num_kyc_rules); i++)
   1347   {
   1348     const struct TALER_KYCLOGIC_KycRule *rule = &rs->kyc_rules[i];
   1349 
   1350     if (rule->verboten)
   1351       continue; /* verboten rules can never be satisfied and their
   1352                    next_measures[] entries are NULL (see rules_parse),
   1353                    so they never contribute a ToS-acceptance requirement */
   1354     for (unsigned int j = 0; j < rule->num_measures; j++)
   1355     {
   1356       const struct TALER_KYCLOGIC_Measure *m;
   1357       const struct TALER_KYCLOGIC_KycCheck *c;
   1358 
   1359       /* Resolve the measure to its check exactly as GET /kyc-info does
   1360          (measure -> check -> form), so that our answer is consistent
   1361          with the requirements the merchant will observe there. */
   1362       m = find_measure (lrs,
   1363                         rule->next_measures[j]);
   1364       if (NULL == m)
   1365         continue;
   1366       c = find_check (m->check_name);
   1367       if (NULL == c)
   1368         continue;
   1369       if ( (TALER_KYCLOGIC_CT_FORM == c->type) &&
   1370            (NULL != c->details.form.name) &&
   1371            (0 == strcasecmp (c->details.form.name,
   1372                              TALER_KYCLOGIC_TOS_ACCEPTANCE_FORM)) )
   1373       {
   1374         found = true;
   1375         break;
   1376       }
   1377     }
   1378   }
   1379   if (NULL != lrs)
   1380     TALER_KYCLOGIC_rules_free (lrs);
   1381   return found;
   1382 }
   1383 
   1384 
   1385 const struct TALER_KYCLOGIC_Measure *
   1386 TALER_KYCLOGIC_rule_get_instant_measure (
   1387   const struct TALER_KYCLOGIC_KycRule *r)
   1388 {
   1389   const struct TALER_KYCLOGIC_LegitimizationRuleSet *lrs
   1390     = r->lrs;
   1391 
   1392   if (r->verboten)
   1393     return NULL;
   1394   for (unsigned int i = 0; i<r->num_measures; i++)
   1395   {
   1396     const char *measure_name = r->next_measures[i];
   1397     const struct TALER_KYCLOGIC_Measure *ms;
   1398 
   1399     if (0 == strcasecmp (measure_name,
   1400                          KYC_MEASURE_IMPOSSIBLE))
   1401     {
   1402       /* If any of the measures if verboten, we do not even
   1403       consider execution of the instant measure. */
   1404       return NULL;
   1405     }
   1406 
   1407     ms = find_measure (lrs,
   1408                        measure_name);
   1409     if (NULL == ms)
   1410     {
   1411       GNUNET_break (0);
   1412       return NULL;
   1413     }
   1414     if (0 == strcasecmp (ms->check_name,
   1415                          "skip"))
   1416       return ms;
   1417   }
   1418   return NULL;
   1419 }
   1420 
   1421 
   1422 json_t *
   1423 TALER_KYCLOGIC_rule_to_measures (
   1424   const struct TALER_KYCLOGIC_KycRule *r)
   1425 {
   1426   const struct TALER_KYCLOGIC_LegitimizationRuleSet *lrs
   1427     = r->lrs;
   1428   json_t *jmeasures;
   1429 
   1430   jmeasures = json_array ();
   1431   GNUNET_assert (NULL != jmeasures);
   1432   if (! r->verboten)
   1433   {
   1434     for (unsigned int i = 0; i<r->num_measures; i++)
   1435     {
   1436       const char *measure_name = r->next_measures[i];
   1437       const struct TALER_KYCLOGIC_Measure *ms;
   1438       json_t *mi;
   1439 
   1440       if (0 ==
   1441           strcasecmp (measure_name,
   1442                       KYC_MEASURE_IMPOSSIBLE))
   1443       {
   1444         /* This case should be covered via the 'verboten' flag! */
   1445         GNUNET_break (0);
   1446         continue;
   1447       }
   1448       ms = find_measure (lrs,
   1449                          measure_name);
   1450       if (NULL == ms)
   1451       {
   1452         GNUNET_break (0);
   1453         json_decref (jmeasures);
   1454         return NULL;
   1455       }
   1456       mi = GNUNET_JSON_PACK (
   1457         GNUNET_JSON_pack_string ("check_name",
   1458                                  ms->check_name),
   1459         GNUNET_JSON_pack_allow_null (
   1460           GNUNET_JSON_pack_string ("prog_name",
   1461                                    ms->prog_name)),
   1462         GNUNET_JSON_pack_allow_null (
   1463           GNUNET_JSON_pack_object_incref ("context",
   1464                                           ms->context)));
   1465       GNUNET_assert (0 ==
   1466                      json_array_append_new (jmeasures,
   1467                                             mi));
   1468     }
   1469   }
   1470 
   1471   return GNUNET_JSON_PACK (
   1472     GNUNET_JSON_pack_array_steal ("measures",
   1473                                   jmeasures),
   1474     GNUNET_JSON_pack_bool ("is_and_combinator",
   1475                            r->is_and_combinator),
   1476     GNUNET_JSON_pack_bool ("verboten",
   1477                            r->verboten));
   1478 }
   1479 
   1480 
   1481 json_t *
   1482 TALER_KYCLOGIC_zero_measures (
   1483   const struct TALER_KYCLOGIC_LegitimizationRuleSet *lrs,
   1484   enum GNUNET_GenericReturnValue is_wallet)
   1485 {
   1486   json_t *zero_measures;
   1487   const struct TALER_KYCLOGIC_KycRule *rules;
   1488   unsigned int num_zero_measures = 0;
   1489 
   1490   if (NULL == lrs)
   1491     lrs = &default_rules;
   1492   rules = lrs->kyc_rules;
   1493   zero_measures = json_array ();
   1494   GNUNET_assert (NULL != zero_measures);
   1495   for (unsigned int i = 0; i<lrs->num_kyc_rules; i++)
   1496   {
   1497     const struct TALER_KYCLOGIC_KycRule *rule = &rules[i];
   1498 
   1499     if (! rule->exposed)
   1500       continue;
   1501     if (rule->verboten)
   1502       continue; /* see: hard_limits */
   1503     if (! trigger_applies (rule->trigger,
   1504                            is_wallet))
   1505       continue;
   1506     if (! TALER_amount_is_zero (&rule->threshold))
   1507       continue;
   1508     for (unsigned int j = 0; j<rule->num_measures; j++)
   1509     {
   1510       const struct TALER_KYCLOGIC_Measure *ms;
   1511       json_t *mi;
   1512 
   1513       ms = find_measure (lrs,
   1514                          rule->next_measures[j]);
   1515       if (NULL == ms)
   1516       {
   1517         /* Error in the configuration, should've been
   1518          * caught before. We simply ignore the bad measure. */
   1519         GNUNET_break (0);
   1520         continue;
   1521       }
   1522       if (0 == strcasecmp (KYC_MEASURE_IMPOSSIBLE,
   1523                            ms->check_name))
   1524         continue; /* not a measure to be selected */
   1525       mi = GNUNET_JSON_PACK (
   1526         GNUNET_JSON_pack_allow_null (
   1527           GNUNET_JSON_pack_string ("rule_name",
   1528                                    rule->rule_name)),
   1529         TALER_JSON_pack_kycte ("operation_type",
   1530                                rule->trigger),
   1531         GNUNET_JSON_pack_string ("check_name",
   1532                                  ms->check_name),
   1533         GNUNET_JSON_pack_allow_null (
   1534           GNUNET_JSON_pack_string ("prog_name",
   1535                                    ms->prog_name)),
   1536         GNUNET_JSON_pack_allow_null (
   1537           GNUNET_JSON_pack_object_incref ("context",
   1538                                           ms->context)));
   1539       GNUNET_assert (0 ==
   1540                      json_array_append_new (zero_measures,
   1541                                             mi));
   1542       num_zero_measures++;
   1543     }
   1544   }
   1545   if (0 == num_zero_measures)
   1546   {
   1547     json_decref (zero_measures);
   1548     return NULL;
   1549   }
   1550   return GNUNET_JSON_PACK (
   1551     GNUNET_JSON_pack_array_steal ("measures",
   1552                                   zero_measures),
   1553     /* Zero-measures are always OR */
   1554     GNUNET_JSON_pack_bool ("is_and_combinator",
   1555                            false),
   1556     /* OR means verboten measures do not matter */
   1557     GNUNET_JSON_pack_bool ("verboten",
   1558                            false));
   1559 }
   1560 
   1561 
   1562 /**
   1563  * Check if @a ms is a voluntary measure, and if so
   1564  * convert to JSON and append to @a voluntary_measures.
   1565  *
   1566  * @param[in,out] voluntary_measures JSON array of MeasureInformation
   1567  * @param ms a measure to possibly append
   1568  */
   1569 static void
   1570 append_voluntary_measure (
   1571   json_t *voluntary_measures,
   1572   const struct TALER_KYCLOGIC_Measure *ms)
   1573 {
   1574 #if 0
   1575   json_t *mj;
   1576 #endif
   1577 
   1578   if (! ms->voluntary)
   1579     return;
   1580   if (0 == strcasecmp (KYC_MEASURE_IMPOSSIBLE,
   1581                        ms->check_name))
   1582     return; /* very strange configuration */
   1583 #if 0
   1584   /* FIXME: support vATTEST-#9048 (this API in kyclogic!) */
   1585   // NOTE: need to convert ms to "KycRequirementInformation"
   1586   // *and* in particular generate "id" values that
   1587   // are then understood to refer to the voluntary measures
   1588   // by the rest of the API (which is the hard part!)
   1589   // => need to change the API to encode the
   1590   // legitimization_outcomes row ID of the lrs from
   1591   // which the voluntary 'ms' originated, and
   1592   // then update the kyc-upload/kyc-start endpoints
   1593   // to recognize the new ID format!
   1594   mj = GNUNET_JSON_PACK (
   1595     GNUNET_JSON_pack_string ("check_name",
   1596                              ms->check_name),
   1597     GNUNET_JSON_pack_allow_null (
   1598       GNUNET_JSON_pack_string ("prog_name",
   1599                                ms->prog_name)),
   1600     GNUNET_JSON_pack_allow_null (
   1601       GNUNET_JSON_pack_object_incref ("context",
   1602                                       ms->context)));
   1603   GNUNET_assert (0 ==
   1604                  json_array_append_new (voluntary_measures,
   1605                                         mj));
   1606 #endif
   1607 }
   1608 
   1609 
   1610 json_t *
   1611 TALER_KYCLOGIC_voluntary_measures (
   1612   const struct TALER_KYCLOGIC_LegitimizationRuleSet *lrs)
   1613 {
   1614   json_t *voluntary_measures;
   1615 
   1616   voluntary_measures = json_array ();
   1617   GNUNET_assert (NULL != voluntary_measures);
   1618   if (NULL != lrs)
   1619   {
   1620     for (unsigned int i = 0; i<lrs->num_custom_measures; i++)
   1621     {
   1622       const struct TALER_KYCLOGIC_Measure *ms
   1623         = &lrs->custom_measures[i];
   1624 
   1625       append_voluntary_measure (voluntary_measures,
   1626                                 ms);
   1627     }
   1628   }
   1629   for (unsigned int i = 0; i<default_rules.num_custom_measures; i++)
   1630   {
   1631     const struct TALER_KYCLOGIC_Measure *ms
   1632       = &default_rules.custom_measures[i];
   1633 
   1634     append_voluntary_measure (voluntary_measures,
   1635                               ms);
   1636   }
   1637   return voluntary_measures;
   1638 }
   1639 
   1640 
   1641 const struct TALER_KYCLOGIC_Measure *
   1642 TALER_KYCLOGIC_get_instant_measure (
   1643   const struct TALER_KYCLOGIC_LegitimizationRuleSet *lrs,
   1644   const char *measures_spec)
   1645 {
   1646   char *nm;
   1647   const struct TALER_KYCLOGIC_Measure *ret = NULL;
   1648 
   1649   GNUNET_assert (NULL != measures_spec);
   1650 
   1651   if ('+' == measures_spec[0])
   1652   {
   1653     nm = GNUNET_strdup (&measures_spec[1]);
   1654   }
   1655   else
   1656   {
   1657     nm = GNUNET_strdup (measures_spec);
   1658   }
   1659   if (! token_list_lower (nm))
   1660   {
   1661     GNUNET_break (0);
   1662     GNUNET_free (nm);
   1663     return NULL;
   1664   }
   1665   for (const char *tok = strtok (nm, " ");
   1666        NULL != tok;
   1667        tok = strtok (NULL, " "))
   1668   {
   1669     const struct TALER_KYCLOGIC_Measure *ms;
   1670 
   1671     if (0 == strcasecmp (KYC_MEASURE_IMPOSSIBLE,
   1672                          tok))
   1673     {
   1674       continue;
   1675     }
   1676     ms = find_measure (lrs,
   1677                        tok);
   1678     if (NULL == ms)
   1679     {
   1680       GNUNET_break (0);
   1681       continue;
   1682     }
   1683     if (0 == strcasecmp (KYC_MEASURE_IMPOSSIBLE,
   1684                          ms->check_name))
   1685     {
   1686       continue;
   1687     }
   1688     if (0 == strcasecmp ("skip",
   1689                          ms->check_name))
   1690     {
   1691       ret = ms;
   1692       goto done;
   1693     }
   1694   }
   1695 done:
   1696   GNUNET_free (nm);
   1697   return ret;
   1698 }
   1699 
   1700 
   1701 const struct TALER_KYCLOGIC_Measure *
   1702 TALER_KYCLOGIC_get_measure (
   1703   const struct TALER_KYCLOGIC_LegitimizationRuleSet *lrs,
   1704   const char *measure_name)
   1705 {
   1706   return find_measure (lrs,
   1707                        measure_name);
   1708 }
   1709 
   1710 
   1711 json_t *
   1712 TALER_KYCLOGIC_get_jmeasures (
   1713   const struct TALER_KYCLOGIC_LegitimizationRuleSet *lrs,
   1714   const char *measures_spec)
   1715 {
   1716   json_t *jmeasures;
   1717   char *nm;
   1718   bool verboten = false;
   1719   bool is_and = false;
   1720 
   1721   if ('+' == measures_spec[0])
   1722   {
   1723     nm = GNUNET_strdup (&measures_spec[1]);
   1724     is_and = true;
   1725   }
   1726   else
   1727   {
   1728     nm = GNUNET_strdup (measures_spec);
   1729   }
   1730   if (! token_list_lower (nm))
   1731   {
   1732     GNUNET_break (0);
   1733     GNUNET_free (nm);
   1734     return NULL;
   1735   }
   1736   jmeasures = json_array ();
   1737   GNUNET_assert (NULL != jmeasures);
   1738   for (const char *tok = strtok (nm, " ");
   1739        NULL != tok;
   1740        tok = strtok (NULL, " "))
   1741   {
   1742     const struct TALER_KYCLOGIC_Measure *ms;
   1743     json_t *mi;
   1744 
   1745     if (0 == strcasecmp (KYC_MEASURE_IMPOSSIBLE,
   1746                          tok))
   1747     {
   1748       verboten = true;
   1749       continue;
   1750     }
   1751     ms = find_measure (lrs,
   1752                        tok);
   1753     if (NULL == ms)
   1754     {
   1755       /* A caller can supply an unknown measure name.  That is a protocol
   1756          violation, not an invariant violation in the exchange. */
   1757       GNUNET_break_op (0);
   1758       GNUNET_free (nm);
   1759       json_decref (jmeasures);
   1760       return NULL;
   1761     }
   1762     mi = GNUNET_JSON_PACK (
   1763       GNUNET_JSON_pack_string ("check_name",
   1764                                ms->check_name),
   1765       GNUNET_JSON_pack_allow_null (
   1766         GNUNET_JSON_pack_string ("prog_name",
   1767                                  ms->prog_name)),
   1768       GNUNET_JSON_pack_allow_null (
   1769         GNUNET_JSON_pack_object_incref ("context",
   1770                                         ms->context)));
   1771     GNUNET_assert (0 ==
   1772                    json_array_append_new (jmeasures,
   1773                                           mi));
   1774   }
   1775   GNUNET_free (nm);
   1776   return GNUNET_JSON_PACK (
   1777     GNUNET_JSON_pack_array_steal ("measures",
   1778                                   jmeasures),
   1779     GNUNET_JSON_pack_bool ("is_and_combinator",
   1780                            is_and),
   1781     GNUNET_JSON_pack_bool ("verboten",
   1782                            verboten));
   1783 }
   1784 
   1785 
   1786 json_t *
   1787 TALER_KYCLOGIC_check_to_jmeasures (
   1788   const struct TALER_KYCLOGIC_KycCheckContext *kcc)
   1789 {
   1790   const struct TALER_KYCLOGIC_KycCheck *check
   1791     = kcc->check;
   1792   json_t *jmeasures;
   1793   json_t *mi;
   1794 
   1795   mi = GNUNET_JSON_PACK (
   1796     GNUNET_JSON_pack_string ("check_name",
   1797                              NULL == check
   1798                              ? "skip"
   1799                              : check->check_name),
   1800     GNUNET_JSON_pack_allow_null (
   1801       GNUNET_JSON_pack_string ("prog_name",
   1802                                kcc->prog_name)),
   1803     GNUNET_JSON_pack_allow_null (
   1804       GNUNET_JSON_pack_object_incref ("context",
   1805                                       (json_t *) kcc->context)));
   1806   jmeasures = json_array ();
   1807   GNUNET_assert (NULL != jmeasures);
   1808   GNUNET_assert (0 ==
   1809                  json_array_append_new (jmeasures,
   1810                                         mi));
   1811   return GNUNET_JSON_PACK (
   1812     GNUNET_JSON_pack_array_steal ("measures",
   1813                                   jmeasures),
   1814     GNUNET_JSON_pack_bool ("is_and_combinator",
   1815                            true),
   1816     GNUNET_JSON_pack_bool ("verboten",
   1817                            false));
   1818 }
   1819 
   1820 
   1821 json_t *
   1822 TALER_KYCLOGIC_measure_to_jmeasures (
   1823   const struct TALER_KYCLOGIC_Measure *m)
   1824 {
   1825   json_t *jmeasures;
   1826   json_t *mi;
   1827 
   1828   mi = GNUNET_JSON_PACK (
   1829     GNUNET_JSON_pack_string ("check_name",
   1830                              m->check_name),
   1831     GNUNET_JSON_pack_allow_null (
   1832       GNUNET_JSON_pack_string ("prog_name",
   1833                                m->prog_name)),
   1834     GNUNET_JSON_pack_allow_null (
   1835       GNUNET_JSON_pack_object_incref ("context",
   1836                                       (json_t *) m->context)));
   1837   jmeasures = json_array ();
   1838   GNUNET_assert (NULL != jmeasures);
   1839   GNUNET_assert (0 ==
   1840                  json_array_append_new (jmeasures,
   1841                                         mi));
   1842   return GNUNET_JSON_PACK (
   1843     GNUNET_JSON_pack_array_steal ("measures",
   1844                                   jmeasures),
   1845     GNUNET_JSON_pack_bool ("is_and_combinator",
   1846                            false),
   1847     GNUNET_JSON_pack_bool ("verboten",
   1848                            false));
   1849 }
   1850 
   1851 
   1852 uint32_t
   1853 TALER_KYCLOGIC_rule2priority (
   1854   const struct TALER_KYCLOGIC_KycRule *r)
   1855 {
   1856   return r->display_priority;
   1857 }
   1858 
   1859 
   1860 /**
   1861  * Run @a command with @a argument and return the
   1862  * respective output from stdout.
   1863  *
   1864  * @param command binary to run
   1865  * @param argument command-line argument to pass
   1866  * @return NULL if @a command failed
   1867  */
   1868 static char *
   1869 command_output (const char *command,
   1870                 const char *argument)
   1871 {
   1872   char *rval;
   1873   unsigned int sval;
   1874   size_t soff;
   1875   ssize_t ret;
   1876   int sout[2];
   1877   pid_t chld;
   1878   const char *extra_args[] = {
   1879     argument,
   1880     "-c",
   1881     cfg_filename,
   1882     NULL,
   1883   };
   1884 
   1885   if (0 != pipe (sout))
   1886   {
   1887     GNUNET_log_strerror (GNUNET_ERROR_TYPE_ERROR,
   1888                          "pipe");
   1889     return NULL;
   1890   }
   1891   chld = fork ();
   1892   if (-1 == chld)
   1893   {
   1894     GNUNET_log_strerror (GNUNET_ERROR_TYPE_ERROR,
   1895                          "fork");
   1896     GNUNET_break (0 == close (sout[0]));
   1897     GNUNET_break (0 == close (sout[1]));
   1898     return NULL;
   1899   }
   1900   if (0 == chld)
   1901   {
   1902     char **argv;
   1903 
   1904     argv = TALER_words_split (command,
   1905                               extra_args);
   1906 
   1907     GNUNET_break (0 ==
   1908                   close (sout[0]));
   1909     GNUNET_break (0 ==
   1910                   close (STDOUT_FILENO));
   1911     GNUNET_assert (STDOUT_FILENO ==
   1912                    dup2 (sout[1],
   1913                          STDOUT_FILENO));
   1914     GNUNET_break (0 ==
   1915                   close (sout[1]));
   1916     execvp (argv[0],
   1917             argv);
   1918     TALER_words_destroy (argv);
   1919     GNUNET_log_strerror_file (GNUNET_ERROR_TYPE_ERROR,
   1920                               "exec",
   1921                               command);
   1922     exit (EXIT_FAILURE);
   1923   }
   1924   GNUNET_break (0 ==
   1925                 close (sout[1]));
   1926   sval = 1024;
   1927   rval = GNUNET_malloc (sval);
   1928   soff = 0;
   1929   while (0 < (ret = read (sout[0],
   1930                           rval + soff,
   1931                           sval - soff)) )
   1932   {
   1933     soff += ret;
   1934     if (soff == sval)
   1935     {
   1936       GNUNET_array_grow (rval,
   1937                          sval,
   1938                          sval * 2);
   1939     }
   1940   }
   1941   GNUNET_break (0 == close (sout[0]));
   1942   {
   1943     int wstatus;
   1944 
   1945     GNUNET_break (chld ==
   1946                   waitpid (chld,
   1947                            &wstatus,
   1948                            0));
   1949     if ( (! WIFEXITED (wstatus)) ||
   1950          (0 != WEXITSTATUS (wstatus)) )
   1951     {
   1952       GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
   1953                   "Command `%s' %s failed with status %d\n",
   1954                   command,
   1955                   argument,
   1956                   wstatus);
   1957       GNUNET_array_grow (rval,
   1958                          sval,
   1959                          0);
   1960       return NULL;
   1961     }
   1962   }
   1963   GNUNET_array_grow (rval,
   1964                      sval,
   1965                      soff + 1);
   1966   rval[soff] = '\0';
   1967   return rval;
   1968 }
   1969 
   1970 
   1971 /**
   1972  * Convert check type @a ctype_s into @a ctype.
   1973  *
   1974  * @param ctype_s check type as a string
   1975  * @param[out] ctype set to check type as enum
   1976  * @return #GNUNET_OK on success
   1977  */
   1978 static enum GNUNET_GenericReturnValue
   1979 check_type_from_string (
   1980   const char *ctype_s,
   1981   enum TALER_KYCLOGIC_CheckType *ctype)
   1982 {
   1983   struct
   1984   {
   1985     const char *in;
   1986     enum TALER_KYCLOGIC_CheckType out;
   1987   } map [] = {
   1988     { "INFO", TALER_KYCLOGIC_CT_INFO },
   1989     { "LINK", TALER_KYCLOGIC_CT_LINK },
   1990     { "FORM", TALER_KYCLOGIC_CT_FORM  },
   1991     { NULL, 0 }
   1992   };
   1993 
   1994   for (unsigned int i = 0; NULL != map[i].in; i++)
   1995     if (0 == strcasecmp (map[i].in,
   1996                          ctype_s))
   1997     {
   1998       *ctype = map[i].out;
   1999       return GNUNET_OK;
   2000     }
   2001   GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
   2002               "Invalid check type `%s'\n",
   2003               ctype_s);
   2004   return GNUNET_SYSERR;
   2005 }
   2006 
   2007 
   2008 enum GNUNET_GenericReturnValue
   2009 TALER_KYCLOGIC_kyc_trigger_from_string (
   2010   const char *trigger_s,
   2011   enum TALER_KYCLOGIC_KycTriggerEvent *trigger)
   2012 {
   2013   /* NOTE: if you change this, also change
   2014      the code in src/json/json_helper.c! */
   2015   struct
   2016   {
   2017     const char *in;
   2018     enum TALER_KYCLOGIC_KycTriggerEvent out;
   2019   } map [] = {
   2020     { "WITHDRAW", TALER_KYCLOGIC_KYC_TRIGGER_WITHDRAW },
   2021     { "DEPOSIT", TALER_KYCLOGIC_KYC_TRIGGER_DEPOSIT  },
   2022     { "MERGE", TALER_KYCLOGIC_KYC_TRIGGER_P2P_RECEIVE },
   2023     { "BALANCE", TALER_KYCLOGIC_KYC_TRIGGER_WALLET_BALANCE },
   2024     { "CLOSE", TALER_KYCLOGIC_KYC_TRIGGER_RESERVE_CLOSE },
   2025     { "AGGREGATE", TALER_KYCLOGIC_KYC_TRIGGER_AGGREGATE },
   2026     { "TRANSACTION", TALER_KYCLOGIC_KYC_TRIGGER_TRANSACTION },
   2027     { "REFUND", TALER_KYCLOGIC_KYC_TRIGGER_REFUND },
   2028     { NULL, 0 }
   2029   };
   2030 
   2031   for (unsigned int i = 0; NULL != map[i].in; i++)
   2032     if (0 == strcasecmp (map[i].in,
   2033                          trigger_s))
   2034     {
   2035       *trigger = map[i].out;
   2036       return GNUNET_OK;
   2037     }
   2038   GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
   2039               "Invalid KYC trigger `%s'\n",
   2040               trigger_s);
   2041   return GNUNET_SYSERR;
   2042 }
   2043 
   2044 
   2045 json_t *
   2046 TALER_KYCLOGIC_get_wallet_thresholds (void)
   2047 {
   2048   json_t *ret;
   2049 
   2050   ret = json_array ();
   2051   GNUNET_assert (NULL != ret);
   2052   for (unsigned int i = 0; i<default_rules.num_kyc_rules; i++)
   2053   {
   2054     struct TALER_KYCLOGIC_KycRule *rule
   2055       = &default_rules.kyc_rules[i];
   2056 
   2057     if (TALER_KYCLOGIC_KYC_TRIGGER_WALLET_BALANCE != rule->trigger)
   2058       continue;
   2059     GNUNET_assert (
   2060       0 ==
   2061       json_array_append_new (
   2062         ret,
   2063         TALER_JSON_from_amount (
   2064           &rule->threshold)));
   2065   }
   2066   return ret;
   2067 }
   2068 
   2069 
   2070 /**
   2071  * Load KYC logic plugin.
   2072  *
   2073  * @param cfg configuration to use
   2074  * @param name name of the plugin
   2075  * @return NULL on error
   2076  */
   2077 static struct TALER_KYCLOGIC_Plugin *
   2078 load_logic (const struct GNUNET_CONFIGURATION_Handle *cfg,
   2079             const char *name)
   2080 {
   2081   char *lib_name;
   2082   struct TALER_KYCLOGIC_Plugin *plugin;
   2083 
   2084 
   2085   GNUNET_asprintf (&lib_name,
   2086                    "libtaler_plugin_kyclogic_%s",
   2087                    name);
   2088   if (! ascii_lower (lib_name))
   2089   {
   2090     GNUNET_free (lib_name);
   2091     return NULL;
   2092   }
   2093   for (unsigned int i = 0; i<num_kyc_logics; i++)
   2094     if (0 == strcasecmp (lib_name,
   2095                          kyc_logics[i]->library_name))
   2096     {
   2097       GNUNET_free (lib_name);
   2098       return kyc_logics[i];
   2099     }
   2100   plugin = GNUNET_PLUGIN_load (TALER_EXCHANGE_project_data (),
   2101                                lib_name,
   2102                                (void *) cfg);
   2103   if (NULL == plugin)
   2104   {
   2105     GNUNET_free (lib_name);
   2106     return NULL;
   2107   }
   2108   plugin->library_name = lib_name;
   2109   plugin->name = GNUNET_strdup (name);
   2110   GNUNET_array_append (kyc_logics,
   2111                        num_kyc_logics,
   2112                        plugin);
   2113   return plugin;
   2114 }
   2115 
   2116 
   2117 /**
   2118  * Parse configuration of a KYC provider.
   2119  *
   2120  * @param cfg configuration to parse
   2121  * @param section name of the section to analyze
   2122  * @return #GNUNET_OK on success
   2123  */
   2124 static enum GNUNET_GenericReturnValue
   2125 add_provider (const struct GNUNET_CONFIGURATION_Handle *cfg,
   2126               const char *section)
   2127 {
   2128   char *logic;
   2129   struct TALER_KYCLOGIC_Plugin *lp;
   2130   struct TALER_KYCLOGIC_ProviderDetails *pd;
   2131 
   2132   GNUNET_log (GNUNET_ERROR_TYPE_INFO,
   2133               "Parsing KYC provider %s\n",
   2134               section);
   2135   if (GNUNET_OK !=
   2136       GNUNET_CONFIGURATION_get_value_string (cfg,
   2137                                              section,
   2138                                              "LOGIC",
   2139                                              &logic))
   2140   {
   2141     GNUNET_log_config_missing (GNUNET_ERROR_TYPE_ERROR,
   2142                                section,
   2143                                "LOGIC");
   2144     return GNUNET_SYSERR;
   2145   }
   2146   if (! ascii_lower (logic))
   2147   {
   2148     GNUNET_log_config_invalid (GNUNET_ERROR_TYPE_ERROR,
   2149                                section,
   2150                                "LOGIC",
   2151                                "Only [a-zA-Z0-9_0] are allowed");
   2152     return GNUNET_SYSERR;
   2153   }
   2154   lp = load_logic (cfg,
   2155                    logic);
   2156   if (NULL == lp)
   2157   {
   2158     GNUNET_log_config_invalid (GNUNET_ERROR_TYPE_ERROR,
   2159                                section,
   2160                                "LOGIC",
   2161                                "logic plugin could not be loaded");
   2162     GNUNET_free (logic);
   2163     return GNUNET_SYSERR;
   2164   }
   2165   GNUNET_free (logic);
   2166   pd = lp->load_configuration (lp->cls,
   2167                                section);
   2168   if (NULL == pd)
   2169     return GNUNET_SYSERR;
   2170 
   2171   {
   2172     struct TALER_KYCLOGIC_KycProvider *kp;
   2173 
   2174     kp = GNUNET_new (struct TALER_KYCLOGIC_KycProvider);
   2175     kp->provider_name
   2176       = GNUNET_strdup (&section[strlen ("kyc-provider-")]);
   2177     kp->logic = lp;
   2178     kp->pd = pd;
   2179     kp->process_timeout = GNUNET_TIME_UNIT_DAYS;
   2180     if (GNUNET_YES ==
   2181         GNUNET_CONFIGURATION_have_value (cfg,
   2182                                          section,
   2183                                          "KYC_PROCESS_TIMEOUT"))
   2184     {
   2185       if (GNUNET_OK !=
   2186           GNUNET_CONFIGURATION_get_value_time (cfg,
   2187                                                section,
   2188                                                "KYC_PROCESS_TIMEOUT",
   2189                                                &kp->process_timeout))
   2190       {
   2191         GNUNET_log_config_invalid (GNUNET_ERROR_TYPE_ERROR,
   2192                                    section,
   2193                                    "KYC_PROCESS_TIMEOUT",
   2194                                    "finite positive duration required");
   2195         GNUNET_free (kp->provider_name);
   2196         GNUNET_free (kp);
   2197         lp->unload_configuration (pd);
   2198         return GNUNET_SYSERR;
   2199       }
   2200     }
   2201     if ( (0 == kp->process_timeout.rel_value_us) ||
   2202          (GNUNET_TIME_UNIT_FOREVER_REL.rel_value_us ==
   2203           kp->process_timeout.rel_value_us) )
   2204     {
   2205       GNUNET_log_config_invalid (GNUNET_ERROR_TYPE_ERROR,
   2206                                  section,
   2207                                  "KYC_PROCESS_TIMEOUT",
   2208                                  "finite positive duration required");
   2209       GNUNET_free (kp->provider_name);
   2210       GNUNET_free (kp);
   2211       lp->unload_configuration (pd);
   2212       return GNUNET_SYSERR;
   2213     }
   2214     GNUNET_array_append (kyc_providers,
   2215                          num_kyc_providers,
   2216                          kp);
   2217   }
   2218   return GNUNET_OK;
   2219 }
   2220 
   2221 
   2222 struct GNUNET_TIME_Relative
   2223 TALER_KYCLOGIC_provider_get_process_timeout (
   2224   const struct TALER_KYCLOGIC_KycProvider *provider)
   2225 {
   2226   return provider->process_timeout;
   2227 }
   2228 
   2229 
   2230 /**
   2231  * Tokenize @a input along @a token
   2232  * and build an array of the tokens.
   2233  *
   2234  * @param[in,out] input the input to tokenize; clobbered
   2235  * @param sep separator between tokens to separate @a input on
   2236  * @param[out] p_strs where to put array of tokens
   2237  * @param[out] num_strs set to length of @a p_strs array
   2238  */
   2239 static void
   2240 add_tokens (char *input,
   2241             const char *sep,
   2242             char ***p_strs,
   2243             unsigned int *num_strs)
   2244 {
   2245   char *sptr;
   2246   char **rstr = NULL;
   2247   unsigned int num_rstr = 0;
   2248 
   2249   for (char *tok = strtok_r (input, sep, &sptr);
   2250        NULL != tok;
   2251        tok = strtok_r (NULL, sep, &sptr))
   2252   {
   2253     GNUNET_array_append (rstr,
   2254                          num_rstr,
   2255                          GNUNET_strdup (tok));
   2256   }
   2257   *p_strs = rstr;
   2258   *num_strs = num_rstr;
   2259 }
   2260 
   2261 
   2262 /**
   2263  * Closure for the handle_XXX_section functions
   2264  * that parse configuration sections matching certain
   2265  * prefixes.
   2266  */
   2267 struct SectionContext
   2268 {
   2269   /**
   2270    * Configuration to handle.
   2271    */
   2272   const struct GNUNET_CONFIGURATION_Handle *cfg;
   2273 
   2274   /**
   2275    * Result to return, set to false on failures.
   2276    */
   2277   bool result;
   2278 };
   2279 
   2280 
   2281 /**
   2282  * Function to iterate over configuration sections.
   2283  *
   2284  * @param cls a `struct SectionContext *`
   2285  * @param section name of the section
   2286  */
   2287 static void
   2288 handle_provider_section (void *cls,
   2289                          const char *section)
   2290 {
   2291   struct SectionContext *sc = cls;
   2292   char *s;
   2293 
   2294   if (! sc->result)
   2295     return;
   2296   s = normalize_section_with_prefix ("kyc-provider-",
   2297                                      section);
   2298   if (NULL == s)
   2299     return;
   2300   if (GNUNET_OK !=
   2301       add_provider (sc->cfg,
   2302                     s))
   2303   {
   2304     GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
   2305                 "Setup failed in configuration section `%s'\n",
   2306                 section);
   2307     sc->result = false;
   2308   }
   2309   GNUNET_free (s);
   2310 }
   2311 
   2312 
   2313 /**
   2314  * Parse configuration @a cfg in section @a section for
   2315  * the specification of a KYC check.
   2316  *
   2317  * @param cfg configuration to parse
   2318  * @param section configuration section to parse
   2319  * @return #GNUNET_OK on success
   2320  */
   2321 static enum GNUNET_GenericReturnValue
   2322 add_check (const struct GNUNET_CONFIGURATION_Handle *cfg,
   2323            const char *section)
   2324 {
   2325   enum TALER_KYCLOGIC_CheckType ct;
   2326   char *description = NULL;
   2327   json_t *description_i18n = NULL;
   2328   char *requires = NULL;
   2329   char *outputs = NULL;
   2330   char *fallback = NULL;
   2331 
   2332   if (0 == strcasecmp (&section[strlen ("kyc-check-")],
   2333                        "skip"))
   2334   {
   2335     GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
   2336                 "The kyc-check-skip section must not exist, 'skip' is reserved name for a built-in check\n");
   2337     return GNUNET_SYSERR;
   2338   }
   2339   GNUNET_log (GNUNET_ERROR_TYPE_INFO,
   2340               "Parsing KYC check %s\n",
   2341               section);
   2342   {
   2343     char *type_s;
   2344 
   2345     if (GNUNET_OK !=
   2346         GNUNET_CONFIGURATION_get_value_string (cfg,
   2347                                                section,
   2348                                                "TYPE",
   2349                                                &type_s))
   2350     {
   2351       GNUNET_log_config_missing (GNUNET_ERROR_TYPE_ERROR,
   2352                                  section,
   2353                                  "TYPE");
   2354       return GNUNET_SYSERR;
   2355     }
   2356     if (GNUNET_OK !=
   2357         check_type_from_string (type_s,
   2358                                 &ct))
   2359     {
   2360       GNUNET_log_config_invalid (GNUNET_ERROR_TYPE_ERROR,
   2361                                  section,
   2362                                  "TYPE",
   2363                                  "valid check type required");
   2364       GNUNET_free (type_s);
   2365       goto fail;
   2366     }
   2367     GNUNET_free (type_s);
   2368   }
   2369 
   2370   if (GNUNET_OK !=
   2371       GNUNET_CONFIGURATION_get_value_string (cfg,
   2372                                              section,
   2373                                              "DESCRIPTION",
   2374                                              &description))
   2375   {
   2376     GNUNET_log_config_missing (GNUNET_ERROR_TYPE_ERROR,
   2377                                section,
   2378                                "DESCRIPTION");
   2379     goto fail;
   2380   }
   2381 
   2382   {
   2383     char *tmp;
   2384 
   2385     if (GNUNET_OK ==
   2386         GNUNET_CONFIGURATION_get_value_string (cfg,
   2387                                                section,
   2388                                                "DESCRIPTION_I18N",
   2389                                                &tmp))
   2390     {
   2391       json_error_t err;
   2392 
   2393       description_i18n = json_loads (tmp,
   2394                                      JSON_REJECT_DUPLICATES,
   2395                                      &err);
   2396       GNUNET_free (tmp);
   2397       if (NULL == description_i18n)
   2398       {
   2399         GNUNET_log_config_invalid (GNUNET_ERROR_TYPE_ERROR,
   2400                                    section,
   2401                                    "DESCRIPTION_I18N",
   2402                                    err.text);
   2403         goto fail;
   2404       }
   2405       if (! TALER_JSON_check_i18n (description_i18n) )
   2406       {
   2407         GNUNET_log_config_invalid (GNUNET_ERROR_TYPE_ERROR,
   2408                                    section,
   2409                                    "DESCRIPTION_I18N",
   2410                                    "JSON with internationalization map required");
   2411         goto fail;
   2412       }
   2413     }
   2414   }
   2415 
   2416   if (GNUNET_OK !=
   2417       GNUNET_CONFIGURATION_get_value_string (cfg,
   2418                                              section,
   2419                                              "REQUIRES",
   2420                                              &requires))
   2421   {
   2422     /* no requirements is OK */
   2423     requires = GNUNET_strdup ("");
   2424   }
   2425 
   2426   if (GNUNET_OK !=
   2427       GNUNET_CONFIGURATION_get_value_string (cfg,
   2428                                              section,
   2429                                              "OUTPUTS",
   2430                                              &outputs))
   2431   {
   2432     /* no outputs is OK */
   2433     outputs = GNUNET_strdup ("");
   2434   }
   2435 
   2436   if (GNUNET_OK !=
   2437       GNUNET_CONFIGURATION_get_value_string (cfg,
   2438                                              section,
   2439                                              "FALLBACK",
   2440                                              &fallback))
   2441   {
   2442     /* We do *not* allow NULL to fall back to default rules because fallbacks
   2443        are used when there is actually a serious error and thus some action
   2444        (usually an investigation) is always in order, and that's basically
   2445        never the default. And as fallbacks should be rare, we really insist on
   2446        them at least being explicitly configured. Otherwise these errors may
   2447        go undetected simply because someone forgot to configure a fallback and
   2448        then nothing happens. */
   2449     GNUNET_log_config_missing (GNUNET_ERROR_TYPE_ERROR,
   2450                                section,
   2451                                "FALLBACK");
   2452     goto fail;
   2453   }
   2454   if (! ascii_lower (fallback))
   2455   {
   2456     GNUNET_log_config_invalid (GNUNET_ERROR_TYPE_ERROR,
   2457                                section,
   2458                                "FALLBACK",
   2459                                "Only [a-zA-Z0-9_0] are allowed");
   2460     goto fail;
   2461   }
   2462 
   2463   {
   2464     struct TALER_KYCLOGIC_KycCheck *kc;
   2465 
   2466     kc = GNUNET_new (struct TALER_KYCLOGIC_KycCheck);
   2467     switch (ct)
   2468     {
   2469     case TALER_KYCLOGIC_CT_INFO:
   2470       /* nothing to do */
   2471       break;
   2472     case TALER_KYCLOGIC_CT_FORM:
   2473       {
   2474         char *form_name;
   2475 
   2476         if (GNUNET_OK !=
   2477             GNUNET_CONFIGURATION_get_value_string (cfg,
   2478                                                    section,
   2479                                                    "FORM_NAME",
   2480                                                    &form_name))
   2481         {
   2482           GNUNET_log_config_missing (GNUNET_ERROR_TYPE_ERROR,
   2483                                      section,
   2484                                      "FORM_NAME");
   2485           goto fail;
   2486         }
   2487         if (! ascii_lower (form_name))
   2488         {
   2489           GNUNET_log_config_invalid (GNUNET_ERROR_TYPE_ERROR,
   2490                                      section,
   2491                                      "FORM_NAME",
   2492                                      "Only [a-zA-Z0-9_0] are allowed");
   2493           goto fail;
   2494         }
   2495         kc->details.form.name = form_name;
   2496       }
   2497       break;
   2498     case TALER_KYCLOGIC_CT_LINK:
   2499       {
   2500         char *provider_id;
   2501 
   2502         if (GNUNET_OK !=
   2503             GNUNET_CONFIGURATION_get_value_string (cfg,
   2504                                                    section,
   2505                                                    "PROVIDER_ID",
   2506                                                    &provider_id))
   2507         {
   2508           GNUNET_log_config_missing (GNUNET_ERROR_TYPE_ERROR,
   2509                                      section,
   2510                                      "PROVIDER_ID");
   2511           goto fail;
   2512         }
   2513         if (! ascii_lower (provider_id))
   2514         {
   2515           GNUNET_log_config_invalid (GNUNET_ERROR_TYPE_ERROR,
   2516                                      section,
   2517                                      "PROVIDER_ID",
   2518                                      "Only [a-zA-Z0-9_0] are allowed");
   2519           goto fail;
   2520         }
   2521         kc->details.link.provider = find_provider (provider_id);
   2522         if (NULL == kc->details.link.provider)
   2523         {
   2524           GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
   2525                       "Unknown KYC provider `%s' used in check `%s'\n",
   2526                       provider_id,
   2527                       &section[strlen ("kyc-check-")]);
   2528           GNUNET_free (kc);
   2529           GNUNET_free (provider_id);
   2530           goto fail;
   2531         }
   2532         GNUNET_free (provider_id);
   2533       }
   2534       break;
   2535     }
   2536     kc->check_name = GNUNET_strdup (&section[strlen ("kyc-check-")]);
   2537     kc->description = description;
   2538     kc->description_i18n = description_i18n;
   2539     kc->fallback = fallback;
   2540     kc->type = ct;
   2541     add_tokens (requires,
   2542                 "; \n\t",
   2543                 &kc->requires,
   2544                 &kc->num_requires);
   2545     GNUNET_free (requires);
   2546     add_tokens (outputs,
   2547                 "; \n\t",
   2548                 &kc->outputs,
   2549                 &kc->num_outputs);
   2550     GNUNET_free (outputs);
   2551     GNUNET_array_append (kyc_checks,
   2552                          num_kyc_checks,
   2553                          kc);
   2554   }
   2555 
   2556   return GNUNET_OK;
   2557 fail:
   2558   GNUNET_free (description);
   2559   json_decref (description_i18n);
   2560   GNUNET_free (requires);
   2561   GNUNET_free (outputs);
   2562   GNUNET_free (fallback);
   2563   return GNUNET_SYSERR;
   2564 }
   2565 
   2566 
   2567 /**
   2568  * Function to iterate over configuration sections.
   2569  *
   2570  * @param cls a `struct SectionContext *`
   2571  * @param section name of the section
   2572  */
   2573 static void
   2574 handle_check_section (void *cls,
   2575                       const char *section)
   2576 {
   2577   struct SectionContext *sc = cls;
   2578   char *s;
   2579 
   2580   if (! sc->result)
   2581     return;
   2582   s = normalize_section_with_prefix ("kyc-check-",
   2583                                      section);
   2584   if (NULL == s)
   2585     return;
   2586   if (GNUNET_OK !=
   2587       add_check (sc->cfg,
   2588                  s))
   2589     sc->result = false;
   2590   GNUNET_free (s);
   2591 }
   2592 
   2593 
   2594 /**
   2595  * Parse configuration @a cfg in section @a section for
   2596  * the specification of a KYC rule.
   2597  *
   2598  * @param cfg configuration to parse
   2599  * @param section configuration section to parse
   2600  * @return #GNUNET_OK on success
   2601  */
   2602 static enum GNUNET_GenericReturnValue
   2603 add_rule (const struct GNUNET_CONFIGURATION_Handle *cfg,
   2604           const char *section)
   2605 {
   2606   struct TALER_Amount threshold;
   2607   struct GNUNET_TIME_Relative timeframe;
   2608   enum TALER_KYCLOGIC_KycTriggerEvent ot;
   2609   char *measures;
   2610   bool exposed;
   2611   bool is_and;
   2612 
   2613   GNUNET_log (GNUNET_ERROR_TYPE_INFO,
   2614               "Parsing KYC rule from %s\n",
   2615               section);
   2616   {
   2617     enum GNUNET_GenericReturnValue r;
   2618 
   2619     r = GNUNET_CONFIGURATION_get_value_yesno (cfg,
   2620                                               section,
   2621                                               "ENABLED");
   2622     if ( (GNUNET_SYSERR == r) &&
   2623          (GNUNET_YES ==
   2624           GNUNET_CONFIGURATION_have_value (cfg,
   2625                                            section,
   2626                                            "ENABLED")) )
   2627     {
   2628       GNUNET_log_config_invalid (GNUNET_ERROR_TYPE_ERROR,
   2629                                  section,
   2630                                  "ENABLED",
   2631                                  "YES or NO required");
   2632       return GNUNET_SYSERR;
   2633     }
   2634     if (GNUNET_YES != r)
   2635       return GNUNET_OK;
   2636   }
   2637   if (GNUNET_OK !=
   2638       TALER_config_get_amount (cfg,
   2639                                section,
   2640                                "THRESHOLD",
   2641                                &threshold))
   2642   {
   2643     GNUNET_log_config_invalid (GNUNET_ERROR_TYPE_ERROR,
   2644                                section,
   2645                                "THRESHOLD",
   2646                                "amount required");
   2647     return GNUNET_SYSERR;
   2648   }
   2649   if (0 !=
   2650       strcasecmp (threshold.currency,
   2651                   my_currency))
   2652   {
   2653     GNUNET_log_config_invalid (GNUNET_ERROR_TYPE_ERROR,
   2654                                section,
   2655                                "THRESHOLD",
   2656                                "currency mismatch");
   2657     return GNUNET_SYSERR;
   2658   }
   2659   {
   2660     enum GNUNET_GenericReturnValue r;
   2661 
   2662     r = GNUNET_CONFIGURATION_get_value_yesno (cfg,
   2663                                               section,
   2664                                               "EXPOSED");
   2665     if ( (GNUNET_SYSERR == r) &&
   2666          (GNUNET_YES ==
   2667           GNUNET_CONFIGURATION_have_value (cfg,
   2668                                            section,
   2669                                            "EXPOSED")) )
   2670     {
   2671       GNUNET_log_config_invalid (GNUNET_ERROR_TYPE_ERROR,
   2672                                  section,
   2673                                  "EXPOSED",
   2674                                  "YES or NO required");
   2675       return GNUNET_SYSERR;
   2676     }
   2677     exposed = (GNUNET_YES == r);
   2678   }
   2679   {
   2680     enum GNUNET_GenericReturnValue r;
   2681 
   2682     r = GNUNET_CONFIGURATION_get_value_yesno (cfg,
   2683                                               section,
   2684                                               "IS_AND_COMBINATOR");
   2685     if (GNUNET_SYSERR == r)
   2686     {
   2687       GNUNET_log_config_invalid (GNUNET_ERROR_TYPE_ERROR,
   2688                                  section,
   2689                                  "IS_AND_COMBINATOR",
   2690                                  "YES or NO required");
   2691       return GNUNET_SYSERR;
   2692     }
   2693     is_and = (GNUNET_YES == r);
   2694   }
   2695 
   2696   {
   2697     char *ot_s;
   2698 
   2699     if (GNUNET_OK !=
   2700         GNUNET_CONFIGURATION_get_value_string (cfg,
   2701                                                section,
   2702                                                "OPERATION_TYPE",
   2703                                                &ot_s))
   2704     {
   2705       GNUNET_log_config_missing (GNUNET_ERROR_TYPE_ERROR,
   2706                                  section,
   2707                                  "OPERATION_TYPE");
   2708       return GNUNET_SYSERR;
   2709     }
   2710     if (GNUNET_OK !=
   2711         TALER_KYCLOGIC_kyc_trigger_from_string (ot_s,
   2712                                                 &ot))
   2713     {
   2714       GNUNET_log_config_invalid (GNUNET_ERROR_TYPE_ERROR,
   2715                                  section,
   2716                                  "OPERATION_TYPE",
   2717                                  "valid trigger type required");
   2718       GNUNET_free (ot_s);
   2719       return GNUNET_SYSERR;
   2720     }
   2721     GNUNET_free (ot_s);
   2722   }
   2723 
   2724   if (GNUNET_OK !=
   2725       GNUNET_CONFIGURATION_get_value_time (cfg,
   2726                                            section,
   2727                                            "TIMEFRAME",
   2728                                            &timeframe))
   2729   {
   2730     if (TALER_KYCLOGIC_KYC_TRIGGER_WALLET_BALANCE == ot)
   2731     {
   2732       timeframe = GNUNET_TIME_UNIT_ZERO;
   2733     }
   2734     else
   2735     {
   2736       GNUNET_log_config_invalid (GNUNET_ERROR_TYPE_ERROR,
   2737                                  section,
   2738                                  "TIMEFRAME",
   2739                                  "duration required");
   2740       return GNUNET_SYSERR;
   2741     }
   2742   }
   2743   if (GNUNET_OK !=
   2744       GNUNET_CONFIGURATION_get_value_string (cfg,
   2745                                              section,
   2746                                              "NEXT_MEASURES",
   2747                                              &measures))
   2748   {
   2749     GNUNET_log_config_missing (GNUNET_ERROR_TYPE_ERROR,
   2750                                section,
   2751                                "NEXT_MEASURES");
   2752     return GNUNET_SYSERR;
   2753   }
   2754   if (! token_list_lower (measures))
   2755   {
   2756     GNUNET_log_config_invalid (GNUNET_ERROR_TYPE_ERROR,
   2757                                section,
   2758                                "NEXT_MEASURES",
   2759                                "Only [a-zA-Z0-9 _-] are allowed");
   2760     GNUNET_free (measures);
   2761     return GNUNET_SYSERR;
   2762   }
   2763 
   2764   GNUNET_log (GNUNET_ERROR_TYPE_INFO,
   2765               "Adding KYC rule %s for trigger %d with threshold %s\n",
   2766               section,
   2767               (int) ot,
   2768               TALER_amount2s (&threshold));
   2769   {
   2770     struct TALER_KYCLOGIC_KycRule kt = {
   2771       .lrs = &default_rules,
   2772       .rule_name = GNUNET_strdup (&section[strlen ("kyc-rule-")]),
   2773       .timeframe = timeframe,
   2774       .threshold = threshold,
   2775       .trigger = ot,
   2776       .is_and_combinator = is_and,
   2777       .exposed = exposed,
   2778       .display_priority = 0,
   2779       .verboten = false
   2780     };
   2781 
   2782     add_tokens (measures,
   2783                 "; \n\t",
   2784                 &kt.next_measures,
   2785                 &kt.num_measures);
   2786     for (unsigned int i=0; i<kt.num_measures; i++)
   2787       if (0 == strcasecmp (KYC_MEASURE_IMPOSSIBLE,
   2788                            kt.next_measures[i]))
   2789         kt.verboten = true;
   2790     GNUNET_free (measures);
   2791     GNUNET_array_append (default_rules.kyc_rules,
   2792                          default_rules.num_kyc_rules,
   2793                          kt);
   2794   }
   2795   return GNUNET_OK;
   2796 }
   2797 
   2798 
   2799 /**
   2800  * Function to iterate over configuration sections.
   2801  *
   2802  * @param cls a `struct SectionContext *`
   2803  * @param section name of the section
   2804  */
   2805 static void
   2806 handle_rule_section (void *cls,
   2807                      const char *section)
   2808 {
   2809   struct SectionContext *sc = cls;
   2810   char *s;
   2811 
   2812   if (! sc->result)
   2813     return;
   2814   s = normalize_section_with_prefix ("kyc-rule-",
   2815                                      section);
   2816   if (NULL == s)
   2817     return;
   2818   if (GNUNET_OK !=
   2819       add_rule (sc->cfg,
   2820                 s))
   2821     sc->result = false;
   2822   GNUNET_free (s);
   2823 }
   2824 
   2825 
   2826 /**
   2827  * Parse array dimension argument of @a tok (if present)
   2828  * and store result in @a dimp. Does nothing if
   2829  * @a tok does not contain '['. Otherwise does some input
   2830  * validation.
   2831  *
   2832  * @param section name of configuration section for logging
   2833  * @param tok input to parse, of form "text[$DIM]"
   2834  * @param[out] dimp set to value of $DIM
   2835  * @return true on success
   2836  */
   2837 static bool
   2838 parse_dim (const char *section,
   2839            const char *tok,
   2840            long long *dimp)
   2841 {
   2842   const char *dim = strchr (tok,
   2843                             '[');
   2844   char dummy;
   2845 
   2846   if (NULL == dim)
   2847     return true;
   2848   if (1 !=
   2849       sscanf (dim,
   2850               "[%lld]%c",
   2851               dimp,
   2852               &dummy))
   2853   {
   2854     GNUNET_log_config_invalid (GNUNET_ERROR_TYPE_ERROR,
   2855                                section,
   2856                                "COMMAND",
   2857                                "output for -i invalid (bad dimension given)");
   2858     return false;
   2859   }
   2860   return true;
   2861 }
   2862 
   2863 
   2864 /**
   2865  * Parse configuration @a cfg in section @a section for
   2866  * the specification of an AML program.
   2867  *
   2868  * @param cfg configuration to parse
   2869  * @param section configuration section to parse
   2870  * @return #GNUNET_OK on success
   2871  */
   2872 static enum GNUNET_GenericReturnValue
   2873 add_program (const struct GNUNET_CONFIGURATION_Handle *cfg,
   2874              const char *section)
   2875 {
   2876   char *command = NULL;
   2877   char *description = NULL;
   2878   char *fallback = NULL;
   2879   char *required_contexts = NULL;
   2880   char *required_attributes = NULL;
   2881   char *required_inputs = NULL;
   2882   enum AmlProgramInputs input_mask = API_NONE;
   2883   long long aml_history_length_limit = INT64_MAX;
   2884   long long kyc_history_length_limit = INT64_MAX;
   2885 
   2886   GNUNET_log (GNUNET_ERROR_TYPE_INFO,
   2887               "Parsing KYC program %s\n",
   2888               section);
   2889   if (GNUNET_OK !=
   2890       GNUNET_CONFIGURATION_get_value_string (cfg,
   2891                                              section,
   2892                                              "COMMAND",
   2893                                              &command))
   2894   {
   2895     GNUNET_log_config_invalid (GNUNET_ERROR_TYPE_ERROR,
   2896                                section,
   2897                                "COMMAND",
   2898                                "command required");
   2899     goto fail;
   2900   }
   2901   if (GNUNET_OK !=
   2902       GNUNET_CONFIGURATION_get_value_string (cfg,
   2903                                              section,
   2904                                              "DESCRIPTION",
   2905                                              &description))
   2906   {
   2907     GNUNET_log_config_invalid (GNUNET_ERROR_TYPE_ERROR,
   2908                                section,
   2909                                "DESCRIPTION",
   2910                                "description required");
   2911     goto fail;
   2912   }
   2913   if (GNUNET_OK !=
   2914       GNUNET_CONFIGURATION_get_value_string (cfg,
   2915                                              section,
   2916                                              "FALLBACK",
   2917                                              &fallback))
   2918   {
   2919     /* We do *not* allow NULL to fall back to default rules because fallbacks
   2920        are used when there is actually a serious error and thus some action
   2921        (usually an investigation) is always in order, and that's basically
   2922        never the default. And as fallbacks should be rare, we really insist on
   2923        them at least being explicitly configured. Otherwise these errors may
   2924        go undetected simply because someone forgot to configure a fallback and
   2925        then nothing happens. */
   2926     GNUNET_log_config_invalid (GNUNET_ERROR_TYPE_ERROR,
   2927                                section,
   2928                                "FALLBACK",
   2929                                "fallback measure name required");
   2930     goto fail;
   2931   }
   2932 
   2933   required_contexts = command_output (command,
   2934                                       "-r");
   2935   if (NULL == required_contexts)
   2936   {
   2937     GNUNET_log_config_invalid (GNUNET_ERROR_TYPE_ERROR,
   2938                                section,
   2939                                "COMMAND",
   2940                                "output for -r invalid");
   2941     goto fail;
   2942   }
   2943 
   2944   required_attributes = command_output (command,
   2945                                         "-a");
   2946   if (NULL == required_attributes)
   2947   {
   2948     GNUNET_log_config_invalid (GNUNET_ERROR_TYPE_ERROR,
   2949                                section,
   2950                                "COMMAND",
   2951                                "output for -a invalid");
   2952     goto fail;
   2953   }
   2954 
   2955   required_inputs = command_output (command,
   2956                                     "-i");
   2957   if (NULL == required_inputs)
   2958   {
   2959     GNUNET_log_config_invalid (GNUNET_ERROR_TYPE_ERROR,
   2960                                section,
   2961                                "COMMAND",
   2962                                "output for -i invalid");
   2963     goto fail;
   2964   }
   2965 
   2966   {
   2967     char *sptr;
   2968 
   2969     for (char *tok = strtok_r (required_inputs,
   2970                                ";\n \t",
   2971                                &sptr);
   2972          NULL != tok;
   2973          tok = strtok_r (NULL,
   2974                          ";\n \t",
   2975                          &sptr) )
   2976     {
   2977       if (0 == strcasecmp (tok,
   2978                            "context"))
   2979         input_mask |= API_CONTEXT;
   2980       else if (0 == strcasecmp (tok,
   2981                                 "attributes"))
   2982         input_mask |= API_ATTRIBUTES;
   2983       else if (0 == strcasecmp (tok,
   2984                                 "current_rules"))
   2985         input_mask |= API_CURRENT_RULES;
   2986       else if (0 == strcasecmp (tok,
   2987                                 "default_rules"))
   2988         input_mask |= API_DEFAULT_RULES;
   2989       else if (0 == strncasecmp (tok,
   2990                                  "aml_history",
   2991                                  strlen ("aml_history")))
   2992       {
   2993         input_mask |= API_AML_HISTORY;
   2994         if (! parse_dim (section,
   2995                          tok,
   2996                          &aml_history_length_limit))
   2997           goto fail;
   2998       }
   2999       else if (0 == strncasecmp (tok,
   3000                                  "kyc_history",
   3001                                  strlen ("kyc_history")))
   3002       {
   3003         input_mask |= API_KYC_HISTORY;
   3004         if (! parse_dim (section,
   3005                          tok,
   3006                          &kyc_history_length_limit))
   3007           goto fail;
   3008       }
   3009       else
   3010       {
   3011         GNUNET_log_config_invalid (GNUNET_ERROR_TYPE_ERROR,
   3012                                    section,
   3013                                    "COMMAND",
   3014                                    "output for -i invalid (unsupported input)");
   3015         goto fail;
   3016       }
   3017     }
   3018   }
   3019   GNUNET_free (required_inputs);
   3020 
   3021   {
   3022     struct TALER_KYCLOGIC_AmlProgram *ap;
   3023 
   3024     ap = GNUNET_new (struct TALER_KYCLOGIC_AmlProgram);
   3025     ap->program_name = GNUNET_strdup (&section[strlen ("aml-program-")]);
   3026     ap->command = command;
   3027     ap->description = description;
   3028     ap->fallback = fallback;
   3029     ap->input_mask = input_mask;
   3030     ap->aml_history_length_limit = aml_history_length_limit;
   3031     ap->kyc_history_length_limit = kyc_history_length_limit;
   3032     add_tokens (required_contexts,
   3033                 "; \n\t",
   3034                 &ap->required_contexts,
   3035                 &ap->num_required_contexts);
   3036     GNUNET_free (required_contexts);
   3037     add_tokens (required_attributes,
   3038                 "; \n\t",
   3039                 &ap->required_attributes,
   3040                 &ap->num_required_attributes);
   3041     GNUNET_free (required_attributes);
   3042     GNUNET_array_append (aml_programs,
   3043                          num_aml_programs,
   3044                          ap);
   3045   }
   3046   return GNUNET_OK;
   3047 fail:
   3048   GNUNET_free (command);
   3049   GNUNET_free (description);
   3050   GNUNET_free (required_inputs);
   3051   GNUNET_free (required_contexts);
   3052   GNUNET_free (required_attributes);
   3053   GNUNET_free (fallback);
   3054   return GNUNET_SYSERR;
   3055 }
   3056 
   3057 
   3058 /**
   3059  * Function to iterate over configuration sections.
   3060  *
   3061  * @param cls a `struct SectionContext *`
   3062  * @param section name of the section
   3063  */
   3064 static void
   3065 handle_program_section (void *cls,
   3066                         const char *section)
   3067 {
   3068   struct SectionContext *sc = cls;
   3069   char *s;
   3070 
   3071   if (! sc->result)
   3072     return;
   3073   s = normalize_section_with_prefix ("aml-program-",
   3074                                      section);
   3075   if (NULL == s)
   3076     return;
   3077   if (GNUNET_OK !=
   3078       add_program (sc->cfg,
   3079                    s))
   3080     sc->result = false;
   3081   GNUNET_free (s);
   3082 }
   3083 
   3084 
   3085 /**
   3086  * Parse configuration @a cfg in section @a section for
   3087  * the specification of a KYC measure.
   3088  *
   3089  * @param cfg configuration to parse
   3090  * @param section configuration section to parse
   3091  * @return #GNUNET_OK on success
   3092  */
   3093 static enum GNUNET_GenericReturnValue
   3094 add_measure (const struct GNUNET_CONFIGURATION_Handle *cfg,
   3095              const char *section)
   3096 {
   3097   bool voluntary;
   3098   char *check_name = NULL;
   3099   struct TALER_KYCLOGIC_KycCheck *kc = NULL;
   3100   char *context_str = NULL;
   3101   char *program = NULL;
   3102   json_t *context;
   3103   json_error_t err;
   3104 
   3105   GNUNET_log (GNUNET_ERROR_TYPE_INFO,
   3106               "Parsing KYC measure %s\n",
   3107               section);
   3108   if (GNUNET_OK !=
   3109       GNUNET_CONFIGURATION_get_value_string (cfg,
   3110                                              section,
   3111                                              "CHECK_NAME",
   3112                                              &check_name))
   3113   {
   3114     check_name = GNUNET_strdup ("skip");
   3115   }
   3116   if (0 != strcasecmp (check_name,
   3117                        "skip"))
   3118   {
   3119     kc = find_check (check_name);
   3120     if (NULL == kc)
   3121     {
   3122       GNUNET_log_config_invalid (GNUNET_ERROR_TYPE_ERROR,
   3123                                  section,
   3124                                  "CHECK_NAME",
   3125                                  "check unknown");
   3126       goto fail;
   3127     }
   3128   }
   3129   if (GNUNET_OK !=
   3130       GNUNET_CONFIGURATION_get_value_string (cfg,
   3131                                              section,
   3132                                              "PROGRAM",
   3133                                              &program))
   3134   {
   3135     if ( (NULL == kc) ||
   3136          (TALER_KYCLOGIC_CT_INFO != kc->type) )
   3137     {
   3138       GNUNET_log_config_missing (GNUNET_ERROR_TYPE_ERROR,
   3139                                  section,
   3140                                  "PROGRAM");
   3141       goto fail;
   3142     }
   3143   }
   3144   else
   3145   {
   3146     /* AML program given, but do we want one? */
   3147     if ( (NULL != kc) &&
   3148          (TALER_KYCLOGIC_CT_INFO == kc->type) )
   3149     {
   3150       GNUNET_log_config_invalid (
   3151         GNUNET_ERROR_TYPE_WARNING,
   3152         section,
   3153         "PROGRAM",
   3154         "AML program specified for a check of type INFO (ignored)");
   3155       GNUNET_free (program);
   3156     }
   3157   }
   3158   voluntary = (GNUNET_YES ==
   3159                GNUNET_CONFIGURATION_get_value_yesno (cfg,
   3160                                                      section,
   3161                                                      "VOLUNTARY"));
   3162   if (GNUNET_OK !=
   3163       GNUNET_CONFIGURATION_get_value_string (cfg,
   3164                                              section,
   3165                                              "CONTEXT",
   3166                                              &context_str))
   3167   {
   3168     GNUNET_log_config_missing (GNUNET_ERROR_TYPE_ERROR,
   3169                                section,
   3170                                "CONTEXT");
   3171     goto fail;
   3172   }
   3173   context = json_loads (context_str,
   3174                         JSON_REJECT_DUPLICATES,
   3175                         &err);
   3176   GNUNET_free (context_str);
   3177   if (NULL == context)
   3178   {
   3179     GNUNET_log_config_invalid (GNUNET_ERROR_TYPE_ERROR,
   3180                                section,
   3181                                "CONTEXT",
   3182                                err.text);
   3183     goto fail;
   3184   }
   3185 
   3186   {
   3187     struct TALER_KYCLOGIC_Measure m;
   3188 
   3189     m.measure_name = GNUNET_strdup (&section[strlen ("kyc-measure-")]);
   3190     m.check_name = check_name;
   3191     m.prog_name = program;
   3192     m.context = context;
   3193     m.voluntary = voluntary;
   3194     GNUNET_array_append (default_rules.custom_measures,
   3195                          default_rules.num_custom_measures,
   3196                          m);
   3197   }
   3198   return GNUNET_OK;
   3199 fail:
   3200   GNUNET_free (check_name);
   3201   GNUNET_free (program);
   3202   GNUNET_free (context_str);
   3203   return GNUNET_SYSERR;
   3204 }
   3205 
   3206 
   3207 /**
   3208  * Function to iterate over configuration sections.
   3209  *
   3210  * @param cls a `struct SectionContext *`
   3211  * @param section name of the section
   3212  */
   3213 static void
   3214 handle_measure_section (void *cls,
   3215                         const char *section)
   3216 {
   3217   struct SectionContext *sc = cls;
   3218   char *s;
   3219 
   3220   if (! sc->result)
   3221     return;
   3222   s = normalize_section_with_prefix ("kyc-measure-",
   3223                                      section);
   3224   if (NULL == s)
   3225     return;
   3226   if (GNUNET_OK !=
   3227       add_measure (sc->cfg,
   3228                    s))
   3229     sc->result = false;
   3230   GNUNET_free (s);
   3231 }
   3232 
   3233 
   3234 /**
   3235  * Comparator for qsort. Compares two rules
   3236  * by timeframe to sort rules by time.
   3237  *
   3238  * @param p1 first trigger to compare
   3239  * @param p2 second trigger to compare
   3240  * @return -1 if p1 < p2, 0 if p1==p2, 1 if p1 > p2.
   3241  */
   3242 static int
   3243 sort_by_timeframe (const void *p1,
   3244                    const void *p2)
   3245 {
   3246   struct TALER_KYCLOGIC_KycRule *r1
   3247     = (struct TALER_KYCLOGIC_KycRule *) p1;
   3248   struct TALER_KYCLOGIC_KycRule *r2
   3249     = (struct TALER_KYCLOGIC_KycRule *) p2;
   3250 
   3251   if (GNUNET_TIME_relative_cmp (r1->timeframe,
   3252                                 <,
   3253                                 r2->timeframe))
   3254     return -1;
   3255   if (GNUNET_TIME_relative_cmp (r1->timeframe,
   3256                                 >,
   3257                                 r2->timeframe))
   3258     return 1;
   3259   return 0;
   3260 }
   3261 
   3262 
   3263 enum GNUNET_GenericReturnValue
   3264 TALER_KYCLOGIC_kyc_init (
   3265   const struct GNUNET_CONFIGURATION_Handle *cfg,
   3266   const char *cfg_fn)
   3267 {
   3268   struct SectionContext sc = {
   3269     .cfg = cfg,
   3270     .result = true
   3271   };
   3272   json_t *jkyc_rules_w;
   3273   json_t *jkyc_rules_a;
   3274 
   3275   if (NULL != cfg_fn)
   3276     cfg_filename = GNUNET_strdup (cfg_fn);
   3277   GNUNET_assert (GNUNET_OK ==
   3278                  TALER_config_get_currency (cfg,
   3279                                             "exchange",
   3280                                             &my_currency));
   3281   GNUNET_CONFIGURATION_iterate_sections (cfg,
   3282                                          &handle_provider_section,
   3283                                          &sc);
   3284   if (! sc.result)
   3285   {
   3286     TALER_KYCLOGIC_kyc_done ();
   3287     return GNUNET_SYSERR;
   3288   }
   3289   GNUNET_CONFIGURATION_iterate_sections (cfg,
   3290                                          &handle_check_section,
   3291                                          &sc);
   3292   if (! sc.result)
   3293   {
   3294     TALER_KYCLOGIC_kyc_done ();
   3295     return GNUNET_SYSERR;
   3296   }
   3297   GNUNET_CONFIGURATION_iterate_sections (cfg,
   3298                                          &handle_rule_section,
   3299                                          &sc);
   3300   if (! sc.result)
   3301   {
   3302     TALER_KYCLOGIC_kyc_done ();
   3303     return GNUNET_SYSERR;
   3304   }
   3305   GNUNET_CONFIGURATION_iterate_sections (cfg,
   3306                                          &handle_program_section,
   3307                                          &sc);
   3308   if (! sc.result)
   3309   {
   3310     TALER_KYCLOGIC_kyc_done ();
   3311     return GNUNET_SYSERR;
   3312   }
   3313   GNUNET_CONFIGURATION_iterate_sections (cfg,
   3314                                          &handle_measure_section,
   3315                                          &sc);
   3316   if (! sc.result)
   3317   {
   3318     TALER_KYCLOGIC_kyc_done ();
   3319     return GNUNET_SYSERR;
   3320   }
   3321 
   3322   if (0 != default_rules.num_kyc_rules)
   3323     qsort (default_rules.kyc_rules,
   3324            default_rules.num_kyc_rules,
   3325            sizeof (struct TALER_KYCLOGIC_KycRule),
   3326            &sort_by_timeframe);
   3327   jkyc_rules_w = json_array ();
   3328   GNUNET_assert (NULL != jkyc_rules_w);
   3329   jkyc_rules_a = json_array ();
   3330   GNUNET_assert (NULL != jkyc_rules_a);
   3331 
   3332   for (unsigned int i=0; i<default_rules.num_kyc_rules; i++)
   3333   {
   3334     const struct TALER_KYCLOGIC_KycRule *rule
   3335       = &default_rules.kyc_rules[i];
   3336     json_t *jrule;
   3337     json_t *jmeasures;
   3338 
   3339     jmeasures = json_array ();
   3340     GNUNET_assert (NULL != jmeasures);
   3341     for (unsigned int j=0; j<rule->num_measures; j++)
   3342     {
   3343       const char *measure_name = rule->next_measures[j];
   3344       const struct TALER_KYCLOGIC_Measure *m;
   3345 
   3346       if (0 == strcasecmp (KYC_MEASURE_IMPOSSIBLE,
   3347                            measure_name))
   3348       {
   3349         GNUNET_assert (
   3350           0 ==
   3351           json_array_append_new (jmeasures,
   3352                                  json_string (KYC_MEASURE_IMPOSSIBLE)));
   3353         continue;
   3354       }
   3355       m = find_measure (&default_rules,
   3356                         measure_name);
   3357       if (NULL == m)
   3358       {
   3359         GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
   3360                     "Unknown measure `%s' used in rule `%s'\n",
   3361                     measure_name,
   3362                     rule->rule_name);
   3363         return GNUNET_SYSERR;
   3364       }
   3365       GNUNET_assert (0 ==
   3366                      json_array_append_new (jmeasures,
   3367                                             json_string (measure_name)));
   3368     }
   3369     jrule = GNUNET_JSON_PACK (
   3370       GNUNET_JSON_pack_allow_null (
   3371         GNUNET_JSON_pack_string ("rule_name",
   3372                                  rule->rule_name)),
   3373       TALER_JSON_pack_kycte ("operation_type",
   3374                              rule->trigger),
   3375       TALER_JSON_pack_amount ("threshold",
   3376                               &rule->threshold),
   3377       GNUNET_JSON_pack_time_rel ("timeframe",
   3378                                  rule->timeframe),
   3379       GNUNET_JSON_pack_array_steal ("measures",
   3380                                     jmeasures),
   3381       GNUNET_JSON_pack_uint64 ("display_priority",
   3382                                rule->display_priority),
   3383       GNUNET_JSON_pack_bool ("exposed",
   3384                              rule->exposed),
   3385       GNUNET_JSON_pack_bool ("is_and_combinator",
   3386                              rule->is_and_combinator)
   3387       );
   3388     switch (rule->trigger)
   3389     {
   3390     case TALER_KYCLOGIC_KYC_TRIGGER_NONE:
   3391       GNUNET_break (0);
   3392       break;
   3393     case TALER_KYCLOGIC_KYC_TRIGGER_WITHDRAW:
   3394       GNUNET_assert (0 ==
   3395                      json_array_append (jkyc_rules_a,
   3396                                         jrule));
   3397       break;
   3398     case TALER_KYCLOGIC_KYC_TRIGGER_DEPOSIT:
   3399       GNUNET_assert (0 ==
   3400                      json_array_append (jkyc_rules_a,
   3401                                         jrule));
   3402       break;
   3403     case TALER_KYCLOGIC_KYC_TRIGGER_P2P_RECEIVE:
   3404       GNUNET_assert (0 ==
   3405                      json_array_append (jkyc_rules_w,
   3406                                         jrule));
   3407       break;
   3408     case TALER_KYCLOGIC_KYC_TRIGGER_WALLET_BALANCE:
   3409       GNUNET_assert (0 ==
   3410                      json_array_append (jkyc_rules_w,
   3411                                         jrule));
   3412       break;
   3413     case TALER_KYCLOGIC_KYC_TRIGGER_RESERVE_CLOSE:
   3414       GNUNET_assert (0 ==
   3415                      json_array_append (jkyc_rules_a,
   3416                                         jrule));
   3417       break;
   3418     case TALER_KYCLOGIC_KYC_TRIGGER_AGGREGATE:
   3419       GNUNET_assert (0 ==
   3420                      json_array_append (jkyc_rules_a,
   3421                                         jrule));
   3422       break;
   3423     case TALER_KYCLOGIC_KYC_TRIGGER_TRANSACTION:
   3424       GNUNET_assert (0 ==
   3425                      json_array_append (jkyc_rules_a,
   3426                                         jrule));
   3427       GNUNET_assert (0 ==
   3428                      json_array_append (jkyc_rules_w,
   3429                                         jrule));
   3430       break;
   3431     case TALER_KYCLOGIC_KYC_TRIGGER_REFUND:
   3432       GNUNET_assert (0 ==
   3433                      json_array_append (jkyc_rules_a,
   3434                                         jrule));
   3435       GNUNET_assert (0 ==
   3436                      json_array_append (jkyc_rules_w,
   3437                                         jrule));
   3438       break;
   3439     }
   3440     json_decref (jrule);
   3441   }
   3442   {
   3443     json_t *empty = json_object ();
   3444 
   3445     GNUNET_assert (NULL != empty);
   3446     wallet_default_lrs
   3447       = GNUNET_JSON_PACK (
   3448           GNUNET_JSON_pack_timestamp ("expiration_time",
   3449                                       GNUNET_TIME_UNIT_FOREVER_TS),
   3450           GNUNET_JSON_pack_array_steal ("rules",
   3451                                         jkyc_rules_w),
   3452           GNUNET_JSON_pack_object_incref ("custom_measures",
   3453                                           empty)
   3454           );
   3455     bankaccount_default_lrs
   3456       = GNUNET_JSON_PACK (
   3457           GNUNET_JSON_pack_timestamp ("expiration_time",
   3458                                       GNUNET_TIME_UNIT_FOREVER_TS),
   3459           GNUNET_JSON_pack_array_steal ("rules",
   3460                                         jkyc_rules_a),
   3461           GNUNET_JSON_pack_object_incref ("custom_measures",
   3462                                           empty)
   3463           );
   3464     json_decref (empty);
   3465   }
   3466   for (unsigned int i=0; i<default_rules.num_custom_measures; i++)
   3467   {
   3468     const struct TALER_KYCLOGIC_Measure *measure
   3469       = &default_rules.custom_measures[i];
   3470 
   3471     if (! check_measure (measure))
   3472     {
   3473       GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
   3474                   "Configuration of AML measures incorrect. Exiting.\n");
   3475       return GNUNET_SYSERR;
   3476     }
   3477   }
   3478 
   3479   for (unsigned int i=0; i<num_aml_programs; i++)
   3480   {
   3481     const struct TALER_KYCLOGIC_AmlProgram *program
   3482       = aml_programs[i];
   3483     const struct TALER_KYCLOGIC_Measure *m;
   3484 
   3485     m = find_measure (&default_rules,
   3486                       program->fallback);
   3487     if (NULL == m)
   3488     {
   3489       GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
   3490                   "Unknown fallback measure `%s' used in program `%s'\n",
   3491                   program->fallback,
   3492                   program->program_name);
   3493       return GNUNET_SYSERR;
   3494     }
   3495     if (0 != strcasecmp (m->check_name,
   3496                          "skip"))
   3497     {
   3498       GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
   3499                   "Fallback measure `%s' used in AML program `%s' has a check `%s' but fallbacks must have a check of type 'skip'\n",
   3500                   program->fallback,
   3501                   program->program_name,
   3502                   m->check_name);
   3503       return GNUNET_SYSERR;
   3504     }
   3505     if (NULL != m->prog_name)
   3506     {
   3507       const struct TALER_KYCLOGIC_AmlProgram *fprogram;
   3508 
   3509       fprogram = find_program (m->prog_name);
   3510       GNUNET_assert (NULL != fprogram);
   3511       if (API_NONE != (fprogram->input_mask & (API_CONTEXT | API_ATTRIBUTES)))
   3512       {
   3513         GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
   3514                     "Fallback program %s of fallback measure `%s' used in AML program `%s' has required inputs, but fallback measures must not require any inputs\n",
   3515                     m->prog_name,
   3516                     program->program_name,
   3517                     m->check_name);
   3518         return GNUNET_SYSERR;
   3519       }
   3520     }
   3521   }
   3522 
   3523   for (unsigned int i = 0; i<num_kyc_checks; i++)
   3524   {
   3525     struct TALER_KYCLOGIC_KycCheck *kyc_check
   3526       = kyc_checks[i];
   3527     const struct TALER_KYCLOGIC_Measure *measure;
   3528 
   3529     measure = find_measure (&default_rules,
   3530                             kyc_check->fallback);
   3531     if (NULL == measure)
   3532     {
   3533       GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
   3534                   "Unknown fallback measure `%s' used in check `%s'\n",
   3535                   kyc_check->fallback,
   3536                   kyc_check->check_name);
   3537       return GNUNET_SYSERR;
   3538     }
   3539     if (0 != strcasecmp (measure->check_name,
   3540                          "skip"))
   3541     {
   3542       GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
   3543                   "Fallback measure `%s' used in KYC check `%s' has a check `%s' but fallbacks must have a check of type 'skip'\n",
   3544                   kyc_check->fallback,
   3545                   kyc_check->check_name,
   3546                   measure->check_name);
   3547       return GNUNET_SYSERR;
   3548     }
   3549     if (NULL != measure->prog_name)
   3550     {
   3551       const struct TALER_KYCLOGIC_AmlProgram *fprogram;
   3552 
   3553       fprogram = find_program (measure->prog_name);
   3554       GNUNET_assert (NULL != fprogram);
   3555       if (API_NONE != (fprogram->input_mask & (API_CONTEXT | API_ATTRIBUTES)))
   3556       {
   3557         GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
   3558                     "AML program `%s' used fallback measure `%s' of KYC check `%s' has required inputs, but fallback measures must not require any inputs\n",
   3559                     measure->prog_name,
   3560                     kyc_check->fallback,
   3561                     kyc_check->check_name);
   3562         return GNUNET_SYSERR;
   3563       }
   3564     }
   3565   }
   3566 
   3567   return GNUNET_OK;
   3568 }
   3569 
   3570 
   3571 void
   3572 TALER_KYCLOGIC_kyc_done (void)
   3573 {
   3574   free_rules (&default_rules);
   3575   memset (&default_rules,
   3576           0,
   3577           sizeof (default_rules));
   3578   for (unsigned int i = 0; i<num_kyc_providers; i++)
   3579   {
   3580     struct TALER_KYCLOGIC_KycProvider *kp = kyc_providers[i];
   3581 
   3582     kp->logic->unload_configuration (kp->pd);
   3583     GNUNET_free (kp->provider_name);
   3584     GNUNET_free (kp);
   3585   }
   3586   GNUNET_array_grow (kyc_providers,
   3587                      num_kyc_providers,
   3588                      0);
   3589   for (unsigned int i = 0; i<num_kyc_logics; i++)
   3590   {
   3591     struct TALER_KYCLOGIC_Plugin *lp = kyc_logics[i];
   3592     char *lib_name = lp->library_name;
   3593 
   3594     GNUNET_free (lp->name);
   3595     GNUNET_assert (NULL == GNUNET_PLUGIN_unload (lib_name,
   3596                                                  lp));
   3597     GNUNET_free (lib_name);
   3598   }
   3599   GNUNET_array_grow (kyc_logics,
   3600                      num_kyc_logics,
   3601                      0);
   3602   for (unsigned int i = 0; i<num_kyc_checks; i++)
   3603   {
   3604     struct TALER_KYCLOGIC_KycCheck *kc = kyc_checks[i];
   3605 
   3606     GNUNET_free (kc->check_name);
   3607     GNUNET_free (kc->description);
   3608     json_decref (kc->description_i18n);
   3609     for (unsigned int j = 0; j<kc->num_requires; j++)
   3610       GNUNET_free (kc->requires[j]);
   3611     GNUNET_array_grow (kc->requires,
   3612                        kc->num_requires,
   3613                        0);
   3614     GNUNET_free (kc->fallback);
   3615     for (unsigned int j = 0; j<kc->num_outputs; j++)
   3616       GNUNET_free (kc->outputs[j]);
   3617     GNUNET_array_grow (kc->outputs,
   3618                        kc->num_outputs,
   3619                        0);
   3620     switch (kc->type)
   3621     {
   3622     case TALER_KYCLOGIC_CT_INFO:
   3623       break;
   3624     case TALER_KYCLOGIC_CT_FORM:
   3625       GNUNET_free (kc->details.form.name);
   3626       break;
   3627     case TALER_KYCLOGIC_CT_LINK:
   3628       break;
   3629     }
   3630     GNUNET_free (kc);
   3631   }
   3632   GNUNET_array_grow (kyc_checks,
   3633                      num_kyc_checks,
   3634                      0);
   3635   for (unsigned int i = 0; i<num_aml_programs; i++)
   3636   {
   3637     struct TALER_KYCLOGIC_AmlProgram *ap = aml_programs[i];
   3638 
   3639     GNUNET_free (ap->program_name);
   3640     GNUNET_free (ap->command);
   3641     GNUNET_free (ap->description);
   3642     GNUNET_free (ap->fallback);
   3643     for (unsigned int j = 0; j<ap->num_required_contexts; j++)
   3644       GNUNET_free (ap->required_contexts[j]);
   3645     GNUNET_array_grow (ap->required_contexts,
   3646                        ap->num_required_contexts,
   3647                        0);
   3648     for (unsigned int j = 0; j<ap->num_required_attributes; j++)
   3649       GNUNET_free (ap->required_attributes[j]);
   3650     GNUNET_array_grow (ap->required_attributes,
   3651                        ap->num_required_attributes,
   3652                        0);
   3653     GNUNET_free (ap);
   3654   }
   3655   GNUNET_array_grow (aml_programs,
   3656                      num_aml_programs,
   3657                      0);
   3658   GNUNET_free (cfg_filename);
   3659 }
   3660 
   3661 
   3662 void
   3663 TALER_KYCLOGIC_provider_to_logic (
   3664   const struct TALER_KYCLOGIC_KycProvider *provider,
   3665   struct TALER_KYCLOGIC_Plugin **plugin,
   3666   struct TALER_KYCLOGIC_ProviderDetails **pd,
   3667   const char **provider_name)
   3668 {
   3669   *plugin = provider->logic;
   3670   *pd = provider->pd;
   3671   *provider_name = provider->provider_name;
   3672 }
   3673 
   3674 
   3675 enum GNUNET_GenericReturnValue
   3676 TALER_KYCLOGIC_get_original_measure (
   3677   const char *measure_name,
   3678   struct TALER_KYCLOGIC_KycCheckContext *kcc)
   3679 {
   3680   const struct TALER_KYCLOGIC_Measure *measure;
   3681 
   3682   measure = find_measure (&default_rules,
   3683                           measure_name);
   3684   if (NULL == measure)
   3685   {
   3686     GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
   3687                 "Default measure `%s' unknown\n",
   3688                 measure_name);
   3689     return GNUNET_SYSERR;
   3690   }
   3691   if (0 == strcasecmp (measure->check_name,
   3692                        "skip"))
   3693   {
   3694     kcc->check = NULL;
   3695     kcc->prog_name = measure->prog_name;
   3696     kcc->context = measure->context;
   3697     return GNUNET_OK;
   3698   }
   3699 
   3700   for (unsigned int i = 0; i<num_kyc_checks; i++)
   3701     if (0 == strcasecmp (measure->check_name,
   3702                          kyc_checks[i]->check_name))
   3703     {
   3704       kcc->check = kyc_checks[i];
   3705       kcc->prog_name = measure->prog_name;
   3706       kcc->context = measure->context;
   3707       return GNUNET_OK;
   3708     }
   3709   GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
   3710               "Check `%s' unknown (but required by measure `%s')\n",
   3711               measure->check_name,
   3712               measure_name);
   3713   return GNUNET_SYSERR;
   3714 }
   3715 
   3716 
   3717 enum GNUNET_GenericReturnValue
   3718 TALER_KYCLOGIC_requirements_to_check (
   3719   const struct TALER_KYCLOGIC_LegitimizationRuleSet *lrs,
   3720   const struct TALER_KYCLOGIC_KycRule *kyc_rule,
   3721   const char *measure_name,
   3722   struct TALER_KYCLOGIC_KycCheckContext *kcc)
   3723 {
   3724   bool found = false;
   3725   const struct TALER_KYCLOGIC_Measure *measure = NULL;
   3726 
   3727   if (NULL == lrs)
   3728     lrs = &default_rules;
   3729   if (NULL == measure_name)
   3730   {
   3731     GNUNET_break (0);
   3732     return GNUNET_SYSERR;
   3733   }
   3734   if (NULL != kyc_rule)
   3735   {
   3736     if (kyc_rule->verboten)
   3737     {
   3738       GNUNET_log (GNUNET_ERROR_TYPE_WARNING,
   3739                   "Rule says operation is categorically is verboten, cannot take measures\n");
   3740       return GNUNET_SYSERR;
   3741     }
   3742     for (unsigned int i = 0; i<kyc_rule->num_measures; i++)
   3743     {
   3744       if (0 != strcasecmp (measure_name,
   3745                            kyc_rule->next_measures[i]))
   3746         continue;
   3747       found = true;
   3748       break;
   3749     }
   3750     if (! found)
   3751     {
   3752       GNUNET_log (GNUNET_ERROR_TYPE_WARNING,
   3753                   "Measure `%s' not allowed for rule `%s'\n",
   3754                   measure_name,
   3755                   kyc_rule->rule_name);
   3756       return GNUNET_SYSERR;
   3757     }
   3758   }
   3759   measure = find_measure (lrs,
   3760                           measure_name);
   3761   if (NULL == measure)
   3762   {
   3763     GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
   3764                 "Measure `%s' unknown (but allowed by rule `%s')\n",
   3765                 measure_name,
   3766                 NULL != kyc_rule
   3767                 ? kyc_rule->rule_name
   3768                 : "<NONE>");
   3769     return GNUNET_SYSERR;
   3770   }
   3771 
   3772   if (0 == strcasecmp (measure->check_name,
   3773                        "skip"))
   3774   {
   3775     kcc->check = NULL;
   3776     kcc->prog_name = measure->prog_name;
   3777     kcc->context = measure->context;
   3778     return GNUNET_OK;
   3779   }
   3780 
   3781   for (unsigned int i = 0; i<num_kyc_checks; i++)
   3782     if (0 == strcasecmp (measure->check_name,
   3783                          kyc_checks[i]->check_name))
   3784     {
   3785       kcc->check = kyc_checks[i];
   3786       kcc->prog_name = measure->prog_name;
   3787       kcc->context = measure->context;
   3788       return GNUNET_OK;
   3789     }
   3790   GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
   3791               "Check `%s' unknown (but required by measure `%s')\n",
   3792               measure->check_name,
   3793               measure_name);
   3794   return GNUNET_SYSERR;
   3795 }
   3796 
   3797 
   3798 enum GNUNET_GenericReturnValue
   3799 TALER_KYCLOGIC_lookup_logic (
   3800   const char *name,
   3801   struct TALER_KYCLOGIC_Plugin **plugin,
   3802   struct TALER_KYCLOGIC_ProviderDetails **pd,
   3803   const char **provider_name)
   3804 {
   3805   for (unsigned int i = 0; i<num_kyc_providers; i++)
   3806   {
   3807     struct TALER_KYCLOGIC_KycProvider *kp = kyc_providers[i];
   3808 
   3809     if (0 !=
   3810         strcasecmp (name,
   3811                     kp->provider_name))
   3812       continue;
   3813     *plugin = kp->logic;
   3814     *pd = kp->pd;
   3815     *provider_name = kp->provider_name;
   3816     return GNUNET_OK;
   3817   }
   3818   for (unsigned int i = 0; i<num_kyc_logics; i++)
   3819   {
   3820     struct TALER_KYCLOGIC_Plugin *logic = kyc_logics[i];
   3821 
   3822     if (0 !=
   3823         strcasecmp (logic->name,
   3824                     name))
   3825       continue;
   3826     *plugin = logic;
   3827     *pd = NULL;
   3828     *provider_name = NULL;
   3829     return GNUNET_OK;
   3830   }
   3831   GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
   3832               "Provider `%s' unknown\n",
   3833               name);
   3834   return GNUNET_SYSERR;
   3835 }
   3836 
   3837 
   3838 void
   3839 TALER_KYCLOGIC_kyc_get_details (
   3840   const char *logic_name,
   3841   TALER_KYCLOGIC_DetailsCallback cb,
   3842   void *cb_cls)
   3843 {
   3844   for (unsigned int i = 0; i<num_kyc_providers; i++)
   3845   {
   3846     struct TALER_KYCLOGIC_KycProvider *kp
   3847       = kyc_providers[i];
   3848 
   3849     if (0 !=
   3850         strcasecmp (kp->logic->name,
   3851                     logic_name))
   3852       continue;
   3853     if (GNUNET_OK !=
   3854         cb (cb_cls,
   3855             kp->pd,
   3856             kp->logic->cls))
   3857       return;
   3858   }
   3859 }
   3860 
   3861 
   3862 /**
   3863  * Closure for check_amount().
   3864  */
   3865 struct KycTestContext
   3866 {
   3867   /**
   3868    * Rule set we apply.
   3869    */
   3870   const struct TALER_KYCLOGIC_LegitimizationRuleSet *lrs;
   3871 
   3872   /**
   3873    * Events we care about.
   3874    */
   3875   enum TALER_KYCLOGIC_KycTriggerEvent event;
   3876 
   3877   /**
   3878    * Total amount encountered so far, invalid if zero.
   3879    */
   3880   struct TALER_Amount sum;
   3881 
   3882   /**
   3883    * Set to the triggered rule.
   3884    */
   3885   const struct TALER_KYCLOGIC_KycRule *triggered_rule;
   3886 
   3887 };
   3888 
   3889 
   3890 /**
   3891  * Function called on each @a amount that was found to
   3892  * be relevant for a KYC check.  Evaluates the given
   3893  * @a amount and @a date against all the applicable
   3894  * rules in the legitimization rule set.
   3895  *
   3896  * @param cls our `struct KycTestContext *`
   3897  * @param amount encountered transaction amount
   3898  * @param date when was the amount encountered
   3899  * @return #GNUNET_OK to continue to iterate,
   3900  *         #GNUNET_NO to abort iteration,
   3901  *         #GNUNET_SYSERR on internal error (also abort itaration)
   3902  */
   3903 static enum GNUNET_GenericReturnValue
   3904 check_amount (
   3905   void *cls,
   3906   const struct TALER_Amount *amount,
   3907   struct GNUNET_TIME_Absolute date)
   3908 {
   3909   struct KycTestContext *ktc = cls;
   3910   struct GNUNET_TIME_Relative dur;
   3911 
   3912   GNUNET_log (GNUNET_ERROR_TYPE_INFO,
   3913               "KYC checking transaction amount %s from %s against %u rules\n",
   3914               TALER_amount2s (amount),
   3915               GNUNET_TIME_absolute2s (date),
   3916               ktc->lrs->num_kyc_rules);
   3917   dur = GNUNET_TIME_absolute_get_duration (date);
   3918   if (GNUNET_OK !=
   3919       TALER_amount_is_valid (&ktc->sum))
   3920     ktc->sum = *amount;
   3921   else
   3922     GNUNET_assert (0 <=
   3923                    TALER_amount_add (&ktc->sum,
   3924                                      &ktc->sum,
   3925                                      amount));
   3926   for (unsigned int i=0; i<ktc->lrs->num_kyc_rules; i++)
   3927   {
   3928     const struct TALER_KYCLOGIC_KycRule *rule
   3929       = &ktc->lrs->kyc_rules[i];
   3930 
   3931     if (ktc->event != rule->trigger)
   3932     {
   3933       GNUNET_log (GNUNET_ERROR_TYPE_INFO,
   3934                   "Wrong event type (%d) for rule %u (%d)\n",
   3935                   (int) ktc->event,
   3936                   i,
   3937                   (int) rule->trigger);
   3938       continue; /* wrong trigger event type */
   3939     }
   3940     if (GNUNET_TIME_relative_cmp (dur,
   3941                                   >,
   3942                                   rule->timeframe))
   3943     {
   3944       GNUNET_log (GNUNET_ERROR_TYPE_INFO,
   3945                   "Out of time range for rule %u\n",
   3946                   i);
   3947       continue; /* out of time range for rule */
   3948     }
   3949     /*
   3950      * A KYC threshold is the inclusive maximum permitted by the rule:
   3951      * clients may transact up to and including this amount.  The rule is
   3952      * triggered only once the accumulated total exceeds the threshold.
   3953      * Keeping equality on the permitted side is also important because
   3954      * exposed AccountLimit values are advertised as maximum contributions.
   3955      */
   3956     if (0 >= TALER_amount_cmp (&ktc->sum,
   3957                                &rule->threshold))
   3958     {
   3959       GNUNET_log (GNUNET_ERROR_TYPE_INFO,
   3960                   "At or below threshold of %s for rule %u\n",
   3961                   TALER_amount2s (&rule->threshold),
   3962                   i);
   3963       continue; /* sum <= threshold */
   3964     }
   3965     if ( (NULL != ktc->triggered_rule) &&
   3966          (1 == TALER_amount_cmp (&ktc->triggered_rule->threshold,
   3967                                  &rule->threshold)) )
   3968     {
   3969       GNUNET_log (GNUNET_ERROR_TYPE_INFO,
   3970                   "Higher than threshold of already triggered rule\n");
   3971       continue; /* threshold of triggered_rule > rule */
   3972     }
   3973     GNUNET_log (GNUNET_ERROR_TYPE_INFO,
   3974                 "Remembering rule %s as triggered\n",
   3975                 rule->rule_name);
   3976     ktc->triggered_rule = rule;
   3977   }
   3978   return GNUNET_OK;
   3979 }
   3980 
   3981 
   3982 enum GNUNET_DB_QueryStatus
   3983 TALER_KYCLOGIC_kyc_test_required (
   3984   enum TALER_KYCLOGIC_KycTriggerEvent event,
   3985   const struct TALER_KYCLOGIC_LegitimizationRuleSet *lrs,
   3986   TALER_KYCLOGIC_KycAmountIterator ai,
   3987   void *ai_cls,
   3988   const struct TALER_KYCLOGIC_KycRule **triggered_rule,
   3989   struct TALER_Amount *next_threshold)
   3990 {
   3991   struct GNUNET_TIME_Relative range
   3992     = GNUNET_TIME_UNIT_ZERO;
   3993   enum GNUNET_DB_QueryStatus qs;
   3994   bool have_threshold = false;
   3995 
   3996   memset (next_threshold,
   3997           0,
   3998           sizeof (struct TALER_Amount));
   3999   if (NULL == lrs)
   4000     lrs = &default_rules;
   4001   GNUNET_log (GNUNET_ERROR_TYPE_INFO,
   4002               "Testing %u KYC rules for trigger %d\n",
   4003               lrs->num_kyc_rules,
   4004               event);
   4005   for (unsigned int i=0; i<lrs->num_kyc_rules; i++)
   4006   {
   4007     const struct TALER_KYCLOGIC_KycRule *rule
   4008       = &lrs->kyc_rules[i];
   4009 
   4010     if (event != rule->trigger)
   4011     {
   4012       GNUNET_log (GNUNET_ERROR_TYPE_INFO,
   4013                   "Rule %u is for a different trigger (%d/%d)\n",
   4014                   i,
   4015                   (int) event,
   4016                   (int) rule->trigger);
   4017       continue;
   4018     }
   4019     if (have_threshold)
   4020     {
   4021       GNUNET_assert (GNUNET_OK ==
   4022                      TALER_amount_min (next_threshold,
   4023                                        next_threshold,
   4024                                        &rule->threshold));
   4025     }
   4026     else
   4027     {
   4028       *next_threshold = rule->threshold;
   4029       have_threshold = true;
   4030     }
   4031     GNUNET_log (GNUNET_ERROR_TYPE_INFO,
   4032                 "Matched rule %u with timeframe %s and threshold %s\n",
   4033                 i,
   4034                 GNUNET_TIME_relative2s (rule->timeframe,
   4035                                         true),
   4036                 TALER_amount2s (&rule->threshold));
   4037     range = GNUNET_TIME_relative_max (range,
   4038                                       rule->timeframe);
   4039   }
   4040 
   4041   if (! have_threshold)
   4042   {
   4043     GNUNET_log (GNUNET_ERROR_TYPE_INFO,
   4044                 "No rules apply\n");
   4045     *triggered_rule = NULL;
   4046     return GNUNET_DB_STATUS_SUCCESS_NO_RESULTS;
   4047   }
   4048 
   4049   {
   4050     struct GNUNET_TIME_Absolute now
   4051       = GNUNET_TIME_absolute_get ();
   4052     struct KycTestContext ktc = {
   4053       .lrs = lrs,
   4054       .event = event
   4055     };
   4056 
   4057     qs = ai (ai_cls,
   4058              GNUNET_TIME_absolute_subtract (now,
   4059                                             range),
   4060              &check_amount,
   4061              &ktc);
   4062     GNUNET_log (GNUNET_ERROR_TYPE_INFO,
   4063                 "Triggered rule is %s\n",
   4064                 (NULL == ktc.triggered_rule)
   4065                 ? "NONE"
   4066                 : ktc.triggered_rule->rule_name);
   4067     *triggered_rule = ktc.triggered_rule;
   4068   }
   4069   return qs;
   4070 }
   4071 
   4072 
   4073 json_t *
   4074 TALER_KYCLOGIC_measure_to_requirement (
   4075   const char *check_name,
   4076   const json_t *context,
   4077   const struct TALER_AccountAccessTokenP *access_token,
   4078   size_t offset,
   4079   uint64_t legitimization_measure_row_id)
   4080 {
   4081   struct TALER_KYCLOGIC_KycCheck *kc;
   4082   json_t *kri;
   4083   struct TALER_KycMeasureAuthorizationHashP shv;
   4084   char *ids;
   4085   char *xids;
   4086 
   4087   kc = find_check (check_name);
   4088   if (NULL == kc)
   4089   {
   4090     GNUNET_break (0);
   4091     return NULL;
   4092   }
   4093   GNUNET_assert (offset <= UINT32_MAX);
   4094   TALER_kyc_measure_authorization_hash (access_token,
   4095                                         legitimization_measure_row_id,
   4096                                         (uint32_t) offset,
   4097                                         &shv);
   4098   switch (kc->type)
   4099   {
   4100   case TALER_KYCLOGIC_CT_INFO:
   4101     return GNUNET_JSON_PACK (
   4102       GNUNET_JSON_pack_string ("form",
   4103                                "INFO"),
   4104       GNUNET_JSON_pack_string ("description",
   4105                                kc->description),
   4106       GNUNET_JSON_pack_allow_null (
   4107         GNUNET_JSON_pack_object_incref ("description_i18n",
   4108                                         (json_t *) kc->description_i18n)));
   4109   case TALER_KYCLOGIC_CT_FORM:
   4110     GNUNET_assert (offset <= UINT_MAX);
   4111     ids = GNUNET_STRINGS_data_to_string_alloc (&shv,
   4112                                                sizeof (shv));
   4113     GNUNET_asprintf (&xids,
   4114                      "%s-%u-%llu",
   4115                      ids,
   4116                      (unsigned int) offset,
   4117                      (unsigned long long) legitimization_measure_row_id);
   4118     GNUNET_free (ids);
   4119     kri = GNUNET_JSON_PACK (
   4120       GNUNET_JSON_pack_string ("form",
   4121                                kc->details.form.name),
   4122       GNUNET_JSON_pack_string ("id",
   4123                                xids),
   4124       GNUNET_JSON_pack_allow_null (
   4125         GNUNET_JSON_pack_object_incref ("context",
   4126                                         (json_t *) context)),
   4127       GNUNET_JSON_pack_string ("description",
   4128                                kc->description),
   4129       GNUNET_JSON_pack_allow_null (
   4130         GNUNET_JSON_pack_object_incref ("description_i18n",
   4131                                         (json_t *) kc->description_i18n)));
   4132     GNUNET_free (xids);
   4133     return kri;
   4134   case TALER_KYCLOGIC_CT_LINK:
   4135     GNUNET_assert (offset <= UINT_MAX);
   4136     ids = GNUNET_STRINGS_data_to_string_alloc (&shv,
   4137                                                sizeof (shv));
   4138     GNUNET_asprintf (&xids,
   4139                      "%s-%u-%llu",
   4140                      ids,
   4141                      (unsigned int) offset,
   4142                      (unsigned long long) legitimization_measure_row_id);
   4143     GNUNET_free (ids);
   4144     kri = GNUNET_JSON_PACK (
   4145       GNUNET_JSON_pack_string ("form",
   4146                                "LINK"),
   4147       GNUNET_JSON_pack_string ("id",
   4148                                xids),
   4149       GNUNET_JSON_pack_string ("description",
   4150                                kc->description),
   4151       GNUNET_JSON_pack_allow_null (
   4152         GNUNET_JSON_pack_object_incref ("description_i18n",
   4153                                         (json_t *) kc->description_i18n)));
   4154     GNUNET_free (xids);
   4155     return kri;
   4156   }
   4157   GNUNET_break (0); /* invalid type */
   4158   return NULL;
   4159 }
   4160 
   4161 
   4162 void
   4163 TALER_KYCLOGIC_get_measure_configuration (
   4164   json_t **proots,
   4165   json_t **pprograms,
   4166   json_t **pchecks,
   4167   json_t **pdefault_rules)
   4168 {
   4169   json_t *roots;
   4170   json_t *programs;
   4171   json_t *checks;
   4172   json_t *drules;
   4173 
   4174   roots = json_object ();
   4175   GNUNET_assert (NULL != roots);
   4176   for (unsigned int i = 0; i<default_rules.num_custom_measures; i++)
   4177   {
   4178     const struct TALER_KYCLOGIC_Measure *m
   4179       = &default_rules.custom_measures[i];
   4180     json_t *jm;
   4181 
   4182     jm = GNUNET_JSON_PACK (
   4183       GNUNET_JSON_pack_string ("check_name",
   4184                                m->check_name),
   4185       GNUNET_JSON_pack_allow_null (
   4186         GNUNET_JSON_pack_string ("prog_name",
   4187                                  m->prog_name)),
   4188       GNUNET_JSON_pack_allow_null (
   4189         GNUNET_JSON_pack_object_incref ("context",
   4190                                         m->context)));
   4191     GNUNET_assert (0 ==
   4192                    json_object_set_new (roots,
   4193                                         m->measure_name,
   4194                                         jm));
   4195   }
   4196 
   4197   programs = json_object ();
   4198   GNUNET_assert (NULL != programs);
   4199   for (unsigned int i = 0; i<num_aml_programs; i++)
   4200   {
   4201     const struct TALER_KYCLOGIC_AmlProgram *ap
   4202       = aml_programs[i];
   4203     json_t *jp;
   4204     json_t *ctx;
   4205     json_t *inp;
   4206 
   4207     ctx = json_array ();
   4208     GNUNET_assert (NULL != ctx);
   4209     for (unsigned int j = 0; j<ap->num_required_contexts; j++)
   4210     {
   4211       const char *rc = ap->required_contexts[j];
   4212 
   4213       GNUNET_assert (0 ==
   4214                      json_array_append_new (ctx,
   4215                                             json_string (rc)));
   4216     }
   4217     inp = json_array ();
   4218     GNUNET_assert (NULL != inp);
   4219     for (unsigned int j = 0; j<ap->num_required_attributes; j++)
   4220     {
   4221       const char *ra = ap->required_attributes[j];
   4222 
   4223       GNUNET_assert (0 ==
   4224                      json_array_append_new (inp,
   4225                                             json_string (ra)));
   4226     }
   4227 
   4228     jp = GNUNET_JSON_PACK (
   4229       GNUNET_JSON_pack_string ("description",
   4230                                ap->description),
   4231       GNUNET_JSON_pack_array_steal ("context",
   4232                                     ctx),
   4233       GNUNET_JSON_pack_array_steal ("inputs",
   4234                                     inp));
   4235     GNUNET_assert (0 ==
   4236                    json_object_set_new (programs,
   4237                                         ap->program_name,
   4238                                         jp));
   4239   }
   4240 
   4241   checks = json_object ();
   4242   GNUNET_assert (NULL != checks);
   4243   for (unsigned int i = 0; i<num_kyc_checks; i++)
   4244   {
   4245     const struct TALER_KYCLOGIC_KycCheck *ck
   4246       = kyc_checks[i];
   4247     json_t *jc;
   4248     json_t *requires;
   4249     json_t *outputs;
   4250 
   4251     requires = json_array ();
   4252     GNUNET_assert (NULL != requires);
   4253     for (unsigned int j = 0; j<ck->num_requires; j++)
   4254     {
   4255       const char *ra = ck->requires[j];
   4256 
   4257       GNUNET_assert (0 ==
   4258                      json_array_append_new (requires,
   4259                                             json_string (ra)));
   4260     }
   4261     outputs = json_array ();
   4262     GNUNET_assert (NULL != outputs);
   4263     for (unsigned int j = 0; j<ck->num_outputs; j++)
   4264     {
   4265       const char *out = ck->outputs[j];
   4266 
   4267       GNUNET_assert (0 ==
   4268                      json_array_append_new (outputs,
   4269                                             json_string (out)));
   4270     }
   4271 
   4272     jc = GNUNET_JSON_PACK (
   4273       GNUNET_JSON_pack_string ("description",
   4274                                ck->description),
   4275       GNUNET_JSON_pack_allow_null (
   4276         GNUNET_JSON_pack_object_incref ("description_i18n",
   4277                                         ck->description_i18n)),
   4278       GNUNET_JSON_pack_array_steal ("requires",
   4279                                     requires),
   4280       GNUNET_JSON_pack_array_steal ("outputs",
   4281                                     outputs),
   4282       GNUNET_JSON_pack_string ("fallback",
   4283                                ck->fallback));
   4284     GNUNET_assert (0 ==
   4285                    json_object_set_new (checks,
   4286                                         ck->check_name,
   4287                                         jc));
   4288   }
   4289   drules = json_array ();
   4290   GNUNET_assert (NULL != drules);
   4291   {
   4292     const struct TALER_KYCLOGIC_KycRule *rules
   4293       = default_rules.kyc_rules;
   4294     unsigned int num_rules
   4295       = default_rules.num_kyc_rules;
   4296 
   4297     for (unsigned int i = 0; i<num_rules; i++)
   4298     {
   4299       const struct TALER_KYCLOGIC_KycRule *rule = &rules[i];
   4300       json_t *measures;
   4301       json_t *limit;
   4302 
   4303       measures = json_array ();
   4304       GNUNET_assert (NULL != measures);
   4305       for (unsigned int j = 0; j<rule->num_measures; j++)
   4306         GNUNET_assert (
   4307           0 ==
   4308           json_array_append_new (measures,
   4309                                  json_string (
   4310                                    rule->next_measures[j])));
   4311       limit = GNUNET_JSON_PACK (
   4312         GNUNET_JSON_pack_allow_null (
   4313           GNUNET_JSON_pack_string ("rule_name",
   4314                                    rule->rule_name)),
   4315         TALER_JSON_pack_kycte ("operation_type",
   4316                                rule->trigger),
   4317         TALER_JSON_pack_amount ("threshold",
   4318                                 &rule->threshold),
   4319         GNUNET_JSON_pack_time_rel ("timeframe",
   4320                                    rule->timeframe),
   4321         GNUNET_JSON_pack_array_steal ("measures",
   4322                                       measures),
   4323         GNUNET_JSON_pack_uint64 ("display_priority",
   4324                                  rule->display_priority),
   4325         GNUNET_JSON_pack_bool ("soft_limit",
   4326                                ! rule->verboten),
   4327         GNUNET_JSON_pack_bool ("exposed",
   4328                                rule->exposed),
   4329         GNUNET_JSON_pack_bool ("is_and_combinator",
   4330                                rule->is_and_combinator)
   4331         );
   4332       GNUNET_assert (0 ==
   4333                      json_array_append_new (drules,
   4334                                             limit));
   4335     }
   4336   }
   4337 
   4338   *proots = roots;
   4339   *pprograms = programs;
   4340   *pchecks = checks;
   4341   *pdefault_rules = drules;
   4342 }
   4343 
   4344 
   4345 enum TALER_ErrorCode
   4346 TALER_KYCLOGIC_select_measure (
   4347   const json_t *jmeasures,
   4348   size_t measure_index,
   4349   const char **check_name,
   4350   const char **prog_name,
   4351   const json_t **context)
   4352 {
   4353   const json_t *jmeasure_arr;
   4354   struct GNUNET_JSON_Specification spec[] = {
   4355     GNUNET_JSON_spec_array_const ("measures",
   4356                                   &jmeasure_arr),
   4357     GNUNET_JSON_spec_end ()
   4358   };
   4359   const json_t *jmeasure;
   4360   struct GNUNET_JSON_Specification ispec[] = {
   4361     GNUNET_JSON_spec_string ("check_name",
   4362                              check_name),
   4363     GNUNET_JSON_spec_mark_optional (
   4364       GNUNET_JSON_spec_string ("prog_name",
   4365                                prog_name),
   4366       NULL),
   4367     GNUNET_JSON_spec_mark_optional (
   4368       GNUNET_JSON_spec_object_const ("context",
   4369                                      context),
   4370       NULL),
   4371     GNUNET_JSON_spec_end ()
   4372   };
   4373 
   4374   *check_name = NULL;
   4375   *prog_name = NULL;
   4376   *context = NULL;
   4377   if (GNUNET_OK !=
   4378       GNUNET_JSON_parse (jmeasures,
   4379                          spec,
   4380                          NULL, NULL))
   4381   {
   4382     GNUNET_break (0);
   4383     return TALER_EC_EXCHANGE_KYC_MEASURES_MALFORMED;
   4384   }
   4385   if (measure_index >= json_array_size (jmeasure_arr))
   4386   {
   4387     GNUNET_break_op (0);
   4388     return TALER_EC_EXCHANGE_KYC_MEASURE_INDEX_INVALID;
   4389   }
   4390   jmeasure = json_array_get (jmeasure_arr,
   4391                              measure_index);
   4392   if (GNUNET_OK !=
   4393       GNUNET_JSON_parse (jmeasure,
   4394                          ispec,
   4395                          NULL, NULL))
   4396   {
   4397     GNUNET_break (0);
   4398     return TALER_EC_EXCHANGE_KYC_MEASURES_MALFORMED;
   4399   }
   4400   return TALER_EC_NONE;
   4401 }
   4402 
   4403 
   4404 enum TALER_ErrorCode
   4405 TALER_KYCLOGIC_check_form (
   4406   const json_t *jmeasures,
   4407   size_t measure_index,
   4408   const json_t *form_data,
   4409   char **form_name,
   4410   const char **error_message)
   4411 {
   4412   const char *check_name;
   4413   const char *prog_name;
   4414   const json_t *context;
   4415   struct TALER_KYCLOGIC_KycCheck *kc;
   4416   struct TALER_KYCLOGIC_AmlProgram *prog;
   4417 
   4418   *error_message = NULL;
   4419   *form_name = NULL;
   4420   if (TALER_EC_NONE !=
   4421       TALER_KYCLOGIC_select_measure (jmeasures,
   4422                                      measure_index,
   4423                                      &check_name,
   4424                                      &prog_name,
   4425                                      &context))
   4426   {
   4427     GNUNET_break_op (0);
   4428     return TALER_EC_EXCHANGE_KYC_MEASURE_INDEX_INVALID;
   4429   }
   4430   kc = find_check (check_name);
   4431   if (NULL == kc)
   4432   {
   4433     GNUNET_break (0);
   4434     *error_message = check_name;
   4435     return TALER_EC_EXCHANGE_KYC_GENERIC_CHECK_GONE;
   4436   }
   4437   if (TALER_KYCLOGIC_CT_FORM != kc->type)
   4438   {
   4439     GNUNET_break_op (0);
   4440     return TALER_EC_EXCHANGE_KYC_NOT_A_FORM;
   4441   }
   4442   if (NULL == prog_name)
   4443   {
   4444     /* non-INFO checks must have an AML program */
   4445     GNUNET_break (0);
   4446     return TALER_EC_EXCHANGE_KYC_GENERIC_LOGIC_BUG;
   4447   }
   4448   for (unsigned int i = 0; i<kc->num_outputs; i++)
   4449   {
   4450     const char *rattr = kc->outputs[i];
   4451 
   4452     if (NULL == json_object_get (form_data,
   4453                                  rattr))
   4454     {
   4455       GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
   4456                   "Form data lacks required attribute `%s' for KYC check `%s'\n",
   4457                   rattr,
   4458                   check_name);
   4459       *error_message = rattr;
   4460       return TALER_EC_EXCHANGE_KYC_AML_FORM_INCOMPLETE;
   4461     }
   4462   }
   4463   prog = find_program (prog_name);
   4464   if (NULL == prog)
   4465   {
   4466     GNUNET_break (0);
   4467     *error_message = prog_name;
   4468     return TALER_EC_EXCHANGE_KYC_GENERIC_AML_PROGRAM_GONE;
   4469   }
   4470   for (unsigned int i = 0; i<prog->num_required_attributes; i++)
   4471   {
   4472     const char *rattr = prog->required_attributes[i];
   4473 
   4474     if (NULL == json_object_get (form_data,
   4475                                  rattr))
   4476     {
   4477       GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
   4478                   "Form data lacks required attribute `%s' for AML program %s\n",
   4479                   rattr,
   4480                   prog_name);
   4481       *error_message = rattr;
   4482       return TALER_EC_EXCHANGE_KYC_AML_FORM_INCOMPLETE;
   4483     }
   4484   }
   4485   *form_name = GNUNET_strdup (kc->details.form.name);
   4486   return TALER_EC_NONE;
   4487 }
   4488 
   4489 
   4490 const char *
   4491 TALER_KYCLOGIC_get_aml_program_fallback (const char *prog_name)
   4492 {
   4493   struct TALER_KYCLOGIC_AmlProgram *prog;
   4494 
   4495   prog = find_program (prog_name);
   4496   if (NULL == prog)
   4497   {
   4498     GNUNET_break (0);
   4499     return NULL;
   4500   }
   4501   return prog->fallback;
   4502 }
   4503 
   4504 
   4505 const struct TALER_KYCLOGIC_KycProvider *
   4506 TALER_KYCLOGIC_check_to_provider (const char *check_name)
   4507 {
   4508   struct TALER_KYCLOGIC_KycCheck *kc;
   4509 
   4510   if (NULL == check_name)
   4511     return NULL;
   4512   if (0 == strcasecmp (check_name,
   4513                        "skip"))
   4514     return NULL;
   4515   kc = find_check (check_name);
   4516   if (NULL == kc)
   4517   {
   4518     GNUNET_break (0);
   4519     return NULL;
   4520   }
   4521   switch (kc->type)
   4522   {
   4523   case TALER_KYCLOGIC_CT_FORM:
   4524   case TALER_KYCLOGIC_CT_INFO:
   4525     return NULL;
   4526   case TALER_KYCLOGIC_CT_LINK:
   4527     break;
   4528   }
   4529   return kc->details.link.provider;
   4530 }
   4531 
   4532 
   4533 struct TALER_KYCLOGIC_AmlProgramRunnerHandle
   4534 {
   4535   /**
   4536    * Function to call back with the result.
   4537    */
   4538   TALER_KYCLOGIC_AmlProgramResultCallback aprc;
   4539 
   4540   /**
   4541    * Closure for @e aprc.
   4542    */
   4543   void *aprc_cls;
   4544 
   4545   /**
   4546    * Handle to an external process.
   4547    */
   4548   struct TALER_JSON_ExternalConversion *proc;
   4549 
   4550   /**
   4551    * AML program to turn.
   4552    */
   4553   const struct TALER_KYCLOGIC_AmlProgram *program;
   4554 
   4555   /**
   4556    * Task to return @e apr result asynchronously.
   4557    */
   4558   struct GNUNET_SCHEDULER_Task *async_cb;
   4559 
   4560   /**
   4561    * Result returned to the client.
   4562    */
   4563   struct TALER_KYCLOGIC_AmlProgramResult apr;
   4564 
   4565   /**
   4566    * How long do we allow the AML program to run?
   4567    */
   4568   struct GNUNET_TIME_Relative timeout;
   4569 
   4570 };
   4571 
   4572 
   4573 /**
   4574  * Function that that receives a JSON @a result from
   4575  * the AML program.
   4576  *
   4577  * @param cls closure of type `struct TALER_KYCLOGIC_AmlProgramRunnerHandle`
   4578  * @param status_type how did the process die
   4579  * @param code termination status code from the process,
   4580  *        non-zero if AML checks are required next
   4581  * @param result some JSON result, NULL if we failed to get an JSON output
   4582  */
   4583 static void
   4584 handle_aml_output (
   4585   void *cls,
   4586   enum GNUNET_OS_ProcessStatusType status_type,
   4587   unsigned long code,
   4588   const json_t *result)
   4589 {
   4590   struct TALER_KYCLOGIC_AmlProgramRunnerHandle *aprh = cls;
   4591   const char *fallback_measure = aprh->program->fallback;
   4592   struct TALER_KYCLOGIC_AmlProgramResult *apr = &aprh->apr;
   4593   const char **evs = NULL;
   4594 
   4595   aprh->proc = NULL;
   4596   if (NULL != aprh->async_cb)
   4597   {
   4598     GNUNET_SCHEDULER_cancel (aprh->async_cb);
   4599     aprh->async_cb = NULL;
   4600   }
   4601 #if DEBUG
   4602   GNUNET_log (GNUNET_ERROR_TYPE_INFO,
   4603               "AML program %s output is:\n",
   4604               aprh->program->program_name);
   4605   json_dumpf (result,
   4606               stderr,
   4607               JSON_INDENT (2));
   4608 #endif
   4609   memset (apr,
   4610           0,
   4611           sizeof (*apr));
   4612   if ( (GNUNET_OS_PROCESS_EXITED != status_type) ||
   4613        (0 != code) )
   4614   {
   4615     GNUNET_log (GNUNET_ERROR_TYPE_WARNING,
   4616                 "AML program %s returned non-zero status %d/%d\n",
   4617                 aprh->program->program_name,
   4618                 (int) status_type,
   4619                 (int) code);
   4620     apr->status = TALER_KYCLOGIC_AMLR_FAILURE;
   4621     apr->details.failure.fallback_measure
   4622       = fallback_measure;
   4623     apr->details.failure.error_message
   4624       = "AML program returned non-zero exit code";
   4625     apr->details.failure.ec
   4626       = TALER_EC_EXCHANGE_KYC_AML_PROGRAM_FAILURE;
   4627     goto ready;
   4628   }
   4629 
   4630   {
   4631     const json_t *jevents = NULL;
   4632     struct GNUNET_JSON_Specification spec[] = {
   4633       GNUNET_JSON_spec_mark_optional (
   4634         GNUNET_JSON_spec_bool (
   4635           "to_investigate",
   4636           &apr->details.success.to_investigate),
   4637         NULL),
   4638       GNUNET_JSON_spec_mark_optional (
   4639         GNUNET_JSON_spec_object_const (
   4640           "properties",
   4641           &apr->details.success.account_properties),
   4642         NULL),
   4643       GNUNET_JSON_spec_mark_optional (
   4644         GNUNET_JSON_spec_array_const (
   4645           "events",
   4646           &jevents),
   4647         NULL),
   4648       GNUNET_JSON_spec_object_const (
   4649         "new_rules",
   4650         &apr->details.success.new_rules),
   4651       GNUNET_JSON_spec_mark_optional (
   4652         GNUNET_JSON_spec_string (
   4653           "new_measures",
   4654           &apr->details.success.new_measures),
   4655         NULL),
   4656       GNUNET_JSON_spec_end ()
   4657     };
   4658     const char *err;
   4659     unsigned int line;
   4660 
   4661     if (GNUNET_OK !=
   4662         GNUNET_JSON_parse (result,
   4663                            spec,
   4664                            &err,
   4665                            &line))
   4666     {
   4667       GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
   4668                   "AML program output is malformed at `%s'\n",
   4669                   err);
   4670       json_dumpf (result,
   4671                   stderr,
   4672                   JSON_INDENT (2));
   4673       apr->status = TALER_KYCLOGIC_AMLR_FAILURE;
   4674       apr->details.failure.fallback_measure
   4675         = fallback_measure;
   4676       apr->details.failure.error_message
   4677         = err;
   4678       apr->details.failure.ec
   4679         = TALER_EC_EXCHANGE_KYC_AML_PROGRAM_MALFORMED_RESULT;
   4680       goto ready;
   4681     }
   4682     apr->details.success.num_events
   4683       = json_array_size (jevents);
   4684 
   4685     GNUNET_assert (((size_t) apr->details.success.num_events) ==
   4686                    json_array_size (jevents));
   4687     evs = GNUNET_new_array (
   4688       apr->details.success.num_events,
   4689       const char *);
   4690     for (unsigned int i = 0; i<apr->details.success.num_events; i++)
   4691     {
   4692       evs[i] = json_string_value (
   4693         json_array_get (jevents,
   4694                         i));
   4695       if (NULL == evs[i])
   4696       {
   4697         apr->status = TALER_KYCLOGIC_AMLR_FAILURE;
   4698         apr->details.failure.fallback_measure
   4699           = fallback_measure;
   4700         apr->details.failure.error_message
   4701           = "events";
   4702         apr->details.failure.ec
   4703           = TALER_EC_EXCHANGE_KYC_AML_PROGRAM_MALFORMED_RESULT;
   4704         goto ready;
   4705       }
   4706     }
   4707     apr->status = TALER_KYCLOGIC_AMLR_SUCCESS;
   4708     apr->details.success.events = evs;
   4709     {
   4710       /* check new_rules */
   4711       struct TALER_KYCLOGIC_LegitimizationRuleSet *lrs;
   4712 
   4713       lrs = TALER_KYCLOGIC_rules_parse (
   4714         apr->details.success.new_rules);
   4715       if (NULL == lrs)
   4716       {
   4717         GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
   4718                     "AML program output is malformed at `%s'\n",
   4719                     "new_rules");
   4720 
   4721         apr->status = TALER_KYCLOGIC_AMLR_FAILURE;
   4722         apr->details.failure.fallback_measure
   4723           = fallback_measure;
   4724         apr->details.failure.error_message
   4725           = "new_rules";
   4726         apr->details.failure.ec
   4727           = TALER_EC_EXCHANGE_KYC_AML_PROGRAM_MALFORMED_RESULT;
   4728         goto ready;
   4729       }
   4730       apr->details.success.expiration_time
   4731         = lrs->expiration_time;
   4732       TALER_KYCLOGIC_rules_free (lrs);
   4733     }
   4734   }
   4735 ready:
   4736   aprh->aprc (aprh->aprc_cls,
   4737               &aprh->apr);
   4738   GNUNET_free (evs);
   4739   TALER_KYCLOGIC_run_aml_program_cancel (aprh);
   4740 }
   4741 
   4742 
   4743 /**
   4744  * Helper function to asynchronously return the result.
   4745  *
   4746  * @param[in] cls a `struct TALER_KYCLOGIC_AmlProgramRunnerHandle` to return results for
   4747  */
   4748 static void
   4749 async_return_task (void *cls)
   4750 {
   4751   struct TALER_KYCLOGIC_AmlProgramRunnerHandle *aprh = cls;
   4752 
   4753   aprh->async_cb = NULL;
   4754   aprh->aprc (aprh->aprc_cls,
   4755               &aprh->apr);
   4756   TALER_KYCLOGIC_run_aml_program_cancel (aprh);
   4757 }
   4758 
   4759 
   4760 /**
   4761  * Helper function called on timeout on the fallback measure.
   4762  *
   4763  * @param[in] cls a `struct TALER_KYCLOGIC_AmlProgramRunnerHandle` to return results for
   4764  */
   4765 static void
   4766 handle_aml_timeout2 (void *cls)
   4767 {
   4768   struct TALER_KYCLOGIC_AmlProgramRunnerHandle *aprh = cls;
   4769   struct TALER_KYCLOGIC_AmlProgramResult *apr = &aprh->apr;
   4770   const char *fallback_measure = aprh->program->fallback;
   4771 
   4772   GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
   4773               "Fallback measure %s ran into timeout (!)\n",
   4774               aprh->program->program_name);
   4775   if (NULL != aprh->proc)
   4776   {
   4777     TALER_JSON_external_conversion_stop (aprh->proc);
   4778     aprh->proc = NULL;
   4779   }
   4780   apr->status = TALER_KYCLOGIC_AMLR_FAILURE;
   4781   apr->details.failure.fallback_measure
   4782     = fallback_measure;
   4783   apr->details.failure.error_message
   4784     = aprh->program->program_name;
   4785   apr->details.failure.ec
   4786     = TALER_EC_EXCHANGE_KYC_GENERIC_AML_PROGRAM_TIMEOUT;
   4787   async_return_task (aprh);
   4788 }
   4789 
   4790 
   4791 /**
   4792  * Helper function called on timeout of an AML program.
   4793  * Runs the fallback measure.
   4794  *
   4795  * @param[in] cls a `struct TALER_KYCLOGIC_AmlProgramRunnerHandle` to return results for
   4796  */
   4797 static void
   4798 handle_aml_timeout (void *cls)
   4799 {
   4800   struct TALER_KYCLOGIC_AmlProgramRunnerHandle *aprh = cls;
   4801   struct TALER_KYCLOGIC_AmlProgramResult *apr = &aprh->apr;
   4802   const char *fallback_measure = aprh->program->fallback;
   4803   const struct TALER_KYCLOGIC_Measure *m;
   4804   const struct TALER_KYCLOGIC_AmlProgram *fprogram;
   4805 
   4806   aprh->async_cb = NULL;
   4807   GNUNET_assert (NULL != fallback_measure);
   4808   GNUNET_log (GNUNET_ERROR_TYPE_WARNING,
   4809               "AML program %s ran into timeout\n",
   4810               aprh->program->program_name);
   4811   if (NULL != aprh->proc)
   4812   {
   4813     TALER_JSON_external_conversion_stop (aprh->proc);
   4814     aprh->proc = NULL;
   4815   }
   4816 
   4817   m = TALER_KYCLOGIC_get_measure (&default_rules,
   4818                                   fallback_measure);
   4819   /* Fallback program could have "disappeared" due to configuration change,
   4820      as we do not check all rule sets in the database when our configuration
   4821      is updated... */
   4822   if (NULL == m)
   4823   {
   4824     GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
   4825                 "Fallback measure `%s' does not exist (anymore?).\n",
   4826                 fallback_measure);
   4827     apr->status = TALER_KYCLOGIC_AMLR_FAILURE;
   4828     apr->details.failure.fallback_measure
   4829       = fallback_measure;
   4830     apr->details.failure.error_message
   4831       = aprh->program->program_name;
   4832     apr->details.failure.ec
   4833       = TALER_EC_EXCHANGE_KYC_GENERIC_AML_PROGRAM_TIMEOUT;
   4834     async_return_task (aprh);
   4835     return;
   4836   }
   4837   /* We require fallback measures to have a 'skip' check */
   4838   GNUNET_break (0 ==
   4839                 strcasecmp (m->check_name,
   4840                             "skip"));
   4841   fprogram = find_program (m->prog_name);
   4842   /* Program associated with an original measure must exist */
   4843   GNUNET_assert (NULL != fprogram);
   4844   if (API_NONE != (fprogram->input_mask & (API_CONTEXT | API_ATTRIBUTES)))
   4845   {
   4846     /* We might not have recognized the fallback measure as such
   4847        because it was not used as such in the plain configuration,
   4848        and legitimization rule sets might have referred to an older
   4849        configuration. So this should be super-rare but possible. */
   4850     GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
   4851                 "Program `%s' used in fallback measure `%s' requires inputs and is thus unsuitable as a fallback measure!\n",
   4852                 m->prog_name,
   4853                 fallback_measure);
   4854     apr->status = TALER_KYCLOGIC_AMLR_FAILURE;
   4855     apr->details.failure.fallback_measure
   4856       = fallback_measure;
   4857     apr->details.failure.error_message
   4858       = aprh->program->program_name;
   4859     apr->details.failure.ec
   4860       = TALER_EC_EXCHANGE_KYC_GENERIC_AML_PROGRAM_TIMEOUT;
   4861     async_return_task (aprh);
   4862     return;
   4863   }
   4864   {
   4865     /* Run fallback AML program */
   4866     json_t *input = json_object ();
   4867     const char *extra_args[] = {
   4868       "-c",
   4869       cfg_filename,
   4870       NULL,
   4871     };
   4872     char **args;
   4873 
   4874     args = TALER_words_split (fprogram->command,
   4875                               extra_args);
   4876     GNUNET_log (GNUNET_ERROR_TYPE_INFO,
   4877                 "Running fallback measure `%s' (%s)\n",
   4878                 fallback_measure,
   4879                 fprogram->command);
   4880     aprh->proc = TALER_JSON_external_conversion_start (
   4881       input,
   4882       &handle_aml_output,
   4883       aprh,
   4884       args[0],
   4885       (const char **) args);
   4886     TALER_words_destroy (args);
   4887     json_decref (input);
   4888   }
   4889   aprh->async_cb = GNUNET_SCHEDULER_add_delayed (aprh->timeout,
   4890                                                  &handle_aml_timeout2,
   4891                                                  aprh);
   4892 }
   4893 
   4894 
   4895 struct TALER_KYCLOGIC_AmlProgramRunnerHandle *
   4896 TALER_KYCLOGIC_run_aml_program (
   4897   const json_t *jmeasures,
   4898   bool is_wallet,
   4899   unsigned int measure_index,
   4900   TALER_KYCLOGIC_HistoryBuilderCallback current_attributes_cb,
   4901   void *current_attributes_cb_cls,
   4902   TALER_KYCLOGIC_HistoryBuilderCallback current_rules_cb,
   4903   void *current_rules_cb_cls,
   4904   TALER_KYCLOGIC_HistoryBuilderCallback aml_history_cb,
   4905   void *aml_history_cb_cls,
   4906   TALER_KYCLOGIC_HistoryBuilderCallback kyc_history_cb,
   4907   void *kyc_history_cb_cls,
   4908   struct GNUNET_TIME_Relative timeout,
   4909   TALER_KYCLOGIC_AmlProgramResultCallback aprc,
   4910   void *aprc_cls)
   4911 {
   4912   const json_t *context;
   4913   const char *check_name;
   4914   const char *prog_name;
   4915 
   4916   {
   4917     enum TALER_ErrorCode ec;
   4918 
   4919     ec = TALER_KYCLOGIC_select_measure (jmeasures,
   4920                                         measure_index,
   4921                                         &check_name,
   4922                                         &prog_name,
   4923                                         &context);
   4924     if (TALER_EC_NONE != ec)
   4925     {
   4926       GNUNET_break (0);
   4927       return NULL;
   4928     }
   4929   }
   4930   if (NULL == prog_name)
   4931   {
   4932     /* Trying to run AML program on a measure that does not
   4933        have one, and that should thus be an INFO check which
   4934        should never lead here. Very strange. */
   4935     GNUNET_break (0);
   4936     GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
   4937                 "Measure %u with check `%s' does not have an AML program!\n",
   4938                 measure_index,
   4939                 check_name);
   4940     json_dumpf (jmeasures,
   4941                 stderr,
   4942                 JSON_INDENT (2));
   4943     return NULL;
   4944   }
   4945   return TALER_KYCLOGIC_run_aml_program2 (prog_name,
   4946                                           context,
   4947                                           is_wallet,
   4948                                           current_attributes_cb,
   4949                                           current_attributes_cb_cls,
   4950                                           current_rules_cb,
   4951                                           current_rules_cb_cls,
   4952                                           aml_history_cb,
   4953                                           aml_history_cb_cls,
   4954                                           kyc_history_cb,
   4955                                           kyc_history_cb_cls,
   4956                                           timeout,
   4957                                           aprc,
   4958                                           aprc_cls);
   4959 }
   4960 
   4961 
   4962 struct TALER_KYCLOGIC_AmlProgramRunnerHandle *
   4963 TALER_KYCLOGIC_run_aml_program2 (
   4964   const char *prog_name,
   4965   const json_t *context,
   4966   bool is_wallet,
   4967   TALER_KYCLOGIC_HistoryBuilderCallback current_attributes_cb,
   4968   void *current_attributes_cb_cls,
   4969   TALER_KYCLOGIC_HistoryBuilderCallback current_rules_cb,
   4970   void *current_rules_cb_cls,
   4971   TALER_KYCLOGIC_HistoryBuilderCallback aml_history_cb,
   4972   void *aml_history_cb_cls,
   4973   TALER_KYCLOGIC_HistoryBuilderCallback kyc_history_cb,
   4974   void *kyc_history_cb_cls,
   4975   struct GNUNET_TIME_Relative timeout,
   4976   TALER_KYCLOGIC_AmlProgramResultCallback aprc,
   4977   void *aprc_cls)
   4978 {
   4979   struct TALER_KYCLOGIC_AmlProgramRunnerHandle *aprh;
   4980   struct TALER_KYCLOGIC_AmlProgram *prog;
   4981   const json_t *jdefault_rules;
   4982   json_t *current_rules;
   4983   json_t *aml_history;
   4984   json_t *kyc_history;
   4985   json_t *attributes;
   4986 
   4987   prog = find_program (prog_name);
   4988   if (NULL == prog)
   4989   {
   4990     GNUNET_break (0);
   4991     return NULL;
   4992   }
   4993   aprh = GNUNET_new (struct TALER_KYCLOGIC_AmlProgramRunnerHandle);
   4994   aprh->aprc = aprc;
   4995   aprh->aprc_cls = aprc_cls;
   4996   aprh->program = prog;
   4997   if (0 != (API_ATTRIBUTES & prog->input_mask))
   4998   {
   4999     attributes = current_attributes_cb (current_attributes_cb_cls);
   5000 #if DEBUG
   5001     GNUNET_log (GNUNET_ERROR_TYPE_INFO,
   5002                 "KYC attributes for AML program %s are:\n",
   5003                 prog_name);
   5004     json_dumpf (attributes,
   5005                 stderr,
   5006                 JSON_INDENT (2));
   5007     fprintf (stderr,
   5008              "\n");
   5009 #endif
   5010     for (unsigned int i = 0; i<prog->num_required_attributes; i++)
   5011     {
   5012       const char *rattr = prog->required_attributes[i];
   5013 
   5014       if (NULL == json_object_get (attributes,
   5015                                    rattr))
   5016       {
   5017         GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
   5018                     "KYC attributes lack required attribute `%s' for AML program %s\n",
   5019                     rattr,
   5020                     prog->program_name);
   5021 #if DEBUG
   5022         json_dumpf (attributes,
   5023                     stderr,
   5024                     JSON_INDENT (2));
   5025 #endif
   5026         aprh->apr.status = TALER_KYCLOGIC_AMLR_FAILURE;
   5027         aprh->apr.details.failure.fallback_measure
   5028           = prog->fallback;
   5029         aprh->apr.details.failure.error_message
   5030           = rattr;
   5031         aprh->apr.details.failure.ec
   5032           = TALER_EC_EXCHANGE_KYC_GENERIC_PROVIDER_INCOMPLETE_REPLY;
   5033         aprh->async_cb
   5034           = GNUNET_SCHEDULER_add_now (&async_return_task,
   5035                                       aprh);
   5036         json_decref (attributes);
   5037         return aprh;
   5038       }
   5039     }
   5040   }
   5041   else
   5042   {
   5043     attributes = NULL;
   5044   }
   5045   if (0 != (API_CONTEXT & prog->input_mask))
   5046   {
   5047     for (unsigned int i = 0; i<prog->num_required_contexts; i++)
   5048     {
   5049       const char *rctx = prog->required_contexts[i];
   5050 
   5051       if (NULL == json_object_get (context,
   5052                                    rctx))
   5053       {
   5054         GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
   5055                     "Context lacks required field `%s' for AML program %s\n",
   5056                     rctx,
   5057                     prog->program_name);
   5058 #if DEBUG
   5059         json_dumpf (context,
   5060                     stderr,
   5061                     JSON_INDENT (2));
   5062 #endif
   5063         aprh->apr.status = TALER_KYCLOGIC_AMLR_FAILURE;
   5064         aprh->apr.details.failure.fallback_measure
   5065           = prog->fallback;
   5066         aprh->apr.details.failure.error_message
   5067           = rctx;
   5068         aprh->apr.details.failure.ec
   5069           = TALER_EC_EXCHANGE_KYC_GENERIC_PROVIDER_INCOMPLETE_CONTEXT;
   5070         aprh->async_cb
   5071           = GNUNET_SCHEDULER_add_now (&async_return_task,
   5072                                       aprh);
   5073         json_decref (attributes);
   5074         return aprh;
   5075       }
   5076     }
   5077   }
   5078   else
   5079   {
   5080     context = NULL;
   5081   }
   5082   if (0 == (API_AML_HISTORY & prog->input_mask))
   5083     aml_history = NULL;
   5084   else
   5085     aml_history = aml_history_cb (aml_history_cb_cls);
   5086   if (0 == (API_KYC_HISTORY & prog->input_mask))
   5087     kyc_history = NULL;
   5088   else
   5089     kyc_history = kyc_history_cb (kyc_history_cb_cls);
   5090   if (0 == (API_CURRENT_RULES & prog->input_mask))
   5091     current_rules = NULL;
   5092   else
   5093     current_rules = current_rules_cb (current_rules_cb_cls);
   5094   if (0 != (API_DEFAULT_RULES & prog->input_mask))
   5095     jdefault_rules =
   5096       (is_wallet
   5097        ? wallet_default_lrs
   5098        : bankaccount_default_lrs);
   5099   else
   5100     jdefault_rules = NULL;
   5101   {
   5102     json_t *input;
   5103     const char *extra_args[] = {
   5104       "-c",
   5105       cfg_filename,
   5106       NULL,
   5107     };
   5108     char **args;
   5109 
   5110     input = GNUNET_JSON_PACK (
   5111       GNUNET_JSON_pack_allow_null (
   5112         GNUNET_JSON_pack_object_steal ("current_rules",
   5113                                        current_rules)),
   5114       GNUNET_JSON_pack_allow_null (
   5115         GNUNET_JSON_pack_object_incref ("default_rules",
   5116                                         (json_t *) jdefault_rules)),
   5117       GNUNET_JSON_pack_allow_null (
   5118         GNUNET_JSON_pack_object_incref ("context",
   5119                                         (json_t *) context)),
   5120       GNUNET_JSON_pack_allow_null (
   5121         GNUNET_JSON_pack_object_steal ("attributes",
   5122                                        attributes)),
   5123       GNUNET_JSON_pack_allow_null (
   5124         GNUNET_JSON_pack_array_steal ("aml_history",
   5125                                       aml_history)),
   5126       GNUNET_JSON_pack_allow_null (
   5127         GNUNET_JSON_pack_array_steal ("kyc_history",
   5128                                       kyc_history))
   5129       );
   5130     GNUNET_log (GNUNET_ERROR_TYPE_INFO,
   5131                 "Running AML program %s\n",
   5132                 prog->command);
   5133     args = TALER_words_split (prog->command,
   5134                               extra_args);
   5135     GNUNET_assert (NULL != args);
   5136     GNUNET_assert (NULL != args[0]);
   5137 #if DEBUG
   5138     json_dumpf (input,
   5139                 stderr,
   5140                 JSON_INDENT (2));
   5141 #endif
   5142     aprh->proc = TALER_JSON_external_conversion_start (
   5143       input,
   5144       &handle_aml_output,
   5145       aprh,
   5146       args[0],
   5147       (const char **) args);
   5148     TALER_words_destroy (args);
   5149     json_decref (input);
   5150   }
   5151   aprh->timeout = timeout;
   5152   aprh->async_cb = GNUNET_SCHEDULER_add_delayed (timeout,
   5153                                                  &handle_aml_timeout,
   5154                                                  aprh);
   5155   return aprh;
   5156 }
   5157 
   5158 
   5159 struct TALER_KYCLOGIC_AmlProgramRunnerHandle *
   5160 TALER_KYCLOGIC_run_aml_program3 (
   5161   bool is_wallet,
   5162   const struct TALER_KYCLOGIC_Measure *measure,
   5163   TALER_KYCLOGIC_HistoryBuilderCallback current_attributes_cb,
   5164   void *current_attributes_cb_cls,
   5165   TALER_KYCLOGIC_HistoryBuilderCallback current_rules_cb,
   5166   void *current_rules_cb_cls,
   5167   TALER_KYCLOGIC_HistoryBuilderCallback aml_history_cb,
   5168   void *aml_history_cb_cls,
   5169   TALER_KYCLOGIC_HistoryBuilderCallback kyc_history_cb,
   5170   void *kyc_history_cb_cls,
   5171   struct GNUNET_TIME_Relative timeout,
   5172   TALER_KYCLOGIC_AmlProgramResultCallback aprc,
   5173   void *aprc_cls)
   5174 {
   5175   return TALER_KYCLOGIC_run_aml_program2 (
   5176     measure->prog_name,
   5177     measure->context,
   5178     is_wallet,
   5179     current_attributes_cb,
   5180     current_attributes_cb_cls,
   5181     current_rules_cb,
   5182     current_rules_cb_cls,
   5183     aml_history_cb,
   5184     aml_history_cb_cls,
   5185     kyc_history_cb,
   5186     kyc_history_cb_cls,
   5187     timeout,
   5188     aprc,
   5189     aprc_cls);
   5190 }
   5191 
   5192 
   5193 const char *
   5194 TALER_KYCLOGIC_run_aml_program_get_name (
   5195   const struct TALER_KYCLOGIC_AmlProgramRunnerHandle *aprh)
   5196 {
   5197   return aprh->program->program_name;
   5198 }
   5199 
   5200 
   5201 void
   5202 TALER_KYCLOGIC_run_aml_program_cancel (
   5203   struct TALER_KYCLOGIC_AmlProgramRunnerHandle *aprh)
   5204 {
   5205   if (NULL != aprh->proc)
   5206   {
   5207     GNUNET_log (GNUNET_ERROR_TYPE_WARNING,
   5208                 "Killing AML program\n");
   5209     TALER_JSON_external_conversion_stop (aprh->proc);
   5210     aprh->proc = NULL;
   5211   }
   5212   if (NULL != aprh->async_cb)
   5213   {
   5214     GNUNET_SCHEDULER_cancel (aprh->async_cb);
   5215     aprh->async_cb = NULL;
   5216   }
   5217   GNUNET_free (aprh);
   5218 }
   5219 
   5220 
   5221 json_t *
   5222 TALER_KYCLOGIC_get_hard_limits ()
   5223 {
   5224   const struct TALER_KYCLOGIC_KycRule *rules
   5225     = default_rules.kyc_rules;
   5226   unsigned int num_rules
   5227     = default_rules.num_kyc_rules;
   5228   json_t *hard_limits;
   5229 
   5230   hard_limits = json_array ();
   5231   GNUNET_assert (NULL != hard_limits);
   5232   for (unsigned int i = 0; i<num_rules; i++)
   5233   {
   5234     const struct TALER_KYCLOGIC_KycRule *rule = &rules[i];
   5235     json_t *hard_limit;
   5236 
   5237     if (! rule->verboten)
   5238       continue;
   5239     if (! rule->exposed)
   5240       continue;
   5241     hard_limit = GNUNET_JSON_PACK (
   5242       GNUNET_JSON_pack_allow_null (
   5243         GNUNET_JSON_pack_string ("rule_name",
   5244                                  rule->rule_name)),
   5245       TALER_JSON_pack_kycte ("operation_type",
   5246                              rule->trigger),
   5247       GNUNET_JSON_pack_time_rel ("timeframe",
   5248                                  rule->timeframe),
   5249       TALER_JSON_pack_amount ("threshold",
   5250                               &rule->threshold)
   5251       );
   5252     GNUNET_assert (0 ==
   5253                    json_array_append_new (hard_limits,
   5254                                           hard_limit));
   5255   }
   5256   return hard_limits;
   5257 }
   5258 
   5259 
   5260 json_t *
   5261 TALER_KYCLOGIC_get_zero_limits ()
   5262 {
   5263   const struct TALER_KYCLOGIC_KycRule *rules
   5264     = default_rules.kyc_rules;
   5265   unsigned int num_rules
   5266     = default_rules.num_kyc_rules;
   5267   json_t *zero_limits;
   5268 
   5269   zero_limits = json_array ();
   5270   GNUNET_assert (NULL != zero_limits);
   5271   for (unsigned int i = 0; i<num_rules; i++)
   5272   {
   5273     const struct TALER_KYCLOGIC_KycRule *rule = &rules[i];
   5274     json_t *zero_limit;
   5275 
   5276     if (! rule->exposed)
   5277       continue;
   5278     if (rule->verboten)
   5279       continue; /* see: hard_limits */
   5280     if (! TALER_amount_is_zero (&rule->threshold))
   5281       continue;
   5282     zero_limit = GNUNET_JSON_PACK (
   5283       GNUNET_JSON_pack_allow_null (
   5284         GNUNET_JSON_pack_string ("rule_name",
   5285                                  rule->rule_name)),
   5286       TALER_JSON_pack_kycte ("operation_type",
   5287                              rule->trigger));
   5288     GNUNET_assert (0 ==
   5289                    json_array_append_new (zero_limits,
   5290                                           zero_limit));
   5291   }
   5292   return zero_limits;
   5293 }
   5294 
   5295 
   5296 json_t *
   5297 TALER_KYCLOGIC_get_default_legi_rules (bool for_wallet)
   5298 {
   5299   const json_t *r;
   5300 
   5301   r = (for_wallet
   5302        ? wallet_default_lrs
   5303        : bankaccount_default_lrs);
   5304   return json_incref ((json_t *) r);
   5305 }
   5306 
   5307 
   5308 /* end of kyclogic_api.c */