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


      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   {
   2566     enum GNUNET_GenericReturnValue r;
   2567 
   2568     r = GNUNET_CONFIGURATION_get_value_yesno (cfg,
   2569                                               section,
   2570                                               "ENABLED");
   2571     if ( (GNUNET_SYSERR == r) &&
   2572          (GNUNET_YES ==
   2573           GNUNET_CONFIGURATION_have_value (cfg,
   2574                                            section,
   2575                                            "ENABLED")) )
   2576     {
   2577       GNUNET_log_config_invalid (GNUNET_ERROR_TYPE_ERROR,
   2578                                  section,
   2579                                  "ENABLED",
   2580                                  "YES or NO required");
   2581       return GNUNET_SYSERR;
   2582     }
   2583     if (GNUNET_YES != r)
   2584       return GNUNET_OK;
   2585   }
   2586   if (GNUNET_OK !=
   2587       TALER_config_get_amount (cfg,
   2588                                section,
   2589                                "THRESHOLD",
   2590                                &threshold))
   2591   {
   2592     GNUNET_log_config_invalid (GNUNET_ERROR_TYPE_ERROR,
   2593                                section,
   2594                                "THRESHOLD",
   2595                                "amount required");
   2596     return GNUNET_SYSERR;
   2597   }
   2598   if (0 !=
   2599       strcasecmp (threshold.currency,
   2600                   my_currency))
   2601   {
   2602     GNUNET_log_config_invalid (GNUNET_ERROR_TYPE_ERROR,
   2603                                section,
   2604                                "THRESHOLD",
   2605                                "currency mismatch");
   2606     return GNUNET_SYSERR;
   2607   }
   2608   {
   2609     enum GNUNET_GenericReturnValue r;
   2610 
   2611     r = GNUNET_CONFIGURATION_get_value_yesno (cfg,
   2612                                               section,
   2613                                               "EXPOSED");
   2614     if ( (GNUNET_SYSERR == r) &&
   2615          (GNUNET_YES ==
   2616           GNUNET_CONFIGURATION_have_value (cfg,
   2617                                            section,
   2618                                            "EXPOSED")) )
   2619     {
   2620       GNUNET_log_config_invalid (GNUNET_ERROR_TYPE_ERROR,
   2621                                  section,
   2622                                  "EXPOSED",
   2623                                  "YES or NO required");
   2624       return GNUNET_SYSERR;
   2625     }
   2626     exposed = (GNUNET_YES == r);
   2627   }
   2628   {
   2629     enum GNUNET_GenericReturnValue r;
   2630 
   2631     r = GNUNET_CONFIGURATION_get_value_yesno (cfg,
   2632                                               section,
   2633                                               "IS_AND_COMBINATOR");
   2634     if (GNUNET_SYSERR == r)
   2635     {
   2636       GNUNET_log_config_invalid (GNUNET_ERROR_TYPE_ERROR,
   2637                                  section,
   2638                                  "IS_AND_COMBINATOR",
   2639                                  "YES or NO required");
   2640       return GNUNET_SYSERR;
   2641     }
   2642     is_and = (GNUNET_YES == r);
   2643   }
   2644 
   2645   {
   2646     char *ot_s;
   2647 
   2648     if (GNUNET_OK !=
   2649         GNUNET_CONFIGURATION_get_value_string (cfg,
   2650                                                section,
   2651                                                "OPERATION_TYPE",
   2652                                                &ot_s))
   2653     {
   2654       GNUNET_log_config_missing (GNUNET_ERROR_TYPE_ERROR,
   2655                                  section,
   2656                                  "OPERATION_TYPE");
   2657       return GNUNET_SYSERR;
   2658     }
   2659     if (GNUNET_OK !=
   2660         TALER_KYCLOGIC_kyc_trigger_from_string (ot_s,
   2661                                                 &ot))
   2662     {
   2663       GNUNET_log_config_invalid (GNUNET_ERROR_TYPE_ERROR,
   2664                                  section,
   2665                                  "OPERATION_TYPE",
   2666                                  "valid trigger type required");
   2667       GNUNET_free (ot_s);
   2668       return GNUNET_SYSERR;
   2669     }
   2670     GNUNET_free (ot_s);
   2671   }
   2672 
   2673   if (GNUNET_OK !=
   2674       GNUNET_CONFIGURATION_get_value_time (cfg,
   2675                                            section,
   2676                                            "TIMEFRAME",
   2677                                            &timeframe))
   2678   {
   2679     if (TALER_KYCLOGIC_KYC_TRIGGER_WALLET_BALANCE == ot)
   2680     {
   2681       timeframe = GNUNET_TIME_UNIT_ZERO;
   2682     }
   2683     else
   2684     {
   2685       GNUNET_log_config_invalid (GNUNET_ERROR_TYPE_ERROR,
   2686                                  section,
   2687                                  "TIMEFRAME",
   2688                                  "duration required");
   2689       return GNUNET_SYSERR;
   2690     }
   2691   }
   2692   if (GNUNET_OK !=
   2693       GNUNET_CONFIGURATION_get_value_string (cfg,
   2694                                              section,
   2695                                              "NEXT_MEASURES",
   2696                                              &measures))
   2697   {
   2698     GNUNET_log_config_missing (GNUNET_ERROR_TYPE_ERROR,
   2699                                section,
   2700                                "NEXT_MEASURES");
   2701     return GNUNET_SYSERR;
   2702   }
   2703   if (! token_list_lower (measures))
   2704   {
   2705     GNUNET_log_config_invalid (GNUNET_ERROR_TYPE_ERROR,
   2706                                section,
   2707                                "NEXT_MEASURES",
   2708                                "Only [a-zA-Z0-9 _-] are allowed");
   2709     GNUNET_free (measures);
   2710     return GNUNET_SYSERR;
   2711   }
   2712 
   2713   GNUNET_log (GNUNET_ERROR_TYPE_INFO,
   2714               "Adding KYC rule %s for trigger %d with threshold %s\n",
   2715               section,
   2716               (int) ot,
   2717               TALER_amount2s (&threshold));
   2718   {
   2719     struct TALER_KYCLOGIC_KycRule kt = {
   2720       .lrs = &default_rules,
   2721       .rule_name = GNUNET_strdup (&section[strlen ("kyc-rule-")]),
   2722       .timeframe = timeframe,
   2723       .threshold = threshold,
   2724       .trigger = ot,
   2725       .is_and_combinator = is_and,
   2726       .exposed = exposed,
   2727       .display_priority = 0,
   2728       .verboten = false
   2729     };
   2730 
   2731     add_tokens (measures,
   2732                 "; \n\t",
   2733                 &kt.next_measures,
   2734                 &kt.num_measures);
   2735     for (unsigned int i=0; i<kt.num_measures; i++)
   2736       if (0 == strcasecmp (KYC_MEASURE_IMPOSSIBLE,
   2737                            kt.next_measures[i]))
   2738         kt.verboten = true;
   2739     GNUNET_free (measures);
   2740     GNUNET_array_append (default_rules.kyc_rules,
   2741                          default_rules.num_kyc_rules,
   2742                          kt);
   2743   }
   2744   return GNUNET_OK;
   2745 }
   2746 
   2747 
   2748 /**
   2749  * Function to iterate over configuration sections.
   2750  *
   2751  * @param cls a `struct SectionContext *`
   2752  * @param section name of the section
   2753  */
   2754 static void
   2755 handle_rule_section (void *cls,
   2756                      const char *section)
   2757 {
   2758   struct SectionContext *sc = cls;
   2759   char *s;
   2760 
   2761   if (! sc->result)
   2762     return;
   2763   s = normalize_section_with_prefix ("kyc-rule-",
   2764                                      section);
   2765   if (NULL == s)
   2766     return;
   2767   if (GNUNET_OK !=
   2768       add_rule (sc->cfg,
   2769                 s))
   2770     sc->result = false;
   2771   GNUNET_free (s);
   2772 }
   2773 
   2774 
   2775 /**
   2776  * Parse array dimension argument of @a tok (if present)
   2777  * and store result in @a dimp. Does nothing if
   2778  * @a tok does not contain '['. Otherwise does some input
   2779  * validation.
   2780  *
   2781  * @param section name of configuration section for logging
   2782  * @param tok input to parse, of form "text[$DIM]"
   2783  * @param[out] dimp set to value of $DIM
   2784  * @return true on success
   2785  */
   2786 static bool
   2787 parse_dim (const char *section,
   2788            const char *tok,
   2789            long long *dimp)
   2790 {
   2791   const char *dim = strchr (tok,
   2792                             '[');
   2793   char dummy;
   2794 
   2795   if (NULL == dim)
   2796     return true;
   2797   if (1 !=
   2798       sscanf (dim,
   2799               "[%lld]%c",
   2800               dimp,
   2801               &dummy))
   2802   {
   2803     GNUNET_log_config_invalid (GNUNET_ERROR_TYPE_ERROR,
   2804                                section,
   2805                                "COMMAND",
   2806                                "output for -i invalid (bad dimension given)");
   2807     return false;
   2808   }
   2809   return true;
   2810 }
   2811 
   2812 
   2813 /**
   2814  * Parse configuration @a cfg in section @a section for
   2815  * the specification of an AML program.
   2816  *
   2817  * @param cfg configuration to parse
   2818  * @param section configuration section to parse
   2819  * @return #GNUNET_OK on success
   2820  */
   2821 static enum GNUNET_GenericReturnValue
   2822 add_program (const struct GNUNET_CONFIGURATION_Handle *cfg,
   2823              const char *section)
   2824 {
   2825   char *command = NULL;
   2826   char *description = NULL;
   2827   char *fallback = NULL;
   2828   char *required_contexts = NULL;
   2829   char *required_attributes = NULL;
   2830   char *required_inputs = NULL;
   2831   enum AmlProgramInputs input_mask = API_NONE;
   2832   long long aml_history_length_limit = INT64_MAX;
   2833   long long kyc_history_length_limit = INT64_MAX;
   2834 
   2835   GNUNET_log (GNUNET_ERROR_TYPE_INFO,
   2836               "Parsing KYC program %s\n",
   2837               section);
   2838   if (GNUNET_OK !=
   2839       GNUNET_CONFIGURATION_get_value_string (cfg,
   2840                                              section,
   2841                                              "COMMAND",
   2842                                              &command))
   2843   {
   2844     GNUNET_log_config_invalid (GNUNET_ERROR_TYPE_ERROR,
   2845                                section,
   2846                                "COMMAND",
   2847                                "command required");
   2848     goto fail;
   2849   }
   2850   if (GNUNET_OK !=
   2851       GNUNET_CONFIGURATION_get_value_string (cfg,
   2852                                              section,
   2853                                              "DESCRIPTION",
   2854                                              &description))
   2855   {
   2856     GNUNET_log_config_invalid (GNUNET_ERROR_TYPE_ERROR,
   2857                                section,
   2858                                "DESCRIPTION",
   2859                                "description required");
   2860     goto fail;
   2861   }
   2862   if (GNUNET_OK !=
   2863       GNUNET_CONFIGURATION_get_value_string (cfg,
   2864                                              section,
   2865                                              "FALLBACK",
   2866                                              &fallback))
   2867   {
   2868     /* We do *not* allow NULL to fall back to default rules because fallbacks
   2869        are used when there is actually a serious error and thus some action
   2870        (usually an investigation) is always in order, and that's basically
   2871        never the default. And as fallbacks should be rare, we really insist on
   2872        them at least being explicitly configured. Otherwise these errors may
   2873        go undetected simply because someone forgot to configure a fallback and
   2874        then nothing happens. */
   2875     GNUNET_log_config_invalid (GNUNET_ERROR_TYPE_ERROR,
   2876                                section,
   2877                                "FALLBACK",
   2878                                "fallback measure name required");
   2879     goto fail;
   2880   }
   2881 
   2882   required_contexts = command_output (command,
   2883                                       "-r");
   2884   if (NULL == required_contexts)
   2885   {
   2886     GNUNET_log_config_invalid (GNUNET_ERROR_TYPE_ERROR,
   2887                                section,
   2888                                "COMMAND",
   2889                                "output for -r invalid");
   2890     goto fail;
   2891   }
   2892 
   2893   required_attributes = command_output (command,
   2894                                         "-a");
   2895   if (NULL == required_attributes)
   2896   {
   2897     GNUNET_log_config_invalid (GNUNET_ERROR_TYPE_ERROR,
   2898                                section,
   2899                                "COMMAND",
   2900                                "output for -a invalid");
   2901     goto fail;
   2902   }
   2903 
   2904   required_inputs = command_output (command,
   2905                                     "-i");
   2906   if (NULL == required_inputs)
   2907   {
   2908     GNUNET_log_config_invalid (GNUNET_ERROR_TYPE_ERROR,
   2909                                section,
   2910                                "COMMAND",
   2911                                "output for -i invalid");
   2912     goto fail;
   2913   }
   2914 
   2915   {
   2916     char *sptr;
   2917 
   2918     for (char *tok = strtok_r (required_inputs,
   2919                                ";\n \t",
   2920                                &sptr);
   2921          NULL != tok;
   2922          tok = strtok_r (NULL,
   2923                          ";\n \t",
   2924                          &sptr) )
   2925     {
   2926       if (0 == strcasecmp (tok,
   2927                            "context"))
   2928         input_mask |= API_CONTEXT;
   2929       else if (0 == strcasecmp (tok,
   2930                                 "attributes"))
   2931         input_mask |= API_ATTRIBUTES;
   2932       else if (0 == strcasecmp (tok,
   2933                                 "current_rules"))
   2934         input_mask |= API_CURRENT_RULES;
   2935       else if (0 == strcasecmp (tok,
   2936                                 "default_rules"))
   2937         input_mask |= API_DEFAULT_RULES;
   2938       else if (0 == strncasecmp (tok,
   2939                                  "aml_history",
   2940                                  strlen ("aml_history")))
   2941       {
   2942         input_mask |= API_AML_HISTORY;
   2943         if (! parse_dim (section,
   2944                          tok,
   2945                          &aml_history_length_limit))
   2946           goto fail;
   2947       }
   2948       else if (0 == strncasecmp (tok,
   2949                                  "kyc_history",
   2950                                  strlen ("kyc_history")))
   2951       {
   2952         input_mask |= API_KYC_HISTORY;
   2953         if (! parse_dim (section,
   2954                          tok,
   2955                          &kyc_history_length_limit))
   2956           goto fail;
   2957       }
   2958       else
   2959       {
   2960         GNUNET_log_config_invalid (GNUNET_ERROR_TYPE_ERROR,
   2961                                    section,
   2962                                    "COMMAND",
   2963                                    "output for -i invalid (unsupported input)");
   2964         goto fail;
   2965       }
   2966     }
   2967   }
   2968   GNUNET_free (required_inputs);
   2969 
   2970   {
   2971     struct TALER_KYCLOGIC_AmlProgram *ap;
   2972 
   2973     ap = GNUNET_new (struct TALER_KYCLOGIC_AmlProgram);
   2974     ap->program_name = GNUNET_strdup (&section[strlen ("aml-program-")]);
   2975     ap->command = command;
   2976     ap->description = description;
   2977     ap->fallback = fallback;
   2978     ap->input_mask = input_mask;
   2979     ap->aml_history_length_limit = aml_history_length_limit;
   2980     ap->kyc_history_length_limit = kyc_history_length_limit;
   2981     add_tokens (required_contexts,
   2982                 "; \n\t",
   2983                 &ap->required_contexts,
   2984                 &ap->num_required_contexts);
   2985     GNUNET_free (required_contexts);
   2986     add_tokens (required_attributes,
   2987                 "; \n\t",
   2988                 &ap->required_attributes,
   2989                 &ap->num_required_attributes);
   2990     GNUNET_free (required_attributes);
   2991     GNUNET_array_append (aml_programs,
   2992                          num_aml_programs,
   2993                          ap);
   2994   }
   2995   return GNUNET_OK;
   2996 fail:
   2997   GNUNET_free (command);
   2998   GNUNET_free (description);
   2999   GNUNET_free (required_inputs);
   3000   GNUNET_free (required_contexts);
   3001   GNUNET_free (required_attributes);
   3002   GNUNET_free (fallback);
   3003   return GNUNET_SYSERR;
   3004 }
   3005 
   3006 
   3007 /**
   3008  * Function to iterate over configuration sections.
   3009  *
   3010  * @param cls a `struct SectionContext *`
   3011  * @param section name of the section
   3012  */
   3013 static void
   3014 handle_program_section (void *cls,
   3015                         const char *section)
   3016 {
   3017   struct SectionContext *sc = cls;
   3018   char *s;
   3019 
   3020   if (! sc->result)
   3021     return;
   3022   s = normalize_section_with_prefix ("aml-program-",
   3023                                      section);
   3024   if (NULL == s)
   3025     return;
   3026   if (GNUNET_OK !=
   3027       add_program (sc->cfg,
   3028                    s))
   3029     sc->result = false;
   3030   GNUNET_free (s);
   3031 }
   3032 
   3033 
   3034 /**
   3035  * Parse configuration @a cfg in section @a section for
   3036  * the specification of a KYC measure.
   3037  *
   3038  * @param cfg configuration to parse
   3039  * @param section configuration section to parse
   3040  * @return #GNUNET_OK on success
   3041  */
   3042 static enum GNUNET_GenericReturnValue
   3043 add_measure (const struct GNUNET_CONFIGURATION_Handle *cfg,
   3044              const char *section)
   3045 {
   3046   bool voluntary;
   3047   char *check_name = NULL;
   3048   struct TALER_KYCLOGIC_KycCheck *kc = NULL;
   3049   char *context_str = NULL;
   3050   char *program = NULL;
   3051   json_t *context;
   3052   json_error_t err;
   3053 
   3054   GNUNET_log (GNUNET_ERROR_TYPE_INFO,
   3055               "Parsing KYC measure %s\n",
   3056               section);
   3057   if (GNUNET_OK !=
   3058       GNUNET_CONFIGURATION_get_value_string (cfg,
   3059                                              section,
   3060                                              "CHECK_NAME",
   3061                                              &check_name))
   3062   {
   3063     check_name = GNUNET_strdup ("skip");
   3064   }
   3065   if (0 != strcasecmp (check_name,
   3066                        "skip"))
   3067   {
   3068     kc = find_check (check_name);
   3069     if (NULL == kc)
   3070     {
   3071       GNUNET_log_config_invalid (GNUNET_ERROR_TYPE_ERROR,
   3072                                  section,
   3073                                  "CHECK_NAME",
   3074                                  "check unknown");
   3075       goto fail;
   3076     }
   3077   }
   3078   if (GNUNET_OK !=
   3079       GNUNET_CONFIGURATION_get_value_string (cfg,
   3080                                              section,
   3081                                              "PROGRAM",
   3082                                              &program))
   3083   {
   3084     if ( (NULL == kc) ||
   3085          (TALER_KYCLOGIC_CT_INFO != kc->type) )
   3086     {
   3087       GNUNET_log_config_missing (GNUNET_ERROR_TYPE_ERROR,
   3088                                  section,
   3089                                  "PROGRAM");
   3090       goto fail;
   3091     }
   3092   }
   3093   else
   3094   {
   3095     /* AML program given, but do we want one? */
   3096     if ( (NULL != kc) &&
   3097          (TALER_KYCLOGIC_CT_INFO == kc->type) )
   3098     {
   3099       GNUNET_log_config_invalid (
   3100         GNUNET_ERROR_TYPE_WARNING,
   3101         section,
   3102         "PROGRAM",
   3103         "AML program specified for a check of type INFO (ignored)");
   3104       GNUNET_free (program);
   3105     }
   3106   }
   3107   voluntary = (GNUNET_YES ==
   3108                GNUNET_CONFIGURATION_get_value_yesno (cfg,
   3109                                                      section,
   3110                                                      "VOLUNTARY"));
   3111   if (GNUNET_OK !=
   3112       GNUNET_CONFIGURATION_get_value_string (cfg,
   3113                                              section,
   3114                                              "CONTEXT",
   3115                                              &context_str))
   3116   {
   3117     GNUNET_log_config_missing (GNUNET_ERROR_TYPE_ERROR,
   3118                                section,
   3119                                "CONTEXT");
   3120     goto fail;
   3121   }
   3122   context = json_loads (context_str,
   3123                         JSON_REJECT_DUPLICATES,
   3124                         &err);
   3125   GNUNET_free (context_str);
   3126   if (NULL == context)
   3127   {
   3128     GNUNET_log_config_invalid (GNUNET_ERROR_TYPE_ERROR,
   3129                                section,
   3130                                "CONTEXT",
   3131                                err.text);
   3132     goto fail;
   3133   }
   3134 
   3135   {
   3136     struct TALER_KYCLOGIC_Measure m;
   3137 
   3138     m.measure_name = GNUNET_strdup (&section[strlen ("kyc-measure-")]);
   3139     m.check_name = check_name;
   3140     m.prog_name = program;
   3141     m.context = context;
   3142     m.voluntary = voluntary;
   3143     GNUNET_array_append (default_rules.custom_measures,
   3144                          default_rules.num_custom_measures,
   3145                          m);
   3146   }
   3147   return GNUNET_OK;
   3148 fail:
   3149   GNUNET_free (check_name);
   3150   GNUNET_free (program);
   3151   GNUNET_free (context_str);
   3152   return GNUNET_SYSERR;
   3153 }
   3154 
   3155 
   3156 /**
   3157  * Function to iterate over configuration sections.
   3158  *
   3159  * @param cls a `struct SectionContext *`
   3160  * @param section name of the section
   3161  */
   3162 static void
   3163 handle_measure_section (void *cls,
   3164                         const char *section)
   3165 {
   3166   struct SectionContext *sc = cls;
   3167   char *s;
   3168 
   3169   if (! sc->result)
   3170     return;
   3171   s = normalize_section_with_prefix ("kyc-measure-",
   3172                                      section);
   3173   if (NULL == s)
   3174     return;
   3175   if (GNUNET_OK !=
   3176       add_measure (sc->cfg,
   3177                    s))
   3178     sc->result = false;
   3179   GNUNET_free (s);
   3180 }
   3181 
   3182 
   3183 /**
   3184  * Comparator for qsort. Compares two rules
   3185  * by timeframe to sort rules by time.
   3186  *
   3187  * @param p1 first trigger to compare
   3188  * @param p2 second trigger to compare
   3189  * @return -1 if p1 < p2, 0 if p1==p2, 1 if p1 > p2.
   3190  */
   3191 static int
   3192 sort_by_timeframe (const void *p1,
   3193                    const void *p2)
   3194 {
   3195   struct TALER_KYCLOGIC_KycRule *r1
   3196     = (struct TALER_KYCLOGIC_KycRule *) p1;
   3197   struct TALER_KYCLOGIC_KycRule *r2
   3198     = (struct TALER_KYCLOGIC_KycRule *) p2;
   3199 
   3200   if (GNUNET_TIME_relative_cmp (r1->timeframe,
   3201                                 <,
   3202                                 r2->timeframe))
   3203     return -1;
   3204   if (GNUNET_TIME_relative_cmp (r1->timeframe,
   3205                                 >,
   3206                                 r2->timeframe))
   3207     return 1;
   3208   return 0;
   3209 }
   3210 
   3211 
   3212 enum GNUNET_GenericReturnValue
   3213 TALER_KYCLOGIC_kyc_init (
   3214   const struct GNUNET_CONFIGURATION_Handle *cfg,
   3215   const char *cfg_fn)
   3216 {
   3217   struct SectionContext sc = {
   3218     .cfg = cfg,
   3219     .result = true
   3220   };
   3221   json_t *jkyc_rules_w;
   3222   json_t *jkyc_rules_a;
   3223 
   3224   if (NULL != cfg_fn)
   3225     cfg_filename = GNUNET_strdup (cfg_fn);
   3226   GNUNET_assert (GNUNET_OK ==
   3227                  TALER_config_get_currency (cfg,
   3228                                             "exchange",
   3229                                             &my_currency));
   3230   GNUNET_CONFIGURATION_iterate_sections (cfg,
   3231                                          &handle_provider_section,
   3232                                          &sc);
   3233   if (! sc.result)
   3234   {
   3235     TALER_KYCLOGIC_kyc_done ();
   3236     return GNUNET_SYSERR;
   3237   }
   3238   GNUNET_CONFIGURATION_iterate_sections (cfg,
   3239                                          &handle_check_section,
   3240                                          &sc);
   3241   if (! sc.result)
   3242   {
   3243     TALER_KYCLOGIC_kyc_done ();
   3244     return GNUNET_SYSERR;
   3245   }
   3246   GNUNET_CONFIGURATION_iterate_sections (cfg,
   3247                                          &handle_rule_section,
   3248                                          &sc);
   3249   if (! sc.result)
   3250   {
   3251     TALER_KYCLOGIC_kyc_done ();
   3252     return GNUNET_SYSERR;
   3253   }
   3254   GNUNET_CONFIGURATION_iterate_sections (cfg,
   3255                                          &handle_program_section,
   3256                                          &sc);
   3257   if (! sc.result)
   3258   {
   3259     TALER_KYCLOGIC_kyc_done ();
   3260     return GNUNET_SYSERR;
   3261   }
   3262   GNUNET_CONFIGURATION_iterate_sections (cfg,
   3263                                          &handle_measure_section,
   3264                                          &sc);
   3265   if (! sc.result)
   3266   {
   3267     TALER_KYCLOGIC_kyc_done ();
   3268     return GNUNET_SYSERR;
   3269   }
   3270 
   3271   if (0 != default_rules.num_kyc_rules)
   3272     qsort (default_rules.kyc_rules,
   3273            default_rules.num_kyc_rules,
   3274            sizeof (struct TALER_KYCLOGIC_KycRule),
   3275            &sort_by_timeframe);
   3276   jkyc_rules_w = json_array ();
   3277   GNUNET_assert (NULL != jkyc_rules_w);
   3278   jkyc_rules_a = json_array ();
   3279   GNUNET_assert (NULL != jkyc_rules_a);
   3280 
   3281   for (unsigned int i=0; i<default_rules.num_kyc_rules; i++)
   3282   {
   3283     const struct TALER_KYCLOGIC_KycRule *rule
   3284       = &default_rules.kyc_rules[i];
   3285     json_t *jrule;
   3286     json_t *jmeasures;
   3287 
   3288     jmeasures = json_array ();
   3289     GNUNET_assert (NULL != jmeasures);
   3290     for (unsigned int j=0; j<rule->num_measures; j++)
   3291     {
   3292       const char *measure_name = rule->next_measures[j];
   3293       const struct TALER_KYCLOGIC_Measure *m;
   3294 
   3295       if (0 == strcasecmp (KYC_MEASURE_IMPOSSIBLE,
   3296                            measure_name))
   3297       {
   3298         GNUNET_assert (
   3299           0 ==
   3300           json_array_append_new (jmeasures,
   3301                                  json_string (KYC_MEASURE_IMPOSSIBLE)));
   3302         continue;
   3303       }
   3304       m = find_measure (&default_rules,
   3305                         measure_name);
   3306       if (NULL == m)
   3307       {
   3308         GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
   3309                     "Unknown measure `%s' used in rule `%s'\n",
   3310                     measure_name,
   3311                     rule->rule_name);
   3312         return GNUNET_SYSERR;
   3313       }
   3314       GNUNET_assert (0 ==
   3315                      json_array_append_new (jmeasures,
   3316                                             json_string (measure_name)));
   3317     }
   3318     jrule = GNUNET_JSON_PACK (
   3319       GNUNET_JSON_pack_allow_null (
   3320         GNUNET_JSON_pack_string ("rule_name",
   3321                                  rule->rule_name)),
   3322       TALER_JSON_pack_kycte ("operation_type",
   3323                              rule->trigger),
   3324       TALER_JSON_pack_amount ("threshold",
   3325                               &rule->threshold),
   3326       GNUNET_JSON_pack_time_rel ("timeframe",
   3327                                  rule->timeframe),
   3328       GNUNET_JSON_pack_array_steal ("measures",
   3329                                     jmeasures),
   3330       GNUNET_JSON_pack_uint64 ("display_priority",
   3331                                rule->display_priority),
   3332       GNUNET_JSON_pack_bool ("exposed",
   3333                              rule->exposed),
   3334       GNUNET_JSON_pack_bool ("is_and_combinator",
   3335                              rule->is_and_combinator)
   3336       );
   3337     switch (rule->trigger)
   3338     {
   3339     case TALER_KYCLOGIC_KYC_TRIGGER_NONE:
   3340       GNUNET_break (0);
   3341       break;
   3342     case TALER_KYCLOGIC_KYC_TRIGGER_WITHDRAW:
   3343       GNUNET_assert (0 ==
   3344                      json_array_append (jkyc_rules_a,
   3345                                         jrule));
   3346       break;
   3347     case TALER_KYCLOGIC_KYC_TRIGGER_DEPOSIT:
   3348       GNUNET_assert (0 ==
   3349                      json_array_append (jkyc_rules_a,
   3350                                         jrule));
   3351       break;
   3352     case TALER_KYCLOGIC_KYC_TRIGGER_P2P_RECEIVE:
   3353       GNUNET_assert (0 ==
   3354                      json_array_append (jkyc_rules_w,
   3355                                         jrule));
   3356       break;
   3357     case TALER_KYCLOGIC_KYC_TRIGGER_WALLET_BALANCE:
   3358       GNUNET_assert (0 ==
   3359                      json_array_append (jkyc_rules_w,
   3360                                         jrule));
   3361       break;
   3362     case TALER_KYCLOGIC_KYC_TRIGGER_RESERVE_CLOSE:
   3363       GNUNET_assert (0 ==
   3364                      json_array_append (jkyc_rules_a,
   3365                                         jrule));
   3366       break;
   3367     case TALER_KYCLOGIC_KYC_TRIGGER_AGGREGATE:
   3368       GNUNET_assert (0 ==
   3369                      json_array_append (jkyc_rules_a,
   3370                                         jrule));
   3371       break;
   3372     case TALER_KYCLOGIC_KYC_TRIGGER_TRANSACTION:
   3373       GNUNET_assert (0 ==
   3374                      json_array_append (jkyc_rules_a,
   3375                                         jrule));
   3376       GNUNET_assert (0 ==
   3377                      json_array_append (jkyc_rules_w,
   3378                                         jrule));
   3379       break;
   3380     case TALER_KYCLOGIC_KYC_TRIGGER_REFUND:
   3381       GNUNET_assert (0 ==
   3382                      json_array_append (jkyc_rules_a,
   3383                                         jrule));
   3384       GNUNET_assert (0 ==
   3385                      json_array_append (jkyc_rules_w,
   3386                                         jrule));
   3387       break;
   3388     }
   3389     json_decref (jrule);
   3390   }
   3391   {
   3392     json_t *empty = json_object ();
   3393 
   3394     GNUNET_assert (NULL != empty);
   3395     wallet_default_lrs
   3396       = GNUNET_JSON_PACK (
   3397           GNUNET_JSON_pack_timestamp ("expiration_time",
   3398                                       GNUNET_TIME_UNIT_FOREVER_TS),
   3399           GNUNET_JSON_pack_array_steal ("rules",
   3400                                         jkyc_rules_w),
   3401           GNUNET_JSON_pack_object_incref ("custom_measures",
   3402                                           empty)
   3403           );
   3404     bankaccount_default_lrs
   3405       = GNUNET_JSON_PACK (
   3406           GNUNET_JSON_pack_timestamp ("expiration_time",
   3407                                       GNUNET_TIME_UNIT_FOREVER_TS),
   3408           GNUNET_JSON_pack_array_steal ("rules",
   3409                                         jkyc_rules_a),
   3410           GNUNET_JSON_pack_object_incref ("custom_measures",
   3411                                           empty)
   3412           );
   3413     json_decref (empty);
   3414   }
   3415   for (unsigned int i=0; i<default_rules.num_custom_measures; i++)
   3416   {
   3417     const struct TALER_KYCLOGIC_Measure *measure
   3418       = &default_rules.custom_measures[i];
   3419 
   3420     if (! check_measure (measure))
   3421     {
   3422       GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
   3423                   "Configuration of AML measures incorrect. Exiting.\n");
   3424       return GNUNET_SYSERR;
   3425     }
   3426   }
   3427 
   3428   for (unsigned int i=0; i<num_aml_programs; i++)
   3429   {
   3430     const struct TALER_KYCLOGIC_AmlProgram *program
   3431       = aml_programs[i];
   3432     const struct TALER_KYCLOGIC_Measure *m;
   3433 
   3434     m = find_measure (&default_rules,
   3435                       program->fallback);
   3436     if (NULL == m)
   3437     {
   3438       GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
   3439                   "Unknown fallback measure `%s' used in program `%s'\n",
   3440                   program->fallback,
   3441                   program->program_name);
   3442       return GNUNET_SYSERR;
   3443     }
   3444     if (0 != strcasecmp (m->check_name,
   3445                          "skip"))
   3446     {
   3447       GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
   3448                   "Fallback measure `%s' used in AML program `%s' has a check `%s' but fallbacks must have a check of type 'skip'\n",
   3449                   program->fallback,
   3450                   program->program_name,
   3451                   m->check_name);
   3452       return GNUNET_SYSERR;
   3453     }
   3454     if (NULL != m->prog_name)
   3455     {
   3456       const struct TALER_KYCLOGIC_AmlProgram *fprogram;
   3457 
   3458       fprogram = find_program (m->prog_name);
   3459       GNUNET_assert (NULL != fprogram);
   3460       if (API_NONE != (fprogram->input_mask & (API_CONTEXT | API_ATTRIBUTES)))
   3461       {
   3462         GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
   3463                     "Fallback program %s of fallback measure `%s' used in AML program `%s' has required inputs, but fallback measures must not require any inputs\n",
   3464                     m->prog_name,
   3465                     program->program_name,
   3466                     m->check_name);
   3467         return GNUNET_SYSERR;
   3468       }
   3469     }
   3470   }
   3471 
   3472   for (unsigned int i = 0; i<num_kyc_checks; i++)
   3473   {
   3474     struct TALER_KYCLOGIC_KycCheck *kyc_check
   3475       = kyc_checks[i];
   3476     const struct TALER_KYCLOGIC_Measure *measure;
   3477 
   3478     measure = find_measure (&default_rules,
   3479                             kyc_check->fallback);
   3480     if (NULL == measure)
   3481     {
   3482       GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
   3483                   "Unknown fallback measure `%s' used in check `%s'\n",
   3484                   kyc_check->fallback,
   3485                   kyc_check->check_name);
   3486       return GNUNET_SYSERR;
   3487     }
   3488     if (0 != strcasecmp (measure->check_name,
   3489                          "skip"))
   3490     {
   3491       GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
   3492                   "Fallback measure `%s' used in KYC check `%s' has a check `%s' but fallbacks must have a check of type 'skip'\n",
   3493                   kyc_check->fallback,
   3494                   kyc_check->check_name,
   3495                   measure->check_name);
   3496       return GNUNET_SYSERR;
   3497     }
   3498     if (NULL != measure->prog_name)
   3499     {
   3500       const struct TALER_KYCLOGIC_AmlProgram *fprogram;
   3501 
   3502       fprogram = find_program (measure->prog_name);
   3503       GNUNET_assert (NULL != fprogram);
   3504       if (API_NONE != (fprogram->input_mask & (API_CONTEXT | API_ATTRIBUTES)))
   3505       {
   3506         GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
   3507                     "AML program `%s' used fallback measure `%s' of KYC check `%s' has required inputs, but fallback measures must not require any inputs\n",
   3508                     measure->prog_name,
   3509                     kyc_check->fallback,
   3510                     kyc_check->check_name);
   3511         return GNUNET_SYSERR;
   3512       }
   3513     }
   3514   }
   3515 
   3516   return GNUNET_OK;
   3517 }
   3518 
   3519 
   3520 void
   3521 TALER_KYCLOGIC_kyc_done (void)
   3522 {
   3523   free_rules (&default_rules);
   3524   memset (&default_rules,
   3525           0,
   3526           sizeof (default_rules));
   3527   for (unsigned int i = 0; i<num_kyc_providers; i++)
   3528   {
   3529     struct TALER_KYCLOGIC_KycProvider *kp = kyc_providers[i];
   3530 
   3531     kp->logic->unload_configuration (kp->pd);
   3532     GNUNET_free (kp->provider_name);
   3533     GNUNET_free (kp);
   3534   }
   3535   GNUNET_array_grow (kyc_providers,
   3536                      num_kyc_providers,
   3537                      0);
   3538   for (unsigned int i = 0; i<num_kyc_logics; i++)
   3539   {
   3540     struct TALER_KYCLOGIC_Plugin *lp = kyc_logics[i];
   3541     char *lib_name = lp->library_name;
   3542 
   3543     GNUNET_free (lp->name);
   3544     GNUNET_assert (NULL == GNUNET_PLUGIN_unload (lib_name,
   3545                                                  lp));
   3546     GNUNET_free (lib_name);
   3547   }
   3548   GNUNET_array_grow (kyc_logics,
   3549                      num_kyc_logics,
   3550                      0);
   3551   for (unsigned int i = 0; i<num_kyc_checks; i++)
   3552   {
   3553     struct TALER_KYCLOGIC_KycCheck *kc = kyc_checks[i];
   3554 
   3555     GNUNET_free (kc->check_name);
   3556     GNUNET_free (kc->description);
   3557     json_decref (kc->description_i18n);
   3558     for (unsigned int j = 0; j<kc->num_requires; j++)
   3559       GNUNET_free (kc->requires[j]);
   3560     GNUNET_array_grow (kc->requires,
   3561                        kc->num_requires,
   3562                        0);
   3563     GNUNET_free (kc->fallback);
   3564     for (unsigned int j = 0; j<kc->num_outputs; j++)
   3565       GNUNET_free (kc->outputs[j]);
   3566     GNUNET_array_grow (kc->outputs,
   3567                        kc->num_outputs,
   3568                        0);
   3569     switch (kc->type)
   3570     {
   3571     case TALER_KYCLOGIC_CT_INFO:
   3572       break;
   3573     case TALER_KYCLOGIC_CT_FORM:
   3574       GNUNET_free (kc->details.form.name);
   3575       break;
   3576     case TALER_KYCLOGIC_CT_LINK:
   3577       break;
   3578     }
   3579     GNUNET_free (kc);
   3580   }
   3581   GNUNET_array_grow (kyc_checks,
   3582                      num_kyc_checks,
   3583                      0);
   3584   for (unsigned int i = 0; i<num_aml_programs; i++)
   3585   {
   3586     struct TALER_KYCLOGIC_AmlProgram *ap = aml_programs[i];
   3587 
   3588     GNUNET_free (ap->program_name);
   3589     GNUNET_free (ap->command);
   3590     GNUNET_free (ap->description);
   3591     GNUNET_free (ap->fallback);
   3592     for (unsigned int j = 0; j<ap->num_required_contexts; j++)
   3593       GNUNET_free (ap->required_contexts[j]);
   3594     GNUNET_array_grow (ap->required_contexts,
   3595                        ap->num_required_contexts,
   3596                        0);
   3597     for (unsigned int j = 0; j<ap->num_required_attributes; j++)
   3598       GNUNET_free (ap->required_attributes[j]);
   3599     GNUNET_array_grow (ap->required_attributes,
   3600                        ap->num_required_attributes,
   3601                        0);
   3602     GNUNET_free (ap);
   3603   }
   3604   GNUNET_array_grow (aml_programs,
   3605                      num_aml_programs,
   3606                      0);
   3607   GNUNET_free (cfg_filename);
   3608 }
   3609 
   3610 
   3611 void
   3612 TALER_KYCLOGIC_provider_to_logic (
   3613   const struct TALER_KYCLOGIC_KycProvider *provider,
   3614   struct TALER_KYCLOGIC_Plugin **plugin,
   3615   struct TALER_KYCLOGIC_ProviderDetails **pd,
   3616   const char **provider_name)
   3617 {
   3618   *plugin = provider->logic;
   3619   *pd = provider->pd;
   3620   *provider_name = provider->provider_name;
   3621 }
   3622 
   3623 
   3624 enum GNUNET_GenericReturnValue
   3625 TALER_KYCLOGIC_get_original_measure (
   3626   const char *measure_name,
   3627   struct TALER_KYCLOGIC_KycCheckContext *kcc)
   3628 {
   3629   const struct TALER_KYCLOGIC_Measure *measure;
   3630 
   3631   measure = find_measure (&default_rules,
   3632                           measure_name);
   3633   if (NULL == measure)
   3634   {
   3635     GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
   3636                 "Default measure `%s' unknown\n",
   3637                 measure_name);
   3638     return GNUNET_SYSERR;
   3639   }
   3640   if (0 == strcasecmp (measure->check_name,
   3641                        "skip"))
   3642   {
   3643     kcc->check = NULL;
   3644     kcc->prog_name = measure->prog_name;
   3645     kcc->context = measure->context;
   3646     return GNUNET_OK;
   3647   }
   3648 
   3649   for (unsigned int i = 0; i<num_kyc_checks; i++)
   3650     if (0 == strcasecmp (measure->check_name,
   3651                          kyc_checks[i]->check_name))
   3652     {
   3653       kcc->check = kyc_checks[i];
   3654       kcc->prog_name = measure->prog_name;
   3655       kcc->context = measure->context;
   3656       return GNUNET_OK;
   3657     }
   3658   GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
   3659               "Check `%s' unknown (but required by measure `%s')\n",
   3660               measure->check_name,
   3661               measure_name);
   3662   return GNUNET_SYSERR;
   3663 }
   3664 
   3665 
   3666 enum GNUNET_GenericReturnValue
   3667 TALER_KYCLOGIC_requirements_to_check (
   3668   const struct TALER_KYCLOGIC_LegitimizationRuleSet *lrs,
   3669   const struct TALER_KYCLOGIC_KycRule *kyc_rule,
   3670   const char *measure_name,
   3671   struct TALER_KYCLOGIC_KycCheckContext *kcc)
   3672 {
   3673   bool found = false;
   3674   const struct TALER_KYCLOGIC_Measure *measure = NULL;
   3675 
   3676   if (NULL == lrs)
   3677     lrs = &default_rules;
   3678   if (NULL == measure_name)
   3679   {
   3680     GNUNET_break (0);
   3681     return GNUNET_SYSERR;
   3682   }
   3683   if (NULL != kyc_rule)
   3684   {
   3685     if (kyc_rule->verboten)
   3686     {
   3687       GNUNET_log (GNUNET_ERROR_TYPE_WARNING,
   3688                   "Rule says operation is categorically is verboten, cannot take measures\n");
   3689       return GNUNET_SYSERR;
   3690     }
   3691     for (unsigned int i = 0; i<kyc_rule->num_measures; i++)
   3692     {
   3693       if (0 != strcasecmp (measure_name,
   3694                            kyc_rule->next_measures[i]))
   3695         continue;
   3696       found = true;
   3697       break;
   3698     }
   3699     if (! found)
   3700     {
   3701       GNUNET_log (GNUNET_ERROR_TYPE_WARNING,
   3702                   "Measure `%s' not allowed for rule `%s'\n",
   3703                   measure_name,
   3704                   kyc_rule->rule_name);
   3705       return GNUNET_SYSERR;
   3706     }
   3707   }
   3708   measure = find_measure (lrs,
   3709                           measure_name);
   3710   if (NULL == measure)
   3711   {
   3712     GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
   3713                 "Measure `%s' unknown (but allowed by rule `%s')\n",
   3714                 measure_name,
   3715                 NULL != kyc_rule
   3716                 ? kyc_rule->rule_name
   3717                 : "<NONE>");
   3718     return GNUNET_SYSERR;
   3719   }
   3720 
   3721   if (0 == strcasecmp (measure->check_name,
   3722                        "skip"))
   3723   {
   3724     kcc->check = NULL;
   3725     kcc->prog_name = measure->prog_name;
   3726     kcc->context = measure->context;
   3727     return GNUNET_OK;
   3728   }
   3729 
   3730   for (unsigned int i = 0; i<num_kyc_checks; i++)
   3731     if (0 == strcasecmp (measure->check_name,
   3732                          kyc_checks[i]->check_name))
   3733     {
   3734       kcc->check = kyc_checks[i];
   3735       kcc->prog_name = measure->prog_name;
   3736       kcc->context = measure->context;
   3737       return GNUNET_OK;
   3738     }
   3739   GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
   3740               "Check `%s' unknown (but required by measure `%s')\n",
   3741               measure->check_name,
   3742               measure_name);
   3743   return GNUNET_SYSERR;
   3744 }
   3745 
   3746 
   3747 enum GNUNET_GenericReturnValue
   3748 TALER_KYCLOGIC_lookup_logic (
   3749   const char *name,
   3750   struct TALER_KYCLOGIC_Plugin **plugin,
   3751   struct TALER_KYCLOGIC_ProviderDetails **pd,
   3752   const char **provider_name)
   3753 {
   3754   for (unsigned int i = 0; i<num_kyc_providers; i++)
   3755   {
   3756     struct TALER_KYCLOGIC_KycProvider *kp = kyc_providers[i];
   3757 
   3758     if (0 !=
   3759         strcasecmp (name,
   3760                     kp->provider_name))
   3761       continue;
   3762     *plugin = kp->logic;
   3763     *pd = kp->pd;
   3764     *provider_name = kp->provider_name;
   3765     return GNUNET_OK;
   3766   }
   3767   for (unsigned int i = 0; i<num_kyc_logics; i++)
   3768   {
   3769     struct TALER_KYCLOGIC_Plugin *logic = kyc_logics[i];
   3770 
   3771     if (0 !=
   3772         strcasecmp (logic->name,
   3773                     name))
   3774       continue;
   3775     *plugin = logic;
   3776     *pd = NULL;
   3777     *provider_name = NULL;
   3778     return GNUNET_OK;
   3779   }
   3780   GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
   3781               "Provider `%s' unknown\n",
   3782               name);
   3783   return GNUNET_SYSERR;
   3784 }
   3785 
   3786 
   3787 void
   3788 TALER_KYCLOGIC_kyc_get_details (
   3789   const char *logic_name,
   3790   TALER_KYCLOGIC_DetailsCallback cb,
   3791   void *cb_cls)
   3792 {
   3793   for (unsigned int i = 0; i<num_kyc_providers; i++)
   3794   {
   3795     struct TALER_KYCLOGIC_KycProvider *kp
   3796       = kyc_providers[i];
   3797 
   3798     if (0 !=
   3799         strcasecmp (kp->logic->name,
   3800                     logic_name))
   3801       continue;
   3802     if (GNUNET_OK !=
   3803         cb (cb_cls,
   3804             kp->pd,
   3805             kp->logic->cls))
   3806       return;
   3807   }
   3808 }
   3809 
   3810 
   3811 /**
   3812  * Closure for check_amount().
   3813  */
   3814 struct KycTestContext
   3815 {
   3816   /**
   3817    * Rule set we apply.
   3818    */
   3819   const struct TALER_KYCLOGIC_LegitimizationRuleSet *lrs;
   3820 
   3821   /**
   3822    * Events we care about.
   3823    */
   3824   enum TALER_KYCLOGIC_KycTriggerEvent event;
   3825 
   3826   /**
   3827    * Total amount encountered so far, invalid if zero.
   3828    */
   3829   struct TALER_Amount sum;
   3830 
   3831   /**
   3832    * Set to the triggered rule.
   3833    */
   3834   const struct TALER_KYCLOGIC_KycRule *triggered_rule;
   3835 
   3836 };
   3837 
   3838 
   3839 /**
   3840  * Function called on each @a amount that was found to
   3841  * be relevant for a KYC check.  Evaluates the given
   3842  * @a amount and @a date against all the applicable
   3843  * rules in the legitimization rule set.
   3844  *
   3845  * @param cls our `struct KycTestContext *`
   3846  * @param amount encountered transaction amount
   3847  * @param date when was the amount encountered
   3848  * @return #GNUNET_OK to continue to iterate,
   3849  *         #GNUNET_NO to abort iteration,
   3850  *         #GNUNET_SYSERR on internal error (also abort itaration)
   3851  */
   3852 static enum GNUNET_GenericReturnValue
   3853 check_amount (
   3854   void *cls,
   3855   const struct TALER_Amount *amount,
   3856   struct GNUNET_TIME_Absolute date)
   3857 {
   3858   struct KycTestContext *ktc = cls;
   3859   struct GNUNET_TIME_Relative dur;
   3860 
   3861   GNUNET_log (GNUNET_ERROR_TYPE_INFO,
   3862               "KYC checking transaction amount %s from %s against %u rules\n",
   3863               TALER_amount2s (amount),
   3864               GNUNET_TIME_absolute2s (date),
   3865               ktc->lrs->num_kyc_rules);
   3866   dur = GNUNET_TIME_absolute_get_duration (date);
   3867   if (GNUNET_OK !=
   3868       TALER_amount_is_valid (&ktc->sum))
   3869     ktc->sum = *amount;
   3870   else
   3871     GNUNET_assert (0 <=
   3872                    TALER_amount_add (&ktc->sum,
   3873                                      &ktc->sum,
   3874                                      amount));
   3875   for (unsigned int i=0; i<ktc->lrs->num_kyc_rules; i++)
   3876   {
   3877     const struct TALER_KYCLOGIC_KycRule *rule
   3878       = &ktc->lrs->kyc_rules[i];
   3879 
   3880     if (ktc->event != rule->trigger)
   3881     {
   3882       GNUNET_log (GNUNET_ERROR_TYPE_INFO,
   3883                   "Wrong event type (%d) for rule %u (%d)\n",
   3884                   (int) ktc->event,
   3885                   i,
   3886                   (int) rule->trigger);
   3887       continue; /* wrong trigger event type */
   3888     }
   3889     if (GNUNET_TIME_relative_cmp (dur,
   3890                                   >,
   3891                                   rule->timeframe))
   3892     {
   3893       GNUNET_log (GNUNET_ERROR_TYPE_INFO,
   3894                   "Out of time range for rule %u\n",
   3895                   i);
   3896       continue; /* out of time range for rule */
   3897     }
   3898     if (-1 == TALER_amount_cmp (&ktc->sum,
   3899                                 &rule->threshold))
   3900     {
   3901       GNUNET_log (GNUNET_ERROR_TYPE_INFO,
   3902                   "Below threshold of %s for rule %u\n",
   3903                   TALER_amount2s (&rule->threshold),
   3904                   i);
   3905       continue; /* sum < threshold */
   3906     }
   3907     if ( (NULL != ktc->triggered_rule) &&
   3908          (1 == TALER_amount_cmp (&ktc->triggered_rule->threshold,
   3909                                  &rule->threshold)) )
   3910     {
   3911       GNUNET_log (GNUNET_ERROR_TYPE_INFO,
   3912                   "Higher than threshold of already triggered rule\n");
   3913       continue; /* threshold of triggered_rule > rule */
   3914     }
   3915     GNUNET_log (GNUNET_ERROR_TYPE_INFO,
   3916                 "Remembering rule %s as triggered\n",
   3917                 rule->rule_name);
   3918     ktc->triggered_rule = rule;
   3919   }
   3920   return GNUNET_OK;
   3921 }
   3922 
   3923 
   3924 enum GNUNET_DB_QueryStatus
   3925 TALER_KYCLOGIC_kyc_test_required (
   3926   enum TALER_KYCLOGIC_KycTriggerEvent event,
   3927   const struct TALER_KYCLOGIC_LegitimizationRuleSet *lrs,
   3928   TALER_KYCLOGIC_KycAmountIterator ai,
   3929   void *ai_cls,
   3930   const struct TALER_KYCLOGIC_KycRule **triggered_rule,
   3931   struct TALER_Amount *next_threshold)
   3932 {
   3933   struct GNUNET_TIME_Relative range
   3934     = GNUNET_TIME_UNIT_ZERO;
   3935   enum GNUNET_DB_QueryStatus qs;
   3936   bool have_threshold = false;
   3937 
   3938   memset (next_threshold,
   3939           0,
   3940           sizeof (struct TALER_Amount));
   3941   if (NULL == lrs)
   3942     lrs = &default_rules;
   3943   GNUNET_log (GNUNET_ERROR_TYPE_INFO,
   3944               "Testing %u KYC rules for trigger %d\n",
   3945               lrs->num_kyc_rules,
   3946               event);
   3947   for (unsigned int i=0; i<lrs->num_kyc_rules; i++)
   3948   {
   3949     const struct TALER_KYCLOGIC_KycRule *rule
   3950       = &lrs->kyc_rules[i];
   3951 
   3952     if (event != rule->trigger)
   3953     {
   3954       GNUNET_log (GNUNET_ERROR_TYPE_INFO,
   3955                   "Rule %u is for a different trigger (%d/%d)\n",
   3956                   i,
   3957                   (int) event,
   3958                   (int) rule->trigger);
   3959       continue;
   3960     }
   3961     if (have_threshold)
   3962     {
   3963       GNUNET_assert (GNUNET_OK ==
   3964                      TALER_amount_min (next_threshold,
   3965                                        next_threshold,
   3966                                        &rule->threshold));
   3967     }
   3968     else
   3969     {
   3970       *next_threshold = rule->threshold;
   3971       have_threshold = true;
   3972     }
   3973     GNUNET_log (GNUNET_ERROR_TYPE_INFO,
   3974                 "Matched rule %u with timeframe %s and threshold %s\n",
   3975                 i,
   3976                 GNUNET_TIME_relative2s (rule->timeframe,
   3977                                         true),
   3978                 TALER_amount2s (&rule->threshold));
   3979     range = GNUNET_TIME_relative_max (range,
   3980                                       rule->timeframe);
   3981   }
   3982 
   3983   if (! have_threshold)
   3984   {
   3985     GNUNET_log (GNUNET_ERROR_TYPE_INFO,
   3986                 "No rules apply\n");
   3987     *triggered_rule = NULL;
   3988     return GNUNET_DB_STATUS_SUCCESS_NO_RESULTS;
   3989   }
   3990 
   3991   {
   3992     struct GNUNET_TIME_Absolute now
   3993       = GNUNET_TIME_absolute_get ();
   3994     struct KycTestContext ktc = {
   3995       .lrs = lrs,
   3996       .event = event
   3997     };
   3998 
   3999     qs = ai (ai_cls,
   4000              GNUNET_TIME_absolute_subtract (now,
   4001                                             range),
   4002              &check_amount,
   4003              &ktc);
   4004     GNUNET_log (GNUNET_ERROR_TYPE_INFO,
   4005                 "Triggered rule is %s\n",
   4006                 (NULL == ktc.triggered_rule)
   4007                 ? "NONE"
   4008                 : ktc.triggered_rule->rule_name);
   4009     *triggered_rule = ktc.triggered_rule;
   4010   }
   4011   return qs;
   4012 }
   4013 
   4014 
   4015 json_t *
   4016 TALER_KYCLOGIC_measure_to_requirement (
   4017   const char *check_name,
   4018   const json_t *context,
   4019   const struct TALER_AccountAccessTokenP *access_token,
   4020   size_t offset,
   4021   uint64_t legitimization_measure_row_id)
   4022 {
   4023   struct TALER_KYCLOGIC_KycCheck *kc;
   4024   json_t *kri;
   4025   struct TALER_KycMeasureAuthorizationHashP shv;
   4026   char *ids;
   4027   char *xids;
   4028 
   4029   kc = find_check (check_name);
   4030   if (NULL == kc)
   4031   {
   4032     GNUNET_break (0);
   4033     return NULL;
   4034   }
   4035   GNUNET_assert (offset <= UINT32_MAX);
   4036   TALER_kyc_measure_authorization_hash (access_token,
   4037                                         legitimization_measure_row_id,
   4038                                         (uint32_t) offset,
   4039                                         &shv);
   4040   switch (kc->type)
   4041   {
   4042   case TALER_KYCLOGIC_CT_INFO:
   4043     return GNUNET_JSON_PACK (
   4044       GNUNET_JSON_pack_string ("form",
   4045                                "INFO"),
   4046       GNUNET_JSON_pack_string ("description",
   4047                                kc->description),
   4048       GNUNET_JSON_pack_allow_null (
   4049         GNUNET_JSON_pack_object_incref ("description_i18n",
   4050                                         (json_t *) kc->description_i18n)));
   4051   case TALER_KYCLOGIC_CT_FORM:
   4052     GNUNET_assert (offset <= UINT_MAX);
   4053     ids = GNUNET_STRINGS_data_to_string_alloc (&shv,
   4054                                                sizeof (shv));
   4055     GNUNET_asprintf (&xids,
   4056                      "%s-%u-%llu",
   4057                      ids,
   4058                      (unsigned int) offset,
   4059                      (unsigned long long) legitimization_measure_row_id);
   4060     GNUNET_free (ids);
   4061     kri = GNUNET_JSON_PACK (
   4062       GNUNET_JSON_pack_string ("form",
   4063                                kc->details.form.name),
   4064       GNUNET_JSON_pack_string ("id",
   4065                                xids),
   4066       GNUNET_JSON_pack_allow_null (
   4067         GNUNET_JSON_pack_object_incref ("context",
   4068                                         (json_t *) context)),
   4069       GNUNET_JSON_pack_string ("description",
   4070                                kc->description),
   4071       GNUNET_JSON_pack_allow_null (
   4072         GNUNET_JSON_pack_object_incref ("description_i18n",
   4073                                         (json_t *) kc->description_i18n)));
   4074     GNUNET_free (xids);
   4075     return kri;
   4076   case TALER_KYCLOGIC_CT_LINK:
   4077     GNUNET_assert (offset <= UINT_MAX);
   4078     ids = GNUNET_STRINGS_data_to_string_alloc (&shv,
   4079                                                sizeof (shv));
   4080     GNUNET_asprintf (&xids,
   4081                      "%s-%u-%llu",
   4082                      ids,
   4083                      (unsigned int) offset,
   4084                      (unsigned long long) legitimization_measure_row_id);
   4085     GNUNET_free (ids);
   4086     kri = GNUNET_JSON_PACK (
   4087       GNUNET_JSON_pack_string ("form",
   4088                                "LINK"),
   4089       GNUNET_JSON_pack_string ("id",
   4090                                xids),
   4091       GNUNET_JSON_pack_string ("description",
   4092                                kc->description),
   4093       GNUNET_JSON_pack_allow_null (
   4094         GNUNET_JSON_pack_object_incref ("description_i18n",
   4095                                         (json_t *) kc->description_i18n)));
   4096     GNUNET_free (xids);
   4097     return kri;
   4098   }
   4099   GNUNET_break (0); /* invalid type */
   4100   return NULL;
   4101 }
   4102 
   4103 
   4104 void
   4105 TALER_KYCLOGIC_get_measure_configuration (
   4106   json_t **proots,
   4107   json_t **pprograms,
   4108   json_t **pchecks,
   4109   json_t **pdefault_rules)
   4110 {
   4111   json_t *roots;
   4112   json_t *programs;
   4113   json_t *checks;
   4114   json_t *drules;
   4115 
   4116   roots = json_object ();
   4117   GNUNET_assert (NULL != roots);
   4118   for (unsigned int i = 0; i<default_rules.num_custom_measures; i++)
   4119   {
   4120     const struct TALER_KYCLOGIC_Measure *m
   4121       = &default_rules.custom_measures[i];
   4122     json_t *jm;
   4123 
   4124     jm = GNUNET_JSON_PACK (
   4125       GNUNET_JSON_pack_string ("check_name",
   4126                                m->check_name),
   4127       GNUNET_JSON_pack_allow_null (
   4128         GNUNET_JSON_pack_string ("prog_name",
   4129                                  m->prog_name)),
   4130       GNUNET_JSON_pack_allow_null (
   4131         GNUNET_JSON_pack_object_incref ("context",
   4132                                         m->context)));
   4133     GNUNET_assert (0 ==
   4134                    json_object_set_new (roots,
   4135                                         m->measure_name,
   4136                                         jm));
   4137   }
   4138 
   4139   programs = json_object ();
   4140   GNUNET_assert (NULL != programs);
   4141   for (unsigned int i = 0; i<num_aml_programs; i++)
   4142   {
   4143     const struct TALER_KYCLOGIC_AmlProgram *ap
   4144       = aml_programs[i];
   4145     json_t *jp;
   4146     json_t *ctx;
   4147     json_t *inp;
   4148 
   4149     ctx = json_array ();
   4150     GNUNET_assert (NULL != ctx);
   4151     for (unsigned int j = 0; j<ap->num_required_contexts; j++)
   4152     {
   4153       const char *rc = ap->required_contexts[j];
   4154 
   4155       GNUNET_assert (0 ==
   4156                      json_array_append_new (ctx,
   4157                                             json_string (rc)));
   4158     }
   4159     inp = json_array ();
   4160     GNUNET_assert (NULL != inp);
   4161     for (unsigned int j = 0; j<ap->num_required_attributes; j++)
   4162     {
   4163       const char *ra = ap->required_attributes[j];
   4164 
   4165       GNUNET_assert (0 ==
   4166                      json_array_append_new (inp,
   4167                                             json_string (ra)));
   4168     }
   4169 
   4170     jp = GNUNET_JSON_PACK (
   4171       GNUNET_JSON_pack_string ("description",
   4172                                ap->description),
   4173       GNUNET_JSON_pack_array_steal ("context",
   4174                                     ctx),
   4175       GNUNET_JSON_pack_array_steal ("inputs",
   4176                                     inp));
   4177     GNUNET_assert (0 ==
   4178                    json_object_set_new (programs,
   4179                                         ap->program_name,
   4180                                         jp));
   4181   }
   4182 
   4183   checks = json_object ();
   4184   GNUNET_assert (NULL != checks);
   4185   for (unsigned int i = 0; i<num_kyc_checks; i++)
   4186   {
   4187     const struct TALER_KYCLOGIC_KycCheck *ck
   4188       = kyc_checks[i];
   4189     json_t *jc;
   4190     json_t *requires;
   4191     json_t *outputs;
   4192 
   4193     requires = json_array ();
   4194     GNUNET_assert (NULL != requires);
   4195     for (unsigned int j = 0; j<ck->num_requires; j++)
   4196     {
   4197       const char *ra = ck->requires[j];
   4198 
   4199       GNUNET_assert (0 ==
   4200                      json_array_append_new (requires,
   4201                                             json_string (ra)));
   4202     }
   4203     outputs = json_array ();
   4204     GNUNET_assert (NULL != outputs);
   4205     for (unsigned int j = 0; j<ck->num_outputs; j++)
   4206     {
   4207       const char *out = ck->outputs[j];
   4208 
   4209       GNUNET_assert (0 ==
   4210                      json_array_append_new (outputs,
   4211                                             json_string (out)));
   4212     }
   4213 
   4214     jc = GNUNET_JSON_PACK (
   4215       GNUNET_JSON_pack_string ("description",
   4216                                ck->description),
   4217       GNUNET_JSON_pack_allow_null (
   4218         GNUNET_JSON_pack_object_incref ("description_i18n",
   4219                                         ck->description_i18n)),
   4220       GNUNET_JSON_pack_array_steal ("requires",
   4221                                     requires),
   4222       GNUNET_JSON_pack_array_steal ("outputs",
   4223                                     outputs),
   4224       GNUNET_JSON_pack_string ("fallback",
   4225                                ck->fallback));
   4226     GNUNET_assert (0 ==
   4227                    json_object_set_new (checks,
   4228                                         ck->check_name,
   4229                                         jc));
   4230   }
   4231   drules = json_array ();
   4232   GNUNET_assert (NULL != drules);
   4233   {
   4234     const struct TALER_KYCLOGIC_KycRule *rules
   4235       = default_rules.kyc_rules;
   4236     unsigned int num_rules
   4237       = default_rules.num_kyc_rules;
   4238 
   4239     for (unsigned int i = 0; i<num_rules; i++)
   4240     {
   4241       const struct TALER_KYCLOGIC_KycRule *rule = &rules[i];
   4242       json_t *measures;
   4243       json_t *limit;
   4244 
   4245       measures = json_array ();
   4246       GNUNET_assert (NULL != measures);
   4247       for (unsigned int j = 0; j<rule->num_measures; j++)
   4248         GNUNET_assert (
   4249           0 ==
   4250           json_array_append_new (measures,
   4251                                  json_string (
   4252                                    rule->next_measures[j])));
   4253       limit = GNUNET_JSON_PACK (
   4254         GNUNET_JSON_pack_allow_null (
   4255           GNUNET_JSON_pack_string ("rule_name",
   4256                                    rule->rule_name)),
   4257         TALER_JSON_pack_kycte ("operation_type",
   4258                                rule->trigger),
   4259         TALER_JSON_pack_amount ("threshold",
   4260                                 &rule->threshold),
   4261         GNUNET_JSON_pack_time_rel ("timeframe",
   4262                                    rule->timeframe),
   4263         GNUNET_JSON_pack_array_steal ("measures",
   4264                                       measures),
   4265         GNUNET_JSON_pack_uint64 ("display_priority",
   4266                                  rule->display_priority),
   4267         GNUNET_JSON_pack_bool ("soft_limit",
   4268                                ! rule->verboten),
   4269         GNUNET_JSON_pack_bool ("exposed",
   4270                                rule->exposed),
   4271         GNUNET_JSON_pack_bool ("is_and_combinator",
   4272                                rule->is_and_combinator)
   4273         );
   4274       GNUNET_assert (0 ==
   4275                      json_array_append_new (drules,
   4276                                             limit));
   4277     }
   4278   }
   4279 
   4280   *proots = roots;
   4281   *pprograms = programs;
   4282   *pchecks = checks;
   4283   *pdefault_rules = drules;
   4284 }
   4285 
   4286 
   4287 enum TALER_ErrorCode
   4288 TALER_KYCLOGIC_select_measure (
   4289   const json_t *jmeasures,
   4290   size_t measure_index,
   4291   const char **check_name,
   4292   const char **prog_name,
   4293   const json_t **context)
   4294 {
   4295   const json_t *jmeasure_arr;
   4296   struct GNUNET_JSON_Specification spec[] = {
   4297     GNUNET_JSON_spec_array_const ("measures",
   4298                                   &jmeasure_arr),
   4299     GNUNET_JSON_spec_end ()
   4300   };
   4301   const json_t *jmeasure;
   4302   struct GNUNET_JSON_Specification ispec[] = {
   4303     GNUNET_JSON_spec_string ("check_name",
   4304                              check_name),
   4305     GNUNET_JSON_spec_mark_optional (
   4306       GNUNET_JSON_spec_string ("prog_name",
   4307                                prog_name),
   4308       NULL),
   4309     GNUNET_JSON_spec_mark_optional (
   4310       GNUNET_JSON_spec_object_const ("context",
   4311                                      context),
   4312       NULL),
   4313     GNUNET_JSON_spec_end ()
   4314   };
   4315 
   4316   *check_name = NULL;
   4317   *prog_name = NULL;
   4318   *context = NULL;
   4319   if (GNUNET_OK !=
   4320       GNUNET_JSON_parse (jmeasures,
   4321                          spec,
   4322                          NULL, NULL))
   4323   {
   4324     GNUNET_break (0);
   4325     return TALER_EC_EXCHANGE_KYC_MEASURES_MALFORMED;
   4326   }
   4327   if (measure_index >= json_array_size (jmeasure_arr))
   4328   {
   4329     GNUNET_break_op (0);
   4330     return TALER_EC_EXCHANGE_KYC_MEASURE_INDEX_INVALID;
   4331   }
   4332   jmeasure = json_array_get (jmeasure_arr,
   4333                              measure_index);
   4334   if (GNUNET_OK !=
   4335       GNUNET_JSON_parse (jmeasure,
   4336                          ispec,
   4337                          NULL, NULL))
   4338   {
   4339     GNUNET_break (0);
   4340     return TALER_EC_EXCHANGE_KYC_MEASURES_MALFORMED;
   4341   }
   4342   return TALER_EC_NONE;
   4343 }
   4344 
   4345 
   4346 enum TALER_ErrorCode
   4347 TALER_KYCLOGIC_check_form (
   4348   const json_t *jmeasures,
   4349   size_t measure_index,
   4350   const json_t *form_data,
   4351   char **form_name,
   4352   const char **error_message)
   4353 {
   4354   const char *check_name;
   4355   const char *prog_name;
   4356   const json_t *context;
   4357   struct TALER_KYCLOGIC_KycCheck *kc;
   4358   struct TALER_KYCLOGIC_AmlProgram *prog;
   4359 
   4360   *error_message = NULL;
   4361   *form_name = NULL;
   4362   if (TALER_EC_NONE !=
   4363       TALER_KYCLOGIC_select_measure (jmeasures,
   4364                                      measure_index,
   4365                                      &check_name,
   4366                                      &prog_name,
   4367                                      &context))
   4368   {
   4369     GNUNET_break_op (0);
   4370     return TALER_EC_EXCHANGE_KYC_MEASURE_INDEX_INVALID;
   4371   }
   4372   kc = find_check (check_name);
   4373   if (NULL == kc)
   4374   {
   4375     GNUNET_break (0);
   4376     *error_message = check_name;
   4377     return TALER_EC_EXCHANGE_KYC_GENERIC_CHECK_GONE;
   4378   }
   4379   if (TALER_KYCLOGIC_CT_FORM != kc->type)
   4380   {
   4381     GNUNET_break_op (0);
   4382     return TALER_EC_EXCHANGE_KYC_NOT_A_FORM;
   4383   }
   4384   if (NULL == prog_name)
   4385   {
   4386     /* non-INFO checks must have an AML program */
   4387     GNUNET_break (0);
   4388     return TALER_EC_EXCHANGE_KYC_GENERIC_LOGIC_BUG;
   4389   }
   4390   for (unsigned int i = 0; i<kc->num_outputs; i++)
   4391   {
   4392     const char *rattr = kc->outputs[i];
   4393 
   4394     if (NULL == json_object_get (form_data,
   4395                                  rattr))
   4396     {
   4397       GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
   4398                   "Form data lacks required attribute `%s' for KYC check `%s'\n",
   4399                   rattr,
   4400                   check_name);
   4401       *error_message = rattr;
   4402       return TALER_EC_EXCHANGE_KYC_AML_FORM_INCOMPLETE;
   4403     }
   4404   }
   4405   prog = find_program (prog_name);
   4406   if (NULL == prog)
   4407   {
   4408     GNUNET_break (0);
   4409     *error_message = prog_name;
   4410     return TALER_EC_EXCHANGE_KYC_GENERIC_AML_PROGRAM_GONE;
   4411   }
   4412   for (unsigned int i = 0; i<prog->num_required_attributes; i++)
   4413   {
   4414     const char *rattr = prog->required_attributes[i];
   4415 
   4416     if (NULL == json_object_get (form_data,
   4417                                  rattr))
   4418     {
   4419       GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
   4420                   "Form data lacks required attribute `%s' for AML program %s\n",
   4421                   rattr,
   4422                   prog_name);
   4423       *error_message = rattr;
   4424       return TALER_EC_EXCHANGE_KYC_AML_FORM_INCOMPLETE;
   4425     }
   4426   }
   4427   *form_name = GNUNET_strdup (kc->details.form.name);
   4428   return TALER_EC_NONE;
   4429 }
   4430 
   4431 
   4432 const char *
   4433 TALER_KYCLOGIC_get_aml_program_fallback (const char *prog_name)
   4434 {
   4435   struct TALER_KYCLOGIC_AmlProgram *prog;
   4436 
   4437   prog = find_program (prog_name);
   4438   if (NULL == prog)
   4439   {
   4440     GNUNET_break (0);
   4441     return NULL;
   4442   }
   4443   return prog->fallback;
   4444 }
   4445 
   4446 
   4447 const struct TALER_KYCLOGIC_KycProvider *
   4448 TALER_KYCLOGIC_check_to_provider (const char *check_name)
   4449 {
   4450   struct TALER_KYCLOGIC_KycCheck *kc;
   4451 
   4452   if (NULL == check_name)
   4453     return NULL;
   4454   if (0 == strcasecmp (check_name,
   4455                        "skip"))
   4456     return NULL;
   4457   kc = find_check (check_name);
   4458   if (NULL == kc)
   4459   {
   4460     GNUNET_break (0);
   4461     return NULL;
   4462   }
   4463   switch (kc->type)
   4464   {
   4465   case TALER_KYCLOGIC_CT_FORM:
   4466   case TALER_KYCLOGIC_CT_INFO:
   4467     return NULL;
   4468   case TALER_KYCLOGIC_CT_LINK:
   4469     break;
   4470   }
   4471   return kc->details.link.provider;
   4472 }
   4473 
   4474 
   4475 struct TALER_KYCLOGIC_AmlProgramRunnerHandle
   4476 {
   4477   /**
   4478    * Function to call back with the result.
   4479    */
   4480   TALER_KYCLOGIC_AmlProgramResultCallback aprc;
   4481 
   4482   /**
   4483    * Closure for @e aprc.
   4484    */
   4485   void *aprc_cls;
   4486 
   4487   /**
   4488    * Handle to an external process.
   4489    */
   4490   struct TALER_JSON_ExternalConversion *proc;
   4491 
   4492   /**
   4493    * AML program to turn.
   4494    */
   4495   const struct TALER_KYCLOGIC_AmlProgram *program;
   4496 
   4497   /**
   4498    * Task to return @e apr result asynchronously.
   4499    */
   4500   struct GNUNET_SCHEDULER_Task *async_cb;
   4501 
   4502   /**
   4503    * Result returned to the client.
   4504    */
   4505   struct TALER_KYCLOGIC_AmlProgramResult apr;
   4506 
   4507   /**
   4508    * How long do we allow the AML program to run?
   4509    */
   4510   struct GNUNET_TIME_Relative timeout;
   4511 
   4512 };
   4513 
   4514 
   4515 /**
   4516  * Function that that receives a JSON @a result from
   4517  * the AML program.
   4518  *
   4519  * @param cls closure of type `struct TALER_KYCLOGIC_AmlProgramRunnerHandle`
   4520  * @param status_type how did the process die
   4521  * @param code termination status code from the process,
   4522  *        non-zero if AML checks are required next
   4523  * @param result some JSON result, NULL if we failed to get an JSON output
   4524  */
   4525 static void
   4526 handle_aml_output (
   4527   void *cls,
   4528   enum GNUNET_OS_ProcessStatusType status_type,
   4529   unsigned long code,
   4530   const json_t *result)
   4531 {
   4532   struct TALER_KYCLOGIC_AmlProgramRunnerHandle *aprh = cls;
   4533   const char *fallback_measure = aprh->program->fallback;
   4534   struct TALER_KYCLOGIC_AmlProgramResult *apr = &aprh->apr;
   4535   const char **evs = NULL;
   4536 
   4537   aprh->proc = NULL;
   4538   if (NULL != aprh->async_cb)
   4539   {
   4540     GNUNET_SCHEDULER_cancel (aprh->async_cb);
   4541     aprh->async_cb = NULL;
   4542   }
   4543 #if DEBUG
   4544   GNUNET_log (GNUNET_ERROR_TYPE_INFO,
   4545               "AML program %s output is:\n",
   4546               aprh->program->program_name);
   4547   json_dumpf (result,
   4548               stderr,
   4549               JSON_INDENT (2));
   4550 #endif
   4551   memset (apr,
   4552           0,
   4553           sizeof (*apr));
   4554   if ( (GNUNET_OS_PROCESS_EXITED != status_type) ||
   4555        (0 != code) )
   4556   {
   4557     GNUNET_log (GNUNET_ERROR_TYPE_WARNING,
   4558                 "AML program %s returned non-zero status %d/%d\n",
   4559                 aprh->program->program_name,
   4560                 (int) status_type,
   4561                 (int) code);
   4562     apr->status = TALER_KYCLOGIC_AMLR_FAILURE;
   4563     apr->details.failure.fallback_measure
   4564       = fallback_measure;
   4565     apr->details.failure.error_message
   4566       = "AML program returned non-zero exit code";
   4567     apr->details.failure.ec
   4568       = TALER_EC_EXCHANGE_KYC_AML_PROGRAM_FAILURE;
   4569     goto ready;
   4570   }
   4571 
   4572   {
   4573     const json_t *jevents = NULL;
   4574     struct GNUNET_JSON_Specification spec[] = {
   4575       GNUNET_JSON_spec_mark_optional (
   4576         GNUNET_JSON_spec_bool (
   4577           "to_investigate",
   4578           &apr->details.success.to_investigate),
   4579         NULL),
   4580       GNUNET_JSON_spec_mark_optional (
   4581         GNUNET_JSON_spec_object_const (
   4582           "properties",
   4583           &apr->details.success.account_properties),
   4584         NULL),
   4585       GNUNET_JSON_spec_mark_optional (
   4586         GNUNET_JSON_spec_array_const (
   4587           "events",
   4588           &jevents),
   4589         NULL),
   4590       GNUNET_JSON_spec_object_const (
   4591         "new_rules",
   4592         &apr->details.success.new_rules),
   4593       GNUNET_JSON_spec_mark_optional (
   4594         GNUNET_JSON_spec_string (
   4595           "new_measures",
   4596           &apr->details.success.new_measures),
   4597         NULL),
   4598       GNUNET_JSON_spec_end ()
   4599     };
   4600     const char *err;
   4601     unsigned int line;
   4602 
   4603     if (GNUNET_OK !=
   4604         GNUNET_JSON_parse (result,
   4605                            spec,
   4606                            &err,
   4607                            &line))
   4608     {
   4609       GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
   4610                   "AML program output is malformed at `%s'\n",
   4611                   err);
   4612       json_dumpf (result,
   4613                   stderr,
   4614                   JSON_INDENT (2));
   4615       apr->status = TALER_KYCLOGIC_AMLR_FAILURE;
   4616       apr->details.failure.fallback_measure
   4617         = fallback_measure;
   4618       apr->details.failure.error_message
   4619         = err;
   4620       apr->details.failure.ec
   4621         = TALER_EC_EXCHANGE_KYC_AML_PROGRAM_MALFORMED_RESULT;
   4622       goto ready;
   4623     }
   4624     apr->details.success.num_events
   4625       = json_array_size (jevents);
   4626 
   4627     GNUNET_assert (((size_t) apr->details.success.num_events) ==
   4628                    json_array_size (jevents));
   4629     evs = GNUNET_new_array (
   4630       apr->details.success.num_events,
   4631       const char *);
   4632     for (unsigned int i = 0; i<apr->details.success.num_events; i++)
   4633     {
   4634       evs[i] = json_string_value (
   4635         json_array_get (jevents,
   4636                         i));
   4637       if (NULL == evs[i])
   4638       {
   4639         apr->status = TALER_KYCLOGIC_AMLR_FAILURE;
   4640         apr->details.failure.fallback_measure
   4641           = fallback_measure;
   4642         apr->details.failure.error_message
   4643           = "events";
   4644         apr->details.failure.ec
   4645           = TALER_EC_EXCHANGE_KYC_AML_PROGRAM_MALFORMED_RESULT;
   4646         goto ready;
   4647       }
   4648     }
   4649     apr->status = TALER_KYCLOGIC_AMLR_SUCCESS;
   4650     apr->details.success.events = evs;
   4651     {
   4652       /* check new_rules */
   4653       struct TALER_KYCLOGIC_LegitimizationRuleSet *lrs;
   4654 
   4655       lrs = TALER_KYCLOGIC_rules_parse (
   4656         apr->details.success.new_rules);
   4657       if (NULL == lrs)
   4658       {
   4659         GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
   4660                     "AML program output is malformed at `%s'\n",
   4661                     "new_rules");
   4662 
   4663         apr->status = TALER_KYCLOGIC_AMLR_FAILURE;
   4664         apr->details.failure.fallback_measure
   4665           = fallback_measure;
   4666         apr->details.failure.error_message
   4667           = "new_rules";
   4668         apr->details.failure.ec
   4669           = TALER_EC_EXCHANGE_KYC_AML_PROGRAM_MALFORMED_RESULT;
   4670         goto ready;
   4671       }
   4672       apr->details.success.expiration_time
   4673         = lrs->expiration_time;
   4674       TALER_KYCLOGIC_rules_free (lrs);
   4675     }
   4676   }
   4677 ready:
   4678   aprh->aprc (aprh->aprc_cls,
   4679               &aprh->apr);
   4680   GNUNET_free (evs);
   4681   TALER_KYCLOGIC_run_aml_program_cancel (aprh);
   4682 }
   4683 
   4684 
   4685 /**
   4686  * Helper function to asynchronously return the result.
   4687  *
   4688  * @param[in] cls a `struct TALER_KYCLOGIC_AmlProgramRunnerHandle` to return results for
   4689  */
   4690 static void
   4691 async_return_task (void *cls)
   4692 {
   4693   struct TALER_KYCLOGIC_AmlProgramRunnerHandle *aprh = cls;
   4694 
   4695   aprh->async_cb = NULL;
   4696   aprh->aprc (aprh->aprc_cls,
   4697               &aprh->apr);
   4698   TALER_KYCLOGIC_run_aml_program_cancel (aprh);
   4699 }
   4700 
   4701 
   4702 /**
   4703  * Helper function called on timeout on the fallback measure.
   4704  *
   4705  * @param[in] cls a `struct TALER_KYCLOGIC_AmlProgramRunnerHandle` to return results for
   4706  */
   4707 static void
   4708 handle_aml_timeout2 (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 
   4714   GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
   4715               "Fallback measure %s ran into timeout (!)\n",
   4716               aprh->program->program_name);
   4717   if (NULL != aprh->proc)
   4718   {
   4719     TALER_JSON_external_conversion_stop (aprh->proc);
   4720     aprh->proc = NULL;
   4721   }
   4722   apr->status = TALER_KYCLOGIC_AMLR_FAILURE;
   4723   apr->details.failure.fallback_measure
   4724     = fallback_measure;
   4725   apr->details.failure.error_message
   4726     = aprh->program->program_name;
   4727   apr->details.failure.ec
   4728     = TALER_EC_EXCHANGE_KYC_GENERIC_AML_PROGRAM_TIMEOUT;
   4729   async_return_task (aprh);
   4730 }
   4731 
   4732 
   4733 /**
   4734  * Helper function called on timeout of an AML program.
   4735  * Runs the fallback measure.
   4736  *
   4737  * @param[in] cls a `struct TALER_KYCLOGIC_AmlProgramRunnerHandle` to return results for
   4738  */
   4739 static void
   4740 handle_aml_timeout (void *cls)
   4741 {
   4742   struct TALER_KYCLOGIC_AmlProgramRunnerHandle *aprh = cls;
   4743   struct TALER_KYCLOGIC_AmlProgramResult *apr = &aprh->apr;
   4744   const char *fallback_measure = aprh->program->fallback;
   4745   const struct TALER_KYCLOGIC_Measure *m;
   4746   const struct TALER_KYCLOGIC_AmlProgram *fprogram;
   4747 
   4748   aprh->async_cb = NULL;
   4749   GNUNET_assert (NULL != fallback_measure);
   4750   GNUNET_log (GNUNET_ERROR_TYPE_WARNING,
   4751               "AML program %s ran into timeout\n",
   4752               aprh->program->program_name);
   4753   if (NULL != aprh->proc)
   4754   {
   4755     TALER_JSON_external_conversion_stop (aprh->proc);
   4756     aprh->proc = NULL;
   4757   }
   4758 
   4759   m = TALER_KYCLOGIC_get_measure (&default_rules,
   4760                                   fallback_measure);
   4761   /* Fallback program could have "disappeared" due to configuration change,
   4762      as we do not check all rule sets in the database when our configuration
   4763      is updated... */
   4764   if (NULL == m)
   4765   {
   4766     GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
   4767                 "Fallback measure `%s' does not exist (anymore?).\n",
   4768                 fallback_measure);
   4769     apr->status = TALER_KYCLOGIC_AMLR_FAILURE;
   4770     apr->details.failure.fallback_measure
   4771       = fallback_measure;
   4772     apr->details.failure.error_message
   4773       = aprh->program->program_name;
   4774     apr->details.failure.ec
   4775       = TALER_EC_EXCHANGE_KYC_GENERIC_AML_PROGRAM_TIMEOUT;
   4776     async_return_task (aprh);
   4777     return;
   4778   }
   4779   /* We require fallback measures to have a 'skip' check */
   4780   GNUNET_break (0 ==
   4781                 strcasecmp (m->check_name,
   4782                             "skip"));
   4783   fprogram = find_program (m->prog_name);
   4784   /* Program associated with an original measure must exist */
   4785   GNUNET_assert (NULL != fprogram);
   4786   if (API_NONE != (fprogram->input_mask & (API_CONTEXT | API_ATTRIBUTES)))
   4787   {
   4788     /* We might not have recognized the fallback measure as such
   4789        because it was not used as such in the plain configuration,
   4790        and legitimization rule sets might have referred to an older
   4791        configuration. So this should be super-rare but possible. */
   4792     GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
   4793                 "Program `%s' used in fallback measure `%s' requires inputs and is thus unsuitable as a fallback measure!\n",
   4794                 m->prog_name,
   4795                 fallback_measure);
   4796     apr->status = TALER_KYCLOGIC_AMLR_FAILURE;
   4797     apr->details.failure.fallback_measure
   4798       = fallback_measure;
   4799     apr->details.failure.error_message
   4800       = aprh->program->program_name;
   4801     apr->details.failure.ec
   4802       = TALER_EC_EXCHANGE_KYC_GENERIC_AML_PROGRAM_TIMEOUT;
   4803     async_return_task (aprh);
   4804     return;
   4805   }
   4806   {
   4807     /* Run fallback AML program */
   4808     json_t *input = json_object ();
   4809     const char *extra_args[] = {
   4810       "-c",
   4811       cfg_filename,
   4812       NULL,
   4813     };
   4814     char **args;
   4815 
   4816     args = TALER_words_split (fprogram->command,
   4817                               extra_args);
   4818     GNUNET_log (GNUNET_ERROR_TYPE_INFO,
   4819                 "Running fallback measure `%s' (%s)\n",
   4820                 fallback_measure,
   4821                 fprogram->command);
   4822     aprh->proc = TALER_JSON_external_conversion_start (
   4823       input,
   4824       &handle_aml_output,
   4825       aprh,
   4826       args[0],
   4827       (const char **) args);
   4828     TALER_words_destroy (args);
   4829     json_decref (input);
   4830   }
   4831   aprh->async_cb = GNUNET_SCHEDULER_add_delayed (aprh->timeout,
   4832                                                  &handle_aml_timeout2,
   4833                                                  aprh);
   4834 }
   4835 
   4836 
   4837 struct TALER_KYCLOGIC_AmlProgramRunnerHandle *
   4838 TALER_KYCLOGIC_run_aml_program (
   4839   const json_t *jmeasures,
   4840   bool is_wallet,
   4841   unsigned int measure_index,
   4842   TALER_KYCLOGIC_HistoryBuilderCallback current_attributes_cb,
   4843   void *current_attributes_cb_cls,
   4844   TALER_KYCLOGIC_HistoryBuilderCallback current_rules_cb,
   4845   void *current_rules_cb_cls,
   4846   TALER_KYCLOGIC_HistoryBuilderCallback aml_history_cb,
   4847   void *aml_history_cb_cls,
   4848   TALER_KYCLOGIC_HistoryBuilderCallback kyc_history_cb,
   4849   void *kyc_history_cb_cls,
   4850   struct GNUNET_TIME_Relative timeout,
   4851   TALER_KYCLOGIC_AmlProgramResultCallback aprc,
   4852   void *aprc_cls)
   4853 {
   4854   const json_t *context;
   4855   const char *check_name;
   4856   const char *prog_name;
   4857 
   4858   {
   4859     enum TALER_ErrorCode ec;
   4860 
   4861     ec = TALER_KYCLOGIC_select_measure (jmeasures,
   4862                                         measure_index,
   4863                                         &check_name,
   4864                                         &prog_name,
   4865                                         &context);
   4866     if (TALER_EC_NONE != ec)
   4867     {
   4868       GNUNET_break (0);
   4869       return NULL;
   4870     }
   4871   }
   4872   if (NULL == prog_name)
   4873   {
   4874     /* Trying to run AML program on a measure that does not
   4875        have one, and that should thus be an INFO check which
   4876        should never lead here. Very strange. */
   4877     GNUNET_break (0);
   4878     GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
   4879                 "Measure %u with check `%s' does not have an AML program!\n",
   4880                 measure_index,
   4881                 check_name);
   4882     json_dumpf (jmeasures,
   4883                 stderr,
   4884                 JSON_INDENT (2));
   4885     return NULL;
   4886   }
   4887   return TALER_KYCLOGIC_run_aml_program2 (prog_name,
   4888                                           context,
   4889                                           is_wallet,
   4890                                           current_attributes_cb,
   4891                                           current_attributes_cb_cls,
   4892                                           current_rules_cb,
   4893                                           current_rules_cb_cls,
   4894                                           aml_history_cb,
   4895                                           aml_history_cb_cls,
   4896                                           kyc_history_cb,
   4897                                           kyc_history_cb_cls,
   4898                                           timeout,
   4899                                           aprc,
   4900                                           aprc_cls);
   4901 }
   4902 
   4903 
   4904 struct TALER_KYCLOGIC_AmlProgramRunnerHandle *
   4905 TALER_KYCLOGIC_run_aml_program2 (
   4906   const char *prog_name,
   4907   const json_t *context,
   4908   bool is_wallet,
   4909   TALER_KYCLOGIC_HistoryBuilderCallback current_attributes_cb,
   4910   void *current_attributes_cb_cls,
   4911   TALER_KYCLOGIC_HistoryBuilderCallback current_rules_cb,
   4912   void *current_rules_cb_cls,
   4913   TALER_KYCLOGIC_HistoryBuilderCallback aml_history_cb,
   4914   void *aml_history_cb_cls,
   4915   TALER_KYCLOGIC_HistoryBuilderCallback kyc_history_cb,
   4916   void *kyc_history_cb_cls,
   4917   struct GNUNET_TIME_Relative timeout,
   4918   TALER_KYCLOGIC_AmlProgramResultCallback aprc,
   4919   void *aprc_cls)
   4920 {
   4921   struct TALER_KYCLOGIC_AmlProgramRunnerHandle *aprh;
   4922   struct TALER_KYCLOGIC_AmlProgram *prog;
   4923   const json_t *jdefault_rules;
   4924   json_t *current_rules;
   4925   json_t *aml_history;
   4926   json_t *kyc_history;
   4927   json_t *attributes;
   4928 
   4929   prog = find_program (prog_name);
   4930   if (NULL == prog)
   4931   {
   4932     GNUNET_break (0);
   4933     return NULL;
   4934   }
   4935   aprh = GNUNET_new (struct TALER_KYCLOGIC_AmlProgramRunnerHandle);
   4936   aprh->aprc = aprc;
   4937   aprh->aprc_cls = aprc_cls;
   4938   aprh->program = prog;
   4939   if (0 != (API_ATTRIBUTES & prog->input_mask))
   4940   {
   4941     attributes = current_attributes_cb (current_attributes_cb_cls);
   4942 #if DEBUG
   4943     GNUNET_log (GNUNET_ERROR_TYPE_INFO,
   4944                 "KYC attributes for AML program %s are:\n",
   4945                 prog_name);
   4946     json_dumpf (attributes,
   4947                 stderr,
   4948                 JSON_INDENT (2));
   4949     fprintf (stderr,
   4950              "\n");
   4951 #endif
   4952     for (unsigned int i = 0; i<prog->num_required_attributes; i++)
   4953     {
   4954       const char *rattr = prog->required_attributes[i];
   4955 
   4956       if (NULL == json_object_get (attributes,
   4957                                    rattr))
   4958       {
   4959         GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
   4960                     "KYC attributes lack required attribute `%s' for AML program %s\n",
   4961                     rattr,
   4962                     prog->program_name);
   4963 #if DEBUG
   4964         json_dumpf (attributes,
   4965                     stderr,
   4966                     JSON_INDENT (2));
   4967 #endif
   4968         aprh->apr.status = TALER_KYCLOGIC_AMLR_FAILURE;
   4969         aprh->apr.details.failure.fallback_measure
   4970           = prog->fallback;
   4971         aprh->apr.details.failure.error_message
   4972           = rattr;
   4973         aprh->apr.details.failure.ec
   4974           = TALER_EC_EXCHANGE_KYC_GENERIC_PROVIDER_INCOMPLETE_REPLY;
   4975         aprh->async_cb
   4976           = GNUNET_SCHEDULER_add_now (&async_return_task,
   4977                                       aprh);
   4978         json_decref (attributes);
   4979         return aprh;
   4980       }
   4981     }
   4982   }
   4983   else
   4984   {
   4985     attributes = NULL;
   4986   }
   4987   if (0 != (API_CONTEXT & prog->input_mask))
   4988   {
   4989     for (unsigned int i = 0; i<prog->num_required_contexts; i++)
   4990     {
   4991       const char *rctx = prog->required_contexts[i];
   4992 
   4993       if (NULL == json_object_get (context,
   4994                                    rctx))
   4995       {
   4996         GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
   4997                     "Context lacks required field `%s' for AML program %s\n",
   4998                     rctx,
   4999                     prog->program_name);
   5000 #if DEBUG
   5001         json_dumpf (context,
   5002                     stderr,
   5003                     JSON_INDENT (2));
   5004 #endif
   5005         aprh->apr.status = TALER_KYCLOGIC_AMLR_FAILURE;
   5006         aprh->apr.details.failure.fallback_measure
   5007           = prog->fallback;
   5008         aprh->apr.details.failure.error_message
   5009           = rctx;
   5010         aprh->apr.details.failure.ec
   5011           = TALER_EC_EXCHANGE_KYC_GENERIC_PROVIDER_INCOMPLETE_CONTEXT;
   5012         aprh->async_cb
   5013           = GNUNET_SCHEDULER_add_now (&async_return_task,
   5014                                       aprh);
   5015         json_decref (attributes);
   5016         return aprh;
   5017       }
   5018     }
   5019   }
   5020   else
   5021   {
   5022     context = NULL;
   5023   }
   5024   if (0 == (API_AML_HISTORY & prog->input_mask))
   5025     aml_history = NULL;
   5026   else
   5027     aml_history = aml_history_cb (aml_history_cb_cls);
   5028   if (0 == (API_KYC_HISTORY & prog->input_mask))
   5029     kyc_history = NULL;
   5030   else
   5031     kyc_history = kyc_history_cb (kyc_history_cb_cls);
   5032   if (0 == (API_CURRENT_RULES & prog->input_mask))
   5033     current_rules = NULL;
   5034   else
   5035     current_rules = current_rules_cb (current_rules_cb_cls);
   5036   if (0 != (API_DEFAULT_RULES & prog->input_mask))
   5037     jdefault_rules =
   5038       (is_wallet
   5039        ? wallet_default_lrs
   5040        : bankaccount_default_lrs);
   5041   else
   5042     jdefault_rules = NULL;
   5043   {
   5044     json_t *input;
   5045     const char *extra_args[] = {
   5046       "-c",
   5047       cfg_filename,
   5048       NULL,
   5049     };
   5050     char **args;
   5051 
   5052     input = GNUNET_JSON_PACK (
   5053       GNUNET_JSON_pack_allow_null (
   5054         GNUNET_JSON_pack_object_steal ("current_rules",
   5055                                        current_rules)),
   5056       GNUNET_JSON_pack_allow_null (
   5057         GNUNET_JSON_pack_object_incref ("default_rules",
   5058                                         (json_t *) jdefault_rules)),
   5059       GNUNET_JSON_pack_allow_null (
   5060         GNUNET_JSON_pack_object_incref ("context",
   5061                                         (json_t *) context)),
   5062       GNUNET_JSON_pack_allow_null (
   5063         GNUNET_JSON_pack_object_steal ("attributes",
   5064                                        attributes)),
   5065       GNUNET_JSON_pack_allow_null (
   5066         GNUNET_JSON_pack_array_steal ("aml_history",
   5067                                       aml_history)),
   5068       GNUNET_JSON_pack_allow_null (
   5069         GNUNET_JSON_pack_array_steal ("kyc_history",
   5070                                       kyc_history))
   5071       );
   5072     GNUNET_log (GNUNET_ERROR_TYPE_INFO,
   5073                 "Running AML program %s\n",
   5074                 prog->command);
   5075     args = TALER_words_split (prog->command,
   5076                               extra_args);
   5077     GNUNET_assert (NULL != args);
   5078     GNUNET_assert (NULL != args[0]);
   5079 #if DEBUG
   5080     json_dumpf (input,
   5081                 stderr,
   5082                 JSON_INDENT (2));
   5083 #endif
   5084     aprh->proc = TALER_JSON_external_conversion_start (
   5085       input,
   5086       &handle_aml_output,
   5087       aprh,
   5088       args[0],
   5089       (const char **) args);
   5090     TALER_words_destroy (args);
   5091     json_decref (input);
   5092   }
   5093   aprh->timeout = timeout;
   5094   aprh->async_cb = GNUNET_SCHEDULER_add_delayed (timeout,
   5095                                                  &handle_aml_timeout,
   5096                                                  aprh);
   5097   return aprh;
   5098 }
   5099 
   5100 
   5101 struct TALER_KYCLOGIC_AmlProgramRunnerHandle *
   5102 TALER_KYCLOGIC_run_aml_program3 (
   5103   bool is_wallet,
   5104   const struct TALER_KYCLOGIC_Measure *measure,
   5105   TALER_KYCLOGIC_HistoryBuilderCallback current_attributes_cb,
   5106   void *current_attributes_cb_cls,
   5107   TALER_KYCLOGIC_HistoryBuilderCallback current_rules_cb,
   5108   void *current_rules_cb_cls,
   5109   TALER_KYCLOGIC_HistoryBuilderCallback aml_history_cb,
   5110   void *aml_history_cb_cls,
   5111   TALER_KYCLOGIC_HistoryBuilderCallback kyc_history_cb,
   5112   void *kyc_history_cb_cls,
   5113   struct GNUNET_TIME_Relative timeout,
   5114   TALER_KYCLOGIC_AmlProgramResultCallback aprc,
   5115   void *aprc_cls)
   5116 {
   5117   return TALER_KYCLOGIC_run_aml_program2 (
   5118     measure->prog_name,
   5119     measure->context,
   5120     is_wallet,
   5121     current_attributes_cb,
   5122     current_attributes_cb_cls,
   5123     current_rules_cb,
   5124     current_rules_cb_cls,
   5125     aml_history_cb,
   5126     aml_history_cb_cls,
   5127     kyc_history_cb,
   5128     kyc_history_cb_cls,
   5129     timeout,
   5130     aprc,
   5131     aprc_cls);
   5132 }
   5133 
   5134 
   5135 const char *
   5136 TALER_KYCLOGIC_run_aml_program_get_name (
   5137   const struct TALER_KYCLOGIC_AmlProgramRunnerHandle *aprh)
   5138 {
   5139   return aprh->program->program_name;
   5140 }
   5141 
   5142 
   5143 void
   5144 TALER_KYCLOGIC_run_aml_program_cancel (
   5145   struct TALER_KYCLOGIC_AmlProgramRunnerHandle *aprh)
   5146 {
   5147   if (NULL != aprh->proc)
   5148   {
   5149     GNUNET_log (GNUNET_ERROR_TYPE_WARNING,
   5150                 "Killing AML program\n");
   5151     TALER_JSON_external_conversion_stop (aprh->proc);
   5152     aprh->proc = NULL;
   5153   }
   5154   if (NULL != aprh->async_cb)
   5155   {
   5156     GNUNET_SCHEDULER_cancel (aprh->async_cb);
   5157     aprh->async_cb = NULL;
   5158   }
   5159   GNUNET_free (aprh);
   5160 }
   5161 
   5162 
   5163 json_t *
   5164 TALER_KYCLOGIC_get_hard_limits ()
   5165 {
   5166   const struct TALER_KYCLOGIC_KycRule *rules
   5167     = default_rules.kyc_rules;
   5168   unsigned int num_rules
   5169     = default_rules.num_kyc_rules;
   5170   json_t *hard_limits;
   5171 
   5172   hard_limits = json_array ();
   5173   GNUNET_assert (NULL != hard_limits);
   5174   for (unsigned int i = 0; i<num_rules; i++)
   5175   {
   5176     const struct TALER_KYCLOGIC_KycRule *rule = &rules[i];
   5177     json_t *hard_limit;
   5178 
   5179     if (! rule->verboten)
   5180       continue;
   5181     if (! rule->exposed)
   5182       continue;
   5183     hard_limit = GNUNET_JSON_PACK (
   5184       GNUNET_JSON_pack_allow_null (
   5185         GNUNET_JSON_pack_string ("rule_name",
   5186                                  rule->rule_name)),
   5187       TALER_JSON_pack_kycte ("operation_type",
   5188                              rule->trigger),
   5189       GNUNET_JSON_pack_time_rel ("timeframe",
   5190                                  rule->timeframe),
   5191       TALER_JSON_pack_amount ("threshold",
   5192                               &rule->threshold)
   5193       );
   5194     GNUNET_assert (0 ==
   5195                    json_array_append_new (hard_limits,
   5196                                           hard_limit));
   5197   }
   5198   return hard_limits;
   5199 }
   5200 
   5201 
   5202 json_t *
   5203 TALER_KYCLOGIC_get_zero_limits ()
   5204 {
   5205   const struct TALER_KYCLOGIC_KycRule *rules
   5206     = default_rules.kyc_rules;
   5207   unsigned int num_rules
   5208     = default_rules.num_kyc_rules;
   5209   json_t *zero_limits;
   5210 
   5211   zero_limits = json_array ();
   5212   GNUNET_assert (NULL != zero_limits);
   5213   for (unsigned int i = 0; i<num_rules; i++)
   5214   {
   5215     const struct TALER_KYCLOGIC_KycRule *rule = &rules[i];
   5216     json_t *zero_limit;
   5217 
   5218     if (! rule->exposed)
   5219       continue;
   5220     if (rule->verboten)
   5221       continue; /* see: hard_limits */
   5222     if (! TALER_amount_is_zero (&rule->threshold))
   5223       continue;
   5224     zero_limit = GNUNET_JSON_PACK (
   5225       GNUNET_JSON_pack_allow_null (
   5226         GNUNET_JSON_pack_string ("rule_name",
   5227                                  rule->rule_name)),
   5228       TALER_JSON_pack_kycte ("operation_type",
   5229                              rule->trigger));
   5230     GNUNET_assert (0 ==
   5231                    json_array_append_new (zero_limits,
   5232                                           zero_limit));
   5233   }
   5234   return zero_limits;
   5235 }
   5236 
   5237 
   5238 json_t *
   5239 TALER_KYCLOGIC_get_default_legi_rules (bool for_wallet)
   5240 {
   5241   const json_t *r;
   5242 
   5243   r = (for_wallet
   5244        ? wallet_default_lrs
   5245        : bankaccount_default_lrs);
   5246   return json_incref ((json_t *) r);
   5247 }
   5248 
   5249 
   5250 /* end of kyclogic_api.c */