commit 288dfa72e86680173f3a6943e95f46807de1626b
parent 656eaab60f20fb3136bcc268a390674404c44908
Author: Christian Grothoff <christian@grothoff.org>
Date: Mon, 2 Feb 2026 18:23:48 +0100
fix #9703
Diffstat:
5 files changed, 157 insertions(+), 37 deletions(-)
diff --git a/src/bank-lib/bank_api_account_token.c b/src/bank-lib/bank_api_account_token.c
@@ -206,17 +206,9 @@ TALER_BANK_account_token (
ath = GNUNET_new (struct TALER_BANK_AccountTokenHandle);
ath->cb = res_cb;
ath->cb_cls = res_cb_cls;
- {
- char *path;
-
- GNUNET_asprintf (&path,
- "accounts/%s/token",
- account_name);
- ath->request_url = TALER_url_join (auth->wire_gateway_url,
- path,
- NULL);
- GNUNET_free (path);
- }
+ ath->request_url = TALER_url_join (auth->core_bank_url,
+ "token",
+ NULL);
if (NULL == ath->request_url)
{
GNUNET_free (ath);
@@ -226,10 +218,6 @@ TALER_BANK_account_token (
GNUNET_log (GNUNET_ERROR_TYPE_INFO,
"Requesting access token at `%s'\n",
ath->request_url);
- ath->post_ctx.headers
- = curl_slist_append (
- ath->post_ctx.headers,
- "Content-Type: application/json");
eh = curl_easy_init ();
if ( (NULL == eh) ||
(GNUNET_OK !=
diff --git a/src/bank-lib/bank_api_parse.c b/src/bank-lib/bank_api_parse.c
@@ -40,6 +40,22 @@ TALER_BANK_auth_parse_cfg (const struct GNUNET_CONFIGURATION_Handle *cfg,
};
char *method;
+ auth->core_bank_url = NULL;
+ if (GNUNET_OK ==
+ GNUNET_CONFIGURATION_get_value_string (cfg,
+ section,
+ "CORE_BANK_URL",
+ &auth->core_bank_url))
+ {
+ if (! TALER_is_web_url (auth->core_bank_url))
+ {
+ GNUNET_log_config_invalid (GNUNET_ERROR_TYPE_ERROR,
+ section,
+ "CORE_BANK_URL",
+ "Not a valid URL");
+ return GNUNET_SYSERR;
+ }
+ }
if (GNUNET_OK !=
GNUNET_CONFIGURATION_get_value_string (cfg,
section,
@@ -51,7 +67,6 @@ TALER_BANK_auth_parse_cfg (const struct GNUNET_CONFIGURATION_Handle *cfg,
"WIRE_GATEWAY_URL");
return GNUNET_SYSERR;
}
-
if (GNUNET_OK !=
GNUNET_CONFIGURATION_get_value_string (cfg,
section,
diff --git a/src/bank-lib/taler-exchange-wire-gateway-client.c b/src/bank-lib/taler-exchange-wire-gateway-client.c
@@ -93,6 +93,11 @@ static struct TALER_BANK_CreditHistoryHandle *chh;
static struct TALER_BANK_DebitHistoryHandle *dhh;
/**
+ * Handle to fetch an access token.
+ */
+static struct TALER_BANK_AccountTokenHandle *ath;
+
+/**
* Handle for executing the wire transfer.
*/
static struct TALER_BANK_TransferHandle *eh;
@@ -133,6 +138,11 @@ do_shutdown (void *cls)
TALER_BANK_debit_history_cancel (dhh);
dhh = NULL;
}
+ if (NULL != ath)
+ {
+ TALER_BANK_account_token_cancel (ath);
+ ath = NULL;
+ }
if (NULL != eh)
{
TALER_BANK_transfer_cancel (eh);
@@ -554,6 +564,76 @@ execute_admin_transfer (void)
/**
+ * Run the actual main operation requested by the user.
+ */
+static void
+execute_tasks (void)
+{
+ if (GNUNET_YES == incoming_history)
+ {
+ execute_credit_history ();
+ return;
+ }
+ if (GNUNET_YES == outgoing_history)
+ {
+ execute_debit_history ();
+ return;
+ }
+ if (NULL != credit_account.full_payto)
+ {
+ execute_wire_transfer ();
+ return;
+ }
+ if (NULL != debit_account.full_payto)
+ {
+ execute_admin_transfer ();
+ return;
+ }
+
+ GNUNET_log (GNUNET_ERROR_TYPE_WARNING,
+ "No operation specified.\n");
+ global_ret = 0;
+ GNUNET_SCHEDULER_shutdown ();
+}
+
+
+/**
+ * Receives an access token to the bank.
+ *
+ * @param cls closure
+ * @param atr response details
+ */
+static void
+access_token_cb (
+ void *cls,
+ const struct TALER_BANK_AccountTokenResponse *atr)
+{
+ (void) cls;
+ ath = NULL;
+ switch (atr->ec)
+ {
+ case TALER_EC_NONE:
+ break; /* continued below */
+ default:
+ GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
+ "Failed to get access token: %s (%u/%d)\n",
+ TALER_ErrorCode_get_hint (atr->ec),
+ atr->http_status,
+ (int) atr->ec);
+ global_ret = EXIT_NOPERMISSION;
+ GNUNET_SCHEDULER_shutdown ();
+ return;
+ }
+ GNUNET_assert (TALER_BANK_AUTH_BASIC == auth.method);
+ GNUNET_free (auth.details.basic.username);
+ GNUNET_free (auth.details.basic.password);
+ auth.method = TALER_BANK_AUTH_BEARER;
+ auth.details.bearer.token = GNUNET_strdup (atr->details.ok.access_token);
+ execute_tasks ();
+}
+
+
+/**
* Main function that will be run.
*
* @param cls closure
@@ -567,6 +647,7 @@ run (void *cls,
const char *cfgfile,
const struct GNUNET_CONFIGURATION_Handle *cfg)
{
+ enum TALER_BANK_TokenScope scope;
(void) cls;
(void) args;
(void) cfgfile;
@@ -653,31 +734,38 @@ run (void *cls,
GNUNET_SCHEDULER_shutdown ();
return;
}
- if (GNUNET_YES == incoming_history)
- {
- execute_credit_history ();
- return;
- }
- if (GNUNET_YES == outgoing_history)
+ if ( (NULL != auth.core_bank_url) &&
+ (TALER_BANK_AUTH_BASIC == auth.method) )
{
- execute_debit_history ();
- return;
- }
- if (NULL != credit_account.full_payto)
- {
- execute_wire_transfer ();
- return;
+ scope = TALER_BANK_TOKEN_SCOPE_READONLY;
+ if (NULL != credit_account.full_payto)
+ scope = TALER_BANK_TOKEN_SCOPE_WIREGATEWAY;
+ if (NULL != debit_account.full_payto)
+ scope = TALER_BANK_TOKEN_SCOPE_READWRITE;
+ ath = TALER_BANK_account_token (ctx,
+ &auth,
+ auth.details.basic.username, // FIXME: why? correct?
+ scope,
+ false, /* refreshable */
+ "taler-exchange-wire-gateway-client CLI token",
+ GNUNET_TIME_UNIT_MINUTES,
+ &access_token_cb,
+ NULL);
+ if (NULL == ath)
+ {
+ GNUNET_break (0);
+ GNUNET_SCHEDULER_shutdown ();
+ return;
+ }
}
- if (NULL != debit_account.full_payto)
+ else
{
- execute_admin_transfer ();
- return;
+ if (TALER_BANK_AUTH_BASIC == auth.method)
+ GNUNET_log (GNUNET_ERROR_TYPE_WARNING,
+ "No CORE_BANK_URL given in `%s' and using basic authentication. Not all taler-wire-gateway implementations allow this.\n",
+ account_section);
+ execute_tasks ();
}
-
- GNUNET_log (GNUNET_ERROR_TYPE_WARNING,
- "No operation specified.\n");
- global_ret = 0;
- GNUNET_SCHEDULER_shutdown ();
}
diff --git a/src/include/taler/taler_bank_service.h b/src/include/taler/taler_bank_service.h
@@ -69,6 +69,15 @@ struct TALER_BANK_AuthenticationData
char *wire_gateway_url;
/**
+ * Base URL including "/accpunts/$USERNAME/" to use
+ * to talk to the core bank API. Useful to get a more
+ * specific access token instead of using basic authentication
+ * the whole time. Optional, can be NULL (as we do not
+ * require the core bank API to actually always be available).
+ */
+ char *core_bank_url;
+
+ /**
* Which authentication method should we use?
*/
enum TALER_BANK_AuthenticationMethod method;
diff --git a/src/testing/test_exchange_api.conf b/src/testing/test_exchange_api.conf
@@ -27,6 +27,7 @@ SERVE = tcp
PORT = 8082
PWD_HASH_CONFIG = { "cost": 4 }
PWD_AUTH_COMPAT = yes
+BASE_URL = http://localhost:8082/
[libeufin-bankdb-postgres]
CONFIG = postgresql:///talercheck
@@ -113,6 +114,7 @@ WIRE_GATEWAY_AUTH_METHOD = basic
USERNAME = Exchange
PASSWORD = password
WIRE_GATEWAY_URL = "http://localhost:8082/accounts/2/taler-wire-gateway/"
+CORE_BANK_URL = "http://localhost:8082/accounts/2/"
[admin-accountcredentials-2]
WIRE_GATEWAY_AUTH_METHOD = basic
@@ -121,6 +123,24 @@ USERNAME = Exchange
PASSWORD = password
WIRE_GATEWAY_URL = "http://localhost:8082/accounts/2/taler-wire-gateway/"
+[exchange-account-3]
+PAYTO_URI = "payto://x-taler-bank/localhost/exchange?receiver-name=Exchange"
+ENABLE_DEBIT = YES
+ENABLE_CREDIT = YES
+
+[exchange-accountcredentials-3]
+WIRE_GATEWAY_AUTH_METHOD = basic
+USERNAME = exchange
+PASSWORD = password
+WIRE_GATEWAY_URL = "http://localhost:8082/accounts/exchange/taler-wire-gateway/"
+CORE_BANK_URL = "http://localhost:8082/accounts/exchange/"
+
+[admin-accountcredentials-3]
+WIRE_GATEWAY_AUTH_METHOD = basic
+USERNAME = exchange
+PASSWORD = password
+WIRE_GATEWAY_URL = "http://localhost:8082/accounts/exchange/taler-wire-gateway/"
+
[exchange-offline]