2 This file is part of GNUnet.
3 Copyright (C) 2013, 2018, 2019 GNUnet e.V.
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.
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.
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/>.
18 SPDX-License-Identifier: AGPL3.0-or-later
21 * @file identity/gnunet-identity.c
22 * @brief IDENTITY management command line tool
23 * @author Christian Grothoff
26 * - add options to get default egos
29 #include "gnunet_util_lib.h"
30 #include "gnunet_identity_service.h"
34 * Return value from main on timeout.
36 #define TIMEOUT_STATUS_CODE 40
39 * Handle to IDENTITY service.
41 static struct GNUNET_IDENTITY_Handle *sh;
44 * Was "list" specified?
49 * Was "monitor" specified?
54 * Was "private" specified?
56 static int private_keys;
59 * Was "verbose" specified?
61 static unsigned int verbose;
64 * Was "quiet" specified?
71 static char *create_ego;
76 static char *delete_ego;
86 static char *set_subsystem;
89 * Operation handle for set operation.
91 static struct GNUNET_IDENTITY_Operation *set_op;
94 * Handle for create operation.
96 static struct GNUNET_IDENTITY_Operation *create_op;
99 * Handle for delete operation.
101 static struct GNUNET_IDENTITY_Operation *delete_op;
104 * Value to return from #main().
106 static int global_ret;
110 * Task run on shutdown.
115 shutdown_task (void *cls)
119 GNUNET_IDENTITY_cancel (set_op);
122 if (NULL != create_op)
124 GNUNET_IDENTITY_cancel (create_op);
127 if (NULL != delete_op)
129 GNUNET_IDENTITY_cancel (delete_op);
134 GNUNET_free (set_ego);
137 GNUNET_IDENTITY_disconnect (sh);
143 * Test if we are finished yet.
148 if ( (NULL == create_op) &&
149 (NULL == delete_op) &&
151 (NULL == set_subsystem) &&
155 if (TIMEOUT_STATUS_CODE == global_ret)
157 GNUNET_SCHEDULER_shutdown ();
163 * Deletion operation finished.
165 * @param cls pointer to operation handle
166 * @param emsg NULL on success, otherwise an error message
169 delete_finished (void *cls,
172 struct GNUNET_IDENTITY_Operation **op = cls;
176 fprintf (stderr, "%s\n", gettext (emsg));
182 * Creation operation finished.
184 * @param cls pointer to operation handle
185 * @param pk private key of the ego, or NULL on error
186 * @param emsg error message, NULL on success
189 create_finished (void *cls,
190 const struct GNUNET_CRYPTO_EcdsaPrivateKey *pk,
193 struct GNUNET_IDENTITY_Operation **op = cls;
199 _ ("Failed to create ego: %s\n"),
205 struct GNUNET_CRYPTO_EcdsaPublicKey pub;
208 GNUNET_CRYPTO_ecdsa_key_get_public (pk, &pub);
209 pubs = GNUNET_CRYPTO_ecdsa_public_key_to_string (&pub);
214 privs = GNUNET_CRYPTO_ecdsa_private_key_to_string (pk);
215 fprintf (stdout, "%s - %s\n", pubs, privs);
220 fprintf (stdout, "%s\n", pubs);
229 * Function called by #GNUNET_IDENTITY_set up on completion.
232 * @param emsg error message (NULL on success)
235 set_done (void *cls, const char *emsg)
240 fprintf (stderr, _ ("Failed to set default ego: %s\n"), emsg);
248 * If listing is enabled, prints information about the egos.
250 * This function is initially called for all egos and then again
251 * whenever a ego's identifier changes or if it is deleted. At the
252 * end of the initial pass over all egos, the function is once called
253 * with 'NULL' for 'ego'. That does NOT mean that the callback won't
254 * be invoked in the future or that there was an error.
256 * When used with 'GNUNET_IDENTITY_create' or 'GNUNET_IDENTITY_get',
257 * this function is only called ONCE, and 'NULL' being passed in
258 * 'ego' does indicate an error (i.e. name is taken or no default
259 * value is known). If 'ego' is non-NULL and if '*ctx'
260 * is set in those callbacks, the value WILL be passed to a subsequent
261 * call to the identity callback of 'GNUNET_IDENTITY_connect' (if
262 * that one was not NULL).
264 * When an identity is renamed, this function is called with the
265 * (known) ego but the NEW identifier.
267 * When an identity is deleted, this function is called with the
268 * (known) ego and "NULL" for the 'identifier'. In this case,
269 * the 'ego' is henceforth invalid (and the 'ctx' should also be
273 * @param ego ego handle
274 * @param ctx context for application to store data for this ego
275 * (during the lifetime of this process, initially NULL)
276 * @param identifier identifier assigned by the user for this ego,
277 * NULL if the user just deleted the ego and it
278 * must thus no longer be used
281 print_ego (void *cls,
282 struct GNUNET_IDENTITY_Ego *ego,
284 const char *identifier)
286 struct GNUNET_CRYPTO_EcdsaPublicKey pk;
290 if ( (NULL != set_ego) &&
291 (NULL != set_subsystem) &&
293 (NULL != identifier) &&
294 (0 == strcmp (identifier, set_ego)))
296 set_op = GNUNET_IDENTITY_set (sh,
301 GNUNET_free (set_subsystem);
302 set_subsystem = NULL;
303 GNUNET_free (set_ego);
306 if ( (NULL == ego) &&
308 (NULL != set_subsystem) )
311 "Could not set ego to `%s' for subsystem `%s', ego not known\n",
314 GNUNET_free (set_subsystem);
315 set_subsystem = NULL;
316 GNUNET_free (set_ego);
319 if ((NULL == ego) && (! monitor))
325 if (! (list | monitor))
327 if ( (NULL == ego) ||
328 (NULL == identifier) )
330 if ( (NULL != set_ego) &&
331 (0 != strcmp (identifier,
334 GNUNET_IDENTITY_ego_get_public_key (ego, &pk);
335 s = GNUNET_CRYPTO_ecdsa_public_key_to_string (&pk);
336 privs = GNUNET_CRYPTO_ecdsa_private_key_to_string (
337 GNUNET_IDENTITY_ego_get_private_key (ego));
338 if ((monitor) || (NULL != identifier))
343 fprintf (stdout, "%s - %s\n", s, privs);
345 fprintf (stdout, "%s\n", s);
350 fprintf (stdout, "%s - %s - %s\n", identifier, s, privs);
352 fprintf (stdout, "%s - %s\n", identifier, s);
361 * Main function that will be run by the scheduler.
364 * @param args remaining command-line arguments
365 * @param cfgfile name of the configuration file used (for saving, can be NULL!)
366 * @param cfg configuration
372 const struct GNUNET_CONFIGURATION_Handle *cfg)
374 if ((NULL != set_subsystem) && (NULL == set_ego))
376 fprintf (stderr, "Option -s requires option -e to be specified as well.\n");
379 sh = GNUNET_IDENTITY_connect (cfg,
382 (NULL != set_subsystem)
386 if (NULL != delete_ego)
388 GNUNET_IDENTITY_delete (sh,
392 if (NULL != create_ego)
394 GNUNET_IDENTITY_create (sh,
398 GNUNET_SCHEDULER_add_shutdown (&shutdown_task,
407 * @param argc number of arguments from the command line
408 * @param argv command line arguments
409 * @return 0 ok, 1 on error
412 main (int argc, char *const *argv)
414 struct GNUNET_GETOPT_CommandLineOption options[] = {
415 GNUNET_GETOPT_option_string ('C',
418 gettext_noop ("create ego NAME"),
420 GNUNET_GETOPT_option_string ('D',
423 gettext_noop ("delete ego NAME "),
425 GNUNET_GETOPT_option_flag ('d',
427 gettext_noop ("display all egos"),
429 GNUNET_GETOPT_option_flag ('q',
431 gettext_noop ("reduce output"),
433 GNUNET_GETOPT_option_string (
438 "set default identity to NAME for a subsystem SUBSYSTEM (use together with -s) or restrict results to NAME (use together with -d)"),
440 GNUNET_GETOPT_option_flag ('m',
442 gettext_noop ("run in monitor mode egos"),
444 GNUNET_GETOPT_option_flag ('p',
446 gettext_noop ("display private keys as well"),
448 GNUNET_GETOPT_option_string (
453 "set default identity to EGO for a subsystem SUBSYSTEM (use together with -e)"),
455 GNUNET_GETOPT_option_verbose (&verbose),
456 GNUNET_GETOPT_OPTION_END
461 GNUNET_STRINGS_get_utf8_args (argc, argv,
464 global_ret = TIMEOUT_STATUS_CODE; /* timeout */
465 res = GNUNET_PROGRAM_run (argc,
468 gettext_noop ("Maintain egos"),
472 GNUNET_free_nz ((void *) argv);
474 if (GNUNET_OK != res)
480 /* end of gnunet-identity.c */