summaryrefslogtreecommitdiff
path: root/src
diff options
context:
space:
mode:
authorChristian Grothoff <christian@grothoff.org>2021-11-09 15:39:31 +0100
committerChristian Grothoff <christian@grothoff.org>2021-11-09 15:39:31 +0100
commita9b2140b1ece806847aa45a6b95a959c9ddaa7bf (patch)
tree1e99fa21fa001dac1aa9934830c0fd3f2c84b26a /src
parenta79cc16067285cee7de72d889eaf8152cc17739d (diff)
downloadexchange-a9b2140b1ece806847aa45a6b95a959c9ddaa7bf.tar.gz
exchange-a9b2140b1ece806847aa45a6b95a959c9ddaa7bf.tar.bz2
exchange-a9b2140b1ece806847aa45a6b95a959c9ddaa7bf.zip
get first KYC test to pass
Diffstat (limited to 'src')
-rw-r--r--src/exchange/exchange.conf6
-rw-r--r--src/exchange/taler-exchange-httpd_kyc-proof.c43
-rw-r--r--src/include/taler_exchange_service.h5
-rw-r--r--src/lib/exchange_api_kyc_proof.c34
-rw-r--r--src/testing/test_exchange_api.c4
-rw-r--r--src/testing/test_kyc_api.c32
-rw-r--r--src/testing/test_kyc_api.conf16
-rw-r--r--src/testing/testing_api_cmd_kyc_proof.c12
-rw-r--r--src/testing/testing_api_cmd_oauth.c151
9 files changed, 229 insertions, 74 deletions
diff --git a/src/exchange/exchange.conf b/src/exchange/exchange.conf
index 3bcea08fb..391dc9344 100644
--- a/src/exchange/exchange.conf
+++ b/src/exchange/exchange.conf
@@ -90,7 +90,9 @@ KYC_MODE = NONE
# Balance threshold above which wallets are told
# to undergo a KYC check at the exchange. Optional,
# if not given there is no limit.
-# KYC_WALLET_BALANCE_LIMIT = 150:CURRENCY
+# KYC_WALLET_BALANCE_LIMIT = CURRENCY:150
+#
+# KYC_WITHDRAW_PERIOD = 1 month
[exchange-kyc-oauth2]
@@ -105,4 +107,4 @@ KYC_MODE = NONE
# Where to redirect clients after successful
# authorization?
-# KYC_OAUTH_POST_URL = https://bank.com/
+# KYC_OAUTH2_POST_URL = https://bank.com/
diff --git a/src/exchange/taler-exchange-httpd_kyc-proof.c b/src/exchange/taler-exchange-httpd_kyc-proof.c
index 842e5dfd2..fdf5ade54 100644
--- a/src/exchange/taler-exchange-httpd_kyc-proof.c
+++ b/src/exchange/taler-exchange-httpd_kyc-proof.c
@@ -108,6 +108,24 @@ static struct KycProofContext *kpc_head;
static struct KycProofContext *kpc_tail;
+/**
+ * Resume processing the @a kpc request.
+ *
+ * @param kpc request to resume
+ */
+static void
+kpc_resume (struct KycProofContext *kpc)
+{
+ GNUNET_assert (GNUNET_YES == kpc->suspended);
+ kpc->suspended = GNUNET_NO;
+ GNUNET_CONTAINER_DLL_remove (kpc_head,
+ kpc_tail,
+ kpc);
+ MHD_resume_connection (kpc->rc->connection);
+ TALER_MHD_daemon_trigger ();
+}
+
+
void
TEH_kyc_proof_cleanup (void)
{
@@ -120,11 +138,7 @@ TEH_kyc_proof_cleanup (void)
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);
+ kpc_resume (kpc);
}
}
@@ -210,8 +224,7 @@ handle_curl_login_finished (void *cls,
"Unexpected response from KYC gateway");
kpc->response_code
= MHD_HTTP_BAD_GATEWAY;
- MHD_resume_connection (kpc->rc->connection);
- TALER_MHD_daemon_trigger ();
+ kpc_resume (kpc);
return;
}
}
@@ -225,8 +238,7 @@ handle_curl_login_finished (void *cls,
"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 ();
+ kpc_resume (kpc);
return;
}
@@ -234,8 +246,7 @@ handle_curl_login_finished (void *cls,
possibly use the access_token to download information we should
persist; then continue! */
- MHD_resume_connection (kpc->rc->connection);
- TALER_MHD_daemon_trigger ();
+ kpc_resume (kpc);
return;
}
default:
@@ -268,8 +279,7 @@ handle_curl_login_finished (void *cls,
"Unexpected response from KYC gateway");
kpc->response_code
= MHD_HTTP_BAD_GATEWAY;
- MHD_resume_connection (kpc->rc->connection);
- TALER_MHD_daemon_trigger ();
+ kpc_resume (kpc);
return;
}
}
@@ -292,8 +302,7 @@ handle_curl_login_finished (void *cls,
GNUNET_free (reply);
}
kpc->response_code = MHD_HTTP_FORBIDDEN;
- MHD_resume_connection (kpc->rc->connection);
- TALER_MHD_daemon_trigger ();
+ kpc_resume (kpc);
}
break;
}
@@ -387,7 +396,7 @@ TEH_handler_kyc_proof (
"curl_easy_init");
}
GNUNET_asprintf (&kpc->token_url,
- "%s/token",
+ "%stoken",
TEH_kyc_config.details.oauth2.url);
GNUNET_assert (CURLE_OK ==
curl_easy_setopt (eh,
@@ -411,7 +420,7 @@ TEH_handler_kyc_proof (
char *request_uri;
GNUNET_asprintf (&request_uri,
- "%s/login?client_id=%s",
+ "%slogin?client_id=%s",
TEH_kyc_config.details.oauth2.url,
TEH_kyc_config.details.oauth2.client_id);
redirect_uri = curl_easy_escape (eh,
diff --git a/src/include/taler_exchange_service.h b/src/include/taler_exchange_service.h
index 54fca65cb..09c50b17e 100644
--- a/src/include/taler_exchange_service.h
+++ b/src/include/taler_exchange_service.h
@@ -2170,11 +2170,6 @@ struct TALER_EXCHANGE_KycProofResponse
*/
unsigned int http_status;
- /**
- * Taler error code, if any.
- */
- enum TALER_ErrorCode ec;
-
union
{
diff --git a/src/lib/exchange_api_kyc_proof.c b/src/lib/exchange_api_kyc_proof.c
index 802152277..f8e84d7ca 100644
--- a/src/lib/exchange_api_kyc_proof.c
+++ b/src/lib/exchange_api_kyc_proof.c
@@ -75,15 +75,16 @@ struct TALER_EXCHANGE_KycProofHandle
*
* @param cls the `struct TALER_EXCHANGE_KycProofHandle`
* @param response_code HTTP response code, 0 on error
- * @param response parsed JSON result, NULL on error
+ * @param body response body
+ * @param body_size number of bytes in @a body
*/
static void
handle_kyc_proof_finished (void *cls,
long response_code,
- const void *response)
+ const void *body,
+ size_t body_size)
{
struct TALER_EXCHANGE_KycProofHandle *kph = cls;
- const json_t *j = response;
struct TALER_EXCHANGE_KycProofResponse kpr = {
.http_status = (unsigned int) response_code
};
@@ -92,9 +93,8 @@ handle_kyc_proof_finished (void *cls,
switch (response_code)
{
case 0:
- kpr.ec = TALER_EC_GENERIC_INVALID_RESPONSE;
break;
- case MHD_HTTP_FOUND:
+ case MHD_HTTP_SEE_OTHER:
{
char *redirect_url;
@@ -106,34 +106,29 @@ handle_kyc_proof_finished (void *cls,
break;
}
case MHD_HTTP_BAD_REQUEST:
- kpr.ec = TALER_JSON_get_error_code (j);
/* This should never happen, either us or the exchange is buggy
(or API version conflict); just pass JSON reply to the application */
break;
case MHD_HTTP_UNAUTHORIZED:
- kpr.ec = TALER_JSON_get_error_code (j);
+ break;
+ case MHD_HTTP_FORBIDDEN:
break;
case MHD_HTTP_NOT_FOUND:
- kpr.ec = TALER_JSON_get_error_code (j);
break;
case MHD_HTTP_BAD_GATEWAY:
- kpr.ec = TALER_JSON_get_error_code (j);
/* Server had an internal issue; we should retry, but this API
leaves this to the application */
break;
case MHD_HTTP_GATEWAY_TIMEOUT:
- kpr.ec = TALER_JSON_get_error_code (j);
/* Server had an internal issue; we should retry, but this API
leaves this to the application */
break;
default:
/* unexpected response code */
GNUNET_break_op (0);
- kpr.ec = TALER_JSON_get_error_code (j);
GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
- "Unexpected response code %u/%d for exchange kyc_proof\n",
- (unsigned int) response_code,
- (int) kpr.ec);
+ "Unexpected response code %u for exchange kyc_proof\n",
+ (unsigned int) response_code);
break;
}
kph->cb (kph->cb_cls,
@@ -187,16 +182,17 @@ TALER_EXCHANGE_kyc_proof (struct TALER_EXCHANGE_Handle *exchange,
return NULL;
}
/* disable location following, we want to learn the
- result of a 302 redirect! */
+ result of a 303 redirect! */
GNUNET_assert (CURLE_OK ==
curl_easy_setopt (kph->eh,
CURLOPT_FOLLOWLOCATION,
0L));
ctx = TEAH_handle_to_context (exchange);
- kph->job = GNUNET_CURL_job_add_with_ct_json (ctx,
- kph->eh,
- &handle_kyc_proof_finished,
- kph);
+ kph->job = GNUNET_CURL_job_add_raw (ctx,
+ kph->eh,
+ NULL,
+ &handle_kyc_proof_finished,
+ kph);
return kph;
}
diff --git a/src/testing/test_exchange_api.c b/src/testing/test_exchange_api.c
index c5544637b..72968c256 100644
--- a/src/testing/test_exchange_api.c
+++ b/src/testing/test_exchange_api.c
@@ -343,7 +343,7 @@ run (void *cls,
/* Try resolving a deposit's WTID for a failed deposit.
* As the deposit failed, the answer should be that the
* exchange does NOT know about the deposit.
- *///
+ */
TALER_TESTING_cmd_track_transaction ("deposit-wtid-failing",
"deposit-double-2",
0,
@@ -352,7 +352,7 @@ run (void *cls,
/* Try resolving an undefined (all zeros) WTID; this
* should fail as obviously the exchange didn't use that
* WTID value for any transaction.
- *///
+ */
TALER_TESTING_cmd_track_transfer_empty ("wire-deposit-failing",
NULL,
MHD_HTTP_NOT_FOUND),
diff --git a/src/testing/test_kyc_api.c b/src/testing/test_kyc_api.c
index ea2964958..b1a43df56 100644
--- a/src/testing/test_kyc_api.c
+++ b/src/testing/test_kyc_api.c
@@ -66,7 +66,7 @@ static struct TALER_TESTING_BankConfiguration bc;
*/
#define CMD_EXEC_AGGREGATOR(label) \
TALER_TESTING_cmd_sleep (label "-sleep", 1), \
- TALER_TESTING_cmd_exec_aggregator /*_with_kyc*/ (label, CONFIG_FILE), \
+ TALER_TESTING_cmd_exec_aggregator_with_kyc (label, CONFIG_FILE), \
TALER_TESTING_cmd_exec_transfer (label, CONFIG_FILE)
/**
@@ -118,11 +118,39 @@ run (void *cls,
GNUNET_TIME_UNIT_ZERO,
"EUR:5",
MHD_HTTP_OK),
+ TALER_TESTING_cmd_track_transaction (
+ "track-deposit",
+ "deposit-simple",
+ 0,
+ MHD_HTTP_ACCEPTED,
+ NULL),
TALER_TESTING_cmd_end ()
};
struct TALER_TESTING_Command track[] = {
- CMD_EXEC_AGGREGATOR ("run-aggregator"),
+ CMD_EXEC_AGGREGATOR ("run-aggregator-before-kyc"),
+ TALER_TESTING_cmd_check_bank_empty ("check_bank_empty-no-kyc"),
+ TALER_TESTING_cmd_check_kyc_get ("check-kyc-deposit",
+ "track-deposit",
+ MHD_HTTP_ACCEPTED),
+ TALER_TESTING_cmd_proof_kyc ("proof-kyc-no-service",
+ "track-deposit",
+ "bad",
+ "state",
+ MHD_HTTP_BAD_GATEWAY),
+ TALER_TESTING_cmd_oauth ("start-oauth-service",
+ 6666),
+ TALER_TESTING_cmd_proof_kyc ("proof-kyc-fail",
+ "track-deposit",
+ "bad",
+ "state",
+ MHD_HTTP_FORBIDDEN),
+ TALER_TESTING_cmd_proof_kyc ("proof-kyc-fail",
+ "track-deposit",
+ "pass",
+ "state",
+ MHD_HTTP_SEE_OTHER),
+ CMD_EXEC_AGGREGATOR ("run-aggregator-after-kyc"),
TALER_TESTING_cmd_check_bank_transfer (
"check_bank_transfer-499c",
ec.exchange_url,
diff --git a/src/testing/test_kyc_api.conf b/src/testing/test_kyc_api.conf
index 03a5e2453..105ee3b26 100644
--- a/src/testing/test_kyc_api.conf
+++ b/src/testing/test_kyc_api.conf
@@ -45,6 +45,22 @@ DB = postgres
# exchange (or the twister) is actually listening.
BASE_URL = "http://localhost:8081/"
+
+KYC_MODE = OAUTH2
+
+KYC_WALLET_BALANCE_LIMIT = EUR:1
+
+KYC_WITHDRAW_PERIOD = "31 days"
+
+KYC_WITHDRAW_LIMIT = EUR:150
+
+[exchange-kyc-oauth2]
+
+KYC_OAUTH2_URL = http://localhost:6666/
+KYC_OAUTH2_CLIENT_ID = taler-exchange
+KYC_OAUTH2_CLIENT_SECRET = exchange-secret
+KYC_OAUTH2_POST_URL = http://example.com/
+
[exchangedb-postgres]
CONFIG = "postgres:///talercheck"
diff --git a/src/testing/testing_api_cmd_kyc_proof.c b/src/testing/testing_api_cmd_kyc_proof.c
index bd6162698..fdd3affdc 100644
--- a/src/testing/testing_api_cmd_kyc_proof.c
+++ b/src/testing/testing_api_cmd_kyc_proof.c
@@ -89,9 +89,8 @@ proof_kyc_cb (void *cls,
if (kcg->expected_response_code != kpr->http_status)
{
GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
- "Unexpected response code %u/%d to command %s in %s:%u\n",
+ "Unexpected response code %u to command %s in %s:%u\n",
kpr->http_status,
- (int) kpr->ec,
cmd->label,
__FILE__,
__LINE__);
@@ -100,11 +99,18 @@ proof_kyc_cb (void *cls,
}
switch (kpr->http_status)
{
- case MHD_HTTP_FOUND:
+ case MHD_HTTP_SEE_OTHER:
kcg->redirect_url = GNUNET_strdup (kpr->details.found.redirect_url);
break;
+ case MHD_HTTP_FORBIDDEN:
+ break;
+ case MHD_HTTP_BAD_GATEWAY:
+ break;
default:
GNUNET_break (0);
+ GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
+ "Unexpected response code %u to /kyc-proof\n",
+ kpr->http_status);
break;
}
TALER_TESTING_interpreter_next (kcg->is);
diff --git a/src/testing/testing_api_cmd_oauth.c b/src/testing/testing_api_cmd_oauth.c
index 6cfad32bc..b71cc8386 100644
--- a/src/testing/testing_api_cmd_oauth.c
+++ b/src/testing/testing_api_cmd_oauth.c
@@ -46,6 +46,76 @@ struct OAuthState
};
+struct RequestCtx
+{
+ struct MHD_PostProcessor *pp;
+ char *code;
+ char *client_id;
+ char *redirect_uri;
+ char *client_secret;
+};
+
+
+static void
+append (char **target,
+ const char *data,
+ size_t size)
+{
+ char *tmp;
+
+ if (NULL == *target)
+ {
+ *target = GNUNET_strndup (data,
+ size);
+ return;
+ }
+ GNUNET_asprintf (&tmp,
+ "%s%.*s",
+ *target,
+ (int) size,
+ data);
+ GNUNET_free (*target);
+ *target = tmp;
+}
+
+
+static enum MHD_Result
+handle_post (void *cls,
+ enum MHD_ValueKind kind,
+ const char *key,
+ const char *filename,
+ const char *content_type,
+ const char *transfer_encoding,
+ const char *data,
+ uint64_t off,
+ size_t size)
+{
+ struct RequestCtx *rc = cls;
+
+ if (0 == strcmp (key,
+ "code"))
+ append (&rc->code,
+ data,
+ size);
+ if (0 == strcmp (key,
+ "client_id"))
+ append (&rc->client_id,
+ data,
+ size);
+ if (0 == strcmp (key,
+ "redirect_uri"))
+ append (&rc->redirect_uri,
+ data,
+ size);
+ if (0 == strcmp (key,
+ "client_secret"))
+ append (&rc->client_secret,
+ data,
+ size);
+ return MHD_YES;
+}
+
+
/**
* A client has requested the given url using the given method
* (#MHD_HTTP_METHOD_GET, #MHD_HTTP_METHOD_PUT,
@@ -95,38 +165,52 @@ handler_cb (void *cls,
size_t *upload_data_size,
void **con_cls)
{
- const char *code;
- const char *client_id;
- const char *redirect_uri;
- const char *client_secret;
+ struct RequestCtx *rc = *con_cls;
unsigned int hc;
json_t *body;
+ if (NULL == rc)
+ {
+ rc = GNUNET_new (struct RequestCtx);
+ *con_cls = rc;
+ rc->pp = MHD_create_post_processor (connection,
+ 4092,
+ &handle_post,
+ rc);
+ return MHD_YES;
+ }
+ if (0 != *upload_data_size)
+ {
+ enum MHD_Result ret;
+
+ ret = MHD_post_process (rc->pp,
+ upload_data,
+ *upload_data_size);
+ *upload_data_size = 0;
+ return ret;
+ }
+
+
/* NOTE: In the future, we MAY want to distinguish between
the different URLs and possibly return more information.
For now, just do the minimum: implement the main handler
that checks the code. */
- code = MHD_lookup_connection_value (connection,
- MHD_GET_ARGUMENT_KIND,
- "code");
- client_id = MHD_lookup_connection_value (connection,
- MHD_GET_ARGUMENT_KIND,
- "client_id");
- redirect_uri = MHD_lookup_connection_value (connection,
- MHD_GET_ARGUMENT_KIND,
- "redirect_uri");
- client_secret = MHD_lookup_connection_value (connection,
- MHD_GET_ARGUMENT_KIND,
- "client_secret");
- if ( (NULL == code) ||
- (NULL == client_id) ||
- (NULL == redirect_uri) ||
- (NULL == client_secret) )
+ if ( (NULL == rc->code) ||
+ (NULL == rc->client_id) ||
+ (NULL == rc->redirect_uri) ||
+ (NULL == rc->client_secret) )
{
GNUNET_break (0);
+ GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
+ "Bad request to Oauth faker: `%s' with %s/%s/%s/%s\n",
+ url,
+ rc->code,
+ rc->client_id,
+ rc->redirect_uri,
+ rc->client_secret);
return MHD_NO;
}
- if (0 != strcmp (client_id,
+ if (0 != strcmp (rc->client_id,
"taler-exchange"))
{
body = GNUNET_JSON_PACK (
@@ -136,7 +220,7 @@ handler_cb (void *cls,
"only 'taler-exchange' is allowed"));
hc = MHD_HTTP_NOT_FOUND;
}
- else if (0 != strcmp (client_secret,
+ else if (0 != strcmp (rc->client_secret,
"exchange-secret"))
{
body = GNUNET_JSON_PACK (
@@ -148,7 +232,7 @@ handler_cb (void *cls,
}
else
{
- if (0 != strcmp (code,
+ if (0 != strcmp (rc->code,
"pass"))
{
body = GNUNET_JSON_PACK (
@@ -178,6 +262,24 @@ handler_cb (void *cls,
}
+static void
+cleanup (void *cls,
+ struct MHD_Connection *connection,
+ void **con_cls,
+ enum MHD_RequestTerminationCode toe)
+{
+ struct RequestCtx *rc = *con_cls;
+
+ if (NULL == rc)
+ return;
+ GNUNET_free (rc->code);
+ GNUNET_free (rc->client_id);
+ GNUNET_free (rc->redirect_uri);
+ GNUNET_free (rc->client_secret);
+ GNUNET_free (rc);
+}
+
+
/**
* Run the command.
*
@@ -193,12 +295,13 @@ oauth_run (void *cls,
struct OAuthState *oas = cls;
(void) cmd;
- (void) is;
oas->mhd = MHD_start_daemon (MHD_USE_AUTO_INTERNAL_THREAD,
oas->port,
NULL, NULL,
&handler_cb, oas,
+ MHD_OPTION_NOTIFY_COMPLETED, &cleanup, NULL,
NULL);
+ TALER_TESTING_interpreter_next (is);
}