commit ed93a77ce51c41c52868318bb955e3462e171251
parent a14ef50b776e583c5730ea7b0a514c04322c3ee0
Author: Christian Grothoff <christian@grothoff.org>
Date: Wed, 28 May 2025 19:49:13 +0200
fix #10044
Diffstat:
7 files changed, 69 insertions(+), 14 deletions(-)
diff --git a/src/exchange/taler-exchange-httpd_kyc-check.c b/src/exchange/taler-exchange-httpd_kyc-check.c
@@ -77,6 +77,12 @@ struct KycPoller
union TALER_AccountSignatureP account_sig;
/**
+ * Public key from the account owner authorizing this
+ * operation. Optional, see @e have_pub.
+ */
+ union TALER_AccountPublicKeyP account_pub;
+
+ /**
* Generation of KYC rules already known to the client
* (when long-polling). Do not send these rules again.
*/
@@ -92,6 +98,11 @@ struct KycPoller
*/
bool suspended;
+ /**
+ * True if we have an @e account_pub.
+ */
+ bool have_pub;
+
};
@@ -197,7 +208,6 @@ TEH_handler_kyc_check (
struct KycPoller *kyp = rc->rh_ctx;
json_t *jrules = NULL;
json_t *jlimits = NULL;
- union TALER_AccountPublicKeyP account_pub;
union TALER_AccountPublicKeyP reserve_pub;
struct TALER_AccountAccessTokenP access_token;
bool aml_review;
@@ -236,6 +246,11 @@ TEH_handler_kyc_check (
TALER_HTTP_HEADER_ACCOUNT_OWNER_SIGNATURE,
&kyp->account_sig,
sig_required);
+ TALER_MHD_parse_request_header_auto (
+ rc->connection,
+ TALER_HTTP_HEADER_ACCOUNT_OWNER_PUBKEY,
+ &kyp->account_pub,
+ kyp->have_pub);
TALER_MHD_parse_request_timeout (rc->connection,
&kyp->timeout);
{
@@ -308,7 +323,8 @@ TEH_handler_kyc_check (
qs = TEH_plugin->lookup_kyc_requirement_by_row (
TEH_plugin->cls,
&kyp->h_payto,
- &account_pub,
+ kyp->have_pub,
+ &kyp->account_pub,
&is_wallet,
&reserve_pub.reserve_pub,
&access_token,
@@ -345,9 +361,9 @@ TEH_handler_kyc_check (
else
{
access_ok =
- ( (! GNUNET_is_zero (&account_pub) &&
+ ( (! GNUNET_is_zero (&kyp->account_pub) &&
(GNUNET_OK ==
- TALER_account_kyc_auth_verify (&account_pub,
+ TALER_account_kyc_auth_verify (&kyp->account_pub,
&kyp->account_sig)) ) ||
(! GNUNET_is_zero (&reserve_pub) &&
(GNUNET_OK ==
@@ -410,7 +426,7 @@ TEH_handler_kyc_check (
{
json_decref (jrules);
jrules = NULL;
- if (GNUNET_is_zero (&account_pub))
+ if (GNUNET_is_zero (&kyp->account_pub))
{
GNUNET_break_op (0);
return TALER_MHD_reply_with_error (
@@ -427,7 +443,7 @@ TEH_handler_kyc_check (
TALER_JSON_pack_ec (
TALER_EC_EXCHANGE_KYC_CHECK_AUTHORIZATION_FAILED),
GNUNET_JSON_pack_data_auto ("expected_account_pub",
- &account_pub));
+ &kyp->account_pub));
}
GNUNET_log (GNUNET_ERROR_TYPE_INFO,
diff --git a/src/exchangedb/exchange_do_lookup_kyc_requirement_by_row.sql b/src/exchangedb/exchange_do_lookup_kyc_requirement_by_row.sql
@@ -19,6 +19,7 @@ DROP FUNCTION IF EXISTS exchange_do_lookup_kyc_requirement_by_row;
CREATE FUNCTION exchange_do_lookup_kyc_requirement_by_row(
IN in_h_normalized_payto BYTEA,
+ IN in_account_pub BYTEA, -- NULL allowed
OUT out_account_pub BYTEA, -- NULL allowed
OUT out_reserve_pub BYTEA, -- NULL allowed
OUT out_access_token BYTEA, -- NULL if 'out_not_found'
@@ -33,6 +34,7 @@ AS $$
DECLARE
my_wtrec RECORD;
my_lorec RECORD;
+ my_ok BOOL;
BEGIN
-- Find the access token and the current account public key.
@@ -43,7 +45,28 @@ SELECT access_token
FROM kyc_targets
WHERE h_normalized_payto=in_h_normalized_payto;
-IF NOT FOUND
+my_ok = FOUND;
+
+IF ( (NOT my_ok) AND
+ (in_account_pub IS NOT NULL) AND
+ (my_wtrec.target_pub!=in_account_pub) )
+THEN
+ -- Try to see if the in_account_pub appears in ANY reserve_in
+ -- for this account.
+ PERFORM
+ FROM reserves_in
+ WHERE wire_source_h_payto IN
+ (SELECT wire_target_h_payto
+ FROM wire_targets
+ WHERE h_normalized_payto=in_h_normalized_payto);
+ IF FOUND
+ THEN
+ my_wtrec.target_pub = in_account_pub;
+ my_ok = TRUE;
+ END IF;
+END IF;
+
+IF NOT my_ok
THEN
out_not_found = TRUE;
out_kyc_required = FALSE;
diff --git a/src/exchangedb/pg_lookup_kyc_requirement_by_row.c b/src/exchangedb/pg_lookup_kyc_requirement_by_row.c
@@ -30,6 +30,7 @@ enum GNUNET_DB_QueryStatus
TEH_PG_lookup_kyc_requirement_by_row (
void *cls,
const struct TALER_NormalizedPaytoHashP *h_payto,
+ bool have_pub,
union TALER_AccountPublicKeyP *account_pub,
bool *is_wallet,
struct TALER_ReservePublicKeyP *reserve_pub,
@@ -42,6 +43,9 @@ TEH_PG_lookup_kyc_requirement_by_row (
struct PostgresClosure *pg = cls;
struct GNUNET_PQ_QueryParam params[] = {
GNUNET_PQ_query_param_auto_from_type (h_payto),
+ have_pub
+ ? GNUNET_PQ_query_param_auto_from_type (account_pub)
+ : GNUNET_PQ_query_param_null (),
GNUNET_PQ_query_param_end
};
bool not_found;
@@ -111,7 +115,7 @@ TEH_PG_lookup_kyc_requirement_by_row (
",out_kyc_required AS kyc_required"
",out_rule_gen AS rule_gen"
" FROM exchange_do_lookup_kyc_requirement_by_row"
- " ($1);");
+ " ($1, $2);");
qs = GNUNET_PQ_eval_prepared_singleton_select (
pg->conn,
"lookup_kyc_requirement_by_row",
diff --git a/src/exchangedb/pg_lookup_kyc_requirement_by_row.h b/src/exchangedb/pg_lookup_kyc_requirement_by_row.h
@@ -31,6 +31,8 @@
*
* @param cls closure
* @param h_payto identifies account to look up requirement for
+ * @param have_pub true if @a account_pub is provided as an input,
+ * false if it is merely provided for the public key to be returned
* @param[out] account_pub set to public key of the account
* needed to authorize access, all zeros if not known
* @param[out] is_wallet set to true if the account is
@@ -55,6 +57,7 @@ enum GNUNET_DB_QueryStatus
TEH_PG_lookup_kyc_requirement_by_row (
void *cls,
const struct TALER_NormalizedPaytoHashP *h_payto,
+ bool have_pub,
union TALER_AccountPublicKeyP *account_pub,
bool *is_wallet,
struct TALER_ReservePublicKeyP *reserve_pub,
diff --git a/src/include/taler_crypto_lib.h b/src/include/taler_crypto_lib.h
@@ -61,6 +61,11 @@
#define TALER_HTTP_HEADER_ACCOUNT_OWNER_SIGNATURE "Account-Owner-Signature"
/**
+ * Account owner public key for KYC.
+ */
+#define TALER_HTTP_HEADER_ACCOUNT_OWNER_PUBKEY "Account-Owner-Pub"
+
+/**
* Possible algorithms for confirmation code generation.
*/
enum TALER_MerchantConfirmationAlgorithm
diff --git a/src/include/taler_exchangedb_plugin.h b/src/include/taler_exchangedb_plugin.h
@@ -7158,7 +7158,9 @@ struct TALER_EXCHANGEDB_Plugin
*
* @param cls closure
* @param h_payto identifies account to look up requirement for
- * @param[out] account_pub set to public key of the account
+ * @param have_pub true if @a account_pub is provided as an input,
+ * false if it is merely provided for the public key to be returned
+ * @param[in,out] account_pub set to public key of the account
* needed to authorize access, all zeros if not known
* @param[out] is_wallet set to true if the account is
* that of a wallet (false is used if unknown)
@@ -7182,6 +7184,7 @@ struct TALER_EXCHANGEDB_Plugin
(*lookup_kyc_requirement_by_row)(
void *cls,
const struct TALER_NormalizedPaytoHashP *h_payto,
+ bool have_pub,
union TALER_AccountPublicKeyP *account_pub,
bool *is_wallet,
struct TALER_ReservePublicKeyP *reserve_pub,
diff --git a/src/include/taler_mhd_lib.h b/src/include/taler_mhd_lib.h
@@ -788,11 +788,12 @@ TALER_MHD_parse_request_header_data (struct MHD_Connection *connection,
* #GNUNET_NO if the argument is absent or malformed
* #GNUNET_SYSERR on internal error (error response could not be sent)
*/
-#define TALER_MHD_parse_request_header_auto(connection,name,val,required) \
- do { \
- bool p; \
- switch (TALER_MHD_parse_request_header_data (connection, name, \
- val, sizeof (*val), &p)) \
+#define TALER_MHD_parse_request_header_auto(connection,name,val,required) \
+ do { \
+ bool p; \
+ switch (TALER_MHD_parse_request_header_data (connection, name, \
+ val, sizeof (*val), \
+ &p)) \
{ \
case GNUNET_SYSERR: \
GNUNET_break (0); \