From 6f0c639478c7a0dced00043ef01e38655d2e461a Mon Sep 17 00:00:00 2001 From: Christian Grothoff Date: Fri, 4 Dec 2020 16:43:23 +0100 Subject: start skeleton for taler-exchange-offline tool --- src/exchange-tools/.gitignore | 1 + src/exchange-tools/Makefile.am | 13 ++ src/exchange-tools/taler-exchange-offline.c | 300 ++++++++++++++++++++++++++++ 3 files changed, 314 insertions(+) create mode 100644 src/exchange-tools/taler-exchange-offline.c diff --git a/src/exchange-tools/.gitignore b/src/exchange-tools/.gitignore index 6e9e12faf..af97f4b07 100644 --- a/src/exchange-tools/.gitignore +++ b/src/exchange-tools/.gitignore @@ -1,3 +1,4 @@ test_taler_exchange_httpd_home/.local/share/taler/exchange/live-keys/ test_taler_exchange_httpd_home/.local/share/taler/exchange/wirefees/ test_taler_exchange_httpd_home/.config/taler/account-1.json +taler-exchange-offline diff --git a/src/exchange-tools/Makefile.am b/src/exchange-tools/Makefile.am index a7761a3d3..95919c82c 100644 --- a/src/exchange-tools/Makefile.am +++ b/src/exchange-tools/Makefile.am @@ -15,6 +15,7 @@ endif bin_PROGRAMS = \ taler-exchange-keyup \ taler-exchange-keycheck \ + taler-exchange-offline \ taler-exchange-wire \ taler-exchange-dbinit @@ -32,6 +33,18 @@ taler_exchange_keyup_LDADD = \ taler_exchange_keyup_LDFLAGS = $(POSTGRESQL_LDFLAGS) +taler_exchange_offline_SOURCES = \ + taler-exchange-offline.c +taler_exchange_offline_LDADD = \ + $(LIBGCRYPT_LIBS) \ + $(top_builddir)/src/lib/libtalerexchange.la \ + $(top_builddir)/src/json/libtalerjson.la \ + $(top_builddir)/src/util/libtalerutil.la \ + -lgnunetcurl \ + -lgnunetutil \ + $(XLIB) + + taler_exchange_wire_SOURCES = \ taler-exchange-wire.c taler_exchange_wire_LDADD = \ diff --git a/src/exchange-tools/taler-exchange-offline.c b/src/exchange-tools/taler-exchange-offline.c new file mode 100644 index 000000000..f8cbbc40a --- /dev/null +++ b/src/exchange-tools/taler-exchange-offline.c @@ -0,0 +1,300 @@ +/* + This file is part of TALER + Copyright (C) 2020 Taler Systems SA + + TALER is free software; you can redistribute it and/or modify it under the + terms of the GNU General Public License as published by the Free Software + Foundation; either version 3, or (at your option) any later version. + + TALER is distributed in the hope that it will be useful, but WITHOUT ANY + WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR + A PARTICULAR PURPOSE. See the GNU General Public License for more details. + + You should have received a copy of the GNU General Public License along with + TALER; see the file COPYING. If not, see +*/ +/** + * @file taler-exchange-offline.c + * @brief Support for operations involving the exchange's offline master key. + * @author Christian Grothoff + */ +#include +#include "taler_exchange_service.h" + + +/** + * Our context for making HTTP requests. + */ +static struct GNUNET_CURL_Context *ctx; + +/** + * Reschedule context for #ctx. + */ +static struct GNUNET_CURL_RescheduleContext *rc; + +/** + * Handle to the exchange's configuration + */ +static const struct GNUNET_CONFIGURATION_Handle *kcfg; + +/** + * Return value from main(). + */ +static int global_ret; + + +/** + * A subcommand supported by this program. + */ +struct SubCommand +{ + /** + * Name of the command. + */ + const char *name; + + /** + * Help text for the command. + */ + const char *help; + + /** + * Function implementing the command. + * + * @param args subsequent command line arguments (char **) + */ + void (*cb)(char *const *args); +}; + + +/** + * Next work item to perform. + */ +static struct GNUNET_SCHEDULER_Task *nxt; + +/** + * Handle for #do_download. + */ +static struct TALER_EXCHANGE_ManagementGetKeysHandle *mgkh; + + +/** + * Shutdown task. Invoked when the application is being terminated. + * + * @param cls NULL + */ +static void +do_shutdown (void *cls) +{ + (void) cls; + if (NULL != nxt) + { + GNUNET_SCHEDULER_cancel (nxt); + nxt = NULL; + } + if (NULL != mgkh) + { + TALER_EXCHANGE_get_management_keys_cancel (mgkh); + mgkh = NULL; + } + if (NULL != ctx) + { + GNUNET_CURL_fini (ctx); + ctx = NULL; + } + if (NULL != rc) + { + GNUNET_CURL_gnunet_rc_destroy (rc); + rc = NULL; + } +} + + +/** + * Function to continue processing the next command. + * + * @param cls must be a `char *const*` with the array of + * command-line arguments to process next + */ +static void +work (void *cls); + + +/** + * Function to schedule job to process the next command. + * + * @param args the array of command-line arguments to process next + */ +static void +next (char *const *args) +{ + GNUNET_assert (NULL == nxt); + nxt = GNUNET_SCHEDULER_add_now (&work, + (void *) args); +} + + +/** + * Function called with information about future keys. Dumps the JSON output + * (on success), either into an internal buffer or to stdout (depending on + * whether there are subsequent commands). + * + * @param cls closure with the `char **` remaining args + * @param hr HTTP response data + * @param keys information about the various keys used + * by the exchange, NULL if /management/keys failed + */ +static void +download_cb (void *cls, + const struct TALER_EXCHANGE_HttpResponse *hr, + const struct TALER_EXCHANGE_FutureKeys *keys) +{ + char *const *args = cls; + + mgkh = NULL; + fprintf (stderr, + "FIXME: dump!\n"); + next (args); +} + + +/** + * Download future keys. + * + * @param args the array of command-line arguments to process next + */ +static void +do_download (char *const *args) +{ + char *exchange_url; + + if (GNUNET_OK != + GNUNET_CONFIGURATION_get_value_string (kcfg, + "exchange", + "BASE_URL", + &exchange_url)) + { + GNUNET_log_config_missing (GNUNET_ERROR_TYPE_ERROR, + "exchange", + "BASE_URL"); + GNUNET_SCHEDULER_shutdown (); + return; + } + mgkh = TALER_EXCHANGE_get_management_keys (ctx, + exchange_url, + &download_cb, + (void *) args); + GNUNET_free (exchange_url); +} + + +static void +work (void *cls) +{ + char *const *args = cls; + struct SubCommand cmds[] = { + { + .name = "download", + .help = + "obtain future public keys from exchange (to be performed online!)", + .cb = &do_download + }, + /* list terminator */ + { + .name = NULL, + } + }; + (void) cls; + + nxt = NULL; + for (unsigned int i = 0; NULL != cmds[i].name; i++) + { + if (0 == strcasecmp (cmds[i].name, + args[0])) + { + cmds[i].cb (&args[1]); + return; + } + } + + if (0 != strcasecmp ("help", + args[0])) + fprintf (stderr, + "Unexpected command `%s'\n", + args[0]); + fprintf (stderr, + "Supported subcommands:"); + for (unsigned int i = 0; NULL != cmds[i].name; i++) + { + fprintf (stderr, + "%s - %s\n", + cmds[i].name, + cmds[i].help); + } +} + + +/** + * Main function that will be run. + * + * @param cls closure + * @param args remaining command-line arguments + * @param cfgfile name of the configuration file used (for saving, can be NULL!) + * @param cfg configuration + */ +static void +run (void *cls, + char *const *args, + const char *cfgfile, + const struct GNUNET_CONFIGURATION_Handle *cfg) +{ + kcfg = cfg; + ctx = GNUNET_CURL_init (&GNUNET_CURL_gnunet_scheduler_reschedule, + &rc); + rc = GNUNET_CURL_gnunet_rc_create (ctx); + GNUNET_SCHEDULER_add_shutdown (&do_shutdown, + NULL); + next (args); +} + + +/** + * The main function of the taler-exchange-keyup tool. This tool is used to + * create the signing and denomination keys for the exchange. It uses the + * long-term offline private key and writes the (additional) key files to the + * respective exchange directory (from where they can then be copied to the + * online server). Note that we need (at least) the most recent generated + * previous keys to align the validity periods. + * + * @param argc number of arguments from the command line + * @param argv command line arguments + * @return 0 ok, 1 on error + */ +int +main (int argc, + char *const *argv) +{ + struct GNUNET_GETOPT_CommandLineOption options[] = { + GNUNET_GETOPT_OPTION_END + }; + + /* force linker to link against libtalerutil; if we do + not do this, the linker may "optimize" libtalerutil + away and skip #TALER_OS_init(), which we do need */ + (void) TALER_project_data_default (); + GNUNET_assert (GNUNET_OK == + GNUNET_log_setup ("taler-exchange-offline", + "WARNING", + NULL)); + if (GNUNET_OK != + GNUNET_PROGRAM_run (argc, argv, + "taler-exchange-offline", + "Operations for offline signing for a Taler exchange", + options, + &run, NULL)) + return 1; + return global_ret; +} + + +/* end of taler-exchange-offline.c */ -- cgit v1.2.3