aboutsummaryrefslogtreecommitdiff
path: root/src/escrow/gnunet-escrow.c
diff options
context:
space:
mode:
Diffstat (limited to 'src/escrow/gnunet-escrow.c')
-rw-r--r--src/escrow/gnunet-escrow.c528
1 files changed, 528 insertions, 0 deletions
diff --git a/src/escrow/gnunet-escrow.c b/src/escrow/gnunet-escrow.c
new file mode 100644
index 000000000..ad34dd8f3
--- /dev/null
+++ b/src/escrow/gnunet-escrow.c
@@ -0,0 +1,528 @@
1/*
2 This file is part of GNUnet.
3 Copyright (C) 2020 GNUnet e.V.
4
5 GNUnet is free software: you can redistribute it and/or modify it
6 under the terms of the GNU Affero General Public License as published
7 by the Free Software Foundation, either version 3 of the License,
8 or (at your option) any later version.
9
10 GNUnet is distributed in the hope that it will be useful, but
11 WITHOUT ANY WARRANTY; without even the implied warranty of
12 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
13 Affero General Public License for more details.
14
15 You should have received a copy of the GNU Affero General Public License
16 along with this program. If not, see <http://www.gnu.org/licenses/>.
17
18 SPDX-License-Identifier: AGPL3.0-or-later
19 */
20/**
21 * @author Johannes Späth
22 * @file src/escrow/gnunet-escrow.c
23 * @brief Identity Escrow utility
24 *
25 */
26
27#include "platform.h"
28
29#include "gnunet_util_lib.h"
30#include "gnunet_escrow_lib.h"
31
32/**
33 * return value
34 */
35static int ret;
36
37/**
38 * -P option
39 */
40static char *put_ego;
41
42/**
43 * -V option
44 */
45static char *verify_ego;
46
47/**
48 * -G option
49 */
50static int get_flag;
51
52/**
53 * -S option
54 */
55static char *status_ego;
56
57/**
58 * The ego
59 */
60struct GNUNET_IDENTITY_Ego *ego;
61
62/**
63 * User secret string
64 */
65static char *user_secret_string;
66
67/**
68 * Anchor string
69 */
70static char *anchor_string;
71
72/**
73 * The escrow anchor
74 */
75struct GNUNET_ESCROW_Anchor *anchor;
76
77/**
78 * Plugin name
79 */
80static char *method_name;
81
82/**
83 * Escrow method
84 */
85enum GNUNET_ESCROW_Key_Escrow_Method method;
86
87/**
88 * Handle to the escrow component
89 */
90static struct GNUNET_ESCROW_Handle *escrow_handle;
91
92/**
93 * Escrow operation
94 */
95static struct GNUNET_ESCROW_Operation *escrow_op;
96
97/**
98 * Escrow status
99 */
100static struct GNUNET_ESCROW_Status *escrow_status;
101
102/**
103 * Handle to the identity service
104 */
105static struct GNUNET_IDENTITY_Handle *identity_handle;
106
107/**
108 * Cleanup task
109 */
110static struct GNUNET_SCHEDULER_Task *cleanup_task;
111
112
113/**
114 * Called to clean up the escrow component
115 */
116static void
117do_cleanup (void *cls)
118{
119 cleanup_task = NULL;
120 if (NULL != escrow_op)
121 {
122 GNUNET_ESCROW_cancel (escrow_op);
123 escrow_op = NULL;
124 }
125 if (NULL != escrow_handle)
126 GNUNET_ESCROW_fini (escrow_handle);
127 if (NULL != identity_handle)
128 GNUNET_IDENTITY_disconnect (identity_handle);
129 if (NULL != method_name)
130 {
131 GNUNET_free (method_name);
132 method_name = NULL;
133 }
134 if (NULL != user_secret_string)
135 {
136 GNUNET_free (user_secret_string);
137 user_secret_string = NULL;
138 }
139 if (NULL != anchor_string)
140 {
141 GNUNET_free (anchor_string);
142 anchor_string = NULL;
143 }
144 if (NULL != anchor)
145 {
146 GNUNET_free (anchor);
147 anchor = NULL;
148 }
149 if (NULL != put_ego)
150 {
151 GNUNET_free (put_ego);
152 put_ego = NULL;
153 }
154 if (NULL != verify_ego)
155 {
156 GNUNET_free (verify_ego);
157 verify_ego = NULL;
158 }
159 if (NULL != status_ego)
160 {
161 GNUNET_free (status_ego);
162 status_ego = NULL;
163 }
164 if (NULL != escrow_status)
165 {
166 GNUNET_free (escrow_status);
167 escrow_status = NULL;
168 }
169 if (NULL != ego)
170 {
171 /* does not have to be freed, as this is done when
172 cleaning up the ego list in the plugin */
173 ego = NULL;
174 }
175 method = -1;
176}
177
178
179static void
180put_cb (void *cls,
181 struct GNUNET_ESCROW_Anchor *anchor,
182 const char *emsg)
183{
184 char *anchorString;
185
186 escrow_op = NULL;
187
188 if (NULL == anchor)
189 {
190 ret = 1;
191 if (NULL != emsg)
192 fprintf (stderr, "Escrow failed: %s", emsg);
193 }
194 else
195 {
196 anchorString = GNUNET_ESCROW_anchor_data_to_string (anchor);
197
198 fprintf (stdout, "Escrow finished! Please keep the following anchor "
199 "in order to restore the key later!\n%s\n", anchorString);
200 }
201 cleanup_task = GNUNET_SCHEDULER_add_now (&do_cleanup, NULL);
202 GNUNET_free (anchor);
203}
204
205
206static void
207verify_cb (void *cls,
208 int verificationResult,
209 const char *emsg)
210{
211 escrow_op = NULL;
212
213 if (NULL != emsg)
214 fprintf (stderr, "%s", emsg);
215
216 switch (verificationResult)
217 {
218 case GNUNET_ESCROW_VALID:
219 fprintf (stdout, "Escrow is valid!\n");
220 break;
221 case GNUNET_ESCROW_SHARES_MISSING:
222 fprintf (stdout, "Escrow can be restored, but some shares are missing! "
223 "Please perform a new escrow.\n");
224 break;
225 case GNUNET_ESCROW_INVALID:
226 ret = 2;
227 fprintf (stdout, "Escrow is INvalid! Please perform a new escrow.\n");
228 break;
229 default:
230 ret = 1;
231 fprintf (stderr, "invalid verificationResult");
232 }
233 cleanup_task = GNUNET_SCHEDULER_add_now (&do_cleanup, NULL);
234}
235
236
237static void
238get_cb (void *cls,
239 struct GNUNET_IDENTITY_Ego *ego,
240 const char *emsg)
241{
242 escrow_op = NULL;
243
244 if (NULL == ego)
245 {
246 ret = 1;
247 if (NULL != emsg)
248 fprintf (stderr, "Escrow failed: %s", emsg);
249 }
250 else
251 fprintf (stdout, "Identity %s could successfully be restored!\n", anchor->egoName);
252 cleanup_task = GNUNET_SCHEDULER_add_now (&do_cleanup, NULL);
253}
254
255
256static void
257start_process ()
258{
259 /* put */
260 if (NULL != put_ego)
261 {
262 if (NULL == ego)
263 {
264 ret = 1;
265 fprintf (stderr, "Ego %s not found\n", put_ego);
266 cleanup_task = GNUNET_SCHEDULER_add_now (&do_cleanup, NULL);
267 return;
268 }
269 escrow_op = GNUNET_ESCROW_put (escrow_handle,
270 ego,
271 user_secret_string,
272 method,
273 &put_cb,
274 NULL);
275 return;
276 }
277 /* verify */
278 if (NULL != verify_ego)
279 {
280 if (NULL == ego)
281 {
282 ret = 1;
283 fprintf (stderr, "Ego %s not found\n", verify_ego);
284 cleanup_task = GNUNET_SCHEDULER_add_now (&do_cleanup, NULL);
285 return;
286 }
287 escrow_op = GNUNET_ESCROW_verify (escrow_handle,
288 ego,
289 anchor,
290 method,
291 &verify_cb,
292 NULL);
293 return;
294 }
295 /* get */
296 if (GNUNET_YES == get_flag)
297 {
298 escrow_op = GNUNET_ESCROW_get (escrow_handle,
299 anchor,
300 &get_cb,
301 NULL);
302 return;
303 }
304 /* status */
305 if (NULL != status_ego)
306 {
307 if (NULL == ego)
308 {
309 ret = 1;
310 fprintf (stderr, "Ego %s not found\n", status_ego);
311 cleanup_task = GNUNET_SCHEDULER_add_now (&do_cleanup, NULL);
312 return;
313 }
314 escrow_status = GNUNET_ESCROW_get_status (escrow_handle,
315 ego,
316 method);
317
318 if (GNUNET_ESCROW_KEY_NONE == escrow_status->last_method)
319 fprintf (stdout, "No escrow has been performed for identity %s!\n", status_ego);
320 else
321 {
322 fprintf (stdout, "Escrow STATUS information for identity %s\n", status_ego);
323 fprintf (stdout, "=======================================================\n");
324 if (0 == escrow_status->last_successful_verification_time.abs_value_us)
325 fprintf (stdout, "No successful verification! Please VERIFY now.\n");
326 else
327 {
328 fprintf (stdout, "Last successful verification:\t%s\n",
329 GNUNET_STRINGS_absolute_time_to_string (escrow_status->last_successful_verification_time));
330 fprintf (stdout, "Next recommended verification:\t%s\n",
331 GNUNET_STRINGS_absolute_time_to_string (escrow_status->next_recommended_verification_time));
332 }
333 fprintf (stdout, "Last method:\t\t\t%s\n",
334 GNUNET_ESCROW_method_number_to_string (escrow_status->last_method));
335 }
336
337 cleanup_task = GNUNET_SCHEDULER_add_now (&do_cleanup, NULL);
338 return;
339 }
340}
341
342
343static int init = GNUNET_YES;
344
345static void
346ego_cb (void *cls,
347 struct GNUNET_IDENTITY_Ego *e,
348 void **ctx,
349 const char *name)
350{
351 char *ego_name = cls;
352
353 if (NULL == name)
354 {
355 if (GNUNET_YES == init)
356 {
357 init = GNUNET_NO;
358 start_process ();
359 }
360 return;
361 }
362 if (NULL != ego_name && 0 != strcmp (name, ego_name))
363 return;
364 ego = e;
365}
366
367
368static void
369run (void *cls,
370 char *const *args,
371 const char *cfgfile,
372 const struct GNUNET_CONFIGURATION_Handle *c)
373{
374 char *ego_name;
375
376 ret = 0;
377
378 /* check if method is set (needed for all operations except GET) */
379 if (NULL == method_name && GNUNET_YES != get_flag)
380 {
381 ret = 1;
382 fprintf (stderr, _ ("Escrow method (-m option) is missing\n"));
383 return;
384 }
385
386 if (NULL != put_ego)
387 {
388 if (NULL != verify_ego || GNUNET_YES == get_flag || NULL != status_ego)
389 {
390 ret = 1;
391 fprintf (stderr, _ ("-P may only be used without -V, -G or -S!\n"));
392 return;
393 }
394 /* put */
395 ego_name = put_ego;
396 }
397 else if (NULL != verify_ego)
398 {
399 if (GNUNET_YES == get_flag || NULL != status_ego)
400 {
401 ret = 1;
402 fprintf (stderr, _ ("-V may only be used without -P, -G or -S!\n"));
403 return;
404 }
405 /* verify */
406 if (NULL == anchor_string)
407 {
408 ret = 1;
409 fprintf (stderr, _ ("-a is needed for -V!\n"));
410 return;
411 }
412 ego_name = verify_ego;
413 }
414 else if (GNUNET_YES == get_flag)
415 {
416 if (NULL != status_ego)
417 {
418 ret = 1;
419 fprintf (stderr, _ ("-G may only be used without -P, -V or -S!\n"));
420 return;
421 }
422 /* get */
423 if (NULL == anchor_string)
424 {
425 ret = 1;
426 fprintf (stderr, _ ("-a is needed for -G!\n"));
427 return;
428 }
429 ego_name = NULL;
430 }
431 else if (NULL != status_ego)
432 {
433 /* status */
434 ego_name = status_ego;
435 }
436 else
437 {
438 /* nothing */
439 ret = 1;
440 fprintf (stderr, _ ("-P, -V, -G or -S option must be specified!\n"));
441 return;
442 }
443
444 /* determine method */
445 if (NULL != method_name)
446 {
447 method = GNUNET_ESCROW_method_string_to_number (method_name);
448 if (GNUNET_ESCROW_KEY_NONE == method)
449 {
450 ret = 1;
451 fprintf (stderr, _ ("unknown method name!\n"));
452 return;
453 }
454 }
455 else // initialize to error value (should not be used in this case)
456 method = GNUNET_ESCROW_KEY_NONE;
457
458 escrow_handle = GNUNET_ESCROW_init (c);
459
460 if (NULL != anchor_string)
461 {
462 /* parse anchor_string according to method */
463 anchor = GNUNET_ESCROW_anchor_string_to_data (anchor_string);
464 if (NULL == anchor)
465 {
466 ret = 1;
467 fprintf (stderr, _ ("failed to parse anchor string!\n"));
468 cleanup_task = GNUNET_SCHEDULER_add_now (&do_cleanup, NULL);
469 return;
470 }
471 }
472
473 /* connect to identity service in order to get the egos */
474 identity_handle = GNUNET_IDENTITY_connect (c, &ego_cb, ego_name);
475}
476
477
478int
479main (int argc, char *const argv[])
480{
481 struct GNUNET_GETOPT_CommandLineOption options[] = {
482 GNUNET_GETOPT_option_string ('P',
483 "put",
484 "NAME",
485 gettext_noop ("Put the ego NAME in escrow"),
486 &put_ego),
487 GNUNET_GETOPT_option_string ('V',
488 "verify",
489 "NAME",
490 gettext_noop ("Verify the escrow of the ego NAME"),
491 &verify_ego),
492 GNUNET_GETOPT_option_flag ('G',
493 "get",
494 gettext_noop ("Get an ego back from escrow"),
495 &get_flag),
496 GNUNET_GETOPT_option_string ('S',
497 "status",
498 "NAME",
499 gettext_noop ("Get the status of the escrow of ego NAME"),
500 &status_ego),
501 GNUNET_GETOPT_option_string ('u',
502 "userSecret",
503 "USER_SECRET",
504 gettext_noop ("The user secret string"),
505 &user_secret_string),
506 GNUNET_GETOPT_option_string ('a',
507 "anchor",
508 "ANCHOR",
509 gettext_noop ("The escrow anchor"),
510 &anchor_string),
511 GNUNET_GETOPT_option_string ('m',
512 "method",
513 "METHOD",
514 gettext_noop ("The escrow method (and plugin) to use"),
515 &method_name),
516 GNUNET_GETOPT_OPTION_END
517 };
518 if (GNUNET_OK != GNUNET_PROGRAM_run (argc,
519 argv,
520 "gnunet-escrow",
521 _ ("escrow command line tool"),
522 options,
523 &run,
524 NULL))
525 return 1;
526 else
527 return ret;
528}