commit 3340ddb38d5af7573f2715f39d847a80c052dea8
parent d4f372748e094177d1b6a36cf685ada5afb066b6
Author: Christian Grothoff <christian@grothoff.org>
Date: Tue, 7 Apr 2026 20:45:34 +0200
fix issue where merchant backend with wrong public key would get access token (ugh) and KYC OK if account was previously involved in reserve_in; breaks kyc-fail-recover-simple
Diffstat:
6 files changed, 25 insertions(+), 95 deletions(-)
diff --git a/src/exchange/taler-exchange-httpd_common_kyc.c b/src/exchange/taler-exchange-httpd_common_kyc.c
@@ -1609,11 +1609,12 @@ legitimization_check_run (
break;
}
GNUNET_log (GNUNET_ERROR_TYPE_INFO,
- "get_kyc_rules returned %d/%d/%d/%d\n",
+ "get_kyc_rules returned %d/%d/%d/%d(%d)\n",
(int) qs,
! no_account_pub,
! no_reserve_pub,
- NULL != jrules);
+ NULL != jrules,
+ (int) lch->have_merchant_pub);
lch->lcr.kyc.have_account_pub
= ! no_account_pub;
diff --git a/src/exchange/taler-exchange-httpd_get-kyc-check-H_NORMALIZED_PAYTO.c b/src/exchange/taler-exchange-httpd_get-kyc-check-H_NORMALIZED_PAYTO.c
@@ -83,7 +83,7 @@ struct KycPoller
/**
* Public key from the account owner authorizing this
- * operation. Optional, see @e have_pub.
+ * operation.
*/
union TALER_AccountPublicKeyP account_pub;
@@ -103,11 +103,6 @@ struct KycPoller
*/
bool suspended;
- /**
- * True if we have an @e account_pub.
- */
- bool have_pub;
-
};
@@ -218,7 +213,6 @@ TEH_handler_kyc_check (
struct KycPoller *kyp = rc->rh_ctx;
json_t *jrules = NULL;
json_t *jlimits = NULL;
- union TALER_AccountPublicKeyP reserve_pub;
struct TALER_AccountAccessTokenP access_token;
bool aml_review;
bool kyc_required;
@@ -229,6 +223,7 @@ TEH_handler_kyc_check (
if (NULL == kyp)
{
bool sig_required = true;
+ bool acc_required = true;
kyp = GNUNET_new (struct KycPoller);
kyp->connection = rc->connection;
@@ -261,7 +256,7 @@ TEH_handler_kyc_check (
rc->connection,
TALER_HTTP_HEADER_ACCOUNT_OWNER_PUBKEY,
&kyp->account_pub,
- kyp->have_pub);
+ acc_required);
TALER_MHD_parse_request_timeout (rc->connection,
&kyp->timeout);
{
@@ -327,16 +322,13 @@ TEH_handler_kyc_check (
bool do_suspend;
GNUNET_log (GNUNET_ERROR_TYPE_INFO,
- "Looking up KYC requirements for account %s (%s)\n",
- TALER_B2S (&kyp->h_payto),
- kyp->have_pub ? "with account-pub" : "legacy wallet");
+ "Looking up KYC requirements for account %s\n",
+ TALER_B2S (&kyp->h_payto));
qs = TEH_plugin->lookup_kyc_requirement_by_row (
TEH_plugin->cls,
&kyp->h_payto,
- kyp->have_pub,
&kyp->account_pub,
&is_wallet,
- &reserve_pub.reserve_pub,
&access_token,
&rule_gen,
&jrules,
@@ -375,14 +367,9 @@ TEH_handler_kyc_check (
(unsigned long long) kyp->min_rule,
(int) kyp->lpt);
access_ok =
- ( (! GNUNET_is_zero (&kyp->account_pub) &&
- (GNUNET_OK ==
- TALER_account_kyc_auth_verify (&kyp->account_pub,
- &kyp->account_sig)) ) ||
- (! GNUNET_is_zero (&reserve_pub) &&
- (GNUNET_OK ==
- TALER_account_kyc_auth_verify (&reserve_pub,
- &kyp->account_sig)) ) );
+ (GNUNET_OK ==
+ TALER_account_kyc_auth_verify (&kyp->account_pub,
+ &kyp->account_sig));
if (GNUNET_TIME_absolute_is_future (kyp->timeout) &&
(rule_gen <= kyp->min_rule) )
{
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,9 +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
+ IN in_account_pub BYTEA,
OUT out_access_token BYTEA, -- NULL if 'out_not_found'
OUT out_jrules JSONB, -- NULL allowed
OUT out_is_wallet BOOLEAN, -- NULL allowed
@@ -57,11 +55,9 @@ THEN
END IF;
-- It is definitively OK if we were given a public key AND it matches
-my_ok = (in_account_pub IS NOT NULL) AND
- (my_wtrec.target_pub = in_account_pub);
+my_ok = (my_wtrec.target_pub = in_account_pub);
-IF ( (NOT my_ok) AND
- (in_account_pub IS NOT NULL) )
+IF (NOT my_ok)
THEN
-- We were given an in_account_pub, but it did not match the
-- target pub.
@@ -92,11 +88,9 @@ THEN
END IF;
END IF;
-IF (NOT my_ok AND
- ( (in_account_pub IS NOT NULL) OR
- (my_wtrec.target_pub IS NULL) ) )
+IF (NOT my_ok)
THEN
- -- RAISE WARNING 'No match and target_pub is NOT NULL';
+ -- RAISE WARNING 'No match';
-- We failed to find a matching public key for in_account_pub, and
-- either the client provided a specific one to match OR
-- we could not return any one that could even work, which means
@@ -112,7 +106,6 @@ END IF;
out_not_found = FALSE;
out_is_wallet = my_wtrec.is_wallet;
-out_account_pub = my_wtrec.target_pub;
out_access_token = my_wtrec.access_token;
-- Check if there are active measures for the account.
@@ -141,18 +134,4 @@ THEN
out_rule_gen=my_lorec.outcome_serial_id;
END IF;
--- Check most recent reserve_in wire transfer, we also
--- allow that reserve public key for authentication!
--- Only needed for old wallets that don't pass
--- in the account pub explicitly.
-SELECT reserve_pub
- INTO out_reserve_pub
- FROM reserves_in
- WHERE wire_source_h_payto
- IN (SELECT wt.wire_target_h_payto
- FROM wire_targets wt
- WHERE h_normalized_payto=in_h_normalized_payto)
- ORDER BY execution_date DESC, reserve_in_serial_id DESC
- LIMIT 1;
-
END $$;
diff --git a/src/exchangedb/pg_lookup_kyc_requirement_by_row.c b/src/exchangedb/pg_lookup_kyc_requirement_by_row.c
@@ -30,10 +30,8 @@ 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,
+ const union TALER_AccountPublicKeyP *account_pub,
enum GNUNET_GenericReturnValue *is_wallet,
- struct TALER_ReservePublicKeyP *reserve_pub,
struct TALER_AccountAccessTokenP *access_token,
uint64_t *rule_gen,
json_t **jrules,
@@ -43,9 +41,7 @@ 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_auto_from_type (account_pub),
GNUNET_PQ_query_param_end
};
bool bis_wallet;
@@ -53,14 +49,6 @@ TEH_PG_lookup_kyc_requirement_by_row (
bool not_found;
struct GNUNET_PQ_ResultSpec rs[] = {
GNUNET_PQ_result_spec_allow_null (
- GNUNET_PQ_result_spec_auto_from_type ("account_pub",
- account_pub),
- NULL),
- GNUNET_PQ_result_spec_allow_null (
- GNUNET_PQ_result_spec_auto_from_type ("reserve_pub",
- reserve_pub),
- NULL),
- GNUNET_PQ_result_spec_allow_null (
GNUNET_PQ_result_spec_auto_from_type ("access_token",
access_token),
NULL),
@@ -95,22 +83,13 @@ TEH_PG_lookup_kyc_requirement_by_row (
*aml_review = false;
*is_wallet = GNUNET_SYSERR;
*rule_gen = 0;
- if (! have_pub)
- memset (account_pub,
- 0,
- sizeof (*account_pub));
- memset (reserve_pub,
- 0,
- sizeof (*reserve_pub));
memset (access_token,
0,
sizeof (*access_token));
PREPARE (pg,
"lookup_kyc_requirement_by_row",
"SELECT "
- " out_account_pub AS account_pub"
- ",out_reserve_pub AS reserve_pub"
- ",out_access_token AS access_token"
+ " out_access_token AS access_token"
",out_jrules::TEXT AS jrules"
",out_is_wallet AS is_wallet"
",out_not_found AS not_found"
diff --git a/src/exchangedb/pg_lookup_kyc_requirement_by_row.h b/src/exchangedb/pg_lookup_kyc_requirement_by_row.h
@@ -31,16 +31,10 @@
*
* @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 account_pub set to public key of the account
+ * needed to authorize access
* @param[out] is_wallet set to #GNUNET_YES if the account is
* that of a wallet (#GNUNET_SYSERR is used if unknown)
- * @param[out] reserve_pub set to last reserve public key
- * used for a wire transfer from the account to the
- * exchange; alternatively used to authorize access,
- * all zeros if not known
* @param[out] access_token set to the access token to begin
* work on KYC processes for this account
* @param[out] rule_gen row ID of the last decision this
@@ -57,10 +51,8 @@ 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,
+ const union TALER_AccountPublicKeyP *account_pub,
enum GNUNET_GenericReturnValue *is_wallet,
- struct TALER_ReservePublicKeyP *reserve_pub,
struct TALER_AccountAccessTokenP *access_token,
uint64_t *rule_gen,
json_t **jrules,
diff --git a/src/include/taler/taler_exchangedb_plugin.h b/src/include/taler/taler_exchangedb_plugin.h
@@ -7243,16 +7243,10 @@ struct TALER_EXCHANGEDB_Plugin
*
* @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[in,out] account_pub set to public key of the account
- * needed to authorize access, all zeros if not known
+ * @param account_pub set to public key of the account
+ * needed to authorize access
* @param[out] is_wallet set to #GNUNET_YES if the account is
* that of a wallet (#GNUNET_SYSERR is used if unknown)
- * @param[out] reserve_pub set to last reserve public key
- * used for a wire transfer from the account to the
- * exchange; alternatively used to authorize access,
- * all zeros if not known
* @param[out] access_token set to the access token to begin
* work on KYC processes for this account
* @param[out] rule_gen row ID of the last decision this
@@ -7269,10 +7263,8 @@ 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,
+ const union TALER_AccountPublicKeyP *account_pub,
enum GNUNET_GenericReturnValue *is_wallet,
- struct TALER_ReservePublicKeyP *reserve_pub,
struct TALER_AccountAccessTokenP *access_token,
uint64_t *rule_gen,
json_t **jrules,