diff options
author | Christian Grothoff <christian@grothoff.org> | 2024-07-27 22:59:40 +0200 |
---|---|---|
committer | Christian Grothoff <christian@grothoff.org> | 2024-07-29 12:18:49 +0200 |
commit | 16f967fe07ab1dac37a2a0622999efd01f49858e (patch) | |
tree | 7305c5ba3b8bc56d482a5cb09de5067bf481733d /src | |
parent | c97633adb8bdfc6f6f2d574e2ada7127c7ba949d (diff) |
-work on bugs
Diffstat (limited to 'src')
-rw-r--r-- | src/exchange/taler-exchange-httpd_kyc-start.c | 24 | ||||
-rw-r--r-- | src/exchange/taler-exchange-httpd_kyc-upload.c | 59 | ||||
-rw-r--r-- | src/exchangedb/pg_lookup_pending_legitimization.c | 26 | ||||
-rw-r--r-- | src/exchangedb/pg_lookup_pending_legitimization.h | 13 | ||||
-rw-r--r-- | src/exchangedb/pg_update_kyc_process_by_row.c | 15 | ||||
-rw-r--r-- | src/exchangedb/pg_update_kyc_process_by_row.h | 8 | ||||
-rw-r--r-- | src/include/taler_exchangedb_plugin.h | 20 | ||||
-rw-r--r-- | src/include/taler_kyclogic_lib.h | 16 | ||||
-rw-r--r-- | src/kyclogic/kyclogic_api.c | 57 |
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) { |