diff options
24 files changed, 285 insertions, 81 deletions
diff --git a/contrib/gana b/contrib/gana -Subproject d0a05d57c856c8b68342ac075fb8d5f0f26f5df +Subproject 3ae4bcc5c40d63d91c5248311b93419e4faabf8 diff --git a/src/exchange/taler-exchange-httpd_age-withdraw.c b/src/exchange/taler-exchange-httpd_age-withdraw.c index 9102fa346..dba4b9bef 100644 --- a/src/exchange/taler-exchange-httpd_age-withdraw.c +++ b/src/exchange/taler-exchange-httpd_age-withdraw.c @@ -92,6 +92,13 @@ static void free_age_withdraw_context_resources (struct AgeWithdrawContext *awc) { GNUNET_free (awc->denom_hs); + for (unsigned int i = 0; i<awc->num_coins; i++) + { + for (unsigned int kappa = 0; kappa<TALER_CNC_KAPPA; kappa++) + { + TALER_blinded_planchet_free (&awc->coin_evs[i][kappa]); + } + } GNUNET_free (awc->coin_evs); GNUNET_free (awc->commitment.denom_serials); /* @@ -204,6 +211,7 @@ parse_age_withdraw_json ( /* Parse blinded envelopes. */ json_array_foreach (j_blinded_coin_evs, idx, value) { const json_t *j_kappa_coin_evs = value; + if (! json_is_array (j_kappa_coin_evs)) { GNUNET_snprintf (buf, diff --git a/src/exchange/taler-exchange-httpd_aml-decision.c b/src/exchange/taler-exchange-httpd_aml-decision.c index eef1e9ead..67e1246eb 100644 --- a/src/exchange/taler-exchange-httpd_aml-decision.c +++ b/src/exchange/taler-exchange-httpd_aml-decision.c @@ -39,6 +39,7 @@ TEH_handler_post_aml_decision ( { struct MHD_Connection *connection = rc->connection; const char *justification; + const char *new_measure = NULL; bool to_investigate; struct GNUNET_TIME_Timestamp decision_time; const json_t *new_rules; @@ -46,6 +47,11 @@ TEH_handler_post_aml_decision ( struct TALER_PaytoHashP h_payto; struct TALER_AmlOfficerSignatureP officer_sig; struct GNUNET_JSON_Specification spec[] = { + GNUNET_JSON_spec_mark_optional ( + GNUNET_JSON_spec_string ( + "new_measure", + &new_measure), + NULL), GNUNET_JSON_spec_string ("justification", &justification), GNUNET_JSON_spec_fixed_auto ("h_payto", @@ -65,6 +71,7 @@ TEH_handler_post_aml_decision ( GNUNET_JSON_spec_end () }; struct GNUNET_TIME_Timestamp expiration_time; + json_t *jmeasures = NULL; { enum GNUNET_GenericReturnValue res; @@ -88,6 +95,7 @@ TEH_handler_post_aml_decision ( &h_payto, new_rules, properties, + new_measure, to_investigate, officer_pub, &officer_sig)) @@ -114,7 +122,22 @@ TEH_handler_post_aml_decision ( "legitimization rule malformed"); } expiration_time = TALER_KYCLOGIC_rules_get_expiration (lrs); - + if (NULL != new_measure) + { + jmeasures = TALER_KYCLOGIC_get_measure (lrs, + new_measure); + if (NULL == jmeasures) + { + GNUNET_break_op (0); + /* Request specified a new_measure for which the given + rule set does not work as it does not define the measure */ + return TALER_MHD_reply_with_error ( + connection, + MHD_HTTP_BAD_REQUEST, + TALER_EC_GENERIC_PARAMETER_MALFORMED, + "new_measure/new_rules"); + } + } TALER_KYCLOGIC_rules_free (lrs); } @@ -122,6 +145,7 @@ TEH_handler_post_aml_decision ( enum GNUNET_DB_QueryStatus qs; struct GNUNET_TIME_Timestamp last_date; bool invalid_officer = true; + bool unknown_account = false; qs = TEH_plugin->insert_aml_decision (TEH_plugin->cls, &h_payto, @@ -130,11 +154,14 @@ TEH_handler_post_aml_decision ( properties, new_rules, to_investigate, + jmeasures, justification, officer_pub, &officer_sig, &invalid_officer, + &unknown_account, &last_date); + json_decref (jmeasures); if (qs <= 0) { GNUNET_break (0); @@ -152,7 +179,15 @@ TEH_handler_post_aml_decision ( MHD_HTTP_FORBIDDEN, TALER_EC_EXCHANGE_AML_DECISION_INVALID_OFFICER, NULL); - return GNUNET_DB_STATUS_HARD_ERROR; + } + if (unknown_account) + { + GNUNET_break_op (0); + return TALER_MHD_reply_with_error ( + connection, + MHD_HTTP_NOT_FOUND, + TALER_EC_EXCHANGE_GENERIC_BANK_ACCOUNT_UNKNOWN, + "h_payto"); } if (GNUNET_TIME_timestamp_cmp (last_date, >=, @@ -165,6 +200,8 @@ TEH_handler_post_aml_decision ( TALER_EC_EXCHANGE_AML_DECISION_MORE_RECENT_PRESENT, NULL); } + + } return TALER_MHD_reply_static ( connection, diff --git a/src/exchange/taler-exchange-httpd_aml-decisions-get.c b/src/exchange/taler-exchange-httpd_aml-decisions-get.c index 2d1c1192e..9059d1437 100644 --- a/src/exchange/taler-exchange-httpd_aml-decisions-get.c +++ b/src/exchange/taler-exchange-httpd_aml-decisions-get.c @@ -68,7 +68,7 @@ record_cb ( GNUNET_assert ( 0 == - json_array_append ( + json_array_append_new ( records, GNUNET_JSON_PACK ( GNUNET_JSON_pack_data_auto ("h_payto", diff --git a/src/exchange/taler-exchange-httpd_kyc-info.c b/src/exchange/taler-exchange-httpd_kyc-info.c index 768703690..88c9fc579 100644 --- a/src/exchange/taler-exchange-httpd_kyc-info.c +++ b/src/exchange/taler-exchange-httpd_kyc-info.c @@ -424,7 +424,7 @@ TEH_handler_kyc_info ( GNUNET_JSON_pack_object_steal ("voluntary_checks", NULL))); } - if ( (last_row == kyp->etag_in) && + if ( (legitimization_measure_last_row == kyp->etag_in) && GNUNET_TIME_absolute_is_future (kyp->timeout) ) { GNUNET_log (GNUNET_ERROR_TYPE_INFO, diff --git a/src/exchange/taler-exchange-httpd_kyc-proof.c b/src/exchange/taler-exchange-httpd_kyc-proof.c index 2539dd614..657c28c6a 100644 --- a/src/exchange/taler-exchange-httpd_kyc-proof.c +++ b/src/exchange/taler-exchange-httpd_kyc-proof.c @@ -181,6 +181,7 @@ proof_finish ( struct KycProofContext *kpc = cls; kpc->kat = NULL; + GNUNET_assert (NULL == kpc->response); kpc->response_code = http_status; kpc->response = response; kpc_resume (kpc); diff --git a/src/exchange/taler-exchange-httpd_kyc-upload.c b/src/exchange/taler-exchange-httpd_kyc-upload.c index 2b870249d..9dd16b0cb 100644 --- a/src/exchange/taler-exchange-httpd_kyc-upload.c +++ b/src/exchange/taler-exchange-httpd_kyc-upload.c @@ -242,6 +242,11 @@ upload_cleaner (struct TEH_RequestContext *rc) TEH_kyc_finished_cancel (uc->kat); uc->kat = NULL; } + if (NULL != uc->response) + { + MHD_destroy_response (uc->response); + uc->response = NULL; + } MHD_destroy_post_processor (uc->pp); GNUNET_free (uc->filename); GNUNET_free (uc->content_type); @@ -340,6 +345,9 @@ aml_trigger_callback ( { struct UploadContext *uc = cls; + uc->kat = NULL; + GNUNET_assert (NULL == uc->response); + GNUNET_assert (NULL != response); uc->response_code = http_status; uc->response = response; MHD_resume_connection (uc->rc->connection); @@ -443,6 +451,7 @@ TEH_handler_kyc_upload ( return mres; } finish_key (uc); + GNUNET_assert (NULL == uc->kat); { uint64_t legi_process_row; @@ -584,6 +593,7 @@ TEH_handler_kyc_upload ( TALER_EC_EXCHANGE_KYC_GENERIC_AML_LOGIC_BUG, "TEH_kyc_finished"); } + MHD_suspend_connection (uc->rc->connection); GNUNET_CONTAINER_DLL_insert (uc_head, uc_tail, uc); diff --git a/src/exchange/taler-exchange-httpd_kyc-webhook.c b/src/exchange/taler-exchange-httpd_kyc-webhook.c index 67e28276d..9cdcfb66b 100644 --- a/src/exchange/taler-exchange-httpd_kyc-webhook.c +++ b/src/exchange/taler-exchange-httpd_kyc-webhook.c @@ -162,6 +162,7 @@ kyc_aml_webhook_finished ( struct KycWebhookContext *kwh = cls; kwh->kat = NULL; + GNUNET_assert (NULL == kwh->response); kwh->response = response; kwh->response_code = http_status; kwh_resume (kwh); diff --git a/src/exchange/taler-exchange-httpd_reserves_get_attest.c b/src/exchange/taler-exchange-httpd_reserves_get_attest.c index ca671f621..c3cb7bc16 100644 --- a/src/exchange/taler-exchange-httpd_reserves_get_attest.c +++ b/src/exchange/taler-exchange-httpd_reserves_get_attest.c @@ -104,9 +104,10 @@ kyc_process_cb (void *cls, if (duplicate) continue; GNUNET_assert (0 == - json_array_append (rsc->attributes, - json_string (name))); + json_array_append_new (rsc->attributes, + json_string (name))); } + json_decref (attrs); } diff --git a/src/exchange/taler-exchange-httpd_reserves_purse.c b/src/exchange/taler-exchange-httpd_reserves_purse.c index bb635c3cc..6186afe4e 100644 --- a/src/exchange/taler-exchange-httpd_reserves_purse.c +++ b/src/exchange/taler-exchange-httpd_reserves_purse.c @@ -744,9 +744,12 @@ TEH_handler_reserves_purse ( GNUNET_free (rpc.payto_uri); if (! rpc.kyc.ok) + { + GNUNET_JSON_parse_free (spec); return TEH_RESPONSE_reply_kyc_required (connection, &rpc.h_payto, &rpc.kyc); + } /* generate regular response */ { MHD_RESULT res; diff --git a/src/exchangedb/exchange_do_insert_aml_decision.sql b/src/exchangedb/exchange_do_insert_aml_decision.sql index 59c62d55b..9c86f13f3 100644 --- a/src/exchangedb/exchange_do_insert_aml_decision.sql +++ b/src/exchangedb/exchange_do_insert_aml_decision.sql @@ -22,17 +22,25 @@ CREATE OR REPLACE FUNCTION exchange_do_insert_aml_decision( IN in_properties TEXT, IN in_new_rules TEXT, IN in_to_investigate BOOLEAN, + IN in_jmeasures TEXT, IN in_justification TEXT, IN in_decider_pub BYTEA, IN in_decider_sig BYTEA, IN in_notify_s TEXT, OUT out_invalid_officer BOOLEAN, + OUT out_account_unknown BOOLEAN, OUT out_last_date INT8) LANGUAGE plpgsql AS $$ DECLARE my_outcome_serial_id INT8; + my_access_token BYTEA; + my_max_dp INT4; BEGIN + +out_account_unknown=FALSE; + + -- Check officer is eligible to make decisions. PERFORM FROM aml_staff @@ -70,6 +78,56 @@ ELSE out_last_date = 0; END IF; +-- Only do this if we have in_jmeasures to trigger +IF in_jmeasures IS NOT NULL +THEN + + -- Note: in_payto_uri is allowed to be NULL *if* + -- in_h_payto is already in wire_targets + SELECT + access_token + INTO + my_access_token + FROM wire_targets + WHERE wire_target_h_payto=in_h_payto; + + -- Very strange, should never happen that we + -- take an AML decision on an unknown account! + IF NOT FOUND + THEN + out_account_unknown=TRUE; + RETURN; + END IF; + + -- Find current maximum DP + SELECT COALESCE(MAX(display_priority),0) + INTO my_max_dp + FROM legitimization_measures + WHERE access_token=my_access_token + AND NOT is_finished; + + -- Enable legitimization measure + INSERT INTO legitimization_measures + (access_token + ,start_time + ,jmeasures + ,display_priority) + VALUES + (my_access_token + ,in_decision_time + ,in_jmeasures + ,my_max_dp + 1); + + -- end if for where we had non-NULL in_jmeasures +END IF; + +UPDATE legitimization_outcomes + SET is_active=FALSE + WHERE h_payto=in_h_payto + -- this clause is a minor optimization to avoid + -- updating outcomes that have long expired. + AND expiration_time >= in_decision_time; + INSERT INTO legitimization_outcomes (h_payto ,decision_time @@ -120,5 +178,5 @@ INSERT INTO kyc_alerts END $$; -COMMENT ON FUNCTION exchange_do_insert_aml_decision(BYTEA, INT8, INT8, TEXT, TEXT, BOOLEAN, TEXT, BYTEA, BYTEA, TEXT) +COMMENT ON FUNCTION exchange_do_insert_aml_decision(BYTEA, INT8, INT8, TEXT, TEXT, BOOLEAN, TEXT, TEXT, BYTEA, BYTEA, TEXT) IS 'Checks whether the AML officer is eligible to make AML decisions and if so inserts the decision into the table'; diff --git a/src/exchangedb/exchange_do_insert_kyc_attributes.sql b/src/exchangedb/exchange_do_insert_kyc_attributes.sql index 12f76c17d..0c907f279 100644 --- a/src/exchangedb/exchange_do_insert_kyc_attributes.sql +++ b/src/exchangedb/exchange_do_insert_kyc_attributes.sql @@ -41,6 +41,14 @@ DECLARE ini_event TEXT; BEGIN + +UPDATE legitimization_outcomes + SET is_active=FALSE + WHERE h_payto=in_h_payto + -- this clause is a minor optimization to avoid + -- updating outcomes that have long expired. + AND expiration_time >= in_collection_time_ts; + INSERT INTO legitimization_outcomes (h_payto ,decision_time @@ -107,7 +115,6 @@ UPDATE reserves ((current_balance).val > 0 ) ) AND (expiration_date > in_collection_time_ts); - IF in_to_investigate THEN INSERT INTO aml_status @@ -135,13 +142,12 @@ EXECUTE FORMAT ( 'NOTIFY %s' ,in_kyc_completed_notify_s); - INSERT INTO kyc_alerts (h_payto ,trigger_type) VALUES - (in_h_payto,1); - + (in_h_payto,1) + ON CONFLICT DO NOTHING; END $$; diff --git a/src/exchangedb/pg_insert_aml_decision.c b/src/exchangedb/pg_insert_aml_decision.c index d1e618282..f33aa0a01 100644 --- a/src/exchangedb/pg_insert_aml_decision.c +++ b/src/exchangedb/pg_insert_aml_decision.c @@ -36,10 +36,12 @@ TEH_PG_insert_aml_decision ( const json_t *properties, const json_t *new_rules, bool to_investigate, + const json_t *jmeasures, const char *justification, const struct TALER_AmlOfficerPublicKeyP *decider_pub, const struct TALER_AmlOfficerSignatureP *decider_sig, bool *invalid_officer, + bool *unknown_account, struct GNUNET_TIME_Timestamp *last_date) { struct PostgresClosure *pg = cls; @@ -59,6 +61,9 @@ TEH_PG_insert_aml_decision ( : GNUNET_PQ_query_param_null (), TALER_PQ_query_param_json (new_rules), GNUNET_PQ_query_param_bool (to_investigate), + NULL != jmeasures + ? TALER_PQ_query_param_json (jmeasures) + : GNUNET_PQ_query_param_null (), GNUNET_PQ_query_param_string (justification), GNUNET_PQ_query_param_auto_from_type (decider_pub), GNUNET_PQ_query_param_auto_from_type (decider_sig), @@ -68,6 +73,8 @@ TEH_PG_insert_aml_decision ( struct GNUNET_PQ_ResultSpec rs[] = { GNUNET_PQ_result_spec_bool ("out_invalid_officer", invalid_officer), + GNUNET_PQ_result_spec_bool ("out_account_unknown", + unknown_account), GNUNET_PQ_result_spec_timestamp ("out_last_date", last_date), GNUNET_PQ_result_spec_end @@ -78,9 +85,10 @@ TEH_PG_insert_aml_decision ( "do_insert_aml_decision", "SELECT" " out_invalid_officer" + ",out_account_unknown" ",out_last_date" " FROM exchange_do_insert_aml_decision" - "($1, $2, $3, $4, $5, $6, $7, $8, $9, $10);"); + "($1, $2, $3, $4, $5, $6, $7, $8, $9, $10, $11);"); qs = GNUNET_PQ_eval_prepared_singleton_select (pg->conn, "do_insert_aml_decision", params, diff --git a/src/exchangedb/pg_insert_aml_decision.h b/src/exchangedb/pg_insert_aml_decision.h index 84fc4387c..ab75845ff 100644 --- a/src/exchangedb/pg_insert_aml_decision.h +++ b/src/exchangedb/pg_insert_aml_decision.h @@ -37,10 +37,13 @@ * @param properties JSON object with properties to set for the account * @param new_rules JSON array with new AML/KYC rules * @param to_investigate true if AML staff should look more into this account + * @param jmeasures a JSON with LegitimizationMeasures to apply to the + * account, or NULL to not apply any measure right now * @param justification human-readable text justifying the decision * @param decider_pub public key of the staff member * @param decider_sig signature of the staff member * @param[out] invalid_officer set to TRUE if @a decider_pub is not allowed to make decisions right now + * @param[out] unknown_account set to TRUE if @a h_payto does not refer to a known account and @a jmeasures was given * @param[out] last_date set to the previous decision time; * the INSERT is not performed if @a last_date is not before @a decision_time * @return database transaction status @@ -54,10 +57,12 @@ TEH_PG_insert_aml_decision ( const json_t *properties, const json_t *new_rules, bool to_investigate, + const json_t *jmeasures, const char *justification, const struct TALER_AmlOfficerPublicKeyP *decider_pub, const struct TALER_AmlOfficerSignatureP *decider_sig, bool *invalid_officer, + bool *unknown_account, struct GNUNET_TIME_Timestamp *last_date); diff --git a/src/exchangedb/pg_insert_kyc_attributes.c b/src/exchangedb/pg_insert_kyc_attributes.c index cbdcb7c63..e7a0c12bd 100644 --- a/src/exchangedb/pg_insert_kyc_attributes.c +++ b/src/exchangedb/pg_insert_kyc_attributes.c @@ -109,7 +109,7 @@ TEH_PG_insert_kyc_attributes ( GNUNET_PQ_cleanup_query_params_closures (params); GNUNET_free (kyc_completed_notify_s); GNUNET_PQ_event_do_poll (pg->conn); - if (qs < 0) + if (qs <= 0) return qs; if (! ok) return GNUNET_DB_STATUS_SUCCESS_NO_RESULTS; diff --git a/src/exchangedb/pg_lookup_aml_history.c b/src/exchangedb/pg_lookup_aml_history.c index 077e2781c..0eab9a2a2 100644 --- a/src/exchangedb/pg_lookup_aml_history.c +++ b/src/exchangedb/pg_lookup_aml_history.c @@ -86,9 +86,9 @@ handle_aml_entry (void *cls, &justification), GNUNET_PQ_result_spec_auto_from_type ("decider_pub", &decider_pub), - TALER_PQ_result_spec_json ("properties", + TALER_PQ_result_spec_json ("jproperties", &jproperties), - TALER_PQ_result_spec_json ("new_rules", + TALER_PQ_result_spec_json ("jnew_rules", &jnew_rules), GNUNET_PQ_result_spec_bool ("to_investigate", &to_investigate), diff --git a/src/include/taler_crypto_lib.h b/src/include/taler_crypto_lib.h index 11ab2bce8..ac95e4756 100644 --- a/src/include/taler_crypto_lib.h +++ b/src/include/taler_crypto_lib.h @@ -2668,6 +2668,7 @@ TALER_officer_aml_query_verify ( * @param new_rules new KYC rules to apply to the account * Must be a "LegitimizationRuleSet". * @param properties properties of the account, can be NULL + * @param new_check new KYC check to run, NULL for none * @param to_investigate true if the account should be investigated by AML staff * @param officer_priv private key of AML officer * @param[out] officer_sig where to write the signature @@ -2679,6 +2680,7 @@ TALER_officer_aml_decision_sign ( const struct TALER_PaytoHashP *h_payto, const json_t *new_rules, const json_t *properties, + const char *new_check, bool to_investigate, const struct TALER_AmlOfficerPrivateKeyP *officer_priv, struct TALER_AmlOfficerSignatureP *officer_sig); @@ -2693,6 +2695,7 @@ TALER_officer_aml_decision_sign ( * decision is about * @param new_rules new KYC rules to apply to the account * @param properties properties of the account, can be NULL + * @param new_check new KYC check to run, NULL for none * @param to_investigate true if the account should be investigated by AML staff * @param officer_pub public key of AML officer * @param officer_sig signature to verify @@ -2705,6 +2708,7 @@ TALER_officer_aml_decision_verify ( const struct TALER_PaytoHashP *h_payto, const json_t *new_rules, const json_t *properties, + const char *new_check, bool to_investigate, const struct TALER_AmlOfficerPublicKeyP *officer_pub, const struct TALER_AmlOfficerSignatureP *officer_sig); diff --git a/src/include/taler_exchangedb_plugin.h b/src/include/taler_exchangedb_plugin.h index 98596382c..3a6610f3d 100644 --- a/src/include/taler_exchangedb_plugin.h +++ b/src/include/taler_exchangedb_plugin.h @@ -7490,14 +7490,18 @@ struct TALER_EXCHANGEDB_Plugin * * @param cls closure * @param h_payto account for which the attribute data is stored - * @param new_rules new rules to apply * @param decision_time when was the decision made + * @param expiration_time when does the decision expire + * @param properties JSON object with properties to set for the account + * @param new_rules JSON array with new AML/KYC rules + * @param to_investigate true if AML staff should look more into this account + * @param jmeasures a JSON with LegitimizationMeasures to apply to the + * account, or NULL to not apply any measure right now * @param justification human-readable text justifying the decision - * @param kyc_requirements specific KYC requirements being imposed - * @param requirements_row row in the KYC table for this process, 0 for none * @param decider_pub public key of the staff member * @param decider_sig signature of the staff member * @param[out] invalid_officer set to TRUE if @a decider_pub is not allowed to make decisions right now + * @param[out] unknown_account set to TRUE if @a h_payto does not refer to a known account and @a jmeasures was given * @param[out] last_date set to the previous decision time; * the INSERT is not performed if @a last_date is not before @a decision_time * @return database transaction status @@ -7511,10 +7515,12 @@ struct TALER_EXCHANGEDB_Plugin const json_t *properties, const json_t *new_rules, bool to_investigate, + const json_t *jmeasures, const char *justification, const struct TALER_AmlOfficerPublicKeyP *decider_pub, const struct TALER_AmlOfficerSignatureP *decider_sig, bool *invalid_officer, + bool *unknown_account, struct GNUNET_TIME_Timestamp *last_date); diff --git a/src/include/taler_kyclogic_lib.h b/src/include/taler_kyclogic_lib.h index 1fcf65ace..e99a3f2a9 100644 --- a/src/include/taler_kyclogic_lib.h +++ b/src/include/taler_kyclogic_lib.h @@ -534,6 +534,19 @@ TALER_KYCLOGIC_measure_to_requirement ( /** + * Lookup @a measure_name in @a lrs and create JSON + * object with the corresponding LegitimizationMeasures. + * + * @param lrs set of legitimization rules + * @param measure_name name of a measure to trigger from @a lrs + * @return JSON object of type LegitimizationMeasures + */ +json_t * +TALER_KYCLOGIC_get_measure ( + const struct TALER_KYCLOGIC_LegitimizationRuleSet *lrs, + const char *measure_name); + +/** * Lookup the provider for the given @a check_name. * * @param check_name check to lookup provider for diff --git a/src/kyclogic/kyclogic_api.c b/src/kyclogic/kyclogic_api.c index 0930371c6..fad66e914 100644 --- a/src/kyclogic/kyclogic_api.c +++ b/src/kyclogic/kyclogic_api.c @@ -176,13 +176,6 @@ struct TALER_KYCLOGIC_LegitimizationRuleSet char *successor_measure; /** - * Name of the check that becomes active when this - * measure is triggered. - * NULL for no check (allowed, but should be rare). - */ - char *new_check; - - /** * Array of the rules. */ struct TALER_KYCLOGIC_KycRule *kyc_rules; @@ -487,7 +480,6 @@ TALER_KYCLOGIC_rules_parse (const json_t *jlrs) struct GNUNET_TIME_Timestamp expiration_time; const char *successor_measure = NULL; const json_t *jrules; - const char *new_check = NULL; const json_t *jcustom_measures = NULL; struct GNUNET_JSON_Specification spec[] = { GNUNET_JSON_spec_timestamp ( @@ -498,11 +490,6 @@ TALER_KYCLOGIC_rules_parse (const json_t *jlrs) "successor_measure", &successor_measure), NULL), - GNUNET_JSON_spec_mark_optional ( - GNUNET_JSON_spec_string ( - "new_check", - &new_check), - NULL), GNUNET_JSON_spec_array_const ("rules", &jrules), GNUNET_JSON_spec_mark_optional ( @@ -541,10 +528,6 @@ TALER_KYCLOGIC_rules_parse (const json_t *jlrs) = (NULL == successor_measure) ? NULL : GNUNET_strdup (successor_measure); - lrs->new_check - = (NULL == new_check) - ? NULL - : GNUNET_strdup (new_check); lrs->num_kyc_rules = (unsigned int) json_array_size (jrules); if (((size_t) lrs->num_kyc_rules) != @@ -606,10 +589,10 @@ TALER_KYCLOGIC_rules_parse (const json_t *jlrs) goto cleanup; } rule->lrs = lrs; + rule->num_measures = json_array_size (jmeasures); rule->next_measures = GNUNET_new_array (rule->num_measures, char *); - rule->num_measures = json_array_size (jmeasures); if (((size_t) rule->num_measures) != json_array_size (jmeasures)) { @@ -727,7 +710,6 @@ TALER_KYCLOGIC_rules_free (struct TALER_KYCLOGIC_LegitimizationRuleSet *lrs) GNUNET_free (lrs->kyc_rules); GNUNET_free (lrs->custom_measures); GNUNET_free (lrs->successor_measure); - GNUNET_free (lrs->new_check); GNUNET_free (lrs); } @@ -883,15 +865,18 @@ find_measure (const struct TALER_KYCLOGIC_LegitimizationRuleSet *lrs, return cm; } } - /* Try measures from default rules */ - for (unsigned int i = 0; i<default_rules.num_custom_measures; i++) + if (lrs != &default_rules) { - const struct TALER_KYCLOGIC_Measure *cm - = &default_rules.custom_measures[i]; + /* Try measures from default rules */ + for (unsigned int i = 0; i<default_rules.num_custom_measures; i++) + { + const struct TALER_KYCLOGIC_Measure *cm + = &default_rules.custom_measures[i]; - if (0 == strcmp (measure_name, - cm->measure_name)) - return cm; + if (0 == strcmp (measure_name, + cm->measure_name)) + return cm; + } } GNUNET_log (GNUNET_ERROR_TYPE_ERROR, "Measure `%s' not found\n", @@ -950,6 +935,58 @@ TALER_KYCLOGIC_rule_to_measures (const struct TALER_KYCLOGIC_KycRule *r) json_t * +TALER_KYCLOGIC_get_measure ( + const struct TALER_KYCLOGIC_LegitimizationRuleSet *lrs, + const char *measure_name) +{ + const struct TALER_KYCLOGIC_Measure *ms; + json_t *mi; + json_t *jmeasures; + + if (0 == strcmp ("verboten", + measure_name)) + { + jmeasures = json_array (); + GNUNET_assert (NULL != jmeasures); + return GNUNET_JSON_PACK ( + GNUNET_JSON_pack_array_steal ("measures", + jmeasures), + GNUNET_JSON_pack_bool ("is_and_combinator", + false), + GNUNET_JSON_pack_bool ("verboten", + true)); + } + ms = find_measure (lrs, + measure_name); + if (NULL == ms) + { + GNUNET_break (0); + return NULL; + } + mi = GNUNET_JSON_PACK ( + GNUNET_JSON_pack_string ("check_name", + ms->check_name), + GNUNET_JSON_pack_string ("prog_name", + ms->prog_name), + GNUNET_JSON_pack_allow_null ( + GNUNET_JSON_pack_object_incref ("context", + ms->context))); + jmeasures = json_array (); + GNUNET_assert (NULL != jmeasures); + GNUNET_assert (0 == + json_array_append_new (jmeasures, + mi)); + return GNUNET_JSON_PACK ( + GNUNET_JSON_pack_array_steal ("measures", + jmeasures), + GNUNET_JSON_pack_bool ("is_and_combinator", + false), + GNUNET_JSON_pack_bool ("verboten", + false)); +} + + +json_t * TALER_KYCLOGIC_check_to_measures ( const struct TALER_KYCLOGIC_KycCheckContext *kcc) { @@ -2109,18 +2146,18 @@ static int sort_by_timeframe (const void *p1, const void *p2) { - struct TALER_KYCLOGIC_KycRule **r1 - = (struct TALER_KYCLOGIC_KycRule **) p1; - struct TALER_KYCLOGIC_KycRule **r2 - = (struct TALER_KYCLOGIC_KycRule **) p2; + struct TALER_KYCLOGIC_KycRule *r1 + = (struct TALER_KYCLOGIC_KycRule *) p1; + struct TALER_KYCLOGIC_KycRule *r2 + = (struct TALER_KYCLOGIC_KycRule *) p2; - if (GNUNET_TIME_relative_cmp ((*r1)->timeframe, + if (GNUNET_TIME_relative_cmp (r1->timeframe, <, - (*r2)->timeframe)) + r2->timeframe)) return -1; - if (GNUNET_TIME_relative_cmp ((*r1)->timeframe, + if (GNUNET_TIME_relative_cmp (r1->timeframe, >, - (*r2)->timeframe)) + r2->timeframe)) return 1; return 0; } @@ -2439,20 +2476,8 @@ TALER_KYCLOGIC_requirements_to_check ( lrs = &default_rules; if (NULL == measure_name) { - /* No measure selected, return the "new_check" */ - if (0 != strcasecmp (lrs->new_check, - "SKIP")) - { - kcc->check = find_check (lrs->new_check); - GNUNET_break (NULL != kcc->check); - } - else - { - kcc->check = NULL; - } - kcc->prog_name = measure->prog_name; - kcc->context = measure->context; - return GNUNET_OK; + GNUNET_break (0); + return GNUNET_SYSERR; } for (unsigned int i = 0; i<kyc_rule->num_measures; i++) { @@ -2976,8 +3001,10 @@ TALER_KYCLOGIC_select_measure ( check_name), GNUNET_JSON_spec_string ("prog_name", prog_name), - GNUNET_JSON_spec_object_const ("context", - context), + GNUNET_JSON_spec_mark_optional ( + GNUNET_JSON_spec_object_const ("context", + context), + NULL), GNUNET_JSON_spec_end () }; @@ -3414,8 +3441,9 @@ TALER_KYCLOGIC_run_aml_program2 ( json_t *input; input = GNUNET_JSON_PACK ( - GNUNET_JSON_pack_object_incref ("context", - (json_t *) context), + GNUNET_JSON_pack_allow_null ( + GNUNET_JSON_pack_object_incref ("context", + (json_t *) context)), GNUNET_JSON_pack_object_incref ("attributes", (json_t *) attributes), GNUNET_JSON_pack_array_incref ("aml_history", diff --git a/src/lib/exchange_api_add_aml_decision.c b/src/lib/exchange_api_add_aml_decision.c index 1fee742b8..53cd04eb5 100644 --- a/src/lib/exchange_api_add_aml_decision.c +++ b/src/lib/exchange_api_add_aml_decision.c @@ -130,7 +130,7 @@ TALER_EXCHANGE_add_aml_decision ( const struct TALER_PaytoHashP *h_payto, struct GNUNET_TIME_Timestamp decision_time, const char *successor_measure, - const char *new_check, + const char *new_measure, struct GNUNET_TIME_Timestamp expiration_time, unsigned int num_rules, const struct TALER_EXCHANGE_AccountRule *rules, @@ -216,9 +216,6 @@ TALER_EXCHANGE_add_aml_decision ( GNUNET_JSON_pack_allow_null ( GNUNET_JSON_pack_string ("successor_measure", successor_measure)), - GNUNET_JSON_pack_allow_null ( - GNUNET_JSON_pack_string ("new_check", - new_check)), GNUNET_JSON_pack_array_steal ("rules", jrules), GNUNET_JSON_pack_object_steal ("custom_measures", @@ -233,6 +230,7 @@ TALER_EXCHANGE_add_aml_decision ( h_payto, new_rules, properties, + new_measure, keep_investigating, officer_priv, &officer_sig); @@ -276,6 +274,9 @@ TALER_EXCHANGE_add_aml_decision ( new_rules), GNUNET_JSON_pack_object_incref ("properties", (json_t *) properties), + GNUNET_JSON_pack_allow_null ( + GNUNET_JSON_pack_string ("new_measure", + new_measure)), GNUNET_JSON_pack_bool ("keep_investigating", keep_investigating), GNUNET_JSON_pack_data_auto ("officer_sig", diff --git a/src/testing/test_kyc_api.c b/src/testing/test_kyc_api.c index 2b19e33f0..423198433 100644 --- a/src/testing/test_kyc_api.c +++ b/src/testing/test_kyc_api.c @@ -699,11 +699,12 @@ run (void *cls, " \"timeframe\":{\"d_us\":3600000000}" " ,\"threshold\":\"EUR:0\"" " ,\"operation_type\":\"BALANCE\"" + " ,\"display_priority\":65536" " ,\"measures\":[\"form-measure\"]" " ,\"verboten\":false" " }" " ]" /* end new rules */ - ",\"new_check\":\"form-check\"" // FIXME: do we need this? + ",\"new_measure\":\"form-measure\"" ",\"custom_measures\":" " {" " \"form-measure\":" @@ -726,7 +727,6 @@ run (void *cls, "get-kyc-info-form", "check-kyc-form", MHD_HTTP_OK), -#if FIXME TALER_TESTING_cmd_post_kyc_form ( "wallet-post-kyc-form", "get-kyc-info-form", @@ -740,7 +740,6 @@ run (void *cls, "wallet-trigger-kyc-for-form-aml", "EUR:500", MHD_HTTP_NO_CONTENT), -#endif TALER_TESTING_cmd_end () }; diff --git a/src/testing/testing_api_cmd_take_aml_decision.c b/src/testing/testing_api_cmd_take_aml_decision.c index f0eca3e39..e61c03efa 100644 --- a/src/testing/testing_api_cmd_take_aml_decision.c +++ b/src/testing/testing_api_cmd_take_aml_decision.c @@ -149,7 +149,7 @@ take_aml_decision_run (void *cls, const json_t *jmeasures = NULL; struct GNUNET_TIME_Timestamp expiration_time = GNUNET_TIME_relative_to_timestamp (ds->expiration_delay); - const char *new_check = NULL; + const char *new_measure = NULL; struct GNUNET_JSON_Specification spec[] = { GNUNET_JSON_spec_array_const ("rules", &jrules), @@ -158,8 +158,8 @@ take_aml_decision_run (void *cls, &jmeasures), NULL), GNUNET_JSON_spec_mark_optional ( - GNUNET_JSON_spec_string ("new_check", - &new_check), + GNUNET_JSON_spec_string ("new_measure", + &new_measure), NULL), GNUNET_JSON_spec_end () }; @@ -356,7 +356,7 @@ take_aml_decision_run (void *cls, h_payto, now, ds->successor_measure, - new_check, + new_measure, expiration_time, num_rules, rules, diff --git a/src/util/aml_signatures.c b/src/util/aml_signatures.c index 49859ef79..a41a0126c 100644 --- a/src/util/aml_signatures.c +++ b/src/util/aml_signatures.c @@ -62,6 +62,11 @@ struct TALER_AmlDecisionPS struct GNUNET_HashCode h_new_rules; /** + * Hash over string with new check. + */ + struct GNUNET_HashCode h_new_measure; + + /** * 0: no investigation, 1: yes investigation. */ uint64_t flags; @@ -76,6 +81,7 @@ TALER_officer_aml_decision_sign ( const struct TALER_PaytoHashP *h_payto, const json_t *new_rules, const json_t *properties, + const char *new_measure, bool to_investigate, const struct TALER_AmlOfficerPrivateKeyP *officer_priv, struct TALER_AmlOfficerSignatureP *officer_sig) @@ -96,6 +102,10 @@ TALER_officer_aml_decision_sign ( &ad.h_properties); TALER_json_hash (new_rules, &ad.h_new_rules); + if (NULL != new_measure) + GNUNET_CRYPTO_hash (new_measure, + strlen (new_measure), + &ad.h_new_measure); GNUNET_CRYPTO_eddsa_sign (&officer_priv->eddsa_priv, &ad, &officer_sig->eddsa_signature); @@ -109,6 +119,7 @@ TALER_officer_aml_decision_verify ( const struct TALER_PaytoHashP *h_payto, const json_t *new_rules, const json_t *properties, + const char *new_measure, bool to_investigate, const struct TALER_AmlOfficerPublicKeyP *officer_pub, const struct TALER_AmlOfficerSignatureP *officer_sig) @@ -129,6 +140,10 @@ TALER_officer_aml_decision_verify ( &ad.h_properties); TALER_json_hash (new_rules, &ad.h_new_rules); + if (NULL != new_measure) + GNUNET_CRYPTO_hash (new_measure, + strlen (new_measure), + &ad.h_new_measure); return GNUNET_CRYPTO_eddsa_verify ( TALER_SIGNATURE_AML_DECISION, &ad, |