aboutsummaryrefslogtreecommitdiff
path: root/src/identity/gnunet-identity.c
diff options
context:
space:
mode:
Diffstat (limited to 'src/identity/gnunet-identity.c')
-rw-r--r--src/identity/gnunet-identity.c737
1 files changed, 0 insertions, 737 deletions
diff --git a/src/identity/gnunet-identity.c b/src/identity/gnunet-identity.c
deleted file mode 100644
index 97dc2ce7e..000000000
--- a/src/identity/gnunet-identity.c
+++ /dev/null
@@ -1,737 +0,0 @@
1/*
2 This file is part of GNUnet.
3 Copyright (C) 2013, 2018, 2019 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 * @file identity/gnunet-identity.c
22 * @brief IDENTITY management command line tool
23 * @author Christian Grothoff
24 *
25 * Todo:
26 * - add options to get default egos
27 */
28#include "platform.h"
29#include "gnunet_util_lib.h"
30#include "gnunet_identity_service.h"
31
32
33/**
34 * Return value from main on timeout.
35 */
36#define TIMEOUT_STATUS_CODE 40
37
38/**
39 * Handle to IDENTITY service.
40 */
41static struct GNUNET_IDENTITY_Handle *sh;
42
43/**
44 * Was "list" specified?
45 */
46static int list;
47
48/**
49 * Was "monitor" specified?
50 */
51static int monitor;
52
53/**
54 * Was "private" specified?
55 */
56static int private_keys;
57
58/**
59 * Was "verbose" specified?
60 */
61static unsigned int verbose;
62
63/**
64 * Was "quiet" specified?
65 */
66static int quiet;
67
68/**
69 * Was "eddsa" specified?
70 */
71static int type_eddsa;
72
73/**
74 * -W option
75 */
76static char *write_msg;
77
78/**
79 * -R option
80 */
81static char *read_msg;
82
83/**
84 * -C option
85 */
86static char *create_ego;
87
88/**
89 * -D option
90 */
91static char *delete_ego;
92
93/**
94 * -P option
95 */
96static char *privkey_ego;
97
98/**
99 * -k option
100 */
101static char *pubkey_msg;
102
103/**
104 * -s option.
105 */
106static char *set_ego;
107
108/**
109 * -S option.
110 */
111static char *set_subsystem;
112
113/**
114 * Operation handle for set operation.
115 */
116static struct GNUNET_IDENTITY_Operation *set_op;
117
118/**
119 * Handle for create operation.
120 */
121static struct GNUNET_IDENTITY_Operation *create_op;
122
123/**
124 * Handle for delete operation.
125 */
126static struct GNUNET_IDENTITY_Operation *delete_op;
127
128/**
129 * Private key from command line option, or NULL.
130 */
131struct GNUNET_IDENTITY_PrivateKey pk;
132
133/**
134 * Value to return from #main().
135 */
136static int global_ret;
137
138
139/**
140 * Task run on shutdown.
141 *
142 * @param cls NULL
143 */
144static void
145shutdown_task (void *cls)
146{
147 if (NULL != set_op)
148 {
149 GNUNET_IDENTITY_cancel (set_op);
150 set_op = NULL;
151 }
152 if (NULL != create_op)
153 {
154 GNUNET_IDENTITY_cancel (create_op);
155 create_op = NULL;
156 }
157 if (NULL != delete_op)
158 {
159 GNUNET_IDENTITY_cancel (delete_op);
160 delete_op = NULL;
161 }
162 if (NULL != set_ego)
163 {
164 GNUNET_free (set_ego);
165 set_ego = NULL;
166 }
167 GNUNET_IDENTITY_disconnect (sh);
168 sh = NULL;
169}
170
171
172/**
173 * Test if we are finished yet.
174 */
175static void
176test_finished (void)
177{
178 if ( (NULL == create_op) &&
179 (NULL == delete_op) &&
180 (NULL == set_op) &&
181 (NULL == set_subsystem) &&
182 (NULL == write_msg) &&
183 (NULL == read_msg) &&
184 (! list) &&
185 (! monitor))
186 {
187 if (TIMEOUT_STATUS_CODE == global_ret)
188 global_ret = 0;
189 GNUNET_SCHEDULER_shutdown ();
190 }
191}
192
193
194/**
195 * Deletion operation finished.
196 *
197 * @param cls pointer to operation handle
198 * @param emsg NULL on success, otherwise an error message
199 */
200static void
201delete_finished (void *cls,
202 const char *emsg)
203{
204 struct GNUNET_IDENTITY_Operation **op = cls;
205
206 *op = NULL;
207 if (NULL != emsg)
208 fprintf (stderr, "%s\n", gettext (emsg));
209 test_finished ();
210}
211
212
213/**
214 * Creation operation finished.
215 *
216 * @param cls pointer to operation handle
217 * @param pk private key of the ego, or NULL on error
218 * @param emsg error message, NULL on success
219 */
220static void
221create_finished (void *cls,
222 const struct GNUNET_IDENTITY_PrivateKey *pk,
223 const char *emsg)
224{
225 struct GNUNET_IDENTITY_Operation **op = cls;
226
227 *op = NULL;
228 if (NULL == pk)
229 {
230 fprintf (stderr,
231 _ ("Failed to create ego: %s\n"),
232 emsg);
233 global_ret = 1;
234 }
235 else if (verbose)
236 {
237 struct GNUNET_IDENTITY_PublicKey pub;
238 char *pubs;
239
240 GNUNET_IDENTITY_key_get_public (pk, &pub);
241 pubs = GNUNET_IDENTITY_public_key_to_string (&pub);
242 if (private_keys)
243 {
244 char *privs;
245
246 privs = GNUNET_IDENTITY_private_key_to_string (pk);
247 fprintf (stdout, "%s - %s\n", pubs, privs);
248 GNUNET_free (privs);
249 }
250 else
251 {
252 fprintf (stdout, "%s\n", pubs);
253 }
254 GNUNET_free (pubs);
255 }
256 test_finished ();
257}
258
259
260/**
261 * Function called by #GNUNET_IDENTITY_set up on completion.
262 *
263 * @param cls NULL
264 * @param emsg error message (NULL on success)
265 */
266static void
267set_done (void *cls, const char *emsg)
268{
269 set_op = NULL;
270 if (NULL != emsg)
271 {
272 fprintf (stderr, _ ("Failed to set default ego: %s\n"), emsg);
273 global_ret = 1;
274 }
275 test_finished ();
276}
277
278
279/**
280 * Encrypt a message given with -W, encrypted using public key of
281 * an identity given with -k.
282 */
283static void
284write_encrypted_message (void)
285{
286 struct GNUNET_IDENTITY_PublicKey recipient;
287 if (GNUNET_IDENTITY_public_key_from_string (pubkey_msg, &recipient) !=
288 GNUNET_SYSERR)
289 {
290 struct GNUNET_CRYPTO_EcdhePublicKey message_key;
291 size_t msg_len = strlen (write_msg);
292 ssize_t res = GNUNET_IDENTITY_encrypt (write_msg,
293 msg_len,
294 &recipient,
295 &message_key,
296 write_msg);
297 if (-1 != res)
298 {
299 char *keystr;
300 char *serialized_msg;
301 keystr = GNUNET_STRINGS_data_to_string_alloc (&message_key,
302 sizeof(struct
303 GNUNET_CRYPTO_EcdhePublicKey));
304 serialized_msg = GNUNET_STRINGS_data_to_string_alloc (write_msg,
305 msg_len);
306 fprintf (stdout,
307 "%s.%s\n",
308 keystr, serialized_msg);
309 GNUNET_free (keystr);
310 GNUNET_free (serialized_msg);
311 }
312 else
313 {
314 fprintf (stderr, "Error during encryption.\n");
315 global_ret = 1;
316 }
317 }
318 else
319 {
320 fprintf (stderr, "Invalid recipient public key.\n");
321 global_ret = 1;
322 }
323}
324
325
326/**
327 * Decrypt a message given with -R, encrypted using public key of @c ego
328 * and ephemeral key given with -k.
329 *
330 * @param ego ego whose private key is used for decryption
331 */
332static void
333read_encrypted_message (struct GNUNET_IDENTITY_Ego *ego)
334{
335 // message contains ECDHE key and ciphertext divided by ".", so split up first
336 char delim[2] = ".";
337 char *key_msg = strtok (read_msg, delim);
338 char *cipher;
339 if (NULL == key_msg)
340 {
341 fprintf (stderr, "Invalid message format.\n");
342 global_ret = 1;
343 return;
344 }
345 cipher = strtok (NULL, delim);
346 if (NULL == cipher)
347 {
348 fprintf (stderr, "Invalid message format, text missing.\n");
349 global_ret = 1;
350 return;
351 }
352
353 if (NULL != strtok (NULL, delim))
354 {
355 fprintf (stderr,
356 "Invalid message format, expecting only key and cipher components.\n");
357 global_ret = 1;
358 return;
359 }
360
361 struct GNUNET_CRYPTO_EcdhePublicKey message_key;
362 if (GNUNET_OK == GNUNET_STRINGS_string_to_data (key_msg, strlen (
363 key_msg),
364 &message_key,
365 sizeof(message_key)))
366 {
367 char *deserialized_msg;
368 size_t msg_len;
369 if (GNUNET_OK == GNUNET_STRINGS_string_to_data_alloc (cipher, strlen (
370 cipher),
371 (void **) &
372 deserialized_msg,
373 &msg_len))
374 {
375 ssize_t res = GNUNET_IDENTITY_decrypt (deserialized_msg,
376 msg_len,
377 GNUNET_IDENTITY_ego_get_private_key (
378 ego),
379 &message_key,
380 deserialized_msg);
381 if (-1 != res)
382 {
383 fprintf (stdout,
384 "%s\n",
385 deserialized_msg);
386 }
387 else
388 {
389 fprintf (stderr, "Failed to decrypt message.\n");
390 global_ret = 1;
391 }
392 GNUNET_free (deserialized_msg);
393 }
394 else
395 {
396 fprintf (stderr, "Invalid message format.\n");
397 global_ret = 1;
398 }
399 }
400 else
401 {
402 fprintf (stderr, "Invalid message ephemeral key.\n");
403 global_ret = 1;
404 }
405}
406
407
408/**
409 * If listing is enabled, prints information about the egos.
410 *
411 * This function is initially called for all egos and then again
412 * whenever a ego's identifier changes or if it is deleted. At the
413 * end of the initial pass over all egos, the function is once called
414 * with 'NULL' for 'ego'. That does NOT mean that the callback won't
415 * be invoked in the future or that there was an error.
416 *
417 * When used with 'GNUNET_IDENTITY_create' or 'GNUNET_IDENTITY_get', this
418 * function is only called ONCE, and 'NULL' being passed in 'ego' does
419 * indicate an error (for example because name is taken or no default value is
420 * known). If 'ego' is non-NULL and if '*ctx' is set in those callbacks, the
421 * value WILL be passed to a subsequent call to the identity callback of
422 * 'GNUNET_IDENTITY_connect' (if that one was not NULL).
423 *
424 * When an identity is renamed, this function is called with the
425 * (known) ego but the NEW identifier.
426 *
427 * When an identity is deleted, this function is called with the
428 * (known) ego and "NULL" for the 'identifier'. In this case,
429 * the 'ego' is henceforth invalid (and the 'ctx' should also be
430 * cleaned up).
431 *
432 * @param cls closure
433 * @param ego ego handle
434 * @param ctx context for application to store data for this ego
435 * (during the lifetime of this process, initially NULL)
436 * @param identifier identifier assigned by the user for this ego,
437 * NULL if the user just deleted the ego and it
438 * must thus no longer be used
439 */
440static void
441print_ego (void *cls,
442 struct GNUNET_IDENTITY_Ego *ego,
443 void **ctx,
444 const char *identifier)
445{
446 struct GNUNET_IDENTITY_PublicKey pk;
447 char *s;
448 char *privs;
449
450 if ( (NULL != set_ego) &&
451 (NULL != set_subsystem) &&
452 (NULL != ego) &&
453 (NULL != identifier) &&
454 (0 == strcmp (identifier, set_ego)))
455 {
456 set_op = GNUNET_IDENTITY_set (sh,
457 set_subsystem,
458 ego,
459 &set_done,
460 NULL);
461 GNUNET_free (set_subsystem);
462 set_subsystem = NULL;
463 GNUNET_free (set_ego);
464 set_ego = NULL;
465 }
466 if ( (NULL == ego) &&
467 (NULL != set_ego) &&
468 (NULL != set_subsystem) )
469 {
470 fprintf (stderr,
471 "Could not set ego to `%s' for subsystem `%s', ego not known\n",
472 set_ego,
473 set_subsystem);
474 GNUNET_free (set_subsystem);
475 set_subsystem = NULL;
476 GNUNET_free (set_ego);
477 set_ego = NULL;
478 }
479 if ( (NULL == ego) &&
480 (NULL != set_ego) &&
481 (NULL != read_msg) )
482 {
483 fprintf (stderr,
484 "Ego `%s' is not known, cannot decrypt message.\n",
485 set_ego);
486 GNUNET_free (read_msg);
487 read_msg = NULL;
488 GNUNET_free (set_ego);
489 set_ego = NULL;
490 }
491 if ((NULL == ego) && (! monitor))
492 {
493 list = 0;
494 test_finished ();
495 return;
496 }
497 if (! (list | monitor) && (NULL == read_msg))
498 return;
499 if ( (NULL == ego) ||
500 (NULL == identifier) )
501 return;
502 if ( (NULL != set_ego) &&
503 (0 != strcmp (identifier,
504 set_ego)) )
505 return;
506 GNUNET_IDENTITY_ego_get_public_key (ego, &pk);
507 s = GNUNET_IDENTITY_public_key_to_string (&pk);
508 privs = GNUNET_IDENTITY_private_key_to_string (
509 GNUNET_IDENTITY_ego_get_private_key (ego));
510 if ((NULL != read_msg) && (NULL != set_ego))
511 {
512 // due to the check above, set_ego and the identifier are equal
513 read_encrypted_message (ego);
514 GNUNET_free (read_msg);
515 read_msg = NULL;
516 }
517 else if ((monitor) || (NULL != identifier))
518 {
519 if (quiet)
520 {
521 if (private_keys)
522 fprintf (stdout, "%s - %s\n", s, privs);
523 else
524 fprintf (stdout, "%s\n", s);
525 }
526 else
527 {
528 if (private_keys)
529 fprintf (stdout, "%s - %s - %s - %s\n",
530 identifier, s, privs,
531 (ntohl (pk.type) == GNUNET_IDENTITY_TYPE_ECDSA) ?
532 "ECDSA" : "EdDSA");
533 else
534 fprintf (stdout, "%s - %s - %s\n",
535 identifier, s,
536 (ntohl (pk.type) == GNUNET_IDENTITY_TYPE_ECDSA) ?
537 "ECDSA" : "EdDSA");
538
539 }
540 }
541 GNUNET_free (privs);
542 GNUNET_free (s);
543}
544
545
546/**
547 * Main function that will be run by the scheduler.
548 *
549 * @param cls closure
550 * @param args remaining command-line arguments
551 * @param cfgfile name of the configuration file used (for saving, can be NULL!)
552 * @param cfg configuration
553 */
554static void
555run (void *cls,
556 char *const *args,
557 const char *cfgfile,
558 const struct GNUNET_CONFIGURATION_Handle *cfg)
559{
560 if ((NULL != set_subsystem) && (NULL == set_ego))
561 {
562 fprintf (stderr, "Option -s requires option -e to be specified as well.\n");
563 return;
564 }
565
566 if ((NULL != read_msg) && (NULL == set_ego))
567 {
568 fprintf (stderr,
569 "Option -R requires options -e to be specified as well.\n");
570 return;
571 }
572
573 if ((NULL != write_msg) && (NULL == pubkey_msg))
574 {
575 fprintf (stderr, "Option -W requires option -k to be specified as well.\n");
576 return;
577 }
578 sh = GNUNET_IDENTITY_connect (cfg,
579 (monitor | list) ||
580 (NULL != set_ego) ||
581 (NULL != set_subsystem)
582 ? &print_ego
583 : NULL,
584 NULL);
585 if (NULL != write_msg)
586 {
587 write_encrypted_message ();
588 GNUNET_free (write_msg);
589 write_msg = NULL;
590 }
591 // read message is handled in ego callback (print_ego)
592 if (NULL != delete_ego)
593 delete_op =
594 GNUNET_IDENTITY_delete (sh,
595 delete_ego,
596 &delete_finished,
597 &delete_op);
598 if (NULL != create_ego)
599 {
600 if (NULL != privkey_ego)
601 {
602 GNUNET_STRINGS_string_to_data (privkey_ego,
603 strlen (privkey_ego),
604 &pk,
605 sizeof(struct
606 GNUNET_IDENTITY_PrivateKey));
607 create_op =
608 GNUNET_IDENTITY_create (sh,
609 create_ego,
610 &pk,
611 0, // Ignored
612 &create_finished,
613 &create_op);
614 }
615 else
616 create_op =
617 GNUNET_IDENTITY_create (sh,
618 create_ego,
619 NULL,
620 (type_eddsa) ?
621 GNUNET_IDENTITY_TYPE_EDDSA :
622 GNUNET_IDENTITY_TYPE_ECDSA,
623 &create_finished,
624 &create_op);
625 }
626 GNUNET_SCHEDULER_add_shutdown (&shutdown_task,
627 NULL);
628 test_finished ();
629}
630
631
632/**
633 * The main function.
634 *
635 * @param argc number of arguments from the command line
636 * @param argv command line arguments
637 * @return 0 ok, 1 on error
638 */
639int
640main (int argc, char *const *argv)
641{
642 struct GNUNET_GETOPT_CommandLineOption options[] = {
643 GNUNET_GETOPT_option_string ('C',
644 "create",
645 "NAME",
646 gettext_noop ("create ego NAME"),
647 &create_ego),
648 GNUNET_GETOPT_option_string ('D',
649 "delete",
650 "NAME",
651 gettext_noop ("delete ego NAME "),
652 &delete_ego),
653 GNUNET_GETOPT_option_string ('P',
654 "privkey",
655 "PRIVATE_KEY",
656 gettext_noop (
657 "set the private key for the identity to PRIVATE_KEY (use together with -C)"),
658 &privkey_ego),
659 GNUNET_GETOPT_option_string ('R',
660 "read",
661 "MESSAGE",
662 gettext_noop (
663 "Read and decrypt message encrypted for the given ego (use together with -e EGO)"),
664 &read_msg),
665 GNUNET_GETOPT_option_string ('W',
666 "write",
667 "MESSAGE",
668 gettext_noop (
669 "Encrypt and write message for recipient identity PULBIC_KEY, (use together with -k RECIPIENT_PUBLIC_KEY)"),
670 &write_msg),
671 GNUNET_GETOPT_option_flag ('X',
672 "eddsa",
673 gettext_noop (
674 "generate an EdDSA identity. (use together with -C) EXPERIMENTAL"),
675 &type_eddsa),
676 GNUNET_GETOPT_option_flag ('d',
677 "display",
678 gettext_noop ("display all egos"),
679 &list),
680 GNUNET_GETOPT_option_flag ('q',
681 "quiet",
682 gettext_noop ("reduce output"),
683 &quiet),
684 GNUNET_GETOPT_option_string (
685 'e',
686 "ego",
687 "NAME",
688 gettext_noop (
689 "set default identity to NAME for a subsystem SUBSYSTEM (use together with -s), restrict results to NAME (use together with -d) or read and decrypt a message for NAME (use together with -R)"),
690 &set_ego),
691 GNUNET_GETOPT_option_string ('k',
692 "key",
693 "PUBLIC_KEY",
694 gettext_noop (
695 "The public key of the recipient (with -W)"),
696 &pubkey_msg),
697 GNUNET_GETOPT_option_flag ('m',
698 "monitor",
699 gettext_noop ("run in monitor mode egos"),
700 &monitor),
701 GNUNET_GETOPT_option_flag ('p',
702 "private-keys",
703 gettext_noop ("display private keys as well"),
704 &private_keys),
705 GNUNET_GETOPT_option_string (
706 's',
707 "set",
708 "SUBSYSTEM",
709 gettext_noop (
710 "set default identity to EGO for a subsystem SUBSYSTEM (use together with -e)"),
711 &set_subsystem),
712 GNUNET_GETOPT_option_verbose (&verbose),
713 GNUNET_GETOPT_OPTION_END
714 };
715 int res;
716
717 if (GNUNET_OK !=
718 GNUNET_STRINGS_get_utf8_args (argc, argv,
719 &argc, &argv))
720 return 4;
721 global_ret = TIMEOUT_STATUS_CODE; /* timeout */
722 res = GNUNET_PROGRAM_run (argc,
723 argv,
724 "gnunet-identity",
725 gettext_noop ("Maintain egos"),
726 options,
727 &run,
728 NULL);
729 GNUNET_free_nz ((void *) argv);
730
731 if (GNUNET_OK != res)
732 return 3;
733 return global_ret;
734}
735
736
737/* end of gnunet-identity.c */