summaryrefslogtreecommitdiff
path: root/src/cli/anastasis-cli-discover.c
diff options
context:
space:
mode:
Diffstat (limited to 'src/cli/anastasis-cli-discover.c')
-rw-r--r--src/cli/anastasis-cli-discover.c261
1 files changed, 261 insertions, 0 deletions
diff --git a/src/cli/anastasis-cli-discover.c b/src/cli/anastasis-cli-discover.c
new file mode 100644
index 0000000..f614165
--- /dev/null
+++ b/src/cli/anastasis-cli-discover.c
@@ -0,0 +1,261 @@
+/*
+ This file is part of Anastasis
+ Copyright (C) 2022 Anastasis SARL
+
+ Anastasis is free software; you can redistribute it and/or modify it under the
+ terms of the GNU Lesser General Public License as published by the Free Software
+ Foundation; either version 3, or (at your option) any later version.
+
+ Anastasis 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 Affero General Public License for more details.
+
+ You should have received a copy of the GNU Affero General Public License along with
+ Anastasis; see the file COPYING.GPL. If not, see <http://www.gnu.org/licenses/>
+*/
+/**
+ * @file cli/anastasis-cli-discover.c
+ * @brief command line tool to discover recovery policies
+ * @author Christian Grothoff
+ */
+
+#include "platform.h"
+#include <gnunet/gnunet_util_lib.h>
+#include <gnunet/gnunet_curl_lib.h>
+#include "anastasis_redux.h"
+#include <taler/taler_util.h>
+#include <taler/taler_error_codes.h>
+#include <taler/taler_json_lib.h>
+#include "anastasis_util_lib.h"
+
+/**
+ * Closure for #GNUNET_CURL_gnunet_scheduler_reschedule().
+ */
+static struct GNUNET_CURL_RescheduleContext *rc;
+
+/**
+ * Curl context for communication with anastasis backend
+ */
+static struct GNUNET_CURL_Context *ctx;
+
+/**
+ * Input to -a option given.
+ */
+static char *input;
+
+/**
+ * JSON containing previous state
+ */
+static json_t *prev_state;
+
+/**
+ * JSON containing arguments for action
+ */
+static json_t *arguments;
+
+/**
+ * Handle to an ongoing action.
+ */
+struct ANASTASIS_PolicyDiscovery *pd;
+
+/**
+ * Return value from main.
+ */
+static int global_ret;
+
+
+/**
+ * Function called on each discovered recovery policy. Called
+ * with all arguments NULL if we have received all policies that
+ * we could possibly receive for the current operation.
+ *
+ * The client can then start a new policy discovery process, using the
+ * smallest (also most recent) @a version received per @a provider_url
+ * in the cursor to resume. Note that in this case, the application
+ * logic is responsible for de-duplication using @a hcpd, or it may show
+ * policies again if they are at different providers under versions not
+ * queried up to the cursor.
+ *
+ * @param cls closure
+ * @param hcpd hash of the compressed policy document (unique per policy)
+ * @param provider_url which provider claims to have this policy
+ * @param version version of the policy at this provider
+ * @param attribute_mask combination of optional identity attributes
+ * present in the state that was used to locate this version
+ * @param server_time when did the provider receive the upload
+ * @param secret_name name the user assigned to the backup
+ */
+static void
+print_policy_cb (void *cls,
+ const struct GNUNET_HashCode *hcpd,
+ const char *provider_url,
+ uint32_t version,
+ json_int_t attribute_mask,
+ struct GNUNET_TIME_Timestamp server_time,
+ const char *secret_name,
+ const json_t *providers)
+{
+ if (NULL == hcpd)
+ {
+ fprintf (stderr,
+ "All results received, terminating\n");
+ pd = NULL;
+ global_ret = 0;
+ GNUNET_SCHEDULER_shutdown ();
+ return;
+ }
+ fprintf (stdout,
+ "%s %u %u : \"%s\" \"%s\" (%s)\n",
+ provider_url,
+ (unsigned int) version,
+ (unsigned int) attribute_mask,
+ GNUNET_TIME_timestamp2s (server_time),
+ secret_name,
+ GNUNET_h2s (hcpd));
+}
+
+
+/**
+ * @brief Shutdown the application.
+ *
+ * @param cls closure
+ */
+static void
+shutdown_task (void *cls)
+{
+ (void) cls;
+
+ GNUNET_log (GNUNET_ERROR_TYPE_INFO,
+ "Shutdown initiated\n");
+ if (NULL != pd)
+ {
+ ANASTASIS_policy_discovery_stop (pd);
+ pd = NULL;
+ }
+ ANASTASIS_redux_done ();
+ if (NULL != ctx)
+ {
+ GNUNET_CURL_fini (ctx);
+ ctx = NULL;
+ }
+ if (NULL != rc)
+ {
+ GNUNET_CURL_gnunet_rc_destroy (rc);
+ rc = NULL;
+ }
+ GNUNET_log (GNUNET_ERROR_TYPE_INFO,
+ "Shutdown complete\n");
+}
+
+
+/**
+ * @brief Start the application
+ *
+ * @param cls closure
+ * @param args arguments left
+ * @param cfgfile config file name
+ * @param cfg handle for the configuration file
+ */
+static void
+run (void *cls,
+ char *const *args,
+ const char *cfgfile,
+ const struct GNUNET_CONFIGURATION_Handle *cfg)
+{
+ (void) cls;
+ json_error_t error;
+
+ GNUNET_log (GNUNET_ERROR_TYPE_INFO,
+ "Starting anastasis-discover\n");
+ GNUNET_SCHEDULER_add_shutdown (&shutdown_task,
+ NULL);
+ /* load cursor */
+ if (NULL != input)
+ {
+ arguments = json_loads (input,
+ JSON_DECODE_ANY,
+ &error);
+ if (NULL == arguments)
+ {
+ GNUNET_log (GNUNET_ERROR_TYPE_MESSAGE,
+ "Failed to parse arguments on line %u:%u: %s!\n",
+ error.line,
+ error.column,
+ error.text);
+ GNUNET_SCHEDULER_shutdown ();
+ return;
+ }
+ }
+ /* load state */
+ if (NULL != args[0])
+ {
+ prev_state = json_load_file (args[0],
+ JSON_DECODE_ANY,
+ &error);
+ args++;
+ }
+ else
+ {
+ prev_state = json_loadf (stdin,
+ JSON_DECODE_ANY,
+ &error);
+ }
+ if (NULL == prev_state)
+ {
+ GNUNET_log (GNUNET_ERROR_TYPE_MESSAGE,
+ "Failed to parse initial state on line %u:%u: %s!\n",
+ error.line,
+ error.column,
+ error.text);
+ GNUNET_SCHEDULER_shutdown ();
+ return;
+ }
+ /* initialize HTTP client event loop */
+ ctx = GNUNET_CURL_init (&GNUNET_CURL_gnunet_scheduler_reschedule,
+ &rc);
+ rc = GNUNET_CURL_gnunet_rc_create (ctx);
+ ANASTASIS_redux_init (ctx);
+ pd = ANASTASIS_policy_discovery_start (prev_state,
+ arguments,
+ &print_policy_cb,
+ NULL);
+}
+
+
+int
+main (int argc,
+ char *const *argv)
+{
+ /* the available command line options */
+ struct GNUNET_GETOPT_CommandLineOption options[] = {
+ GNUNET_GETOPT_option_string ('a',
+ "arguments",
+ "JSON",
+ "pass a JSON string containing cursor to use",
+ &input),
+
+ GNUNET_GETOPT_OPTION_END
+ };
+ enum GNUNET_GenericReturnValue ret;
+
+ /* FIRST get the libtalerutil initialization out
+ of the way. Then throw that one away, and force
+ the SYNC defaults to be used! */
+ (void) TALER_project_data_default ();
+ GNUNET_OS_init (ANASTASIS_project_data_default ());
+ ret = GNUNET_PROGRAM_run (argc,
+ argv,
+ "anastasis-discover",
+ "This is an application for finding secrets that could be recovered.\n",
+ options,
+ &run,
+ NULL);
+ if (GNUNET_SYSERR == ret)
+ return 3;
+ if (GNUNET_NO == ret)
+ return 0;
+ return global_ret;
+}
+
+
+/* end of anastasis-cli-discover.c */