From ff202ef296527083b7b0c879bfc8363eb429b642 Mon Sep 17 00:00:00 2001 From: Christian Grothoff Date: Sun, 29 Jan 2023 13:58:56 +0100 Subject: [PATCH] KYC: misc. fixes to attribute attestation logic --- .../taler-exchange-httpd_reserves_attest.c | 17 +++++++++---- ...taler-exchange-httpd_reserves_get_attest.c | 6 +++-- src/exchangedb/0003-kyc_attributes.sql | 2 +- src/exchangedb/pg_select_kyc_attributes.c | 3 --- src/include/taler_exchange_service.h | 2 +- src/kyclogic/kyclogic-oauth2.conf | 2 +- src/lib/exchange_api_reserves_attest.c | 6 ++--- src/testing/test_kyc_api.c | 24 +++++++++++++++---- src/testing/test_kyc_api.conf | 1 + src/testing/testing_api_cmd_oauth.c | 7 +++++- .../testing_api_cmd_reserve_get_attestable.c | 10 ++++---- 11 files changed, 55 insertions(+), 25 deletions(-) diff --git a/src/exchange/taler-exchange-httpd_reserves_attest.c b/src/exchange/taler-exchange-httpd_reserves_attest.c index 0d759e1b5..297d8ceec 100644 --- a/src/exchange/taler-exchange-httpd_reserves_attest.c +++ b/src/exchange/taler-exchange-httpd_reserves_attest.c @@ -76,7 +76,7 @@ struct ReserveAttestContext struct TALER_ReserveSignatureP reserve_sig; /** - * Attributes we are affirming. + * Attributes we are affirming. JSON object. */ json_t *json_attest; @@ -140,8 +140,12 @@ reply_reserve_attest_success (struct MHD_Connection *connection, &exchange_sig), GNUNET_JSON_pack_data_auto ("exchange_pub", &exchange_pub), - GNUNET_JSON_pack_array_steal ("attest", - rhc->json_attest)); + GNUNET_JSON_pack_timestamp ("exchange_timestamp", + now), + GNUNET_JSON_pack_timestamp ("expiration_time", + rhc->etime), + GNUNET_JSON_pack_object_steal ("attributes", + rhc->json_attest)); } @@ -201,7 +205,12 @@ kyc_process_cb (void *cls, } } if (! requested) + { + GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, + "Skipping attribute `%s': not requested\n", + name); continue; + } match = true; GNUNET_assert (0 == json_object_set (rsc->json_attest, /* NOT set_new! */ @@ -239,7 +248,7 @@ reserve_attest_transaction (void *cls, struct ReserveAttestContext *rsc = cls; enum GNUNET_DB_QueryStatus qs; - rsc->json_attest = json_array (); + rsc->json_attest = json_object (); GNUNET_assert (NULL != rsc->json_attest); qs = TEH_plugin->select_kyc_attributes (TEH_plugin->cls, &rsc->h_payto, diff --git a/src/exchange/taler-exchange-httpd_reserves_get_attest.c b/src/exchange/taler-exchange-httpd_reserves_get_attest.c index df800caad..b53a8641a 100644 --- a/src/exchange/taler-exchange-httpd_reserves_get_attest.c +++ b/src/exchange/taler-exchange-httpd_reserves_get_attest.c @@ -210,6 +210,7 @@ TEH_handler_reserves_get_attest (struct TEH_RequestContext *rc, &rsc)) { json_decref (rsc.attributes); + rsc.attributes = NULL; return mhd_ret; } } @@ -217,6 +218,7 @@ TEH_handler_reserves_get_attest (struct TEH_RequestContext *rc, if (rsc.not_found) { json_decref (rsc.attributes); + rsc.attributes = NULL; return TALER_MHD_reply_with_error (rc->connection, MHD_HTTP_NOT_FOUND, TALER_EC_EXCHANGE_GENERIC_RESERVE_UNKNOWN, @@ -225,8 +227,8 @@ TEH_handler_reserves_get_attest (struct TEH_RequestContext *rc, return TALER_MHD_REPLY_JSON_PACK ( rc->connection, MHD_HTTP_OK, - GNUNET_JSON_pack_object_steal ("attributes", - rsc.attributes)); + GNUNET_JSON_pack_array_steal ("details", + rsc.attributes)); } diff --git a/src/exchangedb/0003-kyc_attributes.sql b/src/exchangedb/0003-kyc_attributes.sql index 1547466f8..18093358e 100644 --- a/src/exchangedb/0003-kyc_attributes.sql +++ b/src/exchangedb/0003-kyc_attributes.sql @@ -32,7 +32,7 @@ BEGIN ',birthdate VARCHAR' ',collection_time INT8 NOT NULL' ',expiration_time INT8 NOT NULL' - ',encrypted_attributes VARCHAR NOT NULL' + ',encrypted_attributes BYTEA NOT NULL' ') %s ;' ,table_name ,'PARTITION BY HASH (h_payto)' diff --git a/src/exchangedb/pg_select_kyc_attributes.c b/src/exchangedb/pg_select_kyc_attributes.c index e8b2e43db..c9b992da2 100644 --- a/src/exchangedb/pg_select_kyc_attributes.c +++ b/src/exchangedb/pg_select_kyc_attributes.c @@ -75,7 +75,6 @@ get_attributes_cb (void *cls, for (unsigned int i = 0; i < num_results; i++) { - struct TALER_PaytoHashP h_payto; struct GNUNET_TIME_Timestamp collection_time; struct GNUNET_TIME_Timestamp expiration_time; size_t enc_attributes_size; @@ -83,8 +82,6 @@ get_attributes_cb (void *cls, char *provider; char *birthdate = NULL; struct GNUNET_PQ_ResultSpec rs[] = { - GNUNET_PQ_result_spec_auto_from_type ("h_payto", - &h_payto), GNUNET_PQ_result_spec_string ("provider", &provider), GNUNET_PQ_result_spec_allow_null ( diff --git a/src/include/taler_exchange_service.h b/src/include/taler_exchange_service.h index bc98e5329..ede42cc4a 100644 --- a/src/include/taler_exchange_service.h +++ b/src/include/taler_exchange_service.h @@ -5774,7 +5774,7 @@ struct TALER_EXCHANGE_ReservePostAttestResult struct GNUNET_TIME_Timestamp exchange_time; /** - * Current expiration time of the reserve. + * Expiration time of the attested attributes. */ struct GNUNET_TIME_Timestamp expiration_time; diff --git a/src/kyclogic/kyclogic-oauth2.conf b/src/kyclogic/kyclogic-oauth2.conf index 40e0bd127..6f83c0e44 100644 --- a/src/kyclogic/kyclogic-oauth2.conf +++ b/src/kyclogic/kyclogic-oauth2.conf @@ -32,4 +32,4 @@ KYC_OAUTH2_CLIENT_SECRET = password # This is just an example, details will depend on the # provider! # -KYC_OAUTH2_ATTRIBUTE_TEMPLATE = "{"fullname":"{{first_name}} {{last_name}}","phone":"{{phone}}"}" \ No newline at end of file +KYC_OAUTH2_ATTRIBUTE_TEMPLATE = "{"fullname":"{{last_name}}, {{first_name}}","phone":"{{phone}}"}" \ No newline at end of file diff --git a/src/lib/exchange_api_reserves_attest.c b/src/lib/exchange_api_reserves_attest.c index c1cf82761..0a9134e85 100644 --- a/src/lib/exchange_api_reserves_attest.c +++ b/src/lib/exchange_api_reserves_attest.c @@ -97,7 +97,7 @@ handle_reserves_attest_ok (struct TALER_EXCHANGE_ReservesAttestHandle *rsh, struct GNUNET_JSON_Specification spec[] = { GNUNET_JSON_spec_timestamp ("exchange_timestamp", &rs.details.ok.exchange_time), - GNUNET_JSON_spec_timestamp ("exchange_timestamp", + GNUNET_JSON_spec_timestamp ("expiration_time", &rs.details.ok.expiration_time), GNUNET_JSON_spec_fixed_auto ("exchange_sig", &rs.details.ok.exchange_sig), @@ -311,8 +311,8 @@ TALER_EXCHANGE_reserves_attest ( &reserve_sig), GNUNET_JSON_pack_timestamp ("request_timestamp", ts), - GNUNET_JSON_pack_object_steal ("details", - details)); + GNUNET_JSON_pack_array_steal ("details", + details)); if (GNUNET_OK != TALER_curl_easy_post (&rsh->post_ctx, diff --git a/src/testing/test_kyc_api.c b/src/testing/test_kyc_api.c index dc302f3a4..8de5ee7bd 100644 --- a/src/testing/test_kyc_api.c +++ b/src/testing/test_kyc_api.c @@ -23,6 +23,7 @@ */ #include "platform.h" #include "taler_util.h" +#include "taler_attributes.h" #include "taler_signatures.h" #include "taler_exchange_service.h" #include "taler_json_lib.h" @@ -91,15 +92,14 @@ static void run (void *cls, struct TALER_TESTING_Interpreter *is) { - /** - * Test withdraw. - */ struct TALER_TESTING_Command withdraw[] = { CMD_TRANSFER_TO_EXCHANGE ("create-reserve-1", "EUR:15.02"), TALER_TESTING_cmd_check_bank_admin_transfer ( "check-create-reserve-1", - "EUR:15.02", bc.user42_payto, bc.exchange_payto, + "EUR:15.02", + bc.user42_payto, + bc.exchange_payto, "create-reserve-1"), CMD_EXEC_WIREWATCH ("wirewatch-1"), TALER_TESTING_cmd_withdraw_amount ("withdraw-coin-1-no-kyc", @@ -137,6 +137,12 @@ run (void *cls, "EUR:5", 0, /* age restriction off */ MHD_HTTP_OK), + /* Attestations above are bound to the originating *bank* account, + not to the reserve (!). Hence, they are NOT found here! */ + TALER_TESTING_cmd_reserve_get_attestable ("reserve-get-attestable", + "create-reserve-1", + MHD_HTTP_NOT_FOUND, + NULL), TALER_TESTING_cmd_end () }; struct TALER_TESTING_Command spend[] = { @@ -216,6 +222,16 @@ run (void *cls, TALER_TESTING_cmd_check_kyc_get ("wallet-kyc-check", "wallet-kyc-fail", MHD_HTTP_NO_CONTENT), + TALER_TESTING_cmd_reserve_get_attestable ("wallet-get-attestable", + "wallet-kyc-fail", + MHD_HTTP_OK, + TALER_ATTRIBUTE_FULL_NAME, + NULL), + TALER_TESTING_cmd_reserve_attest ("wallet-get-attestable", + "wallet-kyc-fail", + MHD_HTTP_OK, + TALER_ATTRIBUTE_FULL_NAME, + NULL), TALER_TESTING_cmd_end () }; diff --git a/src/testing/test_kyc_api.conf b/src/testing/test_kyc_api.conf index ba706116f..bf6f9e292 100644 --- a/src/testing/test_kyc_api.conf +++ b/src/testing/test_kyc_api.conf @@ -58,6 +58,7 @@ KYC_OAUTH2_INFO_URL = http://localhost:6666/api/user/me KYC_OAUTH2_CLIENT_ID = taler-exchange KYC_OAUTH2_CLIENT_SECRET = exchange-secret KYC_OAUTH2_POST_URL = http://example.com/ +KYC_OAUTH2_ATTRIBUTE_TEMPLATE = "{"fullname":"{{last_name}}, {{first_name}}"}" [kyc-legitimization-balance-high] OPERATION_TYPE = BALANCE diff --git a/src/testing/testing_api_cmd_oauth.c b/src/testing/testing_api_cmd_oauth.c index 045b5eefa..514b4ac8c 100644 --- a/src/testing/testing_api_cmd_oauth.c +++ b/src/testing/testing_api_cmd_oauth.c @@ -188,7 +188,12 @@ handler_cb (void *cls, "data", GNUNET_JSON_PACK ( GNUNET_JSON_pack_string ("id", - "XXXID12345678")))); + "XXXID12345678"), + GNUNET_JSON_pack_string ("first_name", + "Bob"), + GNUNET_JSON_pack_string ("last_name", + "Builder") + ))); return TALER_MHD_reply_json_steal (connection, body, MHD_HTTP_OK); diff --git a/src/testing/testing_api_cmd_reserve_get_attestable.c b/src/testing/testing_api_cmd_reserve_get_attestable.c index 29c8f6a3a..3b400a36c 100644 --- a/src/testing/testing_api_cmd_reserve_get_attestable.c +++ b/src/testing/testing_api_cmd_reserve_get_attestable.c @@ -122,23 +122,23 @@ get_attestable_run (void *cls, struct TALER_TESTING_Interpreter *is) { struct GetAttestableState *ss = cls; - const struct TALER_TESTING_Command *create_reserve; + const struct TALER_TESTING_Command *ref_reserve; const struct TALER_ReservePrivateKeyP *reserve_priv; const struct TALER_ReservePublicKeyP *reserve_pub; ss->is = is; - create_reserve + ref_reserve = TALER_TESTING_interpreter_lookup_command (is, ss->reserve_reference); - if (NULL == create_reserve) + if (NULL == ref_reserve) { GNUNET_break (0); TALER_TESTING_interpreter_fail (is); return; } if (GNUNET_OK == - TALER_TESTING_get_trait_reserve_priv (create_reserve, + TALER_TESTING_get_trait_reserve_priv (ref_reserve, &reserve_priv)) { GNUNET_CRYPTO_eddsa_key_get_public (&reserve_priv->eddsa_priv, @@ -147,7 +147,7 @@ get_attestable_run (void *cls, else { if (GNUNET_OK != - TALER_TESTING_get_trait_reserve_pub (create_reserve, + TALER_TESTING_get_trait_reserve_pub (ref_reserve, &reserve_pub)) { GNUNET_break (0);