-implement more of the KYC handlers
This commit is contained in:
parent
fa30a132a5
commit
778a402d07
@ -1 +1 @@
|
|||||||
Subproject commit ca56accac72b6ce050a38d36172390b14100a538
|
Subproject commit 8c7d9be40ba627348da3e01b91b4f1d3cc78631f
|
@ -37,7 +37,7 @@
|
|||||||
* @param body JSON body to add to @e ctx
|
* @param body JSON body to add to @e ctx
|
||||||
* @return #GNUNET_OK on success #GNUNET_SYSERR on failure
|
* @return #GNUNET_OK on success #GNUNET_SYSERR on failure
|
||||||
*/
|
*/
|
||||||
int
|
enum GNUNET_GenericReturnValue
|
||||||
TALER_curl_easy_post (struct TALER_CURL_PostContext *ctx,
|
TALER_curl_easy_post (struct TALER_CURL_PostContext *ctx,
|
||||||
CURL *eh,
|
CURL *eh,
|
||||||
const json_t *body)
|
const json_t *body)
|
||||||
|
@ -123,6 +123,7 @@ taler_exchange_httpd_LDADD = \
|
|||||||
-lgnunetutil \
|
-lgnunetutil \
|
||||||
-lgnunetjson \
|
-lgnunetjson \
|
||||||
-ljansson \
|
-ljansson \
|
||||||
|
-lcurl \
|
||||||
-lz \
|
-lz \
|
||||||
$(XLIB)
|
$(XLIB)
|
||||||
|
|
||||||
|
@ -102,3 +102,7 @@ KYC_MODE = NONE
|
|||||||
|
|
||||||
# KYC Client secret used to obtain access tokens.
|
# KYC Client secret used to obtain access tokens.
|
||||||
# KYC_OAUTH2_CLIENT_SECRET =
|
# KYC_OAUTH2_CLIENT_SECRET =
|
||||||
|
|
||||||
|
# Where to redirect clients after successful
|
||||||
|
# authorization?
|
||||||
|
# KYC_OAUTH_POST_URL = https://bank.com/
|
||||||
|
@ -102,6 +102,11 @@ struct TALER_EXCHANGEDB_Plugin *TEH_plugin;
|
|||||||
*/
|
*/
|
||||||
char *TEH_currency;
|
char *TEH_currency;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Our base URL.
|
||||||
|
*/
|
||||||
|
char *TEH_base_url;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Default timeout in seconds for HTTP requests.
|
* Default timeout in seconds for HTTP requests.
|
||||||
*/
|
*/
|
||||||
@ -134,6 +139,17 @@ static unsigned long long req_count;
|
|||||||
*/
|
*/
|
||||||
static unsigned long long req_max;
|
static unsigned long long req_max;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Context for all CURL operations (useful to the event loop)
|
||||||
|
*/
|
||||||
|
struct GNUNET_CURL_Context *TEH_curl_ctx;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Context for integrating #exchange_curl_ctx with the
|
||||||
|
* GNUnet event loop.
|
||||||
|
*/
|
||||||
|
static struct GNUNET_CURL_RescheduleContext *exchange_curl_rc;
|
||||||
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Signature of functions that handle operations on coins.
|
* Signature of functions that handle operations on coins.
|
||||||
@ -1203,6 +1219,19 @@ parse_kyc_oauth_cfg (void)
|
|||||||
return GNUNET_SYSERR;
|
return GNUNET_SYSERR;
|
||||||
}
|
}
|
||||||
TEH_kyc_config.details.oauth2.client_secret = s;
|
TEH_kyc_config.details.oauth2.client_secret = s;
|
||||||
|
|
||||||
|
if (GNUNET_OK !=
|
||||||
|
GNUNET_CONFIGURATION_get_value_string (TEH_cfg,
|
||||||
|
"exchange-kyc-oauth2",
|
||||||
|
"KYC_OAUTH2_POST_URL",
|
||||||
|
&s))
|
||||||
|
{
|
||||||
|
GNUNET_log_config_missing (GNUNET_ERROR_TYPE_ERROR,
|
||||||
|
"exchange-kyc-oauth2",
|
||||||
|
"KYC_OAUTH2_POST_URL");
|
||||||
|
return GNUNET_SYSERR;
|
||||||
|
}
|
||||||
|
TEH_kyc_config.details.oauth2.post_kyc_redirect_url = s;
|
||||||
return GNUNET_OK;
|
return GNUNET_OK;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -1301,6 +1330,26 @@ exchange_serve_process_config (void)
|
|||||||
"CURRENCY");
|
"CURRENCY");
|
||||||
return GNUNET_SYSERR;
|
return GNUNET_SYSERR;
|
||||||
}
|
}
|
||||||
|
if (GNUNET_OK !=
|
||||||
|
GNUNET_CONFIGURATION_get_value_string (TEH_cfg,
|
||||||
|
"exchange",
|
||||||
|
"BASE_URL",
|
||||||
|
&TEH_base_url))
|
||||||
|
{
|
||||||
|
GNUNET_log_config_missing (GNUNET_ERROR_TYPE_ERROR,
|
||||||
|
"exchange",
|
||||||
|
"BASE_URL");
|
||||||
|
return GNUNET_SYSERR;
|
||||||
|
}
|
||||||
|
if (! TALER_url_valid_charset (TEH_base_url))
|
||||||
|
{
|
||||||
|
GNUNET_log_config_invalid (GNUNET_ERROR_TYPE_ERROR,
|
||||||
|
"exchange",
|
||||||
|
"BASE_URL",
|
||||||
|
"invalid URL");
|
||||||
|
return GNUNET_SYSERR;
|
||||||
|
}
|
||||||
|
|
||||||
if (TEH_KYC_NONE != TEH_kyc_config.mode)
|
if (TEH_KYC_NONE != TEH_kyc_config.mode)
|
||||||
{
|
{
|
||||||
if (GNUNET_YES ==
|
if (GNUNET_YES ==
|
||||||
@ -1593,11 +1642,26 @@ do_shutdown (void *cls)
|
|||||||
mhd = TALER_MHD_daemon_stop ();
|
mhd = TALER_MHD_daemon_stop ();
|
||||||
TEH_resume_keys_requests (true);
|
TEH_resume_keys_requests (true);
|
||||||
TEH_reserves_get_cleanup ();
|
TEH_reserves_get_cleanup ();
|
||||||
|
TEH_kyc_proof_cleanup ();
|
||||||
if (NULL != mhd)
|
if (NULL != mhd)
|
||||||
MHD_stop_daemon (mhd);
|
MHD_stop_daemon (mhd);
|
||||||
TEH_WIRE_done ();
|
TEH_WIRE_done ();
|
||||||
TEH_keys_finished ();
|
TEH_keys_finished ();
|
||||||
TALER_EXCHANGEDB_plugin_unload (TEH_plugin);
|
if (NULL != TEH_plugin)
|
||||||
|
{
|
||||||
|
TALER_EXCHANGEDB_plugin_unload (TEH_plugin);
|
||||||
|
TEH_plugin = NULL;
|
||||||
|
}
|
||||||
|
if (NULL != TEH_curl_ctx)
|
||||||
|
{
|
||||||
|
GNUNET_CURL_fini (TEH_curl_ctx);
|
||||||
|
TEH_curl_ctx = NULL;
|
||||||
|
}
|
||||||
|
if (NULL != exchange_curl_rc)
|
||||||
|
{
|
||||||
|
GNUNET_CURL_gnunet_rc_destroy (exchange_curl_rc);
|
||||||
|
exchange_curl_rc = NULL;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
@ -1655,6 +1719,17 @@ run (void *cls,
|
|||||||
}
|
}
|
||||||
|
|
||||||
TEH_load_terms (TEH_cfg);
|
TEH_load_terms (TEH_cfg);
|
||||||
|
TEH_curl_ctx
|
||||||
|
= GNUNET_CURL_init (&GNUNET_CURL_gnunet_scheduler_reschedule,
|
||||||
|
&exchange_curl_rc);
|
||||||
|
if (NULL == TEH_curl_ctx)
|
||||||
|
{
|
||||||
|
GNUNET_break (0);
|
||||||
|
global_ret = EXIT_FAILURE;
|
||||||
|
GNUNET_SCHEDULER_shutdown ();
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
exchange_curl_rc = GNUNET_CURL_gnunet_rc_create (TEH_curl_ctx);
|
||||||
GNUNET_SCHEDULER_add_shutdown (&do_shutdown,
|
GNUNET_SCHEDULER_add_shutdown (&do_shutdown,
|
||||||
NULL);
|
NULL);
|
||||||
fh = TALER_MHD_bind (TEH_cfg,
|
fh = TALER_MHD_bind (TEH_cfg,
|
||||||
|
@ -105,6 +105,12 @@ struct TEH_KycOptions
|
|||||||
*/
|
*/
|
||||||
char *client_secret;
|
char *client_secret;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Where to redirect clients after the
|
||||||
|
* Web-based KYC process is done?
|
||||||
|
*/
|
||||||
|
char *post_kyc_redirect_url;
|
||||||
|
|
||||||
} oauth2;
|
} oauth2;
|
||||||
|
|
||||||
} details;
|
} details;
|
||||||
@ -162,11 +168,20 @@ extern struct TALER_EXCHANGEDB_Plugin *TEH_plugin;
|
|||||||
*/
|
*/
|
||||||
extern char *TEH_currency;
|
extern char *TEH_currency;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Our (externally visible) base URL.
|
||||||
|
*/
|
||||||
|
extern char *TEH_base_url;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Are we shutting down?
|
* Are we shutting down?
|
||||||
*/
|
*/
|
||||||
extern volatile bool MHD_terminating;
|
extern volatile bool MHD_terminating;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Context for all CURL operations (useful to the event loop)
|
||||||
|
*/
|
||||||
|
extern struct GNUNET_CURL_Context *TEH_curl_ctx;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @brief Struct describing an URL and the handler for it.
|
* @brief Struct describing an URL and the handler for it.
|
||||||
|
@ -381,7 +381,7 @@ TEH_handler_deposit (struct MHD_Connection *connection,
|
|||||||
sizeof (deposit));
|
sizeof (deposit));
|
||||||
deposit.coin.coin_pub = *coin_pub;
|
deposit.coin.coin_pub = *coin_pub;
|
||||||
{
|
{
|
||||||
int res;
|
enum GNUNET_GenericReturnValue res;
|
||||||
|
|
||||||
res = TALER_MHD_parse_json_data (connection,
|
res = TALER_MHD_parse_json_data (connection,
|
||||||
root,
|
root,
|
||||||
|
@ -1345,7 +1345,7 @@ get_date_string (struct GNUNET_TIME_Absolute at,
|
|||||||
* @param[in,out] response the response to modify
|
* @param[in,out] response the response to modify
|
||||||
* @return #GNUNET_OK on success
|
* @return #GNUNET_OK on success
|
||||||
*/
|
*/
|
||||||
static int
|
static enum GNUNET_GenericReturnValue
|
||||||
setup_general_response_headers (const struct TEH_KeyStateHandle *ksh,
|
setup_general_response_headers (const struct TEH_KeyStateHandle *ksh,
|
||||||
struct MHD_Response *response)
|
struct MHD_Response *response)
|
||||||
{
|
{
|
||||||
|
@ -143,12 +143,31 @@ TEH_handler_kyc_check (
|
|||||||
return res;
|
return res;
|
||||||
if (! kcc.kyc.ok)
|
if (! kcc.kyc.ok)
|
||||||
{
|
{
|
||||||
|
char *url;
|
||||||
|
char *redirect_uri;
|
||||||
|
char *redirect_uri_encoded;
|
||||||
|
|
||||||
GNUNET_assert (TEH_KYC_OAUTH2 == TEH_kyc_config.mode);
|
GNUNET_assert (TEH_KYC_OAUTH2 == TEH_kyc_config.mode);
|
||||||
return TALER_MHD_REPLY_JSON_PACK (
|
GNUNET_asprintf (&redirect_uri,
|
||||||
|
"%s/kyc-proof/%llu",
|
||||||
|
TEH_base_url,
|
||||||
|
payment_target_uuid);
|
||||||
|
redirect_uri_encoded = TALER_urlencode (redirect_uri);
|
||||||
|
GNUNET_free (redirect_uri);
|
||||||
|
GNUNET_asprintf (&url,
|
||||||
|
"%s/login?client_id=%s&redirect_uri=%s",
|
||||||
|
TEH_kyc_config.details.oauth2.url,
|
||||||
|
TEH_kyc_config.details.oauth2.client_id,
|
||||||
|
redirect_uri_encoded);
|
||||||
|
GNUNET_free (redirect_uri_encoded);
|
||||||
|
|
||||||
|
res = TALER_MHD_REPLY_JSON_PACK (
|
||||||
rc->connection,
|
rc->connection,
|
||||||
MHD_HTTP_ACCEPTED,
|
MHD_HTTP_ACCEPTED,
|
||||||
GNUNET_JSON_pack_string ("kyc_url",
|
GNUNET_JSON_pack_string ("kyc_url",
|
||||||
TEH_kyc_config.details.oauth2.url));
|
url));
|
||||||
|
GNUNET_free (url);
|
||||||
|
return res;
|
||||||
}
|
}
|
||||||
{
|
{
|
||||||
struct TALER_ExchangePublicKeyP pub;
|
struct TALER_ExchangePublicKeyP pub;
|
||||||
|
@ -36,9 +36,99 @@
|
|||||||
struct KycProofContext
|
struct KycProofContext
|
||||||
{
|
{
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Kept in a DLL while suspended.
|
||||||
|
*/
|
||||||
|
struct KycProofContext *next;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Kept in a DLL while suspended.
|
||||||
|
*/
|
||||||
|
struct KycProofContext *prev;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Details about the connection we are processing.
|
||||||
|
*/
|
||||||
|
struct TEH_RequestContext *rc;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Handle for the OAuth 2.0 CURL request.
|
||||||
|
*/
|
||||||
|
struct GNUNET_CURL_Job *job;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* OAuth 2.0 authorization code.
|
||||||
|
*/
|
||||||
|
const char *authorization_code;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* OAuth 2.0 token URL we are using for the
|
||||||
|
* request.
|
||||||
|
*/
|
||||||
|
char *token_url;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Body of the POST request.
|
||||||
|
*/
|
||||||
|
char *post_body;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Payment target this is about.
|
||||||
|
*/
|
||||||
|
unsigned long long payment_target_uuid;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* HTTP response to return.
|
||||||
|
*/
|
||||||
|
struct MHD_Response *response;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 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.
|
||||||
|
*/
|
||||||
|
enum GNUNET_GenericReturnValue suspended;
|
||||||
|
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Contexts are kept in a DLL while suspended.
|
||||||
|
*/
|
||||||
|
static struct KycProofContext *kpc_head;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Contexts are kept in a DLL while suspended.
|
||||||
|
*/
|
||||||
|
static struct KycProofContext *kpc_tail;
|
||||||
|
|
||||||
|
|
||||||
|
void
|
||||||
|
TEH_kyc_proof_cleanup (void)
|
||||||
|
{
|
||||||
|
struct KycProofContext *kpc;
|
||||||
|
|
||||||
|
while (NULL != (kpc = kpc_head))
|
||||||
|
{
|
||||||
|
if (NULL != kpc->job)
|
||||||
|
{
|
||||||
|
GNUNET_CURL_job_cancel (kpc->job);
|
||||||
|
kpc->job = NULL;
|
||||||
|
}
|
||||||
|
GNUNET_CONTAINER_DLL_remove (kpc_head,
|
||||||
|
kpc_tail,
|
||||||
|
kpc);
|
||||||
|
kpc->suspended = GNUNET_NO;
|
||||||
|
MHD_resume_connection (kpc->rc->connection);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Function implementing database transaction to check proof's KYC status.
|
* Function implementing database transaction to check proof's KYC status.
|
||||||
* Runs the transaction logic; IF it returns a non-error code, the transaction
|
* Runs the transaction logic; IF it returns a non-error code, the transaction
|
||||||
@ -54,14 +144,185 @@ struct KycProofContext
|
|||||||
* @return transaction status
|
* @return transaction status
|
||||||
*/
|
*/
|
||||||
static enum GNUNET_DB_QueryStatus
|
static enum GNUNET_DB_QueryStatus
|
||||||
proof_kyc_check (void *cls,
|
persist_kyc_ok (void *cls,
|
||||||
struct MHD_Connection *connection,
|
struct MHD_Connection *connection,
|
||||||
MHD_RESULT *mhd_ret)
|
MHD_RESULT *mhd_ret)
|
||||||
{
|
{
|
||||||
struct KycProofContext *kpc = cls;
|
struct KycProofContext *kpc = cls;
|
||||||
|
|
||||||
(void) kpc; // FIXME: do work here!
|
return TEH_plugin->set_kyc_ok (TEH_plugin->cls,
|
||||||
return -2;
|
kpc->payment_target_uuid);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
/**
|
||||||
|
* After we are done with the CURL interaction we
|
||||||
|
* need to update our database state.
|
||||||
|
*
|
||||||
|
* @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_login_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:
|
||||||
|
{
|
||||||
|
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 ()
|
||||||
|
};
|
||||||
|
|
||||||
|
{
|
||||||
|
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;
|
||||||
|
MHD_resume_connection (kpc->rc->connection);
|
||||||
|
TALER_MHD_daemon_trigger ();
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
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;
|
||||||
|
MHD_resume_connection (kpc->rc->connection);
|
||||||
|
TALER_MHD_daemon_trigger ();
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* TODO: Here we might want to keep something to persist in the DB, and
|
||||||
|
possibly use the access_token to download information we should
|
||||||
|
persist; then continue! */
|
||||||
|
|
||||||
|
MHD_resume_connection (kpc->rc->connection);
|
||||||
|
TALER_MHD_daemon_trigger ();
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
default:
|
||||||
|
{
|
||||||
|
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;
|
||||||
|
MHD_resume_connection (kpc->rc->connection);
|
||||||
|
TALER_MHD_daemon_trigger ();
|
||||||
|
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;
|
||||||
|
MHD_resume_connection (kpc->rc->connection);
|
||||||
|
TALER_MHD_daemon_trigger ();
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Function called to clean up a context.
|
||||||
|
*
|
||||||
|
* @param rc request context
|
||||||
|
*/
|
||||||
|
static void
|
||||||
|
clean_kpc (struct TEH_RequestContext *rc)
|
||||||
|
{
|
||||||
|
struct KycProofContext *kpc = rc->rh_ctx;
|
||||||
|
|
||||||
|
if (NULL != kpc->job)
|
||||||
|
{
|
||||||
|
GNUNET_CURL_job_cancel (kpc->job);
|
||||||
|
kpc->job = 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);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
@ -70,44 +331,188 @@ TEH_handler_kyc_proof (
|
|||||||
struct TEH_RequestContext *rc,
|
struct TEH_RequestContext *rc,
|
||||||
const char *const args[])
|
const char *const args[])
|
||||||
{
|
{
|
||||||
struct KycProofContext kpc;
|
struct KycProofContext *kpc = rc->rh_ctx;
|
||||||
MHD_RESULT res;
|
|
||||||
enum GNUNET_GenericReturnValue ret;
|
|
||||||
unsigned long long payment_target_uuid;
|
|
||||||
char dummy;
|
|
||||||
|
|
||||||
if (1 !=
|
if (NULL == kpc)
|
||||||
sscanf (args[0],
|
{ /* first time */
|
||||||
"%llu%c",
|
char dummy;
|
||||||
&payment_target_uuid,
|
|
||||||
&dummy))
|
kpc = GNUNET_new (struct KycProofContext);
|
||||||
{
|
kpc->rc = rc;
|
||||||
GNUNET_break_op (0);
|
rc->rh_ctx = kpc;
|
||||||
return TALER_MHD_reply_with_error (rc->connection,
|
rc->rh_cleaner = &clean_kpc;
|
||||||
MHD_HTTP_BAD_REQUEST,
|
|
||||||
TALER_EC_GENERIC_PARAMETER_MALFORMED,
|
if (1 !=
|
||||||
"payment_target_uuid");
|
sscanf (args[0],
|
||||||
|
"%llu%c",
|
||||||
|
&kpc->payment_target_uuid,
|
||||||
|
&dummy))
|
||||||
|
{
|
||||||
|
GNUNET_break_op (0);
|
||||||
|
return TALER_MHD_reply_with_error (rc->connection,
|
||||||
|
MHD_HTTP_BAD_REQUEST,
|
||||||
|
TALER_EC_GENERIC_PARAMETER_MALFORMED,
|
||||||
|
"payment_target_uuid");
|
||||||
|
}
|
||||||
|
kpc->authorization_code
|
||||||
|
= MHD_lookup_connection_value (rc->connection,
|
||||||
|
MHD_GET_ARGUMENT_KIND,
|
||||||
|
"code");
|
||||||
|
if (NULL == kpc->authorization_code)
|
||||||
|
{
|
||||||
|
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);
|
||||||
|
|
||||||
|
{
|
||||||
|
CURL *eh;
|
||||||
|
|
||||||
|
eh = curl_easy_init ();
|
||||||
|
if (NULL == eh)
|
||||||
|
{
|
||||||
|
GNUNET_break (0);
|
||||||
|
return TALER_MHD_reply_with_error (rc->connection,
|
||||||
|
MHD_HTTP_INTERNAL_SERVER_ERROR,
|
||||||
|
TALER_EC_GENERIC_ALLOCATION_FAILURE,
|
||||||
|
"curl_easy_init");
|
||||||
|
}
|
||||||
|
GNUNET_asprintf (&kpc->token_url,
|
||||||
|
"%s/token",
|
||||||
|
TEH_kyc_config.details.oauth2.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));
|
||||||
|
{
|
||||||
|
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/login?client_id=%s",
|
||||||
|
TEH_kyc_config.details.oauth2.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);
|
||||||
|
}
|
||||||
|
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;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if (1 || (TEH_KYC_NONE == TEH_kyc_config.mode))
|
if (NULL != kpc->response)
|
||||||
return TALER_MHD_reply_static (
|
{
|
||||||
rc->connection,
|
/* handle _failed_ resumed cases */
|
||||||
MHD_HTTP_NO_CONTENT,
|
return MHD_queue_response (rc->connection,
|
||||||
NULL,
|
kpc->response_code,
|
||||||
NULL,
|
kpc->response);
|
||||||
0);
|
}
|
||||||
ret = TEH_DB_run_transaction (rc->connection,
|
|
||||||
"check proof kyc",
|
/* _successfully_ resumed case */
|
||||||
&res,
|
{
|
||||||
&proof_kyc_check,
|
MHD_RESULT res;
|
||||||
&kpc);
|
enum GNUNET_GenericReturnValue ret;
|
||||||
if (GNUNET_SYSERR == ret)
|
|
||||||
|
ret = TEH_DB_run_transaction (kpc->rc->connection,
|
||||||
|
"check proof kyc",
|
||||||
|
&res,
|
||||||
|
&persist_kyc_ok,
|
||||||
|
kpc);
|
||||||
|
if (GNUNET_SYSERR == ret)
|
||||||
|
return res;
|
||||||
|
}
|
||||||
|
|
||||||
|
{
|
||||||
|
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;
|
return res;
|
||||||
return TALER_MHD_REPLY_JSON_PACK (
|
}
|
||||||
rc->connection,
|
|
||||||
MHD_HTTP_OK,
|
|
||||||
GNUNET_JSON_pack_uint64 ("42",
|
|
||||||
42));
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
@ -25,6 +25,14 @@
|
|||||||
#include "taler-exchange-httpd.h"
|
#include "taler-exchange-httpd.h"
|
||||||
|
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Shutdown kyc-proof subsystem. Resumes all suspended long-polling clients
|
||||||
|
* and cleans up data structures.
|
||||||
|
*/
|
||||||
|
void
|
||||||
|
TEH_kyc_proof_cleanup (void);
|
||||||
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Handle a "/kyc-proof" request.
|
* Handle a "/kyc-proof" request.
|
||||||
*
|
*
|
||||||
|
@ -360,6 +360,12 @@ prepare_statements (struct PostgresClosure *pg)
|
|||||||
" LIMIT 1;",
|
" LIMIT 1;",
|
||||||
1),
|
1),
|
||||||
#if FIXME_DD23
|
#if FIXME_DD23
|
||||||
|
/* Used in #postgres_set_kyc_ok() */
|
||||||
|
GNUNET_PQ_make_prepare ("set_kyc_ok",
|
||||||
|
"UPDATE wire_targets"
|
||||||
|
" SET kyc_ok=TRUE"
|
||||||
|
" WHERE wire_target_serial_id=$1",
|
||||||
|
1),
|
||||||
/* Used in #postgres_get_kyc_status() */
|
/* Used in #postgres_get_kyc_status() */
|
||||||
GNUNET_PQ_make_prepare ("get_kyc_status",
|
GNUNET_PQ_make_prepare ("get_kyc_status",
|
||||||
"SELECT"
|
"SELECT"
|
||||||
@ -3555,6 +3561,31 @@ postgres_reserves_get (void *cls,
|
|||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Set the KYC status to "OK" for a bank account.
|
||||||
|
*
|
||||||
|
* @param cls the @e cls of this struct with the plugin-specific state
|
||||||
|
* @param payment_target_uuid which account has been checked
|
||||||
|
* @param ... possibly additional data to persist (TODO)
|
||||||
|
* @return transaction status
|
||||||
|
*/
|
||||||
|
static enum GNUNET_DB_QueryStatus
|
||||||
|
postgres_set_kyc_ok (void *cls,
|
||||||
|
uint64_t payment_target_uuid,
|
||||||
|
...)
|
||||||
|
{
|
||||||
|
struct PostgresClosure *pg = cls;
|
||||||
|
struct GNUNET_PQ_QueryParam params[] = {
|
||||||
|
GNUNET_PQ_query_param_uint64 (&payment_target_uuid),
|
||||||
|
GNUNET_PQ_query_param_end
|
||||||
|
};
|
||||||
|
|
||||||
|
return GNUNET_PQ_eval_prepared_non_select (pg->conn,
|
||||||
|
"set_kyc_ok",
|
||||||
|
params);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Get the KYC status for a bank account.
|
* Get the KYC status for a bank account.
|
||||||
*
|
*
|
||||||
@ -11261,6 +11292,7 @@ libtaler_plugin_exchangedb_postgres_init (void *cls)
|
|||||||
plugin->iterate_auditor_denominations =
|
plugin->iterate_auditor_denominations =
|
||||||
&postgres_iterate_auditor_denominations;
|
&postgres_iterate_auditor_denominations;
|
||||||
plugin->reserves_get = &postgres_reserves_get;
|
plugin->reserves_get = &postgres_reserves_get;
|
||||||
|
plugin->set_kyc_ok = &postgres_set_kyc_ok;
|
||||||
plugin->get_kyc_status = &postgres_get_kyc_status;
|
plugin->get_kyc_status = &postgres_get_kyc_status;
|
||||||
plugin->select_kyc_status = &postgres_select_kyc_status;
|
plugin->select_kyc_status = &postgres_select_kyc_status;
|
||||||
plugin->inselect_wallet_kyc_status = &postgres_inselect_wallet_kyc_status;
|
plugin->inselect_wallet_kyc_status = &postgres_inselect_wallet_kyc_status;
|
||||||
|
@ -59,7 +59,7 @@ struct TALER_CURL_PostContext
|
|||||||
* @param body JSON body to add to @e ctx
|
* @param body JSON body to add to @e ctx
|
||||||
* @return #GNUNET_OK on success #GNUNET_SYSERR on failure
|
* @return #GNUNET_OK on success #GNUNET_SYSERR on failure
|
||||||
*/
|
*/
|
||||||
int
|
enum GNUNET_GenericReturnValue
|
||||||
TALER_curl_easy_post (struct TALER_CURL_PostContext *ctx,
|
TALER_curl_easy_post (struct TALER_CURL_PostContext *ctx,
|
||||||
CURL *eh,
|
CURL *eh,
|
||||||
const json_t *body);
|
const json_t *body);
|
||||||
|
@ -2360,6 +2360,20 @@ struct TALER_EXCHANGEDB_Plugin
|
|||||||
struct TALER_EXCHANGEDB_KycStatus *kyc);
|
struct TALER_EXCHANGEDB_KycStatus *kyc);
|
||||||
|
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Set the KYC status to "OK" for a bank account.
|
||||||
|
*
|
||||||
|
* @param cls the @e cls of this struct with the plugin-specific state
|
||||||
|
* @param payment_target_uuid which account has been checked
|
||||||
|
* @param ... possibly additional data to persist (TODO)
|
||||||
|
* @return transaction status
|
||||||
|
*/
|
||||||
|
enum GNUNET_DB_QueryStatus
|
||||||
|
(*set_kyc_ok)(void *cls,
|
||||||
|
uint64_t payment_target_uuid,
|
||||||
|
...);
|
||||||
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Get the KYC status for a bank account.
|
* Get the KYC status for a bank account.
|
||||||
*
|
*
|
||||||
|
@ -82,7 +82,7 @@ struct TALER_EXCHANGE_LinkHandle
|
|||||||
* @param[out] pub where to return the public key for the coin
|
* @param[out] pub where to return the public key for the coin
|
||||||
* @return #GNUNET_OK on success, #GNUNET_SYSERR on error
|
* @return #GNUNET_OK on success, #GNUNET_SYSERR on error
|
||||||
*/
|
*/
|
||||||
static int
|
static enum GNUNET_GenericReturnValue
|
||||||
parse_link_coin (const struct TALER_EXCHANGE_LinkHandle *lh,
|
parse_link_coin (const struct TALER_EXCHANGE_LinkHandle *lh,
|
||||||
const json_t *json,
|
const json_t *json,
|
||||||
uint32_t coin_num,
|
uint32_t coin_num,
|
||||||
@ -175,7 +175,7 @@ parse_link_coin (const struct TALER_EXCHANGE_LinkHandle *lh,
|
|||||||
* @param json json reply with the data for one coin
|
* @param json json reply with the data for one coin
|
||||||
* @return #GNUNET_OK on success, #GNUNET_SYSERR on error
|
* @return #GNUNET_OK on success, #GNUNET_SYSERR on error
|
||||||
*/
|
*/
|
||||||
static int
|
static enum GNUNET_GenericReturnValue
|
||||||
parse_link_ok (struct TALER_EXCHANGE_LinkHandle *lh,
|
parse_link_ok (struct TALER_EXCHANGE_LinkHandle *lh,
|
||||||
const json_t *json)
|
const json_t *json)
|
||||||
{
|
{
|
||||||
|
Loading…
Reference in New Issue
Block a user