diff options
Diffstat (limited to 'src/kyclogic/taler-exchange-kyc-tester.c')
-rw-r--r-- | src/kyclogic/taler-exchange-kyc-tester.c | 253 |
1 files changed, 190 insertions, 63 deletions
diff --git a/src/kyclogic/taler-exchange-kyc-tester.c b/src/kyclogic/taler-exchange-kyc-tester.c index 40aadba1a..c2efafd72 100644 --- a/src/kyclogic/taler-exchange-kyc-tester.c +++ b/src/kyclogic/taler-exchange-kyc-tester.c @@ -28,7 +28,7 @@ #include "taler_mhd_lib.h" #include "taler_json_lib.h" #include "taler_templating_lib.h" -#include "taler_crypto_lib.h" +#include "taler_util.h" #include "taler_kyclogic_lib.h" #include "taler_kyclogic_plugin.h" #include <gnunet/gnunet_mhd_compat.h> @@ -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. @@ -390,7 +401,6 @@ kwh_resume (struct KycWebhookContext *kwh) kwh_tail, kwh); MHD_resume_connection (kwh->rc->connection); - TALER_MHD_daemon_trigger (); } @@ -419,30 +429,61 @@ 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 * @param expiration until when is the KYC check valid + * @param attributes user attributes returned by the provider * @param http_status HTTP status code of @a response * @param[in] response to return to the HTTP client */ 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, struct GNUNET_TIME_Absolute expiration, + const json_t *attributes, unsigned int http_status, struct MHD_Response *response) { struct KycWebhookContext *kwh = cls; + (void) expiration; + (void) provider_section; kwh->wh = NULL; + if ( (NULL != account_id) && + (0 != GNUNET_memcmp (account_id, + &cmd_line_h_payto)) ) + { + GNUNET_log (GNUNET_ERROR_TYPE_WARNING, + "Received webhook for unexpected account\n"); + } + if ( (NULL != provider_user_id) && + (NULL != cmd_provider_user_id) && + (0 != strcmp (provider_user_id, + cmd_provider_user_id)) ) + { + GNUNET_log (GNUNET_ERROR_TYPE_WARNING, + "Received webhook for unexpected provider user ID (%s)\n", + provider_user_id); + } + if ( (NULL != provider_legitimization_id) && + (NULL != cmd_provider_legitimization_id) && + (0 != strcmp (provider_legitimization_id, + cmd_provider_legitimization_id)) ) + { + GNUNET_log (GNUNET_ERROR_TYPE_WARNING, + "Received webhook for unexpected provider legitimization ID (%s)\n", + provider_legitimization_id); + } switch (status) { case TALER_KYCLOGIC_STATUS_SUCCESS: @@ -451,19 +492,26 @@ webhook_finished_cb ( "KYC successful for user `%s' (legi: %s)\n", provider_user_id, provider_legitimization_id); + GNUNET_break (NULL != attributes); + fprintf (stderr, + "Extracted attributes:\n"); + json_dumpf (attributes, + stderr, + JSON_INDENT (2)); 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; } kwh->response = response; kwh->response_code = http_status; kwh_resume (kwh); + TALER_MHD_daemon_trigger (); } @@ -487,7 +535,6 @@ clean_kwh (struct TEKT_RequestContext *rc) MHD_destroy_response (kwh->response); kwh->response = NULL; } - GNUNET_free (kwh->logic); GNUNET_free (kwh); } @@ -511,6 +558,7 @@ kyc_provider_account_lookup ( struct TALER_PaytoHashP *h_payto, uint64_t *legi_row) { + (void) cls; GNUNET_log (GNUNET_ERROR_TYPE_INFO, "Simulated account lookup using `%s/%s'\n", provider_section, @@ -542,23 +590,24 @@ 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)) + if ( (NULL == args[0]) || + (GNUNET_OK != + 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]); } GNUNET_log (GNUNET_ERROR_TYPE_INFO, "Calling KYC provider specific webhook\n"); @@ -600,7 +649,7 @@ handler_kyc_webhook_generic ( /* We resumed, but got no response? This should not happen. */ - GNUNET_break (0); + GNUNET_assert (0); return TALER_MHD_reply_with_error (rc->connection, MHD_HTTP_INTERNAL_SERVER_ERROR, TALER_EC_GENERIC_INTERNAL_INVARIANT_FAILURE, @@ -620,6 +669,8 @@ handler_kyc_webhook_get ( struct TEKT_RequestContext *rc, const char *const args[]) { + GNUNET_log (GNUNET_ERROR_TYPE_INFO, + "Webhook GET triggered\n"); return handler_kyc_webhook_generic (rc, MHD_HTTP_METHOD_GET, NULL, @@ -641,6 +692,8 @@ handler_kyc_webhook_post ( const json_t *root, const char *const args[]) { + GNUNET_log (GNUNET_ERROR_TYPE_INFO, + "Webhook POST triggered\n"); return handler_kyc_webhook_generic (rc, MHD_HTTP_METHOD_POST, root, @@ -659,6 +712,7 @@ handler_kyc_webhook_post ( * @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 expiration until when is the KYC check valid + * @param attributes attributes about the user * @param http_status HTTP status code of @a response * @param[in] response to return to the HTTP client */ @@ -669,24 +723,39 @@ proof_cb ( const char *provider_user_id, const char *provider_legitimization_id, struct GNUNET_TIME_Absolute expiration, + const json_t *attributes, unsigned int http_status, struct MHD_Response *response) { struct ProofRequestState *rs = cls; + (void) expiration; GNUNET_log (GNUNET_ERROR_TYPE_MESSAGE, "KYC legitimization %s completed with status %d (%u) for %s\n", provider_legitimization_id, status, http_status, provider_user_id); - MHD_resume_connection (rs->rc->connection); - TALER_MHD_daemon_trigger (); + if (TALER_KYCLOGIC_STATUS_SUCCESS == status) + { + GNUNET_break (NULL != attributes); + fprintf (stderr, + "Extracted attributes:\n"); + json_dumpf (attributes, + stderr, + JSON_INDENT (2)); + } + GNUNET_log (GNUNET_ERROR_TYPE_INFO, + "Returning response %p with status %u\n", + response, + http_status); rs->rc->response = response; rs->rc->http_status = http_status; GNUNET_CONTAINER_DLL_remove (rs_head, rs_tail, rs); + MHD_resume_connection (rs->rc->connection); + TALER_MHD_daemon_trigger (); GNUNET_free (rs); } @@ -697,31 +766,44 @@ proof_cb ( * * @param rc request context * @param args remaining URL arguments; - * args[0] is the 'h_payto', - * args[1] should be the logic plugin name + * args[0] should be the logic plugin name */ static MHD_RESULT handler_kyc_proof_get ( struct TEKT_RequestContext *rc, - const char *const args[]) + const char *const args[1]) { struct TALER_PaytoHashP h_payto; struct TALER_KYCLOGIC_ProviderDetails *pd; struct TALER_KYCLOGIC_Plugin *logic; struct ProofRequestState *rs; + const char *section_name; + const char *h_paytos; - if ( (NULL == args[0]) || - (NULL == args[1]) ) + GNUNET_log (GNUNET_ERROR_TYPE_INFO, + "GET /kyc-proof triggered\n"); + if (NULL == args[0]) { GNUNET_break_op (0); return TALER_MHD_reply_with_error (rc->connection, MHD_HTTP_NOT_FOUND, TALER_EC_GENERIC_ENDPOINT_UNKNOWN, - "'/$H_PAYTO/$LOGIC' required after '/kyc-proof'"); + "'/kyc-proof/$PROVIDER_SECTION?state=$H_PAYTO' required"); + } + h_paytos = MHD_lookup_connection_value (rc->connection, + MHD_GET_ARGUMENT_KIND, + "state"); + if (NULL == h_paytos) + { + GNUNET_break_op (0); + return TALER_MHD_reply_with_error (rc->connection, + MHD_HTTP_BAD_REQUEST, + TALER_EC_GENERIC_PARAMETER_MISSING, + "h_payto"); } if (GNUNET_OK != - GNUNET_STRINGS_string_to_data (args[0], - strlen (args[0]), + GNUNET_STRINGS_string_to_data (h_paytos, + strlen (h_paytos), &h_payto, sizeof (h_payto))) { @@ -743,17 +825,18 @@ handler_kyc_proof_get ( } if (GNUNET_OK != - TALER_KYCLOGIC_kyc_get_logic (args[1], - &logic, - &pd)) + TALER_KYCLOGIC_lookup_logic (args[0], + &logic, + &pd, + §ion_name)) { GNUNET_log (GNUNET_ERROR_TYPE_ERROR, "Could not initiate KYC with provider `%s' (configuration error?)\n", - initiate_section); + args[0]); return TALER_MHD_reply_with_error (rc->connection, MHD_HTTP_NOT_FOUND, TALER_EC_EXCHANGE_KYC_GENERIC_LOGIC_UNKNOWN, - args[1]); + args[0]); } rs = GNUNET_new (struct ProofRequestState); rs->rc = rc; @@ -764,7 +847,6 @@ handler_kyc_proof_get ( rs); rs->ph = logic->proof (logic->cls, pd, - &args[2], rc->connection, &h_payto, kyc_row_id, @@ -829,6 +911,8 @@ handle_mhd_completion_callback (void *cls, TALER_MHD_parse_post_cleanup_callback (rc->opaque_post_parsing_context); /* Sanity-check that we didn't leave any transactions hanging */ + if (NULL != rc->root) + json_decref (rc->root); GNUNET_free (rc); *con_cls = NULL; } @@ -906,9 +990,9 @@ proceed_with_handler (struct TEKT_RequestContext *rc, /* Parse command-line arguments */ /* make a copy of 'url' because 'strtok_r()' will modify */ - memcpy (d, - url, - ulen); + GNUNET_memcpy (d, + url, + ulen); i = 0; args[i++] = strtok_r (d, "/", &sp); while ( (NULL != args[i - 1]) && @@ -998,8 +1082,7 @@ handle_mhd_request (void *cls, .url = "kyc-proof", .method = MHD_HTTP_METHOD_GET, .handler.get = &handler_kyc_proof_get, - .nargs = 128, - .nargs_is_upper_bound = true + .nargs = 1 }, { .url = "kyc-webhook", @@ -1103,15 +1186,19 @@ handle_mhd_request (void *cls, return TALER_MHD_reply_cors_preflight (connection); } GNUNET_assert (NULL != rh->method); - if (0 == strcasecmp (method, + if (0 != strcasecmp (method, rh->method)) - /* cache to avoid the loop next time */ - rc->rh = rh; - /* run handler */ - return proceed_with_handler (rc, - url + tok_size + 1, - upload_data, - upload_data_size); + { + found = true; + continue; + } + /* cache to avoid the loop next time */ + rc->rh = rh; + GNUNET_log (GNUNET_ERROR_TYPE_INFO, + "Handler found for %s '%s'\n", + method, + url); + return MHD_YES; } if (found) @@ -1280,6 +1367,7 @@ initiate_cb ( const char *provider_legitimization_id, const char *error_msg_hint) { + (void) cls; ih = NULL; if (TALER_EC_NONE != ec) { @@ -1291,11 +1379,30 @@ initiate_cb ( GNUNET_SCHEDULER_shutdown (); return; } - fprintf (stdout, - "Visit `%s' to begin KYC process (-u: '%s', -U: '%s')\n", - redirect_url, - provider_user_id, - provider_legitimization_id); + { + char *s; + + s = GNUNET_STRINGS_data_to_string_alloc (&cmd_line_h_payto, + sizeof (cmd_line_h_payto)); + if (NULL != provider_user_id) + { + fprintf (stdout, + "Visit `%s' to begin KYC process.\nAlso use: taler-exchange-kyc-tester -w -u '%s' -U '%s' -p %s\n", + redirect_url, + provider_user_id, + provider_legitimization_id, + s); + } + else + { + fprintf (stdout, + "Visit `%s' to begin KYC process.\nAlso use: taler-exchange-kyc-tester -w -U '%s' -p %s\n", + redirect_url, + provider_legitimization_id, + s); + } + GNUNET_free (s); + } GNUNET_free (cmd_provider_user_id); GNUNET_free (cmd_provider_legitimization_id); if (NULL != provider_user_id) @@ -1330,7 +1437,8 @@ run (void *cls, if (GNUNET_OK != TALER_TEMPLATING_init ("exchange")) { - GNUNET_break (0); + GNUNET_log (GNUNET_ERROR_TYPE_ERROR, + "Could not load templates. Installation broken.\n"); return; } if (print_h_payto) @@ -1363,18 +1471,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; @@ -1471,11 +1592,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", |