merchant

Merchant backend to process payments, run by merchants
Log | Files | Refs | Submodules | README | LICENSE

commit 819981a623029949ba904a1025fb4a473f610c2f
parent a62f5547684814d9bfad5a3ad94e810626a94570
Author: Florian Dold <florian@dold.me>
Date:   Fri,  8 May 2026 15:17:27 +0200

allow arguments in 2FA helper binaries

Diffstat:
Msrc/backend/taler-merchant-httpd_post-challenge-ID.c | 85++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++-----------
1 file changed, 74 insertions(+), 11 deletions(-)

diff --git a/src/backend/taler-merchant-httpd_post-challenge-ID.c b/src/backend/taler-merchant-httpd_post-challenge-ID.c @@ -378,6 +378,55 @@ transmission_done_cb (void *cls, /** + * Resolve a binary name via PATH. + * + * Needed because the GNUnet process helpers to not support + * an execp equivalent at present. + * + * @param binary_name name to search for + * @returns resolved path or NULL if not found + */ +static char * +resolve_path (const char *binary_name) +{ + char *path_env; + char full_path[2048]; + char *dir; + char *path_copy; + + if (NULL != strchr (binary_name, + '/')) + { + /* Already a full path, do not search. */ + return GNUNET_strdup (binary_name); + } + path_env = getenv ("PATH"); + if (path_env == NULL) + return NULL; + /* Duplicate PATH because strtok modifies the string it parses */ + path_copy = GNUNET_strdup (path_env); + dir = strtok (path_copy, ":"); + while (dir != NULL) + { + snprintf (full_path, + sizeof(full_path), + "%s/%s", + dir, + binary_name); + if (0 == access (full_path, + X_OK)) + { + GNUNET_free (path_copy); + return GNUNET_strdup (full_path); + } + dir = strtok (NULL, ":"); + } + GNUNET_free (path_copy); + return NULL; +} + + +/** * Setup challenge code for @a mfa and send it to the * @a required_address; on success. * @@ -387,7 +436,9 @@ static void phase_send_challenge (struct MfaState *mfa) { const char *prog = NULL; + char *binary_path = NULL; unsigned long long challenge_num; + char **cmd_argv = NULL; challenge_num = (unsigned long long) GNUNET_CRYPTO_random_u64 (GNUNET_CRYPTO_QUALITY_NONCE, @@ -424,7 +475,7 @@ phase_send_challenge (struct MfaState *mfa) MHD_HTTP_NOT_IMPLEMENTED, TALER_EC_GENERIC_FEATURE_NOT_IMPLEMENTED, "#10327"); - return; + goto done; } if (NULL == prog) { @@ -433,12 +484,21 @@ phase_send_challenge (struct MfaState *mfa) MHD_HTTP_INTERNAL_SERVER_ERROR, TALER_EC_GENERIC_INTERNAL_INVARIANT_FAILURE, TALER_MERCHANT_MFA_channel_to_string (mfa->channel)); - return; + goto done; } { /* Start child process and feed pipe */ struct GNUNET_DISK_PipeHandle *p; struct GNUNET_DISK_FileHandle *pipe_stdin; + const char *extra_args[] = { + mfa->required_address, + NULL, + }; + + cmd_argv = TALER_words_split (prog, + extra_args); + + GNUNET_assert (NULL != cmd_argv[0]); p = GNUNET_DISK_pipe (GNUNET_DISK_PF_BLOCKING_RW); if (NULL == p) @@ -447,7 +507,7 @@ phase_send_challenge (struct MfaState *mfa) MHD_HTTP_INTERNAL_SERVER_ERROR, TALER_EC_GENERIC_ALLOCATION_FAILURE, "pipe"); - return; + goto done; } mfa->child = GNUNET_process_create (GNUNET_OS_INHERIT_STD_ERR); GNUNET_assert (GNUNET_OK == @@ -455,12 +515,12 @@ phase_send_challenge (struct MfaState *mfa) mfa->child, GNUNET_process_option_inherit_rpipe (p, STDIN_FILENO))); - if (GNUNET_OK != - GNUNET_process_run_command_va (mfa->child, - prog, - prog, - mfa->required_address, - NULL)) + binary_path = resolve_path (cmd_argv[0]); + if ( (NULL == binary_path) || + (GNUNET_OK != + GNUNET_process_run_command_argv (mfa->child, + binary_path, + (const char **) cmd_argv)) ) { GNUNET_process_destroy (mfa->child); mfa->child = NULL; @@ -470,7 +530,7 @@ phase_send_challenge (struct MfaState *mfa) MHD_HTTP_BAD_GATEWAY, TALER_EC_MERCHANT_TAN_MFA_HELPER_EXEC_FAILED, "exec"); - return; + goto done; } pipe_stdin = GNUNET_DISK_pipe_detach_end (p, @@ -510,7 +570,7 @@ phase_send_challenge (struct MfaState *mfa) MHD_HTTP_BAD_GATEWAY, TALER_EC_MERCHANT_TAN_MFA_HELPER_EXEC_FAILED, "write"); - return; + goto done; } mfa->msg_off += ret; off += ret; @@ -520,6 +580,9 @@ phase_send_challenge (struct MfaState *mfa) } } mfa->phase = MFA_PHASE_SUSPENDING; +done: + GNUNET_free (binary_path); + TALER_words_destroy (cmd_argv); }