exchange

Base system with REST service to issue digital coins, run by the payment service provider
Log | Files | Refs | Submodules | README | LICENSE

commit 5f0500232d861461f43c523536fadf4e8e147ab8
parent 8f8dc36bdbef15c2b079c87a1f7fc02198cf5e4e
Author: Christian Grothoff <grothoff@gnunet.org>
Date:   Mon, 22 Dec 2025 15:17:33 +0100

attempt to fix #10760 (but test still fails)

Diffstat:
Msrc/kyclogic/kyclogic_api.c | 371+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++------------------
Msrc/testing/testing_api_cmd_auditor_exec_auditor.c | 2+-
Msrc/testing/testing_api_cmd_auditor_exec_auditor_dbinit.c | 2+-
Msrc/testing/testing_api_cmd_exec_aggregator.c | 2+-
Msrc/testing/testing_api_cmd_exec_auditor-offline.c | 2+-
Msrc/testing/testing_api_cmd_exec_closer.c | 2+-
Msrc/testing/testing_api_cmd_exec_expire.c | 2+-
Msrc/testing/testing_api_cmd_exec_router.c | 2+-
Msrc/testing/testing_api_cmd_exec_transfer.c | 2+-
Msrc/testing/testing_api_cmd_exec_wget.c | 2+-
Msrc/testing/testing_api_cmd_exec_wirewatch.c | 2+-
Msrc/testing/testing_api_cmd_kyc_wallet_get.c | 2++
Msrc/testing/testing_api_cmd_offline_sign_extensions.c | 2+-
Msrc/testing/testing_api_cmd_offline_sign_global_fees.c | 2+-
Msrc/testing/testing_api_cmd_offline_sign_keys.c | 2+-
Msrc/testing/testing_api_cmd_offline_sign_wire_fees.c | 2+-
Msrc/testing/testing_api_cmd_system_start.c | 2+-
17 files changed, 304 insertions(+), 99 deletions(-)

