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


      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     for (unsigned int j = 0; j < rule->num_measures; j++)
   1345     {
   1346       const struct TALER_KYCLOGIC_Measure *m;
   1347       const struct TALER_KYCLOGIC_KycCheck *c;
   1348 
   1349       /* Resolve the measure to its check exactly as GET /kyc-info does
   1350          (measure -> check -> form), so that our answer is consistent
   1351          with the requirements the merchant will observe there. */
   1352       m = find_measure (lrs,
   1353                         rule->next_measures[j]);
   1354       if (NULL == m)
   1355         continue;
   1356       c = find_check (m->check_name);
   1357       if (NULL == c)
   1358         continue;
   1359       if ( (TALER_KYCLOGIC_CT_FORM == c->type) &&
   1360            (NULL != c->details.form.name) &&
   1361            (0 == strcasecmp (c->details.form.name,
   1362                              TALER_KYCLOGIC_TOS_ACCEPTANCE_FORM)) )
   1363       {
   1364         found = true;
   1365         break;
   1366       }
   1367     }
   1368   }
   1369   if (NULL != lrs)
   1370     TALER_KYCLOGIC_rules_free (lrs);
   1371   return found;
   1372 }
   1373 
   1374 
   1375 const struct TALER_KYCLOGIC_Measure *
   1376 TALER_KYCLOGIC_rule_get_instant_measure (
   1377   const struct TALER_KYCLOGIC_KycRule *r)
   1378 {
   1379   const struct TALER_KYCLOGIC_LegitimizationRuleSet *lrs
   1380     = r->lrs;
   1381 
   1382   if (r->verboten)
   1383     return NULL;
   1384   for (unsigned int i = 0; i<r->num_measures; i++)
   1385   {
   1386     const char *measure_name = r->next_measures[i];
   1387     const struct TALER_KYCLOGIC_Measure *ms;
   1388 
   1389     if (0 == strcasecmp (measure_name,
   1390                          KYC_MEASURE_IMPOSSIBLE))
   1391     {
   1392       /* If any of the measures if verboten, we do not even
   1393       consider execution of the instant measure. */
   1394       return NULL;
   1395     }
   1396 
   1397     ms = find_measure (lrs,
   1398                        measure_name);
   1399     if (NULL == ms)
   1400     {
   1401       GNUNET_break (0);
   1402       return NULL;
   1403     }
   1404     if (0 == strcasecmp (ms->check_name,
   1405                          "skip"))
   1406       return ms;
   1407   }
   1408   return NULL;
   1409 }
   1410 
   1411 
   1412 json_t *
   1413 TALER_KYCLOGIC_rule_to_measures (
   1414   const struct TALER_KYCLOGIC_KycRule *r)
   1415 {
   1416   const struct TALER_KYCLOGIC_LegitimizationRuleSet *lrs
   1417     = r->lrs;
   1418   json_t *jmeasures;
   1419 
   1420   jmeasures = json_array ();
   1421   GNUNET_assert (NULL != jmeasures);
   1422   if (! r->verboten)
   1423   {
   1424     for (unsigned int i = 0; i<r->num_measures; i++)
   1425     {
   1426       const char *measure_name = r->next_measures[i];
   1427       const struct TALER_KYCLOGIC_Measure *ms;
   1428       json_t *mi;
   1429 
   1430       if (0 ==
   1431           strcasecmp (measure_name,
   1432                       KYC_MEASURE_IMPOSSIBLE))
   1433       {
   1434         /* This case should be covered via the 'verboten' flag! */
   1435         GNUNET_break (0);
   1436         continue;
   1437       }
   1438       ms = find_measure (lrs,
   1439                          measure_name);
   1440       if (NULL == ms)
   1441       {
   1442         GNUNET_break (0);
   1443         json_decref (jmeasures);
   1444         return NULL;
   1445       }
   1446       mi = GNUNET_JSON_PACK (
   1447         GNUNET_JSON_pack_string ("check_name",
   1448                                  ms->check_name),
   1449         GNUNET_JSON_pack_allow_null (
   1450           GNUNET_JSON_pack_string ("prog_name",
   1451                                    ms->prog_name)),
   1452         GNUNET_JSON_pack_allow_null (
   1453           GNUNET_JSON_pack_object_incref ("context",
   1454                                           ms->context)));
   1455       GNUNET_assert (0 ==
   1456                      json_array_append_new (jmeasures,
   1457                                             mi));
   1458     }
   1459   }
   1460 
   1461   return GNUNET_JSON_PACK (
   1462     GNUNET_JSON_pack_array_steal ("measures",
   1463                                   jmeasures),
   1464     GNUNET_JSON_pack_bool ("is_and_combinator",
   1465                            r->is_and_combinator),
   1466     GNUNET_JSON_pack_bool ("verboten",
   1467                            r->verboten));
   1468 }
   1469 
   1470 
   1471 json_t *
   1472 TALER_KYCLOGIC_zero_measures (
   1473   const struct TALER_KYCLOGIC_LegitimizationRuleSet *lrs,
   1474   enum GNUNET_GenericReturnValue is_wallet)
   1475 {
   1476   json_t *zero_measures;
   1477   const struct TALER_KYCLOGIC_KycRule *rules;
   1478   unsigned int num_zero_measures = 0;
   1479 
   1480   if (NULL == lrs)
   1481     lrs = &default_rules;
   1482   rules = lrs->kyc_rules;
   1483   zero_measures = json_array ();
   1484   GNUNET_assert (NULL != zero_measures);
   1485   for (unsigned int i = 0; i<lrs->num_kyc_rules; i++)
   1486   {
   1487     const struct TALER_KYCLOGIC_KycRule *rule = &rules[i];
   1488 
   1489     if (! rule->exposed)
   1490       continue;
   1491     if (rule->verboten)
   1492       continue; /* see: hard_limits */
   1493     if (! trigger_applies (rule->trigger,
   1494                            is_wallet))
   1495       continue;
   1496     if (! TALER_amount_is_zero (&rule->threshold))
   1497       continue;
   1498     for (unsigned int j = 0; j<rule->num_measures; j++)
   1499     {
   1500       const struct TALER_KYCLOGIC_Measure *ms;
   1501       json_t *mi;
   1502 
   1503       ms = find_measure (lrs,
   1504                          rule->next_measures[j]);
   1505       if (NULL == ms)
   1506       {
   1507         /* Error in the configuration, should've been
   1508          * caught before. We simply ignore the bad measure. */
   1509         GNUNET_break (0);
   1510         continue;
   1511       }
   1512       if (0 == strcasecmp (KYC_MEASURE_IMPOSSIBLE,
   1513                            ms->check_name))
   1514         continue; /* not a measure to be selected */
   1515       mi = GNUNET_JSON_PACK (
   1516         GNUNET_JSON_pack_allow_null (
   1517           GNUNET_JSON_pack_string ("rule_name",
   1518                                    rule->rule_name)),
   1519         TALER_JSON_pack_kycte ("operation_type",
   1520                                rule->trigger),
   1521         GNUNET_JSON_pack_string ("check_name",
   1522                                  ms->check_name),
   1523         GNUNET_JSON_pack_allow_null (
   1524           GNUNET_JSON_pack_string ("prog_name",
   1525                                    ms->prog_name)),
   1526         GNUNET_JSON_pack_allow_null (
   1527           GNUNET_JSON_pack_object_incref ("context",
   1528                                           ms->context)));
   1529       GNUNET_assert (0 ==
   1530                      json_array_append_new (zero_measures,
   1531                                             mi));
   1532       num_zero_measures++;
   1533     }
   1534   }
   1535   if (0 == num_zero_measures)
   1536   {
   1537     json_decref (zero_measures);
   1538     return NULL;
   1539   }
   1540   return GNUNET_JSON_PACK (
   1541     GNUNET_JSON_pack_array_steal ("measures",
   1542                                   zero_measures),
   1543     /* Zero-measures are always OR */
   1544     GNUNET_JSON_pack_bool ("is_and_combinator",
   1545                            false),
   1546     /* OR means verboten measures do not matter */
   1547     GNUNET_JSON_pack_bool ("verboten",
   1548                            false));
   1549 }
   1550 
   1551 
   1552 /**
   1553  * Check if @a ms is a voluntary measure, and if so
   1554  * convert to JSON and append to @a voluntary_measures.
   1555  *
   1556  * @param[in,out] voluntary_measures JSON array of MeasureInformation
   1557  * @param ms a measure to possibly append
   1558  */
   1559 static void
   1560 append_voluntary_measure (
   1561   json_t *voluntary_measures,
   1562   const struct TALER_KYCLOGIC_Measure *ms)
   1563 {
   1564 #if 0
   1565   json_t *mj;
   1566 #endif
   1567 
   1568   if (! ms->voluntary)
   1569     return;
   1570   if (0 == strcasecmp (KYC_MEASURE_IMPOSSIBLE,
   1571                        ms->check_name))
   1572     return; /* very strange configuration */
   1573 #if 0
   1574   /* FIXME: support vATTEST-#9048 (this API in kyclogic!) */
   1575   // NOTE: need to convert ms to "KycRequirementInformation"
   1576   // *and* in particular generate "id" values that
   1577   // are then understood to refer to the voluntary measures
   1578   // by the rest of the API (which is the hard part!)
   1579   // => need to change the API to encode the
   1580   // legitimization_outcomes row ID of the lrs from
   1581   // which the voluntary 'ms' originated, and
   1582   // then update the kyc-upload/kyc-start endpoints
   1583   // to recognize the new ID format!
   1584   mj = GNUNET_JSON_PACK (
   1585     GNUNET_JSON_pack_string ("check_name",
   1586                              ms->check_name),
   1587     GNUNET_JSON_pack_allow_null (
   1588       GNUNET_JSON_pack_string ("prog_name",
   1589                                ms->prog_name)),
   1590     GNUNET_JSON_pack_allow_null (
   1591       GNUNET_JSON_pack_object_incref ("context",
   1592                                       ms->context)));
   1593   GNUNET_assert (0 ==
   1594                  json_array_append_new (voluntary_measures,
   1595                                         mj));
   1596 #endif
   1597 }
   1598 
   1599 
   1600 json_t *
   1601 TALER_KYCLOGIC_voluntary_measures (
   1602   const struct TALER_KYCLOGIC_LegitimizationRuleSet *lrs)
   1603 {
   1604   json_t *voluntary_measures;
   1605 
   1606   voluntary_measures = json_array ();
   1607   GNUNET_assert (NULL != voluntary_measures);
   1608   if (NULL != lrs)
   1609   {
   1610     for (unsigned int i = 0; i<lrs->num_custom_measures; i++)
   1611     {
   1612       const struct TALER_KYCLOGIC_Measure *ms
   1613         = &lrs->custom_measures[i];
   1614 
   1615       append_voluntary_measure (voluntary_measures,
   1616                                 ms);
   1617     }
   1618   }
   1619   for (unsigned int i = 0; i<default_rules.num_custom_measures; i++)
   1620   {
   1621     const struct TALER_KYCLOGIC_Measure *ms
   1622       = &default_rules.custom_measures[i];
   1623 
   1624     append_voluntary_measure (voluntary_measures,
   1625                               ms);
   1626   }
   1627   return voluntary_measures;
   1628 }
   1629 
   1630 
   1631 const struct TALER_KYCLOGIC_Measure *
   1632 TALER_KYCLOGIC_get_instant_measure (
   1633   const struct TALER_KYCLOGIC_LegitimizationRuleSet *lrs,
   1634   const char *measures_spec)
   1635 {
   1636   char *nm;
   1637   const struct TALER_KYCLOGIC_Measure *ret = NULL;
   1638 
   1639   GNUNET_assert (NULL != measures_spec);
   1640 
   1641   if ('+' == measures_spec[0])
   1642   {
   1643     nm = GNUNET_strdup (&measures_spec[1]);
   1644   }
   1645   else
   1646   {
   1647     nm = GNUNET_strdup (measures_spec);
   1648   }
   1649   if (! token_list_lower (nm))
   1650   {
   1651     GNUNET_break (0);
   1652     GNUNET_free (nm);
   1653     return NULL;
   1654   }
   1655   for (const char *tok = strtok (nm, " ");
   1656        NULL != tok;
   1657        tok = strtok (NULL, " "))
   1658   {
   1659     const struct TALER_KYCLOGIC_Measure *ms;
   1660 
   1661     if (0 == strcasecmp (KYC_MEASURE_IMPOSSIBLE,
   1662                          tok))
   1663     {
   1664       continue;
   1665     }
   1666     ms = find_measure (lrs,
   1667                        tok);
   1668     if (NULL == ms)
   1669     {
   1670       GNUNET_break (0);
   1671       continue;
   1672     }
   1673     if (0 == strcasecmp (KYC_MEASURE_IMPOSSIBLE,
   1674                          ms->check_name))
   1675     {
   1676       continue;
   1677     }
   1678     if (0 == strcasecmp ("skip",
   1679                          ms->check_name))
   1680     {
   1681       ret = ms;
   1682       goto done;
   1683     }
   1684   }
   1685 done:
   1686   GNUNET_free (nm);
   1687   return ret;
   1688 }
   1689 
   1690 
   1691 const struct TALER_KYCLOGIC_Measure *
   1692 TALER_KYCLOGIC_get_measure (
   1693   const struct TALER_KYCLOGIC_LegitimizationRuleSet *lrs,
   1694   const char *measure_name)
   1695 {
   1696   return find_measure (lrs,
   1697                        measure_name);
   1698 }
   1699 
   1700 
   1701 json_t *
   1702 TALER_KYCLOGIC_get_jmeasures (
   1703   const struct TALER_KYCLOGIC_LegitimizationRuleSet *lrs,
   1704   const char *measures_spec)
   1705 {
   1706   json_t *jmeasures;
   1707   char *nm;
   1708   bool verboten = false;
   1709   bool is_and = false;
   1710 
   1711   if ('+' == measures_spec[0])
   1712   {
   1713     nm = GNUNET_strdup (&measures_spec[1]);
   1714     is_and = true;
   1715   }
   1716   else
   1717   {
   1718     nm = GNUNET_strdup (measures_spec);
   1719   }
   1720   if (! token_list_lower (nm))
   1721   {
   1722     GNUNET_break (0);
   1723     GNUNET_free (nm);
   1724     return NULL;
   1725   }
   1726   jmeasures = json_array ();
   1727   GNUNET_assert (NULL != jmeasures);
   1728   for (const char *tok = strtok (nm, " ");
   1729        NULL != tok;
   1730        tok = strtok (NULL, " "))
   1731   {
   1732     const struct TALER_KYCLOGIC_Measure *ms;
   1733     json_t *mi;
   1734 
   1735     if (0 == strcasecmp (KYC_MEASURE_IMPOSSIBLE,
   1736                          tok))
   1737     {
   1738       verboten = true;
   1739       continue;
   1740     }
   1741     ms = find_measure (lrs,
   1742                        tok);
   1743     if (NULL == ms)
   1744     {
   1745       GNUNET_break (0);
   1746       GNUNET_free (nm);
   1747       json_decref (jmeasures);
   1748       return NULL;
   1749     }
   1750     mi = GNUNET_JSON_PACK (
   1751       GNUNET_JSON_pack_string ("check_name",
   1752                                ms->check_name),
   1753       GNUNET_JSON_pack_allow_null (
   1754         GNUNET_JSON_pack_string ("prog_name",
   1755                                  ms->prog_name)),
   1756       GNUNET_JSON_pack_allow_null (
   1757         GNUNET_JSON_pack_object_incref ("context",
   1758                                         ms->context)));
   1759     GNUNET_assert (0 ==
   1760                    json_array_append_new (jmeasures,
   1761                                           mi));
   1762   }
   1763   GNUNET_free (nm);
   1764   return GNUNET_JSON_PACK (
   1765     GNUNET_JSON_pack_array_steal ("measures",
   1766                                   jmeasures),
   1767     GNUNET_JSON_pack_bool ("is_and_combinator",
   1768                            is_and),
   1769     GNUNET_JSON_pack_bool ("verboten",
   1770                            verboten));
   1771 }
   1772 
   1773 
   1774 json_t *
   1775 TALER_KYCLOGIC_check_to_jmeasures (
   1776   const struct TALER_KYCLOGIC_KycCheckContext *kcc)
   1777 {
   1778   const struct TALER_KYCLOGIC_KycCheck *check
   1779     = kcc->check;
   1780   json_t *jmeasures;
   1781   json_t *mi;
   1782 
   1783   mi = GNUNET_JSON_PACK (
   1784     GNUNET_JSON_pack_string ("check_name",
   1785                              NULL == check
   1786                              ? "skip"
   1787                              : check->check_name),
   1788     GNUNET_JSON_pack_allow_null (
   1789       GNUNET_JSON_pack_string ("prog_name",
   1790                                kcc->prog_name)),
   1791     GNUNET_JSON_pack_allow_null (
   1792       GNUNET_JSON_pack_object_incref ("context",
   1793                                       (json_t *) kcc->context)));
   1794   jmeasures = json_array ();
   1795   GNUNET_assert (NULL != jmeasures);
   1796   GNUNET_assert (0 ==
   1797                  json_array_append_new (jmeasures,
   1798                                         mi));
   1799   return GNUNET_JSON_PACK (
   1800     GNUNET_JSON_pack_array_steal ("measures",
   1801                                   jmeasures),
   1802     GNUNET_JSON_pack_bool ("is_and_combinator",
   1803                            true),
   1804     GNUNET_JSON_pack_bool ("verboten",
   1805                            false));
   1806 }
   1807 
   1808 
   1809 json_t *
   1810 TALER_KYCLOGIC_measure_to_jmeasures (
   1811   const struct TALER_KYCLOGIC_Measure *m)
   1812 {
   1813   json_t *jmeasures;
   1814   json_t *mi;
   1815 
   1816   mi = GNUNET_JSON_PACK (
   1817     GNUNET_JSON_pack_string ("check_name",
   1818                              m->check_name),
   1819     GNUNET_JSON_pack_allow_null (
   1820       GNUNET_JSON_pack_string ("prog_name",
   1821                                m->prog_name)),
   1822     GNUNET_JSON_pack_allow_null (
   1823       GNUNET_JSON_pack_object_incref ("context",
   1824                                       (json_t *) m->context)));
   1825   jmeasures = json_array ();
   1826   GNUNET_assert (NULL != jmeasures);
   1827   GNUNET_assert (0 ==
   1828                  json_array_append_new (jmeasures,
   1829                                         mi));
   1830   return GNUNET_JSON_PACK (
   1831     GNUNET_JSON_pack_array_steal ("measures",
   1832                                   jmeasures),
   1833     GNUNET_JSON_pack_bool ("is_and_combinator",
   1834                            false),
   1835     GNUNET_JSON_pack_bool ("verboten",
   1836                            false));
   1837 }
   1838 
   1839 
   1840 uint32_t
   1841 TALER_KYCLOGIC_rule2priority (
   1842   const struct TALER_KYCLOGIC_KycRule *r)
   1843 {
   1844   return r->display_priority;
   1845 }
   1846 
   1847 
   1848 /**
   1849  * Run @a command with @a argument and return the
   1850  * respective output from stdout.
   1851  *
   1852  * @param command binary to run
   1853  * @param argument command-line argument to pass
   1854  * @return NULL if @a command failed
   1855  */
   1856 static char *
   1857 command_output (const char *command,
   1858                 const char *argument)
   1859 {
   1860   char *rval;
   1861   unsigned int sval;
   1862   size_t soff;
   1863   ssize_t ret;
   1864   int sout[2];
   1865   pid_t chld;
   1866   const char *extra_args[] = {
   1867     argument,
   1868     "-c",
   1869     cfg_filename,
   1870     NULL,
   1871   };
   1872 
   1873   if (0 != pipe (sout))
   1874   {
   1875     GNUNET_log_strerror (GNUNET_ERROR_TYPE_ERROR,
   1876                          "pipe");
   1877     return NULL;
   1878   }
   1879   chld = fork ();
   1880   if (-1 == chld)
   1881   {
   1882     GNUNET_log_strerror (GNUNET_ERROR_TYPE_ERROR,
   1883                          "fork");
   1884     GNUNET_break (0 == close (sout[0]));
   1885     GNUNET_break (0 == close (sout[1]));
   1886     return NULL;
   1887   }
   1888   if (0 == chld)
   1889   {
   1890     char **argv;
   1891 
   1892     argv = TALER_words_split (command,
   1893                               extra_args);
   1894 
   1895     GNUNET_break (0 ==
   1896                   close (sout[0]));
   1897     GNUNET_break (0 ==
   1898                   close (STDOUT_FILENO));
   1899     GNUNET_assert (STDOUT_FILENO ==
   1900                    dup2 (sout[1],
   1901                          STDOUT_FILENO));
   1902     GNUNET_break (0 ==
   1903                   close (sout[1]));
   1904     execvp (argv[0],
   1905             argv);
   1906     TALER_words_destroy (argv);
   1907     GNUNET_log_strerror_file (GNUNET_ERROR_TYPE_ERROR,
   1908                               "exec",
   1909                               command);
   1910     exit (EXIT_FAILURE);
   1911   }
   1912   GNUNET_break (0 ==
   1913                 close (sout[1]));
   1914   sval = 1024;
   1915   rval = GNUNET_malloc (sval);
   1916   soff = 0;
   1917   while (0 < (ret = read (sout[0],
   1918                           rval + soff,
   1919                           sval - soff)) )
   1920   {
   1921     soff += ret;
   1922     if (soff == sval)
   1923     {
   1924       GNUNET_array_grow (rval,
   1925                          sval,
   1926                          sval * 2);
   1927     }
   1928   }
   1929   GNUNET_break (0 == close (sout[0]));
   1930   {
   1931     int wstatus;
   1932 
   1933     GNUNET_break (chld ==
   1934                   waitpid (chld,
   1935                            &wstatus,
   1936                            0));
   1937     if ( (! WIFEXITED (wstatus)) ||
   1938          (0 != WEXITSTATUS (wstatus)) )
   1939     {
   1940       GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
   1941                   "Command `%s' %s failed with status %d\n",
   1942                   command,
   1943                   argument,
   1944                   wstatus);
   1945       GNUNET_array_grow (rval,
   1946                          sval,
   1947                          0);
   1948       return NULL;
   1949     }
   1950   }
   1951   GNUNET_array_grow (rval,
   1952                      sval,
   1953                      soff + 1);
   1954   rval[soff] = '\0';
   1955   return rval;
   1956 }
   1957 
   1958 
   1959 /**
   1960  * Convert check type @a ctype_s into @a ctype.
   1961  *
   1962  * @param ctype_s check type as a string
   1963  * @param[out] ctype set to check type as enum
   1964  * @return #GNUNET_OK on success
   1965  */
   1966 static enum GNUNET_GenericReturnValue
   1967 check_type_from_string (
   1968   const char *ctype_s,
   1969   enum TALER_KYCLOGIC_CheckType *ctype)
   1970 {
   1971   struct
   1972   {
   1973     const char *in;
   1974     enum TALER_KYCLOGIC_CheckType out;
   1975   } map [] = {
   1976     { "INFO", TALER_KYCLOGIC_CT_INFO },
   1977     { "LINK", TALER_KYCLOGIC_CT_LINK },
   1978     { "FORM", TALER_KYCLOGIC_CT_FORM  },
   1979     { NULL, 0 }
   1980   };
   1981 
   1982   for (unsigned int i = 0; NULL != map[i].in; i++)
   1983     if (0 == strcasecmp (map[i].in,
   1984                          ctype_s))
   1985     {
   1986       *ctype = map[i].out;
   1987       return GNUNET_OK;
   1988     }
   1989   GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
   1990               "Invalid check type `%s'\n",
   1991               ctype_s);
   1992   return GNUNET_SYSERR;
   1993 }
   1994 
   1995 
   1996 enum GNUNET_GenericReturnValue
   1997 TALER_KYCLOGIC_kyc_trigger_from_string (
   1998   const char *trigger_s,
   1999   enum TALER_KYCLOGIC_KycTriggerEvent *trigger)
   2000 {
   2001   /* NOTE: if you change this, also change
   2002      the code in src/json/json_helper.c! */
   2003   struct
   2004   {
   2005     const char *in;
   2006     enum TALER_KYCLOGIC_KycTriggerEvent out;
   2007   } map [] = {
   2008     { "WITHDRAW", TALER_KYCLOGIC_KYC_TRIGGER_WITHDRAW },
   2009     { "DEPOSIT", TALER_KYCLOGIC_KYC_TRIGGER_DEPOSIT  },
   2010     { "MERGE", TALER_KYCLOGIC_KYC_TRIGGER_P2P_RECEIVE },
   2011     { "BALANCE", TALER_KYCLOGIC_KYC_TRIGGER_WALLET_BALANCE },
   2012     { "CLOSE", TALER_KYCLOGIC_KYC_TRIGGER_RESERVE_CLOSE },
   2013     { "AGGREGATE", TALER_KYCLOGIC_KYC_TRIGGER_AGGREGATE },
   2014     { "TRANSACTION", TALER_KYCLOGIC_KYC_TRIGGER_TRANSACTION },
   2015     { "REFUND", TALER_KYCLOGIC_KYC_TRIGGER_REFUND },
   2016     { NULL, 0 }
   2017   };
   2018 
   2019   for (unsigned int i = 0; NULL != map[i].in; i++)
   2020     if (0 == strcasecmp (map[i].in,
   2021                          trigger_s))
   2022     {
   2023       *trigger = map[i].out;
   2024       return GNUNET_OK;
   2025     }
   2026   GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
   2027               "Invalid KYC trigger `%s'\n",
   2028               trigger_s);
   2029   return GNUNET_SYSERR;
   2030 }
   2031 
   2032 
   2033 json_t *
   2034 TALER_KYCLOGIC_get_wallet_thresholds (void)
   2035 {
   2036   json_t *ret;
   2037 
   2038   ret = json_array ();
   2039   GNUNET_assert (NULL != ret);
   2040   for (unsigned int i = 0; i<default_rules.num_kyc_rules; i++)
   2041   {
   2042     struct TALER_KYCLOGIC_KycRule *rule
   2043       = &default_rules.kyc_rules[i];
   2044 
   2045     if (TALER_KYCLOGIC_KYC_TRIGGER_WALLET_BALANCE != rule->trigger)
   2046       continue;
   2047     GNUNET_assert (
   2048       0 ==
   2049       json_array_append_new (
   2050         ret,
   2051         TALER_JSON_from_amount (
   2052           &rule->threshold)));
   2053   }
   2054   return ret;
   2055 }
   2056 
   2057 
   2058 /**
   2059  * Load KYC logic plugin.
   2060  *
   2061  * @param cfg configuration to use
   2062  * @param name name of the plugin
   2063  * @return NULL on error
   2064  */
   2065 static struct TALER_KYCLOGIC_Plugin *
   2066 load_logic (const struct GNUNET_CONFIGURATION_Handle *cfg,
   2067             const char *name)
   2068 {
   2069   char *lib_name;
   2070   struct TALER_KYCLOGIC_Plugin *plugin;
   2071 
   2072 
   2073   GNUNET_asprintf (&lib_name,
   2074                    "libtaler_plugin_kyclogic_%s",
   2075                    name);
   2076   if (! ascii_lower (lib_name))
   2077   {
   2078     GNUNET_free (lib_name);
   2079     return NULL;
   2080   }
   2081   for (unsigned int i = 0; i<num_kyc_logics; i++)
   2082     if (0 == strcasecmp (lib_name,
   2083                          kyc_logics[i]->library_name))
   2084     {
   2085       GNUNET_free (lib_name);
   2086       return kyc_logics[i];
   2087     }
   2088   plugin = GNUNET_PLUGIN_load (TALER_EXCHANGE_project_data (),
   2089                                lib_name,
   2090                                (void *) cfg);
   2091   if (NULL == plugin)
   2092   {
   2093     GNUNET_free (lib_name);
   2094     return NULL;
   2095   }
   2096   plugin->library_name = lib_name;
   2097   plugin->name = GNUNET_strdup (name);
   2098   GNUNET_array_append (kyc_logics,
   2099                        num_kyc_logics,
   2100                        plugin);
   2101   return plugin;
   2102 }
   2103 
   2104 
   2105 /**
   2106  * Parse configuration of a KYC provider.
   2107  *
   2108  * @param cfg configuration to parse
   2109  * @param section name of the section to analyze
   2110  * @return #GNUNET_OK on success
   2111  */
   2112 static enum GNUNET_GenericReturnValue
   2113 add_provider (const struct GNUNET_CONFIGURATION_Handle *cfg,
   2114               const char *section)
   2115 {
   2116   char *logic;
   2117   struct TALER_KYCLOGIC_Plugin *lp;
   2118   struct TALER_KYCLOGIC_ProviderDetails *pd;
   2119 
   2120   GNUNET_log (GNUNET_ERROR_TYPE_INFO,
   2121               "Parsing KYC provider %s\n",
   2122               section);
   2123   if (GNUNET_OK !=
   2124       GNUNET_CONFIGURATION_get_value_string (cfg,
   2125                                              section,
   2126                                              "LOGIC",
   2127                                              &logic))
   2128   {
   2129     GNUNET_log_config_missing (GNUNET_ERROR_TYPE_ERROR,
   2130                                section,
   2131                                "LOGIC");
   2132     return GNUNET_SYSERR;
   2133   }
   2134   if (! ascii_lower (logic))
   2135   {
   2136     GNUNET_log_config_invalid (GNUNET_ERROR_TYPE_ERROR,
   2137                                section,
   2138                                "LOGIC",
   2139                                "Only [a-zA-Z0-9_0] are allowed");
   2140     return GNUNET_SYSERR;
   2141   }
   2142   lp = load_logic (cfg,
   2143                    logic);
   2144   if (NULL == lp)
   2145   {
   2146     GNUNET_log_config_invalid (GNUNET_ERROR_TYPE_ERROR,
   2147                                section,
   2148                                "LOGIC",
   2149                                "logic plugin could not be loaded");
   2150     GNUNET_free (logic);
   2151     return GNUNET_SYSERR;
   2152   }
   2153   GNUNET_free (logic);
   2154   pd = lp->load_configuration (lp->cls,
   2155                                section);
   2156   if (NULL == pd)
   2157     return GNUNET_SYSERR;
   2158 
   2159   {
   2160     struct TALER_KYCLOGIC_KycProvider *kp;
   2161 
   2162     kp = GNUNET_new (struct TALER_KYCLOGIC_KycProvider);
   2163     kp->provider_name
   2164       = GNUNET_strdup (&section[strlen ("kyc-provider-")]);
   2165     kp->logic = lp;
   2166     kp->pd = pd;
   2167     GNUNET_array_append (kyc_providers,
   2168                          num_kyc_providers,
   2169                          kp);
   2170   }
   2171   return GNUNET_OK;
   2172 }
   2173 
   2174 
   2175 /**
   2176  * Tokenize @a input along @a token
   2177  * and build an array of the tokens.
   2178  *
   2179  * @param[in,out] input the input to tokenize; clobbered
   2180  * @param sep separator between tokens to separate @a input on
   2181  * @param[out] p_strs where to put array of tokens
   2182  * @param[out] num_strs set to length of @a p_strs array
   2183  */
   2184 static void
   2185 add_tokens (char *input,
   2186             const char *sep,
   2187             char ***p_strs,
   2188             unsigned int *num_strs)
   2189 {
   2190   char *sptr;
   2191   char **rstr = NULL;
   2192   unsigned int num_rstr = 0;
   2193 
   2194   for (char *tok = strtok_r (input, sep, &sptr);
   2195        NULL != tok;
   2196        tok = strtok_r (NULL, sep, &sptr))
   2197   {
   2198     GNUNET_array_append (rstr,
   2199                          num_rstr,
   2200                          GNUNET_strdup (tok));
   2201   }
   2202   *p_strs = rstr;
   2203   *num_strs = num_rstr;
   2204 }
   2205 
   2206 
   2207 /**
   2208  * Closure for the handle_XXX_section functions
   2209  * that parse configuration sections matching certain
   2210  * prefixes.
   2211  */
   2212 struct SectionContext
   2213 {
   2214   /**
   2215    * Configuration to handle.
   2216    */
   2217   const struct GNUNET_CONFIGURATION_Handle *cfg;
   2218 
   2219   /**
   2220    * Result to return, set to false on failures.
   2221    */
   2222   bool result;
   2223 };
   2224 
   2225 
   2226 /**
   2227  * Function to iterate over configuration sections.
   2228  *
   2229  * @param cls a `struct SectionContext *`
   2230  * @param section name of the section
   2231  */
   2232 static void
   2233 handle_provider_section (void *cls,
   2234                          const char *section)
   2235 {
   2236   struct SectionContext *sc = cls;
   2237   char *s;
   2238 
   2239   if (! sc->result)
   2240     return;
   2241   s = normalize_section_with_prefix ("kyc-provider-",
   2242                                      section);
   2243   if (NULL == s)
   2244     return;
   2245   if (GNUNET_OK !=
   2246       add_provider (sc->cfg,
   2247                     s))
   2248   {
   2249     GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
   2250                 "Setup failed in configuration section `%s'\n",
   2251                 section);
   2252     sc->result = false;
   2253   }
   2254   GNUNET_free (s);
   2255 }
   2256 
   2257 
   2258 /**
   2259  * Parse configuration @a cfg in section @a section for
   2260  * the specification of a KYC check.
   2261  *
   2262  * @param cfg configuration to parse
   2263  * @param section configuration section to parse
   2264  * @return #GNUNET_OK on success
   2265  */
   2266 static enum GNUNET_GenericReturnValue
   2267 add_check (const struct GNUNET_CONFIGURATION_Handle *cfg,
   2268            const char *section)
   2269 {
   2270   enum TALER_KYCLOGIC_CheckType ct;
   2271   char *description = NULL;
   2272   json_t *description_i18n = NULL;
   2273   char *requires = NULL;
   2274   char *outputs = NULL;
   2275   char *fallback = NULL;
   2276 
   2277   if (0 == strcasecmp (&section[strlen ("kyc-check-")],
   2278                        "skip"))
   2279   {
   2280     GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
   2281                 "The kyc-check-skip section must not exist, 'skip' is reserved name for a built-in check\n");
   2282     return GNUNET_SYSERR;
   2283   }
   2284   GNUNET_log (GNUNET_ERROR_TYPE_INFO,
   2285               "Parsing KYC check %s\n",
   2286               section);
   2287   {
   2288     char *type_s;
   2289 
   2290     if (GNUNET_OK !=
   2291         GNUNET_CONFIGURATION_get_value_string (cfg,
   2292                                                section,
   2293                                                "TYPE",
   2294                                                &type_s))
   2295     {
   2296       GNUNET_log_config_missing (GNUNET_ERROR_TYPE_ERROR,
   2297                                  section,
   2298                                  "TYPE");
   2299       return GNUNET_SYSERR;
   2300     }
   2301     if (GNUNET_OK !=
   2302         check_type_from_string (type_s,
   2303                                 &ct))
   2304     {
   2305       GNUNET_log_config_invalid (GNUNET_ERROR_TYPE_ERROR,
   2306                                  section,
   2307                                  "TYPE",
   2308                                  "valid check type required");
   2309       GNUNET_free (type_s);
   2310       return GNUNET_SYSERR;
   2311     }
   2312     GNUNET_free (type_s);
   2313   }
   2314 
   2315   if (GNUNET_OK !=
   2316       GNUNET_CONFIGURATION_get_value_string (cfg,
   2317                                              section,
   2318                                              "DESCRIPTION",
   2319                                              &description))
   2320   {
   2321     GNUNET_log_config_missing (GNUNET_ERROR_TYPE_ERROR,
   2322                                section,
   2323                                "DESCRIPTION");
   2324     goto fail;
   2325   }
   2326 
   2327   {
   2328     char *tmp;
   2329 
   2330     if (GNUNET_OK ==
   2331         GNUNET_CONFIGURATION_get_value_string (cfg,
   2332                                                section,
   2333                                                "DESCRIPTION_I18N",
   2334                                                &tmp))
   2335     {
   2336       json_error_t err;
   2337 
   2338       description_i18n = json_loads (tmp,
   2339                                      JSON_REJECT_DUPLICATES,
   2340                                      &err);
   2341       GNUNET_free (tmp);
   2342       if (NULL == description_i18n)
   2343       {
   2344         GNUNET_log_config_invalid (GNUNET_ERROR_TYPE_ERROR,
   2345                                    section,
   2346                                    "DESCRIPTION_I18N",
   2347                                    err.text);
   2348         goto fail;
   2349       }
   2350       if (! TALER_JSON_check_i18n (description_i18n) )
   2351       {
   2352         GNUNET_log_config_invalid (GNUNET_ERROR_TYPE_ERROR,
   2353                                    section,
   2354                                    "DESCRIPTION_I18N",
   2355                                    "JSON with internationalization map required");
   2356         goto fail;
   2357       }
   2358     }
   2359   }
   2360 
   2361   if (GNUNET_OK !=
   2362       GNUNET_CONFIGURATION_get_value_string (cfg,
   2363                                              section,
   2364                                              "REQUIRES",
   2365                                              &requires))
   2366   {
   2367     /* no requirements is OK */
   2368     requires = GNUNET_strdup ("");
   2369   }
   2370 
   2371   if (GNUNET_OK !=
   2372       GNUNET_CONFIGURATION_get_value_string (cfg,
   2373                                              section,
   2374                                              "OUTPUTS",
   2375                                              &outputs))
   2376   {
   2377     /* no outputs is OK */
   2378     outputs = GNUNET_strdup ("");
   2379   }
   2380 
   2381   if (GNUNET_OK !=
   2382       GNUNET_CONFIGURATION_get_value_string (cfg,
   2383                                              section,
   2384                                              "FALLBACK",
   2385                                              &fallback))
   2386   {
   2387     /* We do *not* allow NULL to fall back to default rules because fallbacks
   2388        are used when there is actually a serious error and thus some action
   2389        (usually an investigation) is always in order, and that's basically
   2390        never the default. And as fallbacks should be rare, we really insist on
   2391        them at least being explicitly configured. Otherwise these errors may
   2392        go undetected simply because someone forgot to configure a fallback and
   2393        then nothing happens. */
   2394     GNUNET_log_config_missing (GNUNET_ERROR_TYPE_ERROR,
   2395                                section,
   2396                                "FALLBACK");
   2397     goto fail;
   2398   }
   2399   if (! ascii_lower (fallback))
   2400   {
   2401     GNUNET_log_config_invalid (GNUNET_ERROR_TYPE_ERROR,
   2402                                section,
   2403                                "FALLBACK",
   2404                                "Only [a-zA-Z0-9_0] are allowed");
   2405     goto fail;
   2406   }
   2407 
   2408   {
   2409     struct TALER_KYCLOGIC_KycCheck *kc;
   2410 
   2411     kc = GNUNET_new (struct TALER_KYCLOGIC_KycCheck);
   2412     switch (ct)
   2413     {
   2414     case TALER_KYCLOGIC_CT_INFO:
   2415       /* nothing to do */
   2416       break;
   2417     case TALER_KYCLOGIC_CT_FORM:
   2418       {
   2419         char *form_name;
   2420 
   2421         if (GNUNET_OK !=
   2422             GNUNET_CONFIGURATION_get_value_string (cfg,
   2423                                                    section,
   2424                                                    "FORM_NAME",
   2425                                                    &form_name))
   2426         {
   2427           GNUNET_log_config_missing (GNUNET_ERROR_TYPE_ERROR,
   2428                                      section,
   2429                                      "FORM_NAME");
   2430           GNUNET_free (requires);
   2431           GNUNET_free (outputs);
   2432           GNUNET_free (kc);
   2433           return GNUNET_SYSERR;
   2434         }
   2435         if (! ascii_lower (form_name))
   2436         {
   2437           GNUNET_log_config_invalid (GNUNET_ERROR_TYPE_ERROR,
   2438                                      section,
   2439                                      "FORM_NAME",
   2440                                      "Only [a-zA-Z0-9_0] are allowed");
   2441           goto fail;
   2442         }
   2443         kc->details.form.name = form_name;
   2444       }
   2445       break;
   2446     case TALER_KYCLOGIC_CT_LINK:
   2447       {
   2448         char *provider_id;
   2449 
   2450         if (GNUNET_OK !=
   2451             GNUNET_CONFIGURATION_get_value_string (cfg,
   2452                                                    section,
   2453                                                    "PROVIDER_ID",
   2454                                                    &provider_id))
   2455         {
   2456           GNUNET_log_config_missing (GNUNET_ERROR_TYPE_ERROR,
   2457                                      section,
   2458                                      "PROVIDER_ID");
   2459           GNUNET_free (requires);
   2460           GNUNET_free (outputs);
   2461           GNUNET_free (kc);
   2462           return GNUNET_SYSERR;
   2463         }
   2464         if (! ascii_lower (provider_id))
   2465         {
   2466           GNUNET_log_config_invalid (GNUNET_ERROR_TYPE_ERROR,
   2467                                      section,
   2468                                      "PROVIDER_ID",
   2469                                      "Only [a-zA-Z0-9_0] are allowed");
   2470           goto fail;
   2471         }
   2472         kc->details.link.provider = find_provider (provider_id);
   2473         if (NULL == kc->details.link.provider)
   2474         {
   2475           GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
   2476                       "Unknown KYC provider `%s' used in check `%s'\n",
   2477                       provider_id,
   2478                       &section[strlen ("kyc-check-")]);
   2479           GNUNET_free (provider_id);
   2480           GNUNET_free (requires);
   2481           GNUNET_free (outputs);
   2482           GNUNET_free (kc);
   2483           return GNUNET_SYSERR;
   2484         }
   2485         GNUNET_free (provider_id);
   2486       }
   2487       break;
   2488     }
   2489     kc->check_name = GNUNET_strdup (&section[strlen ("kyc-check-")]);
   2490     kc->description = description;
   2491     kc->description_i18n = description_i18n;
   2492     kc->fallback = fallback;
   2493     kc->type = ct;
   2494     add_tokens (requires,
   2495                 "; \n\t",
   2496                 &kc->requires,
   2497                 &kc->num_requires);
   2498     GNUNET_free (requires);
   2499     add_tokens (outputs,
   2500                 "; \n\t",
   2501                 &kc->outputs,
   2502                 &kc->num_outputs);
   2503     GNUNET_free (outputs);
   2504     GNUNET_array_append (kyc_checks,
   2505                          num_kyc_checks,
   2506                          kc);
   2507   }
   2508 
   2509   return GNUNET_OK;
   2510 fail:
   2511   GNUNET_free (description);
   2512   json_decref (description_i18n);
   2513   GNUNET_free (requires);
   2514   GNUNET_free (outputs);
   2515   GNUNET_free (fallback);
   2516   return GNUNET_SYSERR;
   2517 }
   2518 
   2519 
   2520 /**
   2521  * Function to iterate over configuration sections.
   2522  *
   2523  * @param cls a `struct SectionContext *`
   2524  * @param section name of the section
   2525  */
   2526 static void
   2527 handle_check_section (void *cls,
   2528                       const char *section)
   2529 {
   2530   struct SectionContext *sc = cls;
   2531   char *s;
   2532 
   2533   if (! sc->result)
   2534     return;
   2535   s = normalize_section_with_prefix ("kyc-check-",
   2536                                      section);
   2537   if (NULL == s)
   2538     return;
   2539   if (GNUNET_OK !=
   2540       add_check (sc->cfg,
   2541                  s))
   2542     sc->result = false;
   2543   GNUNET_free (s);
   2544 }
   2545 
   2546 
   2547 /**
   2548  * Parse configuration @a cfg in section @a section for
   2549  * the specification of a KYC rule.
   2550  *
   2551  * @param cfg configuration to parse
   2552  * @param section configuration section to parse
   2553  * @return #GNUNET_OK on success
   2554  */
   2555 static enum GNUNET_GenericReturnValue
   2556 add_rule (const struct GNUNET_CONFIGURATION_Handle *cfg,
   2557           const char *section)
   2558 {
   2559   struct TALER_Amount threshold;
   2560   struct GNUNET_TIME_Relative timeframe;
   2561   enum TALER_KYCLOGIC_KycTriggerEvent ot;
   2562   char *measures;
   2563   bool exposed;
   2564   bool is_and;
   2565 
   2566   GNUNET_log (GNUNET_ERROR_TYPE_INFO,
   2567               "Parsing KYC rule from %s\n",
   2568               section);
   2569   if (GNUNET_YES !=
   2570       GNUNET_CONFIGURATION_get_value_yesno (cfg,
   2571                                             section,
   2572                                             "ENABLED"))
   2573     return GNUNET_OK;
   2574   if (GNUNET_OK !=
   2575       TALER_config_get_amount (cfg,
   2576                                section,
   2577                                "THRESHOLD",
   2578                                &threshold))
   2579   {
   2580     GNUNET_log_config_invalid (GNUNET_ERROR_TYPE_ERROR,
   2581                                section,
   2582                                "THRESHOLD",
   2583                                "amount required");
   2584     return GNUNET_SYSERR;
   2585   }
   2586   if (0 !=
   2587       strcasecmp (threshold.currency,
   2588                   my_currency))
   2589   {
   2590     GNUNET_log_config_invalid (GNUNET_ERROR_TYPE_ERROR,
   2591                                section,
   2592                                "THRESHOLD",
   2593                                "currency mismatch");
   2594     return GNUNET_SYSERR;
   2595   }
   2596   exposed = (GNUNET_YES ==
   2597              GNUNET_CONFIGURATION_get_value_yesno (cfg,
   2598                                                    section,
   2599                                                    "EXPOSED"));
   2600   {
   2601     enum GNUNET_GenericReturnValue r;
   2602 
   2603     r = GNUNET_CONFIGURATION_get_value_yesno (cfg,
   2604                                               section,
   2605                                               "IS_AND_COMBINATOR");
   2606     if (GNUNET_SYSERR == r)
   2607     {
   2608       GNUNET_log_config_invalid (GNUNET_ERROR_TYPE_ERROR,
   2609                                  section,
   2610                                  "IS_AND_COMBINATOR",
   2611                                  "YES or NO required");
   2612       return GNUNET_SYSERR;
   2613     }
   2614     is_and = (GNUNET_YES == r);
   2615   }
   2616 
   2617   {
   2618     char *ot_s;
   2619 
   2620     if (GNUNET_OK !=
   2621         GNUNET_CONFIGURATION_get_value_string (cfg,
   2622                                                section,
   2623                                                "OPERATION_TYPE",
   2624                                                &ot_s))
   2625     {
   2626       GNUNET_log_config_missing (GNUNET_ERROR_TYPE_ERROR,
   2627                                  section,
   2628                                  "OPERATION_TYPE");
   2629       return GNUNET_SYSERR;
   2630     }
   2631     if (GNUNET_OK !=
   2632         TALER_KYCLOGIC_kyc_trigger_from_string (ot_s,
   2633                                                 &ot))
   2634     {
   2635       GNUNET_log_config_invalid (GNUNET_ERROR_TYPE_ERROR,
   2636                                  section,
   2637                                  "OPERATION_TYPE",
   2638                                  "valid trigger type required");
   2639       GNUNET_free (ot_s);
   2640       return GNUNET_SYSERR;
   2641     }
   2642     GNUNET_free (ot_s);
   2643   }
   2644 
   2645   if (GNUNET_OK !=
   2646       GNUNET_CONFIGURATION_get_value_time (cfg,
   2647                                            section,
   2648                                            "TIMEFRAME",
   2649                                            &timeframe))
   2650   {
   2651     if (TALER_KYCLOGIC_KYC_TRIGGER_WALLET_BALANCE == ot)
   2652     {
   2653       timeframe = GNUNET_TIME_UNIT_ZERO;
   2654     }
   2655     else
   2656     {
   2657       GNUNET_log_config_invalid (GNUNET_ERROR_TYPE_ERROR,
   2658                                  section,
   2659                                  "TIMEFRAME",
   2660                                  "duration required");
   2661       return GNUNET_SYSERR;
   2662     }
   2663   }
   2664   if (GNUNET_OK !=
   2665       GNUNET_CONFIGURATION_get_value_string (cfg,
   2666                                              section,
   2667                                              "NEXT_MEASURES",
   2668                                              &measures))
   2669   {
   2670     GNUNET_log_config_missing (GNUNET_ERROR_TYPE_ERROR,
   2671                                section,
   2672                                "NEXT_MEASURES");
   2673     return GNUNET_SYSERR;
   2674   }
   2675   if (! token_list_lower (measures))
   2676   {
   2677     GNUNET_log_config_invalid (GNUNET_ERROR_TYPE_ERROR,
   2678                                section,
   2679                                "NEXT_MEASURES",
   2680                                "Only [a-zA-Z0-9 _-] are allowed");
   2681     GNUNET_free (measures);
   2682     return GNUNET_SYSERR;
   2683   }
   2684 
   2685   GNUNET_log (GNUNET_ERROR_TYPE_INFO,
   2686               "Adding KYC rule %s for trigger %d with threshold %s\n",
   2687               section,
   2688               (int) ot,
   2689               TALER_amount2s (&threshold));
   2690   {
   2691     struct TALER_KYCLOGIC_KycRule kt = {
   2692       .lrs = &default_rules,
   2693       .rule_name = GNUNET_strdup (&section[strlen ("kyc-rule-")]),
   2694       .timeframe = timeframe,
   2695       .threshold = threshold,
   2696       .trigger = ot,
   2697       .is_and_combinator = is_and,
   2698       .exposed = exposed,
   2699       .display_priority = 0,
   2700       .verboten = false
   2701     };
   2702 
   2703     add_tokens (measures,
   2704                 "; \n\t",
   2705                 &kt.next_measures,
   2706                 &kt.num_measures);
   2707     for (unsigned int i=0; i<kt.num_measures; i++)
   2708       if (0 == strcasecmp (KYC_MEASURE_IMPOSSIBLE,
   2709                            kt.next_measures[i]))
   2710         kt.verboten = true;
   2711     GNUNET_free (measures);
   2712     GNUNET_array_append (default_rules.kyc_rules,
   2713                          default_rules.num_kyc_rules,
   2714                          kt);
   2715   }
   2716   return GNUNET_OK;
   2717 }
   2718 
   2719 
   2720 /**
   2721  * Function to iterate over configuration sections.
   2722  *
   2723  * @param cls a `struct SectionContext *`
   2724  * @param section name of the section
   2725  */
   2726 static void
   2727 handle_rule_section (void *cls,
   2728                      const char *section)
   2729 {
   2730   struct SectionContext *sc = cls;
   2731   char *s;
   2732 
   2733   if (! sc->result)
   2734     return;
   2735   s = normalize_section_with_prefix ("kyc-rule-",
   2736                                      section);
   2737   if (NULL == s)
   2738     return;
   2739   if (GNUNET_OK !=
   2740       add_rule (sc->cfg,
   2741                 s))
   2742     sc->result = false;
   2743   GNUNET_free (s);
   2744 }
   2745 
   2746 
   2747 /**
   2748  * Parse array dimension argument of @a tok (if present)
   2749  * and store result in @a dimp. Does nothing if
   2750  * @a tok does not contain '['. Otherwise does some input
   2751  * validation.
   2752  *
   2753  * @param section name of configuration section for logging
   2754  * @param tok input to parse, of form "text[$DIM]"
   2755  * @param[out] dimp set to value of $DIM
   2756  * @return true on success
   2757  */
   2758 static bool
   2759 parse_dim (const char *section,
   2760            const char *tok,
   2761            long long *dimp)
   2762 {
   2763   const char *dim = strchr (tok,
   2764                             '[');
   2765   char dummy;
   2766 
   2767   if (NULL == dim)
   2768     return true;
   2769   if (1 !=
   2770       sscanf (dim,
   2771               "[%lld]%c",
   2772               dimp,
   2773               &dummy))
   2774   {
   2775     GNUNET_log_config_invalid (GNUNET_ERROR_TYPE_ERROR,
   2776                                section,
   2777                                "COMMAND",
   2778                                "output for -i invalid (bad dimension given)");
   2779     return false;
   2780   }
   2781   return true;
   2782 }
   2783 
   2784 
   2785 /**
   2786  * Parse configuration @a cfg in section @a section for
   2787  * the specification of an AML program.
   2788  *
   2789  * @param cfg configuration to parse
   2790  * @param section configuration section to parse
   2791  * @return #GNUNET_OK on success
   2792  */
   2793 static enum GNUNET_GenericReturnValue
   2794 add_program (const struct GNUNET_CONFIGURATION_Handle *cfg,
   2795              const char *section)
   2796 {
   2797   char *command = NULL;
   2798   char *description = NULL;
   2799   char *fallback = NULL;
   2800   char *required_contexts = NULL;
   2801   char *required_attributes = NULL;
   2802   char *required_inputs = NULL;
   2803   enum AmlProgramInputs input_mask = API_NONE;
   2804   long long aml_history_length_limit = INT64_MAX;
   2805   long long kyc_history_length_limit = INT64_MAX;
   2806 
   2807   GNUNET_log (GNUNET_ERROR_TYPE_INFO,
   2808               "Parsing KYC program %s\n",
   2809               section);
   2810   if (GNUNET_OK !=
   2811       GNUNET_CONFIGURATION_get_value_string (cfg,
   2812                                              section,
   2813                                              "COMMAND",
   2814                                              &command))
   2815   {
   2816     GNUNET_log_config_invalid (GNUNET_ERROR_TYPE_ERROR,
   2817                                section,
   2818                                "COMMAND",
   2819                                "command required");
   2820     goto fail;
   2821   }
   2822   if (GNUNET_OK !=
   2823       GNUNET_CONFIGURATION_get_value_string (cfg,
   2824                                              section,
   2825                                              "DESCRIPTION",
   2826                                              &description))
   2827   {
   2828     GNUNET_log_config_invalid (GNUNET_ERROR_TYPE_ERROR,
   2829                                section,
   2830                                "DESCRIPTION",
   2831                                "description required");
   2832     goto fail;
   2833   }
   2834   if (GNUNET_OK !=
   2835       GNUNET_CONFIGURATION_get_value_string (cfg,
   2836                                              section,
   2837                                              "FALLBACK",
   2838                                              &fallback))
   2839   {
   2840     /* We do *not* allow NULL to fall back to default rules because fallbacks
   2841        are used when there is actually a serious error and thus some action
   2842        (usually an investigation) is always in order, and that's basically
   2843        never the default. And as fallbacks should be rare, we really insist on
   2844        them at least being explicitly configured. Otherwise these errors may
   2845        go undetected simply because someone forgot to configure a fallback and
   2846        then nothing happens. */
   2847     GNUNET_log_config_invalid (GNUNET_ERROR_TYPE_ERROR,
   2848                                section,
   2849                                "FALLBACK",
   2850                                "fallback measure name required");
   2851     goto fail;
   2852   }
   2853 
   2854   required_contexts = command_output (command,
   2855                                       "-r");
   2856   if (NULL == required_contexts)
   2857   {
   2858     GNUNET_log_config_invalid (GNUNET_ERROR_TYPE_ERROR,
   2859                                section,
   2860                                "COMMAND",
   2861                                "output for -r invalid");
   2862     goto fail;
   2863   }
   2864 
   2865   required_attributes = command_output (command,
   2866                                         "-a");
   2867   if (NULL == required_attributes)
   2868   {
   2869     GNUNET_log_config_invalid (GNUNET_ERROR_TYPE_ERROR,
   2870                                section,
   2871                                "COMMAND",
   2872                                "output for -a invalid");
   2873     goto fail;
   2874   }
   2875 
   2876   required_inputs = command_output (command,
   2877                                     "-i");
   2878   if (NULL == required_inputs)
   2879   {
   2880     GNUNET_log_config_invalid (GNUNET_ERROR_TYPE_ERROR,
   2881                                section,
   2882                                "COMMAND",
   2883                                "output for -i invalid");
   2884     goto fail;
   2885   }
   2886 
   2887   {
   2888     char *sptr;
   2889 
   2890     for (char *tok = strtok_r (required_inputs,
   2891                                ";\n \t",
   2892                                &sptr);
   2893          NULL != tok;
   2894          tok = strtok_r (NULL,
   2895                          ";\n \t",
   2896                          &sptr) )
   2897     {
   2898       if (0 == strcasecmp (tok,
   2899                            "context"))
   2900         input_mask |= API_CONTEXT;
   2901       else if (0 == strcasecmp (tok,
   2902                                 "attributes"))
   2903         input_mask |= API_ATTRIBUTES;
   2904       else if (0 == strcasecmp (tok,
   2905                                 "current_rules"))
   2906         input_mask |= API_CURRENT_RULES;
   2907       else if (0 == strcasecmp (tok,
   2908                                 "default_rules"))
   2909         input_mask |= API_DEFAULT_RULES;
   2910       else if (0 == strncasecmp (tok,
   2911                                  "aml_history",
   2912                                  strlen ("aml_history")))
   2913       {
   2914         input_mask |= API_AML_HISTORY;
   2915         if (! parse_dim (section,
   2916                          tok,
   2917                          &aml_history_length_limit))
   2918           goto fail;
   2919       }
   2920       else if (0 == strncasecmp (tok,
   2921                                  "kyc_history",
   2922                                  strlen ("kyc_history")))
   2923       {
   2924         input_mask |= API_KYC_HISTORY;
   2925         if (! parse_dim (section,
   2926                          tok,
   2927                          &kyc_history_length_limit))
   2928           goto fail;
   2929       }
   2930       else
   2931       {
   2932         GNUNET_log_config_invalid (GNUNET_ERROR_TYPE_ERROR,
   2933                                    section,
   2934                                    "COMMAND",
   2935                                    "output for -i invalid (unsupported input)");
   2936         goto fail;
   2937       }
   2938     }
   2939   }
   2940   GNUNET_free (required_inputs);
   2941 
   2942   {
   2943     struct TALER_KYCLOGIC_AmlProgram *ap;
   2944 
   2945     ap = GNUNET_new (struct TALER_KYCLOGIC_AmlProgram);
   2946     ap->program_name = GNUNET_strdup (&section[strlen ("aml-program-")]);
   2947     ap->command = command;
   2948     ap->description = description;
   2949     ap->fallback = fallback;
   2950     ap->input_mask = input_mask;
   2951     ap->aml_history_length_limit = aml_history_length_limit;
   2952     ap->kyc_history_length_limit = kyc_history_length_limit;
   2953     add_tokens (required_contexts,
   2954                 "; \n\t",
   2955                 &ap->required_contexts,
   2956                 &ap->num_required_contexts);
   2957     GNUNET_free (required_contexts);
   2958     add_tokens (required_attributes,
   2959                 "; \n\t",
   2960                 &ap->required_attributes,
   2961                 &ap->num_required_attributes);
   2962     GNUNET_free (required_attributes);
   2963     GNUNET_array_append (aml_programs,
   2964                          num_aml_programs,
   2965                          ap);
   2966   }
   2967   return GNUNET_OK;
   2968 fail:
   2969   GNUNET_free (command);
   2970   GNUNET_free (description);
   2971   GNUNET_free (required_inputs);
   2972   GNUNET_free (required_contexts);
   2973   GNUNET_free (required_attributes);
   2974   GNUNET_free (fallback);
   2975   return GNUNET_SYSERR;
   2976 }
   2977 
   2978 
   2979 /**
   2980  * Function to iterate over configuration sections.
   2981  *
   2982  * @param cls a `struct SectionContext *`
   2983  * @param section name of the section
   2984  */
   2985 static void
   2986 handle_program_section (void *cls,
   2987                         const char *section)
   2988 {
   2989   struct SectionContext *sc = cls;
   2990   char *s;
   2991 
   2992   if (! sc->result)
   2993     return;
   2994   s = normalize_section_with_prefix ("aml-program-",
   2995                                      section);
   2996   if (NULL == s)
   2997     return;
   2998   if (GNUNET_OK !=
   2999       add_program (sc->cfg,
   3000                    s))
   3001     sc->result = false;
   3002   GNUNET_free (s);
   3003 }
   3004 
   3005 
   3006 /**
   3007  * Parse configuration @a cfg in section @a section for
   3008  * the specification of a KYC measure.
   3009  *
   3010  * @param cfg configuration to parse
   3011  * @param section configuration section to parse
   3012  * @return #GNUNET_OK on success
   3013  */
   3014 static enum GNUNET_GenericReturnValue
   3015 add_measure (const struct GNUNET_CONFIGURATION_Handle *cfg,
   3016              const char *section)
   3017 {
   3018   bool voluntary;
   3019   char *check_name = NULL;
   3020   struct TALER_KYCLOGIC_KycCheck *kc = NULL;
   3021   char *context_str = NULL;
   3022   char *program = NULL;
   3023   json_t *context;
   3024   json_error_t err;
   3025 
   3026   GNUNET_log (GNUNET_ERROR_TYPE_INFO,
   3027               "Parsing KYC measure %s\n",
   3028               section);
   3029   if (GNUNET_OK !=
   3030       GNUNET_CONFIGURATION_get_value_string (cfg,
   3031                                              section,
   3032                                              "CHECK_NAME",
   3033                                              &check_name))
   3034   {
   3035     check_name = GNUNET_strdup ("skip");
   3036   }
   3037   if (0 != strcasecmp (check_name,
   3038                        "skip"))
   3039   {
   3040     kc = find_check (check_name);
   3041     if (NULL == kc)
   3042     {
   3043       GNUNET_log_config_invalid (GNUNET_ERROR_TYPE_ERROR,
   3044                                  section,
   3045                                  "CHECK_NAME",
   3046                                  "check unknown");
   3047       goto fail;
   3048     }
   3049   }
   3050   if (GNUNET_OK !=
   3051       GNUNET_CONFIGURATION_get_value_string (cfg,
   3052                                              section,
   3053                                              "PROGRAM",
   3054                                              &program))
   3055   {
   3056     if ( (NULL == kc) ||
   3057          (TALER_KYCLOGIC_CT_INFO != kc->type) )
   3058     {
   3059       GNUNET_log_config_missing (GNUNET_ERROR_TYPE_ERROR,
   3060                                  section,
   3061                                  "PROGRAM");
   3062       goto fail;
   3063     }
   3064   }
   3065   else
   3066   {
   3067     /* AML program given, but do we want one? */
   3068     if ( (NULL != kc) &&
   3069          (TALER_KYCLOGIC_CT_INFO == kc->type) )
   3070     {
   3071       GNUNET_log_config_invalid (
   3072         GNUNET_ERROR_TYPE_WARNING,
   3073         section,
   3074         "PROGRAM",
   3075         "AML program specified for a check of type INFO (ignored)");
   3076       GNUNET_free (program);
   3077     }
   3078   }
   3079   voluntary = (GNUNET_YES ==
   3080                GNUNET_CONFIGURATION_get_value_yesno (cfg,
   3081                                                      section,
   3082                                                      "VOLUNTARY"));
   3083   if (GNUNET_OK !=
   3084       GNUNET_CONFIGURATION_get_value_string (cfg,
   3085                                              section,
   3086                                              "CONTEXT",
   3087                                              &context_str))
   3088   {
   3089     GNUNET_log_config_missing (GNUNET_ERROR_TYPE_ERROR,
   3090                                section,
   3091                                "CONTEXT");
   3092     goto fail;
   3093   }
   3094   context = json_loads (context_str,
   3095                         JSON_REJECT_DUPLICATES,
   3096                         &err);
   3097   GNUNET_free (context_str);
   3098   if (NULL == context)
   3099   {
   3100     GNUNET_log_config_invalid (GNUNET_ERROR_TYPE_ERROR,
   3101                                section,
   3102                                "CONTEXT",
   3103                                err.text);
   3104     goto fail;
   3105   }
   3106 
   3107   {
   3108     struct TALER_KYCLOGIC_Measure m;
   3109 
   3110     m.measure_name = GNUNET_strdup (&section[strlen ("kyc-measure-")]);
   3111     m.check_name = check_name;
   3112     m.prog_name = program;
   3113     m.context = context;
   3114     m.voluntary = voluntary;
   3115     GNUNET_array_append (default_rules.custom_measures,
   3116                          default_rules.num_custom_measures,
   3117                          m);
   3118   }
   3119   return GNUNET_OK;
   3120 fail:
   3121   GNUNET_free (check_name);
   3122   GNUNET_free (program);
   3123   GNUNET_free (context_str);
   3124   return GNUNET_SYSERR;
   3125 }
   3126 
   3127 
   3128 /**
   3129  * Function to iterate over configuration sections.
   3130  *
   3131  * @param cls a `struct SectionContext *`
   3132  * @param section name of the section
   3133  */
   3134 static void
   3135 handle_measure_section (void *cls,
   3136                         const char *section)
   3137 {
   3138   struct SectionContext *sc = cls;
   3139   char *s;
   3140 
   3141   if (! sc->result)
   3142     return;
   3143   s = normalize_section_with_prefix ("kyc-measure-",
   3144                                      section);
   3145   if (NULL == s)
   3146     return;
   3147   if (GNUNET_OK !=
   3148       add_measure (sc->cfg,
   3149                    s))
   3150     sc->result = false;
   3151   GNUNET_free (s);
   3152 }
   3153 
   3154 
   3155 /**
   3156  * Comparator for qsort. Compares two rules
   3157  * by timeframe to sort rules by time.
   3158  *
   3159  * @param p1 first trigger to compare
   3160  * @param p2 second trigger to compare
   3161  * @return -1 if p1 < p2, 0 if p1==p2, 1 if p1 > p2.
   3162  */
   3163 static int
   3164 sort_by_timeframe (const void *p1,
   3165                    const void *p2)
   3166 {
   3167   struct TALER_KYCLOGIC_KycRule *r1
   3168     = (struct TALER_KYCLOGIC_KycRule *) p1;
   3169   struct TALER_KYCLOGIC_KycRule *r2
   3170     = (struct TALER_KYCLOGIC_KycRule *) p2;
   3171 
   3172   if (GNUNET_TIME_relative_cmp (r1->timeframe,
   3173                                 <,
   3174                                 r2->timeframe))
   3175     return -1;
   3176   if (GNUNET_TIME_relative_cmp (r1->timeframe,
   3177                                 >,
   3178                                 r2->timeframe))
   3179     return 1;
   3180   return 0;
   3181 }
   3182 
   3183 
   3184 enum GNUNET_GenericReturnValue
   3185 TALER_KYCLOGIC_kyc_init (
   3186   const struct GNUNET_CONFIGURATION_Handle *cfg,
   3187   const char *cfg_fn)
   3188 {
   3189   struct SectionContext sc = {
   3190     .cfg = cfg,
   3191     .result = true
   3192   };
   3193   json_t *jkyc_rules_w;
   3194   json_t *jkyc_rules_a;
   3195 
   3196   if (NULL != cfg_fn)
   3197     cfg_filename = GNUNET_strdup (cfg_fn);
   3198   GNUNET_assert (GNUNET_OK ==
   3199                  TALER_config_get_currency (cfg,
   3200                                             "exchange",
   3201                                             &my_currency));
   3202   GNUNET_CONFIGURATION_iterate_sections (cfg,
   3203                                          &handle_provider_section,
   3204                                          &sc);
   3205   if (! sc.result)
   3206   {
   3207     TALER_KYCLOGIC_kyc_done ();
   3208     return GNUNET_SYSERR;
   3209   }
   3210   GNUNET_CONFIGURATION_iterate_sections (cfg,
   3211                                          &handle_check_section,
   3212                                          &sc);
   3213   if (! sc.result)
   3214   {
   3215     TALER_KYCLOGIC_kyc_done ();
   3216     return GNUNET_SYSERR;
   3217   }
   3218   GNUNET_CONFIGURATION_iterate_sections (cfg,
   3219                                          &handle_rule_section,
   3220                                          &sc);
   3221   if (! sc.result)
   3222   {
   3223     TALER_KYCLOGIC_kyc_done ();
   3224     return GNUNET_SYSERR;
   3225   }
   3226   GNUNET_CONFIGURATION_iterate_sections (cfg,
   3227                                          &handle_program_section,
   3228                                          &sc);
   3229   if (! sc.result)
   3230   {
   3231     TALER_KYCLOGIC_kyc_done ();
   3232     return GNUNET_SYSERR;
   3233   }
   3234   GNUNET_CONFIGURATION_iterate_sections (cfg,
   3235                                          &handle_measure_section,
   3236                                          &sc);
   3237   if (! sc.result)
   3238   {
   3239     TALER_KYCLOGIC_kyc_done ();
   3240     return GNUNET_SYSERR;
   3241   }
   3242 
   3243   if (0 != default_rules.num_kyc_rules)
   3244     qsort (default_rules.kyc_rules,
   3245            default_rules.num_kyc_rules,
   3246            sizeof (struct TALER_KYCLOGIC_KycRule),
   3247            &sort_by_timeframe);
   3248   jkyc_rules_w = json_array ();
   3249   GNUNET_assert (NULL != jkyc_rules_w);
   3250   jkyc_rules_a = json_array ();
   3251   GNUNET_assert (NULL != jkyc_rules_a);
   3252 
   3253   for (unsigned int i=0; i<default_rules.num_kyc_rules; i++)
   3254   {
   3255     const struct TALER_KYCLOGIC_KycRule *rule
   3256       = &default_rules.kyc_rules[i];
   3257     json_t *jrule;
   3258     json_t *jmeasures;
   3259 
   3260     jmeasures = json_array ();
   3261     GNUNET_assert (NULL != jmeasures);
   3262     for (unsigned int j=0; j<rule->num_measures; j++)
   3263     {
   3264       const char *measure_name = rule->next_measures[j];
   3265       const struct TALER_KYCLOGIC_Measure *m;
   3266 
   3267       if (0 == strcasecmp (KYC_MEASURE_IMPOSSIBLE,
   3268                            measure_name))
   3269       {
   3270         GNUNET_assert (
   3271           0 ==
   3272           json_array_append_new (jmeasures,
   3273                                  json_string (KYC_MEASURE_IMPOSSIBLE)));
   3274         continue;
   3275       }
   3276       m = find_measure (&default_rules,
   3277                         measure_name);
   3278       if (NULL == m)
   3279       {
   3280         GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
   3281                     "Unknown measure `%s' used in rule `%s'\n",
   3282                     measure_name,
   3283                     rule->rule_name);
   3284         return GNUNET_SYSERR;
   3285       }
   3286       GNUNET_assert (0 ==
   3287                      json_array_append_new (jmeasures,
   3288                                             json_string (measure_name)));
   3289     }
   3290     jrule = GNUNET_JSON_PACK (
   3291       GNUNET_JSON_pack_allow_null (
   3292         GNUNET_JSON_pack_string ("rule_name",
   3293                                  rule->rule_name)),
   3294       TALER_JSON_pack_kycte ("operation_type",
   3295                              rule->trigger),
   3296       TALER_JSON_pack_amount ("threshold",
   3297                               &rule->threshold),
   3298       GNUNET_JSON_pack_time_rel ("timeframe",
   3299                                  rule->timeframe),
   3300       GNUNET_JSON_pack_array_steal ("measures",
   3301                                     jmeasures),
   3302       GNUNET_JSON_pack_uint64 ("display_priority",
   3303                                rule->display_priority),
   3304       GNUNET_JSON_pack_bool ("exposed",
   3305                              rule->exposed),
   3306       GNUNET_JSON_pack_bool ("is_and_combinator",
   3307                              rule->is_and_combinator)
   3308       );
   3309     switch (rule->trigger)
   3310     {
   3311     case TALER_KYCLOGIC_KYC_TRIGGER_NONE:
   3312       GNUNET_break (0);
   3313       break;
   3314     case TALER_KYCLOGIC_KYC_TRIGGER_WITHDRAW:
   3315       GNUNET_assert (0 ==
   3316                      json_array_append (jkyc_rules_a,
   3317                                         jrule));
   3318       break;
   3319     case TALER_KYCLOGIC_KYC_TRIGGER_DEPOSIT:
   3320       GNUNET_assert (0 ==
   3321                      json_array_append (jkyc_rules_a,
   3322                                         jrule));
   3323       break;
   3324     case TALER_KYCLOGIC_KYC_TRIGGER_P2P_RECEIVE:
   3325       GNUNET_assert (0 ==
   3326                      json_array_append (jkyc_rules_w,
   3327                                         jrule));
   3328       break;
   3329     case TALER_KYCLOGIC_KYC_TRIGGER_WALLET_BALANCE:
   3330       GNUNET_assert (0 ==
   3331                      json_array_append (jkyc_rules_w,
   3332                                         jrule));
   3333       break;
   3334     case TALER_KYCLOGIC_KYC_TRIGGER_RESERVE_CLOSE:
   3335       GNUNET_assert (0 ==
   3336                      json_array_append (jkyc_rules_a,
   3337                                         jrule));
   3338       break;
   3339     case TALER_KYCLOGIC_KYC_TRIGGER_AGGREGATE:
   3340       GNUNET_assert (0 ==
   3341                      json_array_append (jkyc_rules_a,
   3342                                         jrule));
   3343       break;
   3344     case TALER_KYCLOGIC_KYC_TRIGGER_TRANSACTION:
   3345       GNUNET_assert (0 ==
   3346                      json_array_append (jkyc_rules_a,
   3347                                         jrule));
   3348       GNUNET_assert (0 ==
   3349                      json_array_append (jkyc_rules_w,
   3350                                         jrule));
   3351       break;
   3352     case TALER_KYCLOGIC_KYC_TRIGGER_REFUND:
   3353       GNUNET_assert (0 ==
   3354                      json_array_append (jkyc_rules_a,
   3355                                         jrule));
   3356       GNUNET_assert (0 ==
   3357                      json_array_append (jkyc_rules_w,
   3358                                         jrule));
   3359       break;
   3360     }
   3361     json_decref (jrule);
   3362   }
   3363   {
   3364     json_t *empty = json_object ();
   3365 
   3366     GNUNET_assert (NULL != empty);
   3367     wallet_default_lrs
   3368       = GNUNET_JSON_PACK (
   3369           GNUNET_JSON_pack_timestamp ("expiration_time",
   3370                                       GNUNET_TIME_UNIT_FOREVER_TS),
   3371           GNUNET_JSON_pack_array_steal ("rules",
   3372                                         jkyc_rules_w),
   3373           GNUNET_JSON_pack_object_incref ("custom_measures",
   3374                                           empty)
   3375           );
   3376     bankaccount_default_lrs
   3377       = GNUNET_JSON_PACK (
   3378           GNUNET_JSON_pack_timestamp ("expiration_time",
   3379                                       GNUNET_TIME_UNIT_FOREVER_TS),
   3380           GNUNET_JSON_pack_array_steal ("rules",
   3381                                         jkyc_rules_a),
   3382           GNUNET_JSON_pack_object_incref ("custom_measures",
   3383                                           empty)
   3384           );
   3385     json_decref (empty);
   3386   }
   3387   for (unsigned int i=0; i<default_rules.num_custom_measures; i++)
   3388   {
   3389     const struct TALER_KYCLOGIC_Measure *measure
   3390       = &default_rules.custom_measures[i];
   3391 
   3392     if (! check_measure (measure))
   3393     {
   3394       GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
   3395                   "Configuration of AML measures incorrect. Exiting.\n");
   3396       return GNUNET_SYSERR;
   3397     }
   3398   }
   3399 
   3400   for (unsigned int i=0; i<num_aml_programs; i++)
   3401   {
   3402     const struct TALER_KYCLOGIC_AmlProgram *program
   3403       = aml_programs[i];
   3404     const struct TALER_KYCLOGIC_Measure *m;
   3405 
   3406     m = find_measure (&default_rules,
   3407                       program->fallback);
   3408     if (NULL == m)
   3409     {
   3410       GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
   3411                   "Unknown fallback measure `%s' used in program `%s'\n",
   3412                   program->fallback,
   3413                   program->program_name);
   3414       return GNUNET_SYSERR;
   3415     }
   3416     if (0 != strcasecmp (m->check_name,
   3417                          "skip"))
   3418     {
   3419       GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
   3420                   "Fallback measure `%s' used in AML program `%s' has a check `%s' but fallbacks must have a check of type 'skip'\n",
   3421                   program->fallback,
   3422                   program->program_name,
   3423                   m->check_name);
   3424       return GNUNET_SYSERR;
   3425     }
   3426     if (NULL != m->prog_name)
   3427     {
   3428       const struct TALER_KYCLOGIC_AmlProgram *fprogram;
   3429 
   3430       fprogram = find_program (m->prog_name);
   3431       GNUNET_assert (NULL != fprogram);
   3432       if (API_NONE != (fprogram->input_mask & (API_CONTEXT | API_ATTRIBUTES)))
   3433       {
   3434         GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
   3435                     "Fallback program %s of fallback measure `%s' used in AML program `%s' has required inputs, but fallback measures must not require any inputs\n",
   3436                     m->prog_name,
   3437                     program->program_name,
   3438                     m->check_name);
   3439         return GNUNET_SYSERR;
   3440       }
   3441     }
   3442   }
   3443 
   3444   for (unsigned int i = 0; i<num_kyc_checks; i++)
   3445   {
   3446     struct TALER_KYCLOGIC_KycCheck *kyc_check
   3447       = kyc_checks[i];
   3448     const struct TALER_KYCLOGIC_Measure *measure;
   3449 
   3450     measure = find_measure (&default_rules,
   3451                             kyc_check->fallback);
   3452     if (NULL == measure)
   3453     {
   3454       GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
   3455                   "Unknown fallback measure `%s' used in check `%s'\n",
   3456                   kyc_check->fallback,
   3457                   kyc_check->check_name);
   3458       return GNUNET_SYSERR;
   3459     }
   3460     if (0 != strcasecmp (measure->check_name,
   3461                          "skip"))
   3462     {
   3463       GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
   3464                   "Fallback measure `%s' used in KYC check `%s' has a check `%s' but fallbacks must have a check of type 'skip'\n",
   3465                   kyc_check->fallback,
   3466                   kyc_check->check_name,
   3467                   measure->check_name);
   3468       return GNUNET_SYSERR;
   3469     }
   3470     if (NULL != measure->prog_name)
   3471     {
   3472       const struct TALER_KYCLOGIC_AmlProgram *fprogram;
   3473 
   3474       fprogram = find_program (measure->prog_name);
   3475       GNUNET_assert (NULL != fprogram);
   3476       if (API_NONE != (fprogram->input_mask & (API_CONTEXT | API_ATTRIBUTES)))
   3477       {
   3478         GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
   3479                     "AML program `%s' used fallback measure `%s' of KYC check `%s' has required inputs, but fallback measures must not require any inputs\n",
   3480                     measure->prog_name,
   3481                     kyc_check->fallback,
   3482                     kyc_check->check_name);
   3483         return GNUNET_SYSERR;
   3484       }
   3485     }
   3486   }
   3487 
   3488   return GNUNET_OK;
   3489 }
   3490 
   3491 
   3492 void
   3493 TALER_KYCLOGIC_kyc_done (void)
   3494 {
   3495   free_rules (&default_rules);
   3496   memset (&default_rules,
   3497           0,
   3498           sizeof (default_rules));
   3499   for (unsigned int i = 0; i<num_kyc_providers; i++)
   3500   {
   3501     struct TALER_KYCLOGIC_KycProvider *kp = kyc_providers[i];
   3502 
   3503     kp->logic->unload_configuration (kp->pd);
   3504     GNUNET_free (kp->provider_name);
   3505     GNUNET_free (kp);
   3506   }
   3507   GNUNET_array_grow (kyc_providers,
   3508                      num_kyc_providers,
   3509                      0);
   3510   for (unsigned int i = 0; i<num_kyc_logics; i++)
   3511   {
   3512     struct TALER_KYCLOGIC_Plugin *lp = kyc_logics[i];
   3513     char *lib_name = lp->library_name;
   3514 
   3515     GNUNET_free (lp->name);
   3516     GNUNET_assert (NULL == GNUNET_PLUGIN_unload (lib_name,
   3517                                                  lp));
   3518     GNUNET_free (lib_name);
   3519   }
   3520   GNUNET_array_grow (kyc_logics,
   3521                      num_kyc_logics,
   3522                      0);
   3523   for (unsigned int i = 0; i<num_kyc_checks; i++)
   3524   {
   3525     struct TALER_KYCLOGIC_KycCheck *kc = kyc_checks[i];
   3526 
   3527     GNUNET_free (kc->check_name);
   3528     GNUNET_free (kc->description);
   3529     json_decref (kc->description_i18n);
   3530     for (unsigned int j = 0; j<kc->num_requires; j++)
   3531       GNUNET_free (kc->requires[j]);
   3532     GNUNET_array_grow (kc->requires,
   3533                        kc->num_requires,
   3534                        0);
   3535     GNUNET_free (kc->fallback);
   3536     for (unsigned int j = 0; j<kc->num_outputs; j++)
   3537       GNUNET_free (kc->outputs[j]);
   3538     GNUNET_array_grow (kc->outputs,
   3539                        kc->num_outputs,
   3540                        0);
   3541     switch (kc->type)
   3542     {
   3543     case TALER_KYCLOGIC_CT_INFO:
   3544       break;
   3545     case TALER_KYCLOGIC_CT_FORM:
   3546       GNUNET_free (kc->details.form.name);
   3547       break;
   3548     case TALER_KYCLOGIC_CT_LINK:
   3549       break;
   3550     }
   3551     GNUNET_free (kc);
   3552   }
   3553   GNUNET_array_grow (kyc_checks,
   3554                      num_kyc_checks,
   3555                      0);
   3556   for (unsigned int i = 0; i<num_aml_programs; i++)
   3557   {
   3558     struct TALER_KYCLOGIC_AmlProgram *ap = aml_programs[i];
   3559 
   3560     GNUNET_free (ap->program_name);
   3561     GNUNET_free (ap->command);
   3562     GNUNET_free (ap->description);
   3563     GNUNET_free (ap->fallback);
   3564     for (unsigned int j = 0; j<ap->num_required_contexts; j++)
   3565       GNUNET_free (ap->required_contexts[j]);
   3566     GNUNET_array_grow (ap->required_contexts,
   3567                        ap->num_required_contexts,
   3568                        0);
   3569     for (unsigned int j = 0; j<ap->num_required_attributes; j++)
   3570       GNUNET_free (ap->required_attributes[j]);
   3571     GNUNET_array_grow (ap->required_attributes,
   3572                        ap->num_required_attributes,
   3573                        0);
   3574     GNUNET_free (ap);
   3575   }
   3576   GNUNET_array_grow (aml_programs,
   3577                      num_aml_programs,
   3578                      0);
   3579   GNUNET_free (cfg_filename);
   3580 }
   3581 
   3582 
   3583 void
   3584 TALER_KYCLOGIC_provider_to_logic (
   3585   const struct TALER_KYCLOGIC_KycProvider *provider,
   3586   struct TALER_KYCLOGIC_Plugin **plugin,
   3587   struct TALER_KYCLOGIC_ProviderDetails **pd,
   3588   const char **provider_name)
   3589 {
   3590   *plugin = provider->logic;
   3591   *pd = provider->pd;
   3592   *provider_name = provider->provider_name;
   3593 }
   3594 
   3595 
   3596 enum GNUNET_GenericReturnValue
   3597 TALER_KYCLOGIC_get_original_measure (
   3598   const char *measure_name,
   3599   struct TALER_KYCLOGIC_KycCheckContext *kcc)
   3600 {
   3601   const struct TALER_KYCLOGIC_Measure *measure;
   3602 
   3603   measure = find_measure (&default_rules,
   3604                           measure_name);
   3605   if (NULL == measure)
   3606   {
   3607     GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
   3608                 "Default measure `%s' unknown\n",
   3609                 measure_name);
   3610     return GNUNET_SYSERR;
   3611   }
   3612   if (0 == strcasecmp (measure->check_name,
   3613                        "skip"))
   3614   {
   3615     kcc->check = NULL;
   3616     kcc->prog_name = measure->prog_name;
   3617     kcc->context = measure->context;
   3618     return GNUNET_OK;
   3619   }
   3620 
   3621   for (unsigned int i = 0; i<num_kyc_checks; i++)
   3622     if (0 == strcasecmp (measure->check_name,
   3623                          kyc_checks[i]->check_name))
   3624     {
   3625       kcc->check = kyc_checks[i];
   3626       kcc->prog_name = measure->prog_name;
   3627       kcc->context = measure->context;
   3628       return GNUNET_OK;
   3629     }
   3630   GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
   3631               "Check `%s' unknown (but required by measure `%s')\n",
   3632               measure->check_name,
   3633               measure_name);
   3634   return GNUNET_SYSERR;
   3635 }
   3636 
   3637 
   3638 enum GNUNET_GenericReturnValue
   3639 TALER_KYCLOGIC_requirements_to_check (
   3640   const struct TALER_KYCLOGIC_LegitimizationRuleSet *lrs,
   3641   const struct TALER_KYCLOGIC_KycRule *kyc_rule,
   3642   const char *measure_name,
   3643   struct TALER_KYCLOGIC_KycCheckContext *kcc)
   3644 {
   3645   bool found = false;
   3646   const struct TALER_KYCLOGIC_Measure *measure = NULL;
   3647 
   3648   if (NULL == lrs)
   3649     lrs = &default_rules;
   3650   if (NULL == measure_name)
   3651   {
   3652     GNUNET_break (0);
   3653     return GNUNET_SYSERR;
   3654   }
   3655   if (NULL != kyc_rule)
   3656   {
   3657     if (kyc_rule->verboten)
   3658     {
   3659       GNUNET_log (GNUNET_ERROR_TYPE_WARNING,
   3660                   "Rule says operation is categorically is verboten, cannot take measures\n");
   3661       return GNUNET_SYSERR;
   3662     }
   3663     for (unsigned int i = 0; i<kyc_rule->num_measures; i++)
   3664     {
   3665       if (0 != strcasecmp (measure_name,
   3666                            kyc_rule->next_measures[i]))
   3667         continue;
   3668       found = true;
   3669       break;
   3670     }
   3671     if (! found)
   3672     {
   3673       GNUNET_log (GNUNET_ERROR_TYPE_WARNING,
   3674                   "Measure `%s' not allowed for rule `%s'\n",
   3675                   measure_name,
   3676                   kyc_rule->rule_name);
   3677       return GNUNET_SYSERR;
   3678     }
   3679   }
   3680   measure = find_measure (lrs,
   3681                           measure_name);
   3682   if (NULL == measure)
   3683   {
   3684     GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
   3685                 "Measure `%s' unknown (but allowed by rule `%s')\n",
   3686                 measure_name,
   3687                 NULL != kyc_rule
   3688                 ? kyc_rule->rule_name
   3689                 : "<NONE>");
   3690     return GNUNET_SYSERR;
   3691   }
   3692 
   3693   if (0 == strcasecmp (measure->check_name,
   3694                        "skip"))
   3695   {
   3696     kcc->check = NULL;
   3697     kcc->prog_name = measure->prog_name;
   3698     kcc->context = measure->context;
   3699     return GNUNET_OK;
   3700   }
   3701 
   3702   for (unsigned int i = 0; i<num_kyc_checks; i++)
   3703     if (0 == strcasecmp (measure->check_name,
   3704                          kyc_checks[i]->check_name))
   3705     {
   3706       kcc->check = kyc_checks[i];
   3707       kcc->prog_name = measure->prog_name;
   3708       kcc->context = measure->context;
   3709       return GNUNET_OK;
   3710     }
   3711   GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
   3712               "Check `%s' unknown (but required by measure `%s')\n",
   3713               measure->check_name,
   3714               measure_name);
   3715   return GNUNET_SYSERR;
   3716 }
   3717 
   3718 
   3719 enum GNUNET_GenericReturnValue
   3720 TALER_KYCLOGIC_lookup_logic (
   3721   const char *name,
   3722   struct TALER_KYCLOGIC_Plugin **plugin,
   3723   struct TALER_KYCLOGIC_ProviderDetails **pd,
   3724   const char **provider_name)
   3725 {
   3726   for (unsigned int i = 0; i<num_kyc_providers; i++)
   3727   {
   3728     struct TALER_KYCLOGIC_KycProvider *kp = kyc_providers[i];
   3729 
   3730     if (0 !=
   3731         strcasecmp (name,
   3732                     kp->provider_name))
   3733       continue;
   3734     *plugin = kp->logic;
   3735     *pd = kp->pd;
   3736     *provider_name = kp->provider_name;
   3737     return GNUNET_OK;
   3738   }
   3739   for (unsigned int i = 0; i<num_kyc_logics; i++)
   3740   {
   3741     struct TALER_KYCLOGIC_Plugin *logic = kyc_logics[i];
   3742 
   3743     if (0 !=
   3744         strcasecmp (logic->name,
   3745                     name))
   3746       continue;
   3747     *plugin = logic;
   3748     *pd = NULL;
   3749     *provider_name = NULL;
   3750     return GNUNET_OK;
   3751   }
   3752   GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
   3753               "Provider `%s' unknown\n",
   3754               name);
   3755   return GNUNET_SYSERR;
   3756 }
   3757 
   3758 
   3759 void
   3760 TALER_KYCLOGIC_kyc_get_details (
   3761   const char *logic_name,
   3762   TALER_KYCLOGIC_DetailsCallback cb,
   3763   void *cb_cls)
   3764 {
   3765   for (unsigned int i = 0; i<num_kyc_providers; i++)
   3766   {
   3767     struct TALER_KYCLOGIC_KycProvider *kp
   3768       = kyc_providers[i];
   3769 
   3770     if (0 !=
   3771         strcasecmp (kp->logic->name,
   3772                     logic_name))
   3773       continue;
   3774     if (GNUNET_OK !=
   3775         cb (cb_cls,
   3776             kp->pd,
   3777             kp->logic->cls))
   3778       return;
   3779   }
   3780 }
   3781 
   3782 
   3783 /**
   3784  * Closure for check_amount().
   3785  */
   3786 struct KycTestContext
   3787 {
   3788   /**
   3789    * Rule set we apply.
   3790    */
   3791   const struct TALER_KYCLOGIC_LegitimizationRuleSet *lrs;
   3792 
   3793   /**
   3794    * Events we care about.
   3795    */
   3796   enum TALER_KYCLOGIC_KycTriggerEvent event;
   3797 
   3798   /**
   3799    * Total amount encountered so far, invalid if zero.
   3800    */
   3801   struct TALER_Amount sum;
   3802 
   3803   /**
   3804    * Set to the triggered rule.
   3805    */
   3806   const struct TALER_KYCLOGIC_KycRule *triggered_rule;
   3807 
   3808 };
   3809 
   3810 
   3811 /**
   3812  * Function called on each @a amount that was found to
   3813  * be relevant for a KYC check.  Evaluates the given
   3814  * @a amount and @a date against all the applicable
   3815  * rules in the legitimization rule set.
   3816  *
   3817  * @param cls our `struct KycTestContext *`
   3818  * @param amount encountered transaction amount
   3819  * @param date when was the amount encountered
   3820  * @return #GNUNET_OK to continue to iterate,
   3821  *         #GNUNET_NO to abort iteration,
   3822  *         #GNUNET_SYSERR on internal error (also abort itaration)
   3823  */
   3824 static enum GNUNET_GenericReturnValue
   3825 check_amount (
   3826   void *cls,
   3827   const struct TALER_Amount *amount,
   3828   struct GNUNET_TIME_Absolute date)
   3829 {
   3830   struct KycTestContext *ktc = cls;
   3831   struct GNUNET_TIME_Relative dur;
   3832 
   3833   GNUNET_log (GNUNET_ERROR_TYPE_INFO,
   3834               "KYC checking transaction amount %s from %s against %u rules\n",
   3835               TALER_amount2s (amount),
   3836               GNUNET_TIME_absolute2s (date),
   3837               ktc->lrs->num_kyc_rules);
   3838   dur = GNUNET_TIME_absolute_get_duration (date);
   3839   if (GNUNET_OK !=
   3840       TALER_amount_is_valid (&ktc->sum))
   3841     ktc->sum = *amount;
   3842   else
   3843     GNUNET_assert (0 <=
   3844                    TALER_amount_add (&ktc->sum,
   3845                                      &ktc->sum,
   3846                                      amount));
   3847   for (unsigned int i=0; i<ktc->lrs->num_kyc_rules; i++)
   3848   {
   3849     const struct TALER_KYCLOGIC_KycRule *rule
   3850       = &ktc->lrs->kyc_rules[i];
   3851 
   3852     if (ktc->event != rule->trigger)
   3853     {
   3854       GNUNET_log (GNUNET_ERROR_TYPE_INFO,
   3855                   "Wrong event type (%d) for rule %u (%d)\n",
   3856                   (int) ktc->event,
   3857                   i,
   3858                   (int) rule->trigger);
   3859       continue; /* wrong trigger event type */
   3860     }
   3861     if (GNUNET_TIME_relative_cmp (dur,
   3862                                   >,
   3863                                   rule->timeframe))
   3864     {
   3865       GNUNET_log (GNUNET_ERROR_TYPE_INFO,
   3866                   "Out of time range for rule %u\n",
   3867                   i);
   3868       continue; /* out of time range for rule */
   3869     }
   3870     if (-1 == TALER_amount_cmp (&ktc->sum,
   3871                                 &rule->threshold))
   3872     {
   3873       GNUNET_log (GNUNET_ERROR_TYPE_INFO,
   3874                   "Below threshold of %s for rule %u\n",
   3875                   TALER_amount2s (&rule->threshold),
   3876                   i);
   3877       continue; /* sum < threshold */
   3878     }
   3879     if ( (NULL != ktc->triggered_rule) &&
   3880          (1 == TALER_amount_cmp (&ktc->triggered_rule->threshold,
   3881                                  &rule->threshold)) )
   3882     {
   3883       GNUNET_log (GNUNET_ERROR_TYPE_INFO,
   3884                   "Higher than threshold of already triggered rule\n");
   3885       continue; /* threshold of triggered_rule > rule */
   3886     }
   3887     GNUNET_log (GNUNET_ERROR_TYPE_INFO,
   3888                 "Remembering rule %s as triggered\n",
   3889                 rule->rule_name);
   3890     ktc->triggered_rule = rule;
   3891   }
   3892   return GNUNET_OK;
   3893 }
   3894 
   3895 
   3896 enum GNUNET_DB_QueryStatus
   3897 TALER_KYCLOGIC_kyc_test_required (
   3898   enum TALER_KYCLOGIC_KycTriggerEvent event,
   3899   const struct TALER_KYCLOGIC_LegitimizationRuleSet *lrs,
   3900   TALER_KYCLOGIC_KycAmountIterator ai,
   3901   void *ai_cls,
   3902   const struct TALER_KYCLOGIC_KycRule **triggered_rule,
   3903   struct TALER_Amount *next_threshold)
   3904 {
   3905   struct GNUNET_TIME_Relative range
   3906     = GNUNET_TIME_UNIT_ZERO;
   3907   enum GNUNET_DB_QueryStatus qs;
   3908   bool have_threshold = false;
   3909 
   3910   memset (next_threshold,
   3911           0,
   3912           sizeof (struct TALER_Amount));
   3913   if (NULL == lrs)
   3914     lrs = &default_rules;
   3915   GNUNET_log (GNUNET_ERROR_TYPE_INFO,
   3916               "Testing %u KYC rules for trigger %d\n",
   3917               lrs->num_kyc_rules,
   3918               event);
   3919   for (unsigned int i=0; i<lrs->num_kyc_rules; i++)
   3920   {
   3921     const struct TALER_KYCLOGIC_KycRule *rule
   3922       = &lrs->kyc_rules[i];
   3923 
   3924     if (event != rule->trigger)
   3925     {
   3926       GNUNET_log (GNUNET_ERROR_TYPE_INFO,
   3927                   "Rule %u is for a different trigger (%d/%d)\n",
   3928                   i,
   3929                   (int) event,
   3930                   (int) rule->trigger);
   3931       continue;
   3932     }
   3933     if (have_threshold)
   3934     {
   3935       GNUNET_assert (GNUNET_OK ==
   3936                      TALER_amount_min (next_threshold,
   3937                                        next_threshold,
   3938                                        &rule->threshold));
   3939     }
   3940     else
   3941     {
   3942       *next_threshold = rule->threshold;
   3943       have_threshold = true;
   3944     }
   3945     GNUNET_log (GNUNET_ERROR_TYPE_INFO,
   3946                 "Matched rule %u with timeframe %s and threshold %s\n",
   3947                 i,
   3948                 GNUNET_TIME_relative2s (rule->timeframe,
   3949                                         true),
   3950                 TALER_amount2s (&rule->threshold));
   3951     range = GNUNET_TIME_relative_max (range,
   3952                                       rule->timeframe);
   3953   }
   3954 
   3955   if (! have_threshold)
   3956   {
   3957     GNUNET_log (GNUNET_ERROR_TYPE_INFO,
   3958                 "No rules apply\n");
   3959     *triggered_rule = NULL;
   3960     return GNUNET_DB_STATUS_SUCCESS_NO_RESULTS;
   3961   }
   3962 
   3963   {
   3964     struct GNUNET_TIME_Absolute now
   3965       = GNUNET_TIME_absolute_get ();
   3966     struct KycTestContext ktc = {
   3967       .lrs = lrs,
   3968       .event = event
   3969     };
   3970 
   3971     qs = ai (ai_cls,
   3972              GNUNET_TIME_absolute_subtract (now,
   3973                                             range),
   3974              &check_amount,
   3975              &ktc);
   3976     GNUNET_log (GNUNET_ERROR_TYPE_INFO,
   3977                 "Triggered rule is %s\n",
   3978                 (NULL == ktc.triggered_rule)
   3979                 ? "NONE"
   3980                 : ktc.triggered_rule->rule_name);
   3981     *triggered_rule = ktc.triggered_rule;
   3982   }
   3983   return qs;
   3984 }
   3985 
   3986 
   3987 json_t *
   3988 TALER_KYCLOGIC_measure_to_requirement (
   3989   const char *check_name,
   3990   const json_t *context,
   3991   const struct TALER_AccountAccessTokenP *access_token,
   3992   size_t offset,
   3993   uint64_t legitimization_measure_row_id)
   3994 {
   3995   struct TALER_KYCLOGIC_KycCheck *kc;
   3996   json_t *kri;
   3997   struct TALER_KycMeasureAuthorizationHashP shv;
   3998   char *ids;
   3999   char *xids;
   4000 
   4001   kc = find_check (check_name);
   4002   if (NULL == kc)
   4003   {
   4004     GNUNET_break (0);
   4005     return NULL;
   4006   }
   4007   GNUNET_assert (offset <= UINT32_MAX);
   4008   TALER_kyc_measure_authorization_hash (access_token,
   4009                                         legitimization_measure_row_id,
   4010                                         (uint32_t) offset,
   4011                                         &shv);
   4012   switch (kc->type)
   4013   {
   4014   case TALER_KYCLOGIC_CT_INFO:
   4015     return GNUNET_JSON_PACK (
   4016       GNUNET_JSON_pack_string ("form",
   4017                                "INFO"),
   4018       GNUNET_JSON_pack_string ("description",
   4019                                kc->description),
   4020       GNUNET_JSON_pack_allow_null (
   4021         GNUNET_JSON_pack_object_incref ("description_i18n",
   4022                                         (json_t *) kc->description_i18n)));
   4023   case TALER_KYCLOGIC_CT_FORM:
   4024     GNUNET_assert (offset <= UINT_MAX);
   4025     ids = GNUNET_STRINGS_data_to_string_alloc (&shv,
   4026                                                sizeof (shv));
   4027     GNUNET_asprintf (&xids,
   4028                      "%s-%u-%llu",
   4029                      ids,
   4030                      (unsigned int) offset,
   4031                      (unsigned long long) legitimization_measure_row_id);
   4032     GNUNET_free (ids);
   4033     kri = GNUNET_JSON_PACK (
   4034       GNUNET_JSON_pack_string ("form",
   4035                                kc->details.form.name),
   4036       GNUNET_JSON_pack_string ("id",
   4037                                xids),
   4038       GNUNET_JSON_pack_allow_null (
   4039         GNUNET_JSON_pack_object_incref ("context",
   4040                                         (json_t *) context)),
   4041       GNUNET_JSON_pack_string ("description",
   4042                                kc->description),
   4043       GNUNET_JSON_pack_allow_null (
   4044         GNUNET_JSON_pack_object_incref ("description_i18n",
   4045                                         (json_t *) kc->description_i18n)));
   4046     GNUNET_free (xids);
   4047     return kri;
   4048   case TALER_KYCLOGIC_CT_LINK:
   4049     GNUNET_assert (offset <= UINT_MAX);
   4050     ids = GNUNET_STRINGS_data_to_string_alloc (&shv,
   4051                                                sizeof (shv));
   4052     GNUNET_asprintf (&xids,
   4053                      "%s-%u-%llu",
   4054                      ids,
   4055                      (unsigned int) offset,
   4056                      (unsigned long long) legitimization_measure_row_id);
   4057     GNUNET_free (ids);
   4058     kri = GNUNET_JSON_PACK (
   4059       GNUNET_JSON_pack_string ("form",
   4060                                "LINK"),
   4061       GNUNET_JSON_pack_string ("id",
   4062                                xids),
   4063       GNUNET_JSON_pack_string ("description",
   4064                                kc->description),
   4065       GNUNET_JSON_pack_allow_null (
   4066         GNUNET_JSON_pack_object_incref ("description_i18n",
   4067                                         (json_t *) kc->description_i18n)));
   4068     GNUNET_free (xids);
   4069     return kri;
   4070   }
   4071   GNUNET_break (0); /* invalid type */
   4072   return NULL;
   4073 }
   4074 
   4075 
   4076 void
   4077 TALER_KYCLOGIC_get_measure_configuration (
   4078   json_t **proots,
   4079   json_t **pprograms,
   4080   json_t **pchecks,
   4081   json_t **pdefault_rules)
   4082 {
   4083   json_t *roots;
   4084   json_t *programs;
   4085   json_t *checks;
   4086   json_t *drules;
   4087 
   4088   roots = json_object ();
   4089   GNUNET_assert (NULL != roots);
   4090   for (unsigned int i = 0; i<default_rules.num_custom_measures; i++)
   4091   {
   4092     const struct TALER_KYCLOGIC_Measure *m
   4093       = &default_rules.custom_measures[i];
   4094     json_t *jm;
   4095 
   4096     jm = GNUNET_JSON_PACK (
   4097       GNUNET_JSON_pack_string ("check_name",
   4098                                m->check_name),
   4099       GNUNET_JSON_pack_allow_null (
   4100         GNUNET_JSON_pack_string ("prog_name",
   4101                                  m->prog_name)),
   4102       GNUNET_JSON_pack_allow_null (
   4103         GNUNET_JSON_pack_object_incref ("context",
   4104                                         m->context)));
   4105     GNUNET_assert (0 ==
   4106                    json_object_set_new (roots,
   4107                                         m->measure_name,
   4108                                         jm));
   4109   }
   4110 
   4111   programs = json_object ();
   4112   GNUNET_assert (NULL != programs);
   4113   for (unsigned int i = 0; i<num_aml_programs; i++)
   4114   {
   4115     const struct TALER_KYCLOGIC_AmlProgram *ap
   4116       = aml_programs[i];
   4117     json_t *jp;
   4118     json_t *ctx;
   4119     json_t *inp;
   4120 
   4121     ctx = json_array ();
   4122     GNUNET_assert (NULL != ctx);
   4123     for (unsigned int j = 0; j<ap->num_required_contexts; j++)
   4124     {
   4125       const char *rc = ap->required_contexts[j];
   4126 
   4127       GNUNET_assert (0 ==
   4128                      json_array_append_new (ctx,
   4129                                             json_string (rc)));
   4130     }
   4131     inp = json_array ();
   4132     GNUNET_assert (NULL != inp);
   4133     for (unsigned int j = 0; j<ap->num_required_attributes; j++)
   4134     {
   4135       const char *ra = ap->required_attributes[j];
   4136 
   4137       GNUNET_assert (0 ==
   4138                      json_array_append_new (inp,
   4139                                             json_string (ra)));
   4140     }
   4141 
   4142     jp = GNUNET_JSON_PACK (
   4143       GNUNET_JSON_pack_string ("description",
   4144                                ap->description),
   4145       GNUNET_JSON_pack_array_steal ("context",
   4146                                     ctx),
   4147       GNUNET_JSON_pack_array_steal ("inputs",
   4148                                     inp));
   4149     GNUNET_assert (0 ==
   4150                    json_object_set_new (programs,
   4151                                         ap->program_name,
   4152                                         jp));
   4153   }
   4154 
   4155   checks = json_object ();
   4156   GNUNET_assert (NULL != checks);
   4157   for (unsigned int i = 0; i<num_kyc_checks; i++)
   4158   {
   4159     const struct TALER_KYCLOGIC_KycCheck *ck
   4160       = kyc_checks[i];
   4161     json_t *jc;
   4162     json_t *requires;
   4163     json_t *outputs;
   4164 
   4165     requires = json_array ();
   4166     GNUNET_assert (NULL != requires);
   4167     for (unsigned int j = 0; j<ck->num_requires; j++)
   4168     {
   4169       const char *ra = ck->requires[j];
   4170 
   4171       GNUNET_assert (0 ==
   4172                      json_array_append_new (requires,
   4173                                             json_string (ra)));
   4174     }
   4175     outputs = json_array ();
   4176     GNUNET_assert (NULL != outputs);
   4177     for (unsigned int j = 0; j<ck->num_outputs; j++)
   4178     {
   4179       const char *out = ck->outputs[j];
   4180 
   4181       GNUNET_assert (0 ==
   4182                      json_array_append_new (outputs,
   4183                                             json_string (out)));
   4184     }
   4185 
   4186     jc = GNUNET_JSON_PACK (
   4187       GNUNET_JSON_pack_string ("description",
   4188                                ck->description),
   4189       GNUNET_JSON_pack_allow_null (
   4190         GNUNET_JSON_pack_object_incref ("description_i18n",
   4191                                         ck->description_i18n)),
   4192       GNUNET_JSON_pack_array_steal ("requires",
   4193                                     requires),
   4194       GNUNET_JSON_pack_array_steal ("outputs",
   4195                                     outputs),
   4196       GNUNET_JSON_pack_string ("fallback",
   4197                                ck->fallback));
   4198     GNUNET_assert (0 ==
   4199                    json_object_set_new (checks,
   4200                                         ck->check_name,
   4201                                         jc));
   4202   }
   4203   drules = json_array ();
   4204   GNUNET_assert (NULL != drules);
   4205   {
   4206     const struct TALER_KYCLOGIC_KycRule *rules
   4207       = default_rules.kyc_rules;
   4208     unsigned int num_rules
   4209       = default_rules.num_kyc_rules;
   4210 
   4211     for (unsigned int i = 0; i<num_rules; i++)
   4212     {
   4213       const struct TALER_KYCLOGIC_KycRule *rule = &rules[i];
   4214       json_t *measures;
   4215       json_t *limit;
   4216 
   4217       measures = json_array ();
   4218       GNUNET_assert (NULL != measures);
   4219       for (unsigned int j = 0; j<rule->num_measures; j++)
   4220         GNUNET_assert (
   4221           0 ==
   4222           json_array_append_new (measures,
   4223                                  json_string (
   4224                                    rule->next_measures[j])));
   4225       limit = GNUNET_JSON_PACK (
   4226         GNUNET_JSON_pack_allow_null (
   4227           GNUNET_JSON_pack_string ("rule_name",
   4228                                    rule->rule_name)),
   4229         TALER_JSON_pack_kycte ("operation_type",
   4230                                rule->trigger),
   4231         TALER_JSON_pack_amount ("threshold",
   4232                                 &rule->threshold),
   4233         GNUNET_JSON_pack_time_rel ("timeframe",
   4234                                    rule->timeframe),
   4235         GNUNET_JSON_pack_array_steal ("measures",
   4236                                       measures),
   4237         GNUNET_JSON_pack_uint64 ("display_priority",
   4238                                  rule->display_priority),
   4239         GNUNET_JSON_pack_bool ("soft_limit",
   4240                                ! rule->verboten),
   4241         GNUNET_JSON_pack_bool ("exposed",
   4242                                rule->exposed),
   4243         GNUNET_JSON_pack_bool ("is_and_combinator",
   4244                                rule->is_and_combinator)
   4245         );
   4246       GNUNET_assert (0 ==
   4247                      json_array_append_new (drules,
   4248                                             limit));
   4249     }
   4250   }
   4251 
   4252   *proots = roots;
   4253   *pprograms = programs;
   4254   *pchecks = checks;
   4255   *pdefault_rules = drules;
   4256 }
   4257 
   4258 
   4259 enum TALER_ErrorCode
   4260 TALER_KYCLOGIC_select_measure (
   4261   const json_t *jmeasures,
   4262   size_t measure_index,
   4263   const char **check_name,
   4264   const char **prog_name,
   4265   const json_t **context)
   4266 {
   4267   const json_t *jmeasure_arr;
   4268   struct GNUNET_JSON_Specification spec[] = {
   4269     GNUNET_JSON_spec_array_const ("measures",
   4270                                   &jmeasure_arr),
   4271     GNUNET_JSON_spec_end ()
   4272   };
   4273   const json_t *jmeasure;
   4274   struct GNUNET_JSON_Specification ispec[] = {
   4275     GNUNET_JSON_spec_string ("check_name",
   4276                              check_name),
   4277     GNUNET_JSON_spec_mark_optional (
   4278       GNUNET_JSON_spec_string ("prog_name",
   4279                                prog_name),
   4280       NULL),
   4281     GNUNET_JSON_spec_mark_optional (
   4282       GNUNET_JSON_spec_object_const ("context",
   4283                                      context),
   4284       NULL),
   4285     GNUNET_JSON_spec_end ()
   4286   };
   4287 
   4288   *check_name = NULL;
   4289   *prog_name = NULL;
   4290   *context = NULL;
   4291   if (GNUNET_OK !=
   4292       GNUNET_JSON_parse (jmeasures,
   4293                          spec,
   4294                          NULL, NULL))
   4295   {
   4296     GNUNET_break (0);
   4297     return TALER_EC_EXCHANGE_KYC_MEASURES_MALFORMED;
   4298   }
   4299   if (measure_index >= json_array_size (jmeasure_arr))
   4300   {
   4301     GNUNET_break_op (0);
   4302     return TALER_EC_EXCHANGE_KYC_MEASURE_INDEX_INVALID;
   4303   }
   4304   jmeasure = json_array_get (jmeasure_arr,
   4305                              measure_index);
   4306   if (GNUNET_OK !=
   4307       GNUNET_JSON_parse (jmeasure,
   4308                          ispec,
   4309                          NULL, NULL))
   4310   {
   4311     GNUNET_break (0);
   4312     return TALER_EC_EXCHANGE_KYC_MEASURES_MALFORMED;
   4313   }
   4314   return TALER_EC_NONE;
   4315 }
   4316 
   4317 
   4318 enum TALER_ErrorCode
   4319 TALER_KYCLOGIC_check_form (
   4320   const json_t *jmeasures,
   4321   size_t measure_index,
   4322   const json_t *form_data,
   4323   char **form_name,
   4324   const char **error_message)
   4325 {
   4326   const char *check_name;
   4327   const char *prog_name;
   4328   const json_t *context;
   4329   struct TALER_KYCLOGIC_KycCheck *kc;
   4330   struct TALER_KYCLOGIC_AmlProgram *prog;
   4331 
   4332   *error_message = NULL;
   4333   *form_name = NULL;
   4334   if (TALER_EC_NONE !=
   4335       TALER_KYCLOGIC_select_measure (jmeasures,
   4336                                      measure_index,
   4337                                      &check_name,
   4338                                      &prog_name,
   4339                                      &context))
   4340   {
   4341     GNUNET_break_op (0);
   4342     return TALER_EC_EXCHANGE_KYC_MEASURE_INDEX_INVALID;
   4343   }
   4344   kc = find_check (check_name);
   4345   if (NULL == kc)
   4346   {
   4347     GNUNET_break (0);
   4348     *error_message = check_name;
   4349     return TALER_EC_EXCHANGE_KYC_GENERIC_CHECK_GONE;
   4350   }
   4351   if (TALER_KYCLOGIC_CT_FORM != kc->type)
   4352   {
   4353     GNUNET_break_op (0);
   4354     return TALER_EC_EXCHANGE_KYC_NOT_A_FORM;
   4355   }
   4356   if (NULL == prog_name)
   4357   {
   4358     /* non-INFO checks must have an AML program */
   4359     GNUNET_break (0);
   4360     return TALER_EC_EXCHANGE_KYC_GENERIC_LOGIC_BUG;
   4361   }
   4362   for (unsigned int i = 0; i<kc->num_outputs; i++)
   4363   {
   4364     const char *rattr = kc->outputs[i];
   4365 
   4366     if (NULL == json_object_get (form_data,
   4367                                  rattr))
   4368     {
   4369       GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
   4370                   "Form data lacks required attribute `%s' for KYC check `%s'\n",
   4371                   rattr,
   4372                   check_name);
   4373       *error_message = rattr;
   4374       return TALER_EC_EXCHANGE_KYC_AML_FORM_INCOMPLETE;
   4375     }
   4376   }
   4377   prog = find_program (prog_name);
   4378   if (NULL == prog)
   4379   {
   4380     GNUNET_break (0);
   4381     *error_message = prog_name;
   4382     return TALER_EC_EXCHANGE_KYC_GENERIC_AML_PROGRAM_GONE;
   4383   }
   4384   for (unsigned int i = 0; i<prog->num_required_attributes; i++)
   4385   {
   4386     const char *rattr = prog->required_attributes[i];
   4387 
   4388     if (NULL == json_object_get (form_data,
   4389                                  rattr))
   4390     {
   4391       GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
   4392                   "Form data lacks required attribute `%s' for AML program %s\n",
   4393                   rattr,
   4394                   prog_name);
   4395       *error_message = rattr;
   4396       return TALER_EC_EXCHANGE_KYC_AML_FORM_INCOMPLETE;
   4397     }
   4398   }
   4399   *form_name = GNUNET_strdup (kc->details.form.name);
   4400   return TALER_EC_NONE;
   4401 }
   4402 
   4403 
   4404 const char *
   4405 TALER_KYCLOGIC_get_aml_program_fallback (const char *prog_name)
   4406 {
   4407   struct TALER_KYCLOGIC_AmlProgram *prog;
   4408 
   4409   prog = find_program (prog_name);
   4410   if (NULL == prog)
   4411   {
   4412     GNUNET_break (0);
   4413     return NULL;
   4414   }
   4415   return prog->fallback;
   4416 }
   4417 
   4418 
   4419 const struct TALER_KYCLOGIC_KycProvider *
   4420 TALER_KYCLOGIC_check_to_provider (const char *check_name)
   4421 {
   4422   struct TALER_KYCLOGIC_KycCheck *kc;
   4423 
   4424   if (NULL == check_name)
   4425     return NULL;
   4426   if (0 == strcasecmp (check_name,
   4427                        "skip"))
   4428     return NULL;
   4429   kc = find_check (check_name);
   4430   if (NULL == kc)
   4431   {
   4432     GNUNET_break (0);
   4433     return NULL;
   4434   }
   4435   switch (kc->type)
   4436   {
   4437   case TALER_KYCLOGIC_CT_FORM:
   4438   case TALER_KYCLOGIC_CT_INFO:
   4439     return NULL;
   4440   case TALER_KYCLOGIC_CT_LINK:
   4441     break;
   4442   }
   4443   return kc->details.link.provider;
   4444 }
   4445 
   4446 
   4447 struct TALER_KYCLOGIC_AmlProgramRunnerHandle
   4448 {
   4449   /**
   4450    * Function to call back with the result.
   4451    */
   4452   TALER_KYCLOGIC_AmlProgramResultCallback aprc;
   4453 
   4454   /**
   4455    * Closure for @e aprc.
   4456    */
   4457   void *aprc_cls;
   4458 
   4459   /**
   4460    * Handle to an external process.
   4461    */
   4462   struct TALER_JSON_ExternalConversion *proc;
   4463 
   4464   /**
   4465    * AML program to turn.
   4466    */
   4467   const struct TALER_KYCLOGIC_AmlProgram *program;
   4468 
   4469   /**
   4470    * Task to return @e apr result asynchronously.
   4471    */
   4472   struct GNUNET_SCHEDULER_Task *async_cb;
   4473 
   4474   /**
   4475    * Result returned to the client.
   4476    */
   4477   struct TALER_KYCLOGIC_AmlProgramResult apr;
   4478 
   4479   /**
   4480    * How long do we allow the AML program to run?
   4481    */
   4482   struct GNUNET_TIME_Relative timeout;
   4483 
   4484 };
   4485 
   4486 
   4487 /**
   4488  * Function that that receives a JSON @a result from
   4489  * the AML program.
   4490  *
   4491  * @param cls closure of type `struct TALER_KYCLOGIC_AmlProgramRunnerHandle`
   4492  * @param status_type how did the process die
   4493  * @param code termination status code from the process,
   4494  *        non-zero if AML checks are required next
   4495  * @param result some JSON result, NULL if we failed to get an JSON output
   4496  */
   4497 static void
   4498 handle_aml_output (
   4499   void *cls,
   4500   enum GNUNET_OS_ProcessStatusType status_type,
   4501   unsigned long code,
   4502   const json_t *result)
   4503 {
   4504   struct TALER_KYCLOGIC_AmlProgramRunnerHandle *aprh = cls;
   4505   const char *fallback_measure = aprh->program->fallback;
   4506   struct TALER_KYCLOGIC_AmlProgramResult *apr = &aprh->apr;
   4507   const char **evs = NULL;
   4508 
   4509   aprh->proc = NULL;
   4510   if (NULL != aprh->async_cb)
   4511   {
   4512     GNUNET_SCHEDULER_cancel (aprh->async_cb);
   4513     aprh->async_cb = NULL;
   4514   }
   4515 #if DEBUG
   4516   GNUNET_log (GNUNET_ERROR_TYPE_INFO,
   4517               "AML program %s output is:\n",
   4518               aprh->program->program_name);
   4519   json_dumpf (result,
   4520               stderr,
   4521               JSON_INDENT (2));
   4522 #endif
   4523   memset (apr,
   4524           0,
   4525           sizeof (*apr));
   4526   if ( (GNUNET_OS_PROCESS_EXITED != status_type) ||
   4527        (0 != code) )
   4528   {
   4529     GNUNET_log (GNUNET_ERROR_TYPE_WARNING,
   4530                 "AML program %s returned non-zero status %d/%d\n",
   4531                 aprh->program->program_name,
   4532                 (int) status_type,
   4533                 (int) code);
   4534     apr->status = TALER_KYCLOGIC_AMLR_FAILURE;
   4535     apr->details.failure.fallback_measure
   4536       = fallback_measure;
   4537     apr->details.failure.error_message
   4538       = "AML program returned non-zero exit code";
   4539     apr->details.failure.ec
   4540       = TALER_EC_EXCHANGE_KYC_AML_PROGRAM_FAILURE;
   4541     goto ready;
   4542   }
   4543 
   4544   {
   4545     const json_t *jevents = NULL;
   4546     struct GNUNET_JSON_Specification spec[] = {
   4547       GNUNET_JSON_spec_mark_optional (
   4548         GNUNET_JSON_spec_bool (
   4549           "to_investigate",
   4550           &apr->details.success.to_investigate),
   4551         NULL),
   4552       GNUNET_JSON_spec_mark_optional (
   4553         GNUNET_JSON_spec_object_const (
   4554           "properties",
   4555           &apr->details.success.account_properties),
   4556         NULL),
   4557       GNUNET_JSON_spec_mark_optional (
   4558         GNUNET_JSON_spec_array_const (
   4559           "events",
   4560           &jevents),
   4561         NULL),
   4562       GNUNET_JSON_spec_object_const (
   4563         "new_rules",
   4564         &apr->details.success.new_rules),
   4565       GNUNET_JSON_spec_mark_optional (
   4566         GNUNET_JSON_spec_string (
   4567           "new_measures",
   4568           &apr->details.success.new_measures),
   4569         NULL),
   4570       GNUNET_JSON_spec_end ()
   4571     };
   4572     const char *err;
   4573     unsigned int line;
   4574 
   4575     if (GNUNET_OK !=
   4576         GNUNET_JSON_parse (result,
   4577                            spec,
   4578                            &err,
   4579                            &line))
   4580     {
   4581       GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
   4582                   "AML program output is malformed at `%s'\n",
   4583                   err);
   4584       json_dumpf (result,
   4585                   stderr,
   4586                   JSON_INDENT (2));
   4587       apr->status = TALER_KYCLOGIC_AMLR_FAILURE;
   4588       apr->details.failure.fallback_measure
   4589         = fallback_measure;
   4590       apr->details.failure.error_message
   4591         = err;
   4592       apr->details.failure.ec
   4593         = TALER_EC_EXCHANGE_KYC_AML_PROGRAM_MALFORMED_RESULT;
   4594       goto ready;
   4595     }
   4596     apr->details.success.num_events
   4597       = json_array_size (jevents);
   4598 
   4599     GNUNET_assert (((size_t) apr->details.success.num_events) ==
   4600                    json_array_size (jevents));
   4601     evs = GNUNET_new_array (
   4602       apr->details.success.num_events,
   4603       const char *);
   4604     for (unsigned int i = 0; i<apr->details.success.num_events; i++)
   4605     {
   4606       evs[i] = json_string_value (
   4607         json_array_get (jevents,
   4608                         i));
   4609       if (NULL == evs[i])
   4610       {
   4611         apr->status = TALER_KYCLOGIC_AMLR_FAILURE;
   4612         apr->details.failure.fallback_measure
   4613           = fallback_measure;
   4614         apr->details.failure.error_message
   4615           = "events";
   4616         apr->details.failure.ec
   4617           = TALER_EC_EXCHANGE_KYC_AML_PROGRAM_MALFORMED_RESULT;
   4618         goto ready;
   4619       }
   4620     }
   4621     apr->status = TALER_KYCLOGIC_AMLR_SUCCESS;
   4622     apr->details.success.events = evs;
   4623     {
   4624       /* check new_rules */
   4625       struct TALER_KYCLOGIC_LegitimizationRuleSet *lrs;
   4626 
   4627       lrs = TALER_KYCLOGIC_rules_parse (
   4628         apr->details.success.new_rules);
   4629       if (NULL == lrs)
   4630       {
   4631         GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
   4632                     "AML program output is malformed at `%s'\n",
   4633                     "new_rules");
   4634 
   4635         apr->status = TALER_KYCLOGIC_AMLR_FAILURE;
   4636         apr->details.failure.fallback_measure
   4637           = fallback_measure;
   4638         apr->details.failure.error_message
   4639           = "new_rules";
   4640         apr->details.failure.ec
   4641           = TALER_EC_EXCHANGE_KYC_AML_PROGRAM_MALFORMED_RESULT;
   4642         goto ready;
   4643       }
   4644       apr->details.success.expiration_time
   4645         = lrs->expiration_time;
   4646       TALER_KYCLOGIC_rules_free (lrs);
   4647     }
   4648   }
   4649 ready:
   4650   aprh->aprc (aprh->aprc_cls,
   4651               &aprh->apr);
   4652   GNUNET_free (evs);
   4653   TALER_KYCLOGIC_run_aml_program_cancel (aprh);
   4654 }
   4655 
   4656 
   4657 /**
   4658  * Helper function to asynchronously return the result.
   4659  *
   4660  * @param[in] cls a `struct TALER_KYCLOGIC_AmlProgramRunnerHandle` to return results for
   4661  */
   4662 static void
   4663 async_return_task (void *cls)
   4664 {
   4665   struct TALER_KYCLOGIC_AmlProgramRunnerHandle *aprh = cls;
   4666 
   4667   aprh->async_cb = NULL;
   4668   aprh->aprc (aprh->aprc_cls,
   4669               &aprh->apr);
   4670   TALER_KYCLOGIC_run_aml_program_cancel (aprh);
   4671 }
   4672 
   4673 
   4674 /**
   4675  * Helper function called on timeout on the fallback measure.
   4676  *
   4677  * @param[in] cls a `struct TALER_KYCLOGIC_AmlProgramRunnerHandle` to return results for
   4678  */
   4679 static void
   4680 handle_aml_timeout2 (void *cls)
   4681 {
   4682   struct TALER_KYCLOGIC_AmlProgramRunnerHandle *aprh = cls;
   4683   struct TALER_KYCLOGIC_AmlProgramResult *apr = &aprh->apr;
   4684   const char *fallback_measure = aprh->program->fallback;
   4685 
   4686   GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
   4687               "Fallback measure %s ran into timeout (!)\n",
   4688               aprh->program->program_name);
   4689   if (NULL != aprh->proc)
   4690   {
   4691     TALER_JSON_external_conversion_stop (aprh->proc);
   4692     aprh->proc = NULL;
   4693   }
   4694   apr->status = TALER_KYCLOGIC_AMLR_FAILURE;
   4695   apr->details.failure.fallback_measure
   4696     = fallback_measure;
   4697   apr->details.failure.error_message
   4698     = aprh->program->program_name;
   4699   apr->details.failure.ec
   4700     = TALER_EC_EXCHANGE_KYC_GENERIC_AML_PROGRAM_TIMEOUT;
   4701   async_return_task (aprh);
   4702 }
   4703 
   4704 
   4705 /**
   4706  * Helper function called on timeout of an AML program.
   4707  * Runs the fallback measure.
   4708  *
   4709  * @param[in] cls a `struct TALER_KYCLOGIC_AmlProgramRunnerHandle` to return results for
   4710  */
   4711 static void
   4712 handle_aml_timeout (void *cls)
   4713 {
   4714   struct TALER_KYCLOGIC_AmlProgramRunnerHandle *aprh = cls;
   4715   struct TALER_KYCLOGIC_AmlProgramResult *apr = &aprh->apr;
   4716   const char *fallback_measure = aprh->program->fallback;
   4717   const struct TALER_KYCLOGIC_Measure *m;
   4718   const struct TALER_KYCLOGIC_AmlProgram *fprogram;
   4719 
   4720   aprh->async_cb = NULL;
   4721   GNUNET_assert (NULL != fallback_measure);
   4722   GNUNET_log (GNUNET_ERROR_TYPE_WARNING,
   4723               "AML program %s ran into timeout\n",
   4724               aprh->program->program_name);
   4725   if (NULL != aprh->proc)
   4726   {
   4727     TALER_JSON_external_conversion_stop (aprh->proc);
   4728     aprh->proc = NULL;
   4729   }
   4730 
   4731   m = TALER_KYCLOGIC_get_measure (&default_rules,
   4732                                   fallback_measure);
   4733   /* Fallback program could have "disappeared" due to configuration change,
   4734      as we do not check all rule sets in the database when our configuration
   4735      is updated... */
   4736   if (NULL == m)
   4737   {
   4738     GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
   4739                 "Fallback measure `%s' does not exist (anymore?).\n",
   4740                 fallback_measure);
   4741     apr->status = TALER_KYCLOGIC_AMLR_FAILURE;
   4742     apr->details.failure.fallback_measure
   4743       = fallback_measure;
   4744     apr->details.failure.error_message
   4745       = aprh->program->program_name;
   4746     apr->details.failure.ec
   4747       = TALER_EC_EXCHANGE_KYC_GENERIC_AML_PROGRAM_TIMEOUT;
   4748     async_return_task (aprh);
   4749     return;
   4750   }
   4751   /* We require fallback measures to have a 'skip' check */
   4752   GNUNET_break (0 ==
   4753                 strcasecmp (m->check_name,
   4754                             "skip"));
   4755   fprogram = find_program (m->prog_name);
   4756   /* Program associated with an original measure must exist */
   4757   GNUNET_assert (NULL != fprogram);
   4758   if (API_NONE != (fprogram->input_mask & (API_CONTEXT | API_ATTRIBUTES)))
   4759   {
   4760     /* We might not have recognized the fallback measure as such
   4761        because it was not used as such in the plain configuration,
   4762        and legitimization rule sets might have referred to an older
   4763        configuration. So this should be super-rare but possible. */
   4764     GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
   4765                 "Program `%s' used in fallback measure `%s' requires inputs and is thus unsuitable as a fallback measure!\n",
   4766                 m->prog_name,
   4767                 fallback_measure);
   4768     apr->status = TALER_KYCLOGIC_AMLR_FAILURE;
   4769     apr->details.failure.fallback_measure
   4770       = fallback_measure;
   4771     apr->details.failure.error_message
   4772       = aprh->program->program_name;
   4773     apr->details.failure.ec
   4774       = TALER_EC_EXCHANGE_KYC_GENERIC_AML_PROGRAM_TIMEOUT;
   4775     async_return_task (aprh);
   4776     return;
   4777   }
   4778   {
   4779     /* Run fallback AML program */
   4780     json_t *input = json_object ();
   4781     const char *extra_args[] = {
   4782       "-c",
   4783       cfg_filename,
   4784       NULL,
   4785     };
   4786     char **args;
   4787 
   4788     args = TALER_words_split (fprogram->command,
   4789                               extra_args);
   4790     GNUNET_log (GNUNET_ERROR_TYPE_INFO,
   4791                 "Running fallback measure `%s' (%s)\n",
   4792                 fallback_measure,
   4793                 fprogram->command);
   4794     aprh->proc = TALER_JSON_external_conversion_start (
   4795       input,
   4796       &handle_aml_output,
   4797       aprh,
   4798       args[0],
   4799       (const char **) args);
   4800     TALER_words_destroy (args);
   4801     json_decref (input);
   4802   }
   4803   aprh->async_cb = GNUNET_SCHEDULER_add_delayed (aprh->timeout,
   4804                                                  &handle_aml_timeout2,
   4805                                                  aprh);
   4806 }
   4807 
   4808 
   4809 struct TALER_KYCLOGIC_AmlProgramRunnerHandle *
   4810 TALER_KYCLOGIC_run_aml_program (
   4811   const json_t *jmeasures,
   4812   bool is_wallet,
   4813   unsigned int measure_index,
   4814   TALER_KYCLOGIC_HistoryBuilderCallback current_attributes_cb,
   4815   void *current_attributes_cb_cls,
   4816   TALER_KYCLOGIC_HistoryBuilderCallback current_rules_cb,
   4817   void *current_rules_cb_cls,
   4818   TALER_KYCLOGIC_HistoryBuilderCallback aml_history_cb,
   4819   void *aml_history_cb_cls,
   4820   TALER_KYCLOGIC_HistoryBuilderCallback kyc_history_cb,
   4821   void *kyc_history_cb_cls,
   4822   struct GNUNET_TIME_Relative timeout,
   4823   TALER_KYCLOGIC_AmlProgramResultCallback aprc,
   4824   void *aprc_cls)
   4825 {
   4826   const json_t *context;
   4827   const char *check_name;
   4828   const char *prog_name;
   4829 
   4830   {
   4831     enum TALER_ErrorCode ec;
   4832 
   4833     ec = TALER_KYCLOGIC_select_measure (jmeasures,
   4834                                         measure_index,
   4835                                         &check_name,
   4836                                         &prog_name,
   4837                                         &context);
   4838     if (TALER_EC_NONE != ec)
   4839     {
   4840       GNUNET_break (0);
   4841       return NULL;
   4842     }
   4843   }
   4844   if (NULL == prog_name)
   4845   {
   4846     /* Trying to run AML program on a measure that does not
   4847        have one, and that should thus be an INFO check which
   4848        should never lead here. Very strange. */
   4849     GNUNET_break (0);
   4850     GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
   4851                 "Measure %u with check `%s' does not have an AML program!\n",
   4852                 measure_index,
   4853                 check_name);
   4854     json_dumpf (jmeasures,
   4855                 stderr,
   4856                 JSON_INDENT (2));
   4857     return NULL;
   4858   }
   4859   return TALER_KYCLOGIC_run_aml_program2 (prog_name,
   4860                                           context,
   4861                                           is_wallet,
   4862                                           current_attributes_cb,
   4863                                           current_attributes_cb_cls,
   4864                                           current_rules_cb,
   4865                                           current_rules_cb_cls,
   4866                                           aml_history_cb,
   4867                                           aml_history_cb_cls,
   4868                                           kyc_history_cb,
   4869                                           kyc_history_cb_cls,
   4870                                           timeout,
   4871                                           aprc,
   4872                                           aprc_cls);
   4873 }
   4874 
   4875 
   4876 struct TALER_KYCLOGIC_AmlProgramRunnerHandle *
   4877 TALER_KYCLOGIC_run_aml_program2 (
   4878   const char *prog_name,
   4879   const json_t *context,
   4880   bool is_wallet,
   4881   TALER_KYCLOGIC_HistoryBuilderCallback current_attributes_cb,
   4882   void *current_attributes_cb_cls,
   4883   TALER_KYCLOGIC_HistoryBuilderCallback current_rules_cb,
   4884   void *current_rules_cb_cls,
   4885   TALER_KYCLOGIC_HistoryBuilderCallback aml_history_cb,
   4886   void *aml_history_cb_cls,
   4887   TALER_KYCLOGIC_HistoryBuilderCallback kyc_history_cb,
   4888   void *kyc_history_cb_cls,
   4889   struct GNUNET_TIME_Relative timeout,
   4890   TALER_KYCLOGIC_AmlProgramResultCallback aprc,
   4891   void *aprc_cls)
   4892 {
   4893   struct TALER_KYCLOGIC_AmlProgramRunnerHandle *aprh;
   4894   struct TALER_KYCLOGIC_AmlProgram *prog;
   4895   const json_t *jdefault_rules;
   4896   json_t *current_rules;
   4897   json_t *aml_history;
   4898   json_t *kyc_history;
   4899   json_t *attributes;
   4900 
   4901   prog = find_program (prog_name);
   4902   if (NULL == prog)
   4903   {
   4904     GNUNET_break (0);
   4905     return NULL;
   4906   }
   4907   aprh = GNUNET_new (struct TALER_KYCLOGIC_AmlProgramRunnerHandle);
   4908   aprh->aprc = aprc;
   4909   aprh->aprc_cls = aprc_cls;
   4910   aprh->program = prog;
   4911   if (0 != (API_ATTRIBUTES & prog->input_mask))
   4912   {
   4913     attributes = current_attributes_cb (current_attributes_cb_cls);
   4914 #if DEBUG
   4915     GNUNET_log (GNUNET_ERROR_TYPE_INFO,
   4916                 "KYC attributes for AML program %s are:\n",
   4917                 prog_name);
   4918     json_dumpf (attributes,
   4919                 stderr,
   4920                 JSON_INDENT (2));
   4921     fprintf (stderr,
   4922              "\n");
   4923 #endif
   4924     for (unsigned int i = 0; i<prog->num_required_attributes; i++)
   4925     {
   4926       const char *rattr = prog->required_attributes[i];
   4927 
   4928       if (NULL == json_object_get (attributes,
   4929                                    rattr))
   4930       {
   4931         GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
   4932                     "KYC attributes lack required attribute `%s' for AML program %s\n",
   4933                     rattr,
   4934                     prog->program_name);
   4935 #if DEBUG
   4936         json_dumpf (attributes,
   4937                     stderr,
   4938                     JSON_INDENT (2));
   4939 #endif
   4940         aprh->apr.status = TALER_KYCLOGIC_AMLR_FAILURE;
   4941         aprh->apr.details.failure.fallback_measure
   4942           = prog->fallback;
   4943         aprh->apr.details.failure.error_message
   4944           = rattr;
   4945         aprh->apr.details.failure.ec
   4946           = TALER_EC_EXCHANGE_KYC_GENERIC_PROVIDER_INCOMPLETE_REPLY;
   4947         aprh->async_cb
   4948           = GNUNET_SCHEDULER_add_now (&async_return_task,
   4949                                       aprh);
   4950         json_decref (attributes);
   4951         return aprh;
   4952       }
   4953     }
   4954   }
   4955   else
   4956   {
   4957     attributes = NULL;
   4958   }
   4959   if (0 != (API_CONTEXT & prog->input_mask))
   4960   {
   4961     for (unsigned int i = 0; i<prog->num_required_contexts; i++)
   4962     {
   4963       const char *rctx = prog->required_contexts[i];
   4964 
   4965       if (NULL == json_object_get (context,
   4966                                    rctx))
   4967       {
   4968         GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
   4969                     "Context lacks required field `%s' for AML program %s\n",
   4970                     rctx,
   4971                     prog->program_name);
   4972 #if DEBUG
   4973         json_dumpf (context,
   4974                     stderr,
   4975                     JSON_INDENT (2));
   4976 #endif
   4977         aprh->apr.status = TALER_KYCLOGIC_AMLR_FAILURE;
   4978         aprh->apr.details.failure.fallback_measure
   4979           = prog->fallback;
   4980         aprh->apr.details.failure.error_message
   4981           = rctx;
   4982         aprh->apr.details.failure.ec
   4983           = TALER_EC_EXCHANGE_KYC_GENERIC_PROVIDER_INCOMPLETE_CONTEXT;
   4984         aprh->async_cb
   4985           = GNUNET_SCHEDULER_add_now (&async_return_task,
   4986                                       aprh);
   4987         json_decref (attributes);
   4988         return aprh;
   4989       }
   4990     }
   4991   }
   4992   else
   4993   {
   4994     context = NULL;
   4995   }
   4996   if (0 == (API_AML_HISTORY & prog->input_mask))
   4997     aml_history = NULL;
   4998   else
   4999     aml_history = aml_history_cb (aml_history_cb_cls);
   5000   if (0 == (API_KYC_HISTORY & prog->input_mask))
   5001     kyc_history = NULL;
   5002   else
   5003     kyc_history = kyc_history_cb (kyc_history_cb_cls);
   5004   if (0 == (API_CURRENT_RULES & prog->input_mask))
   5005     current_rules = NULL;
   5006   else
   5007     current_rules = current_rules_cb (current_rules_cb_cls);
   5008   if (0 != (API_DEFAULT_RULES & prog->input_mask))
   5009     jdefault_rules =
   5010       (is_wallet
   5011        ? wallet_default_lrs
   5012        : bankaccount_default_lrs);
   5013   else
   5014     jdefault_rules = NULL;
   5015   {
   5016     json_t *input;
   5017     const char *extra_args[] = {
   5018       "-c",
   5019       cfg_filename,
   5020       NULL,
   5021     };
   5022     char **args;
   5023 
   5024     input = GNUNET_JSON_PACK (
   5025       GNUNET_JSON_pack_allow_null (
   5026         GNUNET_JSON_pack_object_steal ("current_rules",
   5027                                        current_rules)),
   5028       GNUNET_JSON_pack_allow_null (
   5029         GNUNET_JSON_pack_object_incref ("default_rules",
   5030                                         (json_t *) jdefault_rules)),
   5031       GNUNET_JSON_pack_allow_null (
   5032         GNUNET_JSON_pack_object_incref ("context",
   5033                                         (json_t *) context)),
   5034       GNUNET_JSON_pack_allow_null (
   5035         GNUNET_JSON_pack_object_steal ("attributes",
   5036                                        attributes)),
   5037       GNUNET_JSON_pack_allow_null (
   5038         GNUNET_JSON_pack_array_steal ("aml_history",
   5039                                       aml_history)),
   5040       GNUNET_JSON_pack_allow_null (
   5041         GNUNET_JSON_pack_array_steal ("kyc_history",
   5042                                       kyc_history))
   5043       );
   5044     GNUNET_log (GNUNET_ERROR_TYPE_INFO,
   5045                 "Running AML program %s\n",
   5046                 prog->command);
   5047     args = TALER_words_split (prog->command,
   5048                               extra_args);
   5049     GNUNET_assert (NULL != args);
   5050     GNUNET_assert (NULL != args[0]);
   5051 #if DEBUG
   5052     json_dumpf (input,
   5053                 stderr,
   5054                 JSON_INDENT (2));
   5055 #endif
   5056     aprh->proc = TALER_JSON_external_conversion_start (
   5057       input,
   5058       &handle_aml_output,
   5059       aprh,
   5060       args[0],
   5061       (const char **) args);
   5062     TALER_words_destroy (args);
   5063     json_decref (input);
   5064   }
   5065   aprh->timeout = timeout;
   5066   aprh->async_cb = GNUNET_SCHEDULER_add_delayed (timeout,
   5067                                                  &handle_aml_timeout,
   5068                                                  aprh);
   5069   return aprh;
   5070 }
   5071 
   5072 
   5073 struct TALER_KYCLOGIC_AmlProgramRunnerHandle *
   5074 TALER_KYCLOGIC_run_aml_program3 (
   5075   bool is_wallet,
   5076   const struct TALER_KYCLOGIC_Measure *measure,
   5077   TALER_KYCLOGIC_HistoryBuilderCallback current_attributes_cb,
   5078   void *current_attributes_cb_cls,
   5079   TALER_KYCLOGIC_HistoryBuilderCallback current_rules_cb,
   5080   void *current_rules_cb_cls,
   5081   TALER_KYCLOGIC_HistoryBuilderCallback aml_history_cb,
   5082   void *aml_history_cb_cls,
   5083   TALER_KYCLOGIC_HistoryBuilderCallback kyc_history_cb,
   5084   void *kyc_history_cb_cls,
   5085   struct GNUNET_TIME_Relative timeout,
   5086   TALER_KYCLOGIC_AmlProgramResultCallback aprc,
   5087   void *aprc_cls)
   5088 {
   5089   return TALER_KYCLOGIC_run_aml_program2 (
   5090     measure->prog_name,
   5091     measure->context,
   5092     is_wallet,
   5093     current_attributes_cb,
   5094     current_attributes_cb_cls,
   5095     current_rules_cb,
   5096     current_rules_cb_cls,
   5097     aml_history_cb,
   5098     aml_history_cb_cls,
   5099     kyc_history_cb,
   5100     kyc_history_cb_cls,
   5101     timeout,
   5102     aprc,
   5103     aprc_cls);
   5104 }
   5105 
   5106 
   5107 const char *
   5108 TALER_KYCLOGIC_run_aml_program_get_name (
   5109   const struct TALER_KYCLOGIC_AmlProgramRunnerHandle *aprh)
   5110 {
   5111   return aprh->program->program_name;
   5112 }
   5113 
   5114 
   5115 void
   5116 TALER_KYCLOGIC_run_aml_program_cancel (
   5117   struct TALER_KYCLOGIC_AmlProgramRunnerHandle *aprh)
   5118 {
   5119   if (NULL != aprh->proc)
   5120   {
   5121     GNUNET_log (GNUNET_ERROR_TYPE_WARNING,
   5122                 "Killing AML program\n");
   5123     TALER_JSON_external_conversion_stop (aprh->proc);
   5124     aprh->proc = NULL;
   5125   }
   5126   if (NULL != aprh->async_cb)
   5127   {
   5128     GNUNET_SCHEDULER_cancel (aprh->async_cb);
   5129     aprh->async_cb = NULL;
   5130   }
   5131   GNUNET_free (aprh);
   5132 }
   5133 
   5134 
   5135 json_t *
   5136 TALER_KYCLOGIC_get_hard_limits ()
   5137 {
   5138   const struct TALER_KYCLOGIC_KycRule *rules
   5139     = default_rules.kyc_rules;
   5140   unsigned int num_rules
   5141     = default_rules.num_kyc_rules;
   5142   json_t *hard_limits;
   5143 
   5144   hard_limits = json_array ();
   5145   GNUNET_assert (NULL != hard_limits);
   5146   for (unsigned int i = 0; i<num_rules; i++)
   5147   {
   5148     const struct TALER_KYCLOGIC_KycRule *rule = &rules[i];
   5149     json_t *hard_limit;
   5150 
   5151     if (! rule->verboten)
   5152       continue;
   5153     if (! rule->exposed)
   5154       continue;
   5155     hard_limit = GNUNET_JSON_PACK (
   5156       GNUNET_JSON_pack_allow_null (
   5157         GNUNET_JSON_pack_string ("rule_name",
   5158                                  rule->rule_name)),
   5159       TALER_JSON_pack_kycte ("operation_type",
   5160                              rule->trigger),
   5161       GNUNET_JSON_pack_time_rel ("timeframe",
   5162                                  rule->timeframe),
   5163       TALER_JSON_pack_amount ("threshold",
   5164                               &rule->threshold)
   5165       );
   5166     GNUNET_assert (0 ==
   5167                    json_array_append_new (hard_limits,
   5168                                           hard_limit));
   5169   }
   5170   return hard_limits;
   5171 }
   5172 
   5173 
   5174 json_t *
   5175 TALER_KYCLOGIC_get_zero_limits ()
   5176 {
   5177   const struct TALER_KYCLOGIC_KycRule *rules
   5178     = default_rules.kyc_rules;
   5179   unsigned int num_rules
   5180     = default_rules.num_kyc_rules;
   5181   json_t *zero_limits;
   5182 
   5183   zero_limits = json_array ();
   5184   GNUNET_assert (NULL != zero_limits);
   5185   for (unsigned int i = 0; i<num_rules; i++)
   5186   {
   5187     const struct TALER_KYCLOGIC_KycRule *rule = &rules[i];
   5188     json_t *zero_limit;
   5189 
   5190     if (! rule->exposed)
   5191       continue;
   5192     if (rule->verboten)
   5193       continue; /* see: hard_limits */
   5194     if (! TALER_amount_is_zero (&rule->threshold))
   5195       continue;
   5196     zero_limit = GNUNET_JSON_PACK (
   5197       GNUNET_JSON_pack_allow_null (
   5198         GNUNET_JSON_pack_string ("rule_name",
   5199                                  rule->rule_name)),
   5200       TALER_JSON_pack_kycte ("operation_type",
   5201                              rule->trigger));
   5202     GNUNET_assert (0 ==
   5203                    json_array_append_new (zero_limits,
   5204                                           zero_limit));
   5205   }
   5206   return zero_limits;
   5207 }
   5208 
   5209 
   5210 json_t *
   5211 TALER_KYCLOGIC_get_default_legi_rules (bool for_wallet)
   5212 {
   5213   const json_t *r;
   5214 
   5215   r = (for_wallet
   5216        ? wallet_default_lrs
   5217        : bankaccount_default_lrs);
   5218   return json_incref ((json_t *) r);
   5219 }
   5220 
   5221 
   5222 /* end of kyclogic_api.c */