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 (147751B)


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