diff options
Diffstat (limited to 'src/kyclogic')
| -rw-r--r-- | src/kyclogic/kyclogic_api.c | 206 | ||||
| -rw-r--r-- | src/kyclogic/plugin_kyclogic_kycaid.c | 43 | ||||
| -rw-r--r-- | src/kyclogic/plugin_kyclogic_oauth2.c | 7 | ||||
| -rw-r--r-- | src/kyclogic/plugin_kyclogic_persona.c | 27 | ||||
| -rw-r--r-- | src/kyclogic/plugin_kyclogic_template.c | 4 | ||||
| -rw-r--r-- | src/kyclogic/taler-exchange-kyc-tester.c | 98 | 
6 files changed, 289 insertions, 96 deletions
diff --git a/src/kyclogic/kyclogic_api.c b/src/kyclogic/kyclogic_api.c index 22d2129c..5081e09d 100644 --- a/src/kyclogic/kyclogic_api.c +++ b/src/kyclogic/kyclogic_api.c @@ -992,10 +992,8 @@ TALER_KYCLOGIC_kyc_test_required (enum TALER_KYCLOGIC_KycTriggerEvent event,  {    struct TALER_KYCLOGIC_KycCheck *needed[num_kyc_checks];    unsigned int needed_cnt = 0; +  char *ret;    struct GNUNET_TIME_Relative timeframe; -  unsigned long long min_cost = ULONG_LONG_MAX; -  unsigned int max_checks = 0; -  const struct TALER_KYCLOGIC_KycProvider *kp_best = NULL;    timeframe = GNUNET_TIME_UNIT_ZERO;    for (unsigned int i = 0; i<num_kyc_triggers; i++) @@ -1024,6 +1022,50 @@ TALER_KYCLOGIC_kyc_test_required (enum TALER_KYCLOGIC_KycTriggerEvent event,    }    if (0 == needed_cnt)      return NULL; +  timeframe = GNUNET_TIME_UNIT_ZERO; +  for (unsigned int i = 0; i<num_kyc_triggers; i++) +  { +    const struct TALER_KYCLOGIC_KycTrigger *kt = kyc_triggers[i]; + +    if (event != kt->trigger) +      continue; +    timeframe = GNUNET_TIME_relative_max (timeframe, +                                          kt->timeframe); +  } +  { +    struct GNUNET_TIME_Absolute now; +    struct ThresholdTestContext ttc = { +      .event = event, +      .needed = needed, +      .needed_cnt = &needed_cnt +    }; + +    now = GNUNET_TIME_absolute_get (); +    ai (ai_cls, +        GNUNET_TIME_absolute_subtract (now, +                                       timeframe), +        &eval_trigger, +        &ttc); +  } +  if (0 == needed_cnt) +    return NULL; +  { +    struct RemoveContext rc = { +      .needed = needed, +      .needed_cnt = &needed_cnt +    }; +    enum GNUNET_DB_QueryStatus qs; + +    /* Check what provider checks are already satisfied for h_payto (with +       database), remove those from the 'needed' array. */ +    qs = ki (ki_cls, +             h_payto, +             &remove_satisfied, +             &rc); +    GNUNET_break (qs >= 0);  // FIXME: handle DB failure more nicely? +  } +  if (0 == needed_cnt) +    return NULL;    {      struct RemoveContext rc = {        .needed = needed, @@ -1041,6 +1083,117 @@ TALER_KYCLOGIC_kyc_test_required (enum TALER_KYCLOGIC_KycTriggerEvent event,    }    if (0 == needed_cnt)      return NULL; +  ret = NULL; +  for (unsigned int k = 0; k<needed_cnt; k++) +  { +    const struct TALER_KYCLOGIC_KycCheck *kc = needed[k]; + +    if (NULL == ret) +    { +      ret = GNUNET_strdup (kc->name); +    } +    else /* append */ +    { +      char *tmp = ret; + +      GNUNET_asprintf (&ret, +                       "%s %s", +                       tmp, +                       kc->name); +      GNUNET_free (tmp); +    } +  } +  return ret; +} + + +void +TALER_KYCLOGIC_kyc_get_details ( +  const char *logic_name, +  TALER_KYCLOGIC_DetailsCallback cb, +  void *cb_cls) +{ +  for (unsigned int i = 0; i<num_kyc_providers; i++) +  { +    struct TALER_KYCLOGIC_KycProvider *kp = kyc_providers[i]; + +    if (0 != +        strcmp (kp->logic->name, +                logic_name)) +      continue; +    if (GNUNET_OK != +        cb (cb_cls, +            kp->pd, +            kp->logic->cls)) +      return; +  } +} + + +bool +TALER_KYCLOGIC_check_satisfied (const char *requirements, +                                const struct TALER_PaytoHashP *h_payto, +                                TALER_KYCLOGIC_KycSatisfiedIterator ki, +                                void *ki_cls) +{ +  struct TALER_KYCLOGIC_KycCheck *needed[num_kyc_checks]; +  unsigned int needed_cnt = 0; + +  if (NULL == requirements) +    return true; +  { +    char *req = GNUNET_strdup (requirements); + +    for (const char *tok = strtok (req, " "); +         NULL != tok; +         tok = strtok (NULL, " ")) +      needed[needed_cnt++] = add_check (tok); +    GNUNET_free (req); +  } + +  { +    struct RemoveContext rc = { +      .needed = needed, +      .needed_cnt = &needed_cnt +    }; +    enum GNUNET_DB_QueryStatus qs; + +    /* Check what provider checks are already satisfied for h_payto (with +       database), remove those from the 'needed' array. */ +    qs = ki (ki_cls, +             h_payto, +             &remove_satisfied, +             &rc); +    GNUNET_break (qs >= 0);  // FIXME: handle DB failure more nicely? +  } +  return (0 == needed_cnt); +} + + +enum GNUNET_GenericReturnValue +TALER_KYCLOGIC_requirements_to_logic (const char *requirements, +                                      enum TALER_KYCLOGIC_KycUserType ut, +                                      struct TALER_KYCLOGIC_Plugin **plugin, +                                      struct TALER_KYCLOGIC_ProviderDetails **pd, +                                      const char **configuration_section) +{ +  struct TALER_KYCLOGIC_KycCheck *needed[num_kyc_checks]; +  unsigned int needed_cnt = 0; +  unsigned long long min_cost = ULONG_LONG_MAX; +  unsigned int max_checks = 0; +  const struct TALER_KYCLOGIC_KycProvider *kp_best = NULL; + +  if (NULL == requirements) +    return GNUNET_NO; +  { +    char *req = GNUNET_strdup (requirements); + +    for (const char *tok = strtok (req, " "); +         NULL != tok; +         tok = strtok (NULL, " ")) +      needed[needed_cnt++] = add_check (tok); +    GNUNET_free (req); +  }    /* Count maximum number of remaining checks covered by any       provider */ @@ -1063,6 +1216,8 @@ TALER_KYCLOGIC_kyc_test_required (enum TALER_KYCLOGIC_KycTriggerEvent event,      max_checks = GNUNET_MAX (max_checks,                               matched);    } +  if (0 == max_checks) +    return GNUNET_SYSERR;    /* Find min-cost provider covering max_checks. */    for (unsigned int i = 0; i<num_kyc_providers; i++) @@ -1088,50 +1243,30 @@ TALER_KYCLOGIC_kyc_test_required (enum TALER_KYCLOGIC_KycTriggerEvent event,        kp_best = kp;      }    } - -  GNUNET_assert (NULL != kp_best); -  return kp_best->provider_section_name; -} - - -void -TALER_KYCLOGIC_kyc_get_details ( -  const char *logic_name, -  TALER_KYCLOGIC_DetailsCallback cb, -  void *cb_cls) -{ -  for (unsigned int i = 0; i<num_kyc_providers; i++) -  { -    struct TALER_KYCLOGIC_KycProvider *kp = kyc_providers[i]; - -    if (0 != -        strcmp (kp->logic->name, -                logic_name)) -      continue; -    if (GNUNET_OK != -        cb (cb_cls, -            kp->pd, -            kp->logic->cls)) -      return; -  } +  *plugin = kp_best->logic; +  *pd = kp_best->pd; +  *configuration_section = kp_best->provider_section_name; +  return GNUNET_OK;  }  enum GNUNET_GenericReturnValue -TALER_KYCLOGIC_kyc_get_logic (const char *provider_section_name, -                              struct TALER_KYCLOGIC_Plugin **plugin, -                              struct TALER_KYCLOGIC_ProviderDetails **pd) +TALER_KYCLOGIC_lookup_logic (const char *name, +                             struct TALER_KYCLOGIC_Plugin **plugin, +                             struct TALER_KYCLOGIC_ProviderDetails **pd, +                             const char **provider_section)  {    for (unsigned int i = 0; i<num_kyc_providers; i++)    {      struct TALER_KYCLOGIC_KycProvider *kp = kyc_providers[i];      if (0 != -        strcasecmp (provider_section_name, +        strcasecmp (name,                      kp->provider_section_name))        continue;      *plugin = kp->logic;      *pd = kp->pd; +    *provider_section = kp->provider_section_name;      return GNUNET_OK;    }    for (unsigned int i = 0; i<num_kyc_logics; i++) @@ -1140,15 +1275,16 @@ TALER_KYCLOGIC_kyc_get_logic (const char *provider_section_name,      if (0 !=          strcasecmp (logic->name, -                    provider_section_name)) +                    name))        continue;      *plugin = logic;      *pd = NULL; +    *provider_section = NULL;      return GNUNET_OK;    }    GNUNET_log (GNUNET_ERROR_TYPE_ERROR,                "Provider `%s' unknown\n", -              provider_section_name); +              name);    return GNUNET_SYSERR;  } diff --git a/src/kyclogic/plugin_kyclogic_kycaid.c b/src/kyclogic/plugin_kyclogic_kycaid.c index 05bcb4f6..c08948f7 100644 --- a/src/kyclogic/plugin_kyclogic_kycaid.c +++ b/src/kyclogic/plugin_kyclogic_kycaid.c @@ -257,7 +257,7 @@ struct TALER_KYCLOGIC_WebhookHandle     * Row in legitimizations for the given     * @e verification_id.     */ -  uint64_t legi_row; +  uint64_t process_row;    /**     * HTTP response code to return asynchronously. @@ -646,7 +646,7 @@ proof_reply (void *cls)   * @param url_path rest of the URL after `/kyc-webhook/`   * @param connection MHD connection object (for HTTP headers)   * @param account_id which account to trigger process for - * @param legi_row row in the table the legitimization is for + * @param process_row row in the legitimization processes table the legitimization is for   * @param provider_user_id user ID (or NULL) the proof is for   * @param provider_legitimization_id legitimization ID the proof is for   * @param cb function to call with the result @@ -659,7 +659,7 @@ kycaid_proof (void *cls,                const char *const url_path[],                struct MHD_Connection *connection,                const struct TALER_PaytoHashP *account_id, -              uint64_t legi_row, +              uint64_t process_row,                const char *provider_user_id,                const char *provider_legitimization_id,                TALER_KYCLOGIC_ProofCallback cb, @@ -805,8 +805,9 @@ handle_webhook_finished (void *cls,            GNUNET_JSON_pack_object_incref ("kycaid_body",                                            (json_t *) j));          wh->cb (wh->cb_cls, -                wh->legi_row, +                wh->process_row,                  &wh->h_payto, +                wh->pd->section,                  wh->applicant_id,                  wh->verification_id,                  TALER_KYCLOGIC_STATUS_PROVIDER_FAILED, @@ -826,8 +827,9 @@ handle_webhook_finished (void *cls,        {          expiration = GNUNET_TIME_relative_to_absolute (wh->pd->validity);          wh->cb (wh->cb_cls, -                wh->legi_row, +                wh->process_row,                  &wh->h_payto, +                wh->pd->section,                  wh->applicant_id,                  wh->verification_id,                  TALER_KYCLOGIC_STATUS_SUCCESS, @@ -838,8 +840,9 @@ handle_webhook_finished (void *cls,        else        {          wh->cb (wh->cb_cls, -                wh->legi_row, +                wh->process_row,                  &wh->h_payto, +                wh->pd->section,                  wh->applicant_id,                  wh->verification_id,                  TALER_KYCLOGIC_STATUS_USER_ABORTED, @@ -863,8 +866,9 @@ handle_webhook_finished (void *cls,        GNUNET_JSON_pack_uint64 ("kycaid_http_status",                                 response_code));      wh->cb (wh->cb_cls, -            wh->legi_row, +            wh->process_row,              &wh->h_payto, +            wh->pd->section,              wh->applicant_id,              wh->verification_id,              TALER_KYCLOGIC_STATUS_PROVIDER_FAILED, @@ -883,8 +887,9 @@ handle_webhook_finished (void *cls,        GNUNET_JSON_pack_object_incref ("kycaid_body",                                        (json_t *) j));      wh->cb (wh->cb_cls, -            wh->legi_row, +            wh->process_row,              &wh->h_payto, +            wh->pd->section,              wh->applicant_id,              wh->verification_id,              TALER_KYCLOGIC_STATUS_PROVIDER_FAILED, @@ -899,8 +904,9 @@ handle_webhook_finished (void *cls,        GNUNET_JSON_pack_object_incref ("kycaid_body",                                        (json_t *) j));      wh->cb (wh->cb_cls, -            wh->legi_row, +            wh->process_row,              &wh->h_payto, +            wh->pd->section,              wh->applicant_id,              wh->verification_id,              TALER_KYCLOGIC_STATUS_PROVIDER_FAILED, @@ -921,8 +927,9 @@ handle_webhook_finished (void *cls,        GNUNET_JSON_pack_object_incref ("kycaid_body",                                        (json_t *) j));      wh->cb (wh->cb_cls, -            wh->legi_row, +            wh->process_row,              &wh->h_payto, +            wh->pd->section,              wh->applicant_id,              wh->verification_id,              TALER_KYCLOGIC_STATUS_PROVIDER_FAILED, @@ -937,8 +944,9 @@ handle_webhook_finished (void *cls,        GNUNET_JSON_pack_object_incref ("kycaid_body",                                        (json_t *) j));      wh->cb (wh->cb_cls, -            wh->legi_row, +            wh->process_row,              &wh->h_payto, +            wh->pd->section,              wh->applicant_id,              wh->verification_id,              TALER_KYCLOGIC_STATUS_PROVIDER_FAILED, @@ -953,8 +961,9 @@ handle_webhook_finished (void *cls,        GNUNET_JSON_pack_object_incref ("kycaid_body",                                        (json_t *) j));      wh->cb (wh->cb_cls, -            wh->legi_row, +            wh->process_row,              &wh->h_payto, +            wh->pd->section,              wh->applicant_id,              wh->verification_id,              TALER_KYCLOGIC_STATUS_PROVIDER_FAILED, @@ -975,8 +984,9 @@ handle_webhook_finished (void *cls,                  stderr,                  JSON_INDENT (2));      wh->cb (wh->cb_cls, -            wh->legi_row, +            wh->process_row,              &wh->h_payto, +            wh->pd->section,              wh->applicant_id,              wh->verification_id,              TALER_KYCLOGIC_STATUS_PROVIDER_FAILED, @@ -1000,10 +1010,11 @@ async_webhook_reply (void *cls)    struct TALER_KYCLOGIC_WebhookHandle *wh = cls;    wh->cb (wh->cb_cls, -          wh->legi_row, -          (0 == wh->legi_row) +          wh->process_row, +          (0 == wh->process_row)            ? NULL            : &wh->h_payto, +          wh->pd->section,            wh->applicant_id, /* provider user ID */            wh->verification_id, /* provider legi ID */            TALER_KYCLOGIC_STATUS_PROVIDER_FAILED, @@ -1117,7 +1128,7 @@ kycaid_webhook (void *cls,              pd->section,              verification_id,              &wh->h_payto, -            &wh->legi_row); +            &wh->process_row);    if (qs < 0)    {      wh->resp = TALER_MHD_make_error (TALER_EC_GENERIC_DB_FETCH_FAILED, diff --git a/src/kyclogic/plugin_kyclogic_oauth2.c b/src/kyclogic/plugin_kyclogic_oauth2.c index da7ddfc3..b8f2d70f 100644 --- a/src/kyclogic/plugin_kyclogic_oauth2.c +++ b/src/kyclogic/plugin_kyclogic_oauth2.c @@ -920,7 +920,7 @@ handle_curl_login_finished (void *cls,   * @param url_path rest of the URL after `/kyc-webhook/`   * @param connection MHD connection object (for HTTP headers)   * @param account_id which account to trigger process for - * @param legi_row row in the table the legitimization is for + * @param process_row row in the legitimization processes table the legitimization is for   * @param provider_user_id user ID (or NULL) the proof is for   * @param provider_legitimization_id legitimization ID the proof is for   * @param cb function to call with the result @@ -933,7 +933,7 @@ oauth2_proof (void *cls,                const char *const url_path[],                struct MHD_Connection *connection,                const struct TALER_PaytoHashP *account_id, -              uint64_t legi_row, +              uint64_t process_row,                const char *provider_user_id,                const char *provider_legitimization_id,                TALER_KYCLOGIC_ProofCallback cb, @@ -948,7 +948,7 @@ oauth2_proof (void *cls,    GNUNET_snprintf (ph->provider_legitimization_id,                     sizeof (ph->provider_legitimization_id),                     "%llu", -                   (unsigned long long) legi_row); +                   (unsigned long long) process_row);    if ( (NULL != provider_legitimization_id) &&         (0 != strcmp (provider_legitimization_id,                       ph->provider_legitimization_id))) @@ -1114,6 +1114,7 @@ wh_return_not_found (void *cls)            NULL,            NULL,            NULL, +          NULL,            TALER_KYCLOGIC_STATUS_KEEP,            GNUNET_TIME_UNIT_ZERO_ABS,            MHD_HTTP_NOT_FOUND, diff --git a/src/kyclogic/plugin_kyclogic_persona.c b/src/kyclogic/plugin_kyclogic_persona.c index 960b9f0e..fba3a263 100644 --- a/src/kyclogic/plugin_kyclogic_persona.c +++ b/src/kyclogic/plugin_kyclogic_persona.c @@ -234,9 +234,10 @@ struct TALER_KYCLOGIC_ProofHandle    struct TALER_PaytoHashP h_payto;    /** -   * UUID being checked. +   * Row in the legitimization processes of the +   * legitimization proof that is being checked.     */ -  uint64_t legitimization_uuid; +  uint64_t process_row;    /**     * Account ID at the provider. @@ -320,7 +321,7 @@ struct TALER_KYCLOGIC_WebhookHandle    /**     * UUID being checked.     */ -  uint64_t legitimization_uuid; +  uint64_t process_row;    /**     * HTTP response code to return asynchronously. @@ -1041,7 +1042,7 @@ handle_proof_finished (void *cls,                               "%llu%c",                               &idr,                               &dummy)) || -               (idr != ph->legitimization_uuid) ) +               (idr != ph->process_row) )            {              GNUNET_break_op (0);              proof_reply_error (ph, @@ -1347,7 +1348,7 @@ handle_proof_finished (void *cls,   * @param url_path rest of the URL after `/kyc-webhook/`   * @param connection MHD connection object (for HTTP headers)   * @param account_id which account to trigger process for - * @param legi_row row in the table the legitimization is for + * @param process_row row in the legitimization processes table the legitimization is for   * @param provider_user_id user ID (or NULL) the proof is for   * @param inquiry_id legitimization ID the proof is for   * @param cb function to call with the result @@ -1360,7 +1361,7 @@ persona_proof (void *cls,                 const char *const url_path[],                 struct MHD_Connection *connection,                 const struct TALER_PaytoHashP *account_id, -               uint64_t legi_row, +               uint64_t process_row,                 const char *provider_user_id,                 const char *inquiry_id,                 TALER_KYCLOGIC_ProofCallback cb, @@ -1382,7 +1383,7 @@ persona_proof (void *cls,    ph->cb = cb;    ph->cb_cls = cb_cls;    ph->connection = connection; -  ph->legitimization_uuid = legi_row; +  ph->process_row = process_row;    ph->h_payto = *account_id;    /* Note: we do not expect this to be non-NULL */    if (NULL != provider_user_id) @@ -1465,9 +1466,10 @@ webhook_generic_reply (struct TALER_KYCLOGIC_WebhookHandle *wh,                                            MHD_RESPMEM_PERSISTENT);    TALER_MHD_add_global_headers (resp);    wh->cb (wh->cb_cls, -          wh->legitimization_uuid, +          wh->process_row,            &wh->h_payto,            account_id, +          wh->pd->section,            inquiry_id,            status,            expiration, @@ -1591,7 +1593,7 @@ handle_webhook_finished (void *cls,                               "%llu%c",                               &idr,                               &dummy)) || -               (idr != wh->legitimization_uuid) ) +               (idr != wh->process_row) )            {              GNUNET_break_op (0);              webhook_reply_error (wh, @@ -1761,10 +1763,11 @@ async_webhook_reply (void *cls)    wh->task = NULL;    wh->cb (wh->cb_cls, -          wh->legitimization_uuid, -          (0 == wh->legitimization_uuid) +          wh->process_row, +          (0 == wh->process_row)            ? NULL            : &wh->h_payto, +          wh->pd->section,            NULL,            wh->inquiry_id, /* provider legi ID */            TALER_KYCLOGIC_STATUS_PROVIDER_FAILED, @@ -1967,7 +1970,7 @@ persona_webhook (void *cls,              wh->pd->section,              persona_inquiry_id,              &wh->h_payto, -            &wh->legitimization_uuid); +            &wh->process_row);    if (qs < 0)    {      wh->resp = TALER_MHD_make_error (TALER_EC_GENERIC_DB_FETCH_FAILED, diff --git a/src/kyclogic/plugin_kyclogic_template.c b/src/kyclogic/plugin_kyclogic_template.c index 4a21882b..190c3321 100644 --- a/src/kyclogic/plugin_kyclogic_template.c +++ b/src/kyclogic/plugin_kyclogic_template.c @@ -281,7 +281,7 @@ template_proof_cancel (struct TALER_KYCLOGIC_ProofHandle *ph)   * @param url_path rest of the URL after `/kyc-webhook/`   * @param connection MHD connection object (for HTTP headers)   * @param account_id which account to trigger process for - * @param legi_row row in the table the legitimization is for + * @param process_row row in the legitimization processes table the legitimization is for   * @param provider_user_id user ID (or NULL) the proof is for   * @param provider_legitimization_id legitimization ID the proof is for   * @param cb function to call with the result @@ -294,7 +294,7 @@ template_proof (void *cls,                  const char *const url_path[],                  struct MHD_Connection *connection,                  const struct TALER_PaytoHashP *account_id, -                uint64_t legi_row, +                uint64_t process_row,                  const char *provider_user_id,                  const char *provider_legitimization_id,                  TALER_KYCLOGIC_ProofCallback cb, diff --git a/src/kyclogic/taler-exchange-kyc-tester.c b/src/kyclogic/taler-exchange-kyc-tester.c index bb2894b1..306493e2 100644 --- a/src/kyclogic/taler-exchange-kyc-tester.c +++ b/src/kyclogic/taler-exchange-kyc-tester.c @@ -252,6 +252,12 @@ static char *cmd_provider_user_id;  static char *cmd_provider_legitimization_id;  /** + * Name of the configuration section with the + * configuration data of the selected provider. + */ +static const char *provider_section_name; + +/**   * Row ID to use, override with '-r'   */  static unsigned int kyc_row_id = 42; @@ -272,9 +278,14 @@ static int run_webservice;  static int global_ret;  /** + * -r command-line flag. + */ +static char *requirements; + +/**   * -i command-line flag.   */ -static char *initiate_section; +static char *ut_s = "individual";  /**   * Handle for ongoing initiation operation. @@ -345,10 +356,10 @@ struct KycWebhookContext    struct MHD_Response *response;    /** -   * Logic the request is for. Name of the configuration +   * Name of the configuration     * section defining the KYC logic.     */ -  char *logic; +  const char *section_name;    /**     * HTTP response code to return. @@ -418,8 +429,9 @@ kyc_webhook_cleanup (void)   * will be done by the plugin.   *   * @param cls closure - * @param legi_row legitimization request the webhook was about + * @param process_row legitimization process request the webhook was about   * @param account_id account the webhook was about + * @param provider_section configuration section of the logic   * @param provider_user_id set to user ID at the provider, or NULL if not supported or unknown   * @param provider_legitimization_id set to legitimization process ID at the provider, or NULL if not supported or unknown   * @param status KYC status @@ -430,8 +442,9 @@ kyc_webhook_cleanup (void)  static void  webhook_finished_cb (    void *cls, -  uint64_t legi_row, +  uint64_t process_row,    const struct TALER_PaytoHashP *account_id, +  const char *provider_section,    const char *provider_user_id,    const char *provider_legitimization_id,    enum TALER_KYCLOGIC_KycStatus status, @@ -442,6 +455,7 @@ webhook_finished_cb (    struct KycWebhookContext *kwh = cls;    kwh->wh = NULL; +  // FIXME: check arguments for validity?    switch (status)    {    case TALER_KYCLOGIC_STATUS_SUCCESS: @@ -453,10 +467,10 @@ webhook_finished_cb (      break;    default:      GNUNET_log (GNUNET_ERROR_TYPE_INFO, -                "KYC status of %s/%s (Row #%llu) is %d\n", +                "KYC status of %s/%s (process #%llu) is %d\n",                  provider_user_id,                  provider_legitimization_id, -                (unsigned long long) legi_row, +                (unsigned long long) process_row,                  status);      break;    } @@ -487,7 +501,6 @@ clean_kwh (struct TEKT_RequestContext *rc)      MHD_destroy_response (kwh->response);      kwh->response = NULL;    } -  GNUNET_free (kwh->logic);    GNUNET_free (kwh);  } @@ -542,23 +555,31 @@ handler_kyc_webhook_generic (    if (NULL == kwh)    { /* first time */      kwh = GNUNET_new (struct KycWebhookContext); -    kwh->logic = GNUNET_strdup (args[0]);      kwh->rc = rc;      rc->rh_ctx = kwh;      rc->rh_cleaner = &clean_kwh;      if (GNUNET_OK != -        TALER_KYCLOGIC_kyc_get_logic (kwh->logic, -                                      &kwh->plugin, -                                      &kwh->pd)) +        TALER_KYCLOGIC_lookup_logic (args[0], +                                     &kwh->plugin, +                                     &kwh->pd, +                                     &kwh->section_name))      {        GNUNET_log (GNUNET_ERROR_TYPE_ERROR,                    "KYC logic `%s' unknown (check KYC provider configuration)\n", -                  kwh->logic); +                  args[0]);        return TALER_MHD_reply_with_error (rc->connection,                                           MHD_HTTP_NOT_FOUND,                                           TALER_EC_EXCHANGE_KYC_GENERIC_LOGIC_UNKNOWN, -                                         "$LOGIC"); +                                         args[0]); +    } +    if (0 != strcmp (args[0], +                     kwh->section_name)) +    { +      return TALER_MHD_reply_with_error (rc->connection, +                                         MHD_HTTP_BAD_REQUEST, +                                         TALER_EC_GENERIC_PARAMETER_MALFORMED, +                                         "$PROVIDER_SECTION");      }      GNUNET_log (GNUNET_ERROR_TYPE_INFO,                  "Calling KYC provider specific webhook\n"); @@ -709,6 +730,7 @@ handler_kyc_proof_get (    struct TALER_KYCLOGIC_ProviderDetails *pd;    struct TALER_KYCLOGIC_Plugin *logic;    struct ProofRequestState *rs; +  const char *section_name;    if ( (NULL == args[0]) ||         (NULL == args[1]) ) @@ -743,13 +765,14 @@ handler_kyc_proof_get (    }    if (GNUNET_OK != -      TALER_KYCLOGIC_kyc_get_logic (args[1], -                                    &logic, -                                    &pd)) +      TALER_KYCLOGIC_lookup_logic (args[1], +                                   &logic, +                                   &pd, +                                   §ion_name))    {      GNUNET_log (GNUNET_ERROR_TYPE_ERROR,                  "Could not initiate KYC with provider `%s' (configuration error?)\n", -                initiate_section); +                args[1]);      return TALER_MHD_reply_with_error (rc->connection,                                         MHD_HTTP_NOT_FOUND,                                         TALER_EC_EXCHANGE_KYC_GENERIC_LOGIC_UNKNOWN, @@ -1366,18 +1389,31 @@ run (void *cls,      return;    }    global_ret = EXIT_SUCCESS; -  if (NULL != initiate_section) +  if (NULL != requirements)    {      struct TALER_KYCLOGIC_ProviderDetails *pd; +    enum TALER_KYCLOGIC_KycUserType ut;      if (GNUNET_OK != -        TALER_KYCLOGIC_kyc_get_logic (initiate_section, -                                      &ih_logic, -                                      &pd)) +        TALER_KYCLOGIC_kyc_user_type_from_string (ut_s, +                                                  &ut)) +    { +      GNUNET_log (GNUNET_ERROR_TYPE_ERROR, +                  "Invalid user type specified ('-i')\n"); +      global_ret = EXIT_INVALIDARGUMENT; +      GNUNET_SCHEDULER_shutdown (); +      return; +    } +    if (GNUNET_OK != +        TALER_KYCLOGIC_requirements_to_logic (requirements, +                                              ut, +                                              &ih_logic, +                                              &pd, +                                              &provider_section_name))      {        GNUNET_log (GNUNET_ERROR_TYPE_ERROR, -                  "Could not initiate KYC with provider `%s' (configuration error?)\n", -                  initiate_section); +                  "Could not initiate KYC for requirements `%s' (configuration error?)\n", +                  requirements);        global_ret = EXIT_NOTCONFIGURED;        GNUNET_SCHEDULER_shutdown ();        return; @@ -1474,11 +1510,17 @@ main (int argc,        "run the integrated HTTP service",        &run_webservice),      GNUNET_GETOPT_option_string ( +      'R', +      "requirements", +      "CHECKS", +      "initiate KYC check for the given list of (space-separated) checks", +      &requirements), +    GNUNET_GETOPT_option_string (        'i', -      "initiate", -      "SECTION_NAME", -      "initiate KYC check using provider configured in SECTION_NAME of the configuration", -      &initiate_section), +      "identify", +      "USERTYPE", +      "self-identify as USERTYPE 'business' or 'individual' (defaults to 'individual')", +      &requirements),      GNUNET_GETOPT_option_string (        'u',        "user",  | 
