anastasis-cli-discover.c (7121B)
1 /* 2 This file is part of Anastasis 3 Copyright (C) 2022 Anastasis SARL 4 5 Anastasis is free software; you can redistribute it and/or modify it under the 6 terms of the GNU Lesser General Public License as published by the Free Software 7 Foundation; either version 3, or (at your option) any later version. 8 9 Anastasis is distributed in the hope that it will be useful, but WITHOUT ANY 10 WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR 11 A PARTICULAR PURPOSE. See the GNU Affero General Public License for more details. 12 13 You should have received a copy of the GNU Affero General Public License along with 14 Anastasis; see the file COPYING.GPL. If not, see <http://www.gnu.org/licenses/> 15 */ 16 /** 17 * @file cli/anastasis-cli-discover.c 18 * @brief command line tool to discover recovery policies 19 * @author Christian Grothoff 20 */ 21 22 #include "platform.h" 23 #include <gnunet/gnunet_util_lib.h> 24 #include <gnunet/gnunet_curl_lib.h> 25 #include "anastasis_redux.h" 26 #include <taler/taler_util.h> 27 #include <taler/taler_error_codes.h> 28 #include <taler/taler_json_lib.h> 29 #include "anastasis_util_lib.h" 30 31 /** 32 * Closure for #GNUNET_CURL_gnunet_scheduler_reschedule(). 33 */ 34 static struct GNUNET_CURL_RescheduleContext *rc; 35 36 /** 37 * Curl context for communication with anastasis backend 38 */ 39 static struct GNUNET_CURL_Context *ctx; 40 41 /** 42 * Input to -a option given. 43 */ 44 static char *input; 45 46 /** 47 * JSON containing previous state 48 */ 49 static json_t *prev_state; 50 51 /** 52 * JSON containing arguments for action 53 */ 54 static json_t *arguments; 55 56 /** 57 * Handle to an ongoing action. 58 */ 59 struct ANASTASIS_PolicyDiscovery *pd; 60 61 /** 62 * Return value from main. 63 */ 64 static int global_ret; 65 66 67 /** 68 * Function called on each discovered recovery policy. Called 69 * with all arguments NULL if we have received all policies that 70 * we could possibly receive for the current operation. 71 * 72 * The client can then start a new policy discovery process, using the 73 * smallest (also most recent) @a version received per @a provider_url 74 * in the cursor to resume. Note that in this case, the application 75 * logic is responsible for de-duplication using @a hcpd, or it may show 76 * policies again if they are at different providers under versions not 77 * queried up to the cursor. 78 * 79 * @param cls closure 80 * @param hcpd hash of the compressed policy document (unique per policy) 81 * @param provider_url which provider claims to have this policy 82 * @param version version of the policy at this provider 83 * @param attribute_mask combination of optional identity attributes 84 * present in the state that was used to locate this version 85 * @param server_time when did the provider receive the upload 86 * @param secret_name name the user assigned to the backup 87 */ 88 static void 89 print_policy_cb (void *cls, 90 const struct GNUNET_HashCode *hcpd, 91 const char *provider_url, 92 uint32_t version, 93 json_int_t attribute_mask, 94 struct GNUNET_TIME_Timestamp server_time, 95 const char *secret_name, 96 const json_t *providers) 97 { 98 if (NULL == hcpd) 99 { 100 fprintf (stderr, 101 "All results received, terminating\n"); 102 pd = NULL; 103 global_ret = 0; 104 GNUNET_SCHEDULER_shutdown (); 105 return; 106 } 107 fprintf (stdout, 108 "%s %u %u : \"%s\" \"%s\" (%s)\n", 109 provider_url, 110 (unsigned int) version, 111 (unsigned int) attribute_mask, 112 GNUNET_TIME_timestamp2s (server_time), 113 secret_name, 114 GNUNET_h2s (hcpd)); 115 } 116 117 118 /** 119 * @brief Shutdown the application. 120 * 121 * @param cls closure 122 */ 123 static void 124 shutdown_task (void *cls) 125 { 126 (void) cls; 127 128 GNUNET_log (GNUNET_ERROR_TYPE_INFO, 129 "Shutdown initiated\n"); 130 if (NULL != pd) 131 { 132 ANASTASIS_policy_discovery_stop (pd); 133 pd = NULL; 134 } 135 ANASTASIS_redux_done (); 136 if (NULL != ctx) 137 { 138 GNUNET_CURL_fini (ctx); 139 ctx = NULL; 140 } 141 if (NULL != rc) 142 { 143 GNUNET_CURL_gnunet_rc_destroy (rc); 144 rc = NULL; 145 } 146 GNUNET_log (GNUNET_ERROR_TYPE_INFO, 147 "Shutdown complete\n"); 148 } 149 150 151 /** 152 * @brief Start the application 153 * 154 * @param cls closure 155 * @param args arguments left 156 * @param cfgfile config file name 157 * @param cfg handle for the configuration file 158 */ 159 static void 160 run (void *cls, 161 char *const *args, 162 const char *cfgfile, 163 const struct GNUNET_CONFIGURATION_Handle *cfg) 164 { 165 json_error_t error; 166 167 (void) cls; 168 GNUNET_log (GNUNET_ERROR_TYPE_INFO, 169 "Starting anastasis-discover\n"); 170 GNUNET_SCHEDULER_add_shutdown (&shutdown_task, 171 NULL); 172 /* load cursor */ 173 if (NULL != input) 174 { 175 arguments = json_loads (input, 176 JSON_DECODE_ANY, 177 &error); 178 if (NULL == arguments) 179 { 180 GNUNET_log (GNUNET_ERROR_TYPE_MESSAGE, 181 "Failed to parse arguments on line %u:%u: %s!\n", 182 error.line, 183 error.column, 184 error.text); 185 GNUNET_SCHEDULER_shutdown (); 186 return; 187 } 188 } 189 /* load state */ 190 if (NULL != args[0]) 191 { 192 prev_state = json_load_file (args[0], 193 JSON_DECODE_ANY, 194 &error); 195 args++; 196 } 197 else 198 { 199 prev_state = json_loadf (stdin, 200 JSON_DECODE_ANY, 201 &error); 202 } 203 if (NULL == prev_state) 204 { 205 GNUNET_log (GNUNET_ERROR_TYPE_MESSAGE, 206 "Failed to parse initial state on line %u:%u: %s!\n", 207 error.line, 208 error.column, 209 error.text); 210 GNUNET_SCHEDULER_shutdown (); 211 return; 212 } 213 /* initialize HTTP client event loop */ 214 ctx = GNUNET_CURL_init (&GNUNET_CURL_gnunet_scheduler_reschedule, 215 &rc); 216 rc = GNUNET_CURL_gnunet_rc_create (ctx); 217 ANASTASIS_redux_init (ctx); 218 pd = ANASTASIS_policy_discovery_start (prev_state, 219 arguments, 220 &print_policy_cb, 221 NULL); 222 } 223 224 225 int 226 main (int argc, 227 char *const *argv) 228 { 229 /* the available command line options */ 230 struct GNUNET_GETOPT_CommandLineOption options[] = { 231 GNUNET_GETOPT_option_string ('a', 232 "arguments", 233 "JSON", 234 "pass a JSON string containing cursor to use", 235 &input), 236 237 GNUNET_GETOPT_OPTION_END 238 }; 239 enum GNUNET_GenericReturnValue ret; 240 241 ret = GNUNET_PROGRAM_run (ANASTASIS_project_data (), 242 argc, 243 argv, 244 "anastasis-discover", 245 "This is an application for finding secrets that could be recovered.\n", 246 options, 247 &run, 248 NULL); 249 if (GNUNET_SYSERR == ret) 250 return 3; 251 if (GNUNET_NO == ret) 252 return 0; 253 return global_ret; 254 } 255 256 257 /* end of anastasis-cli-discover.c */