/* 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 */