diff --git a/src/kyclogic/kyclogic_api.c b/src/kyclogic/kyclogic_api.c @@ -353,6 +353,108 @@ static json_t *wallet_default_lrs; static json_t *bankaccount_default_lrs; +/** + * Convert the ASCII string in @a s to lower-case. Here, + * @a s must only contain the characters "[a-zA-Z0-9.-_]", + * otherwise the function fails and returns false. + * + * @param[in,out] s string to lower-case + * @return true on success, if false is returned, the + * value in @a s may be partially transformed + */ +static bool +ascii_lower (char *s) +{ + for (size_t i = 0; '\0' != s[i]; i++) + { + int c = (int) s[i]; + + if (isdigit (c)) + continue; + if (isalpha (c)) + { + s[i] = (char) tolower (c); + continue; + } + if ( ('-' == c) || + ('.' == c) || + ('_' == c) ) + continue; + return false; + } + return true; +} + + +/** + * Convert the ASCII string in @a s to lower-case. Here, + * @a s must only contain the characters "[a-zA-Z0-9 \n\t;.-_]", + * otherwise the function fails and returns false. + * Note that the main difference to ascii_lower is that + * " \n\t;" are allowed. + * + * @param[in,out] s string to lower-case + * @return true on success, if false is returned, the + * value in @a s may be partially transformed + */ +static bool +token_list_lower (char *s) +{ + for (size_t i = 0; '\0' != s[i]; i++) + { + int c = (int) s[i]; + + if (isdigit (c)) + continue; + if (isalpha (c)) + { + s[i] = (char) tolower (c); + continue; + } + if ( ('-' == c) || + (' ' == c) || + ('.' == c) || + ('\n' == c) || + ('\t' == c) || + (';' == c) || + ('_' == c) ) + continue; + return false; + } + return true; +} + + +/** + * Check that @a section begins with @a prefix and afterwards + * only contains characters "[a-zA-Z0-9-_]". If so, convert all + * characters to lower-case and return the result. + * + * @param prefix section prefix to match + * @param section section name to match against + * @return NULL if @a prefix does not match or @a section contains + * invalid characters after the prefix + */ +static char * +normalize_section_with_prefix (const char *prefix, + const char *section) +{ + char *ret; + + if (0 != strncasecmp (section, + prefix, + strlen (prefix))) + return NULL; /* no match */ + ret = GNUNET_strdup (section); + if (! ascii_lower (ret)) + { + GNUNET_free (ret); + return NULL; + } + return ret; +} + + struct GNUNET_TIME_Timestamp TALER_KYCLOGIC_rules_get_expiration ( const struct TALER_KYCLOGIC_LegitimizationRuleSet *lrs) @@ -511,17 +613,40 @@ check_measure (const struct TALER_KYCLOGIC_Measure *measure) { const struct TALER_KYCLOGIC_KycCheck *check; - check = find_check (measure->check_name); - if ( (NULL == check) && - (0 != strcasecmp (measure->check_name, - "SKIP")) ) + if (! ascii_lower (measure->measure_name)) { - GNUNET_log (GNUNET_ERROR_TYPE_ERROR, - "Unknown check `%s' used in measure `%s'\n", - measure->check_name, - measure->measure_name); + GNUNET_break (0); + return false; + } + if (! ascii_lower (measure->check_name)) + { + GNUNET_break (0); + return false; + } + if ( (NULL != measure->prog_name) && + (! ascii_lower (measure->prog_name)) ) + { + GNUNET_break (0); return false; } + + if (0 == strcasecmp (measure->check_name, + "skip")) + { + check = NULL; + } + else + { + check = find_check (measure->check_name); + if (NULL == check) + { + GNUNET_log (GNUNET_ERROR_TYPE_ERROR, + "Unknown check `%s' used in measure `%s'\n", + measure->check_name, + measure->measure_name); + return false; + } + } if ( (NULL == check) || (TALER_KYCLOGIC_CT_INFO != check->type) ) { @@ -553,12 +678,12 @@ check_measure (const struct TALER_KYCLOGIC_Measure *measure) } } if (0 == strcasecmp (measure->check_name, - "SKIP")) + "skip")) { if (0 != program->num_required_attributes) { GNUNET_log (GNUNET_ERROR_TYPE_ERROR, - "AML program `%s' of measure `%s' has required attributes, but check is of type `SKIP' and thus cannot provide any!\n", + "AML program `%s' of measure `%s' has required attributes, but check is of type `skip' and thus cannot provide any!\n", program->program_name, measure->measure_name); return false; @@ -603,10 +728,10 @@ check_measure (const struct TALER_KYCLOGIC_Measure *measure) measure->prog_name, measure->measure_name); if (0 == strcasecmp (measure->check_name, - "SKIP")) + "skip")) { GNUNET_log (GNUNET_ERROR_TYPE_ERROR, - "INFO check of measure `%s' should not be called 'SKIP'.\n", + "INFO check of measure `%s' should not be called `skip'.\n", measure->measure_name); return false; } @@ -732,6 +857,12 @@ TALER_KYCLOGIC_rules_parse (const json_t *jlrs) = (NULL == successor_measure) ? NULL : GNUNET_strdup (successor_measure); + if ( (NULL != lrs->successor_measure) && + (! ascii_lower (lrs->successor_measure)) ) + { + GNUNET_break (0); + goto cleanup; + } lrs->num_custom_measures = (unsigned int) json_object_size (jcustom_measures); if (((size_t) lrs->num_custom_measures) != @@ -907,9 +1038,17 @@ TALER_KYCLOGIC_rules_parse (const json_t *jlrs) rule->verboten = true; continue; } - else if (NULL == - find_measure (lrs, - str)) + + rule->next_measures[j] + = GNUNET_strdup (str); + if (! ascii_lower (rule->next_measures[j])) + { + GNUNET_break (0); + goto cleanup; + } + if (NULL == + find_measure (lrs, + rule->next_measures[j])) { GNUNET_log (GNUNET_ERROR_TYPE_ERROR, "Measure `%s' specified in rule set unknown\n", @@ -917,8 +1056,6 @@ TALER_KYCLOGIC_rules_parse (const json_t *jlrs) GNUNET_break_op (0); goto cleanup; } - rule->next_measures[j] - = GNUNET_strdup (str); } } } @@ -1187,7 +1324,7 @@ TALER_KYCLOGIC_rule_get_instant_measure ( return NULL; } if (0 == strcasecmp (ms->check_name, - "SKIP")) + "skip")) return ms; } return NULL; @@ -1431,6 +1568,12 @@ TALER_KYCLOGIC_get_instant_measure ( { nm = GNUNET_strdup (measures_spec); } + if (! token_list_lower (nm)) + { + GNUNET_break (0); + GNUNET_free (nm); + return NULL; + } for (const char *tok = strtok (nm, " "); NULL != tok; tok = strtok (NULL, " ")) @@ -1454,7 +1597,7 @@ TALER_KYCLOGIC_get_instant_measure ( { continue; } - if (0 == strcasecmp ("SKIP", + if (0 == strcasecmp ("skip", ms->check_name)) { ret = ms; @@ -1496,6 +1639,12 @@ TALER_KYCLOGIC_get_jmeasures ( { nm = GNUNET_strdup (measures_spec); } + if (! token_list_lower (nm)) + { + GNUNET_break (0); + GNUNET_free (nm); + return NULL; + } jmeasures = json_array (); GNUNET_assert (NULL != jmeasures); for (const char *tok = strtok (nm, " "); @@ -1556,7 +1705,7 @@ TALER_KYCLOGIC_check_to_jmeasures ( mi = GNUNET_JSON_PACK ( GNUNET_JSON_pack_string ("check_name", NULL == check - ? "SKIP" + ? "skip" : check->check_name), GNUNET_JSON_pack_allow_null ( GNUNET_JSON_pack_string ("prog_name", @@ -1674,7 +1823,9 @@ split_words (const char *command, for (const char **m = extra_args; *m; m++) { res[n - 1] = GNUNET_strdup (*m); - GNUNET_array_append (res, n, NULL); + GNUNET_array_append (res, + n, + NULL); } } @@ -1927,6 +2078,11 @@ load_logic (const struct GNUNET_CONFIGURATION_Handle *cfg, GNUNET_asprintf (&lib_name, "libtaler_plugin_kyclogic_%s", name); + if (! ascii_lower (lib_name)) + { + GNUNET_free (lib_name); + return NULL; + } for (unsigned int i = 0; i<num_kyc_logics; i++) if (0 == strcasecmp (lib_name, kyc_logics[i]->library_name)) @@ -1980,6 +2136,14 @@ add_provider (const struct GNUNET_CONFIGURATION_Handle *cfg, "LOGIC"); return GNUNET_SYSERR; } + if (! ascii_lower (logic)) + { + GNUNET_log_config_invalid (GNUNET_ERROR_TYPE_ERROR, + section, + "LOGIC", + "Only [a-zA-Z0-9_0] are allowed"); + return GNUNET_SYSERR; + } lp = load_logic (cfg, logic); if (NULL == lp) @@ -2075,24 +2239,24 @@ handle_provider_section (void *cls, const char *section) { struct SectionContext *sc = cls; + char *s; if (! sc->result) return; - if (0 == strncasecmp (section, - "kyc-provider-", - strlen ("kyc-provider-"))) - { - if (GNUNET_OK != - add_provider (sc->cfg, - section)) - { - GNUNET_log (GNUNET_ERROR_TYPE_ERROR, - "Setup failed in configuration section `%s'\n", - section); - sc->result = false; - } + s = normalize_section_with_prefix ("kyc-provider-", + section); + if (NULL == s) return; + if (GNUNET_OK != + add_provider (sc->cfg, + s)) + { + GNUNET_log (GNUNET_ERROR_TYPE_ERROR, + "Setup failed in configuration section `%s'\n", + section); + sc->result = false; } + GNUNET_free (s); } @@ -2116,7 +2280,7 @@ add_check (const struct GNUNET_CONFIGURATION_Handle *cfg, char *fallback = NULL; if (0 == strcasecmp (&section[strlen ("kyc-check-")], - "SKIP")) + "skip")) { GNUNET_log (GNUNET_ERROR_TYPE_ERROR, "The kyc-check-skip section must not exist, 'skip' is reserved name for a built-in check\n"); @@ -2237,6 +2401,14 @@ add_check (const struct GNUNET_CONFIGURATION_Handle *cfg, "FALLBACK"); goto fail; } + if (! ascii_lower (fallback)) + { + GNUNET_log_config_invalid (GNUNET_ERROR_TYPE_ERROR, + section, + "FALLBACK", + "Only [a-zA-Z0-9_0] are allowed"); + goto fail; + } { struct TALER_KYCLOGIC_KycCheck *kc; @@ -2265,6 +2437,14 @@ add_check (const struct GNUNET_CONFIGURATION_Handle *cfg, GNUNET_free (kc); return GNUNET_SYSERR; } + if (! ascii_lower (form_name)) + { + GNUNET_log_config_invalid (GNUNET_ERROR_TYPE_ERROR, + section, + "FORM_NAME", + "Only [a-zA-Z0-9_0] are allowed"); + goto fail; + } kc->details.form.name = form_name; } break; @@ -2286,6 +2466,14 @@ add_check (const struct GNUNET_CONFIGURATION_Handle *cfg, GNUNET_free (kc); return GNUNET_SYSERR; } + if (! ascii_lower (provider_id)) + { + GNUNET_log_config_invalid (GNUNET_ERROR_TYPE_ERROR, + section, + "PROVIDER_ID", + "Only [a-zA-Z0-9_0] are allowed"); + goto fail; + } kc->details.link.provider = find_provider (provider_id); if (NULL == kc->details.link.provider) { @@ -2345,18 +2533,19 @@ handle_check_section (void *cls, const char *section) { struct SectionContext *sc = cls; + char *s; if (! sc->result) return; - if (0 == strncasecmp (section, - "kyc-check-", - strlen ("kyc-check-"))) - { - if (GNUNET_OK != - add_check (sc->cfg, - section)) - sc->result = false; - } + s = normalize_section_with_prefix ("kyc-check-", + section); + if (NULL == s) + return; + if (GNUNET_OK != + add_check (sc->cfg, + s)) + sc->result = false; + GNUNET_free (s); } @@ -2478,6 +2667,15 @@ add_rule (const struct GNUNET_CONFIGURATION_Handle *cfg, "NEXT_MEASURES"); return GNUNET_SYSERR; } + if (! token_list_lower (measures)) + { + GNUNET_log_config_invalid (GNUNET_ERROR_TYPE_ERROR, + section, + "NEXT_MEASURES", + "Only [a-zA-Z0-9 _-] are allowed"); + GNUNET_free (measures); + return GNUNET_SYSERR; + } GNUNET_log (GNUNET_ERROR_TYPE_INFO, "Adding KYC rule %s for trigger %d with threshold %s\n", @@ -2525,18 +2723,19 @@ handle_rule_section (void *cls, const char *section) { struct SectionContext *sc = cls; + char *s; if (! sc->result) return; - if (0 == strncasecmp (section, - "kyc-rule-", - strlen ("kyc-rule-"))) - { - if (GNUNET_OK != - add_rule (sc->cfg, - section)) - sc->result = false; - } + s = normalize_section_with_prefix ("kyc-rule-", + section); + if (NULL == s) + return; + if (GNUNET_OK != + add_rule (sc->cfg, + s)) + sc->result = false; + GNUNET_free (s); } @@ -2657,6 +2856,7 @@ add_program (const struct GNUNET_CONFIGURATION_Handle *cfg, "output for -r invalid"); goto fail; } + required_attributes = command_output (command, "-a"); if (NULL == required_attributes) @@ -2678,6 +2878,7 @@ add_program (const struct GNUNET_CONFIGURATION_Handle *cfg, "output for -i invalid"); goto fail; } + { char *sptr; @@ -2781,18 +2982,19 @@ handle_program_section (void *cls, const char *section) { struct SectionContext *sc = cls; + char *s; if (! sc->result) return; - if (0 == strncasecmp (section, - "aml-program-", - strlen ("aml-program-"))) - { - if (GNUNET_OK != - add_program (sc->cfg, - section)) - sc->result = false; - } + s = normalize_section_with_prefix ("aml-program-", + section); + if (NULL == s) + return; + if (GNUNET_OK != + add_program (sc->cfg, + s)) + sc->result = false; + GNUNET_free (s); } @@ -2825,10 +3027,10 @@ add_measure (const struct GNUNET_CONFIGURATION_Handle *cfg, "CHECK_NAME", &check_name)) { - check_name = GNUNET_strdup ("SKIP"); + check_name = GNUNET_strdup ("skip"); } if (0 != strcasecmp (check_name, - "SKIP")) + "skip")) { kc = find_check (check_name); if (NULL == kc) @@ -2929,18 +3131,19 @@ handle_measure_section (void *cls, const char *section) { struct SectionContext *sc = cls; + char *s; if (! sc->result) return; - if (0 == strncasecmp (section, - "kyc-measure-", - strlen ("kyc-measure-"))) - { - if (GNUNET_OK != - add_measure (sc->cfg, - section)) - sc->result = false; - } + s = normalize_section_with_prefix ("kyc-measure-", + section); + if (NULL == s) + return; + if (GNUNET_OK != + add_measure (sc->cfg, + s)) + sc->result = false; + GNUNET_free (s); } @@ -3206,10 +3409,10 @@ TALER_KYCLOGIC_kyc_init ( return GNUNET_SYSERR; } if (0 != strcasecmp (m->check_name, - "SKIP")) + "skip")) { GNUNET_log (GNUNET_ERROR_TYPE_ERROR, - "Fallback measure `%s' used in AML program `%s' has a check `%s' but fallbacks must have a check of type 'SKIP'\n", + "Fallback measure `%s' used in AML program `%s' has a check `%s' but fallbacks must have a check of type 'skip'\n", program->fallback, program->program_name, m->check_name); @@ -3250,10 +3453,10 @@ TALER_KYCLOGIC_kyc_init ( return GNUNET_SYSERR; } if (0 != strcasecmp (measure->check_name, - "SKIP")) + "skip")) { GNUNET_log (GNUNET_ERROR_TYPE_ERROR, - "Fallback measure `%s' used in KYC check `%s' has a check `%s' but fallbacks must have a check of type 'SKIP'\n", + "Fallback measure `%s' used in KYC check `%s' has a check `%s' but fallbacks must have a check of type 'skip'\n", kyc_check->fallback, kyc_check->check_name, measure->check_name); @@ -3413,7 +3616,7 @@ TALER_KYCLOGIC_get_original_measure ( return GNUNET_SYSERR; } if (0 == strcasecmp (measure->check_name, - "SKIP")) + "skip")) { kcc->check = NULL; kcc->prog_name = measure->prog_name; @@ -3431,7 +3634,7 @@ TALER_KYCLOGIC_get_original_measure ( return GNUNET_OK; } GNUNET_log (GNUNET_ERROR_TYPE_ERROR, - "Check `%s' unknown (but required by measure %s)\n", + "Check `%s' unknown (but required by measure `%s')\n", measure->check_name, measure_name); return GNUNET_SYSERR; @@ -3494,7 +3697,7 @@ TALER_KYCLOGIC_requirements_to_check ( } if (0 == strcasecmp (measure->check_name, - "SKIP")) + "skip")) { kcc->check = NULL; kcc->prog_name = measure->prog_name; @@ -3512,7 +3715,7 @@ TALER_KYCLOGIC_requirements_to_check ( return GNUNET_OK; } GNUNET_log (GNUNET_ERROR_TYPE_ERROR, - "Check `%s' unknown (but required by measure %s)\n", + "Check `%s' unknown (but required by measure `%s')\n", measure->check_name, measure_name); return GNUNET_SYSERR; @@ -4227,7 +4430,7 @@ TALER_KYCLOGIC_check_to_provider (const char *check_name) if (NULL == check_name) return NULL; if (0 == strcasecmp (check_name, - "SKIP")) + "skip")) return NULL; kc = find_check (check_name); if (NULL == kc) @@ -4551,10 +4754,10 @@ handle_aml_timeout (void *cls) async_return_task (aprh); return; } - /* We require fallback measures to have a 'SKIP' check */ + /* We require fallback measures to have a 'skip' check */ GNUNET_break (0 == strcasecmp (m->check_name, - "SKIP")); + "skip")); fprogram = find_program (m->prog_name); /* Program associated with an original measure must exist */ GNUNET_assert (NULL != fprogram); diff --git a/src/testing/testing_api_cmd_auditor_exec_auditor.c b/src/testing/testing_api_cmd_auditor_exec_auditor.c @@ -48,7 +48,7 @@ struct AuditorState /** - * Run the command; calls the `taler-auditor' program. + * Run the command; calls the `taler-auditor` program. * * @param cls closure. * @param cmd the commaind being run. diff --git a/src/testing/testing_api_cmd_auditor_exec_auditor_dbinit.c b/src/testing/testing_api_cmd_auditor_exec_auditor_dbinit.c @@ -48,7 +48,7 @@ struct AuditorDbinitState /** - * Run the command; calls the `taler-auditor-dbinit' program. + * Run the command; calls the `taler-auditor-dbinit` program. * * @param cls closure. * @param cmd the commaind being run. diff --git a/src/testing/testing_api_cmd_exec_aggregator.c b/src/testing/testing_api_cmd_exec_aggregator.c @@ -52,7 +52,7 @@ struct AggregatorState /** - * Run the command. Use the `taler-exchange-aggregator' program. + * Run the command. Use the `taler-exchange-aggregator` program. * * @param cls closure. * @param cmd command being run. diff --git a/src/testing/testing_api_cmd_exec_auditor-offline.c b/src/testing/testing_api_cmd_exec_auditor-offline.c @@ -48,7 +48,7 @@ struct AuditorOfflineState /** - * Run the command. Use the `taler-exchange-auditor-offline' program. + * Run the command. Use the `taler-exchange-auditor-offline` program. * * @param cls closure. * @param cmd command being run. diff --git a/src/testing/testing_api_cmd_exec_closer.c b/src/testing/testing_api_cmd_exec_closer.c @@ -70,7 +70,7 @@ struct CloserState /** - * Run the command. Use the `taler-exchange-closer' program. + * Run the command. Use the `taler-exchange-closer` program. * * @param cls closure. * @param cmd command being run. diff --git a/src/testing/testing_api_cmd_exec_expire.c b/src/testing/testing_api_cmd_exec_expire.c @@ -48,7 +48,7 @@ struct ExpireState /** - * Run the command; use the `taler-exchange-expire' program. + * Run the command; use the `taler-exchange-expire` program. * * @param cls closure. * @param cmd command currently being executed. diff --git a/src/testing/testing_api_cmd_exec_router.c b/src/testing/testing_api_cmd_exec_router.c @@ -48,7 +48,7 @@ struct RouterState /** - * Run the command; use the `taler-exchange-router' program. + * Run the command; use the `taler-exchange-router` program. * * @param cls closure. * @param cmd command currently being executed. diff --git a/src/testing/testing_api_cmd_exec_transfer.c b/src/testing/testing_api_cmd_exec_transfer.c @@ -47,7 +47,7 @@ struct TransferState /** - * Run the command. Use the `taler-exchange-transfer' program. + * Run the command. Use the `taler-exchange-transfer` program. * * @param cls closure. * @param cmd command being run. diff --git a/src/testing/testing_api_cmd_exec_wget.c b/src/testing/testing_api_cmd_exec_wget.c @@ -46,7 +46,7 @@ struct WgetState /** - * Run the command; use the `wget' program. + * Run the command; use the `wget` program. * * @param cls closure. * @param cmd command currently being executed. diff --git a/src/testing/testing_api_cmd_exec_wirewatch.c b/src/testing/testing_api_cmd_exec_wirewatch.c @@ -52,7 +52,7 @@ struct WirewatchState /** - * Run the command; use the `taler-exchange-wirewatch' program. + * Run the command; use the `taler-exchange-wirewatch` program. * * @param cls closure. * @param cmd command currently being executed. diff --git a/src/testing/testing_api_cmd_kyc_wallet_get.c b/src/testing/testing_api_cmd_kyc_wallet_get.c @@ -115,6 +115,8 @@ wallet_kyc_cb (void *cls, } switch (wkr->hr.http_status) { + case MHD_HTTP_OK: + break; case MHD_HTTP_NO_CONTENT: break; case MHD_HTTP_FORBIDDEN: diff --git a/src/testing/testing_api_cmd_offline_sign_extensions.c b/src/testing/testing_api_cmd_offline_sign_extensions.c @@ -49,7 +49,7 @@ struct ExtensionsSignState /** - * Run the command; calls the `taler-exchange-offline' program. + * Run the command; calls the `taler-exchange-offline` program. * * @param cls closure. * @param cmd the commaind being run. diff --git a/src/testing/testing_api_cmd_offline_sign_global_fees.c b/src/testing/testing_api_cmd_offline_sign_global_fees.c @@ -79,7 +79,7 @@ struct OfflineSignState /** - * Run the command; calls the `taler-exchange-offline' program. + * Run the command; calls the `taler-exchange-offline` program. * * @param cls closure. * @param cmd the commaind being run. diff --git a/src/testing/testing_api_cmd_offline_sign_keys.c b/src/testing/testing_api_cmd_offline_sign_keys.c @@ -50,7 +50,7 @@ struct OfflineSignState /** - * Run the command; calls the `taler-exchange-offline' program. + * Run the command; calls the `taler-exchange-offline` program. * * @param cls closure. * @param cmd the commaind being run. diff --git a/src/testing/testing_api_cmd_offline_sign_wire_fees.c b/src/testing/testing_api_cmd_offline_sign_wire_fees.c @@ -60,7 +60,7 @@ struct OfflineSignState /** - * Run the command; calls the `taler-exchange-offline' program. + * Run the command; calls the `taler-exchange-offline` program. * * @param cls closure. * @param cmd the commaind being run. diff --git a/src/testing/testing_api_cmd_system_start.c b/src/testing/testing_api_cmd_system_start.c @@ -219,7 +219,7 @@ start_reader (struct SystemState *as) /** - * Run the command. Use the `taler-exchange-system' program. + * Run the command. Use the `taler-unified-setup.sh` program. * * @param cls closure. * @param cmd command being run.