GNUnet  0.19.3
gnunet-identity.c
Go to the documentation of this file.
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  */
28 #include "platform.h"
29 #include "gnunet_util_lib.h"
31 
32 
36 #define TIMEOUT_STATUS_CODE 40
37 
41 static struct GNUNET_IDENTITY_Handle *sh;
42 
46 static int list;
47 
51 static int monitor;
52 
56 static int private_keys;
57 
61 static unsigned int verbose;
62 
66 static int quiet;
67 
71 static int type_eddsa;
72 
76 static char *write_msg;
77 
81 static char *read_msg;
82 
86 static char *create_ego;
87 
91 static char *delete_ego;
92 
96 static char *privkey_ego;
97 
101 static char *pubkey_msg;
102 
106 static char *set_ego;
107 
112 
117 
122 
127 
131 static int global_ret;
132 
133 
139 static void
140 shutdown_task (void *cls)
141 {
142  if (NULL != set_op)
143  {
145  set_op = NULL;
146  }
147  if (NULL != create_op)
148  {
150  create_op = NULL;
151  }
152  if (NULL != delete_op)
153  {
155  delete_op = NULL;
156  }
157  if (NULL != set_ego)
158  {
160  set_ego = NULL;
161  }
163  sh = NULL;
164 }
165 
166 
170 static void
172 {
173  if ( (NULL == create_op) &&
174  (NULL == delete_op) &&
175  (NULL == set_op) &&
176  (NULL == write_msg) &&
177  (NULL == read_msg) &&
178  (! list) &&
179  (! monitor))
180  {
182  global_ret = 0;
184  }
185 }
186 
187 
194 static void
195 delete_finished (void *cls,
196  enum GNUNET_ErrorCode ec)
197 {
198  struct GNUNET_IDENTITY_Operation **op = cls;
199 
200  *op = NULL;
201  if (GNUNET_EC_NONE != ec)
202  fprintf (stderr, "%s\n", GNUNET_ErrorCode_get_hint (ec));
203  test_finished ();
204 }
205 
206 
214 static void
216  const struct GNUNET_IDENTITY_PrivateKey *pk,
217  enum GNUNET_ErrorCode ec)
218 {
219  struct GNUNET_IDENTITY_Operation **op = cls;
220 
221  *op = NULL;
222  if (NULL == pk)
223  {
224  fprintf (stderr,
225  _ ("Failed to create ego: %s\n"),
227  global_ret = 1;
228  }
229  else if (verbose)
230  {
232  char *pubs;
233 
236  if (private_keys)
237  {
238  char *privs;
239 
241  fprintf (stdout, "%s - %s\n", pubs, privs);
242  GNUNET_free (privs);
243  }
244  else
245  {
246  fprintf (stdout, "%s\n", pubs);
247  }
248  GNUNET_free (pubs);
249  }
250  test_finished ();
251 }
252 
253 
258 static void
260 {
261  struct GNUNET_IDENTITY_PublicKey recipient;
264  {
265  struct GNUNET_CRYPTO_EcdhePublicKey message_key;
266  size_t msg_len = strlen (write_msg) + 1;
268  msg_len,
269  &recipient,
270  &message_key,
271  write_msg);
272  if (-1 != res)
273  {
274  char *keystr;
275  char *serialized_msg;
276  keystr = GNUNET_STRINGS_data_to_string_alloc (&message_key,
277  sizeof(struct
280  msg_len);
281  fprintf (stdout,
282  "%s.%s\n",
283  keystr, serialized_msg);
284  GNUNET_free (keystr);
285  GNUNET_free (serialized_msg);
286  }
287  else
288  {
289  fprintf (stderr, "Error during encryption.\n");
290  global_ret = 1;
291  }
292  }
293  else
294  {
295  fprintf (stderr, "Invalid recipient public key.\n");
296  global_ret = 1;
297  }
298 }
299 
300 
307 static void
309 {
310  // message contains ECDHE key and ciphertext divided by ".", so split up first
311  char delim[2] = ".";
312  char *key_msg = strtok (read_msg, delim);
313  char *cipher;
314  if (NULL == key_msg)
315  {
316  fprintf (stderr, "Invalid message format.\n");
317  global_ret = 1;
318  return;
319  }
320  cipher = strtok (NULL, delim);
321  if (NULL == cipher)
322  {
323  fprintf (stderr, "Invalid message format, text missing.\n");
324  global_ret = 1;
325  return;
326  }
327 
328  if (NULL != strtok (NULL, delim))
329  {
330  fprintf (stderr,
331  "Invalid message format, expecting only key and cipher components.\n");
332  global_ret = 1;
333  return;
334  }
335 
336  struct GNUNET_CRYPTO_EcdhePublicKey message_key;
337  if (GNUNET_OK == GNUNET_STRINGS_string_to_data (key_msg, strlen (
338  key_msg),
339  &message_key,
340  sizeof(message_key)))
341  {
342  char *deserialized_msg;
343  size_t msg_len;
344  if (GNUNET_OK == GNUNET_STRINGS_string_to_data_alloc (cipher, strlen (
345  cipher),
346  (void **) &
347  deserialized_msg,
348  &msg_len))
349  {
350  ssize_t res = GNUNET_IDENTITY_decrypt (deserialized_msg,
351  msg_len,
353  ego),
354  &message_key,
355  deserialized_msg);
356  if (-1 != res)
357  {
358  deserialized_msg[res - 1] = '\0';
359  fprintf (stdout,
360  "%s\n",
361  deserialized_msg);
362  }
363  else
364  {
365  fprintf (stderr, "Failed to decrypt message.\n");
366  global_ret = 1;
367  }
368  GNUNET_free (deserialized_msg);
369  }
370  else
371  {
372  fprintf (stderr, "Invalid message format.\n");
373  global_ret = 1;
374  }
375  }
376  else
377  {
378  fprintf (stderr, "Invalid message ephemeral key.\n");
379  global_ret = 1;
380  }
381 }
382 
383 
416 static void
417 print_ego (void *cls,
418  struct GNUNET_IDENTITY_Ego *ego,
419  void **ctx,
420  const char *identifier)
421 {
423  char *s;
424  char *privs;
425 
426  if ( (NULL == ego) &&
427  (NULL != set_ego) &&
428  (NULL != read_msg) )
429  {
430  fprintf (stderr,
431  "Ego `%s' is not known, cannot decrypt message.\n",
432  set_ego);
434  read_msg = NULL;
436  set_ego = NULL;
437  }
438  if ((NULL == ego) && (! monitor))
439  {
440  list = 0;
441  test_finished ();
442  return;
443  }
444  if (! (list | monitor) && (NULL == read_msg))
445  return;
446  if ( (NULL == ego) ||
447  (NULL == identifier) )
448  return;
449  if ( (NULL != set_ego) &&
450  (0 != strcmp (identifier,
451  set_ego)) )
452  return;
457  if ((NULL != read_msg) && (NULL != set_ego))
458  {
459  // due to the check above, set_ego and the identifier are equal
462  read_msg = NULL;
463  }
464  else if ((monitor) || (NULL != identifier))
465  {
466  if (quiet)
467  {
468  if (private_keys)
469  fprintf (stdout, "%s - %s\n", s, privs);
470  else
471  fprintf (stdout, "%s\n", s);
472  }
473  else
474  {
475  if (private_keys)
476  fprintf (stdout, "%s - %s - %s - %s\n",
477  identifier, s, privs,
478  (ntohl (pk.type) == GNUNET_IDENTITY_TYPE_ECDSA) ?
479  "ECDSA" : "EdDSA");
480  else
481  fprintf (stdout, "%s - %s - %s\n",
482  identifier, s,
483  (ntohl (pk.type) == GNUNET_IDENTITY_TYPE_ECDSA) ?
484  "ECDSA" : "EdDSA");
485 
486  }
487  }
488  GNUNET_free (privs);
489  GNUNET_free (s);
490 }
491 
492 
501 static void
502 run (void *cls,
503  char *const *args,
504  const char *cfgfile,
505  const struct GNUNET_CONFIGURATION_Handle *cfg)
506 {
507  if ((NULL != read_msg) && (NULL == set_ego))
508  {
509  fprintf (stderr,
510  "Option -R requires options -e to be specified as well.\n");
511  return;
512  }
513 
514  if ((NULL != write_msg) && (NULL == pubkey_msg))
515  {
516  fprintf (stderr, "Option -W requires option -k to be specified as well.\n");
517  return;
518  }
520  (monitor | list) ||
521  (NULL != set_ego)
522  ? &print_ego
523  : NULL,
524  NULL);
525  if (NULL != write_msg)
526  {
529  write_msg = NULL;
530  }
531  // read message is handled in ego callback (print_ego)
532  if (NULL != delete_ego)
533  delete_op =
535  delete_ego,
537  &delete_op);
538  if (NULL != create_ego)
539  {
540  if (NULL != privkey_ego)
541  {
543  strlen (privkey_ego),
544  &pk,
545  sizeof(struct
547  create_op =
549  create_ego,
550  &pk,
551  0, // Ignored
553  &create_op);
554  }
555  else
556  create_op =
558  create_ego,
559  NULL,
560  (type_eddsa) ?
564  &create_op);
565  }
567  NULL);
568  test_finished ();
569 }
570 
571 
579 int
580 main (int argc, char *const *argv)
581 {
584  "create",
585  "NAME",
586  gettext_noop ("create ego NAME"),
587  &create_ego),
589  "delete",
590  "NAME",
591  gettext_noop ("delete ego NAME "),
592  &delete_ego),
594  "privkey",
595  "PRIVATE_KEY",
596  gettext_noop (
597  "set the private key for the identity to PRIVATE_KEY (use together with -C)"),
598  &privkey_ego),
600  "read",
601  "MESSAGE",
602  gettext_noop (
603  "Read and decrypt message encrypted for the given ego (use together with -e EGO)"),
604  &read_msg),
606  "write",
607  "MESSAGE",
608  gettext_noop (
609  "Encrypt and write message for recipient identity PULBIC_KEY, (use together with -k RECIPIENT_PUBLIC_KEY)"),
610  &write_msg),
612  "eddsa",
613  gettext_noop (
614  "generate an EdDSA identity. (use together with -C) EXPERIMENTAL"),
615  &type_eddsa),
617  "display",
618  gettext_noop ("display all egos"),
619  &list),
621  "quiet",
622  gettext_noop ("reduce output"),
623  &quiet),
625  'e',
626  "ego",
627  "NAME",
628  gettext_noop (
629  "restrict results to NAME (use together with -d) or read and decrypt a message for NAME (use together with -R)"),
630  &set_ego),
632  "key",
633  "PUBLIC_KEY",
634  gettext_noop (
635  "The public key of the recipient (with -W)"),
636  &pubkey_msg),
638  "monitor",
639  gettext_noop ("run in monitor mode egos"),
640  &monitor),
642  "private-keys",
643  gettext_noop ("display private keys as well"),
644  &private_keys),
647  };
648  int res;
649 
650  if (GNUNET_OK !=
651  GNUNET_STRINGS_get_utf8_args (argc, argv,
652  &argc, &argv))
653  return 4;
654  global_ret = TIMEOUT_STATUS_CODE; /* timeout */
655  res = GNUNET_PROGRAM_run (argc,
656  argv,
657  "gnunet-identity",
658  gettext_noop ("Maintain egos"),
659  options,
660  &run,
661  NULL);
662  GNUNET_free_nz ((void *) argv);
663 
664  if (GNUNET_OK != res)
665  return 3;
666  return global_ret;
667 }
668 
669 
670 /* end of gnunet-identity.c */
struct GNUNET_GETOPT_CommandLineOption GNUNET_GETOPT_OPTION_END
Definition: 002.c:13
struct GNUNET_GETOPT_CommandLineOption options[]
Definition: 002.c:5
const char * GNUNET_ErrorCode_get_hint(enum GNUNET_ErrorCode ec)
Returns a hint for a given error code.
GNUNET_ErrorCode
Taler error codes.
@ GNUNET_EC_NONE
No error (success).
#define gettext_noop(String)
Definition: gettext.h:70
static const struct GNUNET_CONFIGURATION_Handle * cfg
Configuration we are using.
Definition: gnunet-abd.c:36
static struct GNUNET_ARM_Operation * op
Current operation.
Definition: gnunet-arm.c:144
static int res
#define TIMEOUT_STATUS_CODE
Return value from main on timeout.
static void create_finished(void *cls, const struct GNUNET_IDENTITY_PrivateKey *pk, enum GNUNET_ErrorCode ec)
Creation operation finished.
static unsigned int verbose
Was "verbose" specified?
static void write_encrypted_message(void)
Encrypt a message given with -W, encrypted using public key of an identity given with -k.
struct GNUNET_IDENTITY_PrivateKey pk
Private key from command line option, or NULL.
static struct GNUNET_IDENTITY_Operation * set_op
Operation handle for set operation.
static char * privkey_ego
-P option
static struct GNUNET_IDENTITY_Operation * create_op
Handle for create operation.
static int global_ret
Value to return from main().
static int monitor
Was "monitor" specified?
static int list
Was "list" specified?
static int quiet
Was "quiet" specified?
static struct GNUNET_IDENTITY_Handle * sh
Handle to IDENTITY service.
static char * read_msg
-R option
static void shutdown_task(void *cls)
Task run on shutdown.
static void print_ego(void *cls, struct GNUNET_IDENTITY_Ego *ego, void **ctx, const char *identifier)
If listing is enabled, prints information about the egos.
static void read_encrypted_message(struct GNUNET_IDENTITY_Ego *ego)
Decrypt a message given with -R, encrypted using public key of ego and ephemeral key given with -k.
static int private_keys
Was "private" specified?
static char * delete_ego
-D option
static void test_finished(void)
Test if we are finished yet.
static struct GNUNET_IDENTITY_Operation * delete_op
Handle for delete operation.
static char * create_ego
-C option
static char * pubkey_msg
-k option
static void run(void *cls, char *const *args, const char *cfgfile, const struct GNUNET_CONFIGURATION_Handle *cfg)
Main function that will be run by the scheduler.
int main(int argc, char *const *argv)
The main function.
static int type_eddsa
Was "eddsa" specified?
static void delete_finished(void *cls, enum GNUNET_ErrorCode ec)
Deletion operation finished.
static char * set_ego
-s option.
static char * write_msg
-W option
static struct GNUNET_CRYPTO_EddsaPublicKey pub
Definition: gnunet-scrypt.c:47
static struct GNUNET_DNSSTUB_Context * ctx
Context for DNS resolution.
Identity service; implements identity management for GNUnet.
struct GNUNET_GETOPT_CommandLineOption GNUNET_GETOPT_option_verbose(unsigned int *level)
Define the '-V' verbosity option.
struct GNUNET_GETOPT_CommandLineOption GNUNET_GETOPT_option_flag(char shortName, const char *name, const char *description, int *val)
Allow user to specify a flag (which internally means setting an integer to 1/GNUNET_YES/GNUNET_OK.
struct GNUNET_GETOPT_CommandLineOption GNUNET_GETOPT_option_string(char shortName, const char *name, const char *argumentHelp, const char *description, char **str)
Allow user to specify a string.
const struct GNUNET_IDENTITY_PrivateKey * GNUNET_IDENTITY_ego_get_private_key(const struct GNUNET_IDENTITY_Ego *ego)
Obtain the ECC key associated with a ego.
Definition: identity_api.c:560
enum GNUNET_GenericReturnValue GNUNET_IDENTITY_public_key_from_string(const char *str, struct GNUNET_IDENTITY_PublicKey *key)
Parses a (Base32) string representation of the public key.
ssize_t GNUNET_IDENTITY_decrypt(const void *block, size_t size, const struct GNUNET_IDENTITY_PrivateKey *priv, const struct GNUNET_CRYPTO_EcdhePublicKey *ecc, void *result)
Decrypt a given block with GNUNET_IDENTITY_PrivateKey and a given GNUNET_CRYPTO_EcdhePublicKey using ...
enum GNUNET_GenericReturnValue GNUNET_IDENTITY_key_get_public(const struct GNUNET_IDENTITY_PrivateKey *privkey, struct GNUNET_IDENTITY_PublicKey *key)
Retrieves the public key representation of a private key.
Definition: identity_api.c:179
ssize_t GNUNET_IDENTITY_encrypt(const void *block, size_t size, const struct GNUNET_IDENTITY_PublicKey *pub, struct GNUNET_CRYPTO_EcdhePublicKey *ecc, void *result)
Encrypt a block with GNUNET_IDENTITY_PublicKey and derives a GNUNET_CRYPTO_EcdhePublicKey which is re...
char * GNUNET_IDENTITY_private_key_to_string(const struct GNUNET_IDENTITY_PrivateKey *key)
Creates a (Base32) string representation of the private key.
struct GNUNET_IDENTITY_Operation * GNUNET_IDENTITY_create(struct GNUNET_IDENTITY_Handle *h, const char *name, const struct GNUNET_IDENTITY_PrivateKey *privkey, enum GNUNET_IDENTITY_KeyType ktype, GNUNET_IDENTITY_CreateContinuation cont, void *cont_cls)
Create a new ego with the given name.
Definition: identity_api.c:586
void GNUNET_IDENTITY_ego_get_public_key(struct GNUNET_IDENTITY_Ego *ego, struct GNUNET_IDENTITY_PublicKey *pk)
Get the identifier (public key) of an ego.
Definition: identity_api.c:573
char * GNUNET_IDENTITY_public_key_to_string(const struct GNUNET_IDENTITY_PublicKey *key)
Creates a (Base32) string representation of the public key.
void GNUNET_IDENTITY_cancel(struct GNUNET_IDENTITY_Operation *op)
Cancel an identity operation.
Definition: identity_api.c:740
struct GNUNET_IDENTITY_Handle * GNUNET_IDENTITY_connect(const struct GNUNET_CONFIGURATION_Handle *cfg, GNUNET_IDENTITY_Callback cb, void *cb_cls)
Connect to the identity service.
Definition: identity_api.c:531
void GNUNET_IDENTITY_disconnect(struct GNUNET_IDENTITY_Handle *h)
Disconnect from identity service.
Definition: identity_api.c:757
struct GNUNET_IDENTITY_Operation * GNUNET_IDENTITY_delete(struct GNUNET_IDENTITY_Handle *h, const char *name, GNUNET_IDENTITY_Continuation cb, void *cb_cls)
Delete an existing identity.
Definition: identity_api.c:699
@ GNUNET_IDENTITY_TYPE_ECDSA
The identity type.
@ GNUNET_IDENTITY_TYPE_EDDSA
EDDSA identity.
@ GNUNET_OK
@ GNUNET_SYSERR
#define GNUNET_free(ptr)
Wrapper around free.
#define GNUNET_free_nz(ptr)
Wrapper around free.
enum GNUNET_GenericReturnValue GNUNET_PROGRAM_run(int argc, char *const *argv, const char *binaryName, const char *binaryHelp, const struct GNUNET_GETOPT_CommandLineOption *options, GNUNET_PROGRAM_Main task, void *task_cls)
Run a standard GNUnet command startup sequence (initialize loggers and configuration,...
Definition: program.c:400
void GNUNET_SCHEDULER_shutdown(void)
Request the shutdown of a scheduler.
Definition: scheduler.c:534
struct GNUNET_SCHEDULER_Task * GNUNET_SCHEDULER_add_shutdown(GNUNET_SCHEDULER_TaskCallback task, void *task_cls)
Schedule a new task to be run on shutdown, that is when a CTRL-C signal is received,...
Definition: scheduler.c:1303
enum GNUNET_GenericReturnValue GNUNET_STRINGS_string_to_data_alloc(const char *enc, size_t enclen, void **out, size_t *out_size)
Convert CrockfordBase32 encoding back to data.
Definition: strings.c:854
char * GNUNET_STRINGS_data_to_string_alloc(const void *buf, size_t size)
Return the base32crockford encoding of the given buffer.
Definition: strings.c:763
enum GNUNET_GenericReturnValue GNUNET_STRINGS_string_to_data(const char *enc, size_t enclen, void *out, size_t out_size)
Convert CrockfordBase32 encoding back to data.
Definition: strings.c:788
enum GNUNET_GenericReturnValue GNUNET_STRINGS_get_utf8_args(int argc, char *const *argv, int *u8argc, char *const **u8argv)
Returns utf-8 encoded arguments.
Definition: strings.c:1222
#define _(String)
GNU gettext support macro.
Definition: platform.h:177
Public ECC key (always for Curve25519) encoded in a format suitable for network transmission and encr...
Definition of a command line option.
Handle for an ego.
Definition: identity.h:37
Handle for the service.
Definition: identity_api.c:97
Handle for an operation with the identity service.
Definition: identity_api.c:41
void * cls
Closure for cont or cb.
Definition: identity_api.c:89
A private key for an identity as per LSD0001.
uint32_t type
Type of public key.
An identity key as per LSD0001.