summaryrefslogtreecommitdiff
path: root/src/exchange/taler-exchange-httpd_kyc-proof.c
diff options
context:
space:
mode:
Diffstat (limited to 'src/exchange/taler-exchange-httpd_kyc-proof.c')
-rw-r--r--src/exchange/taler-exchange-httpd_kyc-proof.c828
1 files changed, 341 insertions, 487 deletions
diff --git a/src/exchange/taler-exchange-httpd_kyc-proof.c b/src/exchange/taler-exchange-httpd_kyc-proof.c
index 75ff81e96..bad377a2a 100644
--- a/src/exchange/taler-exchange-httpd_kyc-proof.c
+++ b/src/exchange/taler-exchange-httpd_kyc-proof.c
@@ -1,6 +1,6 @@
/*
This file is part of TALER
- Copyright (C) 2021 Taler Systems SA
+ Copyright (C) 2021-2023 Taler Systems SA
TALER is free software; you can redistribute it and/or modify it under the
terms of the GNU Affero General Public License as published by the Free Software
@@ -23,9 +23,12 @@
#include <gnunet/gnunet_json_lib.h>
#include <jansson.h>
#include <microhttpd.h>
-#include <pthread.h>
+#include "taler_attributes.h"
#include "taler_json_lib.h"
+#include "taler_kyclogic_lib.h"
#include "taler_mhd_lib.h"
+#include "taler_templating_lib.h"
+#include "taler-exchange-httpd_common_kyc.h"
#include "taler-exchange-httpd_kyc-proof.h"
#include "taler-exchange-httpd_responses.h"
@@ -52,30 +55,36 @@ struct KycProofContext
struct TEH_RequestContext *rc;
/**
- * Handle for the OAuth 2.0 CURL request.
+ * Proof logic to run.
*/
- struct GNUNET_CURL_Job *job;
+ struct TALER_KYCLOGIC_Plugin *logic;
/**
- * OAuth 2.0 authorization code.
+ * Configuration for @a logic.
*/
- const char *authorization_code;
+ struct TALER_KYCLOGIC_ProviderDetails *pd;
/**
- * OAuth 2.0 token URL we are using for the
- * request.
+ * Asynchronous operation with the proof system.
*/
- char *token_url;
+ struct TALER_KYCLOGIC_ProofHandle *ph;
/**
- * Body of the POST request.
+ * KYC AML trigger operation.
*/
- char *post_body;
+ struct TEH_KycAmlTrigger *kat;
/**
- * User ID extracted from the OAuth 2.0 service, or NULL.
+ * Process information about the user for the plugin from the database, can
+ * be NULL.
*/
- char *id;
+ char *provider_user_id;
+
+ /**
+ * Process information about the legitimization process for the plugin from the
+ * database, can be NULL.
+ */
+ char *provider_legitimization_id;
/**
* Hash of payment target URI this is about.
@@ -88,16 +97,24 @@ struct KycProofContext
struct MHD_Response *response;
/**
+ * Provider configuration section name of the logic we are running.
+ */
+ const char *provider_section;
+
+ /**
+ * Row in the database for this legitimization operation.
+ */
+ uint64_t process_row;
+
+ /**
* HTTP response code to return.
*/
unsigned int response_code;
/**
- * #GNUNET_YES if we are suspended,
- * #GNUNET_NO if not.
- * #GNUNET_SYSERR if we had some error.
+ * True if we are suspended,
*/
- enum GNUNET_GenericReturnValue suspended;
+ bool suspended;
};
@@ -122,7 +139,7 @@ static void
kpc_resume (struct KycProofContext *kpc)
{
GNUNET_assert (GNUNET_YES == kpc->suspended);
- kpc->suspended = GNUNET_NO;
+ kpc->suspended = false;
GNUNET_CONTAINER_DLL_remove (kpc_head,
kpc_tail,
kpc);
@@ -138,10 +155,10 @@ TEH_kyc_proof_cleanup (void)
while (NULL != (kpc = kpc_head))
{
- if (NULL != kpc->job)
+ if (NULL != kpc->ph)
{
- GNUNET_CURL_job_cancel (kpc->job);
- kpc->job = NULL;
+ kpc->logic->proof_cancel (kpc->ph);
+ kpc->ph = NULL;
}
kpc_resume (kpc);
}
@@ -149,348 +166,232 @@ TEH_kyc_proof_cleanup (void)
/**
- * Function implementing database transaction to check proof's KYC status.
- * Runs the transaction logic; IF it returns a non-error code, the transaction
- * logic MUST NOT queue a MHD response. IF it returns an hard error, the
- * transaction logic MUST queue a MHD response and set @a mhd_ret. IF it
- * returns the soft error code, the function MAY be called again to retry and
- * MUST not queue a MHD response.
+ * Function called after the KYC-AML trigger is done.
*
- * @param cls closure with a `struct KycProofContext *`
- * @param connection MHD proof which triggered the transaction
- * @param[out] mhd_ret set to MHD response status for @a connection,
- * if transaction failed (!)
- * @return transaction status
+ * @param cls closure
+ * @param http_status final HTTP status to return
+ * @param[in] response final HTTP ro return
*/
-static enum GNUNET_DB_QueryStatus
-persist_kyc_ok (void *cls,
- struct MHD_Connection *connection,
- MHD_RESULT *mhd_ret)
+static void
+proof_finish (
+ void *cls,
+ unsigned int http_status,
+ struct MHD_Response *response)
{
struct KycProofContext *kpc = cls;
- enum GNUNET_DB_QueryStatus qs;
- qs = TEH_plugin->set_kyc_ok (TEH_plugin->cls,
- &kpc->h_payto,
- kpc->id);
- if (GNUNET_DB_STATUS_HARD_ERROR == qs)
- {
- GNUNET_break (0);
- *mhd_ret = TALER_MHD_reply_with_ec (connection,
- TALER_EC_GENERIC_DB_STORE_FAILED,
- "set_kyc_ok");
- }
- return qs;
+ kpc->kat = NULL;
+ kpc->response_code = http_status;
+ kpc->response = response;
+ kpc_resume (kpc);
}
/**
- * The request for @a kpc failed. We may have gotten a useful error
- * message in @a j. Generate a failure response.
+ * Generate HTML error for @a connection using @a template.
*
- * @param[in,out] kpc request that failed
- * @param j reply from the server (or NULL)
+ * @param connection HTTP client connection
+ * @param template template to expand
+ * @param[in,out] http_status HTTP status of the response
+ * @param ec Taler error code to return
+ * @param message extended message to return
+ * @return MHD response object
*/
-static void
-handle_error (struct KycProofContext *kpc,
- const json_t *j)
+struct MHD_Response *
+make_html_error (struct MHD_Connection *connection,
+ const char *template,
+ unsigned int *http_status,
+ enum TALER_ErrorCode ec,
+ const char *message)
{
- const char *msg;
- const char *desc;
- struct GNUNET_JSON_Specification spec[] = {
- GNUNET_JSON_spec_string ("error",
- &msg),
- GNUNET_JSON_spec_string ("error_description",
- &desc),
- GNUNET_JSON_spec_end ()
- };
-
- {
- enum GNUNET_GenericReturnValue res;
- const char *emsg;
- unsigned int line;
-
- res = GNUNET_JSON_parse (j,
- spec,
- &emsg,
- &line);
- if (GNUNET_OK != res)
- {
- GNUNET_break_op (0);
- kpc->response
- = TALER_MHD_make_error (
- TALER_EC_EXCHANGE_KYC_PROOF_BACKEND_INVALID_RESPONSE,
- "Unexpected response from KYC gateway");
- kpc->response_code
- = MHD_HTTP_BAD_GATEWAY;
- return;
- }
- }
- /* case TALER_EC_EXCHANGE_KYC_PROOF_BACKEND_AUTHORZATION_FAILED,
- we MAY want to in the future look at the requested content type
- and possibly respond in JSON if indicated. */
- {
- char *reply;
-
- GNUNET_asprintf (&reply,
- "<html><head><title>%s</title></head><body><h1>%s</h1><p>%s</p></body></html>",
- msg,
- msg,
- desc);
- kpc->response
- = MHD_create_response_from_buffer (strlen (reply),
- reply,
- MHD_RESPMEM_MUST_COPY);
- GNUNET_assert (NULL != kpc->response);
- GNUNET_free (reply);
- }
- kpc->response_code = MHD_HTTP_FORBIDDEN;
+ struct MHD_Response *response = NULL;
+ json_t *body;
+
+ body = GNUNET_JSON_PACK (
+ GNUNET_JSON_pack_allow_null (
+ GNUNET_JSON_pack_string ("message",
+ message)),
+ TALER_JSON_pack_ec (
+ ec));
+ GNUNET_break (
+ GNUNET_SYSERR !=
+ TALER_TEMPLATING_build (connection,
+ http_status,
+ template,
+ NULL,
+ NULL,
+ body,
+ &response));
+ json_decref (body);
+ return response;
}
/**
- * The request for @a kpc succeeded (presumably).
- * Parse the user ID and store it in @a kpc (if possible).
+ * Respond with an HTML message on the given @a rc.
*
- * @param[in,out] kpc request that succeeded
- * @param j reply from the server
+ * @param[in,out] rc request to respond to
+ * @param http_status HTTP status code to use
+ * @param template template to fill in
+ * @param ec error code to use for the template
+ * @param message additional message to return
+ * @return MHD result code
*/
-static void
-parse_success_reply (struct KycProofContext *kpc,
- const json_t *j)
+static MHD_RESULT
+respond_html_ec (struct TEH_RequestContext *rc,
+ unsigned int http_status,
+ const char *template,
+ enum TALER_ErrorCode ec,
+ const char *message)
{
- const char *state;
- json_t *data;
- struct GNUNET_JSON_Specification spec[] = {
- GNUNET_JSON_spec_string ("status",
- &state),
- GNUNET_JSON_spec_json ("data",
- &data),
- GNUNET_JSON_spec_end ()
- };
- enum GNUNET_GenericReturnValue res;
- const char *emsg;
- unsigned int line;
-
- res = GNUNET_JSON_parse (j,
- spec,
- &emsg,
- &line);
- if (GNUNET_OK != res)
- {
- GNUNET_break_op (0);
- kpc->response
- = TALER_MHD_make_error (
- TALER_EC_EXCHANGE_KYC_PROOF_BACKEND_INVALID_RESPONSE,
- "Unexpected response from KYC gateway");
- kpc->response_code
- = MHD_HTTP_BAD_GATEWAY;
- return;
- }
- if (0 != strcasecmp (state,
- "success"))
- {
- GNUNET_break_op (0);
- handle_error (kpc,
- j);
- return;
- }
- {
- const char *id;
- struct GNUNET_JSON_Specification ispec[] = {
- GNUNET_JSON_spec_string ("id",
- &id),
- GNUNET_JSON_spec_end ()
- };
-
- res = GNUNET_JSON_parse (data,
- ispec,
- &emsg,
- &line);
- if (GNUNET_OK != res)
- {
- GNUNET_break_op (0);
- kpc->response
- = TALER_MHD_make_error (
- TALER_EC_EXCHANGE_KYC_PROOF_BACKEND_INVALID_RESPONSE,
- "Unexpected response from KYC gateway");
- kpc->response_code
- = MHD_HTTP_BAD_GATEWAY;
- return;
- }
- kpc->id = GNUNET_strdup (id);
- }
+ struct MHD_Response *response;
+ MHD_RESULT res;
+
+ response = make_html_error (rc->connection,
+ template,
+ &http_status,
+ ec,
+ message);
+ res = MHD_queue_response (rc->connection,
+ http_status,
+ response);
+ MHD_destroy_response (response);
+ return res;
}
/**
- * After we are done with the CURL interaction we
- * need to update our database state with the information
- * retrieved.
+ * Function called with the result of a proof check operation.
*
- * @param cls our `struct KycProofContext`
- * @param response_code HTTP response code from server, 0 on hard error
- * @param response in JSON, NULL if response was not in JSON format
- */
-static void
-handle_curl_fetch_finished (void *cls,
- long response_code,
- const void *response)
-{
- struct KycProofContext *kpc = cls;
- const json_t *j = response;
-
- kpc->job = NULL;
- switch (response_code)
- {
- case MHD_HTTP_OK:
- parse_success_reply (kpc,
- j);
- break;
- default:
- handle_error (kpc,
- j);
- break;
- }
- kpc_resume (kpc);
-}
-
-
-/**
- * After we are done with the CURL interaction we
- * need to fetch the user's account details.
+ * Note that the "decref" for the @a response
+ * will be done by the callee and MUST NOT be done by the plugin.
*
- * @param cls our `struct KycProofContext`
- * @param response_code HTTP response code from server, 0 on hard error
- * @param response in JSON, NULL if response was not in JSON format
+ * @param cls closure
+ * @param status KYC status
+ * @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 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
-handle_curl_login_finished (void *cls,
- long response_code,
- const void *response)
+proof_cb (
+ void *cls,
+ enum TALER_KYCLOGIC_KycStatus status,
+ 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 KycProofContext *kpc = cls;
- const json_t *j = response;
+ struct TEH_RequestContext *rc = kpc->rc;
+ struct GNUNET_AsyncScopeSave old_scope;
- kpc->job = NULL;
- switch (response_code)
+ kpc->ph = NULL;
+ GNUNET_async_scope_enter (&rc->async_scope_id,
+ &old_scope);
+ switch (status)
{
- case MHD_HTTP_OK:
+ case TALER_KYCLOGIC_STATUS_SUCCESS:
+ GNUNET_log (GNUNET_ERROR_TYPE_INFO,
+ "KYC process #%llu succeeded with KYC provider\n",
+ (unsigned long long) kpc->process_row);
+ kpc->kat = TEH_kyc_finished (&rc->async_scope_id,
+ kpc->process_row,
+ &kpc->h_payto,
+ kpc->provider_section,
+ provider_user_id,
+ provider_legitimization_id,
+ expiration,
+ attributes,
+ http_status,
+ response,
+ &proof_finish,
+ kpc);
+ if (NULL == kpc->kat)
{
- const char *access_token;
- const char *token_type;
- uint64_t expires_in_s;
- const char *refresh_token;
- struct GNUNET_JSON_Specification spec[] = {
- GNUNET_JSON_spec_string ("access_token",
- &access_token),
- GNUNET_JSON_spec_string ("token_type",
- &token_type),
- GNUNET_JSON_spec_uint64 ("expires_in",
- &expires_in_s),
- GNUNET_JSON_spec_string ("refresh_token",
- &refresh_token),
- GNUNET_JSON_spec_end ()
- };
- CURL *eh;
-
- {
- enum GNUNET_GenericReturnValue res;
- const char *emsg;
- unsigned int line;
-
- res = GNUNET_JSON_parse (j,
- spec,
- &emsg,
- &line);
- if (GNUNET_OK != res)
- {
- GNUNET_break_op (0);
- kpc->response
- = TALER_MHD_make_error (
- TALER_EC_EXCHANGE_KYC_PROOF_BACKEND_INVALID_RESPONSE,
- "Unexpected response from KYC gateway");
- kpc->response_code
- = MHD_HTTP_BAD_GATEWAY;
- break;
- }
- }
- if (0 != strcasecmp (token_type,
- "bearer"))
- {
- GNUNET_break_op (0);
- kpc->response
- = TALER_MHD_make_error (
- TALER_EC_EXCHANGE_KYC_PROOF_BACKEND_INVALID_RESPONSE,
- "Unexpected token type in response from KYC gateway");
- kpc->response_code
- = MHD_HTTP_BAD_GATEWAY;
- break;
- }
-
- /* We guard against a few characters that could
- conceivably be abused to mess with the HTTP header */
- if ( (NULL != strchr (access_token,
- '\n')) ||
- (NULL != strchr (access_token,
- '\r')) ||
- (NULL != strchr (access_token,
- ' ')) ||
- (NULL != strchr (access_token,
- ';')) )
- {
- GNUNET_break_op (0);
- kpc->response
- = TALER_MHD_make_error (
- TALER_EC_EXCHANGE_KYC_PROOF_BACKEND_INVALID_RESPONSE,
- "Illegal character in access token");
- kpc->response_code
- = MHD_HTTP_BAD_GATEWAY;
- break;
- }
-
- eh = curl_easy_init ();
- if (NULL == eh)
- {
- GNUNET_break_op (0);
- kpc->response
- = TALER_MHD_make_error (
- TALER_EC_GENERIC_ALLOCATION_FAILURE,
- "curl_easy_init");
- kpc->response_code
- = MHD_HTTP_INTERNAL_SERVER_ERROR;
- break;
- }
- GNUNET_assert (CURLE_OK ==
- curl_easy_setopt (eh,
- CURLOPT_URL,
- TEH_kyc_config.details.oauth2.info_url));
+ http_status = MHD_HTTP_INTERNAL_SERVER_ERROR;
+ if (NULL != response)
+ MHD_destroy_response (response);
+ response = make_html_error (kpc->rc->connection,
+ "kyc-proof-internal-error",
+ &http_status,
+ TALER_EC_EXCHANGE_GENERIC_BAD_CONFIGURATION,
+ "[exchange] AML_KYC_TRIGGER");
+ }
+ break;
+ case TALER_KYCLOGIC_STATUS_FAILED:
+ case TALER_KYCLOGIC_STATUS_PROVIDER_FAILED:
+ case TALER_KYCLOGIC_STATUS_USER_ABORTED:
+ case TALER_KYCLOGIC_STATUS_ABORTED:
+ GNUNET_assert (NULL == kpc->kat);
+ GNUNET_log (GNUNET_ERROR_TYPE_INFO,
+ "KYC process %s/%s (Row #%llu) failed: %d\n",
+ provider_user_id,
+ provider_legitimization_id,
+ (unsigned long long) kpc->process_row,
+ status);
+ if (5 == http_status / 100)
+ {
+ char *msg;
+
+ /* OAuth2 server had a problem, do NOT log this as a KYC failure */
+ if (NULL != response)
+ MHD_destroy_response (response);
+ GNUNET_asprintf (&msg,
+ "Failure by KYC provider (HTTP status %u)\n",
+ http_status);
+ http_status = MHD_HTTP_BAD_GATEWAY;
+ response = make_html_error (kpc->rc->connection,
+ "kyc-proof-internal-error",
+ &http_status,
+ TALER_EC_EXCHANGE_KYC_GENERIC_PROVIDER_UNEXPECTED_REPLY,
+ msg);
+ GNUNET_free (msg);
+ }
+ else
+ {
+ if (! TEH_kyc_failed (kpc->process_row,
+ &kpc->h_payto,
+ kpc->provider_section,
+ provider_user_id,
+ provider_legitimization_id))
{
- char *hdr;
- struct curl_slist *slist;
-
- GNUNET_asprintf (&hdr,
- "%s: Bearer %s",
- MHD_HTTP_HEADER_AUTHORIZATION,
- access_token);
- slist = curl_slist_append (NULL,
- hdr);
- kpc->job = GNUNET_CURL_job_add2 (TEH_curl_ctx,
- eh,
- slist,
- &handle_curl_fetch_finished,
- kpc);
- curl_slist_free_all (slist);
- GNUNET_free (hdr);
+ GNUNET_break (0);
+ if (NULL != response)
+ MHD_destroy_response (response);
+ http_status = MHD_HTTP_INTERNAL_SERVER_ERROR;
+ response = make_html_error (kpc->rc->connection,
+ "kyc-proof-internal-error",
+ &http_status,
+ TALER_EC_GENERIC_DB_STORE_FAILED,
+ "insert_kyc_failure");
}
- return;
}
+ break;
default:
- handle_error (kpc,
- j);
+ GNUNET_log (GNUNET_ERROR_TYPE_INFO,
+ "KYC status of %s/%s (Row #%llu) is %d\n",
+ provider_user_id,
+ provider_legitimization_id,
+ (unsigned long long) kpc->process_row,
+ (int) status);
break;
}
- kpc_resume (kpc);
+ if (NULL == kpc->kat)
+ {
+ GNUNET_log (GNUNET_ERROR_TYPE_INFO,
+ "KYC process #%llu failed with status %d\n",
+ (unsigned long long) kpc->process_row,
+ status);
+ proof_finish (kpc,
+ http_status,
+ response);
+ }
+ GNUNET_async_scope_restore (&old_scope);
}
@@ -504,19 +405,23 @@ clean_kpc (struct TEH_RequestContext *rc)
{
struct KycProofContext *kpc = rc->rh_ctx;
- if (NULL != kpc->job)
+ if (NULL != kpc->ph)
+ {
+ kpc->logic->proof_cancel (kpc->ph);
+ kpc->ph = NULL;
+ }
+ if (NULL != kpc->kat)
{
- GNUNET_CURL_job_cancel (kpc->job);
- kpc->job = NULL;
+ TEH_kyc_finished_cancel (kpc->kat);
+ kpc->kat = NULL;
}
if (NULL != kpc->response)
{
MHD_destroy_response (kpc->response);
kpc->response = NULL;
}
- GNUNET_free (kpc->post_body);
- GNUNET_free (kpc->token_url);
- GNUNET_free (kpc->id);
+ GNUNET_free (kpc->provider_user_id);
+ GNUNET_free (kpc->provider_legitimization_id);
GNUNET_free (kpc);
}
@@ -524,188 +429,137 @@ clean_kpc (struct TEH_RequestContext *rc)
MHD_RESULT
TEH_handler_kyc_proof (
struct TEH_RequestContext *rc,
- const char *const args[])
+ const char *const args[1])
{
struct KycProofContext *kpc = rc->rh_ctx;
+ const char *provider_section_or_logic = args[0];
if (NULL == kpc)
- { /* first time */
+ {
+ /* first time */
+ if (NULL == provider_section_or_logic)
+ {
+ GNUNET_break_op (0);
+ return respond_html_ec (rc,
+ MHD_HTTP_NOT_FOUND,
+ "kyc-proof-endpoint-unknown",
+ TALER_EC_GENERIC_ENDPOINT_UNKNOWN,
+ "'/kyc-proof/$PROVIDER_SECTION?state=$H_PAYTO' required");
+ }
kpc = GNUNET_new (struct KycProofContext);
kpc->rc = rc;
rc->rh_ctx = kpc;
rc->rh_cleaner = &clean_kpc;
+ TALER_MHD_parse_request_arg_auto_t (rc->connection,
+ "state",
+ &kpc->h_payto);
if (GNUNET_OK !=
- GNUNET_STRINGS_string_to_data (args[0],
- strlen (args[0]),
- &kpc->h_payto,
- sizeof (kpc->h_payto)))
+ TALER_KYCLOGIC_lookup_logic (provider_section_or_logic,
+ &kpc->logic,
+ &kpc->pd,
+ &kpc->provider_section))
{
GNUNET_break_op (0);
- return TALER_MHD_reply_with_error (rc->connection,
- MHD_HTTP_BAD_REQUEST,
- TALER_EC_GENERIC_PARAMETER_MALFORMED,
- "h_payto");
+ return respond_html_ec (rc,
+ MHD_HTTP_NOT_FOUND,
+ "kyc-proof-target-unknown",
+ TALER_EC_EXCHANGE_KYC_GENERIC_LOGIC_UNKNOWN,
+ provider_section_or_logic);
}
- kpc->authorization_code
- = MHD_lookup_connection_value (rc->connection,
- MHD_GET_ARGUMENT_KIND,
- "code");
- if (NULL == kpc->authorization_code)
+ if (NULL != kpc->provider_section)
{
- GNUNET_break_op (0);
- return TALER_MHD_reply_with_error (rc->connection,
- MHD_HTTP_BAD_REQUEST,
- TALER_EC_GENERIC_PARAMETER_MALFORMED,
- "code");
- }
- if (TEH_KYC_NONE == TEH_kyc_config.mode)
- return TALER_MHD_reply_static (
- rc->connection,
- MHD_HTTP_NO_CONTENT,
- NULL,
- NULL,
- 0);
+ enum GNUNET_DB_QueryStatus qs;
+ struct GNUNET_TIME_Absolute expiration;
- {
- CURL *eh;
+ if (0 != strcmp (provider_section_or_logic,
+ kpc->provider_section))
+ {
+ GNUNET_break_op (0);
+ return respond_html_ec (rc,
+ MHD_HTTP_BAD_REQUEST,
+ "kyc-proof-bad-request",
+ TALER_EC_GENERIC_PARAMETER_MALFORMED,
+ "PROVIDER_SECTION");
+ }
- eh = curl_easy_init ();
- if (NULL == eh)
+ qs = TEH_plugin->lookup_kyc_process_by_account (
+ TEH_plugin->cls,
+ kpc->provider_section,
+ &kpc->h_payto,
+ &kpc->process_row,
+ &expiration,
+ &kpc->provider_user_id,
+ &kpc->provider_legitimization_id);
+ switch (qs)
{
- GNUNET_break (0);
- return TALER_MHD_reply_with_error (rc->connection,
- MHD_HTTP_INTERNAL_SERVER_ERROR,
- TALER_EC_GENERIC_ALLOCATION_FAILURE,
- "curl_easy_init");
+ case GNUNET_DB_STATUS_HARD_ERROR:
+ case GNUNET_DB_STATUS_SOFT_ERROR:
+ return respond_html_ec (rc,
+ MHD_HTTP_INTERNAL_SERVER_ERROR,
+ "kyc-proof-internal-error",
+ TALER_EC_GENERIC_DB_FETCH_FAILED,
+ "lookup_kyc_process_by_account");
+ case GNUNET_DB_STATUS_SUCCESS_NO_RESULTS:
+ return respond_html_ec (rc,
+ MHD_HTTP_NOT_FOUND,
+ "kyc-proof-target-unknown",
+ TALER_EC_EXCHANGE_KYC_PROOF_REQUEST_UNKNOWN,
+ kpc->provider_section);
+ case GNUNET_DB_STATUS_SUCCESS_ONE_RESULT:
+ break;
}
- GNUNET_asprintf (&kpc->token_url,
- "%s",
- TEH_kyc_config.details.oauth2.auth_url);
- GNUNET_assert (CURLE_OK ==
- curl_easy_setopt (eh,
- CURLOPT_URL,
- kpc->token_url));
- GNUNET_assert (CURLE_OK ==
- curl_easy_setopt (eh,
- CURLOPT_POST,
- 1));
+ if (GNUNET_TIME_absolute_is_future (expiration))
{
- char *client_id;
- char *redirect_uri;
- char *client_secret;
- char *authorization_code;
-
- client_id = curl_easy_escape (eh,
- TEH_kyc_config.details.oauth2.client_id,
- 0);
- GNUNET_assert (NULL != client_id);
- {
- char *request_uri;
-
- GNUNET_asprintf (&request_uri,
- "%s?client_id=%s",
- TEH_kyc_config.details.oauth2.login_url,
- TEH_kyc_config.details.oauth2.client_id);
- redirect_uri = curl_easy_escape (eh,
- request_uri,
- 0);
- GNUNET_free (request_uri);
- }
- GNUNET_assert (NULL != redirect_uri);
- client_secret = curl_easy_escape (eh,
- TEH_kyc_config.details.oauth2.
- client_secret,
- 0);
- GNUNET_assert (NULL != client_secret);
- authorization_code = curl_easy_escape (eh,
- kpc->authorization_code,
- 0);
- GNUNET_assert (NULL != authorization_code);
- GNUNET_asprintf (&kpc->post_body,
- "client_id=%s&redirect_uri=%s&client_secret=%s&code=%s&grant_type=authorization_code",
- client_id,
- redirect_uri,
- client_secret,
- authorization_code);
- curl_free (authorization_code);
- curl_free (client_secret);
- curl_free (redirect_uri);
- curl_free (client_id);
+ /* KYC not required */
+ return respond_html_ec (rc,
+ MHD_HTTP_OK,
+ "kyc-proof-already-done",
+ TALER_EC_NONE,
+ NULL);
}
- GNUNET_assert (CURLE_OK ==
- curl_easy_setopt (eh,
- CURLOPT_POSTFIELDS,
- kpc->post_body));
- GNUNET_assert (CURLE_OK ==
- curl_easy_setopt (eh,
- CURLOPT_FOLLOWLOCATION,
- 1L));
- /* limit MAXREDIRS to 5 as a simple security measure against
- a potential infinite loop caused by a malicious target */
- GNUNET_assert (CURLE_OK ==
- curl_easy_setopt (eh,
- CURLOPT_MAXREDIRS,
- 5L));
-
- kpc->job = GNUNET_CURL_job_add (TEH_curl_ctx,
- eh,
- &handle_curl_login_finished,
- kpc);
- kpc->suspended = GNUNET_YES;
- GNUNET_CONTAINER_DLL_insert (kpc_head,
- kpc_tail,
- kpc);
- MHD_suspend_connection (rc->connection);
- return MHD_YES;
}
- }
+ kpc->ph = kpc->logic->proof (kpc->logic->cls,
+ kpc->pd,
+ rc->connection,
+ &kpc->h_payto,
+ kpc->process_row,
+ kpc->provider_user_id,
+ kpc->provider_legitimization_id,
+ &proof_cb,
+ kpc);
+ if (NULL == kpc->ph)
+ {
+ GNUNET_break (0);
+ return respond_html_ec (rc,
+ MHD_HTTP_INTERNAL_SERVER_ERROR,
+ "kyc-proof-internal-error",
+ TALER_EC_GENERIC_INTERNAL_INVARIANT_FAILURE,
+ "could not start proof with KYC logic");
+ }
- if (NULL != kpc->response)
- {
- /* handle _failed_ resumed cases */
- return MHD_queue_response (rc->connection,
- kpc->response_code,
- kpc->response);
- }
- /* _successfully_ resumed case */
- {
- MHD_RESULT res;
- enum GNUNET_GenericReturnValue ret;
-
- ret = TEH_DB_run_transaction (kpc->rc->connection,
- "check proof kyc",
- TEH_MT_REQUEST_OTHER,
- &res,
- &persist_kyc_ok,
- kpc);
- if (GNUNET_SYSERR == ret)
- return res;
+ kpc->suspended = true;
+ GNUNET_CONTAINER_DLL_insert (kpc_head,
+ kpc_tail,
+ kpc);
+ MHD_suspend_connection (rc->connection);
+ return MHD_YES;
}
+ if (NULL == kpc->response)
{
- struct MHD_Response *response;
- MHD_RESULT res;
-
- response = MHD_create_response_from_buffer (0,
- "",
- MHD_RESPMEM_PERSISTENT);
- if (NULL == response)
- {
- GNUNET_break (0);
- return MHD_NO;
- }
- GNUNET_break (MHD_YES ==
- MHD_add_response_header (
- response,
- MHD_HTTP_HEADER_LOCATION,
- TEH_kyc_config.details.oauth2.post_kyc_redirect_url));
- res = MHD_queue_response (rc->connection,
- MHD_HTTP_SEE_OTHER,
- response);
- MHD_destroy_response (response);
- return res;
+ GNUNET_break (0);
+ return respond_html_ec (rc,
+ MHD_HTTP_INTERNAL_SERVER_ERROR,
+ "kyc-proof-internal-error",
+ TALER_EC_GENERIC_INTERNAL_INVARIANT_FAILURE,
+ "handler resumed without response");
}
+
+ /* return response from KYC logic */
+ return MHD_queue_response (rc->connection,
+ kpc->response_code,
+ kpc->response);
}