aboutsummaryrefslogtreecommitdiff
path: root/src
diff options
context:
space:
mode:
authorChristian Grothoff <christian@grothoff.org>2024-07-27 22:59:40 +0200
committerChristian Grothoff <christian@grothoff.org>2024-07-29 12:18:49 +0200
commit16f967fe07ab1dac37a2a0622999efd01f49858e (patch)
tree7305c5ba3b8bc56d482a5cb09de5067bf481733d /src
parentc97633adb8bdfc6f6f2d574e2ada7127c7ba949d (diff)
-work on bugs
Diffstat (limited to 'src')
-rw-r--r--src/exchange/taler-exchange-httpd_kyc-start.c24
-rw-r--r--src/exchange/taler-exchange-httpd_kyc-upload.c59
-rw-r--r--src/exchangedb/pg_lookup_pending_legitimization.c26
-rw-r--r--src/exchangedb/pg_lookup_pending_legitimization.h13
-rw-r--r--src/exchangedb/pg_update_kyc_process_by_row.c15
-rw-r--r--src/exchangedb/pg_update_kyc_process_by_row.h8
-rw-r--r--src/include/taler_exchangedb_plugin.h20
-rw-r--r--src/include/taler_kyclogic_lib.h16
-rw-r--r--src/kyclogic/kyclogic_api.c57
9 files changed, 212 insertions, 26 deletions
diff --git a/src/exchange/taler-exchange-httpd_kyc-start.c b/src/exchange/taler-exchange-httpd_kyc-start.c
index c3cd7375c..1f894d45e 100644
--- a/src/exchange/taler-exchange-httpd_kyc-start.c
+++ b/src/exchange/taler-exchange-httpd_kyc-start.c
@@ -228,7 +228,6 @@ initiate_cb (
{
kyp->hint = GNUNET_strdup (error_msg_hint);
}
- // FIXME: also store errors!
qs = TEH_plugin->update_kyc_process_by_row (
TEH_plugin->cls,
kyp->process_row,
@@ -237,7 +236,10 @@ initiate_cb (
provider_user_id,
provider_legitimization_id,
redirect_url,
- GNUNET_TIME_UNIT_ZERO_ABS);
+ GNUNET_TIME_UNIT_ZERO_ABS,
+ ec,
+ error_msg_hint,
+ TALER_EC_NONE != ec);
if (qs <= 0)
GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
"KYC requirement update failed for %s with status %d at %s:%u\n",
@@ -270,6 +272,9 @@ TEH_handler_kyc_start (
enum GNUNET_DB_QueryStatus qs;
const struct TALER_KYCLOGIC_KycProvider *provider;
struct TALER_KYCLOGIC_ProviderDetails *pd;
+ bool is_finished;
+ size_t enc_len;
+ void *enc = NULL;
kyp = GNUNET_new (struct KycPoller);
kyp->connection = rc->connection;
@@ -323,7 +328,10 @@ TEH_handler_kyc_start (
kyp->legitimization_measure_serial_id,
&kyp->access_token,
&kyp->h_payto,
- &kyp->jmeasures);
+ &kyp->jmeasures,
+ &is_finished,
+ &enc_len,
+ &enc);
if (qs < 0)
{
GNUNET_break (GNUNET_DB_STATUS_HARD_ERROR != qs);
@@ -341,6 +349,16 @@ TEH_handler_kyc_start (
TALER_EC_GENERIC_ENDPOINT_UNKNOWN,
rc->url);
}
+ GNUNET_free (enc);
+ if (is_finished)
+ {
+ GNUNET_break_op (0);
+ return TALER_MHD_reply_with_error (
+ rc->connection,
+ MHD_HTTP_CONFLICT,
+ -1, // FIXME: TALER_EC_..._ALREADY_FINISHED
+ rc->url);
+ }
{
struct TALER_KycMeasureAuthorizationHash shv2;
diff --git a/src/exchange/taler-exchange-httpd_kyc-upload.c b/src/exchange/taler-exchange-httpd_kyc-upload.c
index 7ef915e87..12dbcb3e8 100644
--- a/src/exchange/taler-exchange-httpd_kyc-upload.c
+++ b/src/exchange/taler-exchange-httpd_kyc-upload.c
@@ -229,6 +229,8 @@ finish_key (struct UploadContext *uc)
/**
* Function called to clean up upload context.
+ *
+ * @param[in,out] rc context to clean up
*/
static void
upload_cleaner (struct TEH_RequestContext *rc)
@@ -445,13 +447,20 @@ TEH_handler_kyc_upload (struct TEH_RequestContext *rc,
enum GNUNET_DB_QueryStatus qs;
json_t *jmeasures;
struct MHD_Response *empty_response;
+ bool is_finished = false;
+ size_t enc_attributes_len;
+ void *enc_attributes;
+ json_t *xattributes;
qs = TEH_plugin->lookup_pending_legitimization (
TEH_plugin->cls,
uc->legitimization_measure_serial_id,
&uc->access_token,
&h_payto,
- &jmeasures);
+ &jmeasures,
+ &is_finished,
+ &enc_attributes_len,
+ &enc_attributes);
if (qs < 0)
{
GNUNET_break (0);
@@ -463,27 +472,49 @@ TEH_handler_kyc_upload (struct TEH_RequestContext *rc,
}
if (GNUNET_DB_STATUS_SUCCESS_NO_RESULTS == qs)
{
- // FIXME: should check for idempotency!
+ GNUNET_break_op (0);
+ return TALER_MHD_reply_with_error (
+ rc->connection,
+ MHD_HTTP_NOT_FOUND,
+ TALER_EC_EXCHANGE_KYC_CHECK_REQUEST_UNKNOWN,
+ NULL);
+ }
+
+ if (is_finished)
+ {
+ // FIXME: should check for idempotency:
+ // enc_attributes -> xattributes
+ // json_equal (xattributes, attributes)?
+ // => return OK (idempotent)
+ // or fail (conflicting submission)
/* Note: we do not distinguish between row ID unknown and
access token wrong here; this is on purpose to
minimize information leakage (but we could distinguish
the two in the future to help diagnose issues) */
+
+ GNUNET_free (enc_attributes);
+ return TALER_MHD_reply_with_error (
+ rc->connection,
+ MHD_HTTP_CONFLICT,
+ -1, // FIXME: TALER_EC_EXCHANGE_KYC_FORM_ALREADY_SUBMITTED
+ NULL);
+
+ }
+ GNUNET_free (enc_attributes);
+ if (GNUNET_OK !=
+ TALER_KYCLOGIC_check_form (jmeasures,
+ uc->measure_index,
+ uc->result))
+ {
GNUNET_break_op (0);
+ json_decref (jmeasures);
return TALER_MHD_reply_with_error (
rc->connection,
- MHD_HTTP_NOT_FOUND,
- TALER_EC_EXCHANGE_KYC_CHECK_REQUEST_UNKNOWN,
+ MHD_HTTP_CONFLICT,
+ -1, // FIXME: TALER_EC_EXCHANGE_KYC_FORM_MEASURE_MISMATCH
NULL);
}
- // FIXME: Do sanity checks on jmeasures vs. POSTed data:
- //
- // assert ! jmeasures.verboten
- // MeasureInformation mi = jmeasures.measures[measure_index]
- // Have: mi.{check_name,prog_name,context}
- // assert kyc_checks[check_name].type == form
- // assert input data matches form requirements...
-
json_decref (jmeasures);
/* Setup KYC process (which we will then immediately 'finish') */
@@ -492,7 +523,7 @@ TEH_handler_kyc_upload (struct TEH_RequestContext *rc,
&h_payto,
uc->measure_index,
uc->legitimization_measure_serial_id,
- "FORM", // FIXME: correct??? or allow NULL?
+ "FORM",
NULL, /* provider account ID */
NULL, /* provider legi ID */
&legi_process_row);
@@ -514,7 +545,7 @@ TEH_handler_kyc_upload (struct TEH_RequestContext *rc,
&rc->async_scope_id,
legi_process_row,
&h_payto,
- NULL /* provider name */,
+ "FORM",
NULL /* provider account */,
NULL /* provider legi ID */,
GNUNET_TIME_UNIT_FOREVER_ABS, /* expiration time */
diff --git a/src/exchangedb/pg_lookup_pending_legitimization.c b/src/exchangedb/pg_lookup_pending_legitimization.c
index 1a64f8534..8fed37e80 100644
--- a/src/exchangedb/pg_lookup_pending_legitimization.c
+++ b/src/exchangedb/pg_lookup_pending_legitimization.c
@@ -32,7 +32,11 @@ TEH_PG_lookup_pending_legitimization (
uint64_t legitimization_measure_serial_id,
struct TALER_AccountAccessTokenP *access_token,
struct TALER_PaytoHashP *h_payto,
- json_t **jmeasures)
+ json_t **jmeasures,
+ bool *is_finished,
+ size_t *encrypted_attributes_len,
+ void **encrypted_attributes
+ )
{
struct PostgresClosure *pg = cls;
struct GNUNET_PQ_QueryParam params[] = {
@@ -49,20 +53,36 @@ TEH_PG_lookup_pending_legitimization (
GNUNET_PQ_result_spec_auto_from_type (
"access_token",
access_token),
+ GNUNET_PQ_result_spec_bool (
+ "is_finished",
+ is_finished),
+ GNUNET_PQ_result_spec_allow_null (
+ GNUNET_PQ_result_spec_variable_size (
+ "encrypted_attributes",
+ encrypted_attributes,
+ encrypted_attributes_len),
+ NULL),
GNUNET_PQ_result_spec_end
};
+ *encrypted_attributes_len = 0;
+ *encrypted_attributes = NULL;
PREPARE (pg,
"lookup_pending_legitimization",
"SELECT "
" lm.jmeasures"
",wt.wire_target_h_payto"
",lm.access_token"
+ ",lm.is_finished"
+ ",ka.encrypted_attributes"
" FROM legitimization_measures lm"
" JOIN wire_targets wt"
" ON (lm.access_token = wt.access_token)"
- " WHERE lm.legitimization_measure_serial_id=$1"
- " AND NOT lm.is_finished;");
+ " LEFT JOIN legitimization_processes lp"
+ " ON (lm.legitimization_measure_serial_id = lp.legitimization_measure_serial_id)"
+ " LEFT JOIN kyc_attributes ka"
+ " ON (ka.legitimization_serial = lp.legitimization_process_serial)"
+ " WHERE lm.legitimization_measure_serial_id=$1;");
return GNUNET_PQ_eval_prepared_singleton_select (
pg->conn,
"lookup_pending_legitimization",
diff --git a/src/exchangedb/pg_lookup_pending_legitimization.h b/src/exchangedb/pg_lookup_pending_legitimization.h
index 4f4777738..d1c4e0b59 100644
--- a/src/exchangedb/pg_lookup_pending_legitimization.h
+++ b/src/exchangedb/pg_lookup_pending_legitimization.h
@@ -38,6 +38,13 @@
* payto URI of the account undergoing legitimization
* @param[out] jmeasures set to the legitimization
* measures that were put on the account
+ * @param[out] is_finished set to true if the legitimization was
+ * already finished
+ * @param[out] encrypted_attributes_len set to length of
+ * @a encrypted_attributes
+ * @param[out] encrypted_attributes set to the attributes
+ * obtained for the legitimization process, if it
+ * succeeded, otherwise set to NULL
* @return database transaction status
*/
enum GNUNET_DB_QueryStatus
@@ -46,7 +53,9 @@ TEH_PG_lookup_pending_legitimization (
uint64_t legitimization_measure_serial_id,
struct TALER_AccountAccessTokenP *access_token,
struct TALER_PaytoHashP *h_payto,
- json_t **jmeasures);
-
+ json_t **jmeasures,
+ bool *is_finished,
+ size_t *encrypted_attributes_len,
+ void **encrypted_attributes);
#endif
diff --git a/src/exchangedb/pg_update_kyc_process_by_row.c b/src/exchangedb/pg_update_kyc_process_by_row.c
index 2f6724810..507e92ead 100644
--- a/src/exchangedb/pg_update_kyc_process_by_row.c
+++ b/src/exchangedb/pg_update_kyc_process_by_row.c
@@ -35,9 +35,13 @@ TEH_PG_update_kyc_process_by_row (
const char *provider_account_id,
const char *provider_legitimization_id,
const char *redirect_url,
- struct GNUNET_TIME_Absolute expiration)
+ struct GNUNET_TIME_Absolute expiration,
+ enum TALER_ErrorCode ec,
+ const char *error_message_hint,
+ bool finished)
{
struct PostgresClosure *pg = cls;
+ uint32_t ec32 = (uint32_t) ec;
struct GNUNET_PQ_QueryParam params[] = {
GNUNET_PQ_query_param_uint64 (&process_row),
GNUNET_PQ_query_param_string (provider_name),
@@ -52,6 +56,12 @@ TEH_PG_update_kyc_process_by_row (
? GNUNET_PQ_query_param_string (redirect_url)
: GNUNET_PQ_query_param_null (),
GNUNET_PQ_query_param_absolute_time (&expiration),
+ GNUNET_PQ_query_param_string (provider_name),
+ GNUNET_PQ_query_param_uint32 (&ec32),
+ (NULL != error_message_hint)
+ ? GNUNET_PQ_query_param_string (error_message_hint)
+ : GNUNET_PQ_query_param_null (),
+ GNUNET_PQ_query_param_bool (finished),
GNUNET_PQ_query_param_end
};
enum GNUNET_DB_QueryStatus qs;
@@ -67,6 +77,9 @@ TEH_PG_update_kyc_process_by_row (
" ,provider_legitimization_id=$5"
" ,redirect_url=$6"
" ,expiration_time=GREATEST(expiration_time,$7)"
+ " ,error_code=$8"
+ " ,error_message=$9"
+ " ,finished=$10"
" WHERE"
" h_payto=$3"
" AND legitimization_process_serial_id=$1"
diff --git a/src/exchangedb/pg_update_kyc_process_by_row.h b/src/exchangedb/pg_update_kyc_process_by_row.h
index 150e6e8c3..86e82ed30 100644
--- a/src/exchangedb/pg_update_kyc_process_by_row.h
+++ b/src/exchangedb/pg_update_kyc_process_by_row.h
@@ -37,6 +37,9 @@
* @param provider_legitimization_id provider legitimization ID
* @param redirect_url where the user should be redirected to start the KYC process
* @param expiration how long is this KYC check set to be valid (in the past if invalid)
+ * @param ec error code, #TALER_EC_NONE on success
+ * @param error_message_hint human-readable error message details (in addition to @a ec, NULL on success)
+ * @param finished true to mark the process as done
* @return database transaction status
*/
enum GNUNET_DB_QueryStatus
@@ -48,6 +51,9 @@ TEH_PG_update_kyc_process_by_row (
const char *provider_account_id,
const char *provider_legitimization_id,
const char *redirect_url,
- struct GNUNET_TIME_Absolute expiration);
+ struct GNUNET_TIME_Absolute expiration,
+ enum TALER_ErrorCode ec,
+ const char *error_message_hint,
+ bool finished);
#endif
diff --git a/src/include/taler_exchangedb_plugin.h b/src/include/taler_exchangedb_plugin.h
index 19fa1d91a..844e0b6d6 100644
--- a/src/include/taler_exchangedb_plugin.h
+++ b/src/include/taler_exchangedb_plugin.h
@@ -6937,6 +6937,9 @@ struct TALER_EXCHANGEDB_Plugin
* @param provider_legitimization_id provider legitimization ID
* @param redirect_url where the user should be redirected to start the KYC process
* @param expiration how long is this KYC check set to be valid (in the past if invalid)
+ * @param ec error code, #TALER_EC_NONE on success
+ * @param error_message_hint human-readable error message details (in addition to @a ec, NULL on success)
+ * @param finished true to mark the process as done
* @return database transaction status
*/
enum GNUNET_DB_QueryStatus
@@ -6948,7 +6951,10 @@ struct TALER_EXCHANGEDB_Plugin
const char *provider_account_id,
const char *provider_legitimization_id,
const char *redirect_url,
- struct GNUNET_TIME_Absolute expiration);
+ struct GNUNET_TIME_Absolute expiration,
+ enum TALER_ErrorCode ec,
+ const char *error_message_hint,
+ bool finished);
/**
@@ -7387,6 +7393,13 @@ struct TALER_EXCHANGEDB_Plugin
* payto URI of the account undergoing legitimization
* @param[out] jmeasures set to the legitimization
* measures that were put on the account
+ * @param[out] is_finished set to true if the legitimization was
+ * already finished
+ * @param[out] encrypted_attributes_len set to length of
+ * @a encrypted_attributes
+ * @param[out] encrypted_attributes set to the attributes
+ * obtained for the legitimization process, if it
+ * succeeded, otherwise set to NULL
* @return database transaction status
*/
enum GNUNET_DB_QueryStatus
@@ -7395,7 +7408,10 @@ struct TALER_EXCHANGEDB_Plugin
uint64_t legitimization_measure_serial_id,
struct TALER_AccountAccessTokenP *access_token,
struct TALER_PaytoHashP *h_payto,
- json_t **jmeasures);
+ json_t **jmeasures,
+ bool *is_finished,
+ size_t *encrypted_attributes_len,
+ void **encrypted_attributes);
/**
diff --git a/src/include/taler_kyclogic_lib.h b/src/include/taler_kyclogic_lib.h
index af46f17c7..45fc3c56e 100644
--- a/src/include/taler_kyclogic_lib.h
+++ b/src/include/taler_kyclogic_lib.h
@@ -496,6 +496,22 @@ TALER_KYCLOGIC_select_measure (
/**
+ * Check if the form data matches the requirements
+ * of the selected measure.
+ *
+ * @param jmeasures a LegitimizationMeasures object
+ * @param measure_index an index into the measures
+ * @param form_data form data submitted for the measure
+ * @return #GNUNET_OK if the form data matches the measure
+ */
+enum GNUNET_GenericReturnValue
+TALER_KYCLOGIC_check_form (
+ const json_t *jmeasures,
+ size_t measure_index,
+ const json_t *form_data);
+
+
+/**
* Convert MeasureInformation into the
* KycRequirementInformation used by the client.
*
diff --git a/src/kyclogic/kyclogic_api.c b/src/kyclogic/kyclogic_api.c
index 68ac72190..aef9d6369 100644
--- a/src/kyclogic/kyclogic_api.c
+++ b/src/kyclogic/kyclogic_api.c
@@ -3016,6 +3016,63 @@ TALER_KYCLOGIC_select_measure (
}
+enum GNUNET_GenericReturnValue
+TALER_KYCLOGIC_check_form (
+ const json_t *jmeasures,
+ size_t measure_index,
+ const json_t *form_data)
+{
+ const char *check_name;
+ const char *prog_name;
+ const json_t *context;
+ struct TALER_KYCLOGIC_KycCheck *kc;
+ struct TALER_KYCLOGIC_AmlProgram *prog;
+
+ if (TALER_EC_NONE !=
+ TALER_KYCLOGIC_select_measure (jmeasures,
+ measure_index,
+ &check_name,
+ &prog_name,
+ &context))
+ {
+ GNUNET_break_op (0);
+ return GNUNET_SYSERR;
+ }
+ kc = find_check (check_name);
+ if (NULL == kc)
+ {
+ GNUNET_break_op (0);
+ return GNUNET_SYSERR;
+ }
+ if (TALER_KYCLOGIC_CT_FORM != kc->type)
+ {
+ GNUNET_break_op (0);
+ return GNUNET_SYSERR;
+ }
+ prog = find_program (prog_name);
+ if (NULL == prog)
+ {
+ GNUNET_break (0);
+ return GNUNET_SYSERR;
+ }
+ for (unsigned int i = 0; i<prog->num_required_attributes; i++)
+ {
+ const char *rattr = prog->required_attributes[i];
+
+ if (NULL == json_object_get (form_data,
+ rattr))
+ {
+ GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
+ "Form data lacks required attribute `%s' for AML program %s\n",
+ rattr,
+ prog_name);
+ return GNUNET_NO;
+ }
+ }
+ return GNUNET_OK;
+}
+
+
const struct TALER_KYCLOGIC_KycProvider *
TALER_KYCLOGIC_check_to_provider (const char *check_name)
